mirror of
https://github.com/tmux/tmux.git
synced 2026-03-12 03:25:45 +00:00
Compare commits
148 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52869ed182 | ||
|
|
19104d592b | ||
|
|
cf7f3a436a | ||
|
|
c41916ee16 | ||
|
|
bb5798aa0e | ||
|
|
27591570c4 | ||
|
|
acacb718e5 | ||
|
|
30f2e8ff29 | ||
|
|
69e980602b | ||
|
|
cbde98f67b | ||
|
|
895f1d93d5 | ||
|
|
eb50e7a2c8 | ||
|
|
6e8f400edc | ||
|
|
a5b29a1250 | ||
|
|
2e5584c2b4 | ||
|
|
060515684d | ||
|
|
c6cdab1f79 | ||
|
|
3ed0973493 | ||
|
|
f68a908c8a | ||
|
|
fed1e384ad | ||
|
|
999c1c771b | ||
|
|
727ce7e4bb | ||
|
|
2627ab322e | ||
|
|
6c94774b70 | ||
|
|
ae297cb487 | ||
|
|
537964b92d | ||
|
|
1bc467fe52 | ||
|
|
6bf033beae | ||
|
|
88eb302221 | ||
|
|
43f292b2e0 | ||
|
|
baf1550227 | ||
|
|
f811127bb6 | ||
|
|
f8cc48a43f | ||
|
|
af38936473 | ||
|
|
0e11036055 | ||
|
|
a24260bb23 | ||
|
|
9436a31603 | ||
|
|
1718420c48 | ||
|
|
68b1fd0cc6 | ||
|
|
d4eeeb5498 | ||
|
|
0f73af876f | ||
|
|
1fd6ca2260 | ||
|
|
2d843b5021 | ||
|
|
fc118e13a9 | ||
|
|
25e128d398 | ||
|
|
93f42d360b | ||
|
|
325cbe90d9 | ||
|
|
d35a9ac5f2 | ||
|
|
1ad7c6b8f8 | ||
|
|
0c7ddae2ab | ||
|
|
5c12230a08 | ||
|
|
bee3e3e28d | ||
|
|
068b8b03ad | ||
|
|
150c9f3fe0 | ||
|
|
697b912f26 | ||
|
|
b9c95937ed | ||
|
|
1a53e79057 | ||
|
|
c84ed36719 | ||
|
|
17e4744459 | ||
|
|
fa68d0a16e | ||
|
|
d9450bfccd | ||
|
|
cc096ae929 | ||
|
|
1f75c98f49 | ||
|
|
aba4438013 | ||
|
|
00cf5fbde6 | ||
|
|
3c10df4f87 | ||
|
|
89c17e44fb | ||
|
|
20d2a31b40 | ||
|
|
c7a0f56c71 | ||
|
|
1921fac814 | ||
|
|
36ab4c7c49 | ||
|
|
7d105738b6 | ||
|
|
5e9412608e | ||
|
|
7a2fed494b | ||
|
|
344a6a6202 | ||
|
|
382222af8e | ||
|
|
9892d80d6f | ||
|
|
c10d83b4df | ||
|
|
a2e0db67cc | ||
|
|
fcb00a4161 | ||
|
|
762fa58ce8 | ||
|
|
cfef0c6658 | ||
|
|
f2ec81cf21 | ||
|
|
20d97eb849 | ||
|
|
ec7f5305b1 | ||
|
|
95e304d111 | ||
|
|
cd14ac0486 | ||
|
|
05ec232f3e | ||
|
|
266918a580 | ||
|
|
95a4cc3bce | ||
|
|
e81a92449e | ||
|
|
7411f21c5f | ||
|
|
2377092a70 | ||
|
|
af25cab11b | ||
|
|
6cb74f4b7d | ||
|
|
fdd368a294 | ||
|
|
3ec7e3c006 | ||
|
|
9715c61de0 | ||
|
|
e76d44a640 | ||
|
|
373b13b240 | ||
|
|
fe4e9470bb | ||
|
|
29763d006a | ||
|
|
f4648c1ca1 | ||
|
|
9f045787a5 | ||
|
|
ce1ec90fcc | ||
|
|
28e0658fa9 | ||
|
|
96538b489b | ||
|
|
4a6eca5bd7 | ||
|
|
fe4ef307b7 | ||
|
|
87be2da4e1 | ||
|
|
2b9f8ae485 | ||
|
|
88bd5b15ff | ||
|
|
5849c950d0 | ||
|
|
0c7895076e | ||
|
|
bc4f725820 | ||
|
|
975aa3ccd6 | ||
|
|
55d472a9fe | ||
|
|
eb8e76d433 | ||
|
|
ba9f32b464 | ||
|
|
0509be0740 | ||
|
|
0d84fdd953 | ||
|
|
c5443da2d3 | ||
|
|
5f2bfd9807 | ||
|
|
e7de2fe552 | ||
|
|
65e4c57d3a | ||
|
|
a9d501e975 | ||
|
|
97417a1813 | ||
|
|
7abdfbe20e | ||
|
|
7a02910feb | ||
|
|
dd8ba0b5a8 | ||
|
|
36976ce5e6 | ||
|
|
bac7a68023 | ||
|
|
fc70ac4d59 | ||
|
|
fb4585bbe0 | ||
|
|
61f231a496 | ||
|
|
55fdaab365 | ||
|
|
1cedf78284 | ||
|
|
23fdbc9ea6 | ||
|
|
394589d493 | ||
|
|
d3546cc85c | ||
|
|
447ead940e | ||
|
|
7b9c0ced21 | ||
|
|
fb1c929dc6 | ||
|
|
819ad1a007 | ||
|
|
d303e55258 | ||
|
|
3b833a0c01 | ||
|
|
6bf2a43e67 | ||
|
|
5391342b08 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,3 +17,4 @@ Makefile
|
||||
Makefile.in
|
||||
configure
|
||||
tmux.1.*
|
||||
*.dSYM
|
||||
|
||||
1
.mailmap
1
.mailmap
@@ -22,6 +22,7 @@ Pierre-Yves Ritschard <pyr@openbsd.org> pyr <pyr>
|
||||
Ray Lai <ray@openbsd.org> ray <ray>
|
||||
Ryan McBride <mcbride@openbsd.org> mcbride <mcbride>
|
||||
Sebastian Benoit <benno@openbsd.org> benno <benno>
|
||||
Sebastien Marie <semarie@openbsd.org> semarie <semarie>
|
||||
Stefan Sperling <stsp@openbsd.org> stsp <stsp>
|
||||
Stuart Henderson <sthen@openbsd.org> sthen <sthen>
|
||||
Ted Unangst <tedu@openbsd.org> tedu <tedu>
|
||||
|
||||
27
CHANGES
27
CHANGES
@@ -1,3 +1,24 @@
|
||||
CHANGES FROM 2.2 to 2.3 29 September 2016
|
||||
|
||||
Incompatible Changes
|
||||
====================
|
||||
|
||||
None.
|
||||
|
||||
Normal Changes
|
||||
==============
|
||||
|
||||
* New option 'pane-border-status' to add text in the oane borders.
|
||||
* Support for hooks on commands: 'after' and 'before' hooks.
|
||||
* 'source-file' understands '-q' to supress errors for nonexistent files.
|
||||
* Lots of UTF8 improvements, especially on MacOS.
|
||||
* 'window-status-separator' understands #[] expansions.
|
||||
* 'split-window' understands '-f' for performing a full-width split.
|
||||
* Allow report count to be specified when using 'bind-key -R'.
|
||||
* 'set -a' for appending to user options (@foo) is now supported.
|
||||
* 'display-panes' can now accept a command to run, rather than always
|
||||
selecting the pane.
|
||||
|
||||
CHANGES FROM 2.1 to 2.2 10 April 2016
|
||||
|
||||
Incompatible Changes
|
||||
@@ -217,8 +238,8 @@ Normal Changes
|
||||
* A new environment variable TMUX_TMPDIR is now honoured, allowing the
|
||||
socket directory to be set outside of TMPDIR (/tmp/ if not set).
|
||||
* If -s not given to swap-pane the current pane is assumed.
|
||||
* A #{pane_syncronized} format specifier has been added to be a conditional
|
||||
format if a pane is in a syncronised mode (c.f. syncronize-panes)
|
||||
* A #{pane_synchronized} format specifier has been added to be a conditional
|
||||
format if a pane is in a synchronised mode (c.f. synchronize-panes)
|
||||
* Tmux now runs under Cygwin natively.
|
||||
* Formats can now be nested within each other and expanded accordingly.
|
||||
* Added 'automatic-rename-format' option to allow the automatic rename
|
||||
@@ -1018,7 +1039,7 @@ The list of older changes is below.
|
||||
* -u flag to scroll-mode and copy-mode to start scrolled one page
|
||||
up. scroll-mode -u is bound to prefix,page-up (ppage) by default.
|
||||
* Allow status, mode and message attributes to be changed by three new options:
|
||||
status-attr, mode-attr, message-attr. A comma-separataed list is accepted
|
||||
status-attr, mode-attr, message-attr. A comma-separated list is accepted
|
||||
containing: bright, dim, underscore, blink, reverse, hidden, italics, for
|
||||
example:
|
||||
|
||||
|
||||
21
Makefile.am
21
Makefile.am
@@ -7,7 +7,7 @@ CLEANFILES = tmux.1.mdoc tmux.1.man
|
||||
# Distribution tarball options.
|
||||
EXTRA_DIST = \
|
||||
CHANGES FAQ README TODO COPYING example_tmux.conf compat/*.[ch] \
|
||||
array.h compat.h tmux.h osdep-*.c xmalloc.h mdoc2man.awk tmux.1
|
||||
compat.h tmux.h osdep-*.c xmalloc.h mdoc2man.awk tmux.1
|
||||
dist-hook:
|
||||
make clean
|
||||
grep "^#found_debug=" configure
|
||||
@@ -26,7 +26,7 @@ if IS_GCC
|
||||
CFLAGS += -std=gnu99 -O2
|
||||
if IS_DEBUG
|
||||
CFLAGS += -g
|
||||
CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
|
||||
CFLAGS += -Wno-long-long -Wall -W -Wformat=2
|
||||
CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
|
||||
CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
|
||||
CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
|
||||
@@ -37,6 +37,10 @@ if IS_COVERAGE
|
||||
CFLAGS += -g -O0 --coverage
|
||||
LDFLAGS += --coverage
|
||||
endif
|
||||
if IS_PROFILE
|
||||
CFLAGS += -g -O0 -pg
|
||||
LDFLAGS += -pg
|
||||
endif
|
||||
CPPFLAGS += -iquote.
|
||||
endif
|
||||
|
||||
@@ -181,7 +185,12 @@ dist_tmux_SOURCES = \
|
||||
xterm-keys.c
|
||||
nodist_tmux_SOURCES = osdep-@PLATFORM@.c
|
||||
|
||||
# Pile in all the compat/ stuff that is needed.
|
||||
# Add compat file for utf8proc.
|
||||
if HAVE_UTF8PROC
|
||||
nodist_tmux_SOURCES += compat/utf8proc.c
|
||||
endif
|
||||
|
||||
# Add compat for missing or broken functions.
|
||||
if NO_FORKPTY
|
||||
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
|
||||
endif
|
||||
@@ -194,6 +203,12 @@ endif
|
||||
if NO_DAEMON
|
||||
nodist_tmux_SOURCES += compat/daemon.c
|
||||
endif
|
||||
if NO_GETPROGNAME
|
||||
nodist_tmux_SOURCES += compat/getprogname.c
|
||||
endif
|
||||
if NO_SETPROCTITLE
|
||||
nodist_tmux_SOURCES += compat/setproctitle.c
|
||||
endif
|
||||
if NO_SETENV
|
||||
nodist_tmux_SOURCES += compat/setenv.c
|
||||
endif
|
||||
|
||||
14
README
14
README
@@ -33,19 +33,17 @@ the source tree with:
|
||||
|
||||
$ nroff -mdoc tmux.1|less
|
||||
|
||||
Some common questions are answered in the FAQ file and a more extensive (but
|
||||
slightly out of date) guide is available in the OpenBSD FAQ at
|
||||
http://www.openbsd.org/faq/faq7.html#tmux. A rough todo list is in the TODO
|
||||
file and an example configuration in example_tmux.conf.
|
||||
Some common questions are answered in the FAQ file, a rough todo list is in the
|
||||
TODO file and an example configuration in example_tmux.conf.
|
||||
|
||||
A vim(1) syntax file is available at:
|
||||
|
||||
https://github.com/keith/tmux.vim
|
||||
https://raw.githubusercontent.com/keith/tmux.vim/master/syntax/tmux.vim
|
||||
https://github.com/keith/tmux.vim
|
||||
https://raw.githubusercontent.com/keith/tmux.vim/master/syntax/tmux.vim
|
||||
|
||||
And a bash(1) completion file at:
|
||||
|
||||
https://github.com/przepompownia/tmux-bash-completion
|
||||
https://github.com/imomaliev/tmux-bash-completion
|
||||
|
||||
For debugging, running tmux with -v or -vv will generate server and client log
|
||||
files in the current directory.
|
||||
@@ -58,6 +56,8 @@ And for Git commit emails:
|
||||
|
||||
https://groups.google.com/forum/#!forum/tmux-git
|
||||
|
||||
Subscribe by sending an email to <tmux-users+subscribe@googlegroups.com>.
|
||||
|
||||
Bug reports, feature suggestions and especially code contributions are most
|
||||
welcome. Please send by email to:
|
||||
|
||||
|
||||
4
SYNCING
4
SYNCING
@@ -115,7 +115,7 @@ From there, merge the result in, fixing up any conflicts which might arise.
|
||||
|
||||
% git merge obsd-master
|
||||
|
||||
Then ensure things look correct by BULDING the result of that sync:
|
||||
Then ensure things look correct by BUILDING the result of that sync:
|
||||
|
||||
% make clean && ./autogen.sh && ./configure && make
|
||||
|
||||
@@ -172,5 +172,5 @@ Release tmux for next version
|
||||
the Makefile. Commit it, and run 'make' to replace %%VERSION%%. Push
|
||||
the result out.
|
||||
|
||||
8. Bump version in tmu/tmux.git configure.ac and uncomment "found_debug=yes" to
|
||||
8. Bump version in tmux/tmux.git configure.ac and uncomment "found_debug=yes" to
|
||||
create a debug build by default.
|
||||
|
||||
14
TODO
14
TODO
@@ -7,6 +7,7 @@
|
||||
* last-pane across sessions
|
||||
* list-keys should quote output so that bindings can just be used in
|
||||
config file as-is
|
||||
* resize-pane -p to match split-window -p
|
||||
|
||||
- make command sequences more usable
|
||||
* don't require space after ;
|
||||
@@ -44,8 +45,6 @@
|
||||
* bind commands to mouse in different areas?
|
||||
* commands executed when clicking on a pattern (URL)
|
||||
|
||||
- hooks!
|
||||
|
||||
- warts on current naming:
|
||||
* display-time but message-fg/bg/attr
|
||||
* list-* vs show-*
|
||||
@@ -72,10 +71,10 @@
|
||||
table() cb to give the table name ("vi" or "emacs"). anything in the
|
||||
table fires the command, anything not in the table is injected as a
|
||||
key
|
||||
* searching in copy mode should unwrap lines, so if you seach for "foobar"
|
||||
* searching in copy mode should unwrap lines, so if you search for "foobar"
|
||||
then it should be found even if it is now "foo\nbar" (if the WRAP flag
|
||||
is set on the line)
|
||||
* {} to go to next/previous blank line in copy mode
|
||||
* capture-pane option to preserve spaces but not join lines
|
||||
|
||||
- layout stuff
|
||||
* way to tag a layout as a number/name
|
||||
@@ -121,7 +120,12 @@
|
||||
or even guarantee that cmdq->c != NULL and provide a better way to
|
||||
tell when in the config file - then we use cmdq->c if we need a
|
||||
client w/o a session else cmd_current_client
|
||||
* optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx
|
||||
* we do more work than we should if a single read() contains operations
|
||||
that cancel each other out: for example, writing twice to the same
|
||||
cell, or writing and then clearing a line; it would be nice to
|
||||
optimize these. would it mean processing the entire read() data first
|
||||
then applying changes? or an initial optimization step? or something
|
||||
else?
|
||||
|
||||
- miscellaneous
|
||||
* way to keep a job running just read its last line of output for #()
|
||||
|
||||
12
alerts.c
12
alerts.c
@@ -163,15 +163,15 @@ alerts_queue(struct window *w, int flags)
|
||||
if (!event_initialized(&w->alerts_timer))
|
||||
evtimer_set(&w->alerts_timer, alerts_timer, w);
|
||||
|
||||
if (!alerts_fired) {
|
||||
if ((w->flags & flags) != flags) {
|
||||
w->flags |= flags;
|
||||
log_debug("@%u alerts flags added %#x", w->id, flags);
|
||||
}
|
||||
|
||||
if (alerts_enabled(w, flags)) {
|
||||
log_debug("alerts check queued (by @%u)", w->id);
|
||||
event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
|
||||
alerts_fired = 1;
|
||||
}
|
||||
if (!alerts_fired && alerts_enabled(w, flags)) {
|
||||
log_debug("alerts check queued (by @%u)", w->id);
|
||||
event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
|
||||
alerts_fired = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
120
array.h
120
array.h
@@ -1,120 +0,0 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ARRAY_H
|
||||
#define ARRAY_H
|
||||
|
||||
#define ARRAY_INITIALIZER { NULL, 0, 0 }
|
||||
|
||||
#define ARRAY_DECL(n, c) \
|
||||
struct n { \
|
||||
c *list; \
|
||||
u_int num; \
|
||||
size_t space; \
|
||||
}
|
||||
|
||||
#define ARRAY_ITEM(a, i) ((a)->list[i])
|
||||
#define ARRAY_ITEMSIZE(a) (sizeof *(a)->list)
|
||||
#define ARRAY_INITIALSPACE(a) (10 * ARRAY_ITEMSIZE(a))
|
||||
|
||||
#define ARRAY_ENSURE(a, n) do { \
|
||||
if (UINT_MAX - (n) < (a)->num) \
|
||||
fatalx("number too big"); \
|
||||
if (SIZE_MAX / ((a)->num + (n)) < ARRAY_ITEMSIZE(a)) \
|
||||
fatalx("size too big"); \
|
||||
if ((a)->space == 0) { \
|
||||
(a)->space = ARRAY_INITIALSPACE(a); \
|
||||
(a)->list = xrealloc((a)->list, (a)->space); \
|
||||
} \
|
||||
while ((a)->space <= ((a)->num + (n)) * ARRAY_ITEMSIZE(a)) { \
|
||||
(a)->list = xreallocarray((a)->list, 2, (a)->space); \
|
||||
(a)->space *= 2; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_EMPTY(a) (((void *) (a)) == NULL || (a)->num == 0)
|
||||
#define ARRAY_LENGTH(a) ((a)->num)
|
||||
#define ARRAY_DATA(a) ((a)->list)
|
||||
|
||||
#define ARRAY_FIRST(a) ARRAY_ITEM(a, 0)
|
||||
#define ARRAY_LAST(a) ARRAY_ITEM(a, (a)->num - 1)
|
||||
|
||||
#define ARRAY_INIT(a) do { \
|
||||
(a)->num = 0; \
|
||||
(a)->list = NULL; \
|
||||
(a)->space = 0; \
|
||||
} while (0)
|
||||
#define ARRAY_CLEAR(a) do { \
|
||||
(a)->num = 0; \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_SET(a, i, s) do { \
|
||||
(a)->list[i] = s; \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_ADD(a, s) do { \
|
||||
ARRAY_ENSURE(a, 1); \
|
||||
(a)->list[(a)->num] = s; \
|
||||
(a)->num++; \
|
||||
} while (0)
|
||||
#define ARRAY_INSERT(a, i, s) do { \
|
||||
ARRAY_ENSURE(a, 1); \
|
||||
if ((i) < (a)->num) { \
|
||||
memmove((a)->list + (i) + 1, (a)->list + (i), \
|
||||
ARRAY_ITEMSIZE(a) * ((a)->num - (i))); \
|
||||
} \
|
||||
(a)->list[i] = s; \
|
||||
(a)->num++; \
|
||||
} while (0)
|
||||
#define ARRAY_REMOVE(a, i) do { \
|
||||
if ((i) < (a)->num - 1) { \
|
||||
memmove((a)->list + (i), (a)->list + (i) + 1, \
|
||||
ARRAY_ITEMSIZE(a) * ((a)->num - (i) - 1)); \
|
||||
} \
|
||||
(a)->num--; \
|
||||
if ((a)->num == 0) \
|
||||
ARRAY_FREE(a); \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_EXPAND(a, n) do { \
|
||||
ARRAY_ENSURE(a, n); \
|
||||
(a)->num += n; \
|
||||
} while (0)
|
||||
#define ARRAY_TRUNC(a, n) do { \
|
||||
if ((a)->num > n) \
|
||||
(a)->num -= n; \
|
||||
else \
|
||||
ARRAY_FREE(a); \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_CONCAT(a, b) do { \
|
||||
ARRAY_ENSURE(a, (b)->num); \
|
||||
memcpy((a)->list + (a)->num, (b)->list, (b)->num * ARRAY_ITEMSIZE(a)); \
|
||||
(a)->num += (b)->num; \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_FREE(a) do { \
|
||||
free((a)->list); \
|
||||
ARRAY_INIT(a); \
|
||||
} while (0)
|
||||
#define ARRAY_FREEALL(a) do { \
|
||||
ARRAY_FREE(a); \
|
||||
free(a); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
24
cfg.c
24
cfg.c
@@ -47,8 +47,8 @@ set_cfg_file(const char *path)
|
||||
void
|
||||
start_cfg(void)
|
||||
{
|
||||
char *cause = NULL;
|
||||
const char *home;
|
||||
int quiet = 0;
|
||||
|
||||
cfg_cmd_q = cmdq_new(NULL);
|
||||
cfg_cmd_q->emptyfn = cfg_default_done;
|
||||
@@ -60,28 +60,20 @@ start_cfg(void)
|
||||
if (cfg_client != NULL)
|
||||
cfg_client->references++;
|
||||
|
||||
if (access(TMUX_CONF, R_OK) == 0) {
|
||||
if (load_cfg(TMUX_CONF, cfg_cmd_q, &cause) == -1)
|
||||
cfg_add_cause("%s: %s", TMUX_CONF, cause);
|
||||
} else if (errno != ENOENT)
|
||||
cfg_add_cause("%s: %s", TMUX_CONF, strerror(errno));
|
||||
load_cfg(TMUX_CONF, cfg_cmd_q, 1);
|
||||
|
||||
if (cfg_file == NULL && (home = find_home()) != NULL) {
|
||||
xasprintf(&cfg_file, "%s/.tmux.conf", home);
|
||||
if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
|
||||
free(cfg_file);
|
||||
cfg_file = NULL;
|
||||
}
|
||||
quiet = 1;
|
||||
}
|
||||
if (cfg_file != NULL && load_cfg(cfg_file, cfg_cmd_q, &cause) == -1)
|
||||
cfg_add_cause("%s: %s", cfg_file, cause);
|
||||
free(cause);
|
||||
if (cfg_file != NULL)
|
||||
load_cfg(cfg_file, cfg_cmd_q, quiet);
|
||||
|
||||
cmdq_continue(cfg_cmd_q);
|
||||
}
|
||||
|
||||
int
|
||||
load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
|
||||
load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
|
||||
{
|
||||
FILE *f;
|
||||
char delim[3] = { '\\', '\\', '\0' };
|
||||
@@ -92,7 +84,9 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
|
||||
|
||||
log_debug("loading %s", path);
|
||||
if ((f = fopen(path, "rb")) == NULL) {
|
||||
xasprintf(cause, "%s: %s", path, strerror(errno));
|
||||
if (errno == ENOENT && quiet)
|
||||
return (0);
|
||||
cfg_add_cause("%s: %s", path, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ const struct cmd_entry cmd_bind_key_entry = {
|
||||
.name = "bind-key",
|
||||
.alias = "bind",
|
||||
|
||||
.args = { "cnrt:T:", 1, -1 },
|
||||
.usage = "[-cnr] [-t mode-table] [-T key-table] key command "
|
||||
"[arguments]",
|
||||
.args = { "cnrR:t:T:", 1, -1 },
|
||||
.usage = "[-cnr] [-t mode-table] [-R repeat-count] [-T key-table] key "
|
||||
"command [arguments]",
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_bind_key_exec
|
||||
@@ -97,11 +97,12 @@ enum cmd_retval
|
||||
cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
const char *tablename;
|
||||
const char *tablename, *arg;
|
||||
const struct mode_key_table *mtab;
|
||||
struct mode_key_binding *mbind, mtmp;
|
||||
enum mode_key_cmd cmd;
|
||||
const char *arg;
|
||||
char *cause;
|
||||
u_int repeat;
|
||||
|
||||
tablename = args_get(args, 't');
|
||||
if ((mtab = mode_key_findtable(tablename)) == NULL) {
|
||||
@@ -145,6 +146,16 @@ cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
|
||||
break;
|
||||
}
|
||||
|
||||
repeat = 1;
|
||||
if (args_has(args, 'R')) {
|
||||
repeat = args_strtonum(args, 'R', 1, SHRT_MAX, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(cmdq, "repeat count %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
mtmp.key = key;
|
||||
mtmp.mode = !!args_has(args, 'c');
|
||||
if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) == NULL) {
|
||||
@@ -153,6 +164,7 @@ cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
|
||||
mbind->mode = mtmp.mode;
|
||||
RB_INSERT(mode_key_tree, mtab->tree, mbind);
|
||||
}
|
||||
mbind->repeat = repeat;
|
||||
mbind->cmd = cmd;
|
||||
mbind->arg = arg != NULL ? xstrdup(arg) : NULL;
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
@@ -83,7 +83,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
window_copy_start_drag(c, &cmdq->item->mouse);
|
||||
}
|
||||
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
|
||||
window_copy_pageup(wp);
|
||||
window_copy_pageup(wp, 0);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
@@ -78,9 +78,10 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
msg = format_expand_time(ft, template, time(NULL));
|
||||
if (args_has(self->args, 'p'))
|
||||
cmdq_print(cmdq, "%s", msg);
|
||||
else
|
||||
else if (c != NULL)
|
||||
status_message_set(c, "%s", msg);
|
||||
free(msg);
|
||||
|
||||
format_free(ft);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
@@ -18,19 +18,25 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Display panes on a client.
|
||||
*/
|
||||
|
||||
enum cmd_retval cmd_display_panes_exec(struct cmd *, struct cmd_q *);
|
||||
static enum cmd_retval cmd_display_panes_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
static void cmd_display_panes_callback(struct client *,
|
||||
struct window_pane *);
|
||||
|
||||
const struct cmd_entry cmd_display_panes_entry = {
|
||||
.name = "display-panes",
|
||||
.alias = "displayp",
|
||||
|
||||
.args = { "t:", 0, 0 },
|
||||
.args = { "t:", 0, 1 },
|
||||
.usage = CMD_TARGET_CLIENT_USAGE,
|
||||
|
||||
.tflag = CMD_CLIENT,
|
||||
@@ -39,10 +45,53 @@ const struct cmd_entry cmd_display_panes_entry = {
|
||||
.exec = cmd_display_panes_exec
|
||||
};
|
||||
|
||||
enum cmd_retval
|
||||
cmd_display_panes_exec(__unused struct cmd *self, struct cmd_q *cmdq)
|
||||
static enum cmd_retval
|
||||
cmd_display_panes_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
server_set_identify(cmdq->state.c);
|
||||
struct args *args = self->args;
|
||||
struct client *c = cmdq->state.c;
|
||||
|
||||
if (c->identify_callback != NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
c->identify_callback = cmd_display_panes_callback;
|
||||
if (args->argc != 0)
|
||||
c->identify_callback_data = xstrdup(args->argv[0]);
|
||||
else
|
||||
c->identify_callback_data = xstrdup("select-pane -t '%%'");
|
||||
|
||||
server_set_identify(c);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_display_panes_callback(struct client *c, struct window_pane *wp)
|
||||
{
|
||||
struct cmd_list *cmdlist;
|
||||
char *template, *cmd, *expanded, *cause;
|
||||
|
||||
template = c->identify_callback_data;
|
||||
if (wp != NULL) {
|
||||
xasprintf(&expanded, "%%%u", wp->id);
|
||||
cmd = cmd_template_replace(template, expanded, 1);
|
||||
|
||||
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
|
||||
if (cause != NULL) {
|
||||
*cause = toupper((u_char) *cause);
|
||||
status_message_set(c, "%s", cause);
|
||||
free(cause);
|
||||
}
|
||||
} else {
|
||||
cmdq_run(c->cmdq, cmdlist, NULL);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
free(expanded);
|
||||
}
|
||||
|
||||
free(c->identify_callback_data);
|
||||
c->identify_callback_data = NULL;
|
||||
c->identify_callback = NULL;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
cwd = NULL;
|
||||
|
||||
ft = format_create(cmdq, 0);
|
||||
format_defaults(ft, NULL, s, wl, wp);
|
||||
format_defaults(ft, cmdq->state.c, s, wl, wp);
|
||||
shellcmd = format_expand(ft, args->argv[0]);
|
||||
format_free(ft);
|
||||
|
||||
@@ -157,6 +157,7 @@ cmd_if_shell_callback(struct job *job)
|
||||
}
|
||||
|
||||
cmdq1 = cmdq_new(cmdq->client);
|
||||
cmdq1->flags |= cmdq->flags & CMD_Q_NOHOOKS;
|
||||
cmdq1->emptyfn = cmd_if_shell_done;
|
||||
cmdq1->data = cdata;
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
|
||||
else
|
||||
size = (dst_wp->sx * percentage) / 100;
|
||||
}
|
||||
lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b'));
|
||||
lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b'), 0);
|
||||
if (lc == NULL) {
|
||||
cmdq_error(cmdq, "create pane failed: pane too small");
|
||||
return (CMD_RETURN_ERROR);
|
||||
@@ -135,11 +135,6 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
|
||||
window_lost_pane(src_w, src_wp);
|
||||
TAILQ_REMOVE(&src_w->panes, src_wp, entry);
|
||||
|
||||
if (window_count_panes(src_w) == 0)
|
||||
server_kill_window(src_w);
|
||||
else
|
||||
notify_window_layout_changed(src_w);
|
||||
|
||||
src_wp->window = dst_w;
|
||||
TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
|
||||
layout_assign_pane(lc, src_wp);
|
||||
@@ -156,6 +151,11 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
|
||||
} else
|
||||
server_status_session(dst_s);
|
||||
|
||||
if (window_count_panes(src_w) == 0)
|
||||
server_kill_window(src_w);
|
||||
else
|
||||
notify_window_layout_changed(src_w);
|
||||
notify_window_layout_changed(dst_w);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
* List key bindings.
|
||||
*/
|
||||
|
||||
enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_q *);
|
||||
static enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_q *);
|
||||
enum cmd_retval cmd_list_keys_commands(struct cmd_q *);
|
||||
static enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_q *);
|
||||
static enum cmd_retval cmd_list_keys_commands(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_list_keys_entry = {
|
||||
.name = "list-keys",
|
||||
@@ -47,14 +47,14 @@ const struct cmd_entry cmd_list_commands_entry = {
|
||||
.name = "list-commands",
|
||||
.alias = "lscm",
|
||||
|
||||
.args = { "", 0, 0 },
|
||||
.usage = "",
|
||||
.args = { "F:", 0, 0 },
|
||||
.usage = "[-F format]",
|
||||
|
||||
.flags = CMD_STARTSERVER,
|
||||
.exec = cmd_list_keys_exec
|
||||
};
|
||||
|
||||
enum cmd_retval
|
||||
static enum cmd_retval
|
||||
cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
@@ -65,7 +65,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
int repeat, width, tablewidth, keywidth;
|
||||
|
||||
if (self->entry == &cmd_list_commands_entry)
|
||||
return (cmd_list_keys_commands(cmdq));
|
||||
return (cmd_list_keys_commands(self, cmdq));
|
||||
|
||||
if (args_has(args, 't'))
|
||||
return (cmd_list_keys_table(self, cmdq));
|
||||
@@ -131,15 +131,15 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
enum cmd_retval
|
||||
static enum cmd_retval
|
||||
cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
const char *tablename;
|
||||
const char *tablename, *key, *cmdstr, *mode;
|
||||
const struct mode_key_table *mtab;
|
||||
struct mode_key_binding *mbind;
|
||||
const char *key, *cmdstr, *mode;
|
||||
int width, keywidth, any_mode;
|
||||
char repeat[16];
|
||||
int width, keywidth, repeatwidth, any_mode;
|
||||
|
||||
tablename = args_get(args, 't');
|
||||
if ((mtab = mode_key_findtable(tablename)) == NULL) {
|
||||
@@ -147,7 +147,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
width = 0;
|
||||
keywidth = repeatwidth = 0;
|
||||
any_mode = 0;
|
||||
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
|
||||
key = key_string_lookup_key(mbind->key);
|
||||
@@ -155,9 +155,16 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (mbind->mode != 0)
|
||||
any_mode = 1;
|
||||
|
||||
keywidth = strlen(key);
|
||||
if (keywidth > width)
|
||||
width = keywidth;
|
||||
width = strlen(key);
|
||||
if (width > keywidth)
|
||||
keywidth = width;
|
||||
|
||||
if (mbind->repeat != 1) {
|
||||
snprintf(repeat, sizeof repeat, "%u", mbind->repeat);
|
||||
width = strlen(repeat);
|
||||
if (width > repeatwidth)
|
||||
repeatwidth = width;
|
||||
}
|
||||
}
|
||||
|
||||
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
|
||||
@@ -166,11 +173,17 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
|
||||
mode = "";
|
||||
if (mbind->mode != 0)
|
||||
mode = "c";
|
||||
snprintf(repeat, sizeof repeat, "%u", mbind->repeat);
|
||||
cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd);
|
||||
if (cmdstr != NULL) {
|
||||
cmdq_print(cmdq, "bind-key -%st %s%s %*s %s%s%s%s",
|
||||
cmdq_print(cmdq,
|
||||
"bind-key -%st %s%s%s%*s %*s %s%s%s%s",
|
||||
mode, any_mode && *mode == '\0' ? " " : "",
|
||||
mtab->name, (int) width, key, cmdstr,
|
||||
mtab->name,
|
||||
mbind->repeat != 1 ? " -R " :
|
||||
(repeatwidth == 0 ? "" : " "),
|
||||
repeatwidth, mbind->repeat != 1 ? repeat : "",
|
||||
(int)keywidth, key, cmdstr,
|
||||
mbind->arg != NULL ? " \"" : "",
|
||||
mbind->arg != NULL ? mbind->arg : "",
|
||||
mbind->arg != NULL ? "\"": "");
|
||||
@@ -180,21 +193,44 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
enum cmd_retval
|
||||
cmd_list_keys_commands(struct cmd_q *cmdq)
|
||||
static enum cmd_retval
|
||||
cmd_list_keys_commands(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
const struct cmd_entry **entryp;
|
||||
const struct cmd_entry *entry;
|
||||
struct format_tree *ft;
|
||||
const char *template;
|
||||
char *line;
|
||||
|
||||
if ((template = args_get(args, 'F')) == NULL) {
|
||||
template = "#{command_list_name}"
|
||||
"#{?command_list_alias, (#{command_list_alias}),} "
|
||||
"#{command_list_usage}";
|
||||
}
|
||||
|
||||
ft = format_create(cmdq, 0);
|
||||
format_defaults(ft, NULL, NULL, NULL, NULL);
|
||||
|
||||
for (entryp = cmd_table; *entryp != NULL; entryp++) {
|
||||
entry = *entryp;
|
||||
if (entry->alias == NULL) {
|
||||
cmdq_print(cmdq, "%s %s", entry->name, entry->usage);
|
||||
continue;
|
||||
|
||||
format_add(ft, "command_list_name", "%s", entry->name);
|
||||
if (entry->alias != NULL) {
|
||||
format_add(ft, "command_list_alias", "%s",
|
||||
entry->alias);
|
||||
}
|
||||
cmdq_print(cmdq, "%s (%s) %s", entry->name, entry->alias,
|
||||
entry->usage);
|
||||
if (entry->alias != NULL) {
|
||||
format_add(ft, "command_list_usage", "%s",
|
||||
entry->usage);
|
||||
}
|
||||
|
||||
line = format_expand(ft, template);
|
||||
if (*line != '\0')
|
||||
cmdq_print(cmdq, "%s", line);
|
||||
free(line);
|
||||
}
|
||||
|
||||
format_free(ft);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
58
cmd-queue.c
58
cmd-queue.c
@@ -80,7 +80,7 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
|
||||
/* nothing */;
|
||||
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
|
||||
if (~c->flags & CLIENT_UTF8) {
|
||||
vasprintf(&tmp, fmt, ap);
|
||||
xvasprintf(&tmp, fmt, ap);
|
||||
msg = utf8_sanitize(tmp);
|
||||
free(tmp);
|
||||
evbuffer_add(c->stdout_data, msg, strlen(msg));
|
||||
@@ -186,6 +186,9 @@ static enum cmd_retval
|
||||
cmdq_continue_one(struct cmd_q *cmdq)
|
||||
{
|
||||
struct cmd *cmd = cmdq->cmd;
|
||||
const char *name = cmd->entry->name;
|
||||
struct session *s;
|
||||
struct hooks *hooks;
|
||||
enum cmd_retval retval;
|
||||
char *tmp;
|
||||
int flags = !!(cmd->flags & CMD_CONTROL);
|
||||
@@ -197,19 +200,51 @@ cmdq_continue_one(struct cmd_q *cmdq)
|
||||
cmdq->time = time(NULL);
|
||||
cmdq->number++;
|
||||
|
||||
cmdq_guard(cmdq, "begin", flags);
|
||||
if (~cmdq->flags & CMD_Q_REENTRY)
|
||||
cmdq_guard(cmdq, "begin", flags);
|
||||
|
||||
if (cmd_prepare_state(cmd, cmdq, NULL) != 0)
|
||||
if (cmd_prepare_state(cmd, cmdq, cmdq->parent) != 0)
|
||||
goto error;
|
||||
|
||||
if (~cmdq->flags & CMD_Q_NOHOOKS) {
|
||||
s = NULL;
|
||||
if (cmdq->state.tflag.s != NULL)
|
||||
s = cmdq->state.tflag.s;
|
||||
else if (cmdq->state.sflag.s != NULL)
|
||||
s = cmdq->state.sflag.s;
|
||||
else if (cmdq->state.c != NULL)
|
||||
s = cmdq->state.c->session;
|
||||
if (s != NULL)
|
||||
hooks = s->hooks;
|
||||
else
|
||||
hooks = global_hooks;
|
||||
|
||||
if (~cmdq->flags & CMD_Q_REENTRY) {
|
||||
cmdq->flags |= CMD_Q_REENTRY;
|
||||
if (hooks_wait(hooks, cmdq, NULL,
|
||||
"before-%s", name) == 0)
|
||||
return (CMD_RETURN_WAIT);
|
||||
if (cmd_prepare_state(cmd, cmdq, cmdq->parent) != 0)
|
||||
goto error;
|
||||
}
|
||||
} else
|
||||
hooks = NULL;
|
||||
cmdq->flags &= ~CMD_Q_REENTRY;
|
||||
|
||||
retval = cmd->entry->exec(cmd, cmdq);
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
goto error;
|
||||
|
||||
if (hooks != NULL && hooks_wait(hooks, cmdq, NULL,
|
||||
"after-%s", name) == 0)
|
||||
retval = CMD_RETURN_WAIT;
|
||||
cmdq_guard(cmdq, "end", flags);
|
||||
|
||||
return (retval);
|
||||
|
||||
error:
|
||||
cmdq_guard(cmdq, "error", flags);
|
||||
cmdq->flags &= ~CMD_Q_REENTRY;
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
@@ -232,11 +267,18 @@ cmdq_continue(struct cmd_q *cmdq)
|
||||
if (empty)
|
||||
goto empty;
|
||||
|
||||
if (cmdq->item == NULL) {
|
||||
cmdq->item = TAILQ_FIRST(&cmdq->queue);
|
||||
cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list);
|
||||
} else
|
||||
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
|
||||
/*
|
||||
* If the command isn't in the middle of running hooks (due to
|
||||
* CMD_RETURN_WAIT), move onto the next command; otherwise, leave the
|
||||
* state of the queue as it is.
|
||||
*/
|
||||
if (~cmdq->flags & CMD_Q_REENTRY) {
|
||||
if (cmdq->item == NULL) {
|
||||
cmdq->item = TAILQ_FIRST(&cmdq->queue);
|
||||
cmdq->cmd = TAILQ_FIRST(&cmdq->item->cmdlist->list);
|
||||
} else
|
||||
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
|
||||
}
|
||||
|
||||
do {
|
||||
while (cmdq->cmd != NULL) {
|
||||
|
||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_set_hook_entry = {
|
||||
.args = { "gt:u", 1, 2 },
|
||||
.usage = "[-gu] " CMD_TARGET_SESSION_USAGE " hook-name [command]",
|
||||
|
||||
.tflag = CMD_SESSION,
|
||||
.tflag = CMD_SESSION_CANFAIL,
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_set_hook_exec
|
||||
@@ -63,12 +63,21 @@ cmd_set_hook_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct hooks *hooks;
|
||||
struct hook *hook;
|
||||
char *cause, *tmp;
|
||||
const char *name, *cmd;
|
||||
const char *name, *cmd, *target;
|
||||
|
||||
if (args_has(args, 'g'))
|
||||
hooks = global_hooks;
|
||||
else
|
||||
else {
|
||||
if (cmdq->state.tflag.s == NULL) {
|
||||
target = args_get(args, 't');
|
||||
if (target != NULL)
|
||||
cmdq_error(cmdq, "no such session: %s", target);
|
||||
else
|
||||
cmdq_error(cmdq, "no current session");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
hooks = cmdq->state.tflag.s->hooks;
|
||||
}
|
||||
|
||||
if (self->entry == &cmd_show_hooks_entry) {
|
||||
hook = hooks_first(hooks);
|
||||
|
||||
@@ -200,6 +200,17 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
status_timer_start_all();
|
||||
if (strcmp(oe->name, "monitor-silence") == 0)
|
||||
alerts_reset_all();
|
||||
if (strcmp(oe->name, "window-style") == 0 ||
|
||||
strcmp(oe->name, "window-active-style") == 0) {
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
w->flags |= WINDOW_STYLECHANGED;
|
||||
}
|
||||
|
||||
/* When the pane-border-status option has been changed, resize panes. */
|
||||
if (strcmp(oe->name, "pane-border-status") == 0) {
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
layout_fix_panes(w, w->sx, w->sy);
|
||||
}
|
||||
|
||||
/* Update sizes and redraw. May not need it but meh. */
|
||||
recalculate_sizes();
|
||||
@@ -216,10 +227,11 @@ enum cmd_retval
|
||||
cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char *optstr,
|
||||
const char *valstr)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct session *s = cmdq->state.tflag.s;
|
||||
struct winlink *wl = cmdq->state.tflag.wl;
|
||||
struct options *oo;
|
||||
struct args *args = self->args;
|
||||
struct session *s = cmdq->state.tflag.s;
|
||||
struct winlink *wl = cmdq->state.tflag.wl;
|
||||
struct options *oo;
|
||||
struct options_entry *o;
|
||||
|
||||
if (args_has(args, 's'))
|
||||
oo = global_options;
|
||||
@@ -251,18 +263,22 @@ cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char *optstr,
|
||||
}
|
||||
options_remove(oo, optstr);
|
||||
} else {
|
||||
if (valstr == NULL) {
|
||||
cmdq_error(cmdq, "empty value");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (args_has(args, 'o') && options_find1(oo, optstr) != NULL) {
|
||||
o = options_find1(oo, optstr);
|
||||
if (args_has(args, 'o') && o != NULL) {
|
||||
if (!args_has(args, 'q')) {
|
||||
cmdq_error(cmdq, "already set: %s", optstr);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
options_set_string(oo, optstr, "%s", valstr);
|
||||
if (valstr == NULL) {
|
||||
cmdq_error(cmdq, "empty value");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (o != NULL && args_has(args, 'a'))
|
||||
options_set_string(oo, optstr, "%s%s", o->str, valstr);
|
||||
else
|
||||
options_set_string(oo, optstr, "%s", valstr);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ const struct cmd_entry cmd_source_file_entry = {
|
||||
.name = "source-file",
|
||||
.alias = "source",
|
||||
|
||||
.args = { "", 1, 1 },
|
||||
.usage = "path",
|
||||
.args = { "q", 1, 1 },
|
||||
.usage = "[-q] path",
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_source_file_exec
|
||||
@@ -46,27 +46,26 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct cmd_q *cmdq1;
|
||||
char *cause;
|
||||
int quiet;
|
||||
|
||||
cmdq1 = cmdq_new(cmdq->client);
|
||||
cmdq1->flags |= cmdq->flags & CMD_Q_NOHOOKS;
|
||||
cmdq1->emptyfn = cmd_source_file_done;
|
||||
cmdq1->data = cmdq;
|
||||
|
||||
switch (load_cfg(args->argv[0], cmdq1, &cause)) {
|
||||
quiet = args_has(args, 'q');
|
||||
switch (load_cfg(args->argv[0], cmdq1, quiet)) {
|
||||
case -1:
|
||||
cmdq_free(cmdq1);
|
||||
if (cfg_references == 0) {
|
||||
cmdq_free(cmdq1);
|
||||
cmdq_error(cmdq, "%s", cause);
|
||||
free(cause);
|
||||
cfg_print_causes(cmdq);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
cfg_add_cause("%s", cause);
|
||||
free(cause);
|
||||
/* FALLTHROUGH */
|
||||
return (CMD_RETURN_NORMAL);
|
||||
case 0:
|
||||
cmdq_free(cmdq1);
|
||||
if (cfg_references == 0)
|
||||
cfg_print_causes(cmdq);
|
||||
cmdq_free(cmdq1);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ const struct cmd_entry cmd_split_window_entry = {
|
||||
.name = "split-window",
|
||||
.alias = "splitw",
|
||||
|
||||
.args = { "bc:dF:l:hp:Pt:v", 0, -1 },
|
||||
.usage = "[-bdhvP] [-c start-directory] [-F format] "
|
||||
.args = { "bc:dfF:l:hp:Pt:v", 0, -1 },
|
||||
.usage = "[-bdfhvP] [-c start-directory] [-F format] "
|
||||
"[-p percentage|-l size] " CMD_TARGET_PANE_USAGE " [command]",
|
||||
|
||||
.tflag = CMD_PANE,
|
||||
@@ -130,12 +130,13 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (*shell == '\0' || areshell(shell))
|
||||
shell = _PATH_BSHELL;
|
||||
|
||||
lc = layout_split_pane(wp, type, size, args_has(args, 'b'));
|
||||
lc = layout_split_pane(wp, type, size, args_has(args, 'b'),
|
||||
args_has(args, 'f'));
|
||||
if (lc == NULL) {
|
||||
cause = xstrdup("pane too small");
|
||||
goto error;
|
||||
}
|
||||
new_wp = window_add_pane(w, hlimit);
|
||||
new_wp = window_add_pane(w, wp, hlimit);
|
||||
layout_assign_pane(lc, new_wp);
|
||||
|
||||
path = NULL;
|
||||
|
||||
389
colour.c
389
colour.c
@@ -2,6 +2,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
* Copyright (c) 2016 Avi Halachmi <avihpit@yahoo.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -24,334 +25,83 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Colour to string conversion functions. Bit 8 of the colour means it is one
|
||||
* of the 256 colour palette.
|
||||
*/
|
||||
|
||||
struct colour_rgb {
|
||||
u_char i;
|
||||
u_char r;
|
||||
u_char g;
|
||||
u_char b;
|
||||
};
|
||||
|
||||
const struct colour_rgb colour_from_256[] = {
|
||||
{ 0, 0x00, 0x00, 0x00 }, { 1, 0x00, 0x00, 0x5f },
|
||||
{ 2, 0x00, 0x00, 0x87 }, { 3, 0x00, 0x00, 0xaf },
|
||||
{ 4, 0x00, 0x00, 0xd7 }, { 5, 0x00, 0x00, 0xff },
|
||||
{ 6, 0x00, 0x5f, 0x00 }, { 7, 0x00, 0x5f, 0x5f },
|
||||
{ 8, 0x00, 0x5f, 0x87 }, { 9, 0x00, 0x5f, 0xaf },
|
||||
{ 10, 0x00, 0x5f, 0xd7 }, { 11, 0x00, 0x5f, 0xff },
|
||||
{ 12, 0x00, 0x87, 0x00 }, { 13, 0x00, 0x87, 0x5f },
|
||||
{ 14, 0x00, 0x87, 0x87 }, { 15, 0x00, 0x87, 0xaf },
|
||||
{ 16, 0x00, 0x87, 0xd7 }, { 17, 0x00, 0x87, 0xff },
|
||||
{ 18, 0x00, 0xaf, 0x00 }, { 19, 0x00, 0xaf, 0x5f },
|
||||
{ 20, 0x00, 0xaf, 0x87 }, { 21, 0x00, 0xaf, 0xaf },
|
||||
{ 22, 0x00, 0xaf, 0xd7 }, { 23, 0x00, 0xaf, 0xff },
|
||||
{ 24, 0x00, 0xd7, 0x00 }, { 25, 0x00, 0xd7, 0x5f },
|
||||
{ 26, 0x00, 0xd7, 0x87 }, { 27, 0x00, 0xd7, 0xaf },
|
||||
{ 28, 0x00, 0xd7, 0xd7 }, { 29, 0x00, 0xd7, 0xff },
|
||||
{ 30, 0x00, 0xff, 0x00 }, { 31, 0x00, 0xff, 0x5f },
|
||||
{ 32, 0x00, 0xff, 0x87 }, { 33, 0x00, 0xff, 0xaf },
|
||||
{ 34, 0x00, 0xff, 0xd7 }, { 35, 0x00, 0xff, 0xff },
|
||||
{ 36, 0x5f, 0x00, 0x00 }, { 37, 0x5f, 0x00, 0x5f },
|
||||
{ 38, 0x5f, 0x00, 0x87 }, { 39, 0x5f, 0x00, 0xaf },
|
||||
{ 40, 0x5f, 0x00, 0xd7 }, { 41, 0x5f, 0x00, 0xff },
|
||||
{ 42, 0x5f, 0x5f, 0x00 }, { 43, 0x5f, 0x5f, 0x5f },
|
||||
{ 44, 0x5f, 0x5f, 0x87 }, { 45, 0x5f, 0x5f, 0xaf },
|
||||
{ 46, 0x5f, 0x5f, 0xd7 }, { 47, 0x5f, 0x5f, 0xff },
|
||||
{ 48, 0x5f, 0x87, 0x00 }, { 49, 0x5f, 0x87, 0x5f },
|
||||
{ 50, 0x5f, 0x87, 0x87 }, { 51, 0x5f, 0x87, 0xaf },
|
||||
{ 52, 0x5f, 0x87, 0xd7 }, { 53, 0x5f, 0x87, 0xff },
|
||||
{ 54, 0x5f, 0xaf, 0x00 }, { 55, 0x5f, 0xaf, 0x5f },
|
||||
{ 56, 0x5f, 0xaf, 0x87 }, { 57, 0x5f, 0xaf, 0xaf },
|
||||
{ 58, 0x5f, 0xaf, 0xd7 }, { 59, 0x5f, 0xaf, 0xff },
|
||||
{ 60, 0x5f, 0xd7, 0x00 }, { 61, 0x5f, 0xd7, 0x5f },
|
||||
{ 62, 0x5f, 0xd7, 0x87 }, { 63, 0x5f, 0xd7, 0xaf },
|
||||
{ 64, 0x5f, 0xd7, 0xd7 }, { 65, 0x5f, 0xd7, 0xff },
|
||||
{ 66, 0x5f, 0xff, 0x00 }, { 67, 0x5f, 0xff, 0x5f },
|
||||
{ 68, 0x5f, 0xff, 0x87 }, { 69, 0x5f, 0xff, 0xaf },
|
||||
{ 70, 0x5f, 0xff, 0xd7 }, { 71, 0x5f, 0xff, 0xff },
|
||||
{ 72, 0x87, 0x00, 0x00 }, { 73, 0x87, 0x00, 0x5f },
|
||||
{ 74, 0x87, 0x00, 0x87 }, { 75, 0x87, 0x00, 0xaf },
|
||||
{ 76, 0x87, 0x00, 0xd7 }, { 77, 0x87, 0x00, 0xff },
|
||||
{ 78, 0x87, 0x5f, 0x00 }, { 79, 0x87, 0x5f, 0x5f },
|
||||
{ 80, 0x87, 0x5f, 0x87 }, { 81, 0x87, 0x5f, 0xaf },
|
||||
{ 82, 0x87, 0x5f, 0xd7 }, { 83, 0x87, 0x5f, 0xff },
|
||||
{ 84, 0x87, 0x87, 0x00 }, { 85, 0x87, 0x87, 0x5f },
|
||||
{ 86, 0x87, 0x87, 0x87 }, { 87, 0x87, 0x87, 0xaf },
|
||||
{ 88, 0x87, 0x87, 0xd7 }, { 89, 0x87, 0x87, 0xff },
|
||||
{ 90, 0x87, 0xaf, 0x00 }, { 91, 0x87, 0xaf, 0x5f },
|
||||
{ 92, 0x87, 0xaf, 0x87 }, { 93, 0x87, 0xaf, 0xaf },
|
||||
{ 94, 0x87, 0xaf, 0xd7 }, { 95, 0x87, 0xaf, 0xff },
|
||||
{ 96, 0x87, 0xd7, 0x00 }, { 97, 0x87, 0xd7, 0x5f },
|
||||
{ 98, 0x87, 0xd7, 0x87 }, { 99, 0x87, 0xd7, 0xaf },
|
||||
{ 100, 0x87, 0xd7, 0xd7 }, { 101, 0x87, 0xd7, 0xff },
|
||||
{ 102, 0x87, 0xff, 0x00 }, { 103, 0x87, 0xff, 0x5f },
|
||||
{ 104, 0x87, 0xff, 0x87 }, { 105, 0x87, 0xff, 0xaf },
|
||||
{ 106, 0x87, 0xff, 0xd7 }, { 107, 0x87, 0xff, 0xff },
|
||||
{ 108, 0xaf, 0x00, 0x00 }, { 109, 0xaf, 0x00, 0x5f },
|
||||
{ 110, 0xaf, 0x00, 0x87 }, { 111, 0xaf, 0x00, 0xaf },
|
||||
{ 112, 0xaf, 0x00, 0xd7 }, { 113, 0xaf, 0x00, 0xff },
|
||||
{ 114, 0xaf, 0x5f, 0x00 }, { 115, 0xaf, 0x5f, 0x5f },
|
||||
{ 116, 0xaf, 0x5f, 0x87 }, { 117, 0xaf, 0x5f, 0xaf },
|
||||
{ 118, 0xaf, 0x5f, 0xd7 }, { 119, 0xaf, 0x5f, 0xff },
|
||||
{ 120, 0xaf, 0x87, 0x00 }, { 121, 0xaf, 0x87, 0x5f },
|
||||
{ 122, 0xaf, 0x87, 0x87 }, { 123, 0xaf, 0x87, 0xaf },
|
||||
{ 124, 0xaf, 0x87, 0xd7 }, { 125, 0xaf, 0x87, 0xff },
|
||||
{ 126, 0xaf, 0xaf, 0x00 }, { 127, 0xaf, 0xaf, 0x5f },
|
||||
{ 128, 0xaf, 0xaf, 0x87 }, { 129, 0xaf, 0xaf, 0xaf },
|
||||
{ 130, 0xaf, 0xaf, 0xd7 }, { 131, 0xaf, 0xaf, 0xff },
|
||||
{ 132, 0xaf, 0xd7, 0x00 }, { 133, 0xaf, 0xd7, 0x5f },
|
||||
{ 134, 0xaf, 0xd7, 0x87 }, { 135, 0xaf, 0xd7, 0xaf },
|
||||
{ 136, 0xaf, 0xd7, 0xd7 }, { 137, 0xaf, 0xd7, 0xff },
|
||||
{ 138, 0xaf, 0xff, 0x00 }, { 139, 0xaf, 0xff, 0x5f },
|
||||
{ 140, 0xaf, 0xff, 0x87 }, { 141, 0xaf, 0xff, 0xaf },
|
||||
{ 142, 0xaf, 0xff, 0xd7 }, { 143, 0xaf, 0xff, 0xff },
|
||||
{ 144, 0xd7, 0x00, 0x00 }, { 145, 0xd7, 0x00, 0x5f },
|
||||
{ 146, 0xd7, 0x00, 0x87 }, { 147, 0xd7, 0x00, 0xaf },
|
||||
{ 148, 0xd7, 0x00, 0xd7 }, { 149, 0xd7, 0x00, 0xff },
|
||||
{ 150, 0xd7, 0x5f, 0x00 }, { 151, 0xd7, 0x5f, 0x5f },
|
||||
{ 152, 0xd7, 0x5f, 0x87 }, { 153, 0xd7, 0x5f, 0xaf },
|
||||
{ 154, 0xd7, 0x5f, 0xd7 }, { 155, 0xd7, 0x5f, 0xff },
|
||||
{ 156, 0xd7, 0x87, 0x00 }, { 157, 0xd7, 0x87, 0x5f },
|
||||
{ 158, 0xd7, 0x87, 0x87 }, { 159, 0xd7, 0x87, 0xaf },
|
||||
{ 160, 0xd7, 0x87, 0xd7 }, { 161, 0xd7, 0x87, 0xff },
|
||||
{ 162, 0xd7, 0xaf, 0x00 }, { 163, 0xd7, 0xaf, 0x5f },
|
||||
{ 164, 0xd7, 0xaf, 0x87 }, { 165, 0xd7, 0xaf, 0xaf },
|
||||
{ 166, 0xd7, 0xaf, 0xd7 }, { 167, 0xd7, 0xaf, 0xff },
|
||||
{ 168, 0xd7, 0xd7, 0x00 }, { 169, 0xd7, 0xd7, 0x5f },
|
||||
{ 170, 0xd7, 0xd7, 0x87 }, { 171, 0xd7, 0xd7, 0xaf },
|
||||
{ 172, 0xd7, 0xd7, 0xd7 }, { 173, 0xd7, 0xd7, 0xff },
|
||||
{ 174, 0xd7, 0xff, 0x00 }, { 175, 0xd7, 0xff, 0x5f },
|
||||
{ 176, 0xd7, 0xff, 0x87 }, { 177, 0xd7, 0xff, 0xaf },
|
||||
{ 178, 0xd7, 0xff, 0xd7 }, { 179, 0xd7, 0xff, 0xff },
|
||||
{ 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
|
||||
{ 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
|
||||
{ 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
|
||||
{ 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
|
||||
{ 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
|
||||
{ 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
|
||||
{ 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
|
||||
{ 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
|
||||
{ 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
|
||||
{ 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
|
||||
{ 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
|
||||
{ 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
|
||||
{ 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
|
||||
{ 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
|
||||
{ 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
|
||||
{ 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
|
||||
{ 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
|
||||
{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
|
||||
{ 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
|
||||
{ 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
|
||||
{ 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
|
||||
{ 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
|
||||
{ 224, 0x58, 0x58, 0x58 }, { 225, 0x62, 0x62, 0x62 },
|
||||
{ 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
|
||||
{ 228, 0x80, 0x80, 0x80 }, { 229, 0x8a, 0x8a, 0x8a },
|
||||
{ 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
|
||||
{ 232, 0xa8, 0xa8, 0xa8 }, { 233, 0xb2, 0xb2, 0xb2 },
|
||||
{ 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
|
||||
{ 236, 0xd0, 0xd0, 0xd0 }, { 237, 0xda, 0xda, 0xda },
|
||||
{ 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
|
||||
};
|
||||
const struct colour_rgb colour_to_256[] = {
|
||||
{ 0, 0x00, 0x00, 0x00 }, { 1, 0x00, 0x00, 0x5f },
|
||||
{ 2, 0x00, 0x00, 0x87 }, { 3, 0x00, 0x00, 0xaf },
|
||||
{ 4, 0x00, 0x00, 0xd7 }, { 5, 0x00, 0x00, 0xff },
|
||||
{ 6, 0x00, 0x5f, 0x00 }, { 7, 0x00, 0x5f, 0x5f },
|
||||
{ 8, 0x00, 0x5f, 0x87 }, { 9, 0x00, 0x5f, 0xaf },
|
||||
{ 10, 0x00, 0x5f, 0xd7 }, { 11, 0x00, 0x5f, 0xff },
|
||||
{ 12, 0x00, 0x87, 0x00 }, { 13, 0x00, 0x87, 0x5f },
|
||||
{ 14, 0x00, 0x87, 0x87 }, { 15, 0x00, 0x87, 0xaf },
|
||||
{ 16, 0x00, 0x87, 0xd7 }, { 17, 0x00, 0x87, 0xff },
|
||||
{ 18, 0x00, 0xaf, 0x00 }, { 19, 0x00, 0xaf, 0x5f },
|
||||
{ 20, 0x00, 0xaf, 0x87 }, { 21, 0x00, 0xaf, 0xaf },
|
||||
{ 22, 0x00, 0xaf, 0xd7 }, { 23, 0x00, 0xaf, 0xff },
|
||||
{ 24, 0x00, 0xd7, 0x00 }, { 25, 0x00, 0xd7, 0x5f },
|
||||
{ 26, 0x00, 0xd7, 0x87 }, { 27, 0x00, 0xd7, 0xaf },
|
||||
{ 28, 0x00, 0xd7, 0xd7 }, { 29, 0x00, 0xd7, 0xff },
|
||||
{ 30, 0x00, 0xff, 0x00 }, { 31, 0x00, 0xff, 0x5f },
|
||||
{ 32, 0x00, 0xff, 0x87 }, { 33, 0x00, 0xff, 0xaf },
|
||||
{ 34, 0x00, 0xff, 0xd7 }, { 35, 0x00, 0xff, 0xff },
|
||||
{ 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
|
||||
{ 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
|
||||
{ 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
|
||||
{ 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
|
||||
{ 224, 0x58, 0x58, 0x58 }, { 36, 0x5f, 0x00, 0x00 },
|
||||
{ 37, 0x5f, 0x00, 0x5f }, { 38, 0x5f, 0x00, 0x87 },
|
||||
{ 39, 0x5f, 0x00, 0xaf }, { 40, 0x5f, 0x00, 0xd7 },
|
||||
{ 41, 0x5f, 0x00, 0xff }, { 42, 0x5f, 0x5f, 0x00 },
|
||||
{ 43, 0x5f, 0x5f, 0x5f }, { 44, 0x5f, 0x5f, 0x87 },
|
||||
{ 45, 0x5f, 0x5f, 0xaf }, { 46, 0x5f, 0x5f, 0xd7 },
|
||||
{ 47, 0x5f, 0x5f, 0xff }, { 48, 0x5f, 0x87, 0x00 },
|
||||
{ 49, 0x5f, 0x87, 0x5f }, { 50, 0x5f, 0x87, 0x87 },
|
||||
{ 51, 0x5f, 0x87, 0xaf }, { 52, 0x5f, 0x87, 0xd7 },
|
||||
{ 53, 0x5f, 0x87, 0xff }, { 54, 0x5f, 0xaf, 0x00 },
|
||||
{ 55, 0x5f, 0xaf, 0x5f }, { 56, 0x5f, 0xaf, 0x87 },
|
||||
{ 57, 0x5f, 0xaf, 0xaf }, { 58, 0x5f, 0xaf, 0xd7 },
|
||||
{ 59, 0x5f, 0xaf, 0xff }, { 60, 0x5f, 0xd7, 0x00 },
|
||||
{ 61, 0x5f, 0xd7, 0x5f }, { 62, 0x5f, 0xd7, 0x87 },
|
||||
{ 63, 0x5f, 0xd7, 0xaf }, { 64, 0x5f, 0xd7, 0xd7 },
|
||||
{ 65, 0x5f, 0xd7, 0xff }, { 66, 0x5f, 0xff, 0x00 },
|
||||
{ 67, 0x5f, 0xff, 0x5f }, { 68, 0x5f, 0xff, 0x87 },
|
||||
{ 69, 0x5f, 0xff, 0xaf }, { 70, 0x5f, 0xff, 0xd7 },
|
||||
{ 71, 0x5f, 0xff, 0xff }, { 225, 0x62, 0x62, 0x62 },
|
||||
{ 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
|
||||
{ 228, 0x80, 0x80, 0x80 }, { 72, 0x87, 0x00, 0x00 },
|
||||
{ 73, 0x87, 0x00, 0x5f }, { 74, 0x87, 0x00, 0x87 },
|
||||
{ 75, 0x87, 0x00, 0xaf }, { 76, 0x87, 0x00, 0xd7 },
|
||||
{ 77, 0x87, 0x00, 0xff }, { 78, 0x87, 0x5f, 0x00 },
|
||||
{ 79, 0x87, 0x5f, 0x5f }, { 80, 0x87, 0x5f, 0x87 },
|
||||
{ 81, 0x87, 0x5f, 0xaf }, { 82, 0x87, 0x5f, 0xd7 },
|
||||
{ 83, 0x87, 0x5f, 0xff }, { 84, 0x87, 0x87, 0x00 },
|
||||
{ 85, 0x87, 0x87, 0x5f }, { 86, 0x87, 0x87, 0x87 },
|
||||
{ 87, 0x87, 0x87, 0xaf }, { 88, 0x87, 0x87, 0xd7 },
|
||||
{ 89, 0x87, 0x87, 0xff }, { 90, 0x87, 0xaf, 0x00 },
|
||||
{ 91, 0x87, 0xaf, 0x5f }, { 92, 0x87, 0xaf, 0x87 },
|
||||
{ 93, 0x87, 0xaf, 0xaf }, { 94, 0x87, 0xaf, 0xd7 },
|
||||
{ 95, 0x87, 0xaf, 0xff }, { 96, 0x87, 0xd7, 0x00 },
|
||||
{ 97, 0x87, 0xd7, 0x5f }, { 98, 0x87, 0xd7, 0x87 },
|
||||
{ 99, 0x87, 0xd7, 0xaf }, { 100, 0x87, 0xd7, 0xd7 },
|
||||
{ 101, 0x87, 0xd7, 0xff }, { 102, 0x87, 0xff, 0x00 },
|
||||
{ 103, 0x87, 0xff, 0x5f }, { 104, 0x87, 0xff, 0x87 },
|
||||
{ 105, 0x87, 0xff, 0xaf }, { 106, 0x87, 0xff, 0xd7 },
|
||||
{ 107, 0x87, 0xff, 0xff }, { 229, 0x8a, 0x8a, 0x8a },
|
||||
{ 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
|
||||
{ 232, 0xa8, 0xa8, 0xa8 }, { 108, 0xaf, 0x00, 0x00 },
|
||||
{ 109, 0xaf, 0x00, 0x5f }, { 110, 0xaf, 0x00, 0x87 },
|
||||
{ 111, 0xaf, 0x00, 0xaf }, { 112, 0xaf, 0x00, 0xd7 },
|
||||
{ 113, 0xaf, 0x00, 0xff }, { 114, 0xaf, 0x5f, 0x00 },
|
||||
{ 115, 0xaf, 0x5f, 0x5f }, { 116, 0xaf, 0x5f, 0x87 },
|
||||
{ 117, 0xaf, 0x5f, 0xaf }, { 118, 0xaf, 0x5f, 0xd7 },
|
||||
{ 119, 0xaf, 0x5f, 0xff }, { 120, 0xaf, 0x87, 0x00 },
|
||||
{ 121, 0xaf, 0x87, 0x5f }, { 122, 0xaf, 0x87, 0x87 },
|
||||
{ 123, 0xaf, 0x87, 0xaf }, { 124, 0xaf, 0x87, 0xd7 },
|
||||
{ 125, 0xaf, 0x87, 0xff }, { 126, 0xaf, 0xaf, 0x00 },
|
||||
{ 127, 0xaf, 0xaf, 0x5f }, { 128, 0xaf, 0xaf, 0x87 },
|
||||
{ 129, 0xaf, 0xaf, 0xaf }, { 130, 0xaf, 0xaf, 0xd7 },
|
||||
{ 131, 0xaf, 0xaf, 0xff }, { 132, 0xaf, 0xd7, 0x00 },
|
||||
{ 133, 0xaf, 0xd7, 0x5f }, { 134, 0xaf, 0xd7, 0x87 },
|
||||
{ 135, 0xaf, 0xd7, 0xaf }, { 136, 0xaf, 0xd7, 0xd7 },
|
||||
{ 137, 0xaf, 0xd7, 0xff }, { 138, 0xaf, 0xff, 0x00 },
|
||||
{ 139, 0xaf, 0xff, 0x5f }, { 140, 0xaf, 0xff, 0x87 },
|
||||
{ 141, 0xaf, 0xff, 0xaf }, { 142, 0xaf, 0xff, 0xd7 },
|
||||
{ 143, 0xaf, 0xff, 0xff }, { 233, 0xb2, 0xb2, 0xb2 },
|
||||
{ 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
|
||||
{ 236, 0xd0, 0xd0, 0xd0 }, { 144, 0xd7, 0x00, 0x00 },
|
||||
{ 145, 0xd7, 0x00, 0x5f }, { 146, 0xd7, 0x00, 0x87 },
|
||||
{ 147, 0xd7, 0x00, 0xaf }, { 148, 0xd7, 0x00, 0xd7 },
|
||||
{ 149, 0xd7, 0x00, 0xff }, { 150, 0xd7, 0x5f, 0x00 },
|
||||
{ 151, 0xd7, 0x5f, 0x5f }, { 152, 0xd7, 0x5f, 0x87 },
|
||||
{ 153, 0xd7, 0x5f, 0xaf }, { 154, 0xd7, 0x5f, 0xd7 },
|
||||
{ 155, 0xd7, 0x5f, 0xff }, { 156, 0xd7, 0x87, 0x00 },
|
||||
{ 157, 0xd7, 0x87, 0x5f }, { 158, 0xd7, 0x87, 0x87 },
|
||||
{ 159, 0xd7, 0x87, 0xaf }, { 160, 0xd7, 0x87, 0xd7 },
|
||||
{ 161, 0xd7, 0x87, 0xff }, { 162, 0xd7, 0xaf, 0x00 },
|
||||
{ 163, 0xd7, 0xaf, 0x5f }, { 164, 0xd7, 0xaf, 0x87 },
|
||||
{ 165, 0xd7, 0xaf, 0xaf }, { 166, 0xd7, 0xaf, 0xd7 },
|
||||
{ 167, 0xd7, 0xaf, 0xff }, { 168, 0xd7, 0xd7, 0x00 },
|
||||
{ 169, 0xd7, 0xd7, 0x5f }, { 170, 0xd7, 0xd7, 0x87 },
|
||||
{ 171, 0xd7, 0xd7, 0xaf }, { 172, 0xd7, 0xd7, 0xd7 },
|
||||
{ 173, 0xd7, 0xd7, 0xff }, { 174, 0xd7, 0xff, 0x00 },
|
||||
{ 175, 0xd7, 0xff, 0x5f }, { 176, 0xd7, 0xff, 0x87 },
|
||||
{ 177, 0xd7, 0xff, 0xaf }, { 178, 0xd7, 0xff, 0xd7 },
|
||||
{ 179, 0xd7, 0xff, 0xff }, { 237, 0xda, 0xda, 0xda },
|
||||
{ 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
|
||||
{ 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
|
||||
{ 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
|
||||
{ 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
|
||||
{ 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
|
||||
{ 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
|
||||
{ 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
|
||||
{ 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
|
||||
{ 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
|
||||
{ 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
|
||||
{ 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
|
||||
{ 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
|
||||
{ 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
|
||||
{ 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
|
||||
{ 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
|
||||
{ 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
|
||||
{ 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
|
||||
{ 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
|
||||
{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
|
||||
};
|
||||
|
||||
int colour_cmp_rgb(const void *, const void *);
|
||||
|
||||
/* Compare function for bsearch(). */
|
||||
int
|
||||
colour_cmp_rgb(const void *lhs0, const void *rhs0)
|
||||
static int
|
||||
colour_dist_sq(int R, int G, int B, int r, int g, int b)
|
||||
{
|
||||
const struct colour_rgb *lhs = lhs0, *rhs = rhs0;
|
||||
|
||||
if (lhs->r < rhs->r)
|
||||
return (-1);
|
||||
if (lhs->r > rhs->r)
|
||||
return (1);
|
||||
|
||||
if (lhs->g < rhs->g)
|
||||
return (-1);
|
||||
if (lhs->g > rhs->g)
|
||||
return (1);
|
||||
|
||||
if (lhs->b < rhs->b)
|
||||
return (-1);
|
||||
if (lhs->b > rhs->b)
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
return ((R - r) * (R - r) + (G - g) * (G - g) + (B - b) * (B - b));
|
||||
}
|
||||
|
||||
/* Work out the nearest colour from the 256 colour set. */
|
||||
static int
|
||||
colour_to_6cube(int v)
|
||||
{
|
||||
if (v < 48)
|
||||
return (0);
|
||||
if (v < 114)
|
||||
return (1);
|
||||
return ((v - 35) / 40);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an RGB triplet to the xterm(1) 256 colour palette.
|
||||
*
|
||||
* xterm provides a 6x6x6 colour cube (16 - 231) and 24 greys (232 - 255). We
|
||||
* map our RGB colour to the closest in the cube, also work out the closest
|
||||
* grey, and use the nearest of the two.
|
||||
*
|
||||
* Note that the xterm has much lower resolution for darker colors (they are
|
||||
* not evenly spread out), so our 6 levels are not evenly spread: 0x0, 0x5f
|
||||
* (95), 0x87 (135), 0xaf (175), 0xd7 (215) and 0xff (255). Greys are more
|
||||
* evenly spread (8, 18, 28 ... 238).
|
||||
*/
|
||||
int
|
||||
colour_find_rgb(u_char r, u_char g, u_char b)
|
||||
{
|
||||
struct colour_rgb rgb = { .r = r, .g = g, .b = b }, *found;
|
||||
u_int distance, lowest, colour, i;
|
||||
int dr, dg, db;
|
||||
static const int q2c[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
|
||||
int qr, qg, qb, cr, cg, cb, d, idx;
|
||||
int grey_avg, grey_idx, grey;
|
||||
|
||||
found = bsearch(&rgb, colour_to_256, nitems(colour_to_256),
|
||||
sizeof colour_to_256[0], colour_cmp_rgb);
|
||||
if (found != NULL)
|
||||
return (16 + found->i);
|
||||
/* Map RGB to 6x6x6 cube. */
|
||||
qr = colour_to_6cube(r); cr = q2c[qr];
|
||||
qg = colour_to_6cube(g); cg = q2c[qg];
|
||||
qb = colour_to_6cube(b); cb = q2c[qb];
|
||||
|
||||
colour = 16;
|
||||
lowest = UINT_MAX;
|
||||
for (i = 0; i < 240; i++) {
|
||||
dr = (int)colour_from_256[i].r - r;
|
||||
dg = (int)colour_from_256[i].g - g;
|
||||
db = (int)colour_from_256[i].b - b;
|
||||
/* If we have hit the colour exactly, return early. */
|
||||
if (cr == r && cg == g && cb == b)
|
||||
return ((16 + (36 * qr) + (6 * qg) + qb) | COLOUR_FLAG_256);
|
||||
|
||||
distance = dr * dr + dg * dg + db * db;
|
||||
if (distance < lowest) {
|
||||
lowest = distance;
|
||||
colour = 16 + i;
|
||||
}
|
||||
}
|
||||
return (colour);
|
||||
/* Work out the closest grey (average of RGB). */
|
||||
grey_avg = (r + g + b) / 3;
|
||||
if (grey_avg > 238)
|
||||
grey_idx = 23;
|
||||
else
|
||||
grey_idx = (grey_avg - 3) / 10;
|
||||
grey = 8 + (10 * grey_idx);
|
||||
|
||||
/* Is grey or 6x6x6 colour closest? */
|
||||
d = colour_dist_sq(cr, cg, cb, r, g, b);
|
||||
if (colour_dist_sq(grey, grey, grey, r, g, b) < d)
|
||||
idx = 232 + grey_idx;
|
||||
else
|
||||
idx = 16 + (36 * qr) + (6 * qg) + qb;
|
||||
return (idx | COLOUR_FLAG_256);
|
||||
}
|
||||
|
||||
/* Set grid cell foreground colour. */
|
||||
void
|
||||
colour_set_fg(struct grid_cell *gc, int c)
|
||||
/* Join RGB into a colour. */
|
||||
int
|
||||
colour_join_rgb(u_char r, u_char g, u_char b)
|
||||
{
|
||||
if (c & 0x100)
|
||||
gc->flags |= GRID_FLAG_FG256;
|
||||
gc->fg = c;
|
||||
return ((((int)((r) & 0xff)) << 16) |
|
||||
(((int)((g) & 0xff)) << 8) |
|
||||
(((int)((b) & 0xff))) | COLOUR_FLAG_RGB);
|
||||
}
|
||||
|
||||
/* Set grid cell background colour. */
|
||||
/* Split colour into RGB. */
|
||||
void
|
||||
colour_set_bg(struct grid_cell *gc, int c)
|
||||
colour_split_rgb(int c, u_char *r, u_char *g, u_char *b)
|
||||
{
|
||||
if (c & 0x100)
|
||||
gc->flags |= GRID_FLAG_BG256;
|
||||
gc->bg = c;
|
||||
*r = (c >> 16) & 0xff;
|
||||
*g = (c >> 8) & 0xff;
|
||||
*b = c & 0xff;
|
||||
}
|
||||
|
||||
/* Convert colour to a string. */
|
||||
@@ -359,9 +109,16 @@ const char *
|
||||
colour_tostring(int c)
|
||||
{
|
||||
static char s[32];
|
||||
u_char r, g, b;
|
||||
|
||||
if (c & 0x100) {
|
||||
xsnprintf(s, sizeof s, "colour%d", c & ~0x100);
|
||||
if (c & COLOUR_FLAG_RGB) {
|
||||
colour_split_rgb(c, &r, &g, &b);
|
||||
xsnprintf(s, sizeof s, "#%02x%02x%02x", r, g, b);
|
||||
return (s);
|
||||
}
|
||||
|
||||
if (c & COLOUR_FLAG_256) {
|
||||
xsnprintf(s, sizeof s, "colour%u", c & 0xff);
|
||||
return (s);
|
||||
}
|
||||
|
||||
@@ -421,14 +178,14 @@ colour_fromstring(const char *s)
|
||||
n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
|
||||
if (n != 3)
|
||||
return (-1);
|
||||
return (colour_find_rgb(r, g, b) | 0x100);
|
||||
return (colour_join_rgb(r, g, b));
|
||||
}
|
||||
|
||||
if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
|
||||
n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
return (n | 0x100);
|
||||
return (n | COLOUR_FLAG_256);
|
||||
}
|
||||
|
||||
if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
|
||||
|
||||
29
compat.h
29
compat.h
@@ -35,6 +35,14 @@
|
||||
#define ECHOPRT 0
|
||||
#endif
|
||||
|
||||
#ifndef ACCESSPERMS
|
||||
#define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
#endif
|
||||
|
||||
#if !defined(FIONREAD) && defined(__sun)
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BSD_TYPES
|
||||
typedef uint8_t u_int8_t;
|
||||
typedef uint16_t u_int16_t;
|
||||
@@ -190,7 +198,7 @@ typedef uint64_t u_int64_t;
|
||||
|
||||
#ifndef HAVE_CLOSEFROM
|
||||
/* closefrom.c */
|
||||
void closefrom(int);
|
||||
void closefrom(int);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRCASESTR
|
||||
@@ -223,6 +231,16 @@ size_t strlcat(char *, const char *, size_t);
|
||||
int daemon(int, int);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETPROGNAME
|
||||
/* getprogname.c */
|
||||
const char *getprogname(void);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SETPROCTITLE
|
||||
/* setproctitle.c */
|
||||
void setproctitle(const char *, ...);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_B64_NTOP
|
||||
/* b64_ntop.c */
|
||||
#undef b64_ntop /* for Cygwin */
|
||||
@@ -269,7 +287,14 @@ int openat(int, const char *, int, ...);
|
||||
|
||||
#ifndef HAVE_REALLOCARRAY
|
||||
/* reallocarray.c */
|
||||
void *reallocarray(void *, size_t, size_t size);
|
||||
void *reallocarray(void *, size_t, size_t);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UTF8PROC
|
||||
/* utf8proc.c */
|
||||
int utf8proc_wcwidth(wchar_t);
|
||||
int utf8proc_mbtowc(wchar_t *, const char *, size_t);
|
||||
int utf8proc_wctomb(char *, wchar_t);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETOPT
|
||||
|
||||
@@ -84,7 +84,8 @@ BSDgetopt(int nargc, char *const *nargv, const char *ostr)
|
||||
++BSDoptind;
|
||||
if (BSDopterr && *ostr != ':')
|
||||
(void)fprintf(stderr,
|
||||
"%s: unknown option -- %c\n", __progname, BSDoptopt);
|
||||
"%s: unknown option -- %c\n", getprogname(),
|
||||
BSDoptopt);
|
||||
return (BADCH);
|
||||
}
|
||||
if (*++oli != ':') { /* don't need argument */
|
||||
@@ -102,7 +103,7 @@ BSDgetopt(int nargc, char *const *nargv, const char *ostr)
|
||||
if (BSDopterr)
|
||||
(void)fprintf(stderr,
|
||||
"%s: option requires an argument -- %c\n",
|
||||
__progname, BSDoptopt);
|
||||
getprogname(), BSDoptopt);
|
||||
return (BADCH);
|
||||
}
|
||||
else /* white space */
|
||||
|
||||
43
compat/getprogname.c
Normal file
43
compat/getprogname.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF 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"
|
||||
|
||||
#if defined(HAVE_PROGRAM_INVOCATION_SHORT_NAME)
|
||||
const char *
|
||||
getprogname(void)
|
||||
{
|
||||
extern char *program_invocation_short_name;
|
||||
|
||||
return (program_invocation_short_name);
|
||||
}
|
||||
#elif defined(HAVE___PROGNAME)
|
||||
const char *
|
||||
getprogname(void)
|
||||
{
|
||||
extern char *__progname;
|
||||
|
||||
return (__progname);
|
||||
}
|
||||
#else
|
||||
const char *
|
||||
getprogname(void)
|
||||
{
|
||||
return ("tmux");
|
||||
}
|
||||
#endif
|
||||
51
compat/setproctitle.c
Normal file
51
compat/setproctitle.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF 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"
|
||||
|
||||
#if defined(HAVE_PRCTL) && defined(HAVE_PR_SET_NAME)
|
||||
|
||||
#include <sys/prctl.h>
|
||||
|
||||
void
|
||||
setproctitle(const char *fmt, ...)
|
||||
{
|
||||
char title[16], name[16], *cp;
|
||||
va_list ap;
|
||||
int used;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(title, sizeof title, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
used = snprintf(name, sizeof name, "%s: %s", getprogname(), title);
|
||||
if (used >= (int)sizeof name) {
|
||||
cp = strrchr(name, ' ');
|
||||
if (cp != NULL)
|
||||
*cp = '\0';
|
||||
}
|
||||
prctl(PR_SET_NAME, name);
|
||||
}
|
||||
#else
|
||||
void
|
||||
setproctitle(const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
70
compat/utf8proc.c
Normal file
70
compat/utf8proc.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Joshua Rubin <joshua@rubixconsulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF 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 <utf8proc.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
int
|
||||
utf8proc_wcwidth(wchar_t wc)
|
||||
{
|
||||
int cat;
|
||||
|
||||
cat = utf8proc_category(wc);
|
||||
if (cat == UTF8PROC_CATEGORY_CO) {
|
||||
/*
|
||||
* The private use category is where powerline and similar
|
||||
* codepoints are stored, they have "ambiguous" width - use 1.
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
if (cat == UTF8PROC_CATEGORY_SO) {
|
||||
/* Symbols, like emoji, should always use width 1. */
|
||||
return (1);
|
||||
}
|
||||
return (utf8proc_charwidth(wc));
|
||||
}
|
||||
|
||||
int
|
||||
utf8proc_mbtowc(wchar_t *pwc, const char *s, size_t n)
|
||||
{
|
||||
utf8proc_ssize_t slen;
|
||||
|
||||
if (s == NULL)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* *pwc == -1 indicates invalid codepoint
|
||||
* slen < 0 indicates an error
|
||||
*/
|
||||
slen = utf8proc_iterate(s, n, pwc);
|
||||
if (*pwc == (wchar_t)-1 || slen < 0)
|
||||
return (-1);
|
||||
return (slen);
|
||||
}
|
||||
|
||||
int
|
||||
utf8proc_wctomb(char *s, wchar_t wc)
|
||||
{
|
||||
if (s == NULL)
|
||||
return (0);
|
||||
|
||||
if (!utf8proc_codepoint_valid(wc))
|
||||
return (-1);
|
||||
return (utf8proc_encode_char(wc, s));
|
||||
}
|
||||
132
configure.ac
132
configure.ac
@@ -1,6 +1,6 @@
|
||||
# configure.ac
|
||||
|
||||
AC_INIT(tmux, 2.2)
|
||||
AC_INIT(tmux, 2.3)
|
||||
|
||||
AC_CONFIG_AUX_DIR(etc)
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
@@ -40,6 +40,14 @@ AC_ARG_ENABLE(
|
||||
)
|
||||
AM_CONDITIONAL(IS_COVERAGE, test "x$found_coverage" = xyes)
|
||||
|
||||
# Is this --enable-profile?
|
||||
AC_ARG_ENABLE(
|
||||
profile,
|
||||
AC_HELP_STRING(--enable-profile, enable profile build flags),
|
||||
found_profile=$enable_profile
|
||||
)
|
||||
AM_CONDITIONAL(IS_PROFILE, test "x$found_profile" = xyes)
|
||||
|
||||
# Is this a static build?
|
||||
AC_ARG_ENABLE(
|
||||
static,
|
||||
@@ -48,7 +56,7 @@ AC_ARG_ENABLE(
|
||||
)
|
||||
if test "x$found_static" = xyes; then
|
||||
LDFLAGS="$LDFLAGS -static"
|
||||
PKG_CONFIG="pkg-config --static"
|
||||
test "x$PKG_CONFIG" != x && PKG_CONFIG="$PKG_CONFIG --static"
|
||||
fi
|
||||
|
||||
# Is this gcc?
|
||||
@@ -87,12 +95,10 @@ AC_MSG_RESULT($found_glibc)
|
||||
AC_CHECK_HEADERS(
|
||||
[ \
|
||||
bitstring.h \
|
||||
curses.h \
|
||||
dirent.h \
|
||||
fcntl.h \
|
||||
inttypes.h \
|
||||
libutil.h \
|
||||
ncurses.h \
|
||||
ndir.h \
|
||||
paths.h \
|
||||
pty.h \
|
||||
@@ -113,7 +119,7 @@ AC_CHECK_FUNCS(
|
||||
[ \
|
||||
dirfd \
|
||||
flock \
|
||||
setproctitle \
|
||||
prctl \
|
||||
sysconf \
|
||||
cfmakeraw \
|
||||
]
|
||||
@@ -140,30 +146,60 @@ PKG_CHECK_MODULES(
|
||||
)
|
||||
]
|
||||
)
|
||||
AC_CHECK_HEADER(
|
||||
event.h,
|
||||
,
|
||||
found_libevent=no
|
||||
)
|
||||
if test "x$found_libevent" = xno; then
|
||||
AC_MSG_ERROR("libevent not found")
|
||||
fi
|
||||
|
||||
# Look for ncurses
|
||||
# Look for ncurses.
|
||||
PKG_CHECK_MODULES(
|
||||
LIBNCURSES,
|
||||
ncurses,
|
||||
[
|
||||
CPPFLAGS="$LIBNCURSES_CFLAGS $CPPFLAGS"
|
||||
LIBS="$LIBNCURSES_LIBS $LIBS"
|
||||
found_curses=yes
|
||||
found_ncurses=yes
|
||||
],
|
||||
[
|
||||
AC_SEARCH_LIBS(
|
||||
setupterm,
|
||||
[ncurses curses terminfo],
|
||||
found_curses=yes,
|
||||
found_curses=no
|
||||
)
|
||||
]
|
||||
found_ncurses=no
|
||||
)
|
||||
if test "x$found_curses" = xno; then
|
||||
AC_MSG_ERROR("curses not found")
|
||||
if test "x$found_ncurses" = xno; then
|
||||
# pkg-config didn't work, try ncurses.
|
||||
AC_CHECK_LIB(
|
||||
ncurses,
|
||||
setupterm,
|
||||
found_ncurses=yes,
|
||||
found_ncurses=no
|
||||
)
|
||||
AC_CHECK_HEADER(
|
||||
ncurses.h,
|
||||
,
|
||||
found_ncurses=no)
|
||||
fi
|
||||
if test "x$found_ncurses" = xyes; then
|
||||
LIBS="$LIBS -lncurses"
|
||||
AC_DEFINE(HAVE_NCURSES_H)
|
||||
else
|
||||
# No ncurses, try curses.
|
||||
AC_CHECK_LIB(
|
||||
curses,
|
||||
setupterm,
|
||||
found_curses=yes,
|
||||
found_curses=no
|
||||
)
|
||||
AC_CHECK_HEADER(
|
||||
curses.h,
|
||||
,
|
||||
found_curses=no)
|
||||
if test "x$found_curses" = xyes; then
|
||||
LIBS="$LIBS -lcurses"
|
||||
AC_DEFINE(HAVE_CURSES_H)
|
||||
else
|
||||
AC_MSG_ERROR("curses or ncurses not found")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Look for utempter.
|
||||
@@ -188,6 +224,29 @@ if test "x$found_utempter" = xyes; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Look for utf8proc.
|
||||
AC_ARG_ENABLE(
|
||||
utf8proc,
|
||||
AC_HELP_STRING(--enable-utf8proc, use utf8proc if it is installed),
|
||||
found_utf8proc=$enable_utf8proc,
|
||||
found_utf8proc=no
|
||||
)
|
||||
if test "x$found_utf8proc" = xyes; then
|
||||
AC_CHECK_HEADER(utf8proc.h, found_utf8proc=yes, found_utf8proc=no)
|
||||
if test "x$found_utf8proc" = xyes; then
|
||||
AC_SEARCH_LIBS(
|
||||
utf8proc_charwidth,
|
||||
utf8proc,
|
||||
found_utf8proc=yes,
|
||||
found_utf8proc=no
|
||||
)
|
||||
if test "x$found_utf8proc" = xyes; then
|
||||
AC_DEFINE(HAVE_UTF8PROC)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_UTF8PROC, [test "x$found_utf8proc" = xyes])
|
||||
|
||||
# Check for b64_ntop.
|
||||
AC_MSG_CHECKING(for b64_ntop)
|
||||
AC_TRY_LINK(
|
||||
@@ -298,6 +357,20 @@ if test "x$found_daemon" = xyes; then
|
||||
fi
|
||||
AM_CONDITIONAL(NO_DAEMON, [test "x$found_daemon" = xno])
|
||||
|
||||
# Look for getprogname, compat/getprogname.c used if missing.
|
||||
AC_CHECK_FUNC(getprogname, found_getprogname=yes, found_getprogname=no)
|
||||
if test "x$found_getprogname" = xyes; then
|
||||
AC_DEFINE(HAVE_GETPROGNAME)
|
||||
fi
|
||||
AM_CONDITIONAL(NO_GETPROGNAME, [test "x$found_getprogname" = xno])
|
||||
|
||||
# Look for setproctitle, compat/setproctitle.c used if missing.
|
||||
AC_CHECK_FUNC(setproctitle, found_setproctitle=yes, found_setproctitle=no)
|
||||
if test "x$found_setproctitle" = xyes; then
|
||||
AC_DEFINE(HAVE_SETPROCTITLE)
|
||||
fi
|
||||
AM_CONDITIONAL(NO_SETPROCTITLE, [test "x$found_setproctitle" = xno])
|
||||
|
||||
# Look for setenv, compat/setenv.c used if missing.
|
||||
AC_CHECK_FUNC(setenv, found_setenv=yes, found_setenv=no)
|
||||
if test "x$found_setenv" = xyes; then
|
||||
@@ -475,6 +548,31 @@ AC_LINK_IFELSE([AC_LANG_SOURCE(
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
# Look for program_invocation_short_name.
|
||||
AC_MSG_CHECKING(for program_invocation_short_name)
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE(
|
||||
[
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
extern char *program_invocation_short_name;
|
||||
int main(void) {
|
||||
const char *cp = program_invocation_short_name;
|
||||
printf("%s\n", cp);
|
||||
exit(0);
|
||||
}
|
||||
])],
|
||||
[AC_DEFINE(HAVE_PROGRAM_INVOCATION_SHORT_NAME) AC_MSG_RESULT(yes)],
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
# Look for prctl(PR_SET_NAME).
|
||||
AC_CHECK_DECL(
|
||||
PR_SET_NAME,
|
||||
AC_DEFINE(HAVE_PR_SET_NAME),
|
||||
,
|
||||
[#include <sys/prctl.h>]
|
||||
)
|
||||
|
||||
# Look for fcntl(F_CLOSEM).
|
||||
AC_CHECK_DECL(
|
||||
F_CLOSEM,
|
||||
|
||||
28
environ.c
28
environ.c
@@ -195,19 +195,25 @@ environ_update(const char *vars, struct environ *srcenv,
|
||||
void
|
||||
environ_push(struct environ *env)
|
||||
{
|
||||
struct environ_entry *envent;
|
||||
char *v;
|
||||
|
||||
while (*environ != NULL) {
|
||||
v = xstrdup(*environ);
|
||||
v[strcspn(v, "=")] = '\0';
|
||||
|
||||
unsetenv(v);
|
||||
free(v);
|
||||
}
|
||||
struct environ_entry *envent;
|
||||
|
||||
environ = xcalloc(1, sizeof *environ);
|
||||
RB_FOREACH(envent, environ, env) {
|
||||
if (envent->value != NULL)
|
||||
if (envent->value != NULL && *envent->name != '\0')
|
||||
setenv(envent->name, envent->value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Log the environment. */
|
||||
void
|
||||
environ_log(struct environ *env, const char *prefix)
|
||||
{
|
||||
struct environ_entry *envent;
|
||||
|
||||
RB_FOREACH(envent, environ, env) {
|
||||
if (envent->value != NULL && *envent->name != '\0') {
|
||||
log_debug("%s%s=%s", prefix, envent->name,
|
||||
envent->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
format.c
22
format.c
@@ -485,6 +485,7 @@ struct format_tree *
|
||||
format_create(struct cmd_q *cmdq, int flags)
|
||||
{
|
||||
struct format_tree *ft;
|
||||
struct cmd *cmd;
|
||||
|
||||
if (!event_initialized(&format_job_event)) {
|
||||
evtimer_set(&format_job_event, format_job_timer, NULL);
|
||||
@@ -503,6 +504,10 @@ format_create(struct cmd_q *cmdq, int flags)
|
||||
|
||||
if (cmdq != NULL && cmdq->cmd != NULL)
|
||||
format_add(ft, "command_name", "%s", cmdq->cmd->entry->name);
|
||||
if (cmdq != NULL && cmdq->parent != NULL) {
|
||||
cmd = cmdq->parent->cmd;
|
||||
format_add(ft, "command_hooked", "%s", cmd->entry->name);
|
||||
}
|
||||
|
||||
return (ft);
|
||||
}
|
||||
@@ -862,27 +867,18 @@ fail:
|
||||
char *
|
||||
format_expand_time(struct format_tree *ft, const char *fmt, time_t t)
|
||||
{
|
||||
char *tmp, *expanded;
|
||||
size_t tmplen;
|
||||
struct tm *tm;
|
||||
char s[2048];
|
||||
|
||||
if (fmt == NULL || *fmt == '\0')
|
||||
return (xstrdup(""));
|
||||
|
||||
tm = localtime(&t);
|
||||
|
||||
tmp = NULL;
|
||||
tmplen = strlen(fmt);
|
||||
if (strftime(s, sizeof s, fmt, tm) == 0)
|
||||
return (xstrdup(""));
|
||||
|
||||
do {
|
||||
tmp = xreallocarray(tmp, 2, tmplen);
|
||||
tmplen *= 2;
|
||||
} while (strftime(tmp, tmplen, fmt, tm) == 0);
|
||||
|
||||
expanded = format_expand(ft, tmp);
|
||||
free(tmp);
|
||||
|
||||
return (expanded);
|
||||
return (format_expand(ft, s));
|
||||
}
|
||||
|
||||
/* Expand keys in a template. */
|
||||
|
||||
@@ -67,6 +67,7 @@ grid_view_clear_history(struct grid *gd)
|
||||
grid_collect_history(gd);
|
||||
grid_scroll_history(gd);
|
||||
}
|
||||
gd->hscrolled = 0;
|
||||
}
|
||||
|
||||
/* Clear area. */
|
||||
|
||||
85
grid.c
85
grid.c
@@ -37,14 +37,12 @@
|
||||
|
||||
/* Default grid cell data. */
|
||||
const struct grid_cell grid_default_cell = {
|
||||
0, 0, { .fg = 8 }, { .bg = 8 }, { { ' ' }, 0, 1, 1 }
|
||||
0, 0, 8, 8, { { ' ' }, 0, 1, 1 }
|
||||
};
|
||||
const struct grid_cell_entry grid_default_entry = {
|
||||
0, { .data = { 0, 8, 8, ' ' } }
|
||||
};
|
||||
|
||||
int grid_check_y(struct grid *, u_int);
|
||||
|
||||
void grid_reflow_copy(struct grid_line *, u_int, struct grid_line *l,
|
||||
u_int, u_int);
|
||||
void grid_reflow_join(struct grid *, u_int *, struct grid_line *, u_int);
|
||||
@@ -64,7 +62,7 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py)
|
||||
}
|
||||
|
||||
/* Check grid y position. */
|
||||
int
|
||||
static int
|
||||
grid_check_y(struct grid *gd, u_int py)
|
||||
{
|
||||
if ((py) >= (gd)->hsize + (gd)->sy) {
|
||||
@@ -74,6 +72,21 @@ grid_check_y(struct grid *gd, u_int py)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Compare grid cells. Return 1 if equal, 0 if not. */
|
||||
int
|
||||
grid_cells_equal(const struct grid_cell *gca, const struct grid_cell *gcb)
|
||||
{
|
||||
if (gca->fg != gcb->fg || gca->bg != gcb->bg)
|
||||
return (0);
|
||||
if (gca->attr != gcb->attr || gca->flags != gcb->flags)
|
||||
return (0);
|
||||
if (gca->data.width != gcb->data.width)
|
||||
return (0);
|
||||
if (gca->data.size != gcb->data.size)
|
||||
return (0);
|
||||
return (memcmp(gca->data.data, gcb->data.data, gca->data.size) == 0);
|
||||
}
|
||||
|
||||
/* Create a new grid. */
|
||||
struct grid *
|
||||
grid_create(u_int sx, u_int sy, u_int hlimit)
|
||||
@@ -86,6 +99,7 @@ grid_create(u_int sx, u_int sy, u_int hlimit)
|
||||
|
||||
gd->flags = GRID_HISTORY;
|
||||
|
||||
gd->hscrolled = 0;
|
||||
gd->hsize = 0;
|
||||
gd->hlimit = hlimit;
|
||||
|
||||
@@ -131,7 +145,7 @@ grid_compare(struct grid *ga, struct grid *gb)
|
||||
for (xx = 0; xx < gla->cellsize; xx++) {
|
||||
grid_get_cell(ga, xx, yy, &gca);
|
||||
grid_get_cell(gb, xx, yy, &gcb);
|
||||
if (memcmp(&gca, &gcb, sizeof (struct grid_cell)) != 0)
|
||||
if (!grid_cells_equal(&gca, &gcb))
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
@@ -157,6 +171,8 @@ grid_collect_history(struct grid *gd)
|
||||
|
||||
grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy);
|
||||
gd->hsize -= yy;
|
||||
if (gd->hscrolled > gd->hsize)
|
||||
gd->hscrolled = gd->hsize;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -173,6 +189,7 @@ grid_scroll_history(struct grid *gd)
|
||||
sizeof *gd->linedata);
|
||||
memset(&gd->linedata[yy], 0, sizeof gd->linedata[yy]);
|
||||
|
||||
gd->hscrolled++;
|
||||
gd->hsize++;
|
||||
}
|
||||
|
||||
@@ -183,7 +200,9 @@ grid_clear_history(struct grid *gd)
|
||||
grid_clear_lines(gd, 0, gd->hsize);
|
||||
grid_move_lines(gd, 0, gd->hsize, gd->sy);
|
||||
|
||||
gd->hscrolled = 0;
|
||||
gd->hsize = 0;
|
||||
|
||||
gd->linedata = xreallocarray(gd->linedata, gd->sy,
|
||||
sizeof *gd->linedata);
|
||||
}
|
||||
@@ -218,6 +237,7 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower)
|
||||
memset(gl_lower, 0, sizeof *gl_lower);
|
||||
|
||||
/* Move the history offset down over the line. */
|
||||
gd->hscrolled++;
|
||||
gd->hsize++;
|
||||
}
|
||||
|
||||
@@ -270,10 +290,14 @@ grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
|
||||
return;
|
||||
}
|
||||
|
||||
gc->flags = gce->flags & ~GRID_FLAG_EXTENDED;
|
||||
gc->flags = gce->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||
gc->attr = gce->data.attr;
|
||||
gc->fg = gce->data.fg;
|
||||
if (gce->flags & GRID_FLAG_FG256)
|
||||
gc->fg |= COLOUR_FLAG_256;
|
||||
gc->bg = gce->data.bg;
|
||||
if (gce->flags & GRID_FLAG_BG256)
|
||||
gc->bg |= COLOUR_FLAG_256;
|
||||
utf8_set(&gc->data, gce->data.data);
|
||||
}
|
||||
|
||||
@@ -297,9 +321,12 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||
extended = (gce->flags & GRID_FLAG_EXTENDED);
|
||||
if (!extended && (gc->data.size != 1 || gc->data.width != 1))
|
||||
extended = 1;
|
||||
if (!extended && (gc->flags & (GRID_FLAG_FGRGB|GRID_FLAG_BGRGB)))
|
||||
if (!extended && ((gc->fg & COLOUR_FLAG_RGB) ||
|
||||
(gc->bg & COLOUR_FLAG_RGB)))
|
||||
extended = 1;
|
||||
if (extended) {
|
||||
gl->flags |= GRID_LINE_EXTENDED;
|
||||
|
||||
if (~gce->flags & GRID_FLAG_EXTENDED) {
|
||||
gl->extddata = xreallocarray(gl->extddata,
|
||||
gl->extdsize + 1, sizeof *gl->extddata);
|
||||
@@ -314,10 +341,14 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||
return;
|
||||
}
|
||||
|
||||
gce->flags = gc->flags & ~GRID_FLAG_EXTENDED;
|
||||
gce->flags = gc->flags;
|
||||
gce->data.attr = gc->attr;
|
||||
gce->data.fg = gc->fg;
|
||||
gce->data.bg = gc->bg;
|
||||
gce->data.fg = gc->fg & 0xff;
|
||||
if (gc->fg & COLOUR_FLAG_256)
|
||||
gce->flags |= GRID_FLAG_FG256;
|
||||
gce->data.bg = gc->bg & 0xff;
|
||||
if (gc->bg & COLOUR_FLAG_256)
|
||||
gce->flags |= GRID_FLAG_BG256;
|
||||
gce->data.data = gc->data.data[0];
|
||||
}
|
||||
|
||||
@@ -446,18 +477,20 @@ size_t
|
||||
grid_string_cells_fg(const struct grid_cell *gc, int *values)
|
||||
{
|
||||
size_t n;
|
||||
u_char r, g, b;
|
||||
|
||||
n = 0;
|
||||
if (gc->flags & GRID_FLAG_FG256) {
|
||||
if (gc->fg & COLOUR_FLAG_256) {
|
||||
values[n++] = 38;
|
||||
values[n++] = 5;
|
||||
values[n++] = gc->fg;
|
||||
} else if (gc->flags & GRID_FLAG_FGRGB) {
|
||||
values[n++] = gc->fg & 0xff;
|
||||
} else if (gc->fg & COLOUR_FLAG_RGB) {
|
||||
values[n++] = 38;
|
||||
values[n++] = 2;
|
||||
values[n++] = gc->fg_rgb.r;
|
||||
values[n++] = gc->fg_rgb.g;
|
||||
values[n++] = gc->fg_rgb.b;
|
||||
colour_split_rgb(gc->fg, &r, &g, &b);
|
||||
values[n++] = r;
|
||||
values[n++] = g;
|
||||
values[n++] = b;
|
||||
} else {
|
||||
switch (gc->fg) {
|
||||
case 0:
|
||||
@@ -493,18 +526,20 @@ size_t
|
||||
grid_string_cells_bg(const struct grid_cell *gc, int *values)
|
||||
{
|
||||
size_t n;
|
||||
u_char r, g, b;
|
||||
|
||||
n = 0;
|
||||
if (gc->flags & GRID_FLAG_BG256) {
|
||||
if (gc->bg & COLOUR_FLAG_256) {
|
||||
values[n++] = 48;
|
||||
values[n++] = 5;
|
||||
values[n++] = gc->bg;
|
||||
} else if (gc->flags & GRID_FLAG_BGRGB) {
|
||||
values[n++] = gc->bg & 0xff;
|
||||
} else if (gc->bg & COLOUR_FLAG_RGB) {
|
||||
values[n++] = 48;
|
||||
values[n++] = 2;
|
||||
values[n++] = gc->bg_rgb.r;
|
||||
values[n++] = gc->bg_rgb.g;
|
||||
values[n++] = gc->bg_rgb.b;
|
||||
colour_split_rgb(gc->bg, &r, &g, &b);
|
||||
values[n++] = r;
|
||||
values[n++] = g;
|
||||
values[n++] = b;
|
||||
} else {
|
||||
switch (gc->bg) {
|
||||
case 0:
|
||||
@@ -525,7 +560,7 @@ grid_string_cells_bg(const struct grid_cell *gc, int *values)
|
||||
case 102:
|
||||
case 103:
|
||||
case 104:
|
||||
case 105:
|
||||
case 105:
|
||||
case 106:
|
||||
case 107:
|
||||
values[n++] = gc->bg - 10;
|
||||
@@ -886,6 +921,10 @@ grid_reflow(struct grid *dst, struct grid *src, u_int new_x)
|
||||
grid_reflow_join(dst, &py, src_gl, new_x);
|
||||
}
|
||||
previous_wrapped = (src_gl->flags & GRID_LINE_WRAPPED);
|
||||
|
||||
/* This is where we started scrolling. */
|
||||
if (line == sy + src->hsize - src->hscrolled - 1)
|
||||
dst->hscrolled = 0;
|
||||
}
|
||||
|
||||
grid_destroy(src);
|
||||
|
||||
45
input.c
45
input.c
@@ -961,7 +961,7 @@ input_reply(struct input_ctx *ictx, const char *fmt, ...)
|
||||
char *reply;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vasprintf(&reply, fmt, ap);
|
||||
xvasprintf(&reply, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
bufferevent_write(ictx->wp->event, reply, strlen(reply));
|
||||
@@ -1628,23 +1628,15 @@ input_csi_dispatch_sgr_256(struct input_ctx *ictx, int fgbg, u_int *i)
|
||||
(*i)++;
|
||||
c = input_get(ictx, *i, 0, -1);
|
||||
if (c == -1) {
|
||||
if (fgbg == 38) {
|
||||
gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
|
||||
if (fgbg == 38)
|
||||
gc->fg = 8;
|
||||
} else if (fgbg == 48) {
|
||||
gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
|
||||
else if (fgbg == 48)
|
||||
gc->bg = 8;
|
||||
}
|
||||
} else {
|
||||
if (fgbg == 38) {
|
||||
gc->flags |= GRID_FLAG_FG256;
|
||||
gc->flags &= ~GRID_FLAG_FGRGB;
|
||||
gc->fg = c;
|
||||
} else if (fgbg == 48) {
|
||||
gc->flags |= GRID_FLAG_BG256;
|
||||
gc->flags &= ~GRID_FLAG_BGRGB;
|
||||
gc->bg = c;
|
||||
}
|
||||
if (fgbg == 38)
|
||||
gc->fg = c | COLOUR_FLAG_256;
|
||||
else if (fgbg == 48)
|
||||
gc->bg = c | COLOUR_FLAG_256;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1668,19 +1660,10 @@ input_csi_dispatch_sgr_rgb(struct input_ctx *ictx, int fgbg, u_int *i)
|
||||
if (b == -1 || b > 255)
|
||||
return;
|
||||
|
||||
if (fgbg == 38) {
|
||||
gc->flags &= ~GRID_FLAG_FG256;
|
||||
gc->flags |= GRID_FLAG_FGRGB;
|
||||
gc->fg_rgb.r = r;
|
||||
gc->fg_rgb.g = g;
|
||||
gc->fg_rgb.b = b;
|
||||
} else if (fgbg == 48) {
|
||||
gc->flags &= ~GRID_FLAG_BG256;
|
||||
gc->flags |= GRID_FLAG_BGRGB;
|
||||
gc->bg_rgb.r = r;
|
||||
gc->bg_rgb.g = g;
|
||||
gc->bg_rgb.b = b;
|
||||
}
|
||||
if (fgbg == 38)
|
||||
gc->fg = colour_join_rgb(r, g, b);
|
||||
else if (fgbg == 48)
|
||||
gc->bg = colour_join_rgb(r, g, b);
|
||||
}
|
||||
|
||||
/* Handle CSI SGR. */
|
||||
@@ -1761,11 +1744,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
|
||||
gc->fg = n - 30;
|
||||
break;
|
||||
case 39:
|
||||
gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
|
||||
gc->fg = 8;
|
||||
break;
|
||||
case 40:
|
||||
@@ -1776,11 +1757,9 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
|
||||
gc->bg = n - 40;
|
||||
break;
|
||||
case 49:
|
||||
gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
|
||||
gc->bg = 8;
|
||||
break;
|
||||
case 90:
|
||||
@@ -1791,7 +1770,6 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
|
||||
case 95:
|
||||
case 96:
|
||||
case 97:
|
||||
gc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
|
||||
gc->fg = n;
|
||||
break;
|
||||
case 100:
|
||||
@@ -1802,7 +1780,6 @@ input_csi_dispatch_sgr(struct input_ctx *ictx)
|
||||
case 105:
|
||||
case 106:
|
||||
case 107:
|
||||
gc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
|
||||
gc->bg = n - 10;
|
||||
break;
|
||||
}
|
||||
|
||||
13
key-string.c
13
key-string.c
@@ -146,8 +146,7 @@ key_string_lookup_string(const char *string)
|
||||
{
|
||||
static const char *other = "!#()+,-.0123456789:;<=>?'\r\t";
|
||||
key_code key;
|
||||
u_short u;
|
||||
int size;
|
||||
u_int u;
|
||||
key_code modifiers;
|
||||
struct utf8_data ud;
|
||||
u_int i;
|
||||
@@ -160,7 +159,9 @@ key_string_lookup_string(const char *string)
|
||||
|
||||
/* Is this a hexadecimal value? */
|
||||
if (string[0] == '0' && string[1] == 'x') {
|
||||
if (sscanf(string + 2, "%hx%n", &u, &size) != 1 || size > 4)
|
||||
if (sscanf(string + 2, "%x", &u) != 1)
|
||||
return (KEYC_UNKNOWN);
|
||||
if (u > 0x1fffff)
|
||||
return (KEYC_UNKNOWN);
|
||||
return (u);
|
||||
}
|
||||
@@ -226,6 +227,7 @@ key_string_lookup_key(key_code key)
|
||||
char tmp[8];
|
||||
u_int i;
|
||||
struct utf8_data ud;
|
||||
size_t off;
|
||||
|
||||
*out = '\0';
|
||||
|
||||
@@ -270,8 +272,9 @@ key_string_lookup_key(key_code key)
|
||||
/* Is this a UTF-8 key? */
|
||||
if (key > 127 && key < KEYC_BASE) {
|
||||
if (utf8_split(key, &ud) == UTF8_DONE) {
|
||||
memcpy(out, ud.data, ud.size);
|
||||
out[ud.size] = '\0';
|
||||
off = strlen(out);
|
||||
memcpy(out + off, ud.data, ud.size);
|
||||
out[off + ud.size] = '\0';
|
||||
return (out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,17 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
struct layout_cell *layout_find_bottomright(struct layout_cell *);
|
||||
u_short layout_checksum(const char *);
|
||||
int layout_append(struct layout_cell *, char *, size_t);
|
||||
struct layout_cell *layout_construct(struct layout_cell *, const char **);
|
||||
void layout_assign(struct window_pane **, struct layout_cell *);
|
||||
static struct layout_cell *layout_find_bottomright(struct layout_cell *);
|
||||
static u_short layout_checksum(const char *);
|
||||
static int layout_append(struct layout_cell *, char *,
|
||||
size_t);
|
||||
static struct layout_cell *layout_construct(struct layout_cell *,
|
||||
const char **);
|
||||
static void layout_assign(struct window_pane **,
|
||||
struct layout_cell *);
|
||||
|
||||
/* Find the bottom-right cell. */
|
||||
struct layout_cell *
|
||||
static struct layout_cell *
|
||||
layout_find_bottomright(struct layout_cell *lc)
|
||||
{
|
||||
if (lc->type == LAYOUT_WINDOWPANE)
|
||||
@@ -40,7 +43,7 @@ layout_find_bottomright(struct layout_cell *lc)
|
||||
}
|
||||
|
||||
/* Calculate layout checksum. */
|
||||
u_short
|
||||
static u_short
|
||||
layout_checksum(const char *layout)
|
||||
{
|
||||
u_short csum;
|
||||
@@ -63,12 +66,12 @@ layout_dump(struct layout_cell *root)
|
||||
if (layout_append(root, layout, sizeof layout) != 0)
|
||||
return (NULL);
|
||||
|
||||
xasprintf(&out, "%04x,%s", layout_checksum(layout), layout);
|
||||
xasprintf(&out, "%04hx,%s", layout_checksum(layout), layout);
|
||||
return (out);
|
||||
}
|
||||
|
||||
/* Append information for a single cell. */
|
||||
int
|
||||
static int
|
||||
layout_append(struct layout_cell *lc, char *buf, size_t len)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
@@ -147,7 +150,7 @@ layout_parse(struct window *w, const char *layout)
|
||||
|
||||
/* Fewer panes than cells - close the bottom right. */
|
||||
lcchild = layout_find_bottomright(lc);
|
||||
layout_destroy_cell(lcchild, &lc);
|
||||
layout_destroy_cell(w, lcchild, &lc);
|
||||
}
|
||||
|
||||
/* Save the old window size and resize to the layout size. */
|
||||
@@ -182,7 +185,7 @@ fail:
|
||||
}
|
||||
|
||||
/* Assign panes into cells. */
|
||||
void
|
||||
static void
|
||||
layout_assign(struct window_pane **wp, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
@@ -201,7 +204,7 @@ layout_assign(struct window_pane **wp, struct layout_cell *lc)
|
||||
}
|
||||
|
||||
/* Construct a cell from all or part of a layout tree. */
|
||||
struct layout_cell *
|
||||
static struct layout_cell *
|
||||
layout_construct(struct layout_cell *lcparent, const char **layout)
|
||||
{
|
||||
struct layout_cell *lc, *lcchild;
|
||||
|
||||
24
layout-set.c
24
layout-set.c
@@ -155,7 +155,8 @@ layout_set_even_h(struct window *w)
|
||||
/* Allocate any remaining space. */
|
||||
if (w->sx > xoff - 1) {
|
||||
lc = TAILQ_LAST(&lc->cells, layout_cells);
|
||||
layout_resize_adjust(lc, LAYOUT_LEFTRIGHT, w->sx - (xoff - 1));
|
||||
layout_resize_adjust(w, lc, LAYOUT_LEFTRIGHT,
|
||||
w->sx - (xoff - 1));
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
@@ -208,7 +209,8 @@ layout_set_even_v(struct window *w)
|
||||
/* Allocate any remaining space. */
|
||||
if (w->sy > yoff - 1) {
|
||||
lc = TAILQ_LAST(&lc->cells, layout_cells);
|
||||
layout_resize_adjust(lc, LAYOUT_TOPBOTTOM, w->sy - (yoff - 1));
|
||||
layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM,
|
||||
w->sy - (yoff - 1));
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
@@ -322,14 +324,16 @@ layout_set_main_h(struct window *w)
|
||||
if (w->sx <= used)
|
||||
continue;
|
||||
lcchild = TAILQ_LAST(&lcrow->cells, layout_cells);
|
||||
layout_resize_adjust(lcchild, LAYOUT_LEFTRIGHT, w->sx - used);
|
||||
layout_resize_adjust(w, lcchild, LAYOUT_LEFTRIGHT,
|
||||
w->sx - used);
|
||||
}
|
||||
|
||||
/* Adjust the last row height to fit if necessary. */
|
||||
used = mainheight + (rows * height) + rows - 1;
|
||||
if (w->sy > used) {
|
||||
lcrow = TAILQ_LAST(&lc->cells, layout_cells);
|
||||
layout_resize_adjust(lcrow, LAYOUT_TOPBOTTOM, w->sy - used);
|
||||
layout_resize_adjust(w, lcrow, LAYOUT_TOPBOTTOM,
|
||||
w->sy - used);
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
@@ -443,14 +447,16 @@ layout_set_main_v(struct window *w)
|
||||
if (w->sy <= used)
|
||||
continue;
|
||||
lcchild = TAILQ_LAST(&lccolumn->cells, layout_cells);
|
||||
layout_resize_adjust(lcchild, LAYOUT_TOPBOTTOM, w->sy - used);
|
||||
layout_resize_adjust(w, lcchild, LAYOUT_TOPBOTTOM,
|
||||
w->sy - used);
|
||||
}
|
||||
|
||||
/* Adjust the last column width to fit if necessary. */
|
||||
used = mainwidth + (columns * width) + columns - 1;
|
||||
if (w->sx > used) {
|
||||
lccolumn = TAILQ_LAST(&lc->cells, layout_cells);
|
||||
layout_resize_adjust(lccolumn, LAYOUT_LEFTRIGHT, w->sx - used);
|
||||
layout_resize_adjust(w, lccolumn, LAYOUT_LEFTRIGHT,
|
||||
w->sx - used);
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
@@ -543,14 +549,16 @@ layout_set_tiled(struct window *w)
|
||||
if (w->sx <= used)
|
||||
continue;
|
||||
lcchild = TAILQ_LAST(&lcrow->cells, layout_cells);
|
||||
layout_resize_adjust(lcchild, LAYOUT_LEFTRIGHT, w->sx - used);
|
||||
layout_resize_adjust(w, lcchild, LAYOUT_LEFTRIGHT,
|
||||
w->sx - used);
|
||||
}
|
||||
|
||||
/* Adjust the last row height to fit if necessary. */
|
||||
used = (rows * height) + rows - 1;
|
||||
if (w->sy > used) {
|
||||
lcrow = TAILQ_LAST(&lc->cells, layout_cells);
|
||||
layout_resize_adjust(lcrow, LAYOUT_TOPBOTTOM, w->sy - used);
|
||||
layout_resize_adjust(w, lcrow, LAYOUT_TOPBOTTOM,
|
||||
w->sy - used);
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
|
||||
417
layout.c
417
layout.c
@@ -2,6 +2,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
* Copyright (c) 2016 Stephen Kent <smkent@smkent.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@@ -32,8 +33,20 @@
|
||||
* cell a pointer to its parent cell.
|
||||
*/
|
||||
|
||||
int layout_resize_pane_grow(struct layout_cell *, enum layout_type, int);
|
||||
int layout_resize_pane_shrink(struct layout_cell *, enum layout_type, int);
|
||||
static u_int layout_resize_check(struct window *, struct layout_cell *,
|
||||
enum layout_type);
|
||||
static int layout_resize_pane_grow(struct window *, struct layout_cell *,
|
||||
enum layout_type, int);
|
||||
static int layout_resize_pane_shrink(struct window *, struct layout_cell *,
|
||||
enum layout_type, int);
|
||||
static int layout_need_status(struct layout_cell *, int);
|
||||
static u_int layout_new_pane_size(struct window *, u_int,
|
||||
struct layout_cell *, enum layout_type, u_int, u_int,
|
||||
u_int);
|
||||
static int layout_set_size_check(struct window *, struct layout_cell *,
|
||||
enum layout_type, int);
|
||||
static void layout_resize_child_cells(struct window *,
|
||||
struct layout_cell *);
|
||||
|
||||
struct layout_cell *
|
||||
layout_create_cell(struct layout_cell *lcparent)
|
||||
@@ -163,6 +176,30 @@ layout_fix_offsets(struct layout_cell *lc)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 1 if we need to reserve space for the pane status line. This is the
|
||||
* case for the most upper panes only.
|
||||
*/
|
||||
static int
|
||||
layout_need_status(struct layout_cell *lc, int at_top)
|
||||
{
|
||||
struct layout_cell *first_lc;
|
||||
|
||||
if (lc->parent) {
|
||||
if (lc->parent->type == LAYOUT_LEFTRIGHT)
|
||||
return (layout_need_status(lc->parent, at_top));
|
||||
|
||||
if (at_top)
|
||||
first_lc = TAILQ_FIRST(&lc->parent->cells);
|
||||
else
|
||||
first_lc = TAILQ_LAST(&lc->parent->cells,layout_cells);
|
||||
if (lc == first_lc)
|
||||
return (layout_need_status(lc->parent, at_top));
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Update pane offsets and sizes based on their cells. */
|
||||
void
|
||||
layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
|
||||
@@ -170,13 +207,25 @@ layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
|
||||
struct window_pane *wp;
|
||||
struct layout_cell *lc;
|
||||
u_int sx, sy;
|
||||
int shift, status, at_top;
|
||||
|
||||
status = options_get_number(w->options, "pane-border-status");
|
||||
at_top = (status == 1);
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if ((lc = wp->layout_cell) == NULL)
|
||||
continue;
|
||||
|
||||
if (status != 0)
|
||||
shift = layout_need_status(lc, at_top);
|
||||
else
|
||||
shift = 0;
|
||||
|
||||
wp->xoff = lc->xoff;
|
||||
wp->yoff = lc->yoff;
|
||||
|
||||
if (shift && at_top)
|
||||
wp->yoff += 1;
|
||||
|
||||
/*
|
||||
* Layout cells are limited by the smallest size of other cells
|
||||
* within the same row or column; if this isn't the case
|
||||
@@ -214,6 +263,9 @@ layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
|
||||
sy = lc->sy;
|
||||
}
|
||||
|
||||
if (shift)
|
||||
sy -= 1;
|
||||
|
||||
window_pane_resize(wp, sx, sy);
|
||||
}
|
||||
}
|
||||
@@ -223,50 +275,55 @@ u_int
|
||||
layout_count_cells(struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
u_int n;
|
||||
u_int count;
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_WINDOWPANE:
|
||||
return (1);
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
n = 0;
|
||||
count = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
n += layout_count_cells(lcchild);
|
||||
return (n);
|
||||
count += layout_count_cells(lcchild);
|
||||
return (count);
|
||||
default:
|
||||
fatalx("bad layout type");
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate how much size is available to be removed from a cell. */
|
||||
u_int
|
||||
layout_resize_check(struct layout_cell *lc, enum layout_type type)
|
||||
static u_int
|
||||
layout_resize_check(struct window *w, struct layout_cell *lc,
|
||||
enum layout_type type)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
u_int available, minimum;
|
||||
|
||||
if (lc->type == LAYOUT_WINDOWPANE) {
|
||||
/* Space available in this cell only. */
|
||||
minimum = PANE_MINIMUM;
|
||||
if (type == LAYOUT_LEFTRIGHT)
|
||||
available = lc->sx;
|
||||
else
|
||||
else {
|
||||
available = lc->sy;
|
||||
|
||||
if (available > PANE_MINIMUM)
|
||||
available -= PANE_MINIMUM;
|
||||
minimum += layout_need_status(lc,
|
||||
options_get_number(w->options,
|
||||
"pane-border-status") == 1);
|
||||
}
|
||||
if (available > minimum)
|
||||
available -= minimum;
|
||||
else
|
||||
available = 0;
|
||||
} else if (lc->type == type) {
|
||||
/* Same type: total of available space in all child cells. */
|
||||
available = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
available += layout_resize_check(lcchild, type);
|
||||
available += layout_resize_check(w, lcchild, type);
|
||||
} else {
|
||||
/* Different type: minimum of available space in child cells. */
|
||||
minimum = UINT_MAX;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
available = layout_resize_check(lcchild, type);
|
||||
available = layout_resize_check(w, lcchild, type);
|
||||
if (available < minimum)
|
||||
minimum = available;
|
||||
}
|
||||
@@ -281,7 +338,8 @@ layout_resize_check(struct layout_cell *lc, enum layout_type type)
|
||||
* expects the change to have already been bounded to the space available.
|
||||
*/
|
||||
void
|
||||
layout_resize_adjust(struct layout_cell *lc, enum layout_type type, int change)
|
||||
layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
||||
enum layout_type type, int change)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
|
||||
@@ -298,7 +356,7 @@ layout_resize_adjust(struct layout_cell *lc, enum layout_type type, int change)
|
||||
/* Child cell runs in a different direction. */
|
||||
if (lc->type != type) {
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
layout_resize_adjust(lcchild, type, change);
|
||||
layout_resize_adjust(w, lcchild, type, change);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -311,12 +369,12 @@ layout_resize_adjust(struct layout_cell *lc, enum layout_type type, int change)
|
||||
if (change == 0)
|
||||
break;
|
||||
if (change > 0) {
|
||||
layout_resize_adjust(lcchild, type, 1);
|
||||
layout_resize_adjust(w, lcchild, type, 1);
|
||||
change--;
|
||||
continue;
|
||||
}
|
||||
if (layout_resize_check(lcchild, type) > 0) {
|
||||
layout_resize_adjust(lcchild, type, -1);
|
||||
if (layout_resize_check(w, lcchild, type) > 0) {
|
||||
layout_resize_adjust(w, lcchild, type, -1);
|
||||
change++;
|
||||
}
|
||||
}
|
||||
@@ -325,7 +383,8 @@ layout_resize_adjust(struct layout_cell *lc, enum layout_type type, int change)
|
||||
|
||||
/* Destroy a cell and redistribute the space. */
|
||||
void
|
||||
layout_destroy_cell(struct layout_cell *lc, struct layout_cell **lcroot)
|
||||
layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
||||
struct layout_cell **lcroot)
|
||||
{
|
||||
struct layout_cell *lcother, *lcparent;
|
||||
|
||||
@@ -346,9 +405,9 @@ layout_destroy_cell(struct layout_cell *lc, struct layout_cell **lcroot)
|
||||
else
|
||||
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||
if (lcparent->type == LAYOUT_LEFTRIGHT)
|
||||
layout_resize_adjust(lcother, lcparent->type, lc->sx + 1);
|
||||
layout_resize_adjust(w, lcother, lcparent->type, lc->sx + 1);
|
||||
else
|
||||
layout_resize_adjust(lcother, lcparent->type, lc->sy + 1);
|
||||
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1);
|
||||
|
||||
/* Remove this from the parent's list. */
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
@@ -412,7 +471,7 @@ layout_resize(struct window *w, u_int sx, u_int sy)
|
||||
* window size.
|
||||
*/
|
||||
xchange = sx - w->sx;
|
||||
xlimit = layout_resize_check(lc, LAYOUT_LEFTRIGHT);
|
||||
xlimit = layout_resize_check(w, lc, LAYOUT_LEFTRIGHT);
|
||||
if (xchange < 0 && xchange < -xlimit)
|
||||
xchange = -xlimit;
|
||||
if (xlimit == 0) {
|
||||
@@ -422,11 +481,11 @@ layout_resize(struct window *w, u_int sx, u_int sy)
|
||||
xchange = sx - lc->sx;
|
||||
}
|
||||
if (xchange != 0)
|
||||
layout_resize_adjust(lc, LAYOUT_LEFTRIGHT, xchange);
|
||||
layout_resize_adjust(w, lc, LAYOUT_LEFTRIGHT, xchange);
|
||||
|
||||
/* Adjust vertically in a similar fashion. */
|
||||
ychange = sy - w->sy;
|
||||
ylimit = layout_resize_check(lc, LAYOUT_TOPBOTTOM);
|
||||
ylimit = layout_resize_check(w, lc, LAYOUT_TOPBOTTOM);
|
||||
if (ychange < 0 && ychange < -ylimit)
|
||||
ychange = -ylimit;
|
||||
if (ylimit == 0) {
|
||||
@@ -436,7 +495,7 @@ layout_resize(struct window *w, u_int sx, u_int sy)
|
||||
ychange = sy - lc->sy;
|
||||
}
|
||||
if (ychange != 0)
|
||||
layout_resize_adjust(lc, LAYOUT_TOPBOTTOM, ychange);
|
||||
layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM, ychange);
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(lc);
|
||||
@@ -480,8 +539,9 @@ layout_resize_pane_to(struct window_pane *wp, enum layout_type type,
|
||||
void
|
||||
layout_resize_pane(struct window_pane *wp, enum layout_type type, int change)
|
||||
{
|
||||
struct layout_cell *lc, *lcparent;
|
||||
int needed, size;
|
||||
struct window *w = wp->window;
|
||||
struct layout_cell *lc, *lcparent;
|
||||
int needed, size;
|
||||
|
||||
lc = wp->layout_cell;
|
||||
|
||||
@@ -502,10 +562,10 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change)
|
||||
needed = change;
|
||||
while (needed != 0) {
|
||||
if (change > 0) {
|
||||
size = layout_resize_pane_grow(lc, type, needed);
|
||||
size = layout_resize_pane_grow(w, lc, type, needed);
|
||||
needed -= size;
|
||||
} else {
|
||||
size = layout_resize_pane_shrink(lc, type, needed);
|
||||
size = layout_resize_pane_shrink(w, lc, type, needed);
|
||||
needed += size;
|
||||
}
|
||||
|
||||
@@ -520,9 +580,9 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change)
|
||||
}
|
||||
|
||||
/* Helper function to grow pane. */
|
||||
int
|
||||
layout_resize_pane_grow(struct layout_cell *lc, enum layout_type type,
|
||||
int needed)
|
||||
static int
|
||||
layout_resize_pane_grow(struct window *w, struct layout_cell *lc,
|
||||
enum layout_type type, int needed)
|
||||
{
|
||||
struct layout_cell *lcadd, *lcremove;
|
||||
u_int size;
|
||||
@@ -533,7 +593,7 @@ layout_resize_pane_grow(struct layout_cell *lc, enum layout_type type,
|
||||
/* Look towards the tail for a suitable cell for reduction. */
|
||||
lcremove = TAILQ_NEXT(lc, entry);
|
||||
while (lcremove != NULL) {
|
||||
size = layout_resize_check(lcremove, type);
|
||||
size = layout_resize_check(w, lcremove, type);
|
||||
if (size > 0)
|
||||
break;
|
||||
lcremove = TAILQ_NEXT(lcremove, entry);
|
||||
@@ -543,7 +603,7 @@ layout_resize_pane_grow(struct layout_cell *lc, enum layout_type type,
|
||||
if (lcremove == NULL) {
|
||||
lcremove = TAILQ_PREV(lc, layout_cells, entry);
|
||||
while (lcremove != NULL) {
|
||||
size = layout_resize_check(lcremove, type);
|
||||
size = layout_resize_check(w, lcremove, type);
|
||||
if (size > 0)
|
||||
break;
|
||||
lcremove = TAILQ_PREV(lcremove, layout_cells, entry);
|
||||
@@ -555,15 +615,15 @@ layout_resize_pane_grow(struct layout_cell *lc, enum layout_type type,
|
||||
/* Change the cells. */
|
||||
if (size > (u_int) needed)
|
||||
size = needed;
|
||||
layout_resize_adjust(lcadd, type, size);
|
||||
layout_resize_adjust(lcremove, type, -size);
|
||||
layout_resize_adjust(w, lcadd, type, size);
|
||||
layout_resize_adjust(w, lcremove, type, -size);
|
||||
return (size);
|
||||
}
|
||||
|
||||
/* Helper function to shrink pane. */
|
||||
int
|
||||
layout_resize_pane_shrink(struct layout_cell *lc, enum layout_type type,
|
||||
int needed)
|
||||
static int
|
||||
layout_resize_pane_shrink(struct window *w, struct layout_cell *lc,
|
||||
enum layout_type type, int needed)
|
||||
{
|
||||
struct layout_cell *lcadd, *lcremove;
|
||||
u_int size;
|
||||
@@ -571,7 +631,7 @@ layout_resize_pane_shrink(struct layout_cell *lc, enum layout_type type,
|
||||
/* Shrinking. Find cell to remove from by walking towards head. */
|
||||
lcremove = lc;
|
||||
do {
|
||||
size = layout_resize_check(lcremove, type);
|
||||
size = layout_resize_check(w, lcremove, type);
|
||||
if (size != 0)
|
||||
break;
|
||||
lcremove = TAILQ_PREV(lcremove, layout_cells, entry);
|
||||
@@ -587,8 +647,8 @@ layout_resize_pane_shrink(struct layout_cell *lc, enum layout_type type,
|
||||
/* Change the cells. */
|
||||
if (size > (u_int) -needed)
|
||||
size = -needed;
|
||||
layout_resize_adjust(lcadd, type, size);
|
||||
layout_resize_adjust(lcremove, type, -size);
|
||||
layout_resize_adjust(w, lcadd, type, size);
|
||||
layout_resize_adjust(w, lcremove, type, -size);
|
||||
return (size);
|
||||
}
|
||||
|
||||
@@ -600,18 +660,166 @@ layout_assign_pane(struct layout_cell *lc, struct window_pane *wp)
|
||||
layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
|
||||
}
|
||||
|
||||
/* Calculate the new pane size for resized parent. */
|
||||
static u_int
|
||||
layout_new_pane_size(struct window *w, u_int previous, struct layout_cell *lc,
|
||||
enum layout_type type, u_int size, u_int count_left, u_int size_left)
|
||||
{
|
||||
u_int new_size, min, max, available;
|
||||
|
||||
/* If this is the last cell, it can take all of the remaining size. */
|
||||
if (count_left == 1)
|
||||
return (size_left);
|
||||
|
||||
/* How much is available in this parent? */
|
||||
available = layout_resize_check(w, lc, type);
|
||||
|
||||
/*
|
||||
* Work out the minimum size of this cell and the new size
|
||||
* proportionate to the previous size.
|
||||
*/
|
||||
min = (PANE_MINIMUM + 1) * (count_left - 1);
|
||||
if (type == LAYOUT_LEFTRIGHT) {
|
||||
if (lc->sx - available > min)
|
||||
min = lc->sx - available;
|
||||
new_size = (lc->sx * size) / previous;
|
||||
} else {
|
||||
if (lc->sy - available > min)
|
||||
min = lc->sy - available;
|
||||
new_size = (lc->sy * size) / previous;
|
||||
}
|
||||
|
||||
/* Check against the maximum and minimum size. */
|
||||
max = size_left - min;
|
||||
if (new_size > max)
|
||||
new_size = max;
|
||||
if (new_size < PANE_MINIMUM)
|
||||
new_size = PANE_MINIMUM;
|
||||
return (new_size);
|
||||
}
|
||||
|
||||
/* Check if the cell and all its children can be resized to a specific size. */
|
||||
static int
|
||||
layout_set_size_check(struct window *w, struct layout_cell *lc,
|
||||
enum layout_type type, int size)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
u_int new_size, available, previous, count, idx;
|
||||
|
||||
/* Cells with no children must just be bigger than minimum. */
|
||||
if (lc->type == LAYOUT_WINDOWPANE)
|
||||
return (size >= PANE_MINIMUM);
|
||||
available = size;
|
||||
|
||||
/* Count number of children. */
|
||||
count = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
count++;
|
||||
|
||||
/* Check new size will work for each child. */
|
||||
if (lc->type == type) {
|
||||
if (type == LAYOUT_LEFTRIGHT)
|
||||
previous = lc->sx;
|
||||
else
|
||||
previous = lc->sy;
|
||||
|
||||
idx = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
new_size = layout_new_pane_size(w, previous, lcchild,
|
||||
type, size, count - idx, available);
|
||||
if (new_size > available)
|
||||
return (0);
|
||||
|
||||
available -= (new_size + 1);
|
||||
if (!layout_set_size_check(w, lcchild, type, new_size))
|
||||
return (0);
|
||||
|
||||
idx++;
|
||||
}
|
||||
} else {
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lcchild->type == LAYOUT_WINDOWPANE)
|
||||
continue;
|
||||
if (!layout_set_size_check(w, lcchild, type, size))
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Resize all child cells to fit within the current cell. */
|
||||
static void
|
||||
layout_resize_child_cells(struct window *w, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
u_int previous, available, count, idx;
|
||||
|
||||
if (lc->type == LAYOUT_WINDOWPANE)
|
||||
return;
|
||||
|
||||
/* What is the current size used? */
|
||||
count = 0;
|
||||
previous = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
count++;
|
||||
if (lc->type == LAYOUT_LEFTRIGHT)
|
||||
previous += lcchild->sx;
|
||||
else if (lc->type == LAYOUT_TOPBOTTOM)
|
||||
previous += lcchild->sy;
|
||||
}
|
||||
previous += (count - 1);
|
||||
|
||||
/* And how much is available? */
|
||||
available = 0;
|
||||
if (lc->type == LAYOUT_LEFTRIGHT)
|
||||
available = lc->sx;
|
||||
else if (lc->type == LAYOUT_TOPBOTTOM)
|
||||
available = lc->sy;
|
||||
|
||||
/* Resize children into the new size. */
|
||||
idx = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lc->type == LAYOUT_TOPBOTTOM) {
|
||||
lcchild->sx = lc->sx;
|
||||
lcchild->xoff = lc->xoff;
|
||||
} else {
|
||||
lcchild->sx = layout_new_pane_size(w, previous, lcchild,
|
||||
lc->type, lc->sx, count - idx, available);
|
||||
available -= (lcchild->sx + 1);
|
||||
}
|
||||
if (lc->type == LAYOUT_LEFTRIGHT)
|
||||
lcchild->sy = lc->sy;
|
||||
else {
|
||||
lcchild->sy = layout_new_pane_size(w, previous, lcchild,
|
||||
lc->type, lc->sy, count - idx, available);
|
||||
available -= (lcchild->sy + 1);
|
||||
}
|
||||
layout_resize_child_cells(w, lcchild);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Split a pane into two. size is a hint, or -1 for default half/half
|
||||
* split. This must be followed by layout_assign_pane before much else happens!
|
||||
**/
|
||||
*/
|
||||
struct layout_cell *
|
||||
layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
int insert_before)
|
||||
int insert_before, int full_size)
|
||||
{
|
||||
struct layout_cell *lc, *lcparent, *lcnew, *lc1, *lc2;
|
||||
u_int sx, sy, xoff, yoff, size1, size2;
|
||||
u_int new_size, saved_size, resize_first = 0;
|
||||
|
||||
lc = wp->layout_cell;
|
||||
/*
|
||||
* If full_size is specified, add a new cell at the top of the window
|
||||
* layout. Otherwise, split the cell for the current pane.
|
||||
*/
|
||||
if (full_size)
|
||||
lc = wp->window->layout_root;
|
||||
else
|
||||
lc = wp->layout_cell;
|
||||
|
||||
/* Copy the old cell size. */
|
||||
sx = lc->sx;
|
||||
@@ -633,19 +841,75 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
fatalx("bad layout type");
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate new cell sizes. size is the target size or -1 for middle
|
||||
* split, size1 is the size of the top/left and size2 the bottom/right.
|
||||
*/
|
||||
if (type == LAYOUT_LEFTRIGHT)
|
||||
saved_size = sx;
|
||||
else
|
||||
saved_size = sy;
|
||||
if (size < 0)
|
||||
size2 = ((saved_size + 1) / 2) - 1;
|
||||
else if (insert_before)
|
||||
size2 = saved_size - size - 1;
|
||||
else
|
||||
size2 = size;
|
||||
if (size2 < PANE_MINIMUM)
|
||||
size2 = PANE_MINIMUM;
|
||||
else if (size2 > saved_size - 2)
|
||||
size2 = saved_size - 2;
|
||||
size1 = saved_size - 1 - size2;
|
||||
|
||||
/* Which size are we using? */
|
||||
if (insert_before)
|
||||
new_size = size2;
|
||||
else
|
||||
new_size = size1;
|
||||
|
||||
/* Confirm there is enough space for full size pane. */
|
||||
if (full_size && !layout_set_size_check(wp->window, lc, type, new_size))
|
||||
return (NULL);
|
||||
|
||||
if (lc->parent != NULL && lc->parent->type == type) {
|
||||
/*
|
||||
* If the parent exists and is of the same type as the split,
|
||||
* create a new cell and insert it after this one.
|
||||
*/
|
||||
|
||||
/* Create the new child cell. */
|
||||
lcparent = lc->parent;
|
||||
lcnew = layout_create_cell(lcparent);
|
||||
if (insert_before)
|
||||
TAILQ_INSERT_BEFORE(lc, lcnew, entry);
|
||||
else
|
||||
TAILQ_INSERT_AFTER(&lcparent->cells, lc, lcnew, entry);
|
||||
} else if (full_size && lc->parent == NULL && lc->type == type) {
|
||||
/*
|
||||
* If the new full size pane is the same type as the root
|
||||
* split, insert the new pane under the existing root cell
|
||||
* instead of creating a new root cell. The existing layout
|
||||
* must be resized before inserting the new cell.
|
||||
*/
|
||||
if (lc->type == LAYOUT_LEFTRIGHT) {
|
||||
lc->sx = new_size;
|
||||
layout_resize_child_cells(wp->window, lc);
|
||||
lc->sx = saved_size;
|
||||
} else if (lc->type == LAYOUT_TOPBOTTOM) {
|
||||
lc->sy = new_size;
|
||||
layout_resize_child_cells(wp->window, lc);
|
||||
lc->sy = saved_size;
|
||||
}
|
||||
resize_first = 1;
|
||||
|
||||
/* Create the new cell. */
|
||||
lcnew = layout_create_cell(lc);
|
||||
if (lc->type == LAYOUT_LEFTRIGHT)
|
||||
layout_set_size(lcnew, new_size, sy, 0, 0);
|
||||
else if (lc->type == LAYOUT_TOPBOTTOM)
|
||||
layout_set_size(lcnew, sx, new_size, 0, 0);
|
||||
if (insert_before)
|
||||
TAILQ_INSERT_HEAD(&lc->cells, lcnew, entry);
|
||||
else
|
||||
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
|
||||
} else {
|
||||
/*
|
||||
* Otherwise create a new parent and insert it.
|
||||
@@ -679,46 +943,23 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
lc2 = lcnew;
|
||||
}
|
||||
|
||||
/* Set new cell sizes. size is the target size or -1 for middle split,
|
||||
* size1 is the size of the top/left and size2 the bottom/right.
|
||||
/*
|
||||
* Set new cell sizes. size1 is the size of the top/left and size2 the
|
||||
* bottom/right.
|
||||
*/
|
||||
switch (type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
if (size < 0)
|
||||
size2 = ((sx + 1) / 2) - 1;
|
||||
else if (insert_before)
|
||||
size2 = sx - size - 1;
|
||||
else
|
||||
size2 = size;
|
||||
if (size2 < PANE_MINIMUM)
|
||||
size2 = PANE_MINIMUM;
|
||||
else if (size2 > sx - 2)
|
||||
size2 = sx - 2;
|
||||
size1 = sx - 1 - size2;
|
||||
if (!resize_first && type == LAYOUT_LEFTRIGHT) {
|
||||
layout_set_size(lc1, size1, sy, xoff, yoff);
|
||||
layout_set_size(lc2, size2, sy, xoff + lc1->sx + 1, yoff);
|
||||
break;
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
if (size < 0)
|
||||
size2 = ((sy + 1) / 2) - 1;
|
||||
else if (insert_before)
|
||||
size2 = sy - size - 1;
|
||||
else
|
||||
size2 = size;
|
||||
if (size2 < PANE_MINIMUM)
|
||||
size2 = PANE_MINIMUM;
|
||||
else if (size2 > sy - 2)
|
||||
size2 = sy - 2;
|
||||
size1 = sy - 1 - size2;
|
||||
} else if (!resize_first && type == LAYOUT_TOPBOTTOM) {
|
||||
layout_set_size(lc1, sx, size1, xoff, yoff);
|
||||
layout_set_size(lc2, sx, size2, xoff, yoff + lc1->sy + 1);
|
||||
break;
|
||||
default:
|
||||
fatalx("bad layout type");
|
||||
}
|
||||
|
||||
/* Assign the panes. */
|
||||
layout_make_leaf(lc, wp);
|
||||
if (full_size) {
|
||||
if (!resize_first)
|
||||
layout_resize_child_cells(wp->window, lc);
|
||||
layout_fix_offsets(wp->window->layout_root);
|
||||
} else
|
||||
layout_make_leaf(lc, wp);
|
||||
|
||||
return (lcnew);
|
||||
}
|
||||
@@ -727,13 +968,15 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
void
|
||||
layout_close_pane(struct window_pane *wp)
|
||||
{
|
||||
struct window *w = wp->window;
|
||||
|
||||
/* Remove the cell. */
|
||||
layout_destroy_cell(wp->layout_cell, &wp->window->layout_root);
|
||||
layout_destroy_cell(w, wp->layout_cell, &w->layout_root);
|
||||
|
||||
/* Fix pane offsets and sizes. */
|
||||
if (wp->window->layout_root != NULL) {
|
||||
layout_fix_offsets(wp->window->layout_root);
|
||||
layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
|
||||
if (w->layout_root != NULL) {
|
||||
layout_fix_offsets(w->layout_root);
|
||||
layout_fix_panes(w, w->sx, w->sy);
|
||||
}
|
||||
notify_window_layout_changed(wp->window);
|
||||
notify_window_layout_changed(w);
|
||||
}
|
||||
|
||||
611
mode-key.c
611
mode-key.c
@@ -50,6 +50,7 @@ struct mode_key_entry {
|
||||
*/
|
||||
int mode;
|
||||
enum mode_key_cmd cmd;
|
||||
u_int repeat;
|
||||
};
|
||||
|
||||
/* Edit keys command strings. */
|
||||
@@ -140,12 +141,14 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
|
||||
{ MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
|
||||
{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
|
||||
{ MODEKEYCOPY_NEXTPAGE, "page-down" },
|
||||
{ MODEKEYCOPY_NEXTPARAGRAPH, "next-paragraph" },
|
||||
{ MODEKEYCOPY_NEXTSPACE, "next-space" },
|
||||
{ MODEKEYCOPY_NEXTSPACEEND, "next-space-end" },
|
||||
{ MODEKEYCOPY_NEXTWORD, "next-word" },
|
||||
{ MODEKEYCOPY_NEXTWORDEND, "next-word-end" },
|
||||
{ MODEKEYCOPY_OTHEREND, "other-end" },
|
||||
{ MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
|
||||
{ MODEKEYCOPY_PREVIOUSPARAGRAPH, "previous-paragraph" },
|
||||
{ MODEKEYCOPY_PREVIOUSSPACE, "previous-space" },
|
||||
{ MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
|
||||
{ MODEKEYCOPY_RIGHT, "cursor-right" },
|
||||
@@ -168,337 +171,341 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
|
||||
|
||||
/* vi editing keys. */
|
||||
const struct mode_key_entry mode_key_vi_edit[] = {
|
||||
{ '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL },
|
||||
{ '\010' /* C-h */, 0, MODEKEYEDIT_BACKSPACE },
|
||||
{ '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE },
|
||||
{ '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE },
|
||||
{ '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD },
|
||||
{ '\033' /* Escape */, 0, MODEKEYEDIT_SWITCHMODE },
|
||||
{ '\n', 0, MODEKEYEDIT_ENTER },
|
||||
{ '\r', 0, MODEKEYEDIT_ENTER },
|
||||
{ KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE },
|
||||
{ KEYC_DC, 0, MODEKEYEDIT_DELETE },
|
||||
{ KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN },
|
||||
{ KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT },
|
||||
{ KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT },
|
||||
{ KEYC_UP, 0, MODEKEYEDIT_HISTORYUP },
|
||||
{ KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE },
|
||||
{ KEYC_END, 0, MODEKEYEDIT_ENDOFLINE },
|
||||
{ '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL, 1 },
|
||||
{ '\010' /* C-h */, 0, MODEKEYEDIT_BACKSPACE, 1 },
|
||||
{ '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE, 1 },
|
||||
{ '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE, 1 },
|
||||
{ '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD, 1 },
|
||||
{ '\033' /* Escape */, 0, MODEKEYEDIT_SWITCHMODE, 1 },
|
||||
{ '\n', 0, MODEKEYEDIT_ENTER, 1 },
|
||||
{ '\r', 0, MODEKEYEDIT_ENTER, 1 },
|
||||
{ KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE, 1 },
|
||||
{ KEYC_DC, 0, MODEKEYEDIT_DELETE, 1 },
|
||||
{ KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN, 1 },
|
||||
{ KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT, 1 },
|
||||
{ KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT, 1 },
|
||||
{ KEYC_UP, 0, MODEKEYEDIT_HISTORYUP, 1 },
|
||||
{ KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE, 1 },
|
||||
{ KEYC_END, 0, MODEKEYEDIT_ENDOFLINE, 1 },
|
||||
|
||||
{ '$', 1, MODEKEYEDIT_ENDOFLINE },
|
||||
{ '0', 1, MODEKEYEDIT_STARTOFLINE },
|
||||
{ 'A', 1, MODEKEYEDIT_SWITCHMODEAPPENDLINE },
|
||||
{ 'B', 1, MODEKEYEDIT_PREVIOUSSPACE },
|
||||
{ 'C', 1, MODEKEYEDIT_SWITCHMODECHANGELINE },
|
||||
{ 'D', 1, MODEKEYEDIT_DELETETOENDOFLINE },
|
||||
{ 'E', 1, MODEKEYEDIT_NEXTSPACEEND },
|
||||
{ 'I', 1, MODEKEYEDIT_SWITCHMODEBEGINLINE },
|
||||
{ 'S', 1, MODEKEYEDIT_SWITCHMODESUBSTITUTELINE },
|
||||
{ 'W', 1, MODEKEYEDIT_NEXTSPACE },
|
||||
{ 'X', 1, MODEKEYEDIT_BACKSPACE },
|
||||
{ '\003' /* C-c */, 1, MODEKEYEDIT_CANCEL },
|
||||
{ '\010' /* C-h */, 1, MODEKEYEDIT_BACKSPACE },
|
||||
{ '\n', 1, MODEKEYEDIT_ENTER },
|
||||
{ '\r', 1, MODEKEYEDIT_ENTER },
|
||||
{ '^', 1, MODEKEYEDIT_STARTOFLINE },
|
||||
{ 'a', 1, MODEKEYEDIT_SWITCHMODEAPPEND },
|
||||
{ 'b', 1, MODEKEYEDIT_PREVIOUSWORD },
|
||||
{ 'd', 1, MODEKEYEDIT_DELETELINE },
|
||||
{ 'e', 1, MODEKEYEDIT_NEXTWORDEND },
|
||||
{ 'h', 1, MODEKEYEDIT_CURSORLEFT },
|
||||
{ 'i', 1, MODEKEYEDIT_SWITCHMODE },
|
||||
{ 'j', 1, MODEKEYEDIT_HISTORYDOWN },
|
||||
{ 'k', 1, MODEKEYEDIT_HISTORYUP },
|
||||
{ 'l', 1, MODEKEYEDIT_CURSORRIGHT },
|
||||
{ 'p', 1, MODEKEYEDIT_PASTE },
|
||||
{ 's', 1, MODEKEYEDIT_SWITCHMODESUBSTITUTE },
|
||||
{ 'w', 1, MODEKEYEDIT_NEXTWORD },
|
||||
{ 'x', 1, MODEKEYEDIT_DELETE },
|
||||
{ KEYC_BSPACE, 1, MODEKEYEDIT_BACKSPACE },
|
||||
{ KEYC_DC, 1, MODEKEYEDIT_DELETE },
|
||||
{ KEYC_DOWN, 1, MODEKEYEDIT_HISTORYDOWN },
|
||||
{ KEYC_LEFT, 1, MODEKEYEDIT_CURSORLEFT },
|
||||
{ KEYC_RIGHT, 1, MODEKEYEDIT_CURSORRIGHT },
|
||||
{ KEYC_UP, 1, MODEKEYEDIT_HISTORYUP },
|
||||
{ '$', 1, MODEKEYEDIT_ENDOFLINE, 1 },
|
||||
{ '0', 1, MODEKEYEDIT_STARTOFLINE, 1 },
|
||||
{ 'A', 1, MODEKEYEDIT_SWITCHMODEAPPENDLINE, 1 },
|
||||
{ 'B', 1, MODEKEYEDIT_PREVIOUSSPACE, 1 },
|
||||
{ 'C', 1, MODEKEYEDIT_SWITCHMODECHANGELINE, 1 },
|
||||
{ 'D', 1, MODEKEYEDIT_DELETETOENDOFLINE, 1 },
|
||||
{ 'E', 1, MODEKEYEDIT_NEXTSPACEEND, 1 },
|
||||
{ 'I', 1, MODEKEYEDIT_SWITCHMODEBEGINLINE, 1 },
|
||||
{ 'S', 1, MODEKEYEDIT_SWITCHMODESUBSTITUTELINE, 1 },
|
||||
{ 'W', 1, MODEKEYEDIT_NEXTSPACE, 1 },
|
||||
{ 'X', 1, MODEKEYEDIT_BACKSPACE, 1 },
|
||||
{ '\003' /* C-c */, 1, MODEKEYEDIT_CANCEL, 1 },
|
||||
{ '\010' /* C-h */, 1, MODEKEYEDIT_BACKSPACE, 1 },
|
||||
{ '\n', 1, MODEKEYEDIT_ENTER, 1 },
|
||||
{ '\r', 1, MODEKEYEDIT_ENTER, 1 },
|
||||
{ '^', 1, MODEKEYEDIT_STARTOFLINE, 1 },
|
||||
{ 'a', 1, MODEKEYEDIT_SWITCHMODEAPPEND, 1 },
|
||||
{ 'b', 1, MODEKEYEDIT_PREVIOUSWORD, 1 },
|
||||
{ 'd', 1, MODEKEYEDIT_DELETELINE, 1 },
|
||||
{ 'e', 1, MODEKEYEDIT_NEXTWORDEND, 1 },
|
||||
{ 'h', 1, MODEKEYEDIT_CURSORLEFT, 1 },
|
||||
{ 'i', 1, MODEKEYEDIT_SWITCHMODE, 1 },
|
||||
{ 'j', 1, MODEKEYEDIT_HISTORYDOWN, 1 },
|
||||
{ 'k', 1, MODEKEYEDIT_HISTORYUP, 1 },
|
||||
{ 'l', 1, MODEKEYEDIT_CURSORRIGHT, 1 },
|
||||
{ 'p', 1, MODEKEYEDIT_PASTE, 1 },
|
||||
{ 's', 1, MODEKEYEDIT_SWITCHMODESUBSTITUTE, 1 },
|
||||
{ 'w', 1, MODEKEYEDIT_NEXTWORD, 1 },
|
||||
{ 'x', 1, MODEKEYEDIT_DELETE, 1 },
|
||||
{ KEYC_BSPACE, 1, MODEKEYEDIT_BACKSPACE, 1 },
|
||||
{ KEYC_DC, 1, MODEKEYEDIT_DELETE, 1 },
|
||||
{ KEYC_DOWN, 1, MODEKEYEDIT_HISTORYDOWN, 1 },
|
||||
{ KEYC_LEFT, 1, MODEKEYEDIT_CURSORLEFT, 1 },
|
||||
{ KEYC_RIGHT, 1, MODEKEYEDIT_CURSORRIGHT, 1 },
|
||||
{ KEYC_UP, 1, MODEKEYEDIT_HISTORYUP, 1 },
|
||||
|
||||
{ 0, -1, 0 }
|
||||
{ 0, -1, 0, 1 }
|
||||
};
|
||||
struct mode_key_tree mode_key_tree_vi_edit;
|
||||
|
||||
/* vi choice selection keys. */
|
||||
const struct mode_key_entry mode_key_vi_choice[] = {
|
||||
{ '0' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '1' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '2' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '3' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '4' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '5' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '6' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '7' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '8' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '9' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '\002' /* C-b */, 0, MODEKEYCHOICE_PAGEUP },
|
||||
{ '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL },
|
||||
{ '\005' /* C-e */, 0, MODEKEYCHOICE_SCROLLDOWN },
|
||||
{ '\006' /* C-f */, 0, MODEKEYCHOICE_PAGEDOWN },
|
||||
{ '\031' /* C-y */, 0, MODEKEYCHOICE_SCROLLUP },
|
||||
{ '\n', 0, MODEKEYCHOICE_CHOOSE },
|
||||
{ '\r', 0, MODEKEYCHOICE_CHOOSE },
|
||||
{ 'j', 0, MODEKEYCHOICE_DOWN },
|
||||
{ 'k', 0, MODEKEYCHOICE_UP },
|
||||
{ 'q', 0, MODEKEYCHOICE_CANCEL },
|
||||
{ KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST },
|
||||
{ 'g', 0, MODEKEYCHOICE_STARTOFLIST },
|
||||
{ 'H', 0, MODEKEYCHOICE_TOPLINE },
|
||||
{ 'L', 0, MODEKEYCHOICE_BOTTOMLINE },
|
||||
{ 'G', 0, MODEKEYCHOICE_ENDOFLIST },
|
||||
{ KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST },
|
||||
{ KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE },
|
||||
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN },
|
||||
{ KEYC_DOWN, 0, MODEKEYCHOICE_DOWN },
|
||||
{ KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN },
|
||||
{ KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP },
|
||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLUP },
|
||||
{ KEYC_UP, 0, MODEKEYCHOICE_UP },
|
||||
{ ' ', 0, MODEKEYCHOICE_TREE_TOGGLE },
|
||||
{ KEYC_LEFT, 0, MODEKEYCHOICE_TREE_COLLAPSE },
|
||||
{ KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND },
|
||||
{ KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL },
|
||||
{ KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL },
|
||||
{ KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE },
|
||||
{ KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE },
|
||||
{ KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP },
|
||||
{ KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN },
|
||||
{ '0' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '1' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '2' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '3' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '4' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '5' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '6' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '7' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '8' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '9' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '\002' /* C-b */, 0, MODEKEYCHOICE_PAGEUP, 1 },
|
||||
{ '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL, 1 },
|
||||
{ '\005' /* C-e */, 0, MODEKEYCHOICE_SCROLLDOWN, 1 },
|
||||
{ '\006' /* C-f */, 0, MODEKEYCHOICE_PAGEDOWN, 1 },
|
||||
{ '\031' /* C-y */, 0, MODEKEYCHOICE_SCROLLUP, 1 },
|
||||
{ '\n', 0, MODEKEYCHOICE_CHOOSE, 1 },
|
||||
{ '\r', 0, MODEKEYCHOICE_CHOOSE, 1 },
|
||||
{ 'j', 0, MODEKEYCHOICE_DOWN, 1 },
|
||||
{ 'k', 0, MODEKEYCHOICE_UP, 1 },
|
||||
{ 'q', 0, MODEKEYCHOICE_CANCEL, 1 },
|
||||
{ KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST, 1 },
|
||||
{ 'g', 0, MODEKEYCHOICE_STARTOFLIST, 1 },
|
||||
{ 'H', 0, MODEKEYCHOICE_TOPLINE, 1 },
|
||||
{ 'L', 0, MODEKEYCHOICE_BOTTOMLINE, 1 },
|
||||
{ 'G', 0, MODEKEYCHOICE_ENDOFLIST, 1 },
|
||||
{ KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST, 1 },
|
||||
{ KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE, 1 },
|
||||
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN, 1 },
|
||||
{ KEYC_DOWN, 0, MODEKEYCHOICE_DOWN, 1 },
|
||||
{ KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN, 1 },
|
||||
{ KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP, 1 },
|
||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLUP, 1 },
|
||||
{ KEYC_UP, 0, MODEKEYCHOICE_UP, 1 },
|
||||
{ ' ', 0, MODEKEYCHOICE_TREE_TOGGLE, 1 },
|
||||
{ KEYC_LEFT, 0, MODEKEYCHOICE_TREE_COLLAPSE, 1 },
|
||||
{ KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND, 1 },
|
||||
{ KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL, 1 },
|
||||
{ KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL, 1 },
|
||||
{ KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE, 1 },
|
||||
{ KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE, 1 },
|
||||
{ KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP, 1 },
|
||||
{ KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN, 1 },
|
||||
|
||||
{ 0, -1, 0 }
|
||||
{ 0, -1, 0, 1 }
|
||||
};
|
||||
struct mode_key_tree mode_key_tree_vi_choice;
|
||||
|
||||
/* vi copy mode keys. */
|
||||
const struct mode_key_entry mode_key_vi_copy[] = {
|
||||
{ ' ', 0, MODEKEYCOPY_STARTSELECTION },
|
||||
{ '"', 0, MODEKEYCOPY_STARTNAMEDBUFFER },
|
||||
{ '$', 0, MODEKEYCOPY_ENDOFLINE },
|
||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE },
|
||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN },
|
||||
{ '/', 0, MODEKEYCOPY_SEARCHDOWN },
|
||||
{ '0', 0, MODEKEYCOPY_STARTOFLINE },
|
||||
{ '1', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '2', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '3', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '4', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '5', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '6', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '7', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '8', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '9', 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ ':', 0, MODEKEYCOPY_GOTOLINE },
|
||||
{ '?', 0, MODEKEYCOPY_SEARCHUP },
|
||||
{ 'A', 0, MODEKEYCOPY_APPENDSELECTION },
|
||||
{ 'B', 0, MODEKEYCOPY_PREVIOUSSPACE },
|
||||
{ 'D', 0, MODEKEYCOPY_COPYENDOFLINE },
|
||||
{ 'E', 0, MODEKEYCOPY_NEXTSPACEEND },
|
||||
{ 'F', 0, MODEKEYCOPY_JUMPBACK },
|
||||
{ 'G', 0, MODEKEYCOPY_HISTORYBOTTOM },
|
||||
{ 'H', 0, MODEKEYCOPY_TOPLINE },
|
||||
{ 'J', 0, MODEKEYCOPY_SCROLLDOWN },
|
||||
{ 'K', 0, MODEKEYCOPY_SCROLLUP },
|
||||
{ 'L', 0, MODEKEYCOPY_BOTTOMLINE },
|
||||
{ 'M', 0, MODEKEYCOPY_MIDDLELINE },
|
||||
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
|
||||
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK },
|
||||
{ 'V', 0, MODEKEYCOPY_SELECTLINE },
|
||||
{ 'W', 0, MODEKEYCOPY_NEXTSPACE },
|
||||
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
||||
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
|
||||
{ '\004' /* C-d */, 0, MODEKEYCOPY_HALFPAGEDOWN },
|
||||
{ '\005' /* C-e */, 0, MODEKEYCOPY_SCROLLDOWN },
|
||||
{ '\006' /* C-f */, 0, MODEKEYCOPY_NEXTPAGE },
|
||||
{ '\010' /* C-h */, 0, MODEKEYCOPY_LEFT },
|
||||
{ '\025' /* C-u */, 0, MODEKEYCOPY_HALFPAGEUP },
|
||||
{ '\031' /* C-y */, 0, MODEKEYCOPY_SCROLLUP },
|
||||
{ '\033' /* Escape */, 0, MODEKEYCOPY_CLEARSELECTION },
|
||||
{ '\n', 0, MODEKEYCOPY_COPYSELECTION },
|
||||
{ '\r', 0, MODEKEYCOPY_COPYSELECTION },
|
||||
{ '^', 0, MODEKEYCOPY_BACKTOINDENTATION },
|
||||
{ 'b', 0, MODEKEYCOPY_PREVIOUSWORD },
|
||||
{ 'e', 0, MODEKEYCOPY_NEXTWORDEND },
|
||||
{ 'f', 0, MODEKEYCOPY_JUMP },
|
||||
{ 'g', 0, MODEKEYCOPY_HISTORYTOP },
|
||||
{ 'h', 0, MODEKEYCOPY_LEFT },
|
||||
{ 'j', 0, MODEKEYCOPY_DOWN },
|
||||
{ 'k', 0, MODEKEYCOPY_UP },
|
||||
{ 'l', 0, MODEKEYCOPY_RIGHT },
|
||||
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
|
||||
{ 'o', 0, MODEKEYCOPY_OTHEREND },
|
||||
{ 't', 0, MODEKEYCOPY_JUMPTO },
|
||||
{ 'q', 0, MODEKEYCOPY_CANCEL },
|
||||
{ 'v', 0, MODEKEYCOPY_RECTANGLETOGGLE },
|
||||
{ 'w', 0, MODEKEYCOPY_NEXTWORD },
|
||||
{ KEYC_BSPACE, 0, MODEKEYCOPY_LEFT },
|
||||
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLDOWN },
|
||||
{ KEYC_DOWN, 0, MODEKEYCOPY_DOWN },
|
||||
{ KEYC_LEFT, 0, MODEKEYCOPY_LEFT },
|
||||
{ KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE },
|
||||
{ KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
||||
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT },
|
||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLUP },
|
||||
{ KEYC_UP, 0, MODEKEYCOPY_UP },
|
||||
{ KEYC_WHEELUP_PANE, 0, MODEKEYCOPY_SCROLLUP },
|
||||
{ KEYC_WHEELDOWN_PANE, 0, MODEKEYCOPY_SCROLLDOWN },
|
||||
{ KEYC_MOUSEDRAG1_PANE, 0, MODEKEYCOPY_STARTSELECTION },
|
||||
{ KEYC_MOUSEDRAGEND1_PANE, 0, MODEKEYCOPY_COPYSELECTION },
|
||||
{ ' ', 0, MODEKEYCOPY_STARTSELECTION, 1 },
|
||||
{ '"', 0, MODEKEYCOPY_STARTNAMEDBUFFER, 1 },
|
||||
{ '$', 0, MODEKEYCOPY_ENDOFLINE, 1 },
|
||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE, 1 },
|
||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN, 1 },
|
||||
{ '/', 0, MODEKEYCOPY_SEARCHDOWN, 1 },
|
||||
{ '0', 0, MODEKEYCOPY_STARTOFLINE, 1 },
|
||||
{ '1', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '2', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '3', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '4', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '5', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '6', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '7', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '8', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '9', 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ ':', 0, MODEKEYCOPY_GOTOLINE, 1 },
|
||||
{ '?', 0, MODEKEYCOPY_SEARCHUP, 1 },
|
||||
{ 'A', 0, MODEKEYCOPY_APPENDSELECTION, 1 },
|
||||
{ 'B', 0, MODEKEYCOPY_PREVIOUSSPACE, 1 },
|
||||
{ 'D', 0, MODEKEYCOPY_COPYENDOFLINE, 1 },
|
||||
{ 'E', 0, MODEKEYCOPY_NEXTSPACEEND, 1 },
|
||||
{ 'F', 0, MODEKEYCOPY_JUMPBACK, 1 },
|
||||
{ 'G', 0, MODEKEYCOPY_HISTORYBOTTOM, 1 },
|
||||
{ 'H', 0, MODEKEYCOPY_TOPLINE, 1 },
|
||||
{ 'J', 0, MODEKEYCOPY_SCROLLDOWN, 1 },
|
||||
{ 'K', 0, MODEKEYCOPY_SCROLLUP, 1 },
|
||||
{ 'L', 0, MODEKEYCOPY_BOTTOMLINE, 1 },
|
||||
{ 'M', 0, MODEKEYCOPY_MIDDLELINE, 1 },
|
||||
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE, 1 },
|
||||
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK, 1 },
|
||||
{ 'V', 0, MODEKEYCOPY_SELECTLINE, 1 },
|
||||
{ 'W', 0, MODEKEYCOPY_NEXTSPACE, 1 },
|
||||
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE, 1 },
|
||||
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL, 1 },
|
||||
{ '\004' /* C-d */, 0, MODEKEYCOPY_HALFPAGEDOWN, 1 },
|
||||
{ '\005' /* C-e */, 0, MODEKEYCOPY_SCROLLDOWN, 1 },
|
||||
{ '\006' /* C-f */, 0, MODEKEYCOPY_NEXTPAGE, 1 },
|
||||
{ '\010' /* C-h */, 0, MODEKEYCOPY_LEFT, 1 },
|
||||
{ '\025' /* C-u */, 0, MODEKEYCOPY_HALFPAGEUP, 1 },
|
||||
{ '\031' /* C-y */, 0, MODEKEYCOPY_SCROLLUP, 1 },
|
||||
{ '\033' /* Escape */, 0, MODEKEYCOPY_CLEARSELECTION, 1 },
|
||||
{ '\n', 0, MODEKEYCOPY_COPYSELECTION, 1 },
|
||||
{ '\r', 0, MODEKEYCOPY_COPYSELECTION, 1 },
|
||||
{ '^', 0, MODEKEYCOPY_BACKTOINDENTATION, 1 },
|
||||
{ 'b', 0, MODEKEYCOPY_PREVIOUSWORD, 1 },
|
||||
{ 'e', 0, MODEKEYCOPY_NEXTWORDEND, 1 },
|
||||
{ 'f', 0, MODEKEYCOPY_JUMP, 1 },
|
||||
{ 'g', 0, MODEKEYCOPY_HISTORYTOP, 1 },
|
||||
{ 'h', 0, MODEKEYCOPY_LEFT, 1 },
|
||||
{ 'j', 0, MODEKEYCOPY_DOWN, 1 },
|
||||
{ 'k', 0, MODEKEYCOPY_UP, 1 },
|
||||
{ 'l', 0, MODEKEYCOPY_RIGHT, 1 },
|
||||
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN, 1 },
|
||||
{ 'o', 0, MODEKEYCOPY_OTHEREND, 1 },
|
||||
{ 't', 0, MODEKEYCOPY_JUMPTO, 1 },
|
||||
{ 'q', 0, MODEKEYCOPY_CANCEL, 1 },
|
||||
{ 'v', 0, MODEKEYCOPY_RECTANGLETOGGLE, 1 },
|
||||
{ 'w', 0, MODEKEYCOPY_NEXTWORD, 1 },
|
||||
{ '{', 0, MODEKEYCOPY_PREVIOUSPARAGRAPH, 1 },
|
||||
{ '}', 0, MODEKEYCOPY_NEXTPARAGRAPH, 1 },
|
||||
{ KEYC_BSPACE, 0, MODEKEYCOPY_LEFT, 1 },
|
||||
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLDOWN, 1 },
|
||||
{ KEYC_DOWN, 0, MODEKEYCOPY_DOWN, 1 },
|
||||
{ KEYC_LEFT, 0, MODEKEYCOPY_LEFT, 1 },
|
||||
{ KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE, 1 },
|
||||
{ KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE, 1 },
|
||||
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT, 1 },
|
||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLUP, 1 },
|
||||
{ KEYC_UP, 0, MODEKEYCOPY_UP, 1 },
|
||||
{ KEYC_WHEELUP_PANE, 0, MODEKEYCOPY_SCROLLUP, 1 },
|
||||
{ KEYC_WHEELDOWN_PANE, 0, MODEKEYCOPY_SCROLLDOWN, 1 },
|
||||
{ KEYC_MOUSEDRAG1_PANE, 0, MODEKEYCOPY_STARTSELECTION, 1 },
|
||||
{ KEYC_MOUSEDRAGEND1_PANE, 0, MODEKEYCOPY_COPYSELECTION, 1 },
|
||||
|
||||
{ 0, -1, 0 }
|
||||
{ 0, -1, 0, 1 }
|
||||
};
|
||||
struct mode_key_tree mode_key_tree_vi_copy;
|
||||
|
||||
/* emacs editing keys. */
|
||||
const struct mode_key_entry mode_key_emacs_edit[] = {
|
||||
{ '\001' /* C-a */, 0, MODEKEYEDIT_STARTOFLINE },
|
||||
{ '\002' /* C-b */, 0, MODEKEYEDIT_CURSORLEFT },
|
||||
{ '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL },
|
||||
{ '\004' /* C-d */, 0, MODEKEYEDIT_DELETE },
|
||||
{ '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE },
|
||||
{ '\006' /* C-f */, 0, MODEKEYEDIT_CURSORRIGHT },
|
||||
{ '\010' /* C-H */, 0, MODEKEYEDIT_BACKSPACE },
|
||||
{ '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE },
|
||||
{ '\013' /* C-k */, 0, MODEKEYEDIT_DELETETOENDOFLINE },
|
||||
{ '\016' /* C-n */, 0, MODEKEYEDIT_HISTORYDOWN },
|
||||
{ '\020' /* C-p */, 0, MODEKEYEDIT_HISTORYUP },
|
||||
{ '\024' /* C-t */, 0, MODEKEYEDIT_TRANSPOSECHARS },
|
||||
{ '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE },
|
||||
{ '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD },
|
||||
{ '\031' /* C-y */, 0, MODEKEYEDIT_PASTE },
|
||||
{ '\033' /* Escape */, 0, MODEKEYEDIT_CANCEL },
|
||||
{ '\n', 0, MODEKEYEDIT_ENTER },
|
||||
{ '\r', 0, MODEKEYEDIT_ENTER },
|
||||
{ 'b' | KEYC_ESCAPE, 0, MODEKEYEDIT_PREVIOUSWORD },
|
||||
{ 'f' | KEYC_ESCAPE, 0, MODEKEYEDIT_NEXTWORDEND },
|
||||
{ 'm' | KEYC_ESCAPE, 0, MODEKEYEDIT_STARTOFLINE },
|
||||
{ KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE },
|
||||
{ KEYC_DC, 0, MODEKEYEDIT_DELETE },
|
||||
{ KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN },
|
||||
{ KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT },
|
||||
{ KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT },
|
||||
{ KEYC_UP, 0, MODEKEYEDIT_HISTORYUP },
|
||||
{ KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE },
|
||||
{ KEYC_END, 0, MODEKEYEDIT_ENDOFLINE },
|
||||
{ '\001' /* C-a */, 0, MODEKEYEDIT_STARTOFLINE, 1 },
|
||||
{ '\002' /* C-b */, 0, MODEKEYEDIT_CURSORLEFT, 1 },
|
||||
{ '\003' /* C-c */, 0, MODEKEYEDIT_CANCEL, 1 },
|
||||
{ '\004' /* C-d */, 0, MODEKEYEDIT_DELETE, 1 },
|
||||
{ '\005' /* C-e */, 0, MODEKEYEDIT_ENDOFLINE, 1 },
|
||||
{ '\006' /* C-f */, 0, MODEKEYEDIT_CURSORRIGHT, 1 },
|
||||
{ '\010' /* C-H */, 0, MODEKEYEDIT_BACKSPACE, 1 },
|
||||
{ '\011' /* Tab */, 0, MODEKEYEDIT_COMPLETE, 1 },
|
||||
{ '\013' /* C-k */, 0, MODEKEYEDIT_DELETETOENDOFLINE, 1 },
|
||||
{ '\016' /* C-n */, 0, MODEKEYEDIT_HISTORYDOWN, 1 },
|
||||
{ '\020' /* C-p */, 0, MODEKEYEDIT_HISTORYUP, 1 },
|
||||
{ '\024' /* C-t */, 0, MODEKEYEDIT_TRANSPOSECHARS, 1 },
|
||||
{ '\025' /* C-u */, 0, MODEKEYEDIT_DELETELINE, 1 },
|
||||
{ '\027' /* C-w */, 0, MODEKEYEDIT_DELETEWORD, 1 },
|
||||
{ '\031' /* C-y */, 0, MODEKEYEDIT_PASTE, 1 },
|
||||
{ '\033' /* Escape */, 0, MODEKEYEDIT_CANCEL, 1 },
|
||||
{ '\n', 0, MODEKEYEDIT_ENTER, 1 },
|
||||
{ '\r', 0, MODEKEYEDIT_ENTER, 1 },
|
||||
{ 'b' | KEYC_ESCAPE, 0, MODEKEYEDIT_PREVIOUSWORD, 1 },
|
||||
{ 'f' | KEYC_ESCAPE, 0, MODEKEYEDIT_NEXTWORDEND, 1 },
|
||||
{ 'm' | KEYC_ESCAPE, 0, MODEKEYEDIT_STARTOFLINE, 1 },
|
||||
{ KEYC_BSPACE, 0, MODEKEYEDIT_BACKSPACE, 1 },
|
||||
{ KEYC_DC, 0, MODEKEYEDIT_DELETE, 1 },
|
||||
{ KEYC_DOWN, 0, MODEKEYEDIT_HISTORYDOWN, 1 },
|
||||
{ KEYC_LEFT, 0, MODEKEYEDIT_CURSORLEFT, 1 },
|
||||
{ KEYC_RIGHT, 0, MODEKEYEDIT_CURSORRIGHT, 1 },
|
||||
{ KEYC_UP, 0, MODEKEYEDIT_HISTORYUP, 1 },
|
||||
{ KEYC_HOME, 0, MODEKEYEDIT_STARTOFLINE, 1 },
|
||||
{ KEYC_END, 0, MODEKEYEDIT_ENDOFLINE, 1 },
|
||||
|
||||
{ 0, -1, 0 }
|
||||
{ 0, -1, 0, 1 }
|
||||
};
|
||||
struct mode_key_tree mode_key_tree_emacs_edit;
|
||||
|
||||
/* emacs choice selection keys. */
|
||||
const struct mode_key_entry mode_key_emacs_choice[] = {
|
||||
{ '0' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '1' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '2' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '3' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '4' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '5' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '6' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '7' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '8' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '9' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX },
|
||||
{ '\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 },
|
||||
{ '\n', 0, MODEKEYCHOICE_CHOOSE },
|
||||
{ '\r', 0, MODEKEYCHOICE_CHOOSE },
|
||||
{ 'q', 0, MODEKEYCHOICE_CANCEL },
|
||||
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCHOICE_PAGEUP },
|
||||
{ KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST },
|
||||
{ '<' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTOFLIST },
|
||||
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCHOICE_TOPLINE },
|
||||
{ '>' | KEYC_ESCAPE, 0, MODEKEYCHOICE_ENDOFLIST },
|
||||
{ KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST },
|
||||
{ KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE },
|
||||
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN },
|
||||
{ KEYC_DOWN, 0, MODEKEYCHOICE_DOWN },
|
||||
{ KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN },
|
||||
{ KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP },
|
||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLUP },
|
||||
{ KEYC_UP, 0, MODEKEYCHOICE_UP },
|
||||
{ ' ', 0, MODEKEYCHOICE_TREE_TOGGLE },
|
||||
{ KEYC_LEFT, 0, MODEKEYCHOICE_TREE_COLLAPSE },
|
||||
{ KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND },
|
||||
{ KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL },
|
||||
{ KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL },
|
||||
{ KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE },
|
||||
{ KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE },
|
||||
{ KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP },
|
||||
{ KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN },
|
||||
{ '0' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '1' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '2' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '3' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '4' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '5' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '6' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '7' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '8' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '9' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTNUMBERPREFIX, 1 },
|
||||
{ '\003' /* C-c */, 0, MODEKEYCHOICE_CANCEL, 1 },
|
||||
{ '\016' /* C-n */, 0, MODEKEYCHOICE_DOWN, 1 },
|
||||
{ '\020' /* C-p */, 0, MODEKEYCHOICE_UP, 1 },
|
||||
{ '\026' /* C-v */, 0, MODEKEYCHOICE_PAGEDOWN, 1 },
|
||||
{ '\033' /* Escape */, 0, MODEKEYCHOICE_CANCEL, 1 },
|
||||
{ '\n', 0, MODEKEYCHOICE_CHOOSE, 1 },
|
||||
{ '\r', 0, MODEKEYCHOICE_CHOOSE, 1 },
|
||||
{ 'q', 0, MODEKEYCHOICE_CANCEL, 1 },
|
||||
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCHOICE_PAGEUP, 1 },
|
||||
{ KEYC_HOME, 0, MODEKEYCHOICE_STARTOFLIST, 1 },
|
||||
{ '<' | KEYC_ESCAPE, 0, MODEKEYCHOICE_STARTOFLIST, 1 },
|
||||
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCHOICE_TOPLINE, 1 },
|
||||
{ '>' | KEYC_ESCAPE, 0, MODEKEYCHOICE_ENDOFLIST, 1 },
|
||||
{ KEYC_END, 0, MODEKEYCHOICE_ENDOFLIST, 1 },
|
||||
{ KEYC_BSPACE, 0, MODEKEYCHOICE_BACKSPACE, 1 },
|
||||
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLDOWN, 1 },
|
||||
{ KEYC_DOWN, 0, MODEKEYCHOICE_DOWN, 1 },
|
||||
{ KEYC_NPAGE, 0, MODEKEYCHOICE_PAGEDOWN, 1 },
|
||||
{ KEYC_PPAGE, 0, MODEKEYCHOICE_PAGEUP, 1 },
|
||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCHOICE_SCROLLUP, 1 },
|
||||
{ KEYC_UP, 0, MODEKEYCHOICE_UP, 1 },
|
||||
{ ' ', 0, MODEKEYCHOICE_TREE_TOGGLE, 1 },
|
||||
{ KEYC_LEFT, 0, MODEKEYCHOICE_TREE_COLLAPSE, 1 },
|
||||
{ KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND, 1 },
|
||||
{ KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL, 1 },
|
||||
{ KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL, 1 },
|
||||
{ KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE, 1 },
|
||||
{ KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE, 1 },
|
||||
{ KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP, 5 },
|
||||
{ KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN, 5 },
|
||||
|
||||
{ 0, -1, 0 }
|
||||
{ 0, -1, 0, 1 }
|
||||
};
|
||||
struct mode_key_tree mode_key_tree_emacs_choice;
|
||||
|
||||
/* emacs copy mode keys. */
|
||||
const struct mode_key_entry mode_key_emacs_copy[] = {
|
||||
{ ' ', 0, MODEKEYCOPY_NEXTPAGE },
|
||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE },
|
||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN },
|
||||
{ '1' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '2' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '3' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '4' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '5' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '6' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '7' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '8' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '9' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX },
|
||||
{ '<' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYTOP },
|
||||
{ '>' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYBOTTOM },
|
||||
{ 'F', 0, MODEKEYCOPY_JUMPBACK },
|
||||
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
|
||||
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCOPY_TOPLINE },
|
||||
{ 'R', 0, MODEKEYCOPY_RECTANGLETOGGLE },
|
||||
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK },
|
||||
{ '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION },
|
||||
{ '\001' /* C-a */, 0, MODEKEYCOPY_STARTOFLINE },
|
||||
{ '\002' /* C-b */, 0, MODEKEYCOPY_LEFT },
|
||||
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
|
||||
{ '\005' /* C-e */, 0, MODEKEYCOPY_ENDOFLINE },
|
||||
{ '\006' /* C-f */, 0, MODEKEYCOPY_RIGHT },
|
||||
{ '\007' /* C-g */, 0, MODEKEYCOPY_CLEARSELECTION },
|
||||
{ '\013' /* C-k */, 0, MODEKEYCOPY_COPYENDOFLINE },
|
||||
{ '\016' /* C-n */, 0, MODEKEYCOPY_DOWN },
|
||||
{ '\020' /* C-p */, 0, MODEKEYCOPY_UP },
|
||||
{ '\022' /* C-r */, 0, MODEKEYCOPY_SEARCHUP },
|
||||
{ '\023' /* C-s */, 0, MODEKEYCOPY_SEARCHDOWN },
|
||||
{ '\026' /* C-v */, 0, MODEKEYCOPY_NEXTPAGE },
|
||||
{ '\027' /* C-w */, 0, MODEKEYCOPY_COPYSELECTION },
|
||||
{ '\033' /* Escape */, 0, MODEKEYCOPY_CANCEL },
|
||||
{ 'b' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSWORD },
|
||||
{ 'f', 0, MODEKEYCOPY_JUMP },
|
||||
{ 'f' | KEYC_ESCAPE, 0, MODEKEYCOPY_NEXTWORDEND },
|
||||
{ 'g', 0, MODEKEYCOPY_GOTOLINE },
|
||||
{ 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION },
|
||||
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
|
||||
{ 'q', 0, MODEKEYCOPY_CANCEL },
|
||||
{ 'r' | KEYC_ESCAPE, 0, MODEKEYCOPY_MIDDLELINE },
|
||||
{ 't', 0, MODEKEYCOPY_JUMPTO },
|
||||
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
||||
{ 'w' | KEYC_ESCAPE, 0, MODEKEYCOPY_COPYSELECTION },
|
||||
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLDOWN },
|
||||
{ KEYC_DOWN | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEDOWN },
|
||||
{ KEYC_DOWN, 0, MODEKEYCOPY_DOWN },
|
||||
{ KEYC_LEFT, 0, MODEKEYCOPY_LEFT },
|
||||
{ KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE },
|
||||
{ KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE },
|
||||
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT },
|
||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLUP },
|
||||
{ KEYC_UP | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEUP },
|
||||
{ KEYC_UP, 0, MODEKEYCOPY_UP },
|
||||
{ KEYC_WHEELUP_PANE, 0, MODEKEYCOPY_SCROLLUP },
|
||||
{ KEYC_WHEELDOWN_PANE, 0, MODEKEYCOPY_SCROLLDOWN },
|
||||
{ KEYC_MOUSEDRAG1_PANE, 0, MODEKEYCOPY_STARTSELECTION },
|
||||
{ KEYC_MOUSEDRAGEND1_PANE, 0, MODEKEYCOPY_COPYSELECTION },
|
||||
{ ' ', 0, MODEKEYCOPY_NEXTPAGE, 1 },
|
||||
{ ',', 0, MODEKEYCOPY_JUMPREVERSE, 1 },
|
||||
{ ';', 0, MODEKEYCOPY_JUMPAGAIN, 1 },
|
||||
{ '1' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '2' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '3' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '4' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '5' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '6' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '7' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '8' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '9' | KEYC_ESCAPE, 0, MODEKEYCOPY_STARTNUMBERPREFIX, 1 },
|
||||
{ '<' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYTOP, 1 },
|
||||
{ '>' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYBOTTOM, 1 },
|
||||
{ 'F', 0, MODEKEYCOPY_JUMPBACK, 1 },
|
||||
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE, 1 },
|
||||
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCOPY_TOPLINE, 1 },
|
||||
{ 'R', 0, MODEKEYCOPY_RECTANGLETOGGLE, 1 },
|
||||
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK, 1 },
|
||||
{ '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION, 1 },
|
||||
{ '\001' /* C-a */, 0, MODEKEYCOPY_STARTOFLINE, 1 },
|
||||
{ '\002' /* C-b */, 0, MODEKEYCOPY_LEFT, 1 },
|
||||
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL, 1 },
|
||||
{ '\005' /* C-e */, 0, MODEKEYCOPY_ENDOFLINE, 1 },
|
||||
{ '\006' /* C-f */, 0, MODEKEYCOPY_RIGHT, 1 },
|
||||
{ '\007' /* C-g */, 0, MODEKEYCOPY_CLEARSELECTION, 1 },
|
||||
{ '\013' /* C-k */, 0, MODEKEYCOPY_COPYENDOFLINE, 1 },
|
||||
{ '\016' /* C-n */, 0, MODEKEYCOPY_DOWN, 1 },
|
||||
{ '\020' /* C-p */, 0, MODEKEYCOPY_UP, 1 },
|
||||
{ '\022' /* C-r */, 0, MODEKEYCOPY_SEARCHUP, 1 },
|
||||
{ '\023' /* C-s */, 0, MODEKEYCOPY_SEARCHDOWN, 1 },
|
||||
{ '\026' /* C-v */, 0, MODEKEYCOPY_NEXTPAGE, 1 },
|
||||
{ '\027' /* C-w */, 0, MODEKEYCOPY_COPYSELECTION, 1 },
|
||||
{ '\033' /* Escape */, 0, MODEKEYCOPY_CANCEL, 1 },
|
||||
{ 'b' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSWORD, 1 },
|
||||
{ 'f', 0, MODEKEYCOPY_JUMP, 1 },
|
||||
{ 'f' | KEYC_ESCAPE, 0, MODEKEYCOPY_NEXTWORDEND, 1 },
|
||||
{ 'g', 0, MODEKEYCOPY_GOTOLINE, 1 },
|
||||
{ 'm' | KEYC_ESCAPE, 0, MODEKEYCOPY_BACKTOINDENTATION, 1 },
|
||||
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN, 1 },
|
||||
{ 'q', 0, MODEKEYCOPY_CANCEL, 1 },
|
||||
{ 'r' | KEYC_ESCAPE, 0, MODEKEYCOPY_MIDDLELINE, 1 },
|
||||
{ 't', 0, MODEKEYCOPY_JUMPTO, 1 },
|
||||
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPAGE, 1 },
|
||||
{ 'w' | KEYC_ESCAPE, 0, MODEKEYCOPY_COPYSELECTION, 1 },
|
||||
{ '{' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPARAGRAPH, 1 },
|
||||
{ '}' | KEYC_ESCAPE, 0, MODEKEYCOPY_NEXTPARAGRAPH, 1 },
|
||||
{ KEYC_DOWN | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLDOWN, 1 },
|
||||
{ KEYC_DOWN | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEDOWN, 1 },
|
||||
{ KEYC_DOWN, 0, MODEKEYCOPY_DOWN, 1 },
|
||||
{ KEYC_LEFT, 0, MODEKEYCOPY_LEFT, 1 },
|
||||
{ KEYC_NPAGE, 0, MODEKEYCOPY_NEXTPAGE, 1 },
|
||||
{ KEYC_PPAGE, 0, MODEKEYCOPY_PREVIOUSPAGE, 1 },
|
||||
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT, 1 },
|
||||
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLUP, 1 },
|
||||
{ KEYC_UP | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEUP, 1 },
|
||||
{ KEYC_UP, 0, MODEKEYCOPY_UP, 1 },
|
||||
{ KEYC_WHEELUP_PANE, 0, MODEKEYCOPY_SCROLLUP, 5 },
|
||||
{ KEYC_WHEELDOWN_PANE, 0, MODEKEYCOPY_SCROLLDOWN, 5 },
|
||||
{ KEYC_MOUSEDRAG1_PANE, 0, MODEKEYCOPY_STARTSELECTION, 1 },
|
||||
{ KEYC_MOUSEDRAGEND1_PANE, 0, MODEKEYCOPY_COPYSELECTION, 1 },
|
||||
|
||||
{ 0, -1, 0 }
|
||||
{ 0, -1, 0, 1 }
|
||||
};
|
||||
struct mode_key_tree mode_key_tree_emacs_copy;
|
||||
|
||||
@@ -580,6 +587,7 @@ mode_key_init_trees(void)
|
||||
for (ment = mtab->table; ment->mode != -1; ment++) {
|
||||
mbind = xmalloc(sizeof *mbind);
|
||||
mbind->key = ment->key;
|
||||
mbind->repeat = ment->repeat;
|
||||
mbind->mode = ment->mode;
|
||||
mbind->cmd = ment->cmd;
|
||||
mbind->arg = NULL;
|
||||
@@ -596,7 +604,8 @@ mode_key_init(struct mode_key_data *mdata, struct mode_key_tree *mtree)
|
||||
}
|
||||
|
||||
enum mode_key_cmd
|
||||
mode_key_lookup(struct mode_key_data *mdata, key_code key, const char **arg)
|
||||
mode_key_lookup(struct mode_key_data *mdata, key_code key, const char **arg,
|
||||
u_int *repeat)
|
||||
{
|
||||
struct mode_key_binding *mbind, mtmp;
|
||||
|
||||
@@ -607,6 +616,8 @@ mode_key_lookup(struct mode_key_data *mdata, key_code key, const char **arg)
|
||||
return (MODEKEY_NONE);
|
||||
return (MODEKEY_OTHER);
|
||||
}
|
||||
if (repeat != NULL)
|
||||
*repeat = mbind->repeat;
|
||||
|
||||
switch (mbind->cmd) {
|
||||
case MODEKEYEDIT_SWITCHMODE:
|
||||
|
||||
9
names.c
9
names.c
@@ -73,12 +73,15 @@ check_window_name(struct window *w)
|
||||
if (!event_initialized(&w->name_event))
|
||||
evtimer_set(&w->name_event, name_time_callback, w);
|
||||
if (!evtimer_pending(&w->name_event, NULL)) {
|
||||
log_debug("@%u name timer queued (%d left)", w->id, left);
|
||||
log_debug("@%u name timer queued (%d left)", w->id,
|
||||
left);
|
||||
timerclear(&next);
|
||||
next.tv_usec = left;
|
||||
event_add(&w->name_event, &next);
|
||||
} else
|
||||
log_debug("@%u name timer already queued (%d left)", w->id, left);
|
||||
} else {
|
||||
log_debug("@%u name timer already queued (%d left)",
|
||||
w->id, left);
|
||||
}
|
||||
return;
|
||||
}
|
||||
memcpy(&w->name_time, &tv, sizeof w->name_time);
|
||||
|
||||
@@ -50,6 +50,9 @@ const char *options_table_status_position_list[] = {
|
||||
const char *options_table_bell_action_list[] = {
|
||||
"none", "any", "current", "other", NULL
|
||||
};
|
||||
const char *options_table_pane_status_list[] = {
|
||||
"off", "top", "bottom", NULL
|
||||
};
|
||||
|
||||
/* Server options. */
|
||||
const struct options_table_entry options_table[] = {
|
||||
@@ -692,6 +695,20 @@ const struct options_table_entry options_table[] = {
|
||||
.style = "pane-border-style"
|
||||
},
|
||||
|
||||
{ .name = "pane-border-format",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "#{?pane_active,#[reverse],}#{pane_index}#[default] "
|
||||
"\"#{pane_title}\""
|
||||
},
|
||||
|
||||
{ .name = "pane-border-status",
|
||||
.type = OPTIONS_TABLE_CHOICE,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.choices = options_table_pane_status_list,
|
||||
.default_num = 0
|
||||
},
|
||||
|
||||
{ .name = "pane-border-style",
|
||||
.type = OPTIONS_TABLE_STYLE,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
|
||||
@@ -128,19 +128,23 @@ options_set_string(struct options *oo, const char *name, const char *fmt, ...)
|
||||
{
|
||||
struct options_entry *o;
|
||||
va_list ap;
|
||||
char *s;
|
||||
|
||||
s = NULL;
|
||||
if ((o = options_find1(oo, name)) == NULL) {
|
||||
o = xmalloc(sizeof *o);
|
||||
o->name = xstrdup(name);
|
||||
RB_INSERT(options_tree, &oo->tree, o);
|
||||
memcpy(&o->style, &grid_default_cell, sizeof o->style);
|
||||
} else if (o->type == OPTIONS_STRING)
|
||||
free(o->str);
|
||||
s = o->str;
|
||||
|
||||
va_start(ap, fmt);
|
||||
o->type = OPTIONS_STRING;
|
||||
xvasprintf(&o->str, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
free(s);
|
||||
return (o);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <Availability.h>
|
||||
#include <event.h>
|
||||
#include <libproc.h>
|
||||
#include <stdlib.h>
|
||||
@@ -33,18 +35,34 @@ struct event_base *osdep_event_init(void);
|
||||
char *
|
||||
osdep_get_name(int fd, __unused char *tty)
|
||||
{
|
||||
struct proc_bsdinfo bsdinfo;
|
||||
#ifdef __MAC_10_7
|
||||
struct proc_bsdshortinfo bsdinfo;
|
||||
pid_t pgrp;
|
||||
int ret;
|
||||
|
||||
if ((pgrp = tcgetpgrp(fd)) == -1)
|
||||
return (NULL);
|
||||
|
||||
ret = proc_pidinfo(pgrp, PROC_PIDTBSDINFO, 0,
|
||||
&bsdinfo, sizeof bsdinfo);
|
||||
if (ret == sizeof bsdinfo && *bsdinfo.pbi_comm != '\0')
|
||||
return (strdup(bsdinfo.pbi_comm));
|
||||
return (NULL);
|
||||
ret = proc_pidinfo(pgrp, PROC_PIDT_SHORTBSDINFO, 0,
|
||||
&bsdinfo, sizeof bsdinfo);
|
||||
if (ret == sizeof bsdinfo && *bsdinfo.pbsi_comm != '\0')
|
||||
return (strdup(bsdinfo.pbsi_comm));
|
||||
#else
|
||||
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 0 };
|
||||
size_t size;
|
||||
struct kinfo_proc kp;
|
||||
|
||||
if ((mib[3] = tcgetpgrp(fd)) == -1)
|
||||
return (NULL);
|
||||
|
||||
size = sizeof kp;
|
||||
if (sysctl(mib, 4, &kp, &size, NULL, 0) == -1)
|
||||
return (NULL);
|
||||
if (*kp.kp_proc.p_comm == '\0')
|
||||
return (NULL);
|
||||
|
||||
return (strdup(kp.kp_proc.p_comm));
|
||||
#endif
|
||||
}
|
||||
|
||||
char *
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <event.h>
|
||||
|
||||
2
proc.c
2
proc.c
@@ -191,9 +191,7 @@ proc_start(const char *name, struct event_base *base, int forkflag,
|
||||
|
||||
log_open(name);
|
||||
|
||||
#ifdef HAVE_SETPROCTITLE
|
||||
setproctitle("%s (%s)", name, socket_path);
|
||||
#endif
|
||||
|
||||
if (uname(&u) < 0)
|
||||
memset(&u, 0, sizeof u);
|
||||
|
||||
183
screen-redraw.c
183
screen-redraw.c
@@ -24,12 +24,16 @@
|
||||
|
||||
int screen_redraw_cell_border1(struct window_pane *, u_int, u_int);
|
||||
int screen_redraw_cell_border(struct client *, u_int, u_int);
|
||||
int screen_redraw_check_cell(struct client *, u_int, u_int,
|
||||
int screen_redraw_check_cell(struct client *, u_int, u_int, int,
|
||||
struct window_pane **);
|
||||
int screen_redraw_check_is(u_int, u_int, int, struct window *,
|
||||
int screen_redraw_check_is(u_int, u_int, int, int, struct window *,
|
||||
struct window_pane *, struct window_pane *);
|
||||
|
||||
void screen_redraw_draw_borders(struct client *, int, u_int);
|
||||
int screen_redraw_make_pane_status(struct client *, struct window *,
|
||||
struct window_pane *);
|
||||
void screen_redraw_draw_pane_status(struct client *, int);
|
||||
|
||||
void screen_redraw_draw_borders(struct client *, int, int, u_int);
|
||||
void screen_redraw_draw_panes(struct client *, u_int);
|
||||
void screen_redraw_draw_status(struct client *, u_int);
|
||||
void screen_redraw_draw_number(struct client *, struct window_pane *, u_int);
|
||||
@@ -50,6 +54,10 @@ void screen_redraw_draw_number(struct client *, struct window_pane *, u_int);
|
||||
|
||||
#define CELL_BORDERS " xqlkmjwvtun~"
|
||||
|
||||
#define CELL_STATUS_OFF 0
|
||||
#define CELL_STATUS_TOP 1
|
||||
#define CELL_STATUS_BOTTOM 2
|
||||
|
||||
/* Check if cell is on the border of a particular pane. */
|
||||
int
|
||||
screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
|
||||
@@ -64,15 +72,15 @@ screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
|
||||
if (wp->xoff != 0 && px == wp->xoff - 1)
|
||||
return (1);
|
||||
if (px == wp->xoff + wp->sx)
|
||||
return (1);
|
||||
return (2);
|
||||
}
|
||||
|
||||
/* Top/bottom borders. */
|
||||
if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= wp->xoff + wp->sx) {
|
||||
if (wp->yoff != 0 && py == wp->yoff - 1)
|
||||
return (1);
|
||||
return (3);
|
||||
if (py == wp->yoff + wp->sy)
|
||||
return (1);
|
||||
return (4);
|
||||
}
|
||||
|
||||
/* Outside pane. */
|
||||
@@ -92,7 +100,7 @@ screen_redraw_cell_border(struct client *c, u_int px, u_int py)
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
if ((retval = screen_redraw_cell_border1(wp, px, py)) != -1)
|
||||
return (retval);
|
||||
return (!!retval);
|
||||
}
|
||||
|
||||
return (0);
|
||||
@@ -100,16 +108,33 @@ screen_redraw_cell_border(struct client *c, u_int px, u_int py)
|
||||
|
||||
/* Check if cell inside a pane. */
|
||||
int
|
||||
screen_redraw_check_cell(struct client *c, u_int px, u_int py,
|
||||
screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
|
||||
struct window_pane **wpp)
|
||||
{
|
||||
struct window *w = c->session->curw->window;
|
||||
struct window_pane *wp;
|
||||
int borders;
|
||||
u_int right, line;
|
||||
|
||||
if (px > w->sx || py > w->sy)
|
||||
return (CELL_OUTSIDE);
|
||||
|
||||
if (pane_status != CELL_STATUS_OFF) {
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
|
||||
if (pane_status == CELL_STATUS_TOP)
|
||||
line = wp->yoff - 1;
|
||||
else
|
||||
line = wp->yoff + wp->sy;
|
||||
right = wp->xoff + 2 + wp->status_size - 1;
|
||||
|
||||
if (py == line && px >= wp->xoff + 2 && px <= right)
|
||||
return (CELL_INSIDE);
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
@@ -135,8 +160,13 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py,
|
||||
borders |= 8;
|
||||
if (px <= w->sx && screen_redraw_cell_border(c, px + 1, py))
|
||||
borders |= 4;
|
||||
if (py == 0 || screen_redraw_cell_border(c, px, py - 1))
|
||||
borders |= 2;
|
||||
if (pane_status == CELL_STATUS_TOP) {
|
||||
if (py != 0 && screen_redraw_cell_border(c, px, py - 1))
|
||||
borders |= 2;
|
||||
} else {
|
||||
if (py == 0 || screen_redraw_cell_border(c, px, py - 1))
|
||||
borders |= 2;
|
||||
}
|
||||
if (py <= w->sy && screen_redraw_cell_border(c, px, py + 1))
|
||||
borders |= 1;
|
||||
|
||||
@@ -177,11 +207,18 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py,
|
||||
|
||||
/* Check if the border of a particular pane. */
|
||||
int
|
||||
screen_redraw_check_is(u_int px, u_int py, int type, struct window *w,
|
||||
struct window_pane *wantwp, struct window_pane *wp)
|
||||
screen_redraw_check_is(u_int px, u_int py, int type, int pane_status,
|
||||
struct window *w, struct window_pane *wantwp, struct window_pane *wp)
|
||||
{
|
||||
int border;
|
||||
|
||||
/* Is this off the active pane border? */
|
||||
if (screen_redraw_cell_border1(wantwp, px, py) != 1)
|
||||
border = screen_redraw_cell_border1(wantwp, px, py);
|
||||
if (border == 0 || border == -1)
|
||||
return (0);
|
||||
if (pane_status == CELL_STATUS_TOP && border == 4)
|
||||
return (0);
|
||||
if (pane_status == CELL_STATUS_BOTTOM && border == 3)
|
||||
return (0);
|
||||
|
||||
/* If there are more than two panes, that's enough. */
|
||||
@@ -192,6 +229,10 @@ screen_redraw_check_is(u_int px, u_int py, int type, struct window *w,
|
||||
if (wp == NULL || (type == CELL_OUTSIDE || type == CELL_INSIDE))
|
||||
return (1);
|
||||
|
||||
/* With status lines mark the entire line. */
|
||||
if (pane_status != CELL_STATUS_OFF)
|
||||
return (1);
|
||||
|
||||
/* Check if the pane covers the whole width. */
|
||||
if (wp->xoff == 0 && wp->sx == w->sx) {
|
||||
/* This can either be the top pane or the bottom pane. */
|
||||
@@ -214,7 +255,77 @@ screen_redraw_check_is(u_int px, u_int py, int type, struct window *w,
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (type);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Update pane status. */
|
||||
int
|
||||
screen_redraw_make_pane_status(struct client *c, struct window *w,
|
||||
struct window_pane *wp)
|
||||
{
|
||||
struct grid_cell gc;
|
||||
const char *fmt;
|
||||
struct format_tree *ft;
|
||||
char *out;
|
||||
size_t outlen, old_size = wp->status_size;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (wp == w->active)
|
||||
style_apply(&gc, w->options, "pane-active-border-style");
|
||||
else
|
||||
style_apply(&gc, w->options, "pane-border-style");
|
||||
|
||||
fmt = options_get_string(w->options, "pane-border-format");
|
||||
|
||||
ft = format_create(NULL, 0);
|
||||
format_defaults(ft, c, NULL, NULL, wp);
|
||||
|
||||
screen_free(&wp->status_screen);
|
||||
screen_init(&wp->status_screen, wp->sx, 1, 0);
|
||||
wp->status_screen.mode = 0;
|
||||
|
||||
out = format_expand(ft, fmt);
|
||||
outlen = screen_write_cstrlen("%s", out);
|
||||
if (outlen > wp->sx - 4)
|
||||
outlen = wp->sx - 4;
|
||||
screen_resize(&wp->status_screen, outlen, 1, 0);
|
||||
|
||||
screen_write_start(&ctx, NULL, &wp->status_screen);
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_clearline(&ctx);
|
||||
screen_write_cnputs(&ctx, outlen, &gc, "%s", out);
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
format_free(ft);
|
||||
|
||||
wp->status_size = outlen;
|
||||
return (wp->status_size != old_size);
|
||||
}
|
||||
|
||||
/* Draw pane status. */
|
||||
void
|
||||
screen_redraw_draw_pane_status(struct client *c, int pane_status)
|
||||
{
|
||||
struct window *w = c->session->curw->window;
|
||||
struct options *oo = c->session->options;
|
||||
struct tty *tty = &c->tty;
|
||||
struct window_pane *wp;
|
||||
int spos;
|
||||
u_int yoff;
|
||||
|
||||
spos = options_get_number(oo, "status-position");
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (pane_status == CELL_STATUS_TOP)
|
||||
yoff = wp->yoff - 1;
|
||||
else
|
||||
yoff = wp->yoff + wp->sy;
|
||||
if (spos == 0)
|
||||
yoff += 1;
|
||||
|
||||
tty_draw_line(tty, NULL, &wp->status_screen, 0, wp->xoff + 2,
|
||||
yoff);
|
||||
}
|
||||
tty_cursor(tty, 0, 0);
|
||||
}
|
||||
|
||||
/* Redraw entire screen. */
|
||||
@@ -222,10 +333,12 @@ void
|
||||
screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
|
||||
int draw_borders)
|
||||
{
|
||||
struct options *oo = c->session->options;
|
||||
struct tty *tty = &c->tty;
|
||||
u_int top;
|
||||
int status, spos;
|
||||
struct options *oo = c->session->options;
|
||||
struct tty *tty = &c->tty;
|
||||
struct window *w = c->session->curw->window;
|
||||
struct window_pane *wp;
|
||||
u_int top;
|
||||
int status, pane_status, spos;
|
||||
|
||||
/* Suspended clients should not be updated. */
|
||||
if (c->flags & CLIENT_SUSPENDED)
|
||||
@@ -243,12 +356,24 @@ screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
|
||||
if (!status)
|
||||
draw_status = 0;
|
||||
|
||||
/* Update pane status lines. */
|
||||
pane_status = options_get_number(w->options, "pane-border-status");
|
||||
if (pane_status != CELL_STATUS_OFF && (draw_borders || draw_status)) {
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (screen_redraw_make_pane_status(c, w, wp))
|
||||
draw_borders = draw_status = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw the elements. */
|
||||
if (draw_borders)
|
||||
screen_redraw_draw_borders(c, status, top);
|
||||
screen_redraw_draw_borders(c, status, pane_status, top);
|
||||
if (draw_panes)
|
||||
screen_redraw_draw_panes(c, top);
|
||||
if (draw_status)
|
||||
screen_redraw_draw_status(c, top);
|
||||
if (pane_status != CELL_STATUS_OFF && (draw_borders || draw_status))
|
||||
screen_redraw_draw_pane_status(c, pane_status);
|
||||
tty_reset(tty);
|
||||
}
|
||||
|
||||
@@ -272,7 +397,8 @@ screen_redraw_pane(struct client *c, struct window_pane *wp)
|
||||
|
||||
/* Draw the borders. */
|
||||
void
|
||||
screen_redraw_draw_borders(struct client *c, int status, u_int top)
|
||||
screen_redraw_draw_borders(struct client *c, int status, int pane_status,
|
||||
u_int top)
|
||||
{
|
||||
struct session *s = c->session;
|
||||
struct window *w = s->curw->window;
|
||||
@@ -323,16 +449,17 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
|
||||
|
||||
for (j = 0; j < tty->sy - status; j++) {
|
||||
for (i = 0; i < tty->sx; i++) {
|
||||
type = screen_redraw_check_cell(c, i, j, &wp);
|
||||
type = screen_redraw_check_cell(c, i, j, pane_status,
|
||||
&wp);
|
||||
if (type == CELL_INSIDE)
|
||||
continue;
|
||||
if (type == CELL_OUTSIDE && small &&
|
||||
i > msgx && j == msgy)
|
||||
continue;
|
||||
active = screen_redraw_check_is(i, j, type, w,
|
||||
w->active, wp);
|
||||
active = screen_redraw_check_is(i, j, type, pane_status,
|
||||
w, w->active, wp);
|
||||
if (server_is_marked(s, s->curw, marked_pane.wp) &&
|
||||
screen_redraw_check_is(i, j, type, w,
|
||||
screen_redraw_check_is(i, j, type, pane_status, w,
|
||||
marked_pane.wp, wp)) {
|
||||
if (active)
|
||||
tty_attributes(tty, &m_active_gc, NULL);
|
||||
@@ -425,9 +552,9 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp, u_int top)
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
if (w->active == wp)
|
||||
colour_set_bg(&gc, active_colour);
|
||||
gc.bg = active_colour;
|
||||
else
|
||||
colour_set_bg(&gc, colour);
|
||||
gc.bg = colour;
|
||||
tty_attributes(tty, &gc, wp);
|
||||
for (ptr = buf; *ptr != '\0'; ptr++) {
|
||||
if (*ptr < '0' || *ptr > '9')
|
||||
@@ -452,9 +579,9 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp, u_int top)
|
||||
draw_text:
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
if (w->active == wp)
|
||||
colour_set_fg(&gc, active_colour);
|
||||
gc.fg = active_colour;
|
||||
else
|
||||
colour_set_fg(&gc, colour);
|
||||
gc.fg = colour;
|
||||
tty_attributes(tty, &gc, wp);
|
||||
tty_puts(tty, buf);
|
||||
|
||||
|
||||
537
screen-write.c
537
screen-write.c
@@ -23,27 +23,115 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
void screen_write_initctx(struct screen_write_ctx *, struct tty_ctx *, int);
|
||||
void screen_write_overwrite(struct screen_write_ctx *, u_int);
|
||||
int screen_write_combine(struct screen_write_ctx *,
|
||||
const struct utf8_data *);
|
||||
static void screen_write_initctx(struct screen_write_ctx *,
|
||||
struct tty_ctx *);
|
||||
static void screen_write_save_last(struct screen_write_ctx *,
|
||||
struct tty_ctx *);
|
||||
static void screen_write_flush(struct screen_write_ctx *);
|
||||
|
||||
/* Initialise writing with a window. */
|
||||
static int screen_write_overwrite(struct screen_write_ctx *,
|
||||
struct grid_cell *, u_int);
|
||||
static int screen_write_combine(struct screen_write_ctx *,
|
||||
const struct utf8_data *);
|
||||
|
||||
static const struct grid_cell screen_write_pad_cell = {
|
||||
GRID_FLAG_PADDING, 0, 8, 8, { { 0 }, 0, 0, 0 }
|
||||
};
|
||||
|
||||
#define screen_dirty_bit(s, x, y) (((y) * screen_size_x(s)) + (x))
|
||||
#define screen_dirty_clear(s, sx, sy, ex, ey) \
|
||||
do { \
|
||||
if (s->dirty != NULL) { \
|
||||
bit_nclear(s->dirty, \
|
||||
screen_dirty_bit(s, sx, sy), \
|
||||
screen_dirty_bit(s, ex, ey)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Initialize writing with a window. */
|
||||
void
|
||||
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
|
||||
struct screen *s)
|
||||
{
|
||||
u_int size;
|
||||
char tmp[16];
|
||||
const char *cp = tmp;
|
||||
|
||||
ctx->wp = wp;
|
||||
if (wp != NULL && s == NULL)
|
||||
ctx->s = wp->screen;
|
||||
else
|
||||
ctx->s = s;
|
||||
|
||||
size = screen_size_x(ctx->s) * screen_size_y(ctx->s);
|
||||
if (ctx->s->dirtysize != size) {
|
||||
free(ctx->s->dirty);
|
||||
ctx->s->dirty = NULL;
|
||||
ctx->s->dirtysize = size;
|
||||
}
|
||||
ctx->dirty = 0;
|
||||
|
||||
ctx->cells = ctx->written = ctx->skipped = 0;
|
||||
|
||||
if (wp == NULL)
|
||||
cp = "no pane";
|
||||
else
|
||||
snprintf(tmp, sizeof tmp, "pane %%%u", wp->id);
|
||||
log_debug("%s: size %ux%u, %s", __func__, screen_size_x(ctx->s),
|
||||
screen_size_y(ctx->s), cp);
|
||||
}
|
||||
|
||||
/* Finish writing. */
|
||||
void
|
||||
screen_write_stop(__unused struct screen_write_ctx *ctx)
|
||||
screen_write_stop(struct screen_write_ctx *ctx)
|
||||
{
|
||||
screen_write_flush(ctx);
|
||||
|
||||
log_debug("%s: %u of %u written (dirty %u, skipped %u)", __func__,
|
||||
ctx->written, ctx->cells, ctx->cells - ctx->written, ctx->skipped);
|
||||
}
|
||||
|
||||
/* Flush outstanding cell writes. */
|
||||
static void
|
||||
screen_write_flush(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int x, y, offset, cx, cy, dirty;
|
||||
struct grid_cell gc;
|
||||
|
||||
if (ctx->dirty == 0)
|
||||
return;
|
||||
dirty = 0;
|
||||
|
||||
cx = s->cx;
|
||||
cy = s->cy;
|
||||
|
||||
offset = 0;
|
||||
for (y = 0; y < screen_size_y(s); y++) {
|
||||
for (x = 0; x < screen_size_x(s); x++) {
|
||||
offset++;
|
||||
if (!bit_test(s->dirty, offset - 1))
|
||||
continue;
|
||||
bit_clear(s->dirty, offset - 1);
|
||||
|
||||
screen_write_cursormove(ctx, x, y);
|
||||
grid_view_get_cell(s->grid, x, y, &gc);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
ttyctx.cell = &gc;
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
ctx->written++;
|
||||
|
||||
if (++dirty == ctx->dirty)
|
||||
break;
|
||||
}
|
||||
if (dirty == ctx->dirty)
|
||||
break;
|
||||
}
|
||||
|
||||
s->cx = cx;
|
||||
s->cy = cy;
|
||||
}
|
||||
|
||||
/* Reset screen state. */
|
||||
@@ -64,11 +152,15 @@ screen_write_reset(struct screen_write_ctx *ctx)
|
||||
|
||||
/* Write character. */
|
||||
void
|
||||
screen_write_putc(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
||||
screen_write_putc(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
|
||||
u_char ch)
|
||||
{
|
||||
utf8_set(&gc->data, ch);
|
||||
screen_write_cell(ctx, gc);
|
||||
struct grid_cell gc;
|
||||
|
||||
memcpy(&gc, gcp, sizeof gc);
|
||||
|
||||
utf8_set(&gc.data, ch);
|
||||
screen_write_cell(ctx, &gc);
|
||||
}
|
||||
|
||||
/* Calculate string length, with embedded formatting. */
|
||||
@@ -148,75 +240,74 @@ screen_write_strlen(const char *fmt, ...)
|
||||
|
||||
/* Write simple string (no UTF-8 or maximum length). */
|
||||
void
|
||||
screen_write_puts(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
||||
screen_write_puts(struct screen_write_ctx *ctx, const struct grid_cell *gcp,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
screen_write_vnputs(ctx, -1, gc, fmt, ap);
|
||||
screen_write_vnputs(ctx, -1, gcp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Write string with length limit (-1 for unlimited). */
|
||||
void
|
||||
screen_write_nputs(struct screen_write_ctx *ctx, ssize_t maxlen,
|
||||
struct grid_cell *gc, const char *fmt, ...)
|
||||
const struct grid_cell *gcp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
screen_write_vnputs(ctx, maxlen, gc, fmt, ap);
|
||||
screen_write_vnputs(ctx, maxlen, gcp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
|
||||
struct grid_cell *gc, const char *fmt, va_list ap)
|
||||
const struct grid_cell *gcp, const char *fmt, va_list ap)
|
||||
{
|
||||
struct grid_cell gc;
|
||||
struct utf8_data *ud = &gc.data;
|
||||
char *msg;
|
||||
struct utf8_data ud;
|
||||
u_char *ptr;
|
||||
size_t left, size = 0;
|
||||
enum utf8_state more;
|
||||
|
||||
memcpy(&gc, gcp, sizeof gc);
|
||||
xvasprintf(&msg, fmt, ap);
|
||||
|
||||
ptr = msg;
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr > 0x7f && utf8_open(&ud, *ptr) == UTF8_MORE) {
|
||||
if (*ptr > 0x7f && utf8_open(ud, *ptr) == UTF8_MORE) {
|
||||
ptr++;
|
||||
|
||||
left = strlen(ptr);
|
||||
if (left < (size_t)ud.size - 1)
|
||||
if (left < (size_t)ud->size - 1)
|
||||
break;
|
||||
while ((more = utf8_append(&ud, *ptr)) == UTF8_MORE)
|
||||
while ((more = utf8_append(ud, *ptr)) == UTF8_MORE)
|
||||
ptr++;
|
||||
ptr++;
|
||||
|
||||
if (more == UTF8_DONE) {
|
||||
if (maxlen > 0 &&
|
||||
size + ud.width > (size_t) maxlen) {
|
||||
while (size < (size_t) maxlen) {
|
||||
screen_write_putc(ctx, gc, ' ');
|
||||
size++;
|
||||
}
|
||||
break;
|
||||
if (more != UTF8_DONE)
|
||||
continue;
|
||||
if (maxlen > 0 && size + ud->width > (size_t)maxlen) {
|
||||
while (size < (size_t)maxlen) {
|
||||
screen_write_putc(ctx, &gc, ' ');
|
||||
size++;
|
||||
}
|
||||
size += ud.width;
|
||||
|
||||
utf8_copy(&gc->data, &ud);
|
||||
screen_write_cell(ctx, gc);
|
||||
break;
|
||||
}
|
||||
size += ud->width;
|
||||
screen_write_cell(ctx, &gc);
|
||||
} else {
|
||||
if (maxlen > 0 && size + 1 > (size_t) maxlen)
|
||||
if (maxlen > 0 && size + 1 > (size_t)maxlen)
|
||||
break;
|
||||
|
||||
if (*ptr == '\001')
|
||||
gc->attr ^= GRID_ATTR_CHARSET;
|
||||
gc.attr ^= GRID_ATTR_CHARSET;
|
||||
else if (*ptr > 0x1f && *ptr < 0x7f) {
|
||||
size++;
|
||||
screen_write_putc(ctx, gc, *ptr);
|
||||
screen_write_putc(ctx, &gc, *ptr);
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
@@ -228,22 +319,22 @@ screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
|
||||
/* Write string, similar to nputs, but with embedded formatting (#[]). */
|
||||
void
|
||||
screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
|
||||
struct grid_cell *gc, const char *fmt, ...)
|
||||
const struct grid_cell *gcp, const char *fmt, ...)
|
||||
{
|
||||
struct grid_cell lgc;
|
||||
struct utf8_data ud;
|
||||
struct grid_cell gc;
|
||||
struct utf8_data *ud = &gc.data;
|
||||
va_list ap;
|
||||
char *msg;
|
||||
u_char *ptr, *last;
|
||||
size_t left, size = 0;
|
||||
enum utf8_state more;
|
||||
|
||||
memcpy(&gc, gcp, sizeof gc);
|
||||
|
||||
va_start(ap, fmt);
|
||||
xvasprintf(&msg, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
memcpy(&lgc, gc, sizeof lgc);
|
||||
|
||||
ptr = msg;
|
||||
while (*ptr != '\0') {
|
||||
if (ptr[0] == '#' && ptr[1] == '[') {
|
||||
@@ -255,42 +346,39 @@ screen_write_cnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
|
||||
}
|
||||
*last = '\0';
|
||||
|
||||
style_parse(gc, &lgc, ptr);
|
||||
style_parse(gcp, &gc, ptr);
|
||||
ptr = last + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*ptr > 0x7f && utf8_open(&ud, *ptr) == UTF8_MORE) {
|
||||
if (*ptr > 0x7f && utf8_open(ud, *ptr) == UTF8_MORE) {
|
||||
ptr++;
|
||||
|
||||
left = strlen(ptr);
|
||||
if (left < (size_t)ud.size - 1)
|
||||
if (left < (size_t)ud->size - 1)
|
||||
break;
|
||||
while ((more = utf8_append(&ud, *ptr)) == UTF8_MORE)
|
||||
while ((more = utf8_append(ud, *ptr)) == UTF8_MORE)
|
||||
ptr++;
|
||||
ptr++;
|
||||
|
||||
if (more == UTF8_DONE) {
|
||||
if (maxlen > 0 &&
|
||||
size + ud.width > (size_t) maxlen) {
|
||||
while (size < (size_t) maxlen) {
|
||||
screen_write_putc(ctx, gc, ' ');
|
||||
size++;
|
||||
}
|
||||
break;
|
||||
if (more != UTF8_DONE)
|
||||
continue;
|
||||
if (maxlen > 0 && size + ud->width > (size_t)maxlen) {
|
||||
while (size < (size_t)maxlen) {
|
||||
screen_write_putc(ctx, &gc, ' ');
|
||||
size++;
|
||||
}
|
||||
size += ud.width;
|
||||
|
||||
utf8_copy(&lgc.data, &ud);
|
||||
screen_write_cell(ctx, &lgc);
|
||||
break;
|
||||
}
|
||||
size += ud->width;
|
||||
screen_write_cell(ctx, &gc);
|
||||
} else {
|
||||
if (maxlen > 0 && size + 1 > (size_t) maxlen)
|
||||
if (maxlen > 0 && size + 1 > (size_t)maxlen)
|
||||
break;
|
||||
|
||||
if (*ptr > 0x1f && *ptr < 0x7f) {
|
||||
size++;
|
||||
screen_write_putc(ctx, &lgc, *ptr);
|
||||
screen_write_putc(ctx, &gc, *ptr);
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
@@ -344,14 +432,10 @@ screen_write_copy(struct screen_write_ctx *ctx,
|
||||
}
|
||||
|
||||
/* Set up context for TTY command. */
|
||||
void
|
||||
screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
|
||||
int save_last)
|
||||
static void
|
||||
screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
struct grid_cell gc;
|
||||
u_int xx;
|
||||
struct screen *s = ctx->s;
|
||||
|
||||
ttyctx->wp = ctx->wp;
|
||||
|
||||
@@ -360,18 +444,23 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
|
||||
|
||||
ttyctx->orlower = s->rlower;
|
||||
ttyctx->orupper = s->rupper;
|
||||
}
|
||||
|
||||
if (!save_last)
|
||||
return;
|
||||
/* Save last cell on screen. */
|
||||
static void
|
||||
screen_write_save_last(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
struct grid_cell gc;
|
||||
u_int xx;
|
||||
|
||||
/* Save the last cell on the screen. */
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
for (xx = 1; xx <= screen_size_x(s); xx++) {
|
||||
grid_view_get_cell(gd, screen_size_x(s) - xx, s->cy, &gc);
|
||||
if (~gc.flags & GRID_FLAG_PADDING)
|
||||
break;
|
||||
}
|
||||
ttyctx->last_width = xx;
|
||||
memcpy(&ttyctx->last_cell, &gc, sizeof ttyctx->last_cell);
|
||||
}
|
||||
|
||||
@@ -506,8 +595,11 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
|
||||
struct tty_ctx ttyctx;
|
||||
struct grid_cell gc;
|
||||
u_int xx, yy;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
utf8_set(&gc.data, 'E');
|
||||
@@ -521,7 +613,6 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
|
||||
s->cy = 0;
|
||||
|
||||
s->rupper = 0;
|
||||
|
||||
s->rlower = screen_size_y(s) - 1;
|
||||
|
||||
tty_write(tty_cmd_alignmenttest, &ttyctx);
|
||||
@@ -542,7 +633,8 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
|
||||
if (nx == 0)
|
||||
return;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_flush(ctx);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
if (s->cx <= screen_size_x(s) - 1)
|
||||
grid_view_insert_cells(s->grid, s->cx, s->cy, nx);
|
||||
@@ -566,7 +658,8 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
|
||||
if (nx == 0)
|
||||
return;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_flush(ctx);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
if (s->cx <= screen_size_x(s) - 1)
|
||||
grid_view_delete_cells(s->grid, s->cx, s->cy, nx);
|
||||
@@ -590,10 +683,13 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx)
|
||||
if (nx == 0)
|
||||
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) {
|
||||
screen_dirty_clear(s, s->cx, s->cy, s->cx + nx - 1, s->cy);
|
||||
grid_view_clear(s->grid, s->cx, s->cy, nx, 1);
|
||||
} else
|
||||
return;
|
||||
|
||||
ttyctx.num = nx;
|
||||
tty_write(tty_cmd_clearcharacter, &ttyctx);
|
||||
@@ -615,7 +711,8 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
|
||||
if (ny == 0)
|
||||
return;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_flush(ctx);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
grid_view_insert_lines(s->grid, s->cy, ny);
|
||||
|
||||
@@ -629,7 +726,8 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
|
||||
if (ny == 0)
|
||||
return;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_flush(ctx);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
if (s->cy < s->rupper || s->cy > s->rlower)
|
||||
grid_view_insert_lines(s->grid, s->cy, ny);
|
||||
@@ -656,7 +754,8 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
|
||||
if (ny == 0)
|
||||
return;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_flush(ctx);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
grid_view_delete_lines(s->grid, s->cy, ny);
|
||||
|
||||
@@ -670,7 +769,8 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
|
||||
if (ny == 0)
|
||||
return;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_flush(ctx);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
if (s->cy < s->rupper || s->cy > s->rlower)
|
||||
grid_view_delete_lines(s->grid, s->cy, ny);
|
||||
@@ -685,12 +785,19 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
|
||||
void
|
||||
screen_write_clearline(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
struct screen *s = ctx->s;
|
||||
struct grid_line *gl;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
|
||||
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
||||
if (gl->cellsize != 0) {
|
||||
screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
|
||||
grid_view_clear(s->grid, 0, s->cy, sx, 1);
|
||||
} else
|
||||
return;
|
||||
|
||||
tty_write(tty_cmd_clearline, &ttyctx);
|
||||
}
|
||||
@@ -699,16 +806,19 @@ screen_write_clearline(struct screen_write_ctx *ctx)
|
||||
void
|
||||
screen_write_clearendofline(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx;
|
||||
struct screen *s = ctx->s;
|
||||
struct grid_line *gl;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
sx = screen_size_x(s);
|
||||
|
||||
if (s->cx <= sx - 1)
|
||||
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
||||
if (s->cx <= sx - 1 && s->cx < gl->cellsize) {
|
||||
screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
|
||||
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
|
||||
} else
|
||||
return;
|
||||
|
||||
tty_write(tty_cmd_clearendofline, &ttyctx);
|
||||
}
|
||||
@@ -719,16 +829,17 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx;
|
||||
u_int sx = screen_size_x(s);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
sx = screen_size_x(s);
|
||||
|
||||
if (s->cx > sx - 1)
|
||||
if (s->cx > sx - 1) {
|
||||
screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
|
||||
grid_view_clear(s->grid, 0, s->cy, sx, 1);
|
||||
else
|
||||
} else {
|
||||
screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
|
||||
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
|
||||
}
|
||||
|
||||
tty_write(tty_cmd_clearstartofline, &ttyctx);
|
||||
}
|
||||
@@ -755,11 +866,12 @@ screen_write_reverseindex(struct screen_write_ctx *ctx)
|
||||
struct screen *s = ctx->s;
|
||||
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) {
|
||||
screen_write_flush(ctx);
|
||||
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
|
||||
else if (s->cy > 0)
|
||||
} else if (s->cy > 0)
|
||||
s->cy--;
|
||||
|
||||
tty_write(tty_cmd_reverseindex, &ttyctx);
|
||||
@@ -794,8 +906,9 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
|
||||
struct screen *s = ctx->s;
|
||||
struct grid_line *gl;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
||||
if (wrapped)
|
||||
@@ -803,9 +916,11 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
|
||||
else
|
||||
gl->flags &= ~GRID_LINE_WRAPPED;
|
||||
|
||||
if (s->cy == s->rlower)
|
||||
if (s->cy == s->rlower) {
|
||||
screen_dirty_clear(s, 0, s->rupper, sx - 1, s->rupper);
|
||||
screen_write_flush(ctx);
|
||||
grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
|
||||
else if (s->cy < screen_size_y(s) - 1)
|
||||
} else if (s->cy < sy - 1)
|
||||
s->cy++;
|
||||
|
||||
ttyctx.num = wrapped;
|
||||
@@ -827,19 +942,20 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx, sy;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
|
||||
sx = screen_size_x(s);
|
||||
sy = screen_size_y(s);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
/* Scroll into history if it is enabled and clearing entire screen. */
|
||||
if (s->cy == 0 && s->grid->flags & GRID_HISTORY)
|
||||
if (s->cy == 0 && s->grid->flags & GRID_HISTORY) {
|
||||
screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
|
||||
grid_view_clear_history(s->grid);
|
||||
else {
|
||||
if (s->cx <= sx - 1)
|
||||
} else {
|
||||
if (s->cx <= sx - 1) {
|
||||
screen_dirty_clear(s, s->cx, s->cy, sx - 1, s->cy);
|
||||
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
|
||||
}
|
||||
screen_dirty_clear(s, 0, s->cy + 1, sx - 1, sy - 1);
|
||||
grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
|
||||
}
|
||||
|
||||
@@ -852,18 +968,21 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx;
|
||||
u_int sx = screen_size_x(s);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
sx = screen_size_x(s);
|
||||
|
||||
if (s->cy > 0)
|
||||
if (s->cy > 0) {
|
||||
screen_dirty_clear(s, 0, 0, sx - 1, s->cy);
|
||||
grid_view_clear(s->grid, 0, 0, sx, s->cy);
|
||||
if (s->cx > sx - 1)
|
||||
}
|
||||
if (s->cx > sx - 1) {
|
||||
screen_dirty_clear(s, 0, s->cy, sx - 1, s->cy);
|
||||
grid_view_clear(s->grid, 0, s->cy, sx, 1);
|
||||
else
|
||||
} else {
|
||||
screen_dirty_clear(s, 0, s->cy, s->cx, s->cy);
|
||||
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
|
||||
}
|
||||
|
||||
tty_write(tty_cmd_clearstartofscreen, &ttyctx);
|
||||
}
|
||||
@@ -874,10 +993,11 @@ screen_write_clearscreen(struct screen_write_ctx *ctx)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s);
|
||||
u_int sy = screen_size_y(s);
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
screen_dirty_clear(s, 0, 0, sx - 1, sy - 1);
|
||||
|
||||
/* Scroll into history if it is enabled. */
|
||||
if (s->grid->flags & GRID_HISTORY)
|
||||
@@ -896,7 +1016,7 @@ screen_write_clearhistory(struct screen_write_ctx *ctx)
|
||||
struct grid *gd = s->grid;
|
||||
|
||||
grid_move_lines(gd, 0, gd->hsize, gd->sy);
|
||||
gd->hsize = 0;
|
||||
gd->hscrolled = gd->hsize = 0;
|
||||
}
|
||||
|
||||
/* Write cell data. */
|
||||
@@ -907,8 +1027,13 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
struct grid *gd = s->grid;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int width, xx, last;
|
||||
struct grid_cell tmp_gc;
|
||||
int insert;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
struct grid_line *gl;
|
||||
struct grid_cell tmp_gc, now_gc;
|
||||
struct grid_cell_entry *gce;
|
||||
int insert, skip, selected, wrapped = 0;
|
||||
|
||||
ctx->cells++;
|
||||
|
||||
/* Ignore padding. */
|
||||
if (gc->flags & GRID_FLAG_PADDING)
|
||||
@@ -919,10 +1044,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
* If this is a wide character and there is no room on the screen, for
|
||||
* the entire character, don't print it.
|
||||
*/
|
||||
if (!(s->mode & MODE_WRAP)
|
||||
&& (width > 1 && (width > screen_size_x(s) ||
|
||||
(s->cx != screen_size_x(s)
|
||||
&& s->cx > screen_size_x(s) - width))))
|
||||
if (!(s->mode & MODE_WRAP) && (width > 1 &&
|
||||
(width > sx || (s->cx != sx && s->cx > sx - width))))
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -931,84 +1054,149 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
*/
|
||||
if (width == 0) {
|
||||
if (screen_write_combine(ctx, &gc->data) == 0) {
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
tty_write(tty_cmd_utf8character, &ttyctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialise the redraw context, saving the last cell. */
|
||||
screen_write_initctx(ctx, &ttyctx, 1);
|
||||
/* Initialise the redraw context. */
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
/* If in insert mode, make space for the cells. */
|
||||
if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) {
|
||||
xx = screen_size_x(s) - s->cx - width;
|
||||
if ((s->mode & MODE_INSERT) && s->cx <= sx - width) {
|
||||
xx = sx - s->cx - width;
|
||||
grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx);
|
||||
insert = 1;
|
||||
} else
|
||||
insert = 0;
|
||||
skip = !insert;
|
||||
|
||||
/* Check this will fit on the current line and wrap if not. */
|
||||
if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) {
|
||||
if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
|
||||
screen_write_flush(ctx);
|
||||
screen_write_save_last(ctx, &ttyctx);
|
||||
screen_write_linefeed(ctx, 1);
|
||||
s->cx = 0; /* carriage return */
|
||||
skip = 0;
|
||||
wrapped = 1;
|
||||
}
|
||||
|
||||
/* Sanity check cursor position. */
|
||||
if (s->cx > screen_size_x(s) - width || s->cy > screen_size_y(s) - 1)
|
||||
if (s->cx > sx - width || s->cy > sy - 1)
|
||||
return;
|
||||
|
||||
/* Handle overwriting of UTF-8 characters. */
|
||||
screen_write_overwrite(ctx, width);
|
||||
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
||||
if (gl->flags & GRID_LINE_EXTENDED) {
|
||||
grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
|
||||
if (screen_write_overwrite(ctx, &now_gc, width))
|
||||
skip = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the new character is UTF-8 wide, fill in padding cells. Have
|
||||
* already ensured there is enough room.
|
||||
*/
|
||||
memcpy(&tmp_gc, &grid_default_cell, sizeof tmp_gc);
|
||||
tmp_gc.flags |= GRID_FLAG_PADDING;
|
||||
tmp_gc.data.width = 0;
|
||||
for (xx = s->cx + 1; xx < s->cx + width; xx++)
|
||||
grid_view_set_cell(gd, xx, s->cy, &tmp_gc);
|
||||
for (xx = s->cx + 1; xx < s->cx + width; xx++) {
|
||||
grid_view_set_cell(gd, xx, s->cy, &screen_write_pad_cell);
|
||||
skip = 0;
|
||||
}
|
||||
|
||||
/* Set the cell. */
|
||||
grid_view_set_cell(gd, s->cx, s->cy, gc);
|
||||
/* If no change, do not draw. */
|
||||
if (skip) {
|
||||
if (s->cx >= gl->cellsize)
|
||||
skip = grid_cells_equal(gc, &grid_default_cell);
|
||||
else {
|
||||
gce = &gl->celldata[s->cx];
|
||||
if (gce->flags & GRID_FLAG_EXTENDED)
|
||||
skip = 0;
|
||||
else if (gc->flags != (gce->flags & ~GRID_FLAG_EXTENDED))
|
||||
skip = 0;
|
||||
else if (gc->attr != gce->data.attr)
|
||||
skip = 0;
|
||||
else if (gc->fg != gce->data.fg)
|
||||
skip = 0;
|
||||
else if (gc->bg != gce->data.bg)
|
||||
skip = 0;
|
||||
else if (gc->data.width != 1 || gce->data.data != gc->data.data[0])
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the selection the flag and set the cell. */
|
||||
selected = screen_check_selection(s, s->cx, s->cy);
|
||||
if (selected && ~gc->flags & GRID_FLAG_SELECTED) {
|
||||
skip = 0;
|
||||
memcpy(&tmp_gc, gc, sizeof tmp_gc);
|
||||
tmp_gc.flags |= GRID_FLAG_SELECTED;
|
||||
grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
|
||||
} else if (!selected && gc->flags & GRID_FLAG_SELECTED) {
|
||||
skip = 0;
|
||||
memcpy(&tmp_gc, gc, sizeof tmp_gc);
|
||||
tmp_gc.flags &= ~GRID_FLAG_SELECTED;
|
||||
grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
|
||||
} else if (!skip)
|
||||
grid_view_set_cell(gd, s->cx, s->cy, gc);
|
||||
|
||||
/*
|
||||
* Move the cursor. If not wrapping, stick at the last character and
|
||||
* replace it.
|
||||
*/
|
||||
last = !(s->mode & MODE_WRAP);
|
||||
if (s->cx <= screen_size_x(s) - last - width)
|
||||
if (s->cx <= sx - last - width)
|
||||
s->cx += width;
|
||||
else
|
||||
s->cx = screen_size_x(s) - last;
|
||||
s->cx = sx - last;
|
||||
|
||||
/* Draw to the screen if necessary. */
|
||||
/* Create space for character in insert mode. */
|
||||
if (insert) {
|
||||
if (!wrapped)
|
||||
screen_write_flush(ctx);
|
||||
ttyctx.num = width;
|
||||
tty_write(tty_cmd_insertcharacter, &ttyctx);
|
||||
}
|
||||
if (screen_check_selection(s, s->cx - width, s->cy)) {
|
||||
|
||||
/* Write to the screen. */
|
||||
if (selected) {
|
||||
memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
|
||||
utf8_copy(&tmp_gc.data, &gc->data);
|
||||
tmp_gc.attr = tmp_gc.attr & ~GRID_ATTR_CHARSET;
|
||||
tmp_gc.attr |= gc->attr & GRID_ATTR_CHARSET;
|
||||
tmp_gc.flags = gc->flags;
|
||||
tmp_gc.flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_BGRGB);
|
||||
tmp_gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||
tmp_gc.flags |= s->sel.cell.flags &
|
||||
(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||
screen_write_flush(ctx);
|
||||
ttyctx.cell = &tmp_gc;
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
} else {
|
||||
ttyctx.cell = gc;
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
}
|
||||
ctx->written++;
|
||||
} else if (!skip) {
|
||||
if (wrapped) {
|
||||
ttyctx.cell = gc;
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
ctx->written++;
|
||||
} else {
|
||||
/*
|
||||
* If wp is NULL, we are not updating the terminal and
|
||||
* don't care about actually writing the cells
|
||||
* (tty_write will just return). So don't even bother
|
||||
* allocating the dirty array.
|
||||
*/
|
||||
if (ctx->wp != NULL && s->dirty == NULL) {
|
||||
log_debug("%s: allocating %u bits", __func__,
|
||||
s->dirtysize);
|
||||
s->dirty = bit_alloc(s->dirtysize);
|
||||
}
|
||||
if (s->dirty != NULL) {
|
||||
bit_set(s->dirty, screen_dirty_bit(s,
|
||||
ttyctx.ocx, ttyctx.ocy));
|
||||
ctx->dirty++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
ctx->skipped++;
|
||||
}
|
||||
|
||||
/* Combine a UTF-8 zero-width character onto the previous. */
|
||||
int
|
||||
static int
|
||||
screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
@@ -1049,16 +1237,17 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud)
|
||||
* character, it is necessary to also overwrite any other cells which covered
|
||||
* by the same character.
|
||||
*/
|
||||
void
|
||||
screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
|
||||
static int
|
||||
screen_write_overwrite(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
||||
u_int width)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
struct grid_cell gc;
|
||||
struct grid_cell tmp_gc;
|
||||
u_int xx;
|
||||
int done = 0;
|
||||
|
||||
grid_view_get_cell(gd, s->cx, s->cy, &gc);
|
||||
if (gc.flags & GRID_FLAG_PADDING) {
|
||||
if (gc->flags & GRID_FLAG_PADDING) {
|
||||
/*
|
||||
* A padding cell, so clear any following and leading padding
|
||||
* cells back to the character. Don't overwrite the current
|
||||
@@ -1066,27 +1255,33 @@ screen_write_overwrite(struct screen_write_ctx *ctx, u_int width)
|
||||
*/
|
||||
xx = s->cx + 1;
|
||||
while (--xx > 0) {
|
||||
grid_view_get_cell(gd, xx, s->cy, &gc);
|
||||
if (~gc.flags & GRID_FLAG_PADDING)
|
||||
grid_view_get_cell(gd, xx, s->cy, &tmp_gc);
|
||||
if (~tmp_gc.flags & GRID_FLAG_PADDING)
|
||||
break;
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
}
|
||||
|
||||
/* Overwrite the character at the start of this padding. */
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
done = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overwrite any padding cells that belong to a UTF-8 character
|
||||
* we'll be overwriting with the current character.
|
||||
* Overwrite any padding cells that belong to any UTF-8 characters we'll be
|
||||
* overwriting with the current character.
|
||||
*/
|
||||
xx = s->cx + width - 1;
|
||||
while (++xx < screen_size_x(s)) {
|
||||
grid_view_get_cell(gd, xx, s->cy, &gc);
|
||||
if (~gc.flags & GRID_FLAG_PADDING)
|
||||
break;
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
if (width != 1 || gc->data.width != 1 || gc->flags & GRID_FLAG_PADDING) {
|
||||
xx = s->cx + width - 1;
|
||||
while (++xx < screen_size_x(s)) {
|
||||
grid_view_get_cell(gd, xx, s->cy, &tmp_gc);
|
||||
if (~tmp_gc.flags & GRID_FLAG_PADDING)
|
||||
break;
|
||||
grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (done);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1094,7 +1289,7 @@ screen_write_setselection(struct screen_write_ctx *ctx, u_char *str, u_int len)
|
||||
{
|
||||
struct tty_ctx ttyctx;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
ttyctx.ptr = str;
|
||||
ttyctx.num = len;
|
||||
|
||||
@@ -1104,9 +1299,9 @@ screen_write_setselection(struct screen_write_ctx *ctx, u_char *str, u_int len)
|
||||
void
|
||||
screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len)
|
||||
{
|
||||
struct tty_ctx ttyctx;
|
||||
struct tty_ctx ttyctx;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
ttyctx.ptr = str;
|
||||
ttyctx.num = len;
|
||||
|
||||
|
||||
21
screen.c
21
screen.c
@@ -38,6 +38,9 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
||||
s->ccolour = xstrdup("");
|
||||
s->tabs = NULL;
|
||||
|
||||
s->dirty = NULL;
|
||||
s->dirtysize = 0;
|
||||
|
||||
screen_reinit(s);
|
||||
}
|
||||
|
||||
@@ -64,6 +67,7 @@ screen_reinit(struct screen *s)
|
||||
void
|
||||
screen_free(struct screen *s)
|
||||
{
|
||||
free(s->dirty);
|
||||
free(s->tabs);
|
||||
free(s->title);
|
||||
free(s->ccolour);
|
||||
@@ -146,7 +150,7 @@ screen_resize_x(struct screen *s, u_int sx)
|
||||
/*
|
||||
* Treat resizing horizontally simply: just ensure the cursor is
|
||||
* on-screen and change the size. Don't bother to truncate any lines -
|
||||
* then the data should be accessible if the size is then incrased.
|
||||
* then the data should be accessible if the size is then increased.
|
||||
*
|
||||
* The only potential wrinkle is if UTF-8 double-width characters are
|
||||
* left in the last column, but UTF-8 terminals should deal with this
|
||||
@@ -173,8 +177,9 @@ screen_resize_y(struct screen *s, u_int sy)
|
||||
* If the height is decreasing, delete lines from the bottom until
|
||||
* hitting the cursor, then push lines from the top into the history.
|
||||
*
|
||||
* When increasing, pull as many lines as possible from the history to
|
||||
* the top, then fill the remaining with blanks at the bottom.
|
||||
* When increasing, pull as many lines as possible from scrolled
|
||||
* history (not explicitly cleared from view) to the top, then fill the
|
||||
* remaining with blanks at the bottom.
|
||||
*/
|
||||
|
||||
/* Size decreasing. */
|
||||
@@ -196,9 +201,10 @@ screen_resize_y(struct screen *s, u_int sy)
|
||||
* lines from the top.
|
||||
*/
|
||||
available = s->cy;
|
||||
if (gd->flags & GRID_HISTORY)
|
||||
if (gd->flags & GRID_HISTORY) {
|
||||
gd->hscrolled += needed;
|
||||
gd->hsize += needed;
|
||||
else if (needed > 0 && available > 0) {
|
||||
} else if (needed > 0 && available > 0) {
|
||||
if (available > needed)
|
||||
available = needed;
|
||||
grid_view_delete_lines(gd, 0, available);
|
||||
@@ -215,13 +221,14 @@ screen_resize_y(struct screen *s, u_int sy)
|
||||
needed = sy - oldy;
|
||||
|
||||
/*
|
||||
* Try to pull as much as possible out of the history, if is
|
||||
* Try to pull as much as possible out of scrolled history, if is
|
||||
* is enabled.
|
||||
*/
|
||||
available = gd->hsize;
|
||||
available = gd->hscrolled;
|
||||
if (gd->flags & GRID_HISTORY && available > 0) {
|
||||
if (available > needed)
|
||||
available = needed;
|
||||
gd->hscrolled -= available;
|
||||
gd->hsize -= available;
|
||||
s->cy += available;
|
||||
} else
|
||||
|
||||
@@ -182,6 +182,7 @@ server_client_lost(struct client *c)
|
||||
|
||||
c->flags |= CLIENT_DEAD;
|
||||
|
||||
server_clear_identify(c, NULL);
|
||||
status_prompt_clear(c);
|
||||
status_message_clear(c);
|
||||
|
||||
@@ -604,16 +605,16 @@ server_client_handle_key(struct client *c, key_code key)
|
||||
return;
|
||||
window_unzoom(w);
|
||||
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);
|
||||
if (wp != NULL && !window_pane_visible(wp))
|
||||
wp = NULL;
|
||||
server_clear_identify(c, wp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle status line. */
|
||||
if (!(c->flags & CLIENT_READONLY)) {
|
||||
status_message_clear(c);
|
||||
server_clear_identify(c);
|
||||
server_clear_identify(c, NULL);
|
||||
}
|
||||
if (c->prompt_string != NULL) {
|
||||
if (!(c->flags & CLIENT_READONLY))
|
||||
@@ -762,11 +763,13 @@ server_client_loop(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if pane should be resized. */
|
||||
void
|
||||
server_client_check_resize(struct window_pane *wp)
|
||||
static void
|
||||
server_client_resize_event(__unused int fd, __unused short events, void *data)
|
||||
{
|
||||
struct winsize ws;
|
||||
struct window_pane *wp = data;
|
||||
struct winsize ws;
|
||||
|
||||
evtimer_del(&wp->resize_timer);
|
||||
|
||||
if (!(wp->flags & PANE_RESIZE))
|
||||
return;
|
||||
@@ -791,6 +794,36 @@ server_client_check_resize(struct window_pane *wp)
|
||||
wp->flags &= ~PANE_RESIZE;
|
||||
}
|
||||
|
||||
/* Check if pane should be resized. */
|
||||
void
|
||||
server_client_check_resize(struct window_pane *wp)
|
||||
{
|
||||
struct timeval tv = { .tv_usec = 250000 };
|
||||
|
||||
if (!(wp->flags & PANE_RESIZE))
|
||||
return;
|
||||
|
||||
if (!event_initialized(&wp->resize_timer))
|
||||
evtimer_set(&wp->resize_timer, server_client_resize_event, wp);
|
||||
|
||||
/*
|
||||
* The first resize should happen immediately, so if the timer is not
|
||||
* running, do it now.
|
||||
*/
|
||||
if (!evtimer_pending(&wp->resize_timer, NULL))
|
||||
server_client_resize_event(-1, 0, wp);
|
||||
|
||||
/*
|
||||
* If the pane is in the alternate screen, let the timer expire and
|
||||
* resize to give the application a chance to redraw. If not, keep
|
||||
* pushing the timer back.
|
||||
*/
|
||||
if (wp->saved_grid != NULL && evtimer_pending(&wp->resize_timer, NULL))
|
||||
return;
|
||||
evtimer_del(&wp->resize_timer);
|
||||
evtimer_add(&wp->resize_timer, &tv);
|
||||
}
|
||||
|
||||
/* Check whether pane should be focused. */
|
||||
void
|
||||
server_client_check_focus(struct window_pane *wp)
|
||||
@@ -862,10 +895,7 @@ server_client_reset_state(struct client *c)
|
||||
struct options *oo = c->session->options;
|
||||
int status, mode, o;
|
||||
|
||||
if (c->flags & CLIENT_SUSPENDED)
|
||||
return;
|
||||
|
||||
if (c->flags & CLIENT_CONTROL)
|
||||
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
|
||||
return;
|
||||
|
||||
tty_region(&c->tty, 0, c->tty.sy - 1);
|
||||
@@ -929,7 +959,7 @@ server_client_check_redraw(struct client *c)
|
||||
struct session *s = c->session;
|
||||
struct tty *tty = &c->tty;
|
||||
struct window_pane *wp;
|
||||
int flags, redraw;
|
||||
int flags, masked, redraw;
|
||||
|
||||
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
|
||||
return;
|
||||
@@ -969,15 +999,15 @@ server_client_check_redraw(struct client *c)
|
||||
}
|
||||
}
|
||||
|
||||
if (c->flags & CLIENT_BORDERS) {
|
||||
masked = c->flags & (CLIENT_BORDERS|CLIENT_STATUS);
|
||||
if (masked != 0)
|
||||
tty_update_mode(tty, tty->mode, NULL);
|
||||
if (masked == CLIENT_BORDERS)
|
||||
screen_redraw_screen(c, 0, 0, 1);
|
||||
}
|
||||
|
||||
if (c->flags & CLIENT_STATUS) {
|
||||
tty_update_mode(tty, tty->mode, NULL);
|
||||
else if (masked == CLIENT_STATUS)
|
||||
screen_redraw_screen(c, 0, 1, 0);
|
||||
}
|
||||
else if (masked != 0)
|
||||
screen_redraw_screen(c, 0, 1, 1);
|
||||
|
||||
tty->flags = (tty->flags & ~(TTY_FREEZE|TTY_NOCURSOR)) | flags;
|
||||
tty_update_mode(tty, tty->mode, NULL);
|
||||
@@ -1098,12 +1128,13 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
|
||||
if (gettimeofday(&c->activity_time, NULL) != 0)
|
||||
fatal("gettimeofday failed");
|
||||
if (s != NULL)
|
||||
session_update_activity(s, &c->activity_time);
|
||||
|
||||
tty_start_tty(&c->tty);
|
||||
server_redraw_client(c);
|
||||
recalculate_sizes();
|
||||
|
||||
if (s != NULL)
|
||||
session_update_activity(s, &c->activity_time);
|
||||
break;
|
||||
case MSG_SHELL:
|
||||
if (datalen != 0)
|
||||
|
||||
20
server-fn.c
20
server-fn.c
@@ -442,21 +442,23 @@ server_set_identify(struct client *c)
|
||||
}
|
||||
|
||||
void
|
||||
server_clear_identify(struct client *c)
|
||||
server_clear_identify(struct client *c, struct window_pane *wp)
|
||||
{
|
||||
if (c->flags & CLIENT_IDENTIFY) {
|
||||
c->flags &= ~CLIENT_IDENTIFY;
|
||||
c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
if (~c->flags & CLIENT_IDENTIFY)
|
||||
return;
|
||||
c->flags &= ~CLIENT_IDENTIFY;
|
||||
|
||||
if (c->identify_callback != NULL)
|
||||
c->identify_callback(c, wp);
|
||||
|
||||
c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
|
||||
void
|
||||
server_callback_identify(__unused int fd, __unused short events, void *data)
|
||||
{
|
||||
struct client *c = data;
|
||||
|
||||
server_clear_identify(c);
|
||||
server_clear_identify(data, NULL);
|
||||
}
|
||||
|
||||
/* Set stdin callback. */
|
||||
|
||||
2
server.c
2
server.c
@@ -260,7 +260,7 @@ server_update_socket(void)
|
||||
|
||||
if (stat(socket_path, &sb) != 0)
|
||||
return;
|
||||
mode = sb.st_mode;
|
||||
mode = sb.st_mode & ACCESSPERMS;
|
||||
if (n != 0) {
|
||||
if (mode & S_IRUSR)
|
||||
mode |= S_IXUSR;
|
||||
|
||||
15
status.c
15
status.c
@@ -257,16 +257,19 @@ status_get_window_at(struct client *c, u_int x)
|
||||
struct session *s = c->session;
|
||||
struct winlink *wl;
|
||||
struct options *oo;
|
||||
size_t len;
|
||||
const char *sep;
|
||||
size_t seplen;
|
||||
|
||||
x += c->wlmouse;
|
||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||
oo = wl->window->options;
|
||||
len = strlen(options_get_string(oo, "window-status-separator"));
|
||||
|
||||
sep = options_get_string(oo, "window-status-separator");
|
||||
seplen = screen_write_cstrlen("%s", sep);
|
||||
|
||||
if (x < wl->status_width)
|
||||
return (wl->window);
|
||||
x -= wl->status_width + len;
|
||||
x -= wl->status_width + seplen;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
@@ -344,7 +347,7 @@ status_redraw(struct client *c)
|
||||
|
||||
oo = wl->window->options;
|
||||
sep = options_get_string(oo, "window-status-separator");
|
||||
seplen = screen_write_strlen("%s", sep);
|
||||
seplen = screen_write_cstrlen("%s", sep);
|
||||
wlwidth += wl->status_width + seplen;
|
||||
}
|
||||
|
||||
@@ -359,7 +362,7 @@ status_redraw(struct client *c)
|
||||
|
||||
oo = wl->window->options;
|
||||
sep = options_get_string(oo, "window-status-separator");
|
||||
screen_write_nputs(&ctx, -1, &stdgc, "%s", sep);
|
||||
screen_write_cnputs(&ctx, -1, &stdgc, "%s", sep);
|
||||
}
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
@@ -815,7 +818,7 @@ status_prompt_key(struct client *c, key_code key)
|
||||
size_t size, n, off, idx, bufsize;
|
||||
|
||||
size = strlen(c->prompt_buffer);
|
||||
switch (mode_key_lookup(&c->prompt_mdata, key, NULL)) {
|
||||
switch (mode_key_lookup(&c->prompt_mdata, key, NULL, NULL)) {
|
||||
case MODEKEYEDIT_CURSORLEFT:
|
||||
if (c->prompt_index > 0) {
|
||||
c->prompt_index--;
|
||||
|
||||
105
style.c
105
style.c
@@ -33,7 +33,8 @@ style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
|
||||
char tmp[32];
|
||||
int val;
|
||||
size_t end;
|
||||
u_char fg, bg, attr, flags;
|
||||
int fg, bg;
|
||||
u_char attr, flags;
|
||||
|
||||
if (*in == '\0')
|
||||
return (0);
|
||||
@@ -56,38 +57,20 @@ style_parse(const struct grid_cell *defgc, struct grid_cell *gc,
|
||||
fg = defgc->fg;
|
||||
bg = defgc->bg;
|
||||
attr = defgc->attr;
|
||||
flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||
flags |=
|
||||
defgc->flags & (GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||
flags = defgc->flags;
|
||||
} else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
|
||||
if ((val = colour_fromstring(tmp + 3)) == -1)
|
||||
goto error;
|
||||
if (*in == 'f' || *in == 'F') {
|
||||
if (val != 8) {
|
||||
if (val & 0x100) {
|
||||
flags |= GRID_FLAG_FG256;
|
||||
val &= ~0x100;
|
||||
} else
|
||||
flags &= ~GRID_FLAG_FG256;
|
||||
if (val != 8)
|
||||
fg = val;
|
||||
} else {
|
||||
else
|
||||
fg = defgc->fg;
|
||||
flags &= ~GRID_FLAG_FG256;
|
||||
flags |= defgc->flags & GRID_FLAG_FG256;
|
||||
}
|
||||
} else if (*in == 'b' || *in == 'B') {
|
||||
if (val != 8) {
|
||||
if (val & 0x100) {
|
||||
flags |= GRID_FLAG_BG256;
|
||||
val &= ~0x100;
|
||||
} else
|
||||
flags &= ~GRID_FLAG_BG256;
|
||||
if (val != 8)
|
||||
bg = val;
|
||||
} else {
|
||||
else
|
||||
bg = defgc->bg;
|
||||
flags &= ~GRID_FLAG_BG256;
|
||||
flags |= defgc->flags & GRID_FLAG_BG256;
|
||||
}
|
||||
} else
|
||||
goto error;
|
||||
} else if (strcasecmp(tmp, "none") == 0)
|
||||
@@ -120,27 +103,19 @@ error:
|
||||
const char *
|
||||
style_tostring(struct grid_cell *gc)
|
||||
{
|
||||
int c, off = 0, comma = 0;
|
||||
int off = 0, comma = 0;
|
||||
static char s[256];
|
||||
|
||||
*s = '\0';
|
||||
|
||||
if (gc->fg != 8 || gc->flags & GRID_FLAG_FG256) {
|
||||
if (gc->flags & GRID_FLAG_FG256)
|
||||
c = gc->fg | 0x100;
|
||||
else
|
||||
c = gc->fg;
|
||||
off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(c));
|
||||
if (gc->fg != 8) {
|
||||
off += xsnprintf(s, sizeof s, "fg=%s", colour_tostring(gc->fg));
|
||||
comma = 1;
|
||||
}
|
||||
|
||||
if (gc->bg != 8 || gc->flags & GRID_FLAG_BG256) {
|
||||
if (gc->flags & GRID_FLAG_BG256)
|
||||
c = gc->bg | 0x100;
|
||||
else
|
||||
c = gc->bg;
|
||||
if (gc->bg != 8) {
|
||||
off += xsnprintf(s + off, sizeof s - off, "%sbg=%s",
|
||||
comma ? "," : "", colour_tostring(c));
|
||||
comma ? "," : "", colour_tostring(gc->bg));
|
||||
comma = 1;
|
||||
}
|
||||
|
||||
@@ -177,9 +152,9 @@ style_update_new(struct options *oo, const char *name, const char *newname)
|
||||
value = o->num;
|
||||
|
||||
if (strstr(name, "-bg") != NULL)
|
||||
colour_set_bg(gc, value);
|
||||
gc->bg = value;
|
||||
else if (strstr(name, "-fg") != NULL)
|
||||
colour_set_fg(gc, value);
|
||||
gc->fg = value;
|
||||
else if (strstr(name, "-attr") != NULL)
|
||||
gc->attr = value;
|
||||
}
|
||||
@@ -189,23 +164,15 @@ void
|
||||
style_update_old(struct options *oo, const char *name, struct grid_cell *gc)
|
||||
{
|
||||
char newname[128];
|
||||
int c, size;
|
||||
int size;
|
||||
|
||||
size = strrchr(name, '-') - name;
|
||||
|
||||
if (gc->flags & GRID_FLAG_BG256)
|
||||
c = gc->bg | 0x100;
|
||||
else
|
||||
c = gc->bg;
|
||||
xsnprintf(newname, sizeof newname, "%.*s-bg", size, name);
|
||||
options_set_number(oo, newname, c);
|
||||
options_set_number(oo, newname, gc->bg);
|
||||
|
||||
if (gc->flags & GRID_FLAG_FG256)
|
||||
c = gc->fg | 0x100;
|
||||
else
|
||||
c = gc->fg;
|
||||
xsnprintf(newname, sizeof newname, "%.*s-fg", size, name);
|
||||
options_set_number(oo, newname, c);
|
||||
options_set_number(oo, newname, gc->fg);
|
||||
|
||||
xsnprintf(newname, sizeof newname, "%.*s-attr", size, name);
|
||||
options_set_number(oo, newname, gc->attr);
|
||||
@@ -219,14 +186,8 @@ style_apply(struct grid_cell *gc, struct options *oo, const char *name)
|
||||
|
||||
memcpy(gc, &grid_default_cell, sizeof *gc);
|
||||
gcp = options_get_style(oo, name);
|
||||
if (gcp->flags & GRID_FLAG_FG256)
|
||||
colour_set_fg(gc, gcp->fg | 0x100);
|
||||
else
|
||||
colour_set_fg(gc, gcp->fg);
|
||||
if (gcp->flags & GRID_FLAG_BG256)
|
||||
colour_set_bg(gc, gcp->bg | 0x100);
|
||||
else
|
||||
colour_set_bg(gc, gcp->bg);
|
||||
gc->fg = gcp->fg;
|
||||
gc->bg = gcp->bg;
|
||||
gc->attr |= gcp->attr;
|
||||
}
|
||||
|
||||
@@ -237,18 +198,10 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
|
||||
struct grid_cell *gcp;
|
||||
|
||||
gcp = options_get_style(oo, name);
|
||||
if (gcp->fg != 8 || gcp->flags & GRID_FLAG_FG256) {
|
||||
if (gcp->flags & GRID_FLAG_FG256)
|
||||
colour_set_fg(gc, gcp->fg | 0x100);
|
||||
else
|
||||
colour_set_fg(gc, gcp->fg);
|
||||
}
|
||||
if (gcp->bg != 8 || gcp->flags & GRID_FLAG_BG256) {
|
||||
if (gcp->flags & GRID_FLAG_BG256)
|
||||
colour_set_bg(gc, gcp->bg | 0x100);
|
||||
else
|
||||
colour_set_bg(gc, gcp->bg);
|
||||
}
|
||||
if (gcp->fg != 8)
|
||||
gc->fg = gcp->fg;
|
||||
if (gcp->bg != 8)
|
||||
gc->bg = gcp->bg;
|
||||
if (gcp->attr != 0)
|
||||
gc->attr |= gcp->attr;
|
||||
}
|
||||
@@ -257,10 +210,10 @@ style_apply_update(struct grid_cell *gc, struct options *oo, const char *name)
|
||||
int
|
||||
style_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
|
||||
{
|
||||
return gc1->fg == gc2->fg &&
|
||||
gc1->bg == gc2->bg &&
|
||||
(gc1->flags & ~GRID_FLAG_PADDING) ==
|
||||
(gc2->flags & ~GRID_FLAG_PADDING) &&
|
||||
(gc1->attr & ~GRID_ATTR_CHARSET) ==
|
||||
(gc2->attr & ~GRID_ATTR_CHARSET);
|
||||
return (gc1->fg == gc2->fg &&
|
||||
gc1->bg == gc2->bg &&
|
||||
(gc1->flags & ~GRID_FLAG_PADDING) ==
|
||||
(gc2->flags & ~GRID_FLAG_PADDING) &&
|
||||
(gc1->attr & ~GRID_ATTR_CHARSET) ==
|
||||
(gc2->attr & ~GRID_ATTR_CHARSET));
|
||||
}
|
||||
|
||||
121
tmux.1
121
tmux.1
@@ -777,7 +777,9 @@ section.
|
||||
If
|
||||
.Ar target-session
|
||||
is specified, list only clients connected to that session.
|
||||
.It Ic list-commands
|
||||
.It Xo Ic list-commands
|
||||
.Op Fl F Ar format
|
||||
.Xc
|
||||
.D1 (alias: Ic lscm )
|
||||
List the syntax of all commands supported by
|
||||
.Nm .
|
||||
@@ -917,10 +919,18 @@ display the log for
|
||||
and
|
||||
.Fl T
|
||||
show debugging information about jobs and terminals.
|
||||
.It Ic source-file Ar path
|
||||
.It Xo Ic source-file
|
||||
.Op Fl q
|
||||
.Ar path
|
||||
.Xc
|
||||
.D1 (alias: Ic source )
|
||||
Execute commands from
|
||||
.Ar path .
|
||||
If
|
||||
.Fl q
|
||||
is given, no error will be returned if
|
||||
.Ar path
|
||||
does not exist.
|
||||
.It Ic start-server
|
||||
.D1 (alias: Ic start )
|
||||
Start the
|
||||
@@ -981,7 +991,7 @@ bind-key -Troot a switch-client -Ttable1
|
||||
.Sh WINDOWS AND PANES
|
||||
A
|
||||
.Nm
|
||||
window may be in one of several modes.
|
||||
window may be in one of two modes.
|
||||
The default permits direct access to the terminal attached to the window.
|
||||
The other is copy mode, which permits a section of a window or its
|
||||
history to be copied to a
|
||||
@@ -1029,6 +1039,7 @@ The following keys are supported as appropriate for the mode:
|
||||
.It Li "Jump to backward" Ta "T" Ta ""
|
||||
.It Li "Jump to forward" Ta "t" Ta ""
|
||||
.It Li "Next page" Ta "C-f" Ta "Page down"
|
||||
.It Li "Next paragraph" Ta "}" Ta "M-}"
|
||||
.It Li "Next space" Ta "W" Ta ""
|
||||
.It Li "Next space, end of word" Ta "E" Ta ""
|
||||
.It Li "Next word" Ta "w" Ta ""
|
||||
@@ -1036,6 +1047,7 @@ The following keys are supported as appropriate for the mode:
|
||||
.It Li "Other end of selection" Ta "o" Ta ""
|
||||
.It Li "Paste buffer" Ta "p" Ta "C-y"
|
||||
.It Li "Previous page" Ta "C-b" Ta "Page up"
|
||||
.It Li "Previous paragraph" Ta "{" Ta "M-{"
|
||||
.It Li "Previous space" Ta "B" Ta ""
|
||||
.It Li "Previous word" Ta "b" Ta "M-b"
|
||||
.It Li "Quit mode" Ta "q" Ta "Escape"
|
||||
@@ -1450,7 +1462,11 @@ flag, see the
|
||||
.Sx FORMATS
|
||||
section.
|
||||
This command works only if at least one client is attached.
|
||||
.It Ic display-panes Op Fl t Ar target-client
|
||||
.It Xo
|
||||
.Ic display-panes
|
||||
.Op Fl t Ar target-client
|
||||
.Op Ar template
|
||||
.Xc
|
||||
.D1 (alias: Ic displayp )
|
||||
Display a visible indicator of each pane shown by
|
||||
.Ar target-client .
|
||||
@@ -1460,11 +1476,18 @@ See the
|
||||
and
|
||||
.Ic display-panes-active-colour
|
||||
session options.
|
||||
While the indicator is on screen, a pane may be selected with the
|
||||
While the indicator is on screen, a pane may be chosen with the
|
||||
.Ql 0
|
||||
to
|
||||
.Ql 9
|
||||
keys.
|
||||
keys, which will cause
|
||||
.Ar template
|
||||
to be executed as a command with
|
||||
.Ql %%
|
||||
substituted by the pane ID.
|
||||
The default
|
||||
.Ar template
|
||||
is "select-pane -t '%%'".
|
||||
.It Xo Ic find-window
|
||||
.Op Fl CNT
|
||||
.Op Fl F Ar format
|
||||
@@ -1992,6 +2015,13 @@ The
|
||||
.Fl b
|
||||
option causes the new pane to be created to the left of or above
|
||||
.Ar target-pane .
|
||||
The
|
||||
.Fl f
|
||||
option creates a new pane spanning the full window height (with
|
||||
.Fl h )
|
||||
or full window width (with
|
||||
.Fl v ) ,
|
||||
instead of splitting the active pane.
|
||||
All other options have the same meaning as for the
|
||||
.Ic new-window
|
||||
command.
|
||||
@@ -2107,6 +2137,7 @@ Commands related to key bindings are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic bind-key
|
||||
.Op Fl cnr
|
||||
.Op Fl R Ar repeat-count
|
||||
.Op Fl t Ar mode-table
|
||||
.Op Fl T Ar key-table
|
||||
.Ar key Ar command Op Ar arguments
|
||||
@@ -2165,6 +2196,14 @@ is bound in
|
||||
the binding for command mode with
|
||||
.Fl c
|
||||
or for normal mode without.
|
||||
For keys in the
|
||||
.Em vi-copy
|
||||
or
|
||||
.Em emacs-copy
|
||||
tables,
|
||||
.Fl R
|
||||
specifies how many times the command should be repeated.
|
||||
.Pp
|
||||
See the
|
||||
.Sx WINDOWS AND PANES
|
||||
section and the
|
||||
@@ -2776,19 +2815,17 @@ will be passed through
|
||||
and formats (see
|
||||
.Sx FORMATS )
|
||||
will be expanded.
|
||||
It may also contain any of the following special character sequences:
|
||||
.Bl -column "Character pair" "Replaced with" -offset indent
|
||||
.It Sy "Character pair" Ta Sy "Replaced with"
|
||||
.It Li "#[attributes]" Ta "Colour or attribute change"
|
||||
.It Li "##" Ta "A literal" Ql #
|
||||
.El
|
||||
It may also contain the special character sequence #[] to change the colour
|
||||
or attributes, for example
|
||||
.Ql #[fg=red,bright]
|
||||
to set a bright red foreground.
|
||||
See the
|
||||
.Ic message-command-style
|
||||
option for a description of colours and attributes.
|
||||
.Pp
|
||||
For details on how the names and titles can be set see the
|
||||
.Sx "NAMES AND TITLES"
|
||||
section.
|
||||
For a list of allowed attributes see the
|
||||
.Ic message-command-style
|
||||
option.
|
||||
.Pp
|
||||
Examples are:
|
||||
.Bd -literal -offset indent
|
||||
@@ -3067,6 +3104,14 @@ Like
|
||||
.Ic base-index ,
|
||||
but set the starting index for pane numbers.
|
||||
.Pp
|
||||
.It Ic pane-border-format Ar format
|
||||
Set the text shown in pane border status lines.
|
||||
.Pp
|
||||
.It Xo Ic pane-border-status
|
||||
.Op Ic off | top | bottom
|
||||
.Xc
|
||||
Turn pane border status lines off or set their position.
|
||||
.Pp
|
||||
.It Ic pane-border-style Ar style
|
||||
Set the pane border style for panes aside from the active pane.
|
||||
For how to specify
|
||||
@@ -3223,9 +3268,35 @@ shows only the option value, not the name.
|
||||
.Nm
|
||||
allows commands to run on various triggers, called
|
||||
.Em hooks .
|
||||
Each hook has a
|
||||
.Em name .
|
||||
The following hooks are available:
|
||||
Each
|
||||
.Nm
|
||||
command has a
|
||||
.Em before
|
||||
hook and an
|
||||
.Em after
|
||||
hook and there are a number of hooks not associated with commands.
|
||||
.Pp
|
||||
A command's before hook is run before the command is executed and its after
|
||||
hook is run afterwards, except when the command is run as part of a hook
|
||||
itself.
|
||||
Before hooks are named using the
|
||||
.Ql before-
|
||||
prefix and after hooks the
|
||||
.Ql after-
|
||||
prefix.
|
||||
For example, the following command adds a hook to select the even-vertical
|
||||
layout after every
|
||||
.Ic split-window :
|
||||
.Bd -literal -offset indent
|
||||
set-hook after-split-window "selectl even-vertical"
|
||||
.Ed
|
||||
.Pp
|
||||
Or to write when each new window is created to a file:
|
||||
.Bd -literal -offset indent
|
||||
set-hook before-new-window 'run "date >>/tmp/log"'
|
||||
.Ed
|
||||
.Pp
|
||||
In addition, the following hooks are available:
|
||||
.Bl -tag -width "XXXXXXXXXXXXXXXX"
|
||||
.It alert-activity
|
||||
Run when a window has activity.
|
||||
@@ -3436,6 +3507,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "alternate_on" Ta "" Ta "If pane is in alternate screen"
|
||||
.It Li "alternate_saved_x" Ta "" Ta "Saved cursor X in alternate screen"
|
||||
.It Li "alternate_saved_y" Ta "" Ta "Saved cursor Y in alternate screen"
|
||||
.It Li "buffer_name" Ta "" Ta "Name of buffer"
|
||||
.It Li "buffer_sample" Ta "" Ta "Sample of start of buffer"
|
||||
.It Li "buffer_size" Ta "" Ta "Size of the specified buffer in bytes"
|
||||
.It Li "client_activity" Ta "" Ta "Integer time client last had activity"
|
||||
@@ -3452,7 +3524,11 @@ The following variables are available, where appropriate:
|
||||
.It Li "client_tty" Ta "" Ta "Pseudo terminal of client"
|
||||
.It Li "client_utf8" Ta "" Ta "1 if client supports utf8"
|
||||
.It Li "client_width" Ta "" Ta "Width of client"
|
||||
.It Li "command_hooked" Ta "" Ta "Name of command hooked, if any"
|
||||
.It Li "command_name" Ta "" Ta "Name of command in use, if any"
|
||||
.It Li "command_list_name" Ta "" Ta "Command name if listing commands"
|
||||
.It Li "command_list_alias" Ta "" Ta "Command alias if listing commands"
|
||||
.It Li "command_list_usage" Ta "" Ta "Command usage if listing commands"
|
||||
.It Li "cursor_flag" Ta "" Ta "Pane cursor flag"
|
||||
.It Li "cursor_x" Ta "" Ta "Cursor X position in pane"
|
||||
.It Li "cursor_y" Ta "" Ta "Cursor Y position in pane"
|
||||
@@ -3506,9 +3582,10 @@ The following variables are available, where appropriate:
|
||||
.It Li "session_name" Ta "#S" Ta "Name of session"
|
||||
.It Li "session_width" Ta "" Ta "Width of session"
|
||||
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
||||
.It Li "socket_path" Ta "" "Server socket path"
|
||||
.It Li "socket_path" Ta "" Ta "Server socket path"
|
||||
.It Li "start_time" Ta "" Ta "Server start time"
|
||||
.It Li "window_activity" Ta "" Ta "Integer time of window last activity"
|
||||
.It Li "window_activity_flag" Ta "" Ta "1 if window has activity"
|
||||
.It Li "window_active" Ta "" Ta "1 if window active"
|
||||
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
|
||||
.It Li "window_find_matches" Ta "" Ta "Matched data from the find-window"
|
||||
@@ -3744,9 +3821,7 @@ Before the command is executed, the first occurrence of the string
|
||||
.Ql %%
|
||||
and all occurrences of
|
||||
.Ql %1
|
||||
are replaced by the response to the first prompt, the second
|
||||
.Ql %%
|
||||
and all
|
||||
are replaced by the response to the first prompt, all
|
||||
.Ql %2
|
||||
are replaced with the response to the second prompt, and so on for further
|
||||
prompts.
|
||||
@@ -3819,7 +3894,7 @@ and so on.
|
||||
When the
|
||||
.Ic buffer-limit
|
||||
option is reached, the oldest automatically named buffer is deleted.
|
||||
Explicitly named are not subject to
|
||||
Explicitly named buffers are not subject to
|
||||
.Ic buffer-limit
|
||||
and may be deleted with
|
||||
.Ic delete-buffer
|
||||
|
||||
15
tmux.c
15
tmux.c
@@ -46,17 +46,13 @@ const char *socket_path;
|
||||
__dead void usage(void);
|
||||
static char *make_label(const char *);
|
||||
|
||||
#ifndef HAVE___PROGNAME
|
||||
char *__progname = (char *) "tmux";
|
||||
#endif
|
||||
|
||||
__dead void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-2CluvV] [-c shell-command] [-f file] [-L socket-name]\n"
|
||||
" [-S socket-path] [command [flags]]\n",
|
||||
__progname);
|
||||
getprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -98,7 +94,7 @@ areshell(const char *shell)
|
||||
ptr++;
|
||||
else
|
||||
ptr = shell;
|
||||
progname = __progname;
|
||||
progname = getprogname();
|
||||
if (*progname == '-')
|
||||
progname++;
|
||||
if (strcmp(ptr, progname) == 0)
|
||||
@@ -196,8 +192,7 @@ main(int argc, char **argv)
|
||||
if (setlocale(LC_CTYPE, "") == NULL)
|
||||
errx(1, "invalid LC_ALL, LC_CTYPE or LANG");
|
||||
s = nl_langinfo(CODESET);
|
||||
if (strcasecmp(s, "UTF-8") != 0 &&
|
||||
strcasecmp(s, "UTF8") != 0)
|
||||
if (strcasecmp(s, "UTF-8") != 0 && strcasecmp(s, "UTF8") != 0)
|
||||
errx(1, "need UTF-8 locale (LC_CTYPE) but have %s", s);
|
||||
}
|
||||
|
||||
@@ -226,7 +221,7 @@ main(int argc, char **argv)
|
||||
flags |= CLIENT_CONTROL;
|
||||
break;
|
||||
case 'V':
|
||||
printf("%s %s\n", __progname, VERSION);
|
||||
printf("%s %s\n", getprogname(), VERSION);
|
||||
exit(0);
|
||||
case 'f':
|
||||
set_cfg_file(optarg);
|
||||
@@ -338,5 +333,5 @@ main(int argc, char **argv)
|
||||
free(label);
|
||||
|
||||
/* Pass control to the client. */
|
||||
exit(client_main(event_init(), argc, argv, flags, shellcmd));
|
||||
exit(client_main(osdep_event_init(), argc, argv, flags, shellcmd));
|
||||
}
|
||||
|
||||
139
tmux.h
139
tmux.h
@@ -38,7 +38,6 @@
|
||||
#include "compat.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
extern char *__progname;
|
||||
extern char **environ;
|
||||
|
||||
struct client;
|
||||
@@ -63,14 +62,17 @@ struct tmuxproc;
|
||||
#define NAME_INTERVAL 500000
|
||||
|
||||
/*
|
||||
* READ_SIZE is the maximum size of data to hold from a pty (the event high
|
||||
* watermark). READ_BACKOFF is the amount of data waiting to be output to a tty
|
||||
* before pty reads will be backed off. READ_TIME is how long to back off
|
||||
* before the next read (in microseconds) if a tty is above READ_BACKOFF.
|
||||
* Event watermarks. We start with FAST then if we hit full size for HITS reads
|
||||
* in succession switch to SLOW, and return when we hit EMPTY the same number
|
||||
* of times.
|
||||
*/
|
||||
#define READ_SIZE 1024
|
||||
#define READ_BACKOFF 512
|
||||
#define READ_TIME 100
|
||||
#define READ_FAST_SIZE 4096
|
||||
#define READ_SLOW_SIZE 128
|
||||
|
||||
#define READ_FULL_SIZE (4096 - 16)
|
||||
#define READ_EMPTY_SIZE 16
|
||||
|
||||
#define READ_CHANGE_HITS 3
|
||||
|
||||
/* Attribute to make gcc check printf-like arguments. */
|
||||
#define printflike(a, b) __attribute__ ((format (printf, a, b)))
|
||||
@@ -538,12 +540,14 @@ enum mode_key_cmd {
|
||||
MODEKEYCOPY_LEFT,
|
||||
MODEKEYCOPY_MIDDLELINE,
|
||||
MODEKEYCOPY_NEXTPAGE,
|
||||
MODEKEYCOPY_NEXTPARAGRAPH,
|
||||
MODEKEYCOPY_NEXTSPACE,
|
||||
MODEKEYCOPY_NEXTSPACEEND,
|
||||
MODEKEYCOPY_NEXTWORD,
|
||||
MODEKEYCOPY_NEXTWORDEND,
|
||||
MODEKEYCOPY_OTHEREND,
|
||||
MODEKEYCOPY_PREVIOUSPAGE,
|
||||
MODEKEYCOPY_PREVIOUSPARAGRAPH,
|
||||
MODEKEYCOPY_PREVIOUSSPACE,
|
||||
MODEKEYCOPY_PREVIOUSWORD,
|
||||
MODEKEYCOPY_RECTANGLETOGGLE,
|
||||
@@ -574,6 +578,7 @@ struct mode_key_data {
|
||||
/* Binding between a key and a command. */
|
||||
struct mode_key_binding {
|
||||
key_code key;
|
||||
u_int repeat;
|
||||
|
||||
int mode;
|
||||
enum mode_key_cmd cmd;
|
||||
@@ -633,6 +638,10 @@ enum utf8_state {
|
||||
UTF8_ERROR
|
||||
};
|
||||
|
||||
/* Colour flags. */
|
||||
#define COLOUR_FLAG_256 0x01000000
|
||||
#define COLOUR_FLAG_RGB 0x02000000
|
||||
|
||||
/* Grid attributes. */
|
||||
#define GRID_ATTR_BRIGHT 0x1
|
||||
#define GRID_ATTR_DIM 0x2
|
||||
@@ -648,31 +657,18 @@ enum utf8_state {
|
||||
#define GRID_FLAG_BG256 0x2
|
||||
#define GRID_FLAG_PADDING 0x4
|
||||
#define GRID_FLAG_EXTENDED 0x8
|
||||
#define GRID_FLAG_FGRGB 0x10
|
||||
#define GRID_FLAG_BGRGB 0x20
|
||||
#define GRID_FLAG_SELECTED 0x10
|
||||
|
||||
/* Grid line flags. */
|
||||
#define GRID_LINE_WRAPPED 0x1
|
||||
|
||||
/* Grid cell RGB colours. */
|
||||
struct grid_cell_rgb {
|
||||
u_char r;
|
||||
u_char g;
|
||||
u_char b;
|
||||
};
|
||||
#define GRID_LINE_EXTENDED 0x2
|
||||
|
||||
/* Grid cell data. */
|
||||
struct grid_cell {
|
||||
u_char flags;
|
||||
u_char attr;
|
||||
union {
|
||||
u_char fg;
|
||||
struct grid_cell_rgb fg_rgb;
|
||||
};
|
||||
union {
|
||||
u_char bg;
|
||||
struct grid_cell_rgb bg_rgb;
|
||||
};
|
||||
int fg;
|
||||
int bg;
|
||||
struct utf8_data data;
|
||||
|
||||
};
|
||||
@@ -708,6 +704,7 @@ struct grid {
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
u_int hscrolled;
|
||||
u_int hsize;
|
||||
u_int hlimit;
|
||||
|
||||
@@ -787,30 +784,38 @@ struct screen_sel {
|
||||
|
||||
/* Virtual screen. */
|
||||
struct screen {
|
||||
char *title;
|
||||
char *title;
|
||||
|
||||
struct grid *grid; /* grid data */
|
||||
struct grid *grid; /* grid data */
|
||||
|
||||
u_int cx; /* cursor x */
|
||||
u_int cy; /* cursor y */
|
||||
u_int cx; /* cursor x */
|
||||
u_int cy; /* cursor y */
|
||||
|
||||
u_int cstyle; /* cursor style */
|
||||
char *ccolour; /* cursor colour string */
|
||||
u_int cstyle; /* cursor style */
|
||||
char *ccolour; /* cursor colour string */
|
||||
|
||||
u_int rupper; /* scroll region top */
|
||||
u_int rlower; /* scroll region bottom */
|
||||
u_int rupper; /* scroll region top */
|
||||
u_int rlower; /* scroll region bottom */
|
||||
|
||||
int mode;
|
||||
int mode;
|
||||
|
||||
bitstr_t *tabs;
|
||||
bitstr_t *tabs;
|
||||
|
||||
struct screen_sel sel;
|
||||
bitstr_t *dirty;
|
||||
u_int dirtysize;
|
||||
|
||||
struct screen_sel sel;
|
||||
};
|
||||
|
||||
/* Screen write context. */
|
||||
struct screen_write_ctx {
|
||||
struct window_pane *wp;
|
||||
struct screen *s;
|
||||
struct window_pane *wp;
|
||||
struct screen *s;
|
||||
u_int dirty;
|
||||
|
||||
u_int cells;
|
||||
u_int written;
|
||||
u_int skipped;
|
||||
};
|
||||
|
||||
/* Screen size. */
|
||||
@@ -830,6 +835,7 @@ struct window_mode {
|
||||
void (*key)(struct window_pane *, struct client *, struct session *,
|
||||
key_code, struct mouse_event *);
|
||||
};
|
||||
#define WINDOW_MODE_TIMEOUT 180
|
||||
|
||||
/* Structures for choose mode. */
|
||||
struct window_choose_data {
|
||||
@@ -889,7 +895,11 @@ struct window_pane {
|
||||
|
||||
int fd;
|
||||
struct bufferevent *event;
|
||||
struct event timer;
|
||||
|
||||
struct event resize_timer;
|
||||
|
||||
u_int wmark_size;
|
||||
u_int wmark_hits;
|
||||
|
||||
struct input_ctx *ictx;
|
||||
|
||||
@@ -902,6 +912,9 @@ struct window_pane {
|
||||
struct screen *screen;
|
||||
struct screen base;
|
||||
|
||||
struct screen status_screen;
|
||||
size_t status_size;
|
||||
|
||||
/* Saved in alternative screen mode. */
|
||||
u_int saved_cx;
|
||||
u_int saved_cy;
|
||||
@@ -910,6 +923,8 @@ struct window_pane {
|
||||
|
||||
const struct window_mode *mode;
|
||||
void *modedata;
|
||||
struct event modetimer;
|
||||
time_t modelast;
|
||||
|
||||
TAILQ_ENTRY(window_pane) entry;
|
||||
RB_ENTRY(window_pane) tree_entry;
|
||||
@@ -949,10 +964,14 @@ struct window {
|
||||
#define WINDOW_ZOOMED 0x1000
|
||||
#define WINDOW_FORCEWIDTH 0x2000
|
||||
#define WINDOW_FORCEHEIGHT 0x4000
|
||||
#define WINDOW_STYLECHANGED 0x8000
|
||||
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
|
||||
|
||||
struct options *options;
|
||||
|
||||
struct grid_cell style;
|
||||
struct grid_cell active_style;
|
||||
|
||||
u_int references;
|
||||
|
||||
RB_ENTRY(window) entry;
|
||||
@@ -1207,7 +1226,6 @@ struct tty_ctx {
|
||||
|
||||
/* Saved last cell on line. */
|
||||
struct grid_cell last_cell;
|
||||
u_int last_width;
|
||||
};
|
||||
|
||||
/* Saved message entry. */
|
||||
@@ -1275,6 +1293,8 @@ struct client {
|
||||
struct key_table *keytable;
|
||||
|
||||
struct event identify_timer;
|
||||
void (*identify_callback)(struct client *, struct window_pane *);
|
||||
void *identify_callback_data;
|
||||
|
||||
char *message_string;
|
||||
struct event message_timer;
|
||||
@@ -1560,7 +1580,7 @@ extern int cfg_finished;
|
||||
extern int cfg_references;
|
||||
extern struct client *cfg_client;
|
||||
void start_cfg(void);
|
||||
int load_cfg(const char *, struct cmd_q *, char **);
|
||||
int load_cfg(const char *, struct cmd_q *, int);
|
||||
void set_cfg_file(const char *);
|
||||
void printflike(1, 2) cfg_add_cause(const char *, ...);
|
||||
void cfg_print_causes(struct cmd_q *);
|
||||
@@ -1631,7 +1651,7 @@ const struct mode_key_table *mode_key_findtable(const char *);
|
||||
void mode_key_init_trees(void);
|
||||
void mode_key_init(struct mode_key_data *, struct mode_key_tree *);
|
||||
enum mode_key_cmd mode_key_lookup(struct mode_key_data *, key_code,
|
||||
const char **);
|
||||
const char **, u_int *);
|
||||
|
||||
/* notify.c */
|
||||
void notify_enable(void);
|
||||
@@ -1692,6 +1712,7 @@ void environ_put(struct environ *, const char *);
|
||||
void environ_unset(struct environ *, const char *);
|
||||
void environ_update(const char *, struct environ *, struct environ *);
|
||||
void environ_push(struct environ *);
|
||||
void environ_log(struct environ *, const char *);
|
||||
|
||||
/* tty.c */
|
||||
void tty_create_log(void);
|
||||
@@ -1730,7 +1751,6 @@ void tty_close(struct tty *);
|
||||
void tty_free(struct tty *);
|
||||
void tty_write(void (*)(struct tty *, const struct tty_ctx *),
|
||||
struct tty_ctx *);
|
||||
int tty_client_ready(struct client *, struct window_pane *wp);
|
||||
void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *);
|
||||
void tty_cmd_cell(struct tty *, const struct tty_ctx *);
|
||||
void tty_cmd_clearendofline(struct tty *, const struct tty_ctx *);
|
||||
@@ -1936,7 +1956,7 @@ void server_destroy_session_group(struct session *);
|
||||
void server_destroy_session(struct session *);
|
||||
void server_check_unattached(void);
|
||||
void server_set_identify(struct client *);
|
||||
void server_clear_identify(struct client *);
|
||||
void server_clear_identify(struct client *, struct window_pane *);
|
||||
int server_set_stdin_callback(struct client *, void (*)(struct client *,
|
||||
int, void *), void *, char **);
|
||||
void server_unzoom_window(struct window *);
|
||||
@@ -1978,10 +1998,10 @@ int xterm_keys_find(const char *, size_t, size_t *, key_code *);
|
||||
|
||||
/* colour.c */
|
||||
int colour_find_rgb(u_char, u_char, u_char);
|
||||
void colour_set_fg(struct grid_cell *, int);
|
||||
void colour_set_bg(struct grid_cell *, int);
|
||||
int colour_join_rgb(u_char, u_char, u_char);
|
||||
void colour_split_rgb(int, u_char *, u_char *, u_char *);
|
||||
const char *colour_tostring(int);
|
||||
int colour_fromstring(const char *);
|
||||
int colour_fromstring(const char *s);
|
||||
u_char colour_256to16(u_char);
|
||||
|
||||
/* attributes.c */
|
||||
@@ -1990,6 +2010,7 @@ int attributes_fromstring(const char *);
|
||||
|
||||
/* grid.c */
|
||||
extern const struct grid_cell grid_default_cell;
|
||||
int grid_cells_equal(const struct grid_cell *, const struct grid_cell *);
|
||||
struct grid *grid_create(u_int, u_int, u_int);
|
||||
void grid_destroy(struct grid *);
|
||||
int grid_compare(struct grid *, struct grid *);
|
||||
@@ -2034,15 +2055,15 @@ void screen_write_stop(struct screen_write_ctx *);
|
||||
void screen_write_reset(struct screen_write_ctx *);
|
||||
size_t printflike(1, 2) screen_write_cstrlen(const char *, ...);
|
||||
void printflike(4, 5) screen_write_cnputs(struct screen_write_ctx *,
|
||||
ssize_t, struct grid_cell *, const char *, ...);
|
||||
ssize_t, const struct grid_cell *, const char *, ...);
|
||||
size_t printflike(1, 2) screen_write_strlen(const char *, ...);
|
||||
void printflike(3, 4) screen_write_puts(struct screen_write_ctx *,
|
||||
struct grid_cell *, const char *, ...);
|
||||
const struct grid_cell *, const char *, ...);
|
||||
void printflike(4, 5) screen_write_nputs(struct screen_write_ctx *,
|
||||
ssize_t, struct grid_cell *, const char *, ...);
|
||||
ssize_t, const struct grid_cell *, const char *, ...);
|
||||
void screen_write_vnputs(struct screen_write_ctx *, ssize_t,
|
||||
struct grid_cell *, const char *, va_list);
|
||||
void screen_write_putc(struct screen_write_ctx *, struct grid_cell *,
|
||||
const struct grid_cell *, const char *, va_list);
|
||||
void screen_write_putc(struct screen_write_ctx *, const struct grid_cell *,
|
||||
u_char);
|
||||
void screen_write_copy(struct screen_write_ctx *, struct screen *, u_int,
|
||||
u_int, u_int, u_int);
|
||||
@@ -2133,7 +2154,8 @@ int window_has_pane(struct window *, struct window_pane *);
|
||||
int window_set_active_pane(struct window *, struct window_pane *);
|
||||
void window_redraw_active_switch(struct window *,
|
||||
struct window_pane *);
|
||||
struct window_pane *window_add_pane(struct window *, u_int);
|
||||
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
||||
u_int);
|
||||
void window_resize(struct window *, u_int, u_int);
|
||||
int window_zoom(struct window_pane *);
|
||||
int window_unzoom(struct window *);
|
||||
@@ -2182,7 +2204,7 @@ u_int layout_count_cells(struct layout_cell *);
|
||||
struct layout_cell *layout_create_cell(struct layout_cell *);
|
||||
void layout_free_cell(struct layout_cell *);
|
||||
void layout_print_cell(struct layout_cell *, const char *, u_int);
|
||||
void layout_destroy_cell(struct layout_cell *,
|
||||
void layout_destroy_cell(struct window *, struct layout_cell *,
|
||||
struct layout_cell **);
|
||||
void layout_set_size(struct layout_cell *, u_int, u_int, u_int,
|
||||
u_int);
|
||||
@@ -2190,9 +2212,8 @@ void layout_make_leaf(struct layout_cell *, struct window_pane *);
|
||||
void layout_make_node(struct layout_cell *, enum layout_type);
|
||||
void layout_fix_offsets(struct layout_cell *);
|
||||
void layout_fix_panes(struct window *, u_int, u_int);
|
||||
u_int layout_resize_check(struct layout_cell *, enum layout_type);
|
||||
void layout_resize_adjust(struct layout_cell *, enum layout_type,
|
||||
int);
|
||||
void layout_resize_adjust(struct window *, struct layout_cell *,
|
||||
enum layout_type, int);
|
||||
void layout_init(struct window *, struct window_pane *);
|
||||
void layout_free(struct window *);
|
||||
void layout_resize(struct window *, u_int, u_int);
|
||||
@@ -2202,7 +2223,7 @@ void layout_resize_pane_to(struct window_pane *, enum layout_type,
|
||||
u_int);
|
||||
void layout_assign_pane(struct layout_cell *, struct window_pane *);
|
||||
struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
|
||||
int, int);
|
||||
int, int, int);
|
||||
void layout_close_pane(struct window_pane *);
|
||||
|
||||
/* layout-custom.c */
|
||||
@@ -2225,7 +2246,7 @@ void window_copy_init_from_pane(struct window_pane *, int);
|
||||
void window_copy_init_for_output(struct window_pane *);
|
||||
void printflike(2, 3) window_copy_add(struct window_pane *, const char *, ...);
|
||||
void window_copy_vadd(struct window_pane *, const char *, va_list);
|
||||
void window_copy_pageup(struct window_pane *);
|
||||
void window_copy_pageup(struct window_pane *, int);
|
||||
void window_copy_start_drag(struct client *, struct mouse_event *);
|
||||
int window_copy_scroll_position(struct window_pane *);
|
||||
|
||||
|
||||
208
tty-keys.c
208
tty-keys.c
@@ -33,14 +33,17 @@
|
||||
* into a ternary tree.
|
||||
*/
|
||||
|
||||
void tty_keys_add1(struct tty_key **, const char *, key_code);
|
||||
void tty_keys_add(struct tty *, const char *, key_code);
|
||||
void tty_keys_free1(struct tty_key *);
|
||||
struct tty_key *tty_keys_find1(struct tty_key *, const char *, size_t,
|
||||
static void tty_keys_add1(struct tty_key **, const char *, key_code);
|
||||
static void tty_keys_add(struct tty *, const char *, key_code);
|
||||
static void tty_keys_free1(struct tty_key *);
|
||||
static struct tty_key *tty_keys_find1(struct tty_key *, const char *, size_t,
|
||||
size_t *);
|
||||
struct tty_key *tty_keys_find(struct tty *, const char *, size_t, size_t *);
|
||||
void tty_keys_callback(int, short, void *);
|
||||
int tty_keys_mouse(struct tty *, const char *, size_t, size_t *);
|
||||
static struct tty_key *tty_keys_find(struct tty *, const char *, size_t,
|
||||
size_t *);
|
||||
static int tty_keys_next1(struct tty *, const char *, size_t, key_code *,
|
||||
size_t *, int);
|
||||
static void tty_keys_callback(int, short, void *);
|
||||
static int tty_keys_mouse(struct tty *, const char *, size_t, size_t *);
|
||||
|
||||
/* Default raw keys. */
|
||||
struct tty_default_key_raw {
|
||||
@@ -316,7 +319,7 @@ const struct tty_default_key_code tty_default_code_keys[] = {
|
||||
};
|
||||
|
||||
/* Add key to tree. */
|
||||
void
|
||||
static void
|
||||
tty_keys_add(struct tty *tty, const char *s, key_code key)
|
||||
{
|
||||
struct tty_key *tk;
|
||||
@@ -334,7 +337,7 @@ tty_keys_add(struct tty *tty, const char *s, key_code key)
|
||||
}
|
||||
|
||||
/* Add next node to the tree. */
|
||||
void
|
||||
static void
|
||||
tty_keys_add1(struct tty_key **tkp, const char *s, key_code key)
|
||||
{
|
||||
struct tty_key *tk;
|
||||
@@ -409,7 +412,7 @@ tty_keys_free(struct tty *tty)
|
||||
}
|
||||
|
||||
/* Free a single key. */
|
||||
void
|
||||
static void
|
||||
tty_keys_free1(struct tty_key *tk)
|
||||
{
|
||||
if (tk->next != NULL)
|
||||
@@ -422,7 +425,7 @@ tty_keys_free1(struct tty_key *tk)
|
||||
}
|
||||
|
||||
/* Lookup a key in the tree. */
|
||||
struct tty_key *
|
||||
static struct tty_key *
|
||||
tty_keys_find(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
{
|
||||
*size = 0;
|
||||
@@ -430,7 +433,7 @@ tty_keys_find(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
}
|
||||
|
||||
/* Find the next node. */
|
||||
struct tty_key *
|
||||
static struct tty_key *
|
||||
tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
|
||||
{
|
||||
/* If the node is NULL, this is the end of the tree. No match. */
|
||||
@@ -460,6 +463,58 @@ tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
|
||||
return (tty_keys_find1(tk, buf, len, size));
|
||||
}
|
||||
|
||||
/* Look up part of the next key. */
|
||||
static int
|
||||
tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
|
||||
size_t *size, int expired)
|
||||
{
|
||||
struct tty_key *tk, *tk1;
|
||||
struct utf8_data ud;
|
||||
enum utf8_state more;
|
||||
u_int i;
|
||||
wchar_t wc;
|
||||
|
||||
log_debug("next key is %zu (%.*s) (expired=%d)", len, (int)len, buf,
|
||||
expired);
|
||||
|
||||
/* Is this a known key? */
|
||||
tk = tty_keys_find(tty, buf, len, size);
|
||||
if (tk != NULL && tk->key != KEYC_UNKNOWN) {
|
||||
tk1 = tk;
|
||||
do
|
||||
log_debug("keys in list: %#llx", tk1->key);
|
||||
while ((tk1 = tk1->next) != NULL);
|
||||
if (tk->next != NULL && !expired)
|
||||
return (1);
|
||||
*key = tk->key;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Is this valid UTF-8? */
|
||||
more = utf8_open(&ud, (u_char)*buf);
|
||||
if (more == UTF8_MORE) {
|
||||
*size = ud.size;
|
||||
if (len < ud.size) {
|
||||
if (!expired)
|
||||
return (1);
|
||||
return (-1);
|
||||
}
|
||||
for (i = 1; i < ud.size; i++)
|
||||
more = utf8_append(&ud, (u_char)buf[i]);
|
||||
if (more != UTF8_DONE)
|
||||
return (-1);
|
||||
|
||||
if (utf8_combine(&ud, &wc) != UTF8_DONE)
|
||||
return (-1);
|
||||
*key = wc;
|
||||
|
||||
log_debug("UTF-8 key %.*s %#llx", (int)ud.size, buf, *key);
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process at least one key in the buffer and invoke tty->key_callback. Return
|
||||
* 0 if there are no further keys, or 1 if there could be more in the buffer.
|
||||
@@ -467,17 +522,12 @@ tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
|
||||
key_code
|
||||
tty_keys_next(struct tty *tty)
|
||||
{
|
||||
struct tty_key *tk;
|
||||
struct timeval tv;
|
||||
const char *buf;
|
||||
size_t len, size;
|
||||
cc_t bspace;
|
||||
int delay, expired = 0;
|
||||
key_code key;
|
||||
struct utf8_data ud;
|
||||
enum utf8_state more;
|
||||
u_int i;
|
||||
wchar_t wc;
|
||||
struct timeval tv;
|
||||
const char *buf;
|
||||
size_t len, size;
|
||||
cc_t bspace;
|
||||
int delay, expired = 0, n;
|
||||
key_code key;
|
||||
|
||||
/* Get key buffer. */
|
||||
buf = EVBUFFER_DATA(tty->event->input);
|
||||
@@ -485,7 +535,7 @@ tty_keys_next(struct tty *tty)
|
||||
|
||||
if (len == 0)
|
||||
return (0);
|
||||
log_debug("keys are %zu (%.*s)", len, (int) len, buf);
|
||||
log_debug("keys are %zu (%.*s)", len, (int)len, buf);
|
||||
|
||||
/* Is this a mouse key press? */
|
||||
switch (tty_keys_mouse(tty, buf, len, &size)) {
|
||||
@@ -501,84 +551,49 @@ tty_keys_next(struct tty *tty)
|
||||
goto partial_key;
|
||||
}
|
||||
|
||||
/* Look for matching key string and return if found. */
|
||||
tk = tty_keys_find(tty, buf, len, &size);
|
||||
if (tk != NULL) {
|
||||
if (tk->next != NULL)
|
||||
goto partial_key;
|
||||
key = tk->key;
|
||||
goto complete_key;
|
||||
}
|
||||
|
||||
/* Try to parse a key with an xterm-style modifier. */
|
||||
switch (xterm_keys_find(buf, len, &size, &key)) {
|
||||
case 0: /* found */
|
||||
goto complete_key;
|
||||
case -1: /* not found */
|
||||
break;
|
||||
case 1:
|
||||
goto partial_key;
|
||||
}
|
||||
|
||||
first_key:
|
||||
/* Is this a meta key? */
|
||||
if (len >= 2 && buf[0] == '\033') {
|
||||
if (buf[1] != '\033') {
|
||||
key = buf[1] | KEYC_ESCAPE;
|
||||
size = 2;
|
||||
/* Handle keys starting with escape. */
|
||||
if (*buf == '\033') {
|
||||
/* Look for a key without the escape. */
|
||||
n = tty_keys_next1(tty, buf + 1, len - 1, &key, &size, expired);
|
||||
if (n == 0) { /* found */
|
||||
key |= KEYC_ESCAPE;
|
||||
size++;
|
||||
goto complete_key;
|
||||
}
|
||||
|
||||
tk = tty_keys_find(tty, buf + 1, len - 1, &size);
|
||||
if (tk != NULL && (!expired || tk->next == NULL)) {
|
||||
size++; /* include escape */
|
||||
if (tk->next != NULL)
|
||||
goto partial_key;
|
||||
key = tk->key;
|
||||
if (key != KEYC_UNKNOWN)
|
||||
key |= KEYC_ESCAPE;
|
||||
goto complete_key;
|
||||
}
|
||||
}
|
||||
|
||||
/* Is this valid UTF-8? */
|
||||
if ((more = utf8_open(&ud, (u_char)*buf) == UTF8_MORE)) {
|
||||
size = ud.size;
|
||||
if (len < size) {
|
||||
if (expired)
|
||||
goto discard_key;
|
||||
if (n == 1) /* partial */
|
||||
goto partial_key;
|
||||
}
|
||||
for (i = 1; i < size; i++)
|
||||
more = utf8_append(&ud, (u_char)buf[i]);
|
||||
if (more != UTF8_DONE)
|
||||
goto discard_key;
|
||||
|
||||
if (utf8_combine(&ud, &wc) != UTF8_DONE)
|
||||
goto discard_key;
|
||||
key = wc;
|
||||
|
||||
log_debug("UTF-8 key %.*s %#llx", (int)size, buf, key);
|
||||
goto complete_key;
|
||||
}
|
||||
|
||||
/* No key found, take first. */
|
||||
key = (u_char)*buf;
|
||||
size = 1;
|
||||
/* Try to lookup key. */
|
||||
n = tty_keys_next1(tty, buf, len, &key, &size, expired);
|
||||
if (n == 0) /* found */
|
||||
goto complete_key;
|
||||
if (n == 1)
|
||||
goto partial_key;
|
||||
|
||||
/* Is this an an xterm(1) key? */
|
||||
n = xterm_keys_find(buf, len, &size, &key);
|
||||
if (n == 0)
|
||||
goto complete_key;
|
||||
if (n == 1 && !expired)
|
||||
goto partial_key;
|
||||
|
||||
/*
|
||||
* Check for backspace key using termios VERASE - the terminfo
|
||||
* kbs entry is extremely unreliable, so cannot be safely
|
||||
* used. termios should have a better idea.
|
||||
* At this point, we know the key is not partial (with or without
|
||||
* escape). So pass it through even if the timer has not expired.
|
||||
*/
|
||||
bspace = tty->tio.c_cc[VERASE];
|
||||
if (bspace != _POSIX_VDISABLE && key == bspace)
|
||||
key = KEYC_BSPACE;
|
||||
|
||||
if (*buf == '\033' && len >= 2) {
|
||||
key = (u_char)buf[1] | KEYC_ESCAPE;
|
||||
size = 2;
|
||||
} else {
|
||||
key = (u_char)buf[0];
|
||||
size = 1;
|
||||
}
|
||||
goto complete_key;
|
||||
|
||||
partial_key:
|
||||
log_debug("partial key %.*s", (int) len, buf);
|
||||
log_debug("partial key %.*s", (int)len, buf);
|
||||
|
||||
/* If timer is going, check for expiration. */
|
||||
if (tty->flags & TTY_TIMER) {
|
||||
@@ -607,6 +622,15 @@ partial_key:
|
||||
complete_key:
|
||||
log_debug("complete key %.*s %#llx", (int)size, buf, key);
|
||||
|
||||
/*
|
||||
* Check for backspace key using termios VERASE - the terminfo
|
||||
* kbs entry is extremely unreliable, so cannot be safely
|
||||
* used. termios should have a better idea.
|
||||
*/
|
||||
bspace = tty->tio.c_cc[VERASE];
|
||||
if (bspace != _POSIX_VDISABLE && (key & KEYC_MASK_KEY) == bspace)
|
||||
key = (key & KEYC_MASK_MOD) | KEYC_BSPACE;
|
||||
|
||||
/* Remove data from buffer. */
|
||||
evbuffer_drain(tty->event->input, size);
|
||||
|
||||
@@ -640,7 +664,7 @@ discard_key:
|
||||
}
|
||||
|
||||
/* Key timer callback. */
|
||||
void
|
||||
static void
|
||||
tty_keys_callback(__unused int fd, __unused short events, void *data)
|
||||
{
|
||||
struct tty *tty = data;
|
||||
@@ -655,7 +679,7 @@ tty_keys_callback(__unused int fd, __unused short events, void *data)
|
||||
* Handle mouse key input. Returns 0 for success, -1 for failure, 1 for partial
|
||||
* (probably a mouse sequence but need more data).
|
||||
*/
|
||||
int
|
||||
static int
|
||||
tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
{
|
||||
struct mouse_event *m = &tty->mouse;
|
||||
|
||||
350
tty.c
350
tty.c
@@ -36,15 +36,10 @@ static int tty_log_fd = -1;
|
||||
void tty_read_callback(struct bufferevent *, void *);
|
||||
void tty_error_callback(struct bufferevent *, short, void *);
|
||||
|
||||
static int tty_same_fg(const struct grid_cell *, const struct grid_cell *);
|
||||
static int tty_same_bg(const struct grid_cell *, const struct grid_cell *);
|
||||
static int tty_same_colours(const struct grid_cell *, const struct grid_cell *);
|
||||
static int tty_is_fg(const struct grid_cell *, int);
|
||||
static int tty_is_bg(const struct grid_cell *, int);
|
||||
static int tty_client_ready(struct client *, struct window_pane *);
|
||||
|
||||
void tty_set_italics(struct tty *);
|
||||
int tty_try_256(struct tty *, u_char, const char *);
|
||||
int tty_try_rgb(struct tty *, const struct grid_cell_rgb *, const char *);
|
||||
int tty_try_colour(struct tty *, int, const char *);
|
||||
|
||||
void tty_colours(struct tty *, const struct grid_cell *);
|
||||
void tty_check_fg(struct tty *, struct grid_cell *);
|
||||
@@ -68,74 +63,6 @@ void tty_default_colours(struct grid_cell *, const struct window_pane *);
|
||||
#define tty_pane_full_width(tty, ctx) \
|
||||
((ctx)->xoff == 0 && screen_size_x((ctx)->wp->screen) >= (tty)->sx)
|
||||
|
||||
static int
|
||||
tty_same_fg(const struct grid_cell *gc1, const struct grid_cell *gc2)
|
||||
{
|
||||
int flags1, flags2;
|
||||
|
||||
flags1 = (gc1->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
|
||||
flags2 = (gc2->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
|
||||
|
||||
if (flags1 != flags2)
|
||||
return (0);
|
||||
|
||||
if (flags1 & GRID_FLAG_FGRGB) {
|
||||
if (gc1->fg_rgb.r != gc2->fg_rgb.r)
|
||||
return (0);
|
||||
if (gc1->fg_rgb.g != gc2->fg_rgb.g)
|
||||
return (0);
|
||||
if (gc1->fg_rgb.b != gc2->fg_rgb.b)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
return (gc1->fg == gc2->fg);
|
||||
}
|
||||
|
||||
static int
|
||||
tty_same_bg(const struct grid_cell *gc1, const struct grid_cell *gc2)
|
||||
{
|
||||
int flags1, flags2;
|
||||
|
||||
flags1 = (gc1->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
|
||||
flags2 = (gc2->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
|
||||
|
||||
if (flags1 != flags2)
|
||||
return (0);
|
||||
|
||||
if (flags1 & GRID_FLAG_BGRGB) {
|
||||
if (gc1->bg_rgb.r != gc2->bg_rgb.r)
|
||||
return (0);
|
||||
if (gc1->bg_rgb.g != gc2->bg_rgb.g)
|
||||
return (0);
|
||||
if (gc1->bg_rgb.b != gc2->bg_rgb.b)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
return (gc1->bg == gc2->bg);
|
||||
}
|
||||
|
||||
static int
|
||||
tty_same_colours(const struct grid_cell *gc1, const struct grid_cell *gc2)
|
||||
{
|
||||
return (tty_same_fg(gc1, gc2) && tty_same_bg(gc1, gc2));
|
||||
}
|
||||
|
||||
static int
|
||||
tty_is_fg(const struct grid_cell *gc, int c)
|
||||
{
|
||||
if (gc->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB))
|
||||
return (0);
|
||||
return (gc->fg == c);
|
||||
}
|
||||
|
||||
static int
|
||||
tty_is_bg(const struct grid_cell *gc, int c)
|
||||
{
|
||||
if (gc->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB))
|
||||
return (0);
|
||||
return (gc->bg == c);
|
||||
}
|
||||
|
||||
void
|
||||
tty_create_log(void)
|
||||
{
|
||||
@@ -674,9 +601,10 @@ tty_fake_bce(const struct tty *tty, const struct window_pane *wp)
|
||||
struct grid_cell gc;
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
tty_default_colours(&gc, wp);
|
||||
if (wp != NULL)
|
||||
tty_default_colours(&gc, wp);
|
||||
|
||||
if (gc.bg == 8 && !(gc.flags & GRID_FLAG_BG256))
|
||||
if (gc.bg == 8)
|
||||
return (0);
|
||||
return (!tty_term_flag(tty->term, TTYC_BCE));
|
||||
}
|
||||
@@ -691,7 +619,7 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct screen *s = wp->screen;
|
||||
u_int i;
|
||||
u_int i;
|
||||
|
||||
/*
|
||||
* If region is large, schedule a window redraw. In most cases this is
|
||||
@@ -751,11 +679,6 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
|
||||
|
||||
for (i = 0; i < sx; i++) {
|
||||
grid_view_get_cell(s->grid, i, py, &gc);
|
||||
if (screen_check_selection(s, i, py)) {
|
||||
gc.flags &= ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||
gc.flags |= s->sel.cell.flags &
|
||||
(GRID_FLAG_FG256|GRID_FLAG_BG256);
|
||||
}
|
||||
tty_cell(tty, &gc, wp);
|
||||
}
|
||||
|
||||
@@ -776,7 +699,7 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
|
||||
tty_update_mode(tty, tty->mode, s);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
tty_client_ready(struct client *c, struct window_pane *wp)
|
||||
{
|
||||
if (c->session == NULL || c->tty.term == NULL)
|
||||
@@ -1022,7 +945,7 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct screen *s = wp->screen;
|
||||
u_int i, j;
|
||||
u_int i, j;
|
||||
|
||||
tty_attributes(tty, &grid_default_cell, wp);
|
||||
|
||||
@@ -1056,7 +979,7 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct screen *s = wp->screen;
|
||||
u_int i, j;
|
||||
u_int i, j;
|
||||
|
||||
tty_attributes(tty, &grid_default_cell, wp);
|
||||
|
||||
@@ -1084,7 +1007,7 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct screen *s = wp->screen;
|
||||
u_int i, j;
|
||||
u_int i, j;
|
||||
|
||||
tty_attributes(tty, &grid_default_cell, wp);
|
||||
|
||||
@@ -1131,10 +1054,10 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct screen *s = wp->screen;
|
||||
u_int cx;
|
||||
u_int width;
|
||||
u_int cx, width;
|
||||
|
||||
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
|
||||
if (ctx->ocy == ctx->orlower)
|
||||
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
|
||||
|
||||
/* Is the cursor in the very last position? */
|
||||
width = ctx->cell->data.width;
|
||||
@@ -1252,7 +1175,7 @@ tty_reset(struct tty *tty)
|
||||
{
|
||||
struct grid_cell *gc = &tty->cell;
|
||||
|
||||
if (memcmp(gc, &grid_default_cell, sizeof *gc) == 0)
|
||||
if (grid_cells_equal(gc, &grid_default_cell))
|
||||
return;
|
||||
|
||||
if ((gc->attr & GRID_ATTR_CHARSET) && tty_use_acs(tty))
|
||||
@@ -1343,7 +1266,7 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy)
|
||||
*/
|
||||
|
||||
/* To left edge. */
|
||||
if (cx == 0) {
|
||||
if (cx == 0) {
|
||||
tty_putc(tty, '\r');
|
||||
goto out;
|
||||
}
|
||||
@@ -1371,6 +1294,11 @@ tty_cursor(struct tty *tty, u_int cx, u_int cy)
|
||||
tty_putcode1(tty, TTYC_HPA, cx);
|
||||
goto out;
|
||||
} else if (change > 0 && tty_term_has(term, TTYC_CUB)) {
|
||||
if (change == 2 && tty_term_has(term, TTYC_CUB1)) {
|
||||
tty_putcode(tty, TTYC_CUB1);
|
||||
tty_putcode(tty, TTYC_CUB1);
|
||||
goto out;
|
||||
}
|
||||
tty_putcode1(tty, TTYC_CUB, change);
|
||||
goto out;
|
||||
} else if (change < 0 && tty_term_has(term, TTYC_CUF)) {
|
||||
@@ -1436,7 +1364,8 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
u_char changed;
|
||||
|
||||
memcpy(&gc2, gc, sizeof gc2);
|
||||
tty_default_colours(&gc2, wp);
|
||||
if (wp != NULL)
|
||||
tty_default_colours(&gc2, wp);
|
||||
|
||||
/*
|
||||
* If no setab, try to use the reverse attribute as a best-effort for a
|
||||
@@ -1498,10 +1427,10 @@ void
|
||||
tty_colours(struct tty *tty, const struct grid_cell *gc)
|
||||
{
|
||||
struct grid_cell *tc = &tty->cell;
|
||||
int have_ax, fg_default, bg_default;
|
||||
int have_ax;
|
||||
|
||||
/* No changes? Nothing is necessary. */
|
||||
if (tty_same_colours(gc, tc))
|
||||
if (gc->fg == tc->fg && gc->bg == tc->bg)
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -1510,9 +1439,7 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
|
||||
* case if only one is default need to fall onward to set the other
|
||||
* colour.
|
||||
*/
|
||||
fg_default = tty_is_fg(gc, 8);
|
||||
bg_default = tty_is_bg(gc, 8);
|
||||
if (fg_default || bg_default) {
|
||||
if (gc->fg == 8 || gc->bg == 8) {
|
||||
/*
|
||||
* If don't have AX but do have op, send sgr0 (op can't
|
||||
* actually be used because it is sometimes the same as sgr0
|
||||
@@ -1524,58 +1451,54 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
|
||||
if (!have_ax && tty_term_has(tty->term, TTYC_OP))
|
||||
tty_reset(tty);
|
||||
else {
|
||||
if (fg_default && !tty_is_fg(tc, 8)) {
|
||||
if (gc->fg == 8 && tc->fg != 8) {
|
||||
if (have_ax)
|
||||
tty_puts(tty, "\033[39m");
|
||||
else if (!tty_is_fg(tc, 7))
|
||||
else if (tc->fg != 7)
|
||||
tty_putcode1(tty, TTYC_SETAF, 7);
|
||||
tc->fg = 8;
|
||||
tc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
|
||||
}
|
||||
if (bg_default && !tty_is_bg(tc, 8)) {
|
||||
if (gc->bg == 8 && tc->bg != 8) {
|
||||
if (have_ax)
|
||||
tty_puts(tty, "\033[49m");
|
||||
else if (!tty_is_bg(tc, 0))
|
||||
else if (tc->bg != 0)
|
||||
tty_putcode1(tty, TTYC_SETAB, 0);
|
||||
tc->bg = 8;
|
||||
tc->flags &= ~(GRID_FLAG_BG256|GRID_FLAG_BGRGB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the foreground colour. */
|
||||
if (!fg_default && !tty_same_fg(gc, tc))
|
||||
if (gc->fg != 8 && gc->fg != tc->fg)
|
||||
tty_colours_fg(tty, gc);
|
||||
|
||||
/*
|
||||
* Set the background colour. This must come after the foreground as
|
||||
* tty_colour_fg() can call tty_reset().
|
||||
*/
|
||||
if (!bg_default && !tty_same_bg(gc, tc))
|
||||
if (gc->bg != 8 && gc->bg != tc->bg)
|
||||
tty_colours_bg(tty, gc);
|
||||
}
|
||||
|
||||
void
|
||||
tty_check_fg(struct tty *tty, struct grid_cell *gc)
|
||||
{
|
||||
struct grid_cell_rgb *rgb = &gc->fg_rgb;
|
||||
u_int colours;
|
||||
u_char r, g, b;
|
||||
u_int colours;
|
||||
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->flags & GRID_FLAG_FGRGB) {
|
||||
if (gc->fg & COLOUR_FLAG_RGB) {
|
||||
/* Not a 24-bit terminal? Translate to 256-colour palette. */
|
||||
if (!tty_term_flag(tty->term, TTYC_TC)) {
|
||||
gc->flags &= ~GRID_FLAG_FGRGB;
|
||||
gc->flags |= GRID_FLAG_FG256;
|
||||
gc->fg = colour_find_rgb(rgb->r, rgb->g, rgb->b);
|
||||
}
|
||||
else
|
||||
colour_split_rgb(gc->fg, &r, &g, &b);
|
||||
gc->fg = colour_find_rgb(r, g, b);
|
||||
} else
|
||||
return;
|
||||
}
|
||||
colours = tty_term_number(tty->term, TTYC_COLORS);
|
||||
|
||||
/* Is this a 256-colour colour? */
|
||||
if (gc->flags & GRID_FLAG_FG256) {
|
||||
if (gc->fg & COLOUR_FLAG_256) {
|
||||
/* And not a 256 colour mode? */
|
||||
if (!(tty->term->flags & TERM_256COLOURS) &&
|
||||
!(tty->term_flags & TERM_256COLOURS)) {
|
||||
@@ -1588,7 +1511,6 @@ tty_check_fg(struct tty *tty, struct grid_cell *gc)
|
||||
gc->attr |= GRID_ATTR_BRIGHT;
|
||||
} else
|
||||
gc->attr &= ~GRID_ATTR_BRIGHT;
|
||||
gc->flags &= ~GRID_FLAG_FG256;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1603,24 +1525,22 @@ tty_check_fg(struct tty *tty, struct grid_cell *gc)
|
||||
void
|
||||
tty_check_bg(struct tty *tty, struct grid_cell *gc)
|
||||
{
|
||||
struct grid_cell_rgb *rgb = &gc->bg_rgb;
|
||||
u_int colours;
|
||||
u_char r, g, b;
|
||||
u_int colours;
|
||||
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->flags & GRID_FLAG_BGRGB) {
|
||||
if (gc->bg & COLOUR_FLAG_RGB) {
|
||||
/* Not a 24-bit terminal? Translate to 256-colour palette. */
|
||||
if (!tty_term_flag(tty->term, TTYC_TC)) {
|
||||
gc->flags &= ~GRID_FLAG_BGRGB;
|
||||
gc->flags |= GRID_FLAG_BG256;
|
||||
gc->bg = colour_find_rgb(rgb->r, rgb->g, rgb->b);
|
||||
}
|
||||
else
|
||||
colour_split_rgb(gc->bg, &r, &g, &b);
|
||||
gc->bg = colour_find_rgb(r, g, b);
|
||||
} else
|
||||
return;
|
||||
}
|
||||
colours = tty_term_number(tty->term, TTYC_COLORS);
|
||||
|
||||
/* Is this a 256-colour colour? */
|
||||
if (gc->flags & GRID_FLAG_BG256) {
|
||||
if (gc->bg & COLOUR_FLAG_256) {
|
||||
/*
|
||||
* And not a 256 colour mode? Translate to 16-colour
|
||||
* palette. Bold background doesn't exist portably, so just
|
||||
@@ -1634,7 +1554,6 @@ tty_check_bg(struct tty *tty, struct grid_cell *gc)
|
||||
if (colours >= 16)
|
||||
gc->fg += 90;
|
||||
}
|
||||
gc->flags &= ~GRID_FLAG_BG256;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1648,137 +1567,111 @@ void
|
||||
tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
|
||||
{
|
||||
struct grid_cell *tc = &tty->cell;
|
||||
u_char fg = gc->fg;
|
||||
char s[32];
|
||||
|
||||
tc->flags &= ~(GRID_FLAG_FG256|GRID_FLAG_FGRGB);
|
||||
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->flags & GRID_FLAG_FGRGB) {
|
||||
if (tty_try_rgb(tty, &gc->fg_rgb, "38") == 0)
|
||||
goto save_fg;
|
||||
/* Should not get here, already converted in tty_check_fg. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is this a 256-colour colour? */
|
||||
if (gc->flags & GRID_FLAG_FG256) {
|
||||
if (tty_try_256(tty, fg, "38") == 0)
|
||||
/* Is this a 24-bit or 256-colour colour? */
|
||||
if (gc->fg & COLOUR_FLAG_RGB ||
|
||||
gc->fg & COLOUR_FLAG_256) {
|
||||
if (tty_try_colour(tty, gc->fg, "38") == 0)
|
||||
goto save_fg;
|
||||
/* Should not get here, already converted in tty_check_fg. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is this an aixterm bright colour? */
|
||||
if (fg >= 90 && fg <= 97) {
|
||||
xsnprintf(s, sizeof s, "\033[%dm", fg);
|
||||
if (gc->fg >= 90 && gc->fg <= 97) {
|
||||
xsnprintf(s, sizeof s, "\033[%dm", gc->fg);
|
||||
tty_puts(tty, s);
|
||||
goto save_fg;
|
||||
}
|
||||
|
||||
/* Otherwise set the foreground colour. */
|
||||
tty_putcode1(tty, TTYC_SETAF, fg);
|
||||
tty_putcode1(tty, TTYC_SETAF, gc->fg);
|
||||
|
||||
save_fg:
|
||||
/* Save the new values in the terminal current cell. */
|
||||
if (gc->flags & GRID_FLAG_FGRGB)
|
||||
memcpy(&tc->fg_rgb, &gc->fg_rgb, sizeof tc->fg_rgb);
|
||||
else
|
||||
tc->fg = fg;
|
||||
tc->flags &= ~(GRID_FLAG_FGRGB|GRID_FLAG_FG256);
|
||||
tc->flags |= (gc->flags & (GRID_FLAG_FG256|GRID_FLAG_FGRGB));
|
||||
tc->fg = gc->fg;
|
||||
}
|
||||
|
||||
void
|
||||
tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
|
||||
{
|
||||
struct grid_cell *tc = &tty->cell;
|
||||
u_char bg = gc->bg;
|
||||
char s[32];
|
||||
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->flags & GRID_FLAG_BGRGB) {
|
||||
if (tty_try_rgb(tty, &gc->bg_rgb, "48") == 0)
|
||||
goto save_bg;
|
||||
/* Should not get here, already converted in tty_check_bg. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is this a 256-colour colour? */
|
||||
if (gc->flags & GRID_FLAG_BG256) {
|
||||
if (tty_try_256(tty, bg, "48") == 0)
|
||||
/* Is this a 24-bit or 256-colour colour? */
|
||||
if (gc->bg & COLOUR_FLAG_RGB ||
|
||||
gc->bg & COLOUR_FLAG_256) {
|
||||
if (tty_try_colour(tty, gc->bg, "48") == 0)
|
||||
goto save_bg;
|
||||
/* Should not get here, already converted in tty_check_bg. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is this an aixterm bright colour? */
|
||||
if (bg >= 90 && bg <= 97) {
|
||||
xsnprintf(s, sizeof s, "\033[%dm", bg + 10);
|
||||
if (gc->bg >= 90 && gc->bg <= 97) {
|
||||
xsnprintf(s, sizeof s, "\033[%dm", gc->bg + 10);
|
||||
tty_puts(tty, s);
|
||||
goto save_bg;
|
||||
}
|
||||
|
||||
/* Otherwise set the background colour. */
|
||||
tty_putcode1(tty, TTYC_SETAB, bg);
|
||||
tty_putcode1(tty, TTYC_SETAB, gc->bg);
|
||||
|
||||
save_bg:
|
||||
/* Save the new values in the terminal current cell. */
|
||||
if (gc->flags & GRID_FLAG_BGRGB)
|
||||
memcpy(&tc->bg_rgb, &gc->bg_rgb, sizeof tc->bg_rgb);
|
||||
else
|
||||
tc->bg = bg;
|
||||
tc->flags &= ~(GRID_FLAG_BGRGB|GRID_FLAG_BG256);
|
||||
tc->flags |= (gc->flags & (GRID_FLAG_BG256|GRID_FLAG_BGRGB));
|
||||
tc->bg = gc->bg;
|
||||
}
|
||||
|
||||
int
|
||||
tty_try_256(struct tty *tty, u_char colour, const char *type)
|
||||
tty_try_colour(struct tty *tty, int colour, const char *type)
|
||||
{
|
||||
u_char r, g, b;
|
||||
char s[32];
|
||||
|
||||
/*
|
||||
* If the user has specified -2 to the client, setaf and setab may not
|
||||
* work (or they may not want to use them), so send the usual sequence.
|
||||
*/
|
||||
if (tty->term_flags & TERM_256COLOURS)
|
||||
goto fallback;
|
||||
if (colour & COLOUR_FLAG_256) {
|
||||
/*
|
||||
* If the user has specified -2 to the client, setaf and setab
|
||||
* may not work (or they may not want to use them), so send the
|
||||
* usual sequence.
|
||||
*/
|
||||
if (tty->term_flags & TERM_256COLOURS)
|
||||
goto fallback_256;
|
||||
|
||||
/*
|
||||
* If the terminfo entry has 256 colours and setaf and setab exist,
|
||||
* assume that they work correctly.
|
||||
*/
|
||||
if (tty->term->flags & TERM_256COLOURS) {
|
||||
if (*type == '3') {
|
||||
if (!tty_term_has(tty->term, TTYC_SETAF))
|
||||
goto fallback;
|
||||
tty_putcode1(tty, TTYC_SETAF, colour);
|
||||
} else {
|
||||
if (!tty_term_has(tty->term, TTYC_SETAB))
|
||||
goto fallback;
|
||||
tty_putcode1(tty, TTYC_SETAB, colour);
|
||||
/*
|
||||
* If the terminfo entry has 256 colours and setaf and setab
|
||||
* exist, assume that they work correctly.
|
||||
*/
|
||||
if (tty->term->flags & TERM_256COLOURS) {
|
||||
if (*type == '3') {
|
||||
if (!tty_term_has(tty->term, TTYC_SETAF))
|
||||
goto fallback_256;
|
||||
tty_putcode1(tty, TTYC_SETAF, colour & 0xff);
|
||||
} else {
|
||||
if (!tty_term_has(tty->term, TTYC_SETAB))
|
||||
goto fallback_256;
|
||||
tty_putcode1(tty, TTYC_SETAB, colour & 0xff);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
goto fallback_256;
|
||||
}
|
||||
|
||||
if (colour & COLOUR_FLAG_RGB) {
|
||||
if (!tty_term_flag(tty->term, TTYC_TC))
|
||||
return (-1);
|
||||
|
||||
colour_split_rgb(colour & 0xffffff, &r, &g, &b);
|
||||
xsnprintf(s, sizeof s, "\033[%s;2;%hhu;%hhu;%hhum", type,
|
||||
r, g, b);
|
||||
tty_puts(tty, s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
|
||||
fallback:
|
||||
xsnprintf(s, sizeof s, "\033[%s;5;%hhum", type, colour);
|
||||
tty_puts(tty, s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
tty_try_rgb(struct tty *tty, const struct grid_cell_rgb *rgb, const char *type)
|
||||
{
|
||||
char s[32];
|
||||
|
||||
if (!tty_term_flag(tty->term, TTYC_TC))
|
||||
return (-1);
|
||||
|
||||
xsnprintf(s, sizeof s, "\033[%s;2;%hhu;%hhu;%hhum", type, rgb->r,
|
||||
rgb->g, rgb->b);
|
||||
fallback_256:
|
||||
xsnprintf(s, sizeof s, "\033[%s;5;%dm", type, colour & 0xff);
|
||||
tty_puts(tty, s);
|
||||
return (0);
|
||||
}
|
||||
@@ -1786,40 +1679,37 @@ tty_try_rgb(struct tty *tty, const struct grid_cell_rgb *rgb, const char *type)
|
||||
void
|
||||
tty_default_colours(struct grid_cell *gc, const struct window_pane *wp)
|
||||
{
|
||||
const struct grid_cell *agc, *pgc, *wgc;
|
||||
|
||||
if (wp == NULL)
|
||||
return;
|
||||
struct window *w = wp->window;
|
||||
struct options *oo = w->options;
|
||||
const struct grid_cell *agc, *pgc, *wgc;
|
||||
|
||||
if (w->flags & WINDOW_STYLECHANGED) {
|
||||
w->flags &= ~WINDOW_STYLECHANGED;
|
||||
agc = options_get_style(oo, "window-active-style");
|
||||
memcpy(&w->active_style, agc, sizeof w->active_style);
|
||||
wgc = options_get_style(oo, "window-style");
|
||||
memcpy(&w->style, wgc, sizeof w->style);
|
||||
} else {
|
||||
agc = &w->active_style;
|
||||
wgc = &w->style;
|
||||
}
|
||||
pgc = &wp->colgc;
|
||||
agc = options_get_style(wp->window->options, "window-active-style");
|
||||
wgc = options_get_style(wp->window->options, "window-style");
|
||||
|
||||
if (gc->fg == 8 && !(gc->flags & GRID_FLAG_FG256)) {
|
||||
if (pgc->fg != 8 || (pgc->flags & GRID_FLAG_FG256)) {
|
||||
if (gc->fg == 8) {
|
||||
if (pgc->fg != 8)
|
||||
gc->fg = pgc->fg;
|
||||
gc->flags |= (pgc->flags & GRID_FLAG_FG256);
|
||||
} else if (wp == wp->window->active &&
|
||||
(agc->fg != 8 || (agc->flags & GRID_FLAG_FG256))) {
|
||||
else if (wp == w->active && agc->fg != 8)
|
||||
gc->fg = agc->fg;
|
||||
gc->flags |= (agc->flags & GRID_FLAG_FG256);
|
||||
} else {
|
||||
else
|
||||
gc->fg = wgc->fg;
|
||||
gc->flags |= (wgc->flags & GRID_FLAG_FG256);
|
||||
}
|
||||
}
|
||||
|
||||
if (gc->bg == 8 && !(gc->flags & GRID_FLAG_BG256)) {
|
||||
if (pgc->bg != 8 || (pgc->flags & GRID_FLAG_BG256)) {
|
||||
if (gc->bg == 8) {
|
||||
if (pgc->bg != 8)
|
||||
gc->bg = pgc->bg;
|
||||
gc->flags |= (pgc->flags & GRID_FLAG_BG256);
|
||||
} else if (wp == wp->window->active &&
|
||||
(agc->bg != 8 || (agc->flags & GRID_FLAG_BG256))) {
|
||||
else if (wp == w->active && agc->bg != 8)
|
||||
gc->bg = agc->bg;
|
||||
gc->flags |= (agc->flags & GRID_FLAG_BG256);
|
||||
} else {
|
||||
else
|
||||
gc->bg = wgc->bg;
|
||||
gc->flags |= (wgc->flags & GRID_FLAG_BG256);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
43
utf8.c
43
utf8.c
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
@@ -30,16 +31,10 @@ static int utf8_width(wchar_t);
|
||||
void
|
||||
utf8_set(struct utf8_data *ud, u_char ch)
|
||||
{
|
||||
u_int i;
|
||||
static const struct utf8_data empty = { { 0 }, 1, 1, 1 };
|
||||
|
||||
memcpy(ud, &empty, sizeof *ud);
|
||||
*ud->data = ch;
|
||||
ud->have = 1;
|
||||
ud->size = 1;
|
||||
|
||||
ud->width = 1;
|
||||
|
||||
for (i = ud->size; i < sizeof ud->data; i++)
|
||||
ud->data[i] = '\0';
|
||||
}
|
||||
|
||||
/* Copy UTF-8 character. */
|
||||
@@ -114,9 +109,29 @@ utf8_width(wchar_t wc)
|
||||
{
|
||||
int width;
|
||||
|
||||
#ifdef HAVE_UTF8PROC
|
||||
width = utf8proc_wcwidth(wc);
|
||||
#else
|
||||
width = wcwidth(wc);
|
||||
if (width < 0 || width > 0xff)
|
||||
#endif
|
||||
if (width < 0 || width > 0xff) {
|
||||
log_debug("Unicode %04x, wcwidth() %d", wc, width);
|
||||
|
||||
#ifndef __OpenBSD__
|
||||
/*
|
||||
* Many platforms (particularly and inevitably OS X) have no
|
||||
* width for relatively common characters (wcwidth() returns
|
||||
* -1); assume width 1 in this case. This will be wrong for
|
||||
* genuinely nonprintable characters, but they should be
|
||||
* rare. We may pass through stuff that ideally we would block,
|
||||
* but this is no worse than sending the same to the terminal
|
||||
* without tmux.
|
||||
*/
|
||||
if (width < 0)
|
||||
return (1);
|
||||
#endif
|
||||
return (-1);
|
||||
}
|
||||
return (width);
|
||||
}
|
||||
|
||||
@@ -124,8 +139,14 @@ utf8_width(wchar_t wc)
|
||||
enum utf8_state
|
||||
utf8_combine(const struct utf8_data *ud, wchar_t *wc)
|
||||
{
|
||||
#ifdef HAVE_UTF8PROC
|
||||
switch (utf8proc_mbtowc(wc, ud->data, ud->size)) {
|
||||
#else
|
||||
switch (mbtowc(wc, ud->data, ud->size)) {
|
||||
#endif
|
||||
case -1:
|
||||
log_debug("UTF-8 %.*s, mbtowc() %d", (int)ud->size, ud->data,
|
||||
errno);
|
||||
mbtowc(NULL, NULL, MB_CUR_MAX);
|
||||
return (UTF8_ERROR);
|
||||
case 0:
|
||||
@@ -142,7 +163,11 @@ utf8_split(wchar_t wc, struct utf8_data *ud)
|
||||
char s[MB_LEN_MAX];
|
||||
int slen;
|
||||
|
||||
#ifdef HAVE_UTF8PROC
|
||||
slen = utf8proc_wctomb(s, wc);
|
||||
#else
|
||||
slen = wctomb(s, wc);
|
||||
#endif
|
||||
if (slen <= 0 || slen > (int)sizeof ud->data)
|
||||
return (UTF8_ERROR);
|
||||
|
||||
|
||||
154
window-choose.c
154
window-choose.c
@@ -22,7 +22,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "array.h"
|
||||
#include "tmux.h"
|
||||
|
||||
struct screen *window_choose_init(struct window_pane *);
|
||||
@@ -72,8 +71,11 @@ struct window_choose_mode_data {
|
||||
|
||||
struct mode_key_data mdata;
|
||||
|
||||
ARRAY_DECL(, struct window_choose_mode_item) list;
|
||||
ARRAY_DECL(, struct window_choose_mode_item) old_list;
|
||||
struct window_choose_mode_item *list;
|
||||
u_int list_size;
|
||||
struct window_choose_mode_item *old_list;
|
||||
u_int old_list_size;
|
||||
|
||||
int width;
|
||||
u_int top;
|
||||
u_int selected;
|
||||
@@ -96,17 +98,18 @@ window_choose_add(struct window_pane *wp, struct window_choose_data *wcd)
|
||||
{
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
struct window_choose_mode_item *item;
|
||||
char tmp[10];
|
||||
char tmp[11];
|
||||
|
||||
ARRAY_EXPAND(&data->list, 1);
|
||||
item = &ARRAY_LAST(&data->list);
|
||||
data->list = xreallocarray(data->list, data->list_size + 1,
|
||||
sizeof *data->list);
|
||||
item = &data->list[data->list_size++];
|
||||
|
||||
item->name = format_expand(wcd->ft, wcd->ft_template);
|
||||
item->wcd = wcd;
|
||||
item->pos = ARRAY_LENGTH(&data->list) - 1;
|
||||
item->pos = data->list_size - 1;
|
||||
item->state = 0;
|
||||
|
||||
data->width = xsnprintf(tmp, sizeof tmp , "%d", item->pos);
|
||||
data->width = xsnprintf(tmp, sizeof tmp, "%d", item->pos);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -136,12 +139,18 @@ window_choose_ready(struct window_pane *wp, u_int cur,
|
||||
void (*callbackfn)(struct window_choose_data *))
|
||||
{
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
u_int size;
|
||||
|
||||
data->callbackfn = callbackfn;
|
||||
if (data->callbackfn == NULL)
|
||||
data->callbackfn = window_choose_default_callback;
|
||||
|
||||
ARRAY_CONCAT(&data->old_list, &data->list);
|
||||
size = data->old_list_size;
|
||||
data->old_list_size += data->list_size;
|
||||
data->old_list = xreallocarray(data->old_list, data->old_list_size,
|
||||
sizeof *data->old_list);
|
||||
memcpy(data->old_list + size, data->list, data->list_size *
|
||||
sizeof *data->list);
|
||||
|
||||
window_choose_set_current(wp, cur);
|
||||
window_choose_collapse_all(wp);
|
||||
@@ -154,15 +163,19 @@ window_choose_init(struct window_pane *wp)
|
||||
struct screen *s;
|
||||
int keys;
|
||||
|
||||
wp->modedata = data = xmalloc(sizeof *data);
|
||||
wp->modedata = data = xcalloc(1, sizeof *data);
|
||||
|
||||
data->callbackfn = NULL;
|
||||
data->input_type = WINDOW_CHOOSE_NORMAL;
|
||||
data->input_str = xstrdup("");
|
||||
data->input_prompt = NULL;
|
||||
|
||||
ARRAY_INIT(&data->list);
|
||||
ARRAY_INIT(&data->old_list);
|
||||
data->list = NULL;
|
||||
data->list_size = 0;
|
||||
|
||||
data->old_list = NULL;
|
||||
data->old_list_size = 0;
|
||||
|
||||
data->top = 0;
|
||||
|
||||
s = &data->screen;
|
||||
@@ -274,13 +287,14 @@ window_choose_free1(struct window_choose_mode_data *data)
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&data->old_list); i++) {
|
||||
item = &ARRAY_ITEM(&data->old_list, i);
|
||||
for (i = 0; i < data->old_list_size; i++) {
|
||||
item = &data->old_list[i];
|
||||
window_choose_data_free(item->wcd);
|
||||
free(item->name);
|
||||
}
|
||||
ARRAY_FREE(&data->list);
|
||||
ARRAY_FREE(&data->old_list);
|
||||
free(data->list);
|
||||
free(data->old_list);
|
||||
|
||||
free(data->input_str);
|
||||
|
||||
screen_free(&data->screen);
|
||||
@@ -334,14 +348,11 @@ void
|
||||
window_choose_collapse(struct window_pane *wp, struct session *s, u_int pos)
|
||||
{
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
struct window_choose_mode_item *item, *chosen;
|
||||
struct window_choose_mode_item *item, *chosen, *copy = NULL;
|
||||
struct window_choose_data *wcd;
|
||||
u_int i;
|
||||
u_int i, copy_size = 0;
|
||||
|
||||
ARRAY_DECL(, struct window_choose_mode_item) list_copy;
|
||||
ARRAY_INIT(&list_copy);
|
||||
|
||||
chosen = &ARRAY_ITEM(&data->list, pos);
|
||||
chosen = &data->list[pos];
|
||||
chosen->state &= ~TREE_EXPANDED;
|
||||
|
||||
/*
|
||||
@@ -349,15 +360,19 @@ window_choose_collapse(struct window_pane *wp, struct session *s, u_int pos)
|
||||
* assign the actual result we want to render and copy the new one over
|
||||
* the top of it.
|
||||
*/
|
||||
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) {
|
||||
item = &ARRAY_ITEM(&data->list, i);
|
||||
for (i = 0; i < data->list_size; i++) {
|
||||
item = &data->list[i];
|
||||
wcd = item->wcd;
|
||||
|
||||
if (s == wcd->tree_session) {
|
||||
/* We only show the session when collapsed. */
|
||||
if (wcd->type & TREE_SESSION) {
|
||||
item->state &= ~TREE_EXPANDED;
|
||||
ARRAY_ADD(&list_copy, *item);
|
||||
|
||||
copy = xreallocarray(copy, copy_size + 1,
|
||||
sizeof *copy);
|
||||
memcpy(©[copy_size], item, sizeof *copy);
|
||||
copy_size++;
|
||||
|
||||
/*
|
||||
* Update the selection to this session item so
|
||||
@@ -366,14 +381,17 @@ window_choose_collapse(struct window_pane *wp, struct session *s, u_int pos)
|
||||
*/
|
||||
data->selected = i;
|
||||
}
|
||||
} else
|
||||
ARRAY_ADD(&list_copy, ARRAY_ITEM(&data->list, i));
|
||||
} else {
|
||||
copy = xreallocarray(copy, copy_size + 1, sizeof *copy);
|
||||
memcpy(©[copy_size], item, sizeof *copy);
|
||||
copy_size++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ARRAY_EMPTY(&list_copy)) {
|
||||
ARRAY_FREE(&data->list);
|
||||
ARRAY_CONCAT(&data->list, &list_copy);
|
||||
ARRAY_FREE(&list_copy);
|
||||
if (copy_size != 0) {
|
||||
free(data->list);
|
||||
data->list = copy;
|
||||
data->list_size = copy_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,14 +404,14 @@ window_choose_collapse_all(struct window_pane *wp)
|
||||
struct session *s, *chosen;
|
||||
u_int i;
|
||||
|
||||
chosen = ARRAY_ITEM(&data->list, data->selected).wcd->start_session;
|
||||
chosen = data->list[data->selected].wcd->start_session;
|
||||
|
||||
RB_FOREACH(s, sessions, &sessions)
|
||||
window_choose_collapse(wp, s, data->selected);
|
||||
|
||||
/* Reset the selection back to the starting session. */
|
||||
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) {
|
||||
item = &ARRAY_ITEM(&data->list, i);
|
||||
for (i = 0; i < data->list_size; i++) {
|
||||
item = &data->list[i];
|
||||
|
||||
if (chosen != item->wcd->tree_session)
|
||||
continue;
|
||||
@@ -414,8 +432,8 @@ window_choose_expand_all(struct window_pane *wp)
|
||||
u_int i;
|
||||
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) {
|
||||
item = &ARRAY_ITEM(&data->list, i);
|
||||
for (i = 0; i < data->list_size; i++) {
|
||||
item = &data->list[i];
|
||||
|
||||
if (s != item->wcd->tree_session)
|
||||
continue;
|
||||
@@ -436,8 +454,8 @@ window_choose_expand(struct window_pane *wp, struct session *s, u_int pos)
|
||||
struct window_choose_data *wcd;
|
||||
u_int i, items;
|
||||
|
||||
chosen = &ARRAY_ITEM(&data->list, pos);
|
||||
items = ARRAY_LENGTH(&data->old_list) - 1;
|
||||
chosen = &data->list[pos];
|
||||
items = data->old_list_size - 1;
|
||||
|
||||
/* It's not possible to expand anything other than sessions. */
|
||||
if (!(chosen->wcd->type & TREE_SESSION))
|
||||
@@ -456,7 +474,7 @@ window_choose_expand(struct window_pane *wp, struct session *s, u_int pos)
|
||||
* to expand.
|
||||
*/
|
||||
for (i = items; i > 0; i--) {
|
||||
item = &ARRAY_ITEM(&data->old_list, i);
|
||||
item = &data->old_list[i];
|
||||
item->state |= TREE_EXPANDED;
|
||||
wcd = item->wcd;
|
||||
|
||||
@@ -473,16 +491,27 @@ window_choose_expand(struct window_pane *wp, struct session *s, u_int pos)
|
||||
* entries in order *AFTER* the selected
|
||||
* session.
|
||||
*/
|
||||
if (pos < i ) {
|
||||
ARRAY_INSERT(&data->list,
|
||||
pos + 1,
|
||||
ARRAY_ITEM(&data->old_list,
|
||||
i));
|
||||
if (pos < i) {
|
||||
data->list = xreallocarray(data->list,
|
||||
data->list_size + 1,
|
||||
sizeof *data->list);
|
||||
memmove(&data->list[pos + 2],
|
||||
&data->list[pos + 1],
|
||||
(data->list_size - (pos + 1)) *
|
||||
sizeof *data->list);
|
||||
memcpy(&data->list[pos + 1],
|
||||
&data->old_list[i],
|
||||
sizeof *data->list);
|
||||
data->list_size++;
|
||||
} else {
|
||||
/* Ran out of room, add to the end. */
|
||||
ARRAY_ADD(&data->list,
|
||||
ARRAY_ITEM(&data->old_list,
|
||||
i));
|
||||
data->list = xreallocarray(data->list,
|
||||
data->list_size + 1,
|
||||
sizeof *data->list);
|
||||
memcpy(&data->list[data->list_size],
|
||||
&data->old_list[i],
|
||||
sizeof *data->list);
|
||||
data->list_size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,15 +526,15 @@ window_choose_get_item(struct window_pane *wp, key_code key,
|
||||
u_int x, y, idx;
|
||||
|
||||
if (!KEYC_IS_MOUSE(key))
|
||||
return (&ARRAY_ITEM(&data->list, data->selected));
|
||||
return (&data->list[data->selected]);
|
||||
|
||||
if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
|
||||
return (NULL);
|
||||
|
||||
idx = data->top + y;
|
||||
if (idx >= ARRAY_LENGTH(&data->list))
|
||||
if (idx >= data->list_size)
|
||||
return (NULL);
|
||||
return (&ARRAY_ITEM(&data->list, idx));
|
||||
return (&data->list[idx]);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -520,10 +549,10 @@ window_choose_key(struct window_pane *wp, __unused struct client *c,
|
||||
u_int items, n;
|
||||
int idx;
|
||||
|
||||
items = ARRAY_LENGTH(&data->list);
|
||||
items = data->list_size;
|
||||
|
||||
if (data->input_type == WINDOW_CHOOSE_GOTO_ITEM) {
|
||||
switch (mode_key_lookup(&data->mdata, key, NULL)) {
|
||||
switch (mode_key_lookup(&data->mdata, key, NULL, NULL)) {
|
||||
case MODEKEYCHOICE_CANCEL:
|
||||
data->input_type = WINDOW_CHOOSE_NORMAL;
|
||||
window_choose_redraw_screen(wp);
|
||||
@@ -535,8 +564,7 @@ window_choose_key(struct window_pane *wp, __unused struct client *c,
|
||||
window_choose_redraw_screen(wp);
|
||||
break;
|
||||
}
|
||||
item = &ARRAY_ITEM(&data->list, n);
|
||||
window_choose_fire_callback(wp, item->wcd);
|
||||
window_choose_fire_callback(wp, data->list[n].wcd);
|
||||
break;
|
||||
case MODEKEYCHOICE_BACKSPACE:
|
||||
input_len = strlen(data->input_str);
|
||||
@@ -554,7 +582,7 @@ window_choose_key(struct window_pane *wp, __unused struct client *c,
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mode_key_lookup(&data->mdata, key, NULL)) {
|
||||
switch (mode_key_lookup(&data->mdata, key, NULL, NULL)) {
|
||||
case MODEKEYCHOICE_CANCEL:
|
||||
window_choose_fire_callback(wp, NULL);
|
||||
break;
|
||||
@@ -733,12 +761,10 @@ window_choose_key(struct window_pane *wp, __unused struct client *c,
|
||||
break;
|
||||
default:
|
||||
idx = window_choose_index_key(data, key);
|
||||
if (idx < 0 || (u_int) idx >= ARRAY_LENGTH(&data->list))
|
||||
if (idx < 0 || (u_int) idx >= data->list_size)
|
||||
break;
|
||||
data->selected = idx;
|
||||
|
||||
item = &ARRAY_ITEM(&data->list, data->selected);
|
||||
window_choose_fire_callback(wp, item->wcd);
|
||||
window_choose_fire_callback(wp, data->list[idx].wcd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -765,8 +791,8 @@ window_choose_write_line(struct window_pane *wp, struct screen_write_ctx *ctx,
|
||||
style_apply(&gc, oo, "mode-style");
|
||||
|
||||
screen_write_cursormove(ctx, 0, py);
|
||||
if (data->top + py < ARRAY_LENGTH(&data->list)) {
|
||||
item = &ARRAY_ITEM(&data->list, data->top + py);
|
||||
if (data->top + py < data->list_size) {
|
||||
item = &data->list[data->top + py];
|
||||
if (item->wcd->wl != NULL &&
|
||||
item->wcd->wl->flags & WINLINK_ALERTFLAGS)
|
||||
gc.attr |= GRID_ATTR_BRIGHT;
|
||||
@@ -811,7 +837,7 @@ window_choose_key_index(struct window_choose_mode_data *data, u_int idx)
|
||||
int mkey;
|
||||
|
||||
for (ptr = keys; *ptr != '\0'; ptr++) {
|
||||
mkey = mode_key_lookup(&data->mdata, *ptr, NULL);
|
||||
mkey = mode_key_lookup(&data->mdata, *ptr, NULL, NULL);
|
||||
if (mkey != MODEKEY_NONE && mkey != MODEKEY_OTHER)
|
||||
continue;
|
||||
if (idx-- == 0)
|
||||
@@ -831,7 +857,7 @@ window_choose_index_key(struct window_choose_mode_data *data, key_code key)
|
||||
u_int idx = 0;
|
||||
|
||||
for (ptr = keys; *ptr != '\0'; ptr++) {
|
||||
mkey = mode_key_lookup(&data->mdata, *ptr, NULL);
|
||||
mkey = mode_key_lookup(&data->mdata, *ptr, NULL, NULL);
|
||||
if (mkey != MODEKEY_NONE && mkey != MODEKEY_OTHER)
|
||||
continue;
|
||||
if (key == (key_code)*ptr)
|
||||
@@ -881,7 +907,7 @@ window_choose_scroll_down(struct window_pane *wp)
|
||||
struct screen *s = &data->screen;
|
||||
struct screen_write_ctx ctx;
|
||||
|
||||
if (data->top >= ARRAY_LENGTH(&data->list))
|
||||
if (data->top >= data->list_size)
|
||||
return;
|
||||
data->top++;
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ window_clock_draw_screen(struct window_pane *wp)
|
||||
screen_write_cursormove(&ctx, x, y);
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
colour_set_fg(&gc, colour);
|
||||
gc.fg = colour;
|
||||
screen_write_puts(&ctx, &gc, "%s", tim);
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ window_clock_draw_screen(struct window_pane *wp)
|
||||
y = (screen_size_y(s) / 2) - 3;
|
||||
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
colour_set_bg(&gc, colour);
|
||||
gc.bg = colour;
|
||||
for (ptr = tim; *ptr != '\0'; ptr++) {
|
||||
if (*ptr >= '0' && *ptr <= '9')
|
||||
idx = *ptr - '0';
|
||||
|
||||
372
window-copy.c
372
window-copy.c
@@ -26,7 +26,9 @@
|
||||
|
||||
struct screen *window_copy_init(struct window_pane *);
|
||||
void window_copy_free(struct window_pane *);
|
||||
void window_copy_pagedown(struct window_pane *);
|
||||
void window_copy_pagedown(struct window_pane *, int);
|
||||
void window_copy_next_paragraph(struct window_pane *);
|
||||
void window_copy_previous_paragraph(struct window_pane *);
|
||||
void window_copy_resize(struct window_pane *, u_int, u_int);
|
||||
void window_copy_key(struct window_pane *, struct client *, struct session *,
|
||||
key_code, struct mouse_event *);
|
||||
@@ -48,8 +50,14 @@ int window_copy_search_lr(struct grid *, struct grid *, u_int *, u_int,
|
||||
u_int, u_int, int);
|
||||
int window_copy_search_rl(struct grid *, struct grid *, u_int *, u_int,
|
||||
u_int, u_int, int);
|
||||
void window_copy_search_up(struct window_pane *, const char *);
|
||||
void window_copy_search_down(struct window_pane *, const char *);
|
||||
void window_copy_move_left(struct screen *, u_int *, u_int *);
|
||||
void window_copy_move_right(struct screen *, u_int *, u_int *);
|
||||
int window_copy_is_lowercase(const char *);
|
||||
void window_copy_search_jump(struct window_pane *, struct grid *,
|
||||
struct grid *, u_int, u_int, u_int, int, int, int);
|
||||
void window_copy_search(struct window_pane *, const char *, int, int);
|
||||
void window_copy_search_up(struct window_pane *, const char *, int);
|
||||
void window_copy_search_down(struct window_pane *, const char *, int);
|
||||
void window_copy_goto_line(struct window_pane *, const char *);
|
||||
void window_copy_update_cursor(struct window_pane *, u_int, u_int);
|
||||
void window_copy_start_selection(struct window_pane *);
|
||||
@@ -321,7 +329,7 @@ window_copy_vadd(struct window_pane *wp, const char *fmt, va_list ap)
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_pageup(struct window_pane *wp)
|
||||
window_copy_pageup(struct window_pane *wp, int half_page)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
@@ -340,8 +348,12 @@ window_copy_pageup(struct window_pane *wp)
|
||||
data->cx = data->lastcx;
|
||||
|
||||
n = 1;
|
||||
if (screen_size_y(s) > 2)
|
||||
n = screen_size_y(s) - 2;
|
||||
if (screen_size_y(s) > 2) {
|
||||
if (half_page)
|
||||
n = screen_size_y(s) / 2;
|
||||
else
|
||||
n = screen_size_y(s) - 2;
|
||||
}
|
||||
|
||||
if (data->oy + n > screen_hsize(data->backing))
|
||||
data->oy = screen_hsize(data->backing);
|
||||
@@ -360,7 +372,7 @@ window_copy_pageup(struct window_pane *wp)
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_pagedown(struct window_pane *wp)
|
||||
window_copy_pagedown(struct window_pane *wp, int half_page)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
@@ -379,8 +391,12 @@ window_copy_pagedown(struct window_pane *wp)
|
||||
data->cx = data->lastcx;
|
||||
|
||||
n = 1;
|
||||
if (screen_size_y(s) > 2)
|
||||
n = screen_size_y(s) - 2;
|
||||
if (screen_size_y(s) > 2) {
|
||||
if (half_page)
|
||||
n = screen_size_y(s) / 2;
|
||||
else
|
||||
n = screen_size_y(s) - 2;
|
||||
}
|
||||
|
||||
if (data->oy < n)
|
||||
data->oy = 0;
|
||||
@@ -403,6 +419,43 @@ window_copy_pagedown(struct window_pane *wp)
|
||||
window_copy_redraw_screen(wp);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_previous_paragraph(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
u_int oy;
|
||||
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
|
||||
while (oy > 0 && window_copy_find_length(wp, oy) == 0)
|
||||
oy--;
|
||||
|
||||
while (oy > 0 && window_copy_find_length(wp, oy) > 0)
|
||||
oy--;
|
||||
|
||||
window_copy_scroll_to(wp, 0, oy);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_next_paragraph(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
u_int maxy, ox, oy;
|
||||
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
maxy = screen_hsize(data->backing) + screen_size_y(s) - 1;
|
||||
|
||||
while (oy < maxy && window_copy_find_length(wp, oy) == 0)
|
||||
oy++;
|
||||
|
||||
while (oy < maxy && window_copy_find_length(wp, oy) > 0)
|
||||
oy++;
|
||||
|
||||
ox = window_copy_find_length(wp, oy);
|
||||
window_copy_scroll_to(wp, ox, oy);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
{
|
||||
@@ -437,7 +490,7 @@ window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
|
||||
const char *word_separators;
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
u_int n, np;
|
||||
u_int np;
|
||||
int keys;
|
||||
enum mode_key_cmd cmd;
|
||||
const char *arg, *ss;
|
||||
@@ -485,7 +538,9 @@ window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
|
||||
return;
|
||||
}
|
||||
|
||||
cmd = mode_key_lookup(&data->mdata, key, &arg);
|
||||
cmd = mode_key_lookup(&data->mdata, key, &arg, &np);
|
||||
if (data->numprefix > 0)
|
||||
np = data->numprefix;
|
||||
if (cmd != MODEKEYCOPY_PREVIOUSPAGE &&
|
||||
cmd != MODEKEYCOPY_NEXTPAGE &&
|
||||
cmd != MODEKEYCOPY_SCROLLUP &&
|
||||
@@ -542,37 +597,27 @@ window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
|
||||
break;
|
||||
case MODEKEYCOPY_PREVIOUSPAGE:
|
||||
for (; np != 0; np--)
|
||||
window_copy_pageup(wp);
|
||||
window_copy_pageup(wp, 0);
|
||||
break;
|
||||
case MODEKEYCOPY_NEXTPAGE:
|
||||
for (; np != 0; np--)
|
||||
window_copy_pagedown(wp);
|
||||
window_copy_pagedown(wp, 0);
|
||||
break;
|
||||
case MODEKEYCOPY_PREVIOUSPARAGRAPH:
|
||||
for (; np != 0; np--)
|
||||
window_copy_previous_paragraph(wp);
|
||||
break;
|
||||
case MODEKEYCOPY_NEXTPARAGRAPH:
|
||||
for (; np != 0; np--)
|
||||
window_copy_next_paragraph(wp);
|
||||
break;
|
||||
case MODEKEYCOPY_HALFPAGEUP:
|
||||
n = screen_size_y(s) / 2;
|
||||
for (; np != 0; np--) {
|
||||
if (data->oy + n > screen_hsize(data->backing))
|
||||
data->oy = screen_hsize(data->backing);
|
||||
else
|
||||
data->oy += n;
|
||||
}
|
||||
window_copy_update_selection(wp, 1);
|
||||
window_copy_redraw_screen(wp);
|
||||
for (; np != 0; np--)
|
||||
window_copy_pageup(wp, 1);
|
||||
break;
|
||||
case MODEKEYCOPY_HALFPAGEDOWN:
|
||||
n = screen_size_y(s) / 2;
|
||||
for (; np != 0; np--) {
|
||||
if (data->oy < n)
|
||||
data->oy = 0;
|
||||
else
|
||||
data->oy -= n;
|
||||
}
|
||||
if (data->scroll_exit && data->oy == 0) {
|
||||
window_pane_reset_mode(wp);
|
||||
return;
|
||||
}
|
||||
window_copy_update_selection(wp, 1);
|
||||
window_copy_redraw_screen(wp);
|
||||
for (; np != 0; np--)
|
||||
window_copy_pagedown(wp, 1);
|
||||
break;
|
||||
case MODEKEYCOPY_TOPLINE:
|
||||
data->cx = 0;
|
||||
@@ -778,20 +823,20 @@ window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
|
||||
ss = data->searchstr;
|
||||
if (cmd == MODEKEYCOPY_SEARCHAGAIN) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wp, ss);
|
||||
window_copy_search_up(wp, ss, 1);
|
||||
} else {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wp, ss);
|
||||
window_copy_search_down(wp, ss, 1);
|
||||
}
|
||||
break;
|
||||
case WINDOW_COPY_SEARCHDOWN:
|
||||
ss = data->searchstr;
|
||||
if (cmd == MODEKEYCOPY_SEARCHAGAIN) {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wp, ss);
|
||||
window_copy_search_down(wp, ss, 1);
|
||||
} else {
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wp, ss);
|
||||
window_copy_search_up(wp, ss, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -857,11 +902,11 @@ window_copy_key_input(struct window_pane *wp, key_code key)
|
||||
struct screen *s = &data->screen;
|
||||
const char *bufdata;
|
||||
size_t inputlen, n, bufsize;
|
||||
int np;
|
||||
u_int np;
|
||||
struct paste_buffer *pb;
|
||||
u_char ch;
|
||||
|
||||
switch (mode_key_lookup(&data->mdata, key, NULL)) {
|
||||
switch (mode_key_lookup(&data->mdata, key, NULL, &np)) {
|
||||
case MODEKEYEDIT_CANCEL:
|
||||
data->numprefix = -1;
|
||||
return (-1);
|
||||
@@ -889,10 +934,8 @@ window_copy_key_input(struct window_pane *wp, key_code key)
|
||||
data->inputstr[inputlen + n] = '\0';
|
||||
break;
|
||||
case MODEKEYEDIT_ENTER:
|
||||
np = data->numprefix;
|
||||
if (np <= 0)
|
||||
np = 1;
|
||||
|
||||
if (data->numprefix > 0)
|
||||
np = data->numprefix;
|
||||
switch (data->inputtype) {
|
||||
case WINDOW_COPY_OFF:
|
||||
case WINDOW_COPY_JUMPFORWARD:
|
||||
@@ -902,16 +945,16 @@ window_copy_key_input(struct window_pane *wp, key_code key)
|
||||
case WINDOW_COPY_NUMERICPREFIX:
|
||||
break;
|
||||
case WINDOW_COPY_SEARCHUP:
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wp, data->inputstr);
|
||||
data->searchtype = data->inputtype;
|
||||
data->searchstr = xstrdup(data->inputstr);
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_up(wp, data->inputstr, 0);
|
||||
break;
|
||||
case WINDOW_COPY_SEARCHDOWN:
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wp, data->inputstr);
|
||||
data->searchtype = data->inputtype;
|
||||
data->searchstr = xstrdup(data->inputstr);
|
||||
for (; np != 0; np--)
|
||||
window_copy_search_down(wp, data->inputstr, 0);
|
||||
break;
|
||||
case WINDOW_COPY_NAMEDBUFFER:
|
||||
window_copy_copy_selection(wp, data->inputstr);
|
||||
@@ -1063,136 +1106,141 @@ window_copy_search_rl(struct grid *gd,
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_search_up(struct window_pane *wp, const char *searchstr)
|
||||
window_copy_move_left(struct screen *s, u_int *fx, u_int *fy)
|
||||
{
|
||||
if (*fx == 0) { /* left */
|
||||
if (*fy == 0) /* top */
|
||||
return;
|
||||
*fx = screen_size_x(s) - 1;
|
||||
*fy = *fy - 1;
|
||||
} else
|
||||
*fx = *fx - 1;
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_move_right(struct screen *s, u_int *fx, u_int *fy)
|
||||
{
|
||||
if (*fx == screen_size_x(s) - 1) { /* right */
|
||||
if (*fy == screen_hsize(s) + screen_size_y(s)) /* bottom */
|
||||
return;
|
||||
*fx = 0;
|
||||
*fy = *fy + 1;
|
||||
} else
|
||||
*fx = *fx + 1;
|
||||
}
|
||||
|
||||
int
|
||||
window_copy_is_lowercase(const char *ptr)
|
||||
{
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr != tolower((u_char)*ptr))
|
||||
return (0);
|
||||
++ptr;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for text stored in sgd starting from position fx,fy up to endline. If
|
||||
* found, jump to it. If cis then ignore case. The direction is 0 for searching
|
||||
* up, down otherwise. If wrap then go to begin/end of grid and try again if
|
||||
* not found.
|
||||
*/
|
||||
void
|
||||
window_copy_search_jump(struct window_pane *wp, struct grid *gd,
|
||||
struct grid *sgd, u_int fx, u_int fy, u_int endline, int cis, int wrap,
|
||||
int direction)
|
||||
{
|
||||
u_int i, px;
|
||||
int found;
|
||||
|
||||
found = 0;
|
||||
if (direction) {
|
||||
for (i = fy; i <= endline; i++) {
|
||||
found = window_copy_search_lr(gd, sgd, &px, i, fx,
|
||||
gd->sx, cis);
|
||||
if (found)
|
||||
break;
|
||||
fx = 0;
|
||||
}
|
||||
} else {
|
||||
for (i = fy + 1; endline < i; i--) {
|
||||
found = window_copy_search_rl(gd, sgd, &px, i - 1, 0,
|
||||
fx, cis);
|
||||
if (found) {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
fx = gd->sx;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
window_copy_scroll_to(wp, px, i);
|
||||
else if (wrap) {
|
||||
window_copy_search_jump(wp, gd, sgd, direction ? 0 : gd->sx - 1,
|
||||
direction ? 0 : gd->hsize + gd->sy - 1, fy, cis, 0,
|
||||
direction);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Search in for text searchstr. If direction is 0 then search up, otherwise
|
||||
* down. If moveflag is 0 then look for string at the current cursor position
|
||||
* as well.
|
||||
*/
|
||||
void
|
||||
window_copy_search(struct window_pane *wp, const char *searchstr, int direction,
|
||||
int moveflag)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = data->backing, ss;
|
||||
struct screen_write_ctx ctx;
|
||||
struct grid *gd = s->grid, *sgd;
|
||||
struct grid_cell gc;
|
||||
size_t searchlen;
|
||||
u_int i, last, fx, fy, px;
|
||||
int n, wrapped, wrapflag, cis;
|
||||
const char *ptr;
|
||||
|
||||
if (*searchstr == '\0')
|
||||
return;
|
||||
wrapflag = options_get_number(wp->window->options, "wrap-search");
|
||||
searchlen = screen_write_strlen("%s", searchstr);
|
||||
|
||||
screen_init(&ss, searchlen, 1, 0);
|
||||
screen_write_start(&ctx, NULL, &ss);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
screen_write_nputs(&ctx, -1, &gc, "%s", searchstr);
|
||||
screen_write_stop(&ctx);
|
||||
struct grid *gd = s->grid;
|
||||
u_int fx, fy, endline;
|
||||
int wrapflag, cis;
|
||||
|
||||
fx = data->cx;
|
||||
fy = gd->hsize - data->oy + data->cy;
|
||||
fy = screen_hsize(data->backing) - data->oy + data->cy;
|
||||
|
||||
if (fx == 0) {
|
||||
if (fy == 0)
|
||||
return;
|
||||
fx = gd->sx - 1;
|
||||
fy--;
|
||||
} else
|
||||
fx--;
|
||||
n = wrapped = 0;
|
||||
screen_init(&ss, screen_write_strlen("%s", searchstr), 1, 0);
|
||||
screen_write_start(&ctx, NULL, &ss);
|
||||
screen_write_nputs(&ctx, -1, &grid_default_cell, "%s", searchstr);
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
cis = 1;
|
||||
for (ptr = searchstr; *ptr != '\0'; ptr++) {
|
||||
if (*ptr != tolower((u_char)*ptr)) {
|
||||
cis = 0;
|
||||
break;
|
||||
}
|
||||
if (moveflag) {
|
||||
if (direction)
|
||||
window_copy_move_right(s, &fx, &fy);
|
||||
else
|
||||
window_copy_move_left(s, &fx, &fy);
|
||||
}
|
||||
window_copy_clear_selection(wp);
|
||||
|
||||
retry:
|
||||
sgd = ss.grid;
|
||||
for (i = fy + 1; i > 0; i--) {
|
||||
last = screen_size_x(s);
|
||||
if (i == fy + 1)
|
||||
last = fx;
|
||||
n = window_copy_search_rl(gd, sgd, &px, i - 1, 0, last, cis);
|
||||
if (n) {
|
||||
window_copy_scroll_to(wp, px, i - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wrapflag && !n && !wrapped) {
|
||||
fx = gd->sx - 1;
|
||||
fy = gd->hsize + gd->sy - 1;
|
||||
wrapped = 1;
|
||||
goto retry;
|
||||
}
|
||||
wrapflag = options_get_number(wp->window->options, "wrap-search");
|
||||
cis = window_copy_is_lowercase(searchstr);
|
||||
|
||||
if (direction)
|
||||
endline = gd->hsize + gd->sy - 1;
|
||||
else
|
||||
endline = 0;
|
||||
window_copy_search_jump(wp, gd, ss.grid, fx, fy, endline, cis, wrapflag,
|
||||
direction);
|
||||
|
||||
screen_free(&ss);
|
||||
}
|
||||
|
||||
void
|
||||
window_copy_search_down(struct window_pane *wp, const char *searchstr)
|
||||
window_copy_search_up(struct window_pane *wp, const char *searchstr,
|
||||
int moveflag)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = data->backing, ss;
|
||||
struct screen_write_ctx ctx;
|
||||
struct grid *gd = s->grid, *sgd;
|
||||
struct grid_cell gc;
|
||||
size_t searchlen;
|
||||
u_int i, first, fx, fy, px;
|
||||
int n, wrapped, wrapflag, cis;
|
||||
const char *ptr;
|
||||
window_copy_search(wp, searchstr, 0, moveflag);
|
||||
}
|
||||
|
||||
if (*searchstr == '\0')
|
||||
return;
|
||||
wrapflag = options_get_number(wp->window->options, "wrap-search");
|
||||
searchlen = screen_write_strlen("%s", searchstr);
|
||||
|
||||
screen_init(&ss, searchlen, 1, 0);
|
||||
screen_write_start(&ctx, NULL, &ss);
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
screen_write_nputs(&ctx, -1, &gc, "%s", searchstr);
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
fx = data->cx;
|
||||
fy = gd->hsize - data->oy + data->cy;
|
||||
|
||||
if (fx == gd->sx - 1) {
|
||||
if (fy == gd->hsize + gd->sy)
|
||||
return;
|
||||
fx = 0;
|
||||
fy++;
|
||||
} else
|
||||
fx++;
|
||||
n = wrapped = 0;
|
||||
|
||||
cis = 1;
|
||||
for (ptr = searchstr; *ptr != '\0'; ptr++) {
|
||||
if (*ptr != tolower((u_char)*ptr)) {
|
||||
cis = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
sgd = ss.grid;
|
||||
for (i = fy + 1; i < gd->hsize + gd->sy + 1; i++) {
|
||||
first = 0;
|
||||
if (i == fy + 1)
|
||||
first = fx;
|
||||
n = window_copy_search_lr(gd, sgd, &px, i - 1, first, gd->sx,
|
||||
cis);
|
||||
if (n) {
|
||||
window_copy_scroll_to(wp, px, i - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (wrapflag && !n && !wrapped) {
|
||||
fx = 0;
|
||||
fy = 0;
|
||||
wrapped = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
screen_free(&ss);
|
||||
void
|
||||
window_copy_search_down(struct window_pane *wp, const char *searchstr,
|
||||
int moveflag)
|
||||
{
|
||||
window_copy_search(wp, searchstr, 1, moveflag);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
133
window.c
133
window.c
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -26,6 +27,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
@@ -54,15 +56,17 @@ struct windows windows;
|
||||
|
||||
/* Global panes tree. */
|
||||
struct window_pane_tree all_window_panes;
|
||||
u_int next_window_pane_id;
|
||||
u_int next_window_id;
|
||||
u_int next_active_point;
|
||||
static u_int next_window_pane_id;
|
||||
static u_int next_window_id;
|
||||
static u_int next_active_point;
|
||||
|
||||
void window_pane_timer_callback(int, short, void *);
|
||||
void window_pane_read_callback(struct bufferevent *, void *);
|
||||
void window_pane_error_callback(struct bufferevent *, short, void *);
|
||||
static void window_pane_set_watermark(struct window_pane *, size_t);
|
||||
|
||||
struct window_pane *window_pane_choose_best(struct window_pane **, u_int);
|
||||
static void window_pane_read_callback(struct bufferevent *, void *);
|
||||
static void window_pane_error_callback(struct bufferevent *, short, void *);
|
||||
|
||||
static struct window_pane *window_pane_choose_best(struct window_pane **,
|
||||
u_int);
|
||||
|
||||
RB_GENERATE(windows, window, entry, window_cmp);
|
||||
|
||||
@@ -291,7 +295,7 @@ window_create1(u_int sx, u_int sy)
|
||||
|
||||
w = xcalloc(1, sizeof *w);
|
||||
w->name = NULL;
|
||||
w->flags = 0;
|
||||
w->flags = WINDOW_STYLECHANGED;
|
||||
|
||||
TAILQ_INIT(&w->panes);
|
||||
w->active = NULL;
|
||||
@@ -323,7 +327,7 @@ window_create(const char *name, int argc, char **argv, const char *path,
|
||||
struct window_pane *wp;
|
||||
|
||||
w = window_create1(sx, sy);
|
||||
wp = window_add_pane(w, hlimit);
|
||||
wp = window_add_pane(w, NULL, hlimit);
|
||||
layout_init(w, wp);
|
||||
|
||||
if (window_pane_spawn(wp, argc, argv, path, shell, cwd, env, tio,
|
||||
@@ -553,15 +557,19 @@ window_unzoom(struct window *w)
|
||||
}
|
||||
|
||||
struct window_pane *
|
||||
window_add_pane(struct window *w, u_int hlimit)
|
||||
window_add_pane(struct window *w, struct window_pane *after, u_int hlimit)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
|
||||
wp = window_pane_create(w, w->sx, w->sy, hlimit);
|
||||
if (TAILQ_EMPTY(&w->panes))
|
||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||
else
|
||||
TAILQ_INSERT_AFTER(&w->panes, w->active, wp, entry);
|
||||
else {
|
||||
if (after == NULL)
|
||||
TAILQ_INSERT_AFTER(&w->panes, w->active, wp, entry);
|
||||
else
|
||||
TAILQ_INSERT_AFTER(&w->panes, after, wp, entry);
|
||||
}
|
||||
return (wp);
|
||||
}
|
||||
|
||||
@@ -764,6 +772,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
screen_init(&wp->base, sx, sy, hlimit);
|
||||
wp->screen = &wp->base;
|
||||
|
||||
screen_init(&wp->status_screen, 1, 1, 0);
|
||||
|
||||
if (gethostname(host, sizeof host) == 0)
|
||||
screen_set_title(&wp->base, host);
|
||||
|
||||
@@ -777,9 +787,6 @@ window_pane_destroy(struct window_pane *wp)
|
||||
{
|
||||
window_pane_reset_mode(wp);
|
||||
|
||||
if (event_initialized(&wp->timer))
|
||||
evtimer_del(&wp->timer);
|
||||
|
||||
if (wp->fd != -1) {
|
||||
#ifdef HAVE_UTEMPTER
|
||||
utempter_remove_record(wp->fd);
|
||||
@@ -799,6 +806,9 @@ window_pane_destroy(struct window_pane *wp)
|
||||
close(wp->pipe_fd);
|
||||
}
|
||||
|
||||
if (event_initialized(&wp->resize_timer))
|
||||
event_del(&wp->resize_timer);
|
||||
|
||||
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
|
||||
|
||||
free((void *)wp->cwd);
|
||||
@@ -807,6 +817,14 @@ window_pane_destroy(struct window_pane *wp)
|
||||
free(wp);
|
||||
}
|
||||
|
||||
static void
|
||||
window_pane_set_watermark(struct window_pane *wp, size_t size)
|
||||
{
|
||||
wp->wmark_hits = 0;
|
||||
wp->wmark_size = size;
|
||||
bufferevent_setwatermark(wp->event, EV_READ, 0, size);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
||||
const char *path, const char *shell, const char *cwd, struct environ *env,
|
||||
@@ -843,6 +861,7 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
||||
log_debug("spawn: %s -- %s", wp->shell, cmd);
|
||||
for (i = 0; i < wp->argc; i++)
|
||||
log_debug("spawn: argv[%d] = %s", i, wp->argv[i]);
|
||||
environ_log(env, "spawn: ");
|
||||
|
||||
memset(&ws, 0, sizeof ws);
|
||||
ws.ws_col = screen_size_x(&wp->base);
|
||||
@@ -924,44 +943,37 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
||||
wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
|
||||
window_pane_error_callback, wp);
|
||||
|
||||
bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE);
|
||||
window_pane_set_watermark(wp, READ_FAST_SIZE);
|
||||
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
||||
|
||||
free(cmd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_timer_callback(__unused int fd, __unused short events, void *data)
|
||||
{
|
||||
window_pane_read_callback(NULL, data);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
|
||||
{
|
||||
struct window_pane *wp = data;
|
||||
struct evbuffer *evb = wp->event->input;
|
||||
size_t size = EVBUFFER_LENGTH(evb);
|
||||
char *new_data;
|
||||
size_t new_size, available;
|
||||
struct client *c;
|
||||
struct timeval tv;
|
||||
size_t new_size;
|
||||
|
||||
if (event_initialized(&wp->timer))
|
||||
evtimer_del(&wp->timer);
|
||||
|
||||
log_debug("%%%u has %zu bytes", wp->id, EVBUFFER_LENGTH(evb));
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (!tty_client_ready(c, wp))
|
||||
continue;
|
||||
|
||||
available = EVBUFFER_LENGTH(c->tty.event->output);
|
||||
if (available > READ_BACKOFF)
|
||||
goto start_timer;
|
||||
if (wp->wmark_size == READ_FAST_SIZE) {
|
||||
if (size > READ_FULL_SIZE)
|
||||
wp->wmark_hits++;
|
||||
if (wp->wmark_hits == READ_CHANGE_HITS)
|
||||
window_pane_set_watermark(wp, READ_SLOW_SIZE);
|
||||
} else if (wp->wmark_size == READ_SLOW_SIZE) {
|
||||
if (size < READ_EMPTY_SIZE)
|
||||
wp->wmark_hits++;
|
||||
if (wp->wmark_hits == READ_CHANGE_HITS)
|
||||
window_pane_set_watermark(wp, READ_FAST_SIZE);
|
||||
}
|
||||
log_debug("%%%u has %zu bytes (of %u, %u hits)", wp->id, size,
|
||||
wp->wmark_size, wp->wmark_hits);
|
||||
|
||||
new_size = EVBUFFER_LENGTH(evb) - wp->pipe_off;
|
||||
new_size = size - wp->pipe_off;
|
||||
if (wp->pipe_fd != -1 && new_size > 0) {
|
||||
new_data = EVBUFFER_DATA(evb) + wp->pipe_off;
|
||||
bufferevent_write(wp->pipe_event, new_data, new_size);
|
||||
@@ -969,21 +981,10 @@ window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
|
||||
|
||||
input_parse(wp);
|
||||
|
||||
wp->pipe_off = EVBUFFER_LENGTH(evb);
|
||||
return;
|
||||
|
||||
start_timer:
|
||||
log_debug("%%%u backing off (%s %zu > %d)", wp->id, c->ttyname,
|
||||
available, READ_BACKOFF);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = READ_TIME;
|
||||
|
||||
evtimer_set(&wp->timer, window_pane_timer_callback, wp);
|
||||
evtimer_add(&wp->timer, &tv);
|
||||
wp->pipe_off = size;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
window_pane_error_callback(__unused struct bufferevent *bufev,
|
||||
__unused short what, void *data)
|
||||
{
|
||||
@@ -1088,15 +1089,38 @@ window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc,
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
|
||||
static void
|
||||
window_pane_mode_timer(__unused int fd, __unused short events, void *arg)
|
||||
{
|
||||
struct window_pane *wp = arg;
|
||||
struct timeval tv = { .tv_sec = 10 };
|
||||
int n = 0;
|
||||
|
||||
evtimer_del(&wp->modetimer);
|
||||
evtimer_add(&wp->modetimer, &tv);
|
||||
|
||||
log_debug("%%%u in mode: last=%ld", wp->id, (long)wp->modelast);
|
||||
|
||||
if (wp->modelast < time(NULL) - WINDOW_MODE_TIMEOUT) {
|
||||
if (ioctl(wp->fd, FIONREAD, &n) == -1 || n > 0)
|
||||
window_pane_reset_mode(wp);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode)
|
||||
{
|
||||
struct screen *s;
|
||||
struct timeval tv = { .tv_sec = 10 };
|
||||
|
||||
if (wp->mode != NULL)
|
||||
return (1);
|
||||
wp->mode = mode;
|
||||
|
||||
wp->modelast = time(NULL);
|
||||
evtimer_set(&wp->modetimer, window_pane_mode_timer, wp);
|
||||
evtimer_add(&wp->modetimer, &tv);
|
||||
|
||||
if ((s = wp->mode->init(wp)) != NULL)
|
||||
wp->screen = s;
|
||||
wp->flags |= (PANE_REDRAW|PANE_CHANGED);
|
||||
@@ -1111,6 +1135,8 @@ window_pane_reset_mode(struct window_pane *wp)
|
||||
if (wp->mode == NULL)
|
||||
return;
|
||||
|
||||
evtimer_del(&wp->modetimer);
|
||||
|
||||
wp->mode->free(wp);
|
||||
wp->mode = NULL;
|
||||
|
||||
@@ -1130,6 +1156,7 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
|
||||
return;
|
||||
|
||||
if (wp->mode != NULL) {
|
||||
wp->modelast = time(NULL);
|
||||
if (wp->mode->key != NULL)
|
||||
wp->mode->key(wp, c, s, key, m);
|
||||
return;
|
||||
@@ -1195,7 +1222,7 @@ window_pane_search(struct window_pane *wp, const char *searchstr,
|
||||
}
|
||||
|
||||
/* Get MRU pane from a list. */
|
||||
struct window_pane *
|
||||
static struct window_pane *
|
||||
window_pane_choose_best(struct window_pane **list, u_int size)
|
||||
{
|
||||
struct window_pane *next, *best;
|
||||
|
||||
Reference in New Issue
Block a user