mirror of
https://github.com/tmux/tmux.git
synced 2026-03-12 03:25:45 +00:00
Compare commits
302 Commits
3.6
...
floating_p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a90fce476 | ||
|
|
e928e80a42 | ||
|
|
28c04b21f6 | ||
|
|
46427f1dd7 | ||
|
|
528e856566 | ||
|
|
14a934d412 | ||
|
|
d0caf0a322 | ||
|
|
91b5108eae | ||
|
|
2c7f73f9c4 | ||
|
|
5310592967 | ||
|
|
41bddae907 | ||
|
|
d9d2b2f1ee | ||
|
|
1e208abd93 | ||
|
|
0faed7aeb5 | ||
|
|
8e6450c8fc | ||
|
|
d32088b58a | ||
|
|
6d37cc94a7 | ||
|
|
55722a7ed7 | ||
|
|
d2fa20a390 | ||
|
|
bcbad050d4 | ||
|
|
27698c468b | ||
|
|
49bb43047d | ||
|
|
77ce0a837d | ||
|
|
bbbfa8f360 | ||
|
|
d781d2eaa1 | ||
|
|
f33b14bda6 | ||
|
|
e603549563 | ||
|
|
e80e0c761a | ||
|
|
9e804202b6 | ||
|
|
0c678b1e1a | ||
|
|
4cb29deb93 | ||
|
|
5413953d30 | ||
|
|
50e51b4513 | ||
|
|
ee0647aba6 | ||
|
|
35be70f1f0 | ||
|
|
dbb23d2182 | ||
|
|
478eaea982 | ||
|
|
0800e51d41 | ||
|
|
5ff385f8a9 | ||
|
|
5b3c642195 | ||
|
|
bd6e201926 | ||
|
|
08779aa2a3 | ||
|
|
09bd686327 | ||
|
|
9316476a73 | ||
|
|
00946007d8 | ||
|
|
6898e26a7a | ||
|
|
bc47bc7c22 | ||
|
|
dc693601f4 | ||
|
|
f1f9c63cdb | ||
|
|
0cc4f0fd76 | ||
|
|
0dc1b5adfb | ||
|
|
a76e6eca6b | ||
|
|
8c7278b53a | ||
|
|
50a3b4c777 | ||
|
|
3094ca1da5 | ||
|
|
23ad10c849 | ||
|
|
c9fb989a31 | ||
|
|
e2cf40ef99 | ||
|
|
8356578a54 | ||
|
|
0310404155 | ||
|
|
96515c9f47 | ||
|
|
03f8690f9c | ||
|
|
4cc3de4f84 | ||
|
|
fedd4440f0 | ||
|
|
55cedc24fa | ||
|
|
c9162837a0 | ||
|
|
f218463976 | ||
|
|
1f0c54f7ea | ||
|
|
d3522c328c | ||
|
|
96e18faa93 | ||
|
|
476c6e89ad | ||
|
|
7e50eb0e83 | ||
|
|
5b455abecc | ||
|
|
7d41761e84 | ||
|
|
25f6d8b1e9 | ||
|
|
5a33616e65 | ||
|
|
1cf17b06ae | ||
|
|
aa03706ed0 | ||
|
|
d8794e2b30 | ||
|
|
b7939eb266 | ||
|
|
19b9a34c48 | ||
|
|
f016e08153 | ||
|
|
7b1c503086 | ||
|
|
5865001e4a | ||
|
|
62944da74b | ||
|
|
588013bb44 | ||
|
|
615c27c117 | ||
|
|
3c3d9ce3a9 | ||
|
|
b46a96d454 | ||
|
|
f67cf7d053 | ||
|
|
66011fe48b | ||
|
|
2ad0f4a9e7 | ||
|
|
d7f59eccaf | ||
|
|
1ec9ca497b | ||
|
|
e652213855 | ||
|
|
f70150a663 | ||
|
|
dd5d0f4f0c | ||
|
|
fe52f76913 | ||
|
|
0d9c3c895c | ||
|
|
6525bb7cef | ||
|
|
0790e74f84 | ||
|
|
195a9cfd88 | ||
|
|
ecbf8d76d0 | ||
|
|
818745a605 | ||
|
|
26aacd0e32 | ||
|
|
d1a6ce8e7f | ||
|
|
b22537e8a4 | ||
|
|
a25c14d472 | ||
|
|
7730d38339 | ||
|
|
58e498c9d3 | ||
|
|
35485f2b5e | ||
|
|
8e06739e26 | ||
|
|
b108653f02 | ||
|
|
25f72cf240 | ||
|
|
ab1f2ef71c | ||
|
|
d2e09cb259 | ||
|
|
bf8ea85bd7 | ||
|
|
9c0aeaff40 | ||
|
|
95b4bb51c6 | ||
|
|
1e5f93b7b6 | ||
|
|
b89d46bb00 | ||
|
|
97d61131df | ||
|
|
5721767921 | ||
|
|
a443531280 | ||
|
|
ad083677c5 | ||
|
|
426467856d | ||
|
|
d1df8dcccc | ||
|
|
844042744e | ||
|
|
65b3a95be8 | ||
|
|
a50d00aa47 | ||
|
|
ca95950148 | ||
|
|
6234d79852 | ||
|
|
a5d8b92012 | ||
|
|
890cfc6dc3 | ||
|
|
34add944f2 | ||
|
|
95f85efc49 | ||
|
|
0e6fc2e88b | ||
|
|
c8ccd420be | ||
|
|
ff4f6b9066 | ||
|
|
7cffa2de78 | ||
|
|
e2afaaea75 | ||
|
|
75d3974c12 | ||
|
|
583f12ea71 | ||
|
|
3de7a8ad8d | ||
|
|
f6c9052082 | ||
|
|
f226804149 | ||
|
|
f2f6a05e2c | ||
|
|
cf94486e32 | ||
|
|
035a2f35d4 | ||
|
|
9b7732eac4 | ||
|
|
5f9dac8abc | ||
|
|
ccd4dd7ff2 | ||
|
|
77417b7cbe | ||
|
|
6a7cd79a63 | ||
|
|
baa3b51b3e | ||
|
|
abeba4910c | ||
|
|
356d0aedbd | ||
|
|
45f23f3a59 | ||
|
|
6ef7375ade | ||
|
|
00030aabf7 | ||
|
|
f72832cc08 | ||
|
|
b5c33ca2b7 | ||
|
|
bd442a27ee | ||
|
|
d607399850 | ||
|
|
d005803934 | ||
|
|
a22ec275b4 | ||
|
|
188f963fe0 | ||
|
|
9c5df33325 | ||
|
|
74f60951cc | ||
|
|
73c0eb96c3 | ||
|
|
6a4a4a432b | ||
|
|
54202fcaad | ||
|
|
fe645c5bcc | ||
|
|
86c15d7ae9 | ||
|
|
3c36d5e433 | ||
|
|
1c7e164c22 | ||
|
|
ce7eb22e3a | ||
|
|
739a97140f | ||
|
|
99ed397e9c | ||
|
|
d2c7668bc2 | ||
|
|
7abf3e8bdf | ||
|
|
506b4db762 | ||
|
|
21c27fdcae | ||
|
|
672e89a640 | ||
|
|
263529e886 | ||
|
|
818797ff08 | ||
|
|
d263dbe9dd | ||
|
|
67319ad9d9 | ||
|
|
4b810ae493 | ||
|
|
52e2a7d990 | ||
|
|
2591df66cc | ||
|
|
2e5e9c0298 | ||
|
|
afa05ae15e | ||
|
|
2ac78bccb5 | ||
|
|
47de44001e | ||
|
|
eaa467618b | ||
|
|
f58b8d0d6a | ||
|
|
5c73d3878d | ||
|
|
ac01f15bfe | ||
|
|
ef0a7e328c | ||
|
|
cc117b5048 | ||
|
|
faebe7a70a | ||
|
|
01962e25dc | ||
|
|
ff207eb583 | ||
|
|
8e922ab690 | ||
|
|
1a3db6b65e | ||
|
|
987e05ff31 | ||
|
|
2fc123cf4a | ||
|
|
3b57077d01 | ||
|
|
33c1ba1549 | ||
|
|
bd16b22dac | ||
|
|
0929d8ddfa | ||
|
|
9d6c69ebde | ||
|
|
1bcd360dfe | ||
|
|
1f2210a3ce | ||
|
|
2fe1378d3a | ||
|
|
796539c60b | ||
|
|
700936b2ad | ||
|
|
a28dbe3a59 | ||
|
|
820df0f551 | ||
|
|
ee9cf1bbaa | ||
|
|
52917abe21 | ||
|
|
a40f98df0a | ||
|
|
2c78a5aceb | ||
|
|
02a8e3fd34 | ||
|
|
322adfbdde | ||
|
|
194d0a0e25 | ||
|
|
b2d6ebaa10 | ||
|
|
bfecbb0685 | ||
|
|
e4c552f5a5 | ||
|
|
04f32073c0 | ||
|
|
e9afd2bb5e | ||
|
|
5df5217e2e | ||
|
|
55d660a548 | ||
|
|
dfaf47d97c | ||
|
|
640e1a7643 | ||
|
|
2a0b078e15 | ||
|
|
0af04295f3 | ||
|
|
3542bfa5b8 | ||
|
|
e3a54ed0f4 | ||
|
|
ec4b5b52af | ||
|
|
a0dfef3b04 | ||
|
|
6db6a30ab5 | ||
|
|
bfa2f73335 | ||
|
|
1decccace7 | ||
|
|
ee53d49059 | ||
|
|
f949f9a23a | ||
|
|
f0dec832b8 | ||
|
|
a6ec2b76c2 | ||
|
|
bc01b300c4 | ||
|
|
c8d4d8cb66 | ||
|
|
315202b007 | ||
|
|
7194fdca38 | ||
|
|
31d0945059 | ||
|
|
466e79d572 | ||
|
|
3bb4f72a4b | ||
|
|
329e9d54ab | ||
|
|
9c45dd693b | ||
|
|
cc671e4495 | ||
|
|
61ca158de1 | ||
|
|
7e0038c691 | ||
|
|
04792d0656 | ||
|
|
6c5cc40039 | ||
|
|
6b462474f0 | ||
|
|
9a061a2fee | ||
|
|
6dd552d689 | ||
|
|
34e858ea05 | ||
|
|
39d2839e37 | ||
|
|
7980d00e8c | ||
|
|
25ce5b4281 | ||
|
|
0cd3ab6299 | ||
|
|
28d038fb16 | ||
|
|
10dc308e6b | ||
|
|
6344bab6cc | ||
|
|
984fbacccf | ||
|
|
cc83ca6628 | ||
|
|
04fc6ea11b | ||
|
|
8a9e2fccbd | ||
|
|
cc1324e2d9 | ||
|
|
b2226d1608 | ||
|
|
8ce0af3fc9 | ||
|
|
b315a6c3d1 | ||
|
|
baf642b7d2 | ||
|
|
8db76e9057 | ||
|
|
e3b7bf9b31 | ||
|
|
38724f2e86 | ||
|
|
65fc09fac9 | ||
|
|
3197b715b3 | ||
|
|
26362dfc72 | ||
|
|
275781ce45 | ||
|
|
72dbbfedce | ||
|
|
a6c6eabb5a | ||
|
|
379e4d976c | ||
|
|
a6514e2656 | ||
|
|
032af23e18 | ||
|
|
b5f9293014 | ||
|
|
a37db55689 | ||
|
|
1b959d0eff | ||
|
|
ce03f1abea | ||
|
|
5faf41b695 | ||
|
|
7634daa834 | ||
|
|
968f439672 |
2
.github/README.md
vendored
2
.github/README.md
vendored
@@ -79,7 +79,7 @@ A small example configuration is in `example_tmux.conf`.
|
|||||||
|
|
||||||
And a bash(1) completion file at:
|
And a bash(1) completion file at:
|
||||||
|
|
||||||
https://github.com/scop/bash-completion/blob/main/completions/tmux
|
https://github.com/scop/bash-completion/blob/main/completions-core/tmux.bash
|
||||||
|
|
||||||
For debugging, run tmux with `-v` or `-vv` to generate server and client log
|
For debugging, run tmux with `-v` or `-vv` to generate server and client log
|
||||||
files in the current directory.
|
files in the current directory.
|
||||||
|
|||||||
1
.mailmap
1
.mailmap
@@ -29,6 +29,7 @@ Ted Unangst <tedu@openbsd.org> tedu <tedu>
|
|||||||
Theo de Raadt <deraadt@openbsd.org> Theo Deraadt <deraadt@openbsd.org>
|
Theo de Raadt <deraadt@openbsd.org> Theo Deraadt <deraadt@openbsd.org>
|
||||||
Theo de Raadt <deraadt@openbsd.org> deraadt <deraadt>
|
Theo de Raadt <deraadt@openbsd.org> deraadt <deraadt>
|
||||||
Thomas Adam <thomas@xteddy.org> Thomas <thomas@xteddy.org>
|
Thomas Adam <thomas@xteddy.org> Thomas <thomas@xteddy.org>
|
||||||
|
Thomas Adam <thomas@xteddy.org> Thomas Adam <thomas.adam22@gmail.com>
|
||||||
Thomas Adam <thomas@xteddy.org> Thomas Adam <thomas.adam@smoothwall.net>
|
Thomas Adam <thomas@xteddy.org> Thomas Adam <thomas.adam@smoothwall.net>
|
||||||
Thomas Adam <thomas@xteddy.org> n6tadam <n6tadam@xteddy.org>
|
Thomas Adam <thomas@xteddy.org> n6tadam <n6tadam@xteddy.org>
|
||||||
Tim van der Molen <tim@openbsd.org> tim <tim>
|
Tim van der Molen <tim@openbsd.org> tim <tim>
|
||||||
|
|||||||
26
CHANGES
26
CHANGES
@@ -1,3 +1,29 @@
|
|||||||
|
CHANGES FROM 3.6 TO 3.6a
|
||||||
|
|
||||||
|
* Fix a buffer overread and an infinite loop in format processing (reported by
|
||||||
|
Giorgi Kobakhia, issue 4735).
|
||||||
|
|
||||||
|
* Allow drag in alternate screen again (issue 4743 reported by Brad King).
|
||||||
|
|
||||||
|
* Fix y offset of mouse if status at top (issue 4738 from Michael Grant).
|
||||||
|
|
||||||
|
* Add a missing skin tone (from Jake Stewart, issue 4736).
|
||||||
|
|
||||||
|
* Allow characters to be combined in either order (issue 4726, reported by Jake
|
||||||
|
Stewart).
|
||||||
|
|
||||||
|
* Fix horizontal mouse resizing when pane status lines are on (from Michael
|
||||||
|
Grant, issue 4720).
|
||||||
|
|
||||||
|
* Fix noattr so it does not delete attributes set in the style itself (issue
|
||||||
|
4713).
|
||||||
|
|
||||||
|
* Newer libevents do not allow event_del on a zero'd event (issue 4706).
|
||||||
|
|
||||||
|
* Place cursor on correct line if message-line is not 0 (issue 4707).
|
||||||
|
|
||||||
|
* Fix compile error on FreeBSD (from Yasuhiro Kimura, issue 4701).
|
||||||
|
|
||||||
CHANGES FROM 3.5a TO 3.6
|
CHANGES FROM 3.5a TO 3.6
|
||||||
|
|
||||||
* Add seconds options for clock mode (issue 4697).
|
* Add seconds options for clock mode (issue 4697).
|
||||||
|
|||||||
21
Makefile.am
21
Makefile.am
@@ -20,17 +20,23 @@ LDADD = $(LIBOBJS)
|
|||||||
|
|
||||||
# Set flags for gcc.
|
# Set flags for gcc.
|
||||||
if IS_GCC
|
if IS_GCC
|
||||||
AM_CFLAGS += -std=gnu99 -O2
|
AM_CFLAGS += -std=gnu99
|
||||||
|
if IS_OPTIMIZED
|
||||||
|
AM_CFLAGS += -O2
|
||||||
|
else
|
||||||
|
AM_CFLAGS += -O0
|
||||||
|
endif
|
||||||
if IS_DEBUG
|
if IS_DEBUG
|
||||||
AM_CFLAGS += -g
|
AM_CFLAGS += -g
|
||||||
AM_CFLAGS += -Wno-long-long -Wall -W -Wformat=2
|
AM_CFLAGS += -Wno-long-long -Wall -W -Wformat=2 -Wno-use-after-free
|
||||||
AM_CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
|
AM_CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
|
||||||
AM_CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
|
AM_CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
|
||||||
AM_CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
|
AM_CFLAGS += -Wundef -Wbad-function-cast -Winline -Wno-cast-align
|
||||||
AM_CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign -Wno-attributes
|
AM_CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign -Wno-attributes
|
||||||
AM_CFLAGS += -Wno-unused-result -Wno-format-y2k
|
AM_CFLAGS += -Wno-unused-result -Wno-format-y2k -Wno-unknown-warning-option
|
||||||
|
AM_CFLAGS += -Wno-maybe-uninitialized
|
||||||
if IS_DARWIN
|
if IS_DARWIN
|
||||||
AM_CFLAGS += -Wno-deprecated-declarations -Wno-cast-align -Wno-macro-redefined
|
AM_CFLAGS += -Wno-deprecated-declarations -Wno-macro-redefined
|
||||||
endif
|
endif
|
||||||
AM_CPPFLAGS += -DDEBUG
|
AM_CPPFLAGS += -DDEBUG
|
||||||
endif
|
endif
|
||||||
@@ -100,13 +106,16 @@ dist_tmux_SOURCES = \
|
|||||||
cmd-kill-window.c \
|
cmd-kill-window.c \
|
||||||
cmd-list-buffers.c \
|
cmd-list-buffers.c \
|
||||||
cmd-list-clients.c \
|
cmd-list-clients.c \
|
||||||
|
cmd-list-commands.c \
|
||||||
cmd-list-keys.c \
|
cmd-list-keys.c \
|
||||||
cmd-list-panes.c \
|
cmd-list-panes.c \
|
||||||
cmd-list-sessions.c \
|
cmd-list-sessions.c \
|
||||||
cmd-list-windows.c \
|
cmd-list-windows.c \
|
||||||
cmd-load-buffer.c \
|
cmd-load-buffer.c \
|
||||||
cmd-lock-server.c \
|
cmd-lock-server.c \
|
||||||
|
cmd-minimise-pane.c \
|
||||||
cmd-move-window.c \
|
cmd-move-window.c \
|
||||||
|
cmd-new-pane.c \
|
||||||
cmd-new-session.c \
|
cmd-new-session.c \
|
||||||
cmd-new-window.c \
|
cmd-new-window.c \
|
||||||
cmd-parse.y \
|
cmd-parse.y \
|
||||||
@@ -183,6 +192,7 @@ dist_tmux_SOURCES = \
|
|||||||
server-fn.c \
|
server-fn.c \
|
||||||
server.c \
|
server.c \
|
||||||
session.c \
|
session.c \
|
||||||
|
sort.c \
|
||||||
spawn.c \
|
spawn.c \
|
||||||
status.c \
|
status.c \
|
||||||
style.c \
|
style.c \
|
||||||
@@ -190,6 +200,7 @@ dist_tmux_SOURCES = \
|
|||||||
tmux.h \
|
tmux.h \
|
||||||
tmux-protocol.h \
|
tmux-protocol.h \
|
||||||
tty-acs.c \
|
tty-acs.c \
|
||||||
|
tty-draw.c \
|
||||||
tty-features.c \
|
tty-features.c \
|
||||||
tty-keys.c \
|
tty-keys.c \
|
||||||
tty-term.c \
|
tty-term.c \
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ attributes_tostring(int attr)
|
|||||||
if (attr == 0)
|
if (attr == 0)
|
||||||
return ("none");
|
return ("none");
|
||||||
|
|
||||||
len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||||
(attr & GRID_ATTR_CHARSET) ? "acs," : "",
|
(attr & GRID_ATTR_CHARSET) ? "acs," : "",
|
||||||
(attr & GRID_ATTR_BRIGHT) ? "bright," : "",
|
(attr & GRID_ATTR_BRIGHT) ? "bright," : "",
|
||||||
(attr & GRID_ATTR_DIM) ? "dim," : "",
|
(attr & GRID_ATTR_DIM) ? "dim," : "",
|
||||||
@@ -45,7 +45,8 @@ attributes_tostring(int attr)
|
|||||||
(attr & GRID_ATTR_UNDERSCORE_3) ? "curly-underscore," : "",
|
(attr & GRID_ATTR_UNDERSCORE_3) ? "curly-underscore," : "",
|
||||||
(attr & GRID_ATTR_UNDERSCORE_4) ? "dotted-underscore," : "",
|
(attr & GRID_ATTR_UNDERSCORE_4) ? "dotted-underscore," : "",
|
||||||
(attr & GRID_ATTR_UNDERSCORE_5) ? "dashed-underscore," : "",
|
(attr & GRID_ATTR_UNDERSCORE_5) ? "dashed-underscore," : "",
|
||||||
(attr & GRID_ATTR_OVERLINE) ? "overline," : "");
|
(attr & GRID_ATTR_OVERLINE) ? "overline," : "",
|
||||||
|
(attr & GRID_ATTR_NOATTR) ? "noattr," : "");
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
buf[len - 1] = '\0';
|
buf[len - 1] = '\0';
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,13 @@ cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct window_pane *wp = target->wp;
|
struct window_pane *wp = target->wp;
|
||||||
const struct window_mode *mode;
|
const struct window_mode *mode;
|
||||||
|
enum sort_order order;
|
||||||
|
|
||||||
|
order = sort_order_from_string(args_get(args, 'O'));
|
||||||
|
if (order == SORT_END && args_has(args, 'O')) {
|
||||||
|
cmdq_error(item, "invalid sort order");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_choose_buffer_entry) {
|
if (cmd_get_entry(self) == &cmd_choose_buffer_entry) {
|
||||||
if (paste_is_empty())
|
if (paste_is_empty())
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
|||||||
.name = "command-prompt",
|
.name = "command-prompt",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "1bFkliI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
.args = { "1beFiklI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
|
||||||
.usage = "[-1bFkliN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
.usage = "[-1beFiklN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
|
||||||
" [-T prompt-type] [template]",
|
" [-T prompt-type] [template]",
|
||||||
|
|
||||||
.flags = CMD_CLIENT_TFLAG,
|
.flags = CMD_CLIENT_TFLAG,
|
||||||
@@ -84,7 +84,7 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct client *tc = cmdq_get_target_client(item);
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
const char *type, *s, *input;
|
const char *type, *s, *input;
|
||||||
struct cmd_command_prompt_cdata *cdata;
|
struct cmd_command_prompt_cdata *cdata;
|
||||||
char *tmp, *prompts, *prompt, *next_prompt;
|
char *tmp, *prompts, *prompt, *next_prompt;
|
||||||
char *inputs = NULL, *next_input;
|
char *inputs = NULL, *next_input;
|
||||||
u_int count = args_count(args);
|
u_int count = args_count(args);
|
||||||
@@ -163,6 +163,8 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cdata->flags |= PROMPT_INCREMENTAL;
|
cdata->flags |= PROMPT_INCREMENTAL;
|
||||||
else if (args_has(args, 'k'))
|
else if (args_has(args, 'k'))
|
||||||
cdata->flags |= PROMPT_KEY;
|
cdata->flags |= PROMPT_KEY;
|
||||||
|
else if (args_has(args, 'e'))
|
||||||
|
cdata->flags |= PROMPT_BSPACE_EXIT;
|
||||||
status_prompt_set(tc, target, cdata->prompts[0].prompt,
|
status_prompt_set(tc, target, cdata->prompts[0].prompt,
|
||||||
cdata->prompts[0].input, cmd_command_prompt_callback,
|
cdata->prompts[0].input, cmd_command_prompt_callback,
|
||||||
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
|
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
|
||||||
@@ -234,7 +236,7 @@ out:
|
|||||||
static void
|
static void
|
||||||
cmd_command_prompt_free(void *data)
|
cmd_command_prompt_free(void *data)
|
||||||
{
|
{
|
||||||
struct cmd_command_prompt_cdata *cdata = data;
|
struct cmd_command_prompt_cdata *cdata = data;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < cdata->count; i++) {
|
for (i = 0; i < cdata->count; i++) {
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cdata->confirm_key = confirm_key[0];
|
cdata->confirm_key = confirm_key[0];
|
||||||
else {
|
else {
|
||||||
cmdq_error(item, "invalid confirm key");
|
cmdq_error(item, "invalid confirm key");
|
||||||
|
cmd_list_free(cdata->cmdlist);
|
||||||
free(cdata);
|
free(cdata);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_copy_mode_entry = {
|
|||||||
.source = { 's', CMD_FIND_PANE, 0 },
|
.source = { 's', CMD_FIND_PANE, 0 },
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK|CMD_READONLY,
|
||||||
.exec = cmd_copy_mode_exec
|
.exec = cmd_copy_mode_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -63,6 +63,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct client *c = cmdq_get_client(item);
|
struct client *c = cmdq_get_client(item);
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct window_pane *wp = target->wp, *swp;
|
struct window_pane *wp = target->wp, *swp;
|
||||||
|
u_int tty_ox, tty_oy, tty_sx, tty_sy;
|
||||||
|
|
||||||
if (args_has(args, 'q')) {
|
if (args_has(args, 'q')) {
|
||||||
window_pane_reset_mode_all(wp);
|
window_pane_reset_mode_all(wp);
|
||||||
@@ -94,8 +95,9 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'd'))
|
if (args_has(args, 'd'))
|
||||||
window_copy_pagedown(wp, 0, args_has(args, 'e'));
|
window_copy_pagedown(wp, 0, args_has(args, 'e'));
|
||||||
if (args_has(args, 'S')) {
|
if (args_has(args, 'S')) {
|
||||||
|
tty_window_offset(&c->tty, &tty_ox, &tty_oy, &tty_sx, &tty_sy);
|
||||||
window_copy_scroll(wp, c->tty.mouse_slider_mpos, event->m.y,
|
window_copy_scroll(wp, c->tty.mouse_slider_mpos, event->m.y,
|
||||||
args_has(args, 'e'));
|
tty_oy, args_has(args, 'e'));
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
const char *border_style = args_get(args, 'S');
|
const char *border_style = args_get(args, 'S');
|
||||||
const char *selected_style = args_get(args, 'H');
|
const char *selected_style = args_get(args, 'H');
|
||||||
enum box_lines lines = BOX_LINES_DEFAULT;
|
enum box_lines lines = BOX_LINES_DEFAULT;
|
||||||
char *title, *cause;
|
char *title, *cause = NULL;
|
||||||
int flags = 0, starting_choice = 0;
|
int flags = 0, starting_choice = 0;
|
||||||
u_int px, py, i, count = args_count(args);
|
u_int px, py, i, count = args_count(args);
|
||||||
struct options *o = target->s->curw->window->options;
|
struct options *o = target->s->curw->window->options;
|
||||||
@@ -312,8 +312,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
&cause);
|
&cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "starting choice %s", cause);
|
cmdq_error(item, "starting choice %s", cause);
|
||||||
free(cause);
|
goto fail;
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,8 +333,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (count - i < 2) {
|
if (count - i < 2) {
|
||||||
cmdq_error(item, "not enough arguments");
|
cmdq_error(item, "not enough arguments");
|
||||||
menu_free(menu);
|
goto fail;
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
key = args_string(args, i++);
|
key = args_string(args, i++);
|
||||||
|
|
||||||
@@ -347,17 +345,13 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
if (menu == NULL) {
|
if (menu == NULL) {
|
||||||
cmdq_error(item, "invalid menu arguments");
|
cmdq_error(item, "invalid menu arguments");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
|
||||||
if (menu->count == 0) {
|
|
||||||
menu_free(menu);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
}
|
||||||
|
if (menu->count == 0)
|
||||||
|
goto out;
|
||||||
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, menu->width + 4,
|
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, menu->width + 4,
|
||||||
menu->count + 2)) {
|
menu->count + 2))
|
||||||
menu_free(menu);
|
goto out;
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
value = args_get(args, 'b');
|
value = args_get(args, 'b');
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
@@ -366,8 +360,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
&cause);
|
&cause);
|
||||||
if (lines == -1) {
|
if (lines == -1) {
|
||||||
cmdq_error(item, "menu-border-lines %s", cause);
|
cmdq_error(item, "menu-border-lines %s", cause);
|
||||||
free(cause);
|
goto fail;
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,8 +370,17 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
flags |= MENU_NOMOUSE;
|
flags |= MENU_NOMOUSE;
|
||||||
if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines,
|
if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines,
|
||||||
style, selected_style, border_style, target, NULL, NULL) != 0)
|
style, selected_style, border_style, target, NULL, NULL) != 0)
|
||||||
return (CMD_RETURN_NORMAL);
|
goto out;
|
||||||
return (CMD_RETURN_WAIT);
|
return (CMD_RETURN_WAIT);
|
||||||
|
|
||||||
|
out:
|
||||||
|
menu_free(menu);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(cause);
|
||||||
|
menu_free(menu);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
@@ -393,7 +395,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
const char *style = args_get(args, 's');
|
const char *style = args_get(args, 's');
|
||||||
const char *border_style = args_get(args, 'S');
|
const char *border_style = args_get(args, 'S');
|
||||||
char *cwd = NULL, *cause = NULL, **argv = NULL;
|
char *cwd = NULL, *cause = NULL, **argv = NULL;
|
||||||
char *title;
|
char *title = NULL;
|
||||||
int modify = popup_present(tc);
|
int modify = popup_present(tc);
|
||||||
int flags = -1, argc = 0;
|
int flags = -1, argc = 0;
|
||||||
enum box_lines lines = BOX_LINES_DEFAULT;
|
enum box_lines lines = BOX_LINES_DEFAULT;
|
||||||
@@ -417,8 +419,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
&cause);
|
&cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "height %s", cause);
|
cmdq_error(item, "height %s", cause);
|
||||||
free(cause);
|
goto fail;
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,8 +429,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
&cause);
|
&cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "width %s", cause);
|
cmdq_error(item, "width %s", cause);
|
||||||
free(cause);
|
goto fail;
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,7 +438,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (h > tty->sy)
|
if (h > tty->sy)
|
||||||
h = tty->sy;
|
h = tty->sy;
|
||||||
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, w, h))
|
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, w, h))
|
||||||
return (CMD_RETURN_NORMAL);
|
goto out;
|
||||||
|
|
||||||
value = args_get(args, 'd');
|
value = args_get(args, 'd');
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
@@ -478,8 +478,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
&cause);
|
&cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "popup-border-lines %s", cause);
|
cmdq_error(item, "popup-border-lines %s", cause);
|
||||||
free(cause);
|
goto fail;
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,22 +506,29 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (modify) {
|
if (modify) {
|
||||||
popup_modify(tc, title, style, border_style, lines, flags);
|
popup_modify(tc, title, style, border_style, lines, flags);
|
||||||
free(title);
|
goto out;
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
}
|
||||||
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
|
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
|
||||||
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) {
|
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0)
|
||||||
cmd_free_argv(argc, argv);
|
goto out;
|
||||||
if (env != NULL)
|
environ_free(env);
|
||||||
environ_free(env);
|
|
||||||
free(cwd);
|
|
||||||
free(title);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
if (env != NULL)
|
|
||||||
environ_free(env);
|
|
||||||
free(cwd);
|
free(cwd);
|
||||||
free(title);
|
free(title);
|
||||||
cmd_free_argv(argc, argv);
|
cmd_free_argv(argc, argv);
|
||||||
return (CMD_RETURN_WAIT);
|
return (CMD_RETURN_WAIT);
|
||||||
|
|
||||||
|
out:
|
||||||
|
cmd_free_argv(argc, argv);
|
||||||
|
environ_free(env);
|
||||||
|
free(cwd);
|
||||||
|
free(title);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(cause);
|
||||||
|
cmd_free_argv(argc, argv);
|
||||||
|
environ_free(env);
|
||||||
|
free(cwd);
|
||||||
|
free(title);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (args_has(args, 'a')) {
|
if (args_has(args, 'a')) {
|
||||||
format_each(ft, cmd_display_message_each, item);
|
format_each(ft, cmd_display_message_each, item);
|
||||||
|
format_free(ft);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +156,5 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
free(msg);
|
free(msg);
|
||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,10 +70,10 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
|||||||
char buf[16], lbuf[16], rbuf[16], *ptr;
|
char buf[16], lbuf[16], rbuf[16], *ptr;
|
||||||
size_t len, llen, rlen;
|
size_t len, llen, rlen;
|
||||||
|
|
||||||
if (wp->xoff + wp->sx <= ctx->ox ||
|
if (wp->xoff + (int)wp->sx <= ctx->ox ||
|
||||||
wp->xoff >= ctx->ox + ctx->sx ||
|
wp->xoff >= ctx->ox + (int)ctx->sx ||
|
||||||
wp->yoff + wp->sy <= ctx->oy ||
|
wp->yoff + (int)wp->sy <= ctx->oy ||
|
||||||
wp->yoff >= ctx->oy + ctx->sy)
|
wp->yoff >= ctx->oy + (int)ctx->sy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
|
if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
|
||||||
|
|||||||
24
cmd-find.c
24
cmd-find.c
@@ -924,6 +924,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
|||||||
const char *target, enum cmd_find_type type, int flags)
|
const char *target, enum cmd_find_type type, int flags)
|
||||||
{
|
{
|
||||||
struct mouse_event *m;
|
struct mouse_event *m;
|
||||||
|
struct client *c;
|
||||||
struct cmd_find_state current;
|
struct cmd_find_state current;
|
||||||
char *colon, *period, *copy = NULL, tmp[256];
|
char *colon, *period, *copy = NULL, tmp[256];
|
||||||
const char *session, *window, *pane, *s;
|
const char *session, *window, *pane, *s;
|
||||||
@@ -977,19 +978,38 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
|||||||
} else if (cmd_find_from_client(¤t, cmdq_get_client(item),
|
} else if (cmd_find_from_client(¤t, cmdq_get_client(item),
|
||||||
flags) == 0) {
|
flags) == 0) {
|
||||||
fs->current = ¤t;
|
fs->current = ¤t;
|
||||||
|
/* No active pane, window empty, return the window instead. */
|
||||||
|
if (current.wp == NULL) {
|
||||||
|
type = CMD_FIND_WINDOW;
|
||||||
|
}
|
||||||
log_debug("%s: current is from client", __func__);
|
log_debug("%s: current is from client", __func__);
|
||||||
} else {
|
} else {
|
||||||
if (~flags & CMD_FIND_QUIET)
|
if (~flags & CMD_FIND_QUIET)
|
||||||
cmdq_error(item, "no current target");
|
cmdq_error(item, "no current target");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (!cmd_find_valid_state(fs->current))
|
if (!cmd_find_valid_state(fs->current))
|
||||||
fatalx("invalid current find state");
|
fatalx("invalid current find state");
|
||||||
|
*/
|
||||||
/* An empty or NULL target is the current. */
|
/* An empty or NULL target is the current. */
|
||||||
if (target == NULL || *target == '\0')
|
if (target == NULL || *target == '\0')
|
||||||
goto current;
|
goto current;
|
||||||
|
|
||||||
|
if (strcmp(target, "@") == 0 ||
|
||||||
|
strcmp(target, "{active}") == 0 ||
|
||||||
|
strcmp(target, "{current}") == 0) {
|
||||||
|
c = cmdq_get_client(item);
|
||||||
|
if (c == NULL) {
|
||||||
|
cmdq_error(item, "no current client");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
fs->wl = c->session->curw;
|
||||||
|
fs->wp = c->session->curw->window->active;
|
||||||
|
fs->w = c->session->curw->window;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mouse target is a plain = or {mouse}. */
|
/* Mouse target is a plain = or {mouse}. */
|
||||||
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
|
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
|
||||||
m = &cmdq_get_event(item)->m;
|
m = &cmdq_get_event(item)->m;
|
||||||
@@ -1010,7 +1030,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
|||||||
fs->w = fs->wl->window;
|
fs->w = fs->wl->window;
|
||||||
fs->wp = fs->w->active;
|
fs->wp = fs->w->active;
|
||||||
}
|
}
|
||||||
break;
|
goto found;
|
||||||
}
|
}
|
||||||
if (fs->wp == NULL) {
|
if (fs->wp == NULL) {
|
||||||
if (~flags & CMD_FIND_QUIET)
|
if (~flags & CMD_FIND_QUIET)
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wp == NULL) {
|
||||||
|
/* No active window pane. */
|
||||||
|
cmdq_error(item, "No active pane to kill.");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
server_kill_pane(wp);
|
server_kill_pane(wp);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ const struct cmd_entry cmd_list_buffers_entry = {
|
|||||||
.name = "list-buffers",
|
.name = "list-buffers",
|
||||||
.alias = "lsb",
|
.alias = "lsb",
|
||||||
|
|
||||||
.args = { "F:f:", 0, 0, NULL },
|
.args = { "F:f:O:r", 0, 0, NULL },
|
||||||
.usage = "[-F format] [-f filter]",
|
.usage = "[-F format] [-f filter] [-O order]",
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_list_buffers_exec
|
.exec = cmd_list_buffers_exec
|
||||||
@@ -46,21 +46,30 @@ const struct cmd_entry cmd_list_buffers_entry = {
|
|||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer **l;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
u_int i, n;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if ((template = args_get(args, 'F')) == NULL)
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
template = LIST_BUFFERS_TEMPLATE;
|
template = LIST_BUFFERS_TEMPLATE;
|
||||||
filter = args_get(args, 'f');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
pb = NULL;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
while ((pb = paste_walk(pb)) != NULL) {
|
if (sort_crit.order == SORT_END && args_has(args, 'O')) {
|
||||||
|
cmdq_error(item, "invalid sort order");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
|
l = sort_get_buffers(&n, &sort_crit);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_defaults_paste_buffer(ft, pb);
|
format_defaults_paste_buffer(ft, l[i]);
|
||||||
|
|
||||||
if (filter != NULL) {
|
if (filter != NULL) {
|
||||||
expanded = format_expand(ft, filter);
|
expanded = format_expand(ft, filter);
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ const struct cmd_entry cmd_list_clients_entry = {
|
|||||||
.name = "list-clients",
|
.name = "list-clients",
|
||||||
.alias = "lsc",
|
.alias = "lsc",
|
||||||
|
|
||||||
.args = { "F:f:t:", 0, 0, NULL },
|
.args = { "F:f:O:rt:", 0, 0, NULL },
|
||||||
.usage = "[-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-F format] [-f filter] [-O order]" CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_SESSION, 0 },
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
@@ -53,15 +53,16 @@ const struct cmd_entry cmd_list_clients_entry = {
|
|||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct client *c;
|
struct client **l;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
u_int idx;
|
u_int i, n;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if (args_has(args, 't'))
|
if (args_has(args, 't'))
|
||||||
s = target->s;
|
s = target->s;
|
||||||
@@ -72,14 +73,21 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
template = LIST_CLIENTS_TEMPLATE;
|
template = LIST_CLIENTS_TEMPLATE;
|
||||||
filter = args_get(args, 'f');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
idx = 0;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
if (sort_crit.order == SORT_END && args_has(args, 'O')) {
|
||||||
if (c->session == NULL || (s != NULL && s != c->session))
|
cmdq_error(item, "invalid sort order");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
|
l = sort_get_clients(&n, &sort_crit);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (l[i]->session == NULL || (s != NULL && s != l[i]->session))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", idx);
|
format_add(ft, "line", "%u", i);
|
||||||
format_defaults(ft, c, NULL, NULL, NULL);
|
format_defaults(ft, l[i], NULL, NULL, NULL);
|
||||||
|
|
||||||
if (filter != NULL) {
|
if (filter != NULL) {
|
||||||
expanded = format_expand(ft, filter);
|
expanded = format_expand(ft, filter);
|
||||||
@@ -94,8 +102,6 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
|
|
||||||
idx++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
107
cmd-list-commands.c
Normal file
107
cmd-list-commands.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2007 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List all commands.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LIST_COMMANDS_TEMPLATE \
|
||||||
|
"#{command_list_name}" \
|
||||||
|
"#{?command_list_alias, (#{command_list_alias}),} " \
|
||||||
|
"#{command_list_usage}"
|
||||||
|
|
||||||
|
static enum cmd_retval cmd_list_commands(struct cmd *, struct cmdq_item *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_list_commands_entry = {
|
||||||
|
.name = "list-commands",
|
||||||
|
.alias = "lscm",
|
||||||
|
|
||||||
|
.args = { "F:", 0, 1, NULL },
|
||||||
|
.usage = "[-F format] [command]",
|
||||||
|
|
||||||
|
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
|
||||||
|
.exec = cmd_list_commands
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_list_single_command(const struct cmd_entry *entry, struct format_tree *ft,
|
||||||
|
const char *template, struct cmdq_item *item)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
format_add(ft, "command_list_name", "%s", entry->name);
|
||||||
|
if (entry->alias != NULL)
|
||||||
|
s = entry->alias;
|
||||||
|
else
|
||||||
|
s = "";
|
||||||
|
format_add(ft, "command_list_alias", "%s", s);
|
||||||
|
if (entry->usage != NULL)
|
||||||
|
s = entry->usage;
|
||||||
|
else
|
||||||
|
s = "";
|
||||||
|
format_add(ft, "command_list_usage", "%s", s);
|
||||||
|
|
||||||
|
line = format_expand(ft, template);
|
||||||
|
if (*line != '\0')
|
||||||
|
cmdq_print(item, "%s", line);
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_list_commands(struct cmd *self, struct cmdq_item *item)
|
||||||
|
{
|
||||||
|
struct args *args = cmd_get_args(self);
|
||||||
|
const struct cmd_entry **entryp;
|
||||||
|
const struct cmd_entry *entry;
|
||||||
|
struct format_tree *ft;
|
||||||
|
const char *template, *command;
|
||||||
|
char *cause;
|
||||||
|
|
||||||
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
|
template = LIST_COMMANDS_TEMPLATE;
|
||||||
|
|
||||||
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
|
format_defaults(ft, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
command = args_string(args, 0);
|
||||||
|
if (command == NULL) {
|
||||||
|
for (entryp = cmd_table; *entryp != NULL; entryp++)
|
||||||
|
cmd_list_single_command(*entryp, ft, template, item);
|
||||||
|
} else {
|
||||||
|
entry = cmd_find(command, &cause);
|
||||||
|
if (entry != NULL)
|
||||||
|
cmd_list_single_command(entry, ft, template, item);
|
||||||
|
else {
|
||||||
|
cmdq_error(item, "%s", cause);
|
||||||
|
free(cause);
|
||||||
|
format_free(ft);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
format_free(ft);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
463
cmd-list-keys.c
463
cmd-list-keys.c
@@ -27,121 +27,140 @@
|
|||||||
* List key bindings.
|
* List key bindings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmdq_item *);
|
#define LIST_KEYS_TEMPLATE \
|
||||||
|
"#{?notes_only," \
|
||||||
|
"#{key_prefix} " \
|
||||||
|
"#{p|#{key_string_width}:key_string} " \
|
||||||
|
"#{?key_note,#{key_note},#{key_command}}" \
|
||||||
|
"," \
|
||||||
|
"bind-key #{?key_has_repeat,#{?key_repeat,-r, },} " \
|
||||||
|
"-T #{p|#{key_table_width}:key_table} " \
|
||||||
|
"#{p|#{key_string_width}:key_string} " \
|
||||||
|
"#{key_command}}"
|
||||||
|
|
||||||
static enum cmd_retval cmd_list_keys_commands(struct cmd *,
|
static enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmdq_item *);
|
||||||
struct cmdq_item *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_list_keys_entry = {
|
const struct cmd_entry cmd_list_keys_entry = {
|
||||||
.name = "list-keys",
|
.name = "list-keys",
|
||||||
.alias = "lsk",
|
.alias = "lsk",
|
||||||
|
|
||||||
.args = { "1aNP:T:", 0, 1, NULL },
|
.args = { "1aF:NO:P:rT:", 0, 1, NULL },
|
||||||
.usage = "[-1aN] [-P prefix-string] [-T key-table] [key]",
|
.usage = "[-1aNr] [-F format] [-O order] [-P prefix-string]"
|
||||||
|
"[-T key-table] [key]",
|
||||||
|
|
||||||
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
|
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
|
||||||
.exec = cmd_list_keys_exec
|
.exec = cmd_list_keys_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct cmd_entry cmd_list_commands_entry = {
|
static char *
|
||||||
.name = "list-commands",
|
cmd_list_keys_get_prefix(struct args *args)
|
||||||
.alias = "lscm",
|
{
|
||||||
|
key_code prefix;
|
||||||
|
|
||||||
.args = { "F:", 0, 1, NULL },
|
if (args_has(args, 'P'))
|
||||||
.usage = "[-F format] [command]",
|
return (xstrdup(args_get(args, 'P')));
|
||||||
|
|
||||||
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
|
prefix = options_get_number(global_s_options, "prefix");
|
||||||
.exec = cmd_list_keys_exec
|
if (prefix == KEYC_NONE)
|
||||||
};
|
return (xstrdup(""));
|
||||||
|
return (xstrdup(key_string_lookup_key(prefix, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
static u_int
|
static u_int
|
||||||
cmd_list_keys_get_width(const char *tablename, key_code only)
|
cmd_list_keys_get_width(struct key_binding **l, u_int n)
|
||||||
{
|
{
|
||||||
struct key_table *table;
|
u_int i, width, keywidth = 0;
|
||||||
struct key_binding *bd;
|
|
||||||
u_int width, keywidth = 0;
|
|
||||||
|
|
||||||
table = key_bindings_get_table(tablename, 0);
|
for (i = 0; i < n; i++) {
|
||||||
if (table == NULL)
|
width = utf8_cstrwidth(key_string_lookup_key(l[i]->key, 0));
|
||||||
return (0);
|
|
||||||
bd = key_bindings_first(table);
|
|
||||||
while (bd != NULL) {
|
|
||||||
if ((only != KEYC_UNKNOWN && bd->key != only) ||
|
|
||||||
KEYC_IS_MOUSE(bd->key) ||
|
|
||||||
bd->note == NULL ||
|
|
||||||
*bd->note == '\0') {
|
|
||||||
bd = key_bindings_next(table, bd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
width = utf8_cstrwidth(key_string_lookup_key(bd->key, 0));
|
|
||||||
if (width > keywidth)
|
if (width > keywidth)
|
||||||
keywidth = width;
|
keywidth = width;
|
||||||
|
|
||||||
bd = key_bindings_next(table, bd);
|
|
||||||
}
|
}
|
||||||
return (keywidth);
|
return (keywidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static u_int
|
||||||
cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
|
cmd_list_keys_get_table_width(struct key_binding **l, u_int n)
|
||||||
const char *tablename, u_int keywidth, key_code only, const char *prefix)
|
|
||||||
{
|
{
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
u_int i, width, tablewidth = 0;
|
||||||
struct key_table *table;
|
|
||||||
struct key_binding *bd;
|
|
||||||
const char *key;
|
|
||||||
char *tmp, *note;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
table = key_bindings_get_table(tablename, 0);
|
for (i = 0; i < n; i++) {
|
||||||
if (table == NULL)
|
width = utf8_cstrwidth(l[i]->tablename);
|
||||||
return (0);
|
if (width > tablewidth)
|
||||||
bd = key_bindings_first(table);
|
tablewidth = width;
|
||||||
while (bd != NULL) {
|
|
||||||
if ((only != KEYC_UNKNOWN && bd->key != only) ||
|
|
||||||
KEYC_IS_MOUSE(bd->key) ||
|
|
||||||
((bd->note == NULL || *bd->note == '\0') &&
|
|
||||||
!args_has(args, 'a'))) {
|
|
||||||
bd = key_bindings_next(table, bd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
found = 1;
|
|
||||||
key = key_string_lookup_key(bd->key, 0);
|
|
||||||
|
|
||||||
if (bd->note == NULL || *bd->note == '\0')
|
|
||||||
note = cmd_list_print(bd->cmdlist, 1);
|
|
||||||
else
|
|
||||||
note = xstrdup(bd->note);
|
|
||||||
tmp = utf8_padcstr(key, keywidth + 1);
|
|
||||||
if (args_has(args, '1') && tc != NULL) {
|
|
||||||
status_message_set(tc, -1, 1, 0, 0, "%s%s%s", prefix,
|
|
||||||
tmp, note);
|
|
||||||
} else
|
|
||||||
cmdq_print(item, "%s%s%s", prefix, tmp, note);
|
|
||||||
free(tmp);
|
|
||||||
free(note);
|
|
||||||
|
|
||||||
if (args_has(args, '1'))
|
|
||||||
break;
|
|
||||||
bd = key_bindings_next(table, bd);
|
|
||||||
}
|
}
|
||||||
return (found);
|
return (tablewidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static struct key_binding **
|
||||||
cmd_list_keys_get_prefix(struct args *args, key_code *prefix)
|
cmd_get_root_and_prefix(u_int *n, struct sort_criteria *sort_crit)
|
||||||
{
|
{
|
||||||
char *s;
|
const char *tables[] = { "prefix", "root" };
|
||||||
|
struct key_table *t;
|
||||||
|
struct key_binding **lt;
|
||||||
|
u_int i, ltsz, len = 0, offset = 0;
|
||||||
|
static struct key_binding **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
*prefix = options_get_number(global_s_options, "prefix");
|
for (i = 0; i < nitems(tables); i++) {
|
||||||
if (!args_has(args, 'P')) {
|
t = key_bindings_get_table(tables[i], 0);
|
||||||
if (*prefix != KEYC_NONE)
|
lt = sort_get_key_bindings_table(t, <sz, sort_crit);
|
||||||
xasprintf(&s, "%s ", key_string_lookup_key(*prefix, 0));
|
len += ltsz;
|
||||||
else
|
if (lsz <= len) {
|
||||||
s = xstrdup("");
|
lsz = len + 100;
|
||||||
} else
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
s = xstrdup(args_get(args, 'P'));
|
}
|
||||||
return (s);
|
memcpy(l + offset, lt, ltsz * sizeof *l);
|
||||||
|
offset += ltsz;
|
||||||
|
}
|
||||||
|
|
||||||
|
*n = len;
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_filter_key_list(int filter_notes, int filter_key, key_code only,
|
||||||
|
struct key_binding **l, u_int *n)
|
||||||
|
{
|
||||||
|
key_code key;
|
||||||
|
u_int i, j = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < *n; i++) {
|
||||||
|
key = l[i]->key & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS);
|
||||||
|
if (filter_key && only != key)
|
||||||
|
continue;
|
||||||
|
if (filter_notes && l[i]->note == NULL)
|
||||||
|
continue;
|
||||||
|
l[j++] = l[i];
|
||||||
|
}
|
||||||
|
*n = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_format_add_key_binding(struct format_tree *ft,
|
||||||
|
const struct key_binding *bd, const char *prefix)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
if (bd->flags & KEY_BINDING_REPEAT)
|
||||||
|
format_add(ft, "key_repeat", "1");
|
||||||
|
else
|
||||||
|
format_add(ft, "key_repeat", "0");
|
||||||
|
|
||||||
|
if (bd->note != NULL)
|
||||||
|
format_add(ft, "key_note", "%s", bd->note);
|
||||||
|
else
|
||||||
|
format_add(ft, "key_note", "%s", "");
|
||||||
|
|
||||||
|
format_add(ft, "key_prefix", "%s", prefix);
|
||||||
|
format_add(ft, "key_table", "%s", bd->tablename);
|
||||||
|
|
||||||
|
s = key_string_lookup_key(bd->key, 0);
|
||||||
|
format_add(ft, "key_string", "%s", s);
|
||||||
|
|
||||||
|
s = cmd_list_print(bd->cmdlist,
|
||||||
|
CMD_LIST_PRINT_ESCAPED|CMD_LIST_PRINT_NO_GROUPS);
|
||||||
|
format_add(ft, "key_command", "%s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
@@ -149,16 +168,16 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
struct key_table *table;
|
struct format_tree *ft;
|
||||||
struct key_binding *bd;
|
struct key_table *table = NULL;
|
||||||
const char *tablename, *r, *keystr;
|
struct key_binding **l;
|
||||||
char *key, *cp, *tmp, *start, *empty;
|
key_code only = KEYC_UNKNOWN;
|
||||||
key_code prefix, only = KEYC_UNKNOWN;
|
const char *template, *tablename, *keystr;
|
||||||
int repeat, width, tablewidth, keywidth, found = 0;
|
char *line;
|
||||||
size_t tmpsize, tmpused, cplen;
|
char *prefix = NULL;
|
||||||
|
u_int i, n;
|
||||||
if (cmd_get_entry(self) == &cmd_list_commands_entry)
|
int single, notes_only, filter_notes, filter_key;
|
||||||
return (cmd_list_keys_commands(self, item));
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if ((keystr = args_string(args, 0)) != NULL) {
|
if ((keystr = args_string(args, 0)) != NULL) {
|
||||||
only = key_string_lookup_string(keystr);
|
only = key_string_lookup_string(keystr);
|
||||||
@@ -169,218 +188,64 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
only &= (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS);
|
only &= (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
tablename = args_get(args, 'T');
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) {
|
if (sort_crit.order == SORT_END && args_has(args, 'O')) {
|
||||||
cmdq_error(item, "table %s doesn't exist", tablename);
|
cmdq_error(item, "invalid sort order");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
if (args_has(args, 'N')) {
|
prefix = cmd_list_keys_get_prefix(args);
|
||||||
if (tablename == NULL) {
|
single = args_has(args, '1');
|
||||||
start = cmd_list_keys_get_prefix(args, &prefix);
|
notes_only = args_has(args, 'N');
|
||||||
keywidth = cmd_list_keys_get_width("root", only);
|
|
||||||
if (prefix != KEYC_NONE) {
|
|
||||||
width = cmd_list_keys_get_width("prefix", only);
|
|
||||||
if (width == 0)
|
|
||||||
prefix = KEYC_NONE;
|
|
||||||
else if (width > keywidth)
|
|
||||||
keywidth = width;
|
|
||||||
}
|
|
||||||
empty = utf8_padcstr("", utf8_cstrwidth(start));
|
|
||||||
|
|
||||||
found = cmd_list_keys_print_notes(item, args, "root",
|
if ((tablename = args_get(args, 'T')) != NULL) {
|
||||||
keywidth, only, empty);
|
table = key_bindings_get_table(tablename, 0);
|
||||||
if (prefix != KEYC_NONE) {
|
if (table == NULL) {
|
||||||
if (cmd_list_keys_print_notes(item, args,
|
cmdq_error(item, "table %s doesn't exist", tablename);
|
||||||
"prefix", keywidth, only, start))
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
free(empty);
|
|
||||||
} else {
|
|
||||||
if (args_has(args, 'P'))
|
|
||||||
start = xstrdup(args_get(args, 'P'));
|
|
||||||
else
|
|
||||||
start = xstrdup("");
|
|
||||||
keywidth = cmd_list_keys_get_width(tablename, only);
|
|
||||||
found = cmd_list_keys_print_notes(item, args, tablename,
|
|
||||||
keywidth, only, start);
|
|
||||||
|
|
||||||
}
|
|
||||||
free(start);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
repeat = 0;
|
|
||||||
tablewidth = keywidth = 0;
|
|
||||||
table = key_bindings_first_table();
|
|
||||||
while (table != NULL) {
|
|
||||||
if (tablename != NULL && strcmp(table->name, tablename) != 0) {
|
|
||||||
table = key_bindings_next_table(table);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bd = key_bindings_first(table);
|
|
||||||
while (bd != NULL) {
|
|
||||||
if (only != KEYC_UNKNOWN && bd->key != only) {
|
|
||||||
bd = key_bindings_next(table, bd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
key = args_escape(key_string_lookup_key(bd->key, 0));
|
|
||||||
|
|
||||||
if (bd->flags & KEY_BINDING_REPEAT)
|
|
||||||
repeat = 1;
|
|
||||||
|
|
||||||
width = utf8_cstrwidth(table->name);
|
|
||||||
if (width > tablewidth)
|
|
||||||
tablewidth = width;
|
|
||||||
width = utf8_cstrwidth(key);
|
|
||||||
if (width > keywidth)
|
|
||||||
keywidth = width;
|
|
||||||
|
|
||||||
free(key);
|
|
||||||
bd = key_bindings_next(table, bd);
|
|
||||||
}
|
|
||||||
table = key_bindings_next_table(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpsize = 256;
|
|
||||||
tmp = xmalloc(tmpsize);
|
|
||||||
|
|
||||||
table = key_bindings_first_table();
|
|
||||||
while (table != NULL) {
|
|
||||||
if (tablename != NULL && strcmp(table->name, tablename) != 0) {
|
|
||||||
table = key_bindings_next_table(table);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
bd = key_bindings_first(table);
|
|
||||||
while (bd != NULL) {
|
|
||||||
if (only != KEYC_UNKNOWN && bd->key != only) {
|
|
||||||
bd = key_bindings_next(table, bd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
found = 1;
|
|
||||||
key = args_escape(key_string_lookup_key(bd->key, 0));
|
|
||||||
|
|
||||||
if (!repeat)
|
|
||||||
r = "";
|
|
||||||
else if (bd->flags & KEY_BINDING_REPEAT)
|
|
||||||
r = "-r ";
|
|
||||||
else
|
|
||||||
r = " ";
|
|
||||||
tmpused = xsnprintf(tmp, tmpsize, "%s-T ", r);
|
|
||||||
|
|
||||||
cp = utf8_padcstr(table->name, tablewidth);
|
|
||||||
cplen = strlen(cp) + 1;
|
|
||||||
while (tmpused + cplen + 1 >= tmpsize) {
|
|
||||||
tmpsize *= 2;
|
|
||||||
tmp = xrealloc(tmp, tmpsize);
|
|
||||||
}
|
|
||||||
strlcat(tmp, cp, tmpsize);
|
|
||||||
tmpused = strlcat(tmp, " ", tmpsize);
|
|
||||||
free(cp);
|
|
||||||
|
|
||||||
cp = utf8_padcstr(key, keywidth);
|
|
||||||
cplen = strlen(cp) + 1;
|
|
||||||
while (tmpused + cplen + 1 >= tmpsize) {
|
|
||||||
tmpsize *= 2;
|
|
||||||
tmp = xrealloc(tmp, tmpsize);
|
|
||||||
}
|
|
||||||
strlcat(tmp, cp, tmpsize);
|
|
||||||
tmpused = strlcat(tmp, " ", tmpsize);
|
|
||||||
free(cp);
|
|
||||||
|
|
||||||
cp = cmd_list_print(bd->cmdlist, 1);
|
|
||||||
cplen = strlen(cp);
|
|
||||||
while (tmpused + cplen + 1 >= tmpsize) {
|
|
||||||
tmpsize *= 2;
|
|
||||||
tmp = xrealloc(tmp, tmpsize);
|
|
||||||
}
|
|
||||||
strlcat(tmp, cp, tmpsize);
|
|
||||||
free(cp);
|
|
||||||
|
|
||||||
if (args_has(args, '1') && tc != NULL) {
|
|
||||||
status_message_set(tc, -1, 1, 0, 0,
|
|
||||||
"bind-key %s", tmp);
|
|
||||||
} else
|
|
||||||
cmdq_print(item, "bind-key %s", tmp);
|
|
||||||
free(key);
|
|
||||||
|
|
||||||
if (args_has(args, '1'))
|
|
||||||
break;
|
|
||||||
bd = key_bindings_next(table, bd);
|
|
||||||
}
|
|
||||||
table = key_bindings_next_table(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(tmp);
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (only != KEYC_UNKNOWN && !found) {
|
|
||||||
cmdq_error(item, "unknown key: %s", args_string(args, 0));
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_list_single_command(const struct cmd_entry *entry, struct format_tree *ft,
|
|
||||||
const char *template, struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
char *line;
|
|
||||||
|
|
||||||
format_add(ft, "command_list_name", "%s", entry->name);
|
|
||||||
if (entry->alias != NULL)
|
|
||||||
s = entry->alias;
|
|
||||||
else
|
|
||||||
s = "";
|
|
||||||
format_add(ft, "command_list_alias", "%s", s);
|
|
||||||
if (entry->usage != NULL)
|
|
||||||
s = entry->usage;
|
|
||||||
else
|
|
||||||
s = "";
|
|
||||||
format_add(ft, "command_list_usage", "%s", s);
|
|
||||||
|
|
||||||
line = format_expand(ft, template);
|
|
||||||
if (*line != '\0')
|
|
||||||
cmdq_print(item, "%s", line);
|
|
||||||
free(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
struct args *args = cmd_get_args(self);
|
|
||||||
const struct cmd_entry **entryp;
|
|
||||||
const struct cmd_entry *entry;
|
|
||||||
struct format_tree *ft;
|
|
||||||
const char *template, *command;
|
|
||||||
char *cause;
|
|
||||||
|
|
||||||
if ((template = args_get(args, 'F')) == NULL) {
|
|
||||||
template = "#{command_list_name}"
|
|
||||||
"#{?command_list_alias, (#{command_list_alias}),} "
|
|
||||||
"#{command_list_usage}";
|
|
||||||
}
|
|
||||||
|
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
|
||||||
format_defaults(ft, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
command = args_string(args, 0);
|
|
||||||
if (command == NULL) {
|
|
||||||
for (entryp = cmd_table; *entryp != NULL; entryp++)
|
|
||||||
cmd_list_single_command(*entryp, ft, template, item);
|
|
||||||
} else {
|
|
||||||
entry = cmd_find(command, &cause);
|
|
||||||
if (entry != NULL)
|
|
||||||
cmd_list_single_command(entry, ft, template, item);
|
|
||||||
else {
|
|
||||||
cmdq_error(item, "%s", cause);
|
|
||||||
free(cause);
|
|
||||||
format_free(ft);
|
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
|
template = LIST_KEYS_TEMPLATE;
|
||||||
|
|
||||||
|
if (table)
|
||||||
|
l = sort_get_key_bindings_table(table, &n, &sort_crit);
|
||||||
|
else if (notes_only)
|
||||||
|
l = cmd_get_root_and_prefix(&n, &sort_crit);
|
||||||
|
else
|
||||||
|
l = sort_get_key_bindings(&n, &sort_crit);
|
||||||
|
|
||||||
|
filter_notes = notes_only && !args_has(args, 'a');
|
||||||
|
filter_key = only != KEYC_UNKNOWN;
|
||||||
|
if (filter_notes || filter_key)
|
||||||
|
cmd_filter_key_list(filter_notes, filter_key, only, l, &n);
|
||||||
|
if (single)
|
||||||
|
n = 1;
|
||||||
|
|
||||||
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
|
format_defaults(ft, NULL, NULL, NULL, NULL);
|
||||||
|
format_add(ft, "notes_only", "%d", notes_only);
|
||||||
|
format_add(ft, "key_has_repeat", "%d", key_bindings_has_repeat(l, n));
|
||||||
|
format_add(ft, "key_string_width", "%u", cmd_list_keys_get_width(l, n));
|
||||||
|
format_add(ft, "key_table_width", "%u",
|
||||||
|
cmd_list_keys_get_table_width(l, n));
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
cmd_format_add_key_binding(ft, l[i], prefix);
|
||||||
|
|
||||||
|
line = format_expand(ft, template);
|
||||||
|
if ((single && tc != NULL) || n == 1)
|
||||||
|
status_message_set(tc, -1, 1, 0, 0, "%s", line);
|
||||||
|
else if (*line != '\0')
|
||||||
|
cmdq_print(item, "%s", line);
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
if (single)
|
||||||
|
break;
|
||||||
|
}
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
|
free(prefix);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,9 @@ const struct cmd_entry cmd_list_panes_entry = {
|
|||||||
.name = "list-panes",
|
.name = "list-panes",
|
||||||
.alias = "lsp",
|
.alias = "lsp",
|
||||||
|
|
||||||
.args = { "asF:f:t:", 0, 0, NULL },
|
.args = { "aF:f:O:rst:", 0, 0, NULL },
|
||||||
.usage = "[-as] [-F format] [-f filter] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-asr] [-F format] [-f filter] [-O order]"
|
||||||
|
CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
@@ -54,6 +55,13 @@ cmd_list_panes_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct session *s = target->s;
|
struct session *s = target->s;
|
||||||
struct winlink *wl = target->wl;
|
struct winlink *wl = target->wl;
|
||||||
|
enum sort_order order;
|
||||||
|
|
||||||
|
order = sort_order_from_string(args_get(args, 'O'));
|
||||||
|
if (order == SORT_END && args_has(args, 'O')) {
|
||||||
|
cmdq_error(item, "invalid sort order");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
if (args_has(args, 'a'))
|
if (args_has(args, 'a'))
|
||||||
cmd_list_panes_server(self, item);
|
cmd_list_panes_server(self, item);
|
||||||
@@ -89,12 +97,13 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
|
|||||||
struct cmdq_item *item, int type)
|
struct cmdq_item *item, int type)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct window_pane *wp;
|
struct window_pane *wp, **l;
|
||||||
u_int n;
|
u_int i, n;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
template = args_get(args, 'F');
|
template = args_get(args, 'F');
|
||||||
if (template == NULL) {
|
if (template == NULL) {
|
||||||
@@ -124,8 +133,12 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
|
|||||||
}
|
}
|
||||||
filter = args_get(args, 'f');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
n = 0;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
|
l = sort_get_panes_window(wl->window, &n, &sort_crit);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
wp = l[i];
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", n);
|
||||||
format_defaults(ft, NULL, s, wl, wp);
|
format_defaults(ft, NULL, s, wl, wp);
|
||||||
@@ -143,6 +156,5 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_list_sessions_entry = {
|
|||||||
.name = "list-sessions",
|
.name = "list-sessions",
|
||||||
.alias = "ls",
|
.alias = "ls",
|
||||||
|
|
||||||
.args = { "F:f:", 0, 0, NULL },
|
.args = { "F:f:O:r", 0, 0, NULL },
|
||||||
.usage = "[-F format] [-f filter]",
|
.usage = "[-r] [-F format] [-f filter] [-O order]",
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_list_sessions_exec
|
.exec = cmd_list_sessions_exec
|
||||||
@@ -52,23 +52,31 @@ const struct cmd_entry cmd_list_sessions_entry = {
|
|||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct session *s;
|
struct session **l;
|
||||||
u_int n;
|
u_int n, i;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if ((template = args_get(args, 'F')) == NULL)
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
template = LIST_SESSIONS_TEMPLATE;
|
template = LIST_SESSIONS_TEMPLATE;
|
||||||
filter = args_get(args, 'f');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
n = 0;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
if (sort_crit.order == SORT_END && args_has(args, 'O')) {
|
||||||
|
cmdq_error(item, "invalid sort order");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
|
l = sort_get_sessions(&n, &sort_crit);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", i);
|
||||||
format_defaults(ft, NULL, s, NULL, NULL);
|
format_defaults(ft, NULL, l[i], NULL, NULL);
|
||||||
|
|
||||||
if (filter != NULL) {
|
if (filter != NULL) {
|
||||||
expanded = format_expand(ft, filter);
|
expanded = format_expand(ft, filter);
|
||||||
@@ -83,7 +91,6 @@ cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -41,16 +41,13 @@
|
|||||||
|
|
||||||
static enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
|
||||||
static void cmd_list_windows_server(struct cmd *, struct cmdq_item *);
|
|
||||||
static void cmd_list_windows_session(struct cmd *, struct session *,
|
|
||||||
struct cmdq_item *, int);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_list_windows_entry = {
|
const struct cmd_entry cmd_list_windows_entry = {
|
||||||
.name = "list-windows",
|
.name = "list-windows",
|
||||||
.alias = "lsw",
|
.alias = "lsw",
|
||||||
|
|
||||||
.args = { "F:f:at:", 0, 0, NULL },
|
.args = { "aF:f:O:rt:", 0, 0, NULL },
|
||||||
.usage = "[-a] [-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-ar] [-F format] [-f filter] [-O order]"
|
||||||
|
CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_SESSION, 0 },
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
@@ -63,51 +60,38 @@ cmd_list_windows_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
|
struct winlink *wl, **l;
|
||||||
if (args_has(args, 'a'))
|
struct session *s;
|
||||||
cmd_list_windows_server(self, item);
|
u_int i, n;
|
||||||
else
|
|
||||||
cmd_list_windows_session(self, target->s, item, 0);
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_list_windows_server(struct cmd *self, struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
struct session *s;
|
|
||||||
|
|
||||||
RB_FOREACH(s, sessions, &sessions)
|
|
||||||
cmd_list_windows_session(self, s, item, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_list_windows_session(struct cmd *self, struct session *s,
|
|
||||||
struct cmdq_item *item, int type)
|
|
||||||
{
|
|
||||||
struct args *args = cmd_get_args(self);
|
|
||||||
struct winlink *wl;
|
|
||||||
u_int n;
|
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template, *filter;
|
const char *template, *filter;
|
||||||
char *line, *expanded;
|
char *line, *expanded;
|
||||||
int flag;
|
int flag;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
template = args_get(args, 'F');
|
template = args_get(args, 'F');
|
||||||
if (template == NULL) {
|
|
||||||
switch (type) {
|
|
||||||
case 0:
|
|
||||||
template = LIST_WINDOWS_TEMPLATE;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
template = LIST_WINDOWS_WITH_SESSION_TEMPLATE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filter = args_get(args, 'f');
|
filter = args_get(args, 'f');
|
||||||
|
|
||||||
n = 0;
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
if (sort_crit.order == SORT_END && args_has(args, 'O')) {
|
||||||
|
cmdq_error(item, "invalid sort order");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
|
if (args_has(args, 'a')) {
|
||||||
|
l = sort_get_winlinks(&n, &sort_crit);
|
||||||
|
if (template == NULL)
|
||||||
|
template = LIST_WINDOWS_WITH_SESSION_TEMPLATE;
|
||||||
|
} else {
|
||||||
|
l = sort_get_winlinks_session(target->s, &n, &sort_crit);
|
||||||
|
if (template == NULL)
|
||||||
|
template = LIST_WINDOWS_TEMPLATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
wl = l[i];
|
||||||
|
s = wl->session;
|
||||||
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", n);
|
||||||
format_defaults(ft, NULL, s, wl, NULL);
|
format_defaults(ft, NULL, s, wl, NULL);
|
||||||
@@ -125,6 +109,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
192
cmd-minimise-pane.c
Normal file
192
cmd-minimise-pane.c
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increase or decrease pane size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static enum cmd_retval cmd_minimise_pane_minimise_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
static enum cmd_retval cmd_minimise_pane_unminimise_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
|
||||||
|
static enum cmd_retval cmd_minimise_pane_minimise(struct window *, struct window_pane *);
|
||||||
|
static enum cmd_retval cmd_minimise_pane_unminimise(struct window *, struct window_pane *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_minimise_pane_entry = {
|
||||||
|
.name = "minimise-pane",
|
||||||
|
.alias = "minimize-pane",
|
||||||
|
|
||||||
|
.args = { "at:", 0, 1, NULL },
|
||||||
|
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
|
.flags = CMD_AFTERHOOK,
|
||||||
|
.exec = cmd_minimise_pane_minimise_exec
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_unminimise_pane_entry = {
|
||||||
|
.name = "unminimise-pane",
|
||||||
|
.alias = "unminimize-pane",
|
||||||
|
|
||||||
|
.args = { "at:", 0, 1, NULL },
|
||||||
|
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
|
.flags = CMD_AFTERHOOK,
|
||||||
|
.exec = cmd_minimise_pane_unminimise_exec
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_minimise_pane_minimise_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
|
{
|
||||||
|
__attribute((unused)) struct args *args = cmd_get_args(self);
|
||||||
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
|
struct winlink *wl = target->wl;
|
||||||
|
struct window *w = wl->window;
|
||||||
|
struct window_pane *wp;
|
||||||
|
u_int id;
|
||||||
|
char *cause = NULL;
|
||||||
|
enum cmd_retval rv;
|
||||||
|
|
||||||
|
if (args_has(args, 'a')) {
|
||||||
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
|
if (!window_pane_visible(wp))
|
||||||
|
continue;
|
||||||
|
rv = cmd_minimise_pane_minimise(w, wp);
|
||||||
|
if (rv != CMD_RETURN_NORMAL)
|
||||||
|
return(rv);
|
||||||
|
}
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
} else {
|
||||||
|
wp = target->wp;
|
||||||
|
if (wp == NULL) {
|
||||||
|
id = args_strtonum_and_expand(args, 't', 0, INT_MAX, item, &cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "%s target pane", cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
wp = window_pane_find_by_id(id);
|
||||||
|
}
|
||||||
|
if (wp == NULL) {
|
||||||
|
cmdq_error(item, "No target pane to miminise.");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
return(cmd_minimise_pane_minimise(w, wp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_minimise_pane_unminimise_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
|
{
|
||||||
|
__attribute((unused)) struct args *args = cmd_get_args(self);
|
||||||
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
|
struct winlink *wl = target->wl;
|
||||||
|
struct window *w = wl->window;
|
||||||
|
struct window_pane *wp;
|
||||||
|
u_int id;
|
||||||
|
char *cause = NULL;
|
||||||
|
enum cmd_retval rv;
|
||||||
|
|
||||||
|
if (args_has(args, 'a')) {
|
||||||
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
|
if (!window_pane_visible(wp))
|
||||||
|
continue;
|
||||||
|
rv = cmd_minimise_pane_unminimise(w, wp);
|
||||||
|
if (rv != CMD_RETURN_NORMAL)
|
||||||
|
return(rv);
|
||||||
|
}
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
} else {
|
||||||
|
wp = target->wp;
|
||||||
|
if (wp == NULL) {
|
||||||
|
id = args_strtonum_and_expand(args, 't', 0, INT_MAX, item, &cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "%s target pane", cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
wp = window_pane_find_by_id(id);
|
||||||
|
}
|
||||||
|
if (wp == NULL) {
|
||||||
|
cmdq_error(item, "No target pane to unmiminise.");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
return(cmd_minimise_pane_unminimise(w, wp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_minimise_pane_minimise(struct window *w, struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_pane *wp2;
|
||||||
|
|
||||||
|
wp->flags |= PANE_MINIMISED;
|
||||||
|
window_deactivate_pane(w, wp, 1);
|
||||||
|
|
||||||
|
/* Fix pane offsets and sizes. */
|
||||||
|
if (w->layout_root != NULL) {
|
||||||
|
wp->saved_layout_cell = wp->layout_cell;
|
||||||
|
layout_minimise_cell(w, wp->layout_cell);
|
||||||
|
layout_fix_offsets(w);
|
||||||
|
layout_fix_panes(w, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find next visible window in z-index. */
|
||||||
|
TAILQ_FOREACH(wp2, &w->z_index, zentry) {
|
||||||
|
if (!window_pane_visible(wp2))
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wp2 != NULL)
|
||||||
|
window_set_active_pane(w, wp2, 1);
|
||||||
|
|
||||||
|
notify_window("window-layout-changed", w);
|
||||||
|
server_redraw_window(w);
|
||||||
|
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_minimise_pane_unminimise(struct window *w, struct window_pane *wp)
|
||||||
|
{
|
||||||
|
wp->flags &= ~PANE_MINIMISED;
|
||||||
|
|
||||||
|
/* Fix pane offsets and sizes. */
|
||||||
|
if (w->layout_root != NULL && wp->saved_layout_cell != NULL) {
|
||||||
|
wp->layout_cell = wp->saved_layout_cell;
|
||||||
|
wp->saved_layout_cell = NULL;
|
||||||
|
layout_unminimise_cell(w, wp->layout_cell);
|
||||||
|
layout_fix_offsets(w);
|
||||||
|
layout_fix_panes(w, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
window_set_active_pane(w, wp, 1);
|
||||||
|
|
||||||
|
notify_window("window-layout-changed", w);
|
||||||
|
server_redraw_window(w);
|
||||||
|
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
245
cmd-new-pane.c
Normal file
245
cmd-new-pane.c
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 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 <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
#define NEW_PANE_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
|
||||||
|
|
||||||
|
static enum cmd_retval cmd_new_pane_exec(struct cmd *,
|
||||||
|
struct cmdq_item *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_new_pane_entry = {
|
||||||
|
.name = "new-pane",
|
||||||
|
.alias = "newp",
|
||||||
|
|
||||||
|
.args = { "bc:de:fF:h:Il:p:Pt:w:x:y:Z", 0, -1, NULL },
|
||||||
|
.usage = "[-bdefhIPvZ] [-c start-directory] [-e environment] "
|
||||||
|
"[-F format] [-l size] " CMD_TARGET_PANE_USAGE
|
||||||
|
" [shell-command [argument ...]]",
|
||||||
|
|
||||||
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
|
.flags = 0,
|
||||||
|
.exec = cmd_new_pane_exec
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_new_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
|
{
|
||||||
|
struct args *args = cmd_get_args(self);
|
||||||
|
struct cmd_find_state *current = cmdq_get_current(item);
|
||||||
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
|
struct spawn_context sc = { 0 };
|
||||||
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
|
struct session *s = target->s;
|
||||||
|
struct winlink *wl = target->wl;
|
||||||
|
struct window *w = wl->window;
|
||||||
|
struct window_pane *wp = target->wp, *new_wp;
|
||||||
|
struct layout_cell *lc;
|
||||||
|
struct cmd_find_state fs;
|
||||||
|
int flags, input;
|
||||||
|
const char *template;
|
||||||
|
char *cause = NULL, *cp;
|
||||||
|
struct args_value *av;
|
||||||
|
u_int count = args_count(args);
|
||||||
|
u_int x, y, sx, sy, pct;
|
||||||
|
static u_int last_x = 0, last_y = 0;
|
||||||
|
|
||||||
|
if (args_has(args, 'f')) {
|
||||||
|
sx = w->sx;
|
||||||
|
sy = w->sy;
|
||||||
|
} else {
|
||||||
|
if (args_has(args, 'l')) {
|
||||||
|
sx = args_percentage_and_expand(args, 'l', 0, INT_MAX, w->sx,
|
||||||
|
item, &cause);
|
||||||
|
sy = args_percentage_and_expand(args, 'l', 0, INT_MAX, w->sy,
|
||||||
|
item, &cause);
|
||||||
|
} else if (args_has(args, 'p')) {
|
||||||
|
pct = args_strtonum_and_expand(args, 'p', 0, 100, item,
|
||||||
|
&cause);
|
||||||
|
if (cause == NULL) {
|
||||||
|
sx = w->sx * pct / 100;
|
||||||
|
sy = w->sy * pct / 100;
|
||||||
|
}
|
||||||
|
} else if (cause == NULL) {
|
||||||
|
sx = w->sx / 2;
|
||||||
|
sy = w->sy / 2;
|
||||||
|
}
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "size %s", cause);
|
||||||
|
free(cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args_has(args, 'w')) {
|
||||||
|
sx = args_strtonum_and_expand(args, 'w', 0, w->sx, item,
|
||||||
|
&cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "size %s", cause);
|
||||||
|
free(cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args_has(args, 'h')) {
|
||||||
|
sy = args_strtonum_and_expand(args, 'h', 0, w->sy, item,
|
||||||
|
&cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "size %s", cause);
|
||||||
|
free(cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args_has(args, 'x')) {
|
||||||
|
x = args_strtonum_and_expand(args, 'x', 0, w->sx, item,
|
||||||
|
&cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "size %s", cause);
|
||||||
|
free(cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (last_x == 0) {
|
||||||
|
x = 5;
|
||||||
|
} else {
|
||||||
|
x = (last_x += 5);
|
||||||
|
if (last_x > w->sx)
|
||||||
|
x = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args_has(args, 'y')) {
|
||||||
|
y = args_strtonum_and_expand(args, 'y', 0, w->sx, item,
|
||||||
|
&cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "size %s", cause);
|
||||||
|
free(cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (last_y == 0) {
|
||||||
|
y = 5;
|
||||||
|
} else {
|
||||||
|
y = (last_y += 5);
|
||||||
|
if (last_y > w->sy)
|
||||||
|
y = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input = (args_has(args, 'I') && count == 0);
|
||||||
|
|
||||||
|
flags = SPAWN_FLOATING;
|
||||||
|
if (args_has(args, 'b'))
|
||||||
|
flags |= SPAWN_BEFORE;
|
||||||
|
if (args_has(args, 'f'))
|
||||||
|
flags |= SPAWN_FULLSIZE;
|
||||||
|
if (input || (count == 1 && *args_string(args, 0) == '\0'))
|
||||||
|
flags |= SPAWN_EMPTY;
|
||||||
|
|
||||||
|
sc.item = item;
|
||||||
|
sc.s = s;
|
||||||
|
sc.wl = wl;
|
||||||
|
|
||||||
|
sc.wp0 = wp;
|
||||||
|
|
||||||
|
/* Floating panes sit in layout cells which are not in the layout_root
|
||||||
|
* tree so we call it with parent == NULL.
|
||||||
|
*/
|
||||||
|
lc = layout_create_cell(NULL);
|
||||||
|
lc->xoff = x;
|
||||||
|
lc->yoff = y;
|
||||||
|
lc->sx = sx;
|
||||||
|
lc->sy = sy;
|
||||||
|
sc.lc = lc;
|
||||||
|
|
||||||
|
last_x = x; /* Statically save last xoff & yoff so that new */
|
||||||
|
last_y = y; /* floating panes offset so they don't overlap. */
|
||||||
|
|
||||||
|
args_to_vector(args, &sc.argc, &sc.argv);
|
||||||
|
sc.environ = environ_create();
|
||||||
|
|
||||||
|
av = args_first_value(args, 'e');
|
||||||
|
while (av != NULL) {
|
||||||
|
environ_put(sc.environ, av->string, 0);
|
||||||
|
av = args_next_value(av);
|
||||||
|
}
|
||||||
|
|
||||||
|
sc.idx = -1;
|
||||||
|
sc.cwd = args_get(args, 'c');
|
||||||
|
|
||||||
|
sc.flags = flags;
|
||||||
|
if (args_has(args, 'd'))
|
||||||
|
sc.flags |= SPAWN_DETACHED;
|
||||||
|
if (args_has(args, 'Z'))
|
||||||
|
sc.flags |= SPAWN_ZOOM;
|
||||||
|
|
||||||
|
if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
|
||||||
|
cmdq_error(item, "create pane failed: %s", cause);
|
||||||
|
free(cause);
|
||||||
|
if (sc.argv != NULL)
|
||||||
|
cmd_free_argv(sc.argc, sc.argv);
|
||||||
|
environ_free(sc.environ);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
if (input) {
|
||||||
|
switch (window_pane_start_input(new_wp, item, &cause)) {
|
||||||
|
case -1:
|
||||||
|
server_client_remove_pane(new_wp);
|
||||||
|
window_remove_pane(wp->window, new_wp);
|
||||||
|
cmdq_error(item, "%s", cause);
|
||||||
|
free(cause);
|
||||||
|
if (sc.argv != NULL)
|
||||||
|
cmd_free_argv(sc.argc, sc.argv);
|
||||||
|
environ_free(sc.environ);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
case 1:
|
||||||
|
input = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!args_has(args, 'd'))
|
||||||
|
cmd_find_from_winlink_pane(current, wl, new_wp, 0);
|
||||||
|
window_pop_zoom(wp->window);
|
||||||
|
server_redraw_window(wp->window);
|
||||||
|
server_status_session(s);
|
||||||
|
|
||||||
|
if (args_has(args, 'P')) {
|
||||||
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
|
template = NEW_PANE_TEMPLATE;
|
||||||
|
cp = format_single(item, template, tc, s, wl, new_wp);
|
||||||
|
cmdq_print(item, "%s", cp);
|
||||||
|
free(cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_find_from_winlink_pane(&fs, wl, new_wp, 0);
|
||||||
|
cmdq_insert_hook(s, item, &fs, "after-split-window");
|
||||||
|
|
||||||
|
if (sc.argv != NULL)
|
||||||
|
cmd_free_argv(sc.argc, sc.argv);
|
||||||
|
environ_free(sc.environ);
|
||||||
|
if (input)
|
||||||
|
return (CMD_RETURN_WAIT);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
@@ -117,8 +117,9 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
as = target->s;
|
as = target->s;
|
||||||
if (as != NULL) {
|
if (as != NULL) {
|
||||||
retval = cmd_attach_session(item, as->name,
|
retval = cmd_attach_session(item, as->name,
|
||||||
args_has(args, 'D'), args_has(args, 'X'), 0, NULL,
|
args_has(args, 'D'), args_has(args, 'X'), 0,
|
||||||
args_has(args, 'E'), args_get(args, 'f'));
|
args_get(args, 'c'), args_has(args, 'E'),
|
||||||
|
args_get(args, 'f'));
|
||||||
free(newname);
|
free(newname);
|
||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -758,7 +758,7 @@ static int
|
|||||||
cmd_parse_expand_alias(struct cmd_parse_command *cmd,
|
cmd_parse_expand_alias(struct cmd_parse_command *cmd,
|
||||||
struct cmd_parse_input *pi, struct cmd_parse_result *pr)
|
struct cmd_parse_input *pi, struct cmd_parse_result *pr)
|
||||||
{
|
{
|
||||||
struct cmd_parse_argument *arg, *arg1, *first;
|
struct cmd_parse_argument *first;
|
||||||
struct cmd_parse_commands *cmds;
|
struct cmd_parse_commands *cmds;
|
||||||
struct cmd_parse_command *last;
|
struct cmd_parse_command *last;
|
||||||
char *alias, *name, *cause;
|
char *alias, *name, *cause;
|
||||||
@@ -798,10 +798,7 @@ cmd_parse_expand_alias(struct cmd_parse_command *cmd,
|
|||||||
TAILQ_REMOVE(&cmd->arguments, first, entry);
|
TAILQ_REMOVE(&cmd->arguments, first, entry);
|
||||||
cmd_parse_free_argument(first);
|
cmd_parse_free_argument(first);
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(arg, &cmd->arguments, entry, arg1) {
|
TAILQ_CONCAT(&last->arguments, &cmd->arguments, entry);
|
||||||
TAILQ_REMOVE(&cmd->arguments, arg, entry);
|
|
||||||
TAILQ_INSERT_TAIL(&last->arguments, arg, entry);
|
|
||||||
}
|
|
||||||
cmd_parse_log_commands(cmds, __func__);
|
cmd_parse_log_commands(cmds, __func__);
|
||||||
|
|
||||||
pi->flags |= CMD_PARSE_NOALIAS;
|
pi->flags |= CMD_PARSE_NOALIAS;
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ const struct cmd_entry cmd_paste_buffer_entry = {
|
|||||||
.name = "paste-buffer",
|
.name = "paste-buffer",
|
||||||
.alias = "pasteb",
|
.alias = "pasteb",
|
||||||
|
|
||||||
.args = { "db:prs:t:", 0, 0, NULL },
|
.args = { "db:prSs:t:", 0, 0, NULL },
|
||||||
.usage = "[-dpr] [-s separator] " CMD_BUFFER_USAGE " "
|
.usage = "[-dprS] [-s separator] " CMD_BUFFER_USAGE " "
|
||||||
CMD_TARGET_PANE_USAGE,
|
CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
@@ -43,6 +43,17 @@ const struct cmd_entry cmd_paste_buffer_entry = {
|
|||||||
.exec = cmd_paste_buffer_exec
|
.exec = cmd_paste_buffer_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_paste_buffer_paste(struct window_pane *wp, const char *buf, size_t len)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
n = utf8_stravisx(&cp, buf, len, VIS_SAFE|VIS_NOSLASH);
|
||||||
|
bufferevent_write(wp->event, cp, n);
|
||||||
|
free(cp);
|
||||||
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
@@ -51,7 +62,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct window_pane *wp = target->wp;
|
struct window_pane *wp = target->wp;
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
const char *sepstr, *bufname, *bufdata, *bufend, *line;
|
const char *sepstr, *bufname, *bufdata, *bufend, *line;
|
||||||
size_t seplen, bufsize;
|
size_t seplen, bufsize, len;
|
||||||
int bracket = args_has(args, 'p');
|
int bracket = args_has(args, 'p');
|
||||||
|
|
||||||
if (window_pane_exited(wp)) {
|
if (window_pane_exited(wp)) {
|
||||||
@@ -93,14 +104,22 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
line = memchr(bufdata, '\n', bufend - bufdata);
|
line = memchr(bufdata, '\n', bufend - bufdata);
|
||||||
if (line == NULL)
|
if (line == NULL)
|
||||||
break;
|
break;
|
||||||
|
len = line - bufdata;
|
||||||
bufferevent_write(wp->event, bufdata, line - bufdata);
|
if (args_has(args, 'S'))
|
||||||
|
bufferevent_write(wp->event, bufdata, len);
|
||||||
|
else
|
||||||
|
cmd_paste_buffer_paste(wp, bufdata, len);
|
||||||
bufferevent_write(wp->event, sepstr, seplen);
|
bufferevent_write(wp->event, sepstr, seplen);
|
||||||
|
|
||||||
bufdata = line + 1;
|
bufdata = line + 1;
|
||||||
}
|
}
|
||||||
if (bufdata != bufend)
|
if (bufdata != bufend) {
|
||||||
bufferevent_write(wp->event, bufdata, bufend - bufdata);
|
len = bufend - bufdata;
|
||||||
|
if (args_has(args, 'S'))
|
||||||
|
bufferevent_write(wp->event, bufdata, len);
|
||||||
|
else
|
||||||
|
cmd_paste_buffer_paste(wp, bufdata, len);
|
||||||
|
}
|
||||||
|
|
||||||
if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
|
if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
|
||||||
bufferevent_write(wp->event, "\033[201~", 6);
|
bufferevent_write(wp->event, "\033[201~", 6);
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
/* Fork the child. */
|
/* Fork the child. */
|
||||||
sigfillset(&set);
|
sigfillset(&set);
|
||||||
sigprocmask(SIG_BLOCK, &set, &oldset);
|
sigprocmask(SIG_BLOCK, &set, &oldset);
|
||||||
switch (fork()) {
|
switch ((wp->pipe_pid = fork())) {
|
||||||
case -1:
|
case -1:
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
cmdq_error(item, "fork error: %s", strerror(errno));
|
cmdq_error(item, "fork error: %s", strerror(errno));
|
||||||
@@ -136,6 +136,9 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
close(pipe_fd[0]);
|
close(pipe_fd[0]);
|
||||||
|
|
||||||
|
if (setpgid(0, 0) == -1)
|
||||||
|
_exit(1);
|
||||||
|
|
||||||
null_fd = open(_PATH_DEVNULL, O_WRONLY);
|
null_fd = open(_PATH_DEVNULL, O_WRONLY);
|
||||||
if (out) {
|
if (out) {
|
||||||
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
|
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const struct cmd_entry cmd_refresh_client_entry = {
|
|||||||
.name = "refresh-client",
|
.name = "refresh-client",
|
||||||
.alias = "refresh",
|
.alias = "refresh",
|
||||||
|
|
||||||
.args = { "A:B:cC:Df:r:F:l::LRSt:U", 0, 1, NULL },
|
.args = { "A:B:cC:Df:r:F:lLRSt:U", 0, 1, NULL },
|
||||||
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
|
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
|
||||||
"[-C XxY] [-f flags] [-r pane:report] " CMD_TARGET_CLIENT_USAGE
|
"[-C XxY] [-f flags] [-r pane:report] " CMD_TARGET_CLIENT_USAGE
|
||||||
" [adjustment]",
|
" [adjustment]",
|
||||||
@@ -163,37 +163,6 @@ out:
|
|||||||
free(copy);
|
free(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_refresh_client_clipboard(struct cmd *self, struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
struct args *args = cmd_get_args(self);
|
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
|
||||||
const char *p;
|
|
||||||
u_int i;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
|
|
||||||
p = args_get(args, 'l');
|
|
||||||
if (p == NULL) {
|
|
||||||
if (tc->flags & CLIENT_CLIPBOARDBUFFER)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
tc->flags |= CLIENT_CLIPBOARDBUFFER;
|
|
||||||
} else {
|
|
||||||
if (cmd_find_target(&fs, item, p, CMD_FIND_PANE, 0) != 0)
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
for (i = 0; i < tc->clipboard_npanes; i++) {
|
|
||||||
if (tc->clipboard_panes[i] == fs.wp->id)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i != tc->clipboard_npanes)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
tc->clipboard_panes = xreallocarray(tc->clipboard_panes,
|
|
||||||
tc->clipboard_npanes + 1, sizeof *tc->clipboard_panes);
|
|
||||||
tc->clipboard_panes[tc->clipboard_npanes++] = fs.wp->id;
|
|
||||||
}
|
|
||||||
tty_clipboard_query(&tc->tty);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_refresh_report(struct tty *tty, const char *value)
|
cmd_refresh_report(struct tty *tty, const char *value)
|
||||||
{
|
{
|
||||||
@@ -284,8 +253,10 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'l'))
|
if (args_has(args, 'l')) {
|
||||||
return (cmd_refresh_client_clipboard(self, item));
|
tty_clipboard_query(&tc->tty);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
if (args_has(args, 'F')) /* -F is an alias for -f */
|
if (args_has(args, 'F')) /* -F is an alias for -f */
|
||||||
server_client_set_flags(tc, args_get(args, 'F'));
|
server_client_set_flags(tc, args_get(args, 'F'));
|
||||||
|
|||||||
@@ -29,7 +29,9 @@
|
|||||||
|
|
||||||
static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
|
||||||
static void cmd_resize_pane_mouse_update(struct client *,
|
static void cmd_resize_pane_mouse_update_floating(struct client *,
|
||||||
|
struct mouse_event *);
|
||||||
|
static void cmd_resize_pane_mouse_update_tiled(struct client *,
|
||||||
struct mouse_event *);
|
struct mouse_event *);
|
||||||
|
|
||||||
const struct cmd_entry cmd_resize_pane_entry = {
|
const struct cmd_entry cmd_resize_pane_entry = {
|
||||||
@@ -80,8 +82,15 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
if (c == NULL || c->session != s)
|
if (c == NULL || c->session != s)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
|
if (c->tty.mouse_wp->flags & PANE_FLOATING) {
|
||||||
cmd_resize_pane_mouse_update(c, &event->m);
|
window_redraw_active_switch(w, c->tty.mouse_wp);
|
||||||
|
window_set_active_pane(w, c->tty.mouse_wp, 1);
|
||||||
|
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_floating;
|
||||||
|
cmd_resize_pane_mouse_update_floating(c, &event->m);
|
||||||
|
} else {
|
||||||
|
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled;
|
||||||
|
cmd_resize_pane_mouse_update_tiled(c, &event->m);
|
||||||
|
}
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +158,136 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
|
cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m)
|
||||||
|
{
|
||||||
|
struct winlink *wl;
|
||||||
|
struct window *w;
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct layout_cell *lc;
|
||||||
|
u_int y, ly, x, lx, new_sx, new_sy;
|
||||||
|
int new_xoff, new_yoff, resizes = 0;
|
||||||
|
|
||||||
|
wl = cmd_mouse_window(m, NULL);
|
||||||
|
if (wl == NULL) {
|
||||||
|
c->tty.mouse_drag_update = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
w = wl->window;
|
||||||
|
|
||||||
|
y = m->y + m->oy; x = m->x + m->ox;
|
||||||
|
if (m->statusat == 0 && y >= m->statuslines)
|
||||||
|
y -= m->statuslines;
|
||||||
|
else if (m->statusat > 0 && y >= (u_int)m->statusat)
|
||||||
|
y = m->statusat - 1;
|
||||||
|
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
||||||
|
if (m->statusat == 0 && ly >= (u_int)m->statuslines)
|
||||||
|
ly -= m->statuslines;
|
||||||
|
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
|
||||||
|
ly = m->statusat - 1;
|
||||||
|
|
||||||
|
wp = c->tty.mouse_wp;
|
||||||
|
lc = wp->layout_cell;
|
||||||
|
|
||||||
|
log_debug("%s: %%%u resize_pane xoff=%u sx=%u xy=%ux%u lxy=%ux%u",
|
||||||
|
__func__, wp->id, wp->xoff, wp->sx, x, y, lx, ly);
|
||||||
|
if ((((int)lx == wp->xoff - 1) || ((int)lx == wp->xoff)) &&
|
||||||
|
((int)ly == wp->yoff - 1)) {
|
||||||
|
/* Top left corner */
|
||||||
|
new_sx = lc->sx + (lx - x);
|
||||||
|
if (new_sx < PANE_MINIMUM)
|
||||||
|
new_sx = PANE_MINIMUM;
|
||||||
|
new_sy = lc->sy + (ly - y);
|
||||||
|
if (new_sy < PANE_MINIMUM)
|
||||||
|
new_sy = PANE_MINIMUM;
|
||||||
|
new_xoff = x + 1; /* Because mouse is on border at xoff - 1 */
|
||||||
|
new_yoff = y + 1;
|
||||||
|
layout_set_size(lc, new_sx, new_sy, new_xoff, new_yoff);
|
||||||
|
resizes++;
|
||||||
|
} else if ((((int)lx == wp->xoff + (int)wp->sx + 1) ||
|
||||||
|
((int)lx == wp->xoff + (int)wp->sx)) &&
|
||||||
|
((int)ly == wp->yoff - 1)) {
|
||||||
|
/* Top right corner */
|
||||||
|
new_sx = x - lc->xoff;
|
||||||
|
if (new_sx < PANE_MINIMUM)
|
||||||
|
new_sx = PANE_MINIMUM;
|
||||||
|
new_sy = lc->sy + (ly - y);
|
||||||
|
if (new_sy < PANE_MINIMUM)
|
||||||
|
new_sy = PANE_MINIMUM;
|
||||||
|
new_yoff = y + 1;
|
||||||
|
layout_set_size(lc, new_sx, new_sy, lc->xoff, new_yoff);
|
||||||
|
resizes++;
|
||||||
|
} else if ((((int)lx == wp->xoff - 1) || ((int)lx == wp->xoff)) &&
|
||||||
|
((int)ly == wp->yoff + (int)wp->sy)) {
|
||||||
|
/* Bottom left corner */
|
||||||
|
new_sx = lc->sx + (lx - x);
|
||||||
|
if (new_sx < PANE_MINIMUM)
|
||||||
|
new_sx = PANE_MINIMUM;
|
||||||
|
new_sy = y - lc->yoff;
|
||||||
|
if (new_sy < PANE_MINIMUM)
|
||||||
|
return;
|
||||||
|
new_xoff = x + 1;
|
||||||
|
layout_set_size(lc, new_sx, new_sy, new_xoff, lc->yoff);
|
||||||
|
resizes++;
|
||||||
|
} else if ((((int)lx == wp->xoff + (int)wp->sx + 1) ||
|
||||||
|
((int)lx == wp->xoff + (int)wp->sx)) &&
|
||||||
|
((int)ly == wp->yoff + (int)wp->sy)) {
|
||||||
|
/* Bottom right corner */
|
||||||
|
new_sx = x - lc->xoff;
|
||||||
|
if (new_sx < PANE_MINIMUM)
|
||||||
|
new_sx = PANE_MINIMUM;
|
||||||
|
new_sy = y - lc->yoff;
|
||||||
|
if (new_sy < PANE_MINIMUM)
|
||||||
|
new_sy = PANE_MINIMUM;
|
||||||
|
layout_set_size(lc, new_sx, new_sy, lc->xoff, lc->yoff);
|
||||||
|
resizes++;
|
||||||
|
} else if ((int)lx == wp->xoff + (int)wp->sx + 1) {
|
||||||
|
/* Right border */
|
||||||
|
new_sx = x - lc->xoff;
|
||||||
|
if (new_sx < PANE_MINIMUM)
|
||||||
|
return;
|
||||||
|
layout_set_size(lc, new_sx, lc->sy, lc->xoff, lc->yoff);
|
||||||
|
resizes++;
|
||||||
|
} else if ((int)lx == wp->xoff - 1) {
|
||||||
|
/* Left border */
|
||||||
|
new_sx = lc->sx + (lx - x);
|
||||||
|
if (new_sx < PANE_MINIMUM)
|
||||||
|
return;
|
||||||
|
new_xoff = x + 1;
|
||||||
|
layout_set_size(lc, new_sx, lc->sy, new_xoff, lc->yoff);
|
||||||
|
resizes++;
|
||||||
|
} else if ((int)ly == wp->yoff + (int)wp->sy) {
|
||||||
|
/* Bottom border */
|
||||||
|
new_sy = y - lc->yoff;
|
||||||
|
if (new_sy < PANE_MINIMUM)
|
||||||
|
return;
|
||||||
|
layout_set_size(lc, lc->sx, new_sy, lc->xoff, lc->yoff);
|
||||||
|
resizes++;
|
||||||
|
} else if ((int)ly == wp->yoff - 1) {
|
||||||
|
/* Top border (move instead of resize) */
|
||||||
|
new_xoff = lc->xoff + (x - lx);
|
||||||
|
new_yoff = y + 1;
|
||||||
|
layout_set_size(lc, lc->sx, lc->sy, new_xoff, new_yoff);
|
||||||
|
/* To resize instead of move:
|
||||||
|
new_sy = wp->sy + (ly - y);
|
||||||
|
if (new_sy < PANE_MINIMUM)
|
||||||
|
return;
|
||||||
|
new_yoff = y + 1;
|
||||||
|
layout_set_size(lc, lc->sx, new_sy, lc->xoff, new_yoff);
|
||||||
|
*/
|
||||||
|
resizes++;
|
||||||
|
} else {
|
||||||
|
log_debug("%s: %%%u resize_pane xoff=%u sx=%u xy=%ux%u lxy=%ux%u <else>",
|
||||||
|
__func__, wp->id, wp->xoff, wp->sx, x, y, lx, ly);
|
||||||
|
}
|
||||||
|
if (resizes != 0) {
|
||||||
|
layout_fix_panes(w, NULL);
|
||||||
|
server_redraw_window(w);
|
||||||
|
server_redraw_window_borders(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_resize_pane_mouse_update_tiled(struct client *c, struct mouse_event *m)
|
||||||
{
|
{
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
previous = 1;
|
previous = 1;
|
||||||
|
|
||||||
oldlayout = w->old_layout;
|
oldlayout = w->old_layout;
|
||||||
w->old_layout = layout_dump(w->layout_root);
|
w->old_layout = layout_dump(w, w->layout_root);
|
||||||
|
|
||||||
if (next || previous) {
|
if (next || previous) {
|
||||||
if (next)
|
if (next)
|
||||||
|
|||||||
@@ -160,6 +160,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
server_redraw_window_borders(markedwp->window);
|
server_redraw_window_borders(markedwp->window);
|
||||||
server_status_window(markedwp->window);
|
server_status_window(markedwp->window);
|
||||||
}
|
}
|
||||||
|
if (wp->flags & PANE_FLOATING) {
|
||||||
|
window_redraw_active_switch(w, wp);
|
||||||
|
window_set_active_pane(w, wp, 1);
|
||||||
|
}
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ const struct cmd_entry cmd_send_keys_entry = {
|
|||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL,
|
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL|
|
||||||
|
CMD_READONLY,
|
||||||
.exec = cmd_send_keys_exec
|
.exec = cmd_send_keys_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -167,6 +168,11 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
u_int count = args_count(args);
|
u_int count = args_count(args);
|
||||||
char *cause = NULL;
|
char *cause = NULL;
|
||||||
|
|
||||||
|
if (tc != NULL && tc->flags & CLIENT_READONLY && !args_has(args, 'X')) {
|
||||||
|
cmdq_error(item, "client is read-only");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
if (args_has(args, 'N')) {
|
if (args_has(args, 'N')) {
|
||||||
np = args_strtonum_and_expand(args, 'N', 1, UINT_MAX, item,
|
np = args_strtonum_and_expand(args, 'N', 1, UINT_MAX, item,
|
||||||
&cause);
|
&cause);
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ cmd_server_access_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
pw = getpwnam(name);
|
pw = getpwnam(name);
|
||||||
if (pw == NULL) {
|
if (pw == NULL) {
|
||||||
cmdq_error(item, "unknown user: %s", name);
|
cmdq_error(item, "unknown user: %s", name);
|
||||||
|
free(name);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
free(name);
|
free(name);
|
||||||
|
|||||||
@@ -57,30 +57,30 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb = NULL;
|
||||||
char *bufdata, *cause;
|
char *bufname = NULL, *bufdata = NULL, *cause = NULL;
|
||||||
const char *bufname, *olddata;
|
const char *olddata;
|
||||||
size_t bufsize, newsize;
|
size_t bufsize = 0, newsize;
|
||||||
|
|
||||||
bufname = args_get(args, 'b');
|
if (args_get(args, 'b') != NULL) {
|
||||||
if (bufname == NULL)
|
bufname = xstrdup(args_get(args, 'b'));
|
||||||
pb = NULL;
|
|
||||||
else
|
|
||||||
pb = paste_get_name(bufname);
|
pb = paste_get_name(bufname);
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_delete_buffer_entry) {
|
if (cmd_get_entry(self) == &cmd_delete_buffer_entry) {
|
||||||
if (pb == NULL) {
|
if (pb == NULL) {
|
||||||
if (bufname != NULL) {
|
if (bufname != NULL) {
|
||||||
cmdq_error(item, "unknown buffer: %s", bufname);
|
cmdq_error(item, "unknown buffer: %s", bufname);
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
pb = paste_get_top(&bufname);
|
pb = paste_get_top(&bufname);
|
||||||
}
|
}
|
||||||
if (pb == NULL) {
|
if (pb == NULL) {
|
||||||
cmdq_error(item, "no buffer");
|
cmdq_error(item, "no buffer");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
paste_free(pb);
|
paste_free(pb);
|
||||||
|
free(bufname);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,32 +88,28 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (pb == NULL) {
|
if (pb == NULL) {
|
||||||
if (bufname != NULL) {
|
if (bufname != NULL) {
|
||||||
cmdq_error(item, "unknown buffer: %s", bufname);
|
cmdq_error(item, "unknown buffer: %s", bufname);
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
pb = paste_get_top(&bufname);
|
pb = paste_get_top(&bufname);
|
||||||
}
|
}
|
||||||
if (pb == NULL) {
|
if (pb == NULL) {
|
||||||
cmdq_error(item, "no buffer");
|
cmdq_error(item, "no buffer");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
if (paste_rename(bufname, args_get(args, 'n'), &cause) != 0) {
|
if (paste_rename(bufname, args_get(args, 'n'), &cause) != 0) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
goto fail;
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_count(args) != 1) {
|
if (args_count(args) != 1) {
|
||||||
cmdq_error(item, "no data specified");
|
cmdq_error(item, "no data specified");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((newsize = strlen(args_string(args, 0))) == 0)
|
if ((newsize = strlen(args_string(args, 0))) == 0)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
bufsize = 0;
|
|
||||||
bufdata = NULL;
|
|
||||||
|
|
||||||
if (args_has(args, 'a') && pb != NULL) {
|
if (args_has(args, 'a') && pb != NULL) {
|
||||||
olddata = paste_buffer_data(pb, &bufsize);
|
olddata = paste_buffer_data(pb, &bufsize);
|
||||||
bufdata = xmalloc(bufsize);
|
bufdata = xmalloc(bufsize);
|
||||||
@@ -126,12 +122,16 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (paste_set(bufdata, bufsize, bufname, &cause) != 0) {
|
if (paste_set(bufdata, bufsize, bufname, &cause) != 0) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(bufdata);
|
goto fail;
|
||||||
free(cause);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
}
|
||||||
if (args_has(args, 'w') && tc != NULL)
|
if (args_has(args, 'w') && tc != NULL)
|
||||||
tty_set_selection(&tc->tty, "", bufdata, bufsize);
|
tty_set_selection(&tc->tty, "", bufdata, bufsize);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(bufdata);
|
||||||
|
free(bufname);
|
||||||
|
free(cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ cmd_show_prompt_history_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (cmd_get_entry(self) == &cmd_clear_prompt_history_entry) {
|
if (cmd_get_entry(self) == &cmd_clear_prompt_history_entry) {
|
||||||
if (typestr == NULL) {
|
if (typestr == NULL) {
|
||||||
for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) {
|
for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) {
|
||||||
|
for (hidx = 0; hidx < status_prompt_hsize[tidx];
|
||||||
|
hidx++)
|
||||||
|
free(status_prompt_hlist[tidx][hidx]);
|
||||||
free(status_prompt_hlist[tidx]);
|
free(status_prompt_hlist[tidx]);
|
||||||
status_prompt_hlist[tidx] = NULL;
|
status_prompt_hlist[tidx] = NULL;
|
||||||
status_prompt_hsize[tidx] = 0;
|
status_prompt_hsize[tidx] = 0;
|
||||||
@@ -70,6 +73,8 @@ cmd_show_prompt_history_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "invalid type: %s", typestr);
|
cmdq_error(item, "invalid type: %s", typestr);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
for (hidx = 0; hidx < status_prompt_hsize[type]; hidx++)
|
||||||
|
free(status_prompt_hlist[type][hidx]);
|
||||||
free(status_prompt_hlist[type]);
|
free(status_prompt_hlist[type]);
|
||||||
status_prompt_hlist[type] = NULL;
|
status_prompt_hlist[type] = NULL;
|
||||||
status_prompt_hsize[type] = 0;
|
status_prompt_hsize[type] = 0;
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct args_value *av;
|
struct args_value *av;
|
||||||
u_int count = args_count(args), curval = 0;
|
u_int count = args_count(args), curval = 0;
|
||||||
|
|
||||||
|
if (wp->flags & PANE_FLOATING) {
|
||||||
|
cmdq_error(item, "can't split a floating pane");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
type = LAYOUT_TOPBOTTOM;
|
type = LAYOUT_TOPBOTTOM;
|
||||||
if (args_has(args, 'h'))
|
if (args_has(args, 'h'))
|
||||||
type = LAYOUT_LEFTRIGHT;
|
type = LAYOUT_LEFTRIGHT;
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ const struct cmd_entry cmd_switch_client_entry = {
|
|||||||
.name = "switch-client",
|
.name = "switch-client",
|
||||||
.alias = "switchc",
|
.alias = "switchc",
|
||||||
|
|
||||||
.args = { "lc:EFnpt:rT:Z", 0, 0, NULL },
|
.args = { "c:EFlnO:pt:rT:Z", 0, 0, NULL },
|
||||||
.usage = "[-ElnprZ] [-c target-client] [-t target-session] "
|
.usage = "[-ElnprZ] [-c target-client] [-t target-session] "
|
||||||
"[-T key-table]",
|
"[-T key-table] [-O order]",
|
||||||
|
|
||||||
/* -t is special */
|
/* -t is special */
|
||||||
|
|
||||||
@@ -60,6 +60,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
const char *tablename;
|
const char *tablename;
|
||||||
struct key_table *table;
|
struct key_table *table;
|
||||||
|
struct sort_criteria sort_crit;
|
||||||
|
|
||||||
if (tflag != NULL &&
|
if (tflag != NULL &&
|
||||||
(tflag[strcspn(tflag, ":.%")] != '\0' || strcmp(tflag, "=") == 0)) {
|
(tflag[strcspn(tflag, ":.%")] != '\0' || strcmp(tflag, "=") == 0)) {
|
||||||
@@ -95,13 +96,22 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
|
if (sort_crit.order == SORT_END && args_has(args, 'O')) {
|
||||||
|
cmdq_error(item, "invalid sort order");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
if (args_has(args, 'n')) {
|
if (args_has(args, 'n')) {
|
||||||
if ((s = session_next_session(tc->session)) == NULL) {
|
s = session_next_session(tc->session, &sort_crit);
|
||||||
|
if (s == NULL) {
|
||||||
cmdq_error(item, "can't find next session");
|
cmdq_error(item, "can't find next session");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
} else if (args_has(args, 'p')) {
|
} else if (args_has(args, 'p')) {
|
||||||
if ((s = session_previous_session(tc->session)) == NULL) {
|
s = session_previous_session(tc->session, &sort_crit);
|
||||||
|
if (s == NULL) {
|
||||||
cmdq_error(item, "can't find previous session");
|
cmdq_error(item, "can't find previous session");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
33
cmd.c
33
cmd.c
@@ -69,8 +69,10 @@ extern const struct cmd_entry cmd_load_buffer_entry;
|
|||||||
extern const struct cmd_entry cmd_lock_client_entry;
|
extern const struct cmd_entry cmd_lock_client_entry;
|
||||||
extern const struct cmd_entry cmd_lock_server_entry;
|
extern const struct cmd_entry cmd_lock_server_entry;
|
||||||
extern const struct cmd_entry cmd_lock_session_entry;
|
extern const struct cmd_entry cmd_lock_session_entry;
|
||||||
|
extern const struct cmd_entry cmd_minimise_pane_entry;
|
||||||
extern const struct cmd_entry cmd_move_pane_entry;
|
extern const struct cmd_entry cmd_move_pane_entry;
|
||||||
extern const struct cmd_entry cmd_move_window_entry;
|
extern const struct cmd_entry cmd_move_window_entry;
|
||||||
|
extern const struct cmd_entry cmd_new_pane_entry;
|
||||||
extern const struct cmd_entry cmd_new_session_entry;
|
extern const struct cmd_entry cmd_new_session_entry;
|
||||||
extern const struct cmd_entry cmd_new_window_entry;
|
extern const struct cmd_entry cmd_new_window_entry;
|
||||||
extern const struct cmd_entry cmd_next_layout_entry;
|
extern const struct cmd_entry cmd_next_layout_entry;
|
||||||
@@ -116,6 +118,7 @@ extern const struct cmd_entry cmd_swap_window_entry;
|
|||||||
extern const struct cmd_entry cmd_switch_client_entry;
|
extern const struct cmd_entry cmd_switch_client_entry;
|
||||||
extern const struct cmd_entry cmd_unbind_key_entry;
|
extern const struct cmd_entry cmd_unbind_key_entry;
|
||||||
extern const struct cmd_entry cmd_unlink_window_entry;
|
extern const struct cmd_entry cmd_unlink_window_entry;
|
||||||
|
extern const struct cmd_entry cmd_unminimise_pane_entry;
|
||||||
extern const struct cmd_entry cmd_wait_for_entry;
|
extern const struct cmd_entry cmd_wait_for_entry;
|
||||||
|
|
||||||
const struct cmd_entry *cmd_table[] = {
|
const struct cmd_entry *cmd_table[] = {
|
||||||
@@ -161,8 +164,10 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_lock_client_entry,
|
&cmd_lock_client_entry,
|
||||||
&cmd_lock_server_entry,
|
&cmd_lock_server_entry,
|
||||||
&cmd_lock_session_entry,
|
&cmd_lock_session_entry,
|
||||||
|
&cmd_minimise_pane_entry,
|
||||||
&cmd_move_pane_entry,
|
&cmd_move_pane_entry,
|
||||||
&cmd_move_window_entry,
|
&cmd_move_window_entry,
|
||||||
|
&cmd_new_pane_entry,
|
||||||
&cmd_new_session_entry,
|
&cmd_new_session_entry,
|
||||||
&cmd_new_window_entry,
|
&cmd_new_window_entry,
|
||||||
&cmd_next_layout_entry,
|
&cmd_next_layout_entry,
|
||||||
@@ -208,6 +213,7 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_switch_client_entry,
|
&cmd_switch_client_entry,
|
||||||
&cmd_unbind_key_entry,
|
&cmd_unbind_key_entry,
|
||||||
&cmd_unlink_window_entry,
|
&cmd_unlink_window_entry,
|
||||||
|
&cmd_unminimise_pane_entry,
|
||||||
&cmd_wait_for_entry,
|
&cmd_wait_for_entry,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
@@ -676,11 +682,16 @@ cmd_list_copy(const struct cmd_list *cmdlist, int argc, char **argv)
|
|||||||
|
|
||||||
/* Get a command list as a string. */
|
/* Get a command list as a string. */
|
||||||
char *
|
char *
|
||||||
cmd_list_print(const struct cmd_list *cmdlist, int escaped)
|
cmd_list_print(const struct cmd_list *cmdlist, int flags)
|
||||||
{
|
{
|
||||||
struct cmd *cmd, *next;
|
struct cmd *cmd, *next;
|
||||||
char *buf, *this;
|
char *buf, *this;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
const char *separator;
|
||||||
|
int escaped = flags & CMD_LIST_PRINT_ESCAPED;
|
||||||
|
int no_groups = flags & CMD_LIST_PRINT_NO_GROUPS;
|
||||||
|
const char *single_separator = escaped ? " \\; " : " ; ";
|
||||||
|
const char *double_separator = escaped ? " \\;\\; " : " ;; ";
|
||||||
|
|
||||||
len = 1;
|
len = 1;
|
||||||
buf = xcalloc(1, len);
|
buf = xcalloc(1, len);
|
||||||
@@ -695,17 +706,11 @@ cmd_list_print(const struct cmd_list *cmdlist, int escaped)
|
|||||||
|
|
||||||
next = TAILQ_NEXT(cmd, qentry);
|
next = TAILQ_NEXT(cmd, qentry);
|
||||||
if (next != NULL) {
|
if (next != NULL) {
|
||||||
if (cmd->group != next->group) {
|
if (!no_groups && cmd->group != next->group)
|
||||||
if (escaped)
|
separator = double_separator;
|
||||||
strlcat(buf, " \\;\\; ", len);
|
else
|
||||||
else
|
separator = single_separator;
|
||||||
strlcat(buf, " ;; ", len);
|
strlcat(buf, separator, len);
|
||||||
} else {
|
|
||||||
if (escaped)
|
|
||||||
strlcat(buf, " \\; ", len);
|
|
||||||
else
|
|
||||||
strlcat(buf, " ; ", len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
@@ -773,9 +778,9 @@ cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
|
|||||||
if (m->statusat == 0 && y >= m->statuslines)
|
if (m->statusat == 0 && y >= m->statuslines)
|
||||||
y -= m->statuslines;
|
y -= m->statuslines;
|
||||||
|
|
||||||
if (x < wp->xoff || x >= wp->xoff + wp->sx)
|
if ((int)x < wp->xoff || (int)x >= wp->xoff + (int)wp->sx)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (y < wp->yoff || y >= wp->yoff + wp->sy)
|
if ((int)y < wp->yoff || (int)y >= wp->yoff + (int)wp->sy)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (xp != NULL)
|
if (xp != NULL)
|
||||||
|
|||||||
27
colour.c
27
colour.c
@@ -1082,22 +1082,22 @@ colour_palette_free(struct colour_palette *p)
|
|||||||
|
|
||||||
/* Get a colour from a palette. */
|
/* Get a colour from a palette. */
|
||||||
int
|
int
|
||||||
colour_palette_get(struct colour_palette *p, int c)
|
colour_palette_get(struct colour_palette *p, int n)
|
||||||
{
|
{
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (c >= 90 && c <= 97)
|
if (n >= 90 && n <= 97)
|
||||||
c = 8 + c - 90;
|
n = 8 + n - 90;
|
||||||
else if (c & COLOUR_FLAG_256)
|
else if (n & COLOUR_FLAG_256)
|
||||||
c &= ~COLOUR_FLAG_256;
|
n &= ~COLOUR_FLAG_256;
|
||||||
else if (c >= 8)
|
else if (n >= 8)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (p->palette != NULL && p->palette[c] != -1)
|
if (p->palette != NULL && p->palette[n] != -1)
|
||||||
return (p->palette[c]);
|
return (p->palette[n]);
|
||||||
if (p->default_palette != NULL && p->default_palette[c] != -1)
|
if (p->default_palette != NULL && p->default_palette[n] != -1)
|
||||||
return (p->default_palette[c]);
|
return (p->default_palette[n]);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1107,15 +1107,14 @@ colour_palette_set(struct colour_palette *p, int n, int c)
|
|||||||
{
|
{
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (p == NULL || n > 255)
|
if (p == NULL || n < 0 || n > 255)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (c == -1 && p->palette == NULL)
|
if (c == -1 && p->palette == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (c != -1 && p->palette == NULL) {
|
if (p->palette == NULL) {
|
||||||
if (p->palette == NULL)
|
p->palette = xcalloc(256, sizeof *p->palette);
|
||||||
p->palette = xcalloc(256, sizeof *p->palette);
|
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
p->palette[i] = -1;
|
p->palette[i] = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
2
compat.h
2
compat.h
@@ -388,7 +388,7 @@ int clock_gettime(int, struct timespec *);
|
|||||||
/* base64.c */
|
/* base64.c */
|
||||||
#undef b64_ntop
|
#undef b64_ntop
|
||||||
#undef b64_pton
|
#undef b64_pton
|
||||||
int b64_ntop(const char *, size_t, char *, size_t);
|
int b64_ntop(const u_char *, size_t, char *, size_t);
|
||||||
int b64_pton(const char *, u_char *, size_t);
|
int b64_pton(const char *, u_char *, size_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: base64.c,v 1.8 2015/01/16 16:48:51 deraadt Exp $ */
|
/* $OpenBSD: base64.c,v 1.15 2021/10/25 14:41:09 jca Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996 by Internet Software Consortium.
|
* Copyright (c) 1996 by Internet Software Consortium.
|
||||||
@@ -46,15 +46,15 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <arpa/nameser.h>
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
static const char Base64[] =
|
static const char Base64[] =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
static const char Pad64 = '=';
|
static const char Pad64 = '=';
|
||||||
@@ -107,9 +107,9 @@ static const char Pad64 = '=';
|
|||||||
end of the data is performed using the '=' character.
|
end of the data is performed using the '=' character.
|
||||||
|
|
||||||
Since all base64 input is an integral number of octets, only the
|
Since all base64 input is an integral number of octets, only the
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
following cases can arise:
|
following cases can arise:
|
||||||
|
|
||||||
(1) the final quantum of encoding input is an integral
|
(1) the final quantum of encoding input is an integral
|
||||||
multiple of 24 bits; here, the final unit of encoded
|
multiple of 24 bits; here, the final unit of encoded
|
||||||
output will be an integral multiple of 4 characters
|
output will be an integral multiple of 4 characters
|
||||||
@@ -123,15 +123,12 @@ static const char Pad64 = '=';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
b64_ntop(src, srclength, target, targsize)
|
b64_ntop(unsigned char const *src, size_t srclength, char *target,
|
||||||
u_char const *src;
|
size_t targsize)
|
||||||
size_t srclength;
|
|
||||||
char *target;
|
|
||||||
size_t targsize;
|
|
||||||
{
|
{
|
||||||
size_t datalength = 0;
|
size_t datalength = 0;
|
||||||
u_char input[3];
|
unsigned char input[3];
|
||||||
u_char output[4];
|
unsigned char output[4];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
while (2 < srclength) {
|
while (2 < srclength) {
|
||||||
@@ -152,14 +149,14 @@ b64_ntop(src, srclength, target, targsize)
|
|||||||
target[datalength++] = Base64[output[2]];
|
target[datalength++] = Base64[output[2]];
|
||||||
target[datalength++] = Base64[output[3]];
|
target[datalength++] = Base64[output[3]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we worry about padding. */
|
/* Now we worry about padding. */
|
||||||
if (0 != srclength) {
|
if (0 != srclength) {
|
||||||
/* Get what's left. */
|
/* Get what's left. */
|
||||||
input[0] = input[1] = input[2] = '\0';
|
input[0] = input[1] = input[2] = '\0';
|
||||||
for (i = 0; i < srclength; i++)
|
for (i = 0; i < srclength; i++)
|
||||||
input[i] = *src++;
|
input[i] = *src++;
|
||||||
|
|
||||||
output[0] = input[0] >> 2;
|
output[0] = input[0] >> 2;
|
||||||
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
|
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
|
||||||
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
|
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
|
||||||
@@ -187,13 +184,10 @@ b64_ntop(src, srclength, target, targsize)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
b64_pton(src, target, targsize)
|
b64_pton(char const *src, unsigned char *target, size_t targsize)
|
||||||
char const *src;
|
|
||||||
u_char *target;
|
|
||||||
size_t targsize;
|
|
||||||
{
|
{
|
||||||
int tarindex, state, ch;
|
int tarindex, state, ch;
|
||||||
u_char nextbyte;
|
unsigned char nextbyte;
|
||||||
char *pos;
|
char *pos;
|
||||||
|
|
||||||
state = 0;
|
state = 0;
|
||||||
@@ -207,7 +201,7 @@ b64_pton(src, target, targsize)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
pos = strchr(Base64, ch);
|
pos = strchr(Base64, ch);
|
||||||
if (pos == 0) /* A non-base64 character. */
|
if (pos == 0) /* A non-base64 character. */
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: imsg-buffer.c,v 1.35 2025/06/04 09:06:56 claudio Exp $ */
|
/* $OpenBSD: imsg-buffer.c,v 1.36 2025/08/25 08:29:49 claudio Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
|
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
|
||||||
@@ -699,8 +699,6 @@ msgbuf_queuelen(struct msgbuf *msgbuf)
|
|||||||
void
|
void
|
||||||
msgbuf_clear(struct msgbuf *msgbuf)
|
msgbuf_clear(struct msgbuf *msgbuf)
|
||||||
{
|
{
|
||||||
struct ibuf *buf;
|
|
||||||
|
|
||||||
/* write side */
|
/* write side */
|
||||||
ibufq_flush(&msgbuf->bufs);
|
ibufq_flush(&msgbuf->bufs);
|
||||||
|
|
||||||
|
|||||||
11
configure.ac
11
configure.ac
@@ -1,6 +1,6 @@
|
|||||||
# configure.ac
|
# configure.ac
|
||||||
|
|
||||||
AC_INIT([tmux], 3.6)
|
AC_INIT([tmux], next-3.7)
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
|
|
||||||
AC_CONFIG_AUX_DIR(etc)
|
AC_CONFIG_AUX_DIR(etc)
|
||||||
@@ -64,6 +64,15 @@ AC_ARG_ENABLE(
|
|||||||
)
|
)
|
||||||
AM_CONDITIONAL(IS_DEBUG, test "x$enable_debug" = xyes)
|
AM_CONDITIONAL(IS_DEBUG, test "x$enable_debug" = xyes)
|
||||||
|
|
||||||
|
# Is this --enable-optimizations?
|
||||||
|
AC_ARG_ENABLE(
|
||||||
|
optimizations,
|
||||||
|
AS_HELP_STRING(--enable-optimizations, enable optimization build flags),
|
||||||
|
,
|
||||||
|
enable_optimizations=yes
|
||||||
|
)
|
||||||
|
AM_CONDITIONAL(IS_OPTIMIZED, test "x$enable_optimizations" = xyes)
|
||||||
|
|
||||||
# Is this a static build?
|
# Is this a static build?
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
static,
|
static,
|
||||||
|
|||||||
@@ -51,29 +51,24 @@ control_notify_window_layout_changed(struct window *w)
|
|||||||
template = "%layout-change #{window_id} #{window_layout} "
|
template = "%layout-change #{window_id} #{window_layout} "
|
||||||
"#{window_visible_layout} #{window_raw_flags}";
|
"#{window_visible_layout} #{window_raw_flags}";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the last pane in a window is closed it won't have a layout root
|
||||||
|
* and we don't need to inform the client about the layout change
|
||||||
|
* because the whole window will go away soon.
|
||||||
|
*/
|
||||||
|
wl = TAILQ_FIRST(&w->winlinks);
|
||||||
|
if (wl == NULL || w->layout_root == NULL)
|
||||||
|
return;
|
||||||
|
cp = format_single(NULL, template, NULL, NULL, wl, NULL);
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||||
continue;
|
continue;
|
||||||
s = c->session;
|
s = c->session;
|
||||||
|
if (winlink_find_by_window_id(&s->windows, w->id) != NULL)
|
||||||
if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When the last pane in a window is closed it won't have a
|
|
||||||
* layout root and we don't need to inform the client about the
|
|
||||||
* layout change because the whole window will go away soon.
|
|
||||||
*/
|
|
||||||
if (w->layout_root == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
wl = winlink_find_by_window(&s->windows, w);
|
|
||||||
if (wl != NULL) {
|
|
||||||
cp = format_single(NULL, template, c, NULL, wl, NULL);
|
|
||||||
control_write(c, "%s", cp);
|
control_write(c, "%s", cp);
|
||||||
free(cp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
free(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
204
control.c
204
control.c
@@ -610,7 +610,7 @@ control_append_data(struct client *c, struct control_pane *cp, uint64_t age,
|
|||||||
struct evbuffer *message, struct window_pane *wp, size_t size)
|
struct evbuffer *message, struct window_pane *wp, size_t size)
|
||||||
{
|
{
|
||||||
u_char *new_data;
|
u_char *new_data;
|
||||||
size_t new_size;
|
size_t new_size, start;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (message == NULL) {
|
if (message == NULL) {
|
||||||
@@ -629,10 +629,16 @@ control_append_data(struct client *c, struct control_pane *cp, uint64_t age,
|
|||||||
if (new_size < size)
|
if (new_size < size)
|
||||||
fatalx("not enough data: %zu < %zu", new_size, size);
|
fatalx("not enough data: %zu < %zu", new_size, size);
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
if (new_data[i] < ' ' || new_data[i] == '\\')
|
if (new_data[i] < ' ' || new_data[i] == '\\') {
|
||||||
evbuffer_add_printf(message, "\\%03o", new_data[i]);
|
evbuffer_add_printf(message, "\\%03o", new_data[i]);
|
||||||
else
|
} else {
|
||||||
evbuffer_add_printf(message, "%c", new_data[i]);
|
start = i;
|
||||||
|
while (i + 1 < size &&
|
||||||
|
new_data[i + 1] >= ' ' &&
|
||||||
|
new_data[i + 1] != '\\')
|
||||||
|
i++;
|
||||||
|
evbuffer_add(message, new_data + start, i - start + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
window_pane_update_used_data(wp, &cp->offset, size);
|
window_pane_update_used_data(wp, &cp->offset, size);
|
||||||
return (message);
|
return (message);
|
||||||
@@ -840,15 +846,13 @@ control_stop(struct client *c)
|
|||||||
|
|
||||||
/* Check session subscription. */
|
/* Check session subscription. */
|
||||||
static void
|
static void
|
||||||
control_check_subs_session(struct client *c, struct control_sub *csub)
|
control_check_subs_session(struct client *c, struct control_sub *csub,
|
||||||
|
struct format_tree *ft)
|
||||||
{
|
{
|
||||||
struct session *s = c->session;
|
struct session *s = c->session;
|
||||||
struct format_tree *ft;
|
|
||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
ft = format_create_defaults(NULL, c, s, NULL, NULL);
|
|
||||||
value = format_expand(ft, csub->format);
|
value = format_expand(ft, csub->format);
|
||||||
format_free(ft);
|
|
||||||
|
|
||||||
if (csub->last != NULL && strcmp(value, csub->last) == 0) {
|
if (csub->last != NULL && strcmp(value, csub->last) == 0) {
|
||||||
free(value);
|
free(value);
|
||||||
@@ -909,48 +913,38 @@ control_check_subs_pane(struct client *c, struct control_sub *csub)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check all panes subscription. */
|
/* Check all-panes subscription for a pane. */
|
||||||
static void
|
static void
|
||||||
control_check_subs_all_panes(struct client *c, struct control_sub *csub)
|
control_check_subs_all_panes_one(struct client *c, struct control_sub *csub,
|
||||||
|
struct format_tree *ft, struct winlink *wl, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct session *s = c->session;
|
struct session *s = c->session;
|
||||||
struct window_pane *wp;
|
struct window *w = wl->window;
|
||||||
struct window *w;
|
|
||||||
struct winlink *wl;
|
|
||||||
struct format_tree *ft;
|
|
||||||
char *value;
|
char *value;
|
||||||
struct control_sub_pane *csp, find;
|
struct control_sub_pane *csp, find;
|
||||||
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
value = format_expand(ft, csub->format);
|
||||||
w = wl->window;
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
|
||||||
ft = format_create_defaults(NULL, c, s, wl, wp);
|
|
||||||
value = format_expand(ft, csub->format);
|
|
||||||
format_free(ft);
|
|
||||||
|
|
||||||
find.pane = wp->id;
|
find.pane = wp->id;
|
||||||
find.idx = wl->idx;
|
find.idx = wl->idx;
|
||||||
|
|
||||||
csp = RB_FIND(control_sub_panes, &csub->panes, &find);
|
csp = RB_FIND(control_sub_panes, &csub->panes, &find);
|
||||||
if (csp == NULL) {
|
if (csp == NULL) {
|
||||||
csp = xcalloc(1, sizeof *csp);
|
csp = xcalloc(1, sizeof *csp);
|
||||||
csp->pane = wp->id;
|
csp->pane = wp->id;
|
||||||
csp->idx = wl->idx;
|
csp->idx = wl->idx;
|
||||||
RB_INSERT(control_sub_panes, &csub->panes, csp);
|
RB_INSERT(control_sub_panes, &csub->panes, csp);
|
||||||
}
|
|
||||||
|
|
||||||
if (csp->last != NULL &&
|
|
||||||
strcmp(value, csp->last) == 0) {
|
|
||||||
free(value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
control_write(c,
|
|
||||||
"%%subscription-changed %s $%u @%u %u %%%u : %s",
|
|
||||||
csub->name, s->id, w->id, wl->idx, wp->id, value);
|
|
||||||
free(csp->last);
|
|
||||||
csp->last = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (csp->last != NULL && strcmp(value, csp->last) == 0) {
|
||||||
|
free(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
control_write(c,
|
||||||
|
"%%subscription-changed %s $%u @%u %u %%%u : %s",
|
||||||
|
csub->name, s->id, w->id, wl->idx, wp->id, value);
|
||||||
|
free(csp->last);
|
||||||
|
csp->last = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check window subscription. */
|
/* Check window subscription. */
|
||||||
@@ -999,45 +993,38 @@ control_check_subs_window(struct client *c, struct control_sub *csub)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check all windows subscription. */
|
/* Check all-windows subscription for a window. */
|
||||||
static void
|
static void
|
||||||
control_check_subs_all_windows(struct client *c, struct control_sub *csub)
|
control_check_subs_all_windows_one(struct client *c, struct control_sub *csub,
|
||||||
|
struct format_tree *ft, struct winlink *wl)
|
||||||
{
|
{
|
||||||
struct session *s = c->session;
|
struct session *s = c->session;
|
||||||
struct window *w;
|
struct window *w = wl->window;
|
||||||
struct winlink *wl;
|
|
||||||
struct format_tree *ft;
|
|
||||||
char *value;
|
char *value;
|
||||||
struct control_sub_window *csw, find;
|
struct control_sub_window *csw, find;
|
||||||
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
value = format_expand(ft, csub->format);
|
||||||
w = wl->window;
|
|
||||||
|
|
||||||
ft = format_create_defaults(NULL, c, s, wl, NULL);
|
find.window = w->id;
|
||||||
value = format_expand(ft, csub->format);
|
find.idx = wl->idx;
|
||||||
format_free(ft);
|
|
||||||
|
|
||||||
find.window = w->id;
|
csw = RB_FIND(control_sub_windows, &csub->windows, &find);
|
||||||
find.idx = wl->idx;
|
if (csw == NULL) {
|
||||||
|
csw = xcalloc(1, sizeof *csw);
|
||||||
csw = RB_FIND(control_sub_windows, &csub->windows, &find);
|
csw->window = w->id;
|
||||||
if (csw == NULL) {
|
csw->idx = wl->idx;
|
||||||
csw = xcalloc(1, sizeof *csw);
|
RB_INSERT(control_sub_windows, &csub->windows, csw);
|
||||||
csw->window = w->id;
|
|
||||||
csw->idx = wl->idx;
|
|
||||||
RB_INSERT(control_sub_windows, &csub->windows, csw);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (csw->last != NULL && strcmp(value, csw->last) == 0) {
|
|
||||||
free(value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
control_write(c,
|
|
||||||
"%%subscription-changed %s $%u @%u %u - : %s",
|
|
||||||
csub->name, s->id, w->id, wl->idx, value);
|
|
||||||
free(csw->last);
|
|
||||||
csw->last = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (csw->last != NULL && strcmp(value, csw->last) == 0) {
|
||||||
|
free(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
control_write(c,
|
||||||
|
"%%subscription-changed %s $%u @%u %u - : %s",
|
||||||
|
csub->name, s->id, w->id, wl->idx, value);
|
||||||
|
free(csw->last);
|
||||||
|
csw->last = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check subscriptions timer. */
|
/* Check subscriptions timer. */
|
||||||
@@ -1047,30 +1034,91 @@ control_check_subs_timer(__unused int fd, __unused short events, void *data)
|
|||||||
struct client *c = data;
|
struct client *c = data;
|
||||||
struct control_state *cs = c->control_state;
|
struct control_state *cs = c->control_state;
|
||||||
struct control_sub *csub, *csub1;
|
struct control_sub *csub, *csub1;
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct format_tree *ft;
|
||||||
|
struct winlink *wl;
|
||||||
|
struct window_pane *wp;
|
||||||
struct timeval tv = { .tv_sec = 1 };
|
struct timeval tv = { .tv_sec = 1 };
|
||||||
|
int have_session = 0, have_all_panes = 0;
|
||||||
|
int have_all_windows = 0;
|
||||||
|
|
||||||
log_debug("%s: timer fired", __func__);
|
log_debug("%s: timer fired", __func__);
|
||||||
evtimer_add(&cs->subs_timer, &tv);
|
evtimer_add(&cs->subs_timer, &tv);
|
||||||
|
|
||||||
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
|
/* Find which subscription types are present. */
|
||||||
|
RB_FOREACH(csub, control_subs, &cs->subs) {
|
||||||
switch (csub->type) {
|
switch (csub->type) {
|
||||||
case CONTROL_SUB_SESSION:
|
case CONTROL_SUB_SESSION:
|
||||||
control_check_subs_session(c, csub);
|
have_session = 1;
|
||||||
break;
|
|
||||||
case CONTROL_SUB_PANE:
|
|
||||||
control_check_subs_pane(c, csub);
|
|
||||||
break;
|
break;
|
||||||
case CONTROL_SUB_ALL_PANES:
|
case CONTROL_SUB_ALL_PANES:
|
||||||
control_check_subs_all_panes(c, csub);
|
have_all_panes = 1;
|
||||||
|
break;
|
||||||
|
case CONTROL_SUB_ALL_WINDOWS:
|
||||||
|
have_all_windows = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check session subscriptions. */
|
||||||
|
if (have_session) {
|
||||||
|
ft = format_create_defaults(NULL, c, s, NULL, NULL);
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
|
||||||
|
if (csub->type == CONTROL_SUB_SESSION)
|
||||||
|
control_check_subs_session(c, csub, ft);
|
||||||
|
}
|
||||||
|
format_free(ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check pane and window subscriptions. */
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
|
||||||
|
switch (csub->type) {
|
||||||
|
case CONTROL_SUB_PANE:
|
||||||
|
control_check_subs_pane(c, csub);
|
||||||
break;
|
break;
|
||||||
case CONTROL_SUB_WINDOW:
|
case CONTROL_SUB_WINDOW:
|
||||||
control_check_subs_window(c, csub);
|
control_check_subs_window(c, csub);
|
||||||
break;
|
break;
|
||||||
|
case CONTROL_SUB_SESSION:
|
||||||
|
case CONTROL_SUB_ALL_PANES:
|
||||||
case CONTROL_SUB_ALL_WINDOWS:
|
case CONTROL_SUB_ALL_WINDOWS:
|
||||||
control_check_subs_all_windows(c, csub);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check all-panes subscriptions. */
|
||||||
|
if (have_all_panes) {
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||||
|
ft = format_create_defaults(NULL, c, s, wl, wp);
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs,
|
||||||
|
csub1) {
|
||||||
|
if (csub->type != CONTROL_SUB_ALL_PANES)
|
||||||
|
continue;
|
||||||
|
control_check_subs_all_panes_one(c,
|
||||||
|
csub, ft, wl, wp);
|
||||||
|
}
|
||||||
|
format_free(ft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check all-windows subscriptions. */
|
||||||
|
if (have_all_windows) {
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
ft = format_create_defaults(NULL, c, s, wl, NULL);
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs,
|
||||||
|
csub1) {
|
||||||
|
if (csub->type != CONTROL_SUB_ALL_WINDOWS)
|
||||||
|
continue;
|
||||||
|
control_check_subs_all_windows_one(c, csub, ft,
|
||||||
|
wl);
|
||||||
|
}
|
||||||
|
format_free(ft);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a subscription. */
|
/* Add a subscription. */
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ environ_free(struct environ *env)
|
|||||||
{
|
{
|
||||||
struct environ_entry *envent, *envent1;
|
struct environ_entry *envent, *envent1;
|
||||||
|
|
||||||
|
if (env == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
RB_FOREACH_SAFE(envent, environ, env, envent1) {
|
RB_FOREACH_SAFE(envent, environ, env, envent1) {
|
||||||
RB_REMOVE(environ, env, envent);
|
RB_REMOVE(environ, env, envent);
|
||||||
free(envent->name);
|
free(envent->name);
|
||||||
@@ -263,11 +266,6 @@ environ_for_session(struct session *s, int no_TERM)
|
|||||||
environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux");
|
environ_set(env, "TERM_PROGRAM", 0, "%s", "tmux");
|
||||||
environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
|
environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
|
||||||
environ_set(env, "COLORTERM", 0, "truecolor");
|
environ_set(env, "COLORTERM", 0, "truecolor");
|
||||||
} else {
|
|
||||||
environ_unset(env, "TERM");
|
|
||||||
environ_unset(env, "TERM_PROGRAM");
|
|
||||||
environ_unset(env, "TERM_PROGRAM_VERSION");
|
|
||||||
environ_unset(env, "COLORTERM");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
#ifdef HAVE_SYSTEMD
|
||||||
|
|||||||
1
file.c
1
file.c
@@ -55,6 +55,7 @@ file_get_path(struct client *c, const char *file)
|
|||||||
if (*path == '/')
|
if (*path == '/')
|
||||||
return (path);
|
return (path);
|
||||||
xasprintf(&full_path, "%s/%s", server_client_get_cwd(c, NULL), path);
|
xasprintf(&full_path, "%s/%s", server_client_get_cwd(c, NULL), path);
|
||||||
|
free(path);
|
||||||
return (full_path);
|
return (full_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1104,8 +1104,6 @@ format_width(const char *expanded)
|
|||||||
more = utf8_append(&ud, *cp);
|
more = utf8_append(&ud, *cp);
|
||||||
if (more == UTF8_DONE)
|
if (more == UTF8_DONE)
|
||||||
width += ud.width;
|
width += ud.width;
|
||||||
else
|
|
||||||
cp -= ud.have;
|
|
||||||
} else if (*cp > 0x1f && *cp < 0x7f) {
|
} else if (*cp > 0x1f && *cp < 0x7f) {
|
||||||
width++;
|
width++;
|
||||||
cp++;
|
cp++;
|
||||||
|
|||||||
345
format.c
345
format.c
@@ -132,17 +132,7 @@ enum format_type {
|
|||||||
FORMAT_TYPE_PANE
|
FORMAT_TYPE_PANE
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Format loop sort type. */
|
static struct sort_criteria sort_crit;
|
||||||
enum format_loop_sort_type {
|
|
||||||
FORMAT_LOOP_BY_INDEX,
|
|
||||||
FORMAT_LOOP_BY_NAME,
|
|
||||||
FORMAT_LOOP_BY_TIME,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct format_loop_sort_criteria {
|
|
||||||
enum format_loop_sort_type field;
|
|
||||||
int reversed;
|
|
||||||
} format_loop_sort_criteria;
|
|
||||||
|
|
||||||
struct format_tree {
|
struct format_tree {
|
||||||
enum format_type type;
|
enum format_type type;
|
||||||
@@ -454,6 +444,20 @@ format_job_tidy(struct format_job_tree *jobs, int force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Work around needless -Wformat-nonliteral gcc warning. */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||||
|
#endif
|
||||||
|
static size_t
|
||||||
|
format_strftime(char *s, size_t max, const char *fmt, const struct tm *tm)
|
||||||
|
{
|
||||||
|
return (strftime(s, max, fmt, tm));
|
||||||
|
}
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Tidy old jobs for all clients. */
|
/* Tidy old jobs for all clients. */
|
||||||
void
|
void
|
||||||
format_tidy_jobs(void)
|
format_tidy_jobs(void)
|
||||||
@@ -821,8 +825,8 @@ format_cb_window_layout(struct format_tree *ft)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
if (w->saved_layout_root != NULL)
|
if (w->saved_layout_root != NULL)
|
||||||
return (layout_dump(w->saved_layout_root));
|
return (layout_dump(w, w->saved_layout_root));
|
||||||
return (layout_dump(w->layout_root));
|
return (layout_dump(w, w->layout_root));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for window_visible_layout. */
|
/* Callback for window_visible_layout. */
|
||||||
@@ -834,7 +838,7 @@ format_cb_window_visible_layout(struct format_tree *ft)
|
|||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
return (layout_dump(w->layout_root));
|
return (layout_dump(w, w->layout_root));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for pane_start_command. */
|
/* Callback for pane_start_command. */
|
||||||
@@ -1000,6 +1004,20 @@ format_cb_pane_fg(struct format_tree *ft)
|
|||||||
return (xstrdup(colour_tostring(gc.fg)));
|
return (xstrdup(colour_tostring(gc.fg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for pane_floating_flag. */
|
||||||
|
static void *
|
||||||
|
format_cb_pane_floating_flag(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
struct window_pane *wp = ft->wp;
|
||||||
|
|
||||||
|
if (wp != NULL) {
|
||||||
|
if (wp->flags & PANE_FLOATING)
|
||||||
|
return (xstrdup("1"));
|
||||||
|
return (xstrdup("0"));
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for pane_bg. */
|
/* Callback for pane_bg. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_pane_bg(struct format_tree *ft)
|
format_cb_pane_bg(struct format_tree *ft)
|
||||||
@@ -1947,6 +1965,18 @@ format_cb_origin_flag(struct format_tree *ft)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for synchronized_output_flag. */
|
||||||
|
static void *
|
||||||
|
format_cb_synchronized_output_flag(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
if (ft->wp != NULL) {
|
||||||
|
if (ft->wp->base.mode & MODE_SYNC)
|
||||||
|
return (xstrdup("1"));
|
||||||
|
return (xstrdup("0"));
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for pane_active. */
|
/* Callback for pane_active. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_pane_active(struct format_tree *ft)
|
format_cb_pane_active(struct format_tree *ft)
|
||||||
@@ -1996,8 +2026,10 @@ format_cb_pane_bottom(struct format_tree *ft)
|
|||||||
static void *
|
static void *
|
||||||
format_cb_pane_dead(struct format_tree *ft)
|
format_cb_pane_dead(struct format_tree *ft)
|
||||||
{
|
{
|
||||||
if (ft->wp != NULL) {
|
struct window_pane *wp = ft->wp;
|
||||||
if (ft->wp->fd == -1)
|
|
||||||
|
if (wp != NULL) {
|
||||||
|
if (wp->fd == -1 && (wp->flags & PANE_STATUSREADY))
|
||||||
return (xstrdup("1"));
|
return (xstrdup("1"));
|
||||||
return (xstrdup("0"));
|
return (xstrdup("0"));
|
||||||
}
|
}
|
||||||
@@ -2221,6 +2253,17 @@ format_cb_pane_pipe(struct format_tree *ft)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for pane_pipe_pid. */
|
||||||
|
static void *
|
||||||
|
format_cb_pane_pipe_pid(struct format_tree *ft)
|
||||||
|
{
|
||||||
|
char *value = NULL;
|
||||||
|
|
||||||
|
if (ft->wp != NULL && ft->wp->pipe_fd != -1)
|
||||||
|
xasprintf(&value, "%ld", (long)ft->wp->pipe_pid);
|
||||||
|
return (value);
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for pane_right. */
|
/* Callback for pane_right. */
|
||||||
static void *
|
static void *
|
||||||
format_cb_pane_right(struct format_tree *ft)
|
format_cb_pane_right(struct format_tree *ft)
|
||||||
@@ -3266,6 +3309,9 @@ static const struct format_table_entry format_table[] = {
|
|||||||
{ "pane_fg", FORMAT_TABLE_STRING,
|
{ "pane_fg", FORMAT_TABLE_STRING,
|
||||||
format_cb_pane_fg
|
format_cb_pane_fg
|
||||||
},
|
},
|
||||||
|
{ "pane_floating_flag", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_pane_floating_flag
|
||||||
|
},
|
||||||
{ "pane_format", FORMAT_TABLE_STRING,
|
{ "pane_format", FORMAT_TABLE_STRING,
|
||||||
format_cb_pane_format
|
format_cb_pane_format
|
||||||
},
|
},
|
||||||
@@ -3311,6 +3357,9 @@ static const struct format_table_entry format_table[] = {
|
|||||||
{ "pane_pipe", FORMAT_TABLE_STRING,
|
{ "pane_pipe", FORMAT_TABLE_STRING,
|
||||||
format_cb_pane_pipe
|
format_cb_pane_pipe
|
||||||
},
|
},
|
||||||
|
{ "pane_pipe_pid", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_pane_pipe_pid
|
||||||
|
},
|
||||||
{ "pane_right", FORMAT_TABLE_STRING,
|
{ "pane_right", FORMAT_TABLE_STRING,
|
||||||
format_cb_pane_right
|
format_cb_pane_right
|
||||||
},
|
},
|
||||||
@@ -3443,6 +3492,9 @@ static const struct format_table_entry format_table[] = {
|
|||||||
{ "start_time", FORMAT_TABLE_TIME,
|
{ "start_time", FORMAT_TABLE_TIME,
|
||||||
format_cb_start_time
|
format_cb_start_time
|
||||||
},
|
},
|
||||||
|
{ "synchronized_output_flag", FORMAT_TABLE_STRING,
|
||||||
|
format_cb_synchronized_output_flag
|
||||||
|
},
|
||||||
{ "tree_mode_format", FORMAT_TABLE_STRING,
|
{ "tree_mode_format", FORMAT_TABLE_STRING,
|
||||||
format_cb_tree_mode_format
|
format_cb_tree_mode_format
|
||||||
},
|
},
|
||||||
@@ -3948,7 +4000,7 @@ found:
|
|||||||
else {
|
else {
|
||||||
if (time_format != NULL) {
|
if (time_format != NULL) {
|
||||||
localtime_r(&t, &tm);
|
localtime_r(&t, &tm);
|
||||||
strftime(s, sizeof s, time_format, &tm);
|
format_strftime(s, sizeof s, time_format, &tm);
|
||||||
} else {
|
} else {
|
||||||
ctime_r(&t, s);
|
ctime_r(&t, s);
|
||||||
s[strcspn(s, "\n")] = '\0';
|
s[strcspn(s, "\n")] = '\0';
|
||||||
@@ -4377,44 +4429,11 @@ format_session_name(struct format_expand_state *es, const char *fmt)
|
|||||||
return (xstrdup("0"));
|
return (xstrdup("0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
format_cmp_session(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
|
||||||
const struct session *const *a = a0;
|
|
||||||
const struct session *const *b = b0;
|
|
||||||
const struct session *sa = *a;
|
|
||||||
const struct session *sb = *b;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
switch (sc->field) {
|
|
||||||
case FORMAT_LOOP_BY_INDEX:
|
|
||||||
result = sa->id - sb->id;
|
|
||||||
break;
|
|
||||||
case FORMAT_LOOP_BY_TIME:
|
|
||||||
if (timercmp(&sa->activity_time, &sb->activity_time, >)) {
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (timercmp(&sa->activity_time, &sb->activity_time, <)) {
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case FORMAT_LOOP_BY_NAME:
|
|
||||||
result = strcmp(sa->name, sb->name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sc->reversed)
|
|
||||||
result = -result;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop over sessions. */
|
/* Loop over sessions. */
|
||||||
static char *
|
static char *
|
||||||
format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
||||||
{
|
{
|
||||||
|
struct sort_criteria *sc = &sort_crit;
|
||||||
struct format_tree *ft = es->ft;
|
struct format_tree *ft = es->ft;
|
||||||
struct client *c = ft->client;
|
struct client *c = ft->client;
|
||||||
struct cmdq_item *item = ft->item;
|
struct cmdq_item *item = ft->item;
|
||||||
@@ -4422,34 +4441,24 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
|||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
struct session *s;
|
struct session *s, **l;
|
||||||
int i, n, last = 0;
|
int i, n, last = 0;
|
||||||
static struct session **l = NULL;
|
|
||||||
static int lsz = 0;
|
|
||||||
|
|
||||||
if (format_choose(es, fmt, &all, &active, 0) != 0) {
|
if (format_choose(es, fmt, &all, &active, 0) != 0) {
|
||||||
all = xstrdup(fmt);
|
all = xstrdup(fmt);
|
||||||
active = NULL;
|
active = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = 0;
|
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
|
||||||
if (lsz <= n) {
|
|
||||||
lsz += 100;
|
|
||||||
l = xreallocarray(l, lsz, sizeof *l);
|
|
||||||
}
|
|
||||||
l[n++] = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(l, n, sizeof *l, format_cmp_session);
|
|
||||||
|
|
||||||
value = xcalloc(1, 1);
|
value = xcalloc(1, 1);
|
||||||
valuelen = 1;
|
valuelen = 1;
|
||||||
|
|
||||||
|
l = sort_get_sessions(&n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
s = l[i];
|
s = l[i];
|
||||||
format_log(es, "session loop: $%u", s->id);
|
format_log(es, "session loop: $%u", s->id);
|
||||||
if (active != NULL && s->id == ft->c->session->id)
|
if (active != NULL &&
|
||||||
|
ft->c != NULL &&
|
||||||
|
s->id == ft->c->session->id)
|
||||||
use = active;
|
use = active;
|
||||||
else
|
else
|
||||||
use = all;
|
use = all;
|
||||||
@@ -4469,6 +4478,9 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
|
|||||||
free(expanded);
|
free(expanded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(active);
|
||||||
|
free(all);
|
||||||
|
|
||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4496,44 +4508,11 @@ format_window_name(struct format_expand_state *es, const char *fmt)
|
|||||||
return (xstrdup("0"));
|
return (xstrdup("0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
format_cmp_window(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
|
||||||
const struct winlink *const *a = a0;
|
|
||||||
const struct winlink *const *b = b0;
|
|
||||||
const struct window *wa = (*a)->window;
|
|
||||||
const struct window *wb = (*b)->window;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
switch (sc->field) {
|
|
||||||
case FORMAT_LOOP_BY_INDEX:
|
|
||||||
break;
|
|
||||||
case FORMAT_LOOP_BY_TIME:
|
|
||||||
if (timercmp(&wa->activity_time, &wb->activity_time, >)) {
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (timercmp(&wa->activity_time, &wb->activity_time, <)) {
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case FORMAT_LOOP_BY_NAME:
|
|
||||||
result = strcmp(wa->name, wb->name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sc->reversed)
|
|
||||||
result = -result;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop over windows. */
|
/* Loop over windows. */
|
||||||
static char *
|
static char *
|
||||||
format_loop_windows(struct format_expand_state *es, const char *fmt)
|
format_loop_windows(struct format_expand_state *es, const char *fmt)
|
||||||
{
|
{
|
||||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
struct sort_criteria *sc = &sort_crit;
|
||||||
struct format_tree *ft = es->ft;
|
struct format_tree *ft = es->ft;
|
||||||
struct client *c = ft->client;
|
struct client *c = ft->client;
|
||||||
struct cmdq_item *item = ft->item;
|
struct cmdq_item *item = ft->item;
|
||||||
@@ -4541,11 +4520,9 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
|||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
struct winlink *wl;
|
struct winlink *wl, **l;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
int i, n, last = 0;
|
int i, n, last = 0;
|
||||||
static struct winlink **l = NULL;
|
|
||||||
static int lsz = 0;
|
|
||||||
|
|
||||||
if (ft->s == NULL) {
|
if (ft->s == NULL) {
|
||||||
format_log(es, "window loop but no session");
|
format_log(es, "window loop but no session");
|
||||||
@@ -4557,31 +4534,10 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
|||||||
active = NULL;
|
active = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = 0;
|
|
||||||
RB_FOREACH(wl, winlinks, &ft->s->windows) {
|
|
||||||
if (lsz <= n) {
|
|
||||||
lsz += 100;
|
|
||||||
l = xreallocarray(l, lsz, sizeof *l);
|
|
||||||
}
|
|
||||||
l[n++] = wl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sc->field != FORMAT_LOOP_BY_INDEX)
|
|
||||||
qsort(l, n, sizeof *l, format_cmp_window);
|
|
||||||
else {
|
|
||||||
/* Use order in the tree as index order. */
|
|
||||||
if (sc->reversed) {
|
|
||||||
for (i = 0; i < n / 2; i++) {
|
|
||||||
wl = l[i];
|
|
||||||
l[i] = l[n - 1 - i];
|
|
||||||
l[n - 1 - i] = wl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = xcalloc(1, 1);
|
value = xcalloc(1, 1);
|
||||||
valuelen = 1;
|
valuelen = 1;
|
||||||
|
|
||||||
|
l = sort_get_winlinks_session(ft->s, &n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
wl = l[i];
|
wl = l[i];
|
||||||
w = wl->window;
|
w = wl->window;
|
||||||
@@ -4613,27 +4569,11 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
|
|||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
format_cmp_pane(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
|
||||||
const struct window_pane *const *a = a0;
|
|
||||||
const struct window_pane *const *b = b0;
|
|
||||||
const struct window_pane *wpa = *a;
|
|
||||||
const struct window_pane *wpb = *b;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
if (sc->reversed)
|
|
||||||
result = wpb->id - wpa->id;
|
|
||||||
else
|
|
||||||
result = wpa->id - wpb->id;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop over panes. */
|
/* Loop over panes. */
|
||||||
static char *
|
static char *
|
||||||
format_loop_panes(struct format_expand_state *es, const char *fmt)
|
format_loop_panes(struct format_expand_state *es, const char *fmt)
|
||||||
{
|
{
|
||||||
|
struct sort_criteria *sc = &sort_crit;
|
||||||
struct format_tree *ft = es->ft;
|
struct format_tree *ft = es->ft;
|
||||||
struct client *c = ft->client;
|
struct client *c = ft->client;
|
||||||
struct cmdq_item *item = ft->item;
|
struct cmdq_item *item = ft->item;
|
||||||
@@ -4641,10 +4581,8 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
|||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *all, *active, *use, *expanded, *value;
|
char *all, *active, *use, *expanded, *value;
|
||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp, **l;
|
||||||
int i, n, last = 0;
|
int i, n, last = 0;
|
||||||
static struct window_pane **l = NULL;
|
|
||||||
static int lsz = 0;
|
|
||||||
|
|
||||||
if (ft->w == NULL) {
|
if (ft->w == NULL) {
|
||||||
format_log(es, "pane loop but no window");
|
format_log(es, "pane loop but no window");
|
||||||
@@ -4656,20 +4594,10 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
|||||||
active = NULL;
|
active = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = 0;
|
|
||||||
TAILQ_FOREACH(wp, &ft->w->panes, entry) {
|
|
||||||
if (lsz <= n) {
|
|
||||||
lsz += 100;
|
|
||||||
l = xreallocarray(l, lsz, sizeof *l);
|
|
||||||
}
|
|
||||||
l[n++] = wp;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(l, n, sizeof *l, format_cmp_pane);
|
|
||||||
|
|
||||||
value = xcalloc(1, 1);
|
value = xcalloc(1, 1);
|
||||||
valuelen = 1;
|
valuelen = 1;
|
||||||
|
|
||||||
|
l = sort_get_panes_window(ft->w, &n, sc);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
wp = l[i];
|
wp = l[i];
|
||||||
format_log(es, "pane loop: %%%u", wp->id);
|
format_log(es, "pane loop: %%%u", wp->id);
|
||||||
@@ -4700,80 +4628,24 @@ format_loop_panes(struct format_expand_state *es, const char *fmt)
|
|||||||
return (value);
|
return (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
format_cmp_client(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
|
||||||
const struct client *const *a = a0;
|
|
||||||
const struct client *const *b = b0;
|
|
||||||
const struct client *ca = *a;
|
|
||||||
const struct client *cb = *b;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
switch (sc->field) {
|
|
||||||
case FORMAT_LOOP_BY_INDEX:
|
|
||||||
break;
|
|
||||||
case FORMAT_LOOP_BY_TIME:
|
|
||||||
if (timercmp(&ca->activity_time, &cb->activity_time, >)) {
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (timercmp(&ca->activity_time, &cb->activity_time, <)) {
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case FORMAT_LOOP_BY_NAME:
|
|
||||||
result = strcmp(ca->name, cb->name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sc->reversed)
|
|
||||||
result = -result;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop over clients. */
|
/* Loop over clients. */
|
||||||
static char *
|
static char *
|
||||||
format_loop_clients(struct format_expand_state *es, const char *fmt)
|
format_loop_clients(struct format_expand_state *es, const char *fmt)
|
||||||
{
|
{
|
||||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
struct sort_criteria *sc = &sort_crit;
|
||||||
struct format_tree *ft = es->ft;
|
struct format_tree *ft = es->ft;
|
||||||
struct client *c;
|
struct client *c, **l;
|
||||||
struct cmdq_item *item = ft->item;
|
struct cmdq_item *item = ft->item;
|
||||||
struct format_tree *nft;
|
struct format_tree *nft;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
char *expanded, *value;
|
char *expanded, *value;
|
||||||
size_t valuelen;
|
size_t valuelen;
|
||||||
int i, n, last = 0;
|
int i, n, last = 0;
|
||||||
static struct client **l = NULL;
|
|
||||||
static int lsz = 0;
|
|
||||||
|
|
||||||
value = xcalloc(1, 1);
|
value = xcalloc(1, 1);
|
||||||
valuelen = 1;
|
valuelen = 1;
|
||||||
|
|
||||||
n = 0;
|
l = sort_get_clients(&n, sc);
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (lsz <= n) {
|
|
||||||
lsz += 100;
|
|
||||||
l = xreallocarray(l, lsz, sizeof *l);
|
|
||||||
}
|
|
||||||
l[n++] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sc->field != FORMAT_LOOP_BY_INDEX)
|
|
||||||
qsort(l, n, sizeof *l, format_cmp_client);
|
|
||||||
else {
|
|
||||||
/* Use order in the list as index order. */
|
|
||||||
if (sc->reversed) {
|
|
||||||
for (i = 0; i < n / 2; i++) {
|
|
||||||
c = l[i];
|
|
||||||
l[i] = l[n - 1 - i];
|
|
||||||
l[n - 1 - i] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
c = l[i];
|
c = l[i];
|
||||||
format_log(es, "client loop: %s", c->name);
|
format_log(es, "client loop: %s", c->name);
|
||||||
@@ -4943,7 +4815,7 @@ static int
|
|||||||
format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||||
char **buf, size_t *len, size_t *off)
|
char **buf, size_t *len, size_t *off)
|
||||||
{
|
{
|
||||||
struct format_loop_sort_criteria *sc = &format_loop_sort_criteria;
|
struct sort_criteria *sc = &sort_crit;
|
||||||
struct format_tree *ft = es->ft;
|
struct format_tree *ft = es->ft;
|
||||||
struct window_pane *wp = ft->wp;
|
struct window_pane *wp = ft->wp;
|
||||||
const char *errstr, *copy, *cp, *cp2;
|
const char *errstr, *copy, *cp, *cp2;
|
||||||
@@ -4960,6 +4832,10 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
u_int i, count, nsub = 0, nrep;
|
u_int i, count, nsub = 0, nrep;
|
||||||
struct format_expand_state next;
|
struct format_expand_state next;
|
||||||
|
|
||||||
|
/* Set sorting defaults. */
|
||||||
|
sc->order = SORT_ORDER;
|
||||||
|
sc->reversed = 0;
|
||||||
|
|
||||||
/* Make a copy of the key. */
|
/* Make a copy of the key. */
|
||||||
copy = copy0 = xstrndup(key, keylen);
|
copy = copy0 = xstrndup(key, keylen);
|
||||||
|
|
||||||
@@ -5070,18 +4946,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case 'S':
|
case 'S':
|
||||||
modifiers |= FORMAT_SESSIONS;
|
modifiers |= FORMAT_SESSIONS;
|
||||||
if (fm->argc < 1) {
|
if (fm->argc < 1) {
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order= SORT_INDEX;
|
||||||
sc->reversed = 0;
|
sc->reversed = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strchr(fm->argv[0], 'i') != NULL)
|
if (strchr(fm->argv[0], 'i') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_INDEX;
|
||||||
else if (strchr(fm->argv[0], 'n') != NULL)
|
else if (strchr(fm->argv[0], 'n') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_NAME;
|
sc->order = SORT_NAME;
|
||||||
else if (strchr(fm->argv[0], 't') != NULL)
|
else if (strchr(fm->argv[0], 't') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_TIME;
|
sc->order = SORT_ACTIVITY;
|
||||||
else
|
else
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_INDEX;
|
||||||
if (strchr(fm->argv[0], 'r') != NULL)
|
if (strchr(fm->argv[0], 'r') != NULL)
|
||||||
sc->reversed = 1;
|
sc->reversed = 1;
|
||||||
else
|
else
|
||||||
@@ -5090,18 +4966,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case 'W':
|
case 'W':
|
||||||
modifiers |= FORMAT_WINDOWS;
|
modifiers |= FORMAT_WINDOWS;
|
||||||
if (fm->argc < 1) {
|
if (fm->argc < 1) {
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
sc->reversed = 0;
|
sc->reversed = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strchr(fm->argv[0], 'i') != NULL)
|
if (strchr(fm->argv[0], 'i') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
else if (strchr(fm->argv[0], 'n') != NULL)
|
else if (strchr(fm->argv[0], 'n') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_NAME;
|
sc->order = SORT_NAME;
|
||||||
else if (strchr(fm->argv[0], 't') != NULL)
|
else if (strchr(fm->argv[0], 't') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_TIME;
|
sc->order = SORT_ACTIVITY;
|
||||||
else
|
else
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
if (strchr(fm->argv[0], 'r') != NULL)
|
if (strchr(fm->argv[0], 'r') != NULL)
|
||||||
sc->reversed = 1;
|
sc->reversed = 1;
|
||||||
else
|
else
|
||||||
@@ -5109,6 +4985,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
modifiers |= FORMAT_PANES;
|
modifiers |= FORMAT_PANES;
|
||||||
|
sc->order = SORT_CREATION;
|
||||||
if (fm->argc < 1) {
|
if (fm->argc < 1) {
|
||||||
sc->reversed = 0;
|
sc->reversed = 0;
|
||||||
break;
|
break;
|
||||||
@@ -5121,18 +4998,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
case 'L':
|
case 'L':
|
||||||
modifiers |= FORMAT_CLIENTS;
|
modifiers |= FORMAT_CLIENTS;
|
||||||
if (fm->argc < 1) {
|
if (fm->argc < 1) {
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
sc->reversed = 0;
|
sc->reversed = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (strchr(fm->argv[0], 'i') != NULL)
|
if (strchr(fm->argv[0], 'i') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
else if (strchr(fm->argv[0], 'n') != NULL)
|
else if (strchr(fm->argv[0], 'n') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_NAME;
|
sc->order = SORT_NAME;
|
||||||
else if (strchr(fm->argv[0], 't') != NULL)
|
else if (strchr(fm->argv[0], 't') != NULL)
|
||||||
sc->field = FORMAT_LOOP_BY_TIME;
|
sc->order = SORT_ACTIVITY;
|
||||||
else
|
else
|
||||||
sc->field = FORMAT_LOOP_BY_INDEX;
|
sc->order = SORT_ORDER;
|
||||||
if (strchr(fm->argv[0], 'r') != NULL)
|
if (strchr(fm->argv[0], 'r') != NULL)
|
||||||
sc->reversed = 1;
|
sc->reversed = 1;
|
||||||
else
|
else
|
||||||
@@ -5523,7 +5400,8 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
|||||||
es->time = time(NULL);
|
es->time = time(NULL);
|
||||||
localtime_r(&es->time, &es->tm);
|
localtime_r(&es->time, &es->tm);
|
||||||
}
|
}
|
||||||
if (strftime(expanded, sizeof expanded, fmt, &es->tm) == 0) {
|
if (format_strftime(expanded, sizeof expanded, fmt,
|
||||||
|
&es->tm) == 0) {
|
||||||
format_log(es, "format is too long");
|
format_log(es, "format is too long");
|
||||||
return (xstrdup(""));
|
return (xstrdup(""));
|
||||||
}
|
}
|
||||||
@@ -5545,7 +5423,8 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
|||||||
buf[off++] = *fmt++;
|
buf[off++] = *fmt++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fmt++;
|
if (*fmt++ == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
ch = (u_char)*fmt++;
|
ch = (u_char)*fmt++;
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ LLVMFuzzerTestOneInput(const u_char *data, size_t size)
|
|||||||
w = window_create(PANE_WIDTH, PANE_HEIGHT, 0, 0);
|
w = window_create(PANE_WIDTH, PANE_HEIGHT, 0, 0);
|
||||||
wp = window_add_pane(w, NULL, 0, 0);
|
wp = window_add_pane(w, NULL, 0, 0);
|
||||||
bufferevent_pair_new(libevent, BEV_OPT_CLOSE_ON_FREE, vpty);
|
bufferevent_pair_new(libevent, BEV_OPT_CLOSE_ON_FREE, vpty);
|
||||||
wp->ictx = input_init(wp, vpty[0], NULL);
|
wp->ictx = input_init(wp, vpty[0], NULL, NULL);
|
||||||
window_add_ref(w, __func__);
|
window_add_ref(w, __func__);
|
||||||
|
|
||||||
wp->fd = open("/dev/null", O_WRONLY);
|
wp->fd = open("/dev/null", O_WRONLY);
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ grid_view_clear_history(struct grid *gd, u_int bg)
|
|||||||
|
|
||||||
/* Scroll the lines into the history. */
|
/* Scroll the lines into the history. */
|
||||||
for (yy = 0; yy < last; yy++) {
|
for (yy = 0; yy < last; yy++) {
|
||||||
grid_collect_history(gd);
|
grid_collect_history(gd, 0);
|
||||||
grid_scroll_history(gd, bg);
|
grid_scroll_history(gd, bg);
|
||||||
}
|
}
|
||||||
if (last < gd->sy)
|
if (last < gd->sy)
|
||||||
@@ -107,7 +107,7 @@ grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower,
|
|||||||
u_int bg)
|
u_int bg)
|
||||||
{
|
{
|
||||||
if (gd->flags & GRID_HISTORY) {
|
if (gd->flags & GRID_HISTORY) {
|
||||||
grid_collect_history(gd);
|
grid_collect_history(gd, 0);
|
||||||
if (rupper == 0 && rlower == gd->sy - 1)
|
if (rupper == 0 && rlower == gd->sy - 1)
|
||||||
grid_scroll_history(gd, bg);
|
grid_scroll_history(gd, bg);
|
||||||
else {
|
else {
|
||||||
|
|||||||
38
grid.c
38
grid.c
@@ -205,9 +205,17 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg)
|
|||||||
struct grid_line *gl = &gd->linedata[py];
|
struct grid_line *gl = &gd->linedata[py];
|
||||||
struct grid_cell_entry *gce = &gl->celldata[px];
|
struct grid_cell_entry *gce = &gl->celldata[px];
|
||||||
struct grid_extd_entry *gee;
|
struct grid_extd_entry *gee;
|
||||||
|
u_int old_offset = gce->offset;
|
||||||
|
int had_extd = (gce->flags & GRID_FLAG_EXTENDED);
|
||||||
|
|
||||||
memcpy(gce, &grid_cleared_entry, sizeof *gce);
|
memcpy(gce, &grid_cleared_entry, sizeof *gce);
|
||||||
if (bg != 8) {
|
if (had_extd && old_offset < gl->extdsize) {
|
||||||
|
gce->flags |= GRID_FLAG_EXTENDED;
|
||||||
|
gce->offset = old_offset;
|
||||||
|
gee = grid_extended_cell(gl, gce, &grid_cleared_cell);
|
||||||
|
if (bg != 8)
|
||||||
|
gee->bg = bg;
|
||||||
|
} else if (bg != 8) {
|
||||||
if (bg & COLOUR_FLAG_RGB) {
|
if (bg & COLOUR_FLAG_RGB) {
|
||||||
grid_get_extended_cell(gl, gce, gce->flags);
|
grid_get_extended_cell(gl, gce, gce->flags);
|
||||||
gee = grid_extended_cell(gl, gce, &grid_cleared_cell);
|
gee = grid_extended_cell(gl, gce, &grid_cleared_cell);
|
||||||
@@ -235,7 +243,7 @@ grid_check_y(struct grid *gd, const char *from, u_int py)
|
|||||||
int
|
int
|
||||||
grid_cells_look_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
|
grid_cells_look_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
|
||||||
{
|
{
|
||||||
int flags1 = gc1->flags, flags2 = gc2->flags;;
|
int flags1 = gc1->flags, flags2 = gc2->flags;
|
||||||
|
|
||||||
if (gc1->fg != gc2->fg || gc1->bg != gc2->bg)
|
if (gc1->fg != gc2->fg || gc1->bg != gc2->bg)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -361,9 +369,13 @@ grid_compare(struct grid *ga, struct grid *gb)
|
|||||||
static void
|
static void
|
||||||
grid_trim_history(struct grid *gd, u_int ny)
|
grid_trim_history(struct grid *gd, u_int ny)
|
||||||
{
|
{
|
||||||
|
u_int remaining;
|
||||||
|
|
||||||
grid_free_lines(gd, 0, ny);
|
grid_free_lines(gd, 0, ny);
|
||||||
|
remaining = gd->hsize + gd->sy - ny;
|
||||||
memmove(&gd->linedata[0], &gd->linedata[ny],
|
memmove(&gd->linedata[0], &gd->linedata[ny],
|
||||||
(gd->hsize + gd->sy - ny) * (sizeof *gd->linedata));
|
remaining * (sizeof *gd->linedata));
|
||||||
|
memset(&gd->linedata[remaining], 0, ny * (sizeof *gd->linedata));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -371,14 +383,17 @@ grid_trim_history(struct grid *gd, u_int ny)
|
|||||||
* and shift up.
|
* and shift up.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
grid_collect_history(struct grid *gd)
|
grid_collect_history(struct grid *gd, int all)
|
||||||
{
|
{
|
||||||
u_int ny;
|
u_int ny;
|
||||||
|
|
||||||
if (gd->hsize == 0 || gd->hsize < gd->hlimit)
|
if (gd->hsize == 0 || gd->hsize < gd->hlimit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ny = gd->hlimit / 10;
|
if (all)
|
||||||
|
ny = gd->hsize - gd->hlimit;
|
||||||
|
else
|
||||||
|
ny = gd->hlimit / 10;
|
||||||
if (ny < 1)
|
if (ny < 1)
|
||||||
ny = 1;
|
ny = 1;
|
||||||
if (ny > gd->hsize)
|
if (ny > gd->hsize)
|
||||||
@@ -493,7 +508,12 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg)
|
|||||||
else if (gd->sx > sx)
|
else if (gd->sx > sx)
|
||||||
sx = gd->sx;
|
sx = gd->sx;
|
||||||
|
|
||||||
gl->celldata = xreallocarray(gl->celldata, sx, sizeof *gl->celldata);
|
gl->celldata = xreallocarray(gl->celldata, sx,
|
||||||
|
sizeof *gl->celldata);
|
||||||
|
if (gl->cellsize < sx) {
|
||||||
|
memset(gl->celldata + gl->cellsize, 0,
|
||||||
|
(sx - gl->cellsize) * sizeof *gl->celldata);
|
||||||
|
}
|
||||||
for (xx = gl->cellsize; xx < sx; xx++)
|
for (xx = gl->cellsize; xx < sx; xx++)
|
||||||
grid_clear_cell(gd, xx, py, bg);
|
grid_clear_cell(gd, xx, py, bg);
|
||||||
gl->cellsize = sx;
|
gl->cellsize = sx;
|
||||||
@@ -1082,12 +1102,16 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
|
|||||||
off = 0;
|
off = 0;
|
||||||
|
|
||||||
gl = grid_peek_line(gd, py);
|
gl = grid_peek_line(gd, py);
|
||||||
|
if (gl == NULL) {
|
||||||
|
buf[0] = '\0';
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
if (flags & GRID_STRING_EMPTY_CELLS)
|
if (flags & GRID_STRING_EMPTY_CELLS)
|
||||||
end = gl->cellsize;
|
end = gl->cellsize;
|
||||||
else
|
else
|
||||||
end = gl->cellused;
|
end = gl->cellused;
|
||||||
for (xx = px; xx < px + nx; xx++) {
|
for (xx = px; xx < px + nx; xx++) {
|
||||||
if (gl == NULL || xx >= end)
|
if (xx >= end)
|
||||||
break;
|
break;
|
||||||
grid_get_cell(gd, xx, py, &gc);
|
grid_get_cell(gd, xx, py, &gc);
|
||||||
if (gc.flags & GRID_FLAG_PADDING)
|
if (gc.flags & GRID_FLAG_PADDING)
|
||||||
|
|||||||
@@ -455,12 +455,12 @@ sixel_scale(struct sixel_image *si, u_int xpixel, u_int ypixel, u_int ox,
|
|||||||
new->p2 = si->p2;
|
new->p2 = si->p2;
|
||||||
|
|
||||||
new->set_ra = si->set_ra;
|
new->set_ra = si->set_ra;
|
||||||
/* clamp to slice end */
|
/* subtract offset */
|
||||||
new->ra_x = si->ra_x < psx ? si->ra_x : psx;
|
|
||||||
new->ra_y = si->ra_y < psy ? si->ra_y : psy;
|
|
||||||
/* subtract slice origin */
|
|
||||||
new->ra_x = new->ra_x > pox ? new->ra_x - pox : 0;
|
new->ra_x = new->ra_x > pox ? new->ra_x - pox : 0;
|
||||||
new->ra_y = new->ra_y > poy ? new->ra_y - poy : 0;
|
new->ra_y = new->ra_y > poy ? new->ra_y - poy : 0;
|
||||||
|
/* clamp to size */
|
||||||
|
new->ra_x = si->ra_x < psx ? si->ra_x : psx;
|
||||||
|
new->ra_y = si->ra_y < psy ? si->ra_y : psy;
|
||||||
/* resize */
|
/* resize */
|
||||||
new->ra_x = new->ra_x * xpixel / si->xpixel;
|
new->ra_x = new->ra_x * xpixel / si->xpixel;
|
||||||
new->ra_y = new->ra_y * ypixel / si->ypixel;
|
new->ra_y = new->ra_y * ypixel / si->ypixel;
|
||||||
|
|||||||
57
image.c
57
image.c
@@ -25,12 +25,38 @@
|
|||||||
|
|
||||||
static struct images all_images = TAILQ_HEAD_INITIALIZER(all_images);
|
static struct images all_images = TAILQ_HEAD_INITIALIZER(all_images);
|
||||||
static u_int all_images_count;
|
static u_int all_images_count;
|
||||||
|
#define MAX_IMAGE_COUNT 20
|
||||||
|
|
||||||
|
static void printflike(3, 4)
|
||||||
|
image_log(struct image *im, const char* from, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char s[128];
|
||||||
|
|
||||||
|
if (log_get_level() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fmt == NULL) {
|
||||||
|
log_debug("%s: %p (%ux%u %u,%u)", from, im, im->sx, im->sy,
|
||||||
|
im->px, im->py);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(s, sizeof s, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
log_debug("%s: %p (%ux%u %u,%u): %s", from, im, im->sx, im->sy,
|
||||||
|
im->px, im->py, s);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
image_free(struct image *im)
|
image_free(struct image *im)
|
||||||
{
|
{
|
||||||
struct screen *s = im->s;
|
struct screen *s = im->s;
|
||||||
|
|
||||||
|
image_log(im, __func__, NULL);
|
||||||
|
|
||||||
TAILQ_REMOVE(&all_images, im, all_entry);
|
TAILQ_REMOVE(&all_images, im, all_entry);
|
||||||
all_images_count--;
|
all_images_count--;
|
||||||
|
|
||||||
@@ -46,6 +72,8 @@ image_free_all(struct screen *s)
|
|||||||
struct image *im, *im1;
|
struct image *im, *im1;
|
||||||
int redraw = !TAILQ_EMPTY(&s->images);
|
int redraw = !TAILQ_EMPTY(&s->images);
|
||||||
|
|
||||||
|
if (redraw)
|
||||||
|
log_debug ("%s", __func__);
|
||||||
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1)
|
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1)
|
||||||
image_free(im);
|
image_free(im);
|
||||||
return (redraw);
|
return (redraw);
|
||||||
@@ -108,10 +136,11 @@ image_store(struct screen *s, struct sixel_image *si)
|
|||||||
|
|
||||||
image_fallback(&im->fallback, im->sx, im->sy);
|
image_fallback(&im->fallback, im->sx, im->sy);
|
||||||
|
|
||||||
|
image_log(im, __func__, NULL);
|
||||||
TAILQ_INSERT_TAIL(&s->images, im, entry);
|
TAILQ_INSERT_TAIL(&s->images, im, entry);
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&all_images, im, all_entry);
|
TAILQ_INSERT_TAIL(&all_images, im, all_entry);
|
||||||
if (++all_images_count == 10/*XXX*/)
|
if (++all_images_count == MAX_IMAGE_COUNT)
|
||||||
image_free(TAILQ_FIRST(&all_images));
|
image_free(TAILQ_FIRST(&all_images));
|
||||||
|
|
||||||
return (im);
|
return (im);
|
||||||
@@ -121,10 +150,12 @@ int
|
|||||||
image_check_line(struct screen *s, u_int py, u_int ny)
|
image_check_line(struct screen *s, u_int py, u_int ny)
|
||||||
{
|
{
|
||||||
struct image *im, *im1;
|
struct image *im, *im1;
|
||||||
int redraw = 0;
|
int redraw = 0, in;
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
|
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
|
||||||
if (py + ny > im->py && py < im->py + im->sy) {
|
in = (py + ny > im->py && py < im->py + im->sy);
|
||||||
|
image_log(im, __func__, "py=%u, ny=%u, in=%d", py, ny, in);
|
||||||
|
if (in) {
|
||||||
image_free(im);
|
image_free(im);
|
||||||
redraw = 1;
|
redraw = 1;
|
||||||
}
|
}
|
||||||
@@ -136,15 +167,18 @@ int
|
|||||||
image_check_area(struct screen *s, u_int px, u_int py, u_int nx, u_int ny)
|
image_check_area(struct screen *s, u_int px, u_int py, u_int nx, u_int ny)
|
||||||
{
|
{
|
||||||
struct image *im, *im1;
|
struct image *im, *im1;
|
||||||
int redraw = 0;
|
int redraw = 0, in;
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
|
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
|
||||||
if (py + ny <= im->py || py >= im->py + im->sy)
|
in = (py < im->py + im->sy &&
|
||||||
continue;
|
py + ny > im->py &&
|
||||||
if (px + nx <= im->px || px >= im->px + im->sx)
|
px < im->px + im->sx &&
|
||||||
continue;
|
px + nx > im->px);
|
||||||
image_free(im);
|
image_log(im, __func__, "py=%u, ny=%u, in=%d", py, ny, in);
|
||||||
redraw = 1;
|
if (in) {
|
||||||
|
image_free(im);
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (redraw);
|
return (redraw);
|
||||||
}
|
}
|
||||||
@@ -159,17 +193,20 @@ image_scroll_up(struct screen *s, u_int lines)
|
|||||||
|
|
||||||
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
|
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
|
||||||
if (im->py >= lines) {
|
if (im->py >= lines) {
|
||||||
|
image_log(im, __func__, "1, lines=%u", lines);
|
||||||
im->py -= lines;
|
im->py -= lines;
|
||||||
redraw = 1;
|
redraw = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (im->py + im->sy <= lines) {
|
if (im->py + im->sy <= lines) {
|
||||||
|
image_log(im, __func__, "2, lines=%u", lines);
|
||||||
image_free(im);
|
image_free(im);
|
||||||
redraw = 1;
|
redraw = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sx = im->sx;
|
sx = im->sx;
|
||||||
sy = (im->py + im->sy) - lines;
|
sy = (im->py + im->sy) - lines;
|
||||||
|
image_log(im, __func__, "3, lines=%u, sy=%u", lines, sy);
|
||||||
|
|
||||||
new = sixel_scale(im->data, 0, 0, 0, im->sy - sy, sx, sy, 1);
|
new = sixel_scale(im->data, 0, 0, 0, im->sy - sy, sx, sy, 1);
|
||||||
sixel_free(im->data);
|
sixel_free(im->data);
|
||||||
|
|||||||
@@ -313,12 +313,6 @@ static struct input_key_entry input_key_defaults[] = {
|
|||||||
{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
|
{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
|
||||||
.data = "\033[3;_~"
|
.data = "\033[3;_~"
|
||||||
},
|
},
|
||||||
{ .key = KEYC_REPORT_DARK_THEME,
|
|
||||||
.data = "\033[?997;1n"
|
|
||||||
},
|
|
||||||
{ .key = KEYC_REPORT_LIGHT_THEME,
|
|
||||||
.data = "\033[?997;2n"
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
static const key_code input_key_modifiers[] = {
|
static const key_code input_key_modifiers[] = {
|
||||||
0,
|
0,
|
||||||
|
|||||||
274
input.c
274
input.c
@@ -63,7 +63,7 @@ struct input_request {
|
|||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
enum input_request_type type;
|
enum input_request_type type;
|
||||||
time_t t;
|
uint64_t t;
|
||||||
enum input_end_type end;
|
enum input_end_type end;
|
||||||
|
|
||||||
int idx;
|
int idx;
|
||||||
@@ -72,7 +72,7 @@ struct input_request {
|
|||||||
TAILQ_ENTRY(input_request) entry;
|
TAILQ_ENTRY(input_request) entry;
|
||||||
TAILQ_ENTRY(input_request) centry;
|
TAILQ_ENTRY(input_request) centry;
|
||||||
};
|
};
|
||||||
#define INPUT_REQUEST_TIMEOUT 2
|
#define INPUT_REQUEST_TIMEOUT 500
|
||||||
|
|
||||||
/* Input parser cell. */
|
/* Input parser cell. */
|
||||||
struct input_cell {
|
struct input_cell {
|
||||||
@@ -101,6 +101,7 @@ struct input_ctx {
|
|||||||
struct bufferevent *event;
|
struct bufferevent *event;
|
||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
struct colour_palette *palette;
|
struct colour_palette *palette;
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
struct input_cell cell;
|
struct input_cell cell;
|
||||||
struct input_cell old_cell;
|
struct input_cell old_cell;
|
||||||
@@ -854,7 +855,7 @@ input_restore_state(struct input_ctx *ictx)
|
|||||||
/* Initialise input parser. */
|
/* Initialise input parser. */
|
||||||
struct input_ctx *
|
struct input_ctx *
|
||||||
input_init(struct window_pane *wp, struct bufferevent *bev,
|
input_init(struct window_pane *wp, struct bufferevent *bev,
|
||||||
struct colour_palette *palette)
|
struct colour_palette *palette, struct client *c)
|
||||||
{
|
{
|
||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
@@ -862,6 +863,7 @@ input_init(struct window_pane *wp, struct bufferevent *bev,
|
|||||||
ictx->wp = wp;
|
ictx->wp = wp;
|
||||||
ictx->event = bev;
|
ictx->event = bev;
|
||||||
ictx->palette = palette;
|
ictx->palette = palette;
|
||||||
|
ictx->c = c;
|
||||||
|
|
||||||
ictx->input_space = INPUT_BUF_START;
|
ictx->input_space = INPUT_BUF_START;
|
||||||
ictx->input_buf = xmalloc(INPUT_BUF_START);
|
ictx->input_buf = xmalloc(INPUT_BUF_START);
|
||||||
@@ -898,6 +900,8 @@ input_free(struct input_ctx *ictx)
|
|||||||
evbuffer_free(ictx->since_ground);
|
evbuffer_free(ictx->since_ground);
|
||||||
event_del(&ictx->ground_timer);
|
event_del(&ictx->ground_timer);
|
||||||
|
|
||||||
|
screen_write_stop_sync(ictx->wp);
|
||||||
|
|
||||||
free(ictx);
|
free(ictx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1135,11 +1139,9 @@ input_get(struct input_ctx *ictx, u_int validx, int minval, int defval)
|
|||||||
static void
|
static void
|
||||||
input_send_reply(struct input_ctx *ictx, const char *reply)
|
input_send_reply(struct input_ctx *ictx, const char *reply)
|
||||||
{
|
{
|
||||||
struct bufferevent *bev = ictx->event;
|
if (ictx->event != NULL) {
|
||||||
|
|
||||||
if (bev != NULL) {
|
|
||||||
log_debug("%s: %s", __func__, reply);
|
log_debug("%s: %s", __func__, reply);
|
||||||
bufferevent_write(bev, reply, strlen(reply));
|
bufferevent_write(ictx->event, reply, strlen(reply));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1623,10 +1625,6 @@ input_csi_dispatch(struct input_ctx *ictx)
|
|||||||
}
|
}
|
||||||
input_reply(ictx, 1, "\033[?12;%d$y", n);
|
input_reply(ictx, 1, "\033[?12;%d$y", n);
|
||||||
break;
|
break;
|
||||||
case 2004: /* bracketed paste */
|
|
||||||
n = (s->mode & MODE_BRACKETPASTE) ? 1 : 2;
|
|
||||||
input_reply(ictx, 1, "\033[?2004;%d$y", n);
|
|
||||||
break;
|
|
||||||
case 1004: /* focus reporting */
|
case 1004: /* focus reporting */
|
||||||
n = (s->mode & MODE_FOCUSON) ? 1 : 2;
|
n = (s->mode & MODE_FOCUSON) ? 1 : 2;
|
||||||
input_reply(ictx, 1, "\033[?1004;%d$y", n);
|
input_reply(ictx, 1, "\033[?1004;%d$y", n);
|
||||||
@@ -1635,6 +1633,14 @@ input_csi_dispatch(struct input_ctx *ictx)
|
|||||||
n = (s->mode & MODE_MOUSE_SGR) ? 1 : 2;
|
n = (s->mode & MODE_MOUSE_SGR) ? 1 : 2;
|
||||||
input_reply(ictx, 1, "\033[?1006;%d$y", n);
|
input_reply(ictx, 1, "\033[?1006;%d$y", n);
|
||||||
break;
|
break;
|
||||||
|
case 2004: /* bracketed paste */
|
||||||
|
n = (s->mode & MODE_BRACKETPASTE) ? 1 : 2;
|
||||||
|
input_reply(ictx, 1, "\033[?2004;%d$y", n);
|
||||||
|
break;
|
||||||
|
case 2026: /* synchronized output */
|
||||||
|
n = (s->mode & MODE_SYNC) ? 1 : 2;
|
||||||
|
input_reply(ictx, 1, "\033[?2026;%d$y", n);
|
||||||
|
break;
|
||||||
case 2031:
|
case 2031:
|
||||||
input_reply(ictx, 1, "\033[?2031;2$y");
|
input_reply(ictx, 1, "\033[?2031;2$y");
|
||||||
break;
|
break;
|
||||||
@@ -1900,6 +1906,13 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
|
|||||||
break;
|
break;
|
||||||
case 2031:
|
case 2031:
|
||||||
screen_write_mode_clear(sctx, MODE_THEME_UPDATES);
|
screen_write_mode_clear(sctx, MODE_THEME_UPDATES);
|
||||||
|
if (ictx->wp != NULL)
|
||||||
|
ictx->wp->flags &= ~PANE_THEMECHANGED;
|
||||||
|
break;
|
||||||
|
case 2026: /* synchronized output */
|
||||||
|
screen_write_stop_sync(ictx->wp);
|
||||||
|
if (ictx->wp != NULL)
|
||||||
|
ictx->wp->flags |= PANE_REDRAW;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||||
@@ -1998,6 +2011,13 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
|
|||||||
break;
|
break;
|
||||||
case 2031:
|
case 2031:
|
||||||
screen_write_mode_set(sctx, MODE_THEME_UPDATES);
|
screen_write_mode_set(sctx, MODE_THEME_UPDATES);
|
||||||
|
if (ictx->wp != NULL) {
|
||||||
|
ictx->wp->last_theme = window_pane_get_theme(ictx->wp);
|
||||||
|
ictx->wp->flags &= ~PANE_THEMECHANGED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2026: /* synchronized output */
|
||||||
|
screen_write_start_sync(ictx->wp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||||
@@ -3069,67 +3089,110 @@ input_osc_133(struct input_ctx *ictx, const char *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle OSC 52 reply. */
|
||||||
|
static void
|
||||||
|
input_osc_52_reply(struct input_ctx *ictx, char clip)
|
||||||
|
{
|
||||||
|
struct bufferevent *ev = ictx->event;
|
||||||
|
struct paste_buffer *pb;
|
||||||
|
int state;
|
||||||
|
const char *buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
state = options_get_number(global_options, "get-clipboard");
|
||||||
|
if (state == 0)
|
||||||
|
return;
|
||||||
|
if (state == 1) {
|
||||||
|
if ((pb = paste_get_top(NULL)) == NULL)
|
||||||
|
return;
|
||||||
|
buf = paste_buffer_data(pb, &len);
|
||||||
|
if (ictx->input_end == INPUT_END_BEL)
|
||||||
|
input_reply_clipboard(ev, buf, len, "\007", clip);
|
||||||
|
else
|
||||||
|
input_reply_clipboard(ev, buf, len, "\033\\", clip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input_add_request(ictx, INPUT_REQUEST_CLIPBOARD, ictx->input_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse and decode OSC 52 clipboard data. Returns 0 on failure or if handled
|
||||||
|
* as a query. On success, returns 1 and sets *out, *outlen, and *flags (caller
|
||||||
|
* must free *out).
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out,
|
||||||
|
int *outlen, char *clip)
|
||||||
|
{
|
||||||
|
char *end;
|
||||||
|
size_t len;
|
||||||
|
const char *allow = "cpqs01234567";
|
||||||
|
u_int i, j = 0;
|
||||||
|
|
||||||
|
if (options_get_number(global_options, "set-clipboard") != 2)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if ((end = strchr(p, ';')) == NULL)
|
||||||
|
return (0);
|
||||||
|
end++;
|
||||||
|
if (*end == '\0')
|
||||||
|
return (0);
|
||||||
|
log_debug("%s: %s", __func__, end);
|
||||||
|
|
||||||
|
for (i = 0; p + i != end; i++) {
|
||||||
|
if (strchr(allow, p[i]) != NULL && strchr(clip, p[i]) == NULL)
|
||||||
|
clip[j++] = p[i];
|
||||||
|
}
|
||||||
|
log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, clip);
|
||||||
|
|
||||||
|
if (strcmp(end, "?") == 0) {
|
||||||
|
input_osc_52_reply(ictx, *clip);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = (strlen(end) / 4) * 3;
|
||||||
|
if (len == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
*out = xmalloc(len);
|
||||||
|
if ((*outlen = b64_pton(end, *out, len)) == -1) {
|
||||||
|
free(*out);
|
||||||
|
*out = NULL;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle the OSC 52 sequence for setting the clipboard. */
|
/* Handle the OSC 52 sequence for setting the clipboard. */
|
||||||
static void
|
static void
|
||||||
input_osc_52(struct input_ctx *ictx, const char *p)
|
input_osc_52(struct input_ctx *ictx, const char *p)
|
||||||
{
|
{
|
||||||
struct window_pane *wp = ictx->wp;
|
struct window_pane *wp = ictx->wp;
|
||||||
char *end;
|
struct screen_write_ctx ctx;
|
||||||
const char *buf = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
u_char *out;
|
u_char *out;
|
||||||
int outlen, state;
|
int outlen;
|
||||||
struct screen_write_ctx ctx;
|
char clip[sizeof "cpqs01234567"] = "";
|
||||||
struct paste_buffer *pb;
|
|
||||||
const char* allow = "cpqs01234567";
|
|
||||||
char flags[sizeof "cpqs01234567"] = "";
|
|
||||||
u_int i, j = 0;
|
|
||||||
|
|
||||||
if (wp == NULL)
|
if (!input_osc_52_parse(ictx, p, &out, &outlen, clip))
|
||||||
return;
|
|
||||||
state = options_get_number(global_options, "set-clipboard");
|
|
||||||
if (state != 2)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((end = strchr(p, ';')) == NULL)
|
if (wp == NULL) {
|
||||||
return;
|
/* Popup window. */
|
||||||
end++;
|
if (ictx->c == NULL) {
|
||||||
if (*end == '\0')
|
free(out);
|
||||||
return;
|
return;
|
||||||
log_debug("%s: %s", __func__, end);
|
}
|
||||||
|
tty_set_selection(&ictx->c->tty, clip, out, outlen);
|
||||||
for (i = 0; p + i != end; i++) {
|
paste_add(NULL, out, outlen);
|
||||||
if (strchr(allow, p[i]) != NULL && strchr(flags, p[i]) == NULL)
|
} else {
|
||||||
flags[j++] = p[i];
|
/* Normal window. */
|
||||||
|
screen_write_start_pane(&ctx, wp, NULL);
|
||||||
|
screen_write_setselection(&ctx, clip, out, outlen);
|
||||||
|
screen_write_stop(&ctx);
|
||||||
|
notify_pane("pane-set-clipboard", wp);
|
||||||
|
paste_add(NULL, out, outlen);
|
||||||
}
|
}
|
||||||
log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, flags);
|
|
||||||
|
|
||||||
if (strcmp(end, "?") == 0) {
|
|
||||||
if ((pb = paste_get_top(NULL)) != NULL)
|
|
||||||
buf = paste_buffer_data(pb, &len);
|
|
||||||
if (ictx->input_end == INPUT_END_BEL)
|
|
||||||
input_reply_clipboard(ictx->event, buf, len, "\007");
|
|
||||||
else
|
|
||||||
input_reply_clipboard(ictx->event, buf, len, "\033\\");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = (strlen(end) / 4) * 3;
|
|
||||||
if (len == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
out = xmalloc(len);
|
|
||||||
if ((outlen = b64_pton(end, out, len)) == -1) {
|
|
||||||
free(out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen_write_start_pane(&ctx, wp, NULL);
|
|
||||||
screen_write_setselection(&ctx, flags, out, outlen);
|
|
||||||
screen_write_stop(&ctx);
|
|
||||||
notify_pane("pane-set-clipboard", wp);
|
|
||||||
|
|
||||||
paste_add(NULL, out, outlen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
|
/* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */
|
||||||
@@ -3169,9 +3232,10 @@ input_osc_104(struct input_ctx *ictx, const char *p)
|
|||||||
free(copy);
|
free(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Send a clipboard reply. */
|
||||||
void
|
void
|
||||||
input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
|
input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
|
||||||
const char *end)
|
const char *end, char clip)
|
||||||
{
|
{
|
||||||
char *out = NULL;
|
char *out = NULL;
|
||||||
int outlen = 0;
|
int outlen = 0;
|
||||||
@@ -3187,7 +3251,10 @@ input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferevent_write(bev, "\033]52;;", 6);
|
bufferevent_write(bev, "\033]52;", 5);
|
||||||
|
if (clip != 0)
|
||||||
|
bufferevent_write(bev, &clip, 1);
|
||||||
|
bufferevent_write(bev, ";", 1);
|
||||||
if (outlen != 0)
|
if (outlen != 0)
|
||||||
bufferevent_write(bev, out, outlen);
|
bufferevent_write(bev, out, outlen);
|
||||||
bufferevent_write(bev, end, strlen(end));
|
bufferevent_write(bev, end, strlen(end));
|
||||||
@@ -3208,7 +3275,7 @@ input_request_timer_callback(__unused int fd, __unused short events, void *arg)
|
|||||||
{
|
{
|
||||||
struct input_ctx *ictx = arg;
|
struct input_ctx *ictx = arg;
|
||||||
struct input_request *ir, *ir1;
|
struct input_request *ir, *ir1;
|
||||||
time_t t = time(NULL);
|
uint64_t t = get_timer();
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(ir, &ictx->requests, entry, ir1) {
|
TAILQ_FOREACH_SAFE(ir, &ictx->requests, entry, ir1) {
|
||||||
if (ir->t >= t - INPUT_REQUEST_TIMEOUT)
|
if (ir->t >= t - INPUT_REQUEST_TIMEOUT)
|
||||||
@@ -3225,7 +3292,7 @@ input_request_timer_callback(__unused int fd, __unused short events, void *arg)
|
|||||||
static void
|
static void
|
||||||
input_start_request_timer(struct input_ctx *ictx)
|
input_start_request_timer(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
struct timeval tv = { .tv_sec = 0, .tv_usec = 500000 };
|
struct timeval tv = { .tv_sec = 0, .tv_usec = 100000 };
|
||||||
|
|
||||||
event_del(&ictx->request_timer);
|
event_del(&ictx->request_timer);
|
||||||
event_add(&ictx->request_timer, &tv);
|
event_add(&ictx->request_timer, &tv);
|
||||||
@@ -3240,7 +3307,7 @@ input_make_request(struct input_ctx *ictx, enum input_request_type type)
|
|||||||
ir = xcalloc (1, sizeof *ir);
|
ir = xcalloc (1, sizeof *ir);
|
||||||
ir->type = type;
|
ir->type = type;
|
||||||
ir->ictx = ictx;
|
ir->ictx = ictx;
|
||||||
ir->t = time(NULL);
|
ir->t = get_timer();
|
||||||
|
|
||||||
if (++ictx->request_count == 1)
|
if (++ictx->request_count == 1)
|
||||||
input_start_request_timer(ictx);
|
input_start_request_timer(ictx);
|
||||||
@@ -3305,6 +3372,9 @@ input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx)
|
|||||||
xsnprintf(s, sizeof s, "\033]4;%d;?\033\\", idx);
|
xsnprintf(s, sizeof s, "\033]4;%d;?\033\\", idx);
|
||||||
tty_puts(&c->tty, s);
|
tty_puts(&c->tty, s);
|
||||||
break;
|
break;
|
||||||
|
case INPUT_REQUEST_CLIPBOARD:
|
||||||
|
tty_putcode_ss(&c->tty, TTYC_MS, "", "?");
|
||||||
|
break;
|
||||||
case INPUT_REQUEST_QUEUE:
|
case INPUT_REQUEST_QUEUE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3312,6 +3382,40 @@ input_add_request(struct input_ctx *ictx, enum input_request_type type, int idx)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle a palette reply. */
|
||||||
|
static void
|
||||||
|
input_request_palette_reply(struct input_request *ir, void *data)
|
||||||
|
{
|
||||||
|
struct input_request_palette_data *pd = data;
|
||||||
|
|
||||||
|
input_osc_colour_reply(ir->ictx, 0, 4, pd->idx, pd->c, ir->end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle a clipboard reply. */
|
||||||
|
static void
|
||||||
|
input_request_clipboard_reply(struct input_request *ir, void *data)
|
||||||
|
{
|
||||||
|
struct input_ctx *ictx = ir->ictx;
|
||||||
|
struct bufferevent *ev = ictx->event;
|
||||||
|
struct input_request_clipboard_data *cd = data;
|
||||||
|
int state;
|
||||||
|
char *copy;
|
||||||
|
|
||||||
|
state = options_get_number(global_options, "get-clipboard");
|
||||||
|
if (state == 0 || state == 1)
|
||||||
|
return;
|
||||||
|
if (state == 3) {
|
||||||
|
copy = xmalloc(cd->len);
|
||||||
|
memcpy(copy, cd->buf, cd->len);
|
||||||
|
paste_add(NULL, copy, cd->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ir->idx == INPUT_END_BEL)
|
||||||
|
input_reply_clipboard(ev, cd->buf, cd->len, "\007", cd->clip);
|
||||||
|
else
|
||||||
|
input_reply_clipboard(ev, cd->buf, cd->len, "\033\\", cd->clip);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle a reply to a request. */
|
/* Handle a reply to a request. */
|
||||||
void
|
void
|
||||||
input_request_reply(struct client *c, enum input_request_type type, void *data)
|
input_request_reply(struct client *c, enum input_request_type type, void *data)
|
||||||
@@ -3321,11 +3425,22 @@ input_request_reply(struct client *c, enum input_request_type type, void *data)
|
|||||||
int complete = 0;
|
int complete = 0;
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(ir, &c->input_requests, centry, ir1) {
|
TAILQ_FOREACH_SAFE(ir, &c->input_requests, centry, ir1) {
|
||||||
if (ir->type == type && pd->idx == ir->idx) {
|
if (ir->type != type) {
|
||||||
|
input_free_request(ir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (type == INPUT_REQUEST_PALETTE) {
|
||||||
|
if (pd->idx != ir->idx) {
|
||||||
|
input_free_request(ir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
found = ir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (type == INPUT_REQUEST_CLIPBOARD) {
|
||||||
found = ir;
|
found = ir;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
input_free_request(ir);
|
|
||||||
}
|
}
|
||||||
if (found == NULL)
|
if (found == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -3335,8 +3450,11 @@ input_request_reply(struct client *c, enum input_request_type type, void *data)
|
|||||||
break;
|
break;
|
||||||
if (ir->type == INPUT_REQUEST_QUEUE)
|
if (ir->type == INPUT_REQUEST_QUEUE)
|
||||||
input_send_reply(ir->ictx, ir->data);
|
input_send_reply(ir->ictx, ir->data);
|
||||||
else if (ir == found && ir->type == INPUT_REQUEST_PALETTE) {
|
else if (ir == found) {
|
||||||
input_osc_colour_reply(ir->ictx, 0, 4, pd->idx, pd->c, ir->end);
|
if (ir->type == INPUT_REQUEST_PALETTE)
|
||||||
|
input_request_palette_reply(ir, data);
|
||||||
|
else if (ir->type == INPUT_REQUEST_CLIPBOARD)
|
||||||
|
input_request_clipboard_reply(ir, data);
|
||||||
complete = 1;
|
complete = 1;
|
||||||
}
|
}
|
||||||
input_free_request(ir);
|
input_free_request(ir);
|
||||||
@@ -3349,7 +3467,7 @@ input_cancel_requests(struct client *c)
|
|||||||
{
|
{
|
||||||
struct input_request *ir, *ir1;
|
struct input_request *ir, *ir1;
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(ir, &c->input_requests, entry, ir1)
|
TAILQ_FOREACH_SAFE(ir, &c->input_requests, centry, ir1)
|
||||||
input_free_request(ir);
|
input_free_request(ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3357,14 +3475,24 @@ input_cancel_requests(struct client *c)
|
|||||||
static void
|
static void
|
||||||
input_report_current_theme(struct input_ctx *ictx)
|
input_report_current_theme(struct input_ctx *ictx)
|
||||||
{
|
{
|
||||||
switch (window_pane_get_theme(ictx->wp)) {
|
struct window_pane *wp = ictx->wp;
|
||||||
|
|
||||||
|
if (wp != NULL) {
|
||||||
|
wp->last_theme = window_pane_get_theme(wp);
|
||||||
|
wp->flags &= ~PANE_THEMECHANGED;
|
||||||
|
|
||||||
|
switch (wp->last_theme) {
|
||||||
case THEME_DARK:
|
case THEME_DARK:
|
||||||
|
log_debug("%s: %%%u dark theme", __func__, wp->id);
|
||||||
input_reply(ictx, 0, "\033[?997;1n");
|
input_reply(ictx, 0, "\033[?997;1n");
|
||||||
break;
|
break;
|
||||||
case THEME_LIGHT:
|
case THEME_LIGHT:
|
||||||
|
log_debug("%s: %%%u light theme", __func__, wp->id);
|
||||||
input_reply(ictx, 0, "\033[?997;2n");
|
input_reply(ictx, 0, "\033[?997;2n");
|
||||||
break;
|
break;
|
||||||
case THEME_UNKNOWN:
|
case THEME_UNKNOWN:
|
||||||
|
log_debug("%s: %%%u unknown theme", __func__, wp->id);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,8 @@
|
|||||||
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Top,}' '<' {send -X history-top}" \
|
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Top,}' '<' {send -X history-top}" \
|
||||||
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Bottom,}' '>' {send -X history-bottom}" \
|
" '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Bottom,}' '>' {send -X history-bottom}" \
|
||||||
" ''" \
|
" ''" \
|
||||||
|
" '#{?#{&&:#{buffer_size},#{!:#{pane_in_mode}}},Paste #[underscore]#{=/9/...:buffer_sample},}' 'p' {paste-buffer}" \
|
||||||
|
" ''" \
|
||||||
" '#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},}' 'C-r' {if -F '#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}' 'copy-mode -t='; send -Xt= search-backward -- \"#{q:mouse_word}\"}" \
|
" '#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},}' 'C-r' {if -F '#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}' 'copy-mode -t='; send -Xt= search-backward -- \"#{q:mouse_word}\"}" \
|
||||||
" '#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}' 'C-y' {copy-mode -q; send-keys -l -- \"#{q:mouse_word}\"}" \
|
" '#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}' 'C-y' {copy-mode -q; send-keys -l -- \"#{q:mouse_word}\"}" \
|
||||||
" '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {copy-mode -q; set-buffer -- \"#{q:mouse_word}\"}" \
|
" '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {copy-mode -q; set-buffer -- \"#{q:mouse_word}\"}" \
|
||||||
@@ -213,6 +215,7 @@ key_bindings_add(const char *name, key_code key, const char *note, int repeat,
|
|||||||
|
|
||||||
bd = xcalloc(1, sizeof *bd);
|
bd = xcalloc(1, sizeof *bd);
|
||||||
bd->key = (key & ~KEYC_MASK_FLAGS);
|
bd->key = (key & ~KEYC_MASK_FLAGS);
|
||||||
|
bd->tablename = table->name;
|
||||||
if (note != NULL)
|
if (note != NULL)
|
||||||
bd->note = xstrdup(note);
|
bd->note = xstrdup(note);
|
||||||
RB_INSERT(key_bindings, &table->key_bindings, bd);
|
RB_INSERT(key_bindings, &table->key_bindings, bd);
|
||||||
@@ -295,12 +298,12 @@ key_bindings_remove_table(const char *name)
|
|||||||
table = key_bindings_get_table(name, 0);
|
table = key_bindings_get_table(name, 0);
|
||||||
if (table != NULL) {
|
if (table != NULL) {
|
||||||
RB_REMOVE(key_tables, &key_tables, table);
|
RB_REMOVE(key_tables, &key_tables, table);
|
||||||
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (c->keytable == table)
|
||||||
|
server_client_set_key_table(c, NULL);
|
||||||
|
}
|
||||||
key_bindings_unref_table(table);
|
key_bindings_unref_table(table);
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (c->keytable == table)
|
|
||||||
server_client_set_key_table(c, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -347,6 +350,10 @@ key_bindings_init(void)
|
|||||||
{
|
{
|
||||||
static const char *const defaults[] = {
|
static const char *const defaults[] = {
|
||||||
/* Prefix keys. */
|
/* Prefix keys. */
|
||||||
|
"bind -N 'Minimise pane' _ { minimise-pane }",
|
||||||
|
/* Mouse button 1 double click on status line. */
|
||||||
|
"bind -n DoubleClick1Status { minimise-pane -t= }",
|
||||||
|
|
||||||
"bind -N 'Send the prefix key' C-b { send-prefix }",
|
"bind -N 'Send the prefix key' C-b { send-prefix }",
|
||||||
"bind -N 'Rotate through the panes' C-o { rotate-window }",
|
"bind -N 'Rotate through the panes' C-o { rotate-window }",
|
||||||
"bind -N 'Suspend the current client' C-z { suspend-client }",
|
"bind -N 'Suspend the current client' C-z { suspend-client }",
|
||||||
@@ -358,6 +365,7 @@ key_bindings_init(void)
|
|||||||
"bind -N 'Split window horizontally' % { split-window -h }",
|
"bind -N 'Split window horizontally' % { split-window -h }",
|
||||||
"bind -N 'Kill current window' & { confirm-before -p\"kill-window #W? (y/n)\" kill-window }",
|
"bind -N 'Kill current window' & { confirm-before -p\"kill-window #W? (y/n)\" kill-window }",
|
||||||
"bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex { select-window -t ':%%' } }",
|
"bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex { select-window -t ':%%' } }",
|
||||||
|
"bind -N 'New floating pane' * { new-pane }",
|
||||||
"bind -N 'Switch to previous client' ( { switch-client -p }",
|
"bind -N 'Switch to previous client' ( { switch-client -p }",
|
||||||
"bind -N 'Switch to next client' ) { switch-client -n }",
|
"bind -N 'Switch to next client' ) { switch-client -n }",
|
||||||
"bind -N 'Rename current window' , { command-prompt -I'#W' { rename-window -- '%%' } }",
|
"bind -N 'Rename current window' , { command-prompt -I'#W' { rename-window -- '%%' } }",
|
||||||
@@ -439,9 +447,10 @@ key_bindings_init(void)
|
|||||||
|
|
||||||
/* Mouse button 1 down on pane. */
|
/* Mouse button 1 down on pane. */
|
||||||
"bind -n MouseDown1Pane { select-pane -t=; send -M }",
|
"bind -n MouseDown1Pane { select-pane -t=; send -M }",
|
||||||
|
"bind -n C-MouseDown1Pane { swap-pane -s@ }",
|
||||||
|
|
||||||
/* Mouse button 1 drag on pane. */
|
/* Mouse button 1 drag on pane. */
|
||||||
"bind -n MouseDrag1Pane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
|
"bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
|
||||||
|
|
||||||
/* Mouse wheel up on pane. */
|
/* Mouse wheel up on pane. */
|
||||||
"bind -n WheelUpPane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }",
|
"bind -n WheelUpPane { if -F '#{||:#{alternate_on},#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -e } }",
|
||||||
@@ -455,11 +464,15 @@ key_bindings_init(void)
|
|||||||
/* Mouse button 1 triple click on pane. */
|
/* Mouse button 1 triple click on pane. */
|
||||||
"bind -n TripleClick1Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel } }",
|
"bind -n TripleClick1Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel } }",
|
||||||
|
|
||||||
|
/* Mouse button 1 on border. */
|
||||||
|
"bind -n MouseDown1Border { select-pane -M }",
|
||||||
|
|
||||||
/* Mouse button 1 drag on border. */
|
/* Mouse button 1 drag on border. */
|
||||||
"bind -n MouseDrag1Border { resize-pane -M }",
|
"bind -n MouseDrag1Border { resize-pane -M }",
|
||||||
|
|
||||||
/* Mouse button 1 down on status line. */
|
/* Mouse button 1 down on status line. */
|
||||||
"bind -n MouseDown1Status { switch-client -t= }",
|
"bind -n MouseDown1Status { switch-client -t= }",
|
||||||
|
"bind -n C-MouseDown1Status { swap-window -t@ }",
|
||||||
|
|
||||||
/* Mouse wheel down on status line. */
|
/* Mouse wheel down on status line. */
|
||||||
"bind -n WheelDownStatus { next-window }",
|
"bind -n WheelDownStatus { next-window }",
|
||||||
@@ -480,9 +493,9 @@ key_bindings_init(void)
|
|||||||
"bind -n M-MouseDown3Pane { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }",
|
"bind -n M-MouseDown3Pane { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }",
|
||||||
|
|
||||||
/* Mouse on scrollbar. */
|
/* Mouse on scrollbar. */
|
||||||
"bind -n MouseDown1ScrollbarUp { copy-mode -u }",
|
"bind -n MouseDown1ScrollbarUp { if -Ft= '#{pane_in_mode}' { send -X page-up } {copy-mode -u } }",
|
||||||
"bind -n MouseDown1ScrollbarDown { copy-mode -d }",
|
"bind -n MouseDown1ScrollbarDown { if -Ft= '#{pane_in_mode}' { send -X page-down } {copy-mode -d } }",
|
||||||
"bind -n MouseDrag1ScrollbarSlider { copy-mode -S }",
|
"bind -n MouseDrag1ScrollbarSlider { if -Ft= '#{pane_in_mode}' { send -X scroll-to-mouse } { copy-mode -S } }",
|
||||||
|
|
||||||
/* Copy mode (emacs) keys. */
|
/* Copy mode (emacs) keys. */
|
||||||
"bind -Tcopy-mode C-Space { send -X begin-selection }",
|
"bind -Tcopy-mode C-Space { send -X begin-selection }",
|
||||||
@@ -683,6 +696,7 @@ key_bindings_dispatch(struct key_binding *bd, struct cmdq_item *item,
|
|||||||
readonly = 1;
|
readonly = 1;
|
||||||
else
|
else
|
||||||
readonly = cmd_list_all_have(bd->cmdlist, CMD_READONLY);
|
readonly = cmd_list_all_have(bd->cmdlist, CMD_READONLY);
|
||||||
|
|
||||||
if (!readonly)
|
if (!readonly)
|
||||||
new_item = cmdq_get_callback(key_bindings_read_only, NULL);
|
new_item = cmdq_get_callback(key_bindings_read_only, NULL);
|
||||||
else {
|
else {
|
||||||
@@ -698,3 +712,15 @@ key_bindings_dispatch(struct key_binding *bd, struct cmdq_item *item,
|
|||||||
new_item = cmdq_append(c, new_item);
|
new_item = cmdq_append(c, new_item);
|
||||||
return (new_item);
|
return (new_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
key_bindings_has_repeat(struct key_binding **l, u_int n)
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (l[i]->flags & KEY_BINDING_REPEAT)
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -382,6 +382,14 @@ key_string_lookup_key(key_code key, int with_flags)
|
|||||||
s = "PasteEnd";
|
s = "PasteEnd";
|
||||||
goto append;
|
goto append;
|
||||||
}
|
}
|
||||||
|
if (key == KEYC_REPORT_DARK_THEME) {
|
||||||
|
s = "ReportDarkTheme";
|
||||||
|
goto append;
|
||||||
|
}
|
||||||
|
if (key == KEYC_REPORT_LIGHT_THEME) {
|
||||||
|
s = "ReportLightTheme";
|
||||||
|
goto append;
|
||||||
|
}
|
||||||
if (key == KEYC_MOUSE) {
|
if (key == KEYC_MOUSE) {
|
||||||
s = "Mouse";
|
s = "Mouse";
|
||||||
goto append;
|
goto append;
|
||||||
|
|||||||
180
layout-custom.c
180
layout-custom.c
@@ -27,10 +27,11 @@ static struct layout_cell *layout_find_bottomright(struct layout_cell *);
|
|||||||
static u_short layout_checksum(const char *);
|
static u_short layout_checksum(const char *);
|
||||||
static int layout_append(struct layout_cell *, char *,
|
static int layout_append(struct layout_cell *, char *,
|
||||||
size_t);
|
size_t);
|
||||||
static struct layout_cell *layout_construct(struct layout_cell *,
|
static int layout_construct(struct layout_cell *,
|
||||||
const char **);
|
const char **, struct layout_cell **,
|
||||||
|
struct layout_cell **);
|
||||||
static void layout_assign(struct window_pane **,
|
static void layout_assign(struct window_pane **,
|
||||||
struct layout_cell *);
|
struct layout_cell *, int);
|
||||||
|
|
||||||
/* Find the bottom-right cell. */
|
/* Find the bottom-right cell. */
|
||||||
static struct layout_cell *
|
static struct layout_cell *
|
||||||
@@ -58,14 +59,33 @@ layout_checksum(const char *layout)
|
|||||||
|
|
||||||
/* Dump layout as a string. */
|
/* Dump layout as a string. */
|
||||||
char *
|
char *
|
||||||
layout_dump(struct layout_cell *root)
|
layout_dump(struct window *w, struct layout_cell *root)
|
||||||
{
|
{
|
||||||
char layout[8192], *out;
|
char layout[8192], *out;
|
||||||
|
int braket;
|
||||||
|
struct window_pane *wp;
|
||||||
|
|
||||||
*layout = '\0';
|
*layout = '\0';
|
||||||
if (layout_append(root, layout, sizeof layout) != 0)
|
if (layout_append(root, layout, sizeof layout) != 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
braket = 0;
|
||||||
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
|
if (~wp->flags & PANE_FLOATING)
|
||||||
|
break;
|
||||||
|
if (!braket) {
|
||||||
|
strcat(layout, "<");
|
||||||
|
braket = 1;
|
||||||
|
}
|
||||||
|
if (layout_append(wp->layout_cell, layout, sizeof layout) != 0)
|
||||||
|
return (NULL);
|
||||||
|
strcat(layout, ",");
|
||||||
|
}
|
||||||
|
if (braket) {
|
||||||
|
/* Overwrite the trailing ','. */
|
||||||
|
layout[strlen(layout) - 1] = '>';
|
||||||
|
}
|
||||||
|
|
||||||
xasprintf(&out, "%04hx,%s", layout_checksum(layout), layout);
|
xasprintf(&out, "%04hx,%s", layout_checksum(layout), layout);
|
||||||
return (out);
|
return (out);
|
||||||
}
|
}
|
||||||
@@ -81,7 +101,8 @@ layout_append(struct layout_cell *lc, char *buf, size_t len)
|
|||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
if (lc == NULL)
|
||||||
|
return (0);
|
||||||
if (lc->wp != NULL) {
|
if (lc->wp != NULL) {
|
||||||
tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%u,%u,%u",
|
tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%u,%u,%u",
|
||||||
lc->sx, lc->sy, lc->xoff, lc->yoff, lc->wp->id);
|
lc->sx, lc->sy, lc->xoff, lc->yoff, lc->wp->id);
|
||||||
@@ -109,6 +130,7 @@ layout_append(struct layout_cell *lc, char *buf, size_t len)
|
|||||||
}
|
}
|
||||||
buf[strlen(buf) - 1] = brackets[0];
|
buf[strlen(buf) - 1] = brackets[0];
|
||||||
break;
|
break;
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
case LAYOUT_WINDOWPANE:
|
case LAYOUT_WINDOWPANE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -125,6 +147,7 @@ layout_check(struct layout_cell *lc)
|
|||||||
|
|
||||||
switch (lc->type) {
|
switch (lc->type) {
|
||||||
case LAYOUT_WINDOWPANE:
|
case LAYOUT_WINDOWPANE:
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
break;
|
break;
|
||||||
case LAYOUT_LEFTRIGHT:
|
case LAYOUT_LEFTRIGHT:
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
@@ -156,7 +179,7 @@ layout_check(struct layout_cell *lc)
|
|||||||
int
|
int
|
||||||
layout_parse(struct window *w, const char *layout, char **cause)
|
layout_parse(struct window *w, const char *layout, char **cause)
|
||||||
{
|
{
|
||||||
struct layout_cell *lc, *lcchild;
|
struct layout_cell *lcchild, *tiled_lc = NULL, *floating_lc = NULL;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
u_int npanes, ncells, sx = 0, sy = 0;
|
u_int npanes, ncells, sx = 0, sy = 0;
|
||||||
u_short csum;
|
u_short csum;
|
||||||
@@ -173,11 +196,16 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Build the layout. */
|
/* Build the layout. */
|
||||||
lc = layout_construct(NULL, &layout);
|
if (layout_construct(NULL, &layout, &tiled_lc, &floating_lc) != 0) {
|
||||||
if (lc == NULL) {
|
|
||||||
*cause = xstrdup("invalid layout");
|
*cause = xstrdup("invalid layout");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
if (tiled_lc == NULL) {
|
||||||
|
/* A stub layout cell for an empty window. */
|
||||||
|
tiled_lc = layout_create_cell(NULL);
|
||||||
|
tiled_lc->type = LAYOUT_LEFTRIGHT;
|
||||||
|
layout_set_size(tiled_lc, w->sx, w->sy, 0, 0);
|
||||||
|
}
|
||||||
if (*layout != '\0') {
|
if (*layout != '\0') {
|
||||||
*cause = xstrdup("invalid layout");
|
*cause = xstrdup("invalid layout");
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -186,8 +214,10 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
|||||||
/* Check this window will fit into the layout. */
|
/* Check this window will fit into the layout. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
npanes = window_count_panes(w);
|
npanes = window_count_panes(w);
|
||||||
ncells = layout_count_cells(lc);
|
ncells = layout_count_cells(tiled_lc);
|
||||||
|
ncells += layout_count_cells(floating_lc);
|
||||||
if (npanes > ncells) {
|
if (npanes > ncells) {
|
||||||
|
/* Modify this to open a new pane */
|
||||||
xasprintf(cause, "have %u panes but need %u", npanes,
|
xasprintf(cause, "have %u panes but need %u", npanes,
|
||||||
ncells);
|
ncells);
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -195,9 +225,17 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
|||||||
if (npanes == ncells)
|
if (npanes == ncells)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Fewer panes than cells - close the bottom right. */
|
/*
|
||||||
lcchild = layout_find_bottomright(lc);
|
* Fewer panes than cells - close floating panes first
|
||||||
layout_destroy_cell(w, lcchild, &lc);
|
* then close the bottom right until.
|
||||||
|
*/
|
||||||
|
if (floating_lc && ! TAILQ_EMPTY(&floating_lc->cells)) {
|
||||||
|
lcchild = TAILQ_FIRST(&floating_lc->cells);
|
||||||
|
layout_destroy_cell(w, lcchild, &floating_lc);
|
||||||
|
} else {
|
||||||
|
lcchild = layout_find_bottomright(tiled_lc);
|
||||||
|
layout_destroy_cell(w, lcchild, &tiled_lc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -205,85 +243,112 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
|||||||
* an incorrect top cell size - if it is larger than the top child then
|
* an incorrect top cell size - if it is larger than the top child then
|
||||||
* correct that (if this is still wrong the check code will catch it).
|
* correct that (if this is still wrong the check code will catch it).
|
||||||
*/
|
*/
|
||||||
switch (lc->type) {
|
|
||||||
|
switch (tiled_lc->type) {
|
||||||
case LAYOUT_WINDOWPANE:
|
case LAYOUT_WINDOWPANE:
|
||||||
break;
|
break;
|
||||||
case LAYOUT_LEFTRIGHT:
|
case LAYOUT_LEFTRIGHT:
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &tiled_lc->cells, entry) {
|
||||||
sy = lcchild->sy + 1;
|
sy = lcchild->sy + 1;
|
||||||
sx += lcchild->sx + 1;
|
sx += lcchild->sx + 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LAYOUT_TOPBOTTOM:
|
case LAYOUT_TOPBOTTOM:
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &tiled_lc->cells, entry) {
|
||||||
sx = lcchild->sx + 1;
|
sx = lcchild->sx + 1;
|
||||||
sy += lcchild->sy + 1;
|
sy += lcchild->sy + 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
|
*cause = xstrdup("invalid layout");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
if (lc->type != LAYOUT_WINDOWPANE && (lc->sx != sx || lc->sy != sy)) {
|
if (tiled_lc->type != LAYOUT_WINDOWPANE &&
|
||||||
log_debug("fix layout %u,%u to %u,%u", lc->sx, lc->sy, sx,sy);
|
(tiled_lc->sx != sx || tiled_lc->sy != sy)) {
|
||||||
layout_print_cell(lc, __func__, 0);
|
log_debug("fix layout %u,%u to %u,%u", tiled_lc->sx,
|
||||||
lc->sx = sx - 1; lc->sy = sy - 1;
|
tiled_lc->sy, sx,sy);
|
||||||
|
layout_print_cell(tiled_lc, __func__, 0);
|
||||||
|
tiled_lc->sx = sx - 1; tiled_lc->sy = sy - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the new layout. */
|
/* Check the new layout. */
|
||||||
if (!layout_check(lc)) {
|
if (!layout_check(tiled_lc)) {
|
||||||
*cause = xstrdup("size mismatch after applying layout");
|
*cause = xstrdup("size mismatch after applying layout");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resize to the layout size. */
|
/* Resize window to the layout size. */
|
||||||
window_resize(w, lc->sx, lc->sy, -1, -1);
|
if (sx != 0 && sy != 0)
|
||||||
|
window_resize(w, tiled_lc->sx, tiled_lc->sy, -1, -1);
|
||||||
|
|
||||||
/* Destroy the old layout and swap to the new. */
|
/* Destroy the old layout and swap to the new. */
|
||||||
layout_free_cell(w->layout_root);
|
layout_free_cell(w->layout_root);
|
||||||
w->layout_root = lc;
|
w->layout_root = tiled_lc;
|
||||||
|
|
||||||
/* Assign the panes into the cells. */
|
/* Assign the panes into the cells. */
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
layout_assign(&wp, lc);
|
layout_assign(&wp, tiled_lc, 0);
|
||||||
|
layout_assign(&wp, floating_lc, 1);
|
||||||
|
|
||||||
|
/* Fix z_indexes. */
|
||||||
|
while (!TAILQ_EMPTY(&w->z_index)) {
|
||||||
|
wp = TAILQ_FIRST(&w->z_index);
|
||||||
|
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||||
|
}
|
||||||
|
layout_fix_zindexes(w, floating_lc);
|
||||||
|
layout_fix_zindexes(w, tiled_lc);
|
||||||
|
|
||||||
/* Update pane offsets and sizes. */
|
/* Update pane offsets and sizes. */
|
||||||
layout_fix_offsets(w);
|
layout_fix_offsets(w);
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
|
||||||
layout_print_cell(lc, __func__, 0);
|
layout_print_cell(tiled_lc, __func__, 0);
|
||||||
|
layout_print_cell(floating_lc, __func__, 0);
|
||||||
|
|
||||||
|
/* Free the floating layout cell, no longer needed. */
|
||||||
|
layout_free_cell(floating_lc);
|
||||||
|
|
||||||
notify_window("window-layout-changed", w);
|
notify_window("window-layout-changed", w);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
layout_free_cell(lc);
|
layout_free_cell(tiled_lc);
|
||||||
|
layout_free_cell(floating_lc);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign panes into cells. */
|
/* Assign panes into cells. */
|
||||||
static void
|
static void
|
||||||
layout_assign(struct window_pane **wp, struct layout_cell *lc)
|
layout_assign(struct window_pane **wp, struct layout_cell *lc, int floating)
|
||||||
{
|
{
|
||||||
struct layout_cell *lcchild;
|
struct layout_cell *lcchild;
|
||||||
|
|
||||||
|
if (lc == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (lc->type) {
|
switch (lc->type) {
|
||||||
case LAYOUT_WINDOWPANE:
|
case LAYOUT_WINDOWPANE:
|
||||||
layout_make_leaf(lc, *wp);
|
layout_make_leaf(lc, *wp);
|
||||||
|
if (floating) {
|
||||||
|
(*wp)->flags |= PANE_FLOATING;
|
||||||
|
}
|
||||||
*wp = TAILQ_NEXT(*wp, entry);
|
*wp = TAILQ_NEXT(*wp, entry);
|
||||||
return;
|
return;
|
||||||
case LAYOUT_LEFTRIGHT:
|
case LAYOUT_LEFTRIGHT:
|
||||||
case LAYOUT_TOPBOTTOM:
|
case LAYOUT_TOPBOTTOM:
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||||
layout_assign(wp, lcchild);
|
layout_assign(wp, lcchild, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct a cell from all or part of a layout tree. */
|
|
||||||
static struct layout_cell *
|
static struct layout_cell *
|
||||||
layout_construct(struct layout_cell *lcparent, const char **layout)
|
layout_construct_cell(struct layout_cell *lcparent, const char **layout)
|
||||||
{
|
{
|
||||||
struct layout_cell *lc, *lcchild;
|
struct layout_cell *lc;
|
||||||
u_int sx, sy, xoff, yoff;
|
u_int sx, sy, xoff, yoff;
|
||||||
const char *saved;
|
const char *saved;
|
||||||
|
|
||||||
@@ -324,17 +389,42 @@ layout_construct(struct layout_cell *lcparent, const char **layout)
|
|||||||
lc->xoff = xoff;
|
lc->xoff = xoff;
|
||||||
lc->yoff = yoff;
|
lc->yoff = yoff;
|
||||||
|
|
||||||
|
return (lc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a character string layout, recursively construct cells.
|
||||||
|
* Possible return values:
|
||||||
|
* lc LAYOUT_WINDOWPANE, no children
|
||||||
|
* lc LAYOUT_LEFTRIGHT or LAYOUT_TOPBOTTOM, with children
|
||||||
|
* floating_lc LAYOUT_FLOATING, with children
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
layout_construct(struct layout_cell *lcparent, const char **layout,
|
||||||
|
struct layout_cell **lc, struct layout_cell **floating_lc)
|
||||||
|
{
|
||||||
|
struct layout_cell *lcchild, *saved_lc;
|
||||||
|
|
||||||
|
*lc = layout_construct_cell(lcparent, layout);
|
||||||
|
|
||||||
switch (**layout) {
|
switch (**layout) {
|
||||||
case ',':
|
case ',':
|
||||||
case '}':
|
case '}':
|
||||||
case ']':
|
case ']':
|
||||||
|
case '>':
|
||||||
case '\0':
|
case '\0':
|
||||||
return (lc);
|
return (0);
|
||||||
case '{':
|
case '{':
|
||||||
lc->type = LAYOUT_LEFTRIGHT;
|
(*lc)->type = LAYOUT_LEFTRIGHT;
|
||||||
break;
|
break;
|
||||||
case '[':
|
case '[':
|
||||||
lc->type = LAYOUT_TOPBOTTOM;
|
(*lc)->type = LAYOUT_TOPBOTTOM;
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
saved_lc = *lc;
|
||||||
|
*lc = layout_create_cell(lcparent);
|
||||||
|
(*lc)->type = LAYOUT_FLOATING;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -342,13 +432,12 @@ layout_construct(struct layout_cell *lcparent, const char **layout)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
(*layout)++;
|
(*layout)++;
|
||||||
lcchild = layout_construct(lc, layout);
|
if (layout_construct(*lc, layout, &lcchild, floating_lc) != 0)
|
||||||
if (lcchild == NULL)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry);
|
TAILQ_INSERT_TAIL(&(*lc)->cells, lcchild, entry);
|
||||||
} while (**layout == ',');
|
} while (**layout == ',');
|
||||||
|
|
||||||
switch (lc->type) {
|
switch ((*lc)->type) {
|
||||||
case LAYOUT_LEFTRIGHT:
|
case LAYOUT_LEFTRIGHT:
|
||||||
if (**layout != '}')
|
if (**layout != '}')
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -357,14 +446,21 @@ layout_construct(struct layout_cell *lcparent, const char **layout)
|
|||||||
if (**layout != ']')
|
if (**layout != ']')
|
||||||
goto fail;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
|
if (**layout != '>')
|
||||||
|
goto fail;
|
||||||
|
*floating_lc = *lc;
|
||||||
|
*lc = saved_lc;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
(*layout)++;
|
(*layout)++;
|
||||||
|
|
||||||
return (lc);
|
return (0);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
layout_free_cell(lc);
|
layout_free_cell(*lc);
|
||||||
return (NULL);
|
layout_free_cell(*floating_lc);
|
||||||
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|||||||
187
layout.c
187
layout.c
@@ -83,9 +83,24 @@ layout_free_cell(struct layout_cell *lc)
|
|||||||
layout_free_cell(lcchild);
|
layout_free_cell(lcchild);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
|
/* A Floating layout cell is only used temporarily
|
||||||
|
* while select-layout constructs a layout.
|
||||||
|
* Cleave the children from the temp layout, then
|
||||||
|
* free temp floating layout cell. Each floating
|
||||||
|
* pane has stub layout.
|
||||||
|
*/
|
||||||
|
while (!TAILQ_EMPTY(&lc->cells)) {
|
||||||
|
lcchild = TAILQ_FIRST(&lc->cells);
|
||||||
|
TAILQ_REMOVE(&lc->cells, lcchild, entry);
|
||||||
|
lcchild->parent = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case LAYOUT_WINDOWPANE:
|
case LAYOUT_WINDOWPANE:
|
||||||
if (lc->wp != NULL)
|
if (lc->wp != NULL) {
|
||||||
|
lc->wp->layout_cell->parent = NULL;
|
||||||
lc->wp->layout_cell = NULL;
|
lc->wp->layout_cell = NULL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +113,9 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
|||||||
struct layout_cell *lcchild;
|
struct layout_cell *lcchild;
|
||||||
const char *type;
|
const char *type;
|
||||||
|
|
||||||
|
if (lc == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (lc->type) {
|
switch (lc->type) {
|
||||||
case LAYOUT_LEFTRIGHT:
|
case LAYOUT_LEFTRIGHT:
|
||||||
type = "LEFTRIGHT";
|
type = "LEFTRIGHT";
|
||||||
@@ -105,6 +123,9 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
|||||||
case LAYOUT_TOPBOTTOM:
|
case LAYOUT_TOPBOTTOM:
|
||||||
type = "TOPBOTTOM";
|
type = "TOPBOTTOM";
|
||||||
break;
|
break;
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
|
type = "FLOATING";
|
||||||
|
break;
|
||||||
case LAYOUT_WINDOWPANE:
|
case LAYOUT_WINDOWPANE:
|
||||||
type = "WINDOWPANE";
|
type = "WINDOWPANE";
|
||||||
break;
|
break;
|
||||||
@@ -118,6 +139,7 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
|||||||
switch (lc->type) {
|
switch (lc->type) {
|
||||||
case LAYOUT_LEFTRIGHT:
|
case LAYOUT_LEFTRIGHT:
|
||||||
case LAYOUT_TOPBOTTOM:
|
case LAYOUT_TOPBOTTOM:
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||||
layout_print_cell(lcchild, hdr, n + 1);
|
layout_print_cell(lcchild, hdr, n + 1);
|
||||||
break;
|
break;
|
||||||
@@ -153,6 +175,7 @@ layout_search_by_border(struct layout_cell *lc, u_int x, u_int y)
|
|||||||
return (last);
|
return (last);
|
||||||
break;
|
break;
|
||||||
case LAYOUT_WINDOWPANE:
|
case LAYOUT_WINDOWPANE:
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,6 +221,29 @@ layout_make_node(struct layout_cell *lc, enum layout_type type)
|
|||||||
lc->wp = NULL;
|
lc->wp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
layout_fix_zindexes(struct window *w, struct layout_cell *lc)
|
||||||
|
{
|
||||||
|
struct layout_cell *lcchild;
|
||||||
|
|
||||||
|
if (lc == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (lc->type) {
|
||||||
|
case LAYOUT_WINDOWPANE:
|
||||||
|
TAILQ_INSERT_TAIL(&w->z_index, lc->wp, zentry);
|
||||||
|
break;
|
||||||
|
case LAYOUT_LEFTRIGHT:
|
||||||
|
case LAYOUT_TOPBOTTOM:
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
|
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||||
|
layout_fix_zindexes(w, lcchild);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
fatalx("bad layout type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fix cell offsets for a child cell. */
|
/* Fix cell offsets for a child cell. */
|
||||||
static void
|
static void
|
||||||
layout_fix_offsets1(struct layout_cell *lc)
|
layout_fix_offsets1(struct layout_cell *lc)
|
||||||
@@ -208,6 +254,9 @@ layout_fix_offsets1(struct layout_cell *lc)
|
|||||||
if (lc->type == LAYOUT_LEFTRIGHT) {
|
if (lc->type == LAYOUT_LEFTRIGHT) {
|
||||||
xoff = lc->xoff;
|
xoff = lc->xoff;
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
|
if (lcchild->type == LAYOUT_WINDOWPANE &&
|
||||||
|
lcchild->wp->flags & PANE_MINIMISED)
|
||||||
|
continue;
|
||||||
lcchild->xoff = xoff;
|
lcchild->xoff = xoff;
|
||||||
lcchild->yoff = lc->yoff;
|
lcchild->yoff = lc->yoff;
|
||||||
if (lcchild->type != LAYOUT_WINDOWPANE)
|
if (lcchild->type != LAYOUT_WINDOWPANE)
|
||||||
@@ -217,6 +266,8 @@ layout_fix_offsets1(struct layout_cell *lc)
|
|||||||
} else {
|
} else {
|
||||||
yoff = lc->yoff;
|
yoff = lc->yoff;
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||||
|
if (lcchild->wp->flags & PANE_MINIMISED)
|
||||||
|
continue;
|
||||||
lcchild->xoff = lc->xoff;
|
lcchild->xoff = lc->xoff;
|
||||||
lcchild->yoff = yoff;
|
lcchild->yoff = yoff;
|
||||||
if (lcchild->type != LAYOUT_WINDOWPANE)
|
if (lcchild->type != LAYOUT_WINDOWPANE)
|
||||||
@@ -307,7 +358,8 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
|||||||
sx = lc->sx;
|
sx = lc->sx;
|
||||||
sy = lc->sy;
|
sy = lc->sy;
|
||||||
|
|
||||||
if (layout_add_horizontal_border(w, lc, status)) {
|
if (~wp->flags & PANE_FLOATING &&
|
||||||
|
layout_add_horizontal_border(w, lc, status)) {
|
||||||
if (status == PANE_STATUS_TOP)
|
if (status == PANE_STATUS_TOP)
|
||||||
wp->yoff++;
|
wp->yoff++;
|
||||||
sy--;
|
sy--;
|
||||||
@@ -353,6 +405,7 @@ layout_count_cells(struct layout_cell *lc)
|
|||||||
return (1);
|
return (1);
|
||||||
case LAYOUT_LEFTRIGHT:
|
case LAYOUT_LEFTRIGHT:
|
||||||
case LAYOUT_TOPBOTTOM:
|
case LAYOUT_TOPBOTTOM:
|
||||||
|
case LAYOUT_FLOATING:
|
||||||
count = 0;
|
count = 0;
|
||||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||||
count += layout_count_cells(lcchild);
|
count += layout_count_cells(lcchild);
|
||||||
@@ -462,7 +515,7 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy a cell and redistribute the space. */
|
/* Destroy a cell and redistribute the space in tiled cells. */
|
||||||
void
|
void
|
||||||
layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
||||||
struct layout_cell **lcroot)
|
struct layout_cell **lcroot)
|
||||||
@@ -470,13 +523,66 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
|||||||
struct layout_cell *lcother, *lcparent;
|
struct layout_cell *lcother, *lcparent;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If no parent, this is the last pane so window close is imminent and
|
* If no parent, this is either a floating pane or the last
|
||||||
* there is no need to resize anything.
|
* pane so window close is imminent and there is no need to
|
||||||
|
* resize anything.
|
||||||
*/
|
*/
|
||||||
lcparent = lc->parent;
|
lcparent = lc->parent;
|
||||||
if (lcparent == NULL) {
|
if (lcparent == NULL) {
|
||||||
|
if (lc->wp != NULL && ~lc->wp->flags & PANE_FLOATING)
|
||||||
|
*lcroot = NULL;
|
||||||
layout_free_cell(lc);
|
layout_free_cell(lc);
|
||||||
*lcroot = NULL;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In tiled layouts, merge the space into the previous or next cell. */
|
||||||
|
if (lcparent->type != LAYOUT_FLOATING) {
|
||||||
|
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||||
|
lcother = TAILQ_NEXT(lc, entry);
|
||||||
|
else
|
||||||
|
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||||
|
if (lcother != NULL && lcparent->type == LAYOUT_LEFTRIGHT)
|
||||||
|
layout_resize_adjust(w, lcother, lcparent->type, lc->sx + 1);
|
||||||
|
else if (lcother != NULL)
|
||||||
|
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove this from the parent's list. */
|
||||||
|
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||||
|
layout_free_cell(lc);
|
||||||
|
|
||||||
|
if (lcparent->type == LAYOUT_FLOATING)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In tiled layouts, if the parent now has one cell, remove
|
||||||
|
* the parent from the tree and replace it by that cell.
|
||||||
|
*/
|
||||||
|
lc = TAILQ_FIRST(&lcparent->cells);
|
||||||
|
if (lc != NULL && TAILQ_NEXT(lc, entry) == NULL) {
|
||||||
|
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||||
|
|
||||||
|
lc->parent = lcparent->parent;
|
||||||
|
if (lc->parent == NULL) {
|
||||||
|
lc->xoff = 0; lc->yoff = 0;
|
||||||
|
*lcroot = lc;
|
||||||
|
} else
|
||||||
|
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
|
||||||
|
|
||||||
|
layout_free_cell(lcparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Minimise a cell and redistribute the space in tiled cells. */
|
||||||
|
void
|
||||||
|
layout_minimise_cell(struct window *w, struct layout_cell *lc)
|
||||||
|
{
|
||||||
|
struct layout_cell *lcother, *lcparent, *lcchild;
|
||||||
|
u_int space = 0;
|
||||||
|
|
||||||
|
lcparent = lc->parent;
|
||||||
|
if (lcparent == NULL ||
|
||||||
|
lcparent->type == LAYOUT_FLOATING) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,26 +596,44 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
|||||||
else if (lcother != NULL)
|
else if (lcother != NULL)
|
||||||
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1);
|
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1);
|
||||||
|
|
||||||
/* Remove this from the parent's list. */
|
/* If the parent cells are all minimised, minimise it too. */
|
||||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
if (lcparent != NULL) {
|
||||||
layout_free_cell(lc);
|
TAILQ_FOREACH(lcchild, &lcparent->cells, entry) {
|
||||||
|
if (lcchild->wp == NULL ||
|
||||||
|
lcchild->wp->flags & PANE_MINIMISED)
|
||||||
|
continue;
|
||||||
|
if (lcparent->type == LAYOUT_LEFTRIGHT) {
|
||||||
|
space += lcchild->sx;
|
||||||
|
} else if (lcparent->type == LAYOUT_TOPBOTTOM) {
|
||||||
|
space += lcchild->sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (space == 0)
|
||||||
|
layout_minimise_cell(w, lcparent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/* Unminimise a cell and redistribute the space in tiled cells. */
|
||||||
* If the parent now has one cell, remove the parent from the tree and
|
void
|
||||||
* replace it by that cell.
|
layout_unminimise_cell(struct window *w, struct layout_cell *lc)
|
||||||
*/
|
{
|
||||||
lc = TAILQ_FIRST(&lcparent->cells);
|
struct layout_cell *lcother, *lcparent;
|
||||||
if (TAILQ_NEXT(lc, entry) == NULL) {
|
|
||||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
|
||||||
|
|
||||||
lc->parent = lcparent->parent;
|
lcparent = lc->parent;
|
||||||
if (lc->parent == NULL) {
|
if (lcparent == NULL) {
|
||||||
lc->xoff = 0; lc->yoff = 0;
|
return;
|
||||||
*lcroot = lc;
|
}
|
||||||
} else
|
|
||||||
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
|
|
||||||
|
|
||||||
layout_free_cell(lcparent);
|
/* In tiled layouts, merge the space into the previous or next cell. */
|
||||||
|
if (lcparent->type != LAYOUT_FLOATING) {
|
||||||
|
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||||
|
lcother = TAILQ_NEXT(lc, entry);
|
||||||
|
else
|
||||||
|
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||||
|
if (lcother != NULL && lcparent->type == LAYOUT_LEFTRIGHT)
|
||||||
|
layout_resize_adjust(w, lcother, lcparent->type, -(lc->sx + 1));
|
||||||
|
else if (lcother != NULL)
|
||||||
|
layout_resize_adjust(w, lcother, lcparent->type, -(lc->sy + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -741,7 +865,7 @@ layout_resize_pane_shrink(struct window *w, struct layout_cell *lc,
|
|||||||
return (size);
|
return (size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign window pane to newly split cell. */
|
/* Assign window pane to new cell. */
|
||||||
void
|
void
|
||||||
layout_assign_pane(struct layout_cell *lc, struct window_pane *wp,
|
layout_assign_pane(struct layout_cell *lc, struct window_pane *wp,
|
||||||
int do_not_resize)
|
int do_not_resize)
|
||||||
@@ -1085,6 +1209,9 @@ layout_close_pane(struct window_pane *wp)
|
|||||||
{
|
{
|
||||||
struct window *w = wp->window;
|
struct window *w = wp->window;
|
||||||
|
|
||||||
|
if (wp->layout_cell == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Remove the cell. */
|
/* Remove the cell. */
|
||||||
layout_destroy_cell(w, wp->layout_cell, &w->layout_root);
|
layout_destroy_cell(w, wp->layout_cell, &w->layout_root);
|
||||||
|
|
||||||
@@ -1100,9 +1227,8 @@ int
|
|||||||
layout_spread_cell(struct window *w, struct layout_cell *parent)
|
layout_spread_cell(struct window *w, struct layout_cell *parent)
|
||||||
{
|
{
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
struct style *sb_style = &w->active->scrollbar_style;
|
|
||||||
u_int number, each, size, this, remainder;
|
u_int number, each, size, this, remainder;
|
||||||
int change, changed, status, scrollbars;
|
int change, changed, status;
|
||||||
|
|
||||||
number = 0;
|
number = 0;
|
||||||
TAILQ_FOREACH (lc, &parent->cells, entry)
|
TAILQ_FOREACH (lc, &parent->cells, entry)
|
||||||
@@ -1110,14 +1236,9 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
|
|||||||
if (number <= 1)
|
if (number <= 1)
|
||||||
return (0);
|
return (0);
|
||||||
status = options_get_number(w->options, "pane-border-status");
|
status = options_get_number(w->options, "pane-border-status");
|
||||||
scrollbars = options_get_number(w->options, "pane-scrollbars");
|
|
||||||
|
|
||||||
if (parent->type == LAYOUT_LEFTRIGHT) {
|
if (parent->type == LAYOUT_LEFTRIGHT)
|
||||||
if (scrollbars)
|
size = parent->sx;
|
||||||
size = parent->sx - sb_style->width + sb_style->pad;
|
|
||||||
else
|
|
||||||
size = parent->sx;
|
|
||||||
}
|
|
||||||
else if (parent->type == LAYOUT_TOPBOTTOM) {
|
else if (parent->type == LAYOUT_TOPBOTTOM) {
|
||||||
if (layout_add_horizontal_border(w, parent, status))
|
if (layout_add_horizontal_border(w, parent, status))
|
||||||
size = parent->sy - 1;
|
size = parent->sy - 1;
|
||||||
|
|||||||
115
menu.c
115
menu.c
@@ -27,13 +27,18 @@ struct menu_data {
|
|||||||
struct cmdq_item *item;
|
struct cmdq_item *item;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
struct grid_cell style;
|
char *style;
|
||||||
struct grid_cell border_style;
|
char *border_style;
|
||||||
struct grid_cell selected_style;
|
char *selected_style;
|
||||||
|
|
||||||
|
struct grid_cell style_gc;
|
||||||
|
struct grid_cell border_style_gc;
|
||||||
|
struct grid_cell selected_style_gc;
|
||||||
enum box_lines border_lines;
|
enum box_lines border_lines;
|
||||||
|
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
struct screen s;
|
struct screen s;
|
||||||
|
struct visible_ranges r;
|
||||||
|
|
||||||
u_int px;
|
u_int px;
|
||||||
u_int py;
|
u_int py;
|
||||||
@@ -85,6 +90,7 @@ menu_add_item(struct menu *menu, const struct menu_item *item,
|
|||||||
else
|
else
|
||||||
s = format_single(qitem, item->name, c, NULL, NULL, NULL);
|
s = format_single(qitem, item->name, c, NULL, NULL, NULL);
|
||||||
if (*s == '\0') { /* no item if empty after format expanded */
|
if (*s == '\0') { /* no item if empty after format expanded */
|
||||||
|
free(s);
|
||||||
menu->count--;
|
menu->count--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -156,6 +162,9 @@ menu_free(struct menu *menu)
|
|||||||
{
|
{
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
|
if (menu == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = 0; i < menu->count; i++) {
|
for (i = 0; i < menu->count; i++) {
|
||||||
free((void *)menu->items[i].name);
|
free((void *)menu->items[i].name);
|
||||||
free((void *)menu->items[i].command);
|
free((void *)menu->items[i].command);
|
||||||
@@ -181,15 +190,70 @@ menu_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return parts of the input range which are not obstructed by the menu. */
|
/* Return parts of the input range which are not obstructed by the menu. */
|
||||||
void
|
struct visible_ranges *
|
||||||
menu_check_cb(__unused struct client *c, void *data, u_int px, u_int py,
|
menu_check_cb(__unused struct client *c, void *data, u_int px, u_int py,
|
||||||
u_int nx, struct overlay_ranges *r)
|
u_int nx)
|
||||||
{
|
{
|
||||||
struct menu_data *md = data;
|
struct menu_data *md = data;
|
||||||
struct menu *menu = md->menu;
|
struct menu *menu = md->menu;
|
||||||
|
|
||||||
server_client_overlay_range(md->px, md->py, menu->width + 4,
|
server_client_overlay_range(md->px, md->py, menu->width + 4,
|
||||||
menu->count + 2, px, py, nx, r);
|
menu->count + 2, px, py, nx, &md->r);
|
||||||
|
return (&md->r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
menu_reapply_styles(struct menu_data *md, struct client *c)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct options *o;
|
||||||
|
struct format_tree *ft;
|
||||||
|
struct style sytmp;
|
||||||
|
|
||||||
|
if (s == NULL)
|
||||||
|
return;
|
||||||
|
o = s->curw->window->options;
|
||||||
|
|
||||||
|
ft = format_create_defaults(NULL, c, s, s->curw, NULL);
|
||||||
|
|
||||||
|
/* Reapply menu style from options. */
|
||||||
|
memcpy(&md->style_gc, &grid_default_cell, sizeof md->style_gc);
|
||||||
|
style_apply(&md->style_gc, o, "menu-style", ft);
|
||||||
|
if (md->style != NULL) {
|
||||||
|
style_set(&sytmp, &grid_default_cell);
|
||||||
|
if (style_parse(&sytmp, &md->style_gc, md->style) == 0) {
|
||||||
|
md->style_gc.fg = sytmp.gc.fg;
|
||||||
|
md->style_gc.bg = sytmp.gc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reapply selected style from options. */
|
||||||
|
memcpy(&md->selected_style_gc, &grid_default_cell,
|
||||||
|
sizeof md->selected_style_gc);
|
||||||
|
style_apply(&md->selected_style_gc, o, "menu-selected-style", ft);
|
||||||
|
if (md->selected_style != NULL) {
|
||||||
|
style_set(&sytmp, &grid_default_cell);
|
||||||
|
if (style_parse(&sytmp, &md->selected_style_gc,
|
||||||
|
md->selected_style) == 0) {
|
||||||
|
md->selected_style_gc.fg = sytmp.gc.fg;
|
||||||
|
md->selected_style_gc.bg = sytmp.gc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reapply border style from options. */
|
||||||
|
memcpy(&md->border_style_gc, &grid_default_cell,
|
||||||
|
sizeof md->border_style_gc);
|
||||||
|
style_apply(&md->border_style_gc, o, "menu-border-style", ft);
|
||||||
|
if (md->border_style != NULL) {
|
||||||
|
style_set(&sytmp, &grid_default_cell);
|
||||||
|
if (style_parse(&sytmp, &md->border_style_gc,
|
||||||
|
md->border_style) == 0) {
|
||||||
|
md->border_style_gc.fg = sytmp.gc.fg;
|
||||||
|
md->border_style_gc.bg = sytmp.gc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
format_free(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -203,16 +267,18 @@ menu_draw_cb(struct client *c, void *data,
|
|||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
u_int i, px = md->px, py = md->py;
|
u_int i, px = md->px, py = md->py;
|
||||||
|
|
||||||
|
menu_reapply_styles(md, c);
|
||||||
|
|
||||||
screen_write_start(&ctx, s);
|
screen_write_start(&ctx, s);
|
||||||
screen_write_clearscreen(&ctx, 8);
|
screen_write_clearscreen(&ctx, 8);
|
||||||
|
|
||||||
if (md->border_lines != BOX_LINES_NONE) {
|
if (md->border_lines != BOX_LINES_NONE) {
|
||||||
screen_write_box(&ctx, menu->width + 4, menu->count + 2,
|
screen_write_box(&ctx, menu->width + 4, menu->count + 2,
|
||||||
md->border_lines, &md->border_style, menu->title);
|
md->border_lines, &md->border_style_gc, menu->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_write_menu(&ctx, menu, md->choice, md->border_lines,
|
screen_write_menu(&ctx, menu, md->choice, md->border_lines,
|
||||||
&md->style, &md->border_style, &md->selected_style);
|
&md->style_gc, &md->border_style_gc, &md->selected_style_gc);
|
||||||
screen_write_stop(&ctx);
|
screen_write_stop(&ctx);
|
||||||
|
|
||||||
for (i = 0; i < screen_size_y(&md->s); i++) {
|
for (i = 0; i < screen_size_y(&md->s); i++) {
|
||||||
@@ -232,8 +298,13 @@ menu_free_cb(__unused struct client *c, void *data)
|
|||||||
if (md->cb != NULL)
|
if (md->cb != NULL)
|
||||||
md->cb(md->menu, UINT_MAX, KEYC_NONE, md->data);
|
md->cb(md->menu, UINT_MAX, KEYC_NONE, md->data);
|
||||||
|
|
||||||
|
free(md->r.ranges);
|
||||||
screen_free(&md->s);
|
screen_free(&md->s);
|
||||||
|
|
||||||
menu_free(md->menu);
|
menu_free(md->menu);
|
||||||
|
free(md->style);
|
||||||
|
free(md->selected_style);
|
||||||
|
free(md->border_style);
|
||||||
free(md);
|
free(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,24 +541,6 @@ menu_resize_cb(struct client *c, void *data)
|
|||||||
md->py = ny;
|
md->py = ny;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
menu_set_style(struct client *c, struct grid_cell *gc, const char *style,
|
|
||||||
const char *option)
|
|
||||||
{
|
|
||||||
struct style sytmp;
|
|
||||||
struct options *o = c->session->curw->window->options;
|
|
||||||
|
|
||||||
memcpy(gc, &grid_default_cell, sizeof *gc);
|
|
||||||
style_apply(gc, o, option, NULL);
|
|
||||||
if (style != NULL) {
|
|
||||||
style_set(&sytmp, &grid_default_cell);
|
|
||||||
if (style_parse(&sytmp, gc, style) == 0) {
|
|
||||||
gc->fg = sytmp.gc.fg;
|
|
||||||
gc->bg = sytmp.gc.bg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct menu_data *
|
struct menu_data *
|
||||||
menu_prepare(struct menu *menu, int flags, int starting_choice,
|
menu_prepare(struct menu *menu, int flags, int starting_choice,
|
||||||
struct cmdq_item *item, u_int px, u_int py, struct client *c,
|
struct cmdq_item *item, u_int px, u_int py, struct client *c,
|
||||||
@@ -515,10 +568,12 @@ menu_prepare(struct menu *menu, int flags, int starting_choice,
|
|||||||
md->flags = flags;
|
md->flags = flags;
|
||||||
md->border_lines = lines;
|
md->border_lines = lines;
|
||||||
|
|
||||||
menu_set_style(c, &md->style, style, "menu-style");
|
if (style != NULL)
|
||||||
menu_set_style(c, &md->selected_style, selected_style,
|
md->style = xstrdup(style);
|
||||||
"menu-selected-style");
|
if (selected_style != NULL)
|
||||||
menu_set_style(c, &md->border_style, border_style, "menu-border-style");
|
md->selected_style = xstrdup(selected_style);
|
||||||
|
if (border_style != NULL)
|
||||||
|
md->border_style = xstrdup(border_style);
|
||||||
|
|
||||||
if (fs != NULL)
|
if (fs != NULL)
|
||||||
cmd_find_copy_state(&md->fs, fs);
|
cmd_find_copy_state(&md->fs, fs);
|
||||||
|
|||||||
37
mode-tree.c
37
mode-tree.c
@@ -48,9 +48,7 @@ struct mode_tree_data {
|
|||||||
void *modedata;
|
void *modedata;
|
||||||
const struct menu_item *menu;
|
const struct menu_item *menu;
|
||||||
|
|
||||||
const char **sort_list;
|
struct sort_criteria sort_crit;
|
||||||
u_int sort_size;
|
|
||||||
struct mode_tree_sort_criteria sort_crit;
|
|
||||||
|
|
||||||
mode_tree_build_cb buildcb;
|
mode_tree_build_cb buildcb;
|
||||||
mode_tree_draw_cb drawcb;
|
mode_tree_draw_cb drawcb;
|
||||||
@@ -59,6 +57,7 @@ struct mode_tree_data {
|
|||||||
mode_tree_height_cb heightcb;
|
mode_tree_height_cb heightcb;
|
||||||
mode_tree_key_cb keycb;
|
mode_tree_key_cb keycb;
|
||||||
mode_tree_swap_cb swapcb;
|
mode_tree_swap_cb swapcb;
|
||||||
|
mode_tree_sort_cb sortcb;
|
||||||
|
|
||||||
struct mode_tree_list children;
|
struct mode_tree_list children;
|
||||||
struct mode_tree_list saved;
|
struct mode_tree_list saved;
|
||||||
@@ -324,7 +323,7 @@ mode_tree_swap(struct mode_tree_data *mtd, int direction)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (mtd->swapcb(mtd->line_list[mtd->current].item->itemdata,
|
if (mtd->swapcb(mtd->line_list[mtd->current].item->itemdata,
|
||||||
mtd->line_list[swap_with].item->itemdata)) {
|
mtd->line_list[swap_with].item->itemdata, &mtd->sort_crit)) {
|
||||||
mtd->current = swap_with;
|
mtd->current = swap_with;
|
||||||
mode_tree_build(mtd);
|
mode_tree_build(mtd);
|
||||||
}
|
}
|
||||||
@@ -382,7 +381,7 @@ mode_tree_expand(struct mode_tree_data *mtd, uint64_t tag)
|
|||||||
u_int found;
|
u_int found;
|
||||||
|
|
||||||
if (!mode_tree_get_tag(mtd, tag, &found))
|
if (!mode_tree_get_tag(mtd, tag, &found))
|
||||||
return;
|
return;
|
||||||
if (!mtd->line_list[found].item->expanded) {
|
if (!mtd->line_list[found].item->expanded) {
|
||||||
mtd->line_list[found].item->expanded = 1;
|
mtd->line_list[found].item->expanded = 1;
|
||||||
mode_tree_build(mtd);
|
mode_tree_build(mtd);
|
||||||
@@ -454,12 +453,10 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
|||||||
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
|
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
|
||||||
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
|
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
|
||||||
mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
|
mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
|
||||||
mode_tree_swap_cb swapcb, void *modedata, const struct menu_item *menu,
|
mode_tree_swap_cb swapcb, mode_tree_sort_cb sortcb, void *modedata,
|
||||||
const char **sort_list, u_int sort_size, struct screen **s)
|
const struct menu_item *menu, struct screen **s)
|
||||||
{
|
{
|
||||||
struct mode_tree_data *mtd;
|
struct mode_tree_data *mtd;
|
||||||
const char *sort;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
mtd = xcalloc(1, sizeof *mtd);
|
mtd = xcalloc(1, sizeof *mtd);
|
||||||
mtd->references = 1;
|
mtd->references = 1;
|
||||||
@@ -468,9 +465,6 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
|||||||
mtd->modedata = modedata;
|
mtd->modedata = modedata;
|
||||||
mtd->menu = menu;
|
mtd->menu = menu;
|
||||||
|
|
||||||
mtd->sort_list = sort_list;
|
|
||||||
mtd->sort_size = sort_size;
|
|
||||||
|
|
||||||
if (args_has(args, 'N') > 1)
|
if (args_has(args, 'N') > 1)
|
||||||
mtd->preview = MODE_TREE_PREVIEW_BIG;
|
mtd->preview = MODE_TREE_PREVIEW_BIG;
|
||||||
else if (args_has(args, 'N'))
|
else if (args_has(args, 'N'))
|
||||||
@@ -478,13 +472,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
|||||||
else
|
else
|
||||||
mtd->preview = MODE_TREE_PREVIEW_NORMAL;
|
mtd->preview = MODE_TREE_PREVIEW_NORMAL;
|
||||||
|
|
||||||
sort = args_get(args, 'O');
|
mtd->sort_crit.order = sort_order_from_string(args_get(args, 'O'));
|
||||||
if (sort != NULL) {
|
|
||||||
for (i = 0; i < sort_size; i++) {
|
|
||||||
if (strcasecmp(sort, sort_list[i]) == 0)
|
|
||||||
mtd->sort_crit.field = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mtd->sort_crit.reversed = args_has(args, 'r');
|
mtd->sort_crit.reversed = args_has(args, 'r');
|
||||||
|
|
||||||
if (args_has(args, 'f'))
|
if (args_has(args, 'f'))
|
||||||
@@ -499,6 +487,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
|
|||||||
mtd->heightcb = heightcb;
|
mtd->heightcb = heightcb;
|
||||||
mtd->keycb = keycb;
|
mtd->keycb = keycb;
|
||||||
mtd->swapcb = swapcb;
|
mtd->swapcb = swapcb;
|
||||||
|
mtd->sortcb = sortcb;
|
||||||
|
|
||||||
TAILQ_INIT(&mtd->children);
|
TAILQ_INIT(&mtd->children);
|
||||||
|
|
||||||
@@ -566,6 +555,8 @@ mode_tree_build(struct mode_tree_data *mtd)
|
|||||||
TAILQ_CONCAT(&mtd->saved, &mtd->children, entry);
|
TAILQ_CONCAT(&mtd->saved, &mtd->children, entry);
|
||||||
TAILQ_INIT(&mtd->children);
|
TAILQ_INIT(&mtd->children);
|
||||||
|
|
||||||
|
if (mtd->sortcb != NULL)
|
||||||
|
mtd->sortcb(&mtd->sort_crit);
|
||||||
mtd->buildcb(mtd->modedata, &mtd->sort_crit, &tag, mtd->filter);
|
mtd->buildcb(mtd->modedata, &mtd->sort_crit, &tag, mtd->filter);
|
||||||
mtd->no_matches = TAILQ_EMPTY(&mtd->children);
|
mtd->no_matches = TAILQ_EMPTY(&mtd->children);
|
||||||
if (mtd->no_matches)
|
if (mtd->no_matches)
|
||||||
@@ -851,9 +842,9 @@ mode_tree_draw(struct mode_tree_data *mtd)
|
|||||||
screen_write_cursormove(&ctx, 0, h, 0);
|
screen_write_cursormove(&ctx, 0, h, 0);
|
||||||
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
|
screen_write_box(&ctx, w, sy - h, BOX_LINES_DEFAULT, NULL, NULL);
|
||||||
|
|
||||||
if (mtd->sort_list != NULL) {
|
if (mtd->sort_crit.order_seq != NULL) {
|
||||||
xasprintf(&text, " %s (sort: %s%s)", mti->name,
|
xasprintf(&text, " %s (sort: %s%s)", mti->name,
|
||||||
mtd->sort_list[mtd->sort_crit.field],
|
sort_order_to_string(mtd->sort_crit.order),
|
||||||
mtd->sort_crit.reversed ? ", reversed" : "");
|
mtd->sort_crit.reversed ? ", reversed" : "");
|
||||||
} else
|
} else
|
||||||
xasprintf(&text, " %s", mti->name);
|
xasprintf(&text, " %s", mti->name);
|
||||||
@@ -1287,9 +1278,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
mtd->sort_crit.field++;
|
sort_next_order(&mtd->sort_crit);
|
||||||
if (mtd->sort_crit.field >= mtd->sort_size)
|
|
||||||
mtd->sort_crit.field = 0;
|
|
||||||
mode_tree_build(mtd);
|
mode_tree_build(mtd);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
|||||||
@@ -84,6 +84,9 @@ static const char *options_table_popup_border_lines_list[] = {
|
|||||||
static const char *options_table_set_clipboard_list[] = {
|
static const char *options_table_set_clipboard_list[] = {
|
||||||
"off", "external", "on", NULL
|
"off", "external", "on", NULL
|
||||||
};
|
};
|
||||||
|
static const char *options_table_get_clipboard_list[] = {
|
||||||
|
"off", "buffer", "request", "both", NULL
|
||||||
|
};
|
||||||
static const char *options_table_window_size_list[] = {
|
static const char *options_table_window_size_list[] = {
|
||||||
"largest", "smallest", "manual", "latest", NULL
|
"largest", "smallest", "manual", "latest", NULL
|
||||||
};
|
};
|
||||||
@@ -405,6 +408,18 @@ const struct options_table_entry options_table[] = {
|
|||||||
.text = "Whether to send focus events to applications."
|
.text = "Whether to send focus events to applications."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{ .name = "get-clipboard",
|
||||||
|
.type = OPTIONS_TABLE_CHOICE,
|
||||||
|
.scope = OPTIONS_TABLE_SERVER,
|
||||||
|
.choices = options_table_get_clipboard_list,
|
||||||
|
.default_num = 1,
|
||||||
|
.text = "When an application requests the clipboard, whether to "
|
||||||
|
"ignore the request ('off'); respond with the newest buffer "
|
||||||
|
"('buffer'); request the clipboard from the most recently "
|
||||||
|
"used terminal ('request'); or to request the clipboard, "
|
||||||
|
"create a buffer, and send it to the application ('both')."
|
||||||
|
},
|
||||||
|
|
||||||
{ .name = "history-file",
|
{ .name = "history-file",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_STRING,
|
||||||
.scope = OPTIONS_TABLE_SERVER,
|
.scope = OPTIONS_TABLE_SERVER,
|
||||||
@@ -649,6 +664,13 @@ const struct options_table_entry options_table[] = {
|
|||||||
.text = "Time for which status line messages should appear."
|
.text = "Time for which status line messages should appear."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{ .name = "focus-follows-mouse",
|
||||||
|
.type = OPTIONS_TABLE_FLAG,
|
||||||
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
|
.default_num = 0,
|
||||||
|
.text = "Whether moving the mouse into a pane selects it."
|
||||||
|
},
|
||||||
|
|
||||||
{ .name = "history-limit",
|
{ .name = "history-limit",
|
||||||
.type = OPTIONS_TABLE_NUMBER,
|
.type = OPTIONS_TABLE_NUMBER,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
@@ -943,7 +965,7 @@ const struct options_table_entry options_table[] = {
|
|||||||
{ .name = "prompt-cursor-colour",
|
{ .name = "prompt-cursor-colour",
|
||||||
.type = OPTIONS_TABLE_COLOUR,
|
.type = OPTIONS_TABLE_COLOUR,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
.default_num = 6,
|
.default_num = -1,
|
||||||
.text = "Colour of the cursor when in the command prompt."
|
.text = "Colour of the cursor when in the command prompt."
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -955,6 +977,15 @@ const struct options_table_entry options_table[] = {
|
|||||||
.text = "Style of the cursor when in the command prompt."
|
.text = "Style of the cursor when in the command prompt."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{ .name = "prompt-command-cursor-style",
|
||||||
|
.type = OPTIONS_TABLE_CHOICE,
|
||||||
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
|
.choices = options_table_cursor_style_list,
|
||||||
|
.default_num = 0,
|
||||||
|
.text = "Style of the cursor in the command prompt when in command "
|
||||||
|
"mode, if 'status-keys' is set to 'vi'."
|
||||||
|
},
|
||||||
|
|
||||||
{ .name = "session-status-current-style",
|
{ .name = "session-status-current-style",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_STRING,
|
||||||
.scope = OPTIONS_TABLE_WINDOW,
|
.scope = OPTIONS_TABLE_WINDOW,
|
||||||
|
|||||||
10
options.c
10
options.c
@@ -749,7 +749,7 @@ options_get_number(struct options *oo, const char *name)
|
|||||||
return (o->value.number);
|
return (o->value.number);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct cmd_list *
|
struct cmd_list *
|
||||||
options_get_command(struct options *oo, const char *name)
|
options_get_command(struct options *oo, const char *name)
|
||||||
{
|
{
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
@@ -1226,6 +1226,10 @@ options_push_changes(const char *name)
|
|||||||
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
|
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
|
||||||
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
|
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
|
||||||
}
|
}
|
||||||
|
if (*name == '@') {
|
||||||
|
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
|
||||||
|
wp->flags |= PANE_STYLECHANGED;
|
||||||
|
}
|
||||||
if (strcmp(name, "pane-colours") == 0) {
|
if (strcmp(name, "pane-colours") == 0) {
|
||||||
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
|
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
|
||||||
colour_palette_from_option(&wp->palette, wp->options);
|
colour_palette_from_option(&wp->palette, wp->options);
|
||||||
@@ -1248,6 +1252,10 @@ options_push_changes(const char *name)
|
|||||||
utf8_update_width_cache();
|
utf8_update_width_cache();
|
||||||
if (strcmp(name, "input-buffer-size") == 0)
|
if (strcmp(name, "input-buffer-size") == 0)
|
||||||
input_set_buffer_size(options_get_number(global_options, name));
|
input_set_buffer_size(options_get_number(global_options, name));
|
||||||
|
if (strcmp(name, "history-limit") == 0) {
|
||||||
|
RB_FOREACH(s, sessions, &sessions)
|
||||||
|
session_update_history(s);
|
||||||
|
}
|
||||||
RB_FOREACH(s, sessions, &sessions)
|
RB_FOREACH(s, sessions, &sessions)
|
||||||
status_update_cache(s);
|
status_update_cache(s);
|
||||||
|
|
||||||
|
|||||||
17
paste.c
17
paste.c
@@ -29,19 +29,6 @@
|
|||||||
* string!
|
* string!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct paste_buffer {
|
|
||||||
char *data;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
char *name;
|
|
||||||
time_t created;
|
|
||||||
int automatic;
|
|
||||||
u_int order;
|
|
||||||
|
|
||||||
RB_ENTRY(paste_buffer) name_entry;
|
|
||||||
RB_ENTRY(paste_buffer) time_entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
static u_int paste_next_index;
|
static u_int paste_next_index;
|
||||||
static u_int paste_next_order;
|
static u_int paste_next_order;
|
||||||
static u_int paste_num_automatic;
|
static u_int paste_num_automatic;
|
||||||
@@ -119,7 +106,7 @@ paste_is_empty(void)
|
|||||||
|
|
||||||
/* Get the most recent automatic buffer. */
|
/* Get the most recent automatic buffer. */
|
||||||
struct paste_buffer *
|
struct paste_buffer *
|
||||||
paste_get_top(const char **name)
|
paste_get_top(char **name)
|
||||||
{
|
{
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
|
|
||||||
@@ -129,7 +116,7 @@ paste_get_top(const char **name)
|
|||||||
if (pb == NULL)
|
if (pb == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
*name = pb->name;
|
*name = xstrdup(pb->name);
|
||||||
return (pb);
|
return (pb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
132
popup.c
132
popup.c
@@ -32,6 +32,8 @@ struct popup_data {
|
|||||||
int flags;
|
int flags;
|
||||||
char *title;
|
char *title;
|
||||||
|
|
||||||
|
char *style;
|
||||||
|
char *border_style;
|
||||||
struct grid_cell border_cell;
|
struct grid_cell border_cell;
|
||||||
enum box_lines border_lines;
|
enum box_lines border_lines;
|
||||||
|
|
||||||
@@ -39,6 +41,9 @@ struct popup_data {
|
|||||||
struct grid_cell defaults;
|
struct grid_cell defaults;
|
||||||
struct colour_palette palette;
|
struct colour_palette palette;
|
||||||
|
|
||||||
|
struct visible_ranges r;
|
||||||
|
struct visible_ranges or[2];
|
||||||
|
|
||||||
struct job *job;
|
struct job *job;
|
||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
int status;
|
int status;
|
||||||
@@ -98,6 +103,49 @@ static const struct menu_item popup_internal_menu_items[] = {
|
|||||||
{ NULL, KEYC_NONE, NULL }
|
{ NULL, KEYC_NONE, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
popup_reapply_styles(struct popup_data *pd)
|
||||||
|
{
|
||||||
|
struct client *c = pd->c;
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct options *o;
|
||||||
|
struct format_tree *ft;
|
||||||
|
struct style sytmp;
|
||||||
|
|
||||||
|
if (s == NULL)
|
||||||
|
return;
|
||||||
|
o = s->curw->window->options;
|
||||||
|
|
||||||
|
ft = format_create_defaults(NULL, c, s, s->curw, NULL);
|
||||||
|
|
||||||
|
/* Reapply popup style from options. */
|
||||||
|
memcpy(&pd->defaults, &grid_default_cell, sizeof pd->defaults);
|
||||||
|
style_apply(&pd->defaults, o, "popup-style", ft);
|
||||||
|
if (pd->style != NULL) {
|
||||||
|
style_set(&sytmp, &grid_default_cell);
|
||||||
|
if (style_parse(&sytmp, &pd->defaults, pd->style) == 0) {
|
||||||
|
pd->defaults.fg = sytmp.gc.fg;
|
||||||
|
pd->defaults.bg = sytmp.gc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pd->defaults.attr = 0;
|
||||||
|
|
||||||
|
/* Reapply border style from options. */
|
||||||
|
memcpy(&pd->border_cell, &grid_default_cell, sizeof pd->border_cell);
|
||||||
|
style_apply(&pd->border_cell, o, "popup-border-style", ft);
|
||||||
|
if (pd->border_style != NULL) {
|
||||||
|
style_set(&sytmp, &grid_default_cell);
|
||||||
|
if (style_parse(&sytmp, &pd->border_cell,
|
||||||
|
pd->border_style) == 0) {
|
||||||
|
pd->border_cell.fg = sytmp.gc.fg;
|
||||||
|
pd->border_cell.bg = sytmp.gc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pd->border_cell.attr = 0;
|
||||||
|
|
||||||
|
format_free(ft);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
popup_redraw_cb(const struct tty_ctx *ttyctx)
|
popup_redraw_cb(const struct tty_ctx *ttyctx)
|
||||||
{
|
{
|
||||||
@@ -164,48 +212,57 @@ popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return parts of the input range which are not obstructed by the popup. */
|
/* Return parts of the input range which are not obstructed by the popup. */
|
||||||
static void
|
static struct visible_ranges *
|
||||||
popup_check_cb(struct client* c, void *data, u_int px, u_int py, u_int nx,
|
popup_check_cb(struct client* c, void *data, u_int px, u_int py, u_int nx)
|
||||||
struct overlay_ranges *r)
|
|
||||||
{
|
{
|
||||||
struct popup_data *pd = data;
|
struct popup_data *pd = data;
|
||||||
struct overlay_ranges or[2];
|
struct visible_ranges *r = &pd->r;
|
||||||
|
struct visible_ranges *mr;
|
||||||
u_int i, j, k = 0;
|
u_int i, j, k = 0;
|
||||||
|
|
||||||
if (pd->md != NULL) {
|
if (pd->md != NULL) {
|
||||||
/* Check each returned range for the menu against the popup. */
|
/*
|
||||||
menu_check_cb(c, pd->md, px, py, nx, r);
|
* Work out the visible ranges for the menu (that is, the
|
||||||
for (i = 0; i < 2; i++) {
|
* ranges not covered by the menu). A menu should have at most
|
||||||
|
* two ranges and we rely on this being the case.
|
||||||
|
*/
|
||||||
|
mr = menu_check_cb(c, pd->md, px, py, nx);
|
||||||
|
if (mr->used > 2)
|
||||||
|
fatalx("too many menu ranges");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the ranges still visible under the menu and check if
|
||||||
|
* each is visible under the popup as well. At most there can be
|
||||||
|
* three total ranges if popup and menu do not intersect.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < mr->used; i++) {
|
||||||
server_client_overlay_range(pd->px, pd->py, pd->sx,
|
server_client_overlay_range(pd->px, pd->py, pd->sx,
|
||||||
pd->sy, r->px[i], py, r->nx[i], &or[i]);
|
pd->sy, r->ranges[i].px, py, r->ranges[i].nx,
|
||||||
|
&pd->or[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* or has up to OVERLAY_MAX_RANGES non-overlapping ranges,
|
* We now have nonoverlapping ranges from left to right.
|
||||||
* ordered from left to right. Collect them in the output.
|
* Combine them together into the output.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < 2; i++) {
|
server_client_ensure_ranges(r, 3);
|
||||||
/* Each or[i] only has 2 ranges. */
|
for (i = 0; i < mr->used; i++) {
|
||||||
for (j = 0; j < 2; j++) {
|
for (j = 0; j < pd->or[i].used; j++) {
|
||||||
if (or[i].nx[j] > 0) {
|
if (pd->or[i].ranges[j].nx == 0)
|
||||||
r->px[k] = or[i].px[j];
|
continue;
|
||||||
r->nx[k] = or[i].nx[j];
|
if (k >= 3)
|
||||||
k++;
|
fatalx("too many popup & menu ranges");
|
||||||
}
|
r->ranges[k].px = pd->or[i].ranges[j].px;
|
||||||
|
r->ranges[k].nx = pd->or[i].ranges[j].nx;
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return (r);
|
||||||
/* Zero remaining ranges if any. */
|
|
||||||
for (i = k; i < OVERLAY_MAX_RANGES; i++) {
|
|
||||||
r->px[i] = 0;
|
|
||||||
r->nx[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server_client_overlay_range(pd->px, pd->py, pd->sx, pd->sy, px, py, nx,
|
server_client_overlay_range(pd->px, pd->py, pd->sx, pd->sy, px, py, nx,
|
||||||
r);
|
r);
|
||||||
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -219,6 +276,8 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
|
|||||||
struct colour_palette *palette = &pd->palette;
|
struct colour_palette *palette = &pd->palette;
|
||||||
struct grid_cell defaults;
|
struct grid_cell defaults;
|
||||||
|
|
||||||
|
popup_reapply_styles(pd);
|
||||||
|
|
||||||
screen_init(&s, pd->sx, pd->sy, 0);
|
screen_init(&s, pd->sx, pd->sy, 0);
|
||||||
screen_write_start(&ctx, &s);
|
screen_write_start(&ctx, &s);
|
||||||
screen_write_clearscreen(&ctx, 8);
|
screen_write_clearscreen(&ctx, 8);
|
||||||
@@ -286,10 +345,15 @@ popup_free_cb(struct client *c, void *data)
|
|||||||
job_free(pd->job);
|
job_free(pd->job);
|
||||||
input_free(pd->ictx);
|
input_free(pd->ictx);
|
||||||
|
|
||||||
|
free(pd->or[0].ranges);
|
||||||
|
free(pd->or[1].ranges);
|
||||||
|
free(pd->r.ranges);
|
||||||
screen_free(&pd->s);
|
screen_free(&pd->s);
|
||||||
colour_palette_free(&pd->palette);
|
colour_palette_free(&pd->palette);
|
||||||
|
|
||||||
free(pd->title);
|
free(pd->title);
|
||||||
|
free(pd->style);
|
||||||
|
free(pd->border_style);
|
||||||
free(pd);
|
free(pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,7 +613,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
|
|||||||
(event->key == '\033' || event->key == ('c'|KEYC_CTRL)))
|
(event->key == '\033' || event->key == ('c'|KEYC_CTRL)))
|
||||||
return (1);
|
return (1);
|
||||||
if (pd->job == NULL && (pd->flags & POPUP_CLOSEANYKEY) &&
|
if (pd->job == NULL && (pd->flags & POPUP_CLOSEANYKEY) &&
|
||||||
!KEYC_IS_MOUSE(event->key) && !KEYC_IS_PASTE(event->key))
|
!KEYC_IS_MOUSE(event->key) && !KEYC_IS_PASTE(event->key))
|
||||||
return (1);
|
return (1);
|
||||||
if (pd->job != NULL) {
|
if (pd->job != NULL) {
|
||||||
if (KEYC_IS_MOUSE(event->key)) {
|
if (KEYC_IS_MOUSE(event->key)) {
|
||||||
@@ -658,6 +722,8 @@ popup_modify(struct client *c, const char *title, const char *style,
|
|||||||
pd->title = xstrdup(title);
|
pd->title = xstrdup(title);
|
||||||
}
|
}
|
||||||
if (border_style != NULL) {
|
if (border_style != NULL) {
|
||||||
|
free(pd->border_style);
|
||||||
|
pd->border_style = xstrdup(border_style);
|
||||||
style_set(&sytmp, &pd->border_cell);
|
style_set(&sytmp, &pd->border_cell);
|
||||||
if (style_parse(&sytmp, &pd->border_cell, border_style) == 0) {
|
if (style_parse(&sytmp, &pd->border_cell, border_style) == 0) {
|
||||||
pd->border_cell.fg = sytmp.gc.fg;
|
pd->border_cell.fg = sytmp.gc.fg;
|
||||||
@@ -665,6 +731,8 @@ popup_modify(struct client *c, const char *title, const char *style,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (style != NULL) {
|
if (style != NULL) {
|
||||||
|
free(pd->style);
|
||||||
|
pd->style = xstrdup(style);
|
||||||
style_set(&sytmp, &pd->defaults);
|
style_set(&sytmp, &pd->defaults);
|
||||||
if (style_parse(&sytmp, &pd->defaults, style) == 0) {
|
if (style_parse(&sytmp, &pd->defaults, style) == 0) {
|
||||||
pd->defaults.fg = sytmp.gc.fg;
|
pd->defaults.fg = sytmp.gc.fg;
|
||||||
@@ -675,7 +743,8 @@ popup_modify(struct client *c, const char *title, const char *style,
|
|||||||
if (lines == BOX_LINES_NONE && pd->border_lines != lines) {
|
if (lines == BOX_LINES_NONE && pd->border_lines != lines) {
|
||||||
screen_resize(&pd->s, pd->sx, pd->sy, 1);
|
screen_resize(&pd->s, pd->sx, pd->sy, 1);
|
||||||
job_resize(pd->job, pd->sx, pd->sy);
|
job_resize(pd->job, pd->sx, pd->sy);
|
||||||
} else if (pd->border_lines == BOX_LINES_NONE && pd->border_lines != lines) {
|
} else if (pd->border_lines == BOX_LINES_NONE &&
|
||||||
|
pd->border_lines != lines) {
|
||||||
screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 1);
|
screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 1);
|
||||||
job_resize(pd->job, pd->sx - 2, pd->sy - 2);
|
job_resize(pd->job, pd->sx - 2, pd->sy - 2);
|
||||||
}
|
}
|
||||||
@@ -725,8 +794,13 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
|
|||||||
pd = xcalloc(1, sizeof *pd);
|
pd = xcalloc(1, sizeof *pd);
|
||||||
pd->item = item;
|
pd->item = item;
|
||||||
pd->flags = flags;
|
pd->flags = flags;
|
||||||
|
|
||||||
if (title != NULL)
|
if (title != NULL)
|
||||||
pd->title = xstrdup(title);
|
pd->title = xstrdup(title);
|
||||||
|
if (style != NULL)
|
||||||
|
pd->style = xstrdup(style);
|
||||||
|
if (border_style != NULL)
|
||||||
|
pd->border_style = xstrdup(border_style);
|
||||||
|
|
||||||
pd->c = c;
|
pd->c = c;
|
||||||
pd->c->references++;
|
pd->c->references++;
|
||||||
@@ -776,7 +850,7 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
|
|||||||
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
|
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
|
||||||
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
|
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
|
||||||
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
|
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
|
||||||
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette);
|
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette, c);
|
||||||
|
|
||||||
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
|
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
|
||||||
popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd);
|
popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd);
|
||||||
|
|||||||
52
regress/border-arrows.sh
Normal file
52
regress/border-arrows.sh
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Test for GitHub issue #4780 - pane-border-indicators both arrows missing
|
||||||
|
# on second pane in a two-pane horizontal split.
|
||||||
|
#
|
||||||
|
# When pane-border-indicators is set to "both", arrow indicators should
|
||||||
|
# appear when EITHER pane is selected. Before the fix, arrows only appeared
|
||||||
|
# when the LEFT pane was selected.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
TMUX_OUTER="$TEST_TMUX -Ltest2"
|
||||||
|
$TMUX_OUTER kill-server 2>/dev/null
|
||||||
|
|
||||||
|
trap "$TMUX kill-server 2>/dev/null; $TMUX_OUTER kill-server 2>/dev/null" 0 1 15
|
||||||
|
|
||||||
|
# Start outer tmux that will capture the inner tmux's rendering
|
||||||
|
$TMUX_OUTER -f/dev/null new -d -x80 -y24 "$TMUX -f/dev/null new -x78 -y22" || exit 1
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Set pane-border-indicators to "both" in inner tmux
|
||||||
|
$TMUX set -g pane-border-indicators both || exit 1
|
||||||
|
|
||||||
|
# Create horizontal split (two panes side by side)
|
||||||
|
$TMUX splitw -h || exit 1
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Helper to check for arrow characters in captured output
|
||||||
|
has_arrow() {
|
||||||
|
echo "$1" | grep -qE '(←|→|↑|↓)'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test 1: Select left pane (pane 0) and check for arrows
|
||||||
|
$TMUX selectp -t 0
|
||||||
|
sleep 1
|
||||||
|
left_output=$($TMUX_OUTER capturep -Cep 2>/dev/null)
|
||||||
|
has_arrow "$left_output" || exit 1
|
||||||
|
|
||||||
|
# Test 2: Select right pane (pane 1) and check for arrows
|
||||||
|
# This is the case that failed before the fix
|
||||||
|
$TMUX selectp -t 1
|
||||||
|
sleep 1
|
||||||
|
right_output=$($TMUX_OUTER capturep -Cep 2>/dev/null)
|
||||||
|
has_arrow "$right_output" || exit 1
|
||||||
|
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
$TMUX_OUTER kill-server 2>/dev/null
|
||||||
|
exit 0
|
||||||
82
regress/decrqm-sync.sh
Normal file
82
regress/decrqm-sync.sh
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Test DECRPM response for mode 2026 (synchronized output).
|
||||||
|
#
|
||||||
|
# DECRQM (ESC[?2026$p) should elicit DECRPM (ESC[?2026;Ps$y) where
|
||||||
|
# Ps=1 when MODE_SYNC is active, Ps=2 when reset.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
TMP2=$(mktemp)
|
||||||
|
trap "rm -f $TMP $TMP2; $TMUX kill-server 2>/dev/null" 0 1 15
|
||||||
|
|
||||||
|
$TMUX -f/dev/null new -d -x80 -y24 || exit 1
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Keep the session alive regardless of pane exits.
|
||||||
|
$TMUX set -g remain-on-exit on
|
||||||
|
|
||||||
|
exit_status=0
|
||||||
|
|
||||||
|
# query_decrpm <outfile> [setup_seq]
|
||||||
|
# Spawn a pane that optionally sends setup_seq, then sends DECRQM for
|
||||||
|
# mode 2026 and captures the response into outfile in cat -v form.
|
||||||
|
query_decrpm () {
|
||||||
|
_outfile=$1
|
||||||
|
_setup=$2
|
||||||
|
|
||||||
|
$TMUX respawnw -k -t:0 -- sh -c "
|
||||||
|
exec 2>/dev/null
|
||||||
|
stty raw -echo
|
||||||
|
${_setup:+printf '$_setup'; sleep 0.2}
|
||||||
|
printf '\033[?2026\$p'
|
||||||
|
dd bs=1 count=11 2>/dev/null | cat -v > $_outfile
|
||||||
|
sleep 0.2
|
||||||
|
" || exit 1
|
||||||
|
sleep 2
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Test 1: mode 2026 should be reset by default (Ps=2)
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
query_decrpm "$TMP"
|
||||||
|
|
||||||
|
actual=$(cat "$TMP")
|
||||||
|
expected='^[[?2026;2$y'
|
||||||
|
|
||||||
|
if [ "$actual" = "$expected" ]; then
|
||||||
|
if [ -n "$VERBOSE" ]; then
|
||||||
|
echo "[PASS] DECRQM 2026 (default/reset) -> $actual"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "[FAIL] DECRQM 2026 (default/reset): expected '$expected', got '$actual'"
|
||||||
|
exit_status=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Test 2: set mode 2026 (SM ?2026), then query (expect Ps=1)
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
query_decrpm "$TMP2" '\033[?2026h'
|
||||||
|
|
||||||
|
actual=$(cat "$TMP2")
|
||||||
|
expected='^[[?2026;1$y'
|
||||||
|
|
||||||
|
if [ "$actual" = "$expected" ]; then
|
||||||
|
if [ -n "$VERBOSE" ]; then
|
||||||
|
echo "[PASS] DECRQM 2026 (set) -> $actual"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "[FAIL] DECRQM 2026 (set): expected '$expected', got '$actual'"
|
||||||
|
exit_status=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
exit $exit_status
|
||||||
70
regress/session-group-resize.sh
Executable file
70
regress/session-group-resize.sh
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Test that window-size=latest resizes windows correctly when switching
|
||||||
|
# windows in session groups. When a client switches to a window, it should
|
||||||
|
# resize immediately to match that client's size.
|
||||||
|
#
|
||||||
|
# Tests both switch-client and select-window, which use different code paths.
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP1=$(mktemp)
|
||||||
|
TMP2=$(mktemp)
|
||||||
|
TMP3=$(mktemp)
|
||||||
|
trap "rm -f $TMP1 $TMP2 $TMP3" 0 1 15
|
||||||
|
|
||||||
|
# Create a session with two windows, staying on window 0.
|
||||||
|
$TMUX -f/dev/null new -d -s test -x 20 -y 6 || exit 1
|
||||||
|
$TMUX neww -t test || exit 1
|
||||||
|
$TMUX selectw -t test:0 || exit 1
|
||||||
|
|
||||||
|
# Attach a small 20x6 client in control-mode and have it select window 1. This makes
|
||||||
|
# the small client the "latest" for window 1. The sleep keeps stdin open so the
|
||||||
|
# control client stays attached.
|
||||||
|
(echo "refresh-client -C 20,6"; echo "selectw -t :1"; sleep 5) |
|
||||||
|
$TMUX -f/dev/null -C attach -t test >$TMP1 2>&1 &
|
||||||
|
|
||||||
|
# Wait for small client to be on window 1.
|
||||||
|
n=0
|
||||||
|
while [ $n -lt 20 ]; do
|
||||||
|
$TMUX lsc -F '#{client_name} #{window_index}' 2>/dev/null | grep -q " 1$" && break
|
||||||
|
sleep 0.1
|
||||||
|
n=$((n + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create a grouped session with a larger 30x10 client, also in control mode. It
|
||||||
|
# starts on window 0 (inherited), then switches to window 1 with
|
||||||
|
# `switch-client`.
|
||||||
|
(echo "refresh-client -C 30,10"; echo "switch-client -t :=1"; sleep 5) |
|
||||||
|
$TMUX -f/dev/null -C new -t test -x 30 -y 10 >$TMP2 2>&1 &
|
||||||
|
|
||||||
|
# Wait briefly for the switch-client command to execute, then check.
|
||||||
|
# The resize should happen immediately (within 0.2s).
|
||||||
|
sleep 0.2
|
||||||
|
OUT1=$($TMUX display -t test:1 -p '#{window_width}x#{window_height}' 2>/dev/null)
|
||||||
|
|
||||||
|
# Also test selectw (select-window) which uses a different code path.
|
||||||
|
# Create a third grouped session with a 25x8 client, switch to window 1
|
||||||
|
# using selectw instead of switch-client.
|
||||||
|
(echo "refresh-client -C 25,8"; echo "selectw -t :1"; sleep 5) |
|
||||||
|
$TMUX -f/dev/null -C new -t test -x 25 -y 8 >$TMP3 2>&1 &
|
||||||
|
|
||||||
|
sleep 0.2
|
||||||
|
OUT2=$($TMUX display -t test:1 -p '#{window_width}x#{window_height}' 2>/dev/null)
|
||||||
|
|
||||||
|
# Clean up - kill server (terminates clients). Don't wait for background
|
||||||
|
# sleeps; they'll be orphaned but harmless.
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
# Window 1 should have resized to 30x10 (the second client's size).
|
||||||
|
[ "$OUT1" = "30x10" ] || { echo "switch-client resize failed: $OUT1"; exit 1; }
|
||||||
|
|
||||||
|
# Window 1 should have resized to 25x8 (the third client's size).
|
||||||
|
[ "$OUT2" = "25x8" ] || { echo "selectw resize failed: $OUT2"; exit 1; }
|
||||||
|
|
||||||
|
exit 0
|
||||||
4
resize.c
4
resize.c
@@ -127,7 +127,7 @@ clients_calculate_size(int type, int current, struct client *c,
|
|||||||
if (type == WINDOW_SIZE_LARGEST) {
|
if (type == WINDOW_SIZE_LARGEST) {
|
||||||
*sx = 0;
|
*sx = 0;
|
||||||
*sy = 0;
|
*sy = 0;
|
||||||
} else if (type == WINDOW_SIZE_MANUAL) {
|
} else if (w != NULL && type == WINDOW_SIZE_MANUAL) {
|
||||||
*sx = w->manual_sx;
|
*sx = w->manual_sx;
|
||||||
*sy = w->manual_sy;
|
*sy = w->manual_sy;
|
||||||
log_debug("%s: manual size %ux%u", __func__, *sx, *sy);
|
log_debug("%s: manual size %ux%u", __func__, *sx, *sy);
|
||||||
@@ -250,7 +250,7 @@ skip:
|
|||||||
/* Return whether a suitable size was found. */
|
/* Return whether a suitable size was found. */
|
||||||
if (type == WINDOW_SIZE_MANUAL) {
|
if (type == WINDOW_SIZE_MANUAL) {
|
||||||
log_debug("%s: type is manual", __func__);
|
log_debug("%s: type is manual", __func__);
|
||||||
return (1);
|
return (w != NULL);
|
||||||
}
|
}
|
||||||
if (type == WINDOW_SIZE_LARGEST) {
|
if (type == WINDOW_SIZE_LARGEST) {
|
||||||
log_debug("%s: type is largest", __func__);
|
log_debug("%s: type is largest", __func__);
|
||||||
|
|||||||
865
screen-redraw.c
865
screen-redraw.c
File diff suppressed because it is too large
Load Diff
561
screen-write.c
561
screen-write.c
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
static struct screen_write_citem *screen_write_collect_trim(
|
static struct screen_write_citem *screen_write_collect_trim(
|
||||||
struct screen_write_ctx *, u_int, u_int, u_int, int *);
|
struct screen_write_ctx *, u_int, u_int, u_int, int *);
|
||||||
|
static void screen_write_collect_insert(struct screen_write_ctx *,
|
||||||
|
struct screen_write_citem *);
|
||||||
static void screen_write_collect_clear(struct screen_write_ctx *, u_int,
|
static void screen_write_collect_clear(struct screen_write_ctx *, u_int,
|
||||||
u_int);
|
u_int);
|
||||||
static void screen_write_collect_scroll(struct screen_write_ctx *, u_int);
|
static void screen_write_collect_scroll(struct screen_write_ctx *, u_int);
|
||||||
@@ -34,6 +36,7 @@ static int screen_write_overwrite(struct screen_write_ctx *,
|
|||||||
struct grid_cell *, u_int);
|
struct grid_cell *, u_int);
|
||||||
static int screen_write_combine(struct screen_write_ctx *,
|
static int screen_write_combine(struct screen_write_ctx *,
|
||||||
const struct grid_cell *);
|
const struct grid_cell *);
|
||||||
|
static int screen_write_pane_obscured(struct window_pane *);
|
||||||
|
|
||||||
struct screen_write_citem {
|
struct screen_write_citem {
|
||||||
u_int x;
|
u_int x;
|
||||||
@@ -61,9 +64,9 @@ screen_write_get_citem(void)
|
|||||||
|
|
||||||
ci = TAILQ_FIRST(&screen_write_citem_freelist);
|
ci = TAILQ_FIRST(&screen_write_citem_freelist);
|
||||||
if (ci != NULL) {
|
if (ci != NULL) {
|
||||||
TAILQ_REMOVE(&screen_write_citem_freelist, ci, entry);
|
TAILQ_REMOVE(&screen_write_citem_freelist, ci, entry);
|
||||||
memset(ci, 0, sizeof *ci);
|
memset(ci, 0, sizeof *ci);
|
||||||
return (ci);
|
return (ci);
|
||||||
}
|
}
|
||||||
return (xcalloc(1, sizeof *ci));
|
return (xcalloc(1, sizeof *ci));
|
||||||
}
|
}
|
||||||
@@ -71,7 +74,7 @@ screen_write_get_citem(void)
|
|||||||
static void
|
static void
|
||||||
screen_write_free_citem(struct screen_write_citem *ci)
|
screen_write_free_citem(struct screen_write_citem *ci)
|
||||||
{
|
{
|
||||||
TAILQ_INSERT_TAIL(&screen_write_citem_freelist, ci, entry);
|
TAILQ_INSERT_TAIL(&screen_write_citem_freelist, ci, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -572,6 +575,8 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
|||||||
struct grid *gd = src->grid;
|
struct grid *gd = src->grid;
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
u_int xx, yy, cx = s->cx, cy = s->cy;
|
u_int xx, yy, cx = s->cx, cy = s->cy;
|
||||||
|
int yoff = 0;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
|
||||||
if (nx == 0 || ny == 0)
|
if (nx == 0 || ny == 0)
|
||||||
return;
|
return;
|
||||||
@@ -580,17 +585,24 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
|||||||
if (yy >= gd->hsize + gd->sy)
|
if (yy >= gd->hsize + gd->sy)
|
||||||
break;
|
break;
|
||||||
s->cx = cx;
|
s->cx = cx;
|
||||||
if (wp != NULL)
|
screen_write_initctx(ctx, &ttyctx, 0);
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
if (wp != NULL) {
|
||||||
|
yoff = wp->yoff;
|
||||||
|
}
|
||||||
|
r = screen_redraw_get_visible_ranges(wp, px, s->cy + yoff, nx,
|
||||||
|
NULL);
|
||||||
for (xx = px; xx < px + nx; xx++) {
|
for (xx = px; xx < px + nx; xx++) {
|
||||||
if (xx >= grid_get_line(gd, yy)->cellsize &&
|
if (xx >= grid_get_line(gd, yy)->cellsize &&
|
||||||
s->cx >= grid_get_line(ctx->s->grid, s->cy)->cellsize)
|
s->cx >= grid_get_line(ctx->s->grid,
|
||||||
|
s->cy)->cellsize)
|
||||||
break;
|
break;
|
||||||
grid_get_cell(gd, xx, yy, &gc);
|
grid_get_cell(gd, xx, yy, &gc);
|
||||||
if (xx + gc.data.width > px + nx)
|
if (xx + gc.data.width > px + nx)
|
||||||
break;
|
break;
|
||||||
grid_view_set_cell(ctx->s->grid, s->cx, s->cy, &gc);
|
grid_view_set_cell(ctx->s->grid, s->cx, s->cy, &gc);
|
||||||
if (wp != NULL) {
|
if (wp != NULL) {
|
||||||
|
if (! screen_redraw_is_visible(r, px))
|
||||||
|
break;
|
||||||
ttyctx.cell = &gc;
|
ttyctx.cell = &gc;
|
||||||
tty_write(tty_cmd_cell, &ttyctx);
|
tty_write(tty_cmd_cell, &ttyctx);
|
||||||
ttyctx.ocx++;
|
ttyctx.ocx++;
|
||||||
@@ -894,6 +906,52 @@ screen_write_mode_clear(struct screen_write_ctx *ctx, int mode)
|
|||||||
log_debug("%s: %s", __func__, screen_mode_to_string(mode));
|
log_debug("%s: %s", __func__, screen_mode_to_string(mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sync timeout callback. */
|
||||||
|
static void
|
||||||
|
screen_write_sync_callback(__unused int fd, __unused short events, void *arg)
|
||||||
|
{
|
||||||
|
struct window_pane *wp = arg;
|
||||||
|
|
||||||
|
log_debug("%s: %%%u sync timer expired", __func__, wp->id);
|
||||||
|
evtimer_del(&wp->sync_timer);
|
||||||
|
|
||||||
|
if (wp->base.mode & MODE_SYNC) {
|
||||||
|
wp->base.mode &= ~MODE_SYNC;
|
||||||
|
wp->flags |= PANE_REDRAW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start sync mode. */
|
||||||
|
void
|
||||||
|
screen_write_start_sync(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
|
||||||
|
|
||||||
|
if (wp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wp->base.mode |= MODE_SYNC;
|
||||||
|
if (!event_initialized(&wp->sync_timer))
|
||||||
|
evtimer_set(&wp->sync_timer, screen_write_sync_callback, wp);
|
||||||
|
evtimer_add(&wp->sync_timer, &tv);
|
||||||
|
|
||||||
|
log_debug("%s: %%%u started sync mode", __func__, wp->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop sync mode. */
|
||||||
|
void
|
||||||
|
screen_write_stop_sync(struct window_pane *wp)
|
||||||
|
{
|
||||||
|
if (wp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (event_initialized(&wp->sync_timer))
|
||||||
|
evtimer_del(&wp->sync_timer);
|
||||||
|
wp->base.mode &= ~MODE_SYNC;
|
||||||
|
|
||||||
|
log_debug("%s: %%%u stopped sync mode", __func__, wp->id);
|
||||||
|
}
|
||||||
|
|
||||||
/* Cursor up by ny. */
|
/* Cursor up by ny. */
|
||||||
void
|
void
|
||||||
screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
|
screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
|
||||||
@@ -1288,7 +1346,7 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct grid_line *gl;
|
struct grid_line *gl;
|
||||||
u_int sx = screen_size_x(s);
|
u_int sx = screen_size_x(s);
|
||||||
struct screen_write_citem *ci = ctx->item, *before;
|
struct screen_write_citem *ci = ctx->item;
|
||||||
|
|
||||||
if (s->cx == 0) {
|
if (s->cx == 0) {
|
||||||
screen_write_clearline(ctx, bg);
|
screen_write_clearline(ctx, bg);
|
||||||
@@ -1306,16 +1364,11 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
|
|
||||||
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
|
grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg);
|
||||||
|
|
||||||
before = screen_write_collect_trim(ctx, s->cy, s->cx, sx - s->cx, NULL);
|
|
||||||
ci->x = s->cx;
|
ci->x = s->cx;
|
||||||
ci->used = sx - s->cx;
|
ci->used = sx - s->cx;
|
||||||
ci->type = CLEAR;
|
ci->type = CLEAR;
|
||||||
ci->bg = bg;
|
ci->bg = bg;
|
||||||
if (before == NULL)
|
screen_write_collect_insert(ctx, ci);
|
||||||
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
|
|
||||||
else
|
|
||||||
TAILQ_INSERT_BEFORE(before, ci, entry);
|
|
||||||
ctx->item = screen_write_get_citem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear to start of line from cursor. */
|
/* Clear to start of line from cursor. */
|
||||||
@@ -1324,7 +1377,7 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
u_int sx = screen_size_x(s);
|
u_int sx = screen_size_x(s);
|
||||||
struct screen_write_citem *ci = ctx->item, *before;
|
struct screen_write_citem *ci = ctx->item;
|
||||||
|
|
||||||
if (s->cx >= sx - 1) {
|
if (s->cx >= sx - 1) {
|
||||||
screen_write_clearline(ctx, bg);
|
screen_write_clearline(ctx, bg);
|
||||||
@@ -1341,16 +1394,28 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
else
|
else
|
||||||
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
|
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
|
||||||
|
|
||||||
before = screen_write_collect_trim(ctx, s->cy, 0, s->cx + 1, NULL);
|
|
||||||
ci->x = 0;
|
ci->x = 0;
|
||||||
ci->used = s->cx + 1;
|
ci->used = s->cx + 1;
|
||||||
ci->type = CLEAR;
|
ci->type = CLEAR;
|
||||||
ci->bg = bg;
|
ci->bg = bg;
|
||||||
if (before == NULL)
|
screen_write_collect_insert(ctx, ci);
|
||||||
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->cy].items, ci, entry);
|
}
|
||||||
else
|
|
||||||
TAILQ_INSERT_BEFORE(before, ci, entry);
|
/* Clear part of a line from px for nx columns. */
|
||||||
ctx->item = screen_write_get_citem();
|
static void
|
||||||
|
screen_write_clearpartofline(struct screen_write_ctx *ctx, u_int px, u_int nx,
|
||||||
|
u_int bg)
|
||||||
|
{
|
||||||
|
struct screen_write_citem *ci = ctx->item;
|
||||||
|
|
||||||
|
if (nx == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ci->x = px;
|
||||||
|
ci->used = nx;
|
||||||
|
ci->type = CLEAR;
|
||||||
|
ci->bg = bg;
|
||||||
|
screen_write_collect_insert(ctx, ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move cursor to px,py. */
|
/* Move cursor to px,py. */
|
||||||
@@ -1535,10 +1600,13 @@ screen_write_carriagereturn(struct screen_write_ctx *ctx)
|
|||||||
void
|
void
|
||||||
screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
|
screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||||
|
u_int y, i, xoff, yoff, cx_save, cy_save;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
if (image_check_line(s, s->cy, sy - s->cy) && ctx->wp != NULL)
|
if (image_check_line(s, s->cy, sy - s->cy) && ctx->wp != NULL)
|
||||||
@@ -1563,16 +1631,64 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
|
|
||||||
screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1));
|
screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1));
|
||||||
screen_write_collect_flush(ctx, 0, __func__);
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
tty_write(tty_cmd_clearendofscreen, &ttyctx);
|
|
||||||
|
if (! screen_write_pane_obscured(ctx->wp)) {
|
||||||
|
tty_write(tty_cmd_clearendofscreen, &ttyctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can't just clear screen, must avoid floating windows. */
|
||||||
|
cx_save = s->cx;
|
||||||
|
cy_save = s->cy;
|
||||||
|
if (ctx->wp != NULL) {
|
||||||
|
xoff = ctx->wp->xoff;
|
||||||
|
yoff = ctx->wp->yoff;
|
||||||
|
} else {
|
||||||
|
xoff = 0;
|
||||||
|
yoff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First line: visible ranges from the current cursor to end. */
|
||||||
|
if (s->cx <= sx - 1) {
|
||||||
|
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||||
|
xoff + s->cx, yoff + s->cy, sx - s->cx, NULL);
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0)
|
||||||
|
continue;
|
||||||
|
screen_write_clearpartofline(ctx,
|
||||||
|
ri->px - xoff, ri->nx, bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remaining lines: visible ranges across the full width. */
|
||||||
|
for (y = s->cy + 1; y < sy; y++) {
|
||||||
|
screen_write_set_cursor(ctx, 0, y);
|
||||||
|
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||||
|
xoff, yoff + y, sx, NULL);
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0)
|
||||||
|
continue;
|
||||||
|
screen_write_clearpartofline(ctx,
|
||||||
|
ri->px - xoff, ri->nx, bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
|
screen_write_set_cursor(ctx, cx_save, cy_save);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear to start of screen. */
|
/* Clear to start of screen. */
|
||||||
void
|
void
|
||||||
screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
|
screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx = screen_size_x(s);
|
u_int sx = screen_size_x(s);
|
||||||
|
u_int y, i, xoff, yoff, cx_save, cy_save;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
if (image_check_line(s, 0, s->cy - 1) && ctx->wp != NULL)
|
if (image_check_line(s, 0, s->cy - 1) && ctx->wp != NULL)
|
||||||
@@ -1591,16 +1707,62 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
|
|
||||||
screen_write_collect_clear(ctx, 0, s->cy);
|
screen_write_collect_clear(ctx, 0, s->cy);
|
||||||
screen_write_collect_flush(ctx, 0, __func__);
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
tty_write(tty_cmd_clearstartofscreen, &ttyctx);
|
|
||||||
|
if (! screen_write_pane_obscured(ctx->wp)) {
|
||||||
|
tty_write(tty_cmd_clearstartofscreen, &ttyctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can't just clear screen, must avoid floating windows. */
|
||||||
|
cx_save = s->cx;
|
||||||
|
cy_save = s->cy;
|
||||||
|
if (ctx->wp != NULL) {
|
||||||
|
xoff = ctx->wp->xoff;
|
||||||
|
yoff = ctx->wp->yoff;
|
||||||
|
} else {
|
||||||
|
xoff = 0;
|
||||||
|
yoff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lines 0 to cy-1: visible ranges across the full width. */
|
||||||
|
for (y = 0; y < s->cy; y++) {
|
||||||
|
screen_write_set_cursor(ctx, 0, y);
|
||||||
|
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||||
|
xoff, yoff + y, sx, NULL);
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0)
|
||||||
|
continue;
|
||||||
|
screen_write_clearpartofline(ctx,
|
||||||
|
ri->px - xoff, ri->nx, bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last line: visible ranges from 0 to cursor (inclusive). */
|
||||||
|
screen_write_set_cursor(ctx, 0, s->cy);
|
||||||
|
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||||
|
xoff, yoff + cy_save, s->cx + 1, NULL);
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0)
|
||||||
|
continue;
|
||||||
|
screen_write_clearpartofline(ctx, ri->px - xoff, ri->nx, bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
|
screen_write_set_cursor(ctx, cx_save, cy_save);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear entire screen. */
|
/* Clear entire screen. */
|
||||||
void
|
void
|
||||||
screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
|
screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||||
|
u_int y, i, xoff, yoff, cx_save, cy_save;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
if (image_free_all(s) && ctx->wp != NULL)
|
if (image_free_all(s) && ctx->wp != NULL)
|
||||||
@@ -1619,7 +1781,38 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
grid_view_clear(s->grid, 0, 0, sx, sy, bg);
|
grid_view_clear(s->grid, 0, 0, sx, sy, bg);
|
||||||
|
|
||||||
screen_write_collect_clear(ctx, 0, sy);
|
screen_write_collect_clear(ctx, 0, sy);
|
||||||
tty_write(tty_cmd_clearscreen, &ttyctx);
|
|
||||||
|
if (! screen_write_pane_obscured(ctx->wp)) {
|
||||||
|
tty_write(tty_cmd_clearscreen, &ttyctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can't just clear screen, must avoid floating windows. */
|
||||||
|
cx_save = s->cx;
|
||||||
|
cy_save = s->cy;
|
||||||
|
if (ctx->wp != NULL) {
|
||||||
|
xoff = ctx->wp->xoff;
|
||||||
|
yoff = ctx->wp->yoff;
|
||||||
|
} else {
|
||||||
|
xoff = 0;
|
||||||
|
yoff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (y = 0; y < sy; y++) {
|
||||||
|
screen_write_set_cursor(ctx, 0, y);
|
||||||
|
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||||
|
xoff, yoff + y, sx, NULL);
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0)
|
||||||
|
continue;
|
||||||
|
screen_write_clearpartofline(ctx,
|
||||||
|
ri->px - xoff, ri->nx, bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
|
screen_write_set_cursor(ctx, cx_save, cy_save);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear entire history. */
|
/* Clear entire history. */
|
||||||
@@ -1771,6 +1964,39 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->rlower].items, ci, entry);
|
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->rlower].items, ci, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if there is a floating window pane overlapping this pane. */
|
||||||
|
static int
|
||||||
|
screen_write_pane_obscured(struct window_pane *base_wp)
|
||||||
|
{
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct window *w;
|
||||||
|
int found_self = 0;
|
||||||
|
|
||||||
|
if (base_wp == NULL)
|
||||||
|
return(0);
|
||||||
|
w = base_wp->window;
|
||||||
|
|
||||||
|
/* Check if there is a floating pane. xxxx borders? scrollbars? */
|
||||||
|
TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry) {
|
||||||
|
if (wp == base_wp) {
|
||||||
|
found_self = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (found_self && wp->flags & PANE_FLOATING &&
|
||||||
|
! (wp->flags & PANE_MINIMISED) &&
|
||||||
|
((wp->yoff >= base_wp->yoff &&
|
||||||
|
wp->yoff <= base_wp->yoff + (int)base_wp->sy) ||
|
||||||
|
(wp->yoff + (int)wp->sy >= base_wp->yoff &&
|
||||||
|
wp->yoff + wp->sy <= base_wp->yoff + base_wp->sy)) &&
|
||||||
|
((wp->xoff >= base_wp->xoff &&
|
||||||
|
wp->xoff <= base_wp->xoff + (int)base_wp->sx) ||
|
||||||
|
(wp->xoff + (int)wp->sx >= base_wp->xoff &&
|
||||||
|
wp->xoff + wp->sx <= base_wp->xoff + base_wp->sx)))
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Flush collected lines. */
|
/* Flush collected lines. */
|
||||||
static void
|
static void
|
||||||
screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||||
@@ -1779,8 +2005,25 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct screen_write_citem *ci, *tmp;
|
struct screen_write_citem *ci, *tmp;
|
||||||
struct screen_write_cline *cl;
|
struct screen_write_cline *cl;
|
||||||
u_int y, cx, cy, last, items = 0;
|
u_int y, cx, cy, last, items = 0, i;
|
||||||
|
u_int wr_start, wr_end, wr_length, wsx, wsy;
|
||||||
|
int r_start, r_end, ci_start, ci_end;
|
||||||
|
int xoff, yoff;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
struct window_pane *wp = ctx->wp;
|
||||||
|
|
||||||
|
if (s->mode & MODE_SYNC) {
|
||||||
|
for (y = 0; y < screen_size_y(s); y++) {
|
||||||
|
cl = &ctx->s->write_list[y];
|
||||||
|
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
|
||||||
|
TAILQ_REMOVE(&cl->items, ci, entry);
|
||||||
|
screen_write_free_citem(ci);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->scrolled != 0) {
|
if (ctx->scrolled != 0) {
|
||||||
log_debug("%s: scrolled %u (region %u-%u)", __func__,
|
log_debug("%s: scrolled %u (region %u-%u)", __func__,
|
||||||
@@ -1789,11 +2032,14 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
ctx->scrolled = s->rlower - s->rupper + 1;
|
ctx->scrolled = s->rlower - s->rupper + 1;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 1);
|
screen_write_initctx(ctx, &ttyctx, 1);
|
||||||
|
if (wp != NULL && wp->yoff + wp->sy > wp->window->sy)
|
||||||
|
ttyctx.orlower -= (wp->yoff + wp->sy - wp->window->sy);
|
||||||
ttyctx.num = ctx->scrolled;
|
ttyctx.num = ctx->scrolled;
|
||||||
ttyctx.bg = ctx->bg;
|
ttyctx.bg = ctx->bg;
|
||||||
|
ttyctx.obscured = screen_write_pane_obscured(wp);
|
||||||
tty_write(tty_cmd_scrollup, &ttyctx);
|
tty_write(tty_cmd_scrollup, &ttyctx);
|
||||||
|
|
||||||
if (ctx->wp != NULL)
|
if (wp != NULL)
|
||||||
ctx->wp->flags |= PANE_REDRAWSCROLLBAR;
|
ctx->wp->flags |= PANE_REDRAWSCROLLBAR;
|
||||||
}
|
}
|
||||||
ctx->scrolled = 0;
|
ctx->scrolled = 0;
|
||||||
@@ -1803,63 +2049,126 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
cx = s->cx; cy = s->cy;
|
cx = s->cx; cy = s->cy;
|
||||||
|
|
||||||
|
/* The xoff and width of window pane relative to the window we
|
||||||
|
* are writing to relative to the visible_ranges array. */
|
||||||
|
if (wp != NULL) {
|
||||||
|
wsx = wp->window->sx;
|
||||||
|
wsy = wp->window->sy;
|
||||||
|
xoff = wp->xoff;
|
||||||
|
yoff = wp->yoff;
|
||||||
|
} else {
|
||||||
|
wsx = screen_size_x(s);
|
||||||
|
wsy = screen_size_y(s);
|
||||||
|
xoff = 0;
|
||||||
|
yoff = 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (y = 0; y < screen_size_y(s); y++) {
|
for (y = 0; y < screen_size_y(s); y++) {
|
||||||
|
if (y + yoff >= wsy)
|
||||||
|
continue;
|
||||||
cl = &ctx->s->write_list[y];
|
cl = &ctx->s->write_list[y];
|
||||||
|
|
||||||
|
r = screen_redraw_get_visible_ranges(wp, 0, y + yoff, wsx,
|
||||||
|
NULL);
|
||||||
|
|
||||||
last = UINT_MAX;
|
last = UINT_MAX;
|
||||||
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
|
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
|
||||||
|
log_debug("collect list: x=%u (last %u), y=%u, used=%u",
|
||||||
|
ci->x, last, y, ci->used);
|
||||||
if (last != UINT_MAX && ci->x <= last) {
|
if (last != UINT_MAX && ci->x <= last) {
|
||||||
fatalx("collect list not in order: %u <= %u",
|
fatalx("collect list not in order: %u <= %u",
|
||||||
ci->x, last);
|
ci->x, last);
|
||||||
}
|
}
|
||||||
screen_write_set_cursor(ctx, ci->x, y);
|
wr_length = 0;
|
||||||
if (ci->type == CLEAR) {
|
for (i = 0; i < r->used; i++) {
|
||||||
screen_write_initctx(ctx, &ttyctx, 1);
|
ri = &r->ranges[i];
|
||||||
ttyctx.bg = ci->bg;
|
if (ri->nx == 0) continue;
|
||||||
ttyctx.num = ci->used;
|
r_start = ri->px;
|
||||||
tty_write(tty_cmd_clearcharacter, &ttyctx);
|
r_end = ri->px + ri->nx;
|
||||||
} else {
|
ci_start = ci->x;
|
||||||
screen_write_initctx(ctx, &ttyctx, 0);
|
ci_end = ci->x + ci->used;
|
||||||
ttyctx.cell = &ci->gc;
|
|
||||||
ttyctx.wrapped = ci->wrapped;
|
|
||||||
ttyctx.ptr = cl->data + ci->x;
|
|
||||||
ttyctx.num = ci->used;
|
|
||||||
tty_write(tty_cmd_cells, &ttyctx);
|
|
||||||
}
|
|
||||||
items++;
|
|
||||||
|
|
||||||
TAILQ_REMOVE(&cl->items, ci, entry);
|
if (ci_start + xoff > r_end ||
|
||||||
screen_write_free_citem(ci);
|
ci_end + xoff < r_start)
|
||||||
last = ci->x;
|
continue;
|
||||||
|
|
||||||
|
if (r_start > ci_start + xoff)
|
||||||
|
wr_start = ci_start +
|
||||||
|
(r_start - (ci_start + xoff));
|
||||||
|
else
|
||||||
|
wr_start = ci_start;
|
||||||
|
if (ci_end + xoff > r_end)
|
||||||
|
wr_end = ci_end -
|
||||||
|
((ci_end + xoff) - r_end);
|
||||||
|
else
|
||||||
|
wr_end = ci_end;
|
||||||
|
wr_length = wr_end - wr_start;
|
||||||
|
|
||||||
|
if (wr_length <= 0)
|
||||||
|
continue;
|
||||||
|
screen_write_set_cursor(ctx, wr_start, y);
|
||||||
|
if (ci->type == CLEAR) {
|
||||||
|
screen_write_initctx(ctx, &ttyctx, 1);
|
||||||
|
ttyctx.bg = ci->bg;
|
||||||
|
ttyctx.num = wr_length;
|
||||||
|
tty_write(tty_cmd_clearcharacter,
|
||||||
|
&ttyctx);
|
||||||
|
} else {
|
||||||
|
screen_write_initctx(ctx, &ttyctx, 0);
|
||||||
|
ttyctx.cell = &ci->gc;
|
||||||
|
ttyctx.wrapped = ci->wrapped;
|
||||||
|
ttyctx.ptr = cl->data + wr_start;
|
||||||
|
ttyctx.num = wr_length;
|
||||||
|
tty_write(tty_cmd_cells, &ttyctx);
|
||||||
|
}
|
||||||
|
items++;
|
||||||
|
|
||||||
|
TAILQ_REMOVE(&cl->items, ci, entry);
|
||||||
|
screen_write_free_citem(ci);
|
||||||
|
last = ci->x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s->cx = cx; s->cy = cy;
|
s->cx = cx; s->cy = cy;
|
||||||
|
|
||||||
log_debug("%s: flushed %u items (%s)", __func__, items, from);
|
log_debug("%s: flushed %u items (%s)", __func__, items, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Insert an item on current line. */
|
||||||
|
void
|
||||||
|
screen_write_collect_insert(struct screen_write_ctx *ctx,
|
||||||
|
struct screen_write_citem *ci)
|
||||||
|
{
|
||||||
|
struct screen *s = ctx->s;
|
||||||
|
struct screen_write_cline *cl = &s->write_list[s->cy];
|
||||||
|
struct screen_write_citem *before;
|
||||||
|
|
||||||
|
before = screen_write_collect_trim(ctx, s->cy, ci->x, ci->used,
|
||||||
|
&ci->wrapped);
|
||||||
|
if (before == NULL)
|
||||||
|
TAILQ_INSERT_TAIL(&cl->items, ci, entry);
|
||||||
|
else
|
||||||
|
TAILQ_INSERT_BEFORE(before, ci, entry);
|
||||||
|
ctx->item = screen_write_get_citem();
|
||||||
|
}
|
||||||
|
|
||||||
/* Finish and store collected cells. */
|
/* Finish and store collected cells. */
|
||||||
void
|
void
|
||||||
screen_write_collect_end(struct screen_write_ctx *ctx)
|
screen_write_collect_end(struct screen_write_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct screen_write_citem *ci = ctx->item, *before;
|
struct screen_write_citem *ci = ctx->item, *bci = NULL, *aci;
|
||||||
struct screen_write_cline *cl = &s->write_list[s->cy];
|
struct screen_write_cline *cl = &s->write_list[s->cy];
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
u_int xx;
|
u_int xx;
|
||||||
int wrapped = ci->wrapped;
|
|
||||||
|
|
||||||
if (ci->used == 0)
|
if (ci->used == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
before = screen_write_collect_trim(ctx, s->cy, s->cx, ci->used,
|
|
||||||
&wrapped);
|
|
||||||
ci->x = s->cx;
|
ci->x = s->cx;
|
||||||
ci->wrapped = wrapped;
|
screen_write_collect_insert(ctx, ci);
|
||||||
if (before == NULL)
|
|
||||||
TAILQ_INSERT_TAIL(&cl->items, ci, entry);
|
|
||||||
else
|
|
||||||
TAILQ_INSERT_BEFORE(before, ci, entry);
|
|
||||||
ctx->item = screen_write_get_citem();
|
|
||||||
|
|
||||||
log_debug("%s: %u %.*s (at %u,%u)", __func__, ci->used,
|
log_debug("%s: %u %.*s (at %u,%u)", __func__, ci->used,
|
||||||
(int)ci->used, cl->data + ci->x, s->cx, s->cy);
|
(int)ci->used, cl->data + ci->x, s->cx, s->cy);
|
||||||
@@ -1871,15 +2180,29 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
|||||||
break;
|
break;
|
||||||
grid_view_set_cell(s->grid, xx, s->cy,
|
grid_view_set_cell(s->grid, xx, s->cy,
|
||||||
&grid_default_cell);
|
&grid_default_cell);
|
||||||
|
log_debug("%s: padding erased (before) at %u (cx %u)",
|
||||||
|
__func__, xx, s->cx);
|
||||||
}
|
}
|
||||||
if (xx != s->cx) {
|
if (xx != s->cx) {
|
||||||
if (xx == 0)
|
if (xx == 0)
|
||||||
grid_view_get_cell(s->grid, 0, s->cy, &gc);
|
grid_view_get_cell(s->grid, 0, s->cy, &gc);
|
||||||
if (gc.data.width > 1) {
|
if (gc.data.width > 1 ||
|
||||||
|
(gc.flags & GRID_FLAG_PADDING)) {
|
||||||
grid_view_set_cell(s->grid, xx, s->cy,
|
grid_view_set_cell(s->grid, xx, s->cy,
|
||||||
&grid_default_cell);
|
&grid_default_cell);
|
||||||
|
log_debug("%s: padding erased (before) at %u "
|
||||||
|
"(cx %u)", __func__, xx, s->cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (xx != s->cx) {
|
||||||
|
bci = ctx->item;
|
||||||
|
bci->type = CLEAR;
|
||||||
|
bci->x = xx;
|
||||||
|
bci->bg = 8;
|
||||||
|
bci->used = s->cx - xx;
|
||||||
|
log_debug("%s: padding erased (before): from %u, "
|
||||||
|
"size %u", __func__, bci->x, bci->used);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
@@ -1889,6 +2212,8 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
|||||||
|
|
||||||
grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, cl->data + ci->x,
|
grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, cl->data + ci->x,
|
||||||
ci->used);
|
ci->used);
|
||||||
|
if (bci != NULL)
|
||||||
|
screen_write_collect_insert(ctx, bci);
|
||||||
screen_write_set_cursor(ctx, s->cx + ci->used, -1);
|
screen_write_set_cursor(ctx, s->cx + ci->used, -1);
|
||||||
|
|
||||||
for (xx = s->cx; xx < screen_size_x(s); xx++) {
|
for (xx = s->cx; xx < screen_size_x(s); xx++) {
|
||||||
@@ -1896,6 +2221,18 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
|||||||
if (~gc.flags & GRID_FLAG_PADDING)
|
if (~gc.flags & GRID_FLAG_PADDING)
|
||||||
break;
|
break;
|
||||||
grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
|
grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
|
||||||
|
log_debug("%s: padding erased (after) at %u (cx %u)",
|
||||||
|
__func__, xx, s->cx);
|
||||||
|
}
|
||||||
|
if (xx != s->cx) {
|
||||||
|
aci = ctx->item;
|
||||||
|
aci->type = CLEAR;
|
||||||
|
aci->x = s->cx;
|
||||||
|
aci->bg = 8;
|
||||||
|
aci->used = xx - s->cx;
|
||||||
|
log_debug("%s: padding erased (after): from %u, size %u",
|
||||||
|
__func__, aci->x, aci->used);
|
||||||
|
screen_write_collect_insert(ctx, aci);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1958,6 +2295,7 @@ void
|
|||||||
screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
|
struct window_pane *wp = ctx->wp;
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
const struct utf8_data *ud = &gc->data;
|
const struct utf8_data *ud = &gc->data;
|
||||||
struct grid_line *gl;
|
struct grid_line *gl;
|
||||||
@@ -1965,8 +2303,10 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
struct grid_cell tmp_gc, now_gc;
|
struct grid_cell tmp_gc, now_gc;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||||
u_int width = ud->width, xx, not_wrap;
|
u_int width = ud->width, xx, not_wrap, i, n, vis;
|
||||||
int selected, skip = 1;
|
int selected, skip = 1, redraw = 0, yoff = 0;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
|
||||||
/* Ignore padding cells. */
|
/* Ignore padding cells. */
|
||||||
if (gc->flags & GRID_FLAG_PADDING)
|
if (gc->flags & GRID_FLAG_PADDING)
|
||||||
@@ -2008,8 +2348,10 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||||
if (gl->flags & GRID_LINE_EXTENDED) {
|
if (gl->flags & GRID_LINE_EXTENDED) {
|
||||||
grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
|
grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
|
||||||
if (screen_write_overwrite(ctx, &now_gc, width))
|
if (screen_write_overwrite(ctx, &now_gc, width)) {
|
||||||
|
redraw = 1;
|
||||||
skip = 0;
|
skip = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2062,6 +2404,11 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
if (selected)
|
if (selected)
|
||||||
skip = 0;
|
skip = 0;
|
||||||
|
|
||||||
|
if (wp != NULL)
|
||||||
|
yoff = wp->yoff;
|
||||||
|
r = screen_redraw_get_visible_ranges(wp, s->cx, s->cy + yoff, width,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move the cursor. If not wrapping, stick at the last character and
|
* Move the cursor. If not wrapping, stick at the last character and
|
||||||
* replace it.
|
* replace it.
|
||||||
@@ -2080,13 +2427,33 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write to the screen. */
|
/* Write to the screen. */
|
||||||
if (!skip) {
|
if (!skip && !(s->mode & MODE_SYNC)) {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
screen_select_cell(s, &tmp_gc, gc);
|
screen_select_cell(s, &tmp_gc, gc);
|
||||||
ttyctx.cell = &tmp_gc;
|
|
||||||
} else
|
} else
|
||||||
ttyctx.cell = gc;
|
memcpy(&tmp_gc, gc, sizeof tmp_gc);
|
||||||
tty_write(tty_cmd_cell, &ttyctx);
|
ttyctx.cell = &tmp_gc;
|
||||||
|
ttyctx.num = redraw ? 2 : 0;
|
||||||
|
for (i=0, vis=0; i < r->used; i++) vis += r->ranges[i].nx;
|
||||||
|
if (vis < width) {
|
||||||
|
/* Wide character or tab partly obscured. Write
|
||||||
|
* spaces one by one in unobscured region(s).
|
||||||
|
*/
|
||||||
|
*tmp_gc.data.data = ' ';
|
||||||
|
tmp_gc.data.width = tmp_gc.data.size =
|
||||||
|
tmp_gc.data.have = 1;
|
||||||
|
for (i=0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0) continue;
|
||||||
|
for (n = 0; n < ri->nx; n++) {
|
||||||
|
screen_write_set_cursor(ctx, ri->px + n,
|
||||||
|
-1);
|
||||||
|
tty_write(tty_cmd_cell, &ttyctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tty_write(tty_cmd_cell, &ttyctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2095,12 +2462,14 @@ static int
|
|||||||
screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
|
struct window_pane *wp = ctx->wp;
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
const struct utf8_data *ud = &gc->data;
|
const struct utf8_data *ud = &gc->data;
|
||||||
u_int n, cx = s->cx, cy = s->cy;
|
u_int i, n, cx = s->cx, cy = s->cy, vis, yoff = 0;
|
||||||
struct grid_cell last;
|
struct grid_cell last;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
int force_wide = 0, zero_width = 0;
|
int force_wide = 0, zero_width = 0;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
|
||||||
/* Ignore U+3164 HANGUL_FILLER entirely. */
|
/* Ignore U+3164 HANGUL_FILLER entirely. */
|
||||||
if (utf8_is_hangul_filler(ud))
|
if (utf8_is_hangul_filler(ud))
|
||||||
@@ -2152,6 +2521,8 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
case HANGULJAMO_STATE_NOT_HANGULJAMO:
|
case HANGULJAMO_STATE_NOT_HANGULJAMO:
|
||||||
if (utf8_should_combine(&last.data, ud))
|
if (utf8_should_combine(&last.data, ud))
|
||||||
force_wide = 1;
|
force_wide = 1;
|
||||||
|
else if (utf8_should_combine(ud, &last.data))
|
||||||
|
force_wide = 1;
|
||||||
else if (!utf8_has_zwj(&last.data))
|
else if (!utf8_has_zwj(&last.data))
|
||||||
return (0);
|
return (0);
|
||||||
break;
|
break;
|
||||||
@@ -2186,6 +2557,23 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
|||||||
if (force_wide)
|
if (force_wide)
|
||||||
grid_view_set_padding(gd, cx - 1, cy);
|
grid_view_set_padding(gd, cx - 1, cy);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if all of this character is visible. No character will
|
||||||
|
* be obscured in the middle, only on left or right, but there
|
||||||
|
* could be an empty range in the visible ranges so we add them all up.
|
||||||
|
*/
|
||||||
|
if (wp != NULL)
|
||||||
|
yoff = wp->yoff;
|
||||||
|
r = screen_redraw_get_visible_ranges(wp, cx - n, cy + yoff, n, NULL);
|
||||||
|
for (i=0, vis=0; i < r->used; i++) vis += r->ranges[i].nx;
|
||||||
|
if (vis < n) {
|
||||||
|
/*
|
||||||
|
* Part of this character is obscured. Return 1
|
||||||
|
* and let screen_write_cell write a space.
|
||||||
|
*/
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Redraw the combined cell. If forcing the cell to width 2, reset the
|
* Redraw the combined cell. If forcing the cell to width 2, reset the
|
||||||
* cached cursor position in the tty, since we don't really know
|
* cached cursor position in the tty, since we don't really know
|
||||||
@@ -2276,14 +2664,14 @@ screen_write_overwrite(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
|||||||
|
|
||||||
/* Set external clipboard. */
|
/* Set external clipboard. */
|
||||||
void
|
void
|
||||||
screen_write_setselection(struct screen_write_ctx *ctx, const char *flags,
|
screen_write_setselection(struct screen_write_ctx *ctx, const char *clip,
|
||||||
u_char *str, u_int len)
|
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, 0);
|
||||||
ttyctx.ptr = str;
|
ttyctx.ptr = str;
|
||||||
ttyctx.ptr2 = (void *)flags;
|
ttyctx.ptr2 = (void *)clip;
|
||||||
ttyctx.num = len;
|
ttyctx.num = len;
|
||||||
|
|
||||||
tty_write(tty_cmd_setselection, &ttyctx);
|
tty_write(tty_cmd_setselection, &ttyctx);
|
||||||
@@ -2316,8 +2704,11 @@ screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si,
|
|||||||
u_int x, y, sx, sy, cx = s->cx, cy = s->cy, i, lines;
|
u_int x, y, sx, sy, cx = s->cx, cy = s->cy, i, lines;
|
||||||
struct sixel_image *new;
|
struct sixel_image *new;
|
||||||
|
|
||||||
|
if (screen_size_y(s) == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
sixel_size_in_cells(si, &x, &y);
|
sixel_size_in_cells(si, &x, &y);
|
||||||
if (x > screen_size_x(s) || y > screen_size_y(s)) {
|
if (x > screen_size_x(s) || y > screen_size_y(s) - 1) {
|
||||||
if (x > screen_size_x(s) - cx)
|
if (x > screen_size_x(s) - cx)
|
||||||
sx = screen_size_x(s) - cx;
|
sx = screen_size_x(s) - cx;
|
||||||
else
|
else
|
||||||
@@ -2328,16 +2719,14 @@ screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si,
|
|||||||
sy = y;
|
sy = y;
|
||||||
new = sixel_scale(si, 0, 0, 0, y - sy, sx, sy, 1);
|
new = sixel_scale(si, 0, 0, 0, y - sy, sx, sy, 1);
|
||||||
sixel_free(si);
|
sixel_free(si);
|
||||||
si = new;
|
if (new == NULL)
|
||||||
|
|
||||||
/* Bail out if the image cannot be scaled. */
|
|
||||||
if (si == NULL)
|
|
||||||
return;
|
return;
|
||||||
sixel_size_in_cells(si, &x, &y);
|
sixel_size_in_cells(new, &x, &y);
|
||||||
|
si = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
sy = screen_size_y(s) - cy;
|
sy = screen_size_y(s) - cy;
|
||||||
if (sy < y) {
|
if (sy <= y) {
|
||||||
lines = y - sy + 1;
|
lines = y - sy + 1;
|
||||||
if (image_scroll_up(s, lines) && ctx->wp != NULL)
|
if (image_scroll_up(s, lines) && ctx->wp != NULL)
|
||||||
ctx->wp->flags |= PANE_REDRAW;
|
ctx->wp->flags |= PANE_REDRAW;
|
||||||
@@ -2377,8 +2766,10 @@ screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
|||||||
screen_write_collect_flush(ctx, 0, __func__);
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
screen_alternate_on(ctx->s, gc, cursor);
|
screen_alternate_on(ctx->s, gc, cursor);
|
||||||
|
|
||||||
if (wp != NULL)
|
if (wp != NULL) {
|
||||||
layout_fix_panes(wp->window, NULL);
|
layout_fix_panes(wp->window, NULL);
|
||||||
|
server_redraw_window_borders(wp->window);
|
||||||
|
}
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 1);
|
screen_write_initctx(ctx, &ttyctx, 1);
|
||||||
if (ttyctx.redraw_cb != NULL)
|
if (ttyctx.redraw_cb != NULL)
|
||||||
@@ -2399,8 +2790,10 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
|||||||
screen_write_collect_flush(ctx, 0, __func__);
|
screen_write_collect_flush(ctx, 0, __func__);
|
||||||
screen_alternate_off(ctx->s, gc, cursor);
|
screen_alternate_off(ctx->s, gc, cursor);
|
||||||
|
|
||||||
if (wp != NULL)
|
if (wp != NULL) {
|
||||||
layout_fix_panes(wp->window, NULL);
|
layout_fix_panes(wp->window, NULL);
|
||||||
|
server_redraw_window_borders(wp->window);
|
||||||
|
}
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx, 1);
|
screen_write_initctx(ctx, &ttyctx, 1);
|
||||||
if (ttyctx.redraw_cb != NULL)
|
if (ttyctx.redraw_cb != NULL)
|
||||||
|
|||||||
84
screen.c
84
screen.c
@@ -581,12 +581,12 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get selected grid cell. */
|
/* Get selected grid cell. */
|
||||||
void
|
int
|
||||||
screen_select_cell(struct screen *s, struct grid_cell *dst,
|
screen_select_cell(struct screen *s, struct grid_cell *dst,
|
||||||
const struct grid_cell *src)
|
const struct grid_cell *src)
|
||||||
{
|
{
|
||||||
if (s->sel == NULL || s->sel->hidden)
|
if (s->sel == NULL || s->sel->hidden)
|
||||||
return;
|
return (0);
|
||||||
|
|
||||||
memcpy(dst, &s->sel->cell, sizeof *dst);
|
memcpy(dst, &s->sel->cell, sizeof *dst);
|
||||||
if (COLOUR_DEFAULT(dst->fg))
|
if (COLOUR_DEFAULT(dst->fg))
|
||||||
@@ -594,8 +594,13 @@ screen_select_cell(struct screen *s, struct grid_cell *dst,
|
|||||||
if (COLOUR_DEFAULT(dst->bg))
|
if (COLOUR_DEFAULT(dst->bg))
|
||||||
dst->bg = src->bg;
|
dst->bg = src->bg;
|
||||||
utf8_copy(&dst->data, &src->data);
|
utf8_copy(&dst->data, &src->data);
|
||||||
dst->attr = src->attr;
|
|
||||||
dst->flags = src->flags;
|
dst->flags = src->flags;
|
||||||
|
|
||||||
|
if (dst->attr & GRID_ATTR_NOATTR)
|
||||||
|
dst->attr |= (src->attr & GRID_ATTR_CHARSET);
|
||||||
|
else
|
||||||
|
dst->attr |= src->attr;
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reflow wrapped lines. */
|
/* Reflow wrapped lines. */
|
||||||
@@ -761,6 +766,79 @@ screen_mode_to_string(int mode)
|
|||||||
strlcat(tmp, "KEYS_EXTENDED,", sizeof tmp);
|
strlcat(tmp, "KEYS_EXTENDED,", sizeof tmp);
|
||||||
if (mode & MODE_KEYS_EXTENDED_2)
|
if (mode & MODE_KEYS_EXTENDED_2)
|
||||||
strlcat(tmp, "KEYS_EXTENDED_2,", sizeof tmp);
|
strlcat(tmp, "KEYS_EXTENDED_2,", sizeof tmp);
|
||||||
|
if (mode & MODE_THEME_UPDATES)
|
||||||
|
strlcat(tmp, "THEME_UPDATES,", sizeof tmp);
|
||||||
tmp[strlen(tmp) - 1] = '\0';
|
tmp[strlen(tmp) - 1] = '\0';
|
||||||
return (tmp);
|
return (tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
screen_print(struct screen *s)
|
||||||
|
{
|
||||||
|
static char *buf;
|
||||||
|
static size_t len = 16384;
|
||||||
|
const char *acs;
|
||||||
|
u_int x, y;
|
||||||
|
int n;
|
||||||
|
size_t last = 0;
|
||||||
|
struct utf8_data ud;
|
||||||
|
struct grid_line *gl;
|
||||||
|
struct grid_cell_entry *gce;
|
||||||
|
|
||||||
|
if (buf == NULL)
|
||||||
|
buf = xmalloc(len);
|
||||||
|
|
||||||
|
for (y = 0; y < screen_hsize(s) + s->grid->sy; y++) {
|
||||||
|
n = snprintf(buf + last, len - last, "%.4d \"", y);
|
||||||
|
if (n <= 0 || (u_int)n >= len - last)
|
||||||
|
goto out;
|
||||||
|
last += n;
|
||||||
|
|
||||||
|
gl = &s->grid->linedata[y];
|
||||||
|
for (x = 0; x < gl->cellused; x++) {
|
||||||
|
gce = &gl->celldata[x];
|
||||||
|
if (gce->flags & GRID_FLAG_PADDING)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (~gce->flags & GRID_FLAG_EXTENDED) {
|
||||||
|
if (last + 2 >= len)
|
||||||
|
goto out;
|
||||||
|
buf[last++] = gce->data.data;
|
||||||
|
} else if (gce->flags & GRID_FLAG_TAB) {
|
||||||
|
if (last + 2 >= len)
|
||||||
|
goto out;
|
||||||
|
buf[last++] = '\t';
|
||||||
|
} else if (gce->flags & GRID_ATTR_CHARSET) {
|
||||||
|
acs = tty_acs_get(NULL, gce->data.data);
|
||||||
|
if (acs != NULL)
|
||||||
|
n = strlen(acs);
|
||||||
|
else {
|
||||||
|
acs = &gce->data.data;
|
||||||
|
n = 1;
|
||||||
|
}
|
||||||
|
if (last + n + 1 >= len)
|
||||||
|
goto out;
|
||||||
|
memcpy(buf + last, acs, n);
|
||||||
|
last += n;
|
||||||
|
} else {
|
||||||
|
utf8_to_data(gl->extddata[gce->offset].data,
|
||||||
|
&ud);
|
||||||
|
if (ud.size > 0) {
|
||||||
|
if (last + ud.size + 1 >= len)
|
||||||
|
goto out;
|
||||||
|
memcpy(buf + last, ud.data, ud.size);
|
||||||
|
last += ud.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last + 3 >= len)
|
||||||
|
goto out;
|
||||||
|
buf[last++] = '"';
|
||||||
|
buf[last++] = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
buf[last] = '\0';
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
|||||||
338
server-client.c
338
server-client.c
@@ -161,38 +161,58 @@ server_client_clear_overlay(struct client *c)
|
|||||||
server_redraw_client(c);
|
server_redraw_client(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Are these ranges empty? That is, nothing is visible. */
|
||||||
|
int
|
||||||
|
server_client_ranges_is_empty(struct visible_ranges *r)
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
if (r->ranges[i].nx != 0)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure we have space for at least n ranges. */
|
||||||
|
void
|
||||||
|
server_client_ensure_ranges(struct visible_ranges *r, u_int n)
|
||||||
|
{
|
||||||
|
if (r->size >= n)
|
||||||
|
return;
|
||||||
|
r->ranges = xrecallocarray(r->ranges, r->size, n, sizeof *r->ranges);
|
||||||
|
r->size = n;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given overlay position and dimensions, return parts of the input range which
|
* Given overlay position and dimensions, return parts of the input range which
|
||||||
* are visible.
|
* are visible.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
server_client_overlay_range(u_int x, u_int y, u_int sx, u_int sy, u_int px,
|
server_client_overlay_range(u_int x, u_int y, u_int sx, u_int sy, u_int px,
|
||||||
u_int py, u_int nx, struct overlay_ranges *r)
|
u_int py, u_int nx, struct visible_ranges *r)
|
||||||
{
|
{
|
||||||
u_int ox, onx;
|
u_int ox, onx;
|
||||||
|
|
||||||
/* Return up to 2 ranges. */
|
|
||||||
r->px[2] = 0;
|
|
||||||
r->nx[2] = 0;
|
|
||||||
|
|
||||||
/* Trivial case of no overlap in the y direction. */
|
/* Trivial case of no overlap in the y direction. */
|
||||||
if (py < y || py > y + sy - 1) {
|
if (py < y || py > y + sy - 1) {
|
||||||
r->px[0] = px;
|
server_client_ensure_ranges(r, 1);
|
||||||
r->nx[0] = nx;
|
r->ranges[0].px = px;
|
||||||
r->px[1] = 0;
|
r->ranges[0].nx = nx;
|
||||||
r->nx[1] = 0;
|
r->used = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
server_client_ensure_ranges(r, 2);
|
||||||
|
|
||||||
/* Visible bit to the left of the popup. */
|
/* Visible bit to the left of the popup. */
|
||||||
if (px < x) {
|
if (px < x) {
|
||||||
r->px[0] = px;
|
r->ranges[0].px = px;
|
||||||
r->nx[0] = x - px;
|
r->ranges[0].nx = x - px;
|
||||||
if (r->nx[0] > nx)
|
if (r->ranges[0].nx > nx)
|
||||||
r->nx[0] = nx;
|
r->ranges[0].nx = nx;
|
||||||
} else {
|
} else {
|
||||||
r->px[0] = 0;
|
r->ranges[0].px = 0;
|
||||||
r->nx[0] = 0;
|
r->ranges[0].nx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Visible bit to the right of the popup. */
|
/* Visible bit to the right of the popup. */
|
||||||
@@ -201,12 +221,13 @@ server_client_overlay_range(u_int x, u_int y, u_int sx, u_int sy, u_int px,
|
|||||||
ox = px;
|
ox = px;
|
||||||
onx = px + nx;
|
onx = px + nx;
|
||||||
if (onx > ox) {
|
if (onx > ox) {
|
||||||
r->px[1] = ox;
|
r->ranges[1].px = ox;
|
||||||
r->nx[1] = onx - ox;
|
r->ranges[1].nx = onx - ox;
|
||||||
} else {
|
} else {
|
||||||
r->px[1] = 0;
|
r->ranges[1].px = 0;
|
||||||
r->nx[1] = 0;
|
r->ranges[1].nx = 0;
|
||||||
}
|
}
|
||||||
|
r->used = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this client is inside this server. */
|
/* Check if this client is inside this server. */
|
||||||
@@ -311,6 +332,8 @@ server_client_create(int fd)
|
|||||||
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
|
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
|
||||||
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
evtimer_set(&c->click_timer, server_client_click_timer, c);
|
||||||
|
|
||||||
|
c->click_wp = -1;
|
||||||
|
|
||||||
TAILQ_INIT(&c->input_requests);
|
TAILQ_INIT(&c->input_requests);
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&clients, c, entry);
|
TAILQ_INSERT_TAIL(&clients, c, entry);
|
||||||
@@ -401,13 +424,13 @@ server_client_set_session(struct client *c, struct session *s)
|
|||||||
if (old != NULL && old->curw != NULL)
|
if (old != NULL && old->curw != NULL)
|
||||||
window_update_focus(old->curw->window);
|
window_update_focus(old->curw->window);
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
|
s->curw->window->latest = c;
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
window_update_focus(s->curw->window);
|
window_update_focus(s->curw->window);
|
||||||
session_update_activity(s, NULL);
|
session_update_activity(s, NULL);
|
||||||
session_theme_changed(s);
|
session_theme_changed(s);
|
||||||
gettimeofday(&s->last_attached_time, NULL);
|
gettimeofday(&s->last_attached_time, NULL);
|
||||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||||
s->curw->window->latest = c;
|
|
||||||
alerts_check_session(s);
|
alerts_check_session(s);
|
||||||
tty_update_client_offset(c);
|
tty_update_client_offset(c);
|
||||||
status_timer_start(c);
|
status_timer_start(c);
|
||||||
@@ -594,7 +617,8 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
|||||||
struct options *wo = w->options;
|
struct options *wo = w->options;
|
||||||
struct window_pane *fwp;
|
struct window_pane *fwp;
|
||||||
int pane_status, sb, sb_pos, sb_w, sb_pad;
|
int pane_status, sb, sb_pos, sb_w, sb_pad;
|
||||||
u_int line, sl_top, sl_bottom;
|
u_int pane_status_line, sl_top, sl_bottom;
|
||||||
|
u_int bdr_bottom, bdr_top, bdr_left, bdr_right;
|
||||||
|
|
||||||
sb = options_get_number(wo, "pane-scrollbars");
|
sb = options_get_number(wo, "pane-scrollbars");
|
||||||
sb_pos = options_get_number(wo, "pane-scrollbars-position");
|
sb_pos = options_get_number(wo, "pane-scrollbars-position");
|
||||||
@@ -607,15 +631,19 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
|||||||
sb_w = 0;
|
sb_w = 0;
|
||||||
sb_pad = 0;
|
sb_pad = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pane_status == PANE_STATUS_TOP)
|
if (pane_status == PANE_STATUS_TOP)
|
||||||
line = wp->yoff - 1;
|
pane_status_line = wp->yoff - 1;
|
||||||
else if (pane_status == PANE_STATUS_BOTTOM)
|
else if (pane_status == PANE_STATUS_BOTTOM)
|
||||||
line = wp->yoff + wp->sy;
|
pane_status_line = wp->yoff + wp->sy;
|
||||||
|
else
|
||||||
|
pane_status_line = -1; /* not used */
|
||||||
|
|
||||||
/* Check if point is within the pane or scrollbar. */
|
/* Check if point is within the pane or scrollbar. */
|
||||||
if (((pane_status != PANE_STATUS_OFF && py != line) ||
|
if (((pane_status != PANE_STATUS_OFF &&
|
||||||
|
py != pane_status_line && py != wp->yoff + wp->sy) ||
|
||||||
(wp->yoff == 0 && py < wp->sy) ||
|
(wp->yoff == 0 && py < wp->sy) ||
|
||||||
(py >= wp->yoff && py < wp->yoff + wp->sy)) &&
|
((int)py >= wp->yoff && py < wp->yoff + wp->sy)) &&
|
||||||
((sb_pos == PANE_SCROLLBARS_RIGHT &&
|
((sb_pos == PANE_SCROLLBARS_RIGHT &&
|
||||||
px < wp->xoff + wp->sx + sb_pad + sb_w) ||
|
px < wp->xoff + wp->sx + sb_pad + sb_w) ||
|
||||||
(sb_pos == PANE_SCROLLBARS_LEFT &&
|
(sb_pos == PANE_SCROLLBARS_LEFT &&
|
||||||
@@ -625,8 +653,8 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
|||||||
(px >= wp->xoff + wp->sx + sb_pad &&
|
(px >= wp->xoff + wp->sx + sb_pad &&
|
||||||
px < wp->xoff + wp->sx + sb_pad + sb_w)) ||
|
px < wp->xoff + wp->sx + sb_pad + sb_w)) ||
|
||||||
(sb_pos == PANE_SCROLLBARS_LEFT &&
|
(sb_pos == PANE_SCROLLBARS_LEFT &&
|
||||||
(px >= wp->xoff - sb_pad - sb_w &&
|
((int)px >= wp->xoff - sb_pad - sb_w &&
|
||||||
px < wp->xoff - sb_pad))) {
|
(int)px < wp->xoff - sb_pad))) {
|
||||||
/* Check where inside the scrollbar. */
|
/* Check where inside the scrollbar. */
|
||||||
sl_top = wp->yoff + wp->sb_slider_y;
|
sl_top = wp->yoff + wp->sb_slider_y;
|
||||||
sl_bottom = (wp->yoff + wp->sb_slider_y +
|
sl_bottom = (wp->yoff + wp->sb_slider_y +
|
||||||
@@ -639,6 +667,12 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
|||||||
return (SCROLLBAR_SLIDER);
|
return (SCROLLBAR_SLIDER);
|
||||||
} else /* py > sl_bottom */
|
} else /* py > sl_bottom */
|
||||||
return (SCROLLBAR_DOWN);
|
return (SCROLLBAR_DOWN);
|
||||||
|
} else if (wp->flags & PANE_FLOATING &&
|
||||||
|
((int)px == wp->xoff - 1 ||
|
||||||
|
(int)py == wp->yoff - 1 ||
|
||||||
|
(int)py == wp->yoff + (int)wp->sy)) {
|
||||||
|
/* Floating pane left, bottom or top border. */
|
||||||
|
return (BORDER);
|
||||||
} else {
|
} else {
|
||||||
/* Must be inside the pane. */
|
/* Must be inside the pane. */
|
||||||
return (PANE);
|
return (PANE);
|
||||||
@@ -646,16 +680,32 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
|||||||
} else if (~w->flags & WINDOW_ZOOMED) {
|
} else if (~w->flags & WINDOW_ZOOMED) {
|
||||||
/* Try the pane borders if not zoomed. */
|
/* Try the pane borders if not zoomed. */
|
||||||
TAILQ_FOREACH(fwp, &w->panes, entry) {
|
TAILQ_FOREACH(fwp, &w->panes, entry) {
|
||||||
if ((((sb_pos == PANE_SCROLLBARS_RIGHT &&
|
if (sb_pos == PANE_SCROLLBARS_LEFT)
|
||||||
fwp->xoff + fwp->sx + sb_pad + sb_w == px) ||
|
bdr_right = fwp->xoff + fwp->sx;
|
||||||
(sb_pos == PANE_SCROLLBARS_LEFT &&
|
else
|
||||||
fwp->xoff + fwp->sx == px)) &&
|
/* PANE_SCROLLBARS_RIGHT or none. */
|
||||||
fwp->yoff <= 1 + py &&
|
bdr_right = fwp->xoff + fwp->sx + sb_pad + sb_w;
|
||||||
fwp->yoff + fwp->sy >= py) ||
|
if ((int)py >= fwp->yoff - 1 && py <= fwp->yoff + fwp->sy) {
|
||||||
(fwp->yoff + fwp->sy == py &&
|
if (px == bdr_right)
|
||||||
fwp->xoff <= 1 + px &&
|
break;
|
||||||
fwp->xoff + fwp->sx >= px))
|
if (wp->flags & PANE_FLOATING) {
|
||||||
break;
|
/* Floating pane, check if left border. */
|
||||||
|
bdr_left = fwp->xoff - 1;
|
||||||
|
if (px == bdr_left)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((int)px >= fwp->xoff - 1 && px <= fwp->xoff + fwp->sx) {
|
||||||
|
bdr_bottom = fwp->yoff + fwp->sy;
|
||||||
|
if (py == bdr_bottom)
|
||||||
|
break;
|
||||||
|
if (wp->flags & PANE_FLOATING) {
|
||||||
|
/* Floating pane, check if top border. */
|
||||||
|
bdr_top = fwp->yoff - 1;
|
||||||
|
if (py == bdr_top)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fwp != NULL)
|
if (fwp != NULL)
|
||||||
return (BORDER);
|
return (BORDER);
|
||||||
@@ -732,21 +782,17 @@ server_client_check_mouse(struct client *c, struct key_event *event)
|
|||||||
if (c->flags & CLIENT_DOUBLECLICK) {
|
if (c->flags & CLIENT_DOUBLECLICK) {
|
||||||
evtimer_del(&c->click_timer);
|
evtimer_del(&c->click_timer);
|
||||||
c->flags &= ~CLIENT_DOUBLECLICK;
|
c->flags &= ~CLIENT_DOUBLECLICK;
|
||||||
if (m->b == c->click_button) {
|
type = SECOND;
|
||||||
type = SECOND;
|
x = m->x, y = m->y, b = m->b;
|
||||||
x = m->x, y = m->y, b = m->b;
|
log_debug("second-click at %u,%u", x, y);
|
||||||
log_debug("second-click at %u,%u", x, y);
|
c->flags |= CLIENT_TRIPLECLICK;
|
||||||
c->flags |= CLIENT_TRIPLECLICK;
|
|
||||||
}
|
|
||||||
} else if (c->flags & CLIENT_TRIPLECLICK) {
|
} else if (c->flags & CLIENT_TRIPLECLICK) {
|
||||||
evtimer_del(&c->click_timer);
|
evtimer_del(&c->click_timer);
|
||||||
c->flags &= ~CLIENT_TRIPLECLICK;
|
c->flags &= ~CLIENT_TRIPLECLICK;
|
||||||
if (m->b == c->click_button) {
|
type = TRIPLE;
|
||||||
type = TRIPLE;
|
x = m->x, y = m->y, b = m->b;
|
||||||
x = m->x, y = m->y, b = m->b;
|
log_debug("triple-click at %u,%u", x, y);
|
||||||
log_debug("triple-click at %u,%u", x, y);
|
goto have_event;
|
||||||
goto have_event;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DOWN is the only remaining event type. */
|
/* DOWN is the only remaining event type. */
|
||||||
@@ -756,17 +802,6 @@ server_client_check_mouse(struct client *c, struct key_event *event)
|
|||||||
log_debug("down at %u,%u", x, y);
|
log_debug("down at %u,%u", x, y);
|
||||||
c->flags |= CLIENT_DOUBLECLICK;
|
c->flags |= CLIENT_DOUBLECLICK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KEYC_CLICK_TIMEOUT != 0) {
|
|
||||||
memcpy(&c->click_event, m, sizeof c->click_event);
|
|
||||||
c->click_button = m->b;
|
|
||||||
|
|
||||||
log_debug("click timer started");
|
|
||||||
tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000;
|
|
||||||
tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L;
|
|
||||||
evtimer_del(&c->click_timer);
|
|
||||||
evtimer_add(&c->click_timer, &tv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
have_event:
|
have_event:
|
||||||
@@ -840,9 +875,11 @@ have_event:
|
|||||||
* scrollbar.
|
* scrollbar.
|
||||||
*/
|
*/
|
||||||
if (where == NOWHERE) {
|
if (where == NOWHERE) {
|
||||||
if (c->tty.mouse_scrolling_flag)
|
if (c->tty.mouse_scrolling_flag) {
|
||||||
where = SCROLLBAR_SLIDER;
|
where = SCROLLBAR_SLIDER;
|
||||||
else {
|
m->wp = c->tty.mouse_wp->id;
|
||||||
|
m->w = c->tty.mouse_wp->window->id;
|
||||||
|
} else {
|
||||||
px = x;
|
px = x;
|
||||||
if (m->statusat == 0 && y >= m->statuslines)
|
if (m->statusat == 0 && y >= m->statuslines)
|
||||||
py = y - m->statuslines;
|
py = y - m->statuslines;
|
||||||
@@ -859,8 +896,13 @@ have_event:
|
|||||||
px = px + m->ox;
|
px = px + m->ox;
|
||||||
py = py + m->oy;
|
py = py + m->oy;
|
||||||
|
|
||||||
/* Try inside the pane. */
|
if (type == DRAG &&
|
||||||
wp = window_get_active_at(w, px, py);
|
c->tty.mouse_wp != NULL)
|
||||||
|
/* Use pane from last mouse event. */
|
||||||
|
wp = c->tty.mouse_wp;
|
||||||
|
else
|
||||||
|
/* Try inside the pane. */
|
||||||
|
wp = window_get_active_at(w, px, py);
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
return (KEYC_UNKNOWN);
|
return (KEYC_UNKNOWN);
|
||||||
where = server_client_check_mouse_in_pane(wp, px, py,
|
where = server_client_check_mouse_in_pane(wp, px, py,
|
||||||
@@ -882,6 +924,34 @@ have_event:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset click type or add a click timer if needed. */
|
||||||
|
if (type == DOWN ||
|
||||||
|
type == SECOND ||
|
||||||
|
type == TRIPLE) {
|
||||||
|
if (type != DOWN &&
|
||||||
|
(m->b != c->click_button ||
|
||||||
|
where != (enum mouse_where)c->click_where ||
|
||||||
|
m->wp != c->click_wp)) {
|
||||||
|
type = DOWN;
|
||||||
|
log_debug("click sequence reset at %u,%u", x, y);
|
||||||
|
c->flags &= ~CLIENT_TRIPLECLICK;
|
||||||
|
c->flags |= CLIENT_DOUBLECLICK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != TRIPLE && KEYC_CLICK_TIMEOUT != 0) {
|
||||||
|
memcpy(&c->click_event, m, sizeof c->click_event);
|
||||||
|
c->click_button = m->b;
|
||||||
|
c->click_where = where;
|
||||||
|
c->click_wp = m->wp;
|
||||||
|
|
||||||
|
log_debug("click timer started");
|
||||||
|
tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000;
|
||||||
|
tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L;
|
||||||
|
evtimer_del(&c->click_timer);
|
||||||
|
evtimer_add(&c->click_timer, &tv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Stop dragging if needed. */
|
/* Stop dragging if needed. */
|
||||||
if (type != DRAG &&
|
if (type != DRAG &&
|
||||||
type != WHEEL &&
|
type != WHEEL &&
|
||||||
@@ -1049,6 +1119,7 @@ have_event:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
c->tty.mouse_drag_flag = 0;
|
c->tty.mouse_drag_flag = 0;
|
||||||
|
c->tty.mouse_wp = NULL;
|
||||||
c->tty.mouse_slider_mpos = -1;
|
c->tty.mouse_slider_mpos = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1059,8 +1130,17 @@ have_event:
|
|||||||
case NOTYPE:
|
case NOTYPE:
|
||||||
break;
|
break;
|
||||||
case MOVE:
|
case MOVE:
|
||||||
if (where == PANE)
|
if (where == PANE) {
|
||||||
key = KEYC_MOUSEMOVE_PANE;
|
key = KEYC_MOUSEMOVE_PANE;
|
||||||
|
if (wp != NULL &&
|
||||||
|
wp != w->active &&
|
||||||
|
options_get_number(s->options, "focus-follows-mouse")) {
|
||||||
|
window_redraw_active_switch(w, wp);
|
||||||
|
window_set_active_pane(w, wp, 1);
|
||||||
|
server_redraw_window_borders(w);
|
||||||
|
server_status_window(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (where == STATUS)
|
if (where == STATUS)
|
||||||
key = KEYC_MOUSEMOVE_STATUS;
|
key = KEYC_MOUSEMOVE_STATUS;
|
||||||
if (where == STATUS_LEFT)
|
if (where == STATUS_LEFT)
|
||||||
@@ -1267,10 +1347,19 @@ have_event:
|
|||||||
* where the user grabbed.
|
* where the user grabbed.
|
||||||
*/
|
*/
|
||||||
c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1;
|
c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1;
|
||||||
|
/* Only change pane if not already dragging a pane border. */
|
||||||
|
if (c->tty.mouse_wp == NULL) {
|
||||||
|
wp = window_get_active_at(w, px, py);
|
||||||
|
c->tty.mouse_wp = wp;
|
||||||
|
}
|
||||||
if (c->tty.mouse_scrolling_flag == 0 &&
|
if (c->tty.mouse_scrolling_flag == 0 &&
|
||||||
where == SCROLLBAR_SLIDER) {
|
where == SCROLLBAR_SLIDER) {
|
||||||
c->tty.mouse_scrolling_flag = 1;
|
c->tty.mouse_scrolling_flag = 1;
|
||||||
c->tty.mouse_slider_mpos = sl_mpos;
|
if (m->statusat == 0) {
|
||||||
|
c->tty.mouse_slider_mpos = sl_mpos +
|
||||||
|
m->statuslines;
|
||||||
|
} else
|
||||||
|
c->tty.mouse_slider_mpos = sl_mpos;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WHEEL:
|
case WHEEL:
|
||||||
@@ -2385,16 +2474,6 @@ server_client_key_callback(struct cmdq_item *item, void *data)
|
|||||||
event->key = key;
|
event->key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle theme reporting keys. */
|
|
||||||
if (key == KEYC_REPORT_LIGHT_THEME) {
|
|
||||||
server_client_report_theme(c, THEME_LIGHT);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (key == KEYC_REPORT_DARK_THEME) {
|
|
||||||
server_client_report_theme(c, THEME_DARK);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find affected pane. */
|
/* Find affected pane. */
|
||||||
if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0)
|
if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0)
|
||||||
cmd_find_from_client(&fs, c, 0);
|
cmd_find_from_client(&fs, c, 0);
|
||||||
@@ -2613,6 +2692,19 @@ server_client_handle_key(struct client *c, struct key_event *event)
|
|||||||
if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle theme reporting keys before overlays so they work even when a
|
||||||
|
* popup is open.
|
||||||
|
*/
|
||||||
|
if (event->key == KEYC_REPORT_LIGHT_THEME) {
|
||||||
|
server_client_report_theme(c, THEME_LIGHT);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (event->key == KEYC_REPORT_DARK_THEME) {
|
||||||
|
server_client_report_theme(c, THEME_DARK);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Key presses in overlay mode and the command prompt are a special
|
* Key presses in overlay mode and the command prompt are a special
|
||||||
* case. The queue might be blocked so they need to be processed
|
* case. The queue might be blocked so they need to be processed
|
||||||
@@ -2653,18 +2745,31 @@ server_client_handle_key(struct client *c, struct key_event *event)
|
|||||||
void
|
void
|
||||||
server_client_loop(void)
|
server_client_loop(void)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
|
struct window_mode_entry *wme;
|
||||||
|
|
||||||
/* Check for window resize. This is done before redrawing. */
|
/* Check for window resize. This is done before redrawing. */
|
||||||
RB_FOREACH(w, windows, &windows)
|
RB_FOREACH(w, windows, &windows)
|
||||||
server_client_check_window_resize(w);
|
server_client_check_window_resize(w);
|
||||||
|
|
||||||
|
/* Notify modes that pane styles may have changed. */
|
||||||
|
RB_FOREACH(w, windows, &windows) {
|
||||||
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
|
if (wp->flags & PANE_STYLECHANGED) {
|
||||||
|
wme = TAILQ_FIRST(&wp->modes);
|
||||||
|
if (wme != NULL &&
|
||||||
|
wme->mode->style_changed != NULL)
|
||||||
|
wme->mode->style_changed(wme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check clients. */
|
/* Check clients. */
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
server_client_check_exit(c);
|
server_client_check_exit(c);
|
||||||
if (c->session != NULL) {
|
if (c->session != NULL && c->session->curw != NULL) {
|
||||||
server_client_check_modes(c);
|
server_client_check_modes(c);
|
||||||
server_client_check_redraw(c);
|
server_client_check_redraw(c);
|
||||||
server_client_reset_state(c);
|
server_client_reset_state(c);
|
||||||
@@ -2901,8 +3006,8 @@ server_client_reset_state(struct client *c)
|
|||||||
struct window_pane *wp = server_client_get_pane(c), *loop;
|
struct window_pane *wp = server_client_get_pane(c), *loop;
|
||||||
struct screen *s = NULL;
|
struct screen *s = NULL;
|
||||||
struct options *oo = c->session->options;
|
struct options *oo = c->session->options;
|
||||||
int mode = 0, cursor, flags, n;
|
int mode = 0, cursor, flags;
|
||||||
u_int cx = 0, cy = 0, ox, oy, sx, sy;
|
u_int cx = 0, cy = 0, ox, oy, sx, sy, n;
|
||||||
|
|
||||||
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
|
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
|
||||||
return;
|
return;
|
||||||
@@ -2915,7 +3020,7 @@ server_client_reset_state(struct client *c)
|
|||||||
if (c->overlay_draw != NULL) {
|
if (c->overlay_draw != NULL) {
|
||||||
if (c->overlay_mode != NULL)
|
if (c->overlay_mode != NULL)
|
||||||
s = c->overlay_mode(c, c->overlay_data, &cx, &cy);
|
s = c->overlay_mode(c, c->overlay_data, &cx, &cy);
|
||||||
} else if (c->prompt_string == NULL)
|
} else if (wp != NULL && c->prompt_string == NULL)
|
||||||
s = wp->screen;
|
s = wp->screen;
|
||||||
else
|
else
|
||||||
s = c->status.active;
|
s = c->status.active;
|
||||||
@@ -2934,16 +3039,16 @@ server_client_reset_state(struct client *c)
|
|||||||
if (c->prompt_string != NULL) {
|
if (c->prompt_string != NULL) {
|
||||||
n = options_get_number(oo, "status-position");
|
n = options_get_number(oo, "status-position");
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
cy = 0;
|
cy = status_prompt_line_at(c);
|
||||||
else {
|
else {
|
||||||
n = status_line_size(c);
|
n = status_line_size(c) - status_prompt_line_at(c);
|
||||||
if (n == 0)
|
if (n <= tty->sy)
|
||||||
cy = tty->sy - 1;
|
|
||||||
else
|
|
||||||
cy = tty->sy - n;
|
cy = tty->sy - n;
|
||||||
|
else
|
||||||
|
cy = tty->sy - 1;
|
||||||
}
|
}
|
||||||
cx = c->prompt_cursor;
|
cx = c->prompt_cursor;
|
||||||
} else if (c->overlay_draw == NULL) {
|
} else if (wp != NULL && c->overlay_draw == NULL) {
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
tty_window_offset(tty, &ox, &oy, &sx, &sy);
|
tty_window_offset(tty, &ox, &oy, &sx, &sy);
|
||||||
if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx &&
|
if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx &&
|
||||||
@@ -2956,15 +3061,22 @@ server_client_reset_state(struct client *c)
|
|||||||
if (status_at_line(c) == 0)
|
if (status_at_line(c) == 0)
|
||||||
cy += status_line_size(c);
|
cy += status_line_size(c);
|
||||||
}
|
}
|
||||||
|
if (!screen_redraw_is_visible(
|
||||||
|
screen_redraw_get_visible_ranges(wp, cx, cy, 1, NULL), cx))
|
||||||
|
cursor = 0;
|
||||||
|
|
||||||
if (!cursor)
|
if (!cursor)
|
||||||
mode &= ~MODE_CURSOR;
|
mode &= ~MODE_CURSOR;
|
||||||
}
|
} else
|
||||||
|
mode &= ~MODE_CURSOR;
|
||||||
|
|
||||||
log_debug("%s: cursor to %u,%u", __func__, cx, cy);
|
log_debug("%s: cursor to %u,%u", __func__, cx, cy);
|
||||||
tty_cursor(tty, cx, cy);
|
tty_cursor(tty, cx, cy);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set mouse mode if requested. To support dragging, always use button
|
* Set mouse mode if requested. To support dragging, always use button
|
||||||
* mode.
|
* mode. For focus-follows-mouse, we need all-motion mode to receive
|
||||||
|
* movement events.
|
||||||
*/
|
*/
|
||||||
if (options_get_number(oo, "mouse")) {
|
if (options_get_number(oo, "mouse")) {
|
||||||
if (c->overlay_draw == NULL) {
|
if (c->overlay_draw == NULL) {
|
||||||
@@ -2974,7 +3086,9 @@ server_client_reset_state(struct client *c)
|
|||||||
mode |= MODE_MOUSE_ALL;
|
mode |= MODE_MOUSE_ALL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (~mode & MODE_MOUSE_ALL)
|
if (options_get_number(oo, "focus-follows-mouse"))
|
||||||
|
mode |= MODE_MOUSE_ALL;
|
||||||
|
else if (~mode & MODE_MOUSE_ALL)
|
||||||
mode |= MODE_MOUSE_BUTTON;
|
mode |= MODE_MOUSE_BUTTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3427,6 +3541,24 @@ server_client_read_only(struct cmdq_item *item, __unused void *data)
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for default command. */
|
||||||
|
static enum cmd_retval
|
||||||
|
server_client_default_command(struct cmdq_item *item, __unused void *data)
|
||||||
|
{
|
||||||
|
struct client *c = cmdq_get_client(item);
|
||||||
|
struct cmd_list *cmdlist;
|
||||||
|
struct cmdq_item *new_item;
|
||||||
|
|
||||||
|
cmdlist = options_get_command(global_options, "default-client-command");
|
||||||
|
if ((c->flags & CLIENT_READONLY) &&
|
||||||
|
!cmd_list_all_have(cmdlist, CMD_READONLY))
|
||||||
|
new_item = cmdq_get_callback(server_client_read_only, NULL);
|
||||||
|
else
|
||||||
|
new_item = cmdq_get_command(cmdlist, NULL);
|
||||||
|
cmdq_insert_after(item, new_item);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback when command is done. */
|
/* Callback when command is done. */
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
server_client_command_done(struct cmdq_item *item, __unused void *data)
|
server_client_command_done(struct cmdq_item *item, __unused void *data)
|
||||||
@@ -3455,7 +3587,6 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
|
|||||||
struct cmd_parse_result *pr;
|
struct cmd_parse_result *pr;
|
||||||
struct args_value *values;
|
struct args_value *values;
|
||||||
struct cmdq_item *new_item;
|
struct cmdq_item *new_item;
|
||||||
struct cmd_list *cmdlist;
|
|
||||||
|
|
||||||
if (c->flags & CLIENT_EXIT)
|
if (c->flags & CLIENT_EXIT)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -3476,8 +3607,8 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
|
|||||||
|
|
||||||
argc = data.argc;
|
argc = data.argc;
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
cmdlist = cmd_list_copy(options_get_command(global_options,
|
new_item = cmdq_get_callback(server_client_default_command,
|
||||||
"default-client-command"), 0, NULL);
|
NULL);
|
||||||
} else {
|
} else {
|
||||||
values = args_from_vector(argc, argv);
|
values = args_from_vector(argc, argv);
|
||||||
pr = cmd_parse_from_arguments(values, argc, NULL);
|
pr = cmd_parse_from_arguments(values, argc, NULL);
|
||||||
@@ -3491,18 +3622,17 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
|
|||||||
args_free_values(values, argc);
|
args_free_values(values, argc);
|
||||||
free(values);
|
free(values);
|
||||||
cmd_free_argv(argc, argv);
|
cmd_free_argv(argc, argv);
|
||||||
cmdlist = pr->cmdlist;
|
if ((c->flags & CLIENT_READONLY) &&
|
||||||
|
!cmd_list_all_have(pr->cmdlist, CMD_READONLY)) {
|
||||||
|
new_item = cmdq_get_callback(server_client_read_only,
|
||||||
|
NULL);
|
||||||
|
} else
|
||||||
|
new_item = cmdq_get_command(pr->cmdlist, NULL);
|
||||||
|
cmd_list_free(pr->cmdlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c->flags & CLIENT_READONLY) &&
|
|
||||||
!cmd_list_all_have(cmdlist, CMD_READONLY))
|
|
||||||
new_item = cmdq_get_callback(server_client_read_only, NULL);
|
|
||||||
else
|
|
||||||
new_item = cmdq_get_command(cmdlist, NULL);
|
|
||||||
cmdq_append(c, new_item);
|
cmdq_append(c, new_item);
|
||||||
cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
|
cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
|
||||||
|
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -3624,7 +3754,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
|||||||
c->term_name = xstrdup("unknown");
|
c->term_name = xstrdup("unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->ttyname == NULL || *c->ttyname != '\0')
|
if (c->ttyname != NULL && *c->ttyname != '\0')
|
||||||
name = xstrdup(c->ttyname);
|
name = xstrdup(c->ttyname);
|
||||||
else
|
else
|
||||||
xasprintf(&name, "client-%ld", (long)c->pid);
|
xasprintf(&name, "client-%ld", (long)c->pid);
|
||||||
|
|||||||
13
server-fn.c
13
server-fn.c
@@ -20,6 +20,7 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -95,7 +96,9 @@ server_redraw_window(struct window *w)
|
|||||||
struct client *c;
|
struct client *c;
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (c->session != NULL && c->session->curw->window == w)
|
if (c->session != NULL &&
|
||||||
|
c->session->curw != NULL &&
|
||||||
|
c->session->curw->window == w)
|
||||||
server_redraw_client(c);
|
server_redraw_client(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +109,9 @@ server_redraw_window_borders(struct window *w)
|
|||||||
struct client *c;
|
struct client *c;
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (c->session != NULL && c->session->curw->window == w)
|
if (c->session != NULL &&
|
||||||
|
c->session->curw != NULL &&
|
||||||
|
c->session->curw->window == w)
|
||||||
c->flags |= CLIENT_REDRAWBORDERS;
|
c->flags |= CLIENT_REDRAWBORDERS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -440,9 +445,9 @@ server_destroy_session(struct session *s)
|
|||||||
else if (detach_on_destroy == 2)
|
else if (detach_on_destroy == 2)
|
||||||
s_new = server_find_session(s, server_newer_detached_session);
|
s_new = server_find_session(s, server_newer_detached_session);
|
||||||
else if (detach_on_destroy == 3)
|
else if (detach_on_destroy == 3)
|
||||||
s_new = session_previous_session(s);
|
s_new = session_previous_session(s, NULL);
|
||||||
else if (detach_on_destroy == 4)
|
else if (detach_on_destroy == 4)
|
||||||
s_new = session_next_session(s);
|
s_new = session_next_session(s, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If no suitable new session was found above, then look for any
|
* If no suitable new session was found above, then look for any
|
||||||
|
|||||||
70
session.c
70
session.c
@@ -293,36 +293,48 @@ session_update_activity(struct session *s, struct timeval *from)
|
|||||||
|
|
||||||
/* Find the next usable session. */
|
/* Find the next usable session. */
|
||||||
struct session *
|
struct session *
|
||||||
session_next_session(struct session *s)
|
session_next_session(struct session *s, struct sort_criteria *sort_crit)
|
||||||
{
|
{
|
||||||
struct session *s2;
|
struct session **l;
|
||||||
|
u_int n, i;
|
||||||
|
|
||||||
if (RB_EMPTY(&sessions) || !session_alive(s))
|
if (RB_EMPTY(&sessions) || !session_alive(s))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
s2 = RB_NEXT(sessions, &sessions, s);
|
l = sort_get_sessions(&n, sort_crit);
|
||||||
if (s2 == NULL)
|
for (i = 0; i < n; i++) {
|
||||||
s2 = RB_MIN(sessions, &sessions);
|
if (l[i] == s)
|
||||||
if (s2 == s)
|
break;
|
||||||
return (NULL);
|
}
|
||||||
return (s2);
|
if (i == n)
|
||||||
|
fatalx("session %s not found in sorted list", s->name);
|
||||||
|
i++;
|
||||||
|
if (i == n)
|
||||||
|
i = 0;
|
||||||
|
return (l[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the previous usable session. */
|
/* Find the previous usable session. */
|
||||||
struct session *
|
struct session *
|
||||||
session_previous_session(struct session *s)
|
session_previous_session(struct session *s, struct sort_criteria *sort_crit)
|
||||||
{
|
{
|
||||||
struct session *s2;
|
struct session **l;
|
||||||
|
u_int n, i;
|
||||||
|
|
||||||
if (RB_EMPTY(&sessions) || !session_alive(s))
|
if (RB_EMPTY(&sessions) || !session_alive(s))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
s2 = RB_PREV(sessions, &sessions, s);
|
l = sort_get_sessions(&n, sort_crit);
|
||||||
if (s2 == NULL)
|
for (i = 0; i < n; i++) {
|
||||||
s2 = RB_MAX(sessions, &sessions);
|
if (l[i] == s)
|
||||||
if (s2 == s)
|
break;
|
||||||
return (NULL);
|
}
|
||||||
return (s2);
|
if (i == n)
|
||||||
|
fatalx("session %s not found in sorted list", s->name);
|
||||||
|
if (i == 0)
|
||||||
|
i = n;
|
||||||
|
i--;
|
||||||
|
return (l[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach a window to a session. */
|
/* Attach a window to a session. */
|
||||||
@@ -766,3 +778,29 @@ session_theme_changed(struct session *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update history for all panes. */
|
||||||
|
void
|
||||||
|
session_update_history(struct session *s)
|
||||||
|
{
|
||||||
|
struct winlink *wl;
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct grid *gd;
|
||||||
|
u_int limit, osize;
|
||||||
|
|
||||||
|
limit = options_get_number(s->options, "history-limit");
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||||
|
gd = wp->base.grid;
|
||||||
|
|
||||||
|
osize = gd->hsize;
|
||||||
|
gd->hlimit = limit;
|
||||||
|
grid_collect_history(gd, 1);
|
||||||
|
|
||||||
|
if (gd->hsize != osize) {
|
||||||
|
log_debug("%s: %%%u %u -> %u", __func__, wp->id,
|
||||||
|
osize, gd->hsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
649
sort.c
Normal file
649
sort.c
Normal file
@@ -0,0 +1,649 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2026 Dane Jensen <dhcjensen@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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
static struct sort_criteria *sort_criteria;
|
||||||
|
|
||||||
|
static void
|
||||||
|
sort_qsort(void *l, u_int len, u_int size, int (*cmp)(const void *, const void *),
|
||||||
|
struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
void *tmp, **ll;
|
||||||
|
|
||||||
|
if (sort_crit->order == SORT_END)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sort_crit->order == SORT_ORDER) {
|
||||||
|
if (sort_crit->reversed) {
|
||||||
|
ll = l;
|
||||||
|
for (i = 0; i < len / 2; i++) {
|
||||||
|
tmp = ll[i];
|
||||||
|
ll[i] = ll[len - 1 - i];
|
||||||
|
ll[len - 1 - i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sort_criteria = sort_crit;
|
||||||
|
qsort(l, len, size, cmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_buffer_cmp(const void *a0, const void *b0)
|
||||||
|
{
|
||||||
|
struct sort_criteria *sort_crit = sort_criteria;
|
||||||
|
const struct paste_buffer *const *a = a0;
|
||||||
|
const struct paste_buffer *const *b = b0;
|
||||||
|
const struct paste_buffer *pa = *a;
|
||||||
|
const struct paste_buffer *pb = *b;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
switch (sort_crit->order) {
|
||||||
|
case SORT_NAME:
|
||||||
|
result = strcmp(pa->name, pb->name);
|
||||||
|
break;
|
||||||
|
case SORT_CREATION:
|
||||||
|
result = pa->order - pb->order;
|
||||||
|
break;
|
||||||
|
case SORT_SIZE:
|
||||||
|
result = pa->size - pb->size;
|
||||||
|
break;
|
||||||
|
case SORT_ACTIVITY:
|
||||||
|
case SORT_INDEX:
|
||||||
|
case SORT_MODIFIER:
|
||||||
|
case SORT_ORDER:
|
||||||
|
case SORT_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
result = strcmp(pa->name, pb->name);
|
||||||
|
|
||||||
|
if (sort_crit->reversed)
|
||||||
|
result = -result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_client_cmp(const void *a0, const void *b0)
|
||||||
|
{
|
||||||
|
struct sort_criteria *sort_crit = sort_criteria;
|
||||||
|
const struct client *const *a = a0;
|
||||||
|
const struct client *const *b = b0;
|
||||||
|
const struct client *ca = *a;
|
||||||
|
const struct client *cb = *b;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
switch (sort_crit->order) {
|
||||||
|
case SORT_NAME:
|
||||||
|
result = strcmp(ca->name, cb->name);
|
||||||
|
break;
|
||||||
|
case SORT_SIZE:
|
||||||
|
result = ca->tty.sx - cb->tty.sx;
|
||||||
|
if (result == 0)
|
||||||
|
result = ca->tty.sy - cb->tty.sy;
|
||||||
|
break;
|
||||||
|
case SORT_CREATION:
|
||||||
|
if (timercmp(&ca->creation_time, &cb->creation_time, >))
|
||||||
|
result = 1;
|
||||||
|
else if (timercmp(&ca->creation_time, &cb->creation_time, <))
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
case SORT_ACTIVITY:
|
||||||
|
if (timercmp(&ca->activity_time, &cb->activity_time, >))
|
||||||
|
result = -1;
|
||||||
|
else if (timercmp(&ca->activity_time, &cb->activity_time, <))
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
case SORT_INDEX:
|
||||||
|
case SORT_MODIFIER:
|
||||||
|
case SORT_ORDER:
|
||||||
|
case SORT_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
result = strcmp(ca->name, cb->name);
|
||||||
|
|
||||||
|
if (sort_crit->reversed)
|
||||||
|
result = -result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_session_cmp(const void *a0, const void *b0)
|
||||||
|
{
|
||||||
|
struct sort_criteria *sort_crit = sort_criteria;
|
||||||
|
const struct session *const *a = a0;
|
||||||
|
const struct session *const *b = b0;
|
||||||
|
const struct session *sa = *a;
|
||||||
|
const struct session *sb = *b;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
switch (sort_crit->order) {
|
||||||
|
case SORT_INDEX:
|
||||||
|
result = sa->id - sb->id;
|
||||||
|
break;
|
||||||
|
case SORT_CREATION:
|
||||||
|
if (timercmp(&sa->creation_time, &sb->creation_time, >)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (timercmp(&sa->creation_time, &sb->creation_time, <)) {
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SORT_ACTIVITY:
|
||||||
|
if (timercmp(&sa->activity_time, &sb->activity_time, >)) {
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (timercmp(&sa->activity_time, &sb->activity_time, <)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SORT_NAME:
|
||||||
|
result = strcmp(sa->name, sb->name);
|
||||||
|
break;
|
||||||
|
case SORT_MODIFIER:
|
||||||
|
case SORT_ORDER:
|
||||||
|
case SORT_SIZE:
|
||||||
|
case SORT_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
result = strcmp(sa->name, sb->name);
|
||||||
|
|
||||||
|
if (sort_crit->reversed)
|
||||||
|
result = -result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_pane_cmp(const void *a0, const void *b0)
|
||||||
|
{
|
||||||
|
struct sort_criteria *sort_crit = sort_criteria;
|
||||||
|
struct window_pane *a = *(struct window_pane **)a0;
|
||||||
|
struct window_pane *b = *(struct window_pane **)b0;
|
||||||
|
int result = 0;
|
||||||
|
u_int ai, bi;
|
||||||
|
|
||||||
|
switch (sort_crit->order) {
|
||||||
|
case SORT_ACTIVITY:
|
||||||
|
result = a->active_point - b->active_point;
|
||||||
|
break;
|
||||||
|
case SORT_CREATION:
|
||||||
|
result = a->id - b->id;
|
||||||
|
break;
|
||||||
|
case SORT_SIZE:
|
||||||
|
result = a->sx * a->sy - b->sx * b->sy;
|
||||||
|
break;
|
||||||
|
case SORT_INDEX:
|
||||||
|
window_pane_index(a, &ai);
|
||||||
|
window_pane_index(b, &bi);
|
||||||
|
result = ai - bi;
|
||||||
|
break;
|
||||||
|
case SORT_NAME:
|
||||||
|
result = strcmp(a->screen->title, b->screen->title);
|
||||||
|
break;
|
||||||
|
case SORT_MODIFIER:
|
||||||
|
case SORT_ORDER:
|
||||||
|
case SORT_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
result = strcmp(a->screen->title, b->screen->title);
|
||||||
|
|
||||||
|
if (sort_crit->reversed)
|
||||||
|
result = -result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_winlink_cmp(const void *a0, const void *b0)
|
||||||
|
{
|
||||||
|
struct sort_criteria *sort_crit = sort_criteria;
|
||||||
|
const struct winlink *const *a = a0;
|
||||||
|
const struct winlink *const *b = b0;
|
||||||
|
const struct winlink *wla = *a;
|
||||||
|
const struct winlink *wlb = *b;
|
||||||
|
struct window *wa = wla->window;
|
||||||
|
struct window *wb = wlb->window;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
switch (sort_crit->order) {
|
||||||
|
case SORT_INDEX:
|
||||||
|
result = wla->idx - wlb->idx;
|
||||||
|
break;
|
||||||
|
case SORT_CREATION:
|
||||||
|
if (timercmp(&wa->creation_time, &wb->creation_time, >)) {
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (timercmp(&wa->creation_time, &wb->creation_time, <)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SORT_ACTIVITY:
|
||||||
|
if (timercmp(&wa->activity_time, &wb->activity_time, >)) {
|
||||||
|
result = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (timercmp(&wa->activity_time, &wb->activity_time, <)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SORT_NAME:
|
||||||
|
result = strcmp(wa->name, wb->name);
|
||||||
|
break;
|
||||||
|
case SORT_SIZE:
|
||||||
|
result = wa->sx * wa->sy - wb->sx * wb->sy;
|
||||||
|
break;
|
||||||
|
case SORT_MODIFIER:
|
||||||
|
case SORT_ORDER:
|
||||||
|
case SORT_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
result = strcmp(wa->name, wb->name);
|
||||||
|
|
||||||
|
if (sort_crit->reversed)
|
||||||
|
result = -result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sort_key_binding_cmp(const void *a0, const void *b0)
|
||||||
|
{
|
||||||
|
struct sort_criteria *sort_crit = sort_criteria;
|
||||||
|
const struct key_binding *a = *(struct key_binding **)a0;
|
||||||
|
const struct key_binding *b = *(struct key_binding **)b0;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
switch (sort_crit->order) {
|
||||||
|
case SORT_INDEX:
|
||||||
|
result = a->key - b->key;
|
||||||
|
break;
|
||||||
|
case SORT_MODIFIER:
|
||||||
|
result = (a->key & KEYC_MASK_MODIFIERS) -
|
||||||
|
(b->key & KEYC_MASK_MODIFIERS);
|
||||||
|
break;
|
||||||
|
case SORT_NAME:
|
||||||
|
result = strcasecmp(a->tablename, b->tablename) == 0;
|
||||||
|
break;
|
||||||
|
case SORT_ACTIVITY:
|
||||||
|
case SORT_CREATION:
|
||||||
|
case SORT_ORDER:
|
||||||
|
case SORT_SIZE:
|
||||||
|
case SORT_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
result = strcasecmp(a->tablename, b->tablename) == 0;
|
||||||
|
|
||||||
|
if (sort_crit->reversed)
|
||||||
|
result = -result;
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sort_next_order(struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
|
||||||
|
if (sort_crit->order_seq == NULL)
|
||||||
|
return;
|
||||||
|
for (i = 0; sort_crit->order_seq[i] != SORT_END; i++) {
|
||||||
|
if (sort_crit->order == sort_crit->order_seq[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort_crit->order_seq[i] == SORT_END)
|
||||||
|
i = 0;
|
||||||
|
else {
|
||||||
|
i++;
|
||||||
|
if (sort_crit->order_seq[i] == SORT_END)
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
sort_crit->order = sort_crit->order_seq[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum sort_order
|
||||||
|
sort_order_from_string(const char* order)
|
||||||
|
{
|
||||||
|
if (order != NULL) {
|
||||||
|
if (strcasecmp(order, "activity") == 0)
|
||||||
|
return (SORT_ACTIVITY);
|
||||||
|
if (strcasecmp(order, "creation") == 0)
|
||||||
|
return (SORT_CREATION);
|
||||||
|
if (strcasecmp(order, "index") == 0 ||
|
||||||
|
strcasecmp(order, "key") == 0)
|
||||||
|
return (SORT_INDEX);
|
||||||
|
if (strcasecmp(order, "modifier") == 0)
|
||||||
|
return (SORT_MODIFIER);
|
||||||
|
if (strcasecmp(order, "name") == 0 ||
|
||||||
|
strcasecmp(order, "title") == 0)
|
||||||
|
return (SORT_NAME);
|
||||||
|
if (strcasecmp(order, "order") == 0)
|
||||||
|
return (SORT_ORDER);
|
||||||
|
if (strcasecmp(order, "size") == 0)
|
||||||
|
return (SORT_SIZE);
|
||||||
|
}
|
||||||
|
return (SORT_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
sort_order_to_string(enum sort_order order)
|
||||||
|
{
|
||||||
|
if (order == SORT_ACTIVITY)
|
||||||
|
return "activity";
|
||||||
|
if (order == SORT_CREATION)
|
||||||
|
return "creation";
|
||||||
|
if (order == SORT_INDEX)
|
||||||
|
return "index";
|
||||||
|
if (order == SORT_MODIFIER)
|
||||||
|
return "modifier";
|
||||||
|
if (order == SORT_NAME)
|
||||||
|
return "name";
|
||||||
|
if (order == SORT_ORDER)
|
||||||
|
return "order";
|
||||||
|
if (order == SORT_SIZE)
|
||||||
|
return "size";
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sort_would_window_tree_swap(struct sort_criteria *sort_crit,
|
||||||
|
struct winlink *wla, struct winlink *wlb)
|
||||||
|
{
|
||||||
|
if (sort_crit->order == SORT_INDEX)
|
||||||
|
return (0);
|
||||||
|
sort_criteria = sort_crit;
|
||||||
|
return (sort_winlink_cmp(&wla, &wlb) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct paste_buffer **
|
||||||
|
sort_get_buffers(u_int *n, struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct paste_buffer *pb = NULL;
|
||||||
|
u_int i;
|
||||||
|
static struct paste_buffer **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while ((pb = paste_walk(pb)) != NULL) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = pb;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_buffer_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct client **
|
||||||
|
sort_get_clients(u_int *n, struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct client *c;
|
||||||
|
u_int i;
|
||||||
|
static struct client **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_client_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct session **
|
||||||
|
sort_get_sessions(u_int *n, struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct session *s;
|
||||||
|
u_int i;
|
||||||
|
static struct session **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_session_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct window_pane **
|
||||||
|
sort_get_panes(u_int *n, struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct session *s;
|
||||||
|
struct winlink *wl;
|
||||||
|
struct window *w;
|
||||||
|
struct window_pane *wp;
|
||||||
|
u_int i;
|
||||||
|
static struct window_pane **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
w = wl->window;
|
||||||
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_pane_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct window_pane **
|
||||||
|
sort_get_panes_session(struct session *s, u_int *n,
|
||||||
|
struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct winlink *wl = NULL;
|
||||||
|
struct window *w = NULL;
|
||||||
|
struct window_pane *wp = NULL;
|
||||||
|
u_int i;
|
||||||
|
static struct window_pane **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_pane_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct window_pane **
|
||||||
|
sort_get_panes_window(struct window *w, u_int *n,
|
||||||
|
struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct window_pane *wp;
|
||||||
|
u_int i;
|
||||||
|
static struct window_pane **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = wp;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_pane_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct winlink **
|
||||||
|
sort_get_winlinks(u_int *n, struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct session *s;
|
||||||
|
struct winlink *wl;
|
||||||
|
u_int i;
|
||||||
|
static struct winlink **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = wl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_winlink_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct winlink **
|
||||||
|
sort_get_winlinks_session(struct session *s, u_int *n,
|
||||||
|
struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct winlink *wl;
|
||||||
|
u_int i;
|
||||||
|
static struct winlink **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = wl;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_winlink_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct key_binding **
|
||||||
|
sort_get_key_bindings(u_int *n, struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct key_table *table;
|
||||||
|
struct key_binding *bd;
|
||||||
|
u_int i = 0;
|
||||||
|
static struct key_binding **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
table = key_bindings_first_table();
|
||||||
|
while (table != NULL) {
|
||||||
|
bd = key_bindings_first(table);
|
||||||
|
while (bd != NULL) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = bd;
|
||||||
|
bd = key_bindings_next(table, bd);
|
||||||
|
}
|
||||||
|
table = key_bindings_next_table(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_key_binding_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct key_binding **
|
||||||
|
sort_get_key_bindings_table(struct key_table *table, u_int *n,
|
||||||
|
struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
struct key_binding *bd;
|
||||||
|
u_int i = 0;
|
||||||
|
static struct key_binding **l = NULL;
|
||||||
|
static u_int lsz = 0;
|
||||||
|
|
||||||
|
bd = key_bindings_first(table);
|
||||||
|
while (bd != NULL) {
|
||||||
|
if (lsz <= i) {
|
||||||
|
lsz += 100;
|
||||||
|
l = xreallocarray(l, lsz, sizeof *l);
|
||||||
|
}
|
||||||
|
l[i++] = bd;
|
||||||
|
bd = key_bindings_next(table, bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
sort_qsort(l, i, sizeof *l, sort_key_binding_cmp, sort_crit);
|
||||||
|
*n = i;
|
||||||
|
|
||||||
|
return (l);
|
||||||
|
}
|
||||||
43
spawn.c
43
spawn.c
@@ -211,7 +211,9 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
|||||||
struct environ *child;
|
struct environ *child;
|
||||||
struct environ_entry *ee;
|
struct environ_entry *ee;
|
||||||
char **argv, *cp, **argvp, *argv0, *cwd, *new_cwd;
|
char **argv, *cp, **argvp, *argv0, *cwd, *new_cwd;
|
||||||
const char *cmd, *tmp;
|
char path[PATH_MAX];
|
||||||
|
const char *cmd, *tmp, *home = find_home();
|
||||||
|
const char *actual_cwd = NULL;
|
||||||
int argc;
|
int argc;
|
||||||
u_int idx;
|
u_int idx;
|
||||||
struct termios now;
|
struct termios now;
|
||||||
@@ -274,6 +276,13 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
|||||||
layout_assign_pane(sc->lc, new_wp, 0);
|
layout_assign_pane(sc->lc, new_wp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If window currently zoomed, window_set_active_pane calls
|
||||||
|
* window_unzoom which it copies back the saved_layout_cell.
|
||||||
|
*/
|
||||||
|
if (w->flags & WINDOW_ZOOMED)
|
||||||
|
new_wp->saved_layout_cell = new_wp->layout_cell;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we have a pane with nothing running in it ready for the new
|
* Now we have a pane with nothing running in it ready for the new
|
||||||
* process. Work out the command and arguments and store the working
|
* process. Work out the command and arguments and store the working
|
||||||
@@ -366,6 +375,16 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
|||||||
goto complete;
|
goto complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store current working directory and change to new one. */
|
||||||
|
if (getcwd(path, sizeof path) != NULL) {
|
||||||
|
if (chdir(new_wp->cwd) == 0)
|
||||||
|
actual_cwd = new_wp->cwd;
|
||||||
|
else if (home != NULL && chdir(home) == 0)
|
||||||
|
actual_cwd = home;
|
||||||
|
else if (chdir("/") == 0)
|
||||||
|
actual_cwd = "/";
|
||||||
|
}
|
||||||
|
|
||||||
/* Fork the new process. */
|
/* Fork the new process. */
|
||||||
new_wp->pid = fdforkpty(ptm_fd, &new_wp->fd, new_wp->tty, NULL, &ws);
|
new_wp->pid = fdforkpty(ptm_fd, &new_wp->fd, new_wp->tty, NULL, &ws);
|
||||||
if (new_wp->pid == -1) {
|
if (new_wp->pid == -1) {
|
||||||
@@ -381,8 +400,15 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In the parent process, everything is done now. */
|
/*
|
||||||
|
* In the parent process, everything is done now. Change the working
|
||||||
|
* directory back.
|
||||||
|
*/
|
||||||
if (new_wp->pid != 0) {
|
if (new_wp->pid != 0) {
|
||||||
|
if (actual_cwd != NULL &&
|
||||||
|
chdir(path) != 0 &&
|
||||||
|
(home == NULL || chdir(home) != 0))
|
||||||
|
chdir("/");
|
||||||
goto complete;
|
goto complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,17 +423,10 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Child process. Change to the working directory or home if that
|
* Child process. Set PWD to the working directory.
|
||||||
* fails.
|
|
||||||
*/
|
*/
|
||||||
if (chdir(new_wp->cwd) == 0)
|
if (actual_cwd != NULL)
|
||||||
environ_set(child, "PWD", 0, "%s", new_wp->cwd);
|
environ_set(child, "PWD", 0, "%s", actual_cwd);
|
||||||
else if ((tmp = find_home()) != NULL && chdir(tmp) == 0)
|
|
||||||
environ_set(child, "PWD", 0, "%s", tmp);
|
|
||||||
else if (chdir("/") == 0)
|
|
||||||
environ_set(child, "PWD", 0, "/");
|
|
||||||
else
|
|
||||||
fatal("chdir failed");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update terminal escape characters from the session if available and
|
* Update terminal escape characters from the session if available and
|
||||||
|
|||||||
33
status.c
33
status.c
@@ -264,14 +264,19 @@ status_line_size(struct client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the prompt line number for client's session. 1 means at the bottom. */
|
/* Get the prompt line number for client's session. 1 means at the bottom. */
|
||||||
static u_int
|
u_int
|
||||||
status_prompt_line_at(struct client *c)
|
status_prompt_line_at(struct client *c)
|
||||||
{
|
{
|
||||||
struct session *s = c->session;
|
struct session *s = c->session;
|
||||||
|
u_int line, lines;
|
||||||
|
|
||||||
if (c->flags & (CLIENT_STATUSOFF|CLIENT_CONTROL))
|
lines = status_line_size(c);
|
||||||
return (1);
|
if (lines == 0)
|
||||||
return (options_get_number(s->options, "message-line"));
|
return (0);
|
||||||
|
line = options_get_number(s->options, "message-line");
|
||||||
|
if (line >= lines)
|
||||||
|
return (lines - 1);
|
||||||
|
return (line);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get window at window list position. */
|
/* Get window at window list position. */
|
||||||
@@ -799,7 +804,10 @@ status_prompt_redraw(struct client *c)
|
|||||||
|
|
||||||
n = options_get_number(s->options, "prompt-cursor-colour");
|
n = options_get_number(s->options, "prompt-cursor-colour");
|
||||||
sl->active->default_ccolour = n;
|
sl->active->default_ccolour = n;
|
||||||
n = options_get_number(s->options, "prompt-cursor-style");
|
if (c->prompt_mode == PROMPT_COMMAND)
|
||||||
|
n = options_get_number(s->options, "prompt-command-cursor-style");
|
||||||
|
else
|
||||||
|
n = options_get_number(s->options, "prompt-cursor-style");
|
||||||
screen_set_cursor_style(n, &sl->active->default_cstyle,
|
screen_set_cursor_style(n, &sl->active->default_cstyle,
|
||||||
&sl->active->default_mode);
|
&sl->active->default_mode);
|
||||||
|
|
||||||
@@ -931,6 +939,8 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
|
|||||||
return (1);
|
return (1);
|
||||||
case '\033': /* Escape */
|
case '\033': /* Escape */
|
||||||
c->prompt_mode = PROMPT_COMMAND;
|
c->prompt_mode = PROMPT_COMMAND;
|
||||||
|
if (c->prompt_index != 0)
|
||||||
|
c->prompt_index--;
|
||||||
c->flags |= CLIENT_REDRAWSTATUS;
|
c->flags |= CLIENT_REDRAWSTATUS;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -956,10 +966,11 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
|
|||||||
*new_key = 'u'|KEYC_CTRL;
|
*new_key = 'u'|KEYC_CTRL;
|
||||||
return (1);
|
return (1);
|
||||||
case 'i':
|
case 'i':
|
||||||
case '\033': /* Escape */
|
|
||||||
c->prompt_mode = PROMPT_ENTRY;
|
c->prompt_mode = PROMPT_ENTRY;
|
||||||
c->flags |= CLIENT_REDRAWSTATUS;
|
c->flags |= CLIENT_REDRAWSTATUS;
|
||||||
return (0);
|
return (0);
|
||||||
|
case '\033': /* Escape */
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
@@ -1372,6 +1383,11 @@ process_key:
|
|||||||
break;
|
break;
|
||||||
case KEYC_BSPACE:
|
case KEYC_BSPACE:
|
||||||
case 'h'|KEYC_CTRL:
|
case 'h'|KEYC_CTRL:
|
||||||
|
if (c->prompt_flags & PROMPT_BSPACE_EXIT && size == 0) {
|
||||||
|
if (c->prompt_inputcb(c, c->prompt_data, NULL, 1) == 0)
|
||||||
|
status_prompt_clear(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (c->prompt_index != 0) {
|
if (c->prompt_index != 0) {
|
||||||
if (c->prompt_index == size)
|
if (c->prompt_index == size)
|
||||||
c->prompt_buffer[--c->prompt_index].size = 0;
|
c->prompt_buffer[--c->prompt_index].size = 0;
|
||||||
@@ -1874,7 +1890,7 @@ status_prompt_complete_window_menu(struct client *c, struct session *s,
|
|||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
char **list = NULL, *tmp;
|
char **list = NULL, *tmp;
|
||||||
u_int lines = status_line_size(c), height;
|
u_int lines = status_line_size(c), height;
|
||||||
u_int py, size = 0;
|
u_int py, size = 0, i;
|
||||||
|
|
||||||
if (c->tty.sy - lines < 3)
|
if (c->tty.sy - lines < 3)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -1953,6 +1969,9 @@ status_prompt_complete_window_menu(struct client *c, struct session *s,
|
|||||||
BOX_LINES_DEFAULT, NULL, NULL, NULL, NULL,
|
BOX_LINES_DEFAULT, NULL, NULL, NULL, NULL,
|
||||||
status_prompt_menu_callback, spm) != 0) {
|
status_prompt_menu_callback, spm) != 0) {
|
||||||
menu_free(menu);
|
menu_free(menu);
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
free(list[i]);
|
||||||
|
free(list);
|
||||||
free(spm);
|
free(spm);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
35
style.c
35
style.c
@@ -218,20 +218,23 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
|
|||||||
sy->gc.attr = 0;
|
sy->gc.attr = 0;
|
||||||
else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
|
else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
|
||||||
if (strcmp(tmp + 2, "attr") == 0)
|
if (strcmp(tmp + 2, "attr") == 0)
|
||||||
value = 0xffff & ~GRID_ATTR_CHARSET;
|
sy->gc.attr |= GRID_ATTR_NOATTR;
|
||||||
else if ((value = attributes_fromstring(tmp + 2)) == -1)
|
else {
|
||||||
goto error;
|
value = attributes_fromstring(tmp + 2);
|
||||||
sy->gc.attr &= ~value;
|
if (value == -1)
|
||||||
|
goto error;
|
||||||
|
sy->gc.attr &= ~value;
|
||||||
|
}
|
||||||
} else if (end > 6 && strncasecmp(tmp, "width=", 6) == 0) {
|
} else if (end > 6 && strncasecmp(tmp, "width=", 6) == 0) {
|
||||||
n = strtonum(tmp + 6, 0, UINT_MAX, &errstr);
|
n = strtonum(tmp + 6, 0, UINT_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
goto error;
|
goto error;
|
||||||
sy->width = (int)n;
|
sy->width = (int)n;
|
||||||
} else if (end > 4 && strncasecmp(tmp, "pad=", 4) == 0) {
|
} else if (end > 4 && strncasecmp(tmp, "pad=", 4) == 0) {
|
||||||
n = strtonum(tmp + 4, 0, UINT_MAX, &errstr);
|
n = strtonum(tmp + 4, 0, UINT_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
goto error;
|
goto error;
|
||||||
sy->pad = (int)n;
|
sy->pad = (int)n;
|
||||||
} else {
|
} else {
|
||||||
if ((value = attributes_fromstring(tmp)) == -1)
|
if ((value = attributes_fromstring(tmp)) == -1)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -344,13 +347,13 @@ style_tostring(struct style *sy)
|
|||||||
attributes_tostring(gc->attr));
|
attributes_tostring(gc->attr));
|
||||||
comma = ",";
|
comma = ",";
|
||||||
}
|
}
|
||||||
if (sy->width >= 0) {
|
if (sy->width >= 0) {
|
||||||
xsnprintf(s + off, sizeof s - off, "%swidth=%u", comma,
|
xsnprintf(s + off, sizeof s - off, "%swidth=%u", comma,
|
||||||
sy->width);
|
sy->width);
|
||||||
comma = ",";
|
comma = ",";
|
||||||
}
|
}
|
||||||
if (sy->pad >= 0) {
|
if (sy->pad >= 0) {
|
||||||
xsnprintf(s + off, sizeof s - off, "%spad=%u", comma,
|
xsnprintf(s + off, sizeof s - off, "%spad=%u", comma,
|
||||||
sy->pad);
|
sy->pad);
|
||||||
comma = ",";
|
comma = ",";
|
||||||
}
|
}
|
||||||
|
|||||||
255
tmux.1
255
tmux.1
@@ -841,6 +841,7 @@ Each has a single-character alternative form.
|
|||||||
.It Li "{last}" Ta "!" Ta "The last (previously current) window"
|
.It Li "{last}" Ta "!" Ta "The last (previously current) window"
|
||||||
.It Li "{next}" Ta "+" Ta "The next window by number"
|
.It Li "{next}" Ta "+" Ta "The next window by number"
|
||||||
.It Li "{previous}" Ta "-" Ta "The previous window by number"
|
.It Li "{previous}" Ta "-" Ta "The previous window by number"
|
||||||
|
.It Li "{current}" Ta "@" Ta "The current window"
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
.Ar target-pane
|
.Ar target-pane
|
||||||
@@ -873,6 +874,7 @@ The following special tokens are available for the pane index:
|
|||||||
.It Li "{down-of}" Ta "" Ta "The pane below the active pane"
|
.It Li "{down-of}" Ta "" Ta "The pane below the active pane"
|
||||||
.It Li "{left-of}" Ta "" Ta "The pane to the left of the active pane"
|
.It Li "{left-of}" Ta "" Ta "The pane to the left of the active pane"
|
||||||
.It Li "{right-of}" Ta "" Ta "The pane to the right of the active pane"
|
.It Li "{right-of}" Ta "" Ta "The pane to the right of the active pane"
|
||||||
|
.It Li "{active}" Ta "@" Ta "The active pane"
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The tokens
|
The tokens
|
||||||
@@ -1183,8 +1185,10 @@ flag clears alerts (bell, activity, or silence) in all windows linked to the
|
|||||||
session.
|
session.
|
||||||
.Tg lsc
|
.Tg lsc
|
||||||
.It Xo Ic list-clients
|
.It Xo Ic list-clients
|
||||||
|
.Op Fl r
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsc
|
.D1 Pq alias: Ic lsc
|
||||||
@@ -1197,6 +1201,16 @@ Only clients for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
section.
|
||||||
|
.Fl O
|
||||||
|
specifies the sort order: one of
|
||||||
|
.Ql name ,
|
||||||
|
.Ql size ,
|
||||||
|
.Ql creation
|
||||||
|
(time), or
|
||||||
|
.Ql activity
|
||||||
|
(time).
|
||||||
|
.Fl r
|
||||||
|
reverses the sort order.
|
||||||
If
|
If
|
||||||
.Ar target-session
|
.Ar target-session
|
||||||
is specified, list only clients connected to that session.
|
is specified, list only clients connected to that session.
|
||||||
@@ -1212,8 +1226,10 @@ or - if omitted - of all commands supported by
|
|||||||
.Nm .
|
.Nm .
|
||||||
.Tg ls
|
.Tg ls
|
||||||
.It Xo Ic list-sessions
|
.It Xo Ic list-sessions
|
||||||
|
.Op Fl r
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic ls
|
.D1 Pq alias: Ic ls
|
||||||
List all sessions managed by the server.
|
List all sessions managed by the server.
|
||||||
@@ -1225,6 +1241,16 @@ Only sessions for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
section.
|
||||||
|
.Fl O
|
||||||
|
specifies the sort order: one of
|
||||||
|
.Ql index ,
|
||||||
|
.Ql name ,
|
||||||
|
.Ql creation
|
||||||
|
(time), or
|
||||||
|
.Ql activity
|
||||||
|
(time).
|
||||||
|
.Fl r
|
||||||
|
reverses the sort order.
|
||||||
.Tg lockc
|
.Tg lockc
|
||||||
.It Ic lock-client Op Fl t Ar target-client
|
.It Ic lock-client Op Fl t Ar target-client
|
||||||
.D1 Pq alias: Ic lockc
|
.D1 Pq alias: Ic lockc
|
||||||
@@ -1363,12 +1389,11 @@ and sets an environment variable for the newly created session; it may be
|
|||||||
specified multiple times.
|
specified multiple times.
|
||||||
.Tg refresh
|
.Tg refresh
|
||||||
.It Xo Ic refresh-client
|
.It Xo Ic refresh-client
|
||||||
.Op Fl cDLRSU
|
.Op Fl cDlLRSU
|
||||||
.Op Fl A Ar pane:state
|
.Op Fl A Ar pane:state
|
||||||
.Op Fl B Ar name:what:format
|
.Op Fl B Ar name:what:format
|
||||||
.Op Fl C Ar size
|
.Op Fl C Ar size
|
||||||
.Op Fl f Ar flags
|
.Op Fl f Ar flags
|
||||||
.Op Fl l Op Ar target-pane
|
|
||||||
.Op Fl r Ar pane:report
|
.Op Fl r Ar pane:report
|
||||||
.Op Fl t Ar target-client
|
.Op Fl t Ar target-client
|
||||||
.Op Ar adjustment
|
.Op Ar adjustment
|
||||||
@@ -1489,11 +1514,7 @@ a colon, then a report escape sequence.
|
|||||||
.Fl l
|
.Fl l
|
||||||
requests the clipboard from the client using the
|
requests the clipboard from the client using the
|
||||||
.Xr xterm 1
|
.Xr xterm 1
|
||||||
escape sequence.
|
escape sequence and stores it in a new paste buffer.
|
||||||
If
|
|
||||||
.Ar target-pane
|
|
||||||
is given, the clipboard is sent (in encoded form), otherwise it is stored in a
|
|
||||||
new paste buffer.
|
|
||||||
.Pp
|
.Pp
|
||||||
.Fl L ,
|
.Fl L ,
|
||||||
.Fl R ,
|
.Fl R ,
|
||||||
@@ -1626,6 +1647,7 @@ Suspend a client by sending
|
|||||||
.It Xo Ic switch-client
|
.It Xo Ic switch-client
|
||||||
.Op Fl ElnprZ
|
.Op Fl ElnprZ
|
||||||
.Op Fl c Ar target-client
|
.Op Fl c Ar target-client
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Op Fl T Ar key-table
|
.Op Fl T Ar key-table
|
||||||
.Xc
|
.Xc
|
||||||
@@ -1652,6 +1674,18 @@ or
|
|||||||
.Fl p
|
.Fl p
|
||||||
is used, the client is moved to the last, next or previous session
|
is used, the client is moved to the last, next or previous session
|
||||||
respectively.
|
respectively.
|
||||||
|
.Fl O
|
||||||
|
may be used with
|
||||||
|
.Fl n
|
||||||
|
and
|
||||||
|
.Fl p
|
||||||
|
to specify the field to sort on: one of
|
||||||
|
.Ql name ,
|
||||||
|
.Ql size ,
|
||||||
|
.Ql creation
|
||||||
|
(time), or
|
||||||
|
.Ql activity
|
||||||
|
(time).
|
||||||
.Fl r
|
.Fl r
|
||||||
toggles the client
|
toggles the client
|
||||||
.Ic read-only
|
.Ic read-only
|
||||||
@@ -1668,9 +1702,10 @@ is used,
|
|||||||
option will not be applied.
|
option will not be applied.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl T
|
.Fl T
|
||||||
sets the client's key table; the next key from the client will be interpreted
|
sets the client's key table; the next key will be looked up using
|
||||||
from
|
|
||||||
.Ar key-table .
|
.Ar key-table .
|
||||||
|
After that key, the client is returned to its default key table (normally
|
||||||
|
.Em root ) .
|
||||||
This may be used to configure multiple prefix keys, or to bind commands to
|
This may be used to configure multiple prefix keys, or to bind commands to
|
||||||
sequences of keys.
|
sequences of keys.
|
||||||
For example, to make typing
|
For example, to make typing
|
||||||
@@ -2212,12 +2247,31 @@ Same as
|
|||||||
.Ic scroll-down
|
.Ic scroll-down
|
||||||
but also exit copy mode if the cursor reaches the bottom.
|
but also exit copy mode if the cursor reaches the bottom.
|
||||||
.It Xo
|
.It Xo
|
||||||
|
.Ic scroll-exit-on
|
||||||
|
.Xc
|
||||||
|
Turn on exiting copy mode when scrolling to the end of the buffer.
|
||||||
|
.It Xo
|
||||||
|
.Ic scroll-exit-off
|
||||||
|
.Xc
|
||||||
|
Turn off exiting copy mode when scrolling to the end of the buffer.
|
||||||
|
.It Xo
|
||||||
|
.Ic scroll-exit-toggle
|
||||||
|
.Xc
|
||||||
|
Toggle exiting copy mode when scrolling to the end of the buffer.
|
||||||
|
.It Xo
|
||||||
.Ic scroll-middle
|
.Ic scroll-middle
|
||||||
(vi: z)
|
(vi: z)
|
||||||
.Xc
|
.Xc
|
||||||
Scroll so that the current line becomes the middle one while keeping the
|
Scroll so that the current line becomes the middle one while keeping the
|
||||||
cursor on that line.
|
cursor on that line.
|
||||||
.It Xo
|
.It Xo
|
||||||
|
.Ic scroll-to-mouse
|
||||||
|
.Xc
|
||||||
|
Scroll pane in copy-mode when bound to a mouse drag event.
|
||||||
|
.Fl e
|
||||||
|
causes copy mode to exit when at the bottom.
|
||||||
|
.Pp
|
||||||
|
.It Xo
|
||||||
.Ic scroll-top
|
.Ic scroll-top
|
||||||
.Xc
|
.Xc
|
||||||
Scroll down until the current line is at the top while keeping the cursor on
|
Scroll down until the current line is at the top while keeping the cursor on
|
||||||
@@ -2454,12 +2508,10 @@ cancels copy mode and any other modes.
|
|||||||
.Fl M
|
.Fl M
|
||||||
begins a mouse drag (only valid if bound to a mouse key binding, see
|
begins a mouse drag (only valid if bound to a mouse key binding, see
|
||||||
.Sx MOUSE SUPPORT ) .
|
.Sx MOUSE SUPPORT ) .
|
||||||
|
.Pp
|
||||||
.Fl S
|
.Fl S
|
||||||
scrolls when bound to a mouse drag event; for example,
|
enters copy-mode and scrolls when bound to a mouse drag event; See
|
||||||
.Ic copy-mode -Se
|
.Ic scroll-to-mouse .
|
||||||
is bound to
|
|
||||||
.Ar MouseDrag1ScrollbarSlider
|
|
||||||
by default.
|
|
||||||
.Pp
|
.Pp
|
||||||
.Fl s
|
.Fl s
|
||||||
copies from
|
copies from
|
||||||
@@ -2666,7 +2718,7 @@ The following keys may be used in client mode:
|
|||||||
.It Li "z" Ta "Suspend selected client"
|
.It Li "z" Ta "Suspend selected client"
|
||||||
.It Li "Z" Ta "Suspend tagged clients"
|
.It Li "Z" Ta "Suspend tagged clients"
|
||||||
.It Li "f" Ta "Enter a format to filter items"
|
.It Li "f" Ta "Enter a format to filter items"
|
||||||
.It Li "O" Ta "Change sort field"
|
.It Li "O" Ta "Change sort order"
|
||||||
.It Li "r" Ta "Reverse sort order"
|
.It Li "r" Ta "Reverse sort order"
|
||||||
.It Li "v" Ta "Toggle preview"
|
.It Li "v" Ta "Toggle preview"
|
||||||
.It Li "q" Ta "Exit mode"
|
.It Li "q" Ta "Exit mode"
|
||||||
@@ -2682,12 +2734,11 @@ If
|
|||||||
is not given, "detach-client -t \[aq]%%\[aq]" is used.
|
is not given, "detach-client -t \[aq]%%\[aq]" is used.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl O
|
.Fl O
|
||||||
specifies the initial sort field: one of
|
specifies the initial sort order: one of
|
||||||
.Ql name ,
|
.Ql name ,
|
||||||
.Ql size ,
|
.Ql size ,
|
||||||
.Ql creation
|
.Ql creation
|
||||||
(time),
|
(time), or
|
||||||
or
|
|
||||||
.Ql activity
|
.Ql activity
|
||||||
(time).
|
(time).
|
||||||
.Fl r
|
.Fl r
|
||||||
@@ -2754,7 +2805,7 @@ The following keys may be used in tree mode:
|
|||||||
.It Li "\&:" Ta "Run a command for each tagged item"
|
.It Li "\&:" Ta "Run a command for each tagged item"
|
||||||
.It Li "f" Ta "Enter a format to filter items"
|
.It Li "f" Ta "Enter a format to filter items"
|
||||||
.It Li "H" Ta "Jump to the starting pane"
|
.It Li "H" Ta "Jump to the starting pane"
|
||||||
.It Li "O" Ta "Change sort field"
|
.It Li "O" Ta "Change sort order"
|
||||||
.It Li "r" Ta "Reverse sort order"
|
.It Li "r" Ta "Reverse sort order"
|
||||||
.It Li "v" Ta "Toggle preview"
|
.It Li "v" Ta "Toggle preview"
|
||||||
.It Li "q" Ta "Exit mode"
|
.It Li "q" Ta "Exit mode"
|
||||||
@@ -2772,12 +2823,12 @@ If
|
|||||||
is not given, "switch-client -t \[aq]%%\[aq]" is used.
|
is not given, "switch-client -t \[aq]%%\[aq]" is used.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl O
|
.Fl O
|
||||||
specifies the initial sort field: one of
|
specifies the initial sort order: one of
|
||||||
.Ql index ,
|
.Ql index ,
|
||||||
.Ql name ,
|
.Ql name ,
|
||||||
or
|
or
|
||||||
.Ql time
|
.Ql activity
|
||||||
(activity).
|
(time).
|
||||||
.Fl r
|
.Fl r
|
||||||
reverses the sort order.
|
reverses the sort order.
|
||||||
.Fl f
|
.Fl f
|
||||||
@@ -3023,9 +3074,10 @@ If
|
|||||||
is given, the newly linked window is not selected.
|
is given, the newly linked window is not selected.
|
||||||
.Tg lsp
|
.Tg lsp
|
||||||
.It Xo Ic list-panes
|
.It Xo Ic list-panes
|
||||||
.Op Fl as
|
.Op Fl ars
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl t Ar target
|
.Op Fl t Ar target
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsp
|
.D1 Pq alias: Ic lsp
|
||||||
@@ -3050,11 +3102,25 @@ Only panes for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
section.
|
||||||
|
.Fl O
|
||||||
|
specifies the sort order: one of
|
||||||
|
.Ql name
|
||||||
|
(title),
|
||||||
|
.Ql index ,
|
||||||
|
.Ql size
|
||||||
|
(area),
|
||||||
|
.Ql creation
|
||||||
|
(time), or
|
||||||
|
.Ql activity
|
||||||
|
(time).
|
||||||
|
.Fl r
|
||||||
|
reverses the sort order.
|
||||||
.Tg lsw
|
.Tg lsw
|
||||||
.It Xo Ic list-windows
|
.It Xo Ic list-windows
|
||||||
.Op Fl a
|
.Op Fl ar
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl t Ar target-session
|
.Op Fl t Ar target-session
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsw
|
.D1 Pq alias: Ic lsw
|
||||||
@@ -3071,6 +3137,19 @@ Only windows for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
section.
|
||||||
|
.Fl O
|
||||||
|
specifies the sort order: one of
|
||||||
|
.Ql index ,
|
||||||
|
.Ql name ,
|
||||||
|
.Ql size
|
||||||
|
(area),
|
||||||
|
.Ql creation
|
||||||
|
(time),
|
||||||
|
or
|
||||||
|
.Ql activity
|
||||||
|
(time).
|
||||||
|
.Fl r
|
||||||
|
reverses the sort order.
|
||||||
.Tg movep
|
.Tg movep
|
||||||
.It Xo Ic move-pane
|
.It Xo Ic move-pane
|
||||||
.Op Fl bdfhv
|
.Op Fl bdfhv
|
||||||
@@ -3760,24 +3839,45 @@ To view the default bindings and possible commands, see the
|
|||||||
command.
|
command.
|
||||||
.Tg lsk
|
.Tg lsk
|
||||||
.It Xo Ic list-keys
|
.It Xo Ic list-keys
|
||||||
.Op Fl 1aN
|
.Op Fl 1aNr
|
||||||
|
.Op Fl F Ar format
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Op Fl P Ar prefix-string
|
.Op Fl P Ar prefix-string
|
||||||
.Op Fl T Ar key-table
|
.Op Fl T Ar key-table
|
||||||
.Op Ar key
|
.Op Ar key
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsk
|
.D1 Pq alias: Ic lsk
|
||||||
List key bindings.
|
List key bindings.
|
||||||
There are two forms: the default lists keys as
|
.Fl F
|
||||||
|
specifies the format of each line.
|
||||||
|
See the
|
||||||
|
.Sx FORMATS
|
||||||
|
section.
|
||||||
|
.Fl T
|
||||||
|
specifies a
|
||||||
|
.Ar key-table
|
||||||
|
to list from.
|
||||||
|
.Fl 1
|
||||||
|
lists only the first matching key.
|
||||||
|
.Fl O
|
||||||
|
specifies the sort order: one of
|
||||||
|
.Ql key ,
|
||||||
|
.Ql modifier ,
|
||||||
|
.Ql name
|
||||||
|
(table name).
|
||||||
|
.Fl r
|
||||||
|
reverses the sort order.
|
||||||
|
.Pp
|
||||||
|
If no
|
||||||
|
.Ar format
|
||||||
|
is given, there are two forms: the default lists keys as
|
||||||
.Ic bind-key
|
.Ic bind-key
|
||||||
commands;
|
commands;
|
||||||
.Fl N
|
.Fl N
|
||||||
lists only keys with attached notes and shows only the key and note for each
|
lists only keys with attached notes and shows only the key and note for each
|
||||||
key.
|
key.
|
||||||
.Pp
|
.Pp
|
||||||
With the default form, all key tables are listed by default.
|
With the default form, all key tables are listed unless specified otherwise.
|
||||||
.Fl T
|
|
||||||
lists only keys in
|
|
||||||
.Ar key-table .
|
|
||||||
.Pp
|
.Pp
|
||||||
With the
|
With the
|
||||||
.Fl N
|
.Fl N
|
||||||
@@ -3790,9 +3890,7 @@ key tables are listed by default;
|
|||||||
also lists only keys in
|
also lists only keys in
|
||||||
.Ar key-table .
|
.Ar key-table .
|
||||||
.Fl P
|
.Fl P
|
||||||
specifies a prefix to print before each key and
|
specifies a prefix to print before each key.
|
||||||
.Fl 1
|
|
||||||
lists only the first matching key.
|
|
||||||
.Fl a
|
.Fl a
|
||||||
lists the command for keys that do not have a note rather than skipping them.
|
lists the command for keys that do not have a note rather than skipping them.
|
||||||
.Tg send
|
.Tg send
|
||||||
@@ -4241,6 +4339,38 @@ passed through to applications running in
|
|||||||
.Nm .
|
.Nm .
|
||||||
Attached clients should be detached and attached again after changing this
|
Attached clients should be detached and attached again after changing this
|
||||||
option.
|
option.
|
||||||
|
.It Xo Ic focus-follows-mouse
|
||||||
|
.Op Ic on | off
|
||||||
|
.Xc
|
||||||
|
When enabled and
|
||||||
|
.Ic mouse
|
||||||
|
is on, moving the mouse into a pane selects it.
|
||||||
|
.It Xo Ic get-clipboard
|
||||||
|
.Op Ic both | request | buffer | off
|
||||||
|
.Xc
|
||||||
|
Controls the behaviour when an application requests the clipboard from
|
||||||
|
.Nm .
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Ic off ,
|
||||||
|
the request is ignored;
|
||||||
|
if
|
||||||
|
.Ic buffer ,
|
||||||
|
.Nm
|
||||||
|
responds with the newest paste buffer;
|
||||||
|
.Ic request
|
||||||
|
causes
|
||||||
|
.Nm
|
||||||
|
to request the clipboard from the most recently used client (if possible) and
|
||||||
|
send the reply (if any) back to the application;
|
||||||
|
.Ic buffer
|
||||||
|
is the same as
|
||||||
|
.Ic request
|
||||||
|
but also creates a paste buffer.
|
||||||
|
.Pp
|
||||||
|
See also the
|
||||||
|
.Ic set-clipboard
|
||||||
|
option.
|
||||||
.It Ic history-file Ar path
|
.It Ic history-file Ar path
|
||||||
If not empty, a file to which
|
If not empty, a file to which
|
||||||
.Nm
|
.Nm
|
||||||
@@ -4550,9 +4680,7 @@ If set to 0, messages and indicators are displayed until a key is pressed.
|
|||||||
.Ar time
|
.Ar time
|
||||||
is in milliseconds.
|
is in milliseconds.
|
||||||
.It Ic history-limit Ar lines
|
.It Ic history-limit Ar lines
|
||||||
Set the maximum number of lines held in window history.
|
Set the maximum number of lines held in pane history.
|
||||||
This setting applies only to new windows - existing window histories are not
|
|
||||||
resized and retain the limit at the point they were created.
|
|
||||||
.It Ic initial-repeat-time Ar time
|
.It Ic initial-repeat-time Ar time
|
||||||
Set the time in milliseconds for the initial repeat when a key is bound with the
|
Set the time in milliseconds for the initial repeat when a key is bound with the
|
||||||
.Fl r
|
.Fl r
|
||||||
@@ -4669,6 +4797,12 @@ Set the style of the cursor in the command prompt.
|
|||||||
See the
|
See the
|
||||||
.Ic cursor-style
|
.Ic cursor-style
|
||||||
options for available styles.
|
options for available styles.
|
||||||
|
.It Ic prompt-command-cursor-style Ar style
|
||||||
|
Set the style of the cursor in the command prompt when vi keys are enabled and
|
||||||
|
the prompt is in command mode.
|
||||||
|
See the
|
||||||
|
.Ic cursor-style
|
||||||
|
options for available styles.
|
||||||
.It Xo Ic renumber-windows
|
.It Xo Ic renumber-windows
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
@@ -6133,9 +6267,17 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "host" Ta "#H" Ta "Hostname of local host"
|
.It Li "host" Ta "#H" Ta "Hostname of local host"
|
||||||
.It Li "host_short" Ta "#h" Ta "Hostname of local host (no domain name)"
|
.It Li "host_short" Ta "#h" Ta "Hostname of local host (no domain name)"
|
||||||
.It Li "insert_flag" Ta "" Ta "Pane insert flag"
|
.It Li "insert_flag" Ta "" Ta "Pane insert flag"
|
||||||
|
.It Li "key_string" Ta "" Ta "String representation of the key binding"
|
||||||
|
.It Li "key_repeat" Ta "" Ta "1 if key binding is repeatable"
|
||||||
|
.It Li "key_note" Ta "" Ta "Note of the key binding"
|
||||||
|
.It Li "key_prefix" Ta "" Ta "Global key prefix"
|
||||||
|
.It Li "key_table" Ta "" Ta "Table name of the key binding"
|
||||||
|
.It Li "key_command" Ta "" Ta "Command of the key binding"
|
||||||
|
.It Li "key_has_repeat" Ta "" Ta "1 if list contain a repeatable key"
|
||||||
|
.It Li "key_string_width" Ta "" Ta "Maximum key_string width in list"
|
||||||
|
.It Li "key_table_width" Ta "" Ta "Maximum key_table width in list"
|
||||||
.It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag"
|
.It Li "keypad_cursor_flag" Ta "" Ta "Pane keypad cursor flag"
|
||||||
.It Li "keypad_flag" Ta "" Ta "Pane keypad flag"
|
.It Li "keypad_flag" Ta "" Ta "Pane keypad flag"
|
||||||
.It Li "last_session_index" Ta "" Ta "Index of last session"
|
|
||||||
.It Li "last_window_index" Ta "" Ta "Index of last window in session"
|
.It Li "last_window_index" Ta "" Ta "Index of last window in session"
|
||||||
.It Li "line" Ta "" Ta "Line number in the list"
|
.It Li "line" Ta "" Ta "Line number in the list"
|
||||||
.It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop"
|
.It Li "loop_last_flag" Ta "" Ta "1 if last window, pane, session, client in the W:, P:, S:, or L: loop"
|
||||||
@@ -6168,6 +6310,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "pane_dead_status" Ta "" Ta "Exit status of process in dead pane"
|
.It Li "pane_dead_status" Ta "" Ta "Exit status of process in dead pane"
|
||||||
.It Li "pane_dead_time" Ta "" Ta "Exit time of process in dead pane"
|
.It Li "pane_dead_time" Ta "" Ta "Exit time of process in dead pane"
|
||||||
.It Li "pane_fg" Ta "" Ta "Pane foreground colour"
|
.It Li "pane_fg" Ta "" Ta "Pane foreground colour"
|
||||||
|
.It Li "pane_floating_flag" Ta "" Ta "1 if pane is floating"
|
||||||
.It Li "pane_format" Ta "" Ta "1 if format is for a pane"
|
.It Li "pane_format" Ta "" Ta "1 if format is for a pane"
|
||||||
.It Li "pane_height" Ta "" Ta "Height of pane"
|
.It Li "pane_height" Ta "" Ta "Height of pane"
|
||||||
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
|
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
|
||||||
@@ -6183,6 +6326,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "pane_path" Ta "" Ta "Path of pane (can be set by application)"
|
.It Li "pane_path" Ta "" Ta "Path of pane (can be set by application)"
|
||||||
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
|
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
|
||||||
.It Li "pane_pipe" Ta "" Ta "1 if pane is being piped"
|
.It Li "pane_pipe" Ta "" Ta "1 if pane is being piped"
|
||||||
|
.It Li "pane_pipe_pid" Ta "" Ta "PID of pipe process, if any"
|
||||||
.It Li "pane_right" Ta "" Ta "Right of pane"
|
.It Li "pane_right" Ta "" Ta "Right of pane"
|
||||||
.It Li "pane_search_string" Ta "" Ta "Last search string in copy mode"
|
.It Li "pane_search_string" Ta "" Ta "Last search string in copy mode"
|
||||||
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
|
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
|
||||||
@@ -6206,6 +6350,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "selection_active" Ta "" Ta "1 if selection started and changes with the cursor in copy mode"
|
.It Li "selection_active" Ta "" Ta "1 if selection started and changes with the cursor in copy mode"
|
||||||
.It Li "selection_end_x" Ta "" Ta "X position of the end of the selection"
|
.It Li "selection_end_x" Ta "" Ta "X position of the end of the selection"
|
||||||
.It Li "selection_end_y" Ta "" Ta "Y position of the end of the selection"
|
.It Li "selection_end_y" Ta "" Ta "Y position of the end of the selection"
|
||||||
|
.It Li "selection_mode" Ta "" Ta "Selection mode"
|
||||||
.It Li "selection_present" Ta "" Ta "1 if selection started in copy mode"
|
.It Li "selection_present" Ta "" Ta "1 if selection started in copy mode"
|
||||||
.It Li "selection_start_x" Ta "" Ta "X position of the start of the selection"
|
.It Li "selection_start_x" Ta "" Ta "X position of the start of the selection"
|
||||||
.It Li "selection_start_y" Ta "" Ta "Y position of the start of the selection"
|
.It Li "selection_start_y" Ta "" Ta "Y position of the start of the selection"
|
||||||
@@ -6227,7 +6372,6 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "session_group_size" Ta "" Ta "Size of session group"
|
.It Li "session_group_size" Ta "" Ta "Size of session group"
|
||||||
.It Li "session_grouped" Ta "" Ta "1 if session in a group"
|
.It Li "session_grouped" Ta "" Ta "1 if session in a group"
|
||||||
.It Li "session_id" Ta "" Ta "Unique session ID"
|
.It Li "session_id" Ta "" Ta "Unique session ID"
|
||||||
.It Li "session_index" Ta "" Ta "Index of session"
|
|
||||||
.It Li "session_last_attached" Ta "" Ta "Time session last attached"
|
.It Li "session_last_attached" Ta "" Ta "Time session last attached"
|
||||||
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
|
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
|
||||||
.It Li "session_marked" Ta "" Ta "1 if this session contains the marked pane"
|
.It Li "session_marked" Ta "" Ta "1 if this session contains the marked pane"
|
||||||
@@ -6239,6 +6383,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "socket_path" Ta "" Ta "Server socket path"
|
.It Li "socket_path" Ta "" Ta "Server socket path"
|
||||||
.It Li "sixel_support" Ta "" Ta "1 if server has support for SIXEL"
|
.It Li "sixel_support" Ta "" Ta "1 if server has support for SIXEL"
|
||||||
.It Li "start_time" Ta "" Ta "Server start time"
|
.It Li "start_time" Ta "" Ta "Server start time"
|
||||||
|
.It Li "synchronized_output_flag" Ta "" Ta "1 if pane has synchronized output enabled"
|
||||||
.It Li "uid" Ta "" Ta "Server UID"
|
.It Li "uid" Ta "" Ta "Server UID"
|
||||||
.It Li "user" Ta "" Ta "Server user"
|
.It Li "user" Ta "" Ta "Server user"
|
||||||
.It Li "version" Ta "" Ta "Server version"
|
.It Li "version" Ta "" Ta "Server version"
|
||||||
@@ -6677,7 +6822,7 @@ See
|
|||||||
for possible values for
|
for possible values for
|
||||||
.Ar prompt-type .
|
.Ar prompt-type .
|
||||||
.It Xo Ic command-prompt
|
.It Xo Ic command-prompt
|
||||||
.Op Fl 1bFiklN
|
.Op Fl 1beFiklN
|
||||||
.Op Fl I Ar inputs
|
.Op Fl I Ar inputs
|
||||||
.Op Fl p Ar prompts
|
.Op Fl p Ar prompts
|
||||||
.Op Fl t Ar target-client
|
.Op Fl t Ar target-client
|
||||||
@@ -6750,6 +6895,10 @@ makes the prompt only accept numeric key presses.
|
|||||||
.Fl i
|
.Fl i
|
||||||
executes the command every time the prompt input changes instead of when the
|
executes the command every time the prompt input changes instead of when the
|
||||||
user exits the command prompt.
|
user exits the command prompt.
|
||||||
|
.Fl e
|
||||||
|
makes
|
||||||
|
.Em BSpace
|
||||||
|
cancel an empty prompt.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl T
|
.Fl T
|
||||||
tells
|
tells
|
||||||
@@ -7204,7 +7353,7 @@ The following keys may be used in buffer mode:
|
|||||||
.It Li "D" Ta "Delete tagged buffers"
|
.It Li "D" Ta "Delete tagged buffers"
|
||||||
.It Li "e" Ta "Open the buffer in an editor"
|
.It Li "e" Ta "Open the buffer in an editor"
|
||||||
.It Li "f" Ta "Enter a format to filter items"
|
.It Li "f" Ta "Enter a format to filter items"
|
||||||
.It Li "O" Ta "Change sort field"
|
.It Li "O" Ta "Change sort order"
|
||||||
.It Li "r" Ta "Reverse sort order"
|
.It Li "r" Ta "Reverse sort order"
|
||||||
.It Li "v" Ta "Toggle preview"
|
.It Li "v" Ta "Toggle preview"
|
||||||
.It Li "q" Ta "Exit mode"
|
.It Li "q" Ta "Exit mode"
|
||||||
@@ -7220,10 +7369,10 @@ If
|
|||||||
is not given, "paste-buffer -p -b \[aq]%%\[aq]" is used.
|
is not given, "paste-buffer -p -b \[aq]%%\[aq]" is used.
|
||||||
.Pp
|
.Pp
|
||||||
.Fl O
|
.Fl O
|
||||||
specifies the initial sort field: one of
|
specifies the initial sort order: one of
|
||||||
.Ql time
|
.Ql creation
|
||||||
(creation),
|
(time),
|
||||||
.Ql name
|
.Ql name ,
|
||||||
or
|
or
|
||||||
.Ql size .
|
.Ql size .
|
||||||
.Fl r
|
.Fl r
|
||||||
@@ -7256,8 +7405,10 @@ Delete the buffer named
|
|||||||
or the most recently added automatically named buffer if not specified.
|
or the most recently added automatically named buffer if not specified.
|
||||||
.Tg lsb
|
.Tg lsb
|
||||||
.It Xo Ic list-buffers
|
.It Xo Ic list-buffers
|
||||||
|
.Op Fl r
|
||||||
.Op Fl F Ar format
|
.Op Fl F Ar format
|
||||||
.Op Fl f Ar filter
|
.Op Fl f Ar filter
|
||||||
|
.Op Fl O Ar sort-order
|
||||||
.Xc
|
.Xc
|
||||||
.D1 Pq alias: Ic lsb
|
.D1 Pq alias: Ic lsb
|
||||||
List the global buffers.
|
List the global buffers.
|
||||||
@@ -7269,6 +7420,15 @@ Only buffers for which the filter is true are shown.
|
|||||||
See the
|
See the
|
||||||
.Sx FORMATS
|
.Sx FORMATS
|
||||||
section.
|
section.
|
||||||
|
.Fl O
|
||||||
|
specifies the sort order: one of
|
||||||
|
.Ql name ,
|
||||||
|
.Ql size ,
|
||||||
|
or
|
||||||
|
.Ql creation
|
||||||
|
(time).
|
||||||
|
.Fl r
|
||||||
|
reverses the sort order.
|
||||||
.It Xo Ic load-buffer
|
.It Xo Ic load-buffer
|
||||||
.Op Fl w
|
.Op Fl w
|
||||||
.Op Fl b Ar buffer-name
|
.Op Fl b Ar buffer-name
|
||||||
@@ -7293,7 +7453,7 @@ is
|
|||||||
the contents are read from stdin.
|
the contents are read from stdin.
|
||||||
.Tg pasteb
|
.Tg pasteb
|
||||||
.It Xo Ic paste-buffer
|
.It Xo Ic paste-buffer
|
||||||
.Op Fl dpr
|
.Op Fl dprS
|
||||||
.Op Fl b Ar buffer-name
|
.Op Fl b Ar buffer-name
|
||||||
.Op Fl s Ar separator
|
.Op Fl s Ar separator
|
||||||
.Op Fl t Ar target-pane
|
.Op Fl t Ar target-pane
|
||||||
@@ -7301,9 +7461,14 @@ the contents are read from stdin.
|
|||||||
.D1 Pq alias: Ic pasteb
|
.D1 Pq alias: Ic pasteb
|
||||||
Insert the contents of a paste buffer into the specified pane.
|
Insert the contents of a paste buffer into the specified pane.
|
||||||
If not specified, paste into the current one.
|
If not specified, paste into the current one.
|
||||||
|
By default, control characters are sanitized with
|
||||||
|
.Xr vis 3 ;
|
||||||
|
.Fl S
|
||||||
|
disables this.
|
||||||
With
|
With
|
||||||
.Fl d ,
|
.Fl d ,
|
||||||
also delete the paste buffer.
|
also delete the paste buffer.
|
||||||
|
.Pp
|
||||||
When output, any linefeed (LF) characters in the paste buffer are replaced with
|
When output, any linefeed (LF) characters in the paste buffer are replaced with
|
||||||
a separator, by default carriage return (CR).
|
a separator, by default carriage return (CR).
|
||||||
A custom separator may be specified using the
|
A custom separator may be specified using the
|
||||||
|
|||||||
233
tmux.h
233
tmux.h
@@ -652,6 +652,7 @@ enum tty_code_code {
|
|||||||
#define MODE_CURSOR_BLINKING_SET 0x20000
|
#define MODE_CURSOR_BLINKING_SET 0x20000
|
||||||
#define MODE_KEYS_EXTENDED_2 0x40000
|
#define MODE_KEYS_EXTENDED_2 0x40000
|
||||||
#define MODE_THEME_UPDATES 0x80000
|
#define MODE_THEME_UPDATES 0x80000
|
||||||
|
#define MODE_SYNC 0x100000
|
||||||
|
|
||||||
#define ALL_MODES 0xffffff
|
#define ALL_MODES 0xffffff
|
||||||
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
|
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
|
||||||
@@ -727,6 +728,7 @@ struct colour_palette {
|
|||||||
#define GRID_ATTR_UNDERSCORE_4 0x800
|
#define GRID_ATTR_UNDERSCORE_4 0x800
|
||||||
#define GRID_ATTR_UNDERSCORE_5 0x1000
|
#define GRID_ATTR_UNDERSCORE_5 0x1000
|
||||||
#define GRID_ATTR_OVERLINE 0x2000
|
#define GRID_ATTR_OVERLINE 0x2000
|
||||||
|
#define GRID_ATTR_NOATTR 0x4000
|
||||||
|
|
||||||
/* All underscore attributes. */
|
/* All underscore attributes. */
|
||||||
#define GRID_ATTR_ALL_UNDERSCORE \
|
#define GRID_ATTR_ALL_UNDERSCORE \
|
||||||
@@ -954,7 +956,7 @@ struct screen_sel;
|
|||||||
struct screen_titles;
|
struct screen_titles;
|
||||||
struct screen {
|
struct screen {
|
||||||
char *title;
|
char *title;
|
||||||
char *path;
|
char *path;
|
||||||
struct screen_titles *titles;
|
struct screen_titles *titles;
|
||||||
|
|
||||||
struct grid *grid; /* grid data */
|
struct grid *grid; /* grid data */
|
||||||
@@ -1061,8 +1063,8 @@ struct screen_redraw_ctx {
|
|||||||
|
|
||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
u_int ox;
|
int ox;
|
||||||
u_int oy;
|
int oy;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Screen size. */
|
/* Screen size. */
|
||||||
@@ -1099,6 +1101,7 @@ struct window_mode {
|
|||||||
void (*free)(struct window_mode_entry *);
|
void (*free)(struct window_mode_entry *);
|
||||||
void (*resize)(struct window_mode_entry *, u_int, u_int);
|
void (*resize)(struct window_mode_entry *, u_int, u_int);
|
||||||
void (*update)(struct window_mode_entry *);
|
void (*update)(struct window_mode_entry *);
|
||||||
|
void (*style_changed)(struct window_mode_entry *);
|
||||||
void (*key)(struct window_mode_entry *, struct client *,
|
void (*key)(struct window_mode_entry *, struct client *,
|
||||||
struct session *, struct winlink *, key_code,
|
struct session *, struct winlink *, key_code,
|
||||||
struct mouse_event *);
|
struct mouse_event *);
|
||||||
@@ -1129,6 +1132,7 @@ struct window_mode_entry {
|
|||||||
/* Type of request to client. */
|
/* Type of request to client. */
|
||||||
enum input_request_type {
|
enum input_request_type {
|
||||||
INPUT_REQUEST_PALETTE,
|
INPUT_REQUEST_PALETTE,
|
||||||
|
INPUT_REQUEST_CLIPBOARD,
|
||||||
INPUT_REQUEST_QUEUE
|
INPUT_REQUEST_QUEUE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1138,6 +1142,13 @@ struct input_request_palette_data {
|
|||||||
int c;
|
int c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Clipboard request reply data. */
|
||||||
|
struct input_request_clipboard_data {
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
char clip;
|
||||||
|
};
|
||||||
|
|
||||||
/* Request sent to client on behalf of pane. */
|
/* Request sent to client on behalf of pane. */
|
||||||
TAILQ_HEAD(input_requests, input_request);
|
TAILQ_HEAD(input_requests, input_request);
|
||||||
|
|
||||||
@@ -1158,6 +1169,29 @@ struct window_pane_resize {
|
|||||||
};
|
};
|
||||||
TAILQ_HEAD(window_pane_resizes, window_pane_resize);
|
TAILQ_HEAD(window_pane_resizes, window_pane_resize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Client theme, this is worked out from the background colour if not reported
|
||||||
|
* by terminal.
|
||||||
|
*/
|
||||||
|
enum client_theme {
|
||||||
|
THEME_UNKNOWN,
|
||||||
|
THEME_LIGHT,
|
||||||
|
THEME_DARK
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Visible range array element. */
|
||||||
|
struct visible_range {
|
||||||
|
u_int px; /* start */
|
||||||
|
u_int nx; /* length */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Visible areas not obstructed. */
|
||||||
|
struct visible_ranges {
|
||||||
|
struct visible_range *ranges; /* dynamically allocated array */
|
||||||
|
u_int used; /* number of entries in ranges */
|
||||||
|
u_int size; /* allocated capacity of ranges */
|
||||||
|
};
|
||||||
|
|
||||||
/* Child window structure. */
|
/* Child window structure. */
|
||||||
struct window_pane {
|
struct window_pane {
|
||||||
u_int id;
|
u_int id;
|
||||||
@@ -1172,10 +1206,11 @@ struct window_pane {
|
|||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
|
|
||||||
u_int xoff;
|
int xoff;
|
||||||
u_int yoff;
|
int yoff;
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
|
int saved_flags;
|
||||||
#define PANE_REDRAW 0x1
|
#define PANE_REDRAW 0x1
|
||||||
#define PANE_DROP 0x2
|
#define PANE_DROP 0x2
|
||||||
#define PANE_FOCUSED 0x4
|
#define PANE_FOCUSED 0x4
|
||||||
@@ -1192,6 +1227,8 @@ struct window_pane {
|
|||||||
#define PANE_THEMECHANGED 0x2000
|
#define PANE_THEMECHANGED 0x2000
|
||||||
#define PANE_UNSEENCHANGES 0x4000
|
#define PANE_UNSEENCHANGES 0x4000
|
||||||
#define PANE_REDRAWSCROLLBAR 0x8000
|
#define PANE_REDRAWSCROLLBAR 0x8000
|
||||||
|
#define PANE_FLOATING 0x10000
|
||||||
|
#define PANE_MINIMISED 0x20000
|
||||||
|
|
||||||
u_int sb_slider_y;
|
u_int sb_slider_y;
|
||||||
u_int sb_slider_h;
|
u_int sb_slider_h;
|
||||||
@@ -1214,14 +1251,17 @@ struct window_pane {
|
|||||||
|
|
||||||
struct window_pane_resizes resize_queue;
|
struct window_pane_resizes resize_queue;
|
||||||
struct event resize_timer;
|
struct event resize_timer;
|
||||||
|
struct event sync_timer;
|
||||||
|
|
||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
struct grid_cell cached_gc;
|
struct grid_cell cached_gc;
|
||||||
struct grid_cell cached_active_gc;
|
struct grid_cell cached_active_gc;
|
||||||
struct colour_palette palette;
|
struct colour_palette palette;
|
||||||
|
enum client_theme last_theme;
|
||||||
|
|
||||||
int pipe_fd;
|
int pipe_fd;
|
||||||
|
pid_t pipe_pid;
|
||||||
struct bufferevent *pipe_event;
|
struct bufferevent *pipe_event;
|
||||||
struct window_pane_offset pipe_offset;
|
struct window_pane_offset pipe_offset;
|
||||||
|
|
||||||
@@ -1244,11 +1284,15 @@ struct window_pane {
|
|||||||
|
|
||||||
struct style scrollbar_style;
|
struct style scrollbar_style;
|
||||||
|
|
||||||
|
struct visible_ranges r;
|
||||||
|
|
||||||
TAILQ_ENTRY(window_pane) entry; /* link in list of all panes */
|
TAILQ_ENTRY(window_pane) entry; /* link in list of all panes */
|
||||||
TAILQ_ENTRY(window_pane) sentry; /* link in list of last visited */
|
TAILQ_ENTRY(window_pane) sentry; /* link in list of last visited */
|
||||||
|
TAILQ_ENTRY(window_pane) zentry; /* z-index link in list of all panes */
|
||||||
RB_ENTRY(window_pane) tree_entry;
|
RB_ENTRY(window_pane) tree_entry;
|
||||||
};
|
};
|
||||||
TAILQ_HEAD(window_panes, window_pane);
|
TAILQ_HEAD(window_panes, window_pane);
|
||||||
|
TAILQ_HEAD(window_panes_zindex, window_pane);
|
||||||
RB_HEAD(window_pane_tree, window_pane);
|
RB_HEAD(window_pane_tree, window_pane);
|
||||||
|
|
||||||
/* Window structure. */
|
/* Window structure. */
|
||||||
@@ -1264,9 +1308,11 @@ struct window {
|
|||||||
struct event offset_timer;
|
struct event offset_timer;
|
||||||
|
|
||||||
struct timeval activity_time;
|
struct timeval activity_time;
|
||||||
|
struct timeval creation_time;
|
||||||
|
|
||||||
struct window_pane *active;
|
struct window_pane *active;
|
||||||
struct window_panes last_panes;
|
struct window_panes last_panes;
|
||||||
|
struct window_panes z_index;
|
||||||
struct window_panes panes;
|
struct window_panes panes;
|
||||||
|
|
||||||
int lastlayout;
|
int lastlayout;
|
||||||
@@ -1360,6 +1406,7 @@ TAILQ_HEAD(winlink_stack, winlink);
|
|||||||
enum layout_type {
|
enum layout_type {
|
||||||
LAYOUT_LEFTRIGHT,
|
LAYOUT_LEFTRIGHT,
|
||||||
LAYOUT_TOPBOTTOM,
|
LAYOUT_TOPBOTTOM,
|
||||||
|
LAYOUT_FLOATING,
|
||||||
LAYOUT_WINDOWPANE
|
LAYOUT_WINDOWPANE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1578,6 +1625,7 @@ struct tty {
|
|||||||
size_t discarded;
|
size_t discarded;
|
||||||
|
|
||||||
struct termios tio;
|
struct termios tio;
|
||||||
|
struct visible_ranges r;
|
||||||
|
|
||||||
struct grid_cell cell;
|
struct grid_cell cell;
|
||||||
struct grid_cell last_cell;
|
struct grid_cell last_cell;
|
||||||
@@ -1609,7 +1657,7 @@ struct tty {
|
|||||||
int mouse_drag_flag;
|
int mouse_drag_flag;
|
||||||
int mouse_scrolling_flag;
|
int mouse_scrolling_flag;
|
||||||
int mouse_slider_mpos;
|
int mouse_slider_mpos;
|
||||||
|
struct window_pane *mouse_wp;
|
||||||
void (*mouse_drag_update)(struct client *,
|
void (*mouse_drag_update)(struct client *,
|
||||||
struct mouse_event *);
|
struct mouse_event *);
|
||||||
void (*mouse_drag_release)(struct client *,
|
void (*mouse_drag_release)(struct client *,
|
||||||
@@ -1655,10 +1703,10 @@ struct tty_ctx {
|
|||||||
u_int orlower;
|
u_int orlower;
|
||||||
|
|
||||||
/* Target region (usually pane) offset and size. */
|
/* Target region (usually pane) offset and size. */
|
||||||
u_int xoff;
|
int xoff;
|
||||||
u_int yoff;
|
int yoff;
|
||||||
u_int rxoff;
|
int rxoff;
|
||||||
u_int ryoff;
|
int ryoff;
|
||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
|
|
||||||
@@ -1675,6 +1723,9 @@ struct tty_ctx {
|
|||||||
u_int woy;
|
u_int woy;
|
||||||
u_int wsx;
|
u_int wsx;
|
||||||
u_int wsy;
|
u_int wsy;
|
||||||
|
|
||||||
|
/* tty partly obscured, it will need to be surgically scrolled. */
|
||||||
|
u_int obscured;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Saved message entry. */
|
/* Saved message entry. */
|
||||||
@@ -1894,32 +1945,15 @@ struct client_window {
|
|||||||
};
|
};
|
||||||
RB_HEAD(client_windows, client_window);
|
RB_HEAD(client_windows, client_window);
|
||||||
|
|
||||||
/* Visible areas not obstructed by overlays. */
|
|
||||||
#define OVERLAY_MAX_RANGES 3
|
|
||||||
struct overlay_ranges {
|
|
||||||
u_int px[OVERLAY_MAX_RANGES];
|
|
||||||
u_int nx[OVERLAY_MAX_RANGES];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Client theme, this is worked out from the background colour if not reported
|
|
||||||
* by terminal.
|
|
||||||
*/
|
|
||||||
enum client_theme {
|
|
||||||
THEME_UNKNOWN,
|
|
||||||
THEME_LIGHT,
|
|
||||||
THEME_DARK
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Client connection. */
|
/* Client connection. */
|
||||||
typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
|
typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
|
||||||
typedef void (*prompt_free_cb)(void *);
|
typedef void (*prompt_free_cb)(void *);
|
||||||
typedef void (*overlay_check_cb)(struct client*, void *, u_int, u_int, u_int,
|
typedef struct visible_ranges *(*overlay_check_cb)(struct client*, void *,
|
||||||
struct overlay_ranges *);
|
u_int, u_int, u_int);
|
||||||
typedef struct screen *(*overlay_mode_cb)(struct client *, void *, u_int *,
|
typedef struct screen *(*overlay_mode_cb)(struct client *, void *, u_int *,
|
||||||
u_int *);
|
u_int *);
|
||||||
typedef void (*overlay_draw_cb)(struct client *, void *,
|
typedef void (*overlay_draw_cb)(struct client *, void *,
|
||||||
struct screen_redraw_ctx *);
|
struct screen_redraw_ctx *);
|
||||||
typedef int (*overlay_key_cb)(struct client *, void *, struct key_event *);
|
typedef int (*overlay_key_cb)(struct client *, void *, struct key_event *);
|
||||||
typedef void (*overlay_free_cb)(struct client *, void *);
|
typedef void (*overlay_free_cb)(struct client *, void *);
|
||||||
typedef void (*overlay_resize_cb)(struct client *, void *);
|
typedef void (*overlay_resize_cb)(struct client *, void *);
|
||||||
@@ -1966,6 +2000,8 @@ struct client {
|
|||||||
struct event repeat_timer;
|
struct event repeat_timer;
|
||||||
|
|
||||||
struct event click_timer;
|
struct event click_timer;
|
||||||
|
int click_where;
|
||||||
|
int click_wp;
|
||||||
u_int click_button;
|
u_int click_button;
|
||||||
struct mouse_event click_event;
|
struct mouse_event click_event;
|
||||||
|
|
||||||
@@ -2009,7 +2045,7 @@ struct client {
|
|||||||
#define CLIENT_CONTROL_PAUSEAFTER 0x100000000ULL
|
#define CLIENT_CONTROL_PAUSEAFTER 0x100000000ULL
|
||||||
#define CLIENT_CONTROL_WAITEXIT 0x200000000ULL
|
#define CLIENT_CONTROL_WAITEXIT 0x200000000ULL
|
||||||
#define CLIENT_WINDOWSIZECHANGED 0x400000000ULL
|
#define CLIENT_WINDOWSIZECHANGED 0x400000000ULL
|
||||||
#define CLIENT_CLIPBOARDBUFFER 0x800000000ULL
|
/* 0x800000000ULL unused */
|
||||||
#define CLIENT_BRACKETPASTING 0x1000000000ULL
|
#define CLIENT_BRACKETPASTING 0x1000000000ULL
|
||||||
#define CLIENT_ASSUMEPASTING 0x2000000000ULL
|
#define CLIENT_ASSUMEPASTING 0x2000000000ULL
|
||||||
#define CLIENT_REDRAWSCROLLBARS 0x4000000000ULL
|
#define CLIENT_REDRAWSCROLLBARS 0x4000000000ULL
|
||||||
@@ -2076,6 +2112,7 @@ struct client {
|
|||||||
#define PROMPT_KEY 0x10
|
#define PROMPT_KEY 0x10
|
||||||
#define PROMPT_ACCEPT 0x20
|
#define PROMPT_ACCEPT 0x20
|
||||||
#define PROMPT_QUOTENEXT 0x40
|
#define PROMPT_QUOTENEXT 0x40
|
||||||
|
#define PROMPT_BSPACE_EXIT 0x80
|
||||||
int prompt_flags;
|
int prompt_flags;
|
||||||
enum prompt_type prompt_type;
|
enum prompt_type prompt_type;
|
||||||
int prompt_cursor;
|
int prompt_cursor;
|
||||||
@@ -2122,6 +2159,7 @@ struct key_binding {
|
|||||||
key_code key;
|
key_code key;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
const char *note;
|
const char *note;
|
||||||
|
const char *tablename;
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
#define KEY_BINDING_REPEAT 0x1
|
#define KEY_BINDING_REPEAT 0x1
|
||||||
@@ -2239,12 +2277,40 @@ struct spawn_context {
|
|||||||
#define SPAWN_FULLSIZE 0x20
|
#define SPAWN_FULLSIZE 0x20
|
||||||
#define SPAWN_EMPTY 0x40
|
#define SPAWN_EMPTY 0x40
|
||||||
#define SPAWN_ZOOM 0x80
|
#define SPAWN_ZOOM 0x80
|
||||||
|
#define SPAWN_FLOATING 0x100
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Mode tree sort order. */
|
/* Paste buffer. */
|
||||||
struct mode_tree_sort_criteria {
|
struct paste_buffer {
|
||||||
u_int field;
|
char *data;
|
||||||
int reversed;
|
size_t size;
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
time_t created;
|
||||||
|
int automatic;
|
||||||
|
u_int order;
|
||||||
|
|
||||||
|
RB_ENTRY(paste_buffer) name_entry;
|
||||||
|
RB_ENTRY(paste_buffer) time_entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Sort orders. */
|
||||||
|
enum sort_order {
|
||||||
|
SORT_ACTIVITY,
|
||||||
|
SORT_CREATION,
|
||||||
|
SORT_INDEX,
|
||||||
|
SORT_MODIFIER,
|
||||||
|
SORT_NAME,
|
||||||
|
SORT_ORDER,
|
||||||
|
SORT_SIZE,
|
||||||
|
SORT_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Sort criteria. */
|
||||||
|
struct sort_criteria {
|
||||||
|
enum sort_order order;
|
||||||
|
int reversed;
|
||||||
|
enum sort_order *order_seq; /* available sort orders */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* tmux.c */
|
/* tmux.c */
|
||||||
@@ -2300,14 +2366,13 @@ void cfg_print_causes(struct cmdq_item *);
|
|||||||
void cfg_show_causes(struct session *);
|
void cfg_show_causes(struct session *);
|
||||||
|
|
||||||
/* paste.c */
|
/* paste.c */
|
||||||
struct paste_buffer;
|
|
||||||
const char *paste_buffer_name(struct paste_buffer *);
|
const char *paste_buffer_name(struct paste_buffer *);
|
||||||
u_int paste_buffer_order(struct paste_buffer *);
|
u_int paste_buffer_order(struct paste_buffer *);
|
||||||
time_t paste_buffer_created(struct paste_buffer *);
|
time_t paste_buffer_created(struct paste_buffer *);
|
||||||
const char *paste_buffer_data(struct paste_buffer *, size_t *);
|
const char *paste_buffer_data(struct paste_buffer *, size_t *);
|
||||||
struct paste_buffer *paste_walk(struct paste_buffer *);
|
struct paste_buffer *paste_walk(struct paste_buffer *);
|
||||||
int paste_is_empty(void);
|
int paste_is_empty(void);
|
||||||
struct paste_buffer *paste_get_top(const char **);
|
struct paste_buffer *paste_get_top(char **);
|
||||||
struct paste_buffer *paste_get_name(const char *);
|
struct paste_buffer *paste_get_name(const char *);
|
||||||
void paste_free(struct paste_buffer *);
|
void paste_free(struct paste_buffer *);
|
||||||
void paste_add(const char *, char *, size_t);
|
void paste_add(const char *, char *, size_t);
|
||||||
@@ -2316,6 +2381,28 @@ int paste_set(char *, size_t, const char *, char **);
|
|||||||
void paste_replace(struct paste_buffer *, char *, size_t);
|
void paste_replace(struct paste_buffer *, char *, size_t);
|
||||||
char *paste_make_sample(struct paste_buffer *);
|
char *paste_make_sample(struct paste_buffer *);
|
||||||
|
|
||||||
|
/* sort.c */
|
||||||
|
void sort_next_order(struct sort_criteria *);
|
||||||
|
enum sort_order sort_order_from_string(const char *);
|
||||||
|
const char *sort_order_to_string(enum sort_order);
|
||||||
|
int sort_would_window_tree_swap(struct sort_criteria *,
|
||||||
|
struct winlink *, struct winlink *);
|
||||||
|
struct paste_buffer **sort_get_buffers(u_int *, struct sort_criteria *);
|
||||||
|
struct client **sort_get_clients(u_int *, struct sort_criteria *);
|
||||||
|
struct session **sort_get_sessions(u_int *, struct sort_criteria *);
|
||||||
|
struct window_pane **sort_get_panes(u_int *, struct sort_criteria *);
|
||||||
|
struct window_pane **sort_get_panes_session(struct session *, u_int *,
|
||||||
|
struct sort_criteria *);
|
||||||
|
struct window_pane **sort_get_panes_window(struct window *, u_int *,
|
||||||
|
struct sort_criteria *);
|
||||||
|
struct winlink **sort_get_winlinks(u_int *, struct sort_criteria *);
|
||||||
|
struct winlink **sort_get_winlinks_session(struct session *, u_int *,
|
||||||
|
struct sort_criteria *);
|
||||||
|
struct key_binding **sort_get_key_bindings(u_int *,
|
||||||
|
struct sort_criteria *);
|
||||||
|
struct key_binding **sort_get_key_bindings_table(struct key_table *,
|
||||||
|
u_int *, struct sort_criteria *);
|
||||||
|
|
||||||
/* format.c */
|
/* format.c */
|
||||||
#define FORMAT_STATUS 0x1
|
#define FORMAT_STATUS 0x1
|
||||||
#define FORMAT_FORCE 0x2
|
#define FORMAT_FORCE 0x2
|
||||||
@@ -2427,7 +2514,7 @@ struct options_entry *options_match_get(struct options *, const char *, int *,
|
|||||||
int, int *);
|
int, int *);
|
||||||
const char *options_get_string(struct options *, const char *);
|
const char *options_get_string(struct options *, const char *);
|
||||||
long long options_get_number(struct options *, const char *);
|
long long options_get_number(struct options *, const char *);
|
||||||
const struct cmd_list *options_get_command(struct options *, const char *);
|
struct cmd_list *options_get_command(struct options *, const char *);
|
||||||
struct options_entry * printflike(4, 5) options_set_string(struct options *,
|
struct options_entry * printflike(4, 5) options_set_string(struct options *,
|
||||||
const char *, int, const char *, ...);
|
const char *, int, const char *, ...);
|
||||||
struct options_entry *options_set_number(struct options *, const char *,
|
struct options_entry *options_set_number(struct options *, const char *,
|
||||||
@@ -2508,6 +2595,8 @@ void tty_reset(struct tty *);
|
|||||||
void tty_region_off(struct tty *);
|
void tty_region_off(struct tty *);
|
||||||
void tty_margin_off(struct tty *);
|
void tty_margin_off(struct tty *);
|
||||||
void tty_cursor(struct tty *, u_int, u_int);
|
void tty_cursor(struct tty *, u_int, u_int);
|
||||||
|
int tty_fake_bce(const struct tty *, const struct grid_cell *, u_int);
|
||||||
|
void tty_repeat_space(struct tty *, u_int);
|
||||||
void tty_clipboard_query(struct tty *);
|
void tty_clipboard_query(struct tty *);
|
||||||
void tty_putcode(struct tty *, enum tty_code_code);
|
void tty_putcode(struct tty *, enum tty_code_code);
|
||||||
void tty_putcode_i(struct tty *, enum tty_code_code, int);
|
void tty_putcode_i(struct tty *, enum tty_code_code, int);
|
||||||
@@ -2532,7 +2621,15 @@ void tty_repeat_requests(struct tty *, int);
|
|||||||
void tty_stop_tty(struct tty *);
|
void tty_stop_tty(struct tty *);
|
||||||
void tty_set_title(struct tty *, const char *);
|
void tty_set_title(struct tty *, const char *);
|
||||||
void tty_set_path(struct tty *, const char *);
|
void tty_set_path(struct tty *, const char *);
|
||||||
|
void tty_default_attributes(struct tty *, const struct grid_cell *,
|
||||||
|
struct colour_palette *, u_int, struct hyperlinks *);
|
||||||
void tty_update_mode(struct tty *, int, struct screen *);
|
void tty_update_mode(struct tty *, int, struct screen *);
|
||||||
|
const struct grid_cell *tty_check_codeset(struct tty *,
|
||||||
|
const struct grid_cell *);
|
||||||
|
struct visible_ranges *tty_check_overlay_range(struct tty *, u_int, u_int,
|
||||||
|
u_int);
|
||||||
|
|
||||||
|
/* tty-draw.c */
|
||||||
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int,
|
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int,
|
||||||
u_int, u_int, const struct grid_cell *, struct colour_palette *);
|
u_int, u_int, const struct grid_cell *, struct colour_palette *);
|
||||||
|
|
||||||
@@ -2724,6 +2821,8 @@ void cmd_list_append(struct cmd_list *, struct cmd *);
|
|||||||
void cmd_list_append_all(struct cmd_list *, struct cmd_list *);
|
void cmd_list_append_all(struct cmd_list *, struct cmd_list *);
|
||||||
void cmd_list_move(struct cmd_list *, struct cmd_list *);
|
void cmd_list_move(struct cmd_list *, struct cmd_list *);
|
||||||
void cmd_list_free(struct cmd_list *);
|
void cmd_list_free(struct cmd_list *);
|
||||||
|
#define CMD_LIST_PRINT_ESCAPED 0x1
|
||||||
|
#define CMD_LIST_PRINT_NO_GROUPS 0x2
|
||||||
char *cmd_list_print(const struct cmd_list *, int);
|
char *cmd_list_print(const struct cmd_list *, int);
|
||||||
struct cmd *cmd_list_first(struct cmd_list *);
|
struct cmd *cmd_list_first(struct cmd_list *);
|
||||||
struct cmd *cmd_list_next(struct cmd *);
|
struct cmd *cmd_list_next(struct cmd *);
|
||||||
@@ -2815,6 +2914,7 @@ void key_bindings_reset(const char *, key_code);
|
|||||||
void key_bindings_remove_table(const char *);
|
void key_bindings_remove_table(const char *);
|
||||||
void key_bindings_reset_table(const char *);
|
void key_bindings_reset_table(const char *);
|
||||||
void key_bindings_init(void);
|
void key_bindings_init(void);
|
||||||
|
int key_bindings_has_repeat(struct key_binding **, u_int);
|
||||||
struct cmdq_item *key_bindings_dispatch(struct key_binding *,
|
struct cmdq_item *key_bindings_dispatch(struct key_binding *,
|
||||||
struct cmdq_item *, struct client *, struct key_event *,
|
struct cmdq_item *, struct client *, struct key_event *,
|
||||||
struct cmd_find_state *);
|
struct cmd_find_state *);
|
||||||
@@ -2887,8 +2987,10 @@ void server_client_set_overlay(struct client *, u_int, overlay_check_cb,
|
|||||||
overlay_mode_cb, overlay_draw_cb, overlay_key_cb,
|
overlay_mode_cb, overlay_draw_cb, overlay_key_cb,
|
||||||
overlay_free_cb, overlay_resize_cb, void *);
|
overlay_free_cb, overlay_resize_cb, void *);
|
||||||
void server_client_clear_overlay(struct client *);
|
void server_client_clear_overlay(struct client *);
|
||||||
|
void server_client_ensure_ranges(struct visible_ranges *, u_int);
|
||||||
|
int server_client_ranges_is_empty(struct visible_ranges *);
|
||||||
void server_client_overlay_range(u_int, u_int, u_int, u_int, u_int, u_int,
|
void server_client_overlay_range(u_int, u_int, u_int, u_int, u_int, u_int,
|
||||||
u_int, struct overlay_ranges *);
|
u_int, struct visible_ranges *);
|
||||||
void server_client_set_key_table(struct client *, const char *);
|
void server_client_set_key_table(struct client *, const char *);
|
||||||
const char *server_client_get_key_table(struct client *);
|
const char *server_client_get_key_table(struct client *);
|
||||||
int server_client_check_nested(struct client *);
|
int server_client_check_nested(struct client *);
|
||||||
@@ -2943,6 +3045,7 @@ extern u_int status_prompt_hsize[];
|
|||||||
void status_timer_start(struct client *);
|
void status_timer_start(struct client *);
|
||||||
void status_timer_start_all(void);
|
void status_timer_start_all(void);
|
||||||
void status_update_cache(struct session *);
|
void status_update_cache(struct session *);
|
||||||
|
u_int status_prompt_line_at(struct client *);
|
||||||
int status_at_line(struct client *);
|
int status_at_line(struct client *);
|
||||||
u_int status_line_size(struct client *);
|
u_int status_line_size(struct client *);
|
||||||
struct style_range *status_get_range(struct client *, u_int, u_int);
|
struct style_range *status_get_range(struct client *, u_int, u_int);
|
||||||
@@ -2976,7 +3079,7 @@ void recalculate_sizes_now(int);
|
|||||||
/* input.c */
|
/* input.c */
|
||||||
#define INPUT_BUF_DEFAULT_SIZE 1048576
|
#define INPUT_BUF_DEFAULT_SIZE 1048576
|
||||||
struct input_ctx *input_init(struct window_pane *, struct bufferevent *,
|
struct input_ctx *input_init(struct window_pane *, struct bufferevent *,
|
||||||
struct colour_palette *);
|
struct colour_palette *, struct client *);
|
||||||
void input_free(struct input_ctx *);
|
void input_free(struct input_ctx *);
|
||||||
void input_reset(struct input_ctx *, int);
|
void input_reset(struct input_ctx *, int);
|
||||||
struct evbuffer *input_pending(struct input_ctx *);
|
struct evbuffer *input_pending(struct input_ctx *);
|
||||||
@@ -2985,7 +3088,7 @@ void input_parse_buffer(struct window_pane *, u_char *, size_t);
|
|||||||
void input_parse_screen(struct input_ctx *, struct screen *,
|
void input_parse_screen(struct input_ctx *, struct screen *,
|
||||||
screen_write_init_ctx_cb, void *, u_char *, size_t);
|
screen_write_init_ctx_cb, void *, u_char *, size_t);
|
||||||
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
|
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
|
||||||
const char *);
|
const char *, char);
|
||||||
void input_set_buffer_size(size_t);
|
void input_set_buffer_size(size_t);
|
||||||
void input_request_reply(struct client *, enum input_request_type, void *);
|
void input_request_reply(struct client *, enum input_request_type, void *);
|
||||||
void input_cancel_requests(struct client *);
|
void input_cancel_requests(struct client *);
|
||||||
@@ -3030,7 +3133,7 @@ int grid_cells_look_equal(const struct grid_cell *,
|
|||||||
struct grid *grid_create(u_int, u_int, u_int);
|
struct grid *grid_create(u_int, u_int, u_int);
|
||||||
void grid_destroy(struct grid *);
|
void grid_destroy(struct grid *);
|
||||||
int grid_compare(struct grid *, struct grid *);
|
int grid_compare(struct grid *, struct grid *);
|
||||||
void grid_collect_history(struct grid *);
|
void grid_collect_history(struct grid *, int);
|
||||||
void grid_remove_history(struct grid *, u_int );
|
void grid_remove_history(struct grid *, u_int );
|
||||||
void grid_scroll_history(struct grid *, u_int);
|
void grid_scroll_history(struct grid *, u_int);
|
||||||
void grid_scroll_history_region(struct grid *, u_int, u_int, u_int);
|
void grid_scroll_history_region(struct grid *, u_int, u_int, u_int);
|
||||||
@@ -3135,6 +3238,8 @@ void screen_write_preview(struct screen_write_ctx *, struct screen *, u_int,
|
|||||||
void screen_write_backspace(struct screen_write_ctx *);
|
void screen_write_backspace(struct screen_write_ctx *);
|
||||||
void screen_write_mode_set(struct screen_write_ctx *, int);
|
void screen_write_mode_set(struct screen_write_ctx *, int);
|
||||||
void screen_write_mode_clear(struct screen_write_ctx *, int);
|
void screen_write_mode_clear(struct screen_write_ctx *, int);
|
||||||
|
void screen_write_start_sync(struct window_pane *);
|
||||||
|
void screen_write_stop_sync(struct window_pane *);
|
||||||
void screen_write_cursorup(struct screen_write_ctx *, u_int);
|
void screen_write_cursorup(struct screen_write_ctx *, u_int);
|
||||||
void screen_write_cursordown(struct screen_write_ctx *, u_int);
|
void screen_write_cursordown(struct screen_write_ctx *, u_int);
|
||||||
void screen_write_cursorright(struct screen_write_ctx *, u_int);
|
void screen_write_cursorright(struct screen_write_ctx *, u_int);
|
||||||
@@ -3180,6 +3285,10 @@ void screen_write_alternateoff(struct screen_write_ctx *,
|
|||||||
/* screen-redraw.c */
|
/* screen-redraw.c */
|
||||||
void screen_redraw_screen(struct client *);
|
void screen_redraw_screen(struct client *);
|
||||||
void screen_redraw_pane(struct client *, struct window_pane *, int);
|
void screen_redraw_pane(struct client *, struct window_pane *, int);
|
||||||
|
int screen_redraw_is_visible(struct visible_ranges *, u_int px);
|
||||||
|
struct visible_ranges *screen_redraw_get_visible_ranges(struct window_pane *,
|
||||||
|
u_int, u_int, u_int, struct visible_ranges *);
|
||||||
|
|
||||||
|
|
||||||
/* screen.c */
|
/* screen.c */
|
||||||
void screen_init(struct screen *, u_int, u_int, u_int);
|
void screen_init(struct screen *, u_int, u_int, u_int);
|
||||||
@@ -3201,11 +3310,12 @@ void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int,
|
|||||||
void screen_clear_selection(struct screen *);
|
void screen_clear_selection(struct screen *);
|
||||||
void screen_hide_selection(struct screen *);
|
void screen_hide_selection(struct screen *);
|
||||||
int screen_check_selection(struct screen *, u_int, u_int);
|
int screen_check_selection(struct screen *, u_int, u_int);
|
||||||
void screen_select_cell(struct screen *, struct grid_cell *,
|
int screen_select_cell(struct screen *, struct grid_cell *,
|
||||||
const struct grid_cell *);
|
const struct grid_cell *);
|
||||||
void screen_alternate_on(struct screen *, struct grid_cell *, int);
|
void screen_alternate_on(struct screen *, struct grid_cell *, int);
|
||||||
void screen_alternate_off(struct screen *, struct grid_cell *, int);
|
void screen_alternate_off(struct screen *, struct grid_cell *, int);
|
||||||
const char *screen_mode_to_string(int);
|
const char *screen_mode_to_string(int);
|
||||||
|
const char *screen_print(struct screen *);
|
||||||
|
|
||||||
/* window.c */
|
/* window.c */
|
||||||
extern struct windows windows;
|
extern struct windows windows;
|
||||||
@@ -3241,6 +3351,8 @@ struct window_pane *window_find_string(struct window *, const char *);
|
|||||||
int window_has_pane(struct window *, struct window_pane *);
|
int window_has_pane(struct window *, struct window_pane *);
|
||||||
int window_set_active_pane(struct window *, struct window_pane *,
|
int window_set_active_pane(struct window *, struct window_pane *,
|
||||||
int);
|
int);
|
||||||
|
int window_deactivate_pane(struct window *, struct window_pane *,
|
||||||
|
int);
|
||||||
void window_update_focus(struct window *);
|
void window_update_focus(struct window *);
|
||||||
void window_pane_update_focus(struct window_pane *);
|
void window_pane_update_focus(struct window_pane *);
|
||||||
void window_redraw_active_switch(struct window *,
|
void window_redraw_active_switch(struct window *,
|
||||||
@@ -3267,6 +3379,7 @@ struct window_pane *window_pane_find_by_id_str(const char *);
|
|||||||
struct window_pane *window_pane_find_by_id(u_int);
|
struct window_pane *window_pane_find_by_id(u_int);
|
||||||
int window_pane_destroy_ready(struct window_pane *);
|
int window_pane_destroy_ready(struct window_pane *);
|
||||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||||
|
void window_pane_move(struct window_pane *, int, int);
|
||||||
int window_pane_set_mode(struct window_pane *,
|
int window_pane_set_mode(struct window_pane *,
|
||||||
struct window_pane *, const struct window_mode *,
|
struct window_pane *, const struct window_mode *,
|
||||||
struct cmd_find_state *, struct args *);
|
struct cmd_find_state *, struct args *);
|
||||||
@@ -3320,6 +3433,8 @@ void layout_free_cell(struct layout_cell *);
|
|||||||
void layout_print_cell(struct layout_cell *, const char *, u_int);
|
void layout_print_cell(struct layout_cell *, const char *, u_int);
|
||||||
void layout_destroy_cell(struct window *, struct layout_cell *,
|
void layout_destroy_cell(struct window *, struct layout_cell *,
|
||||||
struct layout_cell **);
|
struct layout_cell **);
|
||||||
|
void layout_minimise_cell(struct window *, struct layout_cell *);
|
||||||
|
void layout_unminimise_cell(struct window *, struct layout_cell *);
|
||||||
void layout_resize_layout(struct window *, struct layout_cell *,
|
void layout_resize_layout(struct window *, struct layout_cell *,
|
||||||
enum layout_type, int, int);
|
enum layout_type, int, int);
|
||||||
struct layout_cell *layout_search_by_border(struct layout_cell *, u_int, u_int);
|
struct layout_cell *layout_search_by_border(struct layout_cell *, u_int, u_int);
|
||||||
@@ -3327,6 +3442,7 @@ void layout_set_size(struct layout_cell *, u_int, u_int, u_int,
|
|||||||
u_int);
|
u_int);
|
||||||
void layout_make_leaf(struct layout_cell *, struct window_pane *);
|
void layout_make_leaf(struct layout_cell *, struct window_pane *);
|
||||||
void layout_make_node(struct layout_cell *, enum layout_type);
|
void layout_make_node(struct layout_cell *, enum layout_type);
|
||||||
|
void layout_fix_zindexes(struct window *, struct layout_cell *);
|
||||||
void layout_fix_offsets(struct window *);
|
void layout_fix_offsets(struct window *);
|
||||||
void layout_fix_panes(struct window *, struct window_pane *);
|
void layout_fix_panes(struct window *, struct window_pane *);
|
||||||
void layout_resize_adjust(struct window *, struct layout_cell *,
|
void layout_resize_adjust(struct window *, struct layout_cell *,
|
||||||
@@ -3347,7 +3463,7 @@ int layout_spread_cell(struct window *, struct layout_cell *);
|
|||||||
void layout_spread_out(struct window_pane *);
|
void layout_spread_out(struct window_pane *);
|
||||||
|
|
||||||
/* layout-custom.c */
|
/* layout-custom.c */
|
||||||
char *layout_dump(struct layout_cell *);
|
char *layout_dump(struct window *, struct layout_cell *);
|
||||||
int layout_parse(struct window *, const char *, char **);
|
int layout_parse(struct window *, const char *, char **);
|
||||||
|
|
||||||
/* layout-set.c */
|
/* layout-set.c */
|
||||||
@@ -3357,7 +3473,7 @@ u_int layout_set_next(struct window *);
|
|||||||
u_int layout_set_previous(struct window *);
|
u_int layout_set_previous(struct window *);
|
||||||
|
|
||||||
/* mode-tree.c */
|
/* mode-tree.c */
|
||||||
typedef void (*mode_tree_build_cb)(void *, struct mode_tree_sort_criteria *,
|
typedef void (*mode_tree_build_cb)(void *, struct sort_criteria *,
|
||||||
uint64_t *, const char *);
|
uint64_t *, const char *);
|
||||||
typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
|
typedef void (*mode_tree_draw_cb)(void *, void *, struct screen_write_ctx *,
|
||||||
u_int, u_int);
|
u_int, u_int);
|
||||||
@@ -3365,7 +3481,8 @@ typedef int (*mode_tree_search_cb)(void *, void *, const char *, int);
|
|||||||
typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code);
|
typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code);
|
||||||
typedef u_int (*mode_tree_height_cb)(void *, u_int);
|
typedef u_int (*mode_tree_height_cb)(void *, u_int);
|
||||||
typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
|
typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
|
||||||
typedef int (*mode_tree_swap_cb)(void *, void *);
|
typedef int (*mode_tree_swap_cb)(void *, void *, struct sort_criteria *);
|
||||||
|
typedef void (*mode_tree_sort_cb)(struct sort_criteria *);
|
||||||
typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code);
|
typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code);
|
||||||
u_int mode_tree_count_tagged(struct mode_tree_data *);
|
u_int mode_tree_count_tagged(struct mode_tree_data *);
|
||||||
void *mode_tree_get_current(struct mode_tree_data *);
|
void *mode_tree_get_current(struct mode_tree_data *);
|
||||||
@@ -3381,8 +3498,8 @@ int mode_tree_down(struct mode_tree_data *, int);
|
|||||||
struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
|
struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
|
||||||
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
|
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
|
||||||
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb,
|
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb,
|
||||||
mode_tree_swap_cb, void *, const struct menu_item *, const char **,
|
mode_tree_swap_cb, mode_tree_sort_cb, void *,
|
||||||
u_int, struct screen **);
|
const struct menu_item *, struct screen **);
|
||||||
void mode_tree_zoom(struct mode_tree_data *, struct args *);
|
void mode_tree_zoom(struct mode_tree_data *, struct args *);
|
||||||
void mode_tree_build(struct mode_tree_data *);
|
void mode_tree_build(struct mode_tree_data *);
|
||||||
void mode_tree_free(struct mode_tree_data *);
|
void mode_tree_free(struct mode_tree_data *);
|
||||||
@@ -3420,7 +3537,7 @@ void printflike(3, 4) window_copy_add(struct window_pane *, int, const char *,
|
|||||||
...);
|
...);
|
||||||
void printflike(3, 0) window_copy_vadd(struct window_pane *, int, const char *,
|
void printflike(3, 0) window_copy_vadd(struct window_pane *, int, const char *,
|
||||||
va_list);
|
va_list);
|
||||||
void window_copy_scroll(struct window_pane *, int, u_int, int);
|
void window_copy_scroll(struct window_pane *, int, u_int, u_int, int);
|
||||||
void window_copy_pageup(struct window_pane *, int);
|
void window_copy_pageup(struct window_pane *, int);
|
||||||
void window_copy_pagedown(struct window_pane *, int, int);
|
void window_copy_pagedown(struct window_pane *, int, int);
|
||||||
void window_copy_start_drag(struct client *, struct mouse_event *);
|
void window_copy_start_drag(struct client *, struct mouse_event *);
|
||||||
@@ -3492,8 +3609,9 @@ void session_add_ref(struct session *, const char *);
|
|||||||
void session_remove_ref(struct session *, const char *);
|
void session_remove_ref(struct session *, const char *);
|
||||||
char *session_check_name(const char *);
|
char *session_check_name(const char *);
|
||||||
void session_update_activity(struct session *, struct timeval *);
|
void session_update_activity(struct session *, struct timeval *);
|
||||||
struct session *session_next_session(struct session *);
|
struct session *session_next_session(struct session *, struct sort_criteria *);
|
||||||
struct session *session_previous_session(struct session *);
|
struct session *session_previous_session(struct session *,
|
||||||
|
struct sort_criteria *);
|
||||||
struct winlink *session_attach(struct session *, struct window *, int,
|
struct winlink *session_attach(struct session *, struct window *, int,
|
||||||
char **);
|
char **);
|
||||||
int session_detach(struct session *, struct winlink *);
|
int session_detach(struct session *, struct winlink *);
|
||||||
@@ -3514,6 +3632,7 @@ u_int session_group_count(struct session_group *);
|
|||||||
u_int session_group_attached_count(struct session_group *);
|
u_int session_group_attached_count(struct session_group *);
|
||||||
void session_renumber_windows(struct session *);
|
void session_renumber_windows(struct session *);
|
||||||
void session_theme_changed(struct session *);
|
void session_theme_changed(struct session *);
|
||||||
|
void session_update_history(struct session *);
|
||||||
|
|
||||||
/* utf8.c */
|
/* utf8.c */
|
||||||
enum utf8_state utf8_towc (const struct utf8_data *, wchar_t *);
|
enum utf8_state utf8_towc (const struct utf8_data *, wchar_t *);
|
||||||
@@ -3527,9 +3646,9 @@ void utf8_copy(struct utf8_data *, const struct utf8_data *);
|
|||||||
enum utf8_state utf8_open(struct utf8_data *, u_char);
|
enum utf8_state utf8_open(struct utf8_data *, u_char);
|
||||||
enum utf8_state utf8_append(struct utf8_data *, u_char);
|
enum utf8_state utf8_append(struct utf8_data *, u_char);
|
||||||
int utf8_isvalid(const char *);
|
int utf8_isvalid(const char *);
|
||||||
int utf8_strvis(char *, const char *, size_t, int);
|
size_t utf8_strvis(char *, const char *, size_t, int);
|
||||||
int utf8_stravis(char **, const char *, int);
|
size_t utf8_stravis(char **, const char *, int);
|
||||||
int utf8_stravisx(char **, const char *, size_t, int);
|
size_t utf8_stravisx(char **, const char *, size_t, int);
|
||||||
char *utf8_sanitize(const char *);
|
char *utf8_sanitize(const char *);
|
||||||
size_t utf8_strlen(const struct utf8_data *);
|
size_t utf8_strlen(const struct utf8_data *);
|
||||||
u_int utf8_strwidth(const struct utf8_data *, ssize_t);
|
u_int utf8_strwidth(const struct utf8_data *, ssize_t);
|
||||||
@@ -3586,8 +3705,8 @@ int menu_display(struct menu *, int, int, struct cmdq_item *,
|
|||||||
const char *, const char *, struct cmd_find_state *,
|
const char *, const char *, struct cmd_find_state *,
|
||||||
menu_choice_cb, void *);
|
menu_choice_cb, void *);
|
||||||
struct screen *menu_mode_cb(struct client *, void *, u_int *, u_int *);
|
struct screen *menu_mode_cb(struct client *, void *, u_int *, u_int *);
|
||||||
void menu_check_cb(struct client *, void *, u_int, u_int, u_int,
|
struct visible_ranges *menu_check_cb(struct client *, void *, u_int, u_int,
|
||||||
struct overlay_ranges *);
|
u_int);
|
||||||
void menu_draw_cb(struct client *, void *,
|
void menu_draw_cb(struct client *, void *,
|
||||||
struct screen_redraw_ctx *);
|
struct screen_redraw_ctx *);
|
||||||
void menu_free_cb(struct client *, void *);
|
void menu_free_cb(struct client *, void *);
|
||||||
|
|||||||
324
tty-draw.c
Normal file
324
tty-draw.c
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2026 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"
|
||||||
|
|
||||||
|
enum tty_draw_line_state {
|
||||||
|
TTY_DRAW_LINE_FIRST,
|
||||||
|
TTY_DRAW_LINE_FLUSH,
|
||||||
|
TTY_DRAW_LINE_NEW1,
|
||||||
|
TTY_DRAW_LINE_NEW2,
|
||||||
|
TTY_DRAW_LINE_EMPTY,
|
||||||
|
TTY_DRAW_LINE_SAME,
|
||||||
|
TTY_DRAW_LINE_PAD,
|
||||||
|
TTY_DRAW_LINE_DONE
|
||||||
|
};
|
||||||
|
static const char* tty_draw_line_states[] = {
|
||||||
|
"FIRST",
|
||||||
|
"FLUSH",
|
||||||
|
"NEW1",
|
||||||
|
"NEW2",
|
||||||
|
"EMPTY",
|
||||||
|
"SAME",
|
||||||
|
"PAD",
|
||||||
|
"DONE"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Clear part of the line. */
|
||||||
|
static void
|
||||||
|
tty_draw_line_clear(struct tty *tty, u_int px, u_int py, u_int nx,
|
||||||
|
const struct grid_cell *defaults, u_int bg, int wrapped)
|
||||||
|
{
|
||||||
|
/* Nothing to clear. */
|
||||||
|
if (nx == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If genuine BCE is available, can try escape sequences. */
|
||||||
|
if (!wrapped && nx >= 10 && !tty_fake_bce(tty, defaults, bg)) {
|
||||||
|
/* Off the end of the line, use EL if available. */
|
||||||
|
if (px + nx >= tty->sx && tty_term_has(tty->term, TTYC_EL)) {
|
||||||
|
tty_cursor(tty, px, py);
|
||||||
|
tty_putcode(tty, TTYC_EL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At the start of the line. Use EL1. */
|
||||||
|
if (px == 0 && tty_term_has(tty->term, TTYC_EL1)) {
|
||||||
|
tty_cursor(tty, px + nx - 1, py);
|
||||||
|
tty_putcode(tty, TTYC_EL1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Section of line. Use ECH if possible. */
|
||||||
|
if (tty_term_has(tty->term, TTYC_ECH)) {
|
||||||
|
tty_cursor(tty, px, py);
|
||||||
|
tty_putcode_i(tty, TTYC_ECH, nx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Couldn't use an escape sequence, use spaces. */
|
||||||
|
if (px != 0 || !wrapped)
|
||||||
|
tty_cursor(tty, px, py);
|
||||||
|
if (nx == 1)
|
||||||
|
tty_putc(tty, ' ');
|
||||||
|
else if (nx == 2)
|
||||||
|
tty_putn(tty, " ", 2, 2);
|
||||||
|
else
|
||||||
|
tty_repeat_space(tty, nx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is this cell empty? */
|
||||||
|
static u_int
|
||||||
|
tty_draw_line_get_empty(const struct grid_cell *gc, u_int nx)
|
||||||
|
{
|
||||||
|
u_int empty = 0;
|
||||||
|
|
||||||
|
if (gc->data.width != 1 && gc->data.width > nx)
|
||||||
|
empty = nx;
|
||||||
|
else if (gc->attr == 0 && gc->link == 0) {
|
||||||
|
if (gc->flags & GRID_FLAG_CLEARED)
|
||||||
|
empty = 1;
|
||||||
|
else if (gc->flags & GRID_FLAG_TAB)
|
||||||
|
empty = gc->data.width;
|
||||||
|
else if (gc->data.size == 1 && *gc->data.data == ' ')
|
||||||
|
empty = 1;
|
||||||
|
}
|
||||||
|
return (empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw a line from screen to tty. */
|
||||||
|
void
|
||||||
|
tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||||
|
u_int atx, u_int aty, const struct grid_cell *defaults,
|
||||||
|
struct colour_palette *palette)
|
||||||
|
{
|
||||||
|
struct grid *gd = s->grid;
|
||||||
|
const struct grid_cell *gcp;
|
||||||
|
struct grid_cell gc, ngc, last;
|
||||||
|
struct grid_line *gl;
|
||||||
|
u_int i, j, last_i, cx, ex, width;
|
||||||
|
u_int cellsize, bg;
|
||||||
|
int flags, empty, wrapped = 0;
|
||||||
|
char buf[1000];
|
||||||
|
size_t len;
|
||||||
|
enum tty_draw_line_state current_state, next_state;
|
||||||
|
/* xxx maybe check overlay here? */
|
||||||
|
/*
|
||||||
|
* py is the line in the screen to draw. px is the start x and nx is
|
||||||
|
* the width to draw. atx,aty is the line on the terminal to draw it.
|
||||||
|
*/
|
||||||
|
log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__, px, py, nx,
|
||||||
|
atx, aty);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clamp the width to cellsize - note this is not cellused, because
|
||||||
|
* there may be empty background cells after it (from BCE).
|
||||||
|
*/
|
||||||
|
cellsize = grid_get_line(gd, gd->hsize + py)->cellsize;
|
||||||
|
if (screen_size_x(s) > cellsize)
|
||||||
|
ex = cellsize;
|
||||||
|
else {
|
||||||
|
ex = screen_size_x(s);
|
||||||
|
if (px > ex)
|
||||||
|
return;
|
||||||
|
if (px + nx > ex)
|
||||||
|
nx = ex - px;
|
||||||
|
}
|
||||||
|
if (ex < nx)
|
||||||
|
ex = nx;
|
||||||
|
log_debug("%s: drawing %u-%u,%u (end %u) at %u,%u; defaults: fg=%d, "
|
||||||
|
"bg=%d", __func__, px, px + nx, py, ex, atx, aty, defaults->fg,
|
||||||
|
defaults->bg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is padding at the start, we must have truncated a wide
|
||||||
|
* character. Clear it.
|
||||||
|
*/
|
||||||
|
cx = 0;
|
||||||
|
for (i = px; i < px + nx; i++) {
|
||||||
|
grid_view_get_cell(gd, i, py, &gc);
|
||||||
|
if (~gc.flags & GRID_FLAG_PADDING)
|
||||||
|
break;
|
||||||
|
cx++;
|
||||||
|
}
|
||||||
|
if (cx != 0) {
|
||||||
|
/* Find the previous cell for the background colour. */
|
||||||
|
for (i = px + 1; i > 0; i--) {
|
||||||
|
grid_view_get_cell(gd, i - 1, py, &gc);
|
||||||
|
if (~gc.flags & GRID_FLAG_PADDING)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == 0)
|
||||||
|
bg = defaults->bg;
|
||||||
|
else {
|
||||||
|
bg = gc.bg;
|
||||||
|
if (gc.flags & GRID_FLAG_SELECTED) {
|
||||||
|
memcpy(&ngc, &gc, sizeof ngc);
|
||||||
|
if (screen_select_cell(s, &ngc, &gc))
|
||||||
|
bg = ngc.bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tty_attributes(tty, &last, defaults, palette, s->hyperlinks);
|
||||||
|
log_debug("%s: clearing %u padding cells", __func__, cx);
|
||||||
|
tty_draw_line_clear(tty, atx, aty, cx, defaults, bg, 0);
|
||||||
|
if (cx == ex)
|
||||||
|
return;
|
||||||
|
atx += cx;
|
||||||
|
px += cx;
|
||||||
|
nx -= cx;
|
||||||
|
ex -= cx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Did the previous line wrap on to this one? */
|
||||||
|
if (py != 0 && atx == 0 && tty->cx >= tty->sx && nx == tty->sx) {
|
||||||
|
gl = grid_get_line(gd, gd->hsize + py - 1);
|
||||||
|
if (gl->flags & GRID_LINE_WRAPPED)
|
||||||
|
wrapped = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn off cursor while redrawing and reset region and margins. */
|
||||||
|
flags = (tty->flags & TTY_NOCURSOR);
|
||||||
|
tty->flags |= TTY_NOCURSOR;
|
||||||
|
tty_update_mode(tty, tty->mode, s);
|
||||||
|
tty_region_off(tty);
|
||||||
|
tty_margin_off(tty);
|
||||||
|
|
||||||
|
/* Start with the default cell as the last cell. */
|
||||||
|
memcpy(&last, &grid_default_cell, sizeof last);
|
||||||
|
last.bg = defaults->bg;
|
||||||
|
tty_default_attributes(tty, defaults, palette, 8, s->hyperlinks);
|
||||||
|
|
||||||
|
/* Loop over each character in the range. */
|
||||||
|
last_i = i = 0;
|
||||||
|
len = 0;
|
||||||
|
width = 0;
|
||||||
|
current_state = TTY_DRAW_LINE_FIRST;
|
||||||
|
for (;;) {
|
||||||
|
/* Work out the next state. */
|
||||||
|
if (i == nx) {
|
||||||
|
/*
|
||||||
|
* If this is the last cell, we are done. But we need to
|
||||||
|
* go through the loop again to flush anything in
|
||||||
|
* the buffer.
|
||||||
|
*/
|
||||||
|
empty = 0;
|
||||||
|
next_state = TTY_DRAW_LINE_DONE;
|
||||||
|
gcp = &grid_default_cell;
|
||||||
|
} else {
|
||||||
|
/* Get the current cell. */
|
||||||
|
grid_view_get_cell(gd, px + i, py, &gc);
|
||||||
|
|
||||||
|
/* Update for codeset if needed. */
|
||||||
|
gcp = tty_check_codeset(tty, &gc);
|
||||||
|
|
||||||
|
/* And for selection. */
|
||||||
|
if (gcp->flags & GRID_FLAG_SELECTED) {
|
||||||
|
memcpy(&ngc, gcp, sizeof ngc);
|
||||||
|
if (screen_select_cell(s, &ngc, gcp))
|
||||||
|
gcp = &ngc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Work out the the empty width. */
|
||||||
|
if (i >= ex)
|
||||||
|
empty = 1;
|
||||||
|
else if (gcp->bg != last.bg)
|
||||||
|
empty = 0;
|
||||||
|
else
|
||||||
|
empty = tty_draw_line_get_empty(gcp, nx - i);
|
||||||
|
|
||||||
|
/* Work out the next state. */
|
||||||
|
if (empty != 0)
|
||||||
|
next_state = TTY_DRAW_LINE_EMPTY;
|
||||||
|
else if (current_state == TTY_DRAW_LINE_FIRST)
|
||||||
|
next_state = TTY_DRAW_LINE_SAME;
|
||||||
|
else if (gcp->flags & GRID_FLAG_PADDING)
|
||||||
|
next_state = TTY_DRAW_LINE_PAD;
|
||||||
|
else if (grid_cells_look_equal(gcp, &last)) {
|
||||||
|
if (gcp->data.size > (sizeof buf) - len)
|
||||||
|
next_state = TTY_DRAW_LINE_FLUSH;
|
||||||
|
else
|
||||||
|
next_state = TTY_DRAW_LINE_SAME;
|
||||||
|
} else if (current_state == TTY_DRAW_LINE_NEW1)
|
||||||
|
next_state = TTY_DRAW_LINE_NEW2;
|
||||||
|
else
|
||||||
|
next_state = TTY_DRAW_LINE_NEW1;
|
||||||
|
}
|
||||||
|
if (log_get_level() != 0) {
|
||||||
|
log_debug("%s: cell %u empty %u, bg %u; state: "
|
||||||
|
"current %s, next %s", __func__, px + i, empty,
|
||||||
|
gcp->bg, tty_draw_line_states[current_state],
|
||||||
|
tty_draw_line_states[next_state]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the state has changed, flush any collected data. */
|
||||||
|
if (next_state != current_state) {
|
||||||
|
if (current_state == TTY_DRAW_LINE_EMPTY) {
|
||||||
|
tty_attributes(tty, &last, defaults, palette,
|
||||||
|
s->hyperlinks);
|
||||||
|
tty_draw_line_clear(tty, atx + last_i, aty,
|
||||||
|
i - last_i, defaults, last.bg, wrapped);
|
||||||
|
wrapped = 0;
|
||||||
|
} else if (next_state != TTY_DRAW_LINE_SAME &&
|
||||||
|
len != 0) {
|
||||||
|
tty_attributes(tty, &last, defaults, palette,
|
||||||
|
s->hyperlinks);
|
||||||
|
if (atx + i - width != 0 || !wrapped)
|
||||||
|
tty_cursor(tty, atx + i - width, aty);
|
||||||
|
if (~last.attr & GRID_ATTR_CHARSET)
|
||||||
|
tty_putn(tty, buf, len, width);
|
||||||
|
else {
|
||||||
|
for (j = 0; j < len; j++)
|
||||||
|
tty_putc(tty, buf[j]);
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
width = 0;
|
||||||
|
wrapped = 0;
|
||||||
|
}
|
||||||
|
last_i = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the cell if it is not empty and not padding. */
|
||||||
|
if (next_state != TTY_DRAW_LINE_EMPTY &&
|
||||||
|
next_state != TTY_DRAW_LINE_PAD) {
|
||||||
|
memcpy(buf + len, gcp->data.data, gcp->data.size);
|
||||||
|
len += gcp->data.size;
|
||||||
|
width += gcp->data.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is the last cell, we are done. */
|
||||||
|
if (next_state == TTY_DRAW_LINE_DONE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Otherwise move to the next. */
|
||||||
|
current_state = next_state;
|
||||||
|
memcpy(&last, gcp, sizeof last);
|
||||||
|
if (empty != 0)
|
||||||
|
i += empty;
|
||||||
|
else
|
||||||
|
i += gcp->data.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty->flags = (tty->flags & ~TTY_NOCURSOR)|flags;
|
||||||
|
tty_update_mode(tty, tty->mode, s);
|
||||||
|
}
|
||||||
|
|
||||||
130
tty-keys.c
130
tty-keys.c
@@ -909,9 +909,15 @@ first_key:
|
|||||||
* used. termios should have a better idea.
|
* used. termios should have a better idea.
|
||||||
*/
|
*/
|
||||||
bspace = tty->tio.c_cc[VERASE];
|
bspace = tty->tio.c_cc[VERASE];
|
||||||
if (bspace != _POSIX_VDISABLE && key == bspace) {
|
if (bspace != _POSIX_VDISABLE) {
|
||||||
log_debug("%s: key %#llx is backspace", c->name, key);
|
if (key == bspace) {
|
||||||
key = KEYC_BSPACE;
|
log_debug("%s: key %#llx is BSpace", c->name, key);
|
||||||
|
key = KEYC_BSPACE;
|
||||||
|
}
|
||||||
|
if (key == (bspace|KEYC_META)) {
|
||||||
|
log_debug("%s: key %#llx is M-BSpace", c->name, key);
|
||||||
|
key = KEYC_BSPACE|KEYC_META;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -950,7 +956,8 @@ partial_key:
|
|||||||
if (delay == 0)
|
if (delay == 0)
|
||||||
delay = 1;
|
delay = 1;
|
||||||
if ((tty->flags & (TTY_WAITFG|TTY_WAITBG) ||
|
if ((tty->flags & (TTY_WAITFG|TTY_WAITBG) ||
|
||||||
(tty->flags & TTY_ALL_REQUEST_FLAGS) != TTY_ALL_REQUEST_FLAGS)) {
|
(tty->flags & TTY_ALL_REQUEST_FLAGS) != TTY_ALL_REQUEST_FLAGS) ||
|
||||||
|
!TAILQ_EMPTY(&c->input_requests)) {
|
||||||
log_debug("%s: increasing delay for active query", c->name);
|
log_debug("%s: increasing delay for active query", c->name);
|
||||||
if (delay < 500)
|
if (delay < 500)
|
||||||
delay = 500;
|
delay = 500;
|
||||||
@@ -1301,12 +1308,11 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size,
|
|||||||
static int
|
static int
|
||||||
tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
|
tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||||
{
|
{
|
||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
struct window_pane *wp;
|
size_t end, terminator = 0, needed;
|
||||||
size_t end, terminator = 0, needed;
|
char *copy, *out, clip = 0;
|
||||||
char *copy, *out;
|
int outlen;
|
||||||
int outlen;
|
struct input_request_clipboard_data cd;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
*size = 0;
|
*size = 0;
|
||||||
|
|
||||||
@@ -1354,7 +1360,14 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
|
|||||||
/* Adjust end so that it points to the start of the terminator. */
|
/* Adjust end so that it points to the start of the terminator. */
|
||||||
end -= terminator - 1;
|
end -= terminator - 1;
|
||||||
|
|
||||||
/* Get the second argument. */
|
/*
|
||||||
|
* Save which clipboard was used from the second argument. If more than
|
||||||
|
* one is specified (should not happen), ignore the argument.
|
||||||
|
*/
|
||||||
|
if (end >= 2 && buf[0] != ';' && buf[1] == ';')
|
||||||
|
clip = buf[0];
|
||||||
|
|
||||||
|
/* Skip the second argument. */
|
||||||
while (end != 0 && *buf != ';') {
|
while (end != 0 && *buf != ';') {
|
||||||
buf++;
|
buf++;
|
||||||
end--;
|
end--;
|
||||||
@@ -1364,12 +1377,6 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
|
|||||||
buf++;
|
buf++;
|
||||||
end--;
|
end--;
|
||||||
|
|
||||||
/* If we did not request this, ignore it. */
|
|
||||||
if (~tty->flags & TTY_OSC52QUERY)
|
|
||||||
return (0);
|
|
||||||
tty->flags &= ~TTY_OSC52QUERY;
|
|
||||||
evtimer_del(&tty->clipboard_timer);
|
|
||||||
|
|
||||||
/* It has to be a string so copy it. */
|
/* It has to be a string so copy it. */
|
||||||
copy = xmalloc(end + 1);
|
copy = xmalloc(end + 1);
|
||||||
memcpy(copy, buf, end);
|
memcpy(copy, buf, end);
|
||||||
@@ -1377,29 +1384,34 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
|
|||||||
|
|
||||||
/* Convert from base64. */
|
/* Convert from base64. */
|
||||||
needed = (end / 4) * 3;
|
needed = (end / 4) * 3;
|
||||||
|
if (needed == 0) {
|
||||||
|
free(copy);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
out = xmalloc(needed);
|
out = xmalloc(needed);
|
||||||
if ((outlen = b64_pton(copy, out, len)) == -1) {
|
if ((outlen = b64_pton(copy, out, needed)) == -1) {
|
||||||
free(out);
|
free(out);
|
||||||
free(copy);
|
free(copy);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
free(copy);
|
free(copy);
|
||||||
|
|
||||||
/* Create a new paste buffer and forward to panes. */
|
|
||||||
log_debug("%s: %.*s", __func__, outlen, out);
|
log_debug("%s: %.*s", __func__, outlen, out);
|
||||||
if (c->flags & CLIENT_CLIPBOARDBUFFER) {
|
|
||||||
paste_add(NULL, out, outlen);
|
|
||||||
c->flags &= ~CLIENT_CLIPBOARDBUFFER;
|
|
||||||
}
|
|
||||||
for (i = 0; i < c->clipboard_npanes; i++) {
|
|
||||||
wp = window_pane_find_by_id(c->clipboard_panes[i]);
|
|
||||||
if (wp != NULL)
|
|
||||||
input_reply_clipboard(wp->event, out, outlen, "\033\\");
|
|
||||||
}
|
|
||||||
free(c->clipboard_panes);
|
|
||||||
c->clipboard_panes = NULL;
|
|
||||||
c->clipboard_npanes = 0;
|
|
||||||
|
|
||||||
|
/* Set reply if any. */
|
||||||
|
cd.buf = out;
|
||||||
|
cd.len = outlen;
|
||||||
|
cd.clip = clip;
|
||||||
|
input_request_reply(c, INPUT_REQUEST_CLIPBOARD, &cd);
|
||||||
|
|
||||||
|
/* Create a buffer if requested. */
|
||||||
|
if (tty->flags & TTY_OSC52QUERY) {
|
||||||
|
paste_add(NULL, out, outlen);
|
||||||
|
out = NULL;
|
||||||
|
evtimer_del(&tty->clipboard_timer);
|
||||||
|
tty->flags &= ~TTY_OSC52QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(out);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1612,8 +1624,10 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
|
|||||||
}
|
}
|
||||||
if (i == (sizeof tmp) - 1)
|
if (i == (sizeof tmp) - 1)
|
||||||
return (-1);
|
return (-1);
|
||||||
tmp[i - 1] = '\0';
|
|
||||||
*size = 5 + i;
|
*size = 5 + i;
|
||||||
|
if (i == 0)
|
||||||
|
return (0);
|
||||||
|
tmp[i - 1] = '\0';
|
||||||
|
|
||||||
/* Add terminal features. */
|
/* Add terminal features. */
|
||||||
if (strncmp(tmp, "iTerm2 ", 7) == 0)
|
if (strncmp(tmp, "iTerm2 ", 7) == 0)
|
||||||
@@ -1686,12 +1700,15 @@ tty_keys_colours(struct tty *tty, const char *buf, size_t len, size_t *size,
|
|||||||
}
|
}
|
||||||
if (i == (sizeof tmp) - 1)
|
if (i == (sizeof tmp) - 1)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
*size = 6 + i;
|
||||||
|
if (i == 0)
|
||||||
|
return (0);
|
||||||
if (tmp[i - 1] == '\033')
|
if (tmp[i - 1] == '\033')
|
||||||
tmp[i - 1] = '\0';
|
tmp[i - 1] = '\0';
|
||||||
else
|
else
|
||||||
tmp[i] = '\0';
|
tmp[i] = '\0';
|
||||||
*size = 6 + i;
|
|
||||||
|
|
||||||
|
/* Work out the colour. */
|
||||||
n = colour_parseX11(tmp);
|
n = colour_parseX11(tmp);
|
||||||
if (n != -1 && buf[3] == '0') {
|
if (n != -1 && buf[3] == '0') {
|
||||||
if (c != NULL)
|
if (c != NULL)
|
||||||
@@ -1717,7 +1734,7 @@ static int
|
|||||||
tty_keys_palette(struct tty *tty, const char *buf, size_t len, size_t *size)
|
tty_keys_palette(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||||
{
|
{
|
||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
u_int i, start;
|
u_int i;
|
||||||
char tmp[128], *endptr;
|
char tmp[128], *endptr;
|
||||||
int idx;
|
int idx;
|
||||||
struct input_request_palette_data pd;
|
struct input_request_palette_data pd;
|
||||||
@@ -1742,32 +1759,35 @@ tty_keys_palette(struct tty *tty, const char *buf, size_t len, size_t *size)
|
|||||||
if (len == 4)
|
if (len == 4)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
|
/* Copy the rest up to \033\ or \007. */
|
||||||
|
for (i = 0; i < (sizeof tmp) - 1; i++) {
|
||||||
|
if (4 + i == len)
|
||||||
|
return (1);
|
||||||
|
if (buf[4 + i - 1] == '\033' && buf[4 + i] == '\\')
|
||||||
|
break;
|
||||||
|
if (buf[4 + i] == '\007')
|
||||||
|
break;
|
||||||
|
tmp[i] = buf[4 + i];
|
||||||
|
}
|
||||||
|
if (i == (sizeof tmp) - 1)
|
||||||
|
return (-1);
|
||||||
|
*size = 5 + i;
|
||||||
|
if (i == 0)
|
||||||
|
return (0);
|
||||||
|
if (tmp[i - 1] == '\033')
|
||||||
|
tmp[i - 1] = '\0';
|
||||||
|
else
|
||||||
|
tmp[i] = '\0';
|
||||||
|
|
||||||
/* Parse index. */
|
/* Parse index. */
|
||||||
idx = strtol(buf + 4, &endptr, 10);
|
idx = strtol(tmp, &endptr, 10);
|
||||||
if (endptr == buf + 4 || *endptr != ';')
|
if (*endptr != ';')
|
||||||
return (-1);
|
return (-1);
|
||||||
if (idx < 0 || idx > 255)
|
if (idx < 0 || idx > 255)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
/* Copy the rest up to \033\ or \007. */
|
|
||||||
start = (endptr - buf) + 1;
|
|
||||||
for (i = start; i < len && i - start < sizeof tmp; i++) {
|
|
||||||
if (buf[i - 1] == '\033' && buf[i] == '\\')
|
|
||||||
break;
|
|
||||||
if (buf[i] == '\007')
|
|
||||||
break;
|
|
||||||
tmp[i - start] = buf[i];
|
|
||||||
}
|
|
||||||
if (i - start == sizeof tmp)
|
|
||||||
return (-1);
|
|
||||||
if (i > 0 && buf[i - 1] == '\033')
|
|
||||||
tmp[i - start - 1] = '\0';
|
|
||||||
else
|
|
||||||
tmp[i - start] = '\0';
|
|
||||||
*size = i + 1;
|
|
||||||
|
|
||||||
/* Work out the colour. */
|
/* Work out the colour. */
|
||||||
pd.c = colour_parseX11(tmp);
|
pd.c = colour_parseX11(endptr + 1);
|
||||||
if (pd.c == -1)
|
if (pd.c == -1)
|
||||||
return (0);
|
return (0);
|
||||||
pd.idx = idx;
|
pd.idx = idx;
|
||||||
|
|||||||
468
tty.c
468
tty.c
@@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
static int tty_log_fd = -1;
|
static int tty_log_fd = -1;
|
||||||
|
|
||||||
|
static void tty_start_timer_callback(int, short, void *);
|
||||||
|
static void tty_clipboard_query_callback(int, short, void *);
|
||||||
static void tty_set_italics(struct tty *);
|
static void tty_set_italics(struct tty *);
|
||||||
static int tty_try_colour(struct tty *, int, const char *);
|
static int tty_try_colour(struct tty *, int, const char *);
|
||||||
static void tty_force_cursor_colour(struct tty *, int);
|
static void tty_force_cursor_colour(struct tty *, int);
|
||||||
@@ -59,18 +61,11 @@ static void tty_region(struct tty *, u_int, u_int);
|
|||||||
static void tty_margin_pane(struct tty *, const struct tty_ctx *);
|
static void tty_margin_pane(struct tty *, const struct tty_ctx *);
|
||||||
static void tty_margin(struct tty *, u_int, u_int);
|
static void tty_margin(struct tty *, u_int, u_int);
|
||||||
static int tty_large_region(struct tty *, const struct tty_ctx *);
|
static int tty_large_region(struct tty *, const struct tty_ctx *);
|
||||||
static int tty_fake_bce(const struct tty *, const struct grid_cell *,
|
|
||||||
u_int);
|
|
||||||
static void tty_redraw_region(struct tty *, const struct tty_ctx *);
|
static void tty_redraw_region(struct tty *, const struct tty_ctx *);
|
||||||
static void tty_emulate_repeat(struct tty *, enum tty_code_code,
|
static void tty_emulate_repeat(struct tty *, enum tty_code_code,
|
||||||
enum tty_code_code, u_int);
|
enum tty_code_code, u_int);
|
||||||
static void tty_repeat_space(struct tty *, u_int);
|
|
||||||
static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int);
|
static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int);
|
||||||
static void tty_default_attributes(struct tty *, const struct grid_cell *,
|
|
||||||
struct colour_palette *, u_int, struct hyperlinks *);
|
|
||||||
static int tty_check_overlay(struct tty *, u_int, u_int);
|
static int tty_check_overlay(struct tty *, u_int, u_int);
|
||||||
static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int,
|
|
||||||
struct overlay_ranges *);
|
|
||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
static void tty_write_one(void (*)(struct tty *, const struct tty_ctx *),
|
static void tty_write_one(void (*)(struct tty *, const struct tty_ctx *),
|
||||||
@@ -296,6 +291,8 @@ tty_open(struct tty *tty, char **cause)
|
|||||||
if (tty->out == NULL)
|
if (tty->out == NULL)
|
||||||
fatal("out of memory");
|
fatal("out of memory");
|
||||||
|
|
||||||
|
evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty);
|
||||||
|
evtimer_set(&tty->start_timer, tty_start_timer_callback, tty);
|
||||||
evtimer_set(&tty->timer, tty_timer_callback, tty);
|
evtimer_set(&tty->timer, tty_timer_callback, tty);
|
||||||
|
|
||||||
tty_start_tty(tty);
|
tty_start_tty(tty);
|
||||||
@@ -327,7 +324,6 @@ tty_start_start_timer(struct tty *tty)
|
|||||||
|
|
||||||
log_debug("%s: start timer started", c->name);
|
log_debug("%s: start timer started", c->name);
|
||||||
evtimer_del(&tty->start_timer);
|
evtimer_del(&tty->start_timer);
|
||||||
evtimer_set(&tty->start_timer, tty_start_timer_callback, tty);
|
|
||||||
evtimer_add(&tty->start_timer, &tv);
|
evtimer_add(&tty->start_timer, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,6 +441,7 @@ tty_stop_tty(struct tty *tty)
|
|||||||
tty->flags &= ~TTY_STARTED;
|
tty->flags &= ~TTY_STARTED;
|
||||||
|
|
||||||
evtimer_del(&tty->start_timer);
|
evtimer_del(&tty->start_timer);
|
||||||
|
evtimer_del(&tty->clipboard_timer);
|
||||||
|
|
||||||
event_del(&tty->timer);
|
event_del(&tty->timer);
|
||||||
tty->flags &= ~TTY_BLOCK;
|
tty->flags &= ~TTY_BLOCK;
|
||||||
@@ -524,6 +521,8 @@ void
|
|||||||
tty_free(struct tty *tty)
|
tty_free(struct tty *tty)
|
||||||
{
|
{
|
||||||
tty_close(tty);
|
tty_close(tty);
|
||||||
|
|
||||||
|
free(tty->r.ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -634,7 +633,8 @@ tty_add(struct tty *tty, const char *buf, size_t len)
|
|||||||
|
|
||||||
if (tty_log_fd != -1)
|
if (tty_log_fd != -1)
|
||||||
write(tty_log_fd, buf, len);
|
write(tty_log_fd, buf, len);
|
||||||
if (tty->flags & TTY_STARTED)
|
if ((tty->flags & TTY_STARTED) &&
|
||||||
|
!event_pending(&tty->event_out, EV_WRITE, NULL))
|
||||||
event_add(&tty->event_out, NULL);
|
event_add(&tty->event_out, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,7 +908,7 @@ tty_emulate_repeat(struct tty *tty, enum tty_code_code code,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
tty_repeat_space(struct tty *tty, u_int n)
|
tty_repeat_space(struct tty *tty, u_int n)
|
||||||
{
|
{
|
||||||
static char s[500];
|
static char s[500];
|
||||||
@@ -1003,7 +1003,10 @@ tty_window_offset1(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy)
|
|||||||
else if (cy > w->sy - *sy)
|
else if (cy > w->sy - *sy)
|
||||||
*oy = w->sy - *sy;
|
*oy = w->sy - *sy;
|
||||||
else
|
else
|
||||||
*oy = cy - *sy / 2;
|
/* cy-sy/2 was causing panned panes to scroll
|
||||||
|
* when the cursor was half way down the pane.
|
||||||
|
*/
|
||||||
|
*oy = cy - *sy + 1; /* cy - *sy / 2; */
|
||||||
}
|
}
|
||||||
|
|
||||||
c->pan_window = NULL;
|
c->pan_window = NULL;
|
||||||
@@ -1067,7 +1070,7 @@ tty_large_region(__unused struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
* Return if BCE is needed but the terminal doesn't have it - it'll need to be
|
* Return if BCE is needed but the terminal doesn't have it - it'll need to be
|
||||||
* emulated.
|
* emulated.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
tty_fake_bce(const struct tty *tty, const struct grid_cell *gc, u_int bg)
|
tty_fake_bce(const struct tty *tty, const struct grid_cell *gc, u_int bg)
|
||||||
{
|
{
|
||||||
if (tty_term_flag(tty->term, TTYC_BCE))
|
if (tty_term_flag(tty->term, TTYC_BCE))
|
||||||
@@ -1123,23 +1126,23 @@ static int
|
|||||||
tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
|
tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
|
||||||
u_int nx, u_int *i, u_int *x, u_int *rx, u_int *ry)
|
u_int nx, u_int *i, u_int *x, u_int *rx, u_int *ry)
|
||||||
{
|
{
|
||||||
u_int xoff = ctx->rxoff + px;
|
int xoff = ctx->rxoff + px;
|
||||||
|
|
||||||
if (!tty_is_visible(tty, ctx, px, py, nx, 1))
|
if (!tty_is_visible(tty, ctx, px, py, nx, 1))
|
||||||
return (0);
|
return (0);
|
||||||
*ry = ctx->yoff + py - ctx->woy;
|
*ry = ctx->yoff + py - ctx->woy;
|
||||||
|
|
||||||
if (xoff >= ctx->wox && xoff + nx <= ctx->wox + ctx->wsx) {
|
if (xoff >= (int)ctx->wox && xoff + nx <= ctx->wox + ctx->wsx) {
|
||||||
/* All visible. */
|
/* All visible. */
|
||||||
*i = 0;
|
*i = 0;
|
||||||
*x = ctx->xoff + px - ctx->wox;
|
*x = ctx->xoff + px - ctx->wox;
|
||||||
*rx = nx;
|
*rx = nx;
|
||||||
} else if (xoff < ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
|
} else if (xoff < (int)ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
|
||||||
/* Both left and right not visible. */
|
/* Both left and right not visible. */
|
||||||
*i = ctx->wox;
|
*i = ctx->wox;
|
||||||
*x = 0;
|
*x = 0;
|
||||||
*rx = ctx->wsx;
|
*rx = ctx->wsx;
|
||||||
} else if (xoff < ctx->wox) {
|
} else if (xoff < (int)ctx->wox) {
|
||||||
/* Left not visible. */
|
/* Left not visible. */
|
||||||
*i = ctx->wox - (ctx->xoff + px);
|
*i = ctx->wox - (ctx->xoff + px);
|
||||||
*x = 0;
|
*x = 0;
|
||||||
@@ -1162,8 +1165,6 @@ tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
|||||||
u_int px, u_int nx, u_int bg)
|
u_int px, u_int nx, u_int bg)
|
||||||
{
|
{
|
||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
struct overlay_ranges r;
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
|
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
|
||||||
|
|
||||||
@@ -1199,13 +1200,8 @@ tty_clear_line(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
|||||||
* Couldn't use an escape sequence, use spaces. Clear only the visible
|
* Couldn't use an escape sequence, use spaces. Clear only the visible
|
||||||
* bit if there is an overlay.
|
* bit if there is an overlay.
|
||||||
*/
|
*/
|
||||||
tty_check_overlay_range(tty, px, py, nx, &r);
|
tty_cursor(tty, px, py);
|
||||||
for (i = 0; i < OVERLAY_MAX_RANGES; i++) {
|
tty_repeat_space(tty, nx);
|
||||||
if (r.nx[i] == 0)
|
|
||||||
continue;
|
|
||||||
tty_cursor(tty, r.px[i], py);
|
|
||||||
tty_repeat_space(tty, r.nx[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear a line, adjusting to visible part of pane. */
|
/* Clear a line, adjusting to visible part of pane. */
|
||||||
@@ -1213,13 +1209,23 @@ static void
|
|||||||
tty_clear_pane_line(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
tty_clear_pane_line(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
||||||
u_int px, u_int nx, u_int bg)
|
u_int px, u_int nx, u_int bg)
|
||||||
{
|
{
|
||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
u_int i, x, rx, ry;
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
u_int i, l, x, rx, ry;
|
||||||
|
|
||||||
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
|
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
|
||||||
|
|
||||||
if (tty_clamp_line(tty, ctx, px, py, nx, &i, &x, &rx, &ry))
|
if (tty_clamp_line(tty, ctx, px, py, nx, &l, &x, &rx, &ry)) {
|
||||||
tty_clear_line(tty, &ctx->defaults, ry, x, rx, bg);
|
r = tty_check_overlay_range(tty, x, ry, rx);
|
||||||
|
for (i=0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0)
|
||||||
|
continue;
|
||||||
|
tty_clear_line(tty, &ctx->defaults, ry, ri->px, ri->nx,
|
||||||
|
bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clamp area position to visible part of pane. */
|
/* Clamp area position to visible part of pane. */
|
||||||
@@ -1286,12 +1292,17 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
|
|||||||
|
|
||||||
/* Clear an area, adjusting to visible part of pane. */
|
/* Clear an area, adjusting to visible part of pane. */
|
||||||
static void
|
static void
|
||||||
tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
tty_clear_area(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
||||||
u_int ny, u_int px, u_int nx, u_int bg)
|
u_int ny, u_int px, u_int nx, u_int bg)
|
||||||
{
|
{
|
||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
u_int yy;
|
const struct grid_cell *defaults = &ctx->defaults;
|
||||||
char tmp[64];
|
struct window *w = c->session->curw->window;
|
||||||
|
struct window_pane *wpl, *wp = ctx->arg;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
u_int i, yy, overlap = 0, oy = 0;
|
||||||
|
char tmp[64];
|
||||||
|
|
||||||
log_debug("%s: %s, %u,%u at %u,%u", __func__, c->name, nx, ny, px, py);
|
log_debug("%s: %s, %u,%u at %u,%u", __func__, c->name, nx, ny, px, py);
|
||||||
|
|
||||||
@@ -1299,8 +1310,21 @@ tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
|||||||
if (nx == 0 || ny == 0)
|
if (nx == 0 || ny == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Verify there's nothing overlapping in z-index before using BCE. */
|
||||||
|
TAILQ_FOREACH(wpl, &w->z_index, zentry) {
|
||||||
|
if (wpl == wp || ~wpl->flags & PANE_FLOATING)
|
||||||
|
continue;
|
||||||
|
if (wpl->xoff - 1 > (int)(px + nx) || wpl->xoff + wpl->sx + 1 < px)
|
||||||
|
continue;
|
||||||
|
if (wpl->yoff - 1 > (int)(py + ny) || wpl->yoff + wpl->sy + 1 < py)
|
||||||
|
continue;
|
||||||
|
overlap++;
|
||||||
|
if (overlap > 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
/* If genuine BCE is available, can try escape sequences. */
|
/* If genuine BCE is available, can try escape sequences. */
|
||||||
if (c->overlay_check == NULL && !tty_fake_bce(tty, defaults, bg)) {
|
if (!overlap && c->overlay_check == NULL &&
|
||||||
|
!tty_fake_bce(tty, defaults, bg)) {
|
||||||
/* Use ED if clearing off the bottom of the terminal. */
|
/* Use ED if clearing off the bottom of the terminal. */
|
||||||
if (px == 0 &&
|
if (px == 0 &&
|
||||||
px + nx >= tty->sx &&
|
px + nx >= tty->sx &&
|
||||||
@@ -1351,9 +1375,18 @@ tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->session->statusat == 0)
|
||||||
|
oy = c->session->statuslines;
|
||||||
|
|
||||||
/* Couldn't use an escape sequence, loop over the lines. */
|
/* Couldn't use an escape sequence, loop over the lines. */
|
||||||
for (yy = py; yy < py + ny; yy++)
|
for (yy = py; yy < py + ny; yy++) {
|
||||||
tty_clear_line(tty, defaults, yy, px, nx, bg);
|
r = tty_check_overlay_range(tty, px, yy - oy, nx);
|
||||||
|
for (i=0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0) continue;
|
||||||
|
tty_clear_line(tty, defaults, yy, ri->px, ri->nx, bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear an area in a pane. */
|
/* Clear an area in a pane. */
|
||||||
@@ -1361,32 +1394,61 @@ static void
|
|||||||
tty_clear_pane_area(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
tty_clear_pane_area(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
||||||
u_int ny, u_int px, u_int nx, u_int bg)
|
u_int ny, u_int px, u_int nx, u_int bg)
|
||||||
{
|
{
|
||||||
u_int i, j, x, y, rx, ry;
|
u_int i, j, x, y, rx, ry;
|
||||||
|
|
||||||
if (tty_clamp_area(tty, ctx, px, py, nx, ny, &i, &j, &x, &y, &rx, &ry))
|
if (tty_clamp_area(tty, ctx, px, py, nx, ny, &i, &j, &x, &y, &rx, &ry))
|
||||||
tty_clear_area(tty, &ctx->defaults, y, ry, x, rx, bg);
|
tty_clear_area(tty, ctx, y, ry, x, rx, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Redraw a line at py of a screen taking into account obscured ranges.
|
||||||
|
* Menus and popups are always on top, ctx->arg == NULL.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
|
tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
u_int nx = ctx->sx, i, x, rx, ry;
|
struct window_pane *wp = ctx->arg;
|
||||||
|
struct visible_ranges *r = NULL;
|
||||||
|
struct visible_range *ri;
|
||||||
|
u_int nx = ctx->sx, i, px, x, rx, ry;
|
||||||
|
|
||||||
log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger);
|
log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger);
|
||||||
|
|
||||||
if (!ctx->bigger) {
|
if (!ctx->bigger) {
|
||||||
tty_draw_line(tty, s, 0, py, nx, ctx->xoff, ctx->yoff + py,
|
if (wp) {
|
||||||
&ctx->defaults, ctx->palette);
|
r = tty_check_overlay_range(tty, 0, ctx->yoff + py, nx);
|
||||||
|
for (i=0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0) continue;
|
||||||
|
tty_draw_line(tty, s, ri->px, py, ri->nx,
|
||||||
|
ctx->xoff + ri->px, ctx->yoff + py,
|
||||||
|
&ctx->defaults, ctx->palette);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tty_draw_line(tty, s, 0, py, nx, ctx->xoff,
|
||||||
|
ctx->yoff + py, &ctx->defaults, ctx->palette);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tty_clamp_line(tty, ctx, 0, py, nx, &i, &x, &rx, &ry)) {
|
if (tty_clamp_line(tty, ctx, 0, py, nx, &px, &x, &rx, &ry)) {
|
||||||
tty_draw_line(tty, s, i, py, rx, x, ry, &ctx->defaults,
|
if (wp) {
|
||||||
ctx->palette);
|
r = tty_check_overlay_range(tty, i, py, rx);
|
||||||
|
for (i=0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
if (ri->nx == 0)
|
||||||
|
continue;
|
||||||
|
tty_draw_line(tty, s, i, py, ri->nx,
|
||||||
|
x + ri->px, ry, &ctx->defaults,
|
||||||
|
ctx->palette);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tty_draw_line(tty, s, px, py, rx, x, ry, &ctx->defaults,
|
||||||
|
ctx->palette);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct grid_cell *
|
const struct grid_cell *
|
||||||
tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
|
tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
|
||||||
{
|
{
|
||||||
static struct grid_cell new;
|
static struct grid_cell new;
|
||||||
@@ -1419,229 +1481,34 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
|
|||||||
return (&new);
|
return (&new);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Check if a single character is covered by the overlay. */
|
||||||
* Check if a single character is obstructed by the overlay and return a
|
|
||||||
* boolean.
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
tty_check_overlay(struct tty *tty, u_int px, u_int py)
|
tty_check_overlay(struct tty *tty, u_int px, u_int py)
|
||||||
{
|
{
|
||||||
struct overlay_ranges r;
|
struct visible_ranges *r;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A unit width range will always return nx[2] == 0 from a check, even
|
* With a single character, if there is anything visible (that is, the
|
||||||
* with multiple overlays, so it's sufficient to check just the first
|
* range is not empty), it must be that character.
|
||||||
* two entries.
|
|
||||||
*/
|
*/
|
||||||
tty_check_overlay_range(tty, px, py, 1, &r);
|
r = tty_check_overlay_range(tty, px, py, 1);
|
||||||
if (r.nx[0] + r.nx[1] == 0)
|
return (!server_client_ranges_is_empty(r));
|
||||||
return (0);
|
|
||||||
return (1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return parts of the input range which are visible. */
|
/* Return parts of the input range which are visible. */
|
||||||
static void
|
struct visible_ranges *
|
||||||
tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx,
|
tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx)
|
||||||
struct overlay_ranges *r)
|
|
||||||
{
|
{
|
||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
|
|
||||||
if (c->overlay_check == NULL) {
|
if (c->overlay_check == NULL) {
|
||||||
r->px[0] = px;
|
server_client_ensure_ranges(&tty->r, 1);
|
||||||
r->nx[0] = nx;
|
tty->r.ranges[0].px = px;
|
||||||
r->px[1] = 0;
|
tty->r.ranges[0].nx = nx;
|
||||||
r->nx[1] = 0;
|
tty->r.used = 1;
|
||||||
r->px[2] = 0;
|
return (&tty->r);
|
||||||
r->nx[2] = 0;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return (c->overlay_check(c, c->overlay_data, px, py, nx));
|
||||||
c->overlay_check(c, c->overlay_data, px, py, nx, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
|
||||||
u_int atx, u_int aty, const struct grid_cell *defaults,
|
|
||||||
struct colour_palette *palette)
|
|
||||||
{
|
|
||||||
struct grid *gd = s->grid;
|
|
||||||
struct grid_cell gc, last;
|
|
||||||
const struct grid_cell *gcp;
|
|
||||||
struct grid_line *gl;
|
|
||||||
struct client *c = tty->client;
|
|
||||||
struct overlay_ranges r;
|
|
||||||
u_int i, j, ux, sx, width, hidden, eux, nxx;
|
|
||||||
u_int cellsize;
|
|
||||||
int flags, cleared = 0, wrapped = 0;
|
|
||||||
char buf[512];
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__,
|
|
||||||
px, py, nx, atx, aty);
|
|
||||||
log_debug("%s: defaults: fg=%d, bg=%d", __func__, defaults->fg,
|
|
||||||
defaults->bg);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* py is the line in the screen to draw.
|
|
||||||
* px is the start x and nx is the width to draw.
|
|
||||||
* atx,aty is the line on the terminal to draw it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
flags = (tty->flags & TTY_NOCURSOR);
|
|
||||||
tty->flags |= TTY_NOCURSOR;
|
|
||||||
tty_update_mode(tty, tty->mode, s);
|
|
||||||
|
|
||||||
tty_region_off(tty);
|
|
||||||
tty_margin_off(tty);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Clamp the width to cellsize - note this is not cellused, because
|
|
||||||
* there may be empty background cells after it (from BCE).
|
|
||||||
*/
|
|
||||||
sx = screen_size_x(s);
|
|
||||||
if (nx > sx)
|
|
||||||
nx = sx;
|
|
||||||
cellsize = grid_get_line(gd, gd->hsize + py)->cellsize;
|
|
||||||
if (sx > cellsize)
|
|
||||||
sx = cellsize;
|
|
||||||
if (sx > tty->sx)
|
|
||||||
sx = tty->sx;
|
|
||||||
if (sx > nx)
|
|
||||||
sx = nx;
|
|
||||||
ux = 0;
|
|
||||||
|
|
||||||
if (py == 0)
|
|
||||||
gl = NULL;
|
|
||||||
else
|
|
||||||
gl = grid_get_line(gd, gd->hsize + py - 1);
|
|
||||||
if (gl == NULL ||
|
|
||||||
(~gl->flags & GRID_LINE_WRAPPED) ||
|
|
||||||
atx != 0 ||
|
|
||||||
tty->cx < tty->sx ||
|
|
||||||
nx < tty->sx) {
|
|
||||||
if (nx < tty->sx &&
|
|
||||||
atx == 0 &&
|
|
||||||
px + sx != nx &&
|
|
||||||
tty_term_has(tty->term, TTYC_EL1) &&
|
|
||||||
!tty_fake_bce(tty, defaults, 8) &&
|
|
||||||
c->overlay_check == NULL) {
|
|
||||||
tty_default_attributes(tty, defaults, palette, 8,
|
|
||||||
s->hyperlinks);
|
|
||||||
tty_cursor(tty, nx - 1, aty);
|
|
||||||
tty_putcode(tty, TTYC_EL1);
|
|
||||||
cleared = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log_debug("%s: wrapped line %u", __func__, aty);
|
|
||||||
wrapped = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&last, &grid_default_cell, sizeof last);
|
|
||||||
len = 0;
|
|
||||||
width = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < sx; i++) {
|
|
||||||
grid_view_get_cell(gd, px + i, py, &gc);
|
|
||||||
gcp = tty_check_codeset(tty, &gc);
|
|
||||||
if (len != 0 &&
|
|
||||||
(!tty_check_overlay(tty, atx + ux + width, aty) ||
|
|
||||||
(gcp->attr & GRID_ATTR_CHARSET) ||
|
|
||||||
gcp->flags != last.flags ||
|
|
||||||
gcp->attr != last.attr ||
|
|
||||||
gcp->fg != last.fg ||
|
|
||||||
gcp->bg != last.bg ||
|
|
||||||
gcp->us != last.us ||
|
|
||||||
gcp->link != last.link ||
|
|
||||||
ux + width + gcp->data.width > nx ||
|
|
||||||
(sizeof buf) - len < gcp->data.size)) {
|
|
||||||
tty_attributes(tty, &last, defaults, palette,
|
|
||||||
s->hyperlinks);
|
|
||||||
if (last.flags & GRID_FLAG_CLEARED) {
|
|
||||||
log_debug("%s: %zu cleared", __func__, len);
|
|
||||||
tty_clear_line(tty, defaults, aty, atx + ux,
|
|
||||||
width, last.bg);
|
|
||||||
} else {
|
|
||||||
if (!wrapped || atx != 0 || ux != 0)
|
|
||||||
tty_cursor(tty, atx + ux, aty);
|
|
||||||
tty_putn(tty, buf, len, width);
|
|
||||||
}
|
|
||||||
ux += width;
|
|
||||||
|
|
||||||
len = 0;
|
|
||||||
width = 0;
|
|
||||||
wrapped = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gcp->flags & GRID_FLAG_SELECTED)
|
|
||||||
screen_select_cell(s, &last, gcp);
|
|
||||||
else
|
|
||||||
memcpy(&last, gcp, sizeof last);
|
|
||||||
|
|
||||||
tty_check_overlay_range(tty, atx + ux, aty, gcp->data.width,
|
|
||||||
&r);
|
|
||||||
hidden = 0;
|
|
||||||
for (j = 0; j < OVERLAY_MAX_RANGES; j++)
|
|
||||||
hidden += r.nx[j];
|
|
||||||
hidden = gcp->data.width - hidden;
|
|
||||||
if (hidden != 0 && hidden == gcp->data.width) {
|
|
||||||
if (~gcp->flags & GRID_FLAG_PADDING)
|
|
||||||
ux += gcp->data.width;
|
|
||||||
} else if (hidden != 0 || ux + gcp->data.width > nx) {
|
|
||||||
if (~gcp->flags & GRID_FLAG_PADDING) {
|
|
||||||
tty_attributes(tty, &last, defaults, palette,
|
|
||||||
s->hyperlinks);
|
|
||||||
for (j = 0; j < OVERLAY_MAX_RANGES; j++) {
|
|
||||||
if (r.nx[j] == 0)
|
|
||||||
continue;
|
|
||||||
/* Effective width drawn so far. */
|
|
||||||
eux = r.px[j] - atx;
|
|
||||||
if (eux < nx) {
|
|
||||||
tty_cursor(tty, r.px[j], aty);
|
|
||||||
nxx = nx - eux;
|
|
||||||
if (r.nx[j] > nxx)
|
|
||||||
r.nx[j] = nxx;
|
|
||||||
tty_repeat_space(tty, r.nx[j]);
|
|
||||||
ux = eux + r.nx[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (gcp->attr & GRID_ATTR_CHARSET) {
|
|
||||||
tty_attributes(tty, &last, defaults, palette,
|
|
||||||
s->hyperlinks);
|
|
||||||
tty_cursor(tty, atx + ux, aty);
|
|
||||||
for (j = 0; j < gcp->data.size; j++)
|
|
||||||
tty_putc(tty, gcp->data.data[j]);
|
|
||||||
ux += gcp->data.width;
|
|
||||||
} else if (~gcp->flags & GRID_FLAG_PADDING) {
|
|
||||||
memcpy(buf + len, gcp->data.data, gcp->data.size);
|
|
||||||
len += gcp->data.size;
|
|
||||||
width += gcp->data.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (len != 0 && ((~last.flags & GRID_FLAG_CLEARED) || last.bg != 8)) {
|
|
||||||
tty_attributes(tty, &last, defaults, palette, s->hyperlinks);
|
|
||||||
if (last.flags & GRID_FLAG_CLEARED) {
|
|
||||||
log_debug("%s: %zu cleared (end)", __func__, len);
|
|
||||||
tty_clear_line(tty, defaults, aty, atx + ux, width,
|
|
||||||
last.bg);
|
|
||||||
} else {
|
|
||||||
if (!wrapped || atx != 0 || ux != 0)
|
|
||||||
tty_cursor(tty, atx + ux, aty);
|
|
||||||
tty_putn(tty, buf, len, width);
|
|
||||||
}
|
|
||||||
ux += width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cleared && ux < nx) {
|
|
||||||
log_debug("%s: %u to end of line (%zu cleared)", __func__,
|
|
||||||
nx - ux, len);
|
|
||||||
tty_default_attributes(tty, defaults, palette, 8,
|
|
||||||
s->hyperlinks);
|
|
||||||
tty_clear_line(tty, defaults, aty, atx + ux, nx - ux, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
tty->flags = (tty->flags & ~TTY_NOCURSOR) | flags;
|
|
||||||
tty_update_mode(tty, tty->mode, s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SIXEL
|
#ifdef ENABLE_SIXEL
|
||||||
@@ -1660,7 +1527,7 @@ tty_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
|
|||||||
ttyctx->bigger = tty_window_offset(&c->tty, &ttyctx->wox, &ttyctx->woy,
|
ttyctx->bigger = tty_window_offset(&c->tty, &ttyctx->wox, &ttyctx->woy,
|
||||||
&ttyctx->wsx, &ttyctx->wsy);
|
&ttyctx->wsx, &ttyctx->wsy);
|
||||||
|
|
||||||
ttyctx->yoff = ttyctx->ryoff = wp->yoff;
|
ttyctx->yoff = ttyctx->ryoff = wp->yoff; /* xxxx find another way to do this */
|
||||||
if (status_at_line(c) == 0)
|
if (status_at_line(c) == 0)
|
||||||
ttyctx->yoff += status_line_size(c);
|
ttyctx->yoff += status_line_size(c);
|
||||||
|
|
||||||
@@ -1688,7 +1555,7 @@ tty_draw_images(struct client *c, struct window_pane *wp, struct screen *s)
|
|||||||
ttyctx.sy = wp->sy;
|
ttyctx.sy = wp->sy;
|
||||||
|
|
||||||
ttyctx.ptr = im;
|
ttyctx.ptr = im;
|
||||||
ttyctx.arg = wp;
|
ttyctx.arg = wp; /* xxx remove this */
|
||||||
ttyctx.set_client_cb = tty_set_client_cb;
|
ttyctx.set_client_cb = tty_set_client_cb;
|
||||||
ttyctx.allow_invisible_panes = 1;
|
ttyctx.allow_invisible_panes = 1;
|
||||||
tty_write_one(tty_cmd_sixelimage, c, &ttyctx);
|
tty_write_one(tty_cmd_sixelimage, c, &ttyctx);
|
||||||
@@ -2002,8 +1869,8 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
void
|
void
|
||||||
tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct client *c = tty->client;
|
struct client *c = tty->client;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (ctx->bigger ||
|
if (ctx->bigger ||
|
||||||
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
|
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
|
||||||
@@ -2011,7 +1878,8 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
!tty_term_has(tty->term, TTYC_CSR) ||
|
!tty_term_has(tty->term, TTYC_CSR) ||
|
||||||
ctx->sx == 1 ||
|
ctx->sx == 1 ||
|
||||||
ctx->sy == 1 ||
|
ctx->sy == 1 ||
|
||||||
c->overlay_check != NULL) {
|
c->overlay_check != NULL ||
|
||||||
|
ctx->obscured) {
|
||||||
tty_redraw_region(tty, ctx);
|
tty_redraw_region(tty, ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2169,7 +2037,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
{
|
{
|
||||||
const struct grid_cell *gcp = ctx->cell;
|
const struct grid_cell *gcp = ctx->cell;
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct overlay_ranges r;
|
struct visible_ranges *r = NULL;
|
||||||
u_int px, py, i, vis = 0;
|
u_int px, py, i, vis = 0;
|
||||||
|
|
||||||
px = ctx->xoff + ctx->ocx - ctx->wox;
|
px = ctx->xoff + ctx->ocx - ctx->wox;
|
||||||
@@ -2178,11 +2046,18 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
(gcp->data.width == 1 && !tty_check_overlay(tty, px, py)))
|
(gcp->data.width == 1 && !tty_check_overlay(tty, px, py)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (ctx->num == 2) {
|
||||||
|
/* xxxx need to check visible range */
|
||||||
|
tty_draw_line(tty, s, 0, s->cy, screen_size_x(s),
|
||||||
|
ctx->xoff - ctx->wox, py, &ctx->defaults, ctx->palette);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle partially obstructed wide characters. */
|
/* Handle partially obstructed wide characters. */
|
||||||
if (gcp->data.width > 1) {
|
if (gcp->data.width > 1) {
|
||||||
tty_check_overlay_range(tty, px, py, gcp->data.width, &r);
|
r = tty_check_overlay_range(tty, px, py, gcp->data.width);
|
||||||
for (i = 0; i < OVERLAY_MAX_RANGES; i++)
|
for (i = 0; i < r->used; i++)
|
||||||
vis += r.nx[i];
|
vis += r->ranges[i].nx;
|
||||||
if (vis < gcp->data.width) {
|
if (vis < gcp->data.width) {
|
||||||
tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width,
|
tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width,
|
||||||
px, py, &ctx->defaults, ctx->palette);
|
px, py, &ctx->defaults, ctx->palette);
|
||||||
@@ -2198,8 +2073,9 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
tty_margin_off(tty);
|
tty_margin_off(tty);
|
||||||
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
|
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
|
||||||
|
|
||||||
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,
|
if (screen_redraw_is_visible(r, px))
|
||||||
ctx->s->hyperlinks);
|
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,
|
||||||
|
ctx->s->hyperlinks);
|
||||||
|
|
||||||
if (ctx->num == 1)
|
if (ctx->num == 1)
|
||||||
tty_invalidate(tty);
|
tty_invalidate(tty);
|
||||||
@@ -2208,7 +2084,8 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
void
|
void
|
||||||
tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct overlay_ranges r;
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
u_int i, px, py, cx;
|
u_int i, px, py, cx;
|
||||||
char *cp = ctx->ptr;
|
char *cp = ctx->ptr;
|
||||||
|
|
||||||
@@ -2233,20 +2110,21 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
|
|
||||||
tty_margin_off(tty);
|
tty_margin_off(tty);
|
||||||
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
|
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
|
||||||
tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette, ctx->s->hyperlinks);
|
tty_attributes(tty, ctx->cell, &ctx->defaults, ctx->palette,
|
||||||
|
ctx->s->hyperlinks);
|
||||||
|
|
||||||
/* Get tty position from pane position for overlay check. */
|
/* Get tty position from pane position for overlay check. */
|
||||||
px = ctx->xoff + ctx->ocx - ctx->wox;
|
px = ctx->xoff + ctx->ocx - ctx->wox;
|
||||||
py = ctx->yoff + ctx->ocy - ctx->woy;
|
py = ctx->yoff + ctx->ocy - ctx->woy;
|
||||||
|
|
||||||
tty_check_overlay_range(tty, px, py, ctx->num, &r);
|
r = tty_check_overlay_range(tty, px, py, ctx->num);
|
||||||
for (i = 0; i < OVERLAY_MAX_RANGES; i++) {
|
for (i = 0; i < r->used; i++) {
|
||||||
if (r.nx[i] == 0)
|
ri = &r->ranges[i];
|
||||||
continue;
|
if (ri->nx != 0) {
|
||||||
/* Convert back to pane position for printing. */
|
cx = ri->px - ctx->xoff + ctx->wox;
|
||||||
cx = r.px[i] - ctx->xoff + ctx->wox;
|
tty_cursor_pane_unless_wrap(tty, ctx, cx, ctx->ocy);
|
||||||
tty_cursor_pane_unless_wrap(tty, ctx, cx, ctx->ocy);
|
tty_putn(tty, cp + ri->px - px, ri->nx, ri->nx);
|
||||||
tty_putn(tty, cp + r.px[i] - px, r.nx[i], r.nx[i]);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2257,7 +2135,7 @@ tty_cmd_setselection(struct tty *tty, const struct tty_ctx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tty_set_selection(struct tty *tty, const char *flags, const char *buf,
|
tty_set_selection(struct tty *tty, const char *clip, const char *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
char *encoded;
|
char *encoded;
|
||||||
@@ -2273,7 +2151,7 @@ tty_set_selection(struct tty *tty, const char *flags, const char *buf,
|
|||||||
|
|
||||||
b64_ntop(buf, len, encoded, size);
|
b64_ntop(buf, len, encoded, size);
|
||||||
tty->flags |= TTY_NOBLOCK;
|
tty->flags |= TTY_NOBLOCK;
|
||||||
tty_putcode_ss(tty, TTYC_MS, flags, encoded);
|
tty_putcode_ss(tty, TTYC_MS, clip, encoded);
|
||||||
|
|
||||||
free(encoded);
|
free(encoded);
|
||||||
}
|
}
|
||||||
@@ -2380,7 +2258,6 @@ tty_cell(struct tty *tty, const struct grid_cell *gc,
|
|||||||
|
|
||||||
/* If it is a single character, write with putc to handle ACS. */
|
/* If it is a single character, write with putc to handle ACS. */
|
||||||
if (gcp->data.size == 1) {
|
if (gcp->data.size == 1) {
|
||||||
tty_attributes(tty, gcp, defaults, palette, hl);
|
|
||||||
if (*gcp->data.data < 0x20 || *gcp->data.data == 0x7f)
|
if (*gcp->data.data < 0x20 || *gcp->data.data == 0x7f)
|
||||||
return;
|
return;
|
||||||
tty_putc(tty, *gcp->data.data);
|
tty_putc(tty, *gcp->data.data);
|
||||||
@@ -2488,8 +2365,17 @@ tty_margin_off(struct tty *tty)
|
|||||||
static void
|
static void
|
||||||
tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
|
tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
|
||||||
{
|
{
|
||||||
tty_margin(tty, ctx->xoff - ctx->wox,
|
int l, r;
|
||||||
ctx->xoff + ctx->sx - 1 - ctx->wox);
|
|
||||||
|
l = ctx->xoff - ctx->wox;
|
||||||
|
r = ctx->xoff + ctx->sx - 1 - ctx->wox;
|
||||||
|
|
||||||
|
if (l < 0) l = 0;
|
||||||
|
if (l > (int)ctx->wsx) l = ctx->wsx;
|
||||||
|
if (r < 0) r = 0;
|
||||||
|
if (r > (int)ctx->wsx) r = ctx->wsx;
|
||||||
|
|
||||||
|
tty_margin(tty, l, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set margin at absolute position. */
|
/* Set margin at absolute position. */
|
||||||
@@ -3193,7 +3079,7 @@ tty_default_colours(struct grid_cell *gc, struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
tty_default_attributes(struct tty *tty, const struct grid_cell *defaults,
|
tty_default_attributes(struct tty *tty, const struct grid_cell *defaults,
|
||||||
struct colour_palette *palette, u_int bg, struct hyperlinks *hl)
|
struct colour_palette *palette, u_int bg, struct hyperlinks *hl)
|
||||||
{
|
{
|
||||||
@@ -3208,12 +3094,6 @@ static void
|
|||||||
tty_clipboard_query_callback(__unused int fd, __unused short events, void *data)
|
tty_clipboard_query_callback(__unused int fd, __unused short events, void *data)
|
||||||
{
|
{
|
||||||
struct tty *tty = data;
|
struct tty *tty = data;
|
||||||
struct client *c = tty->client;
|
|
||||||
|
|
||||||
c->flags &= ~CLIENT_CLIPBOARDBUFFER;
|
|
||||||
free(c->clipboard_panes);
|
|
||||||
c->clipboard_panes = NULL;
|
|
||||||
c->clipboard_npanes = 0;
|
|
||||||
|
|
||||||
tty->flags &= ~TTY_OSC52QUERY;
|
tty->flags &= ~TTY_OSC52QUERY;
|
||||||
}
|
}
|
||||||
@@ -3223,11 +3103,9 @@ tty_clipboard_query(struct tty *tty)
|
|||||||
{
|
{
|
||||||
struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT };
|
struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT };
|
||||||
|
|
||||||
if ((~tty->flags & TTY_STARTED) || (tty->flags & TTY_OSC52QUERY))
|
if ((tty->flags & TTY_STARTED) && (~tty->flags & TTY_OSC52QUERY)) {
|
||||||
return;
|
tty_putcode_ss(tty, TTYC_MS, "", "?");
|
||||||
tty_putcode_ss(tty, TTYC_MS, "", "?");
|
tty->flags |= TTY_OSC52QUERY;
|
||||||
|
evtimer_add(&tty->clipboard_timer, &tv);
|
||||||
tty->flags |= TTY_OSC52QUERY;
|
}
|
||||||
evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty);
|
|
||||||
evtimer_add(&tty->clipboard_timer, &tv);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ utf8_should_combine(const struct utf8_data *with, const struct utf8_data *add)
|
|||||||
case 0x1F47C:
|
case 0x1F47C:
|
||||||
case 0x1F481:
|
case 0x1F481:
|
||||||
case 0x1F482:
|
case 0x1F482:
|
||||||
|
case 0x1F483:
|
||||||
case 0x1F485:
|
case 0x1F485:
|
||||||
case 0x1F486:
|
case 0x1F486:
|
||||||
case 0x1F487:
|
case 0x1F487:
|
||||||
|
|||||||
10
utf8.c
10
utf8.c
@@ -652,7 +652,7 @@ utf8_append(struct utf8_data *ud, u_char ch)
|
|||||||
* bytes available for each character from src (for \abc or UTF-8) plus space
|
* bytes available for each character from src (for \abc or UTF-8) plus space
|
||||||
* for \0.
|
* for \0.
|
||||||
*/
|
*/
|
||||||
int
|
size_t
|
||||||
utf8_strvis(char *dst, const char *src, size_t len, int flag)
|
utf8_strvis(char *dst, const char *src, size_t len, int flag)
|
||||||
{
|
{
|
||||||
struct utf8_data ud;
|
struct utf8_data ud;
|
||||||
@@ -690,11 +690,11 @@ utf8_strvis(char *dst, const char *src, size_t len, int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Same as utf8_strvis but allocate the buffer. */
|
/* Same as utf8_strvis but allocate the buffer. */
|
||||||
int
|
size_t
|
||||||
utf8_stravis(char **dst, const char *src, int flag)
|
utf8_stravis(char **dst, const char *src, int flag)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
int len;
|
size_t len;
|
||||||
|
|
||||||
buf = xreallocarray(NULL, 4, strlen(src) + 1);
|
buf = xreallocarray(NULL, 4, strlen(src) + 1);
|
||||||
len = utf8_strvis(buf, src, strlen(src), flag);
|
len = utf8_strvis(buf, src, strlen(src), flag);
|
||||||
@@ -704,11 +704,11 @@ utf8_stravis(char **dst, const char *src, int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Same as utf8_strvis but allocate the buffer. */
|
/* Same as utf8_strvis but allocate the buffer. */
|
||||||
int
|
size_t
|
||||||
utf8_stravisx(char **dst, const char *src, size_t srclen, int flag)
|
utf8_stravisx(char **dst, const char *src, size_t srclen, int flag)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
int len;
|
size_t len;
|
||||||
|
|
||||||
buf = xreallocarray(NULL, 4, srclen + 1);
|
buf = xreallocarray(NULL, 4, srclen + 1);
|
||||||
len = utf8_strvis(buf, src, srclen, flag);
|
len = utf8_strvis(buf, src, srclen, flag);
|
||||||
|
|||||||
@@ -76,18 +76,6 @@ const struct window_mode window_buffer_mode = {
|
|||||||
.key = window_buffer_key,
|
.key = window_buffer_key,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum window_buffer_sort_type {
|
|
||||||
WINDOW_BUFFER_BY_TIME,
|
|
||||||
WINDOW_BUFFER_BY_NAME,
|
|
||||||
WINDOW_BUFFER_BY_SIZE,
|
|
||||||
};
|
|
||||||
static const char *window_buffer_sort_list[] = {
|
|
||||||
"time",
|
|
||||||
"name",
|
|
||||||
"size"
|
|
||||||
};
|
|
||||||
static struct mode_tree_sort_criteria *window_buffer_sort;
|
|
||||||
|
|
||||||
struct window_buffer_itemdata {
|
struct window_buffer_itemdata {
|
||||||
const char *name;
|
const char *name;
|
||||||
u_int order;
|
u_int order;
|
||||||
@@ -113,6 +101,13 @@ struct window_buffer_editdata {
|
|||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum sort_order window_buffer_order_seq[] = {
|
||||||
|
SORT_CREATION,
|
||||||
|
SORT_NAME,
|
||||||
|
SORT_SIZE,
|
||||||
|
SORT_END,
|
||||||
|
};
|
||||||
|
|
||||||
static struct window_buffer_itemdata *
|
static struct window_buffer_itemdata *
|
||||||
window_buffer_add_item(struct window_buffer_modedata *data)
|
window_buffer_add_item(struct window_buffer_modedata *data)
|
||||||
{
|
{
|
||||||
@@ -131,35 +126,14 @@ window_buffer_free_item(struct window_buffer_itemdata *item)
|
|||||||
free(item);
|
free(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
window_buffer_cmp(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
const struct window_buffer_itemdata *const *a = a0;
|
|
||||||
const struct window_buffer_itemdata *const *b = b0;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
if (window_buffer_sort->field == WINDOW_BUFFER_BY_TIME)
|
|
||||||
result = (*b)->order - (*a)->order;
|
|
||||||
else if (window_buffer_sort->field == WINDOW_BUFFER_BY_SIZE)
|
|
||||||
result = (*b)->size - (*a)->size;
|
|
||||||
|
|
||||||
/* Use WINDOW_BUFFER_BY_NAME as default order and tie breaker. */
|
|
||||||
if (result == 0)
|
|
||||||
result = strcmp((*a)->name, (*b)->name);
|
|
||||||
|
|
||||||
if (window_buffer_sort->reversed)
|
|
||||||
result = -result;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_buffer_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
window_buffer_build(void *modedata, struct sort_criteria *sort_crit,
|
||||||
__unused uint64_t *tag, const char *filter)
|
__unused uint64_t *tag, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_buffer_modedata *data = modedata;
|
struct window_buffer_modedata *data = modedata;
|
||||||
struct window_buffer_itemdata *item;
|
struct window_buffer_itemdata *item;
|
||||||
u_int i;
|
u_int i, n;
|
||||||
struct paste_buffer *pb = NULL;
|
struct paste_buffer *pb, **l;
|
||||||
char *text, *cp;
|
char *text, *cp;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
struct session *s = NULL;
|
struct session *s = NULL;
|
||||||
@@ -172,17 +146,14 @@ window_buffer_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
|||||||
data->item_list = NULL;
|
data->item_list = NULL;
|
||||||
data->item_size = 0;
|
data->item_size = 0;
|
||||||
|
|
||||||
while ((pb = paste_walk(pb)) != NULL) {
|
l = sort_get_buffers(&n, sort_crit);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
item = window_buffer_add_item(data);
|
item = window_buffer_add_item(data);
|
||||||
item->name = xstrdup(paste_buffer_name(pb));
|
item->name = xstrdup(paste_buffer_name(l[i]));
|
||||||
paste_buffer_data(pb, &item->size);
|
paste_buffer_data(l[i], &item->size);
|
||||||
item->order = paste_buffer_order(pb);
|
item->order = paste_buffer_order(l[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
window_buffer_sort = sort_crit;
|
|
||||||
qsort(data->item_list, data->item_size, sizeof *data->item_list,
|
|
||||||
window_buffer_cmp);
|
|
||||||
|
|
||||||
if (cmd_find_valid_state(&data->fs)) {
|
if (cmd_find_valid_state(&data->fs)) {
|
||||||
s = data->fs.s;
|
s = data->fs.s;
|
||||||
wl = data->fs.wl;
|
wl = data->fs.wl;
|
||||||
@@ -216,7 +187,6 @@ window_buffer_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
|||||||
|
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -351,6 +321,14 @@ window_buffer_get_key(void *modedata, void *itemdata, u_int line)
|
|||||||
return (key);
|
return (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_buffer_sort(struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
sort_crit->order_seq = window_buffer_order_seq;
|
||||||
|
if (sort_crit->order == SORT_END)
|
||||||
|
sort_crit->order = sort_crit->order_seq[0];
|
||||||
|
}
|
||||||
|
|
||||||
static struct screen *
|
static struct screen *
|
||||||
window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||||
struct args *args)
|
struct args *args)
|
||||||
@@ -378,8 +356,8 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
|||||||
|
|
||||||
data->data = mode_tree_start(wp, args, window_buffer_build,
|
data->data = mode_tree_start(wp, args, window_buffer_build,
|
||||||
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
|
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
|
||||||
window_buffer_get_key, NULL, data, window_buffer_menu_items,
|
window_buffer_get_key, NULL, window_buffer_sort, data,
|
||||||
window_buffer_sort_list, nitems(window_buffer_sort_list), &s);
|
window_buffer_menu_items, &s);
|
||||||
mode_tree_zoom(data->data, args);
|
mode_tree_zoom(data->data, args);
|
||||||
|
|
||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
|
|||||||
@@ -71,20 +71,6 @@ const struct window_mode window_client_mode = {
|
|||||||
.key = window_client_key,
|
.key = window_client_key,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum window_client_sort_type {
|
|
||||||
WINDOW_CLIENT_BY_NAME,
|
|
||||||
WINDOW_CLIENT_BY_SIZE,
|
|
||||||
WINDOW_CLIENT_BY_CREATION_TIME,
|
|
||||||
WINDOW_CLIENT_BY_ACTIVITY_TIME,
|
|
||||||
};
|
|
||||||
static const char *window_client_sort_list[] = {
|
|
||||||
"name",
|
|
||||||
"size",
|
|
||||||
"creation",
|
|
||||||
"activity"
|
|
||||||
};
|
|
||||||
static struct mode_tree_sort_criteria *window_client_sort;
|
|
||||||
|
|
||||||
struct window_client_itemdata {
|
struct window_client_itemdata {
|
||||||
struct client *c;
|
struct client *c;
|
||||||
};
|
};
|
||||||
@@ -101,6 +87,14 @@ struct window_client_modedata {
|
|||||||
u_int item_size;
|
u_int item_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum sort_order window_client_order_seq[] = {
|
||||||
|
SORT_NAME,
|
||||||
|
SORT_SIZE,
|
||||||
|
SORT_CREATION,
|
||||||
|
SORT_ACTIVITY,
|
||||||
|
SORT_END,
|
||||||
|
};
|
||||||
|
|
||||||
static struct window_client_itemdata *
|
static struct window_client_itemdata *
|
||||||
window_client_add_item(struct window_client_modedata *data)
|
window_client_add_item(struct window_client_modedata *data)
|
||||||
{
|
{
|
||||||
@@ -119,54 +113,14 @@ window_client_free_item(struct window_client_itemdata *item)
|
|||||||
free(item);
|
free(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
window_client_cmp(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
const struct window_client_itemdata *const *a = a0;
|
|
||||||
const struct window_client_itemdata *const *b = b0;
|
|
||||||
const struct window_client_itemdata *itema = *a;
|
|
||||||
const struct window_client_itemdata *itemb = *b;
|
|
||||||
struct client *ca = itema->c;
|
|
||||||
struct client *cb = itemb->c;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
switch (window_client_sort->field) {
|
|
||||||
case WINDOW_CLIENT_BY_SIZE:
|
|
||||||
result = ca->tty.sx - cb->tty.sx;
|
|
||||||
if (result == 0)
|
|
||||||
result = ca->tty.sy - cb->tty.sy;
|
|
||||||
break;
|
|
||||||
case WINDOW_CLIENT_BY_CREATION_TIME:
|
|
||||||
if (timercmp(&ca->creation_time, &cb->creation_time, >))
|
|
||||||
result = -1;
|
|
||||||
else if (timercmp(&ca->creation_time, &cb->creation_time, <))
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
case WINDOW_CLIENT_BY_ACTIVITY_TIME:
|
|
||||||
if (timercmp(&ca->activity_time, &cb->activity_time, >))
|
|
||||||
result = -1;
|
|
||||||
else if (timercmp(&ca->activity_time, &cb->activity_time, <))
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use WINDOW_CLIENT_BY_NAME as default order and tie breaker. */
|
|
||||||
if (result == 0)
|
|
||||||
result = strcmp(ca->name, cb->name);
|
|
||||||
|
|
||||||
if (window_client_sort->reversed)
|
|
||||||
result = -result;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_client_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
window_client_build(void *modedata, struct sort_criteria *sort_crit,
|
||||||
__unused uint64_t *tag, const char *filter)
|
__unused uint64_t *tag, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_client_modedata *data = modedata;
|
struct window_client_modedata *data = modedata;
|
||||||
struct window_client_itemdata *item;
|
struct window_client_itemdata *item;
|
||||||
u_int i;
|
u_int i, n;
|
||||||
struct client *c;
|
struct client *c, **l;
|
||||||
char *text, *cp;
|
char *text, *cp;
|
||||||
|
|
||||||
for (i = 0; i < data->item_size; i++)
|
for (i = 0; i < data->item_size; i++)
|
||||||
@@ -175,20 +129,18 @@ window_client_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
|||||||
data->item_list = NULL;
|
data->item_list = NULL;
|
||||||
data->item_size = 0;
|
data->item_size = 0;
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
l = sort_get_clients(&n, sort_crit);
|
||||||
if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
for (i = 0; i < n; i++) {
|
||||||
|
if (l[i]->session == NULL ||
|
||||||
|
(l[i]->flags & CLIENT_UNATTACHEDFLAGS))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
item = window_client_add_item(data);
|
item = window_client_add_item(data);
|
||||||
item->c = c;
|
item->c = l[i];
|
||||||
|
|
||||||
c->references++;
|
l[i]->references++;
|
||||||
}
|
}
|
||||||
|
|
||||||
window_client_sort = sort_crit;
|
|
||||||
qsort(data->item_list, data->item_size, sizeof *data->item_list,
|
|
||||||
window_client_cmp);
|
|
||||||
|
|
||||||
for (i = 0; i < data->item_size; i++) {
|
for (i = 0; i < data->item_size; i++) {
|
||||||
item = data->item_list[i];
|
item = data->item_list[i];
|
||||||
c = item->c;
|
c = item->c;
|
||||||
@@ -280,6 +232,14 @@ window_client_get_key(void *modedata, void *itemdata, u_int line)
|
|||||||
return (key);
|
return (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_client_sort(struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
sort_crit->order_seq = window_client_order_seq;
|
||||||
|
if (sort_crit->order == SORT_END)
|
||||||
|
sort_crit->order = sort_crit->order_seq[0];
|
||||||
|
}
|
||||||
|
|
||||||
static struct screen *
|
static struct screen *
|
||||||
window_client_init(struct window_mode_entry *wme,
|
window_client_init(struct window_mode_entry *wme,
|
||||||
__unused struct cmd_find_state *fs, struct args *args)
|
__unused struct cmd_find_state *fs, struct args *args)
|
||||||
@@ -306,8 +266,8 @@ window_client_init(struct window_mode_entry *wme,
|
|||||||
|
|
||||||
data->data = mode_tree_start(wp, args, window_client_build,
|
data->data = mode_tree_start(wp, args, window_client_build,
|
||||||
window_client_draw, NULL, window_client_menu, NULL,
|
window_client_draw, NULL, window_client_menu, NULL,
|
||||||
window_client_get_key, NULL, data, window_client_menu_items,
|
window_client_get_key, NULL, window_client_sort, data,
|
||||||
window_client_sort_list, nitems(window_client_sort_list), &s);
|
window_client_menu_items, &s);
|
||||||
mode_tree_zoom(data->data, args);
|
mode_tree_zoom(data->data, args);
|
||||||
|
|
||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
|
|||||||
@@ -123,6 +123,26 @@ const char window_clock_table[14][5][5] = {
|
|||||||
{ 1,0,0,0,1 } },
|
{ 1,0,0,0,1 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_clock_start_timer(struct window_mode_entry *wme)
|
||||||
|
{
|
||||||
|
struct window_clock_mode_data *data = wme->data;
|
||||||
|
struct timeval tv;
|
||||||
|
struct timespec ts;
|
||||||
|
long delay;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
delay = 1000000 - (ts.tv_nsec / 1000);
|
||||||
|
|
||||||
|
tv.tv_sec = delay / 1000000;
|
||||||
|
tv.tv_usec = delay % 1000000;
|
||||||
|
if (tv.tv_sec < 0 || (tv.tv_sec == 0 && tv.tv_usec <= 0)) {
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
}
|
||||||
|
evtimer_add(&data->timer, &tv);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_clock_timer_callback(__unused int fd, __unused short events, void *arg)
|
window_clock_timer_callback(__unused int fd, __unused short events, void *arg)
|
||||||
{
|
{
|
||||||
@@ -131,23 +151,20 @@ window_clock_timer_callback(__unused int fd, __unused short events, void *arg)
|
|||||||
struct window_clock_mode_data *data = wme->data;
|
struct window_clock_mode_data *data = wme->data;
|
||||||
struct tm now, then;
|
struct tm now, then;
|
||||||
time_t t;
|
time_t t;
|
||||||
struct timeval tv = { .tv_sec = 1 };
|
|
||||||
|
|
||||||
evtimer_del(&data->timer);
|
evtimer_del(&data->timer);
|
||||||
evtimer_add(&data->timer, &tv);
|
|
||||||
|
|
||||||
if (TAILQ_FIRST(&wp->modes) != wme)
|
|
||||||
return;
|
|
||||||
|
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
gmtime_r(&t, &now);
|
gmtime_r(&t, &now);
|
||||||
gmtime_r(&data->tim, &then);
|
gmtime_r(&data->tim, &then);
|
||||||
if (now.tm_sec == then.tm_sec)
|
|
||||||
return;
|
|
||||||
data->tim = t;
|
|
||||||
|
|
||||||
window_clock_draw_screen(wme);
|
if (now.tm_sec != then.tm_sec) {
|
||||||
wp->flags |= PANE_REDRAW;
|
data->tim = t;
|
||||||
|
window_clock_draw_screen(wme);
|
||||||
|
wp->flags |= PANE_REDRAW;
|
||||||
|
}
|
||||||
|
|
||||||
|
window_clock_start_timer(wme);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct screen *
|
static struct screen *
|
||||||
@@ -157,13 +174,12 @@ window_clock_init(struct window_mode_entry *wme,
|
|||||||
struct window_pane *wp = wme->wp;
|
struct window_pane *wp = wme->wp;
|
||||||
struct window_clock_mode_data *data;
|
struct window_clock_mode_data *data;
|
||||||
struct screen *s;
|
struct screen *s;
|
||||||
struct timeval tv = { .tv_sec = 1 };
|
|
||||||
|
|
||||||
wme->data = data = xmalloc(sizeof *data);
|
wme->data = data = xmalloc(sizeof *data);
|
||||||
data->tim = time(NULL);
|
data->tim = time(NULL);
|
||||||
|
|
||||||
evtimer_set(&data->timer, window_clock_timer_callback, wme);
|
evtimer_set(&data->timer, window_clock_timer_callback, wme);
|
||||||
evtimer_add(&data->timer, &tv);
|
window_clock_start_timer(wme);
|
||||||
|
|
||||||
s = &data->screen;
|
s = &data->screen;
|
||||||
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
||||||
@@ -212,7 +228,6 @@ window_clock_draw_screen(struct window_mode_entry *wme)
|
|||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
struct grid_cell gc;
|
struct grid_cell gc;
|
||||||
char tim[64], *ptr;
|
char tim[64], *ptr;
|
||||||
const char *timeformat;
|
|
||||||
time_t t;
|
time_t t;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
u_int i, j, x, y, idx;
|
u_int i, j, x, y, idx;
|
||||||
@@ -226,20 +241,18 @@ window_clock_draw_screen(struct window_mode_entry *wme)
|
|||||||
tm = localtime(&t);
|
tm = localtime(&t);
|
||||||
if (style == 0 || style == 2) {
|
if (style == 0 || style == 2) {
|
||||||
if (style == 2)
|
if (style == 2)
|
||||||
timeformat = "%l:%M:%S ";
|
strftime(tim, sizeof tim, "%l:%M:%S ", localtime(&t));
|
||||||
else
|
else
|
||||||
timeformat = "%l:%M ";
|
strftime(tim, sizeof tim, "%l:%M ", localtime(&t));
|
||||||
strftime(tim, sizeof tim, timeformat, localtime(&t));
|
|
||||||
if (tm->tm_hour >= 12)
|
if (tm->tm_hour >= 12)
|
||||||
strlcat(tim, "PM", sizeof tim);
|
strlcat(tim, "PM", sizeof tim);
|
||||||
else
|
else
|
||||||
strlcat(tim, "AM", sizeof tim);
|
strlcat(tim, "AM", sizeof tim);
|
||||||
} else {
|
} else {
|
||||||
if (style == 3)
|
if (style == 3)
|
||||||
timeformat = "%H:%M:%S";
|
strftime(tim, sizeof tim, "%H:%M:%S", tm);
|
||||||
else
|
else
|
||||||
timeformat = "%H:%M";
|
strftime(tim, sizeof tim, "%H:%M", tm);
|
||||||
strftime(tim, sizeof tim, timeformat, tm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_write_clearscreen(&ctx, 8);
|
screen_write_clearscreen(&ctx, 8);
|
||||||
|
|||||||
264
window-copy.c
264
window-copy.c
@@ -42,7 +42,7 @@ static void window_copy_formats(struct window_mode_entry *,
|
|||||||
struct format_tree *);
|
struct format_tree *);
|
||||||
static struct screen *window_copy_get_screen(struct window_mode_entry *);
|
static struct screen *window_copy_get_screen(struct window_mode_entry *);
|
||||||
static void window_copy_scroll1(struct window_mode_entry *,
|
static void window_copy_scroll1(struct window_mode_entry *,
|
||||||
struct window_pane *wp, int, u_int, int);
|
struct window_pane *wp, int, u_int, u_int, int);
|
||||||
static void window_copy_pageup1(struct window_mode_entry *, int);
|
static void window_copy_pageup1(struct window_mode_entry *, int);
|
||||||
static int window_copy_pagedown1(struct window_mode_entry *, int, int);
|
static int window_copy_pagedown1(struct window_mode_entry *, int, int);
|
||||||
static void window_copy_next_paragraph(struct window_mode_entry *);
|
static void window_copy_next_paragraph(struct window_mode_entry *);
|
||||||
@@ -51,6 +51,7 @@ static void window_copy_redraw_selection(struct window_mode_entry *, u_int);
|
|||||||
static void window_copy_redraw_lines(struct window_mode_entry *, u_int,
|
static void window_copy_redraw_lines(struct window_mode_entry *, u_int,
|
||||||
u_int);
|
u_int);
|
||||||
static void window_copy_redraw_screen(struct window_mode_entry *);
|
static void window_copy_redraw_screen(struct window_mode_entry *);
|
||||||
|
static void window_copy_style_changed(struct window_mode_entry *);
|
||||||
static void window_copy_write_line(struct window_mode_entry *,
|
static void window_copy_write_line(struct window_mode_entry *,
|
||||||
struct screen_write_ctx *, u_int);
|
struct screen_write_ctx *, u_int);
|
||||||
static void window_copy_write_lines(struct window_mode_entry *,
|
static void window_copy_write_lines(struct window_mode_entry *,
|
||||||
@@ -158,6 +159,7 @@ const struct window_mode window_copy_mode = {
|
|||||||
.init = window_copy_init,
|
.init = window_copy_init,
|
||||||
.free = window_copy_free,
|
.free = window_copy_free,
|
||||||
.resize = window_copy_resize,
|
.resize = window_copy_resize,
|
||||||
|
.style_changed = window_copy_style_changed,
|
||||||
.key_table = window_copy_key_table,
|
.key_table = window_copy_key_table,
|
||||||
.command = window_copy_command,
|
.command = window_copy_command,
|
||||||
.formats = window_copy_formats,
|
.formats = window_copy_formats,
|
||||||
@@ -170,6 +172,7 @@ const struct window_mode window_view_mode = {
|
|||||||
.init = window_copy_view_init,
|
.init = window_copy_view_init,
|
||||||
.free = window_copy_free,
|
.free = window_copy_free,
|
||||||
.resize = window_copy_resize,
|
.resize = window_copy_resize,
|
||||||
|
.style_changed = window_copy_style_changed,
|
||||||
.key_table = window_copy_key_table,
|
.key_table = window_copy_key_table,
|
||||||
.command = window_copy_command,
|
.command = window_copy_command,
|
||||||
.formats = window_copy_formats,
|
.formats = window_copy_formats,
|
||||||
@@ -352,7 +355,7 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx,
|
|||||||
if (trim) {
|
if (trim) {
|
||||||
while (sy > screen_hsize(src)) {
|
while (sy > screen_hsize(src)) {
|
||||||
gl = grid_peek_line(src->grid, sy - 1);
|
gl = grid_peek_line(src->grid, sy - 1);
|
||||||
if (gl->cellused != 0)
|
if (gl == NULL || gl->cellused != 0)
|
||||||
break;
|
break;
|
||||||
sy--;
|
sy--;
|
||||||
}
|
}
|
||||||
@@ -491,7 +494,7 @@ window_copy_view_init(struct window_mode_entry *wme,
|
|||||||
|
|
||||||
data->backing = xmalloc(sizeof *data->backing);
|
data->backing = xmalloc(sizeof *data->backing);
|
||||||
screen_init(data->backing, sx, screen_size_y(base), UINT_MAX);
|
screen_init(data->backing, sx, screen_size_y(base), UINT_MAX);
|
||||||
data->ictx = input_init(NULL, NULL, NULL);
|
data->ictx = input_init(NULL, NULL, NULL, NULL);
|
||||||
data->mx = data->cx;
|
data->mx = data->cx;
|
||||||
data->my = screen_hsize(data->backing) + data->cy - data->oy;
|
data->my = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
data->showmark = 0;
|
data->showmark = 0;
|
||||||
@@ -593,19 +596,19 @@ window_copy_vadd(struct window_pane *wp, int parse, const char *fmt, va_list ap)
|
|||||||
|
|
||||||
void
|
void
|
||||||
window_copy_scroll(struct window_pane *wp, int sl_mpos, u_int my,
|
window_copy_scroll(struct window_pane *wp, int sl_mpos, u_int my,
|
||||||
int scroll_exit)
|
u_int tty_oy, int scroll_exit)
|
||||||
{
|
{
|
||||||
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
|
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
|
||||||
|
|
||||||
if (wme != NULL) {
|
if (wme != NULL) {
|
||||||
window_set_active_pane(wp->window, wp, 0);
|
window_set_active_pane(wp->window, wp, 0);
|
||||||
window_copy_scroll1(wme, wp, sl_mpos, my, scroll_exit);
|
window_copy_scroll1(wme, wp, sl_mpos, my, tty_oy, scroll_exit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
|
window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
|
||||||
int sl_mpos, u_int my, int scroll_exit)
|
int sl_mpos, u_int my, u_int tty_oy, int scroll_exit)
|
||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wme->data;
|
struct window_copy_mode_data *data = wme->data;
|
||||||
u_int ox, oy, px, py, n, offset, size;
|
u_int ox, oy, px, py, n, offset, size;
|
||||||
@@ -613,21 +616,29 @@ window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
|
|||||||
u_int slider_height = wp->sb_slider_h;
|
u_int slider_height = wp->sb_slider_h;
|
||||||
u_int sb_height = wp->sy, sb_top = wp->yoff;
|
u_int sb_height = wp->sy, sb_top = wp->yoff;
|
||||||
u_int sy = screen_size_y(data->backing);
|
u_int sy = screen_size_y(data->backing);
|
||||||
|
u_int my_w;
|
||||||
int new_slider_y, delta;
|
int new_slider_y, delta;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sl_mpos is where in the slider the user is dragging, mouse is
|
* sl_mpos is where in the slider the user is dragging, mouse is
|
||||||
* dragging this y point relative to top of slider.
|
* dragging this y point relative to top of slider.
|
||||||
|
*
|
||||||
|
* my is a raw tty y coordinate; sb_top (= wp->yoff) is a window
|
||||||
|
* coordinate. Convert my to window coordinates by adding tty_oy
|
||||||
|
* (the window pan offset). sl_mpos already has the statuslines
|
||||||
|
* adjustment baked in (see server_client_check_mouse), so no further
|
||||||
|
* statuslines correction is needed here.
|
||||||
*/
|
*/
|
||||||
if (my <= sb_top + sl_mpos) {
|
my_w = my + tty_oy;
|
||||||
|
if (my_w <= sb_top + (u_int)sl_mpos) {
|
||||||
/* Slider banged into top. */
|
/* Slider banged into top. */
|
||||||
new_slider_y = sb_top - wp->yoff;
|
new_slider_y = sb_top - wp->yoff;
|
||||||
} else if (my - sl_mpos > sb_top + sb_height - slider_height) {
|
} else if (my_w - sl_mpos > sb_top + sb_height - slider_height) {
|
||||||
/* Slider banged into bottom. */
|
/* Slider banged into bottom. */
|
||||||
new_slider_y = sb_top - wp->yoff + (sb_height - slider_height);
|
new_slider_y = sb_top - wp->yoff + (sb_height - slider_height);
|
||||||
} else {
|
} else {
|
||||||
/* Slider is somewhere in the middle. */
|
/* Slider is somewhere in the middle. */
|
||||||
new_slider_y = my - wp->yoff - sl_mpos + 1;
|
new_slider_y = my_w - wp->yoff - sl_mpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TAILQ_FIRST(&wp->modes) == NULL ||
|
if (TAILQ_FIRST(&wp->modes) == NULL ||
|
||||||
@@ -956,6 +967,18 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft)
|
|||||||
format_add(ft, "selection_present", "0");
|
format_add(ft, "selection_present", "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (data->selflag) {
|
||||||
|
case SEL_CHAR:
|
||||||
|
format_add(ft, "selection_mode", "char");
|
||||||
|
break;
|
||||||
|
case SEL_WORD:
|
||||||
|
format_add(ft, "selection_mode", "word");
|
||||||
|
break;
|
||||||
|
case SEL_LINE:
|
||||||
|
format_add(ft, "selection_mode", "line");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
format_add(ft, "search_present", "%d", data->searchmark != NULL);
|
format_add(ft, "search_present", "%d", data->searchmark != NULL);
|
||||||
format_add(ft, "search_timed_out", "%d", data->timeout);
|
format_add(ft, "search_timed_out", "%d", data->timeout);
|
||||||
if (data->searchcount != -1) {
|
if (data->searchcount != -1) {
|
||||||
@@ -1479,6 +1502,23 @@ window_copy_cmd_scroll_middle(struct window_copy_cmd_state *cs)
|
|||||||
return (window_copy_cmd_scroll_to(cs, mid_value));
|
return (window_copy_cmd_scroll_to(cs, mid_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scroll the pane to the mouse in the scrollbar. */
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_scroll_to_mouse(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct window_pane *wp = wme->wp;
|
||||||
|
struct client *c = cs->c;
|
||||||
|
struct mouse_event *m = cs->m;
|
||||||
|
int scroll_exit = args_has(cs->wargs, 'e');
|
||||||
|
u_int tty_ox, tty_oy, tty_sx, tty_sy;
|
||||||
|
|
||||||
|
tty_window_offset(&c->tty, &tty_ox, &tty_oy, &tty_sx, &tty_sy);
|
||||||
|
window_copy_scroll(wp, c->tty.mouse_slider_mpos, m->y, tty_oy,
|
||||||
|
scroll_exit);
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
/* Scroll line containing the cursor to the top. */
|
/* Scroll line containing the cursor to the top. */
|
||||||
static enum window_copy_cmd_action
|
static enum window_copy_cmd_action
|
||||||
window_copy_cmd_scroll_top(struct window_copy_cmd_state *cs)
|
window_copy_cmd_scroll_top(struct window_copy_cmd_state *cs)
|
||||||
@@ -2098,6 +2138,36 @@ window_copy_cmd_rectangle_toggle(struct window_copy_cmd_state *cs)
|
|||||||
return (WINDOW_COPY_CMD_NOTHING);
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_scroll_exit_on(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = cs->wme->data;
|
||||||
|
|
||||||
|
data->scroll_exit = 1;
|
||||||
|
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_scroll_exit_off(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = cs->wme->data;
|
||||||
|
|
||||||
|
data->scroll_exit = 0;
|
||||||
|
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum window_copy_cmd_action
|
||||||
|
window_copy_cmd_scroll_exit_toggle(struct window_copy_cmd_state *cs)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = cs->wme->data;
|
||||||
|
|
||||||
|
data->scroll_exit = !data->scroll_exit;
|
||||||
|
|
||||||
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
static enum window_copy_cmd_action
|
static enum window_copy_cmd_action
|
||||||
window_copy_cmd_scroll_down(struct window_copy_cmd_state *cs)
|
window_copy_cmd_scroll_down(struct window_copy_cmd_state *cs)
|
||||||
{
|
{
|
||||||
@@ -2673,15 +2743,24 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs)
|
|||||||
struct window_mode_entry *wme = cs->wme;
|
struct window_mode_entry *wme = cs->wme;
|
||||||
struct window_pane *wp = wme->swp;
|
struct window_pane *wp = wme->swp;
|
||||||
struct window_copy_mode_data *data = wme->data;
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
u_int oy_from_top;
|
||||||
|
|
||||||
if (data->viewmode)
|
if (data->viewmode)
|
||||||
return (WINDOW_COPY_CMD_NOTHING);
|
return (WINDOW_COPY_CMD_NOTHING);
|
||||||
|
oy_from_top = screen_hsize(data->backing) - data->oy;
|
||||||
|
|
||||||
screen_free(data->backing);
|
screen_free(data->backing);
|
||||||
free(data->backing);
|
free(data->backing);
|
||||||
data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL,
|
data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL,
|
||||||
NULL, wme->swp != wme->wp);
|
NULL, wme->swp != wme->wp);
|
||||||
|
|
||||||
|
if (oy_from_top <= screen_hsize(data->backing))
|
||||||
|
data->oy = screen_hsize(data->backing) - oy_from_top;
|
||||||
|
else {
|
||||||
|
data->cy = 0;
|
||||||
|
data->oy = screen_hsize(data->backing);
|
||||||
|
}
|
||||||
|
|
||||||
window_copy_size_changed(wme);
|
window_copy_size_changed(wme);
|
||||||
return (WINDOW_COPY_CMD_REDRAW);
|
return (WINDOW_COPY_CMD_REDRAW);
|
||||||
}
|
}
|
||||||
@@ -2691,446 +2770,559 @@ static const struct {
|
|||||||
u_int minargs;
|
u_int minargs;
|
||||||
u_int maxargs;
|
u_int maxargs;
|
||||||
struct args_parse args;
|
struct args_parse args;
|
||||||
|
|
||||||
|
#define WINDOW_COPY_CMD_FLAG_READONLY 0x1
|
||||||
|
int flags;
|
||||||
|
|
||||||
enum window_copy_cmd_clear clear;
|
enum window_copy_cmd_clear clear;
|
||||||
enum window_copy_cmd_action (*f)(struct window_copy_cmd_state *);
|
enum window_copy_cmd_action (*f)(struct window_copy_cmd_state *);
|
||||||
} window_copy_cmd_table[] = {
|
} window_copy_cmd_table[] = {
|
||||||
{ .command = "append-selection",
|
{ .command = "append-selection",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_append_selection
|
.f = window_copy_cmd_append_selection
|
||||||
},
|
},
|
||||||
{ .command = "append-selection-and-cancel",
|
{ .command = "append-selection-and-cancel",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_append_selection_and_cancel
|
.f = window_copy_cmd_append_selection_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "back-to-indentation",
|
{ .command = "back-to-indentation",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_back_to_indentation
|
.f = window_copy_cmd_back_to_indentation
|
||||||
},
|
},
|
||||||
{ .command = "begin-selection",
|
{ .command = "begin-selection",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_begin_selection
|
.f = window_copy_cmd_begin_selection
|
||||||
},
|
},
|
||||||
{ .command = "bottom-line",
|
{ .command = "bottom-line",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_bottom_line
|
.f = window_copy_cmd_bottom_line
|
||||||
},
|
},
|
||||||
{ .command = "cancel",
|
{ .command = "cancel",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_cancel
|
.f = window_copy_cmd_cancel
|
||||||
},
|
},
|
||||||
{ .command = "clear-selection",
|
{ .command = "clear-selection",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_clear_selection
|
.f = window_copy_cmd_clear_selection
|
||||||
},
|
},
|
||||||
{ .command = "copy-end-of-line",
|
{ .command = "copy-end-of-line",
|
||||||
.args = { "CP", 0, 1, NULL },
|
.args = { "CP", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_end_of_line
|
.f = window_copy_cmd_copy_end_of_line
|
||||||
},
|
},
|
||||||
{ .command = "copy-end-of-line-and-cancel",
|
{ .command = "copy-end-of-line-and-cancel",
|
||||||
.args = { "CP", 0, 1, NULL },
|
.args = { "CP", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_end_of_line_and_cancel
|
.f = window_copy_cmd_copy_end_of_line_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "copy-pipe-end-of-line",
|
{ .command = "copy-pipe-end-of-line",
|
||||||
.args = { "CP", 0, 2, NULL },
|
.args = { "CP", 0, 2, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_pipe_end_of_line
|
.f = window_copy_cmd_copy_pipe_end_of_line
|
||||||
},
|
},
|
||||||
{ .command = "copy-pipe-end-of-line-and-cancel",
|
{ .command = "copy-pipe-end-of-line-and-cancel",
|
||||||
.args = { "CP", 0, 2, NULL },
|
.args = { "CP", 0, 2, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_pipe_end_of_line_and_cancel
|
.f = window_copy_cmd_copy_pipe_end_of_line_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "copy-line",
|
{ .command = "copy-line",
|
||||||
.args = { "CP", 0, 1, NULL },
|
.args = { "CP", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_line
|
.f = window_copy_cmd_copy_line
|
||||||
},
|
},
|
||||||
{ .command = "copy-line-and-cancel",
|
{ .command = "copy-line-and-cancel",
|
||||||
.args = { "CP", 0, 1, NULL },
|
.args = { "CP", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_line_and_cancel
|
.f = window_copy_cmd_copy_line_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "copy-pipe-line",
|
{ .command = "copy-pipe-line",
|
||||||
.args = { "CP", 0, 2, NULL },
|
.args = { "CP", 0, 2, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_pipe_line
|
.f = window_copy_cmd_copy_pipe_line
|
||||||
},
|
},
|
||||||
{ .command = "copy-pipe-line-and-cancel",
|
{ .command = "copy-pipe-line-and-cancel",
|
||||||
.args = { "CP", 0, 2, NULL },
|
.args = { "CP", 0, 2, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_pipe_line_and_cancel
|
.f = window_copy_cmd_copy_pipe_line_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "copy-pipe-no-clear",
|
{ .command = "copy-pipe-no-clear",
|
||||||
.args = { "CP", 0, 2, NULL },
|
.args = { "CP", 0, 2, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
.f = window_copy_cmd_copy_pipe_no_clear
|
.f = window_copy_cmd_copy_pipe_no_clear
|
||||||
},
|
},
|
||||||
{ .command = "copy-pipe",
|
{ .command = "copy-pipe",
|
||||||
.args = { "CP", 0, 2, NULL },
|
.args = { "CP", 0, 2, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_pipe
|
.f = window_copy_cmd_copy_pipe
|
||||||
},
|
},
|
||||||
{ .command = "copy-pipe-and-cancel",
|
{ .command = "copy-pipe-and-cancel",
|
||||||
.args = { "CP", 0, 2, NULL },
|
.args = { "CP", 0, 2, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_pipe_and_cancel
|
.f = window_copy_cmd_copy_pipe_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "copy-selection-no-clear",
|
{ .command = "copy-selection-no-clear",
|
||||||
.args = { "CP", 0, 1, NULL },
|
.args = { "CP", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
.f = window_copy_cmd_copy_selection_no_clear
|
.f = window_copy_cmd_copy_selection_no_clear
|
||||||
},
|
},
|
||||||
{ .command = "copy-selection",
|
{ .command = "copy-selection",
|
||||||
.args = { "CP", 0, 1, NULL },
|
.args = { "CP", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_selection
|
.f = window_copy_cmd_copy_selection
|
||||||
},
|
},
|
||||||
{ .command = "copy-selection-and-cancel",
|
{ .command = "copy-selection-and-cancel",
|
||||||
.args = { "CP", 0, 1, NULL },
|
.args = { "CP", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_copy_selection_and_cancel
|
.f = window_copy_cmd_copy_selection_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "cursor-down",
|
{ .command = "cursor-down",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_cursor_down
|
.f = window_copy_cmd_cursor_down
|
||||||
},
|
},
|
||||||
{ .command = "cursor-down-and-cancel",
|
{ .command = "cursor-down-and-cancel",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_cursor_down_and_cancel
|
.f = window_copy_cmd_cursor_down_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "cursor-left",
|
{ .command = "cursor-left",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_cursor_left
|
.f = window_copy_cmd_cursor_left
|
||||||
},
|
},
|
||||||
{ .command = "cursor-right",
|
{ .command = "cursor-right",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_cursor_right
|
.f = window_copy_cmd_cursor_right
|
||||||
},
|
},
|
||||||
{ .command = "cursor-up",
|
{ .command = "cursor-up",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_cursor_up
|
.f = window_copy_cmd_cursor_up
|
||||||
},
|
},
|
||||||
{ .command = "cursor-centre-vertical",
|
{ .command = "cursor-centre-vertical",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_centre_vertical,
|
.f = window_copy_cmd_centre_vertical,
|
||||||
},
|
},
|
||||||
{ .command = "cursor-centre-horizontal",
|
{ .command = "cursor-centre-horizontal",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_centre_horizontal,
|
.f = window_copy_cmd_centre_horizontal,
|
||||||
},
|
},
|
||||||
{ .command = "end-of-line",
|
{ .command = "end-of-line",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_end_of_line
|
.f = window_copy_cmd_end_of_line
|
||||||
},
|
},
|
||||||
{ .command = "goto-line",
|
{ .command = "goto-line",
|
||||||
.args = { "", 1, 1, NULL },
|
.args = { "", 1, 1, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_goto_line
|
.f = window_copy_cmd_goto_line
|
||||||
},
|
},
|
||||||
{ .command = "halfpage-down",
|
{ .command = "halfpage-down",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_halfpage_down
|
.f = window_copy_cmd_halfpage_down
|
||||||
},
|
},
|
||||||
{ .command = "halfpage-down-and-cancel",
|
{ .command = "halfpage-down-and-cancel",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_halfpage_down_and_cancel
|
.f = window_copy_cmd_halfpage_down_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "halfpage-up",
|
{ .command = "halfpage-up",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_halfpage_up
|
.f = window_copy_cmd_halfpage_up
|
||||||
},
|
},
|
||||||
{ .command = "history-bottom",
|
{ .command = "history-bottom",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_history_bottom
|
.f = window_copy_cmd_history_bottom
|
||||||
},
|
},
|
||||||
{ .command = "history-top",
|
{ .command = "history-top",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_history_top
|
.f = window_copy_cmd_history_top
|
||||||
},
|
},
|
||||||
{ .command = "jump-again",
|
{ .command = "jump-again",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_jump_again
|
.f = window_copy_cmd_jump_again
|
||||||
},
|
},
|
||||||
{ .command = "jump-backward",
|
{ .command = "jump-backward",
|
||||||
.args = { "", 1, 1, NULL },
|
.args = { "", 1, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_jump_backward
|
.f = window_copy_cmd_jump_backward
|
||||||
},
|
},
|
||||||
{ .command = "jump-forward",
|
{ .command = "jump-forward",
|
||||||
.args = { "", 1, 1, NULL },
|
.args = { "", 1, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_jump_forward
|
.f = window_copy_cmd_jump_forward
|
||||||
},
|
},
|
||||||
{ .command = "jump-reverse",
|
{ .command = "jump-reverse",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_jump_reverse
|
.f = window_copy_cmd_jump_reverse
|
||||||
},
|
},
|
||||||
{ .command = "jump-to-backward",
|
{ .command = "jump-to-backward",
|
||||||
.args = { "", 1, 1, NULL },
|
.args = { "", 1, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_jump_to_backward
|
.f = window_copy_cmd_jump_to_backward
|
||||||
},
|
},
|
||||||
{ .command = "jump-to-forward",
|
{ .command = "jump-to-forward",
|
||||||
.args = { "", 1, 1, NULL },
|
.args = { "", 1, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_jump_to_forward
|
.f = window_copy_cmd_jump_to_forward
|
||||||
},
|
},
|
||||||
{ .command = "jump-to-mark",
|
{ .command = "jump-to-mark",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_jump_to_mark
|
.f = window_copy_cmd_jump_to_mark
|
||||||
},
|
},
|
||||||
{ .command = "next-prompt",
|
{ .command = "next-prompt",
|
||||||
.args = { "o", 0, 0, NULL },
|
.args = { "o", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_next_prompt
|
.f = window_copy_cmd_next_prompt
|
||||||
},
|
},
|
||||||
{ .command = "previous-prompt",
|
{ .command = "previous-prompt",
|
||||||
.args = { "o", 0, 0, NULL },
|
.args = { "o", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_previous_prompt
|
.f = window_copy_cmd_previous_prompt
|
||||||
},
|
},
|
||||||
{ .command = "middle-line",
|
{ .command = "middle-line",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_middle_line
|
.f = window_copy_cmd_middle_line
|
||||||
},
|
},
|
||||||
{ .command = "next-matching-bracket",
|
{ .command = "next-matching-bracket",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_next_matching_bracket
|
.f = window_copy_cmd_next_matching_bracket
|
||||||
},
|
},
|
||||||
{ .command = "next-paragraph",
|
{ .command = "next-paragraph",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_next_paragraph
|
.f = window_copy_cmd_next_paragraph
|
||||||
},
|
},
|
||||||
{ .command = "next-space",
|
{ .command = "next-space",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_next_space
|
.f = window_copy_cmd_next_space
|
||||||
},
|
},
|
||||||
{ .command = "next-space-end",
|
{ .command = "next-space-end",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_next_space_end
|
.f = window_copy_cmd_next_space_end
|
||||||
},
|
},
|
||||||
{ .command = "next-word",
|
{ .command = "next-word",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_next_word
|
.f = window_copy_cmd_next_word
|
||||||
},
|
},
|
||||||
{ .command = "next-word-end",
|
{ .command = "next-word-end",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_next_word_end
|
.f = window_copy_cmd_next_word_end
|
||||||
},
|
},
|
||||||
{ .command = "other-end",
|
{ .command = "other-end",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_other_end
|
.f = window_copy_cmd_other_end
|
||||||
},
|
},
|
||||||
{ .command = "page-down",
|
{ .command = "page-down",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_page_down
|
.f = window_copy_cmd_page_down
|
||||||
},
|
},
|
||||||
{ .command = "page-down-and-cancel",
|
{ .command = "page-down-and-cancel",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_page_down_and_cancel
|
.f = window_copy_cmd_page_down_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "page-up",
|
{ .command = "page-up",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_page_up
|
.f = window_copy_cmd_page_up
|
||||||
},
|
},
|
||||||
{ .command = "pipe-no-clear",
|
{ .command = "pipe-no-clear",
|
||||||
.args = { "", 0, 1, NULL },
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
.f = window_copy_cmd_pipe_no_clear
|
.f = window_copy_cmd_pipe_no_clear
|
||||||
},
|
},
|
||||||
{ .command = "pipe",
|
{ .command = "pipe",
|
||||||
.args = { "", 0, 1, NULL },
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_pipe
|
.f = window_copy_cmd_pipe
|
||||||
},
|
},
|
||||||
{ .command = "pipe-and-cancel",
|
{ .command = "pipe-and-cancel",
|
||||||
.args = { "", 0, 1, NULL },
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_pipe_and_cancel
|
.f = window_copy_cmd_pipe_and_cancel
|
||||||
},
|
},
|
||||||
{ .command = "previous-matching-bracket",
|
{ .command = "previous-matching-bracket",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_previous_matching_bracket
|
.f = window_copy_cmd_previous_matching_bracket
|
||||||
},
|
},
|
||||||
{ .command = "previous-paragraph",
|
{ .command = "previous-paragraph",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_previous_paragraph
|
.f = window_copy_cmd_previous_paragraph
|
||||||
},
|
},
|
||||||
{ .command = "previous-space",
|
{ .command = "previous-space",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_previous_space
|
.f = window_copy_cmd_previous_space
|
||||||
},
|
},
|
||||||
{ .command = "previous-word",
|
{ .command = "previous-word",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_previous_word
|
.f = window_copy_cmd_previous_word
|
||||||
},
|
},
|
||||||
{ .command = "rectangle-on",
|
{ .command = "rectangle-on",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_rectangle_on
|
.f = window_copy_cmd_rectangle_on
|
||||||
},
|
},
|
||||||
{ .command = "rectangle-off",
|
{ .command = "rectangle-off",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_rectangle_off
|
.f = window_copy_cmd_rectangle_off
|
||||||
},
|
},
|
||||||
{ .command = "rectangle-toggle",
|
{ .command = "rectangle-toggle",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_rectangle_toggle
|
.f = window_copy_cmd_rectangle_toggle
|
||||||
},
|
},
|
||||||
{ .command = "refresh-from-pane",
|
{ .command = "refresh-from-pane",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_refresh_from_pane
|
.f = window_copy_cmd_refresh_from_pane
|
||||||
},
|
},
|
||||||
{ .command = "scroll-bottom",
|
{ .command = "scroll-bottom",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_scroll_bottom
|
.f = window_copy_cmd_scroll_bottom
|
||||||
},
|
},
|
||||||
{ .command = "scroll-down",
|
{ .command = "scroll-down",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_scroll_down
|
.f = window_copy_cmd_scroll_down
|
||||||
},
|
},
|
||||||
{ .command = "scroll-down-and-cancel",
|
{ .command = "scroll-down-and-cancel",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_scroll_down_and_cancel
|
.f = window_copy_cmd_scroll_down_and_cancel
|
||||||
},
|
},
|
||||||
|
{ .command = "scroll-exit-on",
|
||||||
|
.args = { "", 0, 0, NULL },
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
.f = window_copy_cmd_scroll_exit_on
|
||||||
|
},
|
||||||
|
{ .command = "scroll-exit-off",
|
||||||
|
.args = { "", 0, 0, NULL },
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
.f = window_copy_cmd_scroll_exit_off
|
||||||
|
},
|
||||||
|
{ .command = "scroll-exit-toggle",
|
||||||
|
.args = { "", 0, 0, NULL },
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
|
.f = window_copy_cmd_scroll_exit_toggle
|
||||||
|
},
|
||||||
{ .command = "scroll-middle",
|
{ .command = "scroll-middle",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_scroll_middle
|
.f = window_copy_cmd_scroll_middle
|
||||||
},
|
},
|
||||||
|
{ .command = "scroll-to-mouse",
|
||||||
|
.args = { "e", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
|
.f = window_copy_cmd_scroll_to_mouse
|
||||||
|
},
|
||||||
{ .command = "scroll-top",
|
{ .command = "scroll-top",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_scroll_top
|
.f = window_copy_cmd_scroll_top
|
||||||
},
|
},
|
||||||
{ .command = "scroll-up",
|
{ .command = "scroll-up",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_scroll_up
|
.f = window_copy_cmd_scroll_up
|
||||||
},
|
},
|
||||||
{ .command = "search-again",
|
{ .command = "search-again",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_again
|
.f = window_copy_cmd_search_again
|
||||||
},
|
},
|
||||||
{ .command = "search-backward",
|
{ .command = "search-backward",
|
||||||
.args = { "", 0, 1, NULL },
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_backward
|
.f = window_copy_cmd_search_backward
|
||||||
},
|
},
|
||||||
{ .command = "search-backward-text",
|
{ .command = "search-backward-text",
|
||||||
.args = { "", 0, 1, NULL },
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_backward_text
|
.f = window_copy_cmd_search_backward_text
|
||||||
},
|
},
|
||||||
{ .command = "search-backward-incremental",
|
{ .command = "search-backward-incremental",
|
||||||
.args = { "", 1, 1, NULL },
|
.args = { "", 1, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_backward_incremental
|
.f = window_copy_cmd_search_backward_incremental
|
||||||
},
|
},
|
||||||
{ .command = "search-forward",
|
{ .command = "search-forward",
|
||||||
.args = { "", 0, 1, NULL },
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_forward
|
.f = window_copy_cmd_search_forward
|
||||||
},
|
},
|
||||||
{ .command = "search-forward-text",
|
{ .command = "search-forward-text",
|
||||||
.args = { "", 0, 1, NULL },
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_forward_text
|
.f = window_copy_cmd_search_forward_text
|
||||||
},
|
},
|
||||||
{ .command = "search-forward-incremental",
|
{ .command = "search-forward-incremental",
|
||||||
.args = { "", 1, 1, NULL },
|
.args = { "", 1, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_forward_incremental
|
.f = window_copy_cmd_search_forward_incremental
|
||||||
},
|
},
|
||||||
{ .command = "search-reverse",
|
{ .command = "search-reverse",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_search_reverse
|
.f = window_copy_cmd_search_reverse
|
||||||
},
|
},
|
||||||
{ .command = "select-line",
|
{ .command = "select-line",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_select_line
|
.f = window_copy_cmd_select_line
|
||||||
},
|
},
|
||||||
{ .command = "select-word",
|
{ .command = "select-word",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_select_word
|
.f = window_copy_cmd_select_word
|
||||||
},
|
},
|
||||||
{ .command = "selection-mode",
|
{ .command = "selection-mode",
|
||||||
.args = { "", 0, 1, NULL },
|
.args = { "", 0, 1, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = 0,
|
.clear = 0,
|
||||||
.f = window_copy_cmd_selection_mode
|
.f = window_copy_cmd_selection_mode
|
||||||
},
|
},
|
||||||
{ .command = "set-mark",
|
{ .command = "set-mark",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_set_mark
|
.f = window_copy_cmd_set_mark
|
||||||
},
|
},
|
||||||
{ .command = "start-of-line",
|
{ .command = "start-of-line",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_start_of_line
|
.f = window_copy_cmd_start_of_line
|
||||||
},
|
},
|
||||||
{ .command = "stop-selection",
|
{ .command = "stop-selection",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = 0,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
.clear = WINDOW_COPY_CMD_CLEAR_ALWAYS,
|
||||||
.f = window_copy_cmd_stop_selection
|
.f = window_copy_cmd_stop_selection
|
||||||
},
|
},
|
||||||
{ .command = "toggle-position",
|
{ .command = "toggle-position",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
.clear = WINDOW_COPY_CMD_CLEAR_NEVER,
|
||||||
.f = window_copy_cmd_toggle_position
|
.f = window_copy_cmd_toggle_position
|
||||||
},
|
},
|
||||||
{ .command = "top-line",
|
{ .command = "top-line",
|
||||||
.args = { "", 0, 0, NULL },
|
.args = { "", 0, 0, NULL },
|
||||||
|
.flags = WINDOW_COPY_CMD_FLAG_READONLY,
|
||||||
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
.clear = WINDOW_COPY_CMD_CLEAR_EMACS_ONLY,
|
||||||
.f = window_copy_cmd_top_line
|
.f = window_copy_cmd_top_line
|
||||||
}
|
}
|
||||||
@@ -3170,6 +3362,14 @@ window_copy_command(struct window_mode_entry *wme, struct client *c,
|
|||||||
action = WINDOW_COPY_CMD_NOTHING;
|
action = WINDOW_COPY_CMD_NOTHING;
|
||||||
for (i = 0; i < nitems(window_copy_cmd_table); i++) {
|
for (i = 0; i < nitems(window_copy_cmd_table); i++) {
|
||||||
if (strcmp(window_copy_cmd_table[i].command, command) == 0) {
|
if (strcmp(window_copy_cmd_table[i].command, command) == 0) {
|
||||||
|
if (c->flags & CLIENT_READONLY &&
|
||||||
|
(~window_copy_cmd_table[i].flags &
|
||||||
|
WINDOW_COPY_CMD_FLAG_READONLY)) {
|
||||||
|
status_message_set(c, -1, 1, 0, 0,
|
||||||
|
"client is read-only");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cs.wargs = args_parse(&window_copy_cmd_table[i].args,
|
cs.wargs = args_parse(&window_copy_cmd_table[i].args,
|
||||||
args_values(args), count, &error);
|
args_values(args), count, &error);
|
||||||
|
|
||||||
@@ -3206,6 +3406,15 @@ window_copy_command(struct window_mode_entry *wme, struct client *c,
|
|||||||
window_pane_reset_mode(wp);
|
window_pane_reset_mode(wp);
|
||||||
else if (action == WINDOW_COPY_CMD_REDRAW)
|
else if (action == WINDOW_COPY_CMD_REDRAW)
|
||||||
window_copy_redraw_screen(wme);
|
window_copy_redraw_screen(wme);
|
||||||
|
else if (action == WINDOW_COPY_CMD_NOTHING) {
|
||||||
|
/*
|
||||||
|
* Nothing is not actually nothing - most commands at least
|
||||||
|
* move the cursor (what would be the point of a command that
|
||||||
|
* literally does nothing?) and in that case we need to redraw
|
||||||
|
* the first line to update the indicator.
|
||||||
|
*/
|
||||||
|
window_copy_redraw_lines(wme, 0, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -3577,6 +3786,10 @@ window_copy_stringify(struct grid *gd, u_int py, u_int first, u_int last,
|
|||||||
buf = xrealloc(buf, bufsize);
|
buf = xrealloc(buf, bufsize);
|
||||||
|
|
||||||
gl = grid_peek_line(gd, py);
|
gl = grid_peek_line(gd, py);
|
||||||
|
if (gl == NULL) {
|
||||||
|
buf[*size - 1] = '\0';
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
bx = *size - 1;
|
bx = *size - 1;
|
||||||
for (ax = first; ax < last; ax++) {
|
for (ax = first; ax < last; ax++) {
|
||||||
d = window_copy_cellstring(gl, ax, &dlen, &allocated);
|
d = window_copy_cellstring(gl, ax, &dlen, &allocated);
|
||||||
@@ -3622,6 +3835,10 @@ window_copy_cstrtocellpos(struct grid *gd, u_int ncells, u_int *ppx, u_int *ppy,
|
|||||||
px = *ppx;
|
px = *ppx;
|
||||||
pywrap = *ppy;
|
pywrap = *ppy;
|
||||||
gl = grid_peek_line(gd, pywrap);
|
gl = grid_peek_line(gd, pywrap);
|
||||||
|
if (gl == NULL) {
|
||||||
|
free(cells);
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (cell < ncells) {
|
while (cell < ncells) {
|
||||||
cells[cell].d = window_copy_cellstring(gl, px,
|
cells[cell].d = window_copy_cellstring(gl, px,
|
||||||
&cells[cell].dlen, &cells[cell].allocated);
|
&cells[cell].dlen, &cells[cell].allocated);
|
||||||
@@ -3631,6 +3848,8 @@ window_copy_cstrtocellpos(struct grid *gd, u_int ncells, u_int *ppx, u_int *ppy,
|
|||||||
px = 0;
|
px = 0;
|
||||||
pywrap++;
|
pywrap++;
|
||||||
gl = grid_peek_line(gd, pywrap);
|
gl = grid_peek_line(gd, pywrap);
|
||||||
|
if (gl == NULL)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4032,7 +4251,7 @@ window_copy_visible_lines(struct window_copy_mode_data *data, u_int *start,
|
|||||||
|
|
||||||
for (*start = gd->hsize - data->oy; *start > 0; (*start)--) {
|
for (*start = gd->hsize - data->oy; *start > 0; (*start)--) {
|
||||||
gl = grid_peek_line(gd, (*start) - 1);
|
gl = grid_peek_line(gd, (*start) - 1);
|
||||||
if (~gl->flags & GRID_LINE_WRAPPED)
|
if (gl == NULL || ~gl->flags & GRID_LINE_WRAPPED)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*end = gd->hsize - data->oy + gd->sy;
|
*end = gd->hsize - data->oy + gd->sy;
|
||||||
@@ -4223,6 +4442,9 @@ window_copy_clear_marks(struct window_mode_entry *wme)
|
|||||||
{
|
{
|
||||||
struct window_copy_mode_data *data = wme->data;
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
|
||||||
|
data->searchcount = -1;
|
||||||
|
data->searchmore = 0;
|
||||||
|
|
||||||
free(data->searchmark);
|
free(data->searchmark);
|
||||||
data->searchmark = NULL;
|
data->searchmark = NULL;
|
||||||
}
|
}
|
||||||
@@ -4494,7 +4716,7 @@ window_copy_write_lines(struct window_mode_entry *wme,
|
|||||||
u_int yy;
|
u_int yy;
|
||||||
|
|
||||||
for (yy = py; yy < py + ny; yy++)
|
for (yy = py; yy < py + ny; yy++)
|
||||||
window_copy_write_line(wme, ctx, py);
|
window_copy_write_line(wme, ctx, yy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -4550,6 +4772,16 @@ window_copy_redraw_screen(struct window_mode_entry *wme)
|
|||||||
window_copy_redraw_lines(wme, 0, screen_size_y(&data->screen));
|
window_copy_redraw_lines(wme, 0, screen_size_y(&data->screen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_copy_style_changed(struct window_mode_entry *wme)
|
||||||
|
{
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
|
|
||||||
|
if (data->screen.sel != NULL)
|
||||||
|
window_copy_set_selection(wme, 0, 1);
|
||||||
|
window_copy_redraw_screen(wme);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_copy_synchronize_cursor_end(struct window_mode_entry *wme, int begin,
|
window_copy_synchronize_cursor_end(struct window_mode_entry *wme, int begin,
|
||||||
int no_reset)
|
int no_reset)
|
||||||
@@ -4991,9 +5223,9 @@ static void
|
|||||||
window_copy_append_selection(struct window_mode_entry *wme)
|
window_copy_append_selection(struct window_mode_entry *wme)
|
||||||
{
|
{
|
||||||
struct window_pane *wp = wme->wp;
|
struct window_pane *wp = wme->wp;
|
||||||
char *buf;
|
char *buf, *bufname = NULL;
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
const char *bufdata, *bufname = NULL;
|
const char *bufdata;
|
||||||
size_t len, bufsize;
|
size_t len, bufsize;
|
||||||
struct screen_write_ctx ctx;
|
struct screen_write_ctx ctx;
|
||||||
|
|
||||||
@@ -5018,6 +5250,7 @@ window_copy_append_selection(struct window_mode_entry *wme)
|
|||||||
}
|
}
|
||||||
if (paste_set(buf, len, bufname, NULL) != 0)
|
if (paste_set(buf, len, bufname, NULL) != 0)
|
||||||
free(buf);
|
free(buf);
|
||||||
|
free(bufname);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -5849,7 +6082,10 @@ window_copy_drag_update(struct client *c, struct mouse_event *m)
|
|||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wp = cmd_mouse_pane(m, NULL, NULL);
|
if (c->tty.mouse_wp != NULL)
|
||||||
|
wp = c->tty.mouse_wp;
|
||||||
|
else
|
||||||
|
wp = cmd_mouse_pane(m, NULL, NULL);
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
return;
|
return;
|
||||||
wme = TAILQ_FIRST(&wp->modes);
|
wme = TAILQ_FIRST(&wp->modes);
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ window_customize_build_keys(struct window_customize_modedata *data,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
window_customize_build(void *modedata,
|
window_customize_build(void *modedata,
|
||||||
__unused struct mode_tree_sort_criteria *sort_crit, __unused uint64_t *tag,
|
__unused struct sort_criteria *sort_crit, __unused uint64_t *tag,
|
||||||
const char *filter)
|
const char *filter)
|
||||||
{
|
{
|
||||||
struct window_customize_modedata *data = modedata;
|
struct window_customize_modedata *data = modedata;
|
||||||
@@ -891,8 +891,8 @@ window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
|||||||
|
|
||||||
data->data = mode_tree_start(wp, args, window_customize_build,
|
data->data = mode_tree_start(wp, args, window_customize_build,
|
||||||
window_customize_draw, NULL, window_customize_menu,
|
window_customize_draw, NULL, window_customize_menu,
|
||||||
window_customize_height, NULL, NULL, data,
|
window_customize_height, NULL, NULL, NULL, data,
|
||||||
window_customize_menu_items, NULL, 0, &s);
|
window_customize_menu_items, &s);
|
||||||
mode_tree_zoom(data->data, args);
|
mode_tree_zoom(data->data, args);
|
||||||
|
|
||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
|
|||||||
193
window-tree.c
193
window-tree.c
@@ -89,18 +89,6 @@ const struct window_mode window_tree_mode = {
|
|||||||
.key = window_tree_key,
|
.key = window_tree_key,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum window_tree_sort_type {
|
|
||||||
WINDOW_TREE_BY_INDEX,
|
|
||||||
WINDOW_TREE_BY_NAME,
|
|
||||||
WINDOW_TREE_BY_TIME,
|
|
||||||
};
|
|
||||||
static const char *window_tree_sort_list[] = {
|
|
||||||
"index",
|
|
||||||
"name",
|
|
||||||
"time"
|
|
||||||
};
|
|
||||||
static struct mode_tree_sort_criteria *window_tree_sort;
|
|
||||||
|
|
||||||
enum window_tree_type {
|
enum window_tree_type {
|
||||||
WINDOW_TREE_NONE,
|
WINDOW_TREE_NONE,
|
||||||
WINDOW_TREE_SESSION,
|
WINDOW_TREE_SESSION,
|
||||||
@@ -144,6 +132,13 @@ struct window_tree_modedata {
|
|||||||
u_int each;
|
u_int each;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum sort_order window_tree_order_seq[] = {
|
||||||
|
SORT_INDEX,
|
||||||
|
SORT_NAME,
|
||||||
|
SORT_ACTIVITY,
|
||||||
|
SORT_END,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_tree_pull_item(struct window_tree_itemdata *item, struct session **sp,
|
window_tree_pull_item(struct window_tree_itemdata *item, struct session **sp,
|
||||||
struct winlink **wlp, struct window_pane **wp)
|
struct winlink **wlp, struct window_pane **wp)
|
||||||
@@ -196,98 +191,6 @@ window_tree_free_item(struct window_tree_itemdata *item)
|
|||||||
free(item);
|
free(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
window_tree_cmp_session(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
const struct session *const *a = a0;
|
|
||||||
const struct session *const *b = b0;
|
|
||||||
const struct session *sa = *a;
|
|
||||||
const struct session *sb = *b;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
switch (window_tree_sort->field) {
|
|
||||||
case WINDOW_TREE_BY_INDEX:
|
|
||||||
result = sa->id - sb->id;
|
|
||||||
break;
|
|
||||||
case WINDOW_TREE_BY_TIME:
|
|
||||||
if (timercmp(&sa->activity_time, &sb->activity_time, >)) {
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (timercmp(&sa->activity_time, &sb->activity_time, <)) {
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case WINDOW_TREE_BY_NAME:
|
|
||||||
result = strcmp(sa->name, sb->name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window_tree_sort->reversed)
|
|
||||||
result = -result;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
window_tree_cmp_window(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
const struct winlink *const *a = a0;
|
|
||||||
const struct winlink *const *b = b0;
|
|
||||||
const struct winlink *wla = *a;
|
|
||||||
const struct winlink *wlb = *b;
|
|
||||||
struct window *wa = wla->window;
|
|
||||||
struct window *wb = wlb->window;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
switch (window_tree_sort->field) {
|
|
||||||
case WINDOW_TREE_BY_INDEX:
|
|
||||||
result = wla->idx - wlb->idx;
|
|
||||||
break;
|
|
||||||
case WINDOW_TREE_BY_TIME:
|
|
||||||
if (timercmp(&wa->activity_time, &wb->activity_time, >)) {
|
|
||||||
result = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (timercmp(&wa->activity_time, &wb->activity_time, <)) {
|
|
||||||
result = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case WINDOW_TREE_BY_NAME:
|
|
||||||
result = strcmp(wa->name, wb->name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window_tree_sort->reversed)
|
|
||||||
result = -result;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
window_tree_cmp_pane(const void *a0, const void *b0)
|
|
||||||
{
|
|
||||||
struct window_pane **a = (struct window_pane **)a0;
|
|
||||||
struct window_pane **b = (struct window_pane **)b0;
|
|
||||||
int result;
|
|
||||||
u_int ai, bi;
|
|
||||||
|
|
||||||
if (window_tree_sort->field == WINDOW_TREE_BY_TIME)
|
|
||||||
result = (*a)->active_point - (*b)->active_point;
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* Panes don't have names, so use number order for any other
|
|
||||||
* sort field.
|
|
||||||
*/
|
|
||||||
window_pane_index(*a, &ai);
|
|
||||||
window_pane_index(*b, &bi);
|
|
||||||
result = ai - bi;
|
|
||||||
}
|
|
||||||
if (window_tree_sort->reversed)
|
|
||||||
result = -result;
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_tree_build_pane(struct session *s, struct winlink *wl,
|
window_tree_build_pane(struct session *s, struct winlink *wl,
|
||||||
struct window_pane *wp, void *modedata, struct mode_tree_item *parent)
|
struct window_pane *wp, void *modedata, struct mode_tree_item *parent)
|
||||||
@@ -339,7 +242,7 @@ window_tree_filter_pane(struct session *s, struct winlink *wl,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
window_tree_build_window(struct session *s, struct winlink *wl,
|
window_tree_build_window(struct session *s, struct winlink *wl,
|
||||||
void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
void *modedata, struct sort_criteria *sort_crit,
|
||||||
struct mode_tree_item *parent, const char *filter)
|
struct mode_tree_item *parent, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_tree_modedata *data = modedata;
|
struct window_tree_modedata *data = modedata;
|
||||||
@@ -381,24 +284,13 @@ window_tree_build_window(struct session *s, struct winlink *wl,
|
|||||||
goto empty;
|
goto empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
l = NULL;
|
l = sort_get_panes_window(wl->window, &n, sort_crit);
|
||||||
n = 0;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
|
||||||
if (!window_tree_filter_pane(s, wl, wp, filter))
|
|
||||||
continue;
|
|
||||||
l = xreallocarray(l, n + 1, sizeof *l);
|
|
||||||
l[n++] = wp;
|
|
||||||
}
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
goto empty;
|
goto empty;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
window_tree_sort = sort_crit;
|
if (window_tree_filter_pane(s, wl, l[i], filter))
|
||||||
qsort(l, n, sizeof *l, window_tree_cmp_pane);
|
window_tree_build_pane(s, wl, l[i], modedata, mti);
|
||||||
|
}
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
window_tree_build_pane(s, wl, l[i], modedata, mti);
|
|
||||||
free(l);
|
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
empty:
|
empty:
|
||||||
@@ -410,7 +302,7 @@ empty:
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
window_tree_build_session(struct session *s, void *modedata,
|
window_tree_build_session(struct session *s, void *modedata,
|
||||||
struct mode_tree_sort_criteria *sort_crit, const char *filter)
|
struct sort_criteria *sort_crit, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_tree_modedata *data = modedata;
|
struct window_tree_modedata *data = modedata;
|
||||||
struct window_tree_itemdata *item;
|
struct window_tree_itemdata *item;
|
||||||
@@ -440,15 +332,7 @@ window_tree_build_session(struct session *s, void *modedata,
|
|||||||
expanded);
|
expanded);
|
||||||
free(text);
|
free(text);
|
||||||
|
|
||||||
l = NULL;
|
l = sort_get_winlinks_session(s, &n, sort_crit);
|
||||||
n = 0;
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
|
||||||
l = xreallocarray(l, n + 1, sizeof *l);
|
|
||||||
l[n++] = wl;
|
|
||||||
}
|
|
||||||
window_tree_sort = sort_crit;
|
|
||||||
qsort(l, n, sizeof *l, window_tree_cmp_window);
|
|
||||||
|
|
||||||
empty = 0;
|
empty = 0;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
if (!window_tree_build_window(s, l[i], modedata, sort_crit, mti,
|
if (!window_tree_build_window(s, l[i], modedata, sort_crit, mti,
|
||||||
@@ -460,11 +344,10 @@ window_tree_build_session(struct session *s, void *modedata,
|
|||||||
data->item_size--;
|
data->item_size--;
|
||||||
mode_tree_remove(data->data, mti);
|
mode_tree_remove(data->data, mti);
|
||||||
}
|
}
|
||||||
free(l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
window_tree_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
window_tree_build(void *modedata, struct sort_criteria *sort_crit,
|
||||||
uint64_t *tag, const char *filter)
|
uint64_t *tag, const char *filter)
|
||||||
{
|
{
|
||||||
struct window_tree_modedata *data = modedata;
|
struct window_tree_modedata *data = modedata;
|
||||||
@@ -480,24 +363,19 @@ window_tree_build(void *modedata, struct mode_tree_sort_criteria *sort_crit,
|
|||||||
data->item_list = NULL;
|
data->item_list = NULL;
|
||||||
data->item_size = 0;
|
data->item_size = 0;
|
||||||
|
|
||||||
l = NULL;
|
l = sort_get_sessions(&n, sort_crit);
|
||||||
n = 0;
|
if (n == 0)
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
return;
|
||||||
|
s = l[n - 1];
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
if (data->squash_groups &&
|
if (data->squash_groups &&
|
||||||
(sg = session_group_contains(s)) != NULL) {
|
(sg = session_group_contains(s)) != NULL) {
|
||||||
if ((sg == current && s != data->fs.s) ||
|
if ((sg == current && s != data->fs.s) ||
|
||||||
(sg != current && s != TAILQ_FIRST(&sg->sessions)))
|
(sg != current && s != TAILQ_FIRST(&sg->sessions)))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
l = xreallocarray(l, n + 1, sizeof *l);
|
|
||||||
l[n++] = s;
|
|
||||||
}
|
|
||||||
window_tree_sort = sort_crit;
|
|
||||||
qsort(l, n, sizeof *l, window_tree_cmp_session);
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
window_tree_build_session(l[i], modedata, sort_crit, filter);
|
window_tree_build_session(l[i], modedata, sort_crit, filter);
|
||||||
free(l);
|
}
|
||||||
|
|
||||||
switch (data->type) {
|
switch (data->type) {
|
||||||
case WINDOW_TREE_NONE:
|
case WINDOW_TREE_NONE:
|
||||||
@@ -924,7 +802,8 @@ window_tree_get_key(void *modedata, void *itemdata, u_int line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
window_tree_swap(void *cur_itemdata, void *other_itemdata)
|
window_tree_swap(void *cur_itemdata, void *other_itemdata,
|
||||||
|
struct sort_criteria *sort_crit)
|
||||||
{
|
{
|
||||||
struct window_tree_itemdata *cur = cur_itemdata;
|
struct window_tree_itemdata *cur = cur_itemdata;
|
||||||
struct window_tree_itemdata *other = other_itemdata;
|
struct window_tree_itemdata *other = other_itemdata;
|
||||||
@@ -945,14 +824,12 @@ window_tree_swap(void *cur_itemdata, void *other_itemdata)
|
|||||||
if (cur_session != other_session)
|
if (cur_session != other_session)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (window_tree_sort->field != WINDOW_TREE_BY_INDEX &&
|
/*
|
||||||
window_tree_cmp_window(&cur_winlink, &other_winlink) != 0) {
|
* Swapping indexes would not swap positions in the tree, so prevent
|
||||||
/*
|
* swapping to avoid confusing the user.
|
||||||
* Swapping indexes would not swap positions in the tree, so
|
*/
|
||||||
* prevent swapping to avoid confusing the user.
|
if (sort_would_window_tree_swap(sort_crit, cur_winlink, other_winlink))
|
||||||
*/
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
|
||||||
|
|
||||||
other_window = other_winlink->window;
|
other_window = other_winlink->window;
|
||||||
TAILQ_REMOVE(&other_window->winlinks, other_winlink, wentry);
|
TAILQ_REMOVE(&other_window->winlinks, other_winlink, wentry);
|
||||||
@@ -975,6 +852,14 @@ window_tree_swap(void *cur_itemdata, void *other_itemdata)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_tree_sort(struct sort_criteria *sort_crit)
|
||||||
|
{
|
||||||
|
sort_crit->order_seq = window_tree_order_seq;
|
||||||
|
if (sort_crit->order == SORT_END)
|
||||||
|
sort_crit->order = sort_crit->order_seq[0];
|
||||||
|
}
|
||||||
|
|
||||||
static struct screen *
|
static struct screen *
|
||||||
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||||
struct args *args)
|
struct args *args)
|
||||||
@@ -1013,8 +898,8 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
|||||||
|
|
||||||
data->data = mode_tree_start(wp, args, window_tree_build,
|
data->data = mode_tree_start(wp, args, window_tree_build,
|
||||||
window_tree_draw, window_tree_search, window_tree_menu, NULL,
|
window_tree_draw, window_tree_search, window_tree_menu, NULL,
|
||||||
window_tree_get_key, window_tree_swap, data, window_tree_menu_items,
|
window_tree_get_key, window_tree_swap, window_tree_sort, data,
|
||||||
window_tree_sort_list, nitems(window_tree_sort_list), &s);
|
window_tree_menu_items, &s);
|
||||||
mode_tree_zoom(data->data, args);
|
mode_tree_zoom(data->data, args);
|
||||||
|
|
||||||
mode_tree_build(data->data);
|
mode_tree_build(data->data);
|
||||||
|
|||||||
168
window.c
168
window.c
@@ -306,6 +306,7 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
|
|||||||
w->flags = 0;
|
w->flags = 0;
|
||||||
|
|
||||||
TAILQ_INIT(&w->panes);
|
TAILQ_INIT(&w->panes);
|
||||||
|
TAILQ_INIT(&w->z_index);
|
||||||
TAILQ_INIT(&w->last_panes);
|
TAILQ_INIT(&w->last_panes);
|
||||||
w->active = NULL;
|
w->active = NULL;
|
||||||
|
|
||||||
@@ -328,6 +329,9 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
|
|||||||
RB_INSERT(windows, &windows, w);
|
RB_INSERT(windows, &windows, w);
|
||||||
|
|
||||||
window_set_fill_character(w);
|
window_set_fill_character(w);
|
||||||
|
|
||||||
|
if (gettimeofday(&w->creation_time, NULL) != 0)
|
||||||
|
fatal("gettimeofday failed");
|
||||||
window_update_activity(w);
|
window_update_activity(w);
|
||||||
|
|
||||||
log_debug("%s: @%u create %ux%u (%ux%u)", __func__, w->id, sx, sy,
|
log_debug("%s: @%u create %ux%u (%ux%u)", __func__, w->id, sx, sy,
|
||||||
@@ -524,6 +528,8 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
|||||||
|
|
||||||
if (wp == w->active)
|
if (wp == w->active)
|
||||||
return (0);
|
return (0);
|
||||||
|
if (w->flags & WINDOW_ZOOMED)
|
||||||
|
window_unzoom(w, 1);
|
||||||
lastwp = w->active;
|
lastwp = w->active;
|
||||||
|
|
||||||
window_pane_stack_remove(&w->last_panes, wp);
|
window_pane_stack_remove(&w->last_panes, wp);
|
||||||
@@ -533,6 +539,20 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
|||||||
w->active->active_point = next_active_point++;
|
w->active->active_point = next_active_point++;
|
||||||
w->active->flags |= PANE_CHANGED;
|
w->active->flags |= PANE_CHANGED;
|
||||||
|
|
||||||
|
if (wp->flags & PANE_MINIMISED) {
|
||||||
|
wp->flags &= ~PANE_MINIMISED;
|
||||||
|
if (w->layout_root != NULL) {
|
||||||
|
wp->layout_cell = wp->saved_layout_cell;
|
||||||
|
wp->saved_layout_cell = NULL;
|
||||||
|
layout_unminimise_cell(w, wp->layout_cell);
|
||||||
|
layout_fix_offsets(w);
|
||||||
|
layout_fix_panes(w, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notify_window("window-layout-changed", w);
|
||||||
|
server_redraw_window(w);
|
||||||
|
|
||||||
|
|
||||||
if (options_get_number(global_options, "focus-events")) {
|
if (options_get_number(global_options, "focus-events")) {
|
||||||
window_pane_update_focus(lastwp);
|
window_pane_update_focus(lastwp);
|
||||||
window_pane_update_focus(w->active);
|
window_pane_update_focus(w->active);
|
||||||
@@ -545,6 +565,33 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
window_deactivate_pane(struct window *w, struct window_pane *wp, int notify)
|
||||||
|
{
|
||||||
|
struct window_pane *lastwp;
|
||||||
|
|
||||||
|
log_debug("%s: pane %%%u", __func__, wp->id);
|
||||||
|
|
||||||
|
if (w->flags & WINDOW_ZOOMED)
|
||||||
|
window_unzoom(w, 1);
|
||||||
|
lastwp = w->active;
|
||||||
|
|
||||||
|
window_pane_stack_remove(&w->last_panes, wp);
|
||||||
|
window_pane_stack_push(&w->last_panes, lastwp);
|
||||||
|
|
||||||
|
w->active = NULL;
|
||||||
|
|
||||||
|
if (options_get_number(global_options, "focus-events")) {
|
||||||
|
window_pane_update_focus(lastwp);
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_update_window_offset(w);
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
notify_window("window-pane-changed", w);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
window_pane_get_palette(struct window_pane *wp, int c)
|
window_pane_get_palette(struct window_pane *wp, int c)
|
||||||
{
|
{
|
||||||
@@ -585,7 +632,20 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
if (wp == w->active)
|
if (wp == w->active)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* If you want tiled planes to be able to bury
|
||||||
|
* floating planes then do this regardless of
|
||||||
|
* wp->flags & PANE_FLOATING or not. A new option?
|
||||||
|
*/
|
||||||
|
if (wp->flags & PANE_FLOATING) {
|
||||||
|
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||||
|
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||||
|
wp->flags |= PANE_REDRAW;
|
||||||
|
}
|
||||||
|
|
||||||
wp = w->active;
|
wp = w->active;
|
||||||
|
if (wp == NULL)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,16 +653,34 @@ struct window_pane *
|
|||||||
window_get_active_at(struct window *w, u_int x, u_int y)
|
window_get_active_at(struct window *w, u_int x, u_int y)
|
||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
u_int xoff, yoff, sx, sy;
|
int status, xoff, yoff;
|
||||||
|
u_int sx, sy;
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
status = options_get_number(w->options, "pane-border-status");
|
||||||
|
|
||||||
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
if (!window_pane_visible(wp))
|
if (!window_pane_visible(wp))
|
||||||
continue;
|
continue;
|
||||||
window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy);
|
window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy);
|
||||||
if (x < xoff || x > xoff + sx)
|
if (~wp->flags & PANE_FLOATING) {
|
||||||
continue;
|
/* Tiled, select up to including bottom or
|
||||||
if (y < yoff || y > yoff + sy)
|
right border. */
|
||||||
continue;
|
if ((int)x < xoff || x > xoff + sx)
|
||||||
|
continue;
|
||||||
|
if (status == PANE_STATUS_TOP) {
|
||||||
|
if ((int)y < yoff - 1 || y > yoff + sy)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if ((int)y < yoff || y > yoff + sy)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Floating, include top or or left border. */
|
||||||
|
if ((int)x < xoff - 1 || x > xoff + sx)
|
||||||
|
continue;
|
||||||
|
if ((int)y < yoff - 1 || y > yoff + sy)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return (wp);
|
return (wp);
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -658,12 +736,24 @@ window_zoom(struct window_pane *wp)
|
|||||||
if (w->flags & WINDOW_ZOOMED)
|
if (w->flags & WINDOW_ZOOMED)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
if (window_count_panes(w) == 1)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
if (w->active != wp)
|
if (w->active != wp)
|
||||||
window_set_active_pane(w, wp, 1);
|
window_set_active_pane(w, wp, 1);
|
||||||
|
|
||||||
|
/* Bring pane above other tiled panes and minimise floating panes. */
|
||||||
|
TAILQ_FOREACH(wp1, &w->z_index, zentry) {
|
||||||
|
if (wp1 == wp) {
|
||||||
|
wp1->saved_flags |= (wp1->flags & PANE_MINIMISED);
|
||||||
|
wp1->flags &= ~PANE_MINIMISED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (wp1->flags & PANE_FLOATING) {
|
||||||
|
wp1->saved_flags |= (wp1->flags & PANE_MINIMISED);
|
||||||
|
wp1->flags |= PANE_MINIMISED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(wp1, &w->panes, entry) {
|
TAILQ_FOREACH(wp1, &w->panes, entry) {
|
||||||
wp1->saved_layout_cell = wp1->layout_cell;
|
wp1->saved_layout_cell = wp1->layout_cell;
|
||||||
wp1->layout_cell = NULL;
|
wp1->layout_cell = NULL;
|
||||||
@@ -690,6 +780,14 @@ window_unzoom(struct window *w, int notify)
|
|||||||
w->layout_root = w->saved_layout_root;
|
w->layout_root = w->saved_layout_root;
|
||||||
w->saved_layout_root = NULL;
|
w->saved_layout_root = NULL;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
|
if (wp->flags & PANE_FLOATING) {
|
||||||
|
wp->flags &= ~PANE_MINIMISED | (wp->saved_flags & PANE_MINIMISED);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
wp->layout_cell = wp->saved_layout_cell;
|
wp->layout_cell = wp->saved_layout_cell;
|
||||||
wp->saved_layout_cell = NULL;
|
wp->saved_layout_cell = NULL;
|
||||||
@@ -745,11 +843,17 @@ window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
|
|||||||
TAILQ_INSERT_BEFORE(other, wp, entry);
|
TAILQ_INSERT_BEFORE(other, wp, entry);
|
||||||
} else {
|
} else {
|
||||||
log_debug("%s: @%u after %%%u", __func__, w->id, wp->id);
|
log_debug("%s: @%u after %%%u", __func__, w->id, wp->id);
|
||||||
if (flags & SPAWN_FULLSIZE)
|
if (flags & (SPAWN_FULLSIZE|SPAWN_FLOATING))
|
||||||
TAILQ_INSERT_TAIL(&w->panes, wp, entry);
|
TAILQ_INSERT_TAIL(&w->panes, wp, entry);
|
||||||
else
|
else
|
||||||
TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
|
TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
|
||||||
}
|
}
|
||||||
|
/* Floating panes are created above tiled planes. */
|
||||||
|
if (flags & SPAWN_FLOATING) {
|
||||||
|
wp->flags |= PANE_FLOATING;
|
||||||
|
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||||
|
} else
|
||||||
|
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
||||||
return (wp);
|
return (wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,6 +888,7 @@ window_remove_pane(struct window *w, struct window_pane *wp)
|
|||||||
window_lost_pane(w, wp);
|
window_lost_pane(w, wp);
|
||||||
|
|
||||||
TAILQ_REMOVE(&w->panes, wp, entry);
|
TAILQ_REMOVE(&w->panes, wp, entry);
|
||||||
|
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||||
window_pane_destroy(wp);
|
window_pane_destroy(wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -867,6 +972,7 @@ window_destroy_panes(struct window *w)
|
|||||||
while (!TAILQ_EMPTY(&w->panes)) {
|
while (!TAILQ_EMPTY(&w->panes)) {
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
TAILQ_REMOVE(&w->panes, wp, entry);
|
TAILQ_REMOVE(&w->panes, wp, entry);
|
||||||
|
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||||
window_pane_destroy(wp);
|
window_pane_destroy(wp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -933,7 +1039,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
|||||||
wp = xcalloc(1, sizeof *wp);
|
wp = xcalloc(1, sizeof *wp);
|
||||||
wp->window = w;
|
wp->window = w;
|
||||||
wp->options = options_create(w->options);
|
wp->options = options_create(w->options);
|
||||||
wp->flags = (PANE_STYLECHANGED|PANE_THEMECHANGED);
|
wp->flags = PANE_STYLECHANGED;
|
||||||
|
|
||||||
wp->id = next_window_pane_id++;
|
wp->id = next_window_pane_id++;
|
||||||
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
||||||
@@ -1001,6 +1107,8 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
|
|
||||||
if (event_initialized(&wp->resize_timer))
|
if (event_initialized(&wp->resize_timer))
|
||||||
event_del(&wp->resize_timer);
|
event_del(&wp->resize_timer);
|
||||||
|
if (event_initialized(&wp->sync_timer))
|
||||||
|
event_del(&wp->sync_timer);
|
||||||
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||||
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||||
free(r);
|
free(r);
|
||||||
@@ -1066,7 +1174,7 @@ window_pane_set_event(struct window_pane *wp)
|
|||||||
NULL, window_pane_error_callback, wp);
|
NULL, window_pane_error_callback, wp);
|
||||||
if (wp->event == NULL)
|
if (wp->event == NULL)
|
||||||
fatalx("out of memory");
|
fatalx("out of memory");
|
||||||
wp->ictx = input_init(wp, wp->event, &wp->palette);
|
wp->ictx = input_init(wp, wp->event, &wp->palette, NULL);
|
||||||
|
|
||||||
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
||||||
}
|
}
|
||||||
@@ -1080,6 +1188,8 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
if (sx == wp->sx && sy == wp->sy)
|
if (sx == wp->sx && sy == wp->sy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
screen_write_stop_sync(wp);
|
||||||
|
|
||||||
r = xmalloc(sizeof *r);
|
r = xmalloc(sizeof *r);
|
||||||
r->sx = sx;
|
r->sx = sx;
|
||||||
r->sy = sy;
|
r->sy = sy;
|
||||||
@@ -1098,6 +1208,15 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
|||||||
wme->mode->resize(wme, sx, sy);
|
wme->mode->resize(wme, sx, sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
window_pane_move(struct window_pane *wp, int xoff, int yoff)
|
||||||
|
{
|
||||||
|
wp->xoff = xoff;
|
||||||
|
wp->yoff = yoff;
|
||||||
|
|
||||||
|
log_debug("%s: %%%u resize %ux%u", __func__, wp->id, xoff, yoff);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
window_pane_set_mode(struct window_pane *wp, struct window_pane *swp,
|
window_pane_set_mode(struct window_pane *wp, struct window_pane *swp,
|
||||||
const struct window_mode *mode, struct cmd_find_state *fs,
|
const struct window_mode *mode, struct cmd_find_state *fs,
|
||||||
@@ -1265,8 +1384,10 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
|
|||||||
int
|
int
|
||||||
window_pane_visible(struct window_pane *wp)
|
window_pane_visible(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
if (~wp->window->flags & WINDOW_ZOOMED)
|
if (~wp->window->flags & WINDOW_ZOOMED &&
|
||||||
|
~wp->flags & PANE_MINIMISED)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
return (wp == wp->window->active);
|
return (wp == wp->window->active);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1780,7 +1901,7 @@ window_pane_mode(struct window_pane *wp)
|
|||||||
int
|
int
|
||||||
window_pane_show_scrollbar(struct window_pane *wp, int sb_option)
|
window_pane_show_scrollbar(struct window_pane *wp, int sb_option)
|
||||||
{
|
{
|
||||||
if (SCREEN_IS_ALTERNATE(wp->screen))
|
if (SCREEN_IS_ALTERNATE(&wp->base))
|
||||||
return (0);
|
return (0);
|
||||||
if (sb_option == PANE_SCROLLBARS_ALWAYS ||
|
if (sb_option == PANE_SCROLLBARS_ALWAYS ||
|
||||||
(sb_option == PANE_SCROLLBARS_MODAL &&
|
(sb_option == PANE_SCROLLBARS_MODAL &&
|
||||||
@@ -1933,6 +2054,8 @@ window_pane_get_theme(struct window_pane *wp)
|
|||||||
void
|
void
|
||||||
window_pane_send_theme_update(struct window_pane *wp)
|
window_pane_send_theme_update(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
|
enum client_theme theme;
|
||||||
|
|
||||||
if (wp == NULL || window_pane_exited(wp))
|
if (wp == NULL || window_pane_exited(wp))
|
||||||
return;
|
return;
|
||||||
if (~wp->flags & PANE_THEMECHANGED)
|
if (~wp->flags & PANE_THEMECHANGED)
|
||||||
@@ -1940,16 +2063,23 @@ window_pane_send_theme_update(struct window_pane *wp)
|
|||||||
if (~wp->screen->mode & MODE_THEME_UPDATES)
|
if (~wp->screen->mode & MODE_THEME_UPDATES)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (window_pane_get_theme(wp)) {
|
theme = window_pane_get_theme(wp);
|
||||||
|
if (theme == wp->last_theme)
|
||||||
|
return;
|
||||||
|
wp->last_theme = theme;
|
||||||
|
wp->flags &= ~PANE_THEMECHANGED;
|
||||||
|
|
||||||
|
switch (theme) {
|
||||||
case THEME_LIGHT:
|
case THEME_LIGHT:
|
||||||
input_key_pane(wp, KEYC_REPORT_LIGHT_THEME, NULL);
|
log_debug("%s: %%%u light theme", __func__, wp->id);
|
||||||
|
bufferevent_write(wp->event, "\033[?997;2n", 9);
|
||||||
break;
|
break;
|
||||||
case THEME_DARK:
|
case THEME_DARK:
|
||||||
input_key_pane(wp, KEYC_REPORT_DARK_THEME, NULL);
|
log_debug("%s: %%%u dark theme", __func__, wp->id);
|
||||||
|
bufferevent_write(wp->event, "\033[?997;1n", 9);
|
||||||
break;
|
break;
|
||||||
case THEME_UNKNOWN:
|
case THEME_UNKNOWN:
|
||||||
|
log_debug("%s: %%%u unknown theme", __func__, wp->id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
wp->flags &= ~PANE_THEMECHANGED;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user