mirror of
https://github.com/tmux/tmux.git
synced 2026-03-15 05:07:24 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be20fc8699 |
54
CHANGES
54
CHANGES
@@ -1,55 +1,3 @@
|
|||||||
CHANGES FROM 1.0 TO 1.1, 05 November 2009
|
|
||||||
|
|
||||||
* New run-shell (alias run) command to run an external command without a
|
|
||||||
window, capture it's stdout, and send it to output mode.
|
|
||||||
* Ability to define multiple prefix keys.
|
|
||||||
* Internal locking mechanism removed. Instead, detach each client and run the
|
|
||||||
external command specified in the new session option lock-command (by default
|
|
||||||
lock -np), thus allowing the system password to be used.
|
|
||||||
* set-password command, and -U command line flag removed per the above change.
|
|
||||||
* Add support for -c command line flag to execute a shell command.
|
|
||||||
* New lock-client (alias lockc), and lock-session (alias locks) commands to
|
|
||||||
lock a particular client, or all clients attached to a session.
|
|
||||||
* Support C-n/C-p/C-v/M-v with emacs keys in choice mode.
|
|
||||||
* Use : for goto line rather than g in vi mode.
|
|
||||||
* Try to guess which client to use when no target client was specified. Finds
|
|
||||||
the current session, and if only one client is present, use it. Otherwise,
|
|
||||||
return the most recently used client.
|
|
||||||
* Make C-Down/C-Up in copy mode scroll the screen down/up one line without
|
|
||||||
moving the cursor.
|
|
||||||
* Scroll mode superseded by copy mode.
|
|
||||||
* New synchronize-panes window option to send all input to all other panes in
|
|
||||||
the same window.
|
|
||||||
* New lock-server session option to lock, when off (on by default), each
|
|
||||||
session when it has been idle for the lock-after-time setting. When on, the
|
|
||||||
entire server locks when all sessions have been idle for their individual
|
|
||||||
lock-after-time setting.
|
|
||||||
* Add support for grouped sessions which have independent name, options,
|
|
||||||
current window, but where the linked windows are synchronized (ie creating,
|
|
||||||
killing windows are mirrored between the sessions). A grouped session may be
|
|
||||||
created by passing -t to new-session.
|
|
||||||
* New mouse-select-pane session option to select the current pane with the
|
|
||||||
mouse.
|
|
||||||
* Queue, and run commands in the background for if-shell, status-left,
|
|
||||||
status-right, and #() by starting each once every status-interval. Adds the
|
|
||||||
capability to call some programs which would previously cause the server to
|
|
||||||
hang (eg sleep/tmux). It also avoids running commands excessively (ie if used
|
|
||||||
multiple times, it will be run only once).
|
|
||||||
* When a window is zombified and automatic-rename is on, append [dead] to the
|
|
||||||
name.
|
|
||||||
* Split list-panes (alias lsp) off from list-windows.
|
|
||||||
* New pipe-pane (alias pipep) to redirect a pane output to an external command.
|
|
||||||
* Support for automatic-renames for Solaris.
|
|
||||||
* Permit attributes to be turned off in #[] by prefixing with no (eg nobright).
|
|
||||||
* Add H/M/L in vi mode, and M-R/M-r in emacs to move the cursor to the top,
|
|
||||||
middle, and bottom of the screen.
|
|
||||||
* -a option added to kill-pane to kill all except current pane.
|
|
||||||
* The -d command line flag is now gone (can be replaced by terminal-overrides).
|
|
||||||
Just use op/AX to detect default colours.
|
|
||||||
* input/tty/utf8 improvements.
|
|
||||||
* xterm-keys rewrite.
|
|
||||||
* Additional code reduction, and bug fixes.
|
|
||||||
|
|
||||||
CHANGES FROM 0.9 TO 1.0, 20 Sept 2009
|
CHANGES FROM 0.9 TO 1.0, 20 Sept 2009
|
||||||
|
|
||||||
* Option to alter the format of the window title set by tmux.
|
* Option to alter the format of the window title set by tmux.
|
||||||
@@ -1410,7 +1358,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.301 2009-11-05 12:35:47 tcunha Exp $
|
$Id: CHANGES,v 1.300 2009-09-20 18:54:21 nicm Exp $
|
||||||
|
|
||||||
LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
|
LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
|
||||||
LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms
|
LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms
|
||||||
|
|||||||
29
GNUmakefile
29
GNUmakefile
@@ -1,37 +1,16 @@
|
|||||||
# $Id: GNUmakefile,v 1.120 2009-11-05 12:30:55 tcunha Exp $
|
# $Id: GNUmakefile,v 1.114 2009-09-20 18:54:21 nicm Exp $
|
||||||
#
|
|
||||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
#
|
|
||||||
# Permission to use, copy, modify, and distribute this software for any
|
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
|
||||||
# copyright notice and this permission notice appear in all copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
# WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
VERSION= 1.1
|
VERSION= 1.0
|
||||||
|
|
||||||
#FDEBUG= 1
|
#FDEBUG= 1
|
||||||
|
|
||||||
CC?= cc
|
CC?= gcc
|
||||||
CFLAGS+= -DBUILD="\"$(VERSION)\""
|
CFLAGS+= -DBUILD="\"$(VERSION)\""
|
||||||
LDFLAGS+= -L/usr/local/lib
|
LDFLAGS+= -L/usr/local/lib
|
||||||
LIBS+=
|
LIBS+=
|
||||||
|
|
||||||
# Sun CC
|
|
||||||
ifneq ($(shell ($(CC) -V 2>&1|awk '/Sun C/' || true)), )
|
|
||||||
CFLAGS+=-erroff=E_EMPTY_DECLARATION
|
|
||||||
FDEBUG=
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef FDEBUG
|
ifdef FDEBUG
|
||||||
CFLAGS+= -g -ggdb -DDEBUG
|
CFLAGS+= -g -ggdb -DDEBUG
|
||||||
CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
|
CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
|
||||||
@@ -69,7 +48,7 @@ depend: $(SRCS)
|
|||||||
$(CC) $(CPPFLAGS) $(CFLAGS) -MM $(SRCS) > .depend
|
$(CC) $(CPPFLAGS) $(CFLAGS) -MM $(SRCS) > .depend
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f tmux *.o *~ *.core *.log compat/*.o compat/*~
|
rm -f tmux *.o *~ *.core *.log compat/*.o
|
||||||
|
|
||||||
clean-depend:
|
clean-depend:
|
||||||
rm -f .depend
|
rm -f .depend
|
||||||
|
|||||||
21
Makefile
21
Makefile
@@ -1,24 +1,9 @@
|
|||||||
# $Id: Makefile,v 1.153 2009-11-05 12:30:55 tcunha Exp $
|
# $Id: Makefile,v 1.149 2009-09-20 18:54:21 nicm Exp $
|
||||||
#
|
|
||||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
#
|
|
||||||
# Permission to use, copy, modify, and distribute this software for any
|
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
|
||||||
# copyright notice and this permission notice appear in all copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
# WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
.SUFFIXES: .c .o
|
.SUFFIXES: .c .o
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
VERSION= 1.1
|
VERSION= 1.0
|
||||||
|
|
||||||
#FDEBUG= 1
|
#FDEBUG= 1
|
||||||
|
|
||||||
@@ -68,7 +53,7 @@ depend:
|
|||||||
mkdep ${CPPFLAGS} ${CFLAGS} ${SRCS:M*.c}
|
mkdep ${CPPFLAGS} ${CFLAGS} ${SRCS:M*.c}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f tmux *.o *~ *.core *.log compat/*.o compat/*~
|
rm -f tmux *.o *~ *.core *.log compat/*.o
|
||||||
|
|
||||||
clean-depend:
|
clean-depend:
|
||||||
rm -f .depend
|
rm -f .depend
|
||||||
|
|||||||
29
NOTES
29
NOTES
@@ -4,17 +4,15 @@ tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
|
|||||||
to be accessed and controlled from a single terminal. tmux is intended to be a
|
to be accessed and controlled from a single terminal. tmux is intended to be a
|
||||||
simple, modern, BSD-licensed alternative to programs such as GNU screen.
|
simple, modern, BSD-licensed alternative to programs such as GNU screen.
|
||||||
|
|
||||||
This release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
|
This 0.9 release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
|
||||||
run on Solaris and AIX (although they haven't been tested in a while). It is
|
run on Solaris and AIX (although they hasn't been tested in a while). It is
|
||||||
usable, although there remain a number of missing features and some remaining
|
usable, although there remain a number of missing features and some remaining
|
||||||
bugs are expected.
|
bugs are expected.
|
||||||
|
|
||||||
If upgrading from 1.0, PLEASE NOTE:
|
If upgrading from 0.5, PLEASE NOTE the following configuration file changes: it
|
||||||
- The internal locking mechanism has gone, so the set-password command and -U
|
is now required to pass the -g flag to set-option or set-window-option to set
|
||||||
command line option have been removed.
|
global options; remain-by-default and utf8-default are now gone, use global
|
||||||
- The -d command line flag was dropped. It will now automatically detect the
|
window options (set-window-option -g) instead.
|
||||||
default colours by using op/AX. Nevertheless, if needed, the
|
|
||||||
terminal-overrides session option can replace it.
|
|
||||||
|
|
||||||
tmux consists of a server part and multiple clients. The server is created when
|
tmux consists of a server part and multiple clients. The server is created when
|
||||||
required and runs continuously unless killed by the user. Clients access the
|
required and runs continuously unless killed by the user. Clients access the
|
||||||
@@ -39,14 +37,17 @@ The following is a summary of major features implemented in this version:
|
|||||||
- Support for VT100 line drawing characters.
|
- Support for VT100 line drawing characters.
|
||||||
- A large command set.
|
- A large command set.
|
||||||
- Vertical window splitting and layout.
|
- Vertical window splitting and layout.
|
||||||
- Automatic server locking on inactivity by running an external command.
|
- Automatic server locking on inactivity.
|
||||||
- A configuration file.
|
- A configuration file.
|
||||||
- UTF-8 support.
|
- 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. Known working are
|
||||||
|
TERM=screen (tmux in screen), xterm, xterm-color and rxvt. Note that TERM=xterm
|
||||||
|
does not support colour on OpenBSD. screen ignores this, tmux does not: use
|
||||||
|
xterm-color or rxvt for colour.
|
||||||
|
|
||||||
tmux supports UTF-8. To use it, the utf8 option must be set on each window;
|
tmux supports UTF-8. To use it, the utf8 option must be set on each window;
|
||||||
this may be turned on for all windows by setting it as a global option, see
|
this may be turned on for all windows by setting it as a global option, see
|
||||||
@@ -80,12 +81,6 @@ welcome. Please send by email to:
|
|||||||
|
|
||||||
nicm@users.sf.net
|
nicm@users.sf.net
|
||||||
|
|
||||||
This file and the CHANGES, FAQ and TODO files are licensed under the ISC
|
|
||||||
license. Files under examples/ remain copyright their authors unless otherwise
|
|
||||||
stated in the file but permission has been received to distribute them with
|
|
||||||
tmux. All other files have a license and copyright notice at their
|
|
||||||
start. Please contact me with any queries.
|
|
||||||
|
|
||||||
-- Nicholas Marriott <nicm@users.sf.net>
|
-- Nicholas Marriott <nicm@users.sf.net>
|
||||||
|
|
||||||
$Id: NOTES,v 1.51 2009-11-05 12:35:47 tcunha Exp $
|
$Id: NOTES,v 1.49 2009-07-06 18:53:24 nicm Exp $
|
||||||
|
|||||||
65
TODO
65
TODO
@@ -9,30 +9,45 @@
|
|||||||
- garbage collect window history (100 lines at a time?) if it hasn't been used
|
- garbage collect window history (100 lines at a time?) if it hasn't been used
|
||||||
in $x time (need window creation/use times)
|
in $x time (need window creation/use times)
|
||||||
- lift SHRT_MAX limits for history?
|
- lift SHRT_MAX limits for history?
|
||||||
|
- better mode features: search
|
||||||
- flags to centre screen in window
|
- flags to centre screen in window
|
||||||
- better terminal emulation
|
- 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; also ^K
|
||||||
- many more info() displays for various things
|
- many more info() displays for various things
|
||||||
|
- backspace should perhaps wrap backwards over newlines which were not moved
|
||||||
|
down by a newline: screen and the OS X terminal does this but xterm and most
|
||||||
|
others do not. this might be hard: a flag for each grid line (top bit of size
|
||||||
|
maybe)? a single flag is insufficient as can't then tell when to /stop/
|
||||||
|
unwrapping
|
||||||
- input.c is too complicated. simplify?
|
- input.c is too complicated. simplify?
|
||||||
- use a better termcap internally instead of screen, perhaps xterm
|
- use a better termcap internally instead of screen, perhaps xterm
|
||||||
|
- kill all but current pane
|
||||||
- fix rxvt cursor fg issue (text under cursor can have non-white fg)
|
- fix rxvt cursor fg issue (text under cursor can have non-white fg)
|
||||||
|
- client sx/sy should be in tty, then can let the terminal wrap at edge
|
||||||
|
to allow xterm to pick up it should be one line for its c/p
|
||||||
- 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
|
- set-option should be set-session-option and should be overall global options
|
||||||
|
for stuff like mode keys?
|
||||||
also quiet, utf8 and maybe other flags?
|
also quiet, utf8 and maybe other flags?
|
||||||
-g is a bit unexpected in conf file
|
-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
|
- the output code (tty.c) could do with optimisation depending on term
|
||||||
capabilities
|
capibilities
|
||||||
- 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
|
||||||
|
- goto line and search history in copy/scroll modes
|
||||||
|
- clone session command
|
||||||
- make command sequences more usable: don't require space after ;, handle
|
- make command sequences more usable: don't require space after ;, handle
|
||||||
errors better
|
errors better
|
||||||
|
- key to switch to copy mode from scroll mode
|
||||||
- attach should have a flag to create session if it doesn't exist
|
- attach should have a flag to create session if it doesn't exist
|
||||||
|
- rename split-window -> split-pane??
|
||||||
|
- fix UTF-8 guesswork on sparc64, improve tty checks
|
||||||
- choice and more mode would be better per client than per window?
|
- choice and more mode would be better per client than per window?
|
||||||
- hooks to which commands may be attached, for example: tmux add-hook
|
- hooks to which commands may be attached, for example: tmux add-hook
|
||||||
"new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
|
"new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
|
||||||
@@ -44,54 +59,48 @@
|
|||||||
- XXX once env stuff is in, default-path and VISUAL/EDITOR should be picked up
|
- XXX once env stuff is in, default-path and VISUAL/EDITOR should be picked up
|
||||||
when session is started
|
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?
|
||||||
|
- H/M/L commands in copy mode with vi-keys, for jumping to the top/middle/last
|
||||||
|
line on the screen
|
||||||
|
- split list-windows into separate list-windows and list-panes
|
||||||
- warts on current naming:
|
- warts on current naming:
|
||||||
- display-time but message-fg/bg/attr
|
- display-time but message-fg/bg/attr
|
||||||
- list-* vs show-*
|
- list-* vs show-*
|
||||||
- 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??
|
- pcvt25 doesn't work properly, why? (bce?)
|
||||||
- tidy up and prioritise todo list ;-)
|
- tidy up and prioritise todo list ;-)
|
||||||
|
- it is only possible to specify 8 colours to fg/bg options; should be able to
|
||||||
|
set 256 as well
|
||||||
- neww and attach can create a session if none exists?
|
- neww and attach can create a session if none exists?
|
||||||
would work fine with config file since
|
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?)
|
||||||
|
- **** a command to run something without a window and send any output to the
|
||||||
|
window-more. if no output, info() a line saying "'%s' returned %d". so i can
|
||||||
|
bind mpc control commands to function keys ;-)
|
||||||
- command to list what is actually running in each window with command line,
|
- 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)
|
||||||
- string option to change/remove the symbols (*-+ etc) in status line
|
- string option to change/remove the symbols (*-+ etc) in status line
|
||||||
* or to set entire format, eg window-list-format '#N:#W#P' or something,
|
|
||||||
then could use embedded colours
|
|
||||||
- support for bce
|
- support for bce
|
||||||
- it would be nice if the start/end line keys in copy mode were aware of
|
- it would be nice if the start/end line keys in copy mode were aware of
|
||||||
wrapped lines
|
wrapped lines
|
||||||
|
- per session locking
|
||||||
- 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
|
-- idea of a "view" onto a window, need base x/y offsets
|
||||||
for redraw
|
for redraw
|
||||||
|
- a window option which means data is echoed to all panes in a window
|
||||||
|
- support running tmux from inside tmux [#(), if-shell] --
|
||||||
|
generic system-like function which may take a callback
|
||||||
|
also sets up environment (TMUX) and has a timeout
|
||||||
|
for #(): command schedular, status line queues it with a time, run in
|
||||||
|
main loop, and uses most recent result -- can also be used for persistent
|
||||||
|
commands which never exit just continually output
|
||||||
|
for if-shell, callback??
|
||||||
- handle resize better in copy mode
|
- 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
|
||||||
|
- fix line wrapping c&p problems in xterm etc
|
||||||
- a way to address panes by name ("top-left") and position ("0,0")
|
- a way to address panes by name ("top-left") and position ("0,0")
|
||||||
|
- ability to specify multiple prefix keys
|
||||||
- commands should be able to succeed or fail and have || or && for command
|
- commands should be able to succeed or fail and have || or && for command
|
||||||
lists
|
lists
|
||||||
- support the mouse wheel to scroll through history
|
- support the mouse wheel to scroll through history
|
||||||
- some way to KEEP a command running continually and just use its LAST line of
|
|
||||||
output
|
|
||||||
- bind commands to mouse buttons
|
|
||||||
- UTF-8 to a non-UTF-8 terminal should not be able to balls up
|
|
||||||
the terminal - www/ruby-addressable; make regress
|
|
||||||
- copy mode needs a tidy/cleanup
|
|
||||||
- things like display-message will leak job entries if #() is used
|
|
||||||
- message log
|
|
||||||
- an option to NOT remove message when key pressed
|
|
||||||
- would be nice to be able to press 0-9a-zA-Z to select window in choose-window
|
|
||||||
mode, also to start typing and it searches
|
|
||||||
- the wrapping stuff should work when redrawn from scroll mode too (screen_write_copy)
|
|
||||||
- ability to save history (to buffer?)
|
|
||||||
- multiple keys could be done with tables, ie have prefixes go and instead
|
|
||||||
bind -n ^A prefix-table "default"
|
|
||||||
where prefix-table sets command lookup table and sets prefix flag, then next key
|
|
||||||
is looked up in that table
|
|
||||||
- check fix UTF-8 and split-window? should be okay
|
|
||||||
- UTF-8 should be a pointer into a combined string buffer
|
|
||||||
- check irssi (term_charset) works with UTF-8
|
|
||||||
- rectangle copy/paste
|
|
||||||
- half page/up down are missing from key table
|
|
||||||
- support esc-esc to quit in modes
|
|
||||||
|
|||||||
6
array.h
6
array.h
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: array.h,v 1.9 2009-11-02 21:34:32 tcunha Exp $ */
|
/* $Id: array.h,v 1.7 2008-09-29 16:58:02 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
ARRAY_ITEMSIZE(a) * ((a)->num - (i) - 1)); \
|
ARRAY_ITEMSIZE(a) * ((a)->num - (i) - 1)); \
|
||||||
} \
|
} \
|
||||||
(a)->num--; \
|
(a)->num--; \
|
||||||
if ((a)->num == 0) \
|
if ((a)->num == 0) \
|
||||||
ARRAY_FREE(a); \
|
ARRAY_FREE(a); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
|
|
||||||
#define ARRAY_CONCAT(a, b) do { \
|
#define ARRAY_CONCAT(a, b) do { \
|
||||||
ARRAY_ENSURE(a, (b)->num); \
|
ARRAY_ENSURE(a, (b)->num); \
|
||||||
memcpy((a)->list + (a)->num, (b)->list, (b)->num * ARRAY_ITEMSIZE(a)); \
|
memcpy((a)->list + (a)->num, (b)->list, (b)->num * ARRAY_ITEMSIZE(a)) \
|
||||||
(a)->num += (b)->num; \
|
(a)->num += (b)->num; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: buffer-poll.c,v 1.18 2009-10-23 17:49:47 tcunha Exp $ */
|
/* $Id: buffer-poll.c,v 1.16 2009-08-19 09:28:10 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -25,15 +25,15 @@
|
|||||||
|
|
||||||
/* Fill buffers from socket based on poll results. */
|
/* Fill buffers from socket based on poll results. */
|
||||||
int
|
int
|
||||||
buffer_poll(int fd, int events, struct buffer *in, struct buffer *out)
|
buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
|
||||||
{
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
if (events & (POLLERR|POLLNVAL))
|
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
|
||||||
return (-1);
|
return (-1);
|
||||||
if (in != NULL && events & POLLIN) {
|
if (pfd->revents & POLLIN) {
|
||||||
buffer_ensure(in, BUFSIZ);
|
buffer_ensure(in, BUFSIZ);
|
||||||
n = read(fd, BUFFER_IN(in), BUFFER_FREE(in));
|
n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in));
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
@@ -41,10 +41,9 @@ buffer_poll(int fd, int events, struct buffer *in, struct buffer *out)
|
|||||||
return (-1);
|
return (-1);
|
||||||
} else
|
} else
|
||||||
buffer_add(in, n);
|
buffer_add(in, n);
|
||||||
} else if (events & POLLHUP)
|
}
|
||||||
return (-1);
|
if (BUFFER_USED(out) > 0 && pfd->revents & POLLOUT) {
|
||||||
if (out != NULL && BUFFER_USED(out) > 0 && events & POLLOUT) {
|
n = write(pfd->fd, BUFFER_OUT(out), BUFFER_USED(out));
|
||||||
n = write(fd, BUFFER_OUT(out), BUFFER_USED(out));
|
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno != EINTR && errno != EAGAIN)
|
if (errno != EINTR && errno != EAGAIN)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|||||||
6
cfg.c
6
cfg.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cfg.c,v 1.23 2009-10-28 23:12:38 tcunha Exp $ */
|
/* $Id: cfg.c,v 1.22 2009-08-24 16:27:03 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -53,9 +53,9 @@ cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
|
|||||||
int
|
int
|
||||||
load_cfg(const char *path, struct cmd_ctx *ctxin, char **cause)
|
load_cfg(const char *path, struct cmd_ctx *ctxin, char **cause)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
u_int n;
|
u_int n;
|
||||||
char *buf, *line, *ptr;
|
char *buf, *line, *ptr;
|
||||||
size_t len;
|
size_t len;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
struct cmd_ctx ctx;
|
struct cmd_ctx ctx;
|
||||||
|
|||||||
90
client-fn.c
Normal file
90
client-fn.c
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/* $Id: client-fn.c,v 1.10 2009-08-14 21:04:04 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
client_fill_session(struct msg_command_data *data)
|
||||||
|
{
|
||||||
|
char *env, *ptr1, *ptr2, buf[256];
|
||||||
|
size_t len;
|
||||||
|
const char *errstr;
|
||||||
|
long long ll;
|
||||||
|
|
||||||
|
data->pid = -1;
|
||||||
|
if ((env = getenv("TMUX")) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((ptr2 = strrchr(env, ',')) == NULL || ptr2 == env)
|
||||||
|
return;
|
||||||
|
for (ptr1 = ptr2 - 1; ptr1 > env && *ptr1 != ','; ptr1--)
|
||||||
|
;
|
||||||
|
if (*ptr1 != ',')
|
||||||
|
return;
|
||||||
|
ptr1++;
|
||||||
|
ptr2++;
|
||||||
|
|
||||||
|
len = ptr2 - ptr1 - 1;
|
||||||
|
if (len > (sizeof buf) - 1)
|
||||||
|
return;
|
||||||
|
memcpy(buf, ptr1, len);
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
ll = strtonum(buf, 0, LONG_MAX, &errstr);
|
||||||
|
if (errstr != NULL)
|
||||||
|
return;
|
||||||
|
data->pid = ll;
|
||||||
|
|
||||||
|
ll = strtonum(ptr2, 0, UINT_MAX, &errstr);
|
||||||
|
if (errstr != NULL)
|
||||||
|
return;
|
||||||
|
data->idx = ll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_write_server(
|
||||||
|
struct client_ctx *cctx, enum msgtype type, void *buf, size_t len)
|
||||||
|
{
|
||||||
|
imsg_compose(&cctx->ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_suspend(void)
|
||||||
|
{
|
||||||
|
struct sigaction act;
|
||||||
|
|
||||||
|
memset(&act, 0, sizeof act);
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
act.sa_flags = SA_RESTART;
|
||||||
|
|
||||||
|
act.sa_handler = SIG_DFL;
|
||||||
|
if (sigaction(SIGTSTP, &act, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
|
||||||
|
act.sa_handler = sighandler;
|
||||||
|
if (sigaction(SIGCONT, &act, NULL) != 0)
|
||||||
|
fatal("sigaction failed");
|
||||||
|
|
||||||
|
kill(getpid(), SIGTSTP);
|
||||||
|
}
|
||||||
275
client.c
275
client.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: client.c,v 1.84 2009-11-02 21:41:16 tcunha Exp $ */
|
/* $Id: client.c,v 1.70 2009-09-03 21:06:30 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -33,23 +33,21 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
struct imsgbuf client_ibuf;
|
void client_send_environ(struct client_ctx *);
|
||||||
const char *client_exitmsg;
|
void client_handle_winch(struct client_ctx *);
|
||||||
|
|
||||||
void client_send_identify(int);
|
int
|
||||||
void client_send_environ(void);
|
client_init(char *path, struct client_ctx *cctx, int cmdflags, int flags)
|
||||||
void client_write_server(enum msgtype, void *, size_t);
|
|
||||||
int client_dispatch(void);
|
|
||||||
void client_suspend(void);
|
|
||||||
|
|
||||||
struct imsgbuf *
|
|
||||||
client_init(char *path, int cmdflags, int flags)
|
|
||||||
{
|
{
|
||||||
struct sockaddr_un sa;
|
struct sockaddr_un sa;
|
||||||
size_t size;
|
struct stat sb;
|
||||||
int fd, mode;
|
struct msg_identify_data data;
|
||||||
|
struct winsize ws;
|
||||||
|
size_t size;
|
||||||
|
int fd, fd2, mode;
|
||||||
|
char *name, *term;
|
||||||
#ifdef HAVE_SETPROCTITLE
|
#ifdef HAVE_SETPROCTITLE
|
||||||
char rpathbuf[MAXPATHLEN];
|
char rpathbuf[MAXPATHLEN];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SETPROCTITLE
|
#ifdef HAVE_SETPROCTITLE
|
||||||
@@ -58,6 +56,19 @@ client_init(char *path, int cmdflags, int flags)
|
|||||||
setproctitle("client (%s)", rpathbuf);
|
setproctitle("client (%s)", rpathbuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (lstat(path, &sb) != 0) {
|
||||||
|
if (cmdflags & CMD_STARTSERVER && errno == ENOENT) {
|
||||||
|
if ((fd = server_start(path)) == -1)
|
||||||
|
goto start_failed;
|
||||||
|
goto server_started;
|
||||||
|
}
|
||||||
|
goto not_found;
|
||||||
|
}
|
||||||
|
if (!S_ISSOCK(sb.st_mode)) {
|
||||||
|
errno = ENOTSOCK;
|
||||||
|
goto not_found;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@@ -67,17 +78,12 @@ client_init(char *path, int cmdflags, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||||
fatal("socket failed");
|
fatal("socket");
|
||||||
|
|
||||||
if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
|
if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
|
||||||
if (!(cmdflags & CMD_STARTSERVER))
|
if (errno == ECONNREFUSED) {
|
||||||
goto not_found;
|
if (unlink(path) != 0 || !(cmdflags & CMD_STARTSERVER))
|
||||||
switch (errno) {
|
|
||||||
case ECONNREFUSED:
|
|
||||||
if (unlink(path) != 0)
|
|
||||||
goto not_found;
|
goto not_found;
|
||||||
/* FALLTHROUGH */
|
|
||||||
case ENOENT:
|
|
||||||
if ((fd = server_start(path)) == -1)
|
if ((fd = server_start(path)) == -1)
|
||||||
goto start_failed;
|
goto start_failed;
|
||||||
goto server_started;
|
goto server_started;
|
||||||
@@ -90,73 +96,64 @@ server_started:
|
|||||||
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)
|
imsg_init(&cctx->ibuf, fd);
|
||||||
fatal("fcntl failed");
|
|
||||||
imsg_init(&client_ibuf, fd);
|
|
||||||
|
|
||||||
if (cmdflags & CMD_SENDENVIRON)
|
if (cmdflags & CMD_SENDENVIRON)
|
||||||
client_send_environ();
|
client_send_environ(cctx);
|
||||||
if (isatty(STDIN_FILENO))
|
if (isatty(STDIN_FILENO)) {
|
||||||
client_send_identify(flags);
|
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
||||||
|
fatal("ioctl(TIOCGWINSZ)");
|
||||||
|
data.flags = flags;
|
||||||
|
data.sx = ws.ws_col;
|
||||||
|
data.sy = ws.ws_row;
|
||||||
|
|
||||||
return (&client_ibuf);
|
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
|
||||||
|
*data.cwd = '\0';
|
||||||
|
|
||||||
|
*data.term = '\0';
|
||||||
|
if ((term = getenv("TERM")) != NULL) {
|
||||||
|
if (strlcpy(data.term,
|
||||||
|
term, sizeof data.term) >= sizeof data.term)
|
||||||
|
*data.term = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
*data.tty = '\0';
|
||||||
|
if ((name = ttyname(STDIN_FILENO)) == NULL)
|
||||||
|
fatal("ttyname failed");
|
||||||
|
if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty)
|
||||||
|
fatalx("ttyname failed");
|
||||||
|
|
||||||
|
fd2 = dup(STDIN_FILENO);
|
||||||
|
imsg_compose(&cctx->ibuf, MSG_IDENTIFY,
|
||||||
|
PROTOCOL_VERSION, -1, fd2, &data, sizeof data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
start_failed:
|
start_failed:
|
||||||
log_warnx("server failed to start");
|
log_warnx("server failed to start");
|
||||||
return (NULL);
|
return (1);
|
||||||
|
|
||||||
not_found:
|
not_found:
|
||||||
log_warn("server not found");
|
log_warn("server not found");
|
||||||
return (NULL);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
client_send_identify(int flags)
|
client_send_environ(struct client_ctx *cctx)
|
||||||
{
|
{
|
||||||
struct msg_identify_data data;
|
|
||||||
struct winsize ws;
|
|
||||||
char *term;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
|
||||||
fatal("ioctl(TIOCGWINSZ)");
|
|
||||||
data.flags = flags;
|
|
||||||
|
|
||||||
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
|
|
||||||
*data.cwd = '\0';
|
|
||||||
|
|
||||||
term = getenv("TERM");
|
|
||||||
if (term == NULL ||
|
|
||||||
strlcpy(data.term, term, sizeof data.term) >= sizeof data.term)
|
|
||||||
*data.term = '\0';
|
|
||||||
|
|
||||||
if ((fd = dup(STDIN_FILENO)) == -1)
|
|
||||||
fatal("dup failed");
|
|
||||||
imsg_compose(&client_ibuf,
|
|
||||||
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
client_send_environ(void)
|
|
||||||
{
|
|
||||||
struct msg_environ_data data;
|
|
||||||
char **var;
|
char **var;
|
||||||
|
struct msg_environ_data data;
|
||||||
|
|
||||||
for (var = environ; *var != NULL; var++) {
|
for (var = environ; *var != NULL; var++) {
|
||||||
if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
|
if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
|
||||||
continue;
|
continue;
|
||||||
client_write_server(MSG_ENVIRON, &data, sizeof data);
|
client_write_server(cctx, MSG_ENVIRON, &data, sizeof data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
client_write_server(enum msgtype type, void *buf, size_t len)
|
client_main(struct client_ctx *cctx)
|
||||||
{
|
|
||||||
imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
__dead void
|
|
||||||
client_main(void)
|
|
||||||
{
|
{
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
int n, nfds;
|
int n, nfds;
|
||||||
@@ -171,34 +168,27 @@ client_main(void)
|
|||||||
* MSG_READY switched to here. Process anything outstanding now so poll
|
* MSG_READY switched to here. Process anything outstanding now so poll
|
||||||
* doesn't hang waiting for messages that have already arrived.
|
* doesn't hang waiting for messages that have already arrived.
|
||||||
*/
|
*/
|
||||||
if (client_dispatch() != 0)
|
if (client_msg_dispatch(cctx) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (sigterm) {
|
if (sigterm)
|
||||||
client_exitmsg = "terminated";
|
client_write_server(cctx, MSG_EXITING, NULL, 0);
|
||||||
client_write_server(MSG_EXITING, NULL, 0);
|
|
||||||
}
|
|
||||||
if (sigchld) {
|
if (sigchld) {
|
||||||
sigchld = 0;
|
|
||||||
waitpid(WAIT_ANY, NULL, WNOHANG);
|
waitpid(WAIT_ANY, NULL, WNOHANG);
|
||||||
continue;
|
sigchld = 0;
|
||||||
}
|
|
||||||
if (sigwinch) {
|
|
||||||
sigwinch = 0;
|
|
||||||
client_write_server(MSG_RESIZE, NULL, 0);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
if (sigwinch)
|
||||||
|
client_handle_winch(cctx);
|
||||||
if (sigcont) {
|
if (sigcont) {
|
||||||
sigcont = 0;
|
|
||||||
siginit();
|
siginit();
|
||||||
client_write_server(MSG_WAKEUP, NULL, 0);
|
client_write_server(cctx, MSG_WAKEUP, NULL, 0);
|
||||||
continue;
|
sigcont = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfd.fd = client_ibuf.fd;
|
pfd.fd = cctx->ibuf.fd;
|
||||||
pfd.events = POLLIN;
|
pfd.events = POLLIN;
|
||||||
if (client_ibuf.w.queued > 0)
|
if (cctx->ibuf.w.queued > 0)
|
||||||
pfd.events |= POLLOUT;
|
pfd.events |= POLLOUT;
|
||||||
|
|
||||||
if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
|
if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
|
||||||
@@ -213,41 +203,75 @@ client_main(void)
|
|||||||
fatalx("socket error");
|
fatalx("socket error");
|
||||||
|
|
||||||
if (pfd.revents & POLLIN) {
|
if (pfd.revents & POLLIN) {
|
||||||
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) {
|
if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) {
|
||||||
client_exitmsg = "lost server";
|
cctx->exittype = CCTX_DIED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (client_dispatch() != 0)
|
if (client_msg_dispatch(cctx) != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pfd.revents & POLLOUT) {
|
if (pfd.revents & POLLOUT) {
|
||||||
if (msgbuf_write(&client_ibuf.w) < 0) {
|
if (msgbuf_write(&cctx->ibuf.w) < 0) {
|
||||||
client_exitmsg = "lost server";
|
cctx->exittype = CCTX_DIED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
/* Print the exit message, if any, and exit. */
|
if (sigterm) {
|
||||||
if (client_exitmsg != NULL) {
|
printf("[terminated]\n");
|
||||||
if (!login_shell)
|
return (1);
|
||||||
printf("[%s]\n", client_exitmsg);
|
}
|
||||||
exit(1);
|
switch (cctx->exittype) {
|
||||||
|
case CCTX_DIED:
|
||||||
|
printf("[lost server]\n");
|
||||||
|
return (0);
|
||||||
|
case CCTX_SHUTDOWN:
|
||||||
|
printf("[server exited]\n");
|
||||||
|
return (0);
|
||||||
|
case CCTX_EXIT:
|
||||||
|
if (cctx->errstr != NULL) {
|
||||||
|
printf("[error: %s]\n", cctx->errstr);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
printf("[exited]\n");
|
||||||
|
return (0);
|
||||||
|
case CCTX_DETACH:
|
||||||
|
printf("[detached]\n");
|
||||||
|
return (0);
|
||||||
|
default:
|
||||||
|
printf("[unknown error]\n");
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
exit(0);
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_handle_winch(struct client_ctx *cctx)
|
||||||
|
{
|
||||||
|
struct msg_resize_data data;
|
||||||
|
struct winsize ws;
|
||||||
|
|
||||||
|
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
||||||
|
fatal("ioctl failed");
|
||||||
|
|
||||||
|
data.sx = ws.ws_col;
|
||||||
|
data.sy = ws.ws_row;
|
||||||
|
client_write_server(cctx, MSG_RESIZE, &data, sizeof data);
|
||||||
|
|
||||||
|
sigwinch = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
client_dispatch(void)
|
client_msg_dispatch(struct client_ctx *cctx)
|
||||||
{
|
{
|
||||||
struct imsg imsg;
|
struct imsg imsg;
|
||||||
struct msg_lock_data lockdata;
|
struct msg_print_data printdata;
|
||||||
ssize_t n, datalen;
|
ssize_t n, datalen;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
|
if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1)
|
||||||
fatalx("imsg_get failed");
|
fatalx("imsg_get failed");
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -258,15 +282,25 @@ client_dispatch(void)
|
|||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
fatalx("bad MSG_DETACH size");
|
fatalx("bad MSG_DETACH size");
|
||||||
|
|
||||||
client_write_server(MSG_EXITING, NULL, 0);
|
client_write_server(cctx, MSG_EXITING, NULL, 0);
|
||||||
client_exitmsg = "detached";
|
cctx->exittype = CCTX_DETACH;
|
||||||
break;
|
break;
|
||||||
|
case MSG_ERROR:
|
||||||
|
if (datalen != sizeof printdata)
|
||||||
|
fatalx("bad MSG_ERROR size");
|
||||||
|
memcpy(&printdata, imsg.data, sizeof printdata);
|
||||||
|
|
||||||
|
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
|
||||||
|
/* Error string used after exit message from server. */
|
||||||
|
cctx->errstr = xstrdup(printdata.msg);
|
||||||
|
imsg_free(&imsg);
|
||||||
|
return (-1);
|
||||||
case MSG_EXIT:
|
case MSG_EXIT:
|
||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
fatalx("bad MSG_EXIT size");
|
fatalx("bad MSG_EXIT size");
|
||||||
|
|
||||||
client_write_server(MSG_EXITING, NULL, 0);
|
client_write_server(cctx, MSG_EXITING, NULL, 0);
|
||||||
client_exitmsg = "exited";
|
cctx->exittype = CCTX_EXIT;
|
||||||
break;
|
break;
|
||||||
case MSG_EXITED:
|
case MSG_EXITED:
|
||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
@@ -278,8 +312,8 @@ client_dispatch(void)
|
|||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
fatalx("bad MSG_SHUTDOWN size");
|
fatalx("bad MSG_SHUTDOWN size");
|
||||||
|
|
||||||
client_write_server(MSG_EXITING, NULL, 0);
|
client_write_server(cctx, MSG_EXITING, NULL, 0);
|
||||||
client_exitmsg = "server exited";
|
cctx->exittype = CCTX_SHUTDOWN;
|
||||||
break;
|
break;
|
||||||
case MSG_SUSPEND:
|
case MSG_SUSPEND:
|
||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
@@ -287,15 +321,6 @@ client_dispatch(void)
|
|||||||
|
|
||||||
client_suspend();
|
client_suspend();
|
||||||
break;
|
break;
|
||||||
case MSG_LOCK:
|
|
||||||
if (datalen != sizeof lockdata)
|
|
||||||
fatalx("bad MSG_LOCK size");
|
|
||||||
memcpy(&lockdata, imsg.data, sizeof lockdata);
|
|
||||||
|
|
||||||
lockdata.cmd[(sizeof lockdata.cmd) - 1] = '\0';
|
|
||||||
system(lockdata.cmd);
|
|
||||||
client_write_server(MSG_UNLOCK, NULL, 0);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
fatalx("unexpected message");
|
fatalx("unexpected message");
|
||||||
}
|
}
|
||||||
@@ -303,23 +328,3 @@ client_dispatch(void)
|
|||||||
imsg_free(&imsg);
|
imsg_free(&imsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
client_suspend(void)
|
|
||||||
{
|
|
||||||
struct sigaction act;
|
|
||||||
|
|
||||||
memset(&act, 0, sizeof act);
|
|
||||||
sigemptyset(&act.sa_mask);
|
|
||||||
act.sa_flags = SA_RESTART;
|
|
||||||
|
|
||||||
act.sa_handler = SIG_DFL;
|
|
||||||
if (sigaction(SIGTSTP, &act, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
|
|
||||||
act.sa_handler = sighandler;
|
|
||||||
if (sigaction(SIGCONT, &act, NULL) != 0)
|
|
||||||
fatal("sigaction failed");
|
|
||||||
|
|
||||||
kill(getpid(), SIGTSTP);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-break-pane.c,v 1.9 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-break-pane.c,v 1.8 2009-08-16 19:16:27 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -78,7 +78,6 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
session_select(s, wl->idx);
|
session_select(s, wl->idx);
|
||||||
|
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
server_status_session_group(s);
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-choose-session.c,v 1.14 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-choose-session.c,v 1.13 2009-09-07 23:59:19 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -54,9 +54,7 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct cmd_choose_session_data *cdata;
|
struct cmd_choose_session_data *cdata;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct session_group *sg;
|
|
||||||
u_int i, idx, cur;
|
u_int i, idx, cur;
|
||||||
char tmp[64];
|
|
||||||
|
|
||||||
if (ctx->curclient == NULL) {
|
if (ctx->curclient == NULL) {
|
||||||
ctx->error(ctx, "must be run interactively");
|
ctx->error(ctx, "must be run interactively");
|
||||||
@@ -78,18 +76,10 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
cur = idx;
|
cur = idx;
|
||||||
idx++;
|
idx++;
|
||||||
|
|
||||||
sg = session_group_find(s);
|
|
||||||
if (sg == NULL)
|
|
||||||
*tmp = '\0';
|
|
||||||
else {
|
|
||||||
idx = session_group_index(sg);
|
|
||||||
xsnprintf(tmp, sizeof tmp, " (group %u)", idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
window_choose_add(wl->window->active, i,
|
window_choose_add(wl->window->active, i,
|
||||||
"%s: %u windows [%ux%u]%s%s", s->name,
|
"%s: %u windows [%ux%u]%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)");
|
s->flags & SESSION_UNATTACHED ? "" : " (attached)");
|
||||||
}
|
}
|
||||||
|
|
||||||
cdata = xmalloc(sizeof *cdata);
|
cdata = xmalloc(sizeof *cdata);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-choose-window.c,v 1.18 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-choose-window.c,v 1.17 2009-09-07 23:59:19 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -89,7 +89,7 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
flag = '+';
|
flag = '+';
|
||||||
else if (wm == s->curw)
|
else if (wm == s->curw)
|
||||||
flag = '*';
|
flag = '*';
|
||||||
else if (wm == TAILQ_FIRST(&s->lastw))
|
else if (wm == SLIST_FIRST(&s->lastw))
|
||||||
flag = '-';
|
flag = '-';
|
||||||
|
|
||||||
title = w->active->screen->title;
|
title = w->active->screen->title;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-command-prompt.c,v 1.26 2009-09-22 14:06:40 tcunha Exp $ */
|
/* $Id: cmd-command-prompt.c,v 1.25 2009-08-25 13:53:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -90,7 +90,7 @@ cmd_command_prompt_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
struct cmd_command_prompt_data *data;
|
struct cmd_command_prompt_data *data;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
self->entry->init(self, KEYC_NONE);
|
self->entry->init(self, 0);
|
||||||
data = self->data;
|
data = self->data;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "p:t:")) != -1) {
|
while ((opt = getopt(argc, argv, "p:t:")) != -1) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-copy-buffer.c,v 1.5 2009-09-22 14:06:40 tcunha Exp $ */
|
/* $Id: cmd-copy-buffer.c,v 1.4 2009-09-07 23:48:54 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -70,7 +70,7 @@ cmd_copy_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
const char *errstr;
|
const char *errstr;
|
||||||
int n, opt;
|
int n, opt;
|
||||||
|
|
||||||
self->entry->init(self, KEYC_NONE);
|
self->entry->init(self, 0);
|
||||||
data = self->data;
|
data = self->data;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "a:b:s:t:")) != -1) {
|
while ((opt = getopt(argc, argv, "a:b:s:t:")) != -1) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-copy-mode.c,v 1.24 2009-10-06 14:14:06 tcunha Exp $ */
|
/* $Id: cmd-copy-mode.c,v 1.23 2009-08-20 11:37:46 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -24,35 +24,19 @@
|
|||||||
* Enter copy mode.
|
* Enter copy mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void cmd_copy_mode_init(struct cmd *, int);
|
|
||||||
int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
|
int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_copy_mode_entry = {
|
const struct cmd_entry cmd_copy_mode_entry = {
|
||||||
"copy-mode", NULL,
|
"copy-mode", NULL,
|
||||||
"[-u] " CMD_TARGET_PANE_USAGE,
|
"[-u] " CMD_TARGET_PANE_USAGE,
|
||||||
0, CMD_CHFLAG('u'),
|
0, CMD_CHFLAG('u'),
|
||||||
cmd_copy_mode_init,
|
cmd_target_init,
|
||||||
cmd_target_parse,
|
cmd_target_parse,
|
||||||
cmd_copy_mode_exec,
|
cmd_copy_mode_exec,
|
||||||
cmd_target_free,
|
cmd_target_free,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
|
||||||
cmd_copy_mode_init(struct cmd *self, int key)
|
|
||||||
{
|
|
||||||
struct cmd_target_data *data;
|
|
||||||
|
|
||||||
cmd_target_init(self, key);
|
|
||||||
data = self->data;
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case KEYC_PPAGE:
|
|
||||||
data->chflags |= CMD_CHFLAG('u');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
|
cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-display-message.c,v 1.3 2009-10-11 23:55:26 tcunha Exp $ */
|
/* $Id: cmd-display-message.c,v 1.2 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -55,7 +55,7 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
else
|
else
|
||||||
template = data->arg;
|
template = data->arg;
|
||||||
|
|
||||||
msg = status_replace(c, template, time(NULL));
|
msg = status_replace(c->session, template, time(NULL));
|
||||||
status_message_set(c, "%s", msg);
|
status_message_set(c, "%s", msg);
|
||||||
xfree(msg);
|
xfree(msg);
|
||||||
|
|
||||||
|
|||||||
146
cmd-if-shell.c
146
cmd-if-shell.c
@@ -1,8 +1,7 @@
|
|||||||
/* $Id: cmd-if-shell.c,v 1.7 2009-11-02 21:38:26 tcunha Exp $ */
|
/* $Id: cmd-if-shell.c,v 1.4 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@openbsd.org>
|
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -18,8 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@@ -28,90 +28,124 @@
|
|||||||
* Executes a tmux command if a shell command returns true.
|
* Executes a tmux command if a shell command returns true.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int cmd_if_shell_parse(struct cmd *, int, char **, char **);
|
||||||
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
|
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
void cmd_if_shell_free(struct cmd *);
|
||||||
|
void cmd_if_shell_init(struct cmd *, int);
|
||||||
|
size_t cmd_if_shell_print(struct cmd *, char *, size_t);
|
||||||
|
|
||||||
void cmd_if_shell_callback(struct job *);
|
struct cmd_if_shell_data {
|
||||||
void cmd_if_shell_free(void *);
|
char *cmd;
|
||||||
|
char *sh_cmd;
|
||||||
|
};
|
||||||
|
|
||||||
const struct cmd_entry cmd_if_shell_entry = {
|
const struct cmd_entry cmd_if_shell_entry = {
|
||||||
"if-shell", "if",
|
"if-shell", "if",
|
||||||
"shell-command command",
|
"shell-command command",
|
||||||
CMD_ARG2, 0,
|
0, 0,
|
||||||
cmd_target_init,
|
cmd_if_shell_init,
|
||||||
cmd_target_parse,
|
cmd_if_shell_parse,
|
||||||
cmd_if_shell_exec,
|
cmd_if_shell_exec,
|
||||||
cmd_target_free,
|
cmd_if_shell_free,
|
||||||
cmd_target_print
|
cmd_if_shell_print
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cmd_if_shell_data {
|
void
|
||||||
char *cmd;
|
cmd_if_shell_init(struct cmd *self, unused int arg)
|
||||||
struct cmd_ctx ctx;
|
{
|
||||||
};
|
struct cmd_if_shell_data *data;
|
||||||
|
|
||||||
|
self->data = data = xmalloc(sizeof *data);
|
||||||
|
data->cmd = NULL;
|
||||||
|
data->sh_cmd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cmd_if_shell_parse(struct cmd *self, int argc, char **argv, char **cause)
|
||||||
|
{
|
||||||
|
struct cmd_if_shell_data *data;
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
self->entry->init(self, 0);
|
||||||
|
data = self->data;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
default:
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
if (argc != 2)
|
||||||
|
goto usage;
|
||||||
|
|
||||||
|
data->sh_cmd = xstrdup(argv[0]);
|
||||||
|
data->cmd = xstrdup(argv[1]);
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
usage:
|
||||||
|
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
|
||||||
|
|
||||||
|
self->entry->free(self);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
|
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct cmd_target_data *data = self->data;
|
struct cmd_if_shell_data *data = self->data;
|
||||||
struct cmd_if_shell_data *cdata;
|
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
cdata = xmalloc(sizeof *cdata);
|
|
||||||
cdata->cmd = xstrdup(data->arg2);
|
|
||||||
memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
|
|
||||||
|
|
||||||
if (ctx->cmdclient != NULL)
|
|
||||||
ctx->cmdclient->references++;
|
|
||||||
if (ctx->curclient != NULL)
|
|
||||||
ctx->curclient->references++;
|
|
||||||
|
|
||||||
job = job_add(NULL, 0, NULL,
|
|
||||||
data->arg, cmd_if_shell_callback, cmd_if_shell_free, cdata);
|
|
||||||
job_run(job);
|
|
||||||
|
|
||||||
return (1); /* don't let client exit */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
cmd_if_shell_callback(struct job *job)
|
|
||||||
{
|
|
||||||
struct cmd_if_shell_data *cdata = job->data;
|
|
||||||
struct cmd_ctx *ctx = &cdata->ctx;
|
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
char *cause;
|
char *cause;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
|
if ((ret = system(data->sh_cmd)) < 0) {
|
||||||
return;
|
ctx->error(ctx, "system error: %s", strerror(errno));
|
||||||
|
return (-1);
|
||||||
|
} else if (ret != 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
|
if (cmd_string_parse(data->cmd, &cmdlist, &cause) != 0) {
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
ctx->error(ctx, "%s", cause);
|
ctx->error(ctx, "%s", cause);
|
||||||
xfree(cause);
|
xfree(cause);
|
||||||
}
|
}
|
||||||
return;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd_list_exec(cmdlist, ctx) < 0) {
|
if (cmd_list_exec(cmdlist, ctx) < 0) {
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
return;
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cmd_if_shell_free(void *data)
|
cmd_if_shell_free(struct cmd *self)
|
||||||
{
|
{
|
||||||
struct cmd_if_shell_data *cdata = data;
|
struct cmd_if_shell_data *data = self->data;
|
||||||
struct cmd_ctx *ctx = &cdata->ctx;
|
|
||||||
|
|
||||||
if (ctx->cmdclient != NULL) {
|
if (data->cmd != NULL)
|
||||||
ctx->cmdclient->references--;
|
xfree(data->cmd);
|
||||||
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
|
if (data->sh_cmd != NULL)
|
||||||
}
|
xfree(data->sh_cmd);
|
||||||
if (ctx->curclient != NULL)
|
xfree(data);
|
||||||
ctx->curclient->references--;
|
}
|
||||||
|
|
||||||
xfree(cdata->cmd);
|
size_t
|
||||||
xfree(cdata);
|
cmd_if_shell_print(struct cmd *self, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct cmd_if_shell_data *data = self->data;
|
||||||
|
size_t off = 0;
|
||||||
|
|
||||||
|
off += xsnprintf(buf, len, "%s", self->entry->name);
|
||||||
|
if (data == NULL)
|
||||||
|
return (off);
|
||||||
|
if (off < len && data->sh_cmd != NULL)
|
||||||
|
off += cmd_prarg(buf + off, len - off, " ", data->sh_cmd);
|
||||||
|
if (off < len && data->cmd != NULL)
|
||||||
|
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
|
||||||
|
return (off);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-kill-pane.c,v 1.14 2009-10-25 10:41:03 tcunha Exp $ */
|
/* $Id: cmd-kill-pane.c,v 1.12 2009-07-30 20:45:20 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -30,8 +30,8 @@ int cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_kill_pane_entry = {
|
const struct cmd_entry cmd_kill_pane_entry = {
|
||||||
"kill-pane", "killp",
|
"kill-pane", "killp",
|
||||||
"[-a] " CMD_TARGET_PANE_USAGE,
|
CMD_TARGET_PANE_USAGE,
|
||||||
0, CMD_CHFLAG('a'),
|
0, 0,
|
||||||
cmd_target_init,
|
cmd_target_init,
|
||||||
cmd_target_parse,
|
cmd_target_parse,
|
||||||
cmd_kill_pane_exec,
|
cmd_kill_pane_exec,
|
||||||
@@ -44,7 +44,7 @@ cmd_kill_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;
|
||||||
struct window_pane *loopwp, *nextwp, *wp;
|
struct window_pane *wp;
|
||||||
|
|
||||||
if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
|
if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -52,25 +52,11 @@ cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if (window_count_panes(wl->window) == 1) {
|
if (window_count_panes(wl->window) == 1) {
|
||||||
/* Only one pane, kill the window. */
|
/* Only one pane, kill the window. */
|
||||||
server_kill_window(wl->window);
|
server_kill_window(wl->window);
|
||||||
recalculate_sizes();
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->chflags & CMD_CHFLAG('a')) {
|
layout_close_pane(wp);
|
||||||
loopwp = TAILQ_FIRST(&wl->window->panes);
|
window_remove_pane(wl->window, wp);
|
||||||
while (loopwp != NULL) {
|
|
||||||
nextwp = TAILQ_NEXT(loopwp, entry);
|
|
||||||
if (loopwp != wp) {
|
|
||||||
layout_close_pane(loopwp);
|
|
||||||
window_remove_pane(wl->window, loopwp);
|
|
||||||
}
|
|
||||||
loopwp = nextwp;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
layout_close_pane(wp);
|
|
||||||
window_remove_pane(wl->window, wp);
|
|
||||||
}
|
|
||||||
server_redraw_window(wl->window);
|
server_redraw_window(wl->window);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-kill-session.c,v 1.15 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-kill-session.c,v 1.14 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -53,7 +53,7 @@ cmd_kill_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
|
|
||||||
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->session == s) {
|
||||||
c->session = NULL;
|
c->session = NULL;
|
||||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-kill-window.c,v 1.20 2009-09-20 22:15:32 tcunha Exp $ */
|
/* $Id: cmd-kill-window.c,v 1.19 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -47,7 +47,6 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
server_kill_window(wl->window);
|
server_kill_window(wl->window);
|
||||||
recalculate_sizes();
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-link-window.c,v 1.35 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-link-window.c,v 1.32 2009-08-16 19:16:27 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -43,23 +43,55 @@ int
|
|||||||
cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct cmd_srcdst_data *data = self->data;
|
struct cmd_srcdst_data *data = self->data;
|
||||||
struct session *src, *dst;
|
struct session *dst;
|
||||||
struct winlink *wl;
|
struct winlink *wl_src, *wl_dst;
|
||||||
char *cause;
|
char *cause;
|
||||||
int idx, kflag, dflag;
|
int idx;
|
||||||
|
|
||||||
if ((wl = cmd_find_window(ctx, data->src, &src)) == NULL)
|
if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
|
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
kflag = data->chflags & CMD_CHFLAG('k');
|
wl_dst = NULL;
|
||||||
dflag = data->chflags & CMD_CHFLAG('d');
|
if (idx != -1)
|
||||||
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
|
wl_dst = winlink_find_by_index(&dst->windows, idx);
|
||||||
ctx->error(ctx, "can't link window: %s", cause);
|
if (wl_dst != NULL) {
|
||||||
|
if (wl_dst->window == wl_src->window)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if (data->chflags & CMD_CHFLAG('k')) {
|
||||||
|
/*
|
||||||
|
* Can't use session_detach as it will destroy session
|
||||||
|
* if this makes it empty.
|
||||||
|
*/
|
||||||
|
session_alert_cancel(dst, wl_dst);
|
||||||
|
winlink_stack_remove(&dst->lastw, wl_dst);
|
||||||
|
winlink_remove(&dst->windows, wl_dst);
|
||||||
|
|
||||||
|
/* Force select/redraw if current. */
|
||||||
|
if (wl_dst == dst->curw) {
|
||||||
|
data->chflags &= ~CMD_CHFLAG('d');
|
||||||
|
dst->curw = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == -1)
|
||||||
|
idx = -1 - options_get_number(&dst->options, "base-index");
|
||||||
|
wl_dst = session_attach(dst, wl_src->window, idx, &cause);
|
||||||
|
if (wl_dst == NULL) {
|
||||||
|
ctx->error(ctx, "create session failed: %s", cause);
|
||||||
xfree(cause);
|
xfree(cause);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->chflags & CMD_CHFLAG('d'))
|
||||||
|
server_status_session(dst);
|
||||||
|
else {
|
||||||
|
session_select(dst, wl_dst->idx);
|
||||||
|
server_redraw_session(dst);
|
||||||
|
}
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
/* $Id: cmd-list-panes.c,v 1.2 2009-10-15 20:10:28 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 <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List panes on given window..
|
|
||||||
*/
|
|
||||||
|
|
||||||
int cmd_list_panes_exec(struct cmd *, struct cmd_ctx *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_list_panes_entry = {
|
|
||||||
"list-panes", "lsp",
|
|
||||||
CMD_TARGET_WINDOW_USAGE,
|
|
||||||
0, 0,
|
|
||||||
cmd_target_init,
|
|
||||||
cmd_target_parse,
|
|
||||||
cmd_list_panes_exec,
|
|
||||||
cmd_target_free,
|
|
||||||
cmd_target_print
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct cmd_target_data *data = self->data;
|
|
||||||
struct winlink *wl;
|
|
||||||
struct window_pane *wp;
|
|
||||||
struct grid *gd;
|
|
||||||
struct grid_line *gl;
|
|
||||||
u_int i, n;
|
|
||||||
unsigned long long size;
|
|
||||||
|
|
||||||
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
|
||||||
gd = wp->base.grid;
|
|
||||||
|
|
||||||
size = 0;
|
|
||||||
for (i = 0; i < gd->hsize; i++) {
|
|
||||||
gl = &gd->linedata[i];
|
|
||||||
size += gl->cellsize * sizeof *gl->celldata;
|
|
||||||
size += gl->utf8size * sizeof *gl->utf8data;
|
|
||||||
}
|
|
||||||
size += gd->hsize * sizeof *gd->linedata;
|
|
||||||
|
|
||||||
ctx->print(ctx, "%u: [%ux%u] [history %u/%u, %llu bytes]",
|
|
||||||
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-sessions.c,v 1.23 2009-11-04 22:42:31 tcunha Exp $ */
|
/* $Id: cmd-list-sessions.c,v 1.21 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -42,32 +42,23 @@ const struct cmd_entry cmd_list_sessions_entry = {
|
|||||||
int
|
int
|
||||||
cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct session_group *sg;
|
char *tim;
|
||||||
char *tim, tmp[64];
|
u_int i;
|
||||||
u_int i, idx;
|
time_t t;
|
||||||
time_t t;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sg = session_group_find(s);
|
t = s->tv.tv_sec;
|
||||||
if (sg == NULL)
|
|
||||||
*tmp = '\0';
|
|
||||||
else {
|
|
||||||
idx = session_group_index(sg);
|
|
||||||
xsnprintf(tmp, sizeof tmp, " (group %u)", idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
t = s->creation_time.tv_sec;
|
|
||||||
tim = ctime(&t);
|
tim = ctime(&t);
|
||||||
*strchr(tim, '\n') = '\0';
|
*strchr(tim, '\n') = '\0';
|
||||||
|
|
||||||
ctx->print(ctx, "%s: %u windows (created %s) [%ux%u]%s%s",
|
ctx->print(ctx, "%s: %u windows (created %s) [%ux%u]%s",
|
||||||
s->name, winlink_count(&s->windows), tim, s->sx, s->sy,
|
s->name, winlink_count(&s->windows), tim, s->sx, s->sy,
|
||||||
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
|
s->flags & SESSION_UNATTACHED ? "" : " (attached)");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-windows.c,v 1.41 2009-10-12 00:08:12 tcunha Exp $ */
|
/* $Id: cmd-list-windows.c,v 1.40 2009-08-09 17:28:23 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -45,13 +45,42 @@ 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;
|
||||||
|
struct window *w;
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct grid *gd;
|
||||||
|
struct grid_line *gl;
|
||||||
|
u_int i;
|
||||||
|
unsigned long long size;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
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) {
|
||||||
ctx->print(ctx, "%d: %s [%ux%u]",
|
w = wl->window;
|
||||||
wl->idx, wl->window->name, wl->window->sx, wl->window->sy);
|
ctx->print(ctx,
|
||||||
|
"%3d: %s [%ux%u]", wl->idx, w->name, w->sx, w->sy);
|
||||||
|
|
||||||
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
|
gd = wp->base.grid;
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
for (i = 0; i < gd->hsize; i++) {
|
||||||
|
gl = &gd->linedata[i];
|
||||||
|
size += gl->cellsize * sizeof *gl->celldata;
|
||||||
|
size += gl->utf8size * sizeof *gl->utf8data;
|
||||||
|
}
|
||||||
|
size += gd->hsize * sizeof *gd->linedata;
|
||||||
|
|
||||||
|
name = NULL;
|
||||||
|
if (wp->fd != -1)
|
||||||
|
name = ttyname(wp->fd);
|
||||||
|
if (name == NULL)
|
||||||
|
name = "unknown";
|
||||||
|
ctx->print(ctx,
|
||||||
|
" %s [%ux%u] [history %u/%u, %llu bytes]",
|
||||||
|
name, wp->sx, wp->sy, gd->hsize, gd->hlimit, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-load-buffer.c,v 1.11 2009-10-28 23:10:05 tcunha Exp $ */
|
/* $Id: cmd-load-buffer.c,v 1.10 2009-09-07 23:48:54 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -56,14 +56,13 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if ((f = fopen(data->arg, "rb")) == NULL) {
|
if (stat(data->arg, &sb) < 0) {
|
||||||
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat(fileno(f), &sb) < 0) {
|
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));
|
||||||
fclose(f);
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
/* $Id: cmd-lock-client.c,v 1.1 2009-09-25 17:51:39 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"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lock a single client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int cmd_lock_client_exec(struct cmd *, struct cmd_ctx *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_lock_client_entry = {
|
|
||||||
"lock-client", "lockc",
|
|
||||||
CMD_TARGET_CLIENT_USAGE,
|
|
||||||
0, 0,
|
|
||||||
cmd_target_init,
|
|
||||||
cmd_target_parse,
|
|
||||||
cmd_lock_client_exec,
|
|
||||||
cmd_target_free,
|
|
||||||
cmd_target_print
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
cmd_lock_client_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct cmd_target_data *data = self->data;
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if ((c = cmd_find_client(ctx, data->target)) == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
server_lock_client(c);
|
|
||||||
recalculate_sizes();
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-lock-server.c,v 1.7 2009-09-25 17:47:42 tcunha Exp $ */
|
/* $Id: cmd-lock-server.c,v 1.6 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -45,7 +45,6 @@ int
|
|||||||
cmd_lock_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx)
|
cmd_lock_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
server_lock();
|
server_lock();
|
||||||
recalculate_sizes();
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-move-window.c,v 1.12 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-move-window.c,v 1.9 2009-08-16 19:16:27 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -44,23 +44,68 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
{
|
{
|
||||||
struct cmd_srcdst_data *data = self->data;
|
struct cmd_srcdst_data *data = self->data;
|
||||||
struct session *src, *dst;
|
struct session *src, *dst;
|
||||||
struct winlink *wl;
|
struct winlink *wl_src, *wl_dst;
|
||||||
|
struct client *c;
|
||||||
|
u_int i;
|
||||||
|
int destroyed, idx;
|
||||||
char *cause;
|
char *cause;
|
||||||
int idx, kflag, dflag;
|
|
||||||
|
|
||||||
if ((wl = cmd_find_window(ctx, data->src, &src)) == NULL)
|
if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
|
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
kflag = data->chflags & CMD_CHFLAG('k');
|
wl_dst = NULL;
|
||||||
dflag = data->chflags & CMD_CHFLAG('d');
|
if (idx != -1)
|
||||||
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
|
wl_dst = winlink_find_by_index(&dst->windows, idx);
|
||||||
ctx->error(ctx, "can't move window: %s", cause);
|
if (wl_dst != NULL) {
|
||||||
|
if (wl_dst->window == wl_src->window)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if (data->chflags & CMD_CHFLAG('k')) {
|
||||||
|
/*
|
||||||
|
* Can't use session_detach as it will destroy session
|
||||||
|
* if this makes it empty.
|
||||||
|
*/
|
||||||
|
session_alert_cancel(dst, wl_dst);
|
||||||
|
winlink_stack_remove(&dst->lastw, wl_dst);
|
||||||
|
winlink_remove(&dst->windows, wl_dst);
|
||||||
|
|
||||||
|
/* Force select/redraw if current. */
|
||||||
|
if (wl_dst == dst->curw) {
|
||||||
|
data->chflags &= ~CMD_CHFLAG('d');
|
||||||
|
dst->curw = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == -1)
|
||||||
|
idx = -1 - options_get_number(&dst->options, "base-index");
|
||||||
|
wl_dst = session_attach(dst, wl_src->window, idx, &cause);
|
||||||
|
if (wl_dst == NULL) {
|
||||||
|
ctx->error(ctx, "attach window failed: %s", cause);
|
||||||
xfree(cause);
|
xfree(cause);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
server_unlink_window(src, wl);
|
|
||||||
|
destroyed = session_detach(src, wl_src);
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
|
c = ARRAY_ITEM(&clients, i);
|
||||||
|
if (c == NULL || c->session != src)
|
||||||
|
continue;
|
||||||
|
if (destroyed) {
|
||||||
|
c->session = NULL;
|
||||||
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
|
} else
|
||||||
|
server_redraw_client(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->chflags & CMD_CHFLAG('d'))
|
||||||
|
server_status_session(dst);
|
||||||
|
else {
|
||||||
|
session_select(dst, wl_dst->idx);
|
||||||
|
server_redraw_session(dst);
|
||||||
|
}
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-new-session.c,v 1.69 2009-10-12 00:49:06 tcunha Exp $ */
|
/* $Id: cmd-new-session.c,v 1.66 2009-09-16 12:36:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@@ -34,7 +35,6 @@ void cmd_new_session_init(struct cmd *, int);
|
|||||||
size_t cmd_new_session_print(struct cmd *, char *, size_t);
|
size_t cmd_new_session_print(struct cmd *, char *, size_t);
|
||||||
|
|
||||||
struct cmd_new_session_data {
|
struct cmd_new_session_data {
|
||||||
char *target;
|
|
||||||
char *newname;
|
char *newname;
|
||||||
char *winname;
|
char *winname;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
@@ -43,7 +43,7 @@ struct cmd_new_session_data {
|
|||||||
|
|
||||||
const struct cmd_entry cmd_new_session_entry = {
|
const struct cmd_entry cmd_new_session_entry = {
|
||||||
"new-session", "new",
|
"new-session", "new",
|
||||||
"[-d] [-n window-name] [-s session-name] [-t target-session] [command]",
|
"[-d] [-n window-name] [-s session-name] [command]",
|
||||||
CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON, 0,
|
CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON, 0,
|
||||||
cmd_new_session_init,
|
cmd_new_session_init,
|
||||||
cmd_new_session_parse,
|
cmd_new_session_parse,
|
||||||
@@ -59,7 +59,6 @@ cmd_new_session_init(struct cmd *self, unused int arg)
|
|||||||
|
|
||||||
self->data = data = xmalloc(sizeof *data);
|
self->data = data = xmalloc(sizeof *data);
|
||||||
data->flag_detached = 0;
|
data->flag_detached = 0;
|
||||||
data->target = NULL;
|
|
||||||
data->newname = NULL;
|
data->newname = NULL;
|
||||||
data->winname = NULL;
|
data->winname = NULL;
|
||||||
data->cmd = NULL;
|
data->cmd = NULL;
|
||||||
@@ -71,10 +70,10 @@ cmd_new_session_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
struct cmd_new_session_data *data;
|
struct cmd_new_session_data *data;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
self->entry->init(self, KEYC_NONE);
|
self->entry->init(self, 0);
|
||||||
data = self->data;
|
data = self->data;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "ds:t:n:")) != -1) {
|
while ((opt = getopt(argc, argv, "ds:n:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'd':
|
case 'd':
|
||||||
data->flag_detached = 1;
|
data->flag_detached = 1;
|
||||||
@@ -83,10 +82,6 @@ cmd_new_session_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
if (data->newname == NULL)
|
if (data->newname == NULL)
|
||||||
data->newname = xstrdup(optarg);
|
data->newname = xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
case 't':
|
|
||||||
if (data->target == NULL)
|
|
||||||
data->target = xstrdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'n':
|
case 'n':
|
||||||
if (data->winname == NULL)
|
if (data->winname == NULL)
|
||||||
data->winname = xstrdup(optarg);
|
data->winname = xstrdup(optarg);
|
||||||
@@ -100,9 +95,6 @@ cmd_new_session_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
if (argc != 0 && argc != 1)
|
if (argc != 0 && argc != 1)
|
||||||
goto usage;
|
goto usage;
|
||||||
|
|
||||||
if (data->target != NULL && (argc == 1 || data->winname != NULL))
|
|
||||||
goto usage;
|
|
||||||
|
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
data->cmd = xstrdup(argv[0]);
|
data->cmd = xstrdup(argv[0]);
|
||||||
|
|
||||||
@@ -119,7 +111,7 @@ 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, *groupwith;
|
struct session *s;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct environ env;
|
struct environ env;
|
||||||
struct termios tio, *tiop;
|
struct termios tio, *tiop;
|
||||||
@@ -133,11 +125,6 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
groupwith = NULL;
|
|
||||||
if (data->target != NULL &&
|
|
||||||
(groupwith = cmd_find_session(ctx, data->target)) == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are three cases:
|
* There are three cases:
|
||||||
*
|
*
|
||||||
@@ -218,9 +205,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
sy = 1;
|
sy = 1;
|
||||||
|
|
||||||
/* Figure out the command for the new window. */
|
/* Figure out the command for the new window. */
|
||||||
if (data->target != NULL)
|
if (data->cmd != NULL)
|
||||||
cmd = NULL;
|
|
||||||
else if (data->cmd != NULL)
|
|
||||||
cmd = data->cmd;
|
cmd = data->cmd;
|
||||||
else
|
else
|
||||||
cmd = options_get_string(&global_s_options, "default-command");
|
cmd = options_get_string(&global_s_options, "default-command");
|
||||||
@@ -243,7 +228,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
environ_free(&env);
|
environ_free(&env);
|
||||||
|
|
||||||
/* Set the initial window name if one given. */
|
/* Set the initial window name if one given. */
|
||||||
if (cmd != NULL && data->winname != NULL) {
|
if (data->winname != NULL) {
|
||||||
w = s->curw->window;
|
w = s->curw->window;
|
||||||
|
|
||||||
xfree(w->name);
|
xfree(w->name);
|
||||||
@@ -252,16 +237,6 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
options_set_number(&w->options, "automatic-rename", 0);
|
options_set_number(&w->options, "automatic-rename", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If a target session is given, this is to be part of a session group,
|
|
||||||
* so add it to the group and synchronize.
|
|
||||||
*/
|
|
||||||
if (groupwith != NULL) {
|
|
||||||
session_group_add(groupwith, s);
|
|
||||||
session_group_synchronize_to(s);
|
|
||||||
session_select(s, RB_ROOT(&s->windows)->idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the client to the new session. If a command client exists, it is
|
* Set the client to the new session. If a command client exists, it is
|
||||||
* taking this session and needs to get MSG_READY and stay around.
|
* taking this session and needs to get MSG_READY and stay around.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-new-window.c,v 1.39 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-new-window.c,v 1.37 2009-08-16 19:16:27 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -70,7 +70,7 @@ cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
struct cmd_new_window_data *data;
|
struct cmd_new_window_data *data;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
self->entry->init(self, KEYC_NONE);
|
self->entry->init(self, 0);
|
||||||
data = self->data;
|
data = self->data;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "dkt:n:")) != -1) {
|
while ((opt = getopt(argc, argv, "dkt:n:")) != -1) {
|
||||||
@@ -164,9 +164,9 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
if (!data->flag_detached) {
|
if (!data->flag_detached) {
|
||||||
session_select(s, wl->idx);
|
session_select(s, wl->idx);
|
||||||
server_redraw_session_group(s);
|
server_redraw_session(s);
|
||||||
} else
|
} else
|
||||||
server_status_session_group(s);
|
server_status_session(s);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
125
cmd-pipe-pane.c
125
cmd-pipe-pane.c
@@ -1,125 +0,0 @@
|
|||||||
/* $Id: cmd-pipe-pane.c,v 1.3 2009-10-23 17:26:40 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 <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open pipe to redirect pane output. If already open, close first.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int cmd_pipe_pane_exec(struct cmd *, struct cmd_ctx *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_pipe_pane_entry = {
|
|
||||||
"pipe-pane", "pipep",
|
|
||||||
CMD_TARGET_PANE_USAGE "[-o] [command]",
|
|
||||||
CMD_ARG01, CMD_CHFLAG('o'),
|
|
||||||
cmd_target_init,
|
|
||||||
cmd_target_parse,
|
|
||||||
cmd_pipe_pane_exec,
|
|
||||||
cmd_target_free,
|
|
||||||
cmd_target_print
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct cmd_target_data *data = self->data;
|
|
||||||
struct window_pane *wp;
|
|
||||||
int old_fd, pipe_fd[2], null_fd, mode;
|
|
||||||
|
|
||||||
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
/* Destroy the old pipe. */
|
|
||||||
old_fd = wp->pipe_fd;
|
|
||||||
if (wp->pipe_fd != -1) {
|
|
||||||
buffer_destroy(wp->pipe_buf);
|
|
||||||
close(wp->pipe_fd);
|
|
||||||
wp->pipe_fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If no pipe command, that is enough. */
|
|
||||||
if (data->arg == NULL || *data->arg == '\0')
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* With -o, only open the new pipe if there was no previous one. This
|
|
||||||
* allows a pipe to be toggled with a single key, for example:
|
|
||||||
*
|
|
||||||
* bind ^p pipep -o 'cat >>~/output'
|
|
||||||
*/
|
|
||||||
if (data->chflags & CMD_CHFLAG('o') && old_fd != -1)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
/* Open the new pipe. */
|
|
||||||
if (pipe(pipe_fd) != 0) {
|
|
||||||
ctx->error(ctx, "pipe error: %s", strerror(errno));
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fork the child. */
|
|
||||||
switch (fork()) {
|
|
||||||
case -1:
|
|
||||||
ctx->error(ctx, "fork error: %s", strerror(errno));
|
|
||||||
return (-1);
|
|
||||||
case 0:
|
|
||||||
/* Child process. */
|
|
||||||
close(pipe_fd[0]);
|
|
||||||
sigreset();
|
|
||||||
|
|
||||||
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
|
|
||||||
_exit(1);
|
|
||||||
if (pipe_fd[1] != STDIN_FILENO)
|
|
||||||
close(pipe_fd[1]);
|
|
||||||
|
|
||||||
null_fd = open(_PATH_DEVNULL, O_WRONLY, 0);
|
|
||||||
if (dup2(null_fd, STDOUT_FILENO) == -1)
|
|
||||||
_exit(1);
|
|
||||||
if (dup2(null_fd, STDERR_FILENO) == -1)
|
|
||||||
_exit(1);
|
|
||||||
if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO)
|
|
||||||
close(null_fd);
|
|
||||||
|
|
||||||
execl(_PATH_BSHELL, "sh", "-c", data->arg, (char *) NULL);
|
|
||||||
_exit(1);
|
|
||||||
default:
|
|
||||||
/* Parent process. */
|
|
||||||
close(pipe_fd[1]);
|
|
||||||
|
|
||||||
wp->pipe_fd = pipe_fd[0];
|
|
||||||
wp->pipe_buf = buffer_create(BUFSIZ);
|
|
||||||
wp->pipe_off = BUFFER_USED(wp->in);
|
|
||||||
|
|
||||||
if ((mode = fcntl(wp->pipe_fd, F_GETFL)) == -1)
|
|
||||||
fatal("fcntl failed");
|
|
||||||
if (fcntl(wp->pipe_fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
|
||||||
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-window.c,v 1.30 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-rename-window.c,v 1.29 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -53,7 +53,7 @@ cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
wl->window->name = xstrdup(data->arg);
|
wl->window->name = xstrdup(data->arg);
|
||||||
options_set_number(&wl->window->options, "automatic-rename", 0);
|
options_set_number(&wl->window->options, "automatic-rename", 0);
|
||||||
|
|
||||||
server_status_window(wl->window);
|
server_status_session(s);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
137
cmd-run-shell.c
137
cmd-run-shell.c
@@ -1,137 +0,0 @@
|
|||||||
/* $Id: cmd-run-shell.c,v 1.4 2009-11-02 21:38:26 tcunha Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@openbsd.org>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Runs a command without a window.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int cmd_run_shell_exec(struct cmd *, struct cmd_ctx *);
|
|
||||||
|
|
||||||
void cmd_run_shell_callback(struct job *);
|
|
||||||
void cmd_run_shell_free(void *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_run_shell_entry = {
|
|
||||||
"run-shell", "run",
|
|
||||||
"command",
|
|
||||||
CMD_ARG1, 0,
|
|
||||||
cmd_target_init,
|
|
||||||
cmd_target_parse,
|
|
||||||
cmd_run_shell_exec,
|
|
||||||
cmd_target_free,
|
|
||||||
cmd_target_print
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cmd_run_shell_data {
|
|
||||||
char *cmd;
|
|
||||||
struct cmd_ctx ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct cmd_target_data *data = self->data;
|
|
||||||
struct cmd_run_shell_data *cdata;
|
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
cdata = xmalloc(sizeof *cdata);
|
|
||||||
cdata->cmd = xstrdup(data->arg);
|
|
||||||
memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
|
|
||||||
|
|
||||||
if (ctx->cmdclient != NULL)
|
|
||||||
ctx->cmdclient->references++;
|
|
||||||
if (ctx->curclient != NULL)
|
|
||||||
ctx->curclient->references++;
|
|
||||||
|
|
||||||
job = job_add(NULL, 0, NULL,
|
|
||||||
data->arg, cmd_run_shell_callback, cmd_run_shell_free, cdata);
|
|
||||||
job_run(job);
|
|
||||||
|
|
||||||
return (1); /* don't let client exit */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
cmd_run_shell_callback(struct job *job)
|
|
||||||
{
|
|
||||||
struct cmd_run_shell_data *cdata = job->data;
|
|
||||||
struct cmd_ctx *ctx = &cdata->ctx;
|
|
||||||
char *cmd, *msg, *line, *buf;
|
|
||||||
size_t off, len, llen;
|
|
||||||
int retcode;
|
|
||||||
|
|
||||||
buf = BUFFER_OUT(job->out);
|
|
||||||
len = BUFFER_USED(job->out);
|
|
||||||
|
|
||||||
cmd = cdata->cmd;
|
|
||||||
|
|
||||||
if (len != 0) {
|
|
||||||
line = buf;
|
|
||||||
for (off = 0; off < len; off++) {
|
|
||||||
if (buf[off] == '\n') {
|
|
||||||
llen = buf + off - line;
|
|
||||||
if (llen > INT_MAX)
|
|
||||||
break;
|
|
||||||
ctx->print(ctx, "%.*s", (int) llen, line);
|
|
||||||
line = buf + off + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
llen = buf + len - line;
|
|
||||||
if (llen > 0 && llen < INT_MAX)
|
|
||||||
ctx->print(ctx, "%.*s", (int) llen, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = NULL;
|
|
||||||
if (WIFEXITED(job->status)) {
|
|
||||||
if ((retcode = WEXITSTATUS(job->status)) != 0)
|
|
||||||
xasprintf(&msg, "'%s' returned %d", cmd, retcode);
|
|
||||||
} else if (WIFSIGNALED(job->status)) {
|
|
||||||
retcode = WTERMSIG(job->status);
|
|
||||||
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
|
|
||||||
}
|
|
||||||
if (msg != NULL) {
|
|
||||||
if (len != 0)
|
|
||||||
ctx->print(ctx, "%s", msg);
|
|
||||||
else
|
|
||||||
ctx->info(ctx, "%s", msg);
|
|
||||||
xfree(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
cmd_run_shell_free(void *data)
|
|
||||||
{
|
|
||||||
struct cmd_run_shell_data *cdata = data;
|
|
||||||
struct cmd_ctx *ctx = &cdata->ctx;
|
|
||||||
|
|
||||||
if (ctx->cmdclient != NULL) {
|
|
||||||
ctx->cmdclient->references--;
|
|
||||||
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0);
|
|
||||||
}
|
|
||||||
if (ctx->curclient != NULL)
|
|
||||||
ctx->curclient->references--;
|
|
||||||
|
|
||||||
xfree(cdata->cmd);
|
|
||||||
xfree(cdata);
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-save-buffer.c,v 1.9 2009-10-28 23:08:52 tcunha Exp $ */
|
/* $Id: cmd-save-buffer.c,v 1.8 2009-09-07 23:48:54 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -70,7 +70,6 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
f = fopen(data->arg, "ab");
|
f = fopen(data->arg, "ab");
|
||||||
else
|
else
|
||||||
f = fopen(data->arg, "wb");
|
f = fopen(data->arg, "wb");
|
||||||
umask(mask);
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
|
||||||
return (-1);
|
return (-1);
|
||||||
@@ -83,6 +82,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
umask(mask);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* $Id: cmd-lock-session.c,v 1.1 2009-09-25 17:51:39 tcunha Exp $ */
|
/* $Id: cmd-scroll-mode.c,v 1.23 2009-08-20 11:37:46 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 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,33 +21,50 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lock all clients attached to a session.
|
* Enter scroll mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int cmd_lock_session_exec(struct cmd *, struct cmd_ctx *);
|
void cmd_scroll_mode_init(struct cmd *, int);
|
||||||
|
int cmd_scroll_mode_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_lock_session_entry = {
|
const struct cmd_entry cmd_scroll_mode_entry = {
|
||||||
"lock-session", "locks",
|
"scroll-mode", NULL,
|
||||||
CMD_TARGET_SESSION_USAGE,
|
"[-u] " CMD_TARGET_PANE_USAGE,
|
||||||
0, 0,
|
0, CMD_CHFLAG('u'),
|
||||||
cmd_target_init,
|
cmd_scroll_mode_init,
|
||||||
cmd_target_parse,
|
cmd_target_parse,
|
||||||
cmd_lock_session_exec,
|
cmd_scroll_mode_exec,
|
||||||
cmd_target_free,
|
cmd_target_free,
|
||||||
cmd_target_print
|
cmd_target_print
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
cmd_scroll_mode_init(struct cmd *self, int key)
|
||||||
|
{
|
||||||
|
struct cmd_target_data *data;
|
||||||
|
|
||||||
|
cmd_target_init(self, key);
|
||||||
|
data = self->data;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case KEYC_PPAGE:
|
||||||
|
data->chflags |= CMD_CHFLAG('u');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cmd_lock_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
cmd_scroll_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct cmd_target_data *data = self->data;
|
struct cmd_target_data *data = self->data;
|
||||||
struct session *s;
|
struct window_pane *wp;
|
||||||
|
|
||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
server_lock_session(s);
|
window_pane_set_mode(wp, &window_scroll_mode);
|
||||||
recalculate_sizes();
|
if (wp->mode == &window_scroll_mode && data->chflags & CMD_CHFLAG('u'))
|
||||||
|
window_scroll_pageup(wp);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-send-keys.c,v 1.22 2009-09-22 14:03:11 tcunha Exp $ */
|
/* $Id: cmd-send-keys.c,v 1.21 2009-08-20 11:37:46 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -33,6 +33,7 @@ size_t cmd_send_keys_print(struct cmd *, char *, size_t);
|
|||||||
|
|
||||||
struct cmd_send_keys_data {
|
struct cmd_send_keys_data {
|
||||||
char *target;
|
char *target;
|
||||||
|
int idx;
|
||||||
u_int nkeys;
|
u_int nkeys;
|
||||||
int *keys;
|
int *keys;
|
||||||
};
|
};
|
||||||
@@ -57,6 +58,7 @@ cmd_send_keys_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
|
|
||||||
self->data = data = xmalloc(sizeof *data);
|
self->data = data = xmalloc(sizeof *data);
|
||||||
data->target = NULL;
|
data->target = NULL;
|
||||||
|
data->idx = -1;
|
||||||
data->nkeys = 0;
|
data->nkeys = 0;
|
||||||
data->keys = NULL;
|
data->keys = NULL;
|
||||||
|
|
||||||
@@ -141,6 +143,8 @@ cmd_send_keys_print(struct cmd *self, char *buf, size_t len)
|
|||||||
return (off);
|
return (off);
|
||||||
if (off < len && data->target != NULL)
|
if (off < len && data->target != NULL)
|
||||||
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
|
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
|
||||||
|
if (off < len && data->idx != -1)
|
||||||
|
off += xsnprintf(buf + off, len - off, " -i %d", data->idx);
|
||||||
|
|
||||||
for (i = 0; i < data->nkeys; i++) {
|
for (i = 0; i < data->nkeys; i++) {
|
||||||
if (off >= len)
|
if (off >= len)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-send-prefix.c,v 1.27 2009-09-22 14:22:20 tcunha Exp $ */
|
/* $Id: cmd-send-prefix.c,v 1.26 2009-08-20 11:37:46 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -43,13 +43,13 @@ cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct cmd_target_data *data = self->data;
|
struct cmd_target_data *data = self->data;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct keylist *keylist;
|
int key;
|
||||||
|
|
||||||
if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
|
if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
keylist = options_get_data(&s->options, "prefix");
|
key = options_get_number(&s->options, "prefix");
|
||||||
window_pane_key(wp, ctx->curclient, ARRAY_FIRST(keylist));
|
window_pane_key(wp, ctx->curclient, key);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-server-info.c,v 1.33 2009-11-04 22:42:31 tcunha Exp $ */
|
/* $Id: cmd-server-info.c,v 1.28 2009-09-07 23:59:19 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -55,7 +55,6 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct tty_code *code;
|
struct tty_code *code;
|
||||||
struct tty_term_code_entry *ent;
|
struct tty_term_code_entry *ent;
|
||||||
struct utsname un;
|
struct utsname un;
|
||||||
struct job *job;
|
|
||||||
struct grid *gd;
|
struct grid *gd;
|
||||||
struct grid_line *gl;
|
struct grid_line *gl;
|
||||||
u_int i, j, k;
|
u_int i, j, k;
|
||||||
@@ -69,10 +68,11 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
*strchr(tim, '\n') = '\0';
|
*strchr(tim, '\n') = '\0';
|
||||||
ctx->print(ctx,
|
ctx->print(ctx,
|
||||||
"tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim);
|
"tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim);
|
||||||
ctx->print(ctx, "socket path %s, debug level %d%s",
|
ctx->print(ctx, "socket path %s, debug level %d%s%s",
|
||||||
socket_path, debug_level, be_quiet ? ", quiet" : "");
|
socket_path, debug_level, be_quiet ? ", quiet" : "",
|
||||||
if (uname(&un) == 0) {
|
login_shell ? ", login shell" : "");
|
||||||
ctx->print(ctx, "system is %s %s %s %s",
|
if (uname(&un) == 0) {
|
||||||
|
ctx->print(ctx, "system is %s %s %s %s",
|
||||||
un.sysname, un.release, un.version, un.machine);
|
un.sysname, un.release, un.version, un.machine);
|
||||||
}
|
}
|
||||||
if (cfg_file != NULL)
|
if (cfg_file != NULL)
|
||||||
@@ -105,7 +105,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
t = s->creation_time.tv_sec;
|
t = s->tv.tv_sec;
|
||||||
tim = ctime(&t);
|
tim = ctime(&t);
|
||||||
*strchr(tim, '\n') = '\0';
|
*strchr(tim, '\n') = '\0';
|
||||||
|
|
||||||
@@ -179,11 +179,5 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
ctx->print(ctx, "%s", "");
|
ctx->print(ctx, "%s", "");
|
||||||
|
|
||||||
ctx->print(ctx, "Jobs:");
|
|
||||||
SLIST_FOREACH(job, &all_jobs, lentry) {
|
|
||||||
ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d, flags=0x%x]",
|
|
||||||
job->cmd, job->fd, job->pid, job->status, job->flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-set-option.c,v 1.85 2009-11-02 21:38:26 tcunha Exp $ */
|
/* $Id: cmd-set-option.c,v 1.79 2009-09-19 18:53:01 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -62,13 +62,10 @@ const struct set_option_entry set_option_table[] = {
|
|||||||
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
|
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
|
||||||
{ "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
|
{ "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
|
||||||
{ "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
|
{ "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
|
||||||
{ "lock-command", SET_OPTION_STRING, 0, 0, NULL },
|
|
||||||
{ "lock-server", SET_OPTION_FLAG, 0, 0, NULL },
|
|
||||||
{ "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
{ "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
||||||
{ "message-bg", SET_OPTION_COLOUR, 0, 0, NULL },
|
{ "message-bg", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||||
{ "message-fg", SET_OPTION_COLOUR, 0, 0, NULL },
|
{ "message-fg", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||||
{ "mouse-select-pane", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "prefix", SET_OPTION_KEY, 0, 0, NULL },
|
||||||
{ "prefix", SET_OPTION_KEYS, 0, 0, NULL },
|
|
||||||
{ "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
|
{ "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
|
||||||
{ "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
@@ -108,10 +105,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct client *c;
|
struct client *c;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
const struct set_option_entry *entry, *opt;
|
const struct set_option_entry *entry, *opt;
|
||||||
struct jobs *jobs;
|
|
||||||
struct job *job, *nextjob;
|
|
||||||
u_int i;
|
u_int i;
|
||||||
int try_again;
|
|
||||||
|
|
||||||
if (data->chflags & CMD_CHFLAG('g'))
|
if (data->chflags & CMD_CHFLAG('g'))
|
||||||
oo = &global_s_options;
|
oo = &global_s_options;
|
||||||
@@ -168,8 +162,8 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
case SET_OPTION_NUMBER:
|
case SET_OPTION_NUMBER:
|
||||||
set_option_number(ctx, oo, entry, data->arg2);
|
set_option_number(ctx, oo, entry, data->arg2);
|
||||||
break;
|
break;
|
||||||
case SET_OPTION_KEYS:
|
case SET_OPTION_KEY:
|
||||||
set_option_keys(ctx, oo, entry, data->arg2);
|
set_option_key(ctx, oo, entry, data->arg2);
|
||||||
break;
|
break;
|
||||||
case SET_OPTION_COLOUR:
|
case SET_OPTION_COLOUR:
|
||||||
set_option_colour(ctx, oo, entry, data->arg2);
|
set_option_colour(ctx, oo, entry, data->arg2);
|
||||||
@@ -187,36 +181,10 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
/*
|
c = ARRAY_ITEM(&clients, i);
|
||||||
* Special-case: kill all persistent jobs if status-left, status-right
|
if (c != NULL && c->session != NULL)
|
||||||
* or set-titles-string have changed. Persistent jobs are only used by
|
|
||||||
* the status line at the moment so this works XXX.
|
|
||||||
*/
|
|
||||||
if (strcmp(entry->name, "status-left") == 0 ||
|
|
||||||
strcmp(entry->name, "status-right") == 0 ||
|
|
||||||
strcmp(entry->name, "set-titles-string") == 0) {
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
c = ARRAY_ITEM(&clients, i);
|
|
||||||
if (c == NULL || c->session == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
jobs = &c->status_jobs;
|
|
||||||
do {
|
|
||||||
try_again = 0;
|
|
||||||
job = RB_ROOT(jobs);
|
|
||||||
while (job != NULL) {
|
|
||||||
nextjob = RB_NEXT(jobs, jobs, job);
|
|
||||||
if (job->flags & JOB_PERSIST) {
|
|
||||||
job_remove(jobs, job);
|
|
||||||
try_again = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
job = nextjob;
|
|
||||||
}
|
|
||||||
} while (try_again);
|
|
||||||
server_redraw_client(c);
|
server_redraw_client(c);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
145
cmd-set-password.c
Normal file
145
cmd-set-password.c
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/* $Id: cmd-set-password.c,v 1.8 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* 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 <pwd.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set server password.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int cmd_set_password_parse(struct cmd *, int, char **, char **);
|
||||||
|
int cmd_set_password_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
void cmd_set_password_free(struct cmd *);
|
||||||
|
void cmd_set_password_init(struct cmd *, int);
|
||||||
|
size_t cmd_set_password_print(struct cmd *, char *, size_t);
|
||||||
|
|
||||||
|
struct cmd_set_password_data {
|
||||||
|
char *password;
|
||||||
|
int flag_encrypted;
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_set_password_entry = {
|
||||||
|
"set-password", "pass",
|
||||||
|
"[-c] password",
|
||||||
|
0, 0,
|
||||||
|
cmd_set_password_init,
|
||||||
|
cmd_set_password_parse,
|
||||||
|
cmd_set_password_exec,
|
||||||
|
cmd_set_password_free,
|
||||||
|
cmd_set_password_print
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
cmd_set_password_init(struct cmd *self, unused int arg)
|
||||||
|
{
|
||||||
|
struct cmd_set_password_data *data;
|
||||||
|
|
||||||
|
self->data = data = xmalloc(sizeof *data);
|
||||||
|
data->password = NULL;
|
||||||
|
data->flag_encrypted = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cmd_set_password_parse(struct cmd *self, int argc, char **argv, char **cause)
|
||||||
|
{
|
||||||
|
struct cmd_set_password_data *data;
|
||||||
|
int opt;
|
||||||
|
char *out;
|
||||||
|
|
||||||
|
self->entry->init(self, 0);
|
||||||
|
data = self->data;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "c")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'c':
|
||||||
|
data->flag_encrypted = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
if (argc != 1)
|
||||||
|
goto usage;
|
||||||
|
|
||||||
|
if (!data->flag_encrypted) {
|
||||||
|
if ((out = crypt(argv[0], "$1")) != NULL)
|
||||||
|
data->password = xstrdup(out);
|
||||||
|
} else
|
||||||
|
data->password = xstrdup(argv[0]);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
usage:
|
||||||
|
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
|
||||||
|
|
||||||
|
self->entry->free(self);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cmd_set_password_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct cmd_set_password_data *data = self->data;
|
||||||
|
|
||||||
|
if (data->password == NULL) {
|
||||||
|
ctx->error(ctx, "failed to encrypt password");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server_password != NULL)
|
||||||
|
xfree(server_password);
|
||||||
|
if (*data->password == '\0')
|
||||||
|
server_password = NULL;
|
||||||
|
else
|
||||||
|
server_password = xstrdup(data->password);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cmd_set_password_free(struct cmd *self)
|
||||||
|
{
|
||||||
|
struct cmd_set_password_data *data = self->data;
|
||||||
|
|
||||||
|
if (data->password != NULL)
|
||||||
|
xfree(data->password);
|
||||||
|
xfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
cmd_set_password_print(struct cmd *self, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct cmd_set_password_data *data = self->data;
|
||||||
|
size_t off = 0;
|
||||||
|
|
||||||
|
off += xsnprintf(buf, len, "%s", self->entry->name);
|
||||||
|
if (data == NULL)
|
||||||
|
return (off);
|
||||||
|
if (off < len && data->flag_encrypted)
|
||||||
|
off += xsnprintf(buf + off, len - off, " -c");
|
||||||
|
if (off < len && data->password != NULL)
|
||||||
|
off += xsnprintf(buf + off, len - off, " password");
|
||||||
|
return (off);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-set-window-option.c,v 1.40 2009-10-09 13:07:04 tcunha Exp $ */
|
/* $Id: cmd-set-window-option.c,v 1.38 2009-08-11 14:42:59 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -64,7 +64,6 @@ const struct set_option_entry set_window_option_table[] = {
|
|||||||
{ "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 },
|
||||||
{ "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 },
|
|
||||||
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
{ "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
|
||||||
{ "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
|
{ "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||||
@@ -141,8 +140,8 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
case SET_OPTION_NUMBER:
|
case SET_OPTION_NUMBER:
|
||||||
set_option_number(ctx, oo, entry, data->arg2);
|
set_option_number(ctx, oo, entry, data->arg2);
|
||||||
break;
|
break;
|
||||||
case SET_OPTION_KEYS:
|
case SET_OPTION_KEY:
|
||||||
set_option_keys(ctx, oo, entry, data->arg2);
|
set_option_key(ctx, oo, entry, data->arg2);
|
||||||
break;
|
break;
|
||||||
case SET_OPTION_COLOUR:
|
case SET_OPTION_COLOUR:
|
||||||
set_option_colour(ctx, oo, entry, data->arg2);
|
set_option_colour(ctx, oo, entry, data->arg2);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-show-options.c,v 1.17 2009-09-22 13:56:02 tcunha Exp $ */
|
/* $Id: cmd-show-options.c,v 1.16 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -46,9 +46,9 @@ cmd_show_options_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 options *oo;
|
struct options *oo;
|
||||||
struct options_entry *o;
|
|
||||||
const struct set_option_entry *entry;
|
const struct set_option_entry *entry;
|
||||||
const char *optval;
|
char *vs;
|
||||||
|
long long vn;
|
||||||
|
|
||||||
if (data->chflags & CMD_CHFLAG('g'))
|
if (data->chflags & CMD_CHFLAG('g'))
|
||||||
oo = &global_s_options;
|
oo = &global_s_options;
|
||||||
@@ -59,10 +59,46 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (entry = set_option_table; entry->name != NULL; entry++) {
|
for (entry = set_option_table; entry->name != NULL; entry++) {
|
||||||
if ((o = options_find1(oo, entry->name)) == NULL)
|
if (options_find1(oo, entry->name) == NULL)
|
||||||
continue;
|
continue;
|
||||||
optval = set_option_print(entry, o);
|
|
||||||
ctx->print(ctx, "%s %s", entry->name, optval);
|
switch (entry->type) {
|
||||||
|
case SET_OPTION_STRING:
|
||||||
|
vs = options_get_string(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s \"%s\"", entry->name, vs);
|
||||||
|
break;
|
||||||
|
case SET_OPTION_NUMBER:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %lld", entry->name, vn);
|
||||||
|
break;
|
||||||
|
case SET_OPTION_KEY:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %s",
|
||||||
|
entry->name, key_string_lookup_key(vn));
|
||||||
|
break;
|
||||||
|
case SET_OPTION_COLOUR:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %s",
|
||||||
|
entry->name, colour_tostring(vn));
|
||||||
|
break;
|
||||||
|
case SET_OPTION_ATTRIBUTES:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %s",
|
||||||
|
entry->name, attributes_tostring(vn));
|
||||||
|
break;
|
||||||
|
case SET_OPTION_FLAG:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
if (vn)
|
||||||
|
ctx->print(ctx, "%s on", entry->name);
|
||||||
|
else
|
||||||
|
ctx->print(ctx, "%s off", entry->name);
|
||||||
|
break;
|
||||||
|
case SET_OPTION_CHOICE:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %s",
|
||||||
|
entry->name, entry->choices[vn]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-show-window-options.c,v 1.13 2009-09-22 13:56:02 tcunha Exp $ */
|
/* $Id: cmd-show-window-options.c,v 1.12 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -46,9 +46,9 @@ cmd_show_window_options_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct cmd_target_data *data = self->data;
|
struct cmd_target_data *data = self->data;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
struct options_entry *o;
|
|
||||||
const struct set_option_entry *entry;
|
const struct set_option_entry *entry;
|
||||||
const char *optval;
|
char *vs;
|
||||||
|
long long vn;
|
||||||
|
|
||||||
if (data->chflags & CMD_CHFLAG('g'))
|
if (data->chflags & CMD_CHFLAG('g'))
|
||||||
oo = &global_w_options;
|
oo = &global_w_options;
|
||||||
@@ -59,10 +59,46 @@ cmd_show_window_options_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (entry = set_window_option_table; entry->name != NULL; entry++) {
|
for (entry = set_window_option_table; entry->name != NULL; entry++) {
|
||||||
if ((o = options_find1(oo, entry->name)) == NULL)
|
if (options_find1(oo, entry->name) == NULL)
|
||||||
continue;
|
continue;
|
||||||
optval = set_option_print(entry, o);
|
|
||||||
ctx->print(ctx, "%s %s", entry->name, optval);
|
switch (entry->type) {
|
||||||
|
case SET_OPTION_STRING:
|
||||||
|
vs = options_get_string(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s \"%s\"", entry->name, vs);
|
||||||
|
break;
|
||||||
|
case SET_OPTION_NUMBER:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %lld", entry->name, vn);
|
||||||
|
break;
|
||||||
|
case SET_OPTION_KEY:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %s",
|
||||||
|
entry->name, key_string_lookup_key(vn));
|
||||||
|
break;
|
||||||
|
case SET_OPTION_COLOUR:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %s",
|
||||||
|
entry->name, colour_tostring(vn));
|
||||||
|
break;
|
||||||
|
case SET_OPTION_ATTRIBUTES:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %s",
|
||||||
|
entry->name, attributes_tostring(vn));
|
||||||
|
break;
|
||||||
|
case SET_OPTION_FLAG:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
if (vn)
|
||||||
|
ctx->print(ctx, "%s on", entry->name);
|
||||||
|
else
|
||||||
|
ctx->print(ctx, "%s off", entry->name);
|
||||||
|
break;
|
||||||
|
case SET_OPTION_CHOICE:
|
||||||
|
vn = options_get_number(oo, entry->name);
|
||||||
|
ctx->print(ctx, "%s %s",
|
||||||
|
entry->name, entry->choices[vn]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-source-file.c,v 1.9 2009-09-22 14:06:40 tcunha Exp $ */
|
/* $Id: cmd-source-file.c,v 1.8 2009-08-24 16:27:03 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -60,7 +60,7 @@ cmd_source_file_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
struct cmd_source_file_data *data;
|
struct cmd_source_file_data *data;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
self->entry->init(self, KEYC_NONE);
|
self->entry->init(self, 0);
|
||||||
data = self->data;
|
data = self->data;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "")) != -1) {
|
while ((opt = getopt(argc, argv, "")) != -1) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-split-window.c,v 1.28 2009-09-22 14:06:40 tcunha Exp $ */
|
/* $Id: cmd-split-window.c,v 1.27 2009-09-16 12:36:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -83,7 +83,7 @@ cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
|
|||||||
int opt;
|
int opt;
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
|
|
||||||
self->entry->init(self, KEYC_NONE);
|
self->entry->init(self, 0);
|
||||||
data = self->data;
|
data = self->data;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "dhl:p:t:v")) != -1) {
|
while ((opt = getopt(argc, argv, "dhl:p:t:v")) != -1) {
|
||||||
|
|||||||
42
cmd-string.c
42
cmd-string.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-string.c,v 1.24 2009-10-28 23:12:38 tcunha Exp $ */
|
/* $Id: cmd-string.c,v 1.23 2009-08-09 17:48:55 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -204,33 +204,33 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
|
|||||||
char *buf, *t;
|
char *buf, *t;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
while ((ch = cmd_string_getc(s, p)) != endch) {
|
while ((ch = cmd_string_getc(s, p)) != endch) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case EOF:
|
case EOF:
|
||||||
goto error;
|
goto error;
|
||||||
case '\\':
|
case '\\':
|
||||||
if (!esc)
|
if (!esc)
|
||||||
break;
|
break;
|
||||||
switch (ch = cmd_string_getc(s, p)) {
|
switch (ch = cmd_string_getc(s, p)) {
|
||||||
case EOF:
|
case EOF:
|
||||||
goto error;
|
goto error;
|
||||||
case 'e':
|
case 'e':
|
||||||
ch = '\033';
|
ch = '\033';
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
ch = '\r';
|
ch = '\r';
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
ch = '\n';
|
ch = '\n';
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
ch = '\t';
|
ch = '\t';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '$':
|
case '$':
|
||||||
if (!esc)
|
if (!esc)
|
||||||
break;
|
break;
|
||||||
@@ -241,13 +241,13 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
|
|||||||
len += strlen(t);
|
len += strlen(t);
|
||||||
xfree(t);
|
xfree(t);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len >= SIZE_MAX - 2)
|
if (len >= SIZE_MAX - 2)
|
||||||
goto error;
|
goto error;
|
||||||
buf = xrealloc(buf, 1, len + 1);
|
buf = xrealloc(buf, 1, len + 1);
|
||||||
buf[len++] = ch;
|
buf[len++] = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = xrealloc(buf, 1, len + 1);
|
buf = xrealloc(buf, 1, len + 1);
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
@@ -272,7 +272,7 @@ cmd_string_variable(const char *s, size_t *p)
|
|||||||
((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z') || \
|
((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z') || \
|
||||||
((ch) >= '0' && (ch) <= '9'))
|
((ch) >= '0' && (ch) <= '9'))
|
||||||
|
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
fch = EOF;
|
fch = EOF;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-swap-window.c,v 1.18 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-swap-window.c,v 1.17 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -44,7 +44,6 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
{
|
{
|
||||||
struct cmd_srcdst_data *data = self->data;
|
struct cmd_srcdst_data *data = self->data;
|
||||||
struct session *src, *dst;
|
struct session *src, *dst;
|
||||||
struct session_group *sg_src, *sg_dst;
|
|
||||||
struct winlink *wl_src, *wl_dst;
|
struct winlink *wl_src, *wl_dst;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
|
|
||||||
@@ -53,14 +52,6 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if ((wl_dst = cmd_find_window(ctx, data->dst, &dst)) == NULL)
|
if ((wl_dst = cmd_find_window(ctx, data->dst, &dst)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
sg_src = session_group_find(src);
|
|
||||||
sg_dst = session_group_find(dst);
|
|
||||||
if (src != dst &&
|
|
||||||
sg_src != NULL && sg_dst != NULL && sg_src == sg_dst) {
|
|
||||||
ctx->error(ctx, "can't move window, sessions are grouped");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wl_dst->window == wl_src->window)
|
if (wl_dst->window == wl_src->window)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
@@ -73,12 +64,9 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if (src != dst)
|
if (src != dst)
|
||||||
session_select(src, wl_src->idx);
|
session_select(src, wl_src->idx);
|
||||||
}
|
}
|
||||||
session_group_synchronize_from(src);
|
server_redraw_session(src);
|
||||||
server_redraw_session_group(src);
|
if (src != dst)
|
||||||
if (src != dst) {
|
server_redraw_session(dst);
|
||||||
session_group_synchronize_from(dst);
|
|
||||||
server_redraw_session_group(dst);
|
|
||||||
}
|
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-unlink-window.c,v 1.19 2009-10-11 23:38:16 tcunha Exp $ */
|
/* $Id: cmd-unlink-window.c,v 1.16 2009-07-28 22:12:16 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -42,29 +42,30 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
{
|
{
|
||||||
struct cmd_target_data *data = self->data;
|
struct cmd_target_data *data = self->data;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window *w;
|
struct session *s;
|
||||||
struct session *s, *s2;
|
struct client *c;
|
||||||
struct session_group *sg;
|
u_int i;
|
||||||
u_int references;
|
int destroyed;
|
||||||
|
|
||||||
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
|
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
w = wl->window;
|
|
||||||
|
|
||||||
sg = session_group_find(s);
|
if (!(data->chflags & CMD_CHFLAG('k')) && wl->window->references == 1) {
|
||||||
if (sg != NULL) {
|
|
||||||
references = 0;
|
|
||||||
TAILQ_FOREACH(s2, &sg->sessions, gentry)
|
|
||||||
references++;
|
|
||||||
} else
|
|
||||||
references = 1;
|
|
||||||
|
|
||||||
if (!(data->chflags & CMD_CHFLAG('k')) && w->references == references) {
|
|
||||||
ctx->error(ctx, "window is only linked to one session");
|
ctx->error(ctx, "window is only linked to one session");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
server_unlink_window(s, wl);
|
destroyed = session_detach(s, wl);
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
|
c = ARRAY_ITEM(&clients, i);
|
||||||
|
if (c == NULL || c->session != s)
|
||||||
|
continue;
|
||||||
|
if (destroyed) {
|
||||||
|
c->session = NULL;
|
||||||
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
|
} else
|
||||||
|
server_redraw_client(c);
|
||||||
|
}
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|||||||
138
cmd.c
138
cmd.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd.c,v 1.130 2009-11-04 22:46:25 tcunha Exp $ */
|
/* $Id: cmd.c,v 1.115 2009-08-31 22:30:15 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -57,20 +57,16 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_list_clients_entry,
|
&cmd_list_clients_entry,
|
||||||
&cmd_list_commands_entry,
|
&cmd_list_commands_entry,
|
||||||
&cmd_list_keys_entry,
|
&cmd_list_keys_entry,
|
||||||
&cmd_list_panes_entry,
|
|
||||||
&cmd_list_sessions_entry,
|
&cmd_list_sessions_entry,
|
||||||
&cmd_list_windows_entry,
|
&cmd_list_windows_entry,
|
||||||
&cmd_load_buffer_entry,
|
&cmd_load_buffer_entry,
|
||||||
&cmd_lock_client_entry,
|
|
||||||
&cmd_lock_server_entry,
|
&cmd_lock_server_entry,
|
||||||
&cmd_lock_session_entry,
|
|
||||||
&cmd_move_window_entry,
|
&cmd_move_window_entry,
|
||||||
&cmd_new_session_entry,
|
&cmd_new_session_entry,
|
||||||
&cmd_new_window_entry,
|
&cmd_new_window_entry,
|
||||||
&cmd_next_layout_entry,
|
&cmd_next_layout_entry,
|
||||||
&cmd_next_window_entry,
|
&cmd_next_window_entry,
|
||||||
&cmd_paste_buffer_entry,
|
&cmd_paste_buffer_entry,
|
||||||
&cmd_pipe_pane_entry,
|
|
||||||
&cmd_previous_layout_entry,
|
&cmd_previous_layout_entry,
|
||||||
&cmd_previous_window_entry,
|
&cmd_previous_window_entry,
|
||||||
&cmd_refresh_client_entry,
|
&cmd_refresh_client_entry,
|
||||||
@@ -79,8 +75,8 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_resize_pane_entry,
|
&cmd_resize_pane_entry,
|
||||||
&cmd_respawn_window_entry,
|
&cmd_respawn_window_entry,
|
||||||
&cmd_rotate_window_entry,
|
&cmd_rotate_window_entry,
|
||||||
&cmd_run_shell_entry,
|
|
||||||
&cmd_save_buffer_entry,
|
&cmd_save_buffer_entry,
|
||||||
|
&cmd_scroll_mode_entry,
|
||||||
&cmd_select_layout_entry,
|
&cmd_select_layout_entry,
|
||||||
&cmd_select_pane_entry,
|
&cmd_select_pane_entry,
|
||||||
&cmd_select_prompt_entry,
|
&cmd_select_prompt_entry,
|
||||||
@@ -91,6 +87,7 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_set_buffer_entry,
|
&cmd_set_buffer_entry,
|
||||||
&cmd_set_environment_entry,
|
&cmd_set_environment_entry,
|
||||||
&cmd_set_option_entry,
|
&cmd_set_option_entry,
|
||||||
|
&cmd_set_password_entry,
|
||||||
&cmd_set_window_option_entry,
|
&cmd_set_window_option_entry,
|
||||||
&cmd_show_buffer_entry,
|
&cmd_show_buffer_entry,
|
||||||
&cmd_show_environment_entry,
|
&cmd_show_environment_entry,
|
||||||
@@ -109,8 +106,7 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct session *cmd_choose_session(struct sessions *);
|
struct session *cmd_newest_session(struct sessions *);
|
||||||
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 *);
|
||||||
@@ -178,7 +174,7 @@ struct cmd *
|
|||||||
cmd_parse(int argc, char **argv, char **cause)
|
cmd_parse(int argc, char **argv, char **cause)
|
||||||
{
|
{
|
||||||
const struct cmd_entry **entryp, *entry;
|
const struct cmd_entry **entryp, *entry;
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
char s[BUFSIZ];
|
char s[BUFSIZ];
|
||||||
int opt, ambiguous = 0;
|
int opt, ambiguous = 0;
|
||||||
|
|
||||||
@@ -262,6 +258,10 @@ usage:
|
|||||||
int
|
int
|
||||||
cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
|
cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
|
if (server_locked) {
|
||||||
|
ctx->error(ctx, "server is locked");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
return (cmd->entry->exec(cmd, ctx));
|
return (cmd->entry->exec(cmd, ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,10 +284,9 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out the current session. Use: 1) the current session, if the command
|
* Figure out the current session. Use: 1) the current session, if the command
|
||||||
* context has one; 2) the most recently used session containing the pty of the
|
* context has one; 2) the session containing the pty of the calling client, if
|
||||||
* calling client, if any; 3) the session specified in the TMUX variable from
|
* any 3) the session specified in the TMUX variable from the environment (as
|
||||||
* the environment (as passed from the client); 4) the most recently used
|
* passed from the client); 3) the newest session.
|
||||||
* session from all sessions.
|
|
||||||
*/
|
*/
|
||||||
struct session *
|
struct session *
|
||||||
cmd_current_session(struct cmd_ctx *ctx)
|
cmd_current_session(struct cmd_ctx *ctx)
|
||||||
@@ -329,7 +328,7 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
ARRAY_ADD(&ss, s);
|
ARRAY_ADD(&ss, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = cmd_choose_session(&ss);
|
s = cmd_newest_session(&ss);
|
||||||
ARRAY_FREE(&ss);
|
ARRAY_FREE(&ss);
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
return (s);
|
return (s);
|
||||||
@@ -346,92 +345,29 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (cmd_choose_session(&sessions));
|
return (cmd_newest_session(&sessions));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the most recently used session from a list. */
|
/* Find the newest session. */
|
||||||
struct session *
|
struct session *
|
||||||
cmd_choose_session(struct sessions *ss)
|
cmd_newest_session(struct sessions *ss)
|
||||||
{
|
{
|
||||||
struct session *s, *sbest;
|
struct session *s, *snewest;
|
||||||
struct timeval *tv = NULL;
|
struct timeval *tv = NULL;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
sbest = NULL;
|
snewest = NULL;
|
||||||
for (i = 0; i < ARRAY_LENGTH(ss); i++) {
|
for (i = 0; i < ARRAY_LENGTH(ss); i++) {
|
||||||
if ((s = ARRAY_ITEM(ss, i)) == NULL)
|
if ((s = ARRAY_ITEM(ss, i)) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tv == NULL || timercmp(&s->activity_time, tv, >)) {
|
if (tv == NULL || timercmp(&s->tv, tv, >)) {
|
||||||
sbest = s;
|
snewest = s;
|
||||||
tv = &s->activity_time;
|
tv = &s->tv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sbest);
|
return (snewest);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the current client. First try the current client if set, then pick the
|
|
||||||
* most recently used of the clients attached to the current session if any,
|
|
||||||
* then of all clients.
|
|
||||||
*/
|
|
||||||
struct client *
|
|
||||||
cmd_current_client(struct cmd_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
struct client *c;
|
|
||||||
struct clients cc;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
if (ctx->curclient != NULL)
|
|
||||||
return (ctx->curclient);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No current client set. Find the current session and return the
|
|
||||||
* newest of its clients.
|
|
||||||
*/
|
|
||||||
s = cmd_current_session(ctx);
|
|
||||||
if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
|
|
||||||
ARRAY_INIT(&cc);
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
if ((c = ARRAY_ITEM(&clients, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
if (s == c->session)
|
|
||||||
ARRAY_ADD(&cc, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
c = cmd_choose_client(&cc);
|
|
||||||
ARRAY_FREE(&cc);
|
|
||||||
if (c != NULL)
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (cmd_choose_client(&clients));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Choose the most recently used client from a list. */
|
|
||||||
struct client *
|
|
||||||
cmd_choose_client(struct clients *cc)
|
|
||||||
{
|
|
||||||
struct client *c, *cbest;
|
|
||||||
struct timeval *tv = NULL;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
cbest = NULL;
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(cc); i++) {
|
|
||||||
if ((c = ARRAY_ITEM(cc, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
if (c->session == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (tv == NULL || timercmp(&c->activity_time, tv, >)) {
|
|
||||||
cbest = c;
|
|
||||||
tv = &c->activity_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (cbest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the target client or report an error and return NULL. */
|
/* Find the target client or report an error and return NULL. */
|
||||||
@@ -444,7 +380,7 @@ cmd_find_client(struct cmd_ctx *ctx, const char *arg)
|
|||||||
|
|
||||||
/* A NULL argument means the current client. */
|
/* A NULL argument means the current client. */
|
||||||
if (arg == NULL)
|
if (arg == NULL)
|
||||||
return (cmd_current_client(ctx));
|
return (ctx->curclient);
|
||||||
tmparg = xstrdup(arg);
|
tmparg = xstrdup(arg);
|
||||||
|
|
||||||
/* Trim a single trailing colon if any. */
|
/* Trim a single trailing colon if any. */
|
||||||
@@ -475,8 +411,7 @@ cmd_lookup_client(const char *name)
|
|||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
c = ARRAY_ITEM(&clients, i);
|
if ((c = ARRAY_ITEM(&clients, i)) == NULL)
|
||||||
if (c == NULL || c->session == NULL)
|
|
||||||
continue;
|
continue;
|
||||||
path = c->tty.path;
|
path = c->tty.path;
|
||||||
|
|
||||||
@@ -504,25 +439,19 @@ cmd_lookup_session(const char *name, int *ambiguous)
|
|||||||
*ambiguous = 0;
|
*ambiguous = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look for matches. First look for exact matches - session names must
|
* Look for matches. Session names must be unique so an exact match
|
||||||
* be unique so an exact match can't be ambigious and can just be
|
* can't be ambigious and can just be returned.
|
||||||
* returned.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
|
||||||
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
|
|
||||||
* be ambiguous.
|
|
||||||
*/
|
*/
|
||||||
sfound = NULL;
|
sfound = NULL;
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Check for an exact match and return it if found. */
|
||||||
|
if (strcmp(name, s->name) == 0)
|
||||||
|
return (s);
|
||||||
|
|
||||||
|
/* Then check for pattern matches. */
|
||||||
if (strncmp(name, s->name, strlen(name)) == 0 ||
|
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) {
|
||||||
@@ -532,6 +461,7 @@ cmd_lookup_session(const char *name, int *ambiguous)
|
|||||||
sfound = s;
|
sfound = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (sfound);
|
return (sfound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -863,7 +793,7 @@ cmd_find_pane(struct cmd_ctx *ctx,
|
|||||||
|
|
||||||
/* Get the current session. */
|
/* Get the current session. */
|
||||||
if ((s = cmd_current_session(ctx)) == NULL) {
|
if ((s = cmd_current_session(ctx)) == NULL) {
|
||||||
ctx->error(ctx, "can't establish current session");
|
ctx->error(ctx, "can't establish current session");
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (sp != NULL)
|
if (sp != NULL)
|
||||||
|
|||||||
14
compat.h
14
compat.h
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: compat.h,v 1.19 2009-10-06 15:32:21 tcunha Exp $ */
|
/* $Id: compat.h,v 1.17 2009-09-03 20:54:39 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -91,6 +91,10 @@ typedef uint64_t u_int64_t;
|
|||||||
#include "compat/imsg.h"
|
#include "compat/imsg.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LOGIN_CAP
|
||||||
|
#include <login_cap.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
|
#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
|
||||||
/* Broken on OS X. */
|
/* Broken on OS X. */
|
||||||
#undef CMSG_FIRSTHDR
|
#undef CMSG_FIRSTHDR
|
||||||
@@ -138,10 +142,18 @@ typedef uint64_t u_int64_t;
|
|||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PASS_MAX
|
||||||
|
#define PASS_MAX 128
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef TTY_NAME_MAX
|
#ifndef TTY_NAME_MAX
|
||||||
#define TTY_NAME_MAX 32
|
#define TTY_NAME_MAX 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _PW_BUF_LEN
|
||||||
|
#define _PW_BUF_LEN 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_BZERO
|
#ifndef HAVE_BZERO
|
||||||
#define bzero(buf, len) memset((buf), 0, (len));
|
#define bzero(buf, len) memset((buf), 0, (len));
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: forkpty-sunos.c,v 1.9 2009-10-15 07:11:25 nicm Exp $ */
|
/* $Id: forkpty-sunos.c,v 1.8 2009-09-20 18:31:16 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
pid_t
|
pid_t
|
||||||
forkpty(int *master, char *name, struct termios *tio, struct winsize *ws)
|
forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
|
||||||
{
|
{
|
||||||
int slave;
|
int slave;
|
||||||
char *path;
|
char *path;
|
||||||
@@ -42,8 +42,6 @@ forkpty(int *master, char *name, struct termios *tio, struct winsize *ws)
|
|||||||
|
|
||||||
if ((path = ptsname(*master)) == NULL)
|
if ((path = ptsname(*master)) == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
if (name != NULL)
|
|
||||||
strlcpy(name, path, TTY_NAME_MAX);
|
|
||||||
if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1)
|
if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|||||||
30
configure
vendored
30
configure
vendored
@@ -1,20 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# $Id: configure,v 1.43 2009-10-25 21:45:26 nicm Exp $
|
# $Id: configure,v 1.38 2009-09-20 17:51:54 nicm Exp $
|
||||||
#
|
|
||||||
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
#
|
|
||||||
# Permission to use, copy, modify, and distribute this software for any
|
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
|
||||||
# copyright notice and this permission notice appear in all copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
# WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
# OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
#
|
|
||||||
|
|
||||||
TMUX_PLATFORM=${TMUX_PLATFORM:-`uname -s`}
|
TMUX_PLATFORM=${TMUX_PLATFORM:-`uname -s`}
|
||||||
|
|
||||||
@@ -37,6 +22,7 @@ cat <<EOF >>$CONFIG_H
|
|||||||
#undef HAVE_GETOPT
|
#undef HAVE_GETOPT
|
||||||
#undef HAVE_IMSG
|
#undef HAVE_IMSG
|
||||||
#undef HAVE_LIBUTIL_H
|
#undef HAVE_LIBUTIL_H
|
||||||
|
#undef HAVE_LOGIN_CAP
|
||||||
#undef HAVE_PATHS_H
|
#undef HAVE_PATHS_H
|
||||||
#undef HAVE_POLL
|
#undef HAVE_POLL
|
||||||
#undef HAVE_PROGNAME
|
#undef HAVE_PROGNAME
|
||||||
@@ -65,6 +51,7 @@ case $TMUX_PLATFORM in
|
|||||||
#define HAVE_FGETLN
|
#define HAVE_FGETLN
|
||||||
#define HAVE_FORKPTY
|
#define HAVE_FORKPTY
|
||||||
#define HAVE_GETOPT
|
#define HAVE_GETOPT
|
||||||
|
#define HAVE_LOGIN_CAP
|
||||||
#define HAVE_PATHS_H
|
#define HAVE_PATHS_H
|
||||||
#define HAVE_POLL
|
#define HAVE_POLL
|
||||||
#define HAVE_PROGNAME
|
#define HAVE_PROGNAME
|
||||||
@@ -152,9 +139,15 @@ EOF
|
|||||||
#define HAVE_STRLCPY
|
#define HAVE_STRLCPY
|
||||||
EOF
|
EOF
|
||||||
cat <<EOF >>$CONFIG_MK
|
cat <<EOF >>$CONFIG_MK
|
||||||
|
CPPFLAGS+= -I/usr/local/include/ncurses \
|
||||||
|
-I/opt/csw/include -I/opt/csw/include/ncurses \
|
||||||
|
-I/opt/sfw/include -I/opt/sfw/include/ncurses
|
||||||
CFLAGS+= -D_XPG4_2 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
|
CFLAGS+= -D_XPG4_2 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
|
||||||
|
LDFLAGS+= -L/usr/gnu/lib \
|
||||||
|
-L/opt/csw/lib \
|
||||||
|
-L/opt/sfw/lib
|
||||||
LIBS+= -lcurses -lsocket -lnsl
|
LIBS+= -lcurses -lsocket -lnsl
|
||||||
SRCS+= osdep-sunos.c \
|
SRCS+= osdep-unknown.c \
|
||||||
compat/asprintf.c \
|
compat/asprintf.c \
|
||||||
compat/daemon.c \
|
compat/daemon.c \
|
||||||
compat/fgetln.c \
|
compat/fgetln.c \
|
||||||
@@ -209,6 +202,7 @@ EOF
|
|||||||
#define HAVE_FORKPTY
|
#define HAVE_FORKPTY
|
||||||
#define HAVE_GETOPT
|
#define HAVE_GETOPT
|
||||||
#define HAVE_LIBUTIL_H
|
#define HAVE_LIBUTIL_H
|
||||||
|
#define HAVE_LOGIN_CAP
|
||||||
#define HAVE_PATHS_H
|
#define HAVE_PATHS_H
|
||||||
#define HAVE_POLL
|
#define HAVE_POLL
|
||||||
#define HAVE_PROGNAME
|
#define HAVE_PROGNAME
|
||||||
@@ -218,6 +212,7 @@ EOF
|
|||||||
#define HAVE_STRLCPY
|
#define HAVE_STRLCPY
|
||||||
#define HAVE_STRTONUM
|
#define HAVE_STRTONUM
|
||||||
#define HAVE_STRSEP
|
#define HAVE_STRSEP
|
||||||
|
#define HAVE_TREE_H
|
||||||
#define HAVE_U_INT
|
#define HAVE_U_INT
|
||||||
EOF
|
EOF
|
||||||
cat <<EOF >>$CONFIG_MK
|
cat <<EOF >>$CONFIG_MK
|
||||||
@@ -238,6 +233,7 @@ EOF
|
|||||||
#define HAVE_FGETLN
|
#define HAVE_FGETLN
|
||||||
#define HAVE_FORKPTY
|
#define HAVE_FORKPTY
|
||||||
#define HAVE_GETOPT
|
#define HAVE_GETOPT
|
||||||
|
#define HAVE_LOGIN_CAP
|
||||||
#define HAVE_PATHS_H
|
#define HAVE_PATHS_H
|
||||||
#define HAVE_POLL
|
#define HAVE_POLL
|
||||||
#define HAVE_PROGNAME
|
#define HAVE_PROGNAME
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
# $Id: h-boetes.conf,v 1.2 2009-10-25 21:45:26 nicm Exp $
|
|
||||||
#
|
|
||||||
# From Han Boetes.
|
|
||||||
|
|
||||||
set -g default-command zsh
|
set -g default-command zsh
|
||||||
set -g status-right "#(uptime|awk '{print $11}') #(date)"
|
set -g status-right "#(uptime|awk '{print $11}') #(date)"
|
||||||
|
|
||||||
|
|||||||
@@ -1,66 +1,52 @@
|
|||||||
# $Id: n-marriott.conf,v 1.10 2009-10-25 21:45:26 nicm Exp $
|
|
||||||
#
|
|
||||||
# By Nicholas Marriott. Public domain.
|
|
||||||
|
|
||||||
# Default global options.
|
# Default global options.
|
||||||
set -g status-bg green
|
set -g status-bg green
|
||||||
set -g status-right "%H:%M" # %d-%b-%y
|
set -g status-right-length 60
|
||||||
|
set -g default-command "exec /bin/ksh -l"
|
||||||
set -g bell-action none
|
set -g bell-action none
|
||||||
set -g lock-after-time 1800
|
set -g lock-after-time 1800
|
||||||
|
|
||||||
# Default global window options.
|
# Default global window options.
|
||||||
setw -g remain-on-exit on
|
#setw -g remain-on-exit on
|
||||||
setw -g window-status-current-attr "underscore"
|
|
||||||
|
|
||||||
# Prefix key.
|
# Prefix key.
|
||||||
set -g prefix C-a
|
set -g prefix C-a
|
||||||
unbind C-b
|
unbind C-b
|
||||||
bind C-a send-prefix
|
bind C-a send-prefix
|
||||||
|
|
||||||
|
# Unlock password.
|
||||||
|
pass -c '$2a$06$7LpuTSfDjcz.KD3a9mdEuuJmC.zEq6RBqHWMjdv9/qqzrfWedUBHe'
|
||||||
|
|
||||||
# Keys to switch session.
|
# Keys to switch session.
|
||||||
bind Q switchc -t0
|
bind q switchc -t0
|
||||||
bind W switchc -t1
|
bind w switchc -t1
|
||||||
bind E switchc -t2
|
bind e switchc -t2
|
||||||
|
|
||||||
# Other key bindings.
|
# Other key bindings.
|
||||||
bind F1 selectw -t:10
|
bind i choose-window
|
||||||
bind F2 selectw -t:11
|
|
||||||
bind F3 selectw -t:12
|
|
||||||
bind F4 selectw -t:13
|
|
||||||
bind F5 selectw -t:14
|
|
||||||
bind F6 selectw -t:15
|
|
||||||
bind F7 selectw -t:16
|
|
||||||
bind F8 selectw -t:17
|
|
||||||
bind F9 selectw -t:18
|
|
||||||
bind F10 selectw -t:19
|
|
||||||
bind F11 selectw -t:20
|
|
||||||
bind F12 selectw -t:21
|
|
||||||
|
|
||||||
bind m setw monitor-activity
|
bind m setw monitor-activity
|
||||||
|
|
||||||
bind y setw force-width 81
|
bind y setw force-width 81
|
||||||
bind u setw force-width 0
|
bind u setw force-width 0
|
||||||
|
|
||||||
bind -n F1 run-shell 'mpc toggle >/dev/null 2>&1'
|
bind D detach \; lock
|
||||||
bind -n F2 run-shell 'mpc'
|
bind N neww \; splitw -d
|
||||||
bind -n F3 run-shell 'mpc prev >/dev/null 2>&1'
|
|
||||||
bind -n F4 run-shell 'mpc next >/dev/null 2>&1'
|
bind '~' split-window "exec top -s 0.5"
|
||||||
bind -n F5 run-shell 'mpc volume -5 >/dev/null 2>&1'
|
bind "#" split-window "exec ncmpc -f ~/.ncmpc.conf"
|
||||||
bind -n F6 run-shell 'mpc volume +5 >/dev/null 2>&1'
|
bind / command-prompt "split-window 'exec man %%'"
|
||||||
|
|
||||||
# First session.
|
# First session.
|
||||||
new -d -s0 -nirssi 'exec ssh -t natalya exec sh ~/bin/tmux-start'
|
new -d -s0 -nirssi 'exec ssh -t natalya screen -DRS irssi irssi'
|
||||||
setw -t0:0 monitor-activity on
|
setw -t0:0 monitor-activity on
|
||||||
setw -t0:0 aggressive-resize on
|
setw -t0:0 aggressive-resize on
|
||||||
set -t0 status-bg green
|
set -t0 status-bg green
|
||||||
neww -d -ntodo 'exec emacs ~/TODO'
|
neww -d -ntodo 'exec emacs ~/TODO'
|
||||||
setw -t0:1 aggressive-resize on
|
setw -t0:1 aggressive-resize on
|
||||||
neww -d -ntodo2 'exec emacs ~/TODO2'
|
|
||||||
setw -t0:2 aggressive-resize on
|
|
||||||
neww -d -nncmpc 'exec ncmpc -f ~/.ncmpc.conf'
|
neww -d -nncmpc 'exec ncmpc -f ~/.ncmpc.conf'
|
||||||
setw -t0:3 aggressive-resize on
|
setw -t0:2 aggressive-resize on
|
||||||
neww -d -nmutt 'exec mutt'
|
neww -d -nmutt 'exec mutt'
|
||||||
setw -t0:4 aggressive-resize on
|
setw -t0:3 aggressive-resize on
|
||||||
neww -d
|
neww -d
|
||||||
neww -d
|
neww -d
|
||||||
neww -d
|
neww -d
|
||||||
@@ -77,7 +63,6 @@ linkw -dk -t0 -s0:0
|
|||||||
linkw -dk -t1 -s0:1
|
linkw -dk -t1 -s0:1
|
||||||
linkw -dk -t2 -s0:2
|
linkw -dk -t2 -s0:2
|
||||||
linkw -dk -t3 -s0:3
|
linkw -dk -t3 -s0:3
|
||||||
linkw -dk -t4 -s0:4
|
|
||||||
neww -d
|
neww -d
|
||||||
neww -d
|
neww -d
|
||||||
neww -d
|
neww -d
|
||||||
@@ -92,7 +77,6 @@ linkw -dk -t0 -s0:0
|
|||||||
linkw -dk -t1 -s0:1
|
linkw -dk -t1 -s0:1
|
||||||
linkw -dk -t2 -s0:2
|
linkw -dk -t2 -s0:2
|
||||||
linkw -dk -t3 -s0:3
|
linkw -dk -t3 -s0:3
|
||||||
linkw -dk -t4 -s0:4
|
|
||||||
neww -d
|
neww -d
|
||||||
neww -d
|
neww -d
|
||||||
neww -d
|
neww -d
|
||||||
|
|||||||
11
examples/n-marriott.sh
Normal file
11
examples/n-marriott.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh -x
|
||||||
|
|
||||||
|
[ ! -z "$TMUX" ] && exit
|
||||||
|
|
||||||
|
# I alias this script to "session" in .profile and use it to reconnect to
|
||||||
|
# the main session (0) on my main tmux server.
|
||||||
|
|
||||||
|
TMUX="tmux -dLmain"
|
||||||
|
|
||||||
|
$TMUX has -t0 2>/dev/null || $TMUX -qf ~/.tmux.conf.main start
|
||||||
|
exec $TMUX attach -d -t0
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
# $Id: screen-keys.conf,v 1.5 2009-10-25 21:58:05 nicm Exp $
|
# $Id: screen-keys.conf,v 1.3 2009-08-07 12:09:50 nicm Exp $
|
||||||
#
|
|
||||||
# By Nicholas Marriott. Public domain.
|
|
||||||
#
|
#
|
||||||
# This configuration file binds many of the common GNU screen key bindings to
|
# This configuration file binds many of the common GNU screen key bindings to
|
||||||
# appropriate tmux key bindings. Note that for some key bindings there is no
|
# appropriate tmux key bindings. Note that for some key bindings there is no
|
||||||
@@ -75,13 +73,13 @@ bind w list-windows
|
|||||||
|
|
||||||
# quit \
|
# quit \
|
||||||
unbind \
|
unbind \
|
||||||
bind \ confirm-before "kill-server"
|
bind \ kill-server
|
||||||
|
|
||||||
# kill K k
|
# kill K k
|
||||||
unbind K
|
unbind K
|
||||||
bind K confirm-before "kill-window"
|
bind K kill-window
|
||||||
unbind k
|
unbind k
|
||||||
bind k confirm-before "kill-window"
|
bind k kill-window
|
||||||
|
|
||||||
# redisplay ^L l
|
# redisplay ^L l
|
||||||
unbind ^L
|
unbind ^L
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
# $Id: t-williams.conf,v 1.1 2009-11-02 18:59:28 nicm Exp $
|
|
||||||
#
|
|
||||||
# ~/.tmux.conf - tmux terminal multiplexer config
|
|
||||||
# Thayer Williams (http://cinderwick.ca)
|
|
||||||
# "Feel free to do whatever you like with it."
|
|
||||||
|
|
||||||
# I typically start tmux from ~/.xinitrc with the following:
|
|
||||||
#
|
|
||||||
# urxvt -e bash -c "tmux attach -d -t mysession" &
|
|
||||||
#
|
|
||||||
# and recall it any time thereafter with xbindkeys (Mod4+s):
|
|
||||||
#
|
|
||||||
# "urxvt -e bash -c 'tmux attach -d -t mysession'"
|
|
||||||
# m:0x50 + c:39
|
|
||||||
|
|
||||||
|
|
||||||
# set prefix key to ctrl+a until I have time to adapt
|
|
||||||
unbind C-b
|
|
||||||
set -g prefix C-a
|
|
||||||
|
|
||||||
# send the prefix to client inside window (ala nested sessions)
|
|
||||||
bind-key a send-prefix
|
|
||||||
|
|
||||||
# toggle last window like screen
|
|
||||||
bind-key C-a last-window
|
|
||||||
|
|
||||||
# confirm before killing a window or the server
|
|
||||||
bind-key k confirm kill-window
|
|
||||||
bind-key K confirm kill-server
|
|
||||||
|
|
||||||
# toggle statusbar
|
|
||||||
bind-key b set-option status
|
|
||||||
|
|
||||||
# ctrl+left/right cycles thru windows
|
|
||||||
bind-key -n C-right next
|
|
||||||
bind-key -n C-left prev
|
|
||||||
|
|
||||||
# open a man page in new window
|
|
||||||
bind / command-prompt "split-window 'exec man %%'"
|
|
||||||
|
|
||||||
# quick view of processes
|
|
||||||
bind '~' split-window "exec htop"
|
|
||||||
|
|
||||||
# scrollback buffer n lines
|
|
||||||
set -g history-limit 5000
|
|
||||||
|
|
||||||
# listen for activity on all windows
|
|
||||||
set -g bell-action any
|
|
||||||
|
|
||||||
# on-screen time for display-panes in ms
|
|
||||||
set -g display-panes-time 2000
|
|
||||||
|
|
||||||
# start window indexing at one instead of zero
|
|
||||||
set -g base-index 1
|
|
||||||
|
|
||||||
# enable wm window titles
|
|
||||||
set -g set-titles on
|
|
||||||
|
|
||||||
# wm window title string (uses statusbar variables)
|
|
||||||
set -g set-titles-string "tmux.#I.#W"
|
|
||||||
|
|
||||||
# session initialization
|
|
||||||
new -s mysession mutt
|
|
||||||
neww -t 2
|
|
||||||
neww -d -t 3
|
|
||||||
neww -d -t 5 mocp
|
|
||||||
neww -d -t 6 rtorrent
|
|
||||||
selectw -t 1
|
|
||||||
|
|
||||||
# statusbar --------------------------------------------------------------
|
|
||||||
|
|
||||||
set -g display-time 2000
|
|
||||||
|
|
||||||
# default statusbar colors
|
|
||||||
set -g status-fg white
|
|
||||||
set -g status-bg default
|
|
||||||
set -g status-attr default
|
|
||||||
|
|
||||||
# default window title colors
|
|
||||||
set-window-option -g window-status-fg cyan
|
|
||||||
set-window-option -g window-status-bg default
|
|
||||||
set-window-option -g window-status-attr dim
|
|
||||||
|
|
||||||
# active window title colors
|
|
||||||
set-window-option -g window-status-current-fg white
|
|
||||||
set-window-option -g window-status-current-bg default
|
|
||||||
set-window-option -g window-status-current-attr bright
|
|
||||||
|
|
||||||
# command/message line colors
|
|
||||||
set -g message-fg white
|
|
||||||
set -g message-bg black
|
|
||||||
set -g message-attr bright
|
|
||||||
|
|
||||||
# center align the window list
|
|
||||||
set -g status-justify centre
|
|
||||||
|
|
||||||
# show some useful stats but only when tmux is started
|
|
||||||
# outside of Xorg, otherwise dwm statusbar shows these already
|
|
||||||
set -g status-right ""
|
|
||||||
set -g status-left ""
|
|
||||||
if '[ -z "$DISPLAY" ]' 'set -g status-left "[#[fg=green] #H #[default]]"'
|
|
||||||
if '[ -z "$DISPLAY" ]' 'set -g status-right "[ #[fg=magenta]#(cat /proc/loadavg | cut -d \" \" -f 1,2,3)#[default] ][ #[fg=cyan,bright]%a %Y-%m-%d %H:%M #[default]]"'
|
|
||||||
if '[ -z "$DISPLAY" ]' 'set -g status-right-length 50'
|
|
||||||
|
|
||||||
@@ -1,8 +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: 2009-10-25 22:16:55 $
|
" Last Change: $Date: 2009-09-19 18:53:56 $
|
||||||
" License: This file is placed in the public domain.
|
|
||||||
|
|
||||||
if version < 600
|
if version < 600
|
||||||
syntax clear
|
syntax clear
|
||||||
@@ -24,14 +23,14 @@ syn keyword tmuxCmds send-prefix refresh[-client] killw kill-window lsc
|
|||||||
syn keyword tmuxCmds list-clients linkw link-window unlinkw unlink-window
|
syn keyword tmuxCmds list-clients linkw link-window unlinkw unlink-window
|
||||||
syn keyword tmuxCmds next[-window] send[-keys] swapw swap-window
|
syn keyword tmuxCmds next[-window] send[-keys] swapw swap-window
|
||||||
syn keyword tmuxCmds rename[-session] kill-session switchc switch-client
|
syn keyword tmuxCmds rename[-session] kill-session switchc switch-client
|
||||||
syn keyword tmuxCmds has[-session] copy-mode pasteb paste-buffer
|
syn keyword tmuxCmds has[-session] scroll-mode copy-mode pasteb paste-buffer
|
||||||
syn keyword tmuxCmds new[-session] start[-server] kill-server setw
|
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 select-prompt 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 downp down-pane killp
|
syn keyword tmuxCmds pass set-password 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 upp up-pane 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
|
||||||
@@ -39,9 +38,7 @@ 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]
|
||||||
syn keyword tmuxCmds clearhist clear-history selectl select-layout if[-shell]
|
syn keyword tmuxCmds clearhist clear-history selectl select-layout if[-shell]
|
||||||
syn keyword tmuxCmds display[-message] set-environment show-environment
|
syn keyword tmuxCmds display[-message] set-environment show-environment
|
||||||
syn keyword tmuxCmds choose-client displayp display-panes run[-shell] lockc
|
syn keyword tmuxCmds choose-client displayp display-panes
|
||||||
syn keyword tmuxCmds lock-client locks lock-session lsp list-panes pipep
|
|
||||||
syn keyword tmuxCmds pipe-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
|
||||||
@@ -55,8 +52,7 @@ syn keyword tmuxOptsSet terminal-overrides status-left-attr status-left-bg
|
|||||||
syn keyword tmuxOptsSet status-left-fg status-right-attr status-right-bg
|
syn keyword tmuxOptsSet status-left-fg status-right-attr status-right-bg
|
||||||
syn keyword tmuxOptsSet status-right-fg update-environment base-index
|
syn keyword tmuxOptsSet status-right-fg update-environment base-index
|
||||||
syn keyword tmuxOptsSet display-panes-colour display-panes-time default-shell
|
syn keyword tmuxOptsSet display-panes-colour display-panes-time default-shell
|
||||||
syn keyword tmuxOptsSet set-titles-string lock-command lock-server
|
syn keyword tmuxOptsSet set-titles-string
|
||||||
syn keyword tmuxOptsSet mouse-select-pane
|
|
||||||
|
|
||||||
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
|
||||||
@@ -65,7 +61,7 @@ syn keyword tmuxOptsSetw xterm-keys mode-attr window-status-attr
|
|||||||
syn keyword tmuxOptsSetw window-status-bg window-status-fg automatic-rename
|
syn keyword tmuxOptsSetw window-status-bg window-status-fg automatic-rename
|
||||||
syn keyword tmuxOptsSetw main-pane-width main-pane-height monitor-content
|
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
|
||||||
|
|
||||||
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
|
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
|
||||||
|
|
||||||
|
|||||||
23
grid-view.c
23
grid-view.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: grid-view.c,v 1.19 2009-10-15 01:55:12 tcunha Exp $ */
|
/* $Id: grid-view.c,v 1.18 2009-07-14 06:40:33 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -92,20 +92,15 @@ grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower)
|
|||||||
{
|
{
|
||||||
GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
|
GRID_DEBUG(gd, "rupper=%u, rlower=%u", rupper, rlower);
|
||||||
|
|
||||||
if (gd->flags & GRID_HISTORY) {
|
if (gd->flags & GRID_HISTORY && rupper == 0 && rlower == gd->sy - 1) {
|
||||||
grid_collect_history(gd);
|
grid_scroll_line(gd);
|
||||||
if (rupper == 0 && rlower == gd->sy - 1)
|
return;
|
||||||
grid_scroll_history(gd);
|
|
||||||
else {
|
|
||||||
rupper = grid_view_y(gd, rupper);
|
|
||||||
rlower = grid_view_y(gd, rlower);
|
|
||||||
grid_scroll_history_region(gd, rupper, rlower);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rupper = grid_view_y(gd, rupper);
|
|
||||||
rlower = grid_view_y(gd, rlower);
|
|
||||||
grid_move_lines(gd, rupper, rupper + 1, rlower - rupper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rupper = grid_view_y(gd, rupper);
|
||||||
|
rlower = grid_view_y(gd, rlower);
|
||||||
|
|
||||||
|
grid_move_lines(gd, rupper, rupper + 1, rlower - rupper);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scroll region down. */
|
/* Scroll region down. */
|
||||||
|
|||||||
72
grid.c
72
grid.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: grid.c,v 1.34 2009-10-15 01:55:12 tcunha Exp $ */
|
/* $Id: grid.c,v 1.33 2009-09-15 23:54:57 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -161,80 +161,32 @@ grid_compare(struct grid *ga, struct grid *gb)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Scroll a line into the history. */
|
||||||
* Collect lines from the history if at the limit. Free the top (oldest) 10%
|
|
||||||
* and shift up.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
grid_collect_history(struct grid *gd)
|
grid_scroll_line(struct grid *gd)
|
||||||
{
|
{
|
||||||
u_int yy;
|
u_int yy;
|
||||||
|
|
||||||
GRID_DEBUG(gd, "");
|
GRID_DEBUG(gd, "");
|
||||||
|
|
||||||
if (gd->hsize < gd->hlimit)
|
if (gd->hsize >= gd->hlimit) {
|
||||||
return;
|
/* If the limit is hit, free the bottom 10% and shift up. */
|
||||||
|
yy = gd->hlimit / 10;
|
||||||
|
if (yy < 1)
|
||||||
|
yy = 1;
|
||||||
|
|
||||||
yy = gd->hlimit / 10;
|
grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy);
|
||||||
if (yy < 1)
|
gd->hsize -= yy;
|
||||||
yy = 1;
|
}
|
||||||
|
|
||||||
grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy);
|
|
||||||
gd->hsize -= yy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Scroll the entire visible screen, moving one line into the history. Just
|
|
||||||
* allocate a new line at the bottom and move the history size indicator.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
grid_scroll_history(struct grid *gd)
|
|
||||||
{
|
|
||||||
u_int yy;
|
|
||||||
|
|
||||||
GRID_DEBUG(gd, "");
|
|
||||||
|
|
||||||
yy = gd->hsize + gd->sy;
|
yy = gd->hsize + gd->sy;
|
||||||
|
|
||||||
gd->linedata = xrealloc(gd->linedata, yy + 1, sizeof *gd->linedata);
|
gd->linedata = xrealloc(gd->linedata, yy + 1, sizeof *gd->linedata);
|
||||||
memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]);
|
memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]);
|
||||||
|
|
||||||
gd->hsize++;
|
gd->hsize++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scroll a region up, moving the top line into the history. */
|
|
||||||
void
|
|
||||||
grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower)
|
|
||||||
{
|
|
||||||
struct grid_line *gl_history, *gl_upper, *gl_lower;
|
|
||||||
u_int yy;
|
|
||||||
|
|
||||||
GRID_DEBUG(gd, "upper=%u, lower=%u", upper, lower);
|
|
||||||
|
|
||||||
/* Create a space for a new line. */
|
|
||||||
yy = gd->hsize + gd->sy;
|
|
||||||
gd->linedata = xrealloc(gd->linedata, yy + 1, sizeof *gd->linedata);
|
|
||||||
|
|
||||||
/* Move the entire screen down to free a space for this line. */
|
|
||||||
gl_history = &gd->linedata[gd->hsize];
|
|
||||||
memmove(gl_history + 1, gl_history, gd->sy * sizeof *gl_history);
|
|
||||||
|
|
||||||
/* Adjust the region and find its start and end. */
|
|
||||||
upper++;
|
|
||||||
gl_upper = &gd->linedata[upper];
|
|
||||||
lower++;
|
|
||||||
gl_lower = &gd->linedata[lower];
|
|
||||||
|
|
||||||
/* Move the line into the history. */
|
|
||||||
memcpy(gl_history, gl_upper, sizeof *gl_history);
|
|
||||||
|
|
||||||
/* Then move the region up and clear the bottom line. */
|
|
||||||
memmove(gl_upper, gl_upper + 1, (lower - upper) * sizeof *gl_upper);
|
|
||||||
memset(gl_lower, 0, sizeof *gl_lower);
|
|
||||||
|
|
||||||
/* Move the history offset down over the line. */
|
|
||||||
gd->hsize++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expand line to fit to cell. */
|
/* Expand line to fit to cell. */
|
||||||
void
|
void
|
||||||
grid_expand_line(struct grid *gd, u_int py, u_int sx)
|
grid_expand_line(struct grid *gd, u_int py, u_int sx)
|
||||||
|
|||||||
271
input-keys.c
271
input-keys.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: input-keys.c,v 1.39 2009-10-28 23:05:01 tcunha Exp $ */
|
/* $Id: input-keys.c,v 1.29 2009-07-28 22:37:02 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -24,13 +24,6 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is rather misleadingly named, it contains the code which takes a
|
|
||||||
* key code and translates it into something suitable to be sent to the
|
|
||||||
* application running in a pane (similar to input.c does in the other
|
|
||||||
* direction with output).
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct input_key_ent {
|
struct input_key_ent {
|
||||||
int key;
|
int key;
|
||||||
const char *data;
|
const char *data;
|
||||||
@@ -38,138 +31,111 @@ struct input_key_ent {
|
|||||||
int flags;
|
int flags;
|
||||||
#define INPUTKEY_KEYPAD 0x1 /* keypad key */
|
#define INPUTKEY_KEYPAD 0x1 /* keypad key */
|
||||||
#define INPUTKEY_CURSOR 0x2 /* cursor key */
|
#define INPUTKEY_CURSOR 0x2 /* cursor key */
|
||||||
|
#define INPUTKEY_CTRL 0x4 /* may be modified with ctrl */
|
||||||
|
#define INPUTKEY_XTERM 0x4 /* may have xterm argument appended */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct input_key_ent input_keys[] = {
|
struct input_key_ent input_keys[] = {
|
||||||
/* Backspace key. */
|
/* Backspace key. */
|
||||||
{ KEYC_BSPACE, "\177", 0 },
|
{ KEYC_BSPACE, "\177", 0 },
|
||||||
|
|
||||||
/* Function keys. */
|
/* Function keys. */
|
||||||
{ KEYC_F1, "\033OP", 0 },
|
{ KEYC_F1, "\033OP", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F2, "\033OQ", 0 },
|
{ KEYC_F2, "\033OQ", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F3, "\033OR", 0 },
|
{ KEYC_F3, "\033OR", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F4, "\033OS", 0 },
|
{ KEYC_F4, "\033OS", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F5, "\033[15~", 0 },
|
{ KEYC_F5, "\033[15~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F5|KEYC_CTRL, "\033[15^", 0 },
|
{ KEYC_F6, "\033[17~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F6, "\033[17~", 0 },
|
{ KEYC_F7, "\033[18~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F6|KEYC_CTRL, "\033[17^", 0 },
|
{ KEYC_F8, "\033[19~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F7, "\033[18~", 0 },
|
{ KEYC_F9, "\033[20~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F7|KEYC_CTRL, "\033[18^", 0 },
|
{ KEYC_F10, "\033[21~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F8, "\033[19~", 0 },
|
{ KEYC_F11, "\033[23~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F8|KEYC_CTRL, "\033[19^", 0 },
|
{ KEYC_F12, "\033[24~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F9, "\033[20~", 0 },
|
{ KEYC_F13, "\033[25~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F9|KEYC_CTRL, "\033[20^", 0 },
|
{ KEYC_F14, "\033[26~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F10, "\033[21~", 0 },
|
{ KEYC_F15, "\033[28~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F10|KEYC_CTRL, "\033[21^", 0 },
|
{ KEYC_F16, "\033[29~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F11, "\033[23~", 0 },
|
{ KEYC_F17, "\033[31~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F1|KEYC_CTRL, "\033[23^", 0 },
|
{ KEYC_F18, "\033[32~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F12, "\033[24~", 0 },
|
{ KEYC_F19, "\033[33~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F12|KEYC_CTRL, "\033[24^", 0 },
|
{ KEYC_F20, "\033[34~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F13, "\033[25~", 0 },
|
{ KEYC_IC, "\033[2~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F13|KEYC_CTRL, "\033[25^", 0 },
|
{ KEYC_DC, "\033[3~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F14, "\033[26~", 0 },
|
{ KEYC_HOME, "\033[1~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F14|KEYC_CTRL, "\033[26^", 0 },
|
{ KEYC_END, "\033[4~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F15, "\033[28~", 0 },
|
{ KEYC_NPAGE, "\033[6~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F15|KEYC_CTRL, "\033[28^", 0 },
|
{ KEYC_PPAGE, "\033[5~", INPUTKEY_CTRL|INPUTKEY_XTERM },
|
||||||
{ KEYC_F16, "\033[29~", 0 },
|
{ KEYC_BTAB, "\033[Z", INPUTKEY_CTRL },
|
||||||
{ KEYC_F16|KEYC_CTRL, "\033[29^", 0 },
|
|
||||||
{ KEYC_F17, "\033[31~", 0 },
|
|
||||||
{ KEYC_F17|KEYC_CTRL, "\033[31^", 0 },
|
|
||||||
{ KEYC_F18, "\033[32~", 0 },
|
|
||||||
{ KEYC_F18|KEYC_CTRL, "\033[32^", 0 },
|
|
||||||
{ KEYC_F19, "\033[33~", 0 },
|
|
||||||
{ KEYC_F19|KEYC_CTRL, "\033[33^", 0 },
|
|
||||||
{ KEYC_F20, "\033[34~", 0 },
|
|
||||||
{ KEYC_F20|KEYC_CTRL, "\033[34^", 0 },
|
|
||||||
{ KEYC_IC, "\033[2~", 0 },
|
|
||||||
{ KEYC_IC|KEYC_CTRL, "\033[2^", 0 },
|
|
||||||
{ KEYC_DC, "\033[3~", 0 },
|
|
||||||
{ KEYC_DC|KEYC_CTRL, "\033[3^", 0 },
|
|
||||||
{ KEYC_HOME, "\033[1~", 0 },
|
|
||||||
{ KEYC_HOME|KEYC_CTRL, "\033[1^", 0 },
|
|
||||||
{ KEYC_END, "\033[4~", 0 },
|
|
||||||
{ KEYC_END|KEYC_CTRL, "\033[4^", 0 },
|
|
||||||
{ KEYC_NPAGE, "\033[6~", 0 },
|
|
||||||
{ KEYC_NPAGE|KEYC_CTRL, "\033[6^", 0 },
|
|
||||||
{ KEYC_PPAGE, "\033[5~", 0 },
|
|
||||||
{ KEYC_PPAGE|KEYC_CTRL, "\033[5^", 0 },
|
|
||||||
{ KEYC_BTAB, "\033[Z", 0 },
|
|
||||||
|
|
||||||
/*
|
/* Arrow keys. Cursor versions must come first. */
|
||||||
* Arrow keys. Cursor versions must come first. The codes are toggled
|
{ KEYC_UP | KEYC_CTRL, "\033Oa", 0 },
|
||||||
* between CSI and SS3 versions when ctrl is pressed.
|
{ KEYC_DOWN | KEYC_CTRL, "\033Ob", 0 },
|
||||||
*/
|
{ KEYC_RIGHT | KEYC_CTRL, "\033Oc", 0 },
|
||||||
{ KEYC_UP|KEYC_CTRL, "\033[A", INPUTKEY_CURSOR },
|
{ KEYC_LEFT | KEYC_CTRL, "\033Od", 0 },
|
||||||
{ KEYC_DOWN|KEYC_CTRL, "\033[B", INPUTKEY_CURSOR },
|
|
||||||
{ KEYC_RIGHT|KEYC_CTRL, "\033[C", INPUTKEY_CURSOR },
|
|
||||||
{ KEYC_LEFT|KEYC_CTRL, "\033[D", INPUTKEY_CURSOR },
|
|
||||||
|
|
||||||
{ KEYC_UP, "\033OA", INPUTKEY_CURSOR },
|
{ KEYC_UP | KEYC_SHIFT, "\033[a", 0 },
|
||||||
{ KEYC_DOWN, "\033OB", INPUTKEY_CURSOR },
|
{ KEYC_DOWN | KEYC_SHIFT, "\033[b", 0 },
|
||||||
{ KEYC_RIGHT, "\033OC", INPUTKEY_CURSOR },
|
{ KEYC_RIGHT | KEYC_SHIFT, "\033[c", 0 },
|
||||||
{ KEYC_LEFT, "\033OD", INPUTKEY_CURSOR },
|
{ KEYC_LEFT | KEYC_SHIFT, "\033[d", 0 },
|
||||||
|
|
||||||
{ KEYC_UP|KEYC_CTRL, "\033OA", 0 },
|
{ KEYC_UP, "\033OA", INPUTKEY_CURSOR },
|
||||||
{ KEYC_DOWN|KEYC_CTRL, "\033OB", 0 },
|
{ KEYC_DOWN, "\033OB", INPUTKEY_CURSOR },
|
||||||
{ KEYC_RIGHT|KEYC_CTRL, "\033OC", 0 },
|
{ KEYC_RIGHT, "\033OC", INPUTKEY_CURSOR },
|
||||||
{ KEYC_LEFT|KEYC_CTRL, "\033OD", 0 },
|
{ KEYC_LEFT, "\033OD", INPUTKEY_CURSOR },
|
||||||
|
|
||||||
{ KEYC_UP, "\033[A", 0 },
|
{ KEYC_UP, "\033[A", 0 },
|
||||||
{ KEYC_DOWN, "\033[B", 0 },
|
{ KEYC_DOWN, "\033[B", 0 },
|
||||||
{ KEYC_RIGHT, "\033[C", 0 },
|
{ KEYC_RIGHT, "\033[C", 0 },
|
||||||
{ KEYC_LEFT, "\033[D", 0 },
|
{ KEYC_LEFT, "\033[D", 0 },
|
||||||
|
|
||||||
/* Keypad keys. Keypad versions must come first. */
|
/* Keypad keys. Keypad versions must come first. */
|
||||||
{ KEYC_KP_SLASH, "/", INPUTKEY_KEYPAD },
|
{ KEYC_KP0_1, "/", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_STAR, "*", INPUTKEY_KEYPAD },
|
{ KEYC_KP0_2, "*", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_MINUS, "-", INPUTKEY_KEYPAD },
|
{ KEYC_KP0_3, "-", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_SEVEN, "7", INPUTKEY_KEYPAD },
|
{ KEYC_KP1_0, "7", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_EIGHT, "8", INPUTKEY_KEYPAD },
|
{ KEYC_KP1_1, "8", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_NINE, "9", INPUTKEY_KEYPAD },
|
{ KEYC_KP1_2, "9", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_PLUS, "+", INPUTKEY_KEYPAD },
|
{ KEYC_KP1_3, "+", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_FOUR, "4", INPUTKEY_KEYPAD },
|
{ KEYC_KP2_0, "4", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_FIVE, "5", INPUTKEY_KEYPAD },
|
{ KEYC_KP2_1, "5", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_SIX, "6", INPUTKEY_KEYPAD },
|
{ KEYC_KP2_2, "6", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_ONE, "1", INPUTKEY_KEYPAD },
|
{ KEYC_KP3_0, "1", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_TWO, "2", INPUTKEY_KEYPAD },
|
{ KEYC_KP3_1, "2", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_THREE, "3", INPUTKEY_KEYPAD },
|
{ KEYC_KP3_2, "3", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_ENTER, "\n", INPUTKEY_KEYPAD },
|
{ KEYC_KP3_3, "\n", INPUTKEY_KEYPAD }, /* this can be CRLF too? */
|
||||||
{ KEYC_KP_ZERO, "0", INPUTKEY_KEYPAD },
|
{ KEYC_KP4_0, "0", INPUTKEY_KEYPAD },
|
||||||
{ KEYC_KP_PERIOD, ".", INPUTKEY_KEYPAD },
|
{ KEYC_KP4_2, ".", INPUTKEY_KEYPAD },
|
||||||
|
{ KEYC_KP0_1, "\033Oo", 0 },
|
||||||
{ KEYC_KP_SLASH, "\033Oo", 0 },
|
{ KEYC_KP0_2, "\033Oj", 0 },
|
||||||
{ KEYC_KP_STAR, "\033Oj", 0 },
|
{ KEYC_KP0_3, "\033Om", 0 },
|
||||||
{ KEYC_KP_MINUS, "\033Om", 0 },
|
{ KEYC_KP1_0, "\033Ow", 0 },
|
||||||
{ KEYC_KP_SEVEN, "\033Ow", 0 },
|
{ KEYC_KP1_1, "\033Ox", 0 },
|
||||||
{ KEYC_KP_EIGHT, "\033Ox", 0 },
|
{ KEYC_KP1_2, "\033Oy", 0 },
|
||||||
{ KEYC_KP_NINE, "\033Oy", 0 },
|
{ KEYC_KP1_3, "\033Ok", 0 },
|
||||||
{ KEYC_KP_PLUS, "\033Ok", 0 },
|
{ KEYC_KP2_0, "\033Ot", 0 },
|
||||||
{ KEYC_KP_FOUR, "\033Ot", 0 },
|
{ KEYC_KP2_1, "\033Ou", 0 },
|
||||||
{ KEYC_KP_FIVE, "\033Ou", 0 },
|
{ KEYC_KP2_2, "\033Ov", 0 },
|
||||||
{ KEYC_KP_SIX, "\033Ov", 0 },
|
{ KEYC_KP3_0, "\033Oq", 0 },
|
||||||
{ KEYC_KP_ONE, "\033Oq", 0 },
|
{ KEYC_KP3_1, "\033Or", 0 },
|
||||||
{ KEYC_KP_TWO, "\033Or", 0 },
|
{ KEYC_KP3_2, "\033Os", 0 },
|
||||||
{ KEYC_KP_THREE, "\033Os", 0 },
|
{ KEYC_KP3_3, "\033OM", 0 },
|
||||||
{ KEYC_KP_ENTER, "\033OM", 0 },
|
{ KEYC_KP4_0, "\033Op", 0 },
|
||||||
{ KEYC_KP_ZERO, "\033Op", 0 },
|
{ KEYC_KP4_2, "\033On", 0 },
|
||||||
{ KEYC_KP_PERIOD, "\033On", 0 },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Translate a key code into an output key sequence. */
|
/* Translate a key code from client into an output key sequence. */
|
||||||
void
|
void
|
||||||
input_key(struct window_pane *wp, int key)
|
input_key(struct window_pane *wp, int key)
|
||||||
{
|
{
|
||||||
struct input_key_ent *ike;
|
struct input_key_ent *ike;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
char ch;
|
||||||
size_t dlen;
|
size_t dlen;
|
||||||
char *out;
|
int xterm_keys;
|
||||||
|
|
||||||
log_debug2("writing key 0x%x", key);
|
log_debug2("writing key 0x%x", key);
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is a normal 7-bit key, just send it, with a leading escape
|
|
||||||
* if necessary.
|
|
||||||
*/
|
|
||||||
if (key != KEYC_NONE && (key & ~KEYC_ESCAPE) < 0x100) {
|
if (key != KEYC_NONE && (key & ~KEYC_ESCAPE) < 0x100) {
|
||||||
if (key & KEYC_ESCAPE)
|
if (key & KEYC_ESCAPE)
|
||||||
buffer_write8(wp->out, '\033');
|
buffer_write8(wp->out, '\033');
|
||||||
@@ -177,19 +143,6 @@ input_key(struct window_pane *wp, int key)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Then try to look this up as an xterm key, if the flag to output them
|
|
||||||
* is set.
|
|
||||||
*/
|
|
||||||
if (options_get_number(&wp->window->options, "xterm-keys")) {
|
|
||||||
if ((out = xterm_keys_lookup(key)) != NULL) {
|
|
||||||
buffer_write(wp->out, out, strlen(out));
|
|
||||||
xfree(out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise look the key up in the table. */
|
|
||||||
for (i = 0; i < nitems(input_keys); i++) {
|
for (i = 0; i < nitems(input_keys); i++) {
|
||||||
ike = &input_keys[i];
|
ike = &input_keys[i];
|
||||||
|
|
||||||
@@ -202,6 +155,12 @@ input_key(struct window_pane *wp, int key)
|
|||||||
|
|
||||||
if ((key & KEYC_ESCAPE) && (ike->key | KEYC_ESCAPE) == key)
|
if ((key & KEYC_ESCAPE) && (ike->key | KEYC_ESCAPE) == key)
|
||||||
break;
|
break;
|
||||||
|
if ((key & KEYC_SHIFT) && (ike->key | KEYC_SHIFT) == key)
|
||||||
|
break;
|
||||||
|
if ((key & KEYC_CTRL) && (ike->key | KEYC_CTRL) == key) {
|
||||||
|
if (ike->flags & INPUTKEY_CTRL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (ike->key == key)
|
if (ike->key == key)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -210,22 +169,62 @@ input_key(struct window_pane *wp, int key)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dlen = strlen(ike->data);
|
dlen = strlen(ike->data);
|
||||||
|
|
||||||
log_debug2("found key 0x%x: \"%s\"", key, ike->data);
|
log_debug2("found key 0x%x: \"%s\"", key, ike->data);
|
||||||
|
|
||||||
/* Prefix a \033 for escape. */
|
/*
|
||||||
|
* If in xterm keys mode, work out and append the modifier as an
|
||||||
|
* argument.
|
||||||
|
*/
|
||||||
|
xterm_keys = options_get_number(&wp->window->options, "xterm-keys");
|
||||||
|
if (xterm_keys && ike->flags & INPUTKEY_XTERM) {
|
||||||
|
ch = '\0';
|
||||||
|
if (key & (KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL))
|
||||||
|
ch = '8';
|
||||||
|
else if (key & (KEYC_ESCAPE|KEYC_CTRL))
|
||||||
|
ch = '7';
|
||||||
|
else if (key & (KEYC_SHIFT|KEYC_CTRL))
|
||||||
|
ch = '6';
|
||||||
|
else if (key & KEYC_CTRL)
|
||||||
|
ch = '5';
|
||||||
|
else if (key & (KEYC_SHIFT|KEYC_ESCAPE))
|
||||||
|
ch = '4';
|
||||||
|
else if (key & KEYC_ESCAPE)
|
||||||
|
ch = '3';
|
||||||
|
else if (key & KEYC_SHIFT)
|
||||||
|
ch = '2';
|
||||||
|
if (ch != '\0') {
|
||||||
|
buffer_write(wp->out, ike->data, dlen - 1);
|
||||||
|
buffer_write8(wp->out, ';');
|
||||||
|
buffer_write8(wp->out, ch);
|
||||||
|
buffer_write8(wp->out, ike->data[dlen - 1]);
|
||||||
|
} else
|
||||||
|
buffer_write(wp->out, ike->data, dlen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not in xterm mode. Prefix a \033 for escape, and set bit 5 of the
|
||||||
|
* last byte for ctrl.
|
||||||
|
*/
|
||||||
if (key & KEYC_ESCAPE)
|
if (key & KEYC_ESCAPE)
|
||||||
buffer_write8(wp->out, '\033');
|
buffer_write8(wp->out, '\033');
|
||||||
|
if (key & KEYC_CTRL && ike->flags & INPUTKEY_CTRL) {
|
||||||
|
buffer_write(wp->out, ike->data, dlen - 1);
|
||||||
|
buffer_write8(wp->out, ike->data[dlen - 1] ^ 0x20);
|
||||||
|
return;
|
||||||
|
}
|
||||||
buffer_write(wp->out, ike->data, dlen);
|
buffer_write(wp->out, ike->data, dlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translate mouse and output. */
|
/* Handle input mouse. */
|
||||||
void
|
void
|
||||||
input_mouse(struct window_pane *wp, struct mouse_event *m)
|
input_mouse(struct window_pane *wp, u_char b, u_char x, u_char y)
|
||||||
{
|
{
|
||||||
if (wp->screen->mode & MODE_MOUSE) {
|
if (wp->screen->mode & MODE_MOUSE) {
|
||||||
buffer_write(wp->out, "\033[M", 3);
|
buffer_write(wp->out, "\033[M", 3);
|
||||||
buffer_write8(wp->out, m->b + 32);
|
buffer_write8(wp->out, b + 32);
|
||||||
buffer_write8(wp->out, m->x + 33);
|
buffer_write8(wp->out, x + 33);
|
||||||
buffer_write8(wp->out, m->y + 33);
|
buffer_write8(wp->out, y + 33);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
80
input.c
80
input.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: input.c,v 1.101 2009-10-28 23:12:38 tcunha Exp $ */
|
/* $Id: input.c,v 1.95 2009-08-21 21:07:20 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -128,7 +128,7 @@ input_sequence_cmp(const void *a, const void *b)
|
|||||||
void
|
void
|
||||||
input_new_argument(struct input_ctx *ictx)
|
input_new_argument(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
struct input_arg *arg;
|
struct input_arg *arg;
|
||||||
|
|
||||||
ARRAY_EXPAND(&ictx->args, 1);
|
ARRAY_EXPAND(&ictx->args, 1);
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ input_new_argument(struct input_ctx *ictx)
|
|||||||
int
|
int
|
||||||
input_add_argument(struct input_ctx *ictx, u_char ch)
|
input_add_argument(struct input_ctx *ictx, u_char ch)
|
||||||
{
|
{
|
||||||
struct input_arg *arg;
|
struct input_arg *arg;
|
||||||
|
|
||||||
if (ARRAY_LENGTH(&ictx->args) == 0)
|
if (ARRAY_LENGTH(&ictx->args) == 0)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -572,14 +572,15 @@ input_state_string_escape(u_char ch, struct input_ctx *ictx)
|
|||||||
void
|
void
|
||||||
input_state_utf8(u_char ch, struct input_ctx *ictx)
|
input_state_utf8(u_char ch, struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
log_debug2("-- utf8 next: %zu: %hhu (%c)", ictx->off, ch, ch);
|
log_debug2("-- un %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||||
|
|
||||||
if (utf8_append(&ictx->utf8data, ch))
|
ictx->utf8_buf[ictx->utf8_off++] = ch;
|
||||||
return; /* more to come */
|
if (--ictx->utf8_len != 0)
|
||||||
|
return;
|
||||||
input_state(ictx, input_state_first);
|
input_state(ictx, input_state_first);
|
||||||
|
|
||||||
ictx->cell.flags |= GRID_FLAG_UTF8;
|
ictx->cell.flags |= GRID_FLAG_UTF8;
|
||||||
screen_write_cell(&ictx->ctx, &ictx->cell, &ictx->utf8data);
|
screen_write_cell(&ictx->ctx, &ictx->cell, ictx->utf8_buf);
|
||||||
ictx->cell.flags &= ~GRID_FLAG_UTF8;
|
ictx->cell.flags &= ~GRID_FLAG_UTF8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,17 +590,40 @@ input_handle_character(u_char ch, struct input_ctx *ictx)
|
|||||||
struct window_pane *wp = ictx->wp;
|
struct window_pane *wp = ictx->wp;
|
||||||
|
|
||||||
if (ch > 0x7f && options_get_number(&wp->window->options, "utf8")) {
|
if (ch > 0x7f && options_get_number(&wp->window->options, "utf8")) {
|
||||||
if (utf8_open(&ictx->utf8data, ch)) {
|
/*
|
||||||
log_debug2("-- utf8 size %zu: %zu: %hhu (%c)",
|
* UTF-8 sequence.
|
||||||
ictx->utf8data.size, ictx->off, ch, ch);
|
*
|
||||||
|
* 11000010-11011111 C2-DF start of 2-byte sequence
|
||||||
|
* 11100000-11101111 E0-EF start of 3-byte sequence
|
||||||
|
* 11110000-11110100 F0-F4 start of 4-byte sequence
|
||||||
|
*/
|
||||||
|
memset(ictx->utf8_buf, 0xff, sizeof ictx->utf8_buf);
|
||||||
|
ictx->utf8_buf[0] = ch;
|
||||||
|
ictx->utf8_off = 1;
|
||||||
|
|
||||||
|
if (ch >= 0xc2 && ch <= 0xdf) {
|
||||||
|
log_debug2("-- u2 %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||||
input_state(ictx, input_state_utf8);
|
input_state(ictx, input_state_utf8);
|
||||||
|
ictx->utf8_len = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ch >= 0xe0 && ch <= 0xef) {
|
||||||
|
log_debug2("-- u3 %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||||
|
input_state(ictx, input_state_utf8);
|
||||||
|
ictx->utf8_len = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ch >= 0xf0 && ch <= 0xf4) {
|
||||||
|
log_debug2("-- u4 %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||||
|
input_state(ictx, input_state_utf8);
|
||||||
|
ictx->utf8_len = 3;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
|
log_debug2("-- ch %zu: %hhu (%c)", ictx->off, ch, ch);
|
||||||
|
|
||||||
ictx->cell.data = ch;
|
ictx->cell.data = ch;
|
||||||
screen_write_cell(&ictx->ctx, &ictx->cell, NULL);
|
screen_write_cell(&ictx->ctx, &ictx->cell, ictx->utf8_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -622,7 +646,7 @@ input_handle_c0_control(u_char ch, struct input_ctx *ictx)
|
|||||||
ictx->wp->window->flags |= WINDOW_BELL;
|
ictx->wp->window->flags |= WINDOW_BELL;
|
||||||
break;
|
break;
|
||||||
case '\010': /* BS */
|
case '\010': /* BS */
|
||||||
screen_write_backspace(&ictx->ctx);
|
screen_write_cursorleft(&ictx->ctx, 1);
|
||||||
break;
|
break;
|
||||||
case '\011': /* TAB */
|
case '\011': /* TAB */
|
||||||
/* Don't tab beyond the end of the line. */
|
/* Don't tab beyond the end of the line. */
|
||||||
@@ -792,7 +816,7 @@ input_handle_sequence(u_char ch, struct input_ctx *ictx)
|
|||||||
{
|
{
|
||||||
struct input_sequence_entry *entry, find;
|
struct input_sequence_entry *entry, find;
|
||||||
struct screen *s = ictx->ctx.s;
|
struct screen *s = ictx->ctx.s;
|
||||||
u_int i;
|
u_int i;
|
||||||
struct input_arg *iarg;
|
struct input_arg *iarg;
|
||||||
|
|
||||||
log_debug2("-- sq %zu: %hhu (%c): %u [sx=%u, sy=%u, cx=%u, cy=%u, "
|
log_debug2("-- sq %zu: %hhu (%c): %u [sx=%u, sy=%u, cx=%u, cy=%u, "
|
||||||
@@ -1161,10 +1185,6 @@ input_handle_sequence_sm(struct input_ctx *ictx)
|
|||||||
screen_write_kcursormode(&ictx->ctx, 1);
|
screen_write_kcursormode(&ictx->ctx, 1);
|
||||||
log_debug("kcursor on");
|
log_debug("kcursor on");
|
||||||
break;
|
break;
|
||||||
case 3: /* DECCOLM */
|
|
||||||
screen_write_cursormove(&ictx->ctx, 0, 0);
|
|
||||||
screen_write_clearscreen(&ictx->ctx);
|
|
||||||
break;
|
|
||||||
case 25: /* TCEM */
|
case 25: /* TCEM */
|
||||||
screen_write_cursormode(&ictx->ctx, 1);
|
screen_write_cursormode(&ictx->ctx, 1);
|
||||||
log_debug("cursor on");
|
log_debug("cursor on");
|
||||||
@@ -1237,10 +1257,6 @@ input_handle_sequence_rm(struct input_ctx *ictx)
|
|||||||
screen_write_kcursormode(&ictx->ctx, 0);
|
screen_write_kcursormode(&ictx->ctx, 0);
|
||||||
log_debug("kcursor off");
|
log_debug("kcursor off");
|
||||||
break;
|
break;
|
||||||
case 3: /* DECCOLM */
|
|
||||||
screen_write_cursormove(&ictx->ctx, 0, 0);
|
|
||||||
screen_write_clearscreen(&ictx->ctx);
|
|
||||||
break;
|
|
||||||
case 25: /* TCEM */
|
case 25: /* TCEM */
|
||||||
screen_write_cursormode(&ictx->ctx, 0);
|
screen_write_cursormode(&ictx->ctx, 0);
|
||||||
log_debug("cursor off");
|
log_debug("cursor off");
|
||||||
@@ -1470,28 +1486,6 @@ input_handle_sequence_sgr(struct input_ctx *ictx)
|
|||||||
gc->flags &= ~GRID_FLAG_BG256;
|
gc->flags &= ~GRID_FLAG_BG256;
|
||||||
gc->bg = 8;
|
gc->bg = 8;
|
||||||
break;
|
break;
|
||||||
case 90:
|
|
||||||
case 91:
|
|
||||||
case 92:
|
|
||||||
case 93:
|
|
||||||
case 94:
|
|
||||||
case 95:
|
|
||||||
case 96:
|
|
||||||
case 97:
|
|
||||||
gc->flags |= GRID_FLAG_FG256;
|
|
||||||
gc->fg = m - 82;
|
|
||||||
break;
|
|
||||||
case 100:
|
|
||||||
case 101:
|
|
||||||
case 102:
|
|
||||||
case 103:
|
|
||||||
case 104:
|
|
||||||
case 105:
|
|
||||||
case 106:
|
|
||||||
case 107:
|
|
||||||
gc->flags |= GRID_FLAG_BG256;
|
|
||||||
gc->bg = m - 92;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
196
job.c
196
job.c
@@ -1,196 +0,0 @@
|
|||||||
/* $Id: job.c,v 1.9 2009-11-02 21:38:26 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 <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Job scheduling. Run queued commands in the background and record their
|
|
||||||
* output.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* All jobs list. */
|
|
||||||
struct joblist all_jobs = SLIST_HEAD_INITIALIZER(&all_jobs);
|
|
||||||
|
|
||||||
RB_GENERATE(jobs, job, entry, job_cmp);
|
|
||||||
|
|
||||||
int
|
|
||||||
job_cmp(struct job *job1, struct job *job2)
|
|
||||||
{
|
|
||||||
return (strcmp(job1->cmd, job2->cmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialise job tree. */
|
|
||||||
void
|
|
||||||
job_tree_init(struct jobs *jobs)
|
|
||||||
{
|
|
||||||
RB_INIT(jobs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy a job tree. */
|
|
||||||
void
|
|
||||||
job_tree_free(struct jobs *jobs)
|
|
||||||
{
|
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
while (!RB_EMPTY(jobs)) {
|
|
||||||
job = RB_ROOT(jobs);
|
|
||||||
RB_REMOVE(jobs, jobs, job);
|
|
||||||
job_free(job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find a job and return it. */
|
|
||||||
struct job *
|
|
||||||
job_get(struct jobs *jobs, const char *cmd)
|
|
||||||
{
|
|
||||||
struct job job;
|
|
||||||
|
|
||||||
job.cmd = (char *) cmd;
|
|
||||||
return (RB_FIND(jobs, jobs, &job));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a job. */
|
|
||||||
struct job *
|
|
||||||
job_add(struct jobs *jobs, int flags, struct client *c, const char *cmd,
|
|
||||||
void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
|
|
||||||
{
|
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
job = xmalloc(sizeof *job);
|
|
||||||
job->cmd = xstrdup(cmd);
|
|
||||||
job->pid = -1;
|
|
||||||
job->status = 0;
|
|
||||||
|
|
||||||
job->client = c;
|
|
||||||
|
|
||||||
job->fd = -1;
|
|
||||||
job->out = buffer_create(BUFSIZ);
|
|
||||||
|
|
||||||
job->callbackfn = callbackfn;
|
|
||||||
job->freefn = freefn;
|
|
||||||
job->data = data;
|
|
||||||
|
|
||||||
job->flags = flags|JOB_DONE;
|
|
||||||
|
|
||||||
if (jobs != NULL)
|
|
||||||
RB_INSERT(jobs, jobs, job);
|
|
||||||
SLIST_INSERT_HEAD(&all_jobs, job, lentry);
|
|
||||||
|
|
||||||
return (job);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove job from tree and free. */
|
|
||||||
void
|
|
||||||
job_remove(struct jobs *jobs, struct job *job)
|
|
||||||
{
|
|
||||||
if (jobs != NULL)
|
|
||||||
RB_REMOVE(jobs, jobs, job);
|
|
||||||
job_free(job);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Kill and free an individual job. */
|
|
||||||
void
|
|
||||||
job_free(struct job *job)
|
|
||||||
{
|
|
||||||
job_kill(job);
|
|
||||||
|
|
||||||
SLIST_REMOVE(&all_jobs, job, job, lentry);
|
|
||||||
xfree(job->cmd);
|
|
||||||
|
|
||||||
if (job->freefn != NULL && job->data != NULL)
|
|
||||||
job->freefn(job->data);
|
|
||||||
|
|
||||||
if (job->fd != -1)
|
|
||||||
close(job->fd);
|
|
||||||
if (job->out != NULL)
|
|
||||||
buffer_destroy(job->out);
|
|
||||||
|
|
||||||
xfree(job);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start a job running, if it isn't already. */
|
|
||||||
int
|
|
||||||
job_run(struct job *job)
|
|
||||||
{
|
|
||||||
int nullfd, out[2], mode;
|
|
||||||
|
|
||||||
if (!(job->flags & JOB_DONE))
|
|
||||||
return (0);
|
|
||||||
job->flags &= ~JOB_DONE;
|
|
||||||
|
|
||||||
if (pipe(out) != 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
switch (job->pid = fork()) {
|
|
||||||
case -1:
|
|
||||||
return (-1);
|
|
||||||
case 0: /* child */
|
|
||||||
sigreset();
|
|
||||||
/* XXX environ? */
|
|
||||||
|
|
||||||
if (dup2(out[1], STDOUT_FILENO) == -1)
|
|
||||||
fatal("dup2 failed");
|
|
||||||
if (out[1] != STDOUT_FILENO)
|
|
||||||
close(out[1]);
|
|
||||||
close(out[0]);
|
|
||||||
|
|
||||||
nullfd = open(_PATH_DEVNULL, O_RDWR, 0);
|
|
||||||
if (nullfd < 0)
|
|
||||||
fatal("open failed");
|
|
||||||
if (dup2(nullfd, STDIN_FILENO) == -1)
|
|
||||||
fatal("dup2 failed");
|
|
||||||
if (dup2(nullfd, STDERR_FILENO) == -1)
|
|
||||||
fatal("dup2 failed");
|
|
||||||
if (nullfd != STDIN_FILENO && nullfd != STDERR_FILENO)
|
|
||||||
close(nullfd);
|
|
||||||
|
|
||||||
execl(_PATH_BSHELL, "sh", "-c", job->cmd, (char *) NULL);
|
|
||||||
fatal("execl failed");
|
|
||||||
default: /* parent */
|
|
||||||
close(out[1]);
|
|
||||||
|
|
||||||
job->fd = out[0];
|
|
||||||
if ((mode = fcntl(job->fd, F_GETFL)) == -1)
|
|
||||||
fatal("fcntl failed");
|
|
||||||
if (fcntl(job->fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
|
||||||
fatal("fcntl failed");
|
|
||||||
if (fcntl(job->fd, F_SETFD, FD_CLOEXEC) == -1)
|
|
||||||
fatal("fcntl failed");
|
|
||||||
|
|
||||||
if (BUFFER_USED(job->out) != 0)
|
|
||||||
buffer_remove(job->out, BUFFER_USED(job->out));
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Kill a job. */
|
|
||||||
void
|
|
||||||
job_kill(struct job *job)
|
|
||||||
{
|
|
||||||
if (job->pid == -1)
|
|
||||||
return;
|
|
||||||
kill(job->pid, SIGTERM);
|
|
||||||
job->pid = -1;
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: key-bindings.c,v 1.83 2009-10-06 14:14:07 tcunha Exp $ */
|
/* $Id: key-bindings.c,v 1.82 2009-08-31 22:30:15 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -122,6 +122,7 @@ 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_scroll_mode_entry },
|
||||||
{ '?', 0, &cmd_list_keys_entry },
|
{ '?', 0, &cmd_list_keys_entry },
|
||||||
{ '[', 0, &cmd_copy_mode_entry },
|
{ '[', 0, &cmd_copy_mode_entry },
|
||||||
{ '\'', 0, &cmd_select_prompt_entry },
|
{ '\'', 0, &cmd_select_prompt_entry },
|
||||||
@@ -149,7 +150,7 @@ 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 },
|
||||||
{ KEYC_PPAGE, 0, &cmd_copy_mode_entry },
|
{ KEYC_PPAGE, 0, &cmd_scroll_mode_entry },
|
||||||
{ 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry },
|
{ 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry },
|
||||||
{ 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry },
|
{ 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry },
|
||||||
{ KEYC_UP, 0, &cmd_up_pane_entry },
|
{ KEYC_UP, 0, &cmd_up_pane_entry },
|
||||||
|
|||||||
37
key-string.c
37
key-string.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: key-string.c,v 1.25 2009-10-28 22:53:03 tcunha Exp $ */
|
/* $Id: key-string.c,v 1.22 2009-07-28 23:13:00 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -57,7 +57,6 @@ struct {
|
|||||||
{ "PPage", KEYC_PPAGE },
|
{ "PPage", KEYC_PPAGE },
|
||||||
{ "Tab", '\011' },
|
{ "Tab", '\011' },
|
||||||
{ "BTab", KEYC_BTAB },
|
{ "BTab", KEYC_BTAB },
|
||||||
{ "Space", ' ' },
|
|
||||||
{ "BSpace", KEYC_BSPACE },
|
{ "BSpace", KEYC_BSPACE },
|
||||||
{ "Enter", '\r' },
|
{ "Enter", '\r' },
|
||||||
{ "Escape", '\033' },
|
{ "Escape", '\033' },
|
||||||
@@ -69,22 +68,22 @@ struct {
|
|||||||
{ "Right", KEYC_RIGHT },
|
{ "Right", KEYC_RIGHT },
|
||||||
|
|
||||||
/* Numeric keypad. */
|
/* Numeric keypad. */
|
||||||
{ "KP/", KEYC_KP_SLASH },
|
{ "KP/", KEYC_KP0_1 },
|
||||||
{ "KP*", KEYC_KP_STAR },
|
{ "KP*", KEYC_KP0_2 },
|
||||||
{ "KP-", KEYC_KP_MINUS },
|
{ "KP-", KEYC_KP0_3 },
|
||||||
{ "KP7", KEYC_KP_SEVEN },
|
{ "KP7", KEYC_KP1_0 },
|
||||||
{ "KP8", KEYC_KP_EIGHT },
|
{ "KP8", KEYC_KP1_1 },
|
||||||
{ "KP9", KEYC_KP_NINE },
|
{ "KP9", KEYC_KP1_2 },
|
||||||
{ "KP+", KEYC_KP_PLUS },
|
{ "KP+", KEYC_KP1_3 },
|
||||||
{ "KP4", KEYC_KP_FOUR },
|
{ "KP4", KEYC_KP2_0 },
|
||||||
{ "KP5", KEYC_KP_FIVE },
|
{ "KP5", KEYC_KP2_1 },
|
||||||
{ "KP6", KEYC_KP_SIX },
|
{ "KP6", KEYC_KP2_2 },
|
||||||
{ "KP1", KEYC_KP_ONE },
|
{ "KP1", KEYC_KP3_0 },
|
||||||
{ "KP2", KEYC_KP_TWO },
|
{ "KP2", KEYC_KP3_1 },
|
||||||
{ "KP3", KEYC_KP_THREE },
|
{ "KP3", KEYC_KP3_2 },
|
||||||
{ "KPEnter", KEYC_KP_ENTER },
|
{ "KPEnter", KEYC_KP3_3 },
|
||||||
{ "KP0", KEYC_KP_ZERO },
|
{ "KP0", KEYC_KP4_0 },
|
||||||
{ "KP.", KEYC_KP_PERIOD },
|
{ "KP.", KEYC_KP4_2 },
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -121,8 +120,6 @@ key_string_lookup_string(const char *string)
|
|||||||
if (ptr[1] == '\0') {
|
if (ptr[1] == '\0') {
|
||||||
if (ptr[0] == 32)
|
if (ptr[0] == 32)
|
||||||
return (0);
|
return (0);
|
||||||
if (ptr[0] == 63)
|
|
||||||
return (KEYC_BSPACE);
|
|
||||||
if (ptr[0] >= 64 && ptr[0] <= 95)
|
if (ptr[0] >= 64 && ptr[0] <= 95)
|
||||||
return (ptr[0] - 64);
|
return (ptr[0] - 64);
|
||||||
if (ptr[0] >= 97 && ptr[0] <= 122)
|
if (ptr[0] >= 97 && ptr[0] <= 122)
|
||||||
|
|||||||
30
mode-key.c
30
mode-key.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: mode-key.c,v 1.34 2009-10-15 01:52:47 tcunha Exp $ */
|
/* $Id: mode-key.c,v 1.28 2009-09-02 22:45:17 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -77,7 +77,6 @@ struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
|
|||||||
/* Copy keys command strings. */
|
/* Copy keys command strings. */
|
||||||
struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
|
struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
|
||||||
{ MODEKEYCOPY_BACKTOINDENTATION, "back-to-indentation" },
|
{ MODEKEYCOPY_BACKTOINDENTATION, "back-to-indentation" },
|
||||||
{ MODEKEYCOPY_BOTTOMLINE, "bottom-line" },
|
|
||||||
{ MODEKEYCOPY_CANCEL, "cancel" },
|
{ MODEKEYCOPY_CANCEL, "cancel" },
|
||||||
{ MODEKEYCOPY_CLEARSELECTION, "clear-selection" },
|
{ MODEKEYCOPY_CLEARSELECTION, "clear-selection" },
|
||||||
{ MODEKEYCOPY_COPYSELECTION, "copy-selection" },
|
{ MODEKEYCOPY_COPYSELECTION, "copy-selection" },
|
||||||
@@ -85,20 +84,16 @@ struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
|
|||||||
{ MODEKEYCOPY_ENDOFLINE, "end-of-line" },
|
{ MODEKEYCOPY_ENDOFLINE, "end-of-line" },
|
||||||
{ MODEKEYCOPY_GOTOLINE, "goto-line" },
|
{ MODEKEYCOPY_GOTOLINE, "goto-line" },
|
||||||
{ MODEKEYCOPY_LEFT, "cursor-left" },
|
{ MODEKEYCOPY_LEFT, "cursor-left" },
|
||||||
{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
|
|
||||||
{ MODEKEYCOPY_NEXTPAGE, "page-down" },
|
{ MODEKEYCOPY_NEXTPAGE, "page-down" },
|
||||||
{ MODEKEYCOPY_NEXTWORD, "next-word" },
|
{ MODEKEYCOPY_NEXTWORD, "next-word" },
|
||||||
{ MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
|
{ MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
|
||||||
{ MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
|
{ MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
|
||||||
{ MODEKEYCOPY_RIGHT, "cursor-right" },
|
{ MODEKEYCOPY_RIGHT, "cursor-right" },
|
||||||
{ MODEKEYCOPY_SCROLLDOWN, "scroll-down" },
|
|
||||||
{ MODEKEYCOPY_SCROLLUP, "scroll-up" },
|
|
||||||
{ MODEKEYCOPY_SEARCHAGAIN, "search-again" },
|
{ MODEKEYCOPY_SEARCHAGAIN, "search-again" },
|
||||||
{ MODEKEYCOPY_SEARCHDOWN, "search-forward" },
|
{ MODEKEYCOPY_SEARCHDOWN, "search-forward" },
|
||||||
{ MODEKEYCOPY_SEARCHUP, "search-backward" },
|
{ MODEKEYCOPY_SEARCHUP, "search-backward" },
|
||||||
{ MODEKEYCOPY_STARTOFLINE, "start-of-line" },
|
{ MODEKEYCOPY_STARTOFLINE, "start-of-line" },
|
||||||
{ MODEKEYCOPY_STARTSELECTION, "begin-selection" },
|
{ MODEKEYCOPY_STARTSELECTION, "begin-selection" },
|
||||||
{ MODEKEYCOPY_TOPLINE, "top-line" },
|
|
||||||
{ MODEKEYCOPY_UP, "cursor-up" },
|
{ MODEKEYCOPY_UP, "cursor-up" },
|
||||||
|
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
@@ -160,15 +155,9 @@ 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_SEARCHDOWN },
|
{ '/', 0, MODEKEYCOPY_SEARCHUP },
|
||||||
{ '0', 0, MODEKEYCOPY_STARTOFLINE },
|
{ '0', 0, MODEKEYCOPY_STARTOFLINE },
|
||||||
{ ':', 0, MODEKEYCOPY_GOTOLINE },
|
{ '?', 0, MODEKEYCOPY_SEARCHDOWN },
|
||||||
{ '?', 0, MODEKEYCOPY_SEARCHUP },
|
|
||||||
{ 'H', 0, MODEKEYCOPY_TOPLINE },
|
|
||||||
{ 'J', 0, MODEKEYCOPY_SCROLLDOWN },
|
|
||||||
{ 'K', 0, MODEKEYCOPY_SCROLLUP },
|
|
||||||
{ 'L', 0, MODEKEYCOPY_BOTTOMLINE },
|
|
||||||
{ 'M', 0, MODEKEYCOPY_MIDDLELINE },
|
|
||||||
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
||||||
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
|
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
|
||||||
{ '\004' /* C-d */, 0, MODEKEYCOPY_HALFPAGEDOWN },
|
{ '\004' /* C-d */, 0, MODEKEYCOPY_HALFPAGEDOWN },
|
||||||
@@ -179,6 +168,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
|
|||||||
{ '\r', 0, MODEKEYCOPY_COPYSELECTION },
|
{ '\r', 0, MODEKEYCOPY_COPYSELECTION },
|
||||||
{ '^', 0, MODEKEYCOPY_BACKTOINDENTATION },
|
{ '^', 0, MODEKEYCOPY_BACKTOINDENTATION },
|
||||||
{ 'b', 0, MODEKEYCOPY_PREVIOUSWORD },
|
{ 'b', 0, MODEKEYCOPY_PREVIOUSWORD },
|
||||||
|
{ 'g', 0, MODEKEYCOPY_GOTOLINE },
|
||||||
{ 'h', 0, MODEKEYCOPY_LEFT },
|
{ 'h', 0, MODEKEYCOPY_LEFT },
|
||||||
{ 'j', 0, MODEKEYCOPY_DOWN },
|
{ 'j', 0, MODEKEYCOPY_DOWN },
|
||||||
{ 'k', 0, MODEKEYCOPY_UP },
|
{ 'k', 0, MODEKEYCOPY_UP },
|
||||||
@@ -187,13 +177,11 @@ const struct mode_key_entry mode_key_vi_copy[] = {
|
|||||||
{ 'q', 0, MODEKEYCOPY_CANCEL },
|
{ 'q', 0, MODEKEYCOPY_CANCEL },
|
||||||
{ 'w', 0, MODEKEYCOPY_NEXTWORD },
|
{ 'w', 0, MODEKEYCOPY_NEXTWORD },
|
||||||
{ KEYC_BSPACE, 0, MODEKEYCOPY_LEFT },
|
{ KEYC_BSPACE, 0, MODEKEYCOPY_LEFT },
|
||||||
{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
|
|
||||||
{ KEYC_DOWN, 0, MODEKEYCOPY_DOWN },
|
{ KEYC_DOWN, 0, MODEKEYCOPY_DOWN },
|
||||||
{ KEYC_LEFT, 0, MODEKEYCOPY_LEFT },
|
{ KEYC_LEFT, 0, MODEKEYCOPY_LEFT },
|
||||||
{ KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE },
|
{ KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE },
|
||||||
{ KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
{ KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
||||||
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT },
|
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT },
|
||||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLUP },
|
|
||||||
{ KEYC_UP, 0, MODEKEYCOPY_UP },
|
{ KEYC_UP, 0, MODEKEYCOPY_UP },
|
||||||
|
|
||||||
{ 0, -1, 0 }
|
{ 0, -1, 0 }
|
||||||
@@ -203,7 +191,7 @@ struct mode_key_tree mode_key_tree_vi_copy;
|
|||||||
/* emacs editing keys. */
|
/* emacs editing keys. */
|
||||||
const struct mode_key_entry mode_key_emacs_edit[] = {
|
const struct mode_key_entry mode_key_emacs_edit[] = {
|
||||||
{ '\001' /* C-a */, 0, MODEKEYEDIT_STARTOFLINE },
|
{ '\001' /* C-a */, 0, MODEKEYEDIT_STARTOFLINE },
|
||||||
{ '\002' /* C-b */, 0, MODEKEYEDIT_CURSORLEFT },
|
{ '\002' /* C-p */, 0, MODEKEYEDIT_CURSORLEFT },
|
||||||
{ '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL },
|
{ '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL },
|
||||||
{ '\004' /* C-d */, 0, MODEKEYEDIT_DELETE },
|
{ '\004' /* C-d */, 0, MODEKEYEDIT_DELETE },
|
||||||
{ '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE },
|
{ '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE },
|
||||||
@@ -233,13 +221,9 @@ struct mode_key_tree mode_key_tree_emacs_edit;
|
|||||||
/* emacs choice selection keys. */
|
/* emacs choice selection keys. */
|
||||||
const struct mode_key_entry mode_key_emacs_choice[] = {
|
const struct mode_key_entry mode_key_emacs_choice[] = {
|
||||||
{ '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL },
|
{ '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL },
|
||||||
{ '\016' /* C-n */, 0, MODEKEYCHOICE_DOWN },
|
|
||||||
{ '\020' /* C-p */, 0, MODEKEYCHOICE_UP },
|
|
||||||
{ '\026' /* C-v */, 0, MODEKEYCHOICE_PAGEDOWN },
|
|
||||||
{ '\033' /* Escape */, 0, MODEKEYCHOICE_CANCEL },
|
{ '\033' /* Escape */, 0, MODEKEYCHOICE_CANCEL },
|
||||||
{ '\r', 0, MODEKEYCHOICE_CHOOSE },
|
{ '\r', 0, MODEKEYCHOICE_CHOOSE },
|
||||||
{ 'q', 0, MODEKEYCHOICE_CANCEL },
|
{ 'q', 0, MODEKEYCHOICE_CANCEL },
|
||||||
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCHOICE_PAGEUP },
|
|
||||||
{ KEYC_DOWN, 0, MODEKEYCHOICE_DOWN },
|
{ KEYC_DOWN, 0, MODEKEYCHOICE_DOWN },
|
||||||
{ KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN },
|
{ KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN },
|
||||||
{ KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP },
|
{ KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP },
|
||||||
@@ -272,18 +256,14 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
|
|||||||
{ 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION },
|
{ 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION },
|
||||||
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
|
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
|
||||||
{ 'q', 0, MODEKEYCOPY_CANCEL },
|
{ 'q', 0, MODEKEYCOPY_CANCEL },
|
||||||
{ 'r' | KEYC_ESCAPE, 0, MODEKEYCOPY_MIDDLELINE },
|
|
||||||
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCOPY_TOPLINE },
|
|
||||||
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
||||||
{ 'w' | KEYC_ESCAPE, 0, MODEKEYCOPY_COPYSELECTION },
|
{ 'w' | KEYC_ESCAPE, 0, MODEKEYCOPY_COPYSELECTION },
|
||||||
{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
|
|
||||||
{ KEYC_DOWN | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEDOWN },
|
{ KEYC_DOWN | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEDOWN },
|
||||||
{ KEYC_DOWN, 0, MODEKEYCOPY_DOWN },
|
{ KEYC_DOWN, 0, MODEKEYCOPY_DOWN },
|
||||||
{ KEYC_LEFT, 0, MODEKEYCOPY_LEFT },
|
{ KEYC_LEFT, 0, MODEKEYCOPY_LEFT },
|
||||||
{ KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE },
|
{ KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE },
|
||||||
{ KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
{ KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
||||||
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT },
|
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT },
|
||||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLUP },
|
|
||||||
{ KEYC_UP | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEUP },
|
{ KEYC_UP | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEUP },
|
||||||
{ KEYC_UP, 0, MODEKEYCOPY_UP },
|
{ KEYC_UP, 0, MODEKEYCOPY_UP },
|
||||||
|
|
||||||
|
|||||||
10
names.c
10
names.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: names.c,v 1.17 2009-10-12 00:03:04 tcunha Exp $ */
|
/* $Id: names.c,v 1.15 2009-09-02 01:02:44 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -36,7 +36,7 @@ set_window_names(void)
|
|||||||
struct timeval tv, tv2;
|
struct timeval tv, tv2;
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL) != 0)
|
if (gettimeofday(&tv, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday");
|
||||||
|
|
||||||
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);
|
||||||
@@ -73,12 +73,6 @@ set_window_names(void)
|
|||||||
xfree(name);
|
xfree(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->active->fd == -1) {
|
|
||||||
xasprintf(&name, "%s[dead]", wname);
|
|
||||||
xfree(wname);
|
|
||||||
wname = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(wname, w->name) == 0)
|
if (strcmp(wname, w->name) == 0)
|
||||||
xfree(wname);
|
xfree(wname);
|
||||||
else {
|
else {
|
||||||
|
|||||||
136
options-cmd.c
136
options-cmd.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: options-cmd.c,v 1.8 2009-09-22 14:22:20 tcunha Exp $ */
|
/* $Id: options-cmd.c,v 1.5 2009-08-09 16:48:34 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -23,59 +23,11 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
const char *
|
|
||||||
set_option_print(const struct set_option_entry *entry, struct options_entry *o)
|
|
||||||
{
|
|
||||||
static char out[BUFSIZ];
|
|
||||||
const char *s;
|
|
||||||
struct keylist *keylist;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
*out = '\0';
|
|
||||||
switch (entry->type) {
|
|
||||||
case SET_OPTION_STRING:
|
|
||||||
xsnprintf(out, sizeof out, "\"%s\"", o->str);
|
|
||||||
break;
|
|
||||||
case SET_OPTION_NUMBER:
|
|
||||||
xsnprintf(out, sizeof out, "%lld", o->num);
|
|
||||||
break;
|
|
||||||
case SET_OPTION_KEYS:
|
|
||||||
keylist = o->data;
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(keylist); i++) {
|
|
||||||
strlcat(out, key_string_lookup_key(
|
|
||||||
ARRAY_ITEM(keylist, i)), sizeof out);
|
|
||||||
if (i != ARRAY_LENGTH(keylist) - 1)
|
|
||||||
strlcat(out, ",", sizeof out);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SET_OPTION_COLOUR:
|
|
||||||
s = colour_tostring(o->num);
|
|
||||||
xsnprintf(out, sizeof out, "%s", s);
|
|
||||||
break;
|
|
||||||
case SET_OPTION_ATTRIBUTES:
|
|
||||||
s = attributes_tostring(o->num);
|
|
||||||
xsnprintf(out, sizeof out, "%s", s);
|
|
||||||
break;
|
|
||||||
case SET_OPTION_FLAG:
|
|
||||||
if (o->num)
|
|
||||||
strlcpy(out, "on", sizeof out);
|
|
||||||
else
|
|
||||||
strlcpy(out, "off", sizeof out);
|
|
||||||
break;
|
|
||||||
case SET_OPTION_CHOICE:
|
|
||||||
s = entry->choices[o->num];
|
|
||||||
xsnprintf(out, sizeof out, "%s", s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
set_option_string(struct cmd_ctx *ctx, struct options *oo,
|
set_option_string(struct cmd_ctx *ctx, struct options *oo,
|
||||||
const struct set_option_entry *entry, char *value, int append)
|
const struct set_option_entry *entry, char *value, int append)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
char *oldvalue, *newvalue;
|
||||||
char *oldvalue, *newvalue;
|
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
ctx->error(ctx, "empty value");
|
ctx->error(ctx, "empty value");
|
||||||
@@ -88,9 +40,8 @@ set_option_string(struct cmd_ctx *ctx, struct options *oo,
|
|||||||
} else
|
} else
|
||||||
newvalue = value;
|
newvalue = value;
|
||||||
|
|
||||||
o = options_set_string(oo, entry->name, "%s", newvalue);
|
options_set_string(oo, entry->name, "%s", newvalue);
|
||||||
ctx->info(
|
ctx->info(ctx, "set option: %s -> %s", entry->name, newvalue);
|
||||||
ctx, "set option: %s -> %s", o->name, set_option_print(entry, o));
|
|
||||||
|
|
||||||
if (newvalue != value)
|
if (newvalue != value)
|
||||||
xfree(newvalue);
|
xfree(newvalue);
|
||||||
@@ -100,9 +51,8 @@ void
|
|||||||
set_option_number(struct cmd_ctx *ctx, struct options *oo,
|
set_option_number(struct cmd_ctx *ctx, struct options *oo,
|
||||||
const struct set_option_entry *entry, char *value)
|
const struct set_option_entry *entry, char *value)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
long long number;
|
||||||
long long number;
|
const char *errstr;
|
||||||
const char *errstr;
|
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
ctx->error(ctx, "empty value");
|
ctx->error(ctx, "empty value");
|
||||||
@@ -114,52 +64,35 @@ set_option_number(struct cmd_ctx *ctx, struct options *oo,
|
|||||||
ctx->error(ctx, "value is %s: %s", errstr, value);
|
ctx->error(ctx, "value is %s: %s", errstr, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
options_set_number(oo, entry->name, number);
|
||||||
o = options_set_number(oo, entry->name, number);
|
ctx->info(ctx, "set option: %s -> %lld", entry->name, number);
|
||||||
ctx->info(
|
|
||||||
ctx, "set option: %s -> %s", o->name, set_option_print(entry, o));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_option_keys(struct cmd_ctx *ctx, struct options *oo,
|
set_option_key(struct cmd_ctx *ctx, struct options *oo,
|
||||||
const struct set_option_entry *entry, char *value)
|
const struct set_option_entry *entry, char *value)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
int key;
|
||||||
struct keylist *keylist;
|
|
||||||
char *copyvalue, *ptr, *str;
|
|
||||||
int key;
|
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
ctx->error(ctx, "empty value");
|
ctx->error(ctx, "empty value");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
keylist = xmalloc(sizeof *keylist);
|
if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
|
||||||
ARRAY_INIT(keylist);
|
ctx->error(ctx, "unknown key: %s", value);
|
||||||
|
return;
|
||||||
ptr = copyvalue = xstrdup(value);
|
|
||||||
while ((str = strsep(&ptr, ",")) != NULL) {
|
|
||||||
if ((key = key_string_lookup_string(str)) == KEYC_NONE) {
|
|
||||||
xfree(keylist);
|
|
||||||
ctx->error(ctx, "unknown key: %s", str);
|
|
||||||
xfree(copyvalue);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ARRAY_ADD(keylist, key);
|
|
||||||
}
|
}
|
||||||
xfree(copyvalue);
|
options_set_number(oo, entry->name, key);
|
||||||
|
ctx->info(ctx,
|
||||||
o = options_set_data(oo, entry->name, keylist, xfree);
|
"set option: %s -> %s", entry->name, key_string_lookup_key(key));
|
||||||
ctx->info(
|
|
||||||
ctx, "set option: %s -> %s", o->name, set_option_print(entry, o));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_option_colour(struct cmd_ctx *ctx, struct options *oo,
|
set_option_colour(struct cmd_ctx *ctx, struct options *oo,
|
||||||
const struct set_option_entry *entry, char *value)
|
const struct set_option_entry *entry, char *value)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
int colour;
|
||||||
int colour;
|
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
ctx->error(ctx, "empty value");
|
ctx->error(ctx, "empty value");
|
||||||
@@ -171,17 +104,16 @@ set_option_colour(struct cmd_ctx *ctx, struct options *oo,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
o = options_set_number(oo, entry->name, colour);
|
options_set_number(oo, entry->name, colour);
|
||||||
ctx->info(
|
ctx->info(ctx,
|
||||||
ctx, "set option: %s -> %s", o->name, set_option_print(entry, o));
|
"set option: %s -> %s", entry->name, colour_tostring(colour));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_option_attributes(struct cmd_ctx *ctx, struct options *oo,
|
set_option_attributes(struct cmd_ctx *ctx, struct options *oo,
|
||||||
const struct set_option_entry *entry, char *value)
|
const struct set_option_entry *entry, char *value)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
int attr;
|
||||||
int attr;
|
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
ctx->error(ctx, "empty value");
|
ctx->error(ctx, "empty value");
|
||||||
@@ -193,17 +125,16 @@ set_option_attributes(struct cmd_ctx *ctx, struct options *oo,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
o = options_set_number(oo, entry->name, attr);
|
options_set_number(oo, entry->name, attr);
|
||||||
ctx->info(
|
ctx->info(ctx,
|
||||||
ctx, "set option: %s -> %s", o->name, set_option_print(entry, o));
|
"set option: %s -> %s", entry->name, attributes_tostring(attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_option_flag(struct cmd_ctx *ctx, struct options *oo,
|
set_option_flag(struct cmd_ctx *ctx, struct options *oo,
|
||||||
const struct set_option_entry *entry, char *value)
|
const struct set_option_entry *entry, char *value)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
int flag;
|
||||||
int flag;
|
|
||||||
|
|
||||||
if (value == NULL || *value == '\0')
|
if (value == NULL || *value == '\0')
|
||||||
flag = !options_get_number(oo, entry->name);
|
flag = !options_get_number(oo, entry->name);
|
||||||
@@ -222,18 +153,17 @@ set_option_flag(struct cmd_ctx *ctx, struct options *oo,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
o = options_set_number(oo, entry->name, flag);
|
options_set_number(oo, entry->name, flag);
|
||||||
ctx->info(
|
ctx->info(ctx,
|
||||||
ctx, "set option: %s -> %s", o->name, set_option_print(entry, o));
|
"set option: %s -> %s", entry->name, flag ? "on" : "off");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
set_option_choice(struct cmd_ctx *ctx, struct options *oo,
|
set_option_choice(struct cmd_ctx *ctx, struct options *oo,
|
||||||
const struct set_option_entry *entry, char *value)
|
const struct set_option_entry *entry, char *value)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
const char **choicep;
|
||||||
const char **choicep;
|
int n, choice = -1;
|
||||||
int n, choice = -1;
|
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
ctx->error(ctx, "empty value");
|
ctx->error(ctx, "empty value");
|
||||||
@@ -257,7 +187,7 @@ set_option_choice(struct cmd_ctx *ctx, struct options *oo,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
o = options_set_number(oo, entry->name, choice);
|
options_set_number(oo, entry->name, choice);
|
||||||
ctx->info(
|
ctx->info(ctx,
|
||||||
ctx, "set option: %s -> %s", o->name, set_option_print(entry, o));
|
"set option: %s -> %s", entry->name, entry->choices[choice]);
|
||||||
}
|
}
|
||||||
|
|||||||
66
options.c
66
options.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: options.c,v 1.9 2009-09-22 14:22:20 tcunha Exp $ */
|
/* $Id: options.c,v 1.6 2009-07-22 17:46:53 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -53,9 +53,7 @@ options_free(struct options *oo)
|
|||||||
SPLAY_REMOVE(options_tree, &oo->tree, o);
|
SPLAY_REMOVE(options_tree, &oo->tree, o);
|
||||||
xfree(o->name);
|
xfree(o->name);
|
||||||
if (o->type == OPTIONS_STRING)
|
if (o->type == OPTIONS_STRING)
|
||||||
xfree(o->str);
|
xfree(o->value.string);
|
||||||
else if (o->type == OPTIONS_DATA)
|
|
||||||
o->freefn(o->data);
|
|
||||||
xfree(o);
|
xfree(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,13 +94,11 @@ options_remove(struct options *oo, const char *name)
|
|||||||
SPLAY_REMOVE(options_tree, &oo->tree, o);
|
SPLAY_REMOVE(options_tree, &oo->tree, o);
|
||||||
xfree(o->name);
|
xfree(o->name);
|
||||||
if (o->type == OPTIONS_STRING)
|
if (o->type == OPTIONS_STRING)
|
||||||
xfree(o->str);
|
xfree(o->value.string);
|
||||||
else if (o->type == OPTIONS_DATA)
|
|
||||||
o->freefn(o->data);
|
|
||||||
xfree(o);
|
xfree(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct options_entry *printflike3
|
void printflike3
|
||||||
options_set_string(struct options *oo, const char *name, const char *fmt, ...)
|
options_set_string(struct options *oo, const char *name, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
@@ -113,15 +109,12 @@ options_set_string(struct options *oo, const char *name, const char *fmt, ...)
|
|||||||
o->name = xstrdup(name);
|
o->name = xstrdup(name);
|
||||||
SPLAY_INSERT(options_tree, &oo->tree, o);
|
SPLAY_INSERT(options_tree, &oo->tree, o);
|
||||||
} else if (o->type == OPTIONS_STRING)
|
} else if (o->type == OPTIONS_STRING)
|
||||||
xfree(o->str);
|
xfree(o->value.string);
|
||||||
else if (o->type == OPTIONS_DATA)
|
|
||||||
o->freefn(o->data);
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
o->type = OPTIONS_STRING;
|
o->type = OPTIONS_STRING;
|
||||||
xvasprintf(&o->str, fmt, ap);
|
xvasprintf(&o->value.string, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return (o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
@@ -133,10 +126,10 @@ options_get_string(struct options *oo, const char *name)
|
|||||||
fatalx("missing option");
|
fatalx("missing option");
|
||||||
if (o->type != OPTIONS_STRING)
|
if (o->type != OPTIONS_STRING)
|
||||||
fatalx("option not a string");
|
fatalx("option not a string");
|
||||||
return (o->str);
|
return (o->value.string);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct options_entry *
|
void
|
||||||
options_set_number(struct options *oo, const char *name, long long value)
|
options_set_number(struct options *oo, const char *name, long long value)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
@@ -146,13 +139,11 @@ options_set_number(struct options *oo, const char *name, long long value)
|
|||||||
o->name = xstrdup(name);
|
o->name = xstrdup(name);
|
||||||
SPLAY_INSERT(options_tree, &oo->tree, o);
|
SPLAY_INSERT(options_tree, &oo->tree, o);
|
||||||
} else if (o->type == OPTIONS_STRING)
|
} else if (o->type == OPTIONS_STRING)
|
||||||
xfree(o->str);
|
xfree(o->value.string);
|
||||||
else if (o->type == OPTIONS_DATA)
|
|
||||||
o->freefn(o->data);
|
|
||||||
|
|
||||||
o->type = OPTIONS_NUMBER;
|
o->type = OPTIONS_NUMBER;
|
||||||
o->num = value;
|
o->value.number = value;
|
||||||
return (o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long long
|
long long
|
||||||
@@ -164,38 +155,5 @@ options_get_number(struct options *oo, const char *name)
|
|||||||
fatalx("missing option");
|
fatalx("missing option");
|
||||||
if (o->type != OPTIONS_NUMBER)
|
if (o->type != OPTIONS_NUMBER)
|
||||||
fatalx("option not a number");
|
fatalx("option not a number");
|
||||||
return (o->num);
|
return (o->value.number);
|
||||||
}
|
|
||||||
|
|
||||||
struct options_entry *
|
|
||||||
options_set_data(
|
|
||||||
struct options *oo, const char *name, void *value, void (*freefn)(void *))
|
|
||||||
{
|
|
||||||
struct options_entry *o;
|
|
||||||
|
|
||||||
if ((o = options_find1(oo, name)) == NULL) {
|
|
||||||
o = xmalloc(sizeof *o);
|
|
||||||
o->name = xstrdup(name);
|
|
||||||
SPLAY_INSERT(options_tree, &oo->tree, o);
|
|
||||||
} else if (o->type == OPTIONS_STRING)
|
|
||||||
xfree(o->str);
|
|
||||||
else if (o->type == OPTIONS_DATA)
|
|
||||||
o->freefn(o->data);
|
|
||||||
|
|
||||||
o->type = OPTIONS_DATA;
|
|
||||||
o->data = value;
|
|
||||||
o->freefn = freefn;
|
|
||||||
return (o);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
options_get_data(struct options *oo, const char *name)
|
|
||||||
{
|
|
||||||
struct options_entry *o;
|
|
||||||
|
|
||||||
if ((o = options_find(oo, name)) == NULL)
|
|
||||||
fatalx("missing option");
|
|
||||||
if (o->type != OPTIONS_DATA)
|
|
||||||
fatalx("option not data");
|
|
||||||
return (o->data);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: osdep-netbsd.c,v 1.9 2009-09-24 12:30:22 nicm Exp $ */
|
/* $Id: osdep-netbsd.c,v 1.8 2009-08-09 18:00:45 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -77,7 +77,7 @@ osdep_get_name(int fd, __unused char *tty)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
len = sizeof(bestp);
|
len = sizeof(p);
|
||||||
mib[0] = CTL_KERN;
|
mib[0] = CTL_KERN;
|
||||||
mib[1] = KERN_PROC2;
|
mib[1] = KERN_PROC2;
|
||||||
mib[2] = KERN_PROC_PGRP;
|
mib[2] = KERN_PROC_PGRP;
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
/* $Id: osdep-sunos.c,v 1.2 2009-10-15 07:11:25 nicm Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2009 Todd Carson <toc@daybefore.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 <sys/stat.h>
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <procfs.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
char *
|
|
||||||
osdep_get_name(int fd, char *tty)
|
|
||||||
{
|
|
||||||
struct psinfo p;
|
|
||||||
struct stat st;
|
|
||||||
char *path;
|
|
||||||
ssize_t bytes;
|
|
||||||
int f;
|
|
||||||
pid_t pgrp;
|
|
||||||
|
|
||||||
if ((f = open(tty, O_RDONLY)) < 0)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if ((fstat(f, &st) != 0) ||
|
|
||||||
(ioctl(f, TIOCGPGRP, &pgrp) != 0)) {
|
|
||||||
close(f);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
close(f);
|
|
||||||
|
|
||||||
xasprintf(&path, "/proc/%hu/psinfo", pgrp);
|
|
||||||
f = open(path, O_RDONLY);
|
|
||||||
xfree(path);
|
|
||||||
if (f < 0)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
bytes = read(f, &p, sizeof(p));
|
|
||||||
close(f);
|
|
||||||
if (bytes != sizeof(p))
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if (p.pr_ttydev != st.st_rdev)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
return (xstrdup(p.pr_fname));
|
|
||||||
}
|
|
||||||
6
paste.c
6
paste.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: paste.c,v 1.11 2009-11-04 22:39:20 tcunha Exp $ */
|
/* $Id: paste.c,v 1.9 2009-09-07 23:48:54 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -116,6 +116,8 @@ paste_add(struct paste_stack *ps, u_char *data, size_t size, u_int limit)
|
|||||||
|
|
||||||
pb->data = data;
|
pb->data = data;
|
||||||
pb->size = size;
|
pb->size = size;
|
||||||
|
if (gettimeofday(&pb->tv, NULL) != 0)
|
||||||
|
fatal("gettimeofday");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -131,6 +133,8 @@ paste_replace(struct paste_stack *ps, u_int idx, u_char *data, size_t size)
|
|||||||
|
|
||||||
pb->data = data;
|
pb->data = data;
|
||||||
pb->size = size;
|
pb->size = size;
|
||||||
|
if (gettimeofday(&pb->tv, NULL) != 0)
|
||||||
|
fatal("gettimeofday");
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
4
resize.c
4
resize.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: resize.c,v 1.24 2009-09-25 17:47:42 tcunha Exp $ */
|
/* $Id: resize.c,v 1.23 2009-07-20 15:42:05 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -60,7 +60,7 @@ recalculate_sizes(void)
|
|||||||
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);
|
||||||
if (c == NULL || c->flags & CLIENT_SUSPENDED)
|
if (c == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (c->session == s) {
|
if (c->session == s) {
|
||||||
if (c->tty.sx < ssx)
|
if (c->tty.sx < ssx)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: screen-redraw.c,v 1.49 2009-10-28 23:17:28 tcunha Exp $ */
|
/* $Id: screen-redraw.c,v 1.47 2009-09-11 14:13:52 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -195,7 +195,7 @@ screen_redraw_screen(struct client *c, int status_only)
|
|||||||
for (i = 0; i < tty->sx; i++) {
|
for (i = 0; i < tty->sx; i++) {
|
||||||
type = screen_redraw_check_cell(c, i, j);
|
type = screen_redraw_check_cell(c, i, j);
|
||||||
if (type != CELL_INSIDE) {
|
if (type != CELL_INSIDE) {
|
||||||
tty_cursor(tty, i, j);
|
tty_cursor(tty, i, j, 0, 0);
|
||||||
tty_putc(tty, border[type]);
|
tty_putc(tty, border[type]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
|
|||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
struct session *s = c->session;
|
struct session *s = c->session;
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
u_int idx, px, py, i, j, xoff, yoff;
|
u_int idx, px, py, i, j;
|
||||||
int colour;
|
int colour;
|
||||||
char buf[16], *ptr;
|
char buf[16], *ptr;
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -251,13 +251,11 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
|
|||||||
return;
|
return;
|
||||||
colour = options_get_number(&s->options, "display-panes-colour");
|
colour = options_get_number(&s->options, "display-panes-colour");
|
||||||
|
|
||||||
px = wp->sx / 2; py = wp->sy / 2;
|
px = wp->sx / 2;
|
||||||
xoff = wp->xoff; yoff = wp->yoff;
|
py = wp->sy / 2;
|
||||||
|
|
||||||
if (wp->sx < len * 6 || wp->sy < 5) {
|
if (wp->sx < len * 6 || wp->sy < 5) {
|
||||||
tty_cursor(tty, xoff + px - len / 2, yoff + py);
|
tty_cursor(tty, px - len / 2, py, wp->xoff, wp->yoff);
|
||||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
gc.data = '_'; /* not space */
|
|
||||||
colour_set_fg(&gc, colour);
|
colour_set_fg(&gc, colour);
|
||||||
tty_attributes(tty, &gc);
|
tty_attributes(tty, &gc);
|
||||||
tty_puts(tty, buf);
|
tty_puts(tty, buf);
|
||||||
@@ -268,7 +266,6 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
|
|||||||
py -= 2;
|
py -= 2;
|
||||||
|
|
||||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
gc.data = '_'; /* not space */
|
|
||||||
colour_set_bg(&gc, colour);
|
colour_set_bg(&gc, colour);
|
||||||
tty_attributes(tty, &gc);
|
tty_attributes(tty, &gc);
|
||||||
for (ptr = buf; *ptr != '\0'; ptr++) {
|
for (ptr = buf; *ptr != '\0'; ptr++) {
|
||||||
@@ -278,7 +275,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
|
|||||||
|
|
||||||
for (j = 0; j < 5; j++) {
|
for (j = 0; j < 5; j++) {
|
||||||
for (i = px; i < px + 5; i++) {
|
for (i = px; i < px + 5; i++) {
|
||||||
tty_cursor(tty, xoff + i, yoff + py + j);
|
tty_cursor(tty, i, py + j, wp->xoff, wp->yoff);
|
||||||
if (clock_table[idx][j][i - px])
|
if (clock_table[idx][j][i - px])
|
||||||
tty_putc(tty, ' ');
|
tty_putc(tty, ' ');
|
||||||
}
|
}
|
||||||
|
|||||||
357
screen-write.c
357
screen-write.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: screen-write.c,v 1.83 2009-10-23 17:16:24 tcunha Exp $ */
|
/* $Id: screen-write.c,v 1.73 2009-09-15 23:54:57 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -22,10 +22,8 @@
|
|||||||
|
|
||||||
#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 *);
|
||||||
void screen_write_overwrite(struct screen_write_ctx *);
|
void screen_write_overwrite(struct screen_write_ctx *);
|
||||||
int screen_write_combine(
|
|
||||||
struct screen_write_ctx *, const struct utf8_data *);
|
|
||||||
|
|
||||||
/* Initialise writing with a window. */
|
/* Initialise writing with a window. */
|
||||||
void
|
void
|
||||||
@@ -93,11 +91,10 @@ screen_write_cstrlen(int utf8flag, const char *fmt, ...)
|
|||||||
size_t printflike2
|
size_t printflike2
|
||||||
screen_write_strlen(int utf8flag, const char *fmt, ...)
|
screen_write_strlen(int utf8flag, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char *msg;
|
char *msg;
|
||||||
struct utf8_data utf8data;
|
u_char *ptr, utf8buf[4];
|
||||||
u_char *ptr;
|
size_t left, size = 0;
|
||||||
size_t left, size = 0;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
xvasprintf(&msg, fmt, ap);
|
xvasprintf(&msg, fmt, ap);
|
||||||
@@ -105,17 +102,24 @@ screen_write_strlen(int utf8flag, const char *fmt, ...)
|
|||||||
|
|
||||||
ptr = msg;
|
ptr = msg;
|
||||||
while (*ptr != '\0') {
|
while (*ptr != '\0') {
|
||||||
if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
|
if (utf8flag && *ptr > 0x7f) {
|
||||||
ptr++;
|
memset(utf8buf, 0xff, sizeof utf8buf);
|
||||||
|
|
||||||
left = strlen(ptr);
|
left = strlen(ptr);
|
||||||
if (left < utf8data.size - 1)
|
if (*ptr >= 0xc2 && *ptr <= 0xdf && left >= 2) {
|
||||||
break;
|
memcpy(utf8buf, ptr, 2);
|
||||||
while (utf8_append(&utf8data, *ptr))
|
ptr += 2;
|
||||||
|
} else if (*ptr >= 0xe0 && *ptr <= 0xef && left >= 3) {
|
||||||
|
memcpy(utf8buf, ptr, 3);
|
||||||
|
ptr += 3;
|
||||||
|
} else if (*ptr >= 0xf0 && *ptr <= 0xf4 && left >= 4) {
|
||||||
|
memcpy(utf8buf, ptr, 4);
|
||||||
|
ptr += 4;
|
||||||
|
} else {
|
||||||
|
*utf8buf = *ptr;
|
||||||
ptr++;
|
ptr++;
|
||||||
ptr++;
|
}
|
||||||
|
size += utf8_width(utf8buf);
|
||||||
size += utf8data.width;
|
|
||||||
} else {
|
} else {
|
||||||
size++;
|
size++;
|
||||||
ptr++;
|
ptr++;
|
||||||
@@ -154,38 +158,47 @@ void
|
|||||||
screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
|
screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
|
||||||
struct grid_cell *gc, int utf8flag, const char *fmt, va_list ap)
|
struct grid_cell *gc, int utf8flag, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
char *msg;
|
char *msg;
|
||||||
struct utf8_data utf8data;
|
u_char *ptr, utf8buf[4];
|
||||||
u_char *ptr;
|
size_t left, size = 0;
|
||||||
size_t left, size = 0;
|
int width;
|
||||||
|
|
||||||
xvasprintf(&msg, fmt, ap);
|
xvasprintf(&msg, fmt, ap);
|
||||||
|
|
||||||
ptr = msg;
|
ptr = msg;
|
||||||
while (*ptr != '\0') {
|
while (*ptr != '\0') {
|
||||||
if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
|
if (utf8flag && *ptr > 0x7f) {
|
||||||
ptr++;
|
memset(utf8buf, 0xff, sizeof utf8buf);
|
||||||
|
|
||||||
left = strlen(ptr);
|
left = strlen(ptr);
|
||||||
if (left < utf8data.size - 1)
|
if (*ptr >= 0xc2 && *ptr <= 0xdf && left >= 2) {
|
||||||
break;
|
memcpy(utf8buf, ptr, 2);
|
||||||
while (utf8_append(&utf8data, *ptr))
|
ptr += 2;
|
||||||
|
} else if (*ptr >= 0xe0 && *ptr <= 0xef && left >= 3) {
|
||||||
|
memcpy(utf8buf, ptr, 3);
|
||||||
|
ptr += 3;
|
||||||
|
} else if (*ptr >= 0xf0 && *ptr <= 0xf4 && left >= 4) {
|
||||||
|
memcpy(utf8buf, ptr, 4);
|
||||||
|
ptr += 4;
|
||||||
|
} else {
|
||||||
|
*utf8buf = *ptr;
|
||||||
ptr++;
|
ptr++;
|
||||||
ptr++;
|
}
|
||||||
|
|
||||||
if (maxlen > 0 &&
|
width = utf8_width(utf8buf);
|
||||||
size + utf8data.width > (size_t) maxlen) {
|
if (maxlen > 0 && size + width > (size_t) maxlen) {
|
||||||
while (size < (size_t) maxlen) {
|
while (size < (size_t) maxlen) {
|
||||||
screen_write_putc(ctx, gc, ' ');
|
screen_write_putc(ctx, gc, ' ');
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
size += utf8data.width;
|
size += width;
|
||||||
|
|
||||||
gc->flags |= GRID_FLAG_UTF8;
|
gc->flags |= GRID_FLAG_UTF8;
|
||||||
screen_write_cell(ctx, gc, &utf8data);
|
screen_write_cell(ctx, gc, utf8buf);
|
||||||
gc->flags &= ~GRID_FLAG_UTF8;
|
gc->flags &= ~GRID_FLAG_UTF8;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (maxlen > 0 && size + 1 > (size_t) maxlen)
|
if (maxlen > 0 && size + 1 > (size_t) maxlen)
|
||||||
break;
|
break;
|
||||||
@@ -205,11 +218,11 @@ screen_write_cnputs(struct screen_write_ctx *ctx,
|
|||||||
ssize_t maxlen, struct grid_cell *gc, int utf8flag, const char *fmt, ...)
|
ssize_t maxlen, struct grid_cell *gc, int utf8flag, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct grid_cell lgc;
|
struct grid_cell lgc;
|
||||||
struct utf8_data utf8data;
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char *msg;
|
char *msg;
|
||||||
u_char *ptr, *last;
|
u_char *ptr, *last, utf8buf[4];
|
||||||
size_t left, size = 0;
|
size_t left, size = 0;
|
||||||
|
int width;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
xvasprintf(&msg, fmt, ap);
|
xvasprintf(&msg, fmt, ap);
|
||||||
@@ -233,29 +246,38 @@ screen_write_cnputs(struct screen_write_ctx *ctx,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
|
if (utf8flag && *ptr > 0x7f) {
|
||||||
ptr++;
|
memset(utf8buf, 0xff, sizeof utf8buf);
|
||||||
|
|
||||||
left = strlen(ptr);
|
left = strlen(ptr);
|
||||||
if (left < utf8data.size - 1)
|
if (*ptr >= 0xc2 && *ptr <= 0xdf && left >= 2) {
|
||||||
break;
|
memcpy(utf8buf, ptr, 2);
|
||||||
while (utf8_append(&utf8data, *ptr))
|
ptr += 2;
|
||||||
|
} else if (*ptr >= 0xe0 && *ptr <= 0xef && left >= 3) {
|
||||||
|
memcpy(utf8buf, ptr, 3);
|
||||||
|
ptr += 3;
|
||||||
|
} else if (*ptr >= 0xf0 && *ptr <= 0xf4 && left >= 4) {
|
||||||
|
memcpy(utf8buf, ptr, 4);
|
||||||
|
ptr += 4;
|
||||||
|
} else {
|
||||||
|
*utf8buf = *ptr;
|
||||||
ptr++;
|
ptr++;
|
||||||
ptr++;
|
}
|
||||||
|
|
||||||
if (maxlen > 0 &&
|
width = utf8_width(utf8buf);
|
||||||
size + utf8data.width > (size_t) maxlen) {
|
if (maxlen > 0 && size + width > (size_t) maxlen) {
|
||||||
while (size < (size_t) maxlen) {
|
while (size < (size_t) maxlen) {
|
||||||
screen_write_putc(ctx, gc, ' ');
|
screen_write_putc(ctx, gc, ' ');
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
size += utf8data.width;
|
size += width;
|
||||||
|
|
||||||
lgc.flags |= GRID_FLAG_UTF8;
|
lgc.flags |= GRID_FLAG_UTF8;
|
||||||
screen_write_cell(ctx, &lgc, &utf8data);
|
screen_write_cell(ctx, &lgc, utf8buf);
|
||||||
lgc.flags &= ~GRID_FLAG_UTF8;
|
lgc.flags &= ~GRID_FLAG_UTF8;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (maxlen > 0 && size + 1 > (size_t) maxlen)
|
if (maxlen > 0 && size + 1 > (size_t) maxlen)
|
||||||
break;
|
break;
|
||||||
@@ -325,10 +347,6 @@ screen_write_parsestyle(
|
|||||||
bg = defgc->bg;
|
bg = defgc->bg;
|
||||||
} else
|
} else
|
||||||
return;
|
return;
|
||||||
} else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
|
|
||||||
if ((val = attributes_fromstring(tmp + 2)) == -1)
|
|
||||||
return;
|
|
||||||
attr &= ~val;
|
|
||||||
} else {
|
} else {
|
||||||
if ((val = attributes_fromstring(tmp)) == -1)
|
if ((val = attributes_fromstring(tmp)) == -1)
|
||||||
return;
|
return;
|
||||||
@@ -352,9 +370,8 @@ screen_write_copy(struct screen_write_ctx *ctx,
|
|||||||
struct grid *gd = src->grid;
|
struct grid *gd = src->grid;
|
||||||
struct grid_line *gl;
|
struct grid_line *gl;
|
||||||
const struct grid_cell *gc;
|
const struct grid_cell *gc;
|
||||||
const struct grid_utf8 *gu;
|
u_char *udata;
|
||||||
struct utf8_data utf8data;
|
u_int xx, yy, cx, cy, ax, bx;
|
||||||
u_int xx, yy, cx, cy, ax, bx, i;
|
|
||||||
|
|
||||||
cx = s->cx;
|
cx = s->cx;
|
||||||
cy = s->cy;
|
cy = s->cy;
|
||||||
@@ -375,30 +392,21 @@ screen_write_copy(struct screen_write_ctx *ctx,
|
|||||||
bx = gl->cellsize;
|
bx = gl->cellsize;
|
||||||
else
|
else
|
||||||
bx = px + nx;
|
bx = px + nx;
|
||||||
|
|
||||||
for (xx = ax; xx < bx; xx++) {
|
for (xx = ax; xx < bx; xx++) {
|
||||||
|
udata = NULL;
|
||||||
if (xx >= gl->cellsize)
|
if (xx >= gl->cellsize)
|
||||||
gc = &grid_default_cell;
|
gc = &grid_default_cell;
|
||||||
else
|
else {
|
||||||
gc = &gl->celldata[xx];
|
gc = &gl->celldata[xx];
|
||||||
if (gc->flags & GRID_FLAG_UTF8) {
|
if (gc->flags & GRID_FLAG_UTF8)
|
||||||
gu = &gl->utf8data[xx];
|
udata = gl->utf8data[xx].data;
|
||||||
memcpy(utf8data.data,
|
|
||||||
gu->data, sizeof utf8data.data);
|
|
||||||
utf8data.width = gu->width;
|
|
||||||
utf8data.size = 0;
|
|
||||||
for (i = 0; i < UTF8_SIZE; i++) {
|
|
||||||
if (gu->data[i] == 0xff)
|
|
||||||
break;
|
|
||||||
utf8data.size++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
screen_write_cell(ctx, gc, &utf8data);
|
screen_write_cell(ctx, gc, udata);
|
||||||
}
|
}
|
||||||
if (px + nx == gd->sx && px + nx > gl->cellsize)
|
if (px + nx == gd->sx && px + nx > gl->cellsize)
|
||||||
screen_write_clearendofline(ctx);
|
screen_write_clearendofline(ctx);
|
||||||
} else
|
} else
|
||||||
screen_write_clearline(ctx);
|
screen_write_clearline(ctx);
|
||||||
cy++;
|
cy++;
|
||||||
screen_write_cursormove(ctx, cx, cy);
|
screen_write_cursormove(ctx, cx, cy);
|
||||||
}
|
}
|
||||||
@@ -406,14 +414,9 @@ screen_write_copy(struct screen_write_ctx *ctx,
|
|||||||
|
|
||||||
/* Set up context for TTY command. */
|
/* Set up context for TTY command. */
|
||||||
void
|
void
|
||||||
screen_write_initctx(
|
screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
|
||||||
struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, int save_last)
|
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct grid *gd = s->grid;
|
|
||||||
const struct grid_cell *gc;
|
|
||||||
const struct grid_utf8 *gu;
|
|
||||||
u_int xx;
|
|
||||||
|
|
||||||
ttyctx->wp = ctx->wp;
|
ttyctx->wp = ctx->wp;
|
||||||
|
|
||||||
@@ -422,23 +425,6 @@ screen_write_initctx(
|
|||||||
|
|
||||||
ttyctx->orlower = s->rlower;
|
ttyctx->orlower = s->rlower;
|
||||||
ttyctx->orupper = s->rupper;
|
ttyctx->orupper = s->rupper;
|
||||||
|
|
||||||
if (!save_last)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Save the last cell on the screen. */
|
|
||||||
gc = NULL;
|
|
||||||
for (xx = 1; xx < screen_size_x(s); xx++) {
|
|
||||||
gc = grid_view_peek_cell(gd, screen_size_x(s) - xx, s->cy);
|
|
||||||
if (!(gc->flags & GRID_FLAG_PADDING))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ttyctx->last_width = xx;
|
|
||||||
memcpy(&ttyctx->last_cell, gc, sizeof ttyctx->last_cell);
|
|
||||||
if (gc->flags & GRID_FLAG_UTF8) {
|
|
||||||
gu = grid_view_peek_utf8(gd, screen_size_x(s) - xx, s->cy);
|
|
||||||
memcpy(&ttyctx->last_utf8, gu, sizeof ttyctx->last_utf8);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cursor up by ny. */
|
/* Cursor up by ny. */
|
||||||
@@ -523,25 +509,6 @@ screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx)
|
|||||||
s->cx -= nx;
|
s->cx -= nx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Backspace; cursor left unless at start of wrapped line when can move up. */
|
|
||||||
void
|
|
||||||
screen_write_backspace(struct screen_write_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct screen *s = ctx->s;
|
|
||||||
struct grid_line *gl;
|
|
||||||
|
|
||||||
if (s->cx == 0) {
|
|
||||||
if (s->cy == 0)
|
|
||||||
return;
|
|
||||||
gl = &s->grid->linedata[s->grid->hsize + s->cy - 1];
|
|
||||||
if (gl->flags & GRID_LINE_WRAPPED) {
|
|
||||||
s->cy--;
|
|
||||||
s->cx = screen_size_x(s) - 1;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
s->cx--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* VT100 alignment test. */
|
/* VT100 alignment test. */
|
||||||
void
|
void
|
||||||
screen_write_alignmenttest(struct screen_write_ctx *ctx)
|
screen_write_alignmenttest(struct screen_write_ctx *ctx)
|
||||||
@@ -551,7 +518,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
|
|||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
u_int xx, yy;
|
u_int xx, yy;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
gc.data = 'E';
|
gc.data = 'E';
|
||||||
@@ -565,7 +532,6 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
|
|||||||
s->cy = 0;
|
s->cy = 0;
|
||||||
|
|
||||||
s->rupper = 0;
|
s->rupper = 0;
|
||||||
|
|
||||||
s->rlower = screen_size_y(s) - 1;
|
s->rlower = screen_size_y(s) - 1;
|
||||||
|
|
||||||
tty_write(tty_cmd_alignmenttest, &ttyctx);
|
tty_write(tty_cmd_alignmenttest, &ttyctx);
|
||||||
@@ -586,7 +552,7 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
|
|||||||
if (nx == 0)
|
if (nx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
if (s->cx <= screen_size_x(s) - 1)
|
if (s->cx <= screen_size_x(s) - 1)
|
||||||
grid_view_insert_cells(s->grid, s->cx, s->cy, nx);
|
grid_view_insert_cells(s->grid, s->cx, s->cy, nx);
|
||||||
@@ -610,7 +576,7 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
|
|||||||
if (nx == 0)
|
if (nx == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
if (s->cx <= screen_size_x(s) - 1)
|
if (s->cx <= screen_size_x(s) - 1)
|
||||||
grid_view_delete_cells(s->grid, s->cx, s->cy, nx);
|
grid_view_delete_cells(s->grid, s->cx, s->cy, nx);
|
||||||
@@ -635,7 +601,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
|
|||||||
if (ny == 0)
|
if (ny == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
grid_view_insert_lines(s->grid, s->cy, ny);
|
grid_view_insert_lines(s->grid, s->cy, ny);
|
||||||
|
|
||||||
@@ -649,7 +615,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
|
|||||||
if (ny == 0)
|
if (ny == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
if (s->cy < s->rupper || s->cy > s->rlower)
|
if (s->cy < s->rupper || s->cy > s->rlower)
|
||||||
grid_view_insert_lines(s->grid, s->cy, ny);
|
grid_view_insert_lines(s->grid, s->cy, ny);
|
||||||
@@ -676,7 +642,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
|
|||||||
if (ny == 0)
|
if (ny == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
grid_view_delete_lines(s->grid, s->cy, ny);
|
grid_view_delete_lines(s->grid, s->cy, ny);
|
||||||
|
|
||||||
@@ -690,7 +656,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
|
|||||||
if (ny == 0)
|
if (ny == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
if (s->cy < s->rupper || s->cy > s->rlower)
|
if (s->cy < s->rupper || s->cy > s->rlower)
|
||||||
grid_view_delete_lines(s->grid, s->cy, ny);
|
grid_view_delete_lines(s->grid, s->cy, ny);
|
||||||
@@ -708,7 +674,7 @@ screen_write_clearline(struct screen_write_ctx *ctx)
|
|||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
|
grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
|
||||||
|
|
||||||
@@ -723,7 +689,7 @@ screen_write_clearendofline(struct screen_write_ctx *ctx)
|
|||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx;
|
u_int sx;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
sx = screen_size_x(s);
|
sx = screen_size_x(s);
|
||||||
|
|
||||||
@@ -741,7 +707,7 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx)
|
|||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx;
|
u_int sx;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
sx = screen_size_x(s);
|
sx = screen_size_x(s);
|
||||||
|
|
||||||
@@ -787,7 +753,7 @@ screen_write_reverseindex(struct screen_write_ctx *ctx)
|
|||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
if (s->cy == s->rupper)
|
if (s->cy == s->rupper)
|
||||||
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
|
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
|
||||||
@@ -843,15 +809,15 @@ screen_write_mousemode(struct screen_write_ctx *ctx, int state)
|
|||||||
s->mode &= ~MODE_MOUSE;
|
s->mode &= ~MODE_MOUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Line feed. */
|
/* Line feed (down with scroll). */
|
||||||
void
|
void
|
||||||
screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
|
screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct grid_line *gl;
|
struct grid_line *gl;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
||||||
if (wrapped)
|
if (wrapped)
|
||||||
@@ -864,7 +830,6 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
|
|||||||
else if (s->cy < screen_size_y(s) - 1)
|
else if (s->cy < screen_size_y(s) - 1)
|
||||||
s->cy++;
|
s->cy++;
|
||||||
|
|
||||||
ttyctx.num = wrapped;
|
|
||||||
tty_write(tty_cmd_linefeed, &ttyctx);
|
tty_write(tty_cmd_linefeed, &ttyctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,7 +874,7 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx)
|
|||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx, sy;
|
u_int sx, sy;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
sx = screen_size_x(s);
|
sx = screen_size_x(s);
|
||||||
sy = screen_size_y(s);
|
sy = screen_size_y(s);
|
||||||
@@ -929,7 +894,7 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
|
|||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx;
|
u_int sx;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
sx = screen_size_x(s);
|
sx = screen_size_x(s);
|
||||||
|
|
||||||
@@ -950,7 +915,7 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
|
|||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
|
||||||
grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
|
grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
|
||||||
|
|
||||||
@@ -959,15 +924,15 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
|
|||||||
|
|
||||||
/* Write cell data. */
|
/* Write cell data. */
|
||||||
void
|
void
|
||||||
screen_write_cell(struct screen_write_ctx *ctx,
|
screen_write_cell(
|
||||||
const struct grid_cell *gc, const struct utf8_data *utf8data)
|
struct screen_write_ctx *ctx, const struct grid_cell *gc, u_char *udata)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
struct grid_utf8 gu;
|
struct grid_utf8 gu, *tmp_gu;
|
||||||
u_int width, xx;
|
u_int width, xx, i;
|
||||||
struct grid_cell tmp_gc, *tmp_gcp;
|
struct grid_cell tmp_gc, tmp_gc2, *tmp_gcp;
|
||||||
int insert = 0;
|
int insert = 0;
|
||||||
|
|
||||||
/* Ignore padding. */
|
/* Ignore padding. */
|
||||||
@@ -975,33 +940,48 @@ screen_write_cell(struct screen_write_ctx *ctx,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Find character width. */
|
/* Find character width. */
|
||||||
if (gc->flags & GRID_FLAG_UTF8)
|
if (gc->flags & GRID_FLAG_UTF8) {
|
||||||
width = utf8data->width;
|
width = utf8_width(udata);
|
||||||
else
|
|
||||||
|
gu.width = width;
|
||||||
|
memcpy(&gu.data, udata, sizeof gu.data);
|
||||||
|
} else
|
||||||
width = 1;
|
width = 1;
|
||||||
|
|
||||||
/*
|
/* If the width is zero, combine onto the previous character. */
|
||||||
* If this is a wide character and there is no room on the screen, for
|
|
||||||
* the entire character, don't print it.
|
|
||||||
*/
|
|
||||||
if (width > 1 && (width > screen_size_x(s) ||
|
|
||||||
(s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the width is zero, combine onto the previous character, if
|
|
||||||
* there is space.
|
|
||||||
*/
|
|
||||||
if (width == 0) {
|
if (width == 0) {
|
||||||
if (screen_write_combine(ctx, utf8data) == 0) {
|
if (s->cx == 0)
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
return;
|
||||||
tty_write(tty_cmd_utf8character, &ttyctx);
|
tmp_gcp = grid_view_get_cell(gd, s->cx - 1, s->cy);
|
||||||
|
if (!(tmp_gcp->flags & GRID_FLAG_UTF8)) {
|
||||||
|
tmp_gcp->flags |= GRID_FLAG_UTF8;
|
||||||
|
memset(&gu.data, 0xff, sizeof gu.data);
|
||||||
|
*gu.data = tmp_gcp->data;
|
||||||
|
gu.width = 1;
|
||||||
|
grid_view_set_utf8(gd, s->cx - 1, s->cy, &gu);
|
||||||
}
|
}
|
||||||
|
tmp_gu = grid_view_get_utf8(gd, s->cx - 1, s->cy);
|
||||||
|
|
||||||
|
for (i = 0; i < UTF8_SIZE; i++) {
|
||||||
|
if (tmp_gu->data[i] == 0xff)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(tmp_gu->data + i, udata, UTF8_SIZE - i);
|
||||||
|
|
||||||
|
/* Assume the previous character has just been input. */
|
||||||
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
ttyctx.ptr = udata;
|
||||||
|
tty_write(tty_cmd_utf8character, &ttyctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise the redraw context, saving the last cell. */
|
/* If the character is wider than the screen, don't print it. */
|
||||||
screen_write_initctx(ctx, &ttyctx, 1);
|
if (width > screen_size_x(s)) {
|
||||||
|
memcpy(&tmp_gc, gc, sizeof tmp_gc);
|
||||||
|
tmp_gc.data = '_';
|
||||||
|
width = 1;
|
||||||
|
gc = &tmp_gc;
|
||||||
|
}
|
||||||
|
|
||||||
/* If in insert mode, make space for the cells. */
|
/* If in insert mode, make space for the cells. */
|
||||||
if (s->mode & MODE_INSERT && s->cx <= screen_size_x(s) - width) {
|
if (s->mode & MODE_INSERT && s->cx <= screen_size_x(s) - width) {
|
||||||
@@ -1012,8 +992,8 @@ 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->cx > screen_size_x(s) - width) {
|
if (s->cx > screen_size_x(s) - width) {
|
||||||
|
screen_write_carriagereturn(ctx);
|
||||||
screen_write_linefeed(ctx, 1);
|
screen_write_linefeed(ctx, 1);
|
||||||
s->cx = 0; /* carriage return */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity checks. */
|
/* Sanity checks. */
|
||||||
@@ -1035,17 +1015,11 @@ screen_write_cell(struct screen_write_ctx *ctx,
|
|||||||
|
|
||||||
/* Set the cell. */
|
/* Set the cell. */
|
||||||
grid_view_set_cell(gd, s->cx, s->cy, gc);
|
grid_view_set_cell(gd, s->cx, s->cy, gc);
|
||||||
if (gc->flags & GRID_FLAG_UTF8) {
|
if (gc->flags & GRID_FLAG_UTF8)
|
||||||
/* Construct UTF-8 and write it. */
|
|
||||||
gu.width = utf8data->width;
|
|
||||||
memset(gu.data, 0xff, sizeof gu.data);
|
|
||||||
if (utf8data->size > sizeof gu.data)
|
|
||||||
fatalx("UTF-8 data overflow");
|
|
||||||
memcpy(gu.data, utf8data->data, utf8data->size);
|
|
||||||
grid_view_set_utf8(gd, s->cx, s->cy, &gu);
|
grid_view_set_utf8(gd, s->cx, s->cy, &gu);
|
||||||
}
|
|
||||||
|
|
||||||
/* Move the cursor. */
|
/* Move the cursor. */
|
||||||
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
s->cx += width;
|
s->cx += width;
|
||||||
|
|
||||||
/* Draw to the screen if necessary. */
|
/* Draw to the screen if necessary. */
|
||||||
@@ -1055,13 +1029,11 @@ screen_write_cell(struct screen_write_ctx *ctx,
|
|||||||
}
|
}
|
||||||
ttyctx.utf8 = &gu;
|
ttyctx.utf8 = &gu;
|
||||||
if (screen_check_selection(s, s->cx - width, s->cy)) {
|
if (screen_check_selection(s, s->cx - width, s->cy)) {
|
||||||
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
|
memcpy(&tmp_gc2, &s->sel.cell, sizeof tmp_gc2);
|
||||||
tmp_gc.data = gc->data;
|
tmp_gc2.data = gc->data;
|
||||||
tmp_gc.flags = gc->flags &
|
tmp_gc2.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||||
~(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
tmp_gc2.flags |= s->sel.cell.flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||||
tmp_gc.flags |= s->sel.cell.flags &
|
ttyctx.cell = &tmp_gc2;
|
||||||
(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
|
||||||
ttyctx.cell = &tmp_gc;
|
|
||||||
tty_write(tty_cmd_cell, &ttyctx);
|
tty_write(tty_cmd_cell, &ttyctx);
|
||||||
} else {
|
} else {
|
||||||
ttyctx.cell = gc;
|
ttyctx.cell = gc;
|
||||||
@@ -1069,55 +1041,6 @@ screen_write_cell(struct screen_write_ctx *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combine a UTF-8 zero-width character onto the previous. */
|
|
||||||
int
|
|
||||||
screen_write_combine(
|
|
||||||
struct screen_write_ctx *ctx, const struct utf8_data *utf8data)
|
|
||||||
{
|
|
||||||
struct screen *s = ctx->s;
|
|
||||||
struct grid *gd = s->grid;
|
|
||||||
struct grid_cell *gc;
|
|
||||||
struct grid_utf8 *gu, tmp_gu;
|
|
||||||
u_int i, old_size;
|
|
||||||
|
|
||||||
/* Can't combine if at 0. */
|
|
||||||
if (s->cx == 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
/* Retrieve the previous cell and convert to UTF-8 if not already. */
|
|
||||||
gc = grid_view_get_cell(gd, s->cx - 1, s->cy);
|
|
||||||
if (!(gc->flags & GRID_FLAG_UTF8)) {
|
|
||||||
memset(&tmp_gu.data, 0xff, sizeof tmp_gu.data);
|
|
||||||
*tmp_gu.data = gc->data;
|
|
||||||
tmp_gu.width = 1;
|
|
||||||
|
|
||||||
grid_view_set_utf8(gd, s->cx - 1, s->cy, &tmp_gu);
|
|
||||||
gc->flags |= GRID_FLAG_UTF8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the previous cell's UTF-8 data and its size. */
|
|
||||||
gu = grid_view_get_utf8(gd, s->cx - 1, s->cy);
|
|
||||||
for (old_size = 0; old_size < UTF8_SIZE; old_size++) {
|
|
||||||
if (gu->data[old_size] == 0xff)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there isn't space, scrap this character. */
|
|
||||||
if (old_size + utf8data->size > UTF8_SIZE) {
|
|
||||||
for (i = 0; i < gu->width && i != UTF8_SIZE; i++)
|
|
||||||
gu->data[i] = '_';
|
|
||||||
if (i != UTF8_SIZE)
|
|
||||||
gu->data[i] = 0xff;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise save the character. */
|
|
||||||
memcpy(gu->data + old_size, utf8data->data, utf8data->size);
|
|
||||||
if (old_size + utf8data->size != UTF8_SIZE)
|
|
||||||
gu->data[old_size + utf8data->size] = 0xff;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UTF-8 wide characters are a bit of an annoyance. They take up more than one
|
* UTF-8 wide characters are a bit of an annoyance. They take up more than one
|
||||||
* cell on the screen, so following cells must not be drawn by marking them as
|
* cell on the screen, so following cells must not be drawn by marking them as
|
||||||
|
|||||||
768
server-client.c
768
server-client.c
@@ -1,768 +0,0 @@
|
|||||||
/* $Id: server-client.c,v 1.12 2009-11-04 22:46:25 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 <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
void server_client_handle_data(struct client *);
|
|
||||||
void server_client_check_redraw(struct client *);
|
|
||||||
void server_client_set_title(struct client *);
|
|
||||||
void server_client_check_timers(struct client *);
|
|
||||||
|
|
||||||
int server_client_msg_dispatch(struct client *);
|
|
||||||
void server_client_msg_command(struct client *, struct msg_command_data *);
|
|
||||||
void server_client_msg_identify(
|
|
||||||
struct client *, struct msg_identify_data *, int);
|
|
||||||
void server_client_msg_shell(struct client *);
|
|
||||||
|
|
||||||
void printflike2 server_client_msg_error(struct cmd_ctx *, const char *, ...);
|
|
||||||
void printflike2 server_client_msg_print(struct cmd_ctx *, const char *, ...);
|
|
||||||
void printflike2 server_client_msg_info(struct cmd_ctx *, const char *, ...);
|
|
||||||
|
|
||||||
|
|
||||||
/* Create a new client. */
|
|
||||||
void
|
|
||||||
server_client_create(int fd)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
int mode;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
if ((mode = fcntl(fd, F_GETFL)) == -1)
|
|
||||||
fatal("fcntl failed");
|
|
||||||
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
|
|
||||||
fatal("fcntl failed");
|
|
||||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
|
||||||
fatal("fcntl failed");
|
|
||||||
|
|
||||||
c = xcalloc(1, sizeof *c);
|
|
||||||
c->references = 0;
|
|
||||||
imsg_init(&c->ibuf, fd);
|
|
||||||
|
|
||||||
if (gettimeofday(&c->creation_time, NULL) != 0)
|
|
||||||
fatal("gettimeofday failed");
|
|
||||||
memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
|
|
||||||
|
|
||||||
ARRAY_INIT(&c->prompt_hdata);
|
|
||||||
|
|
||||||
c->tty.fd = -1;
|
|
||||||
c->title = NULL;
|
|
||||||
|
|
||||||
c->session = NULL;
|
|
||||||
c->tty.sx = 80;
|
|
||||||
c->tty.sy = 24;
|
|
||||||
|
|
||||||
screen_init(&c->status, c->tty.sx, 1, 0);
|
|
||||||
job_tree_init(&c->status_jobs);
|
|
||||||
|
|
||||||
c->message_string = NULL;
|
|
||||||
|
|
||||||
c->prompt_string = NULL;
|
|
||||||
c->prompt_buffer = NULL;
|
|
||||||
c->prompt_index = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
if (ARRAY_ITEM(&clients, i) == NULL) {
|
|
||||||
ARRAY_SET(&clients, i, c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ARRAY_ADD(&clients, c);
|
|
||||||
log_debug("new client %d", fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lost a client. */
|
|
||||||
void
|
|
||||||
server_client_lost(struct client *c)
|
|
||||||
{
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
if (ARRAY_ITEM(&clients, i) == c)
|
|
||||||
ARRAY_SET(&clients, i, NULL);
|
|
||||||
}
|
|
||||||
log_debug("lost client %d", c->ibuf.fd);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called
|
|
||||||
* and tty_free might close an unrelated fd.
|
|
||||||
*/
|
|
||||||
if (c->flags & CLIENT_TERMINAL)
|
|
||||||
tty_free(&c->tty);
|
|
||||||
|
|
||||||
screen_free(&c->status);
|
|
||||||
job_tree_free(&c->status_jobs);
|
|
||||||
|
|
||||||
if (c->title != NULL)
|
|
||||||
xfree(c->title);
|
|
||||||
|
|
||||||
if (c->message_string != NULL)
|
|
||||||
xfree(c->message_string);
|
|
||||||
|
|
||||||
if (c->prompt_string != NULL)
|
|
||||||
xfree(c->prompt_string);
|
|
||||||
if (c->prompt_buffer != NULL)
|
|
||||||
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)
|
|
||||||
xfree(c->cwd);
|
|
||||||
|
|
||||||
close(c->ibuf.fd);
|
|
||||||
imsg_clear(&c->ibuf);
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
|
|
||||||
if (ARRAY_ITEM(&dead_clients, i) == NULL) {
|
|
||||||
ARRAY_SET(&dead_clients, i, c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == ARRAY_LENGTH(&dead_clients))
|
|
||||||
ARRAY_ADD(&dead_clients, c);
|
|
||||||
c->flags |= CLIENT_DEAD;
|
|
||||||
|
|
||||||
recalculate_sizes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register clients for poll. */
|
|
||||||
void
|
|
||||||
server_client_prepare(void)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
u_int i;
|
|
||||||
int events;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
if ((c = ARRAY_ITEM(&clients, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
events = 0;
|
|
||||||
if (!(c->flags & CLIENT_BAD))
|
|
||||||
events |= POLLIN;
|
|
||||||
if (c->ibuf.w.queued > 0)
|
|
||||||
events |= POLLOUT;
|
|
||||||
server_poll_add(c->ibuf.fd, events, server_client_callback, c);
|
|
||||||
|
|
||||||
if (c->tty.fd == -1)
|
|
||||||
continue;
|
|
||||||
if (c->flags & CLIENT_SUSPENDED || c->session == NULL)
|
|
||||||
continue;
|
|
||||||
events = POLLIN;
|
|
||||||
if (BUFFER_USED(c->tty.out) > 0)
|
|
||||||
events |= POLLOUT;
|
|
||||||
server_poll_add(c->tty.fd, events, server_client_callback, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process a single client event. */
|
|
||||||
void
|
|
||||||
server_client_callback(int fd, int events, void *data)
|
|
||||||
{
|
|
||||||
struct client *c = data;
|
|
||||||
|
|
||||||
if (c->flags & CLIENT_DEAD)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (fd == c->ibuf.fd) {
|
|
||||||
if (events & (POLLERR|POLLNVAL|POLLHUP))
|
|
||||||
goto client_lost;
|
|
||||||
|
|
||||||
if (events & POLLOUT && msgbuf_write(&c->ibuf.w) < 0)
|
|
||||||
goto client_lost;
|
|
||||||
|
|
||||||
if (c->flags & CLIENT_BAD) {
|
|
||||||
if (c->ibuf.w.queued == 0)
|
|
||||||
goto client_lost;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events & POLLIN && server_client_msg_dispatch(c) != 0)
|
|
||||||
goto client_lost;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->tty.fd != -1 && fd == c->tty.fd) {
|
|
||||||
if (c->flags & CLIENT_SUSPENDED || c->session == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (buffer_poll(fd, events, c->tty.in, c->tty.out) != 0)
|
|
||||||
goto client_lost;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
client_lost:
|
|
||||||
server_client_lost(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Client functions that need to happen every loop. */
|
|
||||||
void
|
|
||||||
server_client_loop(void)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
c = ARRAY_ITEM(&clients, i);
|
|
||||||
if (c == NULL || c->session == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
server_client_handle_data(c);
|
|
||||||
if (c->session != NULL) {
|
|
||||||
server_client_check_timers(c);
|
|
||||||
server_client_check_redraw(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Any windows will have been redrawn as part of clients, so clear
|
|
||||||
* their flags now.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
|
||||||
w = ARRAY_ITEM(&windows, i);
|
|
||||||
if (w == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
w->flags &= ~WINDOW_REDRAW;
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry)
|
|
||||||
wp->flags &= ~PANE_REDRAW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle data input or output from client. */
|
|
||||||
void
|
|
||||||
server_client_handle_data(struct client *c)
|
|
||||||
{
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
struct screen *s;
|
|
||||||
struct options *oo;
|
|
||||||
struct timeval tv_add, tv_now;
|
|
||||||
struct key_binding *bd;
|
|
||||||
struct keylist *keylist;
|
|
||||||
struct mouse_event mouse;
|
|
||||||
int key, status, xtimeout, mode, isprefix;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
/* Check and update repeat flag. */
|
|
||||||
if (gettimeofday(&tv_now, NULL) != 0)
|
|
||||||
fatal("gettimeofday failed");
|
|
||||||
xtimeout = options_get_number(&c->session->options, "repeat-time");
|
|
||||||
if (xtimeout != 0 && c->flags & CLIENT_REPEAT) {
|
|
||||||
if (timercmp(&tv_now, &c->repeat_timer, >))
|
|
||||||
c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process keys. */
|
|
||||||
keylist = options_get_data(&c->session->options, "prefix");
|
|
||||||
while (tty_keys_next(&c->tty, &key, &mouse) == 0) {
|
|
||||||
if (c->session == NULL)
|
|
||||||
return;
|
|
||||||
w = c->session->curw->window;
|
|
||||||
wp = w->active; /* could die */
|
|
||||||
oo = &c->session->options;
|
|
||||||
|
|
||||||
/* Update activity timer. */
|
|
||||||
memcpy(&c->activity_time, &tv_now, sizeof c->activity_time);
|
|
||||||
memcpy(&c->session->activity_time,
|
|
||||||
&tv_now, sizeof c->session->activity_time);
|
|
||||||
|
|
||||||
/* Special case: number keys jump to pane in identify mode. */
|
|
||||||
if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
|
|
||||||
wp = window_pane_at_index(w, key - '0');
|
|
||||||
if (wp != NULL && window_pane_visible(wp))
|
|
||||||
window_set_active_pane(w, wp);
|
|
||||||
server_clear_identify(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_message_clear(c);
|
|
||||||
server_clear_identify(c);
|
|
||||||
if (c->prompt_string != NULL) {
|
|
||||||
status_prompt_key(c, key);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for mouse keys. */
|
|
||||||
if (key == KEYC_MOUSE) {
|
|
||||||
if (options_get_number(oo, "mouse-select-pane")) {
|
|
||||||
window_set_active_at(w, mouse.x, mouse.y);
|
|
||||||
wp = w->active;
|
|
||||||
}
|
|
||||||
window_pane_mouse(wp, c, &mouse);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Is this a prefix key? */
|
|
||||||
isprefix = 0;
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(keylist); i++) {
|
|
||||||
if (key == ARRAY_ITEM(keylist, i)) {
|
|
||||||
isprefix = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No previous prefix key. */
|
|
||||||
if (!(c->flags & CLIENT_PREFIX)) {
|
|
||||||
if (isprefix)
|
|
||||||
c->flags |= CLIENT_PREFIX;
|
|
||||||
else {
|
|
||||||
/* Try as a non-prefix key binding. */
|
|
||||||
if ((bd = key_bindings_lookup(key)) == NULL)
|
|
||||||
window_pane_key(wp, c, key);
|
|
||||||
else
|
|
||||||
key_bindings_dispatch(bd, c);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prefix key already pressed. Reset prefix and lookup key. */
|
|
||||||
c->flags &= ~CLIENT_PREFIX;
|
|
||||||
if ((bd = key_bindings_lookup(key | KEYC_PREFIX)) == NULL) {
|
|
||||||
/* If repeating, treat this as a key, else ignore. */
|
|
||||||
if (c->flags & CLIENT_REPEAT) {
|
|
||||||
c->flags &= ~CLIENT_REPEAT;
|
|
||||||
if (isprefix)
|
|
||||||
c->flags |= CLIENT_PREFIX;
|
|
||||||
else
|
|
||||||
window_pane_key(wp, c, key);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If already repeating, but this key can't repeat, skip it. */
|
|
||||||
if (c->flags & CLIENT_REPEAT && !bd->can_repeat) {
|
|
||||||
c->flags &= ~CLIENT_REPEAT;
|
|
||||||
if (isprefix)
|
|
||||||
c->flags |= CLIENT_PREFIX;
|
|
||||||
else
|
|
||||||
window_pane_key(wp, c, key);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this key can repeat, reset the repeat flags and timer. */
|
|
||||||
if (xtimeout != 0 && bd->can_repeat) {
|
|
||||||
c->flags |= CLIENT_PREFIX|CLIENT_REPEAT;
|
|
||||||
|
|
||||||
tv_add.tv_sec = xtimeout / 1000;
|
|
||||||
tv_add.tv_usec = (xtimeout % 1000) * 1000L;
|
|
||||||
timeradd(&tv_now, &tv_add, &c->repeat_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dispatch the command. */
|
|
||||||
key_bindings_dispatch(bd, c);
|
|
||||||
}
|
|
||||||
if (c->session == NULL)
|
|
||||||
return;
|
|
||||||
w = c->session->curw->window;
|
|
||||||
wp = w->active;
|
|
||||||
oo = &c->session->options;
|
|
||||||
s = wp->screen;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update cursor position and mode settings. The scroll region and
|
|
||||||
* attributes are cleared across poll(2) as this is the most likely
|
|
||||||
* time a user may interrupt tmux, for example with ~^Z in ssh(1). This
|
|
||||||
* is a compromise between excessive resets and likelihood of an
|
|
||||||
* interrupt.
|
|
||||||
*
|
|
||||||
* tty_region/tty_reset/tty_update_mode already take care of not
|
|
||||||
* resetting things that are already in their default state.
|
|
||||||
*/
|
|
||||||
tty_region(&c->tty, 0, c->tty.sy - 1);
|
|
||||||
|
|
||||||
status = options_get_number(oo, "status");
|
|
||||||
if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status)
|
|
||||||
tty_cursor(&c->tty, 0, 0);
|
|
||||||
else
|
|
||||||
tty_cursor(&c->tty, wp->xoff + s->cx, wp->yoff + s->cy);
|
|
||||||
|
|
||||||
mode = s->mode;
|
|
||||||
if (TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry) != NULL &&
|
|
||||||
options_get_number(oo, "mouse-select-pane"))
|
|
||||||
mode |= MODE_MOUSE;
|
|
||||||
tty_update_mode(&c->tty, mode);
|
|
||||||
tty_reset(&c->tty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for client redraws. */
|
|
||||||
void
|
|
||||||
server_client_check_redraw(struct client *c)
|
|
||||||
{
|
|
||||||
struct session *s = c->session;
|
|
||||||
struct window_pane *wp;
|
|
||||||
int flags, redraw;
|
|
||||||
|
|
||||||
flags = c->tty.flags & TTY_FREEZE;
|
|
||||||
c->tty.flags &= ~TTY_FREEZE;
|
|
||||||
|
|
||||||
if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) {
|
|
||||||
if (options_get_number(&s->options, "set-titles"))
|
|
||||||
server_client_set_title(c);
|
|
||||||
|
|
||||||
if (c->message_string != NULL)
|
|
||||||
redraw = status_message_redraw(c);
|
|
||||||
else if (c->prompt_string != NULL)
|
|
||||||
redraw = status_prompt_redraw(c);
|
|
||||||
else
|
|
||||||
redraw = status_redraw(c);
|
|
||||||
if (!redraw)
|
|
||||||
c->flags &= ~CLIENT_STATUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->flags & CLIENT_REDRAW) {
|
|
||||||
screen_redraw_screen(c, 0);
|
|
||||||
c->flags &= ~CLIENT_STATUS;
|
|
||||||
} else {
|
|
||||||
TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
|
|
||||||
if (wp->flags & PANE_REDRAW)
|
|
||||||
screen_redraw_pane(c, wp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->flags & CLIENT_STATUS)
|
|
||||||
screen_redraw_screen(c, 1);
|
|
||||||
|
|
||||||
c->tty.flags |= flags;
|
|
||||||
|
|
||||||
c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set client title. */
|
|
||||||
void
|
|
||||||
server_client_set_title(struct client *c)
|
|
||||||
{
|
|
||||||
struct session *s = c->session;
|
|
||||||
const char *template;
|
|
||||||
char *title;
|
|
||||||
|
|
||||||
template = options_get_string(&s->options, "set-titles-string");
|
|
||||||
|
|
||||||
title = status_replace(c, template, time(NULL));
|
|
||||||
if (c->title == NULL || strcmp(title, c->title) != 0) {
|
|
||||||
if (c->title != NULL)
|
|
||||||
xfree(c->title);
|
|
||||||
c->title = xstrdup(title);
|
|
||||||
tty_set_title(&c->tty, c->title);
|
|
||||||
}
|
|
||||||
xfree(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check client timers. */
|
|
||||||
void
|
|
||||||
server_client_check_timers(struct client *c)
|
|
||||||
{
|
|
||||||
struct session *s = c->session;
|
|
||||||
struct job *job;
|
|
||||||
struct timeval tv;
|
|
||||||
u_int interval;
|
|
||||||
|
|
||||||
if (gettimeofday(&tv, NULL) != 0)
|
|
||||||
fatal("gettimeofday failed");
|
|
||||||
|
|
||||||
if (c->flags & CLIENT_IDENTIFY && timercmp(&tv, &c->identify_timer, >))
|
|
||||||
server_clear_identify(c);
|
|
||||||
|
|
||||||
if (c->message_string != NULL && timercmp(&tv, &c->message_timer, >))
|
|
||||||
status_message_clear(c);
|
|
||||||
|
|
||||||
if (c->message_string != NULL || c->prompt_string != NULL) {
|
|
||||||
/*
|
|
||||||
* Don't need timed redraw for messages/prompts so bail now.
|
|
||||||
* The status timer isn't reset when they are redrawn anyway.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (!options_get_number(&s->options, "status"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Check timer; resolution is only a second so don't be too clever. */
|
|
||||||
interval = options_get_number(&s->options, "status-interval");
|
|
||||||
if (interval == 0)
|
|
||||||
return;
|
|
||||||
if (tv.tv_sec < c->status_timer.tv_sec ||
|
|
||||||
((u_int) tv.tv_sec) - c->status_timer.tv_sec >= interval) {
|
|
||||||
/* Run the jobs for this client and schedule for redraw. */
|
|
||||||
RB_FOREACH(job, jobs, &c->status_jobs)
|
|
||||||
job_run(job);
|
|
||||||
c->flags |= CLIENT_STATUS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dispatch message from client. */
|
|
||||||
int
|
|
||||||
server_client_msg_dispatch(struct client *c)
|
|
||||||
{
|
|
||||||
struct imsg imsg;
|
|
||||||
struct msg_command_data commanddata;
|
|
||||||
struct msg_identify_data identifydata;
|
|
||||||
struct msg_environ_data environdata;
|
|
||||||
ssize_t n, datalen;
|
|
||||||
|
|
||||||
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if ((n = imsg_get(&c->ibuf, &imsg)) == -1)
|
|
||||||
return (-1);
|
|
||||||
if (n == 0)
|
|
||||||
return (0);
|
|
||||||
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
|
|
||||||
|
|
||||||
if (imsg.hdr.peerid != PROTOCOL_VERSION) {
|
|
||||||
server_write_client(c, MSG_VERSION, NULL, 0);
|
|
||||||
c->flags |= CLIENT_BAD;
|
|
||||||
imsg_free(&imsg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd);
|
|
||||||
switch (imsg.hdr.type) {
|
|
||||||
case MSG_COMMAND:
|
|
||||||
if (datalen != sizeof commanddata)
|
|
||||||
fatalx("bad MSG_COMMAND size");
|
|
||||||
memcpy(&commanddata, imsg.data, sizeof commanddata);
|
|
||||||
|
|
||||||
server_client_msg_command(c, &commanddata);
|
|
||||||
break;
|
|
||||||
case MSG_IDENTIFY:
|
|
||||||
if (datalen != sizeof identifydata)
|
|
||||||
fatalx("bad MSG_IDENTIFY size");
|
|
||||||
if (imsg.fd == -1)
|
|
||||||
fatalx("MSG_IDENTIFY missing fd");
|
|
||||||
memcpy(&identifydata, imsg.data, sizeof identifydata);
|
|
||||||
|
|
||||||
server_client_msg_identify(c, &identifydata, imsg.fd);
|
|
||||||
break;
|
|
||||||
case MSG_RESIZE:
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_RESIZE size");
|
|
||||||
|
|
||||||
tty_resize(&c->tty);
|
|
||||||
recalculate_sizes();
|
|
||||||
server_redraw_client(c);
|
|
||||||
break;
|
|
||||||
case MSG_EXITING:
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_EXITING size");
|
|
||||||
|
|
||||||
c->session = NULL;
|
|
||||||
tty_close(&c->tty);
|
|
||||||
server_write_client(c, MSG_EXITED, NULL, 0);
|
|
||||||
break;
|
|
||||||
case MSG_WAKEUP:
|
|
||||||
case MSG_UNLOCK:
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_WAKEUP size");
|
|
||||||
|
|
||||||
if (!(c->flags & CLIENT_SUSPENDED))
|
|
||||||
break;
|
|
||||||
c->flags &= ~CLIENT_SUSPENDED;
|
|
||||||
|
|
||||||
if (gettimeofday(&c->activity_time, NULL) != 0)
|
|
||||||
fatal("gettimeofday");
|
|
||||||
if (c->session != NULL) {
|
|
||||||
memcpy(&c->session->activity_time,
|
|
||||||
&c->activity_time,
|
|
||||||
sizeof c->session->activity_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
tty_start_tty(&c->tty);
|
|
||||||
server_redraw_client(c);
|
|
||||||
recalculate_sizes();
|
|
||||||
break;
|
|
||||||
case MSG_ENVIRON:
|
|
||||||
if (datalen != sizeof environdata)
|
|
||||||
fatalx("bad MSG_ENVIRON size");
|
|
||||||
memcpy(&environdata, imsg.data, sizeof environdata);
|
|
||||||
|
|
||||||
environdata.var[(sizeof environdata.var) - 1] = '\0';
|
|
||||||
if (strchr(environdata.var, '=') != NULL)
|
|
||||||
environ_put(&c->environ, environdata.var);
|
|
||||||
break;
|
|
||||||
case MSG_SHELL:
|
|
||||||
if (datalen != 0)
|
|
||||||
fatalx("bad MSG_SHELL size");
|
|
||||||
|
|
||||||
server_client_msg_shell(c);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fatalx("unexpected message");
|
|
||||||
}
|
|
||||||
|
|
||||||
imsg_free(&imsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback to send error message to client. */
|
|
||||||
void printflike2
|
|
||||||
server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
struct msg_print_data data;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
server_write_client(ctx->cmdclient, MSG_ERROR, &data, sizeof data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback to send print message to client. */
|
|
||||||
void printflike2
|
|
||||||
server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
struct msg_print_data data;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback to send print message to client, if not quiet. */
|
|
||||||
void printflike2
|
|
||||||
server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
struct msg_print_data data;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
if (be_quiet)
|
|
||||||
return;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle command message. */
|
|
||||||
void
|
|
||||||
server_client_msg_command(struct client *c, struct msg_command_data *data)
|
|
||||||
{
|
|
||||||
struct cmd_ctx ctx;
|
|
||||||
struct cmd_list *cmdlist = NULL;
|
|
||||||
struct cmd *cmd;
|
|
||||||
int argc;
|
|
||||||
char **argv, *cause;
|
|
||||||
|
|
||||||
ctx.error = server_client_msg_error;
|
|
||||||
ctx.print = server_client_msg_print;
|
|
||||||
ctx.info = server_client_msg_info;
|
|
||||||
|
|
||||||
ctx.msgdata = data;
|
|
||||||
ctx.curclient = NULL;
|
|
||||||
|
|
||||||
ctx.cmdclient = c;
|
|
||||||
|
|
||||||
argc = data->argc;
|
|
||||||
data->argv[(sizeof data->argv) - 1] = '\0';
|
|
||||||
if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) {
|
|
||||||
server_client_msg_error(&ctx, "command too long");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc == 0) {
|
|
||||||
argc = 1;
|
|
||||||
argv = xcalloc(1, sizeof *argv);
|
|
||||||
*argv = xstrdup("new-session");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
|
|
||||||
server_client_msg_error(&ctx, "%s", cause);
|
|
||||||
cmd_free_argv(argc, argv);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
cmd_free_argv(argc, argv);
|
|
||||||
|
|
||||||
if (data->pid != -1) {
|
|
||||||
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
|
||||||
if (cmd->entry->flags & CMD_CANTNEST) {
|
|
||||||
server_client_msg_error(&ctx,
|
|
||||||
"sessions should be nested with care. "
|
|
||||||
"unset $TMUX to force");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd_list_exec(cmdlist, &ctx) != 1)
|
|
||||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
return;
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (cmdlist != NULL)
|
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
server_write_client(c, MSG_EXIT, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle identify message. */
|
|
||||||
void
|
|
||||||
server_client_msg_identify(
|
|
||||||
struct client *c, struct msg_identify_data *data, int fd)
|
|
||||||
{
|
|
||||||
c->cwd = NULL;
|
|
||||||
data->cwd[(sizeof data->cwd) - 1] = '\0';
|
|
||||||
if (*data->cwd != '\0')
|
|
||||||
c->cwd = xstrdup(data->cwd);
|
|
||||||
|
|
||||||
data->term[(sizeof data->term) - 1] = '\0';
|
|
||||||
tty_init(&c->tty, fd, data->term);
|
|
||||||
if (data->flags & IDENTIFY_UTF8)
|
|
||||||
c->tty.flags |= TTY_UTF8;
|
|
||||||
if (data->flags & IDENTIFY_256COLOURS)
|
|
||||||
c->tty.term_flags |= TERM_256COLOURS;
|
|
||||||
else if (data->flags & IDENTIFY_88COLOURS)
|
|
||||||
c->tty.term_flags |= TERM_88COLOURS;
|
|
||||||
|
|
||||||
tty_resize(&c->tty);
|
|
||||||
|
|
||||||
c->flags |= CLIENT_TERMINAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle shell message. */
|
|
||||||
void
|
|
||||||
server_client_msg_shell(struct client *c)
|
|
||||||
{
|
|
||||||
struct msg_shell_data data;
|
|
||||||
const char *shell;
|
|
||||||
|
|
||||||
shell = options_get_string(&global_s_options, "default-shell");
|
|
||||||
|
|
||||||
if (*shell == '\0' || areshell(shell))
|
|
||||||
shell = _PATH_BSHELL;
|
|
||||||
if (strlcpy(data.shell, shell, sizeof data.shell) >= sizeof data.shell)
|
|
||||||
strlcpy(data.shell, _PATH_BSHELL, sizeof data.shell);
|
|
||||||
|
|
||||||
server_write_client(c, MSG_SHELL, &data, sizeof data);
|
|
||||||
c->flags |= CLIENT_BAD; /* it will die after exec */
|
|
||||||
}
|
|
||||||
229
server-fn.c
229
server-fn.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: server-fn.c,v 1.94 2009-10-12 00:37:41 tcunha Exp $ */
|
/* $Id: server-fn.c,v 1.87 2009-09-13 20:37:37 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -18,12 +18,15 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
|
int server_lock_callback(void *, const char *);
|
||||||
|
|
||||||
void
|
void
|
||||||
server_fill_environ(struct session *s, struct environ *env)
|
server_fill_environ(struct session *s, struct environ *env)
|
||||||
{
|
{
|
||||||
@@ -104,19 +107,6 @@ server_redraw_session(struct session *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
server_redraw_session_group(struct session *s)
|
|
||||||
{
|
|
||||||
struct session_group *sg;
|
|
||||||
|
|
||||||
if ((sg = session_group_find(s)) == NULL)
|
|
||||||
server_redraw_session(s);
|
|
||||||
else {
|
|
||||||
TAILQ_FOREACH(s, &sg->sessions, gentry)
|
|
||||||
server_redraw_session(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
server_status_session(struct session *s)
|
server_status_session(struct session *s)
|
||||||
{
|
{
|
||||||
@@ -132,19 +122,6 @@ server_status_session(struct session *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
server_status_session_group(struct session *s)
|
|
||||||
{
|
|
||||||
struct session_group *sg;
|
|
||||||
|
|
||||||
if ((sg = session_group_find(s)) == NULL)
|
|
||||||
server_status_session(s);
|
|
||||||
else {
|
|
||||||
TAILQ_FOREACH(s, &sg->sessions, gentry)
|
|
||||||
server_status_session(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
server_redraw_window(struct window *w)
|
server_redraw_window(struct window *w)
|
||||||
{
|
{
|
||||||
@@ -183,52 +160,117 @@ server_status_window(struct window *w)
|
|||||||
void
|
void
|
||||||
server_lock(void)
|
server_lock(void)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
u_int i;
|
static struct passwd *pw, pwstore;
|
||||||
|
static char pwbuf[_PW_BUF_LEN];
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
if (server_locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (getpwuid_r(getuid(), &pwstore, pwbuf, sizeof pwbuf, &pw) != 0) {
|
||||||
|
server_locked_pw = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
server_locked_pw = pw;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
c = ARRAY_ITEM(&clients, i);
|
c = ARRAY_ITEM(&clients, i);
|
||||||
if (c == NULL || c->session == NULL)
|
if (c == NULL || c->session == NULL)
|
||||||
continue;
|
continue;
|
||||||
server_lock_client(c);
|
|
||||||
|
status_prompt_clear(c);
|
||||||
|
status_prompt_set(c,
|
||||||
|
"Password:", server_lock_callback, NULL, c, PROMPT_HIDDEN);
|
||||||
|
server_redraw_client(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server_locked = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
server_lock_session(struct session *s)
|
server_lock_callback(unused void *data, const char *s)
|
||||||
|
{
|
||||||
|
return (server_unlock(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
server_unlock(const char *s)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
#ifdef HAVE_LOGIN_CAP
|
||||||
|
login_cap_t *lc;
|
||||||
|
#endif
|
||||||
u_int i;
|
u_int i;
|
||||||
|
char *out;
|
||||||
|
u_int failures, tries, backoff;
|
||||||
|
|
||||||
|
if (!server_locked || server_locked_pw == NULL)
|
||||||
|
return (0);
|
||||||
|
server_activity = time(NULL);
|
||||||
|
if (server_activity < password_backoff)
|
||||||
|
return (-2);
|
||||||
|
|
||||||
|
if (server_password != NULL) {
|
||||||
|
if (s == NULL)
|
||||||
|
return (-1);
|
||||||
|
out = crypt(s, server_password);
|
||||||
|
if (strcmp(out, server_password) != 0)
|
||||||
|
goto wrong;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
c = ARRAY_ITEM(&clients, i);
|
c = ARRAY_ITEM(&clients, i);
|
||||||
if (c == NULL || c->session == NULL || c->session != s)
|
if (c == NULL)
|
||||||
continue;
|
continue;
|
||||||
server_lock_client(c);
|
|
||||||
|
status_prompt_clear(c);
|
||||||
|
server_redraw_client(c);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
server_locked = 0;
|
||||||
server_lock_client(struct client *c)
|
password_failures = 0;
|
||||||
{
|
password_backoff = 0;
|
||||||
const char *cmd;
|
return (0);
|
||||||
size_t cmdlen;
|
|
||||||
struct msg_lock_data lockdata;
|
|
||||||
|
|
||||||
if (c->flags & CLIENT_SUSPENDED)
|
wrong:
|
||||||
return;
|
password_failures++;
|
||||||
|
password_backoff = 0;
|
||||||
|
|
||||||
cmd = options_get_string(&c->session->options, "lock-command");
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
cmdlen = strlcpy(lockdata.cmd, cmd, sizeof lockdata.cmd);
|
c = ARRAY_ITEM(&clients, i);
|
||||||
if (cmdlen >= sizeof lockdata.cmd)
|
if (c == NULL || c->prompt_buffer == NULL)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
tty_stop_tty(&c->tty);
|
*c->prompt_buffer = '\0';
|
||||||
tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_SMCUP));
|
c->prompt_index = 0;
|
||||||
tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_CLEAR));
|
server_redraw_client(c);
|
||||||
|
}
|
||||||
|
|
||||||
c->flags |= CLIENT_SUSPENDED;
|
/*
|
||||||
server_write_client(c, MSG_LOCK, &lockdata, sizeof lockdata);
|
* Start slowing down after "login-backoff" attempts and reset every
|
||||||
|
* "login-tries" attempts.
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_LOGIN_CAP
|
||||||
|
lc = login_getclass(server_locked_pw->pw_class);
|
||||||
|
if (lc != NULL) {
|
||||||
|
tries = login_getcapnum(lc, (char *) "login-tries", 10, 10);
|
||||||
|
backoff = login_getcapnum(lc, (char *) "login-backoff", 3, 3);
|
||||||
|
} else {
|
||||||
|
tries = 10;
|
||||||
|
backoff = 3;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
tries = 10;
|
||||||
|
backoff = 3;
|
||||||
|
#endif
|
||||||
|
failures = password_failures % tries;
|
||||||
|
if (failures > backoff) {
|
||||||
|
password_backoff =
|
||||||
|
server_activity + ((failures - backoff) * tries / 2);
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -246,86 +288,11 @@ server_kill_window(struct window *w)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (session_detach(s, wl))
|
if (session_detach(s, wl))
|
||||||
server_destroy_session_group(s);
|
|
||||||
else {
|
|
||||||
server_redraw_session(s);
|
|
||||||
server_status_session_group(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
server_link_window(struct session *src, struct winlink *srcwl,
|
|
||||||
struct session *dst, int dstidx, int killflag, int selectflag, char **cause)
|
|
||||||
{
|
|
||||||
struct winlink *dstwl;
|
|
||||||
struct session_group *srcsg, *dstsg;
|
|
||||||
|
|
||||||
srcsg = session_group_find(src);
|
|
||||||
dstsg = session_group_find(dst);
|
|
||||||
if (src != dst && srcsg != NULL && dstsg != NULL && srcsg == dstsg) {
|
|
||||||
xasprintf(cause, "sessions are grouped");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
dstwl = NULL;
|
|
||||||
if (dstidx != -1)
|
|
||||||
dstwl = winlink_find_by_index(&dst->windows, dstidx);
|
|
||||||
if (dstwl != NULL) {
|
|
||||||
if (dstwl->window == srcwl->window)
|
|
||||||
return (0);
|
|
||||||
if (killflag) {
|
|
||||||
/*
|
|
||||||
* Can't use session_detach as it will destroy session
|
|
||||||
* if this makes it empty.
|
|
||||||
*/
|
|
||||||
session_alert_cancel(dst, dstwl);
|
|
||||||
winlink_stack_remove(&dst->lastw, dstwl);
|
|
||||||
winlink_remove(&dst->windows, dstwl);
|
|
||||||
|
|
||||||
/* Force select/redraw if current. */
|
|
||||||
if (dstwl == dst->curw) {
|
|
||||||
selectflag = 1;
|
|
||||||
dst->curw = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dstidx == -1)
|
|
||||||
dstidx = -1 - options_get_number(&dst->options, "base-index");
|
|
||||||
dstwl = session_attach(dst, srcwl->window, dstidx, cause);
|
|
||||||
if (dstwl == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
if (selectflag)
|
|
||||||
session_select(dst, dstwl->idx);
|
|
||||||
server_redraw_session_group(dst);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
server_unlink_window(struct session *s, struct winlink *wl)
|
|
||||||
{
|
|
||||||
if (session_detach(s, wl))
|
|
||||||
server_destroy_session_group(s);
|
|
||||||
else
|
|
||||||
server_redraw_session_group(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
server_destroy_session_group(struct session *s)
|
|
||||||
{
|
|
||||||
struct session_group *sg;
|
|
||||||
|
|
||||||
if ((sg = session_group_find(s)) == NULL)
|
|
||||||
server_destroy_session(s);
|
|
||||||
else {
|
|
||||||
TAILQ_FOREACH(s, &sg->sessions, gentry)
|
|
||||||
server_destroy_session(s);
|
server_destroy_session(s);
|
||||||
TAILQ_REMOVE(&session_groups, sg, entry);
|
else
|
||||||
xfree(sg);
|
server_redraw_session(s);
|
||||||
}
|
}
|
||||||
|
recalculate_sizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -354,7 +321,7 @@ server_set_identify(struct client *c)
|
|||||||
tv.tv_usec = (delay % 1000) * 1000L;
|
tv.tv_usec = (delay % 1000) * 1000L;
|
||||||
|
|
||||||
if (gettimeofday(&c->identify_timer, NULL) != 0)
|
if (gettimeofday(&c->identify_timer, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday");
|
||||||
timeradd(&c->identify_timer, &tv, &c->identify_timer);
|
timeradd(&c->identify_timer, &tv, &c->identify_timer);
|
||||||
|
|
||||||
c->flags |= CLIENT_IDENTIFY;
|
c->flags |= CLIENT_IDENTIFY;
|
||||||
|
|||||||
73
server-job.c
73
server-job.c
@@ -1,73 +0,0 @@
|
|||||||
/* $Id: server-job.c,v 1.3 2009-11-02 21:38:26 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 <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/* Register jobs for poll. */
|
|
||||||
void
|
|
||||||
server_job_prepare(void)
|
|
||||||
{
|
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
SLIST_FOREACH(job, &all_jobs, lentry) {
|
|
||||||
if (job->fd == -1)
|
|
||||||
continue;
|
|
||||||
server_poll_add(job->fd, POLLIN, server_job_callback, job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process a single job event. */
|
|
||||||
void
|
|
||||||
server_job_callback(int fd, int events, void *data)
|
|
||||||
{
|
|
||||||
struct job *job = data;
|
|
||||||
|
|
||||||
if (job->fd == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (buffer_poll(fd, events, job->out, NULL) != 0) {
|
|
||||||
close(job->fd);
|
|
||||||
job->fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Job functions that happen once a loop. */
|
|
||||||
void
|
|
||||||
server_job_loop(void)
|
|
||||||
{
|
|
||||||
struct job *job;
|
|
||||||
|
|
||||||
restart:
|
|
||||||
SLIST_FOREACH(job, &all_jobs, lentry) {
|
|
||||||
if (job->flags & JOB_DONE || job->fd != -1 || job->pid != -1)
|
|
||||||
continue;
|
|
||||||
job->flags |= JOB_DONE;
|
|
||||||
|
|
||||||
if (job->callbackfn != NULL) {
|
|
||||||
job->callbackfn(job);
|
|
||||||
if ((!job->flags & JOB_PERSIST)) {
|
|
||||||
job_free(job);
|
|
||||||
goto restart;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
292
server-msg.c
Normal file
292
server-msg.c
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
/* $Id: server-msg.c,v 1.84 2009-09-15 23:52:30 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 <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
void server_msg_command(struct client *, struct msg_command_data *);
|
||||||
|
void server_msg_identify(struct client *, struct msg_identify_data *, int);
|
||||||
|
void server_msg_resize(struct client *, struct msg_resize_data *);
|
||||||
|
|
||||||
|
void printflike2 server_msg_command_error(struct cmd_ctx *, const char *, ...);
|
||||||
|
void printflike2 server_msg_command_print(struct cmd_ctx *, const char *, ...);
|
||||||
|
void printflike2 server_msg_command_info(struct cmd_ctx *, const char *, ...);
|
||||||
|
|
||||||
|
int
|
||||||
|
server_msg_dispatch(struct client *c)
|
||||||
|
{
|
||||||
|
struct imsg imsg;
|
||||||
|
struct msg_command_data commanddata;
|
||||||
|
struct msg_identify_data identifydata;
|
||||||
|
struct msg_resize_data resizedata;
|
||||||
|
struct msg_unlock_data unlockdata;
|
||||||
|
struct msg_environ_data environdata;
|
||||||
|
ssize_t n, datalen;
|
||||||
|
|
||||||
|
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((n = imsg_get(&c->ibuf, &imsg)) == -1)
|
||||||
|
return (-1);
|
||||||
|
if (n == 0)
|
||||||
|
return (0);
|
||||||
|
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
|
||||||
|
|
||||||
|
if (imsg.hdr.peerid != PROTOCOL_VERSION) {
|
||||||
|
server_write_client(c, MSG_VERSION, NULL, 0);
|
||||||
|
c->flags |= CLIENT_BAD;
|
||||||
|
imsg_free(&imsg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd);
|
||||||
|
switch (imsg.hdr.type) {
|
||||||
|
case MSG_COMMAND:
|
||||||
|
if (datalen != sizeof commanddata)
|
||||||
|
fatalx("bad MSG_COMMAND size");
|
||||||
|
memcpy(&commanddata, imsg.data, sizeof commanddata);
|
||||||
|
|
||||||
|
server_msg_command(c, &commanddata);
|
||||||
|
break;
|
||||||
|
case MSG_IDENTIFY:
|
||||||
|
if (datalen != sizeof identifydata)
|
||||||
|
fatalx("bad MSG_IDENTIFY size");
|
||||||
|
memcpy(&identifydata, imsg.data, sizeof identifydata);
|
||||||
|
|
||||||
|
server_msg_identify(c, &identifydata, imsg.fd);
|
||||||
|
break;
|
||||||
|
case MSG_RESIZE:
|
||||||
|
if (datalen != sizeof resizedata)
|
||||||
|
fatalx("bad MSG_RESIZE size");
|
||||||
|
memcpy(&resizedata, imsg.data, sizeof resizedata);
|
||||||
|
|
||||||
|
server_msg_resize(c, &resizedata);
|
||||||
|
break;
|
||||||
|
case MSG_EXITING:
|
||||||
|
if (datalen != 0)
|
||||||
|
fatalx("bad MSG_EXITING size");
|
||||||
|
|
||||||
|
c->session = NULL;
|
||||||
|
tty_close(&c->tty);
|
||||||
|
server_write_client(c, MSG_EXITED, NULL, 0);
|
||||||
|
break;
|
||||||
|
case MSG_UNLOCK:
|
||||||
|
if (datalen != sizeof unlockdata)
|
||||||
|
fatalx("bad MSG_UNLOCK size");
|
||||||
|
memcpy(&unlockdata, imsg.data, sizeof unlockdata);
|
||||||
|
|
||||||
|
unlockdata.pass[(sizeof unlockdata.pass) - 1] = '\0';
|
||||||
|
switch (server_unlock(unlockdata.pass)) {
|
||||||
|
case -1:
|
||||||
|
server_write_error(c, "bad password");
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
server_write_error(c,
|
||||||
|
"too many bad passwords, sleeping");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(&unlockdata, 0, sizeof unlockdata);
|
||||||
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
|
break;
|
||||||
|
case MSG_WAKEUP:
|
||||||
|
if (datalen != 0)
|
||||||
|
fatalx("bad MSG_WAKEUP size");
|
||||||
|
|
||||||
|
c->flags &= ~CLIENT_SUSPENDED;
|
||||||
|
tty_start_tty(&c->tty);
|
||||||
|
server_redraw_client(c);
|
||||||
|
break;
|
||||||
|
case MSG_ENVIRON:
|
||||||
|
if (datalen != sizeof environdata)
|
||||||
|
fatalx("bad MSG_ENVIRON size");
|
||||||
|
memcpy(&environdata, imsg.data, sizeof environdata);
|
||||||
|
|
||||||
|
environdata.var[(sizeof environdata.var) - 1] = '\0';
|
||||||
|
if (strchr(environdata.var, '=') != NULL)
|
||||||
|
environ_put(&c->environ, environdata.var);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatalx("unexpected message");
|
||||||
|
}
|
||||||
|
|
||||||
|
imsg_free(&imsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printflike2
|
||||||
|
server_msg_command_error(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct msg_print_data data;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
server_write_client(ctx->cmdclient, MSG_ERROR, &data, sizeof data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printflike2
|
||||||
|
server_msg_command_print(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct msg_print_data data;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printflike2
|
||||||
|
server_msg_command_info(struct cmd_ctx *ctx, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct msg_print_data data;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if (be_quiet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_msg_command(struct client *c, struct msg_command_data *data)
|
||||||
|
{
|
||||||
|
struct cmd_ctx ctx;
|
||||||
|
struct cmd_list *cmdlist = NULL;
|
||||||
|
struct cmd *cmd;
|
||||||
|
int argc;
|
||||||
|
char **argv, *cause;
|
||||||
|
|
||||||
|
server_activity = time(NULL);
|
||||||
|
|
||||||
|
ctx.error = server_msg_command_error;
|
||||||
|
ctx.print = server_msg_command_print;
|
||||||
|
ctx.info = server_msg_command_info;
|
||||||
|
|
||||||
|
ctx.msgdata = data;
|
||||||
|
ctx.curclient = NULL;
|
||||||
|
|
||||||
|
ctx.cmdclient = c;
|
||||||
|
|
||||||
|
argc = data->argc;
|
||||||
|
data->argv[(sizeof data->argv) - 1] = '\0';
|
||||||
|
if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) {
|
||||||
|
server_msg_command_error(&ctx, "command too long");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 0) {
|
||||||
|
argc = 1;
|
||||||
|
argv = xcalloc(1, sizeof *argv);
|
||||||
|
*argv = xstrdup("new-session");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
|
||||||
|
server_msg_command_error(&ctx, "%s", cause);
|
||||||
|
cmd_free_argv(argc, argv);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
cmd_free_argv(argc, argv);
|
||||||
|
|
||||||
|
if (data->pid != -1) {
|
||||||
|
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
||||||
|
if (cmd->entry->flags & CMD_CANTNEST) {
|
||||||
|
server_msg_command_error(&ctx,
|
||||||
|
"sessions should be nested with care. "
|
||||||
|
"unset $TMUX to force");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd_list_exec(cmdlist, &ctx) != 1)
|
||||||
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
|
cmd_list_free(cmdlist);
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (cmdlist != NULL)
|
||||||
|
cmd_list_free(cmdlist);
|
||||||
|
server_write_client(c, MSG_EXIT, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_msg_identify(struct client *c, struct msg_identify_data *data, int fd)
|
||||||
|
{
|
||||||
|
c->tty.sx = data->sx;
|
||||||
|
if (c->tty.sx == 0)
|
||||||
|
c->tty.sx = 80;
|
||||||
|
c->tty.sy = data->sy;
|
||||||
|
if (c->tty.sy == 0)
|
||||||
|
c->tty.sy = 24;
|
||||||
|
|
||||||
|
c->cwd = NULL;
|
||||||
|
data->cwd[(sizeof data->cwd) - 1] = '\0';
|
||||||
|
if (*data->cwd != '\0')
|
||||||
|
c->cwd = xstrdup(data->cwd);
|
||||||
|
|
||||||
|
data->tty[(sizeof data->tty) - 1] = '\0';
|
||||||
|
data->term[(sizeof data->term) - 1] = '\0';
|
||||||
|
tty_init(&c->tty, fd, data->tty, data->term);
|
||||||
|
if (data->flags & IDENTIFY_UTF8)
|
||||||
|
c->tty.flags |= TTY_UTF8;
|
||||||
|
if (data->flags & IDENTIFY_256COLOURS)
|
||||||
|
c->tty.term_flags |= TERM_256COLOURS;
|
||||||
|
else if (data->flags & IDENTIFY_88COLOURS)
|
||||||
|
c->tty.term_flags |= TERM_88COLOURS;
|
||||||
|
if (data->flags & IDENTIFY_HASDEFAULTS)
|
||||||
|
c->tty.term_flags |= TERM_HASDEFAULTS;
|
||||||
|
|
||||||
|
c->flags |= CLIENT_TERMINAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_msg_resize(struct client *c, struct msg_resize_data *data)
|
||||||
|
{
|
||||||
|
c->tty.sx = data->sx;
|
||||||
|
if (c->tty.sx == 0)
|
||||||
|
c->tty.sx = 80;
|
||||||
|
c->tty.sy = data->sy;
|
||||||
|
if (c->tty.sy == 0)
|
||||||
|
c->tty.sy = 24;
|
||||||
|
|
||||||
|
c->tty.cx = UINT_MAX;
|
||||||
|
c->tty.cy = UINT_MAX;
|
||||||
|
c->tty.rupper = UINT_MAX;
|
||||||
|
c->tty.rlower = UINT_MAX;
|
||||||
|
|
||||||
|
recalculate_sizes();
|
||||||
|
|
||||||
|
/* Always redraw this client. */
|
||||||
|
server_redraw_client(c);
|
||||||
|
}
|
||||||
341
server-window.c
341
server-window.c
@@ -1,341 +0,0 @@
|
|||||||
/* $Id: server-window.c,v 1.4 2009-11-04 22:47:29 tcunha Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
int server_window_backoff(struct window_pane *);
|
|
||||||
int server_window_check_bell(struct session *, struct window *);
|
|
||||||
int server_window_check_activity(struct session *, struct window *);
|
|
||||||
int server_window_check_content(
|
|
||||||
struct session *, struct window *, struct window_pane *);
|
|
||||||
void server_window_check_alive(struct window *);
|
|
||||||
|
|
||||||
/* Register windows for poll. */
|
|
||||||
void
|
|
||||||
server_window_prepare(void)
|
|
||||||
{
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
u_int i;
|
|
||||||
int events;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
|
||||||
if ((w = ARRAY_ITEM(&windows, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
|
||||||
if (wp->fd == -1)
|
|
||||||
continue;
|
|
||||||
events = 0;
|
|
||||||
if (!server_window_backoff(wp))
|
|
||||||
events |= POLLIN;
|
|
||||||
if (BUFFER_USED(wp->out) > 0)
|
|
||||||
events |= POLLOUT;
|
|
||||||
server_poll_add(
|
|
||||||
wp->fd, events, server_window_callback, wp);
|
|
||||||
|
|
||||||
if (wp->pipe_fd == -1)
|
|
||||||
continue;
|
|
||||||
events = 0;
|
|
||||||
if (BUFFER_USED(wp->pipe_buf) > 0)
|
|
||||||
events |= POLLOUT;
|
|
||||||
server_poll_add(
|
|
||||||
wp->pipe_fd, events, server_window_callback, wp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 (BUFFER_USED(c->tty.out) > BACKOFF_THRESHOLD)
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process a single window pane event. */
|
|
||||||
void
|
|
||||||
server_window_callback(int fd, int events, void *data)
|
|
||||||
{
|
|
||||||
struct window_pane *wp = data;
|
|
||||||
|
|
||||||
if (wp->fd == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (fd == wp->fd) {
|
|
||||||
if (buffer_poll(fd, events, wp->in, wp->out) != 0) {
|
|
||||||
close(wp->fd);
|
|
||||||
wp->fd = -1;
|
|
||||||
} else
|
|
||||||
window_pane_parse(wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd == wp->pipe_fd) {
|
|
||||||
if (buffer_poll(fd, events, NULL, wp->pipe_buf) != 0) {
|
|
||||||
buffer_destroy(wp->pipe_buf);
|
|
||||||
close(wp->pipe_fd);
|
|
||||||
wp->pipe_fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Window functions that need to happen every loop. */
|
|
||||||
void
|
|
||||||
server_window_loop(void)
|
|
||||||
{
|
|
||||||
struct window *w;
|
|
||||||
struct window_pane *wp;
|
|
||||||
struct session *s;
|
|
||||||
u_int i, j;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
|
||||||
w = ARRAY_ITEM(&windows, i);
|
|
||||||
if (w == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
|
|
||||||
s = ARRAY_ITEM(&sessions, j);
|
|
||||||
if (s == NULL || !session_has(s, w))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (server_window_check_bell(s, w) ||
|
|
||||||
server_window_check_activity(s, w))
|
|
||||||
server_status_session(s);
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry)
|
|
||||||
server_window_check_content(s, w, wp);
|
|
||||||
}
|
|
||||||
w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_CONTENT);
|
|
||||||
|
|
||||||
server_window_check_alive(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_window_names();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for bell in window. */
|
|
||||||
int
|
|
||||||
server_window_check_bell(struct session *s, struct window *w)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
u_int i;
|
|
||||||
int action, visual;
|
|
||||||
|
|
||||||
if (!(w->flags & WINDOW_BELL))
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
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");
|
|
||||||
switch (action) {
|
|
||||||
case BELL_ANY:
|
|
||||||
if (s->flags & SESSION_UNATTACHED)
|
|
||||||
break;
|
|
||||||
visual = options_get_number(&s->options, "visual-bell");
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
c = ARRAY_ITEM(&clients, i);
|
|
||||||
if (c == NULL || c->session != s)
|
|
||||||
continue;
|
|
||||||
if (!visual) {
|
|
||||||
tty_putcode(&c->tty, TTYC_BEL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (c->session->curw->window == w) {
|
|
||||||
status_message_set(c, "Bell in current window");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
status_message_set(c, "Bell in window %u",
|
|
||||||
winlink_find_by_window(&s->windows, w)->idx);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BELL_CURRENT:
|
|
||||||
if (s->flags & SESSION_UNATTACHED)
|
|
||||||
break;
|
|
||||||
visual = options_get_number(&s->options, "visual-bell");
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
c = ARRAY_ITEM(&clients, i);
|
|
||||||
if (c == NULL || c->session != s)
|
|
||||||
continue;
|
|
||||||
if (c->session->curw->window != w)
|
|
||||||
continue;
|
|
||||||
if (!visual) {
|
|
||||||
tty_putcode(&c->tty, TTYC_BEL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
status_message_set(c, "Bell in current window");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for activity in window. */
|
|
||||||
int
|
|
||||||
server_window_check_activity(struct session *s, struct window *w)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
if (!(w->flags & WINDOW_ACTIVITY))
|
|
||||||
return (0);
|
|
||||||
if (s->curw->window == w)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (!options_get_number(&w->options, "monitor-activity"))
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (session_alert_has_window(s, w, WINDOW_ACTIVITY))
|
|
||||||
return (0);
|
|
||||||
session_alert_add(s, w, WINDOW_ACTIVITY);
|
|
||||||
|
|
||||||
if (s->flags & SESSION_UNATTACHED)
|
|
||||||
return (0);
|
|
||||||
if (options_get_number(&s->options, "visual-activity")) {
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
c = ARRAY_ITEM(&clients, i);
|
|
||||||
if (c == NULL || c->session != s)
|
|
||||||
continue;
|
|
||||||
status_message_set(c, "Activity in window %u",
|
|
||||||
winlink_find_by_window(&s->windows, w)->idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for content change in window. */
|
|
||||||
int
|
|
||||||
server_window_check_content(
|
|
||||||
struct session *s, struct window *w, struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct client *c;
|
|
||||||
u_int i;
|
|
||||||
char *found, *ptr;
|
|
||||||
|
|
||||||
if (!(w->flags & WINDOW_ACTIVITY)) /* activity for new content */
|
|
||||||
return (0);
|
|
||||||
if (s->curw->window == w)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
ptr = options_get_string(&w->options, "monitor-content");
|
|
||||||
if (ptr == NULL || *ptr == '\0')
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (session_alert_has_window(s, w, WINDOW_CONTENT))
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if ((found = window_pane_search(wp, ptr, NULL)) == NULL)
|
|
||||||
return (0);
|
|
||||||
xfree(found);
|
|
||||||
|
|
||||||
session_alert_add(s, w, WINDOW_CONTENT);
|
|
||||||
if (s->flags & SESSION_UNATTACHED)
|
|
||||||
return (0);
|
|
||||||
if (options_get_number(&s->options, "visual-content")) {
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
|
||||||
c = ARRAY_ITEM(&clients, i);
|
|
||||||
if (c == NULL || c->session != s)
|
|
||||||
continue;
|
|
||||||
status_message_set(c, "Content in window %u",
|
|
||||||
winlink_find_by_window(&s->windows, w)->idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if window still exists. */
|
|
||||||
void
|
|
||||||
server_window_check_alive(struct window *w)
|
|
||||||
{
|
|
||||||
struct window_pane *wp, *wq;
|
|
||||||
struct options *oo = &w->options;
|
|
||||||
struct session *s;
|
|
||||||
struct winlink *wl;
|
|
||||||
u_int i;
|
|
||||||
int destroyed;
|
|
||||||
|
|
||||||
destroyed = 1;
|
|
||||||
|
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
|
||||||
while (wp != NULL) {
|
|
||||||
wq = TAILQ_NEXT(wp, entry);
|
|
||||||
/*
|
|
||||||
* If the pane has died and the remain-on-exit flag is not set,
|
|
||||||
* remove the pane; otherwise, if the flag is set, don't allow
|
|
||||||
* the window to be destroyed (or it'll close when the last
|
|
||||||
* pane dies).
|
|
||||||
*/
|
|
||||||
if (wp->fd == -1 && !options_get_number(oo, "remain-on-exit")) {
|
|
||||||
layout_close_pane(wp);
|
|
||||||
window_remove_pane(w, wp);
|
|
||||||
server_redraw_window(w);
|
|
||||||
} else
|
|
||||||
destroyed = 0;
|
|
||||||
wp = wq;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!destroyed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
|
||||||
if (s == NULL)
|
|
||||||
continue;
|
|
||||||
if (!session_has(s, w))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
restart:
|
|
||||||
/* Detach window and either redraw or kill clients. */
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
|
||||||
if (wl->window != w)
|
|
||||||
continue;
|
|
||||||
if (session_detach(s, wl)) {
|
|
||||||
server_destroy_session_group(s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
server_redraw_session(s);
|
|
||||||
server_status_session_group(s);
|
|
||||||
goto restart;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
recalculate_sizes();
|
|
||||||
}
|
|
||||||
197
session.c
197
session.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: session.c,v 1.70 2009-11-04 22:42:31 tcunha Exp $ */
|
/* $Id: session.c,v 1.66 2009-09-16 12:36:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -22,14 +22,12 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/* Global session list. */
|
/* Global session list. */
|
||||||
struct sessions sessions;
|
struct sessions sessions;
|
||||||
struct sessions dead_sessions;
|
struct sessions dead_sessions;
|
||||||
struct session_groups session_groups;
|
|
||||||
|
|
||||||
struct winlink *session_next_activity(struct session *, struct winlink *);
|
struct winlink *session_next_activity(struct session *, struct winlink *);
|
||||||
struct winlink *session_previous_activity(struct session *, struct winlink *);
|
struct winlink *session_previous_activity(struct session *, struct winlink *);
|
||||||
@@ -126,12 +124,11 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
s->references = 0;
|
s->references = 0;
|
||||||
s->flags = 0;
|
s->flags = 0;
|
||||||
|
|
||||||
if (gettimeofday(&s->creation_time, NULL) != 0)
|
if (gettimeofday(&s->tv, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday");
|
||||||
memcpy(&s->activity_time, &s->creation_time, sizeof s->activity_time);
|
|
||||||
|
|
||||||
s->curw = NULL;
|
s->curw = NULL;
|
||||||
TAILQ_INIT(&s->lastw);
|
SLIST_INIT(&s->lastw);
|
||||||
RB_INIT(&s->windows);
|
RB_INIT(&s->windows);
|
||||||
SLIST_INIT(&s->alerts);
|
SLIST_INIT(&s->alerts);
|
||||||
|
|
||||||
@@ -164,14 +161,11 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
s->name = xstrdup(name);
|
s->name = xstrdup(name);
|
||||||
else
|
else
|
||||||
xasprintf(&s->name, "%u", i);
|
xasprintf(&s->name, "%u", i);
|
||||||
|
if (session_new(s, NULL, cmd, cwd, idx, cause) == NULL) {
|
||||||
if (cmd != NULL) {
|
session_destroy(s);
|
||||||
if (session_new(s, NULL, cmd, cwd, idx, cause) == NULL) {
|
return (NULL);
|
||||||
session_destroy(s);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
session_select(s, RB_ROOT(&s->windows)->idx);
|
|
||||||
}
|
}
|
||||||
|
session_select(s, RB_ROOT(&s->windows)->idx);
|
||||||
|
|
||||||
log_debug("session %s created", s->name);
|
log_debug("session %s created", s->name);
|
||||||
|
|
||||||
@@ -195,14 +189,13 @@ session_destroy(struct session *s)
|
|||||||
if (s->tio != NULL)
|
if (s->tio != NULL)
|
||||||
xfree(s->tio);
|
xfree(s->tio);
|
||||||
|
|
||||||
session_group_remove(s);
|
|
||||||
session_alert_cancel(s, NULL);
|
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);
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&s->lastw))
|
while (!SLIST_EMPTY(&s->lastw))
|
||||||
winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw));
|
winlink_stack_remove(&s->lastw, SLIST_FIRST(&s->lastw));
|
||||||
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));
|
||||||
|
|
||||||
@@ -272,7 +265,6 @@ session_attach(struct session *s, struct window *w, int idx, char **cause)
|
|||||||
|
|
||||||
if ((wl = winlink_add(&s->windows, w, idx)) == NULL)
|
if ((wl = winlink_add(&s->windows, w, idx)) == NULL)
|
||||||
xasprintf(cause, "index in use: %d", idx);
|
xasprintf(cause, "index in use: %d", idx);
|
||||||
session_group_synchronize_from(s);
|
|
||||||
return (wl);
|
return (wl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +279,6 @@ session_detach(struct session *s, struct winlink *wl)
|
|||||||
session_alert_cancel(s, wl);
|
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);
|
|
||||||
if (RB_EMPTY(&s->windows)) {
|
if (RB_EMPTY(&s->windows)) {
|
||||||
session_destroy(s);
|
session_destroy(s);
|
||||||
return (1);
|
return (1);
|
||||||
@@ -414,7 +405,7 @@ session_last(struct session *s)
|
|||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
|
|
||||||
wl = TAILQ_FIRST(&s->lastw);
|
wl = SLIST_FIRST(&s->lastw);
|
||||||
if (wl == NULL)
|
if (wl == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (wl == s->curw)
|
if (wl == s->curw)
|
||||||
@@ -426,169 +417,3 @@ session_last(struct session *s)
|
|||||||
session_alert_cancel(s, wl);
|
session_alert_cancel(s, wl);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the session group containing a session. */
|
|
||||||
struct session_group *
|
|
||||||
session_group_find(struct session *target)
|
|
||||||
{
|
|
||||||
struct session_group *sg;
|
|
||||||
struct session *s;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(sg, &session_groups, entry) {
|
|
||||||
TAILQ_FOREACH(s, &sg->sessions, gentry) {
|
|
||||||
if (s == target)
|
|
||||||
return (sg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find session group index. */
|
|
||||||
u_int
|
|
||||||
session_group_index(struct session_group *sg)
|
|
||||||
{
|
|
||||||
struct session_group *sg2;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
TAILQ_FOREACH(sg2, &session_groups, entry) {
|
|
||||||
if (sg == sg2)
|
|
||||||
return (i);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fatalx("session group not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add a session to the session group containing target, creating it if
|
|
||||||
* necessary.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
session_group_add(struct session *target, struct session *s)
|
|
||||||
{
|
|
||||||
struct session_group *sg;
|
|
||||||
|
|
||||||
if ((sg = session_group_find(target)) == NULL) {
|
|
||||||
sg = xmalloc(sizeof *sg);
|
|
||||||
TAILQ_INSERT_TAIL(&session_groups, sg, entry);
|
|
||||||
TAILQ_INIT(&sg->sessions);
|
|
||||||
TAILQ_INSERT_TAIL(&sg->sessions, target, gentry);
|
|
||||||
}
|
|
||||||
TAILQ_INSERT_TAIL(&sg->sessions, s, gentry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove a session from its group and destroy the group if empty. */
|
|
||||||
void
|
|
||||||
session_group_remove(struct session *s)
|
|
||||||
{
|
|
||||||
struct session_group *sg;
|
|
||||||
|
|
||||||
if ((sg = session_group_find(s)) == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_REMOVE(&sg->sessions, s, gentry);
|
|
||||||
if (TAILQ_NEXT(TAILQ_FIRST(&sg->sessions), gentry) == NULL)
|
|
||||||
TAILQ_REMOVE(&sg->sessions, TAILQ_FIRST(&sg->sessions), gentry);
|
|
||||||
if (TAILQ_EMPTY(&sg->sessions)) {
|
|
||||||
TAILQ_REMOVE(&session_groups, sg, entry);
|
|
||||||
xfree(sg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Synchronize a session to its session group. */
|
|
||||||
void
|
|
||||||
session_group_synchronize_to(struct session *s)
|
|
||||||
{
|
|
||||||
struct session_group *sg;
|
|
||||||
struct session *target;
|
|
||||||
|
|
||||||
if ((sg = session_group_find(s)) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
target = NULL;
|
|
||||||
TAILQ_FOREACH(target, &sg->sessions, gentry) {
|
|
||||||
if (target != s)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
session_group_synchronize1(target, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Synchronize a session group to a session. */
|
|
||||||
void
|
|
||||||
session_group_synchronize_from(struct session *target)
|
|
||||||
{
|
|
||||||
struct session_group *sg;
|
|
||||||
struct session *s;
|
|
||||||
|
|
||||||
if ((sg = session_group_find(target)) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(s, &sg->sessions, gentry) {
|
|
||||||
if (s != target)
|
|
||||||
session_group_synchronize1(target, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Synchronize a session with a target session. This means destroying all
|
|
||||||
* winlinks then recreating them, then updating the current window, last window
|
|
||||||
* stack and alerts.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
session_group_synchronize1(struct session *target, struct session *s)
|
|
||||||
{
|
|
||||||
struct winlinks old_windows, *ww;
|
|
||||||
struct winlink_stack old_lastw;
|
|
||||||
struct winlink *wl, *wl2;
|
|
||||||
struct session_alert *sa;
|
|
||||||
|
|
||||||
/* Don't do anything if the session is empty (it'll be destroyed). */
|
|
||||||
ww = &target->windows;
|
|
||||||
if (RB_EMPTY(ww))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* If the current window has vanished, move to the next now. */
|
|
||||||
if (s->curw != NULL) {
|
|
||||||
while (winlink_find_by_index(ww, s->curw->idx) == NULL)
|
|
||||||
session_next(s, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the old pointer and reset it. */
|
|
||||||
memcpy(&old_windows, &s->windows, sizeof old_windows);
|
|
||||||
RB_INIT(&s->windows);
|
|
||||||
|
|
||||||
/* Link all the windows from the target. */
|
|
||||||
RB_FOREACH(wl, winlinks, ww)
|
|
||||||
winlink_add(&s->windows, wl->window, wl->idx);
|
|
||||||
|
|
||||||
/* Fix up the current window. */
|
|
||||||
if (s->curw != NULL)
|
|
||||||
s->curw = winlink_find_by_index(&s->windows, s->curw->idx);
|
|
||||||
else
|
|
||||||
s->curw = winlink_find_by_index(&s->windows, target->curw->idx);
|
|
||||||
|
|
||||||
/* Fix up the last window stack. */
|
|
||||||
memcpy(&old_lastw, &s->lastw, sizeof old_lastw);
|
|
||||||
TAILQ_INIT(&s->lastw);
|
|
||||||
TAILQ_FOREACH(wl, &old_lastw, sentry) {
|
|
||||||
wl2 = winlink_find_by_index(&s->windows, wl->idx);
|
|
||||||
if (wl2 != NULL)
|
|
||||||
TAILQ_INSERT_TAIL(&s->lastw, wl2, sentry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And update the alerts list. */
|
|
||||||
SLIST_FOREACH(sa, &s->alerts, entry) {
|
|
||||||
wl = winlink_find_by_index(&s->windows, sa->wl->idx);
|
|
||||||
if (wl == NULL)
|
|
||||||
session_alert_cancel(s, sa->wl);
|
|
||||||
else
|
|
||||||
sa->wl = wl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Then free the old winlinks list. */
|
|
||||||
while (!RB_EMPTY(&old_windows)) {
|
|
||||||
wl = RB_ROOT(&old_windows);
|
|
||||||
RB_REMOVE(winlinks, &old_windows, wl);
|
|
||||||
xfree(wl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
129
status.c
129
status.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: status.c,v 1.125 2009-11-04 23:12:32 tcunha Exp $ */
|
/* $Id: status.c,v 1.118 2009-09-11 14:13:52 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -29,8 +29,7 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
char *status_job(struct client *, char **);
|
char *status_replace_popen(char **);
|
||||||
void status_job_callback(struct job *);
|
|
||||||
size_t status_width(struct winlink *);
|
size_t status_width(struct winlink *);
|
||||||
char *status_print(struct session *, struct winlink *, struct grid_cell *);
|
char *status_print(struct session *, struct winlink *, struct grid_cell *);
|
||||||
|
|
||||||
@@ -65,7 +64,7 @@ status_redraw(struct client *c)
|
|||||||
screen_init(&c->status, c->tty.sx, 1, 0);
|
screen_init(&c->status, c->tty.sx, 1, 0);
|
||||||
|
|
||||||
if (gettimeofday(&c->status_timer, NULL) != 0)
|
if (gettimeofday(&c->status_timer, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday");
|
||||||
memcpy(&stdgc, &grid_default_cell, sizeof gc);
|
memcpy(&stdgc, &grid_default_cell, sizeof gc);
|
||||||
colour_set_fg(&stdgc, options_get_number(&s->options, "status-fg"));
|
colour_set_fg(&stdgc, options_get_number(&s->options, "status-fg"));
|
||||||
colour_set_bg(&stdgc, options_get_number(&s->options, "status-bg"));
|
colour_set_bg(&stdgc, options_get_number(&s->options, "status-bg"));
|
||||||
@@ -105,14 +104,14 @@ status_redraw(struct client *c)
|
|||||||
utf8flag = options_get_number(&s->options, "status-utf8");
|
utf8flag = options_get_number(&s->options, "status-utf8");
|
||||||
|
|
||||||
/* Work out the left and right strings. */
|
/* Work out the left and right strings. */
|
||||||
left = status_replace(c, options_get_string(
|
left = status_replace(s, options_get_string(
|
||||||
&s->options, "status-left"), c->status_timer.tv_sec);
|
&s->options, "status-left"), c->status_timer.tv_sec);
|
||||||
llen = options_get_number(&s->options, "status-left-length");
|
llen = options_get_number(&s->options, "status-left-length");
|
||||||
llen2 = screen_write_cstrlen(utf8flag, "%s", left);
|
llen2 = screen_write_cstrlen(utf8flag, "%s", left);
|
||||||
if (llen2 < llen)
|
if (llen2 < llen)
|
||||||
llen = llen2;
|
llen = llen2;
|
||||||
|
|
||||||
right = status_replace(c, options_get_string(
|
right = status_replace(s, options_get_string(
|
||||||
&s->options, "status-right"), c->status_timer.tv_sec);
|
&s->options, "status-right"), c->status_timer.tv_sec);
|
||||||
rlen = options_get_number(&s->options, "status-right-length");
|
rlen = options_get_number(&s->options, "status-right-length");
|
||||||
rlen2 = screen_write_cstrlen(utf8flag, "%s", right);
|
rlen2 = screen_write_cstrlen(utf8flag, "%s", right);
|
||||||
@@ -318,17 +317,15 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
status_replace(struct client *c, const char *fmt, time_t t)
|
status_replace(struct session *s, const char *fmt, time_t t)
|
||||||
{
|
{
|
||||||
struct session *s = c->session;
|
|
||||||
struct winlink *wl = s->curw;
|
struct winlink *wl = s->curw;
|
||||||
static char out[BUFSIZ];
|
static char out[BUFSIZ];
|
||||||
char in[BUFSIZ], tmp[256], ch, *iptr, *optr, *ptr, *endptr;
|
char in[BUFSIZ], tmp[256], ch, *iptr, *optr, *ptr, *endptr;
|
||||||
char *savedptr; /* freed at end of each loop */
|
char *savedptr;
|
||||||
size_t len;
|
size_t len;
|
||||||
long n;
|
long n;
|
||||||
|
|
||||||
|
|
||||||
strftime(in, sizeof in, fmt, localtime(&t));
|
strftime(in, sizeof in, fmt, localtime(&t));
|
||||||
in[(sizeof in) - 1] = '\0';
|
in[(sizeof in) - 1] = '\0';
|
||||||
|
|
||||||
@@ -355,7 +352,7 @@ status_replace(struct client *c, const char *fmt, time_t t)
|
|||||||
switch (*iptr++) {
|
switch (*iptr++) {
|
||||||
case '(':
|
case '(':
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
ptr = status_job(c, &iptr);
|
ptr = status_replace_popen(&iptr);
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
break;
|
break;
|
||||||
savedptr = ptr;
|
savedptr = ptr;
|
||||||
@@ -364,7 +361,7 @@ status_replace(struct client *c, const char *fmt, time_t t)
|
|||||||
case 'H':
|
case 'H':
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
if (gethostname(tmp, sizeof tmp) != 0)
|
if (gethostname(tmp, sizeof tmp) != 0)
|
||||||
fatal("gethostname failed");
|
fatal("gethostname");
|
||||||
ptr = tmp;
|
ptr = tmp;
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
@@ -377,8 +374,8 @@ status_replace(struct client *c, const char *fmt, time_t t)
|
|||||||
case 'P':
|
case 'P':
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
xsnprintf(tmp, sizeof tmp, "%u",
|
xsnprintf(tmp, sizeof tmp, "%u",
|
||||||
window_pane_index(wl->window,
|
window_pane_index(wl->window,
|
||||||
wl->window->active));
|
wl->window->active));
|
||||||
ptr = tmp;
|
ptr = tmp;
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
@@ -437,12 +434,12 @@ status_replace(struct client *c, const char *fmt, time_t t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
status_job(struct client *c, char **iptr)
|
status_replace_popen(char **iptr)
|
||||||
{
|
{
|
||||||
struct job *job;
|
FILE *f;
|
||||||
char *cmd;
|
char *buf, *cmd, *ptr;
|
||||||
int lastesc;
|
int lastesc;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (**iptr == '\0')
|
if (**iptr == '\0')
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -451,6 +448,8 @@ status_job(struct client *c, char **iptr)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf = NULL;
|
||||||
|
|
||||||
cmd = xmalloc(strlen(*iptr) + 1);
|
cmd = xmalloc(strlen(*iptr) + 1);
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
@@ -465,44 +464,32 @@ status_job(struct client *c, char **iptr)
|
|||||||
lastesc = 0;
|
lastesc = 0;
|
||||||
cmd[len++] = **iptr;
|
cmd[len++] = **iptr;
|
||||||
}
|
}
|
||||||
if (**iptr == '\0') /* no terminating ) */ {
|
if (**iptr == '\0') /* no terminating ) */
|
||||||
xfree(cmd);
|
goto out;
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
(*iptr)++; /* skip final ) */
|
(*iptr)++; /* skip final ) */
|
||||||
cmd[len] = '\0';
|
cmd[len] = '\0';
|
||||||
|
|
||||||
job = job_get(&c->status_jobs, cmd);
|
if ((f = popen(cmd, "r")) == NULL)
|
||||||
if (job == NULL) {
|
goto out;
|
||||||
job = job_add(&c->status_jobs,
|
|
||||||
JOB_PERSIST, c, cmd, status_job_callback, xfree, NULL);
|
if ((buf = fgetln(f, &len)) == NULL) {
|
||||||
job_run(job);
|
pclose(f);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
if (job->data == NULL)
|
if (buf[len - 1] == '\n') {
|
||||||
return (xstrdup(""));
|
buf[len - 1] = '\0';
|
||||||
return (xstrdup(job->data));
|
buf = xstrdup(buf);
|
||||||
}
|
} else {
|
||||||
|
ptr = xmalloc(len + 1);
|
||||||
|
memcpy(ptr, buf, len);
|
||||||
|
ptr[len] = '\0';
|
||||||
|
buf = ptr;
|
||||||
|
}
|
||||||
|
pclose(f);
|
||||||
|
|
||||||
void
|
out:
|
||||||
status_job_callback(struct job *job)
|
xfree(cmd);
|
||||||
{
|
return (buf);
|
||||||
char *buf;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = BUFFER_USED(job->out);
|
|
||||||
buf = xmalloc(len + 1);
|
|
||||||
if (len != 0)
|
|
||||||
buffer_read(job->out, buf, len);
|
|
||||||
buf[len] = '\0';
|
|
||||||
buf[strcspn(buf, "\n")] = '\0';
|
|
||||||
|
|
||||||
if (job->data != NULL)
|
|
||||||
xfree(job->data);
|
|
||||||
else
|
|
||||||
server_redraw_client(job->client);
|
|
||||||
job->data = xstrdup(buf);
|
|
||||||
|
|
||||||
xfree(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@@ -529,7 +516,7 @@ status_print(struct session *s, struct winlink *wl, struct grid_cell *gc)
|
|||||||
gc->attr = attr;
|
gc->attr = attr;
|
||||||
|
|
||||||
flag = ' ';
|
flag = ' ';
|
||||||
if (wl == TAILQ_FIRST(&s->lastw))
|
if (wl == SLIST_FIRST(&s->lastw))
|
||||||
flag = '-';
|
flag = '-';
|
||||||
if (wl == s->curw) {
|
if (wl == s->curw) {
|
||||||
fg = options_get_number(oo, "window-status-current-fg");
|
fg = options_get_number(oo, "window-status-current-fg");
|
||||||
@@ -578,7 +565,7 @@ status_message_set(struct client *c, const char *fmt, ...)
|
|||||||
tv.tv_usec = (delay % 1000) * 1000L;
|
tv.tv_usec = (delay % 1000) * 1000L;
|
||||||
|
|
||||||
if (gettimeofday(&c->message_timer, NULL) != 0)
|
if (gettimeofday(&c->message_timer, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday");
|
||||||
timeradd(&c->message_timer, &tv, &c->message_timer);
|
timeradd(&c->message_timer, &tv, &c->message_timer);
|
||||||
|
|
||||||
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
|
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
|
||||||
@@ -686,6 +673,8 @@ status_prompt_clear(struct client *c)
|
|||||||
xfree(c->prompt_string);
|
xfree(c->prompt_string);
|
||||||
c->prompt_string = NULL;
|
c->prompt_string = NULL;
|
||||||
|
|
||||||
|
if (c->prompt_flags & PROMPT_HIDDEN)
|
||||||
|
memset(c->prompt_buffer, 0, strlen(c->prompt_buffer));
|
||||||
xfree(c->prompt_buffer);
|
xfree(c->prompt_buffer);
|
||||||
c->prompt_buffer = NULL;
|
c->prompt_buffer = NULL;
|
||||||
|
|
||||||
@@ -750,17 +739,26 @@ status_prompt_redraw(struct client *c)
|
|||||||
left--;
|
left--;
|
||||||
size = left;
|
size = left;
|
||||||
}
|
}
|
||||||
screen_write_puts(
|
if (c->prompt_flags & PROMPT_HIDDEN)
|
||||||
&ctx, &gc, "%.*s", (int) left, c->prompt_buffer + off);
|
size = 0;
|
||||||
|
else {
|
||||||
|
screen_write_puts(&ctx, &gc,
|
||||||
|
"%.*s", (int) left, c->prompt_buffer + off);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = len + size; i < c->tty.sx; i++)
|
for (i = len + size; i < c->tty.sx; i++)
|
||||||
screen_write_putc(&ctx, &gc, ' ');
|
screen_write_putc(&ctx, &gc, ' ');
|
||||||
|
|
||||||
/* Draw a fake cursor. */
|
/* Draw a fake cursor. */
|
||||||
ch = ' ';
|
ch = ' ';
|
||||||
screen_write_cursormove(&ctx, len + c->prompt_index - off, 0);
|
if (c->prompt_flags & PROMPT_HIDDEN)
|
||||||
if (c->prompt_index < strlen(c->prompt_buffer))
|
screen_write_cursormove(&ctx, len, 0);
|
||||||
ch = c->prompt_buffer[c->prompt_index];
|
else {
|
||||||
|
screen_write_cursormove(&ctx,
|
||||||
|
len + c->prompt_index - off, 0);
|
||||||
|
if (c->prompt_index < strlen(c->prompt_buffer))
|
||||||
|
ch = c->prompt_buffer[c->prompt_index];
|
||||||
|
}
|
||||||
gc.attr ^= GRID_ATTR_REVERSE;
|
gc.attr ^= GRID_ATTR_REVERSE;
|
||||||
screen_write_putc(&ctx, &gc, ch);
|
screen_write_putc(&ctx, &gc, ch);
|
||||||
}
|
}
|
||||||
@@ -892,8 +890,13 @@ status_prompt_key(struct client *c, int key)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MODEKEYEDIT_HISTORYUP:
|
case MODEKEYEDIT_HISTORYUP:
|
||||||
|
if (server_locked)
|
||||||
|
break;
|
||||||
|
|
||||||
if (ARRAY_LENGTH(&c->prompt_hdata) == 0)
|
if (ARRAY_LENGTH(&c->prompt_hdata) == 0)
|
||||||
break;
|
break;
|
||||||
|
if (c->prompt_flags & PROMPT_HIDDEN)
|
||||||
|
memset(c->prompt_buffer, 0, strlen(c->prompt_buffer));
|
||||||
xfree(c->prompt_buffer);
|
xfree(c->prompt_buffer);
|
||||||
|
|
||||||
c->prompt_buffer = xstrdup(ARRAY_ITEM(&c->prompt_hdata,
|
c->prompt_buffer = xstrdup(ARRAY_ITEM(&c->prompt_hdata,
|
||||||
@@ -905,6 +908,11 @@ status_prompt_key(struct client *c, int key)
|
|||||||
c->flags |= CLIENT_STATUS;
|
c->flags |= CLIENT_STATUS;
|
||||||
break;
|
break;
|
||||||
case MODEKEYEDIT_HISTORYDOWN:
|
case MODEKEYEDIT_HISTORYDOWN:
|
||||||
|
if (server_locked)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (c->prompt_flags & PROMPT_HIDDEN)
|
||||||
|
memset(c->prompt_buffer, 0, strlen(c->prompt_buffer));
|
||||||
xfree(c->prompt_buffer);
|
xfree(c->prompt_buffer);
|
||||||
|
|
||||||
if (c->prompt_hindex != 0) {
|
if (c->prompt_hindex != 0) {
|
||||||
@@ -995,6 +1003,9 @@ status_prompt_key(struct client *c, int key)
|
|||||||
void
|
void
|
||||||
status_prompt_add_history(struct client *c)
|
status_prompt_add_history(struct client *c)
|
||||||
{
|
{
|
||||||
|
if (server_locked)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ARRAY_LENGTH(&c->prompt_hdata) > 0 &&
|
if (ARRAY_LENGTH(&c->prompt_hdata) > 0 &&
|
||||||
strcmp(ARRAY_LAST(&c->prompt_hdata), c->prompt_buffer) == 0)
|
strcmp(ARRAY_LAST(&c->prompt_hdata), c->prompt_buffer) == 0)
|
||||||
return;
|
return;
|
||||||
|
|||||||
289
tmux.1
289
tmux.1
@@ -1,4 +1,4 @@
|
|||||||
.\" $Id: tmux.1,v 1.199 2009-11-04 22:46:25 tcunha Exp $
|
.\" $Id: tmux.1,v 1.168 2009-09-19 18:53:01 tcunha Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
.\"
|
.\"
|
||||||
@@ -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: November 3 2009 $
|
.Dd $Mdocdate: September 18 2009 $
|
||||||
.Dt TMUX 1
|
.Dt TMUX 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -23,8 +23,7 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm tmux
|
.Nm tmux
|
||||||
.Bk -words
|
.Bk -words
|
||||||
.Op Fl 28lquv
|
.Op Fl 28dlqUuv
|
||||||
.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
|
||||||
.Op Fl S Ar socket-path
|
.Op Fl S Ar socket-path
|
||||||
@@ -102,15 +101,10 @@ to assume the terminal supports 256 colours.
|
|||||||
Like
|
Like
|
||||||
.Fl 2 ,
|
.Fl 2 ,
|
||||||
but indicates that the terminal supports 88 colours.
|
but indicates that the terminal supports 88 colours.
|
||||||
.It Fl c Ar shell-command
|
.It Fl d
|
||||||
Execute
|
Force
|
||||||
.Ar shell-command
|
|
||||||
using the default shell.
|
|
||||||
If necessary, the
|
|
||||||
.Nm
|
.Nm
|
||||||
server will be started to retrieve the
|
to assume the terminal supports default colours.
|
||||||
.Ic default-shell
|
|
||||||
option.
|
|
||||||
.It Fl f Ar file
|
.It Fl f Ar file
|
||||||
Specify an alternative configuration file.
|
Specify an alternative configuration file.
|
||||||
By default,
|
By default,
|
||||||
@@ -160,6 +154,8 @@ If
|
|||||||
is specified, the default socket directory is not used and any
|
is specified, the default socket directory is not used and any
|
||||||
.Fl L
|
.Fl L
|
||||||
flag is ignored.
|
flag is ignored.
|
||||||
|
.It Fl U
|
||||||
|
Unlock the server.
|
||||||
.It Fl u
|
.It Fl u
|
||||||
.Nm
|
.Nm
|
||||||
attempts to guess if the terminal is likely to support UTF-8 by checking the
|
attempts to guess if the terminal is likely to support UTF-8 by checking the
|
||||||
@@ -282,7 +278,7 @@ pattern.
|
|||||||
If a single match is found, it is used as the target session; multiple matches
|
If a single match is found, it is used as the target session; multiple matches
|
||||||
produce an error.
|
produce an error.
|
||||||
If a session is omitted, the current session is used if available; if no
|
If a session is omitted, the current session is used if available; if no
|
||||||
current session is available, the most recently used is chosen.
|
current session is available, the most recently created is chosen.
|
||||||
.Pp
|
.Pp
|
||||||
.Ar target-window
|
.Ar target-window
|
||||||
specifies a window in the form
|
specifies a window in the form
|
||||||
@@ -341,6 +337,8 @@ rename-session -tfirst newname
|
|||||||
set-window-option -t:0 monitor-activity on
|
set-window-option -t:0 monitor-activity on
|
||||||
|
|
||||||
new-window ; split-window -d
|
new-window ; split-window -d
|
||||||
|
|
||||||
|
bind-key D detach-client \e\; lock-server
|
||||||
.Ed
|
.Ed
|
||||||
.Sh CLIENTS AND SESSIONS
|
.Sh CLIENTS AND SESSIONS
|
||||||
The following commands are available:
|
The following commands are available:
|
||||||
@@ -388,24 +386,10 @@ 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 Xo Ic lock-client
|
|
||||||
.Op Fl t Ar target-client
|
|
||||||
.Xc
|
|
||||||
Lock
|
|
||||||
.Ar target-client ,
|
|
||||||
see the
|
|
||||||
.Ic lock-server
|
|
||||||
command.
|
|
||||||
.It Xo Ic lock-session
|
|
||||||
.Op Fl t Ar target-session
|
|
||||||
.Xc
|
|
||||||
Lock all clients attached to
|
|
||||||
.Ar target-session .
|
|
||||||
.It Xo Ic new-session
|
.It Xo Ic new-session
|
||||||
.Op Fl d
|
.Op Fl d
|
||||||
.Op Fl n Ar window-name
|
.Op Fl n Ar window-name
|
||||||
.Op Fl s Ar session-name
|
.Op Fl s Ar session-name
|
||||||
.Op Fl t Ar target-session
|
|
||||||
.Op Ar command
|
.Op Ar command
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic new )
|
.D1 (alias: Ic new )
|
||||||
@@ -422,26 +406,6 @@ are the name of and command to execute in the initial window.
|
|||||||
If run from a terminal, any
|
If run from a terminal, any
|
||||||
.Xr termios 4
|
.Xr termios 4
|
||||||
special characters are saved and used for new windows in the new session.
|
special characters are saved and used for new windows in the new session.
|
||||||
.Pp
|
|
||||||
If
|
|
||||||
.Fl t
|
|
||||||
is given, the new session is
|
|
||||||
.Em grouped
|
|
||||||
with
|
|
||||||
.Ar target-session .
|
|
||||||
This means they share the same set of windows - all windows from
|
|
||||||
.Ar target-session
|
|
||||||
are linked to the new session and any subsequent new windows or windows being
|
|
||||||
closed are applied to both sessions.
|
|
||||||
The current and previous window and any session options remain independent and
|
|
||||||
either session may be killed without affecting the other.
|
|
||||||
Giving
|
|
||||||
.Fl n
|
|
||||||
or
|
|
||||||
.Ar command
|
|
||||||
are invalid if
|
|
||||||
.Fl t
|
|
||||||
is used.
|
|
||||||
.It Ic refresh-client Op Fl t Ar target-client
|
.It Ic refresh-client Op Fl t Ar target-client
|
||||||
.D1 (alias: Ic refresh )
|
.D1 (alias: Ic refresh )
|
||||||
Refresh the current client if bound to a key, or a single client if one is given
|
Refresh the current client if bound to a key, or a single client if one is given
|
||||||
@@ -491,6 +455,12 @@ The others are:
|
|||||||
This is entered when a command which produces output, such as
|
This is entered when a command which produces output, such as
|
||||||
.Ic list-keys ,
|
.Ic list-keys ,
|
||||||
is executed from a key binding.
|
is executed from a key binding.
|
||||||
|
.It Em scroll mode
|
||||||
|
This is entered with the
|
||||||
|
.Ic scroll-mode
|
||||||
|
command (bound to
|
||||||
|
.Ql =
|
||||||
|
by default) and permits the window history buffer to be inspected.
|
||||||
.It Em copy mode
|
.It Em copy mode
|
||||||
This permits a section of a window or its history to be copied to a
|
This permits a section of a window or its history to be copied to a
|
||||||
.Em paste buffer
|
.Em paste buffer
|
||||||
@@ -498,7 +468,7 @@ for later insertion into another window.
|
|||||||
This mode is entered with the
|
This mode is entered with the
|
||||||
.Ic copy-mode
|
.Ic copy-mode
|
||||||
command, bound to
|
command, bound to
|
||||||
.Ql \&[
|
.Ql [
|
||||||
by default.
|
by default.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
@@ -507,7 +477,7 @@ The keys available depend on whether emacs or vi mode is selected
|
|||||||
.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 "FunctionXXXXXXXXXXXX" "viXXXXXXXXX" "emacs" -offset indent
|
.Bl -column "FunctionXXXXXXXXXXXX" "viXXXXXX" "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 "Clear selection" Ta "Escape" Ta "C-g"
|
.It Li "Clear selection" Ta "Escape" Ta "C-g"
|
||||||
@@ -515,24 +485,17 @@ The following keys are supported as appropriate for the mode:
|
|||||||
.It Li "Cursor down" Ta "j" Ta "Down"
|
.It Li "Cursor down" Ta "j" Ta "Down"
|
||||||
.It Li "Cursor left" Ta "h" Ta "Left"
|
.It Li "Cursor left" Ta "h" Ta "Left"
|
||||||
.It Li "Cursor right" Ta "l" Ta "Right"
|
.It Li "Cursor right" Ta "l" Ta "Right"
|
||||||
.It Li "Cursor to bottom line" Ta "L" Ta ""
|
|
||||||
.It Li "Cursor to middle line" Ta "M" Ta "M-r"
|
|
||||||
.It Li "Cursor to top line" Ta "H" Ta "M-R"
|
|
||||||
.It Li "Cursor up" Ta "k" Ta "Up"
|
.It Li "Cursor up" Ta "k" Ta "Up"
|
||||||
.It Li "Delete entire line" Ta "d" Ta "C-u"
|
.It Li "Delete entire line" Ta "d" Ta "C-u"
|
||||||
.It Li "Delete to end of line" Ta "D" Ta "C-k"
|
.It Li "Delete to end of line" Ta "D" Ta "C-k"
|
||||||
.It Li "End of line" Ta "$" Ta "C-e"
|
.It Li "End of line" Ta "$" Ta "C-e"
|
||||||
.It Li "Goto line" Ta ":" Ta "g"
|
.It Li "Goto line" Ta "g" Ta "g"
|
||||||
.It Li "Half page down" Ta "C-d" Ta "M-Down"
|
|
||||||
.It Li "Half page up" Ta "C-u" Ta "M-Up"
|
|
||||||
.It Li "Next page" Ta "C-f" Ta "Page down"
|
.It Li "Next page" Ta "C-f" Ta "Page down"
|
||||||
.It Li "Next word" Ta "w" Ta "M-f"
|
.It Li "Next word" Ta "w" Ta "M-f"
|
||||||
.It Li "Paste buffer" Ta "p" Ta "C-y"
|
.It Li "Paste buffer" Ta "p" Ta "C-y"
|
||||||
.It Li "Previous page" Ta "C-b" Ta "Page up"
|
.It Li "Previous page" Ta "C-u" Ta "Page up"
|
||||||
.It Li "Previous word" Ta "b" Ta "M-b"
|
.It Li "Previous word" Ta "b" Ta "M-b"
|
||||||
.It Li "Quit mode" Ta "q" Ta "Escape"
|
.It Li "Quit mode" Ta "q" Ta "Escape"
|
||||||
.It Li "Scroll down" Ta "C-Down or J" Ta "C-Down"
|
|
||||||
.It Li "Scroll up" Ta "C-Up or K" Ta "C-Up"
|
|
||||||
.It Li "Search again" Ta "n" Ta "n"
|
.It Li "Search again" Ta "n" Ta "n"
|
||||||
.It Li "Search backward" Ta "?" Ta "C-r"
|
.It Li "Search backward" Ta "?" Ta "C-r"
|
||||||
.It Li "Search forward" Ta "/" Ta "C-s"
|
.It Li "Search forward" Ta "/" Ta "C-s"
|
||||||
@@ -555,7 +518,7 @@ command) or in output mode; and
|
|||||||
.Em vi-copy
|
.Em vi-copy
|
||||||
and
|
and
|
||||||
.Em emacs-copy
|
.Em emacs-copy
|
||||||
used in copy mode.
|
used in copy and scroll modes.
|
||||||
The tables may be viewed with the
|
The tables may be viewed with the
|
||||||
.Ic list-keys
|
.Ic list-keys
|
||||||
command and keys modified or removed with
|
command and keys modified or removed with
|
||||||
@@ -576,6 +539,16 @@ Enter copy mode.
|
|||||||
The
|
The
|
||||||
.Fl u
|
.Fl u
|
||||||
option scrolls one page up.
|
option scrolls one page up.
|
||||||
|
.It Xo Ic scroll-mode
|
||||||
|
.Op Fl u
|
||||||
|
.Op Fl t Ar target-pane
|
||||||
|
.Xc
|
||||||
|
Enter scroll mode.
|
||||||
|
The
|
||||||
|
.Fl u
|
||||||
|
has the same meaning as in the
|
||||||
|
.Ic copy-mode
|
||||||
|
command.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Each window displayed by
|
Each window displayed by
|
||||||
@@ -723,7 +696,7 @@ to
|
|||||||
keys.
|
keys.
|
||||||
.It Ic down-pane Op Fl t Ar target-pane
|
.It Ic down-pane Op Fl t Ar target-pane
|
||||||
.D1 (alias: Ic downp )
|
.D1 (alias: Ic downp )
|
||||||
Change the active pane to the next pane (higher index).
|
Move down a pane.
|
||||||
.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
|
||||||
@@ -738,17 +711,10 @@ If only one window is matched, it'll be automatically selected, otherwise a
|
|||||||
choice list is shown.
|
choice list is shown.
|
||||||
This command only works from inside
|
This command only works from inside
|
||||||
.Nm .
|
.Nm .
|
||||||
.It Xo Ic kill-pane
|
.It Ic kill-pane Op Fl t Ar target-pane
|
||||||
.Op Fl a
|
|
||||||
.Op Fl t Ar target-pane
|
|
||||||
.Xc
|
|
||||||
.D1 (alias: Ic killp )
|
.D1 (alias: Ic killp )
|
||||||
Destroy the given pane.
|
Destroy the given pane.
|
||||||
If no panes remain in the containing window, it is also destroyed.
|
If no panes remain in the containing window, it is also destroyed.
|
||||||
The
|
|
||||||
.Fl a
|
|
||||||
option kills all but the pane given with
|
|
||||||
.Fl t .
|
|
||||||
.It Ic kill-window Op Fl t Ar target-window
|
.It Ic kill-window Op Fl t Ar target-window
|
||||||
.D1 (alias: Ic killw )
|
.D1 (alias: Ic killw )
|
||||||
Kill the current window or the window at
|
Kill the current window or the window at
|
||||||
@@ -783,10 +749,6 @@ exists, it is killed, otherwise an error is generated.
|
|||||||
If
|
If
|
||||||
.Fl d
|
.Fl d
|
||||||
is given, the newly linked window is not selected.
|
is given, the newly linked window is not selected.
|
||||||
.It Ic list-panes Op Fl t Ar target-window
|
|
||||||
.D1 (alias: Ic lsp )
|
|
||||||
List the panes in the current window or in
|
|
||||||
.Ar target-window .
|
|
||||||
.It Ic list-windows Op Fl t Ar target-session
|
.It Ic list-windows Op Fl t Ar target-session
|
||||||
.D1 (alias: Ic lsw )
|
.D1 (alias: Ic lsw )
|
||||||
List windows in the current session or in
|
List windows in the current session or in
|
||||||
@@ -848,30 +810,6 @@ Move to the next window in the session.
|
|||||||
If
|
If
|
||||||
.Fl a
|
.Fl a
|
||||||
is used, move to the next window with a bell, activity or content alert.
|
is used, move to the next window with a bell, activity or content alert.
|
||||||
.It Xo Ic pipe-pane
|
|
||||||
.Op Fl o
|
|
||||||
.Op Fl t Ar target-pane
|
|
||||||
.Op Ar command
|
|
||||||
.Xc
|
|
||||||
.D1 (alias: Ic pipep )
|
|
||||||
Pipe any output sent by the program in
|
|
||||||
.Ar target-pane
|
|
||||||
to a shell command.
|
|
||||||
A pane may only be piped to one command at a time, any existing pipe is
|
|
||||||
closed before
|
|
||||||
.Ar command
|
|
||||||
is executed.
|
|
||||||
If no
|
|
||||||
.Ar command
|
|
||||||
is given, the current pipe (if any) is closed.
|
|
||||||
.Pp
|
|
||||||
The
|
|
||||||
.Fl o
|
|
||||||
option only opens a new pipe if no previous pipe exists, allowing a pipe to
|
|
||||||
be toggled with a single key, for example:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
bind-key C-p pipe-pane -o 'cat >>~/output'
|
|
||||||
.Ed
|
|
||||||
.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
|
||||||
@@ -1018,52 +956,9 @@ 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
|
.It Ic up-pane Op Fl t Ar target-pane
|
||||||
.D1 (alias: Ic upp )
|
.D1 (alias: Ic upp )
|
||||||
Change the active pane to the previous pane (lower index).
|
Move up a pane.
|
||||||
.El
|
.El
|
||||||
.Sh KEY BINDINGS
|
.Sh KEY BINDINGS
|
||||||
.Nm
|
|
||||||
allows a command to be bound to most keys, with or without a prefix key.
|
|
||||||
When specifying keys, most represent themselves (for example
|
|
||||||
.Ql A
|
|
||||||
to
|
|
||||||
.Ql Z ) .
|
|
||||||
Ctrl keys may be prefixed with
|
|
||||||
.Ql C-
|
|
||||||
or
|
|
||||||
.Ql ^ ,
|
|
||||||
and Alt (meta) with
|
|
||||||
.Ql M- .
|
|
||||||
In addition, the following special key names are accepted:
|
|
||||||
.Em BSpace ,
|
|
||||||
.Em BTab ,
|
|
||||||
.Em DC
|
|
||||||
(Delete),
|
|
||||||
.Em End ,
|
|
||||||
.Em Enter ,
|
|
||||||
.Em Escape ,
|
|
||||||
.Em F1
|
|
||||||
to
|
|
||||||
.Em F20 ,
|
|
||||||
.Em Home ,
|
|
||||||
.Em IC
|
|
||||||
(Insert),
|
|
||||||
.Em NPage
|
|
||||||
(Page Up),
|
|
||||||
.Em PPage
|
|
||||||
(Page Down),
|
|
||||||
.Em Space ,
|
|
||||||
and
|
|
||||||
.Em Tab .
|
|
||||||
Note that to bind the
|
|
||||||
.Ql \&"
|
|
||||||
or
|
|
||||||
.Ql '
|
|
||||||
keys, quotation marks are necessary, for example:
|
|
||||||
.Bd -literal -offset indent
|
|
||||||
bind-key '"' split-window
|
|
||||||
bind-key "'" select-prompt
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
Commands related to key bindings are as follows:
|
Commands related to key bindings are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Xo Ic bind-key
|
.It Xo Ic bind-key
|
||||||
@@ -1076,6 +971,14 @@ Bind key
|
|||||||
.Ar key
|
.Ar key
|
||||||
to
|
to
|
||||||
.Ar command .
|
.Ar command .
|
||||||
|
Keys may be specified prefixed with
|
||||||
|
.Ql C-
|
||||||
|
or
|
||||||
|
.Ql ^
|
||||||
|
for Ctrl keys, or
|
||||||
|
.Ql M-
|
||||||
|
for Alt (meta) keys.
|
||||||
|
.Pp
|
||||||
By default (without
|
By default (without
|
||||||
.Fl t )
|
.Fl t )
|
||||||
the primary key bindings are modified (those normally activated with the prefix
|
the primary key bindings are modified (those normally activated with the prefix
|
||||||
@@ -1145,7 +1048,6 @@ characters.
|
|||||||
All arguments are sent sequentially from first to last.
|
All arguments are sent sequentially from first to last.
|
||||||
.It Ic send-prefix Op Fl t Ar target-pane
|
.It Ic send-prefix Op Fl t Ar target-pane
|
||||||
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.
|
|
||||||
.It Xo Ic unbind-key
|
.It Xo Ic unbind-key
|
||||||
.Op Fl cn
|
.Op Fl cn
|
||||||
.Op Fl t Ar key-table
|
.Op Fl t Ar key-table
|
||||||
@@ -1310,33 +1212,17 @@ Set the maximum number of lines held in window history.
|
|||||||
This setting applies only to new windows - existing window histories are not
|
This setting applies only to new windows - existing window histories are not
|
||||||
resized and retain the limit at the point they were created.
|
resized and retain the limit at the point they were created.
|
||||||
.It Ic lock-after-time Ar number
|
.It Ic lock-after-time Ar number
|
||||||
Lock the session (like the
|
Lock the server after
|
||||||
.Ic lock-session
|
|
||||||
command) after
|
|
||||||
.Ar number
|
.Ar number
|
||||||
seconds of inactivity, or the entire server (all sessions) if the
|
seconds of inactivity.
|
||||||
.Ic lock-server
|
The default is off (set to 0).
|
||||||
option is set.
|
This has no effect as a session option; it must be set as a global option using
|
||||||
The default is not to lock (set to 0).
|
.Fl g .
|
||||||
.It Ic lock-command Ar command
|
When passwords are entered incorrectly,
|
||||||
Command to run when locking each client.
|
.Nm
|
||||||
The default is to run
|
follows the behaviour of
|
||||||
.Xr lock 1
|
.Xr login 1
|
||||||
with
|
and ignores further password attempts for an increasing timeout.
|
||||||
.Fl np .
|
|
||||||
.It Xo Ic lock-server
|
|
||||||
.Op Ic on | off
|
|
||||||
.Xc
|
|
||||||
If this option is
|
|
||||||
.Ic on
|
|
||||||
(the default),
|
|
||||||
instead of each session locking individually as each has been
|
|
||||||
idle for
|
|
||||||
.Ic lock-after-time ,
|
|
||||||
the entire server will lock after
|
|
||||||
.Em all
|
|
||||||
sessions would have locked.
|
|
||||||
This has no effect as a session option; it must be set as a global option.
|
|
||||||
.It Ic message-attr Ar attributes
|
.It Ic message-attr Ar attributes
|
||||||
Set status line message attributes, where
|
Set status line message attributes, where
|
||||||
.Ar attributes
|
.Ar attributes
|
||||||
@@ -1372,19 +1258,8 @@ from the 256-colour palette, or
|
|||||||
.Ic default .
|
.Ic default .
|
||||||
.It Ic message-fg Ar colour
|
.It Ic message-fg Ar colour
|
||||||
Set status line message foreground colour.
|
Set status line message foreground colour.
|
||||||
.It Xo Ic mouse-select-pane
|
.It Ic prefix Ar key
|
||||||
.Op Ic on | off
|
Set the current prefix key.
|
||||||
.Xc
|
|
||||||
If on,
|
|
||||||
.Nm
|
|
||||||
captures the mouse and when a window is split into multiple panes the mouse may
|
|
||||||
be used to select the current pane.
|
|
||||||
The mouse click is also passed through to the application as normal.
|
|
||||||
.It Ic prefix Ar keys
|
|
||||||
Set the keys accepted as a prefix key.
|
|
||||||
.Ar keys
|
|
||||||
is a comma-separated list of key names, each of which individually behave as
|
|
||||||
the prefix key.
|
|
||||||
.It Ic repeat-time Ar time
|
.It Ic repeat-time Ar time
|
||||||
Allow multiple commands to be entered without pressing the prefix-key again
|
Allow multiple commands to be entered without pressing the prefix-key again
|
||||||
in the specified
|
in the specified
|
||||||
@@ -1473,31 +1348,22 @@ may contain any of the following special character sequences:
|
|||||||
The #(command) form executes
|
The #(command) form executes
|
||||||
.Ql command
|
.Ql command
|
||||||
as a shell command and inserts the first line of its output.
|
as a shell command and inserts the first line of its output.
|
||||||
Note that shell commands are only executed once at the interval specified by
|
|
||||||
the
|
|
||||||
.Ic status-interval
|
|
||||||
option: if the status line is redrawn in the meantime, the previous result is
|
|
||||||
used.
|
|
||||||
.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
|
||||||
.Ql fg=colour
|
.Ql fg=colour
|
||||||
to set the foreground colour,
|
to set the foreground colour,
|
||||||
.Ql bg=colour
|
.Ql bg=colour
|
||||||
to set the background colour, the name of one of the attributes (listed under the
|
to set the background colour, or one of the attributes described under the
|
||||||
.Ic message-attr
|
.Ic message-attr
|
||||||
option) to turn an attribute on, or an attribute prefixed with
|
option.
|
||||||
.Ql no
|
|
||||||
to turn one off, for example
|
|
||||||
.Ic nobright .
|
|
||||||
Examples are:
|
Examples are:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
#(sysctl vm.loadavg)
|
#(sysctl vm.loadavg)
|
||||||
#[fg=yellow,bold]#(apm -l)%%#[default] [#S]
|
#[fg=yellow,bold]#(apm -l)%%#[default] [#S]
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Where appropriate, special character sequences may be prefixed with a number to
|
Where appropriate, these may be prefixed with a number to specify the maximum
|
||||||
specify the maximum length, for example
|
length, for example
|
||||||
.Ql #24T .
|
.Ql #24T .
|
||||||
.Pp
|
.Pp
|
||||||
By default, UTF-8 in
|
By default, UTF-8 in
|
||||||
@@ -1714,7 +1580,7 @@ Set window modes foreground colour.
|
|||||||
.It Xo Ic mode-keys
|
.It Xo Ic mode-keys
|
||||||
.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 scroll, copy and choice modes.
|
||||||
Key bindings default to emacs.
|
Key bindings default to emacs.
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic mode-mouse
|
.It Xo Ic mode-mouse
|
||||||
@@ -1749,11 +1615,6 @@ The window may be reactivated with the
|
|||||||
.Ic respawn-window
|
.Ic respawn-window
|
||||||
command.
|
command.
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic synchronize-panes
|
|
||||||
.Op Ic on | off
|
|
||||||
.Xc
|
|
||||||
Duplicate input to any pane to all other panes in the same window, except
|
|
||||||
for panes that are not in output mode.
|
|
||||||
.It Xo Ic utf8
|
.It Xo Ic utf8
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
@@ -1840,7 +1701,6 @@ Commands to alter and view the environment are:
|
|||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Ar name Op Ar value
|
.Ar name Op Ar value
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic setenv )
|
|
||||||
Set or unset an environment variable.
|
Set or unset an environment variable.
|
||||||
If
|
If
|
||||||
.Fl g
|
.Fl g
|
||||||
@@ -1857,7 +1717,6 @@ new process.
|
|||||||
.Op Fl g
|
.Op Fl g
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Xc
|
.Xc
|
||||||
.D1 (alias: Ic showenv )
|
|
||||||
Display the environment for
|
Display the environment for
|
||||||
.Ar target-session
|
.Ar target-session
|
||||||
or the global environment with
|
or the global environment with
|
||||||
@@ -2099,21 +1958,25 @@ if
|
|||||||
returns success.
|
returns success.
|
||||||
.It Ic lock-server
|
.It Ic lock-server
|
||||||
.D1 (alias: Ic lock )
|
.D1 (alias: Ic lock )
|
||||||
Lock each client individually by running the command specified by the
|
Lock the server until a password is entered.
|
||||||
.Ic lock-command
|
|
||||||
option.
|
|
||||||
.It Ic run-shell Ar command
|
|
||||||
.D1 (alias: Ic run )
|
|
||||||
Execute
|
|
||||||
.Ar command
|
|
||||||
in the background without creating a window.
|
|
||||||
After the command finishes, any output to stdout is displayed in output mode.
|
|
||||||
If
|
|
||||||
.Ar 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 )
|
||||||
Show server information and terminal details.
|
Show server information and terminal details.
|
||||||
|
.It Xo Ic set-password
|
||||||
|
.Op Fl c
|
||||||
|
.Ar password
|
||||||
|
.Xc
|
||||||
|
.D1 (alias: Ic pass )
|
||||||
|
Set the server password.
|
||||||
|
If the
|
||||||
|
.Fl c
|
||||||
|
option is given, a pre-encrypted password may be specified.
|
||||||
|
By default, the password is blank, thus any entered password will be accepted
|
||||||
|
when unlocking the server (see the
|
||||||
|
.Ic lock-server
|
||||||
|
command).
|
||||||
|
To prevent variable expansion when an encrypted password is read from a
|
||||||
|
configuration file, enclose it in single quotes (').
|
||||||
.El
|
.El
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width "/etc/tmux.confXXX" -compact
|
.Bl -tag -width "/etc/tmux.confXXX" -compact
|
||||||
|
|||||||
246
tmux.c
246
tmux.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.c,v 1.184 2009-11-04 23:09:09 tcunha Exp $ */
|
/* $Id: tmux.c,v 1.172 2009-09-19 18:53:01 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -29,8 +29,14 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
#if defined(DEBUG) && defined(__OpenBSD__)
|
#ifdef DEBUG
|
||||||
extern char *malloc_options;
|
/* DragonFly uses an OpenBSD-like malloc() since 1.6 */
|
||||||
|
#if defined(__OpenBSD__) || defined(__DragonFly__)
|
||||||
|
const char *malloc_options = "AFGJPX";
|
||||||
|
#endif
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
const char *_malloc_options = "AJX";
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
volatile sig_atomic_t sigwinch;
|
volatile sig_atomic_t sigwinch;
|
||||||
@@ -45,6 +51,13 @@ 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;
|
||||||
|
|
||||||
|
int server_locked;
|
||||||
|
struct passwd *server_locked_pw;
|
||||||
|
u_int password_failures;
|
||||||
|
time_t password_backoff;
|
||||||
|
char *server_password;
|
||||||
|
time_t server_activity;
|
||||||
|
|
||||||
int debug_level;
|
int debug_level;
|
||||||
int be_quiet;
|
int be_quiet;
|
||||||
time_t start_time;
|
time_t start_time;
|
||||||
@@ -52,10 +65,10 @@ char *socket_path;
|
|||||||
int login_shell;
|
int login_shell;
|
||||||
|
|
||||||
__dead void usage(void);
|
__dead void usage(void);
|
||||||
void fill_session(struct msg_command_data *);
|
|
||||||
char *makesockpath(const char *);
|
char *makesockpath(const char *);
|
||||||
int dispatch_imsg(struct imsgbuf *, const char *, int *);
|
int prepare_unlock(enum msgtype *, void **, size_t *, int);
|
||||||
__dead void shell_exec(const char *, const char *);
|
int prepare_cmd(enum msgtype *, void **, size_t *, int, char **);
|
||||||
|
int dispatch_imsg(struct client_ctx *, int *);
|
||||||
|
|
||||||
#ifndef HAVE_PROGNAME
|
#ifndef HAVE_PROGNAME
|
||||||
char *__progname = (char *) "tmux";
|
char *__progname = (char *) "tmux";
|
||||||
@@ -65,7 +78,7 @@ __dead void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: %s [-28lquv] [-c shell-command] [-f file] [-L socket-name]\n"
|
"usage: %s [-28dlqUuv] [-f file] [-L socket-name]\n"
|
||||||
" [-S socket-path] [command [flags]]\n",
|
" [-S socket-path] [command [flags]]\n",
|
||||||
__progname);
|
__progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -218,44 +231,6 @@ areshell(const char *shell)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
fill_session(struct msg_command_data *data)
|
|
||||||
{
|
|
||||||
char *env, *ptr1, *ptr2, buf[256];
|
|
||||||
size_t len;
|
|
||||||
const char *errstr;
|
|
||||||
long long ll;
|
|
||||||
|
|
||||||
data->pid = -1;
|
|
||||||
if ((env = getenv("TMUX")) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((ptr2 = strrchr(env, ',')) == NULL || ptr2 == env)
|
|
||||||
return;
|
|
||||||
for (ptr1 = ptr2 - 1; ptr1 > env && *ptr1 != ','; ptr1--)
|
|
||||||
;
|
|
||||||
if (*ptr1 != ',')
|
|
||||||
return;
|
|
||||||
ptr1++;
|
|
||||||
ptr2++;
|
|
||||||
|
|
||||||
len = ptr2 - ptr1 - 1;
|
|
||||||
if (len > (sizeof buf) - 1)
|
|
||||||
return;
|
|
||||||
memcpy(buf, ptr1, len);
|
|
||||||
buf[len] = '\0';
|
|
||||||
|
|
||||||
ll = strtonum(buf, 0, LONG_MAX, &errstr);
|
|
||||||
if (errstr != NULL)
|
|
||||||
return;
|
|
||||||
data->pid = ll;
|
|
||||||
|
|
||||||
ll = strtonum(ptr2, 0, UINT_MAX, &errstr);
|
|
||||||
if (errstr != NULL)
|
|
||||||
return;
|
|
||||||
data->idx = ll;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
makesockpath(const char *label)
|
makesockpath(const char *label)
|
||||||
{
|
{
|
||||||
@@ -284,32 +259,76 @@ makesockpath(const char *label)
|
|||||||
return (path);
|
return (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
prepare_unlock(enum msgtype *msg, void **buf, size_t *len, int argc)
|
||||||
|
{
|
||||||
|
static struct msg_unlock_data unlockdata;
|
||||||
|
char *pass;
|
||||||
|
|
||||||
|
if (argc != 0) {
|
||||||
|
log_warnx("can't specify a command when unlocking");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pass = getpass("Password:")) == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if (strlen(pass) >= sizeof unlockdata.pass) {
|
||||||
|
log_warnx("password too long");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(unlockdata.pass, pass, sizeof unlockdata.pass);
|
||||||
|
memset(pass, 0, strlen(pass));
|
||||||
|
|
||||||
|
*buf = &unlockdata;
|
||||||
|
*len = sizeof unlockdata;
|
||||||
|
|
||||||
|
*msg = MSG_UNLOCK;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
prepare_cmd(enum msgtype *msg, void **buf, size_t *len, int argc, char **argv)
|
||||||
|
{
|
||||||
|
static struct msg_command_data cmddata;
|
||||||
|
|
||||||
|
client_fill_session(&cmddata);
|
||||||
|
|
||||||
|
cmddata.argc = argc;
|
||||||
|
if (cmd_pack_argv(argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
|
||||||
|
log_warnx("command too long");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*buf = &cmddata;
|
||||||
|
*len = sizeof cmddata;
|
||||||
|
|
||||||
|
*msg = MSG_COMMAND;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
struct client_ctx cctx;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
enum msgtype msg;
|
enum msgtype msg;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct options *so, *wo;
|
struct options *so, *wo;
|
||||||
struct keylist *keylist;
|
char *s, *path, *label, *home, *cause, **var;
|
||||||
struct imsgbuf *ibuf;
|
char cwd[MAXPATHLEN];
|
||||||
struct msg_command_data cmddata;
|
|
||||||
char *s, *shellcmd, *path, *label, *home, *cause;
|
|
||||||
char cwd[MAXPATHLEN], **var;
|
|
||||||
void *buf;
|
void *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
int nfds, retcode, opt, flags, cmdflags = 0;
|
int retcode, opt, flags, unlock, cmdflags = 0;
|
||||||
|
int nfds;
|
||||||
|
|
||||||
#if defined(DEBUG) && defined(__OpenBSD__)
|
unlock = flags = 0;
|
||||||
malloc_options = (char *) "AFGJPX";
|
label = path = NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
flags = 0;
|
|
||||||
shellcmd = label = path = NULL;
|
|
||||||
login_shell = (**argv == '-');
|
login_shell = (**argv == '-');
|
||||||
while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUv")) != -1) {
|
while ((opt = getopt(argc, argv, "28df:lL:qS:uUv")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case '2':
|
case '2':
|
||||||
flags |= IDENTIFY_256COLOURS;
|
flags |= IDENTIFY_256COLOURS;
|
||||||
@@ -319,10 +338,8 @@ main(int argc, char **argv)
|
|||||||
flags |= IDENTIFY_88COLOURS;
|
flags |= IDENTIFY_88COLOURS;
|
||||||
flags &= ~IDENTIFY_256COLOURS;
|
flags &= ~IDENTIFY_256COLOURS;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'd':
|
||||||
if (shellcmd != NULL)
|
flags |= IDENTIFY_HASDEFAULTS;
|
||||||
xfree(shellcmd);
|
|
||||||
shellcmd = xstrdup(optarg);
|
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
if (cfg_file != NULL)
|
if (cfg_file != NULL)
|
||||||
@@ -348,19 +365,19 @@ main(int argc, char **argv)
|
|||||||
case 'u':
|
case 'u':
|
||||||
flags |= IDENTIFY_UTF8;
|
flags |= IDENTIFY_UTF8;
|
||||||
break;
|
break;
|
||||||
|
case 'U':
|
||||||
|
unlock = 1;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
debug_level++;
|
debug_level++;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
if (shellcmd != NULL && argc != 0)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
log_open_tty(debug_level);
|
log_open_tty(debug_level);
|
||||||
siginit();
|
siginit();
|
||||||
|
|
||||||
@@ -398,12 +415,10 @@ main(int argc, char **argv)
|
|||||||
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);
|
||||||
options_set_number(so, "lock-after-time", 0);
|
options_set_number(so, "lock-after-time", 0);
|
||||||
options_set_string(so, "lock-command", "lock -np");
|
|
||||||
options_set_number(so, "lock-server", 1);
|
|
||||||
options_set_number(so, "message-attr", 0);
|
options_set_number(so, "message-attr", 0);
|
||||||
options_set_number(so, "message-bg", 3);
|
options_set_number(so, "message-bg", 3);
|
||||||
options_set_number(so, "message-fg", 0);
|
options_set_number(so, "message-fg", 0);
|
||||||
options_set_number(so, "mouse-select-pane", 0);
|
options_set_number(so, "prefix", '\002');
|
||||||
options_set_number(so, "repeat-time", 500);
|
options_set_number(so, "repeat-time", 500);
|
||||||
options_set_number(so, "set-remain-on-exit", 0);
|
options_set_number(so, "set-remain-on-exit", 0);
|
||||||
options_set_number(so, "set-titles", 0);
|
options_set_number(so, "set-titles", 0);
|
||||||
@@ -433,11 +448,6 @@ main(int argc, char **argv)
|
|||||||
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);
|
||||||
|
|
||||||
keylist = xmalloc(sizeof *keylist);
|
|
||||||
ARRAY_INIT(keylist);
|
|
||||||
ARRAY_ADD(keylist, '\002');
|
|
||||||
options_set_data(so, "prefix", keylist, xfree);
|
|
||||||
|
|
||||||
options_init(&global_w_options, NULL);
|
options_init(&global_w_options, NULL);
|
||||||
wo = &global_w_options;
|
wo = &global_w_options;
|
||||||
options_set_number(wo, "aggressive-resize", 0);
|
options_set_number(wo, "aggressive-resize", 0);
|
||||||
@@ -463,7 +473,6 @@ main(int argc, char **argv)
|
|||||||
options_set_number(wo, "window-status-fg", 8);
|
options_set_number(wo, "window-status-fg", 8);
|
||||||
options_set_number(wo, "xterm-keys", 0);
|
options_set_number(wo, "xterm-keys", 0);
|
||||||
options_set_number(wo, "remain-on-exit", 0);
|
options_set_number(wo, "remain-on-exit", 0);
|
||||||
options_set_number(wo, "synchronize-panes", 0);
|
|
||||||
|
|
||||||
if (flags & IDENTIFY_UTF8) {
|
if (flags & IDENTIFY_UTF8) {
|
||||||
options_set_number(so, "status-utf8", 1);
|
options_set_number(so, "status-utf8", 1);
|
||||||
@@ -509,27 +518,16 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
xfree(label);
|
xfree(label);
|
||||||
|
|
||||||
if (shellcmd != NULL) {
|
if (unlock) {
|
||||||
msg = MSG_SHELL;
|
if (prepare_unlock(&msg, &buf, &len, argc) != 0)
|
||||||
buf = NULL;
|
exit(1);
|
||||||
len = 0;
|
} else {
|
||||||
} else {
|
if (prepare_cmd(&msg, &buf, &len, argc, argv) != 0)
|
||||||
fill_session(&cmddata);
|
|
||||||
|
|
||||||
cmddata.argc = argc;
|
|
||||||
if (cmd_pack_argv(
|
|
||||||
argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
|
|
||||||
log_warnx("command too long");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
|
||||||
|
|
||||||
msg = MSG_COMMAND;
|
|
||||||
buf = &cmddata;
|
|
||||||
len = sizeof cmddata;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shellcmd != NULL)
|
if (unlock)
|
||||||
cmdflags |= CMD_STARTSERVER;
|
cmdflags &= ~CMD_STARTSERVER;
|
||||||
else if (argc == 0) /* new-session is the default */
|
else if (argc == 0) /* new-session is the default */
|
||||||
cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON;
|
cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON;
|
||||||
else {
|
else {
|
||||||
@@ -552,17 +550,19 @@ main(int argc, char **argv)
|
|||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ibuf = client_init(path, cmdflags, flags)) == NULL)
|
memset(&cctx, 0, sizeof cctx);
|
||||||
|
if (client_init(path, &cctx, cmdflags, flags) != 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
xfree(path);
|
xfree(path);
|
||||||
|
|
||||||
imsg_compose(ibuf, msg, PROTOCOL_VERSION, -1, -1, buf, len);
|
client_write_server(&cctx, msg, buf, len);
|
||||||
|
memset(buf, 0, len);
|
||||||
|
|
||||||
retcode = 0;
|
retcode = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
pfd.fd = ibuf->fd;
|
pfd.fd = cctx.ibuf.fd;
|
||||||
pfd.events = POLLIN;
|
pfd.events = POLLIN;
|
||||||
if (ibuf->w.queued != 0)
|
if (cctx.ibuf.w.queued != 0)
|
||||||
pfd.events |= POLLOUT;
|
pfd.events |= POLLOUT;
|
||||||
|
|
||||||
if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
|
if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
|
||||||
@@ -576,13 +576,13 @@ main(int argc, char **argv)
|
|||||||
if (pfd.revents & (POLLERR|POLLHUP|POLLNVAL))
|
if (pfd.revents & (POLLERR|POLLHUP|POLLNVAL))
|
||||||
fatalx("socket error");
|
fatalx("socket error");
|
||||||
|
|
||||||
if (pfd.revents & POLLIN) {
|
if (pfd.revents & POLLIN) {
|
||||||
if (dispatch_imsg(ibuf, shellcmd, &retcode) != 0)
|
if (dispatch_imsg(&cctx, &retcode) != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pfd.revents & POLLOUT) {
|
if (pfd.revents & POLLOUT) {
|
||||||
if (msgbuf_write(&ibuf->w) < 0)
|
if (msgbuf_write(&cctx.ibuf.w) < 0)
|
||||||
fatalx("msgbuf_write failed");
|
fatalx("msgbuf_write failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -594,18 +594,17 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dispatch_imsg(struct imsgbuf *ibuf, const char *shellcmd, int *retcode)
|
dispatch_imsg(struct client_ctx *cctx, int *retcode)
|
||||||
{
|
{
|
||||||
struct imsg imsg;
|
struct imsg imsg;
|
||||||
ssize_t n, datalen;
|
ssize_t n, datalen;
|
||||||
struct msg_print_data printdata;
|
struct msg_print_data printdata;
|
||||||
struct msg_shell_data shelldata;
|
|
||||||
|
|
||||||
if ((n = imsg_read(ibuf)) == -1 || n == 0)
|
if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0)
|
||||||
fatalx("imsg_read failed");
|
fatalx("imsg_read failed");
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((n = imsg_get(ibuf, &imsg)) == -1)
|
if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1)
|
||||||
fatalx("imsg_get failed");
|
fatalx("imsg_get failed");
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -633,7 +632,8 @@ dispatch_imsg(struct imsgbuf *ibuf, const char *shellcmd, int *retcode)
|
|||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
fatalx("bad MSG_READY size");
|
fatalx("bad MSG_READY size");
|
||||||
|
|
||||||
client_main(); /* doesn't return */
|
*retcode = client_main(cctx);
|
||||||
|
return (-1);
|
||||||
case MSG_VERSION:
|
case MSG_VERSION:
|
||||||
if (datalen != 0)
|
if (datalen != 0)
|
||||||
fatalx("bad MSG_VERSION size");
|
fatalx("bad MSG_VERSION size");
|
||||||
@@ -642,13 +642,6 @@ dispatch_imsg(struct imsgbuf *ibuf, const char *shellcmd, int *retcode)
|
|||||||
"server %u)", PROTOCOL_VERSION, imsg.hdr.peerid);
|
"server %u)", PROTOCOL_VERSION, imsg.hdr.peerid);
|
||||||
*retcode = 1;
|
*retcode = 1;
|
||||||
return (-1);
|
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';
|
|
||||||
|
|
||||||
shell_exec(shelldata.shell, shellcmd);
|
|
||||||
default:
|
default:
|
||||||
fatalx("unexpected message");
|
fatalx("unexpected message");
|
||||||
}
|
}
|
||||||
@@ -656,26 +649,3 @@ dispatch_imsg(struct imsgbuf *ibuf, const char *shellcmd, int *retcode)
|
|||||||
imsg_free(&imsg);
|
imsg_free(&imsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__dead void
|
|
||||||
shell_exec(const char *shell, const char *shellcmd)
|
|
||||||
{
|
|
||||||
const char *shellname, *ptr;
|
|
||||||
char *argv0;
|
|
||||||
|
|
||||||
sigreset();
|
|
||||||
|
|
||||||
ptr = strrchr(shell, '/');
|
|
||||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
|
||||||
shellname = ptr + 1;
|
|
||||||
else
|
|
||||||
shellname = shell;
|
|
||||||
if (login_shell)
|
|
||||||
xasprintf(&argv0, "-%s", shellname);
|
|
||||||
else
|
|
||||||
xasprintf(&argv0, "%s", shellname);
|
|
||||||
setenv("SHELL", shell, 1);
|
|
||||||
|
|
||||||
execl(shell, argv0, "-c", shellcmd, (char *) NULL);
|
|
||||||
fatal("execl failed");
|
|
||||||
}
|
|
||||||
|
|||||||
403
tmux.h
403
tmux.h
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.h,v 1.496 2009-11-04 22:46:25 tcunha Exp $ */
|
/* $Id: tmux.h,v 1.443 2009-09-16 12:36:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define PROTOCOL_VERSION 5
|
#define PROTOCOL_VERSION 1
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@@ -58,14 +58,11 @@ extern char **environ;
|
|||||||
#define NAME_INTERVAL 500
|
#define NAME_INTERVAL 500
|
||||||
|
|
||||||
/* Escape timer period, in milliseconds. */
|
/* Escape timer period, in milliseconds. */
|
||||||
#define ESCAPE_PERIOD 500
|
#define ESCAPE_PERIOD 250
|
||||||
|
|
||||||
/* Maximum poll timeout (when attached). */
|
/* Maximum poll timeout (when attached). */
|
||||||
#define POLL_TIMEOUT 50
|
#define POLL_TIMEOUT 50
|
||||||
|
|
||||||
/* Maximum data to buffer for output before suspending reading from panes. */
|
|
||||||
#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
|
||||||
* PROTOCOL_VERSION if any of these change!
|
* PROTOCOL_VERSION if any of these change!
|
||||||
@@ -164,23 +161,23 @@ enum key_code {
|
|||||||
KEYC_LEFT,
|
KEYC_LEFT,
|
||||||
KEYC_RIGHT,
|
KEYC_RIGHT,
|
||||||
|
|
||||||
/* Numeric keypad. */
|
/* Numeric keypad. Numbered from top-left, KPY_X. */
|
||||||
KEYC_KP_SLASH,
|
KEYC_KP0_1,
|
||||||
KEYC_KP_STAR,
|
KEYC_KP0_2,
|
||||||
KEYC_KP_MINUS,
|
KEYC_KP0_3,
|
||||||
KEYC_KP_SEVEN,
|
KEYC_KP1_0,
|
||||||
KEYC_KP_EIGHT,
|
KEYC_KP1_1,
|
||||||
KEYC_KP_NINE,
|
KEYC_KP1_2,
|
||||||
KEYC_KP_PLUS,
|
KEYC_KP1_3,
|
||||||
KEYC_KP_FOUR,
|
KEYC_KP2_0,
|
||||||
KEYC_KP_FIVE,
|
KEYC_KP2_1,
|
||||||
KEYC_KP_SIX,
|
KEYC_KP2_2,
|
||||||
KEYC_KP_ONE,
|
KEYC_KP3_0,
|
||||||
KEYC_KP_TWO,
|
KEYC_KP3_1,
|
||||||
KEYC_KP_THREE,
|
KEYC_KP3_2,
|
||||||
KEYC_KP_ENTER,
|
KEYC_KP3_3,
|
||||||
KEYC_KP_ZERO,
|
KEYC_KP4_0,
|
||||||
KEYC_KP_PERIOD,
|
KEYC_KP4_2,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Termcap codes. */
|
/* Termcap codes. */
|
||||||
@@ -195,15 +192,9 @@ enum tty_code_code {
|
|||||||
TTYC_CNORM, /* cursor_normal, ve */
|
TTYC_CNORM, /* cursor_normal, ve */
|
||||||
TTYC_COLORS, /* max_colors, Co */
|
TTYC_COLORS, /* max_colors, Co */
|
||||||
TTYC_CSR, /* change_scroll_region, cs */
|
TTYC_CSR, /* change_scroll_region, cs */
|
||||||
TTYC_CUB, /* parm_left_cursor, LE */
|
|
||||||
TTYC_CUB1, /* cursor_left, le */
|
|
||||||
TTYC_CUD, /* parm_down_cursor, DO */
|
TTYC_CUD, /* parm_down_cursor, DO */
|
||||||
TTYC_CUD1, /* cursor_down, do */
|
TTYC_CUD1, /* cursor_down, do */
|
||||||
TTYC_CUF, /* parm_right_cursor, RI */
|
|
||||||
TTYC_CUF1, /* cursor_right, nd */
|
|
||||||
TTYC_CUP, /* cursor_address, cm */
|
TTYC_CUP, /* cursor_address, cm */
|
||||||
TTYC_CUU, /* parm_up_cursor, UP */
|
|
||||||
TTYC_CUU1, /* cursor_up, up */
|
|
||||||
TTYC_DCH, /* parm_dch, DC */
|
TTYC_DCH, /* parm_dch, DC */
|
||||||
TTYC_DCH1, /* delete_character, dc */
|
TTYC_DCH1, /* delete_character, dc */
|
||||||
TTYC_DIM, /* enter_dim_mode, mh */
|
TTYC_DIM, /* enter_dim_mode, mh */
|
||||||
@@ -212,8 +203,6 @@ enum tty_code_code {
|
|||||||
TTYC_EL, /* clr_eol, ce */
|
TTYC_EL, /* clr_eol, ce */
|
||||||
TTYC_EL1, /* clr_bol, cb */
|
TTYC_EL1, /* clr_bol, cb */
|
||||||
TTYC_ENACS, /* ena_acs, eA */
|
TTYC_ENACS, /* ena_acs, eA */
|
||||||
TTYC_HOME, /* cursor_home, ho */
|
|
||||||
TTYC_HPA, /* column_address, ch */
|
|
||||||
TTYC_ICH, /* parm_ich, IC */
|
TTYC_ICH, /* parm_ich, IC */
|
||||||
TTYC_ICH1, /* insert_character, ic */
|
TTYC_ICH1, /* insert_character, ic */
|
||||||
TTYC_IL, /* parm_insert_line, IL */
|
TTYC_IL, /* parm_insert_line, IL */
|
||||||
@@ -227,26 +216,8 @@ enum tty_code_code {
|
|||||||
TTYC_KCUD1, /* key_down, kd */
|
TTYC_KCUD1, /* key_down, kd */
|
||||||
TTYC_KCUF1, /* key_right, kr */
|
TTYC_KCUF1, /* key_right, kr */
|
||||||
TTYC_KCUU1, /* key_up, ku */
|
TTYC_KCUU1, /* key_up, ku */
|
||||||
TTYC_KDC2,
|
|
||||||
TTYC_KDC3,
|
|
||||||
TTYC_KDC4,
|
|
||||||
TTYC_KDC5,
|
|
||||||
TTYC_KDC6,
|
|
||||||
TTYC_KDC7,
|
|
||||||
TTYC_KDCH1, /* key_dc, kD */
|
TTYC_KDCH1, /* key_dc, kD */
|
||||||
TTYC_KDN2,
|
|
||||||
TTYC_KDN3,
|
|
||||||
TTYC_KDN4,
|
|
||||||
TTYC_KDN5,
|
|
||||||
TTYC_KDN6,
|
|
||||||
TTYC_KDN7,
|
|
||||||
TTYC_KEND, /* key_end, ke */
|
TTYC_KEND, /* key_end, ke */
|
||||||
TTYC_KEND2,
|
|
||||||
TTYC_KEND3,
|
|
||||||
TTYC_KEND4,
|
|
||||||
TTYC_KEND5,
|
|
||||||
TTYC_KEND6,
|
|
||||||
TTYC_KEND7,
|
|
||||||
TTYC_KF1, /* key_f1, k1 */
|
TTYC_KF1, /* key_f1, k1 */
|
||||||
TTYC_KF10, /* key_f10, k; */
|
TTYC_KF10, /* key_f10, k; */
|
||||||
TTYC_KF11, /* key_f11, F1 */
|
TTYC_KF11, /* key_f11, F1 */
|
||||||
@@ -258,8 +229,8 @@ enum tty_code_code {
|
|||||||
TTYC_KF17, /* key_f17, F7 */
|
TTYC_KF17, /* key_f17, F7 */
|
||||||
TTYC_KF18, /* key_f18, F8 */
|
TTYC_KF18, /* key_f18, F8 */
|
||||||
TTYC_KF19, /* key_f19, F9 */
|
TTYC_KF19, /* key_f19, F9 */
|
||||||
TTYC_KF2, /* key_f2, k2 */
|
|
||||||
TTYC_KF20, /* key_f20, F10 */
|
TTYC_KF20, /* key_f20, F10 */
|
||||||
|
TTYC_KF2, /* key_f2, k2 */
|
||||||
TTYC_KF3, /* key_f3, k3 */
|
TTYC_KF3, /* key_f3, k3 */
|
||||||
TTYC_KF4, /* key_f4, k4 */
|
TTYC_KF4, /* key_f4, k4 */
|
||||||
TTYC_KF5, /* key_f5, k5 */
|
TTYC_KF5, /* key_f5, k5 */
|
||||||
@@ -267,53 +238,11 @@ enum tty_code_code {
|
|||||||
TTYC_KF7, /* key_f7, k7 */
|
TTYC_KF7, /* key_f7, k7 */
|
||||||
TTYC_KF8, /* key_f8, k8 */
|
TTYC_KF8, /* key_f8, k8 */
|
||||||
TTYC_KF9, /* key_f9, k9 */
|
TTYC_KF9, /* key_f9, k9 */
|
||||||
TTYC_KHOM2,
|
|
||||||
TTYC_KHOM3,
|
|
||||||
TTYC_KHOM4,
|
|
||||||
TTYC_KHOM5,
|
|
||||||
TTYC_KHOM6,
|
|
||||||
TTYC_KHOM7,
|
|
||||||
TTYC_KHOME, /* key_home, kh */
|
TTYC_KHOME, /* key_home, kh */
|
||||||
TTYC_KIC2,
|
|
||||||
TTYC_KIC3,
|
|
||||||
TTYC_KIC4,
|
|
||||||
TTYC_KIC5,
|
|
||||||
TTYC_KIC6,
|
|
||||||
TTYC_KIC7,
|
|
||||||
TTYC_KICH1, /* key_ic, kI */
|
TTYC_KICH1, /* key_ic, kI */
|
||||||
TTYC_KLFT2,
|
|
||||||
TTYC_KLFT3,
|
|
||||||
TTYC_KLFT4,
|
|
||||||
TTYC_KLFT5,
|
|
||||||
TTYC_KLFT6,
|
|
||||||
TTYC_KLFT7,
|
|
||||||
TTYC_KMOUS, /* key_mouse, Km */
|
TTYC_KMOUS, /* key_mouse, Km */
|
||||||
TTYC_KNP, /* key_npage, kN */
|
TTYC_KNP, /* key_npage, kN */
|
||||||
TTYC_KNXT2,
|
|
||||||
TTYC_KNXT3,
|
|
||||||
TTYC_KNXT4,
|
|
||||||
TTYC_KNXT5,
|
|
||||||
TTYC_KNXT6,
|
|
||||||
TTYC_KNXT7,
|
|
||||||
TTYC_KPP, /* key_ppage, kP */
|
TTYC_KPP, /* key_ppage, kP */
|
||||||
TTYC_KPRV2,
|
|
||||||
TTYC_KPRV3,
|
|
||||||
TTYC_KPRV4,
|
|
||||||
TTYC_KPRV5,
|
|
||||||
TTYC_KPRV6,
|
|
||||||
TTYC_KPRV7,
|
|
||||||
TTYC_KRIT2,
|
|
||||||
TTYC_KRIT3,
|
|
||||||
TTYC_KRIT4,
|
|
||||||
TTYC_KRIT5,
|
|
||||||
TTYC_KRIT6,
|
|
||||||
TTYC_KRIT7,
|
|
||||||
TTYC_KUP2,
|
|
||||||
TTYC_KUP3,
|
|
||||||
TTYC_KUP4,
|
|
||||||
TTYC_KUP5,
|
|
||||||
TTYC_KUP6,
|
|
||||||
TTYC_KUP7,
|
|
||||||
TTYC_OP, /* orig_pair, op */
|
TTYC_OP, /* orig_pair, op */
|
||||||
TTYC_REV, /* enter_reverse_mode, mr */
|
TTYC_REV, /* enter_reverse_mode, mr */
|
||||||
TTYC_RI, /* scroll_reverse, sr */
|
TTYC_RI, /* scroll_reverse, sr */
|
||||||
@@ -330,7 +259,6 @@ enum tty_code_code {
|
|||||||
TTYC_SMKX, /* keypad_xmit, ks */
|
TTYC_SMKX, /* keypad_xmit, ks */
|
||||||
TTYC_SMSO, /* enter_standout_mode, so */
|
TTYC_SMSO, /* enter_standout_mode, so */
|
||||||
TTYC_SMUL, /* enter_underline_mode, us */
|
TTYC_SMUL, /* enter_underline_mode, us */
|
||||||
TTYC_VPA, /* row_address, cv */
|
|
||||||
TTYC_XENL, /* eat_newline_glitch, xn */
|
TTYC_XENL, /* eat_newline_glitch, xn */
|
||||||
};
|
};
|
||||||
#define NTTYCODE (TTYC_XENL + 1)
|
#define NTTYCODE (TTYC_XENL + 1)
|
||||||
@@ -374,12 +302,10 @@ enum msgtype {
|
|||||||
MSG_RESIZE,
|
MSG_RESIZE,
|
||||||
MSG_SHUTDOWN,
|
MSG_SHUTDOWN,
|
||||||
MSG_SUSPEND,
|
MSG_SUSPEND,
|
||||||
|
MSG_UNLOCK,
|
||||||
MSG_VERSION,
|
MSG_VERSION,
|
||||||
MSG_WAKEUP,
|
MSG_WAKEUP,
|
||||||
MSG_ENVIRON,
|
MSG_ENVIRON
|
||||||
MSG_UNLOCK,
|
|
||||||
MSG_LOCK,
|
|
||||||
MSG_SHELL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -400,6 +326,8 @@ struct msg_command_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct msg_identify_data {
|
struct msg_identify_data {
|
||||||
|
char tty[TTY_NAME_MAX];
|
||||||
|
|
||||||
char cwd[MAXPATHLEN];
|
char cwd[MAXPATHLEN];
|
||||||
|
|
||||||
char term[TERMINAL_LENGTH];
|
char term[TERMINAL_LENGTH];
|
||||||
@@ -407,21 +335,26 @@ struct msg_identify_data {
|
|||||||
#define IDENTIFY_UTF8 0x1
|
#define IDENTIFY_UTF8 0x1
|
||||||
#define IDENTIFY_256COLOURS 0x2
|
#define IDENTIFY_256COLOURS 0x2
|
||||||
#define IDENTIFY_88COLOURS 0x4
|
#define IDENTIFY_88COLOURS 0x4
|
||||||
|
#define IDENTIFY_HASDEFAULTS 0x8
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
u_int sx;
|
||||||
|
u_int sy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msg_lock_data {
|
struct msg_resize_data {
|
||||||
char cmd[COMMAND_LENGTH];
|
u_int sx;
|
||||||
|
u_int sy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msg_unlock_data {
|
||||||
|
char pass[PASS_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msg_environ_data {
|
struct msg_environ_data {
|
||||||
char var[ENVIRON_LENGTH];
|
char var[ENVIRON_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msg_shell_data {
|
|
||||||
char shell[MAXPATHLEN];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Mode key commands. */
|
/* Mode key commands. */
|
||||||
enum mode_key_cmd {
|
enum mode_key_cmd {
|
||||||
MODEKEY_NONE,
|
MODEKEY_NONE,
|
||||||
@@ -456,7 +389,6 @@ enum mode_key_cmd {
|
|||||||
|
|
||||||
/* Copy keys. */
|
/* Copy keys. */
|
||||||
MODEKEYCOPY_BACKTOINDENTATION,
|
MODEKEYCOPY_BACKTOINDENTATION,
|
||||||
MODEKEYCOPY_BOTTOMLINE,
|
|
||||||
MODEKEYCOPY_CANCEL,
|
MODEKEYCOPY_CANCEL,
|
||||||
MODEKEYCOPY_CLEARSELECTION,
|
MODEKEYCOPY_CLEARSELECTION,
|
||||||
MODEKEYCOPY_COPYSELECTION,
|
MODEKEYCOPY_COPYSELECTION,
|
||||||
@@ -466,20 +398,16 @@ enum mode_key_cmd {
|
|||||||
MODEKEYCOPY_HALFPAGEDOWN,
|
MODEKEYCOPY_HALFPAGEDOWN,
|
||||||
MODEKEYCOPY_HALFPAGEUP,
|
MODEKEYCOPY_HALFPAGEUP,
|
||||||
MODEKEYCOPY_LEFT,
|
MODEKEYCOPY_LEFT,
|
||||||
MODEKEYCOPY_MIDDLELINE,
|
|
||||||
MODEKEYCOPY_NEXTPAGE,
|
MODEKEYCOPY_NEXTPAGE,
|
||||||
MODEKEYCOPY_NEXTWORD,
|
MODEKEYCOPY_NEXTWORD,
|
||||||
MODEKEYCOPY_PREVIOUSPAGE,
|
MODEKEYCOPY_PREVIOUSPAGE,
|
||||||
MODEKEYCOPY_PREVIOUSWORD,
|
MODEKEYCOPY_PREVIOUSWORD,
|
||||||
MODEKEYCOPY_RIGHT,
|
MODEKEYCOPY_RIGHT,
|
||||||
MODEKEYCOPY_SCROLLDOWN,
|
|
||||||
MODEKEYCOPY_SCROLLUP,
|
|
||||||
MODEKEYCOPY_SEARCHAGAIN,
|
MODEKEYCOPY_SEARCHAGAIN,
|
||||||
MODEKEYCOPY_SEARCHDOWN,
|
MODEKEYCOPY_SEARCHDOWN,
|
||||||
MODEKEYCOPY_SEARCHUP,
|
MODEKEYCOPY_SEARCHUP,
|
||||||
MODEKEYCOPY_STARTOFLINE,
|
MODEKEYCOPY_STARTOFLINE,
|
||||||
MODEKEYCOPY_STARTSELECTION,
|
MODEKEYCOPY_STARTSELECTION,
|
||||||
MODEKEYCOPY_TOPLINE,
|
|
||||||
MODEKEYCOPY_UP,
|
MODEKEYCOPY_UP,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -537,23 +465,6 @@ struct mode_key_table {
|
|||||||
#define MODE_KKEYPAD 0x8
|
#define MODE_KKEYPAD 0x8
|
||||||
#define MODE_MOUSE 0x10
|
#define MODE_MOUSE 0x10
|
||||||
|
|
||||||
/*
|
|
||||||
* A single UTF-8 character.
|
|
||||||
*
|
|
||||||
* The data member in this must be UTF8_SIZE to allow screen_write_copy to
|
|
||||||
* reinject stored UTF-8 data back into screen_write_cell after combining (ugh
|
|
||||||
* XXX XXX).
|
|
||||||
*/
|
|
||||||
#define UTF8_SIZE 9
|
|
||||||
struct utf8_data {
|
|
||||||
u_char data[UTF8_SIZE];
|
|
||||||
|
|
||||||
size_t have;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
u_int width;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Grid output. */
|
/* Grid output. */
|
||||||
#if defined(DEBUG) && \
|
#if defined(DEBUG) && \
|
||||||
((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
|
((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
|
||||||
@@ -593,6 +504,7 @@ struct grid_cell {
|
|||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/* Grid cell UTF-8 data. Used instead of data in grid_cell for UTF-8 cells. */
|
/* Grid cell UTF-8 data. Used instead of data in grid_cell for UTF-8 cells. */
|
||||||
|
#define UTF8_SIZE 8
|
||||||
struct grid_utf8 {
|
struct grid_utf8 {
|
||||||
u_char width;
|
u_char width;
|
||||||
u_char data[UTF8_SIZE];
|
u_char data[UTF8_SIZE];
|
||||||
@@ -630,14 +542,13 @@ struct options_entry {
|
|||||||
enum {
|
enum {
|
||||||
OPTIONS_STRING,
|
OPTIONS_STRING,
|
||||||
OPTIONS_NUMBER,
|
OPTIONS_NUMBER,
|
||||||
OPTIONS_DATA,
|
OPTIONS_KEY,
|
||||||
} type;
|
} type;
|
||||||
|
union {
|
||||||
char *str;
|
char *string;
|
||||||
long long num;
|
long long number;
|
||||||
void *data;
|
int key;
|
||||||
|
} value;
|
||||||
void (*freefn)(void *);
|
|
||||||
|
|
||||||
SPLAY_ENTRY(options_entry) entry;
|
SPLAY_ENTRY(options_entry) entry;
|
||||||
};
|
};
|
||||||
@@ -647,34 +558,6 @@ struct options {
|
|||||||
struct options *parent;
|
struct options *parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Key list for prefix option. */
|
|
||||||
ARRAY_DECL(keylist, int);
|
|
||||||
|
|
||||||
/* Scheduled job. */
|
|
||||||
struct job {
|
|
||||||
char *cmd;
|
|
||||||
pid_t pid;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
struct client *client;
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
struct buffer *out;
|
|
||||||
|
|
||||||
void (*callbackfn)(struct job *);
|
|
||||||
void (*freefn)(void *);
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
int flags;
|
|
||||||
#define JOB_DONE 0x1
|
|
||||||
#define JOB_PERSIST 0x2 /* don't free after callback */
|
|
||||||
|
|
||||||
RB_ENTRY(job) entry;
|
|
||||||
SLIST_ENTRY(job) lentry;
|
|
||||||
};
|
|
||||||
RB_HEAD(jobs, job);
|
|
||||||
SLIST_HEAD(joblist, job);
|
|
||||||
|
|
||||||
/* Screen selection. */
|
/* Screen selection. */
|
||||||
struct screen_sel {
|
struct screen_sel {
|
||||||
int flag;
|
int flag;
|
||||||
@@ -749,7 +632,9 @@ struct input_ctx {
|
|||||||
#define STRING_APPLICATION 1
|
#define STRING_APPLICATION 1
|
||||||
#define STRING_NAME 2
|
#define STRING_NAME 2
|
||||||
|
|
||||||
struct utf8_data utf8data;
|
u_char utf8_buf[4];
|
||||||
|
u_int utf8_len;
|
||||||
|
u_int utf8_off;
|
||||||
|
|
||||||
u_char intermediate;
|
u_char intermediate;
|
||||||
void *(*state)(u_char, struct input_ctx *);
|
void *(*state)(u_char, struct input_ctx *);
|
||||||
@@ -764,14 +649,13 @@ struct input_ctx {
|
|||||||
*/
|
*/
|
||||||
struct client;
|
struct client;
|
||||||
struct window;
|
struct window;
|
||||||
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 client *, int);
|
void (*key)(struct window_pane *, struct client *, int);
|
||||||
void (*mouse)(struct window_pane *,
|
void (*mouse)(struct window_pane *,
|
||||||
struct client *, struct mouse_event *);
|
struct client *, u_char, u_char, u_char);
|
||||||
void (*timer)(struct window_pane *);
|
void (*timer)(struct window_pane *);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -801,10 +685,6 @@ struct window_pane {
|
|||||||
|
|
||||||
struct input_ctx ictx;
|
struct input_ctx ictx;
|
||||||
|
|
||||||
int pipe_fd;
|
|
||||||
struct buffer *pipe_buf;
|
|
||||||
size_t pipe_off;
|
|
||||||
|
|
||||||
struct screen *screen;
|
struct screen *screen;
|
||||||
struct screen base;
|
struct screen base;
|
||||||
|
|
||||||
@@ -854,10 +734,10 @@ struct winlink {
|
|||||||
struct window *window;
|
struct window *window;
|
||||||
|
|
||||||
RB_ENTRY(winlink) entry;
|
RB_ENTRY(winlink) entry;
|
||||||
TAILQ_ENTRY(winlink) sentry;
|
SLIST_ENTRY(winlink) sentry;
|
||||||
};
|
};
|
||||||
RB_HEAD(winlinks, winlink);
|
RB_HEAD(winlinks, winlink);
|
||||||
TAILQ_HEAD(winlink_stack, winlink);
|
SLIST_HEAD(winlink_stack, winlink);
|
||||||
|
|
||||||
/* Layout direction. */
|
/* Layout direction. */
|
||||||
enum layout_type {
|
enum layout_type {
|
||||||
@@ -891,6 +771,7 @@ struct layout_cell {
|
|||||||
struct paste_buffer {
|
struct paste_buffer {
|
||||||
char *data;
|
char *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
struct timeval tv;
|
||||||
};
|
};
|
||||||
ARRAY_DECL(paste_stack, struct paste_buffer *);
|
ARRAY_DECL(paste_stack, struct paste_buffer *);
|
||||||
|
|
||||||
@@ -911,18 +792,9 @@ struct session_alert {
|
|||||||
SLIST_ENTRY(session_alert) entry;
|
SLIST_ENTRY(session_alert) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct session_group {
|
|
||||||
TAILQ_HEAD(, session) sessions;
|
|
||||||
|
|
||||||
TAILQ_ENTRY(session_group) entry;
|
|
||||||
};
|
|
||||||
TAILQ_HEAD(session_groups, session_group);
|
|
||||||
|
|
||||||
struct session {
|
struct session {
|
||||||
char *name;
|
char *name;
|
||||||
|
struct timeval tv;
|
||||||
struct timeval creation_time;
|
|
||||||
struct timeval activity_time;
|
|
||||||
|
|
||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
@@ -946,8 +818,6 @@ struct session {
|
|||||||
struct environ environ;
|
struct environ environ;
|
||||||
|
|
||||||
int references;
|
int references;
|
||||||
|
|
||||||
TAILQ_ENTRY(session) gentry;
|
|
||||||
};
|
};
|
||||||
ARRAY_DECL(sessions, struct session *);
|
ARRAY_DECL(sessions, struct session *);
|
||||||
|
|
||||||
@@ -969,9 +839,10 @@ struct tty_term {
|
|||||||
|
|
||||||
struct tty_code codes[NTTYCODE];
|
struct tty_code codes[NTTYCODE];
|
||||||
|
|
||||||
#define TERM_256COLOURS 0x1
|
#define TERM_HASDEFAULTS 0x1
|
||||||
#define TERM_88COLOURS 0x2
|
#define TERM_256COLOURS 0x2
|
||||||
#define TERM_EARLYWRAP 0x4
|
#define TERM_88COLOURS 0x4
|
||||||
|
#define TERM_EARLYWRAP 0x8
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
SLIST_ENTRY(tty_term) entry;
|
SLIST_ENTRY(tty_term) entry;
|
||||||
@@ -1043,37 +914,21 @@ struct tty_ctx {
|
|||||||
|
|
||||||
u_int orupper;
|
u_int orupper;
|
||||||
u_int orlower;
|
u_int orlower;
|
||||||
|
|
||||||
/* Saved last cell on line. */
|
|
||||||
struct grid_cell last_cell;
|
|
||||||
struct grid_utf8 last_utf8;
|
|
||||||
u_int last_width;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Mouse input. */
|
|
||||||
struct mouse_event {
|
|
||||||
u_char b;
|
|
||||||
u_char x;
|
|
||||||
u_char y;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Client connection. */
|
/* Client connection. */
|
||||||
struct client {
|
struct client {
|
||||||
struct imsgbuf ibuf;
|
struct imsgbuf ibuf;
|
||||||
|
|
||||||
struct timeval creation_time;
|
|
||||||
struct timeval activity_time;
|
|
||||||
|
|
||||||
struct environ environ;
|
struct environ environ;
|
||||||
|
|
||||||
char *title;
|
char *title;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
|
|
||||||
struct tty tty;
|
struct tty tty;
|
||||||
|
struct timeval status_timer;
|
||||||
struct timeval repeat_timer;
|
struct timeval repeat_timer;
|
||||||
|
|
||||||
struct timeval status_timer;
|
|
||||||
struct jobs status_jobs;
|
|
||||||
struct screen status;
|
struct screen status;
|
||||||
|
|
||||||
#define CLIENT_TERMINAL 0x1
|
#define CLIENT_TERMINAL 0x1
|
||||||
@@ -1100,7 +955,8 @@ struct client {
|
|||||||
void (*prompt_freefn)(void *);
|
void (*prompt_freefn)(void *);
|
||||||
void *prompt_data;
|
void *prompt_data;
|
||||||
|
|
||||||
#define PROMPT_SINGLE 0x1
|
#define PROMPT_HIDDEN 0x1
|
||||||
|
#define PROMPT_SINGLE 0x2
|
||||||
int prompt_flags;
|
int prompt_flags;
|
||||||
|
|
||||||
u_int prompt_hindex;
|
u_int prompt_hindex;
|
||||||
@@ -1114,6 +970,19 @@ struct client {
|
|||||||
};
|
};
|
||||||
ARRAY_DECL(clients, struct client *);
|
ARRAY_DECL(clients, struct client *);
|
||||||
|
|
||||||
|
/* Client context. */
|
||||||
|
struct client_ctx {
|
||||||
|
struct imsgbuf ibuf;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CCTX_DETACH,
|
||||||
|
CCTX_EXIT,
|
||||||
|
CCTX_DIED,
|
||||||
|
CCTX_SHUTDOWN
|
||||||
|
} exittype;
|
||||||
|
const char *errstr;
|
||||||
|
};
|
||||||
|
|
||||||
/* Key/command line command. */
|
/* Key/command line command. */
|
||||||
struct cmd_ctx {
|
struct cmd_ctx {
|
||||||
/*
|
/*
|
||||||
@@ -1217,7 +1086,7 @@ struct set_option_entry {
|
|||||||
enum {
|
enum {
|
||||||
SET_OPTION_STRING,
|
SET_OPTION_STRING,
|
||||||
SET_OPTION_NUMBER,
|
SET_OPTION_NUMBER,
|
||||||
SET_OPTION_KEYS,
|
SET_OPTION_KEY,
|
||||||
SET_OPTION_COLOUR,
|
SET_OPTION_COLOUR,
|
||||||
SET_OPTION_ATTRIBUTES,
|
SET_OPTION_ATTRIBUTES,
|
||||||
SET_OPTION_FLAG,
|
SET_OPTION_FLAG,
|
||||||
@@ -1243,6 +1112,12 @@ 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 char *cfg_file;
|
extern char *cfg_file;
|
||||||
|
extern int server_locked;
|
||||||
|
extern struct passwd *server_locked_pw;
|
||||||
|
extern u_int password_failures;
|
||||||
|
extern time_t password_backoff;
|
||||||
|
extern char *server_password;
|
||||||
|
extern time_t server_activity;
|
||||||
extern int debug_level;
|
extern int debug_level;
|
||||||
extern int be_quiet;
|
extern int be_quiet;
|
||||||
extern time_t start_time;
|
extern time_t start_time;
|
||||||
@@ -1285,29 +1160,11 @@ void options_free(struct options *);
|
|||||||
struct options_entry *options_find1(struct options *, const char *);
|
struct options_entry *options_find1(struct options *, const char *);
|
||||||
struct options_entry *options_find(struct options *, const char *);
|
struct options_entry *options_find(struct options *, const char *);
|
||||||
void options_remove(struct options *, const char *);
|
void options_remove(struct options *, const char *);
|
||||||
struct options_entry *printflike3 options_set_string(
|
void printflike3 options_set_string(
|
||||||
struct options *, const char *, const char *, ...);
|
struct options *, const char *, const char *, ...);
|
||||||
char *options_get_string(struct options *, const char *);
|
char *options_get_string(struct options *, const char *);
|
||||||
struct options_entry *options_set_number(
|
void options_set_number(struct options *, const char *, long long);
|
||||||
struct options *, const char *, long long);
|
|
||||||
long long options_get_number(struct options *, const char *);
|
long long options_get_number(struct options *, const char *);
|
||||||
struct options_entry *options_set_data(
|
|
||||||
struct options *, const char *, void *, void (*)(void *));
|
|
||||||
void *options_get_data(struct options *, const char *);
|
|
||||||
|
|
||||||
/* job.c */
|
|
||||||
extern struct joblist all_jobs;
|
|
||||||
int job_cmp(struct job *, struct job *);
|
|
||||||
RB_PROTOTYPE(jobs, job, entry, job_cmp);
|
|
||||||
void job_tree_init(struct jobs *);
|
|
||||||
void job_tree_free(struct jobs *);
|
|
||||||
struct job *job_get(struct jobs *, const char *);
|
|
||||||
struct job *job_add(struct jobs *, int, struct client *,
|
|
||||||
const char *, void (*)(struct job *), void (*)(void *), void *);
|
|
||||||
void job_remove(struct jobs *, struct job *);
|
|
||||||
void job_free(struct job *);
|
|
||||||
int job_run(struct job *);
|
|
||||||
void job_kill(struct job *);
|
|
||||||
|
|
||||||
/* environ.c */
|
/* environ.c */
|
||||||
int environ_cmp(struct environ_entry *, struct environ_entry *);
|
int environ_cmp(struct environ_entry *, struct environ_entry *);
|
||||||
@@ -1322,24 +1179,21 @@ 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 *);
|
||||||
|
|
||||||
/* tty.c */
|
/* tty.c */
|
||||||
void tty_raw(struct tty *, const char *);
|
|
||||||
u_char tty_get_acs(struct tty *, u_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(struct tty *, u_int, u_int, u_int);
|
||||||
void tty_region(struct tty *, u_int, u_int);
|
void tty_cursor(struct tty *, u_int, u_int, u_int, u_int);
|
||||||
void tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int, u_int);
|
|
||||||
void tty_cursor(struct tty *, u_int, u_int);
|
|
||||||
void tty_putcode(struct tty *, enum tty_code_code);
|
void tty_putcode(struct tty *, enum tty_code_code);
|
||||||
void tty_putcode1(struct tty *, enum tty_code_code, int);
|
void tty_putcode1(struct tty *, enum tty_code_code, int);
|
||||||
void tty_putcode2(struct tty *, enum tty_code_code, int, int);
|
void tty_putcode2(struct tty *, enum tty_code_code, int, int);
|
||||||
void tty_puts(struct tty *, const char *);
|
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 *, char *);
|
||||||
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_detect_utf8(struct tty *);
|
||||||
void tty_set_title(struct tty *, const char *);
|
void tty_set_title(struct tty *, const char *);
|
||||||
void tty_update_mode(struct tty *, int);
|
void tty_update_mode(struct tty *, int);
|
||||||
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int);
|
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int);
|
||||||
@@ -1382,16 +1236,14 @@ int tty_keys_cmp(struct tty_key *, struct tty_key *);
|
|||||||
RB_PROTOTYPE(tty_keys, tty_key, entry, tty_keys_cmp);
|
RB_PROTOTYPE(tty_keys, tty_key, entry, tty_keys_cmp);
|
||||||
void tty_keys_init(struct tty *);
|
void tty_keys_init(struct tty *);
|
||||||
void tty_keys_free(struct tty *);
|
void tty_keys_free(struct tty *);
|
||||||
int tty_keys_next(struct tty *, int *, struct mouse_event *);
|
int tty_keys_next(struct tty *, int *, u_char *);
|
||||||
|
|
||||||
/* options-cmd.c */
|
/* options-cmd.c */
|
||||||
const char *set_option_print(
|
|
||||||
const struct set_option_entry *, struct options_entry *);
|
|
||||||
void set_option_string(struct cmd_ctx *,
|
void set_option_string(struct cmd_ctx *,
|
||||||
struct options *, const struct set_option_entry *, char *, int);
|
struct options *, const struct set_option_entry *, char *, int);
|
||||||
void set_option_number(struct cmd_ctx *,
|
void set_option_number(struct cmd_ctx *,
|
||||||
struct options *, const struct set_option_entry *, char *);
|
struct options *, const struct set_option_entry *, char *);
|
||||||
void set_option_keys(struct cmd_ctx *,
|
void set_option_key(struct cmd_ctx *,
|
||||||
struct options *, const struct set_option_entry *, char *);
|
struct options *, const struct set_option_entry *, char *);
|
||||||
void set_option_colour(struct cmd_ctx *,
|
void set_option_colour(struct cmd_ctx *,
|
||||||
struct options *, const struct set_option_entry *, char *);
|
struct options *, const struct set_option_entry *, char *);
|
||||||
@@ -1426,7 +1278,6 @@ int cmd_exec(struct cmd *, struct cmd_ctx *);
|
|||||||
void cmd_free(struct cmd *);
|
void cmd_free(struct cmd *);
|
||||||
size_t cmd_print(struct cmd *, char *, size_t);
|
size_t cmd_print(struct cmd *, char *, size_t);
|
||||||
struct session *cmd_current_session(struct cmd_ctx *);
|
struct session *cmd_current_session(struct cmd_ctx *);
|
||||||
struct client *cmd_current_client(struct cmd_ctx *);
|
|
||||||
struct client *cmd_find_client(struct cmd_ctx *, const char *);
|
struct client *cmd_find_client(struct cmd_ctx *, const char *);
|
||||||
struct session *cmd_find_session(struct cmd_ctx *, const char *);
|
struct session *cmd_find_session(struct cmd_ctx *, const char *);
|
||||||
struct winlink *cmd_find_window(
|
struct winlink *cmd_find_window(
|
||||||
@@ -1467,20 +1318,16 @@ extern const struct cmd_entry cmd_list_buffers_entry;
|
|||||||
extern const struct cmd_entry cmd_list_clients_entry;
|
extern const struct cmd_entry cmd_list_clients_entry;
|
||||||
extern const struct cmd_entry cmd_list_commands_entry;
|
extern const struct cmd_entry cmd_list_commands_entry;
|
||||||
extern const struct cmd_entry cmd_list_keys_entry;
|
extern const struct cmd_entry cmd_list_keys_entry;
|
||||||
extern const struct cmd_entry cmd_list_panes_entry;
|
|
||||||
extern const struct cmd_entry cmd_list_sessions_entry;
|
extern const struct cmd_entry cmd_list_sessions_entry;
|
||||||
extern const struct cmd_entry cmd_list_windows_entry;
|
extern const struct cmd_entry cmd_list_windows_entry;
|
||||||
extern const struct cmd_entry cmd_load_buffer_entry;
|
extern const struct cmd_entry cmd_load_buffer_entry;
|
||||||
extern const struct cmd_entry cmd_lock_client_entry;
|
|
||||||
extern const struct cmd_entry cmd_lock_server_entry;
|
extern const struct cmd_entry cmd_lock_server_entry;
|
||||||
extern const struct cmd_entry cmd_lock_session_entry;
|
|
||||||
extern const struct cmd_entry cmd_move_window_entry;
|
extern const struct cmd_entry cmd_move_window_entry;
|
||||||
extern const struct cmd_entry cmd_new_session_entry;
|
extern const struct cmd_entry cmd_new_session_entry;
|
||||||
extern const struct cmd_entry cmd_new_window_entry;
|
extern const struct cmd_entry cmd_new_window_entry;
|
||||||
extern const struct cmd_entry cmd_next_layout_entry;
|
extern const struct cmd_entry cmd_next_layout_entry;
|
||||||
extern const struct cmd_entry cmd_next_window_entry;
|
extern const struct cmd_entry cmd_next_window_entry;
|
||||||
extern const struct cmd_entry cmd_paste_buffer_entry;
|
extern const struct cmd_entry cmd_paste_buffer_entry;
|
||||||
extern const struct cmd_entry cmd_pipe_pane_entry;
|
|
||||||
extern const struct cmd_entry cmd_previous_layout_entry;
|
extern const struct cmd_entry cmd_previous_layout_entry;
|
||||||
extern const struct cmd_entry cmd_previous_window_entry;
|
extern const struct cmd_entry cmd_previous_window_entry;
|
||||||
extern const struct cmd_entry cmd_refresh_client_entry;
|
extern const struct cmd_entry cmd_refresh_client_entry;
|
||||||
@@ -1489,8 +1336,8 @@ extern const struct cmd_entry cmd_rename_window_entry;
|
|||||||
extern const struct cmd_entry cmd_resize_pane_entry;
|
extern const struct cmd_entry cmd_resize_pane_entry;
|
||||||
extern const struct cmd_entry cmd_respawn_window_entry;
|
extern const struct cmd_entry cmd_respawn_window_entry;
|
||||||
extern const struct cmd_entry cmd_rotate_window_entry;
|
extern const struct cmd_entry cmd_rotate_window_entry;
|
||||||
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_scroll_mode_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_prompt_entry;
|
||||||
@@ -1501,6 +1348,7 @@ extern const struct cmd_entry cmd_server_info_entry;
|
|||||||
extern const struct cmd_entry cmd_set_buffer_entry;
|
extern const struct cmd_entry cmd_set_buffer_entry;
|
||||||
extern const struct cmd_entry cmd_set_environment_entry;
|
extern const struct cmd_entry cmd_set_environment_entry;
|
||||||
extern const struct cmd_entry cmd_set_option_entry;
|
extern const struct cmd_entry cmd_set_option_entry;
|
||||||
|
extern const struct cmd_entry cmd_set_password_entry;
|
||||||
extern const struct cmd_entry cmd_set_window_option_entry;
|
extern const struct cmd_entry cmd_set_window_option_entry;
|
||||||
extern const struct cmd_entry cmd_show_buffer_entry;
|
extern const struct cmd_entry cmd_show_buffer_entry;
|
||||||
extern const struct cmd_entry cmd_show_environment_entry;
|
extern const struct cmd_entry cmd_show_environment_entry;
|
||||||
@@ -1554,8 +1402,14 @@ 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 */
|
||||||
struct imsgbuf *client_init(char *, int, int);
|
int client_init(char *, struct client_ctx *, int, int);
|
||||||
__dead void client_main(void);
|
int client_main(struct client_ctx *);
|
||||||
|
int client_msg_dispatch(struct client_ctx *);
|
||||||
|
|
||||||
|
/* client-fn.c */
|
||||||
|
void client_write_server(struct client_ctx *, enum msgtype, void *, size_t);
|
||||||
|
void client_fill_session(struct msg_command_data *);
|
||||||
|
void client_suspend(void);
|
||||||
|
|
||||||
/* key-bindings.c */
|
/* key-bindings.c */
|
||||||
extern struct key_bindings key_bindings;
|
extern struct key_bindings key_bindings;
|
||||||
@@ -1580,24 +1434,9 @@ const char *key_string_lookup_key(int);
|
|||||||
extern struct clients clients;
|
extern struct clients clients;
|
||||||
extern struct clients dead_clients;
|
extern struct clients dead_clients;
|
||||||
int server_start(char *);
|
int server_start(char *);
|
||||||
void server_poll_add(int, int, void (*)(int, int, void *), void *);
|
|
||||||
|
|
||||||
/* server-client.c */
|
/* server-msg.c */
|
||||||
void server_client_create(int);
|
int server_msg_dispatch(struct client *);
|
||||||
void server_client_lost(struct client *);
|
|
||||||
void server_client_prepare(void);
|
|
||||||
void server_client_callback(int, int, void *);
|
|
||||||
void server_client_loop(void);
|
|
||||||
|
|
||||||
/* server-job.c */
|
|
||||||
void server_job_prepare(void);
|
|
||||||
void server_job_callback(int, int, void *);
|
|
||||||
void server_job_loop(void);
|
|
||||||
|
|
||||||
/* server-window.c */
|
|
||||||
void server_window_prepare(void);
|
|
||||||
void server_window_callback(int, int, void *);
|
|
||||||
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 *);
|
||||||
@@ -1609,27 +1448,19 @@ void server_write_session(
|
|||||||
void server_redraw_client(struct client *);
|
void server_redraw_client(struct client *);
|
||||||
void server_status_client(struct client *);
|
void server_status_client(struct client *);
|
||||||
void server_redraw_session(struct session *);
|
void server_redraw_session(struct session *);
|
||||||
void server_redraw_session_group(struct session *);
|
|
||||||
void server_status_session(struct session *);
|
void server_status_session(struct session *);
|
||||||
void server_status_session_group(struct session *);
|
|
||||||
void server_redraw_window(struct window *);
|
void server_redraw_window(struct window *);
|
||||||
void server_status_window(struct window *);
|
void server_status_window(struct window *);
|
||||||
void server_lock(void);
|
void server_lock(void);
|
||||||
void server_lock_session(struct session *);
|
|
||||||
void server_lock_client(struct client *);
|
|
||||||
int server_unlock(const char *);
|
int server_unlock(const char *);
|
||||||
void server_kill_window(struct window *);
|
void server_kill_window(struct window *);
|
||||||
int server_link_window(struct session *,
|
|
||||||
struct winlink *, struct session *, int, int, int, char **);
|
|
||||||
void server_unlink_window(struct session *, struct winlink *);
|
|
||||||
void server_destroy_session_group(struct session *);
|
|
||||||
void server_destroy_session(struct session *);
|
void server_destroy_session(struct session *);
|
||||||
void server_set_identify(struct client *);
|
void server_set_identify(struct client *);
|
||||||
void server_clear_identify(struct client *);
|
void server_clear_identify(struct client *);
|
||||||
|
|
||||||
/* status.c */
|
/* status.c */
|
||||||
int status_redraw(struct client *);
|
int status_redraw(struct client *);
|
||||||
char *status_replace(struct client *, const char *, time_t);
|
char *status_replace(struct session *, const char *, time_t);
|
||||||
void printflike2 status_message_set(struct client *, const char *, ...);
|
void printflike2 status_message_set(struct client *, const char *, ...);
|
||||||
void status_message_clear(struct client *);
|
void status_message_clear(struct client *);
|
||||||
int status_message_redraw(struct client *);
|
int status_message_redraw(struct client *);
|
||||||
@@ -1650,11 +1481,7 @@ void input_parse(struct window_pane *);
|
|||||||
|
|
||||||
/* input-key.c */
|
/* input-key.c */
|
||||||
void input_key(struct window_pane *, int);
|
void input_key(struct window_pane *, int);
|
||||||
void input_mouse(struct window_pane *, struct mouse_event *);
|
void input_mouse(struct window_pane *, u_char, u_char, u_char);
|
||||||
|
|
||||||
/* xterm-keys.c */
|
|
||||||
char *xterm_keys_lookup(int);
|
|
||||||
int xterm_keys_find(const char *, size_t, size_t *);
|
|
||||||
|
|
||||||
/* colour.c */
|
/* colour.c */
|
||||||
void colour_set_fg(struct grid_cell *, int);
|
void colour_set_fg(struct grid_cell *, int);
|
||||||
@@ -1673,11 +1500,9 @@ extern const struct grid_cell grid_default_cell;
|
|||||||
struct grid *grid_create(u_int, u_int, u_int);
|
struct grid *grid_create(u_int, u_int, u_int);
|
||||||
void grid_destroy(struct grid *);
|
void grid_destroy(struct grid *);
|
||||||
int grid_compare(struct grid *, struct grid *);
|
int grid_compare(struct grid *, struct grid *);
|
||||||
void grid_collect_history(struct grid *);
|
|
||||||
void grid_scroll_history(struct grid *);
|
|
||||||
void grid_scroll_history_region(struct grid *, u_int, u_int);
|
|
||||||
void grid_expand_line(struct grid *, u_int, u_int);
|
void grid_expand_line(struct grid *, u_int, u_int);
|
||||||
void grid_expand_line_utf8(struct grid *, u_int, u_int);
|
void grid_expand_line_utf8(struct grid *, u_int, u_int);
|
||||||
|
void grid_scroll_line(struct grid *);
|
||||||
const struct grid_cell *grid_peek_cell(struct grid *, u_int, u_int);
|
const struct grid_cell *grid_peek_cell(struct grid *, u_int, u_int);
|
||||||
struct grid_cell *grid_get_cell(struct grid *, u_int, u_int);
|
struct grid_cell *grid_get_cell(struct grid *, u_int, u_int);
|
||||||
void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
|
void grid_set_cell(struct grid *, u_int, u_int, const struct grid_cell *);
|
||||||
@@ -1732,7 +1557,6 @@ void screen_write_putc(
|
|||||||
struct screen_write_ctx *, struct grid_cell *, u_char);
|
struct screen_write_ctx *, struct grid_cell *, u_char);
|
||||||
void screen_write_copy(struct screen_write_ctx *,
|
void screen_write_copy(struct screen_write_ctx *,
|
||||||
struct screen *, u_int, u_int, u_int, u_int);
|
struct screen *, u_int, u_int, u_int, u_int);
|
||||||
void screen_write_backspace(struct screen_write_ctx *);
|
|
||||||
void screen_write_cursorup(struct screen_write_ctx *, u_int);
|
void screen_write_cursorup(struct screen_write_ctx *, u_int);
|
||||||
void screen_write_cursordown(struct screen_write_ctx *, u_int);
|
void screen_write_cursordown(struct screen_write_ctx *, u_int);
|
||||||
void screen_write_cursorright(struct screen_write_ctx *, u_int);
|
void screen_write_cursorright(struct screen_write_ctx *, u_int);
|
||||||
@@ -1752,15 +1576,14 @@ void screen_write_scrollregion(struct screen_write_ctx *, u_int, u_int);
|
|||||||
void screen_write_insertmode(struct screen_write_ctx *, int);
|
void screen_write_insertmode(struct screen_write_ctx *, int);
|
||||||
void screen_write_mousemode(struct screen_write_ctx *, int);
|
void screen_write_mousemode(struct screen_write_ctx *, int);
|
||||||
void screen_write_linefeed(struct screen_write_ctx *, int);
|
void screen_write_linefeed(struct screen_write_ctx *, int);
|
||||||
void screen_write_linefeedscreen(struct screen_write_ctx *, int);
|
|
||||||
void screen_write_carriagereturn(struct screen_write_ctx *);
|
void screen_write_carriagereturn(struct screen_write_ctx *);
|
||||||
void screen_write_kcursormode(struct screen_write_ctx *, int);
|
void screen_write_kcursormode(struct screen_write_ctx *, int);
|
||||||
void screen_write_kkeypadmode(struct screen_write_ctx *, int);
|
void screen_write_kkeypadmode(struct screen_write_ctx *, int);
|
||||||
void screen_write_clearendofscreen(struct screen_write_ctx *);
|
void screen_write_clearendofscreen(struct screen_write_ctx *);
|
||||||
void screen_write_clearstartofscreen(struct screen_write_ctx *);
|
void screen_write_clearstartofscreen(struct screen_write_ctx *);
|
||||||
void screen_write_clearscreen(struct screen_write_ctx *);
|
void screen_write_clearscreen(struct screen_write_ctx *);
|
||||||
void screen_write_cell(struct screen_write_ctx *,
|
void screen_write_cell(
|
||||||
const struct grid_cell *, const struct utf8_data *);
|
struct screen_write_ctx *, const struct grid_cell *, u_char *);
|
||||||
|
|
||||||
/* screen-redraw.c */
|
/* screen-redraw.c */
|
||||||
void screen_redraw_screen(struct client *, int);
|
void screen_redraw_screen(struct client *, int);
|
||||||
@@ -1800,7 +1623,6 @@ struct window *window_create(const char *, const char *, const char *,
|
|||||||
const char *, struct environ *, struct termios *,
|
const char *, struct environ *, struct termios *,
|
||||||
u_int, u_int, u_int, char **);
|
u_int, u_int, u_int, char **);
|
||||||
void window_destroy(struct window *);
|
void window_destroy(struct window *);
|
||||||
void window_set_active_at(struct window *, u_int, u_int);
|
|
||||||
void window_set_active_pane(struct window *, struct window_pane *);
|
void window_set_active_pane(struct window *, struct window_pane *);
|
||||||
struct window_pane *window_add_pane(struct window *, u_int);
|
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);
|
||||||
@@ -1821,7 +1643,7 @@ void window_pane_reset_mode(struct window_pane *);
|
|||||||
void window_pane_parse(struct window_pane *);
|
void window_pane_parse(struct window_pane *);
|
||||||
void window_pane_key(struct window_pane *, struct client *, int);
|
void window_pane_key(struct window_pane *, struct client *, int);
|
||||||
void window_pane_mouse(struct window_pane *,
|
void window_pane_mouse(struct window_pane *,
|
||||||
struct client *, struct mouse_event *);
|
struct client *, u_char, u_char, u_char);
|
||||||
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 *);
|
||||||
@@ -1864,6 +1686,10 @@ extern const struct window_mode window_clock_mode;
|
|||||||
extern const struct window_mode window_copy_mode;
|
extern const struct window_mode window_copy_mode;
|
||||||
void window_copy_pageup(struct window_pane *);
|
void window_copy_pageup(struct window_pane *);
|
||||||
|
|
||||||
|
/* window-scroll.c */
|
||||||
|
extern const struct window_mode window_scroll_mode;
|
||||||
|
void window_scroll_pageup(struct window_pane *);
|
||||||
|
|
||||||
/* window-more.c */
|
/* window-more.c */
|
||||||
extern const struct window_mode window_more_mode;
|
extern const struct window_mode window_more_mode;
|
||||||
void window_more_vadd(struct window_pane *, const char *, va_list);
|
void window_more_vadd(struct window_pane *, const char *, va_list);
|
||||||
@@ -1884,7 +1710,6 @@ char *default_window_name(struct window *);
|
|||||||
/* 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;
|
|
||||||
void session_alert_add(struct session *, struct window *, int);
|
void session_alert_add(struct session *, struct window *, int);
|
||||||
void session_alert_cancel(struct session *, struct winlink *);
|
void session_alert_cancel(struct session *, struct winlink *);
|
||||||
int session_alert_has(struct session *, struct winlink *, int);
|
int session_alert_has(struct session *, struct winlink *, int);
|
||||||
@@ -1905,18 +1730,10 @@ 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);
|
||||||
int session_last(struct session *);
|
int session_last(struct session *);
|
||||||
struct session_group *session_group_find(struct session *);
|
|
||||||
u_int session_group_index(struct session_group *);
|
|
||||||
void session_group_add(struct session *, struct session *);
|
|
||||||
void session_group_remove(struct session *);
|
|
||||||
void session_group_synchronize_to(struct session *);
|
|
||||||
void session_group_synchronize_from(struct session *);
|
|
||||||
void session_group_synchronize1(struct session *, struct session *);
|
|
||||||
|
|
||||||
/* utf8.c */
|
/* utf8.c */
|
||||||
void utf8_build(void);
|
void utf8_build(void);
|
||||||
int utf8_open(struct utf8_data *, u_char);
|
int utf8_width(const u_char *);
|
||||||
int utf8_append(struct utf8_data *, u_char);
|
|
||||||
|
|
||||||
/* osdep-*.c */
|
/* osdep-*.c */
|
||||||
char *osdep_get_name(int, char *);
|
char *osdep_get_name(int, char *);
|
||||||
@@ -1933,7 +1750,7 @@ void buffer_write8(struct buffer *, uint8_t);
|
|||||||
uint8_t buffer_read8(struct buffer *);
|
uint8_t buffer_read8(struct buffer *);
|
||||||
|
|
||||||
/* buffer-poll.c */
|
/* buffer-poll.c */
|
||||||
int buffer_poll(int, int, struct buffer *, struct buffer *);
|
int buffer_poll(struct pollfd *, struct buffer *, struct buffer *);
|
||||||
|
|
||||||
/* log.c */
|
/* log.c */
|
||||||
void log_open_tty(int);
|
void log_open_tty(int);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# $Id: dist.mk,v 1.7 2009-11-05 12:32:46 tcunha Exp $
|
# $Id: dist.mk,v 1.5 2009-09-20 18:54:21 nicm Exp $
|
||||||
|
|
||||||
VERSION= 1.1
|
VERSION= 1.0
|
||||||
|
|
||||||
DISTDIR= tmux-${VERSION}
|
DISTDIR= tmux-${VERSION}
|
||||||
DISTFILES= *.[ch] Makefile GNUmakefile configure tmux.1 \
|
DISTFILES= *.[ch] Makefile GNUmakefile configure tmux.1 \
|
||||||
@@ -19,7 +19,7 @@ dist:
|
|||||||
-f ${DISTDIR}.tar.gz ${DISTFILES}
|
-f ${DISTDIR}.tar.gz ${DISTFILES}
|
||||||
|
|
||||||
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/images/*.png \
|
||||||
nicm,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-*
|
||||||
|
|
||||||
|
|||||||
303
tty-keys.c
303
tty-keys.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tty-keys.c,v 1.38 2009-10-28 23:05:01 tcunha Exp $ */
|
/* $Id: tty-keys.c,v 1.29 2009-07-28 22:37:02 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -25,12 +25,9 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle keys input from the outside terminal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void tty_keys_add(struct tty *, const char *, int, int);
|
void tty_keys_add(struct tty *, const char *, int, int);
|
||||||
int tty_keys_mouse(char *, size_t, size_t *, struct mouse_event *);
|
int tty_keys_parse_xterm(struct tty *, char *, size_t, size_t *);
|
||||||
|
int tty_keys_parse_mouse(struct tty *, char *, size_t, size_t *, u_char *);
|
||||||
|
|
||||||
struct tty_key_ent {
|
struct tty_key_ent {
|
||||||
enum tty_code_code code;
|
enum tty_code_code code;
|
||||||
@@ -42,145 +39,85 @@ struct tty_key_ent {
|
|||||||
|
|
||||||
struct tty_key_ent tty_keys[] = {
|
struct tty_key_ent tty_keys[] = {
|
||||||
/* Function keys. */
|
/* Function keys. */
|
||||||
{ TTYC_KF1, NULL, KEYC_F1, TTYKEY_CTRL },
|
{ TTYC_KF1, NULL, KEYC_F1, TTYKEY_CTRL },
|
||||||
{ TTYC_KF1, NULL, KEYC_F1, TTYKEY_CTRL },
|
{ TTYC_KF2, NULL, KEYC_F2, TTYKEY_CTRL },
|
||||||
{ TTYC_KF2, NULL, KEYC_F2, TTYKEY_CTRL },
|
{ TTYC_KF3, NULL, KEYC_F3, TTYKEY_CTRL },
|
||||||
{ TTYC_KF3, NULL, KEYC_F3, TTYKEY_CTRL },
|
{ TTYC_KF4, NULL, KEYC_F4, TTYKEY_CTRL },
|
||||||
{ TTYC_KF4, NULL, KEYC_F4, TTYKEY_CTRL },
|
{ TTYC_KF5, NULL, KEYC_F5, TTYKEY_CTRL },
|
||||||
{ TTYC_KF5, NULL, KEYC_F5, TTYKEY_CTRL },
|
{ TTYC_KF6, NULL, KEYC_F6, TTYKEY_CTRL },
|
||||||
{ TTYC_KF6, NULL, KEYC_F6, TTYKEY_CTRL },
|
{ TTYC_KF7, NULL, KEYC_F7, TTYKEY_CTRL },
|
||||||
{ TTYC_KF7, NULL, KEYC_F7, TTYKEY_CTRL },
|
{ TTYC_KF8, NULL, KEYC_F8, TTYKEY_CTRL },
|
||||||
{ TTYC_KF8, NULL, KEYC_F8, TTYKEY_CTRL },
|
{ TTYC_KF9, NULL, KEYC_F9, TTYKEY_CTRL },
|
||||||
{ TTYC_KF9, NULL, KEYC_F9, TTYKEY_CTRL },
|
{ TTYC_KF10, NULL, KEYC_F10, TTYKEY_CTRL },
|
||||||
{ TTYC_KF10, NULL, KEYC_F10, TTYKEY_CTRL },
|
{ TTYC_KF11, NULL, KEYC_F11, TTYKEY_CTRL },
|
||||||
{ TTYC_KF11, NULL, KEYC_F11, TTYKEY_CTRL },
|
{ TTYC_KF12, NULL, KEYC_F12, TTYKEY_CTRL },
|
||||||
{ TTYC_KF12, NULL, KEYC_F12, TTYKEY_CTRL },
|
{ TTYC_KF13, NULL, KEYC_F13, TTYKEY_CTRL },
|
||||||
{ TTYC_KF13, NULL, KEYC_F13, TTYKEY_CTRL },
|
{ TTYC_KF14, NULL, KEYC_F14, TTYKEY_CTRL },
|
||||||
{ TTYC_KF14, NULL, KEYC_F14, TTYKEY_CTRL },
|
{ TTYC_KF15, NULL, KEYC_F15, TTYKEY_CTRL },
|
||||||
{ TTYC_KF15, NULL, KEYC_F15, TTYKEY_CTRL },
|
{ TTYC_KF16, NULL, KEYC_F16, TTYKEY_CTRL },
|
||||||
{ TTYC_KF16, NULL, KEYC_F16, TTYKEY_CTRL },
|
{ TTYC_KF17, NULL, KEYC_F17, TTYKEY_CTRL },
|
||||||
{ TTYC_KF17, NULL, KEYC_F17, TTYKEY_CTRL },
|
{ TTYC_KF18, NULL, KEYC_F18, TTYKEY_CTRL },
|
||||||
{ TTYC_KF18, NULL, KEYC_F18, TTYKEY_CTRL },
|
{ TTYC_KF19, NULL, KEYC_F19, TTYKEY_CTRL },
|
||||||
{ TTYC_KF19, NULL, KEYC_F19, TTYKEY_CTRL },
|
{ TTYC_KF20, NULL, KEYC_F20, TTYKEY_CTRL },
|
||||||
{ TTYC_KF20, NULL, KEYC_F20, TTYKEY_CTRL },
|
{ TTYC_KICH1, NULL, KEYC_IC, TTYKEY_CTRL },
|
||||||
{ TTYC_KICH1, NULL, KEYC_IC, TTYKEY_CTRL },
|
{ TTYC_KDCH1, NULL, KEYC_DC, TTYKEY_CTRL },
|
||||||
{ TTYC_KDCH1, NULL, KEYC_DC, TTYKEY_CTRL },
|
{ TTYC_KHOME, NULL, KEYC_HOME, TTYKEY_CTRL },
|
||||||
{ TTYC_KHOME, NULL, KEYC_HOME, TTYKEY_CTRL },
|
{ TTYC_KEND, NULL, KEYC_END, TTYKEY_CTRL },
|
||||||
{ TTYC_KEND, NULL, KEYC_END, TTYKEY_CTRL },
|
{ TTYC_KNP, NULL, KEYC_NPAGE, TTYKEY_CTRL },
|
||||||
{ TTYC_KNP, NULL, KEYC_NPAGE, TTYKEY_CTRL },
|
{ TTYC_KPP, NULL, KEYC_PPAGE, TTYKEY_CTRL },
|
||||||
{ TTYC_KPP, NULL, KEYC_PPAGE, TTYKEY_CTRL },
|
{ TTYC_KCBT, NULL, KEYC_BTAB, TTYKEY_CTRL },
|
||||||
{ TTYC_KCBT, NULL, KEYC_BTAB, TTYKEY_CTRL },
|
|
||||||
|
|
||||||
/* Arrow keys. */
|
/* Arrow keys. */
|
||||||
{ 0, "\033OA", KEYC_UP, TTYKEY_RAW },
|
{ 0, "\033OA", KEYC_UP, TTYKEY_RAW },
|
||||||
{ 0, "\033OB", KEYC_DOWN, TTYKEY_RAW },
|
{ 0, "\033OB", KEYC_DOWN, TTYKEY_RAW },
|
||||||
{ 0, "\033OC", KEYC_RIGHT, TTYKEY_RAW },
|
{ 0, "\033OC", KEYC_RIGHT, TTYKEY_RAW },
|
||||||
{ 0, "\033OD", KEYC_LEFT, TTYKEY_RAW },
|
{ 0, "\033OD", KEYC_LEFT, TTYKEY_RAW },
|
||||||
|
|
||||||
{ 0, "\033[A", KEYC_UP, TTYKEY_RAW },
|
{ 0, "\033[A", KEYC_UP, TTYKEY_RAW },
|
||||||
{ 0, "\033[B", KEYC_DOWN, TTYKEY_RAW },
|
{ 0, "\033[B", KEYC_DOWN, TTYKEY_RAW },
|
||||||
{ 0, "\033[C", KEYC_RIGHT, TTYKEY_RAW },
|
{ 0, "\033[C", KEYC_RIGHT, TTYKEY_RAW },
|
||||||
{ 0, "\033[D", KEYC_LEFT, TTYKEY_RAW },
|
{ 0, "\033[D", KEYC_LEFT, TTYKEY_RAW },
|
||||||
|
|
||||||
{ TTYC_KCUU1, NULL, KEYC_UP, TTYKEY_CTRL },
|
{ 0, "\033Oa", KEYC_UP | KEYC_CTRL, TTYKEY_RAW },
|
||||||
{ TTYC_KCUD1, NULL, KEYC_DOWN, TTYKEY_CTRL },
|
{ 0, "\033Ob", KEYC_DOWN | KEYC_CTRL, TTYKEY_RAW },
|
||||||
{ TTYC_KCUB1, NULL, KEYC_LEFT, TTYKEY_CTRL },
|
{ 0, "\033Oc", KEYC_RIGHT | KEYC_CTRL, TTYKEY_RAW },
|
||||||
{ TTYC_KCUF1, NULL, KEYC_RIGHT, TTYKEY_CTRL },
|
{ 0, "\033Od", KEYC_LEFT | KEYC_CTRL, TTYKEY_RAW },
|
||||||
|
{ 0, "\033[a", KEYC_UP | KEYC_SHIFT, TTYKEY_RAW },
|
||||||
|
{ 0, "\033[b", KEYC_DOWN | KEYC_SHIFT, TTYKEY_RAW },
|
||||||
|
{ 0, "\033[c", KEYC_RIGHT | KEYC_SHIFT, TTYKEY_RAW },
|
||||||
|
{ 0, "\033[d", KEYC_LEFT | KEYC_SHIFT, TTYKEY_RAW },
|
||||||
|
|
||||||
/* Special-case arrow keys for rxvt until terminfo has kRIT5 etc. */
|
{ TTYC_KCUU1, NULL, KEYC_UP, TTYKEY_CTRL },
|
||||||
{ 0, "\033Oa", KEYC_UP|KEYC_CTRL, TTYKEY_RAW },
|
{ TTYC_KCUD1, NULL, KEYC_DOWN, TTYKEY_CTRL },
|
||||||
{ 0, "\033Ob", KEYC_DOWN|KEYC_CTRL, TTYKEY_RAW },
|
{ TTYC_KCUB1, NULL, KEYC_LEFT, TTYKEY_CTRL },
|
||||||
{ 0, "\033Oc", KEYC_RIGHT|KEYC_CTRL, TTYKEY_RAW },
|
{ TTYC_KCUF1, NULL, KEYC_RIGHT, TTYKEY_CTRL },
|
||||||
{ 0, "\033Od", KEYC_LEFT|KEYC_CTRL, TTYKEY_RAW },
|
|
||||||
|
|
||||||
{ 0, "\033[a", KEYC_UP|KEYC_SHIFT, TTYKEY_RAW },
|
|
||||||
{ 0, "\033[b", KEYC_DOWN|KEYC_SHIFT, TTYKEY_RAW },
|
|
||||||
{ 0, "\033[c", KEYC_RIGHT|KEYC_SHIFT, TTYKEY_RAW },
|
|
||||||
{ 0, "\033[d", KEYC_LEFT|KEYC_SHIFT, TTYKEY_RAW },
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Numeric keypad. Just use the vt100 escape sequences here and always
|
* Numeric keypad. termcap and terminfo are totally confusing for this.
|
||||||
* put the terminal into keypad_xmit mode. Translation of numbers
|
* There are definitions for some keypad keys and for function keys,
|
||||||
* mode/applications mode is done in input-keys.c.
|
* but these seem to now be used for the real function keys rather than
|
||||||
|
* for the keypad keys in application mode (which is different from
|
||||||
|
* what it says in the termcap file). So, we just hardcode the vt100
|
||||||
|
* escape sequences here and always put the terminal into keypad_xmit
|
||||||
|
* mode. Translation of numbers mode/applications mode is done in
|
||||||
|
* input-keys.c.
|
||||||
*/
|
*/
|
||||||
{ 0, "\033Oo", KEYC_KP_SLASH, TTYKEY_RAW },
|
{ 0, "\033Oo", KEYC_KP0_1, TTYKEY_RAW },
|
||||||
{ 0, "\033Oj", KEYC_KP_STAR, TTYKEY_RAW },
|
{ 0, "\033Oj", KEYC_KP0_2, TTYKEY_RAW },
|
||||||
{ 0, "\033Om", KEYC_KP_MINUS, TTYKEY_RAW },
|
{ 0, "\033Om", KEYC_KP0_3, TTYKEY_RAW },
|
||||||
{ 0, "\033Ow", KEYC_KP_SEVEN, TTYKEY_RAW },
|
{ 0, "\033Ow", KEYC_KP1_0, TTYKEY_RAW },
|
||||||
{ 0, "\033Ox", KEYC_KP_EIGHT, TTYKEY_RAW },
|
{ 0, "\033Ox", KEYC_KP1_1, TTYKEY_RAW },
|
||||||
{ 0, "\033Oy", KEYC_KP_NINE, TTYKEY_RAW },
|
{ 0, "\033Oy", KEYC_KP1_2, TTYKEY_RAW },
|
||||||
{ 0, "\033Ok", KEYC_KP_PLUS, TTYKEY_RAW },
|
{ 0, "\033Ok", KEYC_KP1_3, TTYKEY_RAW },
|
||||||
{ 0, "\033Ot", KEYC_KP_FOUR, TTYKEY_RAW },
|
{ 0, "\033Ot", KEYC_KP2_0, TTYKEY_RAW },
|
||||||
{ 0, "\033Ou", KEYC_KP_FIVE, TTYKEY_RAW },
|
{ 0, "\033Ou", KEYC_KP2_1, TTYKEY_RAW },
|
||||||
{ 0, "\033Ov", KEYC_KP_SIX, TTYKEY_RAW },
|
{ 0, "\033Ov", KEYC_KP2_2, TTYKEY_RAW },
|
||||||
{ 0, "\033Oq", KEYC_KP_ONE, TTYKEY_RAW },
|
{ 0, "\033Oq", KEYC_KP3_0, TTYKEY_RAW },
|
||||||
{ 0, "\033Or", KEYC_KP_TWO, TTYKEY_RAW },
|
{ 0, "\033Or", KEYC_KP3_1, TTYKEY_RAW },
|
||||||
{ 0, "\033Os", KEYC_KP_THREE, TTYKEY_RAW },
|
{ 0, "\033Os", KEYC_KP3_2, TTYKEY_RAW },
|
||||||
{ 0, "\033OM", KEYC_KP_ENTER, TTYKEY_RAW },
|
{ 0, "\033OM", KEYC_KP3_3, TTYKEY_RAW },
|
||||||
{ 0, "\033Op", KEYC_KP_ZERO, TTYKEY_RAW },
|
{ 0, "\033Op", KEYC_KP4_0, TTYKEY_RAW },
|
||||||
{ 0, "\033On", KEYC_KP_PERIOD, TTYKEY_RAW },
|
{ 0, "\033On", KEYC_KP4_2, TTYKEY_RAW },
|
||||||
|
|
||||||
/* Key and modifier capabilities. */
|
|
||||||
{ TTYC_KDC2, NULL, KEYC_DC|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KDC3, NULL, KEYC_DC|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KDC4, NULL, KEYC_DC|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KDC5, NULL, KEYC_DC|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KDC6, NULL, KEYC_DC|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KDC7, NULL, KEYC_DC|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KDN2, NULL, KEYC_DOWN|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KDN3, NULL, KEYC_DOWN|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KDN4, NULL, KEYC_DOWN|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KDN5, NULL, KEYC_DOWN|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KDN6, NULL, KEYC_DOWN|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KDN7, NULL, KEYC_DOWN|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KEND2, NULL, KEYC_END|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KEND3, NULL, KEYC_END|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KEND4, NULL, KEYC_END|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KEND5, NULL, KEYC_END|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KEND6, NULL, KEYC_END|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KEND7, NULL, KEYC_END|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KHOM2, NULL, KEYC_HOME|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KHOM3, NULL, KEYC_HOME|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KHOM4, NULL, KEYC_HOME|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KHOM5, NULL, KEYC_HOME|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KHOM6, NULL, KEYC_HOME|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KHOM7, NULL, KEYC_HOME|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KIC2, NULL, KEYC_IC|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KIC3, NULL, KEYC_IC|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KIC4, NULL, KEYC_IC|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KIC5, NULL, KEYC_IC|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KIC6, NULL, KEYC_IC|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KIC7, NULL, KEYC_IC|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KLFT2, NULL, KEYC_LEFT|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KLFT3, NULL, KEYC_LEFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KLFT4, NULL, KEYC_LEFT|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KLFT5, NULL, KEYC_LEFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KLFT6, NULL, KEYC_LEFT|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KLFT7, NULL, KEYC_LEFT|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KNXT2, NULL, KEYC_NPAGE|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KNXT3, NULL, KEYC_NPAGE|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KNXT4, NULL, KEYC_NPAGE|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KNXT5, NULL, KEYC_NPAGE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KNXT6, NULL, KEYC_NPAGE|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KNXT7, NULL, KEYC_NPAGE|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KPRV2, NULL, KEYC_PPAGE|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KPRV3, NULL, KEYC_PPAGE|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KPRV4, NULL, KEYC_PPAGE|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KPRV5, NULL, KEYC_PPAGE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KPRV6, NULL, KEYC_PPAGE|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KPRV7, NULL, KEYC_PPAGE|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KRIT2, NULL, KEYC_RIGHT|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KRIT3, NULL, KEYC_RIGHT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KRIT4, NULL, KEYC_RIGHT|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KRIT5, NULL, KEYC_RIGHT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KRIT6, NULL, KEYC_RIGHT|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KRIT7, NULL, KEYC_RIGHT|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KUP2, NULL, KEYC_UP|KEYC_SHIFT, 0 },
|
|
||||||
{ TTYC_KUP3, NULL, KEYC_UP|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KUP4, NULL, KEYC_UP|KEYC_SHIFT|KEYC_ESCAPE, 0 },
|
|
||||||
{ TTYC_KUP5, NULL, KEYC_UP|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KUP6, NULL, KEYC_UP|KEYC_SHIFT|KEYC_CTRL, 0 },
|
|
||||||
{ TTYC_KUP7, NULL, KEYC_UP|KEYC_ESCAPE|KEYC_CTRL, 0 },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RB_GENERATE(tty_keys, tty_key, entry, tty_keys_cmp);
|
RB_GENERATE(tty_keys, tty_key, entry, tty_keys_cmp);
|
||||||
@@ -294,7 +231,7 @@ tty_keys_find(struct tty *tty, char *buf, size_t len, size_t *size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tty_keys_next(struct tty *tty, int *key, struct mouse_event *mouse)
|
tty_keys_next(struct tty *tty, int *key, u_char *mouse)
|
||||||
{
|
{
|
||||||
struct tty_key *tk;
|
struct tty_key *tk;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@@ -332,14 +269,14 @@ tty_keys_next(struct tty *tty, int *key, struct mouse_event *mouse)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Not found. Is this a mouse key press? */
|
/* Not found. Is this a mouse key press? */
|
||||||
*key = tty_keys_mouse(buf, len, &size, mouse);
|
*key = tty_keys_parse_mouse(tty, buf, len, &size, mouse);
|
||||||
if (*key != KEYC_NONE) {
|
if (*key != KEYC_NONE) {
|
||||||
buffer_remove(tty->in, size);
|
buffer_remove(tty->in, size);
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not found. Try to parse a key with an xterm-style modifier. */
|
/* Not found. Try to parse xterm-type arguments. */
|
||||||
*key = xterm_keys_find(buf, len, &size);
|
*key = tty_keys_parse_xterm(tty, buf, len, &size);
|
||||||
if (*key != KEYC_NONE) {
|
if (*key != KEYC_NONE) {
|
||||||
buffer_remove(tty->in, size);
|
buffer_remove(tty->in, size);
|
||||||
goto found;
|
goto found;
|
||||||
@@ -350,7 +287,7 @@ tty_keys_next(struct tty *tty, int *key, struct mouse_event *mouse)
|
|||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = ESCAPE_PERIOD * 1000L;
|
tv.tv_usec = ESCAPE_PERIOD * 1000L;
|
||||||
if (gettimeofday(&tty->key_timer, NULL) != 0)
|
if (gettimeofday(&tty->key_timer, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday");
|
||||||
timeradd(&tty->key_timer, &tv, &tty->key_timer);
|
timeradd(&tty->key_timer, &tv, &tty->key_timer);
|
||||||
|
|
||||||
tty->flags |= TTY_ESCAPE;
|
tty->flags |= TTY_ESCAPE;
|
||||||
@@ -380,7 +317,7 @@ tty_keys_next(struct tty *tty, int *key, struct mouse_event *mouse)
|
|||||||
|
|
||||||
/* If the timer hasn't expired, keep waiting. */
|
/* If the timer hasn't expired, keep waiting. */
|
||||||
if (gettimeofday(&tv, NULL) != 0)
|
if (gettimeofday(&tv, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday");
|
||||||
if (timercmp(&tty->key_timer, &tv, >))
|
if (timercmp(&tty->key_timer, &tv, >))
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
@@ -394,7 +331,8 @@ found:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tty_keys_mouse(char *buf, size_t len, size_t *size, struct mouse_event *m)
|
tty_keys_parse_mouse(
|
||||||
|
unused struct tty *tty, char *buf, size_t len, size_t *size, u_char *mouse)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Mouse sequences are \033[M followed by three characters indicating
|
* Mouse sequences are \033[M followed by three characters indicating
|
||||||
@@ -406,13 +344,76 @@ tty_keys_mouse(char *buf, size_t len, size_t *size, struct mouse_event *m)
|
|||||||
return (KEYC_NONE);
|
return (KEYC_NONE);
|
||||||
*size = 6;
|
*size = 6;
|
||||||
|
|
||||||
m->b = buf[3];
|
if (buf[3] < 32 || buf[4] < 33 || buf[5] < 33)
|
||||||
m->x = buf[4];
|
|
||||||
m->y = buf[5];
|
|
||||||
if (m->b < 32 || m->x < 33 || m->y < 33)
|
|
||||||
return (KEYC_NONE);
|
return (KEYC_NONE);
|
||||||
m->b -= 32;
|
|
||||||
m->x -= 33;
|
mouse[0] = buf[3] - 32;
|
||||||
m->y -= 33;
|
mouse[1] = buf[4] - 33;
|
||||||
|
mouse[2] = buf[5] - 33;
|
||||||
return (KEYC_MOUSE);
|
return (KEYC_MOUSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tty_keys_parse_xterm(struct tty *tty, char *buf, size_t len, size_t *size)
|
||||||
|
{
|
||||||
|
struct tty_key *tk;
|
||||||
|
char tmp[5];
|
||||||
|
size_t tmplen;
|
||||||
|
int key;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xterm sequences with modifier keys are of the form:
|
||||||
|
*
|
||||||
|
* ^[[1;xD becomes ^[[D
|
||||||
|
* ^[[5;x~ becomes ^[[5~
|
||||||
|
*
|
||||||
|
* This function is a bit of a hack. Need to figure out what exact
|
||||||
|
* format and meaning xterm outputs and fix it. XXX
|
||||||
|
*/
|
||||||
|
|
||||||
|
log_debug("xterm input is: %.*s", (int) len, buf);
|
||||||
|
if (len != 6 || memcmp(buf, "\033[1;", 4) != 0)
|
||||||
|
return (KEYC_NONE);
|
||||||
|
*size = 6;
|
||||||
|
|
||||||
|
tmplen = 0;
|
||||||
|
tmp[tmplen++] = '[';
|
||||||
|
if (buf[5] == '~') {
|
||||||
|
tmp[tmplen++] = buf[2];
|
||||||
|
tmp[tmplen++] = '~';
|
||||||
|
} else
|
||||||
|
tmp[tmplen++] = buf[5];
|
||||||
|
log_debug("xterm output is: %.*s", (int) tmplen, tmp);
|
||||||
|
|
||||||
|
tk = tty_keys_find(tty, tmp, tmplen, size);
|
||||||
|
if (tk == NULL)
|
||||||
|
return (KEYC_NONE);
|
||||||
|
key = tk->key;
|
||||||
|
|
||||||
|
switch (buf[4]) {
|
||||||
|
case '8':
|
||||||
|
key |= KEYC_SHIFT|KEYC_ESCAPE|KEYC_CTRL;
|
||||||
|
break;
|
||||||
|
case '7':
|
||||||
|
key |= KEYC_ESCAPE|KEYC_CTRL;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
key |= KEYC_SHIFT|KEYC_CTRL;
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
key |= KEYC_CTRL;
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
key |= KEYC_SHIFT|KEYC_ESCAPE;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
key |= KEYC_ESCAPE;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
key |= KEYC_SHIFT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = 6;
|
||||||
|
return (key);
|
||||||
|
}
|
||||||
|
|||||||
96
tty-term.c
96
tty-term.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: tty-term.c,v 1.35 2009-10-28 23:01:44 tcunha Exp $ */
|
/* $Id: tty-term.c,v 1.30 2009-08-23 11:50:39 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -32,8 +32,8 @@ char *tty_term_strip(const char *);
|
|||||||
struct tty_terms tty_terms = SLIST_HEAD_INITIALIZER(tty_terms);
|
struct tty_terms tty_terms = SLIST_HEAD_INITIALIZER(tty_terms);
|
||||||
|
|
||||||
struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
|
struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
|
||||||
{ TTYC_ACSC, TTYCODE_STRING, "acsc" },
|
|
||||||
{ TTYC_AX, TTYCODE_FLAG, "AX" },
|
{ TTYC_AX, TTYCODE_FLAG, "AX" },
|
||||||
|
{ TTYC_ACSC, TTYCODE_STRING, "acsc" },
|
||||||
{ TTYC_BEL, TTYCODE_STRING, "bel" },
|
{ TTYC_BEL, TTYCODE_STRING, "bel" },
|
||||||
{ TTYC_BLINK, TTYCODE_STRING, "blink" },
|
{ TTYC_BLINK, TTYCODE_STRING, "blink" },
|
||||||
{ TTYC_BOLD, TTYCODE_STRING, "bold" },
|
{ TTYC_BOLD, TTYCODE_STRING, "bold" },
|
||||||
@@ -42,15 +42,9 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
|
|||||||
{ TTYC_CNORM, TTYCODE_STRING, "cnorm" },
|
{ TTYC_CNORM, TTYCODE_STRING, "cnorm" },
|
||||||
{ TTYC_COLORS, TTYCODE_NUMBER, "colors" },
|
{ TTYC_COLORS, TTYCODE_NUMBER, "colors" },
|
||||||
{ TTYC_CSR, TTYCODE_STRING, "csr" },
|
{ TTYC_CSR, TTYCODE_STRING, "csr" },
|
||||||
{ TTYC_CUB, TTYCODE_STRING, "cub" },
|
|
||||||
{ TTYC_CUB1, TTYCODE_STRING, "cub1" },
|
|
||||||
{ TTYC_CUD, TTYCODE_STRING, "cud" },
|
{ TTYC_CUD, TTYCODE_STRING, "cud" },
|
||||||
{ TTYC_CUD1, TTYCODE_STRING, "cud1" },
|
{ TTYC_CUD1, TTYCODE_STRING, "cud1" },
|
||||||
{ TTYC_CUF, TTYCODE_STRING, "cuf" },
|
|
||||||
{ TTYC_CUF1, TTYCODE_STRING, "cuf1" },
|
|
||||||
{ TTYC_CUP, TTYCODE_STRING, "cup" },
|
{ TTYC_CUP, TTYCODE_STRING, "cup" },
|
||||||
{ TTYC_CUU, TTYCODE_STRING, "cuu" },
|
|
||||||
{ TTYC_CUU1, TTYCODE_STRING, "cuu1" },
|
|
||||||
{ TTYC_DCH, TTYCODE_STRING, "dch" },
|
{ TTYC_DCH, TTYCODE_STRING, "dch" },
|
||||||
{ TTYC_DCH1, TTYCODE_STRING, "dch1" },
|
{ TTYC_DCH1, TTYCODE_STRING, "dch1" },
|
||||||
{ TTYC_DIM, TTYCODE_STRING, "dim" },
|
{ TTYC_DIM, TTYCODE_STRING, "dim" },
|
||||||
@@ -59,8 +53,6 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
|
|||||||
{ TTYC_EL, TTYCODE_STRING, "el" },
|
{ TTYC_EL, TTYCODE_STRING, "el" },
|
||||||
{ TTYC_EL1, TTYCODE_STRING, "el1" },
|
{ TTYC_EL1, TTYCODE_STRING, "el1" },
|
||||||
{ TTYC_ENACS, TTYCODE_STRING, "enacs" },
|
{ TTYC_ENACS, TTYCODE_STRING, "enacs" },
|
||||||
{ TTYC_HOME, TTYCODE_STRING, "home" },
|
|
||||||
{ TTYC_HPA, TTYCODE_STRING, "hpa" },
|
|
||||||
{ TTYC_ICH, TTYCODE_STRING, "ich" },
|
{ TTYC_ICH, TTYCODE_STRING, "ich" },
|
||||||
{ TTYC_ICH1, TTYCODE_STRING, "ich1" },
|
{ TTYC_ICH1, TTYCODE_STRING, "ich1" },
|
||||||
{ TTYC_IL, TTYCODE_STRING, "il" },
|
{ TTYC_IL, TTYCODE_STRING, "il" },
|
||||||
@@ -74,26 +66,8 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
|
|||||||
{ TTYC_KCUD1, TTYCODE_STRING, "kcud1" },
|
{ TTYC_KCUD1, TTYCODE_STRING, "kcud1" },
|
||||||
{ TTYC_KCUF1, TTYCODE_STRING, "kcuf1" },
|
{ TTYC_KCUF1, TTYCODE_STRING, "kcuf1" },
|
||||||
{ TTYC_KCUU1, TTYCODE_STRING, "kcuu1" },
|
{ TTYC_KCUU1, TTYCODE_STRING, "kcuu1" },
|
||||||
{ TTYC_KDC2, TTYCODE_STRING, "kDC" },
|
|
||||||
{ TTYC_KDC3, TTYCODE_STRING, "kDC3" },
|
|
||||||
{ TTYC_KDC4, TTYCODE_STRING, "kDC4" },
|
|
||||||
{ TTYC_KDC5, TTYCODE_STRING, "kDC5" },
|
|
||||||
{ TTYC_KDC6, TTYCODE_STRING, "kDC6" },
|
|
||||||
{ TTYC_KDC7, TTYCODE_STRING, "kDC7" },
|
|
||||||
{ TTYC_KDCH1, TTYCODE_STRING, "kdch1" },
|
{ TTYC_KDCH1, TTYCODE_STRING, "kdch1" },
|
||||||
{ TTYC_KDN2, TTYCODE_STRING, "kDN" },
|
|
||||||
{ TTYC_KDN3, TTYCODE_STRING, "kDN3" },
|
|
||||||
{ TTYC_KDN4, TTYCODE_STRING, "kDN4" },
|
|
||||||
{ TTYC_KDN5, TTYCODE_STRING, "kDN5" },
|
|
||||||
{ TTYC_KDN6, TTYCODE_STRING, "kDN6" },
|
|
||||||
{ TTYC_KDN7, TTYCODE_STRING, "kDN7" },
|
|
||||||
{ TTYC_KEND, TTYCODE_STRING, "kend" },
|
{ TTYC_KEND, TTYCODE_STRING, "kend" },
|
||||||
{ TTYC_KEND2, TTYCODE_STRING, "kEND" },
|
|
||||||
{ TTYC_KEND3, TTYCODE_STRING, "kEND3" },
|
|
||||||
{ TTYC_KEND4, TTYCODE_STRING, "kEND4" },
|
|
||||||
{ TTYC_KEND5, TTYCODE_STRING, "kEND5" },
|
|
||||||
{ TTYC_KEND6, TTYCODE_STRING, "kEND6" },
|
|
||||||
{ TTYC_KEND7, TTYCODE_STRING, "kEND7" },
|
|
||||||
{ TTYC_KF1, TTYCODE_STRING, "kf1" },
|
{ TTYC_KF1, TTYCODE_STRING, "kf1" },
|
||||||
{ TTYC_KF10, TTYCODE_STRING, "kf10" },
|
{ TTYC_KF10, TTYCODE_STRING, "kf10" },
|
||||||
{ TTYC_KF11, TTYCODE_STRING, "kf11" },
|
{ TTYC_KF11, TTYCODE_STRING, "kf11" },
|
||||||
@@ -105,8 +79,8 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
|
|||||||
{ TTYC_KF17, TTYCODE_STRING, "kf17" },
|
{ TTYC_KF17, TTYCODE_STRING, "kf17" },
|
||||||
{ TTYC_KF18, TTYCODE_STRING, "kf18" },
|
{ TTYC_KF18, TTYCODE_STRING, "kf18" },
|
||||||
{ TTYC_KF19, TTYCODE_STRING, "kf19" },
|
{ TTYC_KF19, TTYCODE_STRING, "kf19" },
|
||||||
{ TTYC_KF2, TTYCODE_STRING, "kf2" },
|
|
||||||
{ TTYC_KF20, TTYCODE_STRING, "kf20" },
|
{ TTYC_KF20, TTYCODE_STRING, "kf20" },
|
||||||
|
{ TTYC_KF2, TTYCODE_STRING, "kf2" },
|
||||||
{ TTYC_KF3, TTYCODE_STRING, "kf3" },
|
{ TTYC_KF3, TTYCODE_STRING, "kf3" },
|
||||||
{ TTYC_KF4, TTYCODE_STRING, "kf4" },
|
{ TTYC_KF4, TTYCODE_STRING, "kf4" },
|
||||||
{ TTYC_KF5, TTYCODE_STRING, "kf5" },
|
{ TTYC_KF5, TTYCODE_STRING, "kf5" },
|
||||||
@@ -114,53 +88,11 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
|
|||||||
{ TTYC_KF7, TTYCODE_STRING, "kf7" },
|
{ TTYC_KF7, TTYCODE_STRING, "kf7" },
|
||||||
{ TTYC_KF8, TTYCODE_STRING, "kf8" },
|
{ TTYC_KF8, TTYCODE_STRING, "kf8" },
|
||||||
{ TTYC_KF9, TTYCODE_STRING, "kf9" },
|
{ TTYC_KF9, TTYCODE_STRING, "kf9" },
|
||||||
{ TTYC_KHOM2, TTYCODE_STRING, "kHOM" },
|
|
||||||
{ TTYC_KHOM3, TTYCODE_STRING, "kHOM3" },
|
|
||||||
{ TTYC_KHOM4, TTYCODE_STRING, "kHOM4" },
|
|
||||||
{ TTYC_KHOM5, TTYCODE_STRING, "kHOM5" },
|
|
||||||
{ TTYC_KHOM6, TTYCODE_STRING, "kHOM6" },
|
|
||||||
{ TTYC_KHOM7, TTYCODE_STRING, "kHOM7" },
|
|
||||||
{ TTYC_KHOME, TTYCODE_STRING, "khome" },
|
{ TTYC_KHOME, TTYCODE_STRING, "khome" },
|
||||||
{ TTYC_KIC2, TTYCODE_STRING, "kIC" },
|
|
||||||
{ TTYC_KIC3, TTYCODE_STRING, "kIC3" },
|
|
||||||
{ TTYC_KIC4, TTYCODE_STRING, "kIC4" },
|
|
||||||
{ TTYC_KIC5, TTYCODE_STRING, "kIC5" },
|
|
||||||
{ TTYC_KIC6, TTYCODE_STRING, "kIC6" },
|
|
||||||
{ TTYC_KIC7, TTYCODE_STRING, "kIC7" },
|
|
||||||
{ TTYC_KICH1, TTYCODE_STRING, "kich1" },
|
{ TTYC_KICH1, TTYCODE_STRING, "kich1" },
|
||||||
{ TTYC_KLFT2, TTYCODE_STRING, "kLFT" },
|
|
||||||
{ TTYC_KLFT3, TTYCODE_STRING, "kLFT3" },
|
|
||||||
{ TTYC_KLFT4, TTYCODE_STRING, "kLFT4" },
|
|
||||||
{ TTYC_KLFT5, TTYCODE_STRING, "kLFT5" },
|
|
||||||
{ TTYC_KLFT6, TTYCODE_STRING, "kLFT6" },
|
|
||||||
{ TTYC_KLFT7, TTYCODE_STRING, "kLFT7" },
|
|
||||||
{ TTYC_KMOUS, TTYCODE_STRING, "kmous" },
|
{ TTYC_KMOUS, TTYCODE_STRING, "kmous" },
|
||||||
{ TTYC_KNP, TTYCODE_STRING, "knp" },
|
{ TTYC_KNP, TTYCODE_STRING, "knp" },
|
||||||
{ TTYC_KNXT2, TTYCODE_STRING, "kNXT" },
|
|
||||||
{ TTYC_KNXT3, TTYCODE_STRING, "kNXT3" },
|
|
||||||
{ TTYC_KNXT4, TTYCODE_STRING, "kNXT4" },
|
|
||||||
{ TTYC_KNXT5, TTYCODE_STRING, "kNXT5" },
|
|
||||||
{ TTYC_KNXT6, TTYCODE_STRING, "kNXT6" },
|
|
||||||
{ TTYC_KNXT7, TTYCODE_STRING, "kNXT7" },
|
|
||||||
{ TTYC_KPP, TTYCODE_STRING, "kpp" },
|
{ TTYC_KPP, TTYCODE_STRING, "kpp" },
|
||||||
{ TTYC_KPRV2, TTYCODE_STRING, "kPRV" },
|
|
||||||
{ TTYC_KPRV3, TTYCODE_STRING, "kPRV3" },
|
|
||||||
{ TTYC_KPRV4, TTYCODE_STRING, "kPRV4" },
|
|
||||||
{ TTYC_KPRV5, TTYCODE_STRING, "kPRV5" },
|
|
||||||
{ TTYC_KPRV6, TTYCODE_STRING, "kPRV6" },
|
|
||||||
{ TTYC_KPRV7, TTYCODE_STRING, "kPRV7" },
|
|
||||||
{ TTYC_KRIT2, TTYCODE_STRING, "kRIT" },
|
|
||||||
{ TTYC_KRIT3, TTYCODE_STRING, "kRIT3" },
|
|
||||||
{ TTYC_KRIT4, TTYCODE_STRING, "kRIT4" },
|
|
||||||
{ TTYC_KRIT5, TTYCODE_STRING, "kRIT5" },
|
|
||||||
{ TTYC_KRIT6, TTYCODE_STRING, "kRIT6" },
|
|
||||||
{ TTYC_KRIT7, TTYCODE_STRING, "kRIT7" },
|
|
||||||
{ TTYC_KUP2, TTYCODE_STRING, "kUP" },
|
|
||||||
{ TTYC_KUP3, TTYCODE_STRING, "kUP3" },
|
|
||||||
{ TTYC_KUP4, TTYCODE_STRING, "kUP4" },
|
|
||||||
{ TTYC_KUP5, TTYCODE_STRING, "kUP5" },
|
|
||||||
{ TTYC_KUP6, TTYCODE_STRING, "kUP6" },
|
|
||||||
{ TTYC_KUP7, TTYCODE_STRING, "kUP7" },
|
|
||||||
{ TTYC_OP, TTYCODE_STRING, "op" },
|
{ TTYC_OP, TTYCODE_STRING, "op" },
|
||||||
{ TTYC_REV, TTYCODE_STRING, "rev" },
|
{ TTYC_REV, TTYCODE_STRING, "rev" },
|
||||||
{ TTYC_RI, TTYCODE_STRING, "ri" },
|
{ TTYC_RI, TTYCODE_STRING, "ri" },
|
||||||
@@ -177,7 +109,6 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
|
|||||||
{ TTYC_SMKX, TTYCODE_STRING, "smkx" },
|
{ TTYC_SMKX, TTYCODE_STRING, "smkx" },
|
||||||
{ TTYC_SMSO, TTYCODE_STRING, "smso" },
|
{ TTYC_SMSO, TTYCODE_STRING, "smso" },
|
||||||
{ TTYC_SMUL, TTYCODE_STRING, "smul" },
|
{ TTYC_SMUL, TTYCODE_STRING, "smul" },
|
||||||
{ TTYC_VPA, TTYCODE_STRING, "vpa" },
|
|
||||||
{ TTYC_XENL, TTYCODE_FLAG, "xenl" },
|
{ TTYC_XENL, TTYCODE_FLAG, "xenl" },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -407,7 +338,22 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Figure out if we have 256 or 88 colours. */
|
/*
|
||||||
|
* Figure out if terminal support default colours. AX is a screen
|
||||||
|
* extension which indicates this. Also check if op (orig_pair) uses
|
||||||
|
* the default colours - if it does, this is a good indication the
|
||||||
|
* terminal supports them.
|
||||||
|
*/
|
||||||
|
if (tty_term_flag(term, TTYC_AX))
|
||||||
|
term->flags |= TERM_HASDEFAULTS;
|
||||||
|
if (strcmp(tty_term_string(term, TTYC_OP), "\033[39;49m") == 0)
|
||||||
|
term->flags |= TERM_HASDEFAULTS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to figure out if we have 256 or 88 colours. The standard xterm
|
||||||
|
* definitions are broken (well, or the way they are parsed is: in any
|
||||||
|
* case they end up returning 8). So also do a hack.
|
||||||
|
*/
|
||||||
if (tty_term_number(term, TTYC_COLORS) == 256)
|
if (tty_term_number(term, TTYC_COLORS) == 256)
|
||||||
term->flags |= TERM_256COLOURS;
|
term->flags |= TERM_256COLOURS;
|
||||||
if (tty_term_number(term, TTYC_COLORS) == 88)
|
if (tty_term_number(term, TTYC_COLORS) == 88)
|
||||||
@@ -471,13 +417,13 @@ tty_term_string(struct tty_term *term, enum tty_code_code code)
|
|||||||
const char *
|
const char *
|
||||||
tty_term_string1(struct tty_term *term, enum tty_code_code code, int a)
|
tty_term_string1(struct tty_term *term, enum tty_code_code code, int a)
|
||||||
{
|
{
|
||||||
return (tparm((char *) tty_term_string(term, code), a, 0, 0, 0, 0, 0, 0, 0, 0));
|
return (tparm((char *) tty_term_string(term, code), a));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
tty_term_string2(struct tty_term *term, enum tty_code_code code, int a, int b)
|
tty_term_string2(struct tty_term *term, enum tty_code_code code, int a, int b)
|
||||||
{
|
{
|
||||||
return (tparm((char *) tty_term_string(term, code), a, b, 0, 0, 0, 0, 0, 0, 0));
|
return (tparm((char *) tty_term_string(term, code), a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
122
utf8.c
122
utf8.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: utf8.c,v 1.11 2009-10-23 17:21:34 tcunha Exp $ */
|
/* $Id: utf8.c,v 1.9 2009-06-25 16:21:32 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -196,56 +196,9 @@ struct utf8_width_entry utf8_width_table[] = {
|
|||||||
struct utf8_width_entry *utf8_width_root = NULL;
|
struct utf8_width_entry *utf8_width_root = NULL;
|
||||||
|
|
||||||
int utf8_overlap(struct utf8_width_entry *, struct utf8_width_entry *);
|
int utf8_overlap(struct utf8_width_entry *, struct utf8_width_entry *);
|
||||||
u_int utf8_combine(const struct utf8_data *);
|
void utf8_print(struct utf8_width_entry *, int);
|
||||||
u_int utf8_width(const struct utf8_data *);
|
u_int utf8_combine(const u_char *);
|
||||||
|
|
||||||
/*
|
|
||||||
* Open UTF-8 sequence.
|
|
||||||
*
|
|
||||||
* 11000010-11011111 C2-DF start of 2-byte sequence
|
|
||||||
* 11100000-11101111 E0-EF start of 3-byte sequence
|
|
||||||
* 11110000-11110100 F0-F4 start of 4-byte sequence
|
|
||||||
*
|
|
||||||
* Returns 1 if more UTF-8 to come, 0 if not UTF-8.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
utf8_open(struct utf8_data *utf8data, u_char ch)
|
|
||||||
{
|
|
||||||
memset(utf8data, 0, sizeof *utf8data);
|
|
||||||
if (ch >= 0xc2 && ch <= 0xdf)
|
|
||||||
utf8data->size = 2;
|
|
||||||
else if (ch >= 0xe0 && ch <= 0xef)
|
|
||||||
utf8data->size = 3;
|
|
||||||
else if (ch >= 0xf0 && ch <= 0xf4)
|
|
||||||
utf8data->size = 4;
|
|
||||||
else
|
|
||||||
return (0);
|
|
||||||
utf8_append(utf8data, ch);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Append character to UTF-8, closing if finished.
|
|
||||||
*
|
|
||||||
* Returns 1 if more UTF-8 data to come, 0 if finished.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
utf8_append(struct utf8_data *utf8data, u_char ch)
|
|
||||||
{
|
|
||||||
if (utf8data->have >= utf8data->size)
|
|
||||||
fatalx("UTF-8 character overflow");
|
|
||||||
if (utf8data->size > sizeof utf8data->data)
|
|
||||||
fatalx("UTF-8 character size too large");
|
|
||||||
|
|
||||||
utf8data->data[utf8data->have++] = ch;
|
|
||||||
if (utf8data->have != utf8data->size)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
utf8data->width = utf8_width(utf8data);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if two width tree entries overlap. */
|
|
||||||
int
|
int
|
||||||
utf8_overlap(
|
utf8_overlap(
|
||||||
struct utf8_width_entry *item1, struct utf8_width_entry *item2)
|
struct utf8_width_entry *item1, struct utf8_width_entry *item2)
|
||||||
@@ -261,7 +214,6 @@ utf8_overlap(
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build UTF-8 width tree. */
|
|
||||||
void
|
void
|
||||||
utf8_build(void)
|
utf8_build(void)
|
||||||
{
|
{
|
||||||
@@ -288,50 +240,52 @@ utf8_build(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combine UTF-8 into 32-bit Unicode. */
|
void
|
||||||
u_int
|
utf8_print(struct utf8_width_entry *node, int n)
|
||||||
utf8_combine(const struct utf8_data *utf8data)
|
|
||||||
{
|
{
|
||||||
u_int value;
|
log_debug("%*s%04x -> %04x", n, " ", node->first, node->last);
|
||||||
|
if (node->left != NULL)
|
||||||
value = 0xff;
|
utf8_print(node->left, n + 1);
|
||||||
switch (utf8data->size) {
|
if (node->right != NULL)
|
||||||
case 1:
|
utf8_print(node->right, n + 1);
|
||||||
value = utf8data->data[0];
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
value = utf8data->data[1] & 0x3f;
|
|
||||||
value |= (utf8data->data[0] & 0x1f) << 6;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
value = utf8data->data[2] & 0x3f;
|
|
||||||
value |= (utf8data->data[1] & 0x3f) << 6;
|
|
||||||
value |= (utf8data->data[0] & 0x0f) << 12;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
value = utf8data->data[3] & 0x3f;
|
|
||||||
value |= (utf8data->data[2] & 0x3f) << 6;
|
|
||||||
value |= (utf8data->data[1] & 0x3f) << 12;
|
|
||||||
value |= (utf8data->data[0] & 0x3f) << 18;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup width of UTF-8 data in tree. */
|
|
||||||
u_int
|
u_int
|
||||||
utf8_width(const struct utf8_data *utf8data)
|
utf8_combine(const u_char *data)
|
||||||
|
{
|
||||||
|
u_int uvalue;
|
||||||
|
|
||||||
|
if (data[1] == 0xff)
|
||||||
|
uvalue = data[0];
|
||||||
|
else if (data[2] == 0xff) {
|
||||||
|
uvalue = data[1] & 0x3f;
|
||||||
|
uvalue |= (data[0] & 0x1f) << 6;
|
||||||
|
} else if (data[3] == 0xff) {
|
||||||
|
uvalue = data[2] & 0x3f;
|
||||||
|
uvalue |= (data[1] & 0x3f) << 6;
|
||||||
|
uvalue |= (data[0] & 0x0f) << 12;
|
||||||
|
} else {
|
||||||
|
uvalue = data[3] & 0x3f;
|
||||||
|
uvalue |= (data[2] & 0x3f) << 6;
|
||||||
|
uvalue |= (data[1] & 0x3f) << 12;
|
||||||
|
uvalue |= (data[0] & 0x3f) << 18;
|
||||||
|
}
|
||||||
|
return (uvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
utf8_width(const u_char *udata)
|
||||||
{
|
{
|
||||||
struct utf8_width_entry *item;
|
struct utf8_width_entry *item;
|
||||||
u_int value;
|
u_int uvalue;
|
||||||
|
|
||||||
value = utf8_combine(utf8data);
|
uvalue = utf8_combine(udata);
|
||||||
|
|
||||||
item = utf8_width_root;
|
item = utf8_width_root;
|
||||||
while (item != NULL) {
|
while (item != NULL) {
|
||||||
if (value < item->first)
|
if (uvalue < item->first)
|
||||||
item = item->left;
|
item = item->left;
|
||||||
else if (value > item->last)
|
else if (uvalue > item->last)
|
||||||
item = item->right;
|
item = item->right;
|
||||||
else
|
else
|
||||||
return (item->width);
|
return (item->width);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: window-choose.c,v 1.24 2009-10-12 00:18:19 tcunha Exp $ */
|
/* $Id: window-choose.c,v 1.23 2009-09-11 14:13:52 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -27,7 +27,7 @@ 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 client *, int);
|
void window_choose_key(struct window_pane *, struct client *, int);
|
||||||
void window_choose_mouse(
|
void window_choose_mouse(
|
||||||
struct window_pane *, struct client *, struct mouse_event *);
|
struct window_pane *, struct client *, u_char, u_char, u_char);
|
||||||
|
|
||||||
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(
|
||||||
@@ -264,22 +264,22 @@ window_choose_key(struct window_pane *wp, unused struct client *c, int key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_choose_mouse(
|
window_choose_mouse(struct window_pane *wp,
|
||||||
struct window_pane *wp, unused struct client *c, struct mouse_event *m)
|
unused struct client *c, u_char b, u_char x, u_char y)
|
||||||
{
|
{
|
||||||
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;
|
||||||
struct window_choose_mode_item *item;
|
struct window_choose_mode_item *item;
|
||||||
u_int idx;
|
u_int idx;
|
||||||
|
|
||||||
if ((m->b & 3) == 3)
|
if ((b & 3) == 3)
|
||||||
return;
|
return;
|
||||||
if (m->x >= screen_size_x(s))
|
if (x >= screen_size_x(s))
|
||||||
return;
|
return;
|
||||||
if (m->y >= screen_size_y(s))
|
if (y >= screen_size_y(s))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
idx = data->top + m->y;
|
idx = data->top + y;
|
||||||
if (idx >= ARRAY_LENGTH(&data->list))
|
if (idx >= ARRAY_LENGTH(&data->list))
|
||||||
return;
|
return;
|
||||||
data->selected = idx;
|
data->selected = idx;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: window-copy.c,v 1.90 2009-10-23 17:17:20 tcunha Exp $ */
|
/* $Id: window-copy.c,v 1.86 2009-09-11 14:13:52 tcunha Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -29,7 +29,7 @@ void window_copy_resize(struct window_pane *, u_int, u_int);
|
|||||||
void window_copy_key(struct window_pane *, struct client *, int);
|
void window_copy_key(struct window_pane *, struct client *, int);
|
||||||
int window_copy_key_input(struct window_pane *, int);
|
int window_copy_key_input(struct window_pane *, int);
|
||||||
void window_copy_mouse(
|
void window_copy_mouse(
|
||||||
struct window_pane *, struct client *, struct mouse_event *);
|
struct window_pane *, struct client *, u_char, u_char, u_char);
|
||||||
|
|
||||||
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 *);
|
||||||
@@ -61,8 +61,8 @@ void window_copy_cursor_back_to_indentation(struct window_pane *);
|
|||||||
void window_copy_cursor_end_of_line(struct window_pane *);
|
void window_copy_cursor_end_of_line(struct window_pane *);
|
||||||
void window_copy_cursor_left(struct window_pane *);
|
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 *);
|
||||||
void window_copy_cursor_down(struct window_pane *, int);
|
void window_copy_cursor_down(struct window_pane *);
|
||||||
void window_copy_cursor_next_word(struct window_pane *);
|
void window_copy_cursor_next_word(struct window_pane *);
|
||||||
void window_copy_cursor_previous_word(struct window_pane *);
|
void window_copy_cursor_previous_word(struct window_pane *);
|
||||||
void window_copy_scroll_up(struct window_pane *, u_int);
|
void window_copy_scroll_up(struct window_pane *, u_int);
|
||||||
@@ -235,17 +235,11 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
|||||||
window_copy_cursor_right(wp);
|
window_copy_cursor_right(wp);
|
||||||
return;
|
return;
|
||||||
case MODEKEYCOPY_UP:
|
case MODEKEYCOPY_UP:
|
||||||
window_copy_cursor_up(wp, 0);
|
window_copy_cursor_up(wp);
|
||||||
return;
|
return;
|
||||||
case MODEKEYCOPY_DOWN:
|
case MODEKEYCOPY_DOWN:
|
||||||
window_copy_cursor_down(wp, 0);
|
window_copy_cursor_down(wp);
|
||||||
return;
|
return;
|
||||||
case MODEKEYCOPY_SCROLLUP:
|
|
||||||
window_copy_cursor_up(wp, 1);
|
|
||||||
break;
|
|
||||||
case MODEKEYCOPY_SCROLLDOWN:
|
|
||||||
window_copy_cursor_down(wp, 1);
|
|
||||||
break;
|
|
||||||
case MODEKEYCOPY_PREVIOUSPAGE:
|
case MODEKEYCOPY_PREVIOUSPAGE:
|
||||||
window_copy_pageup(wp);
|
window_copy_pageup(wp);
|
||||||
break;
|
break;
|
||||||
@@ -278,24 +272,6 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
|
|||||||
window_copy_update_selection(wp);
|
window_copy_update_selection(wp);
|
||||||
window_copy_redraw_screen(wp);
|
window_copy_redraw_screen(wp);
|
||||||
break;
|
break;
|
||||||
case MODEKEYCOPY_TOPLINE:
|
|
||||||
data->cx = 0;
|
|
||||||
data->cy = 0;
|
|
||||||
window_copy_update_selection(wp);
|
|
||||||
window_copy_redraw_screen(wp);
|
|
||||||
break;
|
|
||||||
case MODEKEYCOPY_MIDDLELINE:
|
|
||||||
data->cx = 0;
|
|
||||||
data->cy = (screen_size_y(s) - 1) / 2;
|
|
||||||
window_copy_update_selection(wp);
|
|
||||||
window_copy_redraw_screen(wp);
|
|
||||||
break;
|
|
||||||
case MODEKEYCOPY_BOTTOMLINE:
|
|
||||||
data->cx = 0;
|
|
||||||
data->cy = screen_size_y(s) - 1;
|
|
||||||
window_copy_update_selection(wp);
|
|
||||||
window_copy_redraw_screen(wp);
|
|
||||||
break;
|
|
||||||
case MODEKEYCOPY_STARTSELECTION:
|
case MODEKEYCOPY_STARTSELECTION:
|
||||||
window_copy_start_selection(wp);
|
window_copy_start_selection(wp);
|
||||||
window_copy_redraw_screen(wp);
|
window_copy_redraw_screen(wp);
|
||||||
@@ -436,20 +412,20 @@ window_copy_key_input(struct window_pane *wp, int key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_mouse(
|
window_copy_mouse(struct window_pane *wp,
|
||||||
struct window_pane *wp, unused struct client *c, struct mouse_event *m)
|
unused struct client *c, u_char b, u_char x, u_char y)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
if ((m->b & 3) == 3)
|
if ((b & 3) == 3)
|
||||||
return;
|
return;
|
||||||
if (m->x >= screen_size_x(s))
|
if (x >= screen_size_x(s))
|
||||||
return;
|
return;
|
||||||
if (m->y >= screen_size_y(s))
|
if (y >= screen_size_y(s))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window_copy_update_cursor(wp, m->x, m->y);
|
window_copy_update_cursor(wp, x, y);
|
||||||
if (window_copy_update_selection(wp))
|
if (window_copy_update_selection(wp))
|
||||||
window_copy_redraw_screen(wp);
|
window_copy_redraw_screen(wp);
|
||||||
}
|
}
|
||||||
@@ -1044,7 +1020,7 @@ window_copy_cursor_left(struct window_pane *wp)
|
|||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
|
|
||||||
if (data->cx == 0) {
|
if (data->cx == 0) {
|
||||||
window_copy_cursor_up(wp, 0);
|
window_copy_cursor_up(wp);
|
||||||
window_copy_cursor_end_of_line(wp);
|
window_copy_cursor_end_of_line(wp);
|
||||||
} else {
|
} else {
|
||||||
window_copy_update_cursor(wp, data->cx - 1, data->cy);
|
window_copy_update_cursor(wp, data->cx - 1, data->cy);
|
||||||
@@ -1064,7 +1040,7 @@ window_copy_cursor_right(struct window_pane *wp)
|
|||||||
|
|
||||||
if (data->cx >= px) {
|
if (data->cx >= px) {
|
||||||
window_copy_cursor_start_of_line(wp);
|
window_copy_cursor_start_of_line(wp);
|
||||||
window_copy_cursor_down(wp, 0);
|
window_copy_cursor_down(wp);
|
||||||
} else {
|
} else {
|
||||||
window_copy_update_cursor(wp, data->cx + 1, data->cy);
|
window_copy_update_cursor(wp, data->cx + 1, data->cy);
|
||||||
if (window_copy_update_selection(wp))
|
if (window_copy_update_selection(wp))
|
||||||
@@ -1073,7 +1049,7 @@ window_copy_cursor_right(struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
window_copy_cursor_up(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wp->modedata;
|
struct window_copy_mode_data *data = wp->modedata;
|
||||||
u_int ox, oy, px, py;
|
u_int ox, oy, px, py;
|
||||||
@@ -1086,11 +1062,9 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
data->cx = data->lastcx;
|
data->cx = data->lastcx;
|
||||||
if (scroll_only || data->cy == 0) {
|
if (data->cy == 0)
|
||||||
window_copy_scroll_down(wp, 1);
|
window_copy_scroll_down(wp, 1);
|
||||||
if (scroll_only)
|
else {
|
||||||
window_copy_redraw_lines(wp, data->cy, 2);
|
|
||||||
} else {
|
|
||||||
window_copy_update_cursor(wp, data->cx, data->cy - 1);
|
window_copy_update_cursor(wp, data->cx, data->cy - 1);
|
||||||
if (window_copy_update_selection(wp))
|
if (window_copy_update_selection(wp))
|
||||||
window_copy_redraw_lines(wp, data->cy, 2);
|
window_copy_redraw_lines(wp, data->cy, 2);
|
||||||
@@ -1103,7 +1077,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
window_copy_cursor_down(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
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;
|
||||||
@@ -1117,11 +1091,9 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
|||||||
}
|
}
|
||||||
|
|
||||||
data->cx = data->lastcx;
|
data->cx = data->lastcx;
|
||||||
if (scroll_only || data->cy == screen_size_y(s) - 1) {
|
if (data->cy == screen_size_y(s) - 1)
|
||||||
window_copy_scroll_up(wp, 1);
|
window_copy_scroll_up(wp, 1);
|
||||||
if (scroll_only && data->cy > 0)
|
else {
|
||||||
window_copy_redraw_lines(wp, data->cy - 1, 2);
|
|
||||||
} else {
|
|
||||||
window_copy_update_cursor(wp, data->cx, data->cy + 1);
|
window_copy_update_cursor(wp, data->cx, data->cy + 1);
|
||||||
if (window_copy_update_selection(wp))
|
if (window_copy_update_selection(wp))
|
||||||
window_copy_redraw_lines(wp, data->cy - 1, 2);
|
window_copy_redraw_lines(wp, data->cy - 1, 2);
|
||||||
@@ -1165,7 +1137,7 @@ window_copy_cursor_next_word(struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
px = 0;
|
px = 0;
|
||||||
window_copy_cursor_down(wp, 0);
|
window_copy_cursor_down(wp);
|
||||||
|
|
||||||
py =screen_hsize(
|
py =screen_hsize(
|
||||||
&wp->base) + data->cy - data->oy;
|
&wp->base) + data->cy - data->oy;
|
||||||
@@ -1213,7 +1185,7 @@ window_copy_cursor_previous_word(struct window_pane *wp)
|
|||||||
(screen_hsize(&wp->base) == 0 ||
|
(screen_hsize(&wp->base) == 0 ||
|
||||||
data->oy >= screen_hsize(&wp->base) - 1))
|
data->oy >= screen_hsize(&wp->base) - 1))
|
||||||
goto out;
|
goto out;
|
||||||
window_copy_cursor_up(wp, 0);
|
window_copy_cursor_up(wp);
|
||||||
|
|
||||||
py = screen_hsize(
|
py = screen_hsize(
|
||||||
&wp->base) + data->cy - data->oy;
|
&wp->base) + data->cy - data->oy;
|
||||||
@@ -1250,10 +1222,7 @@ window_copy_scroll_up(struct window_pane *wp, u_int ny)
|
|||||||
screen_write_deleteline(&ctx, ny);
|
screen_write_deleteline(&ctx, ny);
|
||||||
window_copy_write_lines(wp, &ctx, screen_size_y(s) - ny, ny);
|
window_copy_write_lines(wp, &ctx, screen_size_y(s) - ny, ny);
|
||||||
window_copy_write_line(wp, &ctx, 0);
|
window_copy_write_line(wp, &ctx, 0);
|
||||||
if (screen_size_y(s) > 1)
|
window_copy_write_line(wp, &ctx, 1);
|
||||||
window_copy_write_line(wp, &ctx, 1);
|
|
||||||
if (screen_size_y(s) > 3)
|
|
||||||
window_copy_write_line(wp, &ctx, screen_size_y(s) - 2);
|
|
||||||
if (s->sel.flag && screen_size_y(s) > ny)
|
if (s->sel.flag && screen_size_y(s) > ny)
|
||||||
window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1);
|
window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1);
|
||||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||||
|
|||||||
323
window-scroll.c
Normal file
323
window-scroll.c
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
/* $Id: window-scroll.c,v 1.41 2009-09-11 14:13:52 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_scroll_init(struct window_pane *);
|
||||||
|
void window_scroll_free(struct window_pane *);
|
||||||
|
void window_scroll_resize(struct window_pane *, u_int, u_int);
|
||||||
|
void window_scroll_key(struct window_pane *, struct client *, int);
|
||||||
|
|
||||||
|
void window_scroll_redraw_screen(struct window_pane *);
|
||||||
|
void window_scroll_write_line(
|
||||||
|
struct window_pane *, struct screen_write_ctx *, u_int);
|
||||||
|
void window_scroll_write_column(
|
||||||
|
struct window_pane *, struct screen_write_ctx *, u_int);
|
||||||
|
|
||||||
|
void window_scroll_scroll_up(struct window_pane *);
|
||||||
|
void window_scroll_scroll_down(struct window_pane *);
|
||||||
|
void window_scroll_scroll_left(struct window_pane *);
|
||||||
|
void window_scroll_scroll_right(struct window_pane *);
|
||||||
|
|
||||||
|
const struct window_mode window_scroll_mode = {
|
||||||
|
window_scroll_init,
|
||||||
|
window_scroll_free,
|
||||||
|
window_scroll_resize,
|
||||||
|
window_scroll_key,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct window_scroll_mode_data {
|
||||||
|
struct screen screen;
|
||||||
|
|
||||||
|
struct mode_key_data mdata;
|
||||||
|
|
||||||
|
u_int ox;
|
||||||
|
u_int oy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct screen *
|
||||||
|
window_scroll_init(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data;
|
||||||
|
struct screen *s;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
u_int i;
|
||||||
|
int keys;
|
||||||
|
|
||||||
|
wp->modedata = data = xmalloc(sizeof *data);
|
||||||
|
data->ox = 0;
|
||||||
|
data->oy = 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_copy);
|
||||||
|
else
|
||||||
|
mode_key_init(&data->mdata, &mode_key_tree_vi_copy);
|
||||||
|
|
||||||
|
screen_write_start(&ctx, NULL, s);
|
||||||
|
for (i = 0; i < screen_size_y(s); i++)
|
||||||
|
window_scroll_write_line(wp, &ctx, i);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
|
||||||
|
return (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_free(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
|
||||||
|
screen_free(&data->screen);
|
||||||
|
xfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_pageup(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
u_int n;
|
||||||
|
|
||||||
|
n = 1;
|
||||||
|
if (screen_size_y(s) > 2)
|
||||||
|
n = screen_size_y(s) - 2;
|
||||||
|
if (data->oy + n > screen_hsize(&wp->base))
|
||||||
|
data->oy = screen_hsize(&wp->base);
|
||||||
|
else
|
||||||
|
data->oy += n;
|
||||||
|
|
||||||
|
window_scroll_redraw_screen(wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
screen_resize(s, sx, sy);
|
||||||
|
screen_write_start(&ctx, NULL, s);
|
||||||
|
for (i = 0; i < screen_size_y(s); i++)
|
||||||
|
window_scroll_write_line(wp, &ctx, i);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_key(struct window_pane *wp, unused struct client *c, int key)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
u_int n;
|
||||||
|
|
||||||
|
switch (mode_key_lookup(&data->mdata, key)) {
|
||||||
|
case MODEKEYCOPY_CANCEL:
|
||||||
|
window_pane_reset_mode(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCOPY_LEFT:
|
||||||
|
window_scroll_scroll_left(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCOPY_RIGHT:
|
||||||
|
window_scroll_scroll_right(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCOPY_UP:
|
||||||
|
window_scroll_scroll_up(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCOPY_DOWN:
|
||||||
|
window_scroll_scroll_down(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCOPY_PREVIOUSPAGE:
|
||||||
|
window_scroll_pageup(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCOPY_NEXTPAGE:
|
||||||
|
n = 1;
|
||||||
|
if (screen_size_y(s) > 2)
|
||||||
|
n = screen_size_y(s) - 2;
|
||||||
|
if (data->oy < n)
|
||||||
|
data->oy = 0;
|
||||||
|
else
|
||||||
|
data->oy -= n;
|
||||||
|
window_scroll_redraw_screen(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCOPY_HALFPAGEUP:
|
||||||
|
n = screen_size_y(s) / 2;
|
||||||
|
if (data->oy + n > screen_hsize(&wp->base))
|
||||||
|
data->oy = screen_hsize(&wp->base);
|
||||||
|
else
|
||||||
|
data->oy += n;
|
||||||
|
window_scroll_redraw_screen(wp);
|
||||||
|
break;
|
||||||
|
case MODEKEYCOPY_HALFPAGEDOWN:
|
||||||
|
n = screen_size_y(s) / 2;
|
||||||
|
if (data->oy < n)
|
||||||
|
data->oy = 0;
|
||||||
|
else
|
||||||
|
data->oy -= n;
|
||||||
|
window_scroll_redraw_screen(wp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_write_line(
|
||||||
|
struct window_pane *wp, struct screen_write_ctx *ctx, u_int py)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct options *oo = &wp->window->options;
|
||||||
|
struct grid_cell gc;
|
||||||
|
char hdr[32];
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
if (py == 0) {
|
||||||
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
|
size = xsnprintf(hdr, sizeof hdr,
|
||||||
|
"[%u,%u/%u]", data->ox, data->oy, screen_hsize(&wp->base));
|
||||||
|
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_cursormove(ctx, screen_size_x(s) - size, 0);
|
||||||
|
screen_write_puts(ctx, &gc, "%s", hdr);
|
||||||
|
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||||
|
} else
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
screen_write_cursormove(ctx, 0, py);
|
||||||
|
screen_write_copy(ctx, &wp->base, data->ox, (screen_hsize(&wp->base) -
|
||||||
|
data->oy) + py, screen_size_x(s) - size, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_write_column(
|
||||||
|
struct window_pane *wp, struct screen_write_ctx *ctx, u_int px)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
|
||||||
|
screen_write_cursormove(ctx, px, 0);
|
||||||
|
screen_write_copy(ctx, &wp->base, data->ox + px,
|
||||||
|
screen_hsize(&wp->base) - data->oy, 1, screen_size_y(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_redraw_screen(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_scroll_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_scroll_write_line(wp, &ctx, i);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_scroll_up(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
|
||||||
|
if (data->oy >= screen_hsize(&wp->base))
|
||||||
|
return;
|
||||||
|
data->oy++;
|
||||||
|
|
||||||
|
screen_write_start(&ctx, wp, NULL);
|
||||||
|
screen_write_cursormove(&ctx, 0, 0);
|
||||||
|
screen_write_insertline(&ctx, 1);
|
||||||
|
window_scroll_write_line(wp, &ctx, 0);
|
||||||
|
window_scroll_write_line(wp, &ctx, 1);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_scroll_down(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
|
||||||
|
if (data->oy == 0)
|
||||||
|
return;
|
||||||
|
data->oy--;
|
||||||
|
|
||||||
|
screen_write_start(&ctx, wp, NULL);
|
||||||
|
screen_write_cursormove(&ctx, 0, 0);
|
||||||
|
screen_write_deleteline(&ctx, 1);
|
||||||
|
window_scroll_write_line(wp, &ctx, screen_size_y(s) - 1);
|
||||||
|
window_scroll_write_line(wp, &ctx, 0);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_scroll_right(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
if (data->ox >= SHRT_MAX)
|
||||||
|
return;
|
||||||
|
data->ox++;
|
||||||
|
|
||||||
|
screen_write_start(&ctx, wp, NULL);
|
||||||
|
for (i = 1; i < screen_size_y(s); i++) {
|
||||||
|
screen_write_cursormove(&ctx, 0, i);
|
||||||
|
screen_write_deletecharacter(&ctx, 1);
|
||||||
|
}
|
||||||
|
window_scroll_write_column(wp, &ctx, screen_size_x(s) - 1);
|
||||||
|
window_scroll_write_line(wp, &ctx, 0);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_scroll_scroll_left(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_scroll_mode_data *data = wp->modedata;
|
||||||
|
struct screen *s = &data->screen;
|
||||||
|
struct screen_write_ctx ctx;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
if (data->ox == 0)
|
||||||
|
return;
|
||||||
|
data->ox--;
|
||||||
|
|
||||||
|
screen_write_start(&ctx, wp, NULL);
|
||||||
|
for (i = 1; i < screen_size_y(s); i++) {
|
||||||
|
screen_write_cursormove(&ctx, 0, i);
|
||||||
|
screen_write_insertcharacter(&ctx, 1);
|
||||||
|
}
|
||||||
|
window_scroll_write_column(wp, &ctx, 0);
|
||||||
|
window_scroll_write_line(wp, &ctx, 0);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
}
|
||||||
93
window.c
93
window.c
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: window.c,v 1.117 2009-10-23 17:41:20 tcunha Exp $ */
|
/* $Id: window.c,v 1.107 2009-09-16 12:36:28 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@@ -172,7 +172,7 @@ winlink_stack_push(struct winlink_stack *stack, struct winlink *wl)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
winlink_stack_remove(stack, wl);
|
winlink_stack_remove(stack, wl);
|
||||||
TAILQ_INSERT_HEAD(stack, wl, sentry);
|
SLIST_INSERT_HEAD(stack, wl, sentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -183,9 +183,9 @@ winlink_stack_remove(struct winlink_stack *stack, struct winlink *wl)
|
|||||||
if (wl == NULL)
|
if (wl == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TAILQ_FOREACH(wl2, stack, sentry) {
|
SLIST_FOREACH(wl2, stack, sentry) {
|
||||||
if (wl2 == wl) {
|
if (wl2 == wl) {
|
||||||
TAILQ_REMOVE(stack, wl, sentry);
|
SLIST_REMOVE(stack, wl, winlink, sentry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,23 +302,6 @@ window_set_active_pane(struct window *w, struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
window_set_active_at(struct window *w, u_int x, u_int y)
|
|
||||||
{
|
|
||||||
struct window_pane *wp;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
|
||||||
if (!window_pane_visible(wp))
|
|
||||||
continue;
|
|
||||||
if (x < wp->xoff || x >= wp->xoff + wp->sx)
|
|
||||||
continue;
|
|
||||||
if (y < wp->yoff || y >= wp->yoff + wp->sy)
|
|
||||||
continue;
|
|
||||||
window_set_active_pane(w, wp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct window_pane *
|
struct window_pane *
|
||||||
window_add_pane(struct window *w, u_int hlimit)
|
window_add_pane(struct window *w, u_int hlimit)
|
||||||
{
|
{
|
||||||
@@ -423,10 +406,6 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
|||||||
wp->sx = sx;
|
wp->sx = sx;
|
||||||
wp->sy = sy;
|
wp->sy = sy;
|
||||||
|
|
||||||
wp->pipe_fd = -1;
|
|
||||||
wp->pipe_buf = NULL;
|
|
||||||
wp->pipe_off = 0;
|
|
||||||
|
|
||||||
wp->saved_grid = NULL;
|
wp->saved_grid = NULL;
|
||||||
|
|
||||||
screen_init(&wp->base, sx, sy, hlimit);
|
screen_init(&wp->base, sx, sy, hlimit);
|
||||||
@@ -450,11 +429,6 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
if (wp->saved_grid != NULL)
|
if (wp->saved_grid != NULL)
|
||||||
grid_destroy(wp->saved_grid);
|
grid_destroy(wp->saved_grid);
|
||||||
|
|
||||||
if (wp->pipe_fd != -1) {
|
|
||||||
buffer_destroy(wp->pipe_buf);
|
|
||||||
close(wp->pipe_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_destroy(wp->in);
|
buffer_destroy(wp->in);
|
||||||
buffer_destroy(wp->out);
|
buffer_destroy(wp->out);
|
||||||
|
|
||||||
@@ -504,7 +478,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
|||||||
ws.ws_row = screen_size_y(&wp->base);
|
ws.ws_row = screen_size_y(&wp->base);
|
||||||
|
|
||||||
if (gettimeofday(&wp->window->name_timer, NULL) != 0)
|
if (gettimeofday(&wp->window->name_timer, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday");
|
||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = NAME_INTERVAL * 1000L;
|
tv.tv_usec = NAME_INTERVAL * 1000L;
|
||||||
timeradd(&wp->window->name_timer, &tv, &wp->window->name_timer);
|
timeradd(&wp->window->name_timer, &tv, &wp->window->name_timer);
|
||||||
@@ -594,7 +568,7 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
wp->mode->resize(wp, sx, sy);
|
wp->mode->resize(wp, sx, sy);
|
||||||
|
|
||||||
if (wp->fd != -1 && ioctl(wp->fd, TIOCSWINSZ, &ws) == -1)
|
if (wp->fd != -1 && ioctl(wp->fd, TIOCSWINSZ, &ws) == -1)
|
||||||
#ifdef __sun
|
#ifdef __sun__
|
||||||
/*
|
/*
|
||||||
* Some versions of Solaris apparently can return an error when
|
* Some versions of Solaris apparently can return an error when
|
||||||
* resizing; don't know why this happens, can't reproduce on
|
* resizing; don't know why this happens, can't reproduce on
|
||||||
@@ -617,7 +591,7 @@ window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
|
|||||||
|
|
||||||
if ((s = wp->mode->init(wp)) != NULL)
|
if ((s = wp->mode->init(wp)) != NULL)
|
||||||
wp->screen = s;
|
wp->screen = s;
|
||||||
wp->flags |= PANE_REDRAW;
|
server_redraw_window(wp->window);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,72 +605,49 @@ window_pane_reset_mode(struct window_pane *wp)
|
|||||||
wp->mode = NULL;
|
wp->mode = NULL;
|
||||||
|
|
||||||
wp->screen = &wp->base;
|
wp->screen = &wp->base;
|
||||||
wp->flags |= PANE_REDRAW;
|
server_redraw_window(wp->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_pane_parse(struct window_pane *wp)
|
window_pane_parse(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
size_t new_size;
|
|
||||||
|
|
||||||
if (wp->mode != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
new_size = BUFFER_USED(wp->in) - wp->pipe_off;
|
|
||||||
if (wp->pipe_fd != -1 && new_size > 0)
|
|
||||||
buffer_write(wp->pipe_buf, BUFFER_OUT(wp->in), new_size);
|
|
||||||
|
|
||||||
input_parse(wp);
|
input_parse(wp);
|
||||||
|
|
||||||
wp->pipe_off = BUFFER_USED(wp->in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_pane_key(struct window_pane *wp, struct client *c, int key)
|
window_pane_key(struct window_pane *wp, struct client *c, int key)
|
||||||
{
|
{
|
||||||
struct window_pane *wp2;
|
if (wp->fd == -1 || !window_pane_visible(wp))
|
||||||
|
|
||||||
if (!window_pane_visible(wp))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (wp->mode != NULL) {
|
if (wp->mode != NULL) {
|
||||||
if (wp->mode->key != NULL)
|
if (wp->mode->key != NULL)
|
||||||
wp->mode->key(wp, c, key);
|
wp->mode->key(wp, c, key);
|
||||||
return;
|
} else
|
||||||
}
|
input_key(wp, key);
|
||||||
|
|
||||||
if (wp->fd == -1)
|
|
||||||
return;
|
|
||||||
input_key(wp, key);
|
|
||||||
if (options_get_number(&wp->window->options, "synchronize-panes")) {
|
|
||||||
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
|
|
||||||
if (wp2 == wp || wp2->mode != NULL)
|
|
||||||
continue;
|
|
||||||
if (wp2->fd != -1 && window_pane_visible(wp2))
|
|
||||||
input_key(wp2, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_pane_mouse(
|
window_pane_mouse(
|
||||||
struct window_pane *wp, struct client *c, struct mouse_event *m)
|
struct window_pane *wp, struct client *c, u_char b, u_char x, u_char y)
|
||||||
{
|
{
|
||||||
if (!window_pane_visible(wp))
|
if (wp->fd == -1 || !window_pane_visible(wp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m->x < wp->xoff || m->x >= wp->xoff + wp->sx)
|
/* XXX convert from 1-based? */
|
||||||
|
|
||||||
|
if (x < wp->xoff || x >= wp->xoff + wp->sx)
|
||||||
return;
|
return;
|
||||||
if (m->y < wp->yoff || m->y >= wp->yoff + wp->sy)
|
if (y < wp->yoff || y >= wp->yoff + wp->sy)
|
||||||
return;
|
return;
|
||||||
m->x -= wp->xoff;
|
x -= wp->xoff;
|
||||||
m->y -= wp->yoff;
|
y -= wp->yoff;
|
||||||
|
|
||||||
if (wp->mode != NULL) {
|
if (wp->mode != NULL) {
|
||||||
if (wp->mode->mouse != NULL)
|
if (wp->mode->mouse != NULL)
|
||||||
wp->mode->mouse(wp, c, m);
|
wp->mode->mouse(wp, c, b, x, y);
|
||||||
} else if (wp->fd != -1)
|
} else
|
||||||
input_mouse(wp, m);
|
input_mouse(wp, b, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
BIN
www/images/tmux1.png
Normal file
BIN
www/images/tmux1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
BIN
www/images/tmux2.png
Normal file
BIN
www/images/tmux2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
www/images/tmux6.png
Normal file
BIN
www/images/tmux6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
@@ -1,74 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<!-- $Id: index.html.in,v 1.2 2009-08-05 16:39:28 nicm Exp $ -->
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
<html>
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<head>
|
||||||
<html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
<head>
|
<title>tmux</title>
|
||||||
<title>tmux</title>
|
</head>
|
||||||
<link rel="stylesheet" type="text/css" media="screen" href="main.css"/>
|
<body>
|
||||||
</head>
|
<b>Welcome to the tmux website, such as it is!</b>
|
||||||
<body>
|
<p>tmux is a "terminal multiplexer", it enables a number of terminals (or windows) to be accessed and controlled from a single terminal. tmux is intended to be a simple, modern, BSD-licensed alternative to programs such as GNU screen.</p>
|
||||||
<div id="body-wrapper">
|
<p><a href="http://downloads.sourceforge.net/tmux/tmux-%%VERSION%%.tar.gz">Download tmux %%VERSION%%.</a></p>
|
||||||
<div id="left-menu-container">
|
<p>Please see the <a href="http://tmux.cvs.sourceforge.net/viewvc/*checkout*/tmux/tmux/NOTES">release notes</a> and <a href="http://tmux.cvs.sourceforge.net/viewvc/*checkout*/tmux/tmux/FAQ">FAQ</a>.</p>
|
||||||
<p id="upper-left-title">tmux</p>
|
<p>Also available are: <a href="http://tmux.cvs.sourceforge.net/viewvc/*checkout*/tmux/tmux/CHANGES">the change log</a> (up to CVS HEAD), <a href="http://sf.net/projects/tmux">the project page</a> and <a href="https://sourceforge.net/mail/?group_id=200378">mailing lists</a>. An IRC channel, #tmux, is on the Freenode network.</p>
|
||||||
<ul id="left-menu">
|
<b>Screenshots</b>
|
||||||
<li><a href="http://downloads.sourceforge.net/tmux/tmux-1.0.tar.gz">Download</a></li>
|
<table><tr>
|
||||||
<li><a href="http://tmux.cvs.sourceforge.net/viewvc/*checkout*/tmux/tmux/NOTES">Release Notes</a>
|
<td><a href="tmux1.png"><img src="small-tmux1.png"></a></td>
|
||||||
<li><a href="http://tmux.cvs.sourceforge.net/viewvc/*checkout*/tmux/tmux/CHANGES">Changelog</a></li>
|
<td><a href="tmux2.png"><img src="small-tmux2.png"></a></td>
|
||||||
<li><a href="http://tmux.cvs.sourceforge.net/viewvc/*checkout*/tmux/tmux/FAQ">FAQ</a></li>
|
<td><a href="tmux3.png"><img src="small-tmux3.png"></a></td>
|
||||||
<li><a href="http://tmux.cvs.sourceforge.net/viewvc/tmux/tmux/examples/">Examples</a></li>
|
</tr><tr>
|
||||||
<li> </li>
|
<td><a href="tmux4.png"><img src="small-tmux4.png"></a></td>
|
||||||
<li class="menu-headings">Source Code</li>
|
<td><a href="tmux5.png"><img src="small-tmux5.png"></a></td>
|
||||||
<li><a href="http://tmux.cvs.sf.net/viewvc/tmux/tmux/">SourceForge</a></li>
|
<td><a href="tmux6.png"><img src="small-tmux6.png"></a></td>
|
||||||
<li><a href="http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/tmux/">OpenBSD</a></li>
|
</tr></table>
|
||||||
<li> </li>
|
</body>
|
||||||
<li class="menu-headings">Support</li>
|
|
||||||
<li><a href="https://lists.sourceforge.net/lists/listinfo/tmux-users">tmux-users</a></li>
|
|
||||||
<li><a href="https://lists.sourceforge.net/lists/listinfo/tmux-cvs">tmux-cvs</a></li>
|
|
||||||
<li>IRC: #tmux on Freenode</li>
|
|
||||||
<li><a href="http://sf.net/projects/tmux">SourceForge Project Page</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="main-content-wrapper">
|
|
||||||
|
|
||||||
<p>tmux is a terminal multiplexer: it enables a number of terminals (or
|
|
||||||
windows), each running a separate program, to be created, accessed, and
|
|
||||||
controlled from a single screen. tmux may be detached from a screen and
|
|
||||||
continue running in the background, then later reattached.</p>
|
|
||||||
|
|
||||||
<p>tmux uses a client-server model. The server holds multiple sessions and each
|
|
||||||
window is a independent entity which may be freely linked to multiple sessions,
|
|
||||||
moved between sessions and otherwise manipulated. Each session may be attached
|
|
||||||
to (display and accept keyboard input from) multiple clients.</p>
|
|
||||||
|
|
||||||
<p>tmux is intended to be a modern, BSD-licensed alternative to programs such
|
|
||||||
as GNU screen. Major features include:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>A powerful, consistent, well-documented and easily scriptable command
|
|
||||||
interface.</li>
|
|
||||||
<li>A window may be split horizontally and vertically into panes.</li>
|
|
||||||
<li>Panes can be freely moved and resized, or arranged into one of four preset
|
|
||||||
layouts. </li>
|
|
||||||
<li>Support for UTF-8 and 256-colour terminals.</li>
|
|
||||||
<li>Copy and paste with multiple buffers.</li>
|
|
||||||
<li>Interactive menus to select windows, sessions or clients.</li>
|
|
||||||
<li>Change the current window by searching for text in the target.</li>
|
|
||||||
<li>Terminal locking, manually or after a timeout.</li>
|
|
||||||
<li>A clean, easily extended, BSD-licensed codebase, under active
|
|
||||||
development.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>tmux is part of the <a href="http://www.openbsd.org">OpenBSD</a> base
|
|
||||||
system. The portable version is hosted on SourceForge and runs on Linux,
|
|
||||||
FreeBSD, NetBSD, Solaris and AIX.</p>
|
|
||||||
|
|
||||||
<div id="screenshots">
|
|
||||||
<a href="tmux3.png"><img src="small-tmux3.png"></a>
|
|
||||||
<a href="tmux4.png"><img src="small-tmux4.png"></a>
|
|
||||||
<a href="tmux5.png"><img src="small-tmux5.png"></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user