Compare commits

...

2305 Commits
3.1c ... master

Author SHA1 Message Date
Thomas Adam
96244dd727 Merge branch 'obsd-master' 2025-06-20 18:01:08 +01:00
Thomas Adam
b38b5d3df2 Merge branch 'obsd-master' 2025-06-20 16:01:08 +01:00
nicm
ad3e6ff054 Add noattr and use in mode-style to allow whether attributes are ignored
or used to be configured. GitHub issue 4498.
2025-06-20 14:54:33 +00:00
nicm
522652913f Add S: to list sessions with modifiers for sorting, from Michael Grant. 2025-06-20 13:31:59 +00:00
Thomas Adam
43e88c892d Merge branch 'obsd-master' 2025-06-16 02:01:07 +01:00
nicm
d82d9468b4 Expand mode-style with E: so # is correctly processed, GitHub issue
4533.
2025-06-15 22:24:51 +00:00
nicm
d7f75ac985 Do not replace SHELL when using /bin/sh. From someone in GitHub issue 4528. 2025-06-15 21:57:58 +00:00
Thomas Adam
1dbceaa790 Merge branch 'obsd-master' 2025-05-28 14:01:08 +01:00
nicm
77ca59acac Add missing theme hooks, from Eric NICOLAS in GitHub issue 4519. 2025-05-28 09:53:57 +00:00
Thomas Adam
7be0613657 Merge branch 'obsd-master' 2025-05-22 12:01:07 +01:00
Thomas Adam
b9ad9186fe Merge branch 'obsd-master' 2025-05-22 10:01:08 +01:00
nicm
3f4b154b70 Bump UTF8_SIZE to the maximum 32 because there are some crazy long UTF-8
sequences out there (GitHub issue 4506). This should not significantly
increase typical memory consumption because we only store each Unicode
character once in the shared cache.
2025-05-22 08:01:29 +00:00
Nicholas Marriott
ff73c95547 New bash completion URL, from David Mandelberg. 2025-05-22 08:52:10 +01:00
Nicholas Marriott
aa0d05f676 Typos, from someone in GitHub issue 4511. 2025-05-22 08:51:14 +01:00
nicm
545832e9fa Typo, from someone in GitHub issue 4511. 2025-05-22 07:49:24 +00:00
nicm
a0ac2a5d63 When there are more than two horizontal windows and the active window is
in not on an edge, correctly highlight both its left and right borders.
GitHub issue 4513 from Michael Grant.
2025-05-22 07:46:38 +00:00
nicm
833c7fbf6d Add a set-default style attribute which replaces the current default
colours and attributes completely, useful at the start of compound
format strings (like status-format) to set the default colours for all
the following options.
2025-05-22 07:43:38 +00:00
Thomas Adam
faf2a44890 Merge branch 'obsd-master' 2025-05-12 14:01:10 +01:00
Thomas Adam
d194ceb604 Merge branch 'obsd-master' 2025-05-12 12:01:10 +01:00
nicm
37a2c98d3d Expand prompts when they are used rather than ahead of time, so the
input can be used as part of the format.
2025-05-12 10:34:13 +00:00
nicm
79b02998a6 Add R format modifier to repeat an argument. 2025-05-12 10:26:19 +00:00
nicm
1ce1e7ef27 Add -E to run-shell to forward stderr as well as stdout, from github at
jyn dot dev in GitHub issue 4246.
2025-05-12 10:16:42 +00:00
nicm
7499d925da Do not downgrade styled underscores to standard underscore if the
terminal does not support them, this matches what would happen if the
application tried to use them on a terminal without support.
2025-05-12 09:50:00 +00:00
nicm
367f17a4ff Preserve colours in selection if the option style is default, GitHub
issue 4498.
2025-05-12 09:17:42 +00:00
Thomas Adam
3d2b26dcfe Merge branch 'obsd-master' 2025-05-01 10:01:11 +01:00
nicm
6106a0f2c4 Add an option variation-selector-always-wide to instruct tmux not to
always interpret VS16 as a wide character and assume the terminal does
likewise. This is behaviour seen in a number of newer terminals' Unicode
14 support but not in older terminals; it seems to be a little
contentious and is currently difficult to detect.

Probably in the long run tmux should pick a behaviour, look at a (new)
terminfo(5) capability to tell it what the terminal will do, and emulate
as required, but at this point I'm not sure that is worth it for
something where support is mixed, seems to be in flux, and that mostly
only matters for emojis.

GitHub issues 3923 and 4475 and others before that.
2025-05-01 07:12:00 +00:00
nicm
1926c1b683 Don't map 256 to white-on-white either, and tidy code a bit. 2025-05-01 06:59:32 +00:00
Nicholas Marriott
6cc1a607fc optarg should be "extern char *" not "extern const char *". 2025-05-01 07:53:02 +01:00
Nicholas Marriott
1905afb3d8 tmux has its own warnx so there is no need for logit (and this gets rid of a
warning).
2025-04-29 17:39:56 +01:00
Nicholas Marriott
345a45083d Run the regress/style-trim.sh test in a plain Bash session, from Koichi Murase. 2025-04-29 17:29:32 +01:00
Nicholas Marriott
3a3babf597 Use printf not echo, from Koichi Murase. 2025-04-28 14:51:27 +01:00
Nicholas Marriott
f367e3a6c8 Switch to getopt_long from OpenSSH, from Koichi Murase in GitHub issue 4492. 2025-04-28 09:02:15 +01:00
Nicholas Marriott
f2283b0cb5 Fix some regress tests. 2025-04-28 08:57:29 +01:00
Nicholas Marriott
26081ac125
Create config.yml 2025-04-28 07:27:57 +01:00
Thomas Adam
36fba4cc54 Merge branch 'obsd-master' 2025-04-25 16:01:08 +01:00
Thomas Adam
58b4286edb Merge branch 'obsd-master' 2025-04-25 14:01:10 +01:00
nicm
b0b6a6f665 Revert change to handle command parsing failures in the client because
it breaks aliases.
2025-04-25 12:25:32 +00:00
nicm
63e5989f53 Remove a stray period, reported by David Mandelberg. 2025-04-25 11:39:39 +00:00
Nicholas Marriott
9da5707d3e Add a run-shell output test. 2025-04-25 12:06:51 +01:00
Thomas Adam
55292b72d1 Merge branch 'obsd-master' 2025-04-25 12:01:09 +01:00
Nicholas Marriott
06b1ad6241 Tests for boolean expressions from David Mandelberg. 2025-04-25 09:28:57 +01:00
nicm
1efe41b9b9 Add more features for boolean expressions in formats: 1) extend && and
|| to support arbitrarily many arguments and 2) add ! and !! for not and
not-not.
2025-04-25 08:28:21 +00:00
Nicholas Marriott
1198eed632 Currently the DCS dispatcher detects Sixel sequences based entirely on the
final character of the sequence, ignoring any intermediates. This means that
other DCS sequences with a q final (like DECRQSS), can be mistakenly
interpreted as Sixel. Add a check to make sure there are no intermediates
before dispatching potential Sixel sequences. From James Holderness in GitHub
issue 4488.
2025-04-25 08:26:26 +01:00
Thomas Adam
0772fe822a Merge branch 'obsd-master' 2025-04-24 12:01:10 +01:00
nicm
f53fac1b56 Do not add a trailing / if there is nothing to follow it, Johannes
Altmanninger in GitHub issue 4472.
2025-04-24 08:55:40 +00:00
nicm
68f2ac9296 Fix examples with too many backslashes, pointed out by David Mandelberg. 2025-04-24 08:54:40 +00:00
Thomas Adam
b4f8340f16 Merge branch 'obsd-master' 2025-04-22 16:01:12 +01:00
nicm
d2f73c17d5 Add calls to layout_fix_panes after a pane swap to fix case if one of
the panes is in alternate screen mode and had a scrollbar. From Michael
Grant in GitHub issue 4481.
2025-04-22 12:36:03 +00:00
nicm
5db914b745 Add notes to menu keys, from someone in GitHub issue 4478. 2025-04-22 12:34:56 +00:00
nicm
cd3d2910ee Fix description of pane_in_mode, from Julian Prein in GitHub issue 4469. 2025-04-22 12:33:35 +00:00
Nicholas Marriott
de7653f5a4 Update format tests for #? changes, from David Mandelberg. 2025-04-22 13:23:33 +01:00
nicm
b905039ed2 Improve #? conditional expression in formats:
1) add support for else if, so
   #{?cond1,value1,#{?cond2,value2,else-value}} can be changed to
   #{?cond1,value1,cond2,value2,else-value};

2) add default empty string if there's no else value, so
   #{?cond1,value1,} can be changed to #{?cond1,value1}.

From David Mandelberg in GitHub issue 4451.
2025-04-22 12:23:26 +00:00
Nicholas Marriott
f0a85d0469 Move cgroup dbus requests to the child to avoid a race where a spawned child
that quickly forks will have only the parent process moved to the newly created
cgroup. From Daniel De Graaf, GitHub issue 4435.
2025-04-14 07:27:02 +01:00
Thomas Adam
ac2779f4d8 Merge branch 'obsd-master' 2025-04-09 10:01:12 +01:00
nicm
68ffe65499 Fix documentation around optional arguments. This includes:
- Syncing between the usage string in code and in the man page.
- Adding optional arguments that were not mentioned (such as
  shell-command arguments).
- Adding square brackets around arguments that are actually optional.

From Julian Prein (julian at druck dot dev) in GitHub issue 4419.
2025-04-09 07:03:04 +00:00
nicm
3e14e7c48b Formats can use environment variables, from David Mandelberg. 2025-04-09 06:51:31 +00:00
nicm
b526e678b5 Make some usages more consistent and add -h to show usage, GitHub issue
4455 from David Mandelberg.
2025-04-09 06:27:43 +00:00
Thomas Adam
d3c39375d5 Merge branch 'obsd-master' 2025-04-03 14:01:10 +01:00
nicm
a7991dcbad Fix padding for word function as well, GitHub issue 4425. 2025-04-03 11:52:25 +00:00
nicm
47dff97834 Use backing grid for word in copy mode for wrapped flags, from someone
in GitHub issue 4447.
2025-04-03 11:51:27 +00:00
Thomas Adam
2905395695 Merge branch 'obsd-master' 2025-04-02 12:01:13 +01:00
nicm
4bf38da4d4 Only align panes and windows, not sessions, from David Mandelberg in
GitHub issue 4444.
2025-04-02 09:31:00 +00:00
nicm
9b37b9285e Popup window should not be draggable while mouse still pressed, and do
not try to work out theme if no pane. From Michael Grant in GitHub issue
4330.
2025-04-02 09:12:05 +00:00
Thomas Adam
dfdced2ab1 Merge branch 'obsd-master' 2025-03-31 00:01:10 +01:00
Nicholas Marriott
c2a95a372f Add a note about closed issues, from David Mandelberg. 2025-03-30 23:04:22 +01:00
nicm
ef923d28ff Do not try to trigger theme changed if session is NULL. 2025-03-30 22:01:55 +00:00
nicm
53b0e0bc02 Missing space, from David Mandelberg. 2025-03-30 21:47:01 +00:00
Thomas Adam
096c4b3e63 Merge branch 'obsd-master' 2025-03-28 20:01:10 +00:00
Thomas Adam
b8189d6ee3 Merge branch 'obsd-master' 2025-03-28 18:01:11 +00:00
nicm
f41dc91357 Only copy the key string not two bytes extra, found by David Mandelberg. 2025-03-28 17:15:25 +00:00
nicm
ef0c12ad9e Fix read of uninitialized memory for jobs with JOB_PTY flag. From David
Mandelberg.
2025-03-28 17:03:49 +00:00
Thomas Adam
9e1f110db0 Merge branch 'obsd-master' 2025-03-24 22:01:11 +00:00
nicm
483b2b3edb Correctly skip wide characters in hyperlinks, from someone in GitHub
issue 4425.
2025-03-24 20:17:24 +00:00
nicm
34a35b0f09 Expand formats with the pane modifier in tree mode so that #() doesn't
always use the same value. From Michael Grant in GitHub issues 4412 and
4420.
2025-03-24 20:13:03 +00:00
nicm
aca3ffb30a Add default-client-command to set the command used is tmux is run
without a command (the default stays new-session). From David Mandelberg
in GitHub issue 4422.
2025-03-24 20:01:03 +00:00
Thomas Adam
c3c4524def Merge branch 'obsd-master' 2025-03-21 16:01:11 +00:00
nicm
f101762d1b Fix mouse_hyperlink format in copy mode. From someone in GitHub issue
4418.
2025-03-21 14:04:26 +00:00
nicm
a541be3951 Add S-Up and S-Down to move windows in tree mode. From David Mandelberg
in GitHub issue 4415.
2025-03-21 13:36:42 +00:00
nicm
b7d640e764 Add some additional cursor format variables. From shiro at usagi dot io
in GitHub issue 4414.
2025-03-21 13:26:39 +00:00
Thomas Adam
969f6a60c3 portable: SYNCING: correct tmux-openbsd
The tmux-openbsd repository is called tmux-obsd.

Noticed via Github issue #4419
2025-03-21 12:46:06 +00:00
Thomas Adam
6703cb85d9 Merge branch 'obsd-master' 2025-03-21 04:01:10 +00:00
jsg
111e16e772 remove prototypes for removed functions 2025-03-21 02:10:42 +00:00
Thomas Adam
3eb93383a3 Merge branch 'obsd-master' 2025-03-17 22:01:10 +00:00
nicm
817b621d20 If there is an active query, set escape time temporarily to a higher
value (the old default - 500). Some Windows terminals are very slow to
respond, or the network may be slow. From github at jyn dot dev.
2025-03-17 20:43:29 +00:00
nicm
5eb30c1543 Handle padding cells correctly for regular expression searching, GitHub issue 4399 from
github at jyn dot dev.
2025-03-17 20:33:20 +00:00
Thomas Adam
d4b8635f50 Merge branch 'obsd-master' 2025-03-11 10:01:12 +00:00
nicm
4e4fe3eb39 Cleanup window_get_active_at function. GitHub issue 4401 from Michael
Grant.
2025-03-11 08:14:26 +00:00
Thomas Adam
882fb4d295 Merge branch 'obsd-master' 2025-03-04 10:01:15 +00:00
nicm
eaf70c955b Add mode 2031 support to automatically report dark or light theme. tmux
will guess the theme from the background colour on terminals which do
not themselves support the escape sequence. Written by Jonathan
Slenders, GitHub issue 4353.
2025-03-04 08:45:04 +00:00
nicm
3543d79048 Free fill character string if it cannot be used, GitHub issue 4394. 2025-03-04 08:03:19 +00:00
Thomas Adam
94783addfc Merge branch 'obsd-master' 2025-02-26 10:01:14 +00:00
nicm
91c0de60b4 Also need the implied meta paste keys in the list for output. 2025-02-26 09:02:00 +00:00
nicm
21f7db4c4d Do not allow meta prefix on paste start and end sequences, GitHub issue 4387. 2025-02-26 08:55:27 +00:00
nicm
f224d61f37 Document the use of ';' as a modifier separator, from Matt Liggett in
GitHub issue 4384.
2025-02-26 07:50:36 +00:00
nicm
d938ab5dd7 If command parsing fails in the client, report the error rather than
trying to send the command to the server. GitHub issue 4372 from Nikola
Tadic.
2025-02-26 07:47:46 +00:00
nicm
9a8f46e554 Fix colouring of pane border when scrollbars are enabled, GitHub issue
4378 from Michael Grant.
2025-02-26 07:42:52 +00:00
nicm
27ee0c9c3b Add the width of the scrollbars to the calculation of the width of the
window panes when finding the adjacent panes, GitHub issue 4370 from
Michael Grant.
2025-02-26 07:39:50 +00:00
Thomas Adam
251a87e2d2 Merge branch 'obsd-master' 2025-02-20 16:01:14 +00:00
nicm
084e6ee9ec Add a -M flag to capture-pane to use the copy mode screen, GitHub issue
4358.
2025-02-20 13:39:58 +00:00
nicm
18331e39bf Reset overlay_resize pointer when clearing overlay. 2025-02-20 13:32:07 +00:00
Nicholas Marriott
250c88efdc Add .swp, from Nikola Tadic. 2025-02-20 13:31:07 +00:00
Thomas Adam
9a377485be Merge branch 'obsd-master' 2025-02-13 18:01:08 +00:00
nicm
47a56c11f2 Add a note about C-r and C-s behaviour, GitHub issue 4309.
Also add a missing word, from jmc@.
2025-02-13 16:31:25 +00:00
Nicholas Marriott
c4b9716873 Look for imsg_add not _init now. 2025-02-13 16:24:33 +00:00
Thomas Adam
ec119b2f9e Merge branch 'obsd-master' 2025-02-10 10:01:11 +00:00
nicm
5d1a6acc84 Align index numbers in trees, from David Mandelberg, GitHub issue 4360. 2025-02-10 08:18:23 +00:00
nicm
80eb460fc9 Add display-message -C flag to update pane while message is displayed,
GitHub issue 4363 from Vitaly Ostrosablin.
2025-02-10 08:14:32 +00:00
Thomas Adam
ef68debc8d Merge branch 'obsd-master' 2025-01-27 12:01:13 +00:00
nicm
4c12ac9fb8 Make list-commands command show only one command if an argument is
given, from Ilya Grigoriev in GitHub issue 4352.
2025-01-27 09:16:05 +00:00
nicm
244bb726e2 Add some missing spaces, from Ilya Grigoriev. 2025-01-27 09:05:22 +00:00
Nicholas Marriott
6ab268c7bb Remove old issue template. 2025-01-20 13:06:03 +00:00
Nicholas Marriott
0c9f8ff189
Update issue templates 2025-01-20 13:02:24 +00:00
Nicholas Marriott
dd7d04be95
Update issue templates 2025-01-20 13:00:07 +00:00
Thomas Adam
58392d29da Merge branch 'obsd-master' 2025-01-17 18:01:08 +00:00
nicm
9260f5dc96 Do not update focus on client's without a session. 2025-01-17 15:53:01 +00:00
Thomas Adam
62a6c16b43 Merge branch 'obsd-master' 2025-01-13 12:01:11 +00:00
nicm
31e8d4676a Count line numbers correctly inside strings, reported by Pedro Navarro
in GitHub issue 4325.
2025-01-13 08:58:34 +00:00
Thomas Adam
d3cbe00f78 Merge branch 'obsd-master' 2025-01-12 16:01:11 +00:00
nicm
97fe3563fa Do not crash if moving popup that has exited to a pane, from Michael
Grant in GitHub issue 4312.
2025-01-12 14:36:28 +00:00
nicm
37ad1e2f6d Map bright black (colour 8) to white (7) if the background is black on
terminals with only eight colours so the text is not invisible. From
Dmytro Bagrii in GitHub issue 4322.
2025-01-12 14:20:49 +00:00
Thomas Adam
00894d188d Merge branch 'obsd-master' 2025-01-02 12:01:10 +00:00
nicm
2a5eba7899 Check backspace against VERASE earlier before it is translated to an
internal key and do not go through the mapping on output. Fixes problems
reported by Ben Price in GitHub issue 4284 and by tb@.
2025-01-02 10:34:45 +00:00
Thomas Adam
bf30492d57 Merge branch 'obsd-master' 2025-01-01 18:01:10 +00:00
nicm
e00853ee82 Add an option allowing users to override the width of individual Unicode
codepoints (overriding tmux's default list).
2025-01-01 15:17:36 +00:00
Thomas Adam
e75f3a0060 Merge branch 'obsd-master' 2024-12-20 10:01:10 +00:00
nicm
eece41547e Only map S-Tag in mode 2, not mode 1. GitHub issue 4304. 2024-12-20 07:10:51 +00:00
Thomas Adam
c311202b73 Merge branch 'obsd-master' 2024-12-17 10:01:11 +00:00
nicm
e149d29803 Assign excess space more evenly when spreading out cells, from Torbjorn
Lonnemark.
2024-12-17 08:40:24 +00:00
Thomas Adam
190ddda572 Merge branch 'obsd-master' 2024-12-16 12:01:12 +00:00
Thomas Adam
6b470c5222 Merge branch 'obsd-master' 2024-12-16 10:01:11 +00:00
nicm
6b32d195e8 Add a nesting limit to source-file, from Fadi Afani in GitHub issue
4223.
2024-12-16 09:13:09 +00:00
nicm
bec6ce54c1 Memory leak, GitHub issue 4298. 2024-12-16 08:54:34 +00:00
nicm
106d1c3538 Missing main-vertical-mirrored from layout list, from charlotte at
lottia dot net.
2024-12-16 08:51:41 +00:00
Thomas Adam
ae8f2208c9 Merge branch 'obsd-master' 2024-12-06 12:01:11 +00:00
nicm
5c3cf2f08b Preserve modifiers on backspace. 2024-12-06 09:07:40 +00:00
nicm
102f34090d Do not write bracketed paste keys themselves if the pane has not asked
for them.
2024-12-06 09:06:56 +00:00
Thomas Adam
99790c90aa Merge branch 'obsd-master' 2024-12-04 22:01:08 +00:00
nicm
6d792e4123 Fix backspace option for new key format, GitHub issue 4284. 2024-12-04 19:11:15 +00:00
Thomas Adam
98e322d5a5 Merge branch 'obsd-master' 2024-12-03 14:01:12 +00:00
jmc
01edce40f3 M-1 to M-7 for 7 preset layouts; from bunkmate
ok nicm
2024-12-03 11:18:34 +00:00
Thomas Adam
0549f87ccc Merge branch 'obsd-master' 2024-11-28 10:01:11 +00:00
nicm
72cd0eac29 Add extended keys flag for foot terminal. 2024-11-28 08:49:14 +00:00
Thomas Adam
f0c68533c4 Merge branch 'obsd-master' 2024-11-27 12:01:08 +00:00
Nicholas Marriott
9e4a9c51cc Use evbuffer_readline if readln is not available. It doesn't work properly but
at least it builds.
2024-11-27 10:37:45 +00:00
Nicholas Marriott
6874ec0dcc Remove endian.h. 2024-11-27 10:31:51 +00:00
Nicholas Marriott
252f41818e Update imsg and remove workaround. 2024-11-27 10:30:52 +00:00
nicm
d361f21065 Do not check for latest client in callback since the type may be latest
but with no window, fixes new-session -x and -y with another attached
client. GitHub issue 4268.
2024-11-27 10:12:20 +00:00
nicm
feb090abb3 Do not stop drag on double or triple click, GitHub issue 4272. 2024-11-27 10:10:20 +00:00
Thomas Adam
db771ec6e3 Merge branch 'obsd-master' 2024-11-26 18:01:10 +00:00
nicm
6f7db82b18 Add copy-mode-position-style and copy-mode-selection-style for copy
mode (they default to mode-style as before).
2024-11-26 15:52:41 +00:00
nicm
67cc7f6dc6 Enter is now sent from single prompt as \r not empty string. 2024-11-26 15:51:48 +00:00
Thomas Adam
db978db271 Merge branch 'obsd-master' 2024-11-25 14:01:12 +00:00
nicm
363f35f076 Do not try to terminate an empty buffer. 2024-11-25 12:32:24 +00:00
Thomas Adam
49b7276f2a Merge branch 'obsd-master' 2024-11-25 10:01:11 +00:00
nicm
f57131e11b Use cursor style from global options instead of default for popups, from
Alexander Arch.
2024-11-25 08:36:46 +00:00
nicm
420af9e108 Do not rely on window reference count for linked formats because they
are also used for notifications, GitHub issue 4258.
2024-11-25 08:34:01 +00:00
Thomas Adam
ceaf9b7452 Merge branch 'obsd-master' 2024-11-22 14:01:11 +00:00
nicm
5fd45b3892 Do not strvis output to terminal from commands. 2024-11-22 12:58:05 +00:00
nicm
64d82d5988 Document command prompt escape sequence, from Von Welch. 2024-11-22 12:36:13 +00:00
Nicholas Marriott
0f308bd18f imsg no longer associates file descriptors with the imsg they were sent with,
work around this for the moment (it is not clear if this is intentional).
2024-11-22 09:58:47 +00:00
Nicholas Marriott
1365f1ce52 Add an __unused. 2024-11-22 08:07:21 +00:00
Nicholas Marriott
7fc4e54efe And arpa/inet.h needs to stay... 2024-11-22 08:06:30 +00:00
Nicholas Marriott
c98c08c232 Need to remove endian.h as well. 2024-11-22 08:05:02 +00:00
Nicholas Marriott
990c724bd8 Bring in updated imsg. 2024-11-22 08:03:55 +00:00
Thomas Adam
b82c7b40b0 Merge branch 'obsd-master' 2024-11-21 16:01:11 +00:00
claudio
70299c6646 Convert sbin and usr.bin to check for imsgbuf_init failure and add
imsgbuf_allow_fdpass where needed.

OK tb@
2024-11-21 13:35:20 +00:00
Thomas Adam
ea6c5053c8 Merge branch 'obsd-master' 2024-11-21 10:01:09 +00:00
nicm
3f4fd45d5c Fix save-buffer documentation - it writes to stdout. From Ilya Grigoriev. 2024-11-21 07:37:21 +00:00
nicm
7c7e88253e When the mouse clicked on the border between two horizontal panes, the
location was not being set properly. Pulled the checking of this into
separate function for clarity. Fixes dragging on horizontal pane border.
From Michael Grant.
2024-11-21 07:34:38 +00:00
Thomas Adam
bb94a5437d Merge branch 'obsd-master' 2024-11-21 00:01:13 +00:00
nicm
273f9b2027 Fix word navigation on lines with tabs, from Alexander Arch. 2024-11-20 20:54:02 +00:00
Nicholas Marriott
b6d0b4be30 Define SD_ID128_UUID_FORMAT_STR if missing, from Marc Reisner. 2024-11-19 17:55:12 +00:00
Thomas Adam
2dce45f427 Merge branch 'obsd-master' 2024-11-18 10:01:12 +00:00
nicm
a3ede3106a Check all %if in the list when deciding whether to process an
assignment, not just the most recent.
2024-11-18 08:29:35 +00:00
Thomas Adam
dd9722184b Merge branch 'obsd-master' 2024-11-16 18:01:08 +00:00
nicm
a854e36f2b Do not call layout_fix_panes if wp is NULL (that is, a popup). 2024-11-16 16:49:50 +00:00
Thomas Adam
be594ff8a4 Merge branch 'obsd-master' 2024-11-15 16:01:11 +00:00
nicm
c66628e52b Add no-detach-on-destroy client option (useful for control mode
clients). From laur dot aliste at gmail dot com, GitHub issue 4242.
2024-11-15 14:09:04 +00:00
nicm
350a151ee4 Add two new style parameters, width and pad, which apply to scrollbars.
From Michael Grant, GitHub issue 4241.
2024-11-15 13:12:20 +00:00
Thomas Adam
d35458e3fe Merge branch 'obsd-master' 2024-11-15 10:01:11 +00:00
nicm
d6883c0266 Turn off scrollbar when pane is in alternate screen, from Michael Grant,
GitHub issue 4231.
2024-11-15 09:01:16 +00:00
Thomas Adam
563ed05353 Merge branch 'obsd-master' 2024-11-12 12:01:10 +00:00
nicm
f527412d9b Tidy up loop, from Alexander Arch. 2024-11-12 10:06:35 +00:00
nicm
713cacab1e Mouse support on the scrollbars, from Michael Grant. 2024-11-12 09:32:56 +00:00
Thomas Adam
846f813565 Merge branch 'obsd-master' 2024-11-11 10:01:08 +00:00
nicm
c26d71d3e9 Add an option to control the input buffer size, from Ken Lau. 2024-11-11 08:41:05 +00:00
Thomas Adam
c8677d3272 Merge branch 'obsd-master' 2024-11-08 10:01:08 +00:00
nicm
596ea62dc3 Some fixes for searching for tabs, from Alexander Arch. 2024-11-08 08:51:36 +00:00
Thomas Adam
1fe30bb2e8 Merge branch 'obsd-master' 2024-11-06 20:33:45 +00:00
nicm
809d659e64 Xr to Ic, from jmc. 2024-11-05 21:07:19 +00:00
nicm
09f4e43189 Add support for a scrollbar at the side of each pane. New options
pane-scrollbars turn them on or off, pane-scrollbars-position sets the
position (left or right), and pane-scrollbars-style to set the colours.
Mouse support will come later. From Michael Grant in GitHub issue 4221.
2024-11-05 09:41:17 +00:00
Thomas Adam
679bbdcf8f Merge branch 'obsd-master' 2024-11-04 10:01:09 +00:00
nicm
a0c79aa87b Do not make padding cells extended (there can be a lot of them), from
Alexander Arch .
2024-11-04 08:52:13 +00:00
Nicholas Marriott
46f3846659 Add -Wno-macro-redefined for macOS. 2024-10-31 12:57:40 +00:00
Thomas Adam
bbc3cc558c Merge branch 'obsd-master' 2024-10-28 10:01:08 +00:00
nicm
c8bd42de16 Match tab cells when searching, from Alexander Arch in GitHub issue
4201.
2024-10-28 08:16:51 +00:00
nicm
62e15e905b Treat tabs as a word separator, from Alexander Arch in GitHub issue
4201.
2024-10-28 08:16:06 +00:00
nicm
125a7b9177 Fix issues in the command prompt: set PROMPT_QUOTENEXT after quoting
than before, meaning that accidentally scrolling the mouse wheel doesn't
break quoting; and move the cursor correctly over wide characters. From
Alexander Arch in GitHub issue 4212.
2024-10-28 08:11:59 +00:00
Thomas Adam
895044c52b Merge branch 'obsd-master' 2024-10-25 22:01:10 +01:00
nicm
40c01c2d37 Allow tabs even on terminals without UTF-8, reported by jmc. 2024-10-25 19:36:38 +00:00
Thomas Adam
911d768b71 Merge branch 'obsd-master' 2024-10-25 18:01:11 +01:00
nicm
71a503e40c Allow control characters to be entered at the command prompt prefixed
with with C-v, from  Alexander Arch in GitHub issue 4206.
2024-10-25 15:32:51 +00:00
nicm
487b0ee124 Do not attempt to search for zero length strings, from Alexander Arch in
GitHub issue 4209.
2024-10-25 15:19:15 +00:00
nicm
eaec0a48f4 Do not stop stop at first padding in format_grid_line and handle tabs. 2024-10-25 15:13:10 +00:00
nicm
fdbc6cdea5 Flag tabs if possible in the grid cell so they can be preserved on
copying and capture-pane. From Alexander Arch in GitHub issue 4201.
2024-10-25 15:00:18 +00:00
Thomas Adam
9623ec3ee4 Merge branch 'obsd-master' 2024-10-25 10:01:07 +01:00
nicm
63582c154c Add a helper function for cell data comparison, from Alexander Arch. 2024-10-25 07:57:49 +00:00
Thomas Adam
914815e70f Merge branch 'obsd-master' 2024-10-21 16:01:07 +01:00
nicm
354926a956 Bump up the maximum for repeat-time (some people want it to be
effectively infinite).
2024-10-21 12:42:06 +00:00
nicm
df303770ea Add function to get current offset from copy mode, from Michael Grant. 2024-10-21 12:39:49 +00:00
Thomas Adam
a269c33a54 Merge branch 'obsd-master' 2024-10-21 10:01:08 +01:00
nicm
eb04f9314b Adjust how Ctrl and Meta keys are sent to use standard representation if
available in mode 1, from Stanislav Kljuhhin, GitHub issue 4188.
2024-10-21 07:38:06 +00:00
Thomas Adam
a9d0461839 Merge branch 'obsd-master' 2024-10-17 20:01:07 +01:00
nicm
71aa4fe767 Switch pane-colors and cursor-style options to be in alphabetical order,
from Teubel Gyorgy, GitHub issue 4191.
2024-10-17 17:22:01 +00:00
nicm
cfd3c02306 Allow attributes in menu style, from Japin Li in GitHub issue 4194. 2024-10-17 17:10:41 +00:00
Thomas Adam
35104059ed Merge branch 'obsd-master' 2024-10-15 00:01:10 +01:00
nicm
934035db71 Set ACS flag for REP. Reported by Romain Francoise, GitHub issue 4182. 2024-10-14 20:26:45 +00:00
Nicholas Marriott
8ff65230e1 Optimize sixel_print. Previously, the algorithm scanned each pixel several
times; once to find out which colors are active, and then once for every single
active color to actually construct the output string.

Now it constructs the compressed sixel patterns in the first pass (now x * 12
iters), so we can reduce the second pass (the really expensive part, at active
colors * x * 6 iters) to just appending these to the output buffer.

From nincsnevem662 at gmail dot com in GitHub issue 4184.
2024-10-14 11:05:59 +01:00
Thomas Adam
cb00e869ea Merge branch 'obsd-master' 2024-10-12 12:01:09 +01:00
nicm
f8b56fdc3f Call realpath on the source file to match -f on the command line, GitHub
issue 4180.
2024-10-12 08:20:32 +00:00
nicm
2d8b6fcf23 Do not rename a buffer to itself, GitHub issue 4181. 2024-10-12 08:13:52 +00:00
Nicholas Marriott
6ddee22f81 Portable tmux needs to check ENABLE_SIXEL. 2024-10-10 12:07:29 +01:00
Thomas Adam
66c738bc10 Merge branch 'obsd-master' 2024-10-10 12:01:08 +01:00
nicm
bcc47add38 Add a sixel_support format variable which is 1 if SIXEL is supported
(always 0 on OpenBSD), requested by Misaki Masa in GitHub issue 4177
2024-10-10 10:41:33 +00:00
Thomas Adam
d326c51d79 Merge branch 'obsd-master' 2024-10-08 12:01:09 +01:00
nicm
940fdf7ed0 Draw pane status line on the correct line when at the bottom, fixes
issues if the window size is smaller than the entire terminal. GitHub
issue 3943.
2024-10-08 09:40:50 +00:00
Thomas Adam
4f5d6d97d3 Merge branch 'obsd-master' 2024-10-08 10:01:08 +01:00
nicm
00412b570b Put the prompt cursor attributes into the status line screen and use
that rather than updating the current screen (since there might not be
one).
2024-10-08 06:29:44 +00:00
Thomas Adam
6a35b8ad07 Merge branch 'obsd-master' 2024-10-07 16:01:08 +01:00
nicm
735082b7c2 Add prompt-cursor-colour and prompt-cursor-style to set the style of the
cursor in the command prompt and remove the emulated cursor, from
Alexander Arch in GitHub issue 4170.
2024-10-07 12:58:36 +00:00
Thomas Adam
5b7bdc82c8 Merge branch 'obsd-master' 2024-10-07 12:01:08 +01:00
nicm
a3dea81b49 Add initial-repeat-time option to allow the first repeat time to be
increased and later reduced, from David le Blanc in GitHub issue 4164.
2024-10-07 08:50:47 +00:00
Thomas Adam
486221f206 Merge branch 'obsd-master' 2024-10-06 12:01:07 +01:00
nicm
9528d7470b Try to stay near the same line in modes if the current one is removed. 2024-10-06 09:30:22 +00:00
Thomas Adam
933d6b90ed Merge branch 'obsd-master' 2024-10-05 16:01:07 +01:00
nicm
a869693405 Send focus events to pane when entering or leaving popup, GitHub issue
3991.
2024-10-05 12:10:16 +00:00
Thomas Adam
114977dd25 Merge branch 'obsd-master' 2024-10-05 04:01:08 +01:00
Thomas Adam
aba8ffbe7b Merge branch 'obsd-master' 2024-10-05 02:01:07 +01:00
nicm
455a2b3705 Remove some debugging left behind. 2024-10-05 00:35:35 +00:00
nicm
e0638c48cd Add copy-mode-position-format to configure the position indicator. 2024-10-05 00:32:55 +00:00
nicm
41f6b691e3 Document missing window-layout-changed hook. 2024-10-04 22:36:11 +00:00
Nicholas Marriott
0f30fa34e3 Add install step. 2024-10-04 23:29:36 +01:00
Thomas Adam
e486f5ffdc Merge branch 'obsd-master' 2024-10-04 22:01:09 +01:00
nicm
5a68730e2f Add -y flag to disable confirmation prompts in modes, GitHub issue 4152. 2024-10-04 19:16:13 +00:00
Thomas Adam
16b44d2a5b Merge branch 'obsd-master' 2024-10-04 18:01:07 +01:00
nicm
34775fc235 Do not translate BSpace as Unicode, GitHub issue 4156. 2024-10-04 14:55:17 +00:00
Thomas Adam
f2fd8c854a Merge branch 'obsd-master' 2024-10-04 10:01:08 +01:00
nicm
9f2a853d87 Rework of copy mode commands ("send-keys -X") to parse the arguments so
that flags may be detected propertly rather than just looking for
strings ("-O" and so on). Also add -C and -P flags to the copy commands:
-C prevents the commands from sending the text to the clipboard and -P
prevents them from adding the text as a paste buffer.

Note some of the default key bindings change to add "--" and any similar
custom key bindings using "send-keys -X" may need a similar change.

GitHub issue 4153.
2024-10-04 07:03:08 +00:00
Nicholas Marriott
7a78cdf78c Three SIXEL improvements from nincsnevem662 at gmail dot com in GitHub issue
4149:

- Pass P2 on the received image through when forwarding the image to the
  outside terminal to preserve transparency;

- Preserve raster attribute dimensions which may be smaller than the actual
  image (used to crop out parts of the image to work around the limitation that
  rows must come in groups of six);

- To avoid collapsing empty sixel lines, no longer ignore duplicate "-" new
  line specifiers.
2024-10-04 07:49:07 +01:00
Thomas Adam
2df15ad08c Merge branch 'obsd-master' 2024-10-03 08:01:07 +01:00
nicm
780a87be9a Improve fix for shifted keys so it works for all the keys it should,
Stanislav Kljuhhin in GitHub issue 4146.
2024-10-03 05:41:59 +00:00
Nicholas Marriott
1e303b6a9d Bypass permission check for Cygwin, based on a different change by Yuya Adachi
via Rafael Kitover; GitHub issue 4148.
2024-10-02 14:04:06 +01:00
Thomas Adam
8d2aee34ab Merge branch 'obsd-master' 2024-10-02 14:01:10 +01:00
nicm
05116cefe6 Add MSYSTEM to default update-environment. 2024-10-02 11:51:15 +00:00
nicm
ce4be58eef Add a define for the socket permissions check so it can be overridden
more easily (for Cgywin).
2024-10-02 11:48:16 +00:00
Nicholas Marriott
8d6eb4be40 Set client stdout file descriptor also for Cgywin, from Michael Wild via Rafael
Kitover in GitHub issue 4148.
2024-10-02 12:16:24 +01:00
Thomas Adam
38c38f1c64 Merge branch 'obsd-master' 2024-10-02 10:01:08 +01:00
nicm
ddf6af79e3 Report shifted keys like S-A as A not as S-A in mode 1 extended keys,
from Stanislav Kljuhhin.
2024-10-02 08:06:45 +00:00
Thomas Adam
826ba515be Merge branch 'obsd-master' 2024-10-01 14:01:08 +01:00
Nicholas Marriott
729bded8bf Fix up regression tests. 2024-10-01 13:40:42 +01:00
nicm
b95a06d2d4 Add a way to make the preview larger in tree mode, GitHub issue 4124. 2024-10-01 10:10:29 +00:00
Thomas Adam
157d748949 Merge branch 'obsd-master' 2024-10-01 10:01:10 +01:00
nicm
1c1f4c1219 Use global cursor style and colour options for modes instead of default,
GitHub issue 4117.
2024-10-01 08:01:19 +00:00
nicm
17bab32794 Change pasting to bypass the output key processing entirely and write
what was originally received. Fixes problems with pasted text being
interpreted as extended keys reported by Mark Kelly.
2024-10-01 06:15:47 +00:00
Thomas Adam
25b1cc1e8e Merge branch 'obsd-master' 2024-09-30 12:01:11 +01:00
nicm
89adec0ca5 On some Windows terminals, if TIOCWINSZ does not return xpixel and
ypixel (they are zero), if this is the case then try the query escape
sequences. From Dmitry Galchinsky in GitHub issue 4099.
2024-09-30 08:10:20 +00:00
nicm
f95d055e04 Only use default-shell for popups, return to /bin/sh for run-shell,
if-shell and #() - these have been documented as using /bin/sh for a
long time and scripts rely on it. Pointed out by Gregory Pakosz.
2024-09-30 07:54:51 +00:00
Thomas Adam
7b148f7b5b Merge branch 'obsd-master' 2024-09-29 22:01:09 +01:00
nicm
9bd039d1bc Fix grey colour, from Magnus Gross. 2024-09-29 20:05:42 +00:00
Nicholas Marriott
7c30056d96 Bump to 3.6. 2024-09-27 08:58:00 +01:00
Nicholas Marriott
ac44566c9c tmux 3.5. 2024-09-27 08:56:39 +01:00
Thomas Adam
64f1076d97 Merge branch 'obsd-master' 2024-09-17 00:01:09 +01:00
nicm
489c69f5ed Add copy mode commands which were missed when descriptions were added,
from Julian Prein, GitHub issue 4121.
2024-09-16 20:46:58 +00:00
nicm
f897049935 Change the behaviour of extended-keys always slightly so that
applications can still enter mode 2 if they want, they just cannot turn
extended keys off entirely. From Stanislav Kljuhhin.
2024-09-16 20:38:48 +00:00
nicm
d8b66110f7 Add a prefix timeout option, from Conor Taylor in GitHub issue 4108. 2024-09-16 20:28:22 +00:00
Nicholas Marriott
8b1a3bb2e5 Only default --enable-debug if the user has not turned it off, from Ken Lau. 2024-09-16 21:19:43 +01:00
Thomas Adam
37771a5a8d Merge branch 'obsd-master' 2024-09-11 22:01:10 +01:00
nicm
3a8a31d8d2 Mouse move keys are not useful as key bindings because we do not turn
them on unless the application requests them. Ignore them so they do not
cause the prefix to be canceled, GitHub issue 4111.
2024-09-11 19:12:33 +00:00
Nicholas Marriott
c36ffcbe56 Typo from Bastian Venthur. 2024-09-06 13:09:43 +01:00
Thomas Adam
3d8ead8a97 Merge branch 'obsd-master' 2024-08-28 10:27:21 +01:00
nicm
141cd78407 Display hyperlinks in copy mode and add copy_cursor_hyperlink format to
get the hyperlink under the cursor.
2024-08-27 07:49:07 +00:00
nicm
d0c8124661 Add search_count and search_count_partial formats in copy mode, GitHub
issue 4091.
2024-08-27 07:31:26 +00:00
nicm
2917bc5274 Do not reset mouse pane if clicked on status line, it may have been set
by a range.
2024-08-27 07:25:27 +00:00
nicm
2d1e93447e Use strtonum instead of atoi. 2024-08-26 13:02:15 +00:00
nicm
31b6c9356c C-h should not be treated specially and represented internally as \b but
as C-h like the other Ctrl keys. Backspace is already handled separately
if it VERASE.
2024-08-26 07:45:05 +00:00
nicm
9e2a7c28f5 Pass the screen_redraw_ctx struct into more functions instead of
individual arguments (for example for the pane status), from Michael
Grant.
2024-08-26 07:34:40 +00:00
nicm
73b2277af8 Client flags was changed to uint64_t a while ago, fix a few cases where
it is still int (do not matter now but will with some new flags). From
Michael Grant.
2024-08-26 07:30:46 +00:00
nicm
a84c109604 Add window_pane_mode helper function to tell if a pane is in copy mode,
from Michael Grant.
2024-08-26 07:14:40 +00:00
nicm
4823acca8f Add copy-mode -d flag to scroll a page down if in copy mode already,
from Michael Grant.
2024-08-26 07:09:34 +00:00
Thomas Adam
34807388b0 Merge branch 'obsd-master' 2024-08-23 16:01:10 +01:00
nicm
08be883297 Ignore internal function keys if they have not got an entry in the key
table.
2024-08-23 13:25:39 +00:00
Thomas Adam
13bd0e46db Merge branch 'obsd-master' 2024-08-23 14:01:08 +01:00
nicm
6e9a914014 Check for exact match for layout name before looking for a prefix match. 2024-08-23 10:19:06 +00:00
Thomas Adam
7990e5fa8f Merge branch 'obsd-master' 2024-08-22 12:01:07 +01:00
nicm
4860a58d07 Clear overlay when command prompt is entered. Also fix some spacing in
man page pointed out by jmc.
2024-08-22 09:05:51 +00:00
Thomas Adam
99af9f23bd Merge branch 'obsd-master' 2024-08-22 08:01:08 +01:00
nicm
9ebbe2cca7 Short Ctrl keys like ^A need to be converted to lowercase so they end up
as 'a'|KEYC_CTRL to match the new internal representation. Problem
reported by naddy@.
2024-08-22 05:39:55 +00:00
Thomas Adam
692bae9ea6 Merge branch 'obsd-master' 2024-08-21 08:01:09 +01:00
nicm
a6645c4de4 Mention that load- and save-buffer can use stdin, from Ramon Fischer. 2024-08-21 05:06:45 +00:00
nicm
06292baadc Add mirrored versions of the main-horizontal and main-vertical layouts where
the main pane is bottom or right instead of top or left, from Sherwyn Sen.
2024-08-21 05:03:13 +00:00
nicm
ceda0a68ae C-Space and Meta keys should not be translated in mode 1 extended keys. 2024-08-21 04:55:57 +00:00
nicm
4fa90c9acf Set the default for extended-keys back to off because it appears emacs turns
the keys on but does not correctly handle them except in xterm (!). Also fix so
that off takes effect as expected.
2024-08-21 04:37:42 +00:00
nicm
c7e61a01e5 Revamp extended keys support to more closely match xterm and support
mode 2 as well as mode 1. From Stanislav Kljuhhin (GitHub issue 4038).

This changes tmux to always request mode 2 from parent terminal, change
to an unambiguous internal representation of keys, and adds an option
(extended-keys-format) to control the format similar to the xterm(1)
formatOtherKeys resource.
2024-08-21 04:17:09 +00:00
Thomas Adam
963e824f5f Merge branch 'obsd-master' 2024-08-19 12:01:09 +01:00
nicm
de6bce057a Allow REP to work with Unicode characters, GitHub issue 3687. 2024-08-19 08:31:36 +00:00
nicm
937ba1d8dd Both terminators \007 and \033\\ leave the index pointing to the final
character of the terminator, so correct the size calculation to always
add one. GitHub issue 4082.
2024-08-19 08:29:16 +00:00
Thomas Adam
651891c3bd Merge branch 'obsd-master' 2024-08-04 12:01:09 +01:00
nicm
4008e2ff6d Make a little effort to treate CRLF as LF in config files. GitHub issue
3720.
2024-08-04 09:42:23 +00:00
nicm
b88130d24b The Linux console has some bugs with bright colours. It seems likely
that it is emulating them by setting a bright (or bold) flag; however,
when the colour is changed from a bright colour (say SGR 96) to a
non-bright (say SGR 36), the flag is not reset, so the new colour
remains as bright. SGR 39 (default colour) also does not reset, so you
end up with the bright default colour. Work around this by sending SGR 0
when switching away from a bright colour, and disable AX for TERM=linux.
Also make the check for AX simpler and do not check for the op
capability is not actually used. GitHub issue 3976.
2024-08-04 09:35:30 +00:00
nicm
fc7ee7efc7 -l should be before -r, pointed out by jmc a while ago. 2024-08-04 09:01:18 +00:00
Nicholas Marriott
d0eb3fe543 Use terminal-features instead of terminal-overrides to enable truecolor support
in example_tmux.conf, from Simon Hengel.
2024-08-04 09:59:18 +01:00
Nicholas Marriott
2ac0faf119 If built with systemd, remove some environment variables it uses. From Ciprian
Dorin Craciun, GitHub issue 4035.
2024-08-04 09:58:13 +01:00
Nicholas Marriott
775789fbd5 Rename header guards on compat/queue.h to avoid it conflicting if the system
header is included first. This matters on some platforms (macOS) where queue.h
is old. From Saagar Jha in GitHub issue 4041.
2024-08-04 09:57:26 +01:00
nicm
7b6fbe7262 Adjust the logic when deleting last buffer to better preserve the
selection: if selecting the element below the deleted one fails (because
as the last one), select the one above it instead. From Daniel Mueller,
GitHub issue 4043.
2024-08-04 08:53:43 +00:00
Thomas Adam
109d2bda1a Merge branch 'obsd-master' 2024-07-22 18:01:09 +01:00
nicm
ddd4e57c65 Expand full array option values if no index is provided, GitHub issue
4051.
2024-07-22 15:27:42 +00:00
Nicholas Marriott
3c2621b41b Support building with jemalloc memory allocator, from Romain Francoise. 2024-07-15 11:25:15 +01:00
Nicholas Marriott
5039be657c utf8proc bits for utf8_fromwc. 2024-07-12 14:30:56 +01:00
Thomas Adam
d02254f754 Merge branch 'obsd-master' 2024-07-12 14:01:09 +01:00
nicm
aa1353947e UTF-8 keys now contain the internal representation and not the Unicode
codepoint, so convert extended keys properly. From Stanislav Kljuhhin.
2024-07-12 11:21:18 +00:00
Nicholas Marriott
171004dfd0 Use mdoc on Illumos which uses mandoc, from Andy Fiddaman. 2024-07-08 10:57:32 +01:00
Thomas Adam
c773fe89e7 Merge branch 'obsd-master' 2024-06-24 12:01:10 +01:00
nicm
093b5a5518 Add a way (refresh-client -r) for control mode clients to provide OSC 10
and 11 responses to tmux so they can set the default foreground and
background colours, from George Nachman in GitHub issue 4014.
2024-06-24 08:30:50 +00:00
nicm
db1665868f Check the underline style colour against the correct default value again
(it was changed from 0 to 8), from Romain Francoise.
2024-06-24 08:11:46 +00:00
Thomas Adam
c07e856d24 Merge branch 'obsd-master' 2024-05-24 16:01:08 +01:00
nicm
692ce59bce Do not escape $ unless DQ is set, that is the only case where we need to
escape it.
2024-05-24 12:41:24 +00:00
nicm
9e7c1aee48 Add N to search backwards in tree modes, from Fadi Afani in GitHub issue
3982.
2024-05-24 12:39:06 +00:00
Thomas Adam
4c2eedca5a Merge branch 'obsd-master' 2024-05-19 06:01:09 +01:00
jsg
ac6c1e9589 remove prototype with no matching function 2024-05-19 03:27:58 +00:00
Thomas Adam
0903790b00 Merge branch 'obsd-master' 2024-05-18 12:01:09 +01:00
jsg
03de52653e remove prototypes with no matching function; ok nicm@ 2024-05-18 08:51:26 +00:00
jsg
da06719309 remove externs with no matching var; ok nicm@ 2024-05-18 08:50:11 +00:00
Thomas Adam
fc84097379 Merge branch 'obsd-master' 2024-05-15 14:01:09 +01:00
Thomas Adam
4fd725c6e1 Merge branch 'obsd-master' 2024-05-15 12:01:10 +01:00
nicm
d39dcea30a Use default-shell for command prompt #() and popups as well 2024-05-15 09:59:12 +00:00
nicm
bfd65398a9 Fix memory leaks reported by Lu Ming Yin. 2024-05-15 08:39:30 +00:00
Thomas Adam
452d987e0e Merge branch 'obsd-master' 2024-05-14 14:01:10 +01:00
Thomas Adam
8ef899f315 Merge branch 'obsd-master' 2024-05-14 12:01:09 +01:00
nicm
a18d1146aa Add missing time.h to tty.c (from Ismail Donmez), also remove some stray
spaces.
2024-05-14 10:11:09 +00:00
nicm
5b5004e5ac Revert part of the change for GitHub issue 3675 because it does not work
correctly, it was intended to skip lines that are already being searched
as part of a previous wrapped line but in fact is skipping all lines
except the last in wrapped lines.

Also revert the search-wrapped-lines option (I didn't realize it was
intended to work around this).
2024-05-14 09:32:37 +00:00
Thomas Adam
6ff8f8fbf9 Merge branch 'obsd-master' 2024-05-14 10:01:10 +01:00
nicm
c9616700ca Add a command-error hook when a command fails, from Hugh Davenport in
GitHub issue 3973.
2024-05-14 07:52:19 +00:00
nicm
4c928dce74 Add an option to disable unwrapping lines for searching, from
meanderingprogrammer at gmail dot com, GitHub issue 3975.
2024-05-14 07:40:39 +00:00
nicm
fb37d52dde Restore previous behaviour or writing to stdout if available. 2024-05-14 07:33:01 +00:00
Thomas Adam
363d9c401e Merge branch 'obsd-master' 2024-05-13 14:01:10 +01:00
nicm
8643ece345 Fix memory leak, from Fadi Afani. 2024-05-13 11:45:05 +00:00
Nicholas Marriott
9ba433e521 Use printf not echo -e, from Joyce Lin. 2024-05-13 12:42:14 +01:00
Nicholas Marriott
3823fa2c57 Send SIGHUP since some programs ignore SIGTERM, from Eduardo Grajeda in GitHub
issue 3958.
2024-04-30 12:38:58 +01:00
Thomas Adam
0a8571b6fe Merge branch 'obsd-master' 2024-04-23 16:09:50 +01:00
jsg
ea9f416c99 correct indentation; no functional change
ok tb@
2024-04-23 13:34:51 +00:00
Thomas Adam
036d8993e6 Merge branch 'obsd-master' 2024-04-15 12:01:11 +01:00
nicm
e8530c9fee Fixes for memory leaks reported by Lu Ming Yin, fixes from Howard Chu. 2024-04-15 08:19:55 +00:00
Nicholas Marriott
dd4c0109a9 Missing headers for Android, from Biswapriyo Nath. 2024-04-15 09:07:41 +01:00
Thomas Adam
43530d4397 Merge branch 'obsd-master' 2024-04-10 10:01:13 +01:00
nicm
553d4cba79 Add an option allow-set-title to forbid applications from changing the
pane title, from someone in GitHub issue 3930.
2024-04-10 07:36:25 +00:00
nicm
c62a9ca16b Correct handling of mouse up events (don't ignore all but the last
released button), and always process down event for double click. From
Rudy Dellomas III in GitHub issue 3919.
2024-04-10 07:29:15 +00:00
nicm
424f13fe13 Do not get muddled and crash if focusing a pane that is exiting,
reported by Saul Nogueras in GitHub issue 3776.
2024-04-10 07:15:21 +00:00
Thomas Adam
4bb6da75ba Merge branch 'obsd-master' 2024-04-05 02:01:09 +01:00
nicm
a28175dbfd Pick newest session as documented, not oldest, from Magnus Gross. 2024-04-04 22:44:40 +00:00
Thomas Adam
fc204bb5e5 Merge branch 'obsd-master' 2024-03-26 12:01:11 +00:00
nicm
6207a45139 Fix selection present check, reported by M Kelly. 2024-03-26 10:20:20 +00:00
Thomas Adam
3c3643f580 Merge branch 'obsd-master' 2024-03-21 14:01:10 +00:00
nicm
89c1c43ef9 Write padding character into the right position. 2024-03-21 12:10:57 +00:00
nicm
2e9d7ebf15 Reduce escape-time default to 10 milliseconds, 500 is far too long for
modern terminals and networks. Case made by Kurtis Rader in GitHub issue
3844.
2024-03-21 11:53:11 +00:00
nicm
d8ddeec7db Add -M to always turn mouse on in a menu, GitHub issue 3779. 2024-03-21 11:51:32 +00:00
nicm
6f0254e6a8 Look for feature code 21 for DECSLRM and 28 for DECFRA in the device
attributes and also accept level 1 (there is no hardware with this but
some emulators may use it). Pointed out by James Holderness.
2024-03-21 11:47:55 +00:00
Nicholas Marriott
aa17f0e0c1 Fix crash if SIXEL colour register is invalid and remove SIXEL images before
reflow to avoid a different crash, from Anindya Mukherjee.
2024-03-21 11:37:09 +00:00
nicm
0ae8b681b2 Use -p for default paste-buffer command in buffer mode, it will only do
anything if the application asked for it. From Gregory Anders.
2024-03-21 11:32:49 +00:00
nicm
6c0067c103 Do not notify window-layout-changed if the window is about to be
destroyed (since it may have been freed by the time the notify happens),
from Romain Francoise in GitHub issue 3860.
2024-03-21 11:30:42 +00:00
nicm
5458cb2850 Revert detach-client part of last, did not intend this to go in. 2024-03-21 11:27:18 +00:00
nicm
0c374868ca Do not consider a selection present if it is empty, from Michael Grant
(GitHub issue 3869). Also a typo fix from GitHub issue 3877.
2024-03-21 11:26:28 +00:00
Nicholas Marriott
bf5d3f2e26 Typo, GitHub issue 3877. 2024-03-21 11:19:59 +00:00
Nicholas Marriott
d5ef837f63 Remove duplicate .tmux.conf mention, from Valentin Rylenko. 2024-03-21 11:18:49 +00:00
Thomas Adam
b79e28b2c3 Merge branch 'obsd-master' 2024-03-13 14:01:09 +00:00
nicm
8ffd5458ff Make the attach-session description clearer - do not mention creating a
client which is not important, explicitly say the session must exist,
and mention new-session and new-session -A. Prompted by Theo.
2024-03-13 11:25:50 +00:00
Thomas Adam
b54e1fc4f7 Merge branch 'obsd-master' 2024-03-07 00:01:10 +00:00
Nicholas Marriott
bdb6321229 Update lock.yml. 2024-03-06 21:45:26 +00:00
nicm
bd29a48b56 Check for the right flag to fix split-window -p, from Bryan Childs. 2024-03-06 21:32:39 +00:00
Nicholas Marriott
f3f1c3db58 Add missing headers, from Marvin Schmidt. 2024-03-06 21:29:28 +00:00
Nicholas Marriott
608d113486 next-3.5 2024-02-13 10:20:18 +00:00
Nicholas Marriott
9ae69c3795 3.4. 2024-02-13 10:17:07 +00:00
Thomas Adam
0960862950 Merge branch 'obsd-master' 2024-02-13 10:01:10 +00:00
Nicholas Marriott
44ad25b367 Update CHANGES. 2024-02-13 09:12:08 +00:00
nicm
40b97b1715 Add two new values for the destroy-unattached option to destroy sessions
only if they are not members of sessions groups, from Mark Huang, GitHub
issue 3806.
2024-02-13 08:10:23 +00:00
nicm
4bdb855020 Do not allow paste into panes which have exited, from Romain Francoise
in GitHub issue 3830.
2024-02-13 08:03:50 +00:00
Thomas Adam
ea7136fb83 Merge branch 'obsd-master' 2024-01-22 18:01:09 +00:00
nicm
428f8a9b28 Increase buffer size to avoid truncating styles, GitHub issue 3809 from
Ricardo Bittencourt.
2024-01-22 16:34:46 +00:00
Nicholas Marriott
84faada25b Remove existing defines. 2024-01-17 10:59:07 +00:00
Nicholas Marriott
55d0abad89 Need htonll and ntohll. 2024-01-17 10:57:32 +00:00
Nicholas Marriott
7d91b4b90b htobe is not portable. 2024-01-17 09:47:35 +00:00
Nicholas Marriott
66369416fc Update imsg. 2024-01-17 09:41:53 +00:00
Thomas Adam
001e26d0bb Merge branch 'obsd-master' 2024-01-16 14:01:09 +00:00
claudio
2e39d698d2 Use imsg_get_fd() instead of direct access to imsg.fd
The change in proc.c can be further simplified once imsg_free() takes
care of unclaimed file descriptors.

OK nicm@
2024-01-16 13:09:11 +00:00
Thomas Adam
e809c2ec35 Merge branch 'obsd-master' 2024-01-03 19:17:10 +00:00
Nicholas Marriott
4266d3efc8 Assignment should be inside SIXEL. 2023-12-28 03:12:27 +00:00
nicm
40a20bc8ae Only wrap pattern in *s if using a regular expression. 2023-12-27 20:42:01 +00:00
nicm
f7bf7e9671 Remove flags from the prefix before comparing with the received key so
that modifier keys with flags work correctly, GitHub issue 3764.
2023-12-27 20:23:59 +00:00
nicm
008ecd4592 groff apparently generates broken output for some common characters in
mdoc, so escaped versions have to be used instead. From Alexis
Hildebrandt in GitHub issue 3762.
2023-12-27 20:20:50 +00:00
nicm
73a2b12088 Always initialize screen mode, GitHub issue 3750 from Ding Fei. 2023-12-27 20:17:13 +00:00
Nicholas Marriott
605bf21ff2 Do not use NULL window, GitHub issue 3747. 2023-12-27 20:15:57 +00:00
nicm
f028445407 Correctly handle window ops with no pane, GitHub issue 3747. 2023-12-27 20:13:35 +00:00
Thomas Adam
bdf8e614af Merge branch 'obsd-master' 2023-11-14 22:01:09 +00:00
nicm
4dea352dee Don't strdup NULL filename. 2023-11-14 20:01:11 +00:00
Thomas Adam
151875d144 Merge branch 'obsd-master' 2023-11-14 18:01:10 +00:00
nicm
88fd1f00b8 Handle NULL client (in config file) when showing a status message; also
copy the file when processing if-shell since it may be freed. GitHub
issue 3746.
2023-11-14 15:59:49 +00:00
nicm
1a14d6d2e1 Use SM 2026 for Sync which is more widely supported now. 2023-11-14 15:38:33 +00:00
Thomas Adam
381c00a74e Merge branch 'obsd-master' 2023-11-02 22:58:45 +00:00
nicm
5aadee6df4 next-prompt can have 1 argument. 2023-11-02 10:38:14 +00:00
Nicholas Marriott
a5545dbc9f Allow attributes to have only two parameters, from Tim Culverhouse. 2023-11-01 10:37:41 +00:00
nicm
fdf465925e Do not allow combined UTF-8 characters that are too long, GitHub issue
3729.
2023-10-30 16:05:30 +00:00
nicm
36e1ac6556 Unzoom window at start of destroy so it doesn't happen later (when
destroying panes) after the layout has been freed, GitHub issue 3717.
2023-10-23 08:12:00 +00:00
nicm
ffa376edf7 Switch to tiparm_s (added in ncurses 6.4-20230424) instead of tparm,
which allows ncurses to validate the capabilities correctly.
2023-10-17 09:55:32 +00:00
Thomas Adam
b777780720 Merge branch 'obsd-master' 2023-09-19 12:01:11 +01:00
nicm
347cd0b5f8 Fix a couple of mouse mode flag names. 2023-09-19 08:35:44 +00:00
Nicholas Marriott
0ca28b362e Add combined character test. 2023-09-19 09:29:20 +01:00
Nicholas Marriott
51b80b985e Restore utf8proc code. 2023-09-19 09:29:04 +01:00
Nicholas Marriott
789a98982e Reply to SMGRAPHICS. 2023-09-19 09:27:59 +01:00
Thomas Adam
b202a2f1b5 Merge branch 'obsd-master' 2023-09-17 21:03:06 +01:00
nicm
7e79108f8a Remove next- and previous-prompt added in error. GitHub issue 3696. 2023-09-16 16:18:29 +00:00
nicm
f09cde2542 Change UTF-8 combining to inspect the previous character at the cursor
position rather than keeping the last character from the input stream,
this is how most terminals work and fixes problems with displaying these
characters in vim. GitHub issue 3600.
2023-09-15 15:49:05 +00:00
Thomas Adam
9f9156c030 Merge branch 'obsd-master' 2023-09-15 10:01:11 +01:00
nicm
d394293ba5 Add -t to source-file, GitHub issue 3473. 2023-09-15 06:31:49 +00:00
Thomas Adam
c57a09269b Merge branch 'obsd-master' 2023-09-14 16:01:10 +01:00
nicm
8191c58737 Reset combine flag only if text is actually processed. 2023-09-14 13:01:35 +00:00
Thomas Adam
f68d35c529 Merge branch 'obsd-master' 2023-09-08 10:01:10 +01:00
nicm
c02bc4dbe9 On second thoughts, do check DA2 for DECFRA and DECSLRM since that will
catch terminals that say they are VT520 even if we can't use DA1
(because of VTE).
2023-09-08 07:05:06 +00:00
nicm
4872811ba7 Use DECSLRM and DECFRA only at level 4 rather than checking the terminal
id.
2023-09-08 06:52:31 +00:00
Nicholas Marriott
1a1290f30b Only remove images if reverse index actually scrolls. 2023-09-07 22:02:11 +01:00
Nicholas Marriott
7be7ca7195 Shut autoconf up. 2023-09-07 18:24:28 +01:00
Thomas Adam
32197fa52d Merge branch 'obsd-master' 2023-09-07 14:01:11 +01:00
nicm
9653a52a6a Use DECSLRM and DECFRA on terminals pretending to be VT520 or VT525 as
well as VT420.
2023-09-07 10:21:46 +00:00
Thomas Adam
d60c8942ce Merge branch 'obsd-master' 2023-09-07 10:01:10 +01:00
nicm
c99f9e92e0 Accept 65 for VT525 as well. 2023-09-07 07:19:21 +00:00
Thomas Adam
e26356607e Merge branch 'obsd-master' 2023-09-04 10:01:10 +01:00
nicm
43e5e80343 Skip wrapped lines in top level search loop because they will be
combined in the inner loop (in window_copy_search_rl_regex and the
others), avoids searching the same text multiple times. Also add a line
length limit for regex searches. GitHub issue 3675.
2023-09-04 08:01:43 +00:00
Thomas Adam
1742138f05 Merge branch 'obsd-master' 2023-09-02 22:01:09 +01:00
nicm
c767d62329 Request terminal colours again on SIGWINCH but at most once every 30
seconds, GitHub issue 3582.
2023-09-02 20:03:10 +00:00
Thomas Adam
7ad29b9831 Merge branch 'obsd-master' 2023-09-02 12:01:09 +01:00
nicm
d209fe9b1e Setulc only does RGB colour so add Setulc1 to do non-RGB colours, GitHub
issue 3627.
2023-09-02 09:17:23 +00:00
nicm
c5542637d7 Set visited flag on last windows when linking session. 2023-09-02 08:38:37 +00:00
Thomas Adam
e7c829fc67 Merge branch 'obsd-master' 2023-09-01 20:01:10 +01:00
nicm
579829eef2 Only compare the actual size of the UTF-8 character, not all of it. 2023-09-01 18:43:54 +00:00
Nicholas Marriott
3aa20f6e75 Use %05X not %08X. 2023-09-01 19:37:27 +01:00
nicm
f78279bb2e Add missing -T to getopt string. 2023-09-01 16:40:38 +00:00
Thomas Adam
a99d7c6314 makefile: fixup bad merge 2023-09-01 17:13:55 +01:00
Thomas Adam
cf1ed67fcc Merge branch 'obsd-master' 2023-09-01 17:09:41 +01:00
Thomas Adam
1aec420465 Merge branch 'obsd-master' 2023-09-01 17:06:27 +01:00
nicm
16e4b39359 Clear combine flag when a non-UTF-8 set of characters is encountered. 2023-09-01 16:01:54 +00:00
nicm
9456258ccc Rewrite combined character handling to be more consistent and to support
newer Unicode combined characters (which we have to "know" are combined
since they are not width zero). GitHub issue 3600.
2023-09-01 14:29:11 +00:00
nicm
c41d59f232 Expand name before looking for window with -S, GitHub issue 3670. 2023-09-01 14:24:46 +00:00
Nicholas Marriott
d682ef88e6 Bump width and height to 10000. 2023-09-01 14:54:27 +01:00
nicm
c1e6e54e6e Add detach-on-destroy previous and next, mostly from Alexis Hildebrandt. 2023-09-01 13:48:54 +00:00
Nicholas Marriott
62f657845e Fix merge error, from Jakub Łukasiewicz. 2023-08-26 20:57:44 +01:00
Thomas Adam
a9841a6d1e portable: fixup merge 2023-08-23 20:55:23 +01:00
Thomas Adam
70ecf17f85 Merge branch 'obsd-master' 2023-08-23 20:37:42 +01:00
nicm
71d453f169 Add -c to run-shell to set working directory, from someone in GitHub
issue 3661.
2023-08-23 08:40:25 +00:00
Nicholas Marriott
071849f82f Improve logging of SIXEL parsing errors. 2023-08-23 09:30:20 +01:00
nicm
52084b2948 Log what input_dcs_dispatch does with the input data. 2023-08-23 08:30:07 +00:00
Nicholas Marriott
dfbc6b1888 Merge SIXEL branch.
Squashed commit of the following:

commit 6ebc3feb4671d9b25b3db99d3c16b2323b8e3d02
Author: topcat001 <anindya49@hotmail.com>
Date:   Sun Aug 20 16:09:51 2023 -0700

    Remove redundant {}.

commit 6f013fce39602c259a5be2d690d548c73e51cccc
Author: topcat001 <anindya49@hotmail.com>
Date:   Sun Aug 20 16:02:15 2023 -0700

    Revert "Do not defer redraw if it is just the status line (will need to do more here I"

    This reverts commit 0a15bbf3f1972dc84c5c84d5128024c1bc4c0074.

commit e6322b4196d73c975ba2e73633e6de9c46779059
Author: topcat001 <anindya49@hotmail.com>
Date:   Sun Aug 20 15:46:59 2023 -0700

    Fix placeholder label and clean up.

commit 5896ac52a1f72056a75480b3e1ada328f239df9b
Merge: ad982330 e3a8b843
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Fri Aug 18 17:00:03 2023 +0100

    Merge branch 'master' into sixel

commit ad98233066b72547aee7fa0c87838847ee7f1ece
Author: topcat001 <anindya49@hotmail.com>
Date:   Tue Aug 15 13:57:08 2023 -0700

    Better text placeholder.

commit 312d83252c27fc4d09d09d121bf7573336e3cdca
Merge: 14b8b524 3d93b0c5
Author: topcat001 <anindya49@hotmail.com>
Date:   Tue Aug 15 13:39:22 2023 -0700

    Merge remote-tracking branch 'origin/master' into sixel

commit 14b8b524523a7d5a4e42f7dfa346905c604c91e2
Merge: 4baf7642 fda39377
Author: topcat001 <anindya49@hotmail.com>
Date:   Sat Jul 22 17:29:10 2023 -0700

    Merge branch 'master' into sixel

commit 4baf76422fadb216bf27b47645b52da3379e7dea
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Wed Jun 21 07:43:53 2023 +0100

    Both files can go on one line.

commit 4c92acf6ff24dde37ad41cd168ea2d3bcefb8567
Author: topcat001 <anindya49@hotmail.com>
Date:   Sat Jun 17 17:53:01 2023 -0700

    Merge topcat001/tmux/sixel.

commit 6794facc82e98f8448c192913cf62fe6e10fde63
Merge: 7b85f5ad f41c536f
Author: topcat001 <anindya49@hotmail.com>
Date:   Sat Jun 17 17:21:02 2023 -0700

    Merge remote-tracking branch 'origin/master' into sixel

commit 7b85f5adf9a5094db580ca98e4d2231d8d5b5a4f
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Jun 8 12:55:03 2023 +0100

    Do not require passthrough for SIXEL.

commit a6ee55e0925cac35d011c188db2da0421fc09be1
Merge: 6da391f4 fe385b18
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Jun 8 12:19:55 2023 +0100

    Merge branch 'master' into sixel

commit 6da391f460414ed3dde23e5ab6ca3fe8e988ce51
Merge: 0d71e585 0eb5d254
Author: topcat001 <anindya49@hotmail.com>
Date:   Sat May 20 17:05:55 2023 -0700

    Merge branch 'master' into sixel

commit 0d71e5853ffe797f90b815ac3af25ac0ad92ab07
Merge: 64368a1a fbe6fe7f
Author: topcat001 <anindya49@hotmail.com>
Date:   Sat Apr 29 17:32:07 2023 -0700

    Merge branch 'master' into sixel

commit 64368a1a63f04fb877b57e4286c9a2e1efe966c9
Merge: c630a56a 22eb0334
Author: topcat001 <anindya49@hotmail.com>
Date:   Thu Mar 30 14:21:09 2023 -0700

    Merge branch 'master' into sixel

commit c630a56a621b9761eed558cbd566a36cb09adf8f
Merge: 34c96c4c aaa043a2
Author: topcat001 <anindya49@hotmail.com>
Date:   Thu Nov 10 18:53:01 2022 -0800

    Merge branch 'master' into sixel

commit 34c96c4c4a33f86b49c8a53dc48b2b817db24e95
Merge: 2a1e16a2 50f4e0fa
Author: topcat001 <anindya49@hotmail.com>
Date:   Sat Nov 5 18:05:36 2022 -0700

    Merge branch 'master' into sixel

commit 2a1e16a24dc75741c66f5d72fa5bf26b73507993
Merge: a82f14c7 d001a94d
Author: topcat001 <anindya49@hotmail.com>
Date:   Thu Oct 27 16:01:35 2022 -0700

    Merge branch 'master' into sixel

commit a82f14c7b23a239a2114c756ef73bba8609ebe33
Merge: 742c0634 f7b30ed3
Author: topcat001 <anindya49@hotmail.com>
Date:   Sun Aug 28 13:43:07 2022 -0700

    Merge branch 'master' into sixel

commit 742c0634734e6b2840762e58b0bf27626b5ac24b
Merge: 906c92a5 87b248f3
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Fri Apr 1 10:14:15 2022 +0100

    Merge branch 'master' into sixel

commit 906c92a5f458b8843e7abd1d6f419dc091f8063c
Merge: 6680a024 138ffc7c
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Wed Dec 8 10:37:33 2021 +0000

    Merge branch 'master' into sixel

commit 6680a024be5e173a27c10e9a0be6c9072576086d
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Oct 7 13:59:08 2021 +0100

    Fix build.

commit ebd2c585937f18045d334226d4a0cc788fe14353
Merge: 90dc0519 fed7b29c
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Oct 7 13:19:48 2021 +0100

    Merge branch 'master' into sixel

commit 90dc05191cbba8de6d9d77ee7f9726325abe844e
Merge: a282439f 4694afbe
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Feb 20 20:37:32 2020 +0000

    Merge branch 'master' into sixel

commit a282439fcb2f597927a5ba33d2c378c90eec8b42
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Jan 30 09:12:53 2020 +0000

    Add missing declarations.

commit 3a741aacd108538f99239c68bfa2cd416bf0eb46
Merge: 40ad0107 339832b9
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Jan 30 09:11:01 2020 +0000

    Merge branch 'sixel-passthrough' into sixel

commit 339832b92c298538f398754f6d3fc21d15d13326
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Jan 30 09:04:51 2020 +0000

    Bad merge.

commit 92ed9fc0b20440f2bc553757e6bfe3126fe84be4
Merge: 5bb07548 32be954b
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Jan 30 09:03:38 2020 +0000

    Merge branch 'master' into sixel-passthrough

commit 40ad01073d73a531b4e85b0138f78bf0b472b354
Merge: dd3c72f1 61b075a2
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Sun Jan 12 20:03:41 2020 +0000

    Merge branch 'master' into sixel

commit 5bb075487f5897d7402adb880e678043c0f7f3e0
Merge: 7c033a74 54efe337
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Wed Dec 18 20:24:42 2019 +0000

    Merge branch 'master' into sixel-passthrough

commit dd3c72f132c911b0ba61b56a56f46510704d3392
Merge: 1a0e5fe9 54efe337
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Wed Dec 18 20:24:26 2019 +0000

    Merge branch 'master' into sixel

commit 1a0e5fe933e89932f2f658936c52eb50644fbef4
Merge: cf071ffe 15d7e564
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Tue Dec 10 16:34:11 2019 +0000

    Merge branch 'master' into sixel

commit cf071ffecd5a0d33008fd0a8b66a22f6855c7a8d
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Mon Dec 9 15:41:56 2019 +0000

    Remove images when reflow happens.

commit 2006b7a5631787a7086c6bae364e62d0a0b5948a
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Dec 5 09:27:15 2019 +0000

    More invalidation of images.

commit b642eac4503cc89cde01103f7bacca57cc9c1a2b
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Dec 5 09:11:24 2019 +0000

    Redraw and scroll images and part of invalidating them.

commit 7566e37a461bf245bd2e54e1d522e919071e9c44
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Dec 5 08:51:24 2019 +0000

    Call sixel_scale with the right number of arguments.

commit 62c0280b23cf67fc43f691392a8eca5cd7ff0727
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Dec 5 08:48:58 2019 +0000

    Correctly remove when not visible.

commit 86c5098a887f2cd09b828e051ccf0fab21bf4f6a
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Dec 5 08:32:25 2019 +0000

    Add helpers to scroll image up and a flag to copy the colours.

commit 49f2f0a8f1e72389f4128aa38119ed124cdc31c5
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Dec 5 00:02:55 2019 +0000

    Store images, currently at most 10.

commit 3aebcc67099ccbc5964c744fc1435931c1a78583
Merge: 146ee3f6 92ecd611
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Wed Dec 4 19:27:16 2019 +0000

    Merge branch 'master' into sixel

commit 7c033a74e25957d333217cb71a7658b860583501
Merge: 0a15bbf3 92ecd611
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Wed Dec 4 12:41:09 2019 +0000

    Merge branch 'master' into sixel-passthrough

commit 146ee3f6f8ee2629c6a88b6900a71f3e6fd14e4d
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Sat Nov 30 09:47:53 2019 +0000

    Don't write image as text yet.

commit 0a15bbf3f1972dc84c5c84d5128024c1bc4c0074
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Sat Nov 30 09:15:35 2019 +0000

    Do not defer redraw if it is just the status line (will need to do more here I
    think).

commit a5b1e209417b7d3f5b0099642dd317c312f79377
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Nov 28 14:20:22 2019 +0000

    Add a flag to disable blocking while sending a SIXEL image (turned off when the
    buffer hits 0 size).

commit 968382aa6a4b9c71fbc221aa4f0e899f6a83a260
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Nov 28 12:35:18 2019 +0000

    Pass through SIXEL DCS sequences (treat similarly to the passthrough escape
    sequence) if it appears the terminal outside supports them.

commit b1904c9b8db514133d3372aac13b2ff0b2093cc3
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Sat Nov 30 09:17:18 2019 +0000

    Store SIXELs as a box for the moment.

commit 5d8dbcdf3d76d0e69b8f2d21eff48f819dcec199
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Sat Nov 30 09:15:35 2019 +0000

    Do not defer redraw if it is just the status line (will need to do more here I
    think).

commit 0c999a402ece7b40e6ae84547893421b52d508ff
Merge: 28961dd5 866b053f
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Fri Nov 29 18:54:09 2019 +0000

    Merge branch 'master' into sixel

commit 28961dd5a38dd5a7b703ed0e6625fa9a65556d35
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Nov 28 14:24:57 2019 +0000

    Add an image.

commit d2e3f3c1cca5410570c5392340d14e96ae7a354c
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Nov 28 14:20:22 2019 +0000

    Add a flag to disable blocking while sending a SIXEL image (turned off when the
    buffer hits 0 size).

commit e01df67ca106e57f5c689e75f313f8cda6f8b805
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Nov 28 13:21:40 2019 +0000

    Crop and scale images as needed when drawing them.

commit e24acc0b5c3ac19dcacebdea243dcc7784215ffa
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Nov 28 12:38:02 2019 +0000

    Simple SIXEL parse and modify API.

commit b34111b3da1e4b1769a976cd40486144f7b4f5a2
Author: Nicholas Marriott <nicholas.marriott@gmail.com>
Date:   Thu Nov 28 12:35:18 2019 +0000

    Pass through SIXEL DCS sequences (treat similarly to the passthrough escape
    sequence) if it appears the terminal outside supports them.
2023-08-22 08:43:35 +01:00
Thomas Adam
e3a8b8434c Merge branch 'obsd-master' 2023-08-17 18:01:09 +01:00
nicm
8636848e63 Add a session, pane and user mouse range types for the status line and
add format variables for mouse_status_line and mouse_status_range so
they can be associated with different commands in the key bindings.
GitHub issue 3652.
2023-08-17 14:10:28 +00:00
Thomas Adam
3d93b0c52e Merge branch 'obsd-master' 2023-08-15 12:01:09 +01:00
nicm
d9942c769e Add meta bindings for status line menus as well as the existing pane one
for terminals which steal the mouse menu button.
2023-08-15 09:51:48 +00:00
Thomas Adam
6a45e6c256 Merge branch 'obsd-master' 2023-08-15 10:01:09 +01:00
nicm
b770a429c6 Add an option menu-selected-style to configure the currently selected
menu item, from Alexis Hildebrandt.
2023-08-15 07:01:47 +00:00
Thomas Adam
11e69f6025 Merge branch 'obsd-master' 2023-08-11 20:01:09 +01:00
nicm
57837bbf67 Do not crash if in buffer mode and the last buffer is deleted using the
command.
2023-08-11 17:09:00 +00:00
Thomas Adam
4c60afde78 Merge branch 'obsd-master' 2023-08-08 12:01:10 +01:00
Thomas Adam
ed689cd54e Merge branch 'obsd-master' 2023-08-08 10:01:11 +01:00
nicm
7a44984069 Add flag to next-prompt/previous-prompt to go to command output instead,
from Magnus Gross.
2023-08-08 08:21:29 +00:00
nicm
dee72ed41f Add options and flags for menu styles similar to those existing for
popups, from Alexis Hildebrandt. GitHub issue 3650.
2023-08-08 08:08:47 +00:00
nicm
1071ef8fc5 Extend the menu drawing function to support custom characters and
styles, from Alexis Hildebrandt.
2023-08-08 07:41:04 +00:00
nicm
2b535bc173 Fix a couple of rounded border characters, from Alexis Hildebrandt. 2023-08-08 07:19:48 +00:00
Thomas Adam
b791f00bf1 Merge branch 'obsd-master' 2023-08-07 14:01:12 +01:00
Thomas Adam
3e82ad5340 Merge branch 'obsd-master' 2023-08-07 12:01:10 +01:00
nicm
7b1030293c Free title earlier, from Alexis Hildebrandt. 2023-08-07 10:52:00 +00:00
nicm
a5fd80bbc3 Trim can generate strings longer than the original if there are many #s,
so create a bigger buffer. Reported by Robert Morris.
2023-08-07 10:04:29 +00:00
Thomas Adam
fda3937734 Merge branch 'obsd-master' 2023-07-19 16:01:09 +01:00
nicm
b13c230749 Correct visited flag when the last window list is rebuilt by renumbering
windows, appears to fix hang reported by Mark Kelly.
2023-07-19 13:03:36 +00:00
Thomas Adam
715f39a53a Merge branch 'obsd-master' 2023-07-14 22:01:10 +01:00
nicm
2f74e811f1 Set extended keys flag again after reset, from Eric T Johnson. 2023-07-14 19:32:59 +00:00
Thomas Adam
828efc7bcf Merge branch 'obsd-master' 2023-07-13 18:01:10 +01:00
nicm
84936b832f Use 8 for underscore colour defaults instead of 0 which is less
confusing, and fix writing tge default colour. GitHub issue 3627.
2023-07-13 06:03:48 +00:00
Thomas Adam
c8494dff7b Merge branch 'obsd-master' 2023-07-11 20:01:10 +01:00
nicm
8fcc212e7a Remove Ns and Li and change Nm to Ic, suggested by jmc. 2023-07-11 16:09:09 +00:00
Thomas Adam
0e281530cb Merge branch 'obsd-master' 2023-07-11 10:01:10 +01:00
nicm
efded95ed7 Add descriptions of copy mode commands, from Michael Bianco. 2023-07-11 07:34:23 +00:00
Thomas Adam
18870913c5 Merge branch 'obsd-master' 2023-07-10 14:01:12 +01:00
nicm
63b7282377 It should no longer be necessary to ignore SIGCHLD because it is now
blocked around daemon(), and doing so causes trouble with newer libevent
(it cannot restore the original handler). Reported by Azat Khuzhin in
GitHub issue 3626.
2023-07-10 12:00:08 +00:00
Thomas Adam
269dab4b3e Merge branch 'obsd-master' 2023-07-10 12:01:12 +01:00
nicm
4ece43a029 Loop around waitpid in client, from Azat Khuzhin. 2023-07-10 09:35:46 +00:00
nicm
8b3e2eab5a Use a stack for last panes line windows, from Thomas Bertschinger in
GitHub issue 3588.
2023-07-10 09:24:53 +00:00
Thomas Adam
e4c4ceb286 Merge branch 'obsd-master' 2023-07-10 02:01:11 +01:00
nicm
b7e22d00b4 Call closefrom after removing signals because newer libevent doesn't
like its signal fd being closed Azat Khuzhin.
2023-07-09 22:54:52 +00:00
Thomas Adam
1a11c972ae Merge branch 'obsd-master' 2023-07-03 20:01:12 +01:00
nicm
43b841f188 Add support for marking lines with a shell prompt based on the OSC 133
extension, from Munif Tanjim in GitHub issue 3596.
2023-07-03 16:47:43 +00:00
Thomas Adam
f9b0460840 Merge branch 'obsd-master' 2023-07-03 14:01:10 +01:00
Thomas Adam
659d876cd5 Merge branch 'obsd-master' 2023-07-03 12:01:09 +01:00
nicm
ac43186dff Do not risk writing over the end of the buffer when it ends in #
(because strchr \0 will be non-NULL), reported by Robert Morris in
GitHub issue 3610.
2023-07-03 10:48:26 +00:00
nicm
e79fb214f8 Another warning fix for GCC from Thomas Klausner. 2023-07-03 08:37:14 +00:00
Thomas Adam
9cf58d1a52 Merge branch 'obsd-master' 2023-07-01 02:01:10 +01:00
nicm
a2a02fd7d7 Change a few types to fix warnings, from Thomas Klausner. 2023-06-30 21:55:08 +00:00
Thomas Adam
237ee6f231 Merge branch 'obsd-master' 2023-06-30 16:01:10 +01:00
nicm
4e57894e85 Get rid of some warnings with GCC 10, from Thomas Klausner. 2023-06-30 13:19:32 +00:00
Nicholas Marriott
8c9fbbf4f3 Add libterminfo for NetBSD, from Thomas Klausner. 2023-06-29 15:31:32 +01:00
Thomas Adam
3f3d61bd58 Merge branch 'obsd-master' 2023-06-26 12:01:09 +01:00
Thomas Adam
80d4f4afc6 Merge branch 'obsd-master' 2023-06-26 10:01:10 +01:00
nicm
2546216019 When exiting alternate screen, there is no need to reflow when going
back to old size since the contents will be overwritten. GitHub issue
3510.
2023-06-26 08:14:19 +00:00
nicm
ff8882a24f Add "us" to styles for underscore colour, GitHub issue 3589. 2023-06-26 07:17:40 +00:00
Thomas Adam
ffe2410639 Merge branch 'obsd-master' 2023-06-25 20:01:09 +01:00
nicm
9e14c1f88d SGR 0 should not end hyperlink, reported by Lucas Trzesniewski. 2023-06-25 15:53:07 +00:00
Thomas Adam
29a5dfc7c0 Merge branch 'obsd-master' 2023-06-21 08:01:08 +01:00
nicm
645bf8b3ab Check fdopen return value, from Christian Menges. 2023-06-21 06:28:18 +00:00
Thomas Adam
f41c536ff3 Merge branch 'obsd-master' 2023-06-08 14:01:09 +01:00
nicm
bdd05bdbd3 Fix mismatch between function prototype and definition, from Anindya
Mukherjee.
2023-06-08 11:17:28 +00:00
Nicholas Marriott
fe385b180f Try utf8proc with pkg-config, from Alex Wu. 2023-06-08 09:10:43 +01:00
Thomas Adam
0eb5d25453 Merge branch 'obsd-master' 2023-05-19 10:01:09 +01:00
nicm
1d98394b41 Add format for server_sessions, from Magnus Gross. 2023-05-19 07:46:34 +00:00
Thomas Adam
149d9cc851 Merge branch 'obsd-master' 2023-05-08 12:01:09 +01:00
tb
204d8f31d7 Reorder struct grid_cell_entry
On aarch64 with llvm 15, the new -Wunaligned-access emits noise on every
one of tmux's source files. This avoids this warning by moving a u_char
to the end of the struct. This does not change the size of the struct on
any architecture.

ok nicm
2023-05-08 10:03:39 +00:00
Thomas Adam
fbe6fe7f55 Merge branch 'obsd-master' 2023-04-28 12:52:21 +01:00
Nicholas Marriott
168eab11a7 Cast both strings for tparm. 2023-04-28 07:23:53 +01:00
nicm
41b318ac7c Add options to change the confirm key and default behaviour of
confirm-before. From Elias Assaf in GitHub issue 3548; prompted by an
earlier change from Yutaro Yoshii in GitHub issue 3496.
2023-04-28 06:12:27 +00:00
nicm
bf636d9575 Do not fatal if tparm fails, instead just log it (not working sequences
are better than exiting).
2023-04-28 05:59:35 +00:00
Nicholas Marriott
39d41d0810 Use ncurses' new tparm_s function (added in 6.4-20230424) instead of tparm so
it does not object to string arguments in capabilities it doesn't already know.
2023-04-28 06:44:40 +01:00
Thomas Adam
9d8131c190 Merge branch 'obsd-master' 2023-04-27 19:16:08 +01:00
Nicholas Marriott
0ff991b25f Set default lock command to vlock on Linux if present at build time, from Josh
Boyer in GitHub issue 3527.
2023-04-25 17:23:32 +01:00
Nicholas Marriott
15c70e562c Include NCURSES_VERSION_PATCH in the log. 2023-04-25 16:48:49 +01:00
nicm
8f34504736 Tidy tparm wrapper functions to have more obvious names and check tparm
return value.
2023-04-25 09:31:50 +00:00
nicm
551e0c36d9 Invalidate cached tty state after changing features since they may
change what the terminal can do and need mouse sequences or similar to
be sent again, GitHub issue 3513.
2023-04-25 09:24:44 +00:00
nicm
48eba4c195 Ignore the user keys range when checking if a key is Unicode. 2023-04-17 18:22:24 +00:00
nicm
9f605178c3 It seems silly to use progname for version, just always say tmux. 2023-04-17 18:00:19 +00:00
nicm
bcafe51378 Make the check if printing is allowed the same as writing which is less
confusing.
2023-04-17 17:58:35 +00:00
nicm
280fe77edd Discard mouse sequences that have the right form but actually are
invalid (for example have column zero rather than one).
2023-04-17 17:57:35 +00:00
Nicholas Marriott
b9524f5b72 Add support for spawning panes in separate cgroups with systemd and a configure
flag to disable. From Eric T Johnson yut23 AT gvljohnsons DOT com in GitHub
issue 3514.
2023-04-03 08:54:06 +01:00
nicm
a2018b2c3f Clarify text for new -A slightly, GitHub issue 3508. 2023-04-03 07:39:37 +00:00
nicm
c21af7e446 Add a format to show if there are unseen changes while in a mode, from
Dan Aloni in GitHub issue 3498.
2023-03-27 08:47:57 +00:00
nicm
d73078838d For passthrough, don't write to clients attached to different sessions,
based on a fix from Sergei Grechanik.
2023-03-27 08:31:32 +00:00
Thomas Adam
22eb0334c3 Merge branch 'obsd-master' 2023-03-15 22:01:09 +00:00
nicm
a9ac614691 Do not leak screen in popups, GitHub issue 3492. 2023-03-15 19:23:22 +00:00
Thomas Adam
1d0f68dee9 Merge branch 'obsd-master' 2023-03-15 10:01:10 +00:00
nicm
ac4bb89d43 Fix command prompt not to always append argument but only if there has
actually been expansion. GitHub issue 3493.
2023-03-15 08:15:39 +00:00
Thomas Adam
b55f34029a Merge branch 'obsd-master' 2023-02-10 16:01:10 +00:00
nicm
907f58cc3c Fix cursor position after zero width space, GitHub issue 3469. 2023-02-10 14:01:43 +00:00
Thomas Adam
023b0f76c3 Merge branch 'obsd-master' 2023-02-07 14:01:11 +00:00
Thomas Adam
ddaeebc213 Merge branch 'obsd-master' 2023-02-07 12:01:13 +00:00
nicm
1262e685b8 Remove old buffer when renaming rather than complaining, GitHub issue
3467 from Jean-Philippe Paradis.
2023-02-07 10:56:04 +00:00
nicm
0bd78b42c0 Add an L modifier like P, W, S to loop over clients. Also fix some long
lines in tmux(1).
2023-02-07 10:21:01 +00:00
Thomas Adam
4a0126f7fb Merge branch 'obsd-master' 2023-02-06 12:01:12 +00:00
nicm
7acc8d703d Add -f to list-clients like the other list commands, from Andy Walker in
GitHub issue 3449.
2023-02-06 09:20:30 +00:00
Thomas Adam
77118f3a9f portable: remove vis.h
This is included portably across different systems.
2023-02-06 01:55:02 +00:00
Thomas Adam
e25926d3c4 Merge branch 'obsd-master' 2023-02-06 00:01:11 +00:00
nicm
0cb75f1332 Do not allow multiple line separators in a row. 2023-02-05 21:26:48 +00:00
nicm
93b1b78150 Extend display-message to work for control clients. GitHub issue 3449. 2023-02-05 21:15:32 +00:00
Thomas Adam
493922dc4b Merge branch 'obsd-master' 2023-02-02 12:01:11 +00:00
nicm
f10854cfc5 Add a missing error message which causes an invalid layout name to crash. 2023-02-02 09:24:59 +00:00
nicm
993e7a937f Tweak note for D key binding, from Clark Wang. 2023-02-02 09:06:44 +00:00
Thomas Adam
f5af3cfb21 Merge branch 'obsd-master' 2023-01-23 12:01:11 +00:00
nicm
e7e112fbd0 Too many \s in example, GitHub issue 3445. 2023-01-23 09:33:51 +00:00
Thomas Adam
c42087c789 Merge branch 'obsd-master' 2023-01-21 00:01:11 +00:00
nicm
3aa458ea63 Add a flag to display-menu to select the manu item chosen first, GitHub
issue 3442.
2023-01-20 21:36:00 +00:00
Thomas Adam
c4a6f403bb Merge branch 'obsd-master' 2023-01-17 12:01:09 +00:00
nicm
9789ea3fb4 Support -1 without -N for list-keys. 2023-01-17 10:40:51 +00:00
Thomas Adam
f416ae1c12 Merge branch 'obsd-master' 2023-01-17 10:01:09 +00:00
nicm
d578cf8d3f Update palette when moving a pane, GitHub issue 3437. 2023-01-17 06:50:55 +00:00
Thomas Adam
789cb91f31 Merge branch 'obsd-master' 2023-01-16 14:01:10 +00:00
nicm
eb1f8d70a7 Mark keys sent by command and skip paste handling for them. 2023-01-16 11:26:14 +00:00
Thomas Adam
42895efac3 Merge branch 'obsd-master' 2023-01-12 22:01:09 +00:00
nicm
483cc77c1c Have tmux recognise pasted texts wrapped in bracket paste sequences,
rather than only forwarding them to the program inside. From Andrew
Onyshchuk in GitHub issue 3431.
2023-01-12 18:49:11 +00:00
Thomas Adam
9b1ea8b16d Merge branch 'obsd-master' 2023-01-09 16:01:11 +00:00
nicm
b41892622d Fix behaviour with \007 (used the wrong tree for last change). 2023-01-09 14:12:41 +00:00
Thomas Adam
9051220243 Merge branch 'obsd-master' 2023-01-09 10:01:09 +00:00
nicm
c0031f8b85 Accept \007 as terminator to OSC 10 or 11. 2023-01-09 07:57:14 +00:00
Thomas Adam
c1a30ed995 Merge branch 'obsd-master' 2023-01-09 02:01:10 +00:00
nicm
565de3f54b Fix parsing of optional arguments so that and accept a - starting an
argument.
2023-01-08 23:34:46 +00:00
Thomas Adam
153ae758c9 portable: fixup merge with utf8.c 2023-01-08 23:27:54 +00:00
Thomas Adam
5086377f30 Merge branch 'obsd-master' 2023-01-08 23:26:09 +00:00
nicm
7c0789d2d2 Have client return 1 if process is interrupted to an input pane. 2023-01-08 22:17:04 +00:00
Nicholas Marriott
2a32565e0c Restore code to handle wcwidth failure so that unknown codepoints still
do the most likely right thing. GitHub issue 3427, patch based on an
diff from Jesse Luehrs in GitHub issue 3003.
2023-01-08 22:15:38 +00:00
nicm
7ced0a03d2 Restore code to handle wcwidth failure so that unknown codepoints still
do the most likely right thing. GitHub issue 3427, patch based on an
diff from Jesse Luehrs in GitHub issue 3003.
2023-01-08 22:15:30 +00:00
nicm
cb51942669 Quotes are now required in select-layout example. 2023-01-08 21:00:01 +00:00
Nicholas Marriott
093fb53773 Missing #endif. 2023-01-06 11:38:41 +00:00
Thomas Adam
21e00e4635 Merge branch 'obsd-master' 2023-01-06 09:02:00 +00:00
nicm
09afc6c8ee If a pane is killed, cancel reading from the file. GitHub issue 3422. 2023-01-06 07:09:27 +00:00
nicm
a41a927441 Query the client terminal for foreground and background colours and if
OSC 10 or 11 is received but no colour has been set inside tmux, return
the colour from the first attached client (probably most people will
have all light or or all dark terminals).
2023-01-03 11:43:24 +00:00
jmc
3fe01ff09c spelling fixes; from paul tagliamonte
amendments to his diff are noted on tech
2022-12-26 19:16:03 +00:00
kn
b5ab4d2c13 Denote multiple arguments with 'arg ...' not 'args'
A few programs used the plural in their synopsis which doesn't read as
clear as the obvious triple-dot notation.

mdoc(7) .Ar defaults to "file ..." if no arguments are given and consistent
use of 'arg ...' matches that behaviour.

Cleanup a few markups of the same argument so the text keeps reading
naturally;  omit unhelpful parts like 'if optional arguments are given,
they are passed along' for tools like time(1) and timeout(1) that obviously
execute commands with whatever arguments where given -- just like doas(1)
which doesn't mention arguments in its DESCRIPTION in the first place.

For expr(1) the difference between 'expressions' and 'expression ...' is
crucial, as arguments must be passed as individual words.

Feedback millert jmc schwarze deraadt
OK jmc
2022-12-22 19:53:23 +00:00
nicm
4d79d463ef Allow send-keys without a client again, reported by Stefan Hagen. 2022-12-19 07:30:10 +00:00
nicm
7cb48fc40b Do not escape tabs in output (iTerm2 needs them). GitHub issue 3414. 2022-12-16 08:22:05 +00:00
nicm
8bd17bff49 Make U+FE0F VARIATION SELECTOR-16 change the width from 1 to 2. GitHub
issue 3409.
2022-12-16 08:19:58 +00:00
nicm
3b3f42053a Add send-keys -K to handle keys directly as if typed (so look up in key
table). GitHub issue 3361.
2022-12-16 08:13:40 +00:00
Nicholas Marriott
70ff8cfe1e No vis.h in portable. 2022-12-07 12:30:36 +00:00
Thomas Adam
6249a4b866 Merge branch 'obsd-master' 2022-12-07 12:01:09 +00:00
nicm
7e497c7f23 Process escape sequences in show-buffer, GitHub issue 3401. 2022-12-07 09:44:44 +00:00
Thomas Adam
1536b7e206 Merge branch 'obsd-master' 2022-11-11 10:01:09 +00:00
Nicholas Marriott
e46d0632a5 Add key regression tests from Aaron Jensen. 2022-11-11 08:47:55 +00:00
nicm
20da167377 Tweak previous to set and log the feature instead of just setting the
flag.
2022-11-11 08:44:11 +00:00
nicm
fe475bd856 Parse primary device attributes as well as secondary and add a SIXEL
flag (not used yet), from Anindya Mukherjee.
2022-11-11 08:37:55 +00:00
nicm
079f48e8a6 Document alternative delimiters for substitution, from Jim Wisniewski. 2022-11-11 08:27:17 +00:00
Thomas Adam
aaa043a20f Merge branch 'obsd-master' 2022-11-11 02:01:10 +00:00
jmc
48f41e4a41 - sort options; from josiah frentsos
ok nicm

- add -N to SYNOPSIS

- sort usage()
2022-11-10 22:58:39 +00:00
Thomas Adam
6fb80527f3 Merge branch 'obsd-master' 2022-11-08 12:01:11 +00:00
nicm
f86eba2129 Fix C-S-Tab without extended keys, from Aaron Jensen. 2022-11-08 10:04:31 +00:00
Thomas Adam
50f4e0fac9 Merge branch 'obsd-master' 2022-11-04 10:01:10 +00:00
nicm
77c135349a Unescape the string for the literal operator (l:) so special characters
work.
2022-11-04 08:03:23 +00:00
Thomas Adam
c449512be4 Merge branch 'obsd-master' 2022-11-03 10:01:11 +00:00
nicm
17290b9121 If there are no buffers, reset mode as soon as any key pressed. Fixes
crash reported by Gaoyang Zhang in GitHub issue 3373.
2022-11-03 08:41:53 +00:00
nicm
3be369522b Add a -l flag to display-message to disable format expansion, from Aaron
Jensen. GitHub issue 3372.
2022-11-03 08:33:57 +00:00
Thomas Adam
dbfbd8a195 Merge branch 'obsd-master' 2022-11-02 08:01:11 +00:00
nicm
9614f51560 Instead of always setting the extended flag, set it only when searching.
Allows send-keys to work. From Aaron Jensen.
2022-11-02 07:36:07 +00:00
Thomas Adam
36896f6dd0 Merge branch 'obsd-master' 2022-11-01 12:01:10 +00:00
nicm
2d08235987 Add modified Tab key sequences, from Aaron Jensen, GitHub issue 3368. 2022-11-01 09:54:13 +00:00
nicm
2291045116 Use active pane in target window not current window for +/-. GitHub
issue 3370.
2022-11-01 09:46:14 +00:00
Thomas Adam
9dd1f442c5 Merge branch 'obsd-master' 2022-10-28 16:01:10 +01:00
nicm
8edece2cdb Add paste-buffer-deleted notification and fix name of paste-buffer-changed. 2022-10-28 13:00:02 +00:00
Thomas Adam
d001a94d7b Merge branch 'obsd-master' 2022-10-25 22:01:10 +01:00
nicm
c2580cfe24 Initialize context before testing it. 2022-10-25 17:53:31 +00:00
Thomas Adam
dafd6f462f Merge branch 'obsd-master' 2022-10-25 12:01:10 +01:00
nicm
2111142cf1 Fix a memory leak, from Japin Li in GitHub issue 3358. 2022-10-25 09:12:05 +00:00
nicm
0fc961b22e Do not fire redraw callback if NULL. 2022-10-25 09:04:49 +00:00
Nicholas Marriott
5ce34add77 Do not attempt to connect to the socket as a client if systemd is active, from
Julien Moutinho in GitHub issue 3345.
2022-10-18 15:58:06 +01:00
Thomas Adam
934f357149 Merge branch 'obsd-master' 2022-10-17 14:01:10 +01:00
nicm
ff2766b024 Preserve marked pane when renumbering windows. 2022-10-17 10:59:42 +00:00
Thomas Adam
9ef854f5a9 Merge branch 'obsd-master' 2022-09-28 12:01:09 +01:00
nicm
a10452be2d Add scroll-top and scroll-bottom commands to scroll so cursor is at top
or bottom. From Anindya Mukherjee, GitHub issue 3334.
2022-09-28 07:59:50 +00:00
nicm
9cc8e40aa0 Add a -T flag to capture-pane to stop at the last used cell instead of
the full width. Restore the previous behaviour by making it default to
off unless -J is used (the only time it matters). Fixes mosh unit tests;
GitHub issue 3339.
2022-09-28 07:55:29 +00:00
Thomas Adam
f49f92737f Merge branch 'obsd-master' 2022-09-22 17:10:38 +01:00
Nicholas Marriott
19344ec890 Add headers and fix type, from Marvin Schmidt. GitHub issue 3332. 2022-09-19 07:03:17 +01:00
nicm
a2cc601c3d Don't use options from pane if pane is NULL. 2022-09-12 12:02:17 +00:00
nicm
9ab1ba36cd Use correct option name. 2022-09-10 17:01:33 +00:00
nicm
f03c3ca6c3 Add message-line option to control where message and prompt go, from
Varun Kumar E in GitHub issue 3324.
2022-09-09 11:02:23 +00:00
Nicholas Marriott
0a0ded3268 Regress typos. 2022-09-07 07:28:26 +01:00
Thomas Adam
6da520c5a1 Merge branch 'obsd-master' 2022-08-31 12:01:10 +01:00
nicm
68dc9af9ac Fix window size report, from Vincent Bernat. 2022-08-31 08:07:05 +00:00
Thomas Adam
f7b30ed3d4 Merge branch 'obsd-master' 2022-08-24 10:01:13 +01:00
nicm
e867528209 Check for NULL returns from bufferevent_new. 2022-08-24 07:22:30 +00:00
Thomas Adam
038dfb27a8 Merge branch 'obsd-master' 2022-08-23 12:01:10 +01:00
nicm
416c27c995 Add scroll-middle copy mode command to make cursor line in the middle,
from Varun Kumar E in GitHub issue 3307.
2022-08-23 08:14:19 +00:00
Nicholas Marriott
19344efa78 Fix fallback implementaion of getpeereid, from Pino Toscano. 2022-08-22 08:21:42 +01:00
Thomas Adam
9c34aad21c Merge branch 'obsd-master' 2022-08-15 13:54:47 +01:00
nicm
7c2dcd7238 Notify when a paste buffer is deleted, GitHub issue 3302 from George
Nachman.
2022-08-15 09:10:34 +00:00
nicm
03149bf7f6 Add a Nobr terminfo capability to tell tmux the terminal does not use
bright colours for bold (makes a difference to how tmux applies palette
differences). From Damien Tardy-Panis in GitHub issue 3301.
2022-08-15 08:54:03 +00:00
nicm
497021d0db Add some const, from Markus F X J Oberhumer. 2022-08-15 08:41:13 +00:00
nicm
cfdc5b62ad Don't stop at first match when updating environment. 2022-08-15 08:37:03 +00:00
Thomas Adam
9b08e5139b Merge branch 'obsd-master' 2022-08-11 12:01:10 +01:00
nicm
e139f977b1 vi(1) Home/End bindings, from Markus F X J Oberhumer. 2022-08-11 09:11:26 +00:00
Thomas Adam
9abf5d9fe5 Merge branch 'obsd-master' 2022-08-10 18:01:11 +01:00
nicm
273577ba0a Fix check of home directory (&& not ||), from Markus F X J Oberhumer,
GitHub issue 3297.
2022-08-10 14:03:59 +00:00
Thomas Adam
e15058e60f Merge branch 'obsd-master' 2022-08-04 16:01:09 +01:00
nicm
de5cd54124 Change g and G to go to top and bottom of menu, GitHub issue 3286. 2022-08-04 12:06:09 +00:00
Thomas Adam
c6cf09450a Merge branch 'obsd-master' 2022-08-03 16:01:11 +01:00
nicm
c6e7568471 Do not crash when searching for .* with extremely long lines. Reported
by Torbjorn Lonnemark, GitHub issue 3272.
2022-08-03 13:27:48 +00:00
Thomas Adam
7b8ececd8d Merge branch 'obsd-master' 2022-08-02 14:01:09 +01:00
nicm
42ba6c1b22 Add a third state "all" to allow-passthrough to work even in invisible
panes, from Sergei Grechanik in GitHub issue 3274.
2022-08-02 11:09:26 +00:00
Thomas Adam
9a2fdf8fd4 Merge branch 'obsd-master' 2022-08-02 12:01:09 +01:00
Nicholas Marriott
00812c9053 Check for $YACC, from Wei Shih in GitHub issue 3267. 2022-08-02 11:52:09 +01:00
nicm
33c59100ae Fix validation of missing percentage arguments. 2022-08-02 09:23:34 +00:00
nicm
36d904011a -u is no longer equivalent to -TUTF-8 so don't say it is. 2022-08-02 08:57:01 +00:00
Thomas Adam
9d9445a48e Merge branch 'obsd-master' 2022-07-22 10:01:10 +01:00
nicm
a8da24771c Clear marks when the search string changes. From Anindya Mukherjee,
GitHub issue 3255.
2022-07-22 07:14:07 +00:00
Thomas Adam
ab1d18d00f Merge branch 'obsd-master' 2022-07-19 10:01:08 +01:00
nicm
ee431d482a Do not ignore the "off" flag when checking if a pane should be stopped,
GitHub issue 3250.
2022-07-19 07:10:13 +00:00
Nicholas Marriott
e06c09889c Add permissions for workflow, GitHub issue 3202. 2022-07-19 07:54:11 +01:00
nicm
86dfbda0e4 Process modifiers as bits rather than using a switch, from Koichi Murase. 2022-07-19 06:51:31 +00:00
Nicholas Marriott
697cebb4c1 Include curses properly for hyperlinks ifdef, from chrysn at fsfe dot org. 2022-07-19 07:48:48 +01:00
nicm
3c65475561 Fix memory leak, from Gabriel Souza Franco. 2022-07-19 06:46:57 +00:00
Thomas Adam
dc6bc0e95a Merge branch 'obsd-master' 2022-07-06 12:01:09 +01:00
Thomas Adam
b130e951cc Merge branch 'obsd-master' 2022-07-06 10:01:10 +01:00
Nicholas Marriott
9e19f132f2 Errors are now displayed on attach so use control mode to test
instead.
2022-07-06 09:54:53 +01:00
nicm
1afe22086f Show config errors on attach if they were not shown when the session
was created.
2022-07-06 08:40:52 +00:00
Nicholas Marriott
8e8b9865d1 Add hyperlink test, from Jeff Chiang. 2022-07-06 09:33:30 +01:00
nicm
a39827a85c Remove debugging code. 2022-07-06 08:32:28 +00:00
nicm
9e03df5500 Defer reading from control client until the command line command has
completed.
2022-07-06 08:31:59 +00:00
nicm
dd602eaa61 Mention whether time is creation/activity for sort orders. 2022-07-06 07:51:37 +00:00
nicm
d0d2c39dec Support hyperlinks with capture-pane -e and add a mouse_hyperlink
format, GitHub issue 3247 from Jeff Chiang.
2022-07-06 07:36:36 +00:00
Thomas Adam
57fec74966 Merge branch 'obsd-master' 2022-07-04 12:01:10 +01:00
nicm
9360e0ef32 Sort panes by index not by ID, GitHub issue 3249. 2022-07-04 08:39:45 +00:00
Nicholas Marriott
f08c019d41 Do not set Hls for hyperlinks on ncurses older than 5.9 (for example macOS). 2022-06-30 16:46:26 +01:00
Thomas Adam
c3af8f6b16 hyperlinks: remove vis.h
Not used on Linux.
2022-06-30 16:44:43 +01:00
Thomas Adam
01c4919f5f Merge branch 'obsd-master' 2022-06-30 16:37:18 +01:00
nicm
cdacc12ce3 Add support for OSC 8 hyperlinks (a VTE extension now supported by other
terminals such as iTerm2). Originally written by me then extended and
completed by first Will Noble and later Jeff Chiang. GitHub issues 911,
2621, 2890, 3240.
2022-06-30 09:55:53 +00:00
Thomas Adam
d8c527a5f9 Merge branch 'obsd-master' 2022-06-27 12:01:09 +01:00
nicm
b22edcf3a5 Tweak previous - find end of style correctly. 2022-06-27 09:16:54 +00:00
nicm
786cff8db9 Do not expand single character format aliases inside #[] since they
interfere with colours. GitHub issue 3239 from Magnus Gross.
2022-06-27 09:14:49 +00:00
Thomas Adam
b63afaea61 Merge branch 'obsd-master' 2022-06-21 12:01:09 +01:00
nicm
9c89f7c2af Store time lines are scrolled into history and display in copy mode. 2022-06-21 09:30:01 +00:00
Thomas Adam
d46870ede5 Merge branch 'obsd-master' 2022-06-20 12:01:09 +01:00
nicm
a888ce9963 Do not display configuration file errors in a pane when in control mode,
instead report them with a %config-error notification. GitHub issue 3193.
2022-06-20 07:59:37 +00:00
Thomas Adam
8ff3091d16 Merge branch 'obsd-master' 2022-06-17 10:01:10 +01:00
nicm
d9f84854ac Check cursor options when a pane is created, not just when they are changed. 2022-06-17 07:28:05 +00:00
Thomas Adam
89fe2680a9 Merge branch 'obsd-master' 2022-06-16 16:01:08 +01:00
nicm
7cee982f90 Keep cursor on selected item on menu (useful for blind people), GitHub
issue 3225.
2022-06-16 13:27:39 +00:00
Nicholas Marriott
42358cc521 Typos from Bastian Venthur. 2022-06-15 08:01:50 +01:00
Thomas Adam
06869ff22f Merge branch 'obsd-master' 2022-06-14 10:01:08 +01:00
nicm
616bde08ac kf* terminfo capabilities are poorly defined and rxvt uses them in a
different way from xterm, so add a feature flag for rxvt to make tmux
ignore the capabilities and instead rely on its builtin definitions.
2022-06-14 07:29:00 +00:00
Thomas Adam
6d0828b81c Merge branch 'obsd-master' 2022-06-11 20:01:09 +01:00
nicm
42ddf02ffc Fix size of flags output buffer. 2022-06-11 16:59:33 +00:00
Thomas Adam
56390e0a39 Merge branch 'obsd-master' 2022-06-10 16:01:11 +01:00
nicm
18a5835aff Ignore OSC if the first argument is not properly terminated. 2022-06-10 11:55:30 +00:00
Nicholas Marriott
67960dcc9a Merge tag '3.3a'
3.3a
2022-06-09 13:07:18 +01:00
Nicholas Marriott
0b355ae811 3.3a. 2022-06-09 12:30:50 +01:00
Nicholas Marriott
6a9bb2a622 Remove extra definition of getpeereid. From Eric N Vander Weele in GitHub issue
3209.
2022-06-09 12:28:38 +01:00
nicm
988e59cf3e Do not attempt to use client in config file (it will be NULL), GitHub
issue 3206.
2022-06-09 12:28:34 +01:00
nicm
30e06e9d85 Do not unintentionally turn off all mouse mode when button is also present. 2022-06-09 12:28:22 +01:00
Thomas Adam
810daefdd1 Merge branch 'obsd-master' 2022-06-09 12:01:09 +01:00
nicm
ccc9dc3bb4 If an application gives the first parameter to OSC 52, validate and pass
on to outside terminal. GitHub issue 3192.
2022-06-09 09:12:55 +00:00
Thomas Adam
be2eb57d62 Merge branch 'obsd-master' 2022-06-07 14:01:09 +01:00
nicm
c07d582e24 Expand arguments to some commands where it makes sense, GitHub issue
3204 from Anindya Mukherjee.
2022-06-07 10:02:19 +00:00
Thomas Adam
afb3a5fe71 Merge branch 'obsd-master' 2022-06-04 10:01:09 +01:00
nicm
020c403dff When picking a buffer because one isn't specified by the user, ignore
named buffers. GitHub issue 3212 from David le Blanc.
2022-06-04 07:42:07 +00:00
Thomas Adam
e77e11ec6b Merge branch 'obsd-master' 2022-06-03 12:01:09 +01:00
nicm
3edda3c5e7 Do not unintentionally turn off all mouse mode when button is also present. 2022-06-03 08:09:16 +00:00
Thomas Adam
1184dc08d4 Merge branch 'obsd-master' 2022-06-03 00:01:08 +01:00
nicm
18838fbc87 Do not attempt to use client in config file (it will be NULL), GitHub
issue 3206.
2022-06-02 21:19:32 +00:00
Nicholas Marriott
be2617036f Remove extra definition of getpeereid. From Eric N Vander Weele in GitHub issue
3209.
2022-06-02 21:45:53 +01:00
nicm
0f6227f46b When deleting or renaming a buffer and a buffer name is specified,
complain if the buffer doesn't exist instead of silently deleting or
renaming the most recent buffer. GitHub issue 3205.
2022-06-02 20:41:21 +00:00
Thomas Adam
c1ac007576 Merge branch 'obsd-master' 2022-06-01 18:01:08 +01:00
nicm
201a8d8e7e If escape-time is 0, force to 1 instead - not waiting at all is asking
for problems on some platforms.
2022-06-01 15:43:22 +00:00
Nicholas Marriott
b566cd57bf Now back to 3.4. 2022-06-01 08:50:54 +01:00
Nicholas Marriott
87fe00e8b4 Update CHANGES. 2022-06-01 08:37:14 +01:00
Nicholas Marriott
ced83792b1 Set version to 3.3. 2022-06-01 08:28:32 +01:00
Thomas Adam
42f6d11a6b Merge branch 'obsd-master' 2022-05-31 20:01:10 +01:00
nicm
74fb959f6d Add a missing space. 2022-05-31 16:13:43 +00:00
Thomas Adam
9daaf01730 Merge branch 'obsd-master' 2022-05-31 14:01:09 +01:00
nicm
86a184b288 Trim menu item text correctly, GitHub issue 3197. 2022-05-31 10:22:42 +00:00
Thomas Adam
af596c0828 Merge branch 'obsd-master' 2022-05-30 16:28:27 +01:00
nicm
58c8ea1209 Remove duplicates from completion list, GitHub issue 3178. 2022-05-30 13:07:46 +00:00
nicm
2f2bb82f5f Add pane_start_path to match start_command. 2022-05-30 13:07:06 +00:00
nicm
6a5d210e55 Set PWD so shells have a hint about the real path (this was done before
but lost in a merge). GitHub issue 3186.
2022-05-30 13:06:41 +00:00
nicm
384f0ee269 Fix property name from Sergei Dyshel, and a typo from imcusg at gmail
dot com.
2022-05-30 13:06:10 +00:00
nicm
006a529db1 Check if args_strtonum argument is NULL or not a string, from Anindya
Mukherjee.
2022-05-30 13:04:24 +00:00
nicm
af1496b300 Do not allow pipe-pane on dead panes, from Anindya Mukherjee, GitHub
issue 3174.
2022-05-30 13:03:46 +00:00
nicm
2b60ff588e If a mouse position was above the maximum supported by the normal mouse
protocol (223), tmux was allowing it to wrap around. However, since tmux
was not correctly handling this on input, other programs also do not
handle it correctly, and the alternative SGR mouse mode is now
widespread, this seems unnecessary, so remove this feature. Also define
some constants to make it clearer what the numbers mean. Mostly from
Leonid S Usov in GitHub issue 3165.
2022-05-30 13:02:55 +00:00
nicm
cd89000c1d Add a way for lines added to copy mode to be passed through the parser
to handle escape sequences and use it for run-shell, GitHub issue 3156.
2022-05-30 13:00:18 +00:00
nicm
20b0b38cf4 iTerm2 has OSC 7, from Gregory Anders. 2022-05-30 12:57:31 +00:00
nicm
0a8f356c72 Spacing/style nits. 2022-05-30 12:55:25 +00:00
nicm
af611815ea Emit window-layout-changed on swap-pane, from George Nachman. 2022-05-30 12:54:09 +00:00
nicm
4ae2c64657 Better error reporting when applying custom layouts. 2022-05-30 12:52:02 +00:00
nicm
cd692b5a68 Add an ACL list for users connecting to the tmux socket. Users may be
forbidden from attaching, forced to attach read-only, or allowed to
attach read-write. A new command, server-access, configures the list.
tmux gets the user using getpeereid(3) of the client socket. Users must
still configure file system permissions manually. From Dallas Lyons and
others.
2022-05-30 12:48:57 +00:00
Nicholas Marriott
bf33e807b6 Fix property name, from Sergei Dyshel. 2022-05-30 08:43:06 +01:00
Nicholas Marriott
cf7e1c94df Remove duplicates from completion list, GitHub issue 3178. 2022-05-20 09:00:37 +01:00
Nicholas Marriott
1b28b2b51d Add pane_start_path to match start_command. 2022-05-20 08:49:05 +01:00
Nicholas Marriott
95baa32383 Set PWD so shells have a hint about the real path (this was done before but
lost in a merge). GitHub issue 3186.
2022-05-20 08:33:57 +01:00
Nicholas Marriott
ead75c2d51 Typos, from imcusg at gmail dot com. 2022-05-14 20:16:46 +01:00
Nicholas Marriott
2cad9a6af8 Check if args_strtonum argument is NULL or not a string, from Anindya
Mukherjee.
2022-05-14 20:13:52 +01:00
Nicholas Marriott
3b7dae9a53 Do not allow pipe-pane on dead panes, from Anindya Mukherjee, GitHub issue
3174.
2022-05-02 10:47:08 +01:00
Thomas Adam
5ed64657d8 Merge branch 'obsd-master' 2022-05-01 22:33:38 +01:00
Nicholas Marriott
c6b51cea92 If a mouse position was above the maximum supported by the normal mouse
protocol (223), tmux was allowing it to wrap around. However, since tmux was
not correctly handling this on input, other programs also do not handle it
correctly, and the alternative SGR mouse mode is now widespread, this seems
unnecessary, so remove this feature. Also define some constants to make it
clearer what the numbers mean. Mostly from Leonid S Usov in GitHub issue 3165.
2022-04-27 11:34:08 +01:00
Nicholas Marriott
58d1a206c6 Add a way for lines added to copy mode to be passed through the parser to
handle escape sequences and use it for run-shell, GitHub issue 3156.
2022-04-18 11:47:14 +01:00
Nicholas Marriott
e0c982c5ad iTerm2 has OSC 7, from Gregory Anders. 2022-04-15 12:45:43 +01:00
nicm
d4423dca19 Fix clearphist alias, from Jacqueline Jolicoeur via jmc@. 2022-04-14 06:59:29 +00:00
Nicholas Marriott
8bcd392ee7 On platforms with no way to get peer UID, use getuid(), also fix some failure
checks.
2022-04-06 16:47:59 +01:00
Nicholas Marriott
3a6d82b7c8 Some style nits. 2022-04-06 16:39:46 +01:00
Nicholas Marriott
0c84a20d2f Emit window-layout-changed on swap-pane, from George Nachman. 2022-04-06 14:43:12 +01:00
Nicholas Marriott
996e54763c Better error reporting when applying custom layouts. 2022-04-06 14:41:44 +01:00
Nicholas Marriott
18105c8ecb Do not send focus sequences when focus is enabled or disabled by the
application if it is turned off. GitHub issue 3142.
2022-04-06 14:30:37 +01:00
Nicholas Marriott
d6306b634e Add an ACL list for users connecting to the tmux socket. Users may be forbidden
from attaching, forced to attach read-only, or allowed to attach read-write. A
new command, server-access, configures the list. tmux gets the user using
getpeereid(3) of the client socket. Users must still configure file system
permissions manually.
2022-04-06 14:28:50 +01:00
Nicholas Marriott
6e9a9d265e Fix version. 2022-04-06 14:26:19 +01:00
Nicholas Marriott
36648f2668 Merge remote-tracking branch 'origin/3.3-rc' 2022-04-06 14:25:57 +01:00
Nicholas Marriott
7f86cab1d2 Merge tag '3.3-rc'
3.3-rc
2022-04-06 14:24:33 +01:00
Nicholas Marriott
39b1e96b45 Add to CHANGES. 2022-04-06 14:24:17 +01:00
nicm
1e9c3b3c63 Preserve CRLF flag when respawning. 2022-04-06 14:19:52 +01:00
naddy
fc6580574e man pages: add missing commas between subordinate and main clauses
jmc@ dislikes a comma before "then" in a conditional, so leave those
untouched.

ok jmc@
2022-04-06 14:19:52 +01:00
nicm
2df7bc14fa Capture up to used size not available size for each line. 2022-04-06 14:19:52 +01:00
nicm
880abd0ec2 Report error if creating socket fails with -D. 2022-04-06 14:19:52 +01:00
Nicholas Marriott
1c69a91c25 Add support for systemd socket activation (where systemd creates the Unix
domain socket for tmux rather than tmux creating it). Build with
--enable-systemd. From Julien Moutinho in GitHub issue 3119.
2022-04-06 14:19:52 +01:00
nicm
98de5784a0 Fix exit message if creating socket fails. 2022-04-06 14:19:51 +01:00
nicm
d4eda7f9e5 Add unit (milliseconds) to escape-time, show unset colours as "none"
rather than "invalid" and don't show the same text twice for user
options in customize mode.
2022-04-06 14:19:51 +01:00
nicm
89a0046ad3 Add a capability for OSC 7 and use it similarly to how the title is set
(and controlled by the same set-titles option). GitHub issue 3127.
2022-04-06 14:19:51 +01:00
nicm
60a0a904e0 Check scroll-on-clear for ED also. 2022-04-06 14:19:51 +01:00
nicm
c0508c9321 Add an option (scroll-on-clear) to control if tmux scrolls into history
on clear, from Robert Lange in GitHub issue 3121.
2022-04-06 14:19:51 +01:00
nicm
fe44b105e4 Add an option to set the character used for unused areas of the
terminal, GitHub issue 3110.
2022-04-06 14:19:51 +01:00
nicm
ad7113e0db With -f use percentages of window size not pane size, GitHub issue 2866. 2022-04-06 14:19:51 +01:00
nicm
23e613fcf5 Fix user hooks (which are strings not arrays). 2022-04-06 14:19:51 +01:00
nicm
98b92c0525 Add remain-on-exit-format to set text shown when pane is dead. 2022-04-06 14:19:51 +01:00
nicm
57f331438a Add argument to refresh-client -l to forward clipboard to a pane. GitHub
issue 3068.
2022-04-06 14:19:51 +01:00
nicm
8aed444201 Add formats for client and server UID and user (for multiuser setups). 2022-04-06 14:19:50 +01:00
Nicholas Marriott
f97d784f17 Use getpeerucred if available (not tested). 2022-04-06 14:19:50 +01:00
Nicholas Marriott
759f949654 Need a declaration for getpeereid also. 2022-04-06 14:19:50 +01:00
Nicholas Marriott
f1d8724198 Add getpeerid compat. 2022-04-06 14:19:50 +01:00
Nicholas Marriott
367ee79df0 Remove unnecessary declarations. 2022-04-06 14:19:50 +01:00
nicm
d5a84de842 Pass client when adding menu item, GitHub issue 3103. 2022-04-06 14:19:50 +01:00
nicm
355ced93cc Allow optional arguments. 2022-04-06 14:19:50 +01:00
nicm
bc0bd8213d Don't convert codes for special keys (Tab, Enter, Escape). 2022-04-06 14:19:50 +01:00
topcat001
141a823ea4 Use PATH_MAX instead of MAXPATHLEN. 2022-04-06 14:19:50 +01:00
nicm
42e7959336 Exit on SIGHUP before attach also, GitHub issue 3084. 2022-04-06 14:19:50 +01:00
nicm
9947f7416a Map control keys back to an ASCII uppercase letter when passing them on
as extended keys.
2022-04-06 14:19:50 +01:00
deraadt
c030d6fe36 MAXCOMLEN is no longer needed in these programs, so remove the annotation
from sys/param.h include lines, or remove the include lines entirely if
it this was the least requirement.
ok millert
2022-04-06 14:19:50 +01:00
nicm
046530878b Do not attempt to update focus (and crash) when there is no previous window. 2022-04-06 14:19:50 +01:00
nicm
a26ebccd42 Add next_session_id format with the next session ID, GitHub issue 3078. 2022-04-06 14:19:50 +01:00
nicm
92a26a8b8c Initialize copy_width before adjusting it, GitHub issue 3079. 2022-04-06 14:19:50 +01:00
nicm
f74a98cd07 Use correct size for screen when popup is created without borders. 2022-04-06 14:19:50 +01:00
nicm
4893edd5d6 Add a window-resized hook which is fired when the window is actually
resized which may be later than the client resize, GitHub issue 2995.
2022-04-06 14:19:49 +01:00
nicm
6a0a783c26 Support more mouse buttons when the terminal sends them, GitHub issue
3055.
2022-04-06 14:19:49 +01:00
Nicholas Marriott
7f40c5b647 No not allow static linking on macOS. 2022-04-06 14:19:49 +01:00
nicm
eabbc80b75 Add an option (default off) to control the passthrough escape sequence.
Like set-clipboard and allow-rename it is safer to forbid this by
default.
2022-04-06 14:19:49 +01:00
nicm
190b88fcab Do not create a buffer from an OSC 52 response if we have not sent a
query.
2022-04-06 14:19:49 +01:00
nicm
2adbe3ec16 Do not return error with -q, GitHub issue 3065. 2022-04-06 14:19:49 +01:00
nicm
9efa419955 Use ACS for pane border indicators so they work with different line
types, from Thomas Adam.
2022-04-06 14:19:49 +01:00
nicm
921be61930 Adjust size given to resize-pane for pane status line, GitHub issue
3050.
2022-04-06 14:19:49 +01:00
Thomas Adam
b0ff446727 Merge branch 'obsd-master' into master 2022-04-01 14:01:11 +01:00
nicm
65c0af76fb Preserve CRLF flag when respawning. 2022-04-01 10:11:59 +00:00
Thomas Adam
87b248f3e8 Merge branch 'obsd-master' into master 2022-03-31 20:01:11 +01:00
naddy
2d9f4ca9a1 man pages: add missing commas between subordinate and main clauses
jmc@ dislikes a comma before "then" in a conditional, so leave those
untouched.

ok jmc@
2022-03-31 17:27:27 +00:00
Thomas Adam
fc82f2525c Merge branch 'obsd-master' into master 2022-03-30 10:01:11 +01:00
nicm
ded695504f Capture up to used size not available size for each line. 2022-03-30 07:05:26 +00:00
Thomas Adam
ac16f2c641 Merge branch 'obsd-master' into master 2022-03-28 10:01:11 +01:00
Nicholas Marriott
fc7f1e7acb Add support for systemd socket activation (where systemd creates the Unix
domain socket for tmux rather than tmux creating it). Build with
--enable-systemd. From Julien Moutinho in GitHub issue 3119.
2022-03-28 08:42:13 +01:00
nicm
207b1bc385 Report error if creating socket fails with -D. 2022-03-28 07:40:57 +00:00
Thomas Adam
d26a4ea463 Merge branch 'obsd-master' into master 2022-03-25 08:01:10 +00:00
nicm
422fcd294a Fix exit message if creating socket fails. 2022-03-25 06:14:42 +00:00
Thomas Adam
b638886716 Merge branch 'obsd-master' into master 2022-03-24 14:01:11 +00:00
nicm
938130bc69 Add unit (milliseconds) to escape-time, show unset colours as "none"
rather than "invalid" and don't show the same text twice for user
options in customize mode.
2022-03-24 12:07:25 +00:00
Thomas Adam
5e491e7947 Merge branch 'obsd-master' into master 2022-03-24 12:01:11 +00:00
nicm
792d13af49 Add a capability for OSC 7 and use it similarly to how the title is set
(and controlled by the same set-titles option). GitHub issue 3127.
2022-03-24 09:05:57 +00:00
Thomas Adam
964deae422 Merge branch 'obsd-master' into master 2022-03-17 16:01:11 +00:00
nicm
6a1706a62f Check scroll-on-clear for ED also. 2022-03-17 13:39:13 +00:00
nicm
10d689e735 Add an option (scroll-on-clear) to control if tmux scrolls into history
on clear, from Robert Lange in GitHub issue 3121.
2022-03-17 11:35:37 +00:00
Thomas Adam
5d4c3ef762 Merge branch 'obsd-master' into master 2022-03-16 20:01:10 +00:00
nicm
e6e737ac0b Add an option to set the character used for unused areas of the
terminal, GitHub issue 3110.
2022-03-16 17:00:17 +00:00
Thomas Adam
ee3f1d25d5 Merge branch 'obsd-master' into master 2022-03-09 00:01:12 +00:00
nicm
bfbe972225 With -f use percentages of window size not pane size, GitHub issue 2866. 2022-03-08 22:14:25 +00:00
nicm
cf217fa618 Fix user hooks (which are strings not arrays). 2022-03-08 21:58:37 +00:00
Thomas Adam
25337ac102 Merge branch 'obsd-master' into master 2022-03-08 20:01:11 +00:00
nicm
a3d920930b Add remain-on-exit-format to set text shown when pane is dead. 2022-03-08 18:31:46 +00:00
Thomas Adam
2fb6089e81 Merge branch 'obsd-master' into master 2022-03-08 14:01:11 +00:00
nicm
ad9b805983 Add argument to refresh-client -l to forward clipboard to a pane. GitHub
issue 3068.
2022-03-08 12:01:19 +00:00
Nicholas Marriott
04952f15df Use getpeerucred if available (not tested). 2022-03-08 11:35:06 +00:00
nicm
98cd8e4cad Add formats for client and server UID and user (for multiuser setups). 2022-03-08 11:28:40 +00:00
Nicholas Marriott
9ed1226a66 Need a declaration for getpeereid also. 2022-03-08 11:04:15 +00:00
Nicholas Marriott
afd9b68d10 Add getpeerid compat. 2022-03-08 11:02:17 +00:00
Nicholas Marriott
54d2249716 Remove unnecessary declarations. 2022-03-07 15:21:39 +00:00
Thomas Adam
7eff2fe780 Merge branch 'obsd-master' into master 2022-03-07 14:01:11 +00:00
nicm
a731b1a916 Pass client when adding menu item, GitHub issue 3103. 2022-03-07 11:52:09 +00:00
Thomas Adam
f84f1c0cfe Merge branch 'obsd-master' into master 2022-03-03 10:01:09 +00:00
nicm
7d4224f207 Allow optional arguments. 2022-03-03 08:24:12 +00:00
Thomas Adam
bf14bf6259 Merge branch 'obsd-master' into master 2022-03-01 18:01:10 +00:00
nicm
f39a71aaad Don't convert codes for special keys (Tab, Enter, Escape). 2022-03-01 15:20:22 +00:00
Anindya Mukherjee
cd9a81e242
Merge pull request #3093 from topcat001/pathfix
Use PATH_MAX instead of MAXPATHLEN.
2022-02-28 13:16:23 -08:00
topcat001
047c011a15 Use PATH_MAX instead of MAXPATHLEN. 2022-02-28 13:11:28 -08:00
Thomas Adam
649685ff6d Merge branch 'obsd-master' into master 2022-02-28 12:01:10 +00:00
Thomas Adam
2750195709 Merge branch 'obsd-master' into master 2022-02-28 10:01:11 +00:00
nicm
2da096d828 Exit on SIGHUP before attach also, GitHub issue 3084. 2022-02-28 09:34:57 +00:00
nicm
2e59ff2db9 Map control keys back to an ASCII uppercase letter when passing them on
as extended keys.
2022-02-28 09:24:22 +00:00
Thomas Adam
60688afe9c Merge branch 'obsd-master' into master 2022-02-22 20:01:11 +00:00
deraadt
e8d6d53a7b MAXCOMLEN is no longer needed in these programs, so remove the annotation
from sys/param.h include lines, or remove the include lines entirely if
it this was the least requirement.
ok millert
2022-02-22 17:35:01 +00:00
Thomas Adam
dc0746946e Merge branch 'obsd-master' into master 2022-02-22 16:01:11 +00:00
Thomas Adam
2be5488693 Merge branch 'obsd-master' into master 2022-02-22 14:01:10 +00:00
nicm
d54b18ca2b Do not attempt to update focus (and crash) when there is no previous window. 2022-02-22 13:31:18 +00:00
nicm
fa71e9a079 Add next_session_id format with the next session ID, GitHub issue 3078. 2022-02-22 11:10:41 +00:00
nicm
0fd01f8873 Initialize copy_width before adjusting it, GitHub issue 3079. 2022-02-22 11:07:25 +00:00
nicm
a9b880921d Use correct size for screen when popup is created without borders. 2022-02-22 11:01:57 +00:00
Thomas Adam
88d9a8fc05 Merge branch 'obsd-master' into master 2022-02-17 12:01:10 +00:00
nicm
818b2176ef Add a window-resized hook which is fired when the window is actually
resized which may be later than the client resize, GitHub issue 2995.
2022-02-17 09:58:47 +00:00
Thomas Adam
722f395e61 Merge branch 'obsd-master' into master 2022-02-16 22:01:11 +00:00
nicm
0027ee13a0 Support more mouse buttons when the terminal sends them, GitHub issue
3055.
2022-02-16 18:55:05 +00:00
Nicholas Marriott
c7c7e875a0 No not allow static linking on macOS. 2022-02-16 12:26:23 +00:00
Thomas Adam
85ef73591d Merge branch 'obsd-master' into master 2022-02-15 16:01:11 +00:00
nicm
5076beb009 Add an option (default off) to control the passthrough escape sequence.
Like set-clipboard and allow-rename it is safer to forbid this by
default.
2022-02-15 13:11:29 +00:00
nicm
f85208602d Do not create a buffer from an OSC 52 response if we have not sent a
query.
2022-02-15 13:03:02 +00:00
Thomas Adam
df681390a6 Merge branch 'obsd-master' into master 2022-02-14 10:01:11 +00:00
nicm
040164555a Do not return error with -q, GitHub issue 3065. 2022-02-14 09:10:48 +00:00
Thomas Adam
c67abcf818 Merge branch 'obsd-master' into master 2022-02-04 14:01:09 +00:00
nicm
07e2d88c20 Use ACS for pane border indicators so they work with different line
types, from Thomas Adam.
2022-02-04 11:57:22 +00:00
Thomas Adam
784d6a3929 Merge branch 'obsd-master' into master 2022-02-03 14:01:11 +00:00
Nicholas Marriott
53ee4f0334 Merge branch 'master' into 3.3-rc 2022-02-03 12:50:49 +00:00
Thomas Adam
c0598e2515 Merge branch 'obsd-master' into master 2022-02-03 12:01:10 +00:00
nicm
3276f0c184 Adjust size given to resize-pane for pane status line, GitHub issue
3050.
2022-02-03 11:06:11 +00:00
nicm
948d2fad0a Use format_draw for command prompt prefix to allow styles, GitHub issue
3054.
2022-02-03 10:07:11 +00:00
Thomas Adam
1fdec20b0d Merge branch 'obsd-master' into master 2022-02-03 10:01:10 +00:00
Thomas Adam
375f6c90b0 Merge branch 'obsd-master' into master 2022-02-03 08:01:12 +00:00
Nicholas Marriott
b46abeb34d 3.3-rc. 2022-02-03 07:50:35 +00:00
Nicholas Marriott
57396b55a2 Update CHANGES. 2022-02-03 07:50:06 +00:00
nicm
c401c91ad9 Update focus when active pane changes after pane destroyed. 2022-02-03 07:38:17 +00:00
nicm
5080acc127 Add a key in copy mode to toggle position indicator. 2022-02-03 07:26:43 +00:00
Thomas Adam
a5cf7a9b39 Merge branch 'obsd-master' into master 2022-02-01 20:01:13 +00:00
nicm
97900d0442 A menu must be shown on a client, so always give the client when adding
the items. Also fix mode menus.
2022-02-01 18:12:20 +00:00
Thomas Adam
a4f336a91a Merge branch 'obsd-master' into master 2022-02-01 16:01:11 +00:00
nicm
7e34645fcb Add option to show arrows for active pane indicator, GitHub issue 3022
from Marcel Partap.
2022-02-01 14:46:41 +00:00
Thomas Adam
1b7afd5129 Merge branch 'obsd-master' into master 2022-02-01 14:01:11 +00:00
nicm
7a4ba6d4a5 Mention that if-shell and #() use /bin/sh. 2022-02-01 12:05:42 +00:00
nicm
770d28b8c5 Do not overflow width when not enough space. 2022-02-01 11:52:08 +00:00
Thomas Adam
6c0397f497 Merge branch 'obsd-master' into master 2022-01-17 12:01:10 +00:00
nicm
a6b361e775 Do not try to strdup NULL, from seL4 at disroot dot org in GitHub issue
3038.
2022-01-17 10:40:03 +00:00
Thomas Adam
28b6237c62 Merge branch 'obsd-master' into master 2022-01-06 10:01:12 +00:00
Nicholas Marriott
e5e4df7a22 Mention alternate config files, from Daniel Augusto in GitHub issue 3023. 2022-01-06 08:23:42 +00:00
nicm
b2b94dcba7 Ignore windows without a size set (may be used for pane only), from
Anindya Mukherjee.
2022-01-06 08:20:00 +00:00
Thomas Adam
080079c55a Merge branch 'obsd-master' into master 2021-12-31 14:01:10 +00:00
nicm
e6e3c75ed7 Try to turn on less-capable mouse modes when turning on more-capable, to
increase the chances we get something even if the terminal doesn't support
the one we really want. GitHub issue 3020.
2021-12-31 11:35:49 +00:00
Thomas Adam
47923bd5f6 Merge branch 'obsd-master' into master 2021-12-21 18:01:10 +00:00
nicm
9aad945f7e Support underscore style with capture-pane -e, GitHub issue 2928. 2021-12-21 14:57:28 +00:00
Thomas Adam
9c82ff1778 Merge branch 'obsd-master' into master 2021-12-21 14:01:09 +00:00
nicm
ff64aafeab ARM's Morello CHERI architecture does not support pointers in packed
structures, so remove the packed attribute on struct grid_line and
reorder the members to eliminate unnecessary padding. From Jessica
Clarke in GitHub issue 3012.
2021-12-21 13:07:53 +00:00
Thomas Adam
ba9b9367d5 Merge branch 'obsd-master' into master 2021-12-20 10:01:13 +00:00
nicm
e4856de8bf Do not crash on a zero size character. 2021-12-20 09:02:12 +00:00
Thomas Adam
70d330a353 Merge branch 'obsd-master' into master 2021-12-13 12:01:10 +00:00
nicm
c6149adf55 Make pane-border-format a pane option, GitHub issue 2999. 2021-12-13 09:42:20 +00:00
Thomas Adam
5c5712be5c Merge branch 'obsd-master' into master 2021-12-10 16:01:11 +00:00
Thomas Adam
8941dbe482 Merge branch 'obsd-master' into master 2021-12-10 14:01:10 +00:00
nicm
9c1633a865 Missed unlinked control notifications, GitHub issue 2996. 2021-12-10 12:51:11 +00:00
nicm
1f9aad2bb4 Mention XParseColor(3) for the cursor colour escape sequence. 2021-12-10 12:45:32 +00:00
nicm
db3aabcc34 Add a NOBLOCK flag rather than adding amount to wait for when
dealing with potentially-long sequences. GitHub issue 3001.
2021-12-10 12:42:37 +00:00
Thomas Adam
138ffc7cb6 Merge branch 'obsd-master' into master 2021-12-07 09:52:59 +00:00
nicm
d721fb2a9f Respond to OSC 4 query. 2021-12-07 07:28:44 +00:00
deraadt
7532a5cf95 sys/signal.h (or some master include) must happen before sys/proc.h, which
is not standalone.
This problem is being hidden by a sys/param.h which cannot be deleted yet.
2021-12-07 00:40:03 +00:00
deraadt
71c3234dc7 Use PATH_MAX (the standard name) rather than MAXPATHLEN (from BSD sys/param.h) 2021-12-07 00:38:42 +00:00
Nicholas Marriott
ef676e1202 Remove fallback for wcwidth failure, GitHub issue 3003. 2021-12-06 10:17:34 +00:00
nicm
ecac73f664 Fix g/G keys to be in line with copy mode. 2021-12-06 10:10:52 +00:00
nicm
8fccbbb026 Do not dereference NULL window when resizing client, GitHub issue 2982. 2021-12-06 10:08:42 +00:00
nicm
333cf6429a Bump response timer to three seconds, GitHub issue 2984. 2021-11-29 11:05:28 +00:00
nicm
add03dfb8d Fix user option lookup ordering. 2021-11-29 11:01:51 +00:00
nicm
b55f0ac6b9 Leave the hardware cursor at the position of the selected line in choose
modes and current editing position and at the command prompt. It is
invisible but this is helpful for people using screen readers. GitHub
issue 2970.
2021-11-15 10:58:13 +00:00
nicm
cb8a0d83fb If automatic-rename is off, allow the escape sequence to set an empty
window name, GitHub issue 2964.
2021-11-11 09:31:16 +00:00
nicm
630c592ef8 If trimming menu item text, show key if it would take up less than a
quarter of the space; from Alexis Hildebrandt.

Also new sentence, new line in tmux.1, from jmc.
2021-11-11 09:22:33 +00:00
Nicholas Marriott
10b3cd17fa OS X -> macOS, from J Lewis Muir. 2021-11-11 09:18:04 +00:00
kn
8f1cc0e9fa Fix mandoc HTML rendering for command aliases
Replace hand-rolled parentheses with the proper mdoc(7) macro,
otherwise the closing ")" ends up inside the command description.

Reported by Josh Rickmar, thanks!
2021-11-04 13:15:13 +00:00
Thomas Adam
77fc7ac3be Merge branch 'obsd-master' into master 2021-11-03 16:01:14 +00:00
nicm
57100376cc Add a cursor-style option, from Alexis Hildebrandt in GitHub issue 2960. 2021-11-03 13:37:17 +00:00
Thomas Adam
1fc0d1b74f Merge branch 'obsd-master' into master 2021-11-02 14:01:11 +00:00
nicm
200b6536e1 fatalx on unknown enum members in a couple of places, from Ben Boeckel. 2021-11-02 10:57:04 +00:00
Thomas Adam
7d330c19e8 Merge branch 'obsd-master' into master 2021-11-01 12:01:12 +00:00
Thomas Adam
774903f6c4 Merge branch 'obsd-master' into master 2021-11-01 10:01:13 +00:00
nicm
8d2286b769 Add a cursor-colour option, from Alexis Hildebrandt in GitHub issue
2959.
2021-11-01 09:34:49 +00:00
nicm
4fe5aa99fb Fix a comparison, from Ben Boeckel, and a crash when opening completion
menu, from Anindya Mukherjee.
2021-11-01 07:48:04 +00:00
Nicholas Marriott
c76904343a Spelling, from someone in GitHub issue 2958. 2021-10-29 08:37:06 +01:00
Thomas Adam
60cacdffea Merge branch 'obsd-master' into master 2021-10-28 22:01:13 +01:00
nicm
4acad43013 Do not force the cursor to move if it is in the automargin space at EOL
and that is where we want it to be, GitHub issue 2956.
2021-10-28 18:57:06 +00:00
nicm
49d33a4282 Allow detach even if suspend flag set, GitHub issue 2932. 2021-10-28 18:54:33 +00:00
nicm
76f5d3364c Expand command as a format, GitHub issue 2920. 2021-10-28 18:39:15 +00:00
Thomas Adam
c77924bb56 Merge branch 'obsd-master' into master 2021-10-26 16:01:11 +01:00
nicm
9695114230 Accept some emacs control keys in vi normal mode, from Alexis
Hildebrandt in GitHub issue 2922.
2021-10-26 12:29:41 +00:00
nicm
5745bd27fd Do not allow inline styles to replace mode-style for the selected item,
from Alexis Hildebrandt in GitHub issue 2946.
2021-10-26 12:22:23 +00:00
Thomas Adam
6f46f71d58 Merge branch 'obsd-master' into master 2021-10-26 00:01:13 +01:00
nicm
197a116f5a Add a way to force a colour to RGB and a format to display it. 2021-10-25 21:21:16 +00:00
nicm
eb82ad5216 Missing Pp, from Alexis Hildebrandt. 2021-10-25 20:32:42 +00:00
Thomas Adam
3934d9b24d Merge branch 'obsd-master' into master 2021-10-25 12:01:11 +01:00
nicm
ef46eb91a5 Add -s and -S to display-popup to set popup and border style, from
Alexis Hildebrandt in GitHub issue 2931.
2021-10-25 09:38:36 +00:00
nicm
0cca695d6e Instead of setting the popup default colours in the draw callback, set
it up in popup_display and follow the same routine as panes in the draw
and init_ctx callbacks - use the palette if the option value is default.
Allows application-set fg and bg to work in panes again.
2021-10-25 09:22:17 +00:00
Thomas Adam
619d934d7b Merge branch 'obsd-master' into master 2021-10-25 00:01:11 +01:00
deraadt
9b4148b12c For open/openat, if the flags parameter does not contain O_CREAT, the
3rd (variadic) mode_t parameter is irrelevant.  Many developers in the past
have passed mode_t (0, 044, 0644, or such), which might lead future people
to copy this broken idiom, and perhaps even believe this parameter has some
meaning or implication or application. Delete them all.
This comes out of a conversation where tb@ noticed that a strange (but
intentional) pledge behaviour is to always knock-out high-bits from
mode_t on a number of system calls as a safety factor, and his bewilderment
that this appeared to be happening against valid modes (at least visually),
but no sorry, they are all irrelevant junk.  They could all be 0xdeafbeef.
ok millert
2021-10-24 21:24:17 +00:00
Thomas Adam
5071b82c77 Merge branch 'obsd-master' into master 2021-10-22 20:01:11 +01:00
nicm
8235957eaa Remove key and trim text if menu cannot fit in available space, based on
a change from Alexis Hildebrandt.
2021-10-22 17:12:50 +00:00
Thomas Adam
be2413292f Merge branch 'obsd-master' into master 2021-10-21 12:01:10 +01:00
nicm
289ac55ebd Correctly adjust the end pointer for a two character terminator before
decoding OSC 52 response, from Daniel Ekloef in GitHub issue 2942.
2021-10-21 08:36:51 +00:00
nicm
7bd9cdf6fc Show error if user option doesn't exist, GitHub issue 2938. 2021-10-21 08:23:48 +00:00
Thomas Adam
1bf2f811ea Merge branch 'obsd-master' into master 2021-10-20 14:01:15 +01:00
nicm
acba07629e Remove a TODO comment. 2021-10-20 09:52:27 +00:00
nicm
8a9bfd0cdd Add -T to set a popup title, from Alexis Hildebrandt in GitHub issue 2941. 2021-10-20 09:50:40 +00:00
Thomas Adam
65bb36d6bd Merge branch 'obsd-master' into master 2021-10-19 16:01:12 +01:00
nicm
f26b8c57ff Same as -N, don't send if 0 arguments and -R. 2021-10-19 12:51:43 +00:00
Thomas Adam
9e986d6a96 Merge branch 'obsd-master' into master 2021-10-18 12:01:12 +01:00
nicm
51ff77d47b Fix menu width containing disabled items, from Alexis Hildebrandt in
GitHub issue 2935.
2021-10-18 09:48:35 +00:00
nicm
2c188ee0c5 Spacing fixes from Alexis Hildebrandt. 2021-10-18 09:15:56 +00:00
nicm
cc27a43c40 Remove duplicate options, spotted by Ricky Cintron. 2021-10-18 09:09:46 +00:00
Thomas Adam
c57df2bb73 Merge branch 'obsd-master' into master 2021-10-15 14:01:13 +01:00
nicm
537302f2c1 Do not send any key if -N flag is given even if no other arguments,
fixes problem with repeat in copy mode reported by tb@.
2021-10-15 10:39:22 +00:00
Thomas Adam
264fe7fc2a Merge branch 'obsd-master' into master 2021-10-14 16:01:20 +01:00
nicm
add20637f2 Add popup-border-lines option to set popup line style, from Alexis
Hildebrandt, GitHub issue 2930.
2021-10-14 13:19:01 +00:00
Thomas Adam
ee9885a40c Merge branch 'obsd-master' into master 2021-10-14 12:01:12 +01:00
nicm
d0ab1a837a When checking ranges in tty_cmd_cells, cannot use the tty cursor
position and tty_cursor because it may be at the final invisible cursor
position on automargin terminals. The text to be drawn is confined to
the pane, so use the pane cursor position for the checks instead. Fix
from Anindya Mukherjee, redraw problem reported by naddy@.
2021-10-14 09:54:51 +00:00
Thomas Adam
fb23df679b Merge branch 'obsd-master' into master 2021-10-13 14:01:16 +01:00
nicm
837ca176d1 Add popup-style and popup-border-style options, from Alexis Hildebrandt
in GitHub issue 2927.
2021-10-13 09:28:36 +00:00
Thomas Adam
aff2a473ec Merge branch 'obsd-master' into master 2021-10-11 16:01:13 +01:00
nicm
b8581ec80e Make positions hidden by overlays range-based rather than character-based,
from Anindya Mukherjee.
2021-10-11 13:27:50 +00:00
Thomas Adam
af82106fae Merge branch 'obsd-master' into master 2021-10-11 14:01:13 +01:00
nicm
759efe1b33 Add -e flag to set environment for popup, from Alexis Hildebrandt in
GitHub issue 2924.
2021-10-11 10:55:30 +00:00
Thomas Adam
7ca863c5af Merge branch 'obsd-master' into master 2021-10-08 18:01:11 +01:00
jmc
7800a431ea remove extra .El; 2021-10-08 14:14:31 +00:00
Thomas Adam
bf0f694f91 Merge branch 'obsd-master' into master 2021-10-08 10:01:12 +01:00
kn
50a77f4417 Add tags for command aliases
Make ":tnew" work, i.e. bring the reader to the definition of the full
"new-window" command aliased as "new" just like ":tnew-window" would.

OK nicm
2021-10-08 06:37:39 +00:00
Thomas Adam
fed7b29c7e Merge branch 'obsd-master' into master 2021-10-07 10:01:10 +01:00
nicm
5f63181ed5 Add a missing El, from Alexis Hildebrandt in GitHub issue 2918. 2021-10-07 07:53:31 +00:00
nicm
9574496333 Handle splitw -I correctly when used from an attached client, GitHub
issue 2917.
2021-10-07 07:52:13 +00:00
Thomas Adam
5374417428 Merge branch 'obsd-master' into master 2021-10-06 12:01:10 +01:00
nicm
5359b76619 Do not reset cursor to default if it has never been changed, fixes
problem reported by naddy.
2021-10-06 10:33:12 +00:00
Thomas Adam
c8802c776a Merge branch 'obsd-master' into master 2021-10-06 00:01:12 +01:00
nicm
da05d05824 Fix some warnings. 2021-10-05 20:15:16 +00:00
Thomas Adam
d8996a1c1d Merge branch 'obsd-master' into master 2021-10-05 20:01:11 +01:00
nicm
e06a4e041c Set mouse_x and mouse_y on the status line, GitHub issue 2913. 2021-10-05 17:23:13 +00:00
Thomas Adam
479c9563c7 Merge branch 'obsd-master' into master 2021-10-05 16:01:13 +01:00
nicm
9f6164a05c Make send-keys without any arguments send the key it is bound to (if
any). GitHub issue 2904.
2021-10-05 12:49:37 +00:00
nicm
9b1fdb291e Separate "very visible" flag from blinking flag, it should not affect
DECSCUSR. GitHub issue 2891.
2021-10-05 12:46:02 +00:00
nicm
3d5a02bf45 Do not try to use NULL time values. 2021-10-05 12:45:02 +00:00
Thomas Adam
bf595a0cb0 Merge branch 'obsd-master' into master 2021-09-27 22:01:10 +01:00
nicm
68c8905859 Do not call recalculate_sizes while clearing a client session because it
needs to loop over the clients, instead do it after all clients are
cleared. Fixes a crash reported by martijn@ when a session with multiple
clients attached is destroyed, but there are other sessions so tmux does
not entirely exit. ok deraadt
2021-09-27 19:12:00 +00:00
Thomas Adam
03f9963f3d Merge branch 'obsd-master' into master 2021-09-22 18:01:10 +01:00
nicm
257e9ba69a Fix command prompt with multiple prompts (add the result onto the list
again as we go along). ok deraadt
2021-09-22 15:21:44 +00:00
Nicholas Marriott
9c77a5b9f0 Remove duplicate. 2021-09-21 10:03:38 +01:00
Nicholas Marriott
b2482535d0 Crosscompiling defaults from Romain Francoise. 2021-09-21 09:54:50 +01:00
Nicholas Marriott
097a792f9d Update obsolete autoconf macros, from "kylo252" GitHub issue 2900. 2021-09-21 09:53:44 +01:00
Thomas Adam
25df71b90d Merge branch 'obsd-master' into master 2021-09-17 10:01:10 +01:00
nicm
c4b969ca62 Do not destroy sessions twice, GitHub issue 2889. 2021-09-17 07:20:49 +00:00
Thomas Adam
409e121cac Merge branch 'obsd-master' into master 2021-09-16 10:01:11 +01:00
nicm
3c3d371f99 Fix run-shell -d with no command, GitHub issue 2885. 2021-09-16 06:39:22 +00:00
Nicholas Marriott
8554b80b8b Merge tag '3.3-rc'
3.3-rc
2021-09-15 14:08:15 +01:00
Nicholas Marriott
3be44313aa Next is 3.4. 2021-09-15 14:07:42 +01:00
Nicholas Marriott
ed280e14c8 Missing header. 2021-09-15 14:03:19 +01:00
Nicholas Marriott
86d505af46 3.3-rc. 2021-09-15 13:42:50 +01:00
Nicholas Marriott
7186ab25c9 Those were already there... 2021-09-15 13:40:51 +01:00
Nicholas Marriott
a049ebd6f7 And more CHANGES. 2021-09-15 13:37:39 +01:00
Nicholas Marriott
adb620c4e4 Update CHANGES. 2021-09-15 13:35:08 +01:00
Thomas Adam
2b9830f0e7 Merge branch 'obsd-master' into master 2021-09-15 10:01:10 +01:00
nicm
a19cac5c46 For the moment, restore if-shell and run-shell to parsing at the last
moment (when the shell command completes) rather than when first
invoked, GitHub issue 2872.
2021-09-15 07:38:30 +00:00
Nicholas Marriott
ddcf5b801a Mention FAQ, from Illia Bobyr. 2021-09-13 07:57:37 +01:00
Thomas Adam
b28fffc0f7 Merge branch 'obsd-master' into master 2021-09-10 18:01:11 +01:00
nicm
e6b40cb339 Do fatal/fatalx a different way so the compiler trick to avoid warnings
becomes unnecessary, prompted by theo.
2021-09-10 15:03:18 +00:00
nicm
33ac7a346e Get rid of the last two warnings by turning them off around the problem
statements, if the compiler supports it.
2021-09-10 14:22:24 +00:00
Nicholas Marriott
3b10392bfc Icons, from someone on GitHub in issue 2870. 2021-09-10 15:00:58 +01:00
Thomas Adam
3358c9a8f1 Merge branch 'obsd-master' into master 2021-09-10 12:01:10 +01:00
nicm
5cdc1bdd32 Disable aliases inside aliases for the moment. 2021-09-10 08:52:46 +00:00
Thomas Adam
31a6e5eff4 Merge branch 'obsd-master' into master 2021-09-10 02:01:12 +01:00
nicm
768fb9080f Keep -? as usage. 2021-09-09 21:55:03 +00:00
Thomas Adam
42b0be4cfd Merge branch 'obsd-master' into master 2021-09-09 22:01:11 +01:00
nicm
a0b39dba31 Turn on both button and all mouse modes for menus since some terminals
only support the former.
2021-09-09 19:37:17 +00:00
Thomas Adam
732288c489 Merge branch 'obsd-master' into master 2021-09-09 16:01:09 +01:00
nicm
34312fd6ee Expand argument to run-shell again. 2021-09-09 13:38:32 +00:00
Thomas Adam
cf5e1bb80a Merge branch 'obsd-master' into master 2021-09-09 10:01:10 +01:00
nicm
5a4b2fd68c Fix parsing of aliases again (GitHub issue 2842), also make argument
parsing a bit simpler and fix the names of some client flags.
2021-09-09 06:57:48 +00:00
Thomas Adam
d776c9acfc Merge branch 'obsd-master' into master 2021-09-02 10:01:09 +01:00
nicm
329c2c2a91 Change copying arguments to that flags without arguments are inserted
correctly and empty arguments lists do not crash. Fixes crash reported
by & ok mpi@.
2021-09-02 07:11:03 +00:00
Nicholas Marriott
d62aee506b Regress conf from https://raw.githubusercontent.com/lacygoill/config/master/.config/tmux/tmux.conf. 2021-08-30 08:24:43 +01:00
Nicholas Marriott
388f0fe973 Update CHANGES. 2021-08-30 08:17:38 +01:00
Thomas Adam
609baea95e Merge branch 'obsd-master' into master 2021-08-27 20:01:11 +01:00
nicm
daec63e5e6 Replace %% in command lists (by copying them) for template arguments ,
this means they can be used with {} as well. Also make argument
processing from an existing vector preserve commands. GitHub issue 2858.
2021-08-27 17:25:55 +00:00
nicm
fd756a150b Allow control mode clients to set a hard limit on the window width and
height, GitHub issue 2594.
2021-08-27 17:15:57 +00:00
Thomas Adam
c6375a0d40 Merge branch 'obsd-master' into master 2021-08-25 12:01:11 +01:00
nicm
24636be42b Improve some logging. 2021-08-25 10:18:01 +00:00
nicm
f4f8d3b5ed Ignore client creating session when working out size if it is a control
client.
2021-08-25 10:15:15 +00:00
Nicholas Marriott
6616b42b2c Fix test. 2021-08-25 10:24:33 +01:00
nicm
a3c6057b51 bind-key needs to allow commands for any argument for the moment. 2021-08-25 09:18:08 +00:00
Thomas Adam
c7266ca78d Merge branch 'obsd-master' into master 2021-08-25 10:01:10 +01:00
nicm
03d173cbd8 Validate command argument types (string or command list) and give more
useful error messages.
2021-08-25 08:51:55 +00:00
nicm
c6d6af4903 setupterm needs char * not const char * on some platforms. 2021-08-25 07:37:20 +00:00
Nicholas Marriott
6ac09aa47c Disable a couple of warnings on macOS. 2021-08-25 08:36:51 +01:00
nicm
a252fadf8a Fix up some printflike attributes. 2021-08-25 07:09:30 +00:00
nicm
78da5a3756 Start inputs as NULL so not freeing random stack garbage, GitHub issue 2852. 2021-08-25 06:36:05 +00:00
Thomas Adam
7fe3588e49 Merge branch 'obsd-master' into master 2021-08-23 20:01:09 +01:00
nicm
841ce74b43 args_make_commands_now needs to take an extra reference to the returned
command list since it will be freed already.
2021-08-23 17:05:43 +00:00
Thomas Adam
95a374d7d2 Merge branch 'obsd-master' into master 2021-08-23 16:06:46 +01:00
nicm
210e71edf3 Move command argument parsing common functions and don't bother to parse
again if given a command rather than a string.
2021-08-23 12:33:55 +00:00
nicm
03b83a5a34 Key bindings steal a reference to the command instead of adding their
own, it was correct not to add a reference when parsing, but the
bind-key then needs to add one.
2021-08-23 11:48:21 +00:00
nicm
1f0c0914c7 Revert one of previous, for some reason it is being freed. 2021-08-23 11:08:26 +00:00
nicm
4a753dbefc Fix a few memory leaks. 2021-08-23 11:04:21 +00:00
nicm
3ed37a2079 Limit width and height to tty correctly, GitHub issue 2843. 2021-08-23 08:17:41 +00:00
Thomas Adam
1dec1ca146 Merge branch 'obsd-master' into master 2021-08-22 18:01:18 +01:00
Nicholas Marriott
bc71e233d9 Fix style regress test. 2021-08-22 16:33:57 +01:00
nicm
2e9bafaf14 Fix handling of leading #s when working out width. 2021-08-22 15:33:14 +00:00
Thomas Adam
03054598df Merge branch 'obsd-master' into master 2021-08-22 16:01:19 +01:00
nicm
72d905f32c Do not double free expanded path in source-file, also remove some
unnecessary assignments.
2021-08-22 13:48:29 +00:00
nicm
c0048d6d20 Insert alias in the right place, GitHub issue 2842. 2021-08-22 13:00:28 +00:00
Thomas Adam
324f87cf14 Merge branch 'obsd-master' into master 2021-08-22 12:08:05 +01:00
nicm
0084cbef5a Free value properly. 2021-08-21 20:57:52 +00:00
nicm
069f5925af Preserve argument type in command and convert to string on demand. 2021-08-21 20:46:43 +00:00
Thomas Adam
921991c98d Merge branch 'obsd-master' into master 2021-08-21 20:01:22 +01:00
nicm
326d2ef234 Pass typed arguments out of the parser into the arguments list and let
it convert them into strings.
2021-08-21 18:39:07 +00:00
nicm
63b6eec278 Use new syntax for default key bindings. 2021-08-21 17:41:19 +00:00
nicm
5241dae87d Stop caring about empty commands, just treat as a null command. 2021-08-21 17:25:32 +00:00
Thomas Adam
4d3367e965 Merge branch 'obsd-master' into master 2021-08-21 16:01:26 +01:00
nicm
68cacaec68 Remove some members of struct cmd which are no longer used. 2021-08-21 14:10:08 +00:00
nicm
c286fbdcd7 Preserve command group when moving temporary list to current list being
buit.
2021-08-21 14:06:17 +00:00
Thomas Adam
62036121fa Merge branch 'obsd-master' into master 2021-08-21 12:01:41 +01:00
nicm
110ba767e5 Rename a member to match what it will be in future. 2021-08-21 10:28:05 +00:00
nicm
08e6360f23 Add args parsing callback for some future work, currently unused. 2021-08-21 10:22:38 +00:00
nicm
d371764d02 Wrap command argument definitions in their own struct. 2021-08-21 08:44:59 +00:00
Thomas Adam
b0da0cee4d Merge branch 'obsd-master' into master 2021-08-20 22:01:46 +01:00
nicm
d589be6c65 A couple more spacing fixes. 2021-08-20 20:08:30 +00:00
nicm
caa8703a23 Spacing tweaks. 2021-08-20 20:04:22 +00:00
nicm
5f32b7d961 Hide struct args behind a couple of accessor functions. 2021-08-20 19:50:16 +00:00
nicm
de94a344f6 Add a couple of const and fix some warnings. 2021-08-20 19:34:51 +00:00
nicm
c76b28de24 Remove some unnecessary blank lines. 2021-08-20 19:08:36 +00:00
Thomas Adam
944fde7c57 Merge branch 'obsd-master' into master 2021-08-20 20:01:27 +01:00
nicm
90dd474c3e Expose args_value struct (will be needed soon) and add some missing frees. 2021-08-20 18:59:53 +00:00
nicm
6cbc83c6a6 Add a way to create an empty arguments set. 2021-08-20 17:53:54 +00:00
nicm
e463e8622d Remove stray spaces after function names. 2021-08-20 17:50:42 +00:00
nicm
01b13de655 Fill colour palette correctly from option for new panes, GitHub issue
2831.
2021-08-20 17:36:03 +00:00
Nicholas Marriott
41822ef782 Regress fixes. 2021-08-20 18:20:49 +01:00
Nicholas Marriott
5ed5b11b45 Add zeraphel complex binding to regress. 2021-08-20 14:34:44 +01:00
Thomas Adam
84955e3d62 Merge branch 'obsd-master' into master 2021-08-20 12:01:15 +01:00
nicm
f984446d19 Actually parse contents of {} as a command and then convert to a string
instead of just copying arguments around as strings.
2021-08-20 09:06:26 +00:00
Thomas Adam
0f02fecd95 Merge branch 'obsd-master' into master 2021-08-20 10:01:21 +01:00
Nicholas Marriott
28d26fca35 Update a regress conf for new syntax. 2021-08-20 07:58:44 +01:00
Nicholas Marriott
3676779156 Fix format test for new behaviour. 2021-08-20 07:58:44 +01:00
nicm
3177d7b617 Add a helper function for actually parsing the command. 2021-08-20 06:30:57 +00:00
Thomas Adam
551bafc18d Merge branch 'obsd-master' into master 2021-08-18 20:01:17 +01:00
nicm
5413a73ded Need to flatten arguments for aliases. 2021-08-18 15:16:33 +00:00
Thomas Adam
c587ad027f Merge branch 'obsd-master' into master 2021-08-18 12:01:19 +01:00
nicm
82836c7394 Push the conversion of {} to string up out of the parser and into the
command builder.
2021-08-18 10:15:08 +00:00
Thomas Adam
a8be47f0f4 Merge branch 'obsd-master' into master 2021-08-17 22:01:18 +01:00
nicm
5fdea440ce Treat a pane that has died the same as no pane when sending data to
control mode clients, GitHub issue 2828.
2021-08-17 20:17:21 +00:00
nicm
66aaa9e484 Fix pipe-pane usage. 2021-08-17 19:37:55 +00:00
nicm
2b0d798982 Do not block with incremental command prompt. 2021-08-17 19:26:42 +00:00
Thomas Adam
bacae4b4ad Merge branch 'obsd-master' into master 2021-08-17 18:01:16 +01:00
nicm
4f62aadc93 Set the right session if detach-on-destroy is off. 2021-08-17 16:19:00 +00:00
Thomas Adam
7869ec87e0 Merge branch 'obsd-master' into master 2021-08-17 14:01:16 +01:00
nicm
de9697b456 calloc for confirm-before data since the item needs to start NULL. 2021-08-17 11:20:13 +00:00
Thomas Adam
0dad8dd982 Merge branch 'obsd-master' into master 2021-08-17 10:01:19 +01:00
nicm
41ababdf6c Be more sophisticated about enabling synchronized updates when there is
an overlay and treat it like the active pane (use for commands which
move the cursor only). When there is an overlay also use it for all
panes and not just the active pane. GitHub issue 2826.
2021-08-17 08:44:52 +00:00
nicm
1a7eb6ca90 Revert previous; this is not how it should work. 2021-08-17 08:22:44 +00:00
nicm
158f0e8c41 Start sync before drawing popup. 2021-08-17 07:14:33 +00:00
Nicholas Marriott
f2d4a1f022 Needs fcntl.h. 2021-08-16 13:51:55 +01:00
Nicholas Marriott
21ce1e04fe Fuzzer needs some other bits it seems. 2021-08-14 22:30:20 +01:00
Nicholas Marriott
c1be1b351d Minor cleanups, GitHub issue 2824. 2021-08-14 18:39:56 +01:00
Thomas Adam
22e5fc02c3 Merge branch 'obsd-master' into master 2021-08-14 18:01:17 +01:00
nicm
30786abe0e Some other missing palette NULL checks, from oss-fuzz. 2021-08-14 16:26:29 +00:00
Thomas Adam
3f8954b11b Merge branch 'obsd-master' into master 2021-08-14 16:01:17 +01:00
nicm
befe7cb1c5 Do not use NULL palette when clearing. 2021-08-14 14:00:07 +00:00
Thomas Adam
65a539c02e Merge branch 'obsd-master' into master 2021-08-14 10:01:18 +01:00
nicm
4cc6db7281 Missing argument specifier for -c. 2021-08-14 08:06:37 +00:00
Thomas Adam
79f075bf1b Merge branch 'obsd-master' into master 2021-08-14 01:35:27 +01:00
Thomas Adam
54773d23b5 Merge branch 'obsd-master' into master 2021-08-14 01:34:54 +01:00
nicm
7d7d7c9605 Tweak how mouse works on popup: only Meta alone resizes or moves, not
Meta with other modifiers; button 2 on the left or top border opens
menu, right or bottom resizes; button 1 on any border moves.
2021-08-13 23:05:40 +00:00
nicm
63aa968642 Check callback needs to only return 0 (text should be suppressed) if
menu returns 0, otherwise it should check the popup also.
2021-08-13 20:04:45 +00:00
nicm
7a0cec5ecf Fill in some other bits on new panes. 2021-08-13 19:55:11 +00:00
nicm
2588c3e52e Add menu options to convert a popup into a pane. 2021-08-13 19:27:25 +00:00
nicm
92615b534a Adjust overlay check callback before drawing data from pty. 2021-08-13 19:25:24 +00:00
nicm
7789639b5d Add a menu when a popup is present (mouse only for now). 2021-08-13 18:54:54 +00:00
nicm
614611a8bd Add -B flag to remove border from popup. 2021-08-13 17:03:29 +00:00
Nicholas Marriott
4c07367bfe Fix fuzzer wrapper. 2021-08-13 13:45:45 +01:00
nicm
13a0da205b Break message type stuff out into its own header. 2021-08-13 07:37:58 +00:00
nicm
2bb0b9d6c5 Change focus to be driven by events rather than walking all panes at end
of event loop, this way the ordering of in and out can be enforced.
GitHub issue 2808.
2021-08-13 06:52:51 +00:00
nicm
a2b8506917 Set return code for confirm-before and make command-prompt also block,
GitHub issue 2822.
2021-08-13 06:50:42 +00:00
Thomas Adam
f725f9bc8a Merge branch 'obsd-master' into master 2021-08-13 00:01:19 +01:00
Thomas Adam
94d96c6179 Merge branch 'obsd-master' into master 2021-08-12 22:01:22 +01:00
nicm
e2f6f58fe5 Make newline a style delimiter as well so they can cross multiple lines
for readability.
2021-08-12 20:46:30 +00:00
nicm
db9195463d Now that styles can contain formats, they need to be expanded when
inserted into the status line.
2021-08-12 20:44:49 +00:00
nicm
6feb8f6505 Use COLOUR_DEFAULT not hardcoded 8. 2021-08-12 20:09:34 +00:00
nicm
9b00472820 Evaluate styles with the pane variables. 2021-08-12 19:47:05 +00:00
Thomas Adam
9d7b1960c2 Merge branch 'obsd-master' into master 2021-08-12 14:01:18 +01:00
nicm
5d451551b6 Restore saved cursor position after a ZWJ rather than recalculating it. 2021-08-12 11:35:53 +00:00
Thomas Adam
fada3eb932 Merge branch 'obsd-master' into master 2021-08-12 10:01:22 +01:00
nicm
26773ea9ef Do not dereference pane when it is NULL, fixes a crash when creating a
hook from the config, GitHub issue 2820.
2021-08-12 08:10:20 +00:00
nicm
163908fe8a Move hook format setup earlier and add a hook_client, GitHub issue 2809. 2021-08-12 08:05:11 +00:00
Thomas Adam
44ada9cd67 Merge branch 'obsd-master' into master 2021-08-12 00:01:26 +01:00
nicm
7eea3d7ab8 Break the colour palette into a struct rather than just a single array
and use that to support the OSC palette-setting sequences in popups.
Also add a pane-colours array option to specify the defaults. GitHub
issue 2815.
2021-08-11 20:49:55 +00:00
nicm
01fd4b997e Add pipe variants of the line copy commands. While here make the command
list less unreadable. GitHub issue 2813.
2021-08-11 20:35:46 +00:00
Thomas Adam
e9d49161e0 Merge branch 'obsd-master' into master 2021-08-11 12:01:20 +01:00
nicm
9013600074 Return to applying pane-border-style to the area outside panes, GitHub
issue 2816.
2021-08-11 09:05:21 +00:00
Thomas Adam
7a06b92061 Merge branch 'obsd-master' into master 2021-08-11 10:01:20 +01:00
nicm
338ec859a4 Make confirm-before optionally block the invoking client like run-shell,
GitHub issue 2819.
2021-08-11 08:40:58 +00:00
nicm
f6755c6f2c OSC 52 can be long enough to make tmux think the output buffer is too
big, so treat it as a redraw. GitHub issue 2814.
2021-08-11 07:51:31 +00:00
Nicholas Marriott
705411ea5c Tweak comment about logs. 2021-08-10 08:14:14 +01:00
Thomas Adam
9d80ec6cc9 Merge branch 'obsd-master' into master 2021-08-09 16:01:35 +01:00
nicm
be5988457f Change copy-line and copy-end-of-line not to cancel and add -and-cancel
variants, like the other copy commands. GitHub issue 2799.
2021-08-09 13:08:08 +00:00
Thomas Adam
33e332428c Merge branch 'obsd-master' into master 2021-08-06 12:01:24 +01:00
nicm
24cd6851f6 Add basic support for zero width joiners, GitHub issues 1605 and 2784. 2021-08-06 09:34:09 +00:00
nicm
19812b2d29 Add client focus hooks. 2021-08-06 09:19:02 +00:00
Thomas Adam
4bccff9556 Merge branch 'obsd-master' into master 2021-08-06 10:01:17 +01:00
nicm
ef5602a590 Another minor fix - do not draw positions that are under the popup with
spaces, from Anindya Mukherjee. Also a typo fix from Linus Arver.
2021-08-06 07:32:21 +00:00
Thomas Adam
acd70ea643 Merge branch 'obsd-master' into master 2021-08-06 06:01:18 +01:00
nicm
950d3c5bbc Tweak previous not to replace complete characters with spaces. 2021-08-06 03:29:15 +00:00
nicm
97b5962ab1 Correctly draw wide characters that are partially obscured. 2021-08-06 03:13:05 +00:00
Thomas Adam
e3fa6cd96c Merge branch 'obsd-master' into master 2021-08-05 12:01:19 +01:00
nicm
93cc8df692 Do not freeze output in panes when a popup is open, let them continue to
redraw. From Anindya Mukherjee .
2021-08-05 09:43:51 +00:00
Thomas Adam
4b88872c85 Merge branch 'obsd-master' into master 2021-08-04 10:01:25 +01:00
Nicholas Marriott
c063831df5 Do not configure on macOS without the user making a choice about utf8proc. 2021-08-04 09:49:08 +01:00
nicm
42490f4750 Add a client-active hook, from ncfavier in GitHub issue 2803. 2021-08-04 08:07:19 +00:00
Thomas Adam
63f9f3113c Merge branch 'obsd-master' into master 2021-07-28 10:01:19 +01:00
nicm
e37aa45681 Make window-linked and window-unlinked window options, GitHub issue
2790.
2021-07-28 07:06:54 +00:00
Thomas Adam
7cbf4c9027 Merge branch 'obsd-master' into master 2021-07-21 10:01:24 +01:00
nicm
78ec057916 Do not add height twice when calculating popup_mouse_top, from M Kelly. 2021-07-21 08:09:43 +00:00
nicm
f0e02387b2 Do not close popups on resize, instead adjust them to fit, from Anindya
Mukherjee.
2021-07-21 08:06:36 +00:00
Thomas Adam
e3ff887d2a Merge branch 'obsd-master' into master 2021-07-14 12:01:21 +01:00
Nicholas Marriott
0ea6cdca90 Need all of the TAILQ bits. 2021-07-14 11:09:28 +01:00
Nicholas Marriott
d723466df2 Pick default-terminal from the first of tmux-256color, tmux, screen-256color,
screen that is available on the build system.
2021-07-14 11:03:19 +01:00
nicm
732c72c98e Move default value for TERM into tmux.h. 2021-07-14 08:56:00 +00:00
Thomas Adam
bb4bc8caf4 Merge branch 'obsd-master' into master 2021-07-14 00:01:21 +01:00
nicm
38c5788232 Give #() commands a one second grace period where the output is empty
before telling the user they aren't doing anything. GitHub issue 2774.
2021-07-13 22:09:29 +00:00
Thomas Adam
7496e70bd7 Merge branch 'obsd-master' into master 2021-07-13 12:01:19 +01:00
nicm
df3fe2aa72 Only use client for sizing when not detached, GitHub issue 2772. 2021-07-13 10:38:57 +00:00
Thomas Adam
c1d5dda62e Merge branch 'obsd-master' into master 2021-07-08 14:01:21 +01:00
nicm
51915b9b0a Fix mouse_word format now word-separators has no space and position of
menu if too close to the bottom.
2021-07-08 11:14:53 +00:00
Thomas Adam
ed575182e3 Merge branch 'obsd-master' into master 2021-07-06 10:01:22 +01:00
nicm
32f2d9d089 Improve error reporting when the tmux /tmp directory cannot be created
or used, GitHub issue 2765 from Uwe Kleine-Koenig.
2021-07-06 08:26:00 +00:00
nicm
35c2958ae4 Forbid empty session names, GitHub issue 2758. 2021-07-06 08:18:38 +00:00
Nicholas Marriott
b1a8c0fe02 Fix crosscompiling, Marco A L Barbosa. 2021-06-22 12:16:48 +01:00
Thomas Adam
3dfb77416f Merge branch 'obsd-master' into master 2021-06-18 09:52:47 +01:00
nicm
1d4296f17f Mention %1 under choose-tree also. 2021-06-18 07:46:54 +00:00
nicm
a83fb8127a Minor fixes to option descriptions. 2021-06-16 11:57:04 +00:00
nicm
9f3874e5c7 Pass Ctrl keys through as is when given as hex, GitHub issue 2724. 2021-06-16 08:37:58 +00:00
Nicholas Marriott
87521214d3 Fix incorrect option name, from Gregory Pakosz. 2021-06-15 09:44:56 +01:00
Nicholas Marriott
6a8d848a3e Once a day. 2021-06-11 08:30:51 +01:00
jmc
0d0683c28a fix some formatting errors; 2021-06-10 13:12:31 +00:00
Nicholas Marriott
96ad8280b2 Tweak. 2021-06-10 13:05:22 +01:00
Nicholas Marriott
0490707671 Move lock.yml. 2021-06-10 09:56:35 +01:00
Nicholas Marriott
ac98385e55 Merge branch '3.2a' 2021-06-10 09:26:38 +01:00
Nicholas Marriott
57aaad2ddb Update CHANGES. 2021-06-10 09:25:50 +01:00
Nicholas Marriott
3b929f332a Update CHANGES. 2021-06-10 09:24:57 +01:00
Nicholas Marriott
c827f5092d Do not clear region based on current cursor position, this is not necessary
anymore and causes problems, GitHub issue 2735.
2021-06-10 09:23:54 +01:00
Nicholas Marriott
d8feffd2bf Feature for the mouse since FreeBSD termcap does not have kmous. 2021-06-10 09:23:48 +01:00
Nicholas Marriott
f48c46a76a Fix rectangle selection, from Anindya Mukherjee, GitHub issue 2709. 2021-06-10 09:23:43 +01:00
Nicholas Marriott
f06ee2b87b Bump FORMAT_LOOOP_LIMIT and add a log message when hit, GitHub issue 2715. 2021-06-10 09:23:34 +01:00
Nicholas Marriott
9b4c05b6b9 Er, fix it properly. 2021-06-10 09:23:30 +01:00
Nicholas Marriott
3b9b823df5 Fix <= operator. 2021-06-10 09:23:25 +01:00
Nicholas Marriott
8aa34f616f Do not use NULL client when source-file finishes, GitHub issue 2707. 2021-06-10 09:23:15 +01:00
Nicholas Marriott
5ea6ccbb7f Do not expand the file given with -f so it can contain :s. 2021-06-10 09:23:07 +01:00
Nicholas Marriott
434ac8734a Looks like evports on SunOS are broken also, disable them. GitHub issue 2702. 2021-06-10 09:23:03 +01:00
Nicholas Marriott
47af583a50 Remove old shift function keys which interfere with xterm keys now. GitHub
issue 2696.
2021-06-10 09:22:51 +01:00
Nicholas Marriott
aaf87abfb4 Fire check callback after cleaning up event so it does not get stuck, from
Jeongho Jang in GitHub issue 2695.
2021-06-10 09:22:47 +01:00
Nicholas Marriott
bacb4d1b4d Fix warnings, from Jan Tache in GitHub issue 2692. 2021-06-10 09:22:39 +01:00
Nicholas Marriott
ad2f7642f2 Ctrl keys are < 0x7f, not Unicode. 2021-06-10 09:22:13 +01:00
Nicholas Marriott
059580e0f7 Move "special" keys into the Unicode PUA rather than making them high a top bit
set, some compilers cannot handle enums that are larger than int. GitHub issue
2673.
2021-06-10 09:22:07 +01:00
Nicholas Marriott
cb2943faab Change resize timers and flags into one timer and a queue to fix problems with
vim when resized multiple times. GitHub issue 2677.
2021-06-10 09:21:55 +01:00
Nicholas Marriott
7c28597e0f Mention S- for Shift, GitHub issue 2683. 2021-06-10 09:21:42 +01:00
Nicholas Marriott
fb52921a86 Do not count client if no window. 2021-06-10 09:21:34 +01:00
Nicholas Marriott
ddc67152a5 Three changes to fix problems with xterm in VT340 mode, reported by Thomas
Sattler.

1) Do not include the DECSLRM or DECFRA features for xterm; they will be added
   instead if secondary DA responds as VT420 (this happens already).

2) Set or reset the individual flags after terminal-overrides is applied, so
   the user can properly disable them.

3) Add a capability for DECFRA ("Rect").
2021-06-10 09:21:26 +01:00
Nicholas Marriott
4cf595a402 Include current client in size calcultion for new sessions, GitHub issue 2662. 2021-06-10 09:21:16 +01:00
Nicholas Marriott
5107e84897 Add an "always" value to the extended-keys option to always forward these keys
to applications inside tmux.
2021-06-10 09:21:09 +01:00
Nicholas Marriott
736a276cc9 Minor CHANGES and tmux.1 fixed, from Daniel Hahler, GitHub issue 2664. 2021-06-10 09:21:05 +01:00
Nicholas Marriott
825feac9f8 Add another couple of keys needed for extended keys, GitHub issue 2658. 2021-06-10 09:20:56 +01:00
Nicholas Marriott
d8c0069254 Use = not ==, from Leonardo Taccari. 2021-06-10 09:20:51 +01:00
Nicholas Marriott
33d4f854c0 back-to-indentation fixes, from Anindya Mukherjee. 2021-06-10 09:20:42 +01:00
Nicholas Marriott
9865ad27a5 Fix display-menu -xR, from Alexis Hildebrandt. 2021-06-10 09:20:33 +01:00
Nicholas Marriott
16b497e12b Apple have broken strtonum so check it works, from Teubel Gyorgy. 2021-06-10 09:20:28 +01:00
Nicholas Marriott
a25af7d0f3 Adjust latest client when a client detaches, GitHub issue 2657. 2021-06-10 09:20:22 +01:00
Nicholas Marriott
a11aa870b3 Handle modifier 9 as Meta, GitHub issue 2647. 2021-06-10 09:20:15 +01:00
Nicholas Marriott
0431d4d639 Add crosscompiling fallbacks, from Hasso Tepper. 2021-06-10 09:20:07 +01:00
nicm
d863978464 %begin now has three arguments, not two. GitHubs issue 2646. 2021-06-10 09:20:02 +01:00
nicm
57d5f67552 Include modifiers when looking up an individual key. 2021-06-10 09:19:56 +01:00
nicm
bab7a9a085 Change how extended ctrl keys are processed to fix C-S-Tab and C-;. 2021-06-10 09:19:49 +01:00
Nicholas Marriott
2ab53d30d0 3.2a version. 2021-06-10 09:17:46 +01:00
Nicholas Marriott
d25738b61e Update CHANGES. 2021-06-10 09:16:14 +01:00
nicm
a35c897f0f Do not clear region based on current cursor position, this is not
necessary anymore and causes problems, GitHub issue 2735.
2021-06-10 07:59:31 +00:00
nicm
1e879ef458 Feature for the mouse since FreeBSD termcap does not have kmous. 2021-06-10 07:59:08 +00:00
nicm
43514f4af6 Fix rectangle selection, from Anindya Mukherjee, GitHub issue 2709. 2021-06-10 07:58:42 +00:00
nicm
8d75542986 Bump FORMAT_LOOOP_LIMIT and add a log message when hit, GitHub issue 2715. 2021-06-10 07:58:08 +00:00
nicm
3a5b576399 Fix <= operator. 2021-06-10 07:57:06 +00:00
nicm
77b1290698 More accurate vi(1) word navigation in copy mode and on the status line.
This changes the meaning of the word-separators option - setting it to
the empty string is equivalent to the previous behavior. From Will Noble
in GitHub issue 2693.
2021-06-10 07:56:47 +00:00
nicm
77bd6b9ec3 Do not use NULL client when source-file finishes, GitHub issue 2707. 2021-06-10 07:53:19 +00:00
nicm
1bbdd2aba2 Add -F for command-prompt and use it to fix "Rename" on the window menu,
GitHub issue 2699.
2021-06-10 07:52:56 +00:00
nicm
73bf358f6d Do not expand the file given with -f so it can contain :s. 2021-06-10 07:52:29 +00:00
nicm
f706a7e236 Remove old shift function keys which interfere with xterm keys now.
GitHub issue 2696.
2021-06-10 07:52:07 +00:00
nicm
cfc7c9cf24 Fire check callback after cleaning up event so it does not get stuck,
from Jeongho Jang in GitHub issue 2695.
2021-06-10 07:51:43 +00:00
nicm
866117636e Add different command historys for different types of prompts
("command", "search" etc). From Anindya Mukherjee.
2021-06-10 07:50:03 +00:00
nicm
6c659494f5 Fix warnings, from Jan Tache in GitHub issue 2692. 2021-06-10 07:45:43 +00:00
nicm
02a6b39db7 Improve logging of screen mode changes. 2021-06-10 07:43:44 +00:00
nicm
f02a6c34e0 Move "special" keys into the Unicode PUA rather than making them top bit
set, some compilers do not allow enums that are larger than int. GitHub
issue 2673.
2021-06-10 07:38:28 +00:00
nicm
f9f97c8145 Change cursor style handling so tmux understands which sequences contain
blinking and sets the flag appropriately, means that it works whether
cnorm disables blinking or not. GitHub issue 2682.
2021-06-10 07:36:47 +00:00
nicm
84e22168a5 Change resize timers and flags into one timer and a queue which is
simpler and fixes problems with vim when resized multiple times. GitHub
issue 2677.
2021-06-10 07:33:41 +00:00
nicm
b573dbba90 Do not count client (and crash) if no window. 2021-06-10 07:29:45 +00:00
nicm
0c5cbbbf5c Three changes to fix problems with xterm in VT340 mode, reported by
Thomas Sattler.

1) Do not include the DECSLRM or DECFRA features for xterm; they will be
   added instead if secondary DA responds as VT420 (this happens
   already).

2) Set or reset the individual flags after terminal-overrides is
   applied, so the user can properly disable them.

3) Add a capability for DECFRA ("Rect").
2021-06-10 07:28:45 +00:00
nicm
9f38a8807c Include current client in size calculation for new sessions, GitHub
issue 2662.
2021-06-10 07:24:45 +00:00
nicm
64c276c23b Add an "always" value to the extended-keys option to always forward
these keys to applications inside tmux.
2021-06-10 07:24:10 +00:00
nicm
1ee231956c back-to-indentation fixes, from Anindya Mukherjee. 2021-06-10 07:22:37 +00:00
nicm
788f56b40a Fix display-menu -xR, from Alexis Hildebrandt. 2021-06-10 07:22:06 +00:00
nicm
c46a607dc1 Adjust latest client when a client detaches, GitHub issue 2657. 2021-06-10 07:21:46 +00:00
nicm
e5106bfb96 Add another couple of keys needed for extended keys, GitHub issue 2658.
Handle modifier 9 as Meta, GitHub issue 2647.
2021-06-10 07:21:09 +00:00
Nicholas Marriott
747423be67 Fix empty format strings, from Jean-Philippe Menil. 2021-06-10 08:08:31 +01:00
Nicholas Marriott
607e6b1c33 Do not clear region based on current cursor position, this is not necessary
anymore and causes problems, GitHub issue 2735.
2021-06-09 14:46:24 +01:00
Nicholas Marriott
7a236869ba Feature for the mouse since FreeBSD termcap does not have kmous. 2021-06-08 10:49:40 +01:00
Nicholas Marriott
9ea971dc04 Fix rectangle selection, from Anindya Mukherjee, GitHub issue 2709. 2021-05-19 09:05:53 +01:00
Nicholas Marriott
5f7ff732fa Bump FORMAT_LOOOP_LIMIT and add a log message when hit, GitHub issue 2715. 2021-05-19 09:04:45 +01:00
Nicholas Marriott
83024f57a6 Er, fix it properly. 2021-05-17 06:59:29 +01:00
Nicholas Marriott
01ba6a23f2 Fix <= operator. 2021-05-17 06:58:45 +01:00
Nicholas Marriott
022d0210c5 More accurate vi(1) word navigation in copy mode and on the status line. This
changes the meaning of the word-separators option - setting it to the empty
string is equivalent to the previous behavior. From Will Noble in GitHub issue
2693.
2021-05-13 08:49:58 +01:00
Nicholas Marriott
f03b27c72b Do not use NULL client when source-file finishes, GitHub issue 2707. 2021-05-12 07:08:58 +01:00
Nicholas Marriott
4ca6b42c24 Add -F for command-prompt and use it to fix "Rename" on the window menu, GitHub
issue 2699.
2021-05-10 07:52:30 +01:00
Nicholas Marriott
bde3829131 Do not expand the file given with -f so it can contain :s. 2021-05-10 07:51:30 +01:00
Nicholas Marriott
d00d682069 Looks like evports on SunOS are broken also, disable them. GitHub issue 2702. 2021-05-10 07:42:35 +01:00
Nicholas Marriott
f2951bd4a5 Remove old shift function keys which interfere with xterm keys now. GitHub
issue 2696.
2021-05-05 07:23:23 +01:00
Nicholas Marriott
8da4573088 Fire check callback after cleaning up event so it does not get stuck, from
Jeongho Jang in GitHub issue 2695.
2021-05-03 10:49:51 +01:00
Nicholas Marriott
c03b57465b Add different command historys for different types of prompts ("command",
"search" etc). From Anindya Mukherjee.
2021-05-03 07:39:32 +01:00
Nicholas Marriott
40467726e3 Fix warnings, from Jan Tache in GitHub issue 2692. 2021-05-03 06:39:17 +01:00
Nicholas Marriott
2e7ec8c0b9 Improve logging of screen mode changes. 2021-04-30 20:14:10 +01:00
Nicholas Marriott
32c97a7f2f Ctrl keys are < 0x7f, not Unicode. 2021-04-28 20:20:53 +01:00
Nicholas Marriott
e2d01795d2 Move "special" keys into the Unicode PUA rather than making them high a top bit
set, some compilers cannot handle enums that are larger than int. GitHub issue
2673.
2021-04-28 09:18:04 +01:00
Nicholas Marriott
589d3eb48f Change cursor style handling so tmux understands which sequences contain
blinking and sets the flag appropriately, means that it works whether cnorm
disables blinking or not. GitHub issue 2682.
2021-04-28 09:17:13 +01:00
Nicholas Marriott
cf6034da92 Change resize timers and flags into one timer and a queue to fix problems with
vim when resized multiple times. GitHub issue 2677.
2021-04-28 09:16:30 +01:00
Nicholas Marriott
ce8c56cc97 Mention S- for Shift, GitHub issue 2683. 2021-04-27 08:29:54 +01:00
Nicholas Marriott
43c292fa91 Revert "Revert "Add crosscompiling fallbacks, from Hasso Tepper.""
This reverts commit dda3bf896be9ce87b4066636cc7f94ab8030133a.
2021-04-23 17:18:51 +01:00
Nicholas Marriott
cb9a0627f0 Do not count client if no window. 2021-04-23 13:41:49 +01:00
Nicholas Marriott
7a6446ac17 Three changes to fix problems with xterm in VT340 mode, reported by Thomas
Sattler.

1) Do not include the DECSLRM or DECFRA features for xterm; they will be added
   instead if secondary DA responds as VT420 (this happens already).

2) Set or reset the individual flags after terminal-overrides is applied, so
   the user can properly disable them.

3) Add a capability for DECFRA ("Rect").
2021-04-22 09:01:22 +01:00
Nicholas Marriott
cd6af4a52e Include current client in size calcultion for new sessions, GitHub issue 2662. 2021-04-21 09:47:03 +01:00
Nicholas Marriott
8363c6af2e Add an "always" value to the extended-keys option to always forward these keys
to applications inside tmux.
2021-04-21 09:32:48 +01:00
Nicholas Marriott
6c2bf0e221 Minor CHANGES and tmux.1 fixed, from Daniel Hahler, GitHub issue 2664. 2021-04-20 06:37:01 +01:00
Nicholas Marriott
88575a27e2 Add another couple of keys needed for extended keys, GitHub issue 2658. 2021-04-20 06:35:54 +01:00
Nicholas Marriott
3a892228f4 Use = not ==, from Leonardo Taccari. 2021-04-18 08:48:03 +01:00
Nicholas Marriott
5fa8e5e13f back-to-indentation fixes, from Anindya Mukherjee. 2021-04-18 08:47:11 +01:00
Nicholas Marriott
73cf767a35 Fix display-menu -xR, from Alexis Hildebrandt. 2021-04-16 12:12:50 +01:00
Nicholas Marriott
b2588eed03 Apple have broken strtonum so check it works, from Teubel Gyorgy. 2021-04-16 12:07:54 +01:00
Nicholas Marriott
9af78c8e69 Adjust latest client when a client detaches, GitHub issue 2657. 2021-04-16 11:59:08 +01:00
Nicholas Marriott
dda3bf896b Revert "Add crosscompiling fallbacks, from Hasso Tepper."
This reverts commit bb6242675ad0c7447daef148fffced882e5b4a61.
2021-04-15 16:10:31 +01:00
Nicholas Marriott
98650658a7 Handle modifier 9 as Meta, GitHub issue 2647. 2021-04-15 08:22:36 +01:00
Thomas Adam
6f6b7f8261 Merge branch 'obsd-master' into master 2021-04-15 08:01:23 +01:00
Nicholas Marriott
bb6242675a Add crosscompiling fallbacks, from Hasso Tepper. 2021-04-15 06:46:11 +01:00
nicm
33f9b08bbb %begin now has three arguments, not two. GitHubs issue 2646. 2021-04-15 05:38:11 +00:00
Thomas Adam
e88d48f804 Merge branch 'obsd-master' into master 2021-04-13 18:01:17 +01:00
nicm
dfcc9f8cbc Include modifiers when looking up an individual key. 2021-04-13 16:00:47 +00:00
Thomas Adam
16f1c5f0a1 Merge branch 'obsd-master' into master 2021-04-13 14:01:21 +01:00
nicm
bbb3509bc5 Change how extended ctrl keys are processed to fix C-S-Tab and C-;. 2021-04-13 12:26:34 +00:00
Nicholas Marriott
c5c2871d22 Merge branch '3.2-rc' 2021-04-13 08:46:21 +01:00
nicm
bc4681c83d Move mode set/reset after sync so cursor doesn't flicker, from Avi
Halachmi.
2021-04-13 08:37:57 +01:00
nicm
f29d3c7f74 Handle C-Tab correctly with extended keys, GitHub issue 2642. 2021-04-13 08:37:57 +01:00
Thomas Adam
90614dfe05 Merge branch 'obsd-master' into master 2021-04-13 08:01:22 +01:00
Nicholas Marriott
30cf20d615 Update CHANGES. 2021-04-13 06:28:16 +01:00
Nicholas Marriott
c2048c5c65 Merge branch 'master' into 3.2-rc 2021-04-13 06:25:59 +01:00
nicm
ff860e5fe4 Move mode set/reset after sync so cursor doesn't flicker, from Avi
Halachmi.
2021-04-13 05:25:05 +00:00
nicm
715835510b Handle C-Tab correctly with extended keys, GitHub issue 2642. 2021-04-13 05:23:34 +00:00
Thomas Adam
bedf2bd437 Merge branch 'obsd-master' into master 2021-04-12 12:01:32 +01:00
nicm
e6abe55134 Add a flag to disable keys to close a message, GitHub issue 2625. 2021-04-12 09:36:12 +00:00
Thomas Adam
83cd593b9c Merge branch 'obsd-master' into master 2021-04-12 10:01:27 +01:00
nicm
cd208c9d72 Permit shortcut keys in buffer, client, tree modes to be configured with
a format; the default remains the line number. GitHub issue 2636.
2021-04-12 06:50:25 +00:00
Thomas Adam
7579097db6 Merge branch 'obsd-master' into master 2021-04-09 10:01:19 +01:00
nicm
73cbe46f8d Change a type to fix a warning with some compilers. 2021-04-09 07:02:00 +00:00
Thomas Adam
caf7aeb3a9 Merge branch 'obsd-master' into master 2021-04-08 16:01:17 +01:00
nicm
30fb628388 Log the key written to the terminal as well as tmux's idea of what it
is.
2021-04-08 14:16:12 +00:00
Thomas Adam
a57c2bf97e Merge branch 'obsd-master' into master 2021-04-07 18:01:20 +01:00
nicm
efb5e58c38 Restore previous behaviour so that C-X remains the same as C-x. Instead,
translate incoming extended keys so that they are consistent.
2021-04-07 15:46:12 +00:00
Thomas Adam
3cd63cc9e0 Merge branch 'obsd-master' into master 2021-04-07 16:01:21 +01:00
nicm
71fc9f3ee8 Add a current_file format for the config file being parsed. Originally
suggested by kn@, also GitHub issue 2638.
2021-04-07 12:50:12 +00:00
nicm
1ac47400d2 When display-message used in config file, show the message after the
config file finishes. GitHub issue 2637.
2021-04-07 12:49:33 +00:00
Thomas Adam
998a6b0aea Merge branch 'obsd-master' into master 2021-04-07 10:01:19 +01:00
nicm
ba99996676 Fixes for extended keys: 1) allow C-x and C-X to be bound separately
since some terminals report them differently 2) use the "backspace"
option to translate backspace 3) map ctrl which are have the ctrl
implied (such as C-x) properly when the terminal reports both the key
and the modifier.

Note that any key bindings for C-X where C-x is meant must now be
changed.
2021-04-07 07:30:02 +00:00
Thomas Adam
db97bef60b Merge branch 'obsd-master' into master 2021-04-05 16:01:23 +01:00
nicm
10470cea67 Move client-detached into server_client_lost so it is fired even if a
client is closed unexpectedly.
2021-04-05 14:11:05 +00:00
Thomas Adam
22ccae1c9d Merge branch 'obsd-master' into master 2021-04-05 10:01:19 +01:00
nicm
5900b164a4 Fix a couple of edge cases with the jump-back-xxx commands, and also
update back-to-indentation to use grid_reader, thereby fixing line
wrapping issues. From Anindya Mukherjee, GitHub issue 2633.
2021-04-05 08:43:48 +00:00
Thomas Adam
b307fc8cd5 Merge branch 'obsd-master' into master 2021-04-01 12:01:25 +01:00
nicm
28cd956729 Change search-again with vi keys to work like actual vi(1), also some
other fixes. From Aaron Jensen with help from Anindya Mukherjee.
2021-04-01 06:46:12 +00:00
nicm
6c98f222e9 Missing commas, from Vipul Kumar. 2021-04-01 06:37:46 +00:00
Thomas Adam
8f5ff4bf66 Merge branch 'obsd-master' into master 2021-03-31 10:01:16 +01:00
nicm
a4b9b5a1e5 Do not exit if cannot write to normal log file, GitHub issue 2630. 2021-03-31 08:37:48 +00:00
Nicholas Marriott
4208641de7 Remove queue.h, from Simon Holesch. 2021-03-28 10:16:17 +01:00
Thomas Adam
be568ea3b2 Merge branch 'obsd-master' into master 2021-03-16 10:01:20 +00:00
nicm
8b800b41c9 Add client-detached notification in control mode, from Mohsin Kaleem. 2021-03-16 09:14:58 +00:00
Thomas Adam
60bb8fa86d Merge branch 'obsd-master' into master 2021-03-15 14:01:17 +00:00
nicm
9017af2355 Do not crash if there is no item to show command error, from Anindya
Mukherjee.
2021-03-15 13:06:33 +00:00
Thomas Adam
7019937b52 Merge branch 'obsd-master' into master 2021-03-12 10:01:18 +00:00
nicm
e8224fb0d1 Fix so tmux correctly sends the cvvis (cursor very visible) capability
rather than sending it and then immediately undoing it with cnorm. Also
turn it off when the cursor shape is changed like xterm.
2021-03-12 08:39:17 +00:00
Nicholas Marriott
46cbbe3d45 Merge branch 'master' into 3.2-rc 2021-03-11 08:41:19 +00:00
Nicholas Marriott
ef9700816f malloc_trim is itself very poor and gets slower and slower as the heap becomes
more fragmented. Run it only once an hour. GitHub issue 2551.
2021-03-11 08:39:41 +00:00
Thomas Adam
12cfd0d22b Merge branch 'obsd-master' into master 2021-03-11 08:01:29 +00:00
nicm
ee0df1b8f8 Tidy old jobs every hour instead of every 30 seconds. 2021-03-11 07:08:18 +00:00
nicm
3eb91efba1 Add an "absolute-centre" alignment to use the centre of the total space
instead of only the available space. From Magnus Gross in GitHub issue 2578.
2021-03-11 06:41:04 +00:00
nicm
d98f9f7fe5 Add split-window -Z to start the pane zoomed, GitHub issue 2591. 2021-03-11 06:31:05 +00:00
Thomas Adam
541872bc57 Merge branch 'obsd-master' into master 2021-03-09 14:01:24 +00:00
nicm
7f87280cd5 Allow cursor to be just after match if copying, GitHub issue 2602. 2021-03-09 13:07:50 +00:00
Thomas Adam
ff77658f27 Merge branch 'obsd-master' into master 2021-03-09 10:01:19 +00:00
nicm
81e5736510 Copy mode improvements from Anindya Mukherjee:
- Fix word and word-end for wrapped lines.
- Fix copying of selection end on wrapped lines.
- Fix wrapped word selection edge case.
- Update select-line to respect wrapped lines.
- Update window_copy_..._pos() functions to use grid_reader.

GitHub issue 2605.
2021-03-09 08:24:09 +00:00
Nicholas Marriott
7bef887fd1 Update version. 2021-03-08 08:59:58 +00:00
Nicholas Marriott
8995d571d8 Merge branch 'master' into 3.2-rc 2021-03-08 08:59:40 +00:00
Nicholas Marriott
0792b65863 Remove compat.h again. 2021-03-08 08:59:13 +00:00
Nicholas Marriott
de4ac37baa 3.3. 2021-03-02 12:37:52 +00:00
Nicholas Marriott
b243f1b2ee No sys/queue.h. 2021-03-02 12:37:23 +00:00
Nicholas Marriott
d06c7197d4 Merge branch 'master' into 3.2-rc 2021-03-02 12:10:14 +00:00
Nicholas Marriott
fb039d5b82 paths.h is compat. 2021-03-02 12:09:59 +00:00
Nicholas Marriott
c01251d023 Merge branch 'master' into 3.2-rc 2021-03-02 12:08:34 +00:00
Nicholas Marriott
1466b570ee Update CHANGES. 2021-03-02 12:05:41 +00:00
Thomas Adam
2301bee87d Merge branch 'obsd-master' into master 2021-03-02 12:01:25 +00:00
nicm
81f9a23d25 Do not use NULL active window; also do not leak window name. GitHub
issue 2590 from Chester Liu.
2021-03-02 11:00:38 +00:00
nicm
c44750792a Drop support for popups where the content is provided directly to tmux
(which does not have many practical uses) and only support running a
program in the popup. display-popup is now simpler and can accept
multiple arguments to avoid escaping problems (like the other commands).
2021-03-02 10:56:45 +00:00
Thomas Adam
48131c6d02 Merge branch 'obsd-master' into master 2021-03-01 20:01:20 +00:00
Thomas Adam
9d99dad9e8 Merge branch 'obsd-master' into master 2021-03-01 17:54:47 +00:00
jmc
de3a898e8a escape quotes and remove some unneccessary Pp; ok nicm 2021-03-01 17:49:08 +00:00
Nicholas Marriott
9cd45ddad3 Reinstate del_curterm ifdef bits. 2021-03-01 10:51:24 +00:00
nicm
8a4a2153fd There is no need to call del_curterm in the server anymore. 2021-03-01 10:50:14 +00:00
nicm
b6dfb9996a Add some text with examples of ; as a separator, GitHub issues 2522 and
2580.
2021-03-01 10:44:38 +00:00
Thomas Adam
ba9f89c44e Merge branch 'obsd-master' into master 2021-02-27 08:01:20 +00:00
nicm
40ad11b2b5 Handle NULL term_type. 2021-02-27 06:28:16 +00:00
Thomas Adam
a7d4703bfe Merge branch 'obsd-master' into master 2021-02-27 00:01:19 +00:00
nicm
583aaebc0a Check session, window, pane in the right order when working out format type. 2021-02-26 21:53:41 +00:00
Thomas Adam
9c6502fcc9 Merge branch 'obsd-master' into master 2021-02-26 10:01:22 +00:00
nicm
dd7006c850 Add a couple of format variables for active and last window index. 2021-02-26 07:53:26 +00:00
Thomas Adam
9710ec5244 Merge branch 'obsd-master' into master 2021-02-24 10:01:19 +00:00
nicm
6aaef3e705 Correct client_prefix so it returns 1 if in prefix, not 0. 2021-02-24 09:22:15 +00:00
Thomas Adam
0982a1a975 Merge branch 'obsd-master' into master 2021-02-22 12:01:18 +00:00
nicm
6d8efe9319 expand_paths needs the global environment to be set up, do that first. 2021-02-22 11:42:50 +00:00
Thomas Adam
0cd5ed9e9b Merge branch 'obsd-master' into master 2021-02-22 10:01:22 +00:00
nicm
5f425ee318 Fix regex searching with wrapped lines, from Anindya Mukherjee; GitHub
issue 2570.
2021-02-22 08:31:19 +00:00
nicm
6876381276 Move config file path expansion much earlier, keep the list of paths
around rather than freeing later, and add a config_files format variable
containing it. Suggested by kn@ a while back.
2021-02-22 08:18:13 +00:00
Thomas Adam
cb7e6698f3 Merge branch 'obsd-master' into master 2021-02-22 08:01:22 +00:00
nicm
e858270006 There are many format variables now so allocating all the default ones
each time a tree is created is too expensive. Instead, convert them all
into callbacks and put them in a static table so they only allocate on
demand. The tree remains for the moment for extra (non-default)
variables added by for example copy mode or popups. Also reduce
expensive calls to localtime_r/strftime. GitHub issue 2253.
2021-02-22 07:09:06 +00:00
nicm
8986c8dfcd Move jump commands to grid reader, make them UTF-8 aware, and tidy up,
from Anindya Mukherjee.
2021-02-22 06:53:04 +00:00
Thomas Adam
742e670805 Merge branch 'obsd-master' into master 2021-02-19 10:01:19 +00:00
nicm
b04f8acb70 Check return value of chdir() to stop a silly warning with some
compilers, GitHub issue 2573.
2021-02-19 09:09:16 +00:00
Thomas Adam
11e404ca3c Merge branch 'obsd-master' into master 2021-02-18 16:01:18 +00:00
nicm
fb42ae3071 Reduce len when moving past spaces in OSC 11 parameter. 2021-02-18 13:30:24 +00:00
Thomas Adam
3a76a56824 Merge branch 'obsd-master' into master 2021-02-17 09:58:51 +00:00
Thomas Adam
ce5de76592 Merge branch 'obsd-master' into master 2021-02-17 09:58:12 +00:00
nicm
af3ffa9c41 Move the call to setupterm() into the client and have it pass the
results to the server over imsg, means the server does not need to enter
ncurses or read terminfo db. Old clients will not work with a new
server.
2021-02-17 07:18:36 +00:00
nicm
5c275c2a1a Log missing keys when extended keys is on rather than fatal(). 2021-02-16 09:41:55 +00:00
nicm
5df9b3650a In the end UTF-8 did not become a terminal feature, should not be listed
in man page.
2021-02-16 09:40:00 +00:00
nicm
d768fc2553 Make SGR 6 (rapid blink) the same as SGR 5 (blink) and make SGR 21 to
the same as SGR 4:2, it is an old alternative. GitHub issue 2567.
2021-02-15 14:22:35 +00:00
Nicholas Marriott
0526d074d0 OSC 11 test. 2021-02-15 09:40:50 +00:00
nicm
6642706f7b Support X11 colour names and some other variations for OSC 10/11, also
add OSC 110 and 111. GitHub issue 2567.
2021-02-15 09:39:37 +00:00
nicm
632636dba5 Do not care about the server socket closing if exiting anyway. 2021-02-12 06:52:48 +00:00
nicm
2b58c226db Add a couple of helper functions, and flush imsgs on exit. 2021-02-11 09:39:29 +00:00
nicm
79e1984962 O_TRUNC is needed in case file exists. 2021-02-11 09:03:38 +00:00
nicm
e40831a002 Move file handling protocol stuff all into file.c so it can be reused
more easily.
2021-02-11 08:28:45 +00:00
Nicholas Marriott
679b2288e8 Restore utf8proc bits that went missing, GitHub issue 2564. 2021-02-10 17:18:37 +00:00
Thomas Adam
5b6d4c4fd1 Merge branch 'obsd-master' into master 2021-02-10 08:01:20 +00:00
nicm
32186950f5 Use ~/.tmux.conf as an example rather than /etc/passwd, suggested by
deraadt@.
2021-02-10 07:17:07 +00:00
Thomas Adam
c6215b55e0 Merge branch 'obsd-master' into master 2021-02-09 16:01:18 +00:00
nicm
1492ae11a5 Do not expand times and #() inside #(). 2021-02-09 14:25:40 +00:00
Thomas Adam
8d7f341a85 Merge branch 'obsd-master' into master 2021-02-08 16:01:21 +00:00
nicm
e3005e5ec4 Add "pipe" variants of the "copy-pipe" commands which do not copy, from
Christian Zangl.
2021-02-08 14:46:53 +00:00
Thomas Adam
fe3ab51b78 Merge branch 'obsd-master' into master 2021-02-08 10:01:20 +00:00
nicm
c579be1f2a Include "focused" in client flags, from Dan Aloni in GitHub issue 2558. 2021-02-08 08:33:54 +00:00
Thomas Adam
03430887be Merge branch 'obsd-master' into master 2021-02-06 14:01:20 +00:00
nicm
1e29ebd412 In the end UTF-8 did not become a terminal feature, should not be listed
in man page.
2021-02-06 13:02:52 +00:00
Thomas Adam
39904f7fc6 Merge branch 'obsd-master' into master 2021-02-05 14:01:23 +00:00
nicm
3dddc11603 Send Unicode directional isolate characters around horizontal pane
borders if the terminal support UTF-8 and an extension terminfo(5)
capability "Bidi" is present. On terminals with BiDi support (ie, VTE)
this seems to be enough to display right-to-left text acceptably enough
to be usable (with some caveats about the mouse position). Requested by
and with help from Mahmoud Elagdar in GitHub issue 2425.
2021-02-05 12:29:18 +00:00
nicm
be471c328e Add a -S flag to new-window to make it select the existing window if one
with the given name already exists rather than failing with an error.
Also add a format to check if a window or session name exists which
allows the same with other commands. Requested by and discussed with
kn@.
2021-02-05 12:23:49 +00:00
Nicholas Marriott
e3d71d9bdf Add compat clock_gettime for older macOS. GitHub issue 2555. 2021-02-05 11:01:21 +00:00
Thomas Adam
3dd2e85075 Merge branch 'obsd-master' into master 2021-02-04 16:01:18 +00:00
nicm
c13f2e1135 Redraw status line and borders on pane enable/disable, GitHub issue 2554. 2021-02-04 14:02:24 +00:00
Thomas Adam
86955dbfe1 Merge branch 'obsd-master' into master 2021-02-02 14:01:19 +00:00
nicm
f0546b0ff8 Fix popup mouse position. 2021-02-02 13:03:03 +00:00
Thomas Adam
a5d69ab4b0 Merge branch 'obsd-master' into master 2021-02-02 08:01:19 +00:00
jmc
5c48086e5c article fixes; from eddie youseph 2021-02-02 07:33:29 +00:00
Thomas Adam
0242513ce7 Merge branch 'obsd-master' into master 2021-02-01 10:01:20 +00:00
nicm
509221520c Add a no-detached choice to detach-on-destroy which detaches only if
there are no other detached sessions to switch to, from Sencer Selcuk in
GitHub issue 2553.
2021-02-01 08:01:14 +00:00
Thomas Adam
545a610c6b Merge branch 'obsd-master' into master 2021-01-29 12:01:21 +00:00
nicm
255802d8d7 Trim output overwritten by later text or clears completely rather than
only in a few cases. This means we can better track when a line should
wrap. GitHub issue 2537.
2021-01-29 09:48:43 +00:00
Thomas Adam
ffc159a456 Merge branch 'obsd-master' into master 2021-01-27 12:01:21 +00:00
nicm
8156d9ba41 Flush pending output before entering or exiting alternate screen rather
than leaking it, oss-fuzz issue 29959.
2021-01-27 10:42:52 +00:00
Thomas Adam
70a6af6287 Merge branch 'obsd-master' into master 2021-01-26 10:01:18 +00:00
nicm
d6542c333d Always resize the original screen before copying when exiting the
alternate screen, GitHub issue 2536.
2021-01-26 09:32:52 +00:00
Thomas Adam
3b51abcf22 Merge branch 'obsd-master' into master 2021-01-22 14:01:18 +00:00
Thomas Adam
0898a868c6 Merge branch 'obsd-master' into master 2021-01-22 12:01:21 +00:00
nicm
9fcf413d87 Revert clear changes to writing as they don't work properly, better
change to come.
2021-01-22 11:28:33 +00:00
nicm
bba71f696f Add rectangle-on and rectangle-off copy mode commands, GitHub isse 2546
from author at will dot party.
2021-01-22 10:24:52 +00:00
nicm
8d185395e4 Fix some cursor movement commands, from Anindya Mukherjee. 2021-01-22 10:21:24 +00:00
Thomas Adam
9ff017e908 Merge branch 'obsd-master' into master 2021-01-20 08:01:22 +00:00
nicm
fb774b77d0 Change so that window_flags escapes # automatically which means configs
will not have to change. A new format window_raw_flags contains the old
unescaped version.
2021-01-20 07:16:54 +00:00
Thomas Adam
82423975df Merge branch 'obsd-master' into master 2021-01-18 14:01:21 +00:00
Thomas Adam
66da51b631 Merge branch 'obsd-master' into master 2021-01-18 12:01:22 +00:00
Nicholas Marriott
3c86fa2ad0 Add -Wno-format-y2k. 2021-01-18 11:14:37 +00:00
nicm
0730dce5ab Hide some warnings on newer GCC versions, GitHUb issue 2525. 2021-01-18 11:14:23 +00:00
Nicholas Marriott
63f4a3c4e5 Extra result message. 2021-01-18 10:48:49 +00:00
nicm
91d112bf12 There is no need to clear every line entirely before drawing to it, this
means moving the cursor and messes up wrapping. Better to just clear the
sections that aren't written over. GitHub issue 2537.
2021-01-18 10:27:54 +00:00
Nicholas Marriott
4148417a2a PKG_CHECK_MODULES needs to be separate. 2021-01-17 19:03:18 +00:00
Nicholas Marriott
607594f6e5 Show config.log on failure. 2021-01-17 18:47:14 +00:00
Nicholas Marriott
b18834be8a Revert "Set CFLAGS also."
This reverts commit 032723c8740710cd34bdf6e7a0124f8fb18f6d70.
2021-01-17 18:24:52 +00:00
Nicholas Marriott
032723c874 Set CFLAGS also. 2021-01-17 18:21:54 +00:00
Nicholas Marriott
c6bcf3dba5 Fix yes/no for b64_ntop check. 2021-01-17 18:20:15 +00:00
Thomas Adam
24c15eda79 Merge branch 'obsd-master' into master 2021-01-17 18:01:21 +00:00
Nicholas Marriott
d4866d5fe6 Fix SEARCH_LIBS. 2021-01-17 17:55:14 +00:00
Nicholas Marriott
603280cb28 +compat.h 2021-01-17 17:52:10 +00:00
Nicholas Marriott
a3011be0d2 Look for libevent2 differently from libevent for platforms with both. 2021-01-17 17:21:51 +00:00
nicm
71c590a37f Add -N flag to never start server even if command would normally do so,
GitHub issue 2523.
2021-01-17 16:17:41 +00:00
Thomas Adam
dc1e1125a5 Merge branch 'obsd-master' into master 2021-01-08 12:01:21 +00:00
nicm
a75aca4d6a Missed from last commit. 2021-01-08 10:09:44 +00:00
Thomas Adam
9df33bc536 Merge branch 'obsd-master' into master 2021-01-08 10:01:20 +00:00
nicm
b96c5e3687 With incremental search, start empty and only repeat the previous search
if the user tries to search again with an empty prompt. This matches
emacs behaviour more closely.
2021-01-08 08:22:10 +00:00
Thomas Adam
fc28e2065a Merge branch 'obsd-master' into master 2021-01-06 10:01:22 +00:00
nicm
199689954b Insert joined pane before the target pane with -b, like for split. From
Takeshi Banse.
2021-01-06 07:32:23 +00:00
nicm
ccb8b9eb2a Remove unused variable, from Ben Boeckel. 2021-01-06 07:29:49 +00:00
Thomas Adam
5a2db4c7e8 Merge branch 'obsd-master' into master 2021-01-04 10:01:20 +00:00
nicm
bd0fb22f0a Add a variant of remain-on-exit that only keeps the pane if the program
failed, GitHub issue 2513.
2021-01-04 08:43:16 +00:00
Thomas Adam
f04cc39976 Merge branch 'obsd-master' into master 2021-01-01 10:01:21 +00:00
nicm
606bd5f8c6 Add a -C flag to run-shell to use a tmux command rather than a shell command. 2021-01-01 08:36:51 +00:00
Thomas Adam
f72deb092a Merge branch 'obsd-master' into master 2020-12-30 22:01:23 +00:00
nicm
f97305af31 Use right format for session loop, GitHub issue 2519. 2020-12-30 18:29:40 +00:00
Thomas Adam
3cbe186efb Merge branch 'obsd-master' into master 2020-12-28 12:01:21 +00:00
nicm
a98ee00dd9 Do not list user options with show-hooks. 2020-12-28 09:40:27 +00:00
nicm
c68baaad98 Remove current match indicator which can't work anymore since we only
search the visible region. From Anindya Mukherjee, GitHub issue 2508.
2020-12-28 09:36:26 +00:00
Thomas Adam
d936fde7ef Makefile.am: add grid-reader.c
Add grid-reader.c to Makefile.am so it's included for compilation.
2020-12-24 22:22:10 +00:00
Thomas Adam
70a0eb3a22 Merge branch 'obsd-master' into master 2020-12-24 22:21:21 +00:00
nicm
c43f2dce1b Break cursor movement in grid into a common set of functions that can
handle line wrapping and so on in one place and use them for the obvious
copy mode commands. From Anindya Mukherjee.
2020-12-22 09:22:14 +00:00
Thomas Adam
950e982001 Merge branch 'obsd-master' into master 2020-12-15 10:01:22 +00:00
nicm
8bd29a30bf Make synchronize-panes a pane option and add -U flag to set-option to
unset an option on all panes. GitHub issue 2491 from Rostislav Nesin.
2020-12-15 08:31:50 +00:00
Nicholas Marriott
681c0d2bfb Include compat.h after system headers, GitHub issue 2492. 2020-12-07 12:13:20 +00:00
Thomas Adam
caf096394b Merge branch 'obsd-master' into master 2020-12-07 10:01:20 +00:00
nicm
f6095cad99 Do not include the status line size when working out the character for
the pane status line. GitHub issue 2493.
2020-12-07 09:46:58 +00:00
nicm
ed786309cc Do not clear the wrapped flag on linefeeds if it is already set - this
does not appear to be what applications want. GitHub issue 2478 and 2414.
2020-12-07 09:23:57 +00:00
Thomas Adam
e288ea153c Merge branch 'obsd-master' into master 2020-12-03 08:01:22 +00:00
nicm
fd451aa796 Redraw any visible modes when status line changes so that formats like
the pane title are updated. GitHub issue 2487. Also a man page fix from
jmc.
2020-12-03 07:12:11 +00:00
Thomas Adam
4724702d4e Merge branch 'obsd-master' into master 2020-12-01 12:01:20 +00:00
nicm
f0c1233d4f Leave newlines inside multiline quotes. 2020-12-01 10:48:03 +00:00
Thomas Adam
27634645e9 Merge branch 'obsd-master' into master 2020-12-01 10:01:22 +00:00
nicm
9a74bba007 Make replacement of ##s consistent when drawing formats, whether
followed by [ or not. Add a flag (e) to the q: format modifier to double
up #s and use it for the window_flags format variable so it doesn't end
up escaping any following text. GitHub issue 2485.
2020-12-01 08:12:58 +00:00
Thomas Adam
70a5207bd1 Merge branch 'obsd-master' into master 2020-11-30 16:01:22 +00:00
nicm
33046ecee2 Ignore running command when checking for no-hooks flag if it is blocked.
GitHub issue 2483.
2020-11-30 13:37:45 +00:00
Thomas Adam
bf8aa9804b Merge branch 'obsd-master' into master 2020-11-26 14:01:19 +00:00
nicm
fd5c3e6122 Fix check for vertical centre. 2020-11-26 13:06:21 +00:00
Thomas Adam
82fbff4e08 Merge branch 'obsd-master' into master 2020-11-26 10:01:21 +00:00
nicm
76cfb5f471 Add -N flag to display-panes to ignore keys, GitHub issue 2473. 2020-11-26 09:19:10 +00:00
Nicholas Marriott
2f1578ef83 Update closefrom from OpenSSH for macOS code which is now needed. 2020-11-20 09:05:32 +00:00
Nicholas Marriott
bfdc4373d7 Update closefrom from OpenSSH for macOS code which is now needed. 2020-11-17 17:57:21 +00:00
Thomas Adam
3ee1addbb9 Merge branch 'obsd-master' into master 2020-11-17 10:01:22 +00:00
nicm
0d28ee9274 Log missing keys when extended keys is on rather than fatal(). 2020-11-17 08:13:35 +00:00
Thomas Adam
e94bd5ccff Merge branch 'obsd-master' 2020-11-10 10:01:22 +00:00
nicm
bbab5b7a30 Allow previous-word to scroll onto the first line, noticed by Anindya
Mukherjee.
2020-11-10 08:16:52 +00:00
Nicholas Marriott
3eb1519bd7 Scaffold for oss-fuzz, from Sergey Nizovtsev. 2020-11-09 16:44:39 +00:00
Thomas Adam
0dcb6e5eb4 Merge branch 'obsd-master' 2020-11-09 12:01:21 +00:00
nicm
f1193b4891 If mouse bits change, clear them all and set again to avoid problems
with some bits implying others. GitHub issue 2458.
2020-11-09 10:54:28 +00:00
Thomas Adam
5ddbf0c918 Merge branch 'obsd-master' 2020-11-09 10:01:27 +00:00
nicm
61e55fa50d Change how escaping is processed for formats so that ## and # can be
used in styles. Also add a 'w' format modifier for the width. From Chas
J Owens IV in GitHub issue 2389.
2020-11-09 09:10:10 +00:00
Nicholas Marriott
72c46aa15e Add support for Haiku, from David Carlier. GitHub issue 2453. 2020-11-09 09:00:41 +00:00
nicm
1326529f99 Remove some old debug logging. 2020-11-09 08:42:43 +00:00
Thomas Adam
dac285c92a Merge branch 'obsd-master' 2020-11-03 10:01:21 +00:00
Nicholas Marriott
572a6b21b5 Back to 3.3. 2020-11-03 08:41:24 +00:00
Nicholas Marriott
5306bb0db7 Update to 3.2-rc3, bring in all the changes from master. 2020-11-03 08:37:08 +00:00
Nicholas Marriott
ba9962b568 Merge branch 'master' into 3.2-rc 2020-11-03 08:35:52 +00:00
nicm
9d83c5e948 Expand menu and popup -x and -y as a format, from teo_paul1 at yahoo dot
com in GitHub issue 2442.
2020-11-03 08:09:35 +00:00
Thomas Adam
ff53eed402 Merge branch 'obsd-master' 2020-11-02 10:01:20 +00:00
nicm
ac5045a00f Add numeric comparisons for formats, from teo_paul1 at yahoo dot com in
GitHub issue 2442.
2020-11-02 08:21:30 +00:00
Thomas Adam
ffe39edf2f Merge branch 'obsd-master' 2020-10-30 20:01:20 +00:00
nicm
95841ba16a With csh, a tmux client gets SIGTERM before SIGCONT when killed with
"kill %%", so when the client tells the server it got SIGCONT, don't use
bits that may already have been freed when it got SIGTERM. Also don't
print anything on exit if we get SIGTERM while suspended. Reported by
Theo.
2020-10-30 18:54:23 +00:00
Thomas Adam
d064060904 Merge branch 'obsd-master' 2020-10-30 14:01:20 +00:00
Nicholas Marriott
0b8ae4de5c Update CHANGES. 2020-10-30 12:29:40 +00:00
nicm
9726c4454e Do not allow disabled items to be selected. 2020-10-30 12:00:01 +00:00
nicm
8e1d28453d Limit range of repeat to avoid silly high numbers causing delays, from
Sergey Nizovtsev.
2020-10-30 11:34:13 +00:00
nicm
02197f20d0 Do not leak path when freeing screen, from Sergey Nizovtsev. 2020-10-30 11:33:41 +00:00
Thomas Adam
970e8f734c Merge branch 'obsd-master' 2020-10-30 10:01:22 +00:00
Nicholas Marriott
ce2b6ff40e Style trim test (currently failing). 2020-10-30 09:25:41 +00:00
nicm
910457f68d There is no reason not to fire focus events when a pane is in a mode,
GitHub issue 2372.
2020-10-30 09:00:07 +00:00
nicm
649e5970e9 Add a -O flag to display-menu to change the mouse behaviour and not
close the menu when the mouse is released, from teo_paul1 at yahoo dot
com.
2020-10-30 08:55:56 +00:00
nicm
733abfcfc5 Do not write after the end of the array and overwrite the stack when
colon-separated SGR sequences contain empty arguments. Reported by Sergey
Nizovtsev.
2020-10-30 08:17:38 +00:00
Thomas Adam
7f321a4cc6 Merge branch 'obsd-master' 2020-10-29 18:01:21 +00:00
nicm
a868bacb46 Do not write after the end of the array and overwrite the stack when
colon-separated SGR sequences contain empty arguments. Reported by Sergey
Nizovtsev.
2020-10-29 16:33:01 +00:00
nicm
7a4aa14618 Do not require that there be no other clients before loading the config,
being the first client is enough. GitHub issue 2438.
2020-10-29 14:10:24 +00:00
Thomas Adam
d5fac75667 Merge branch 'obsd-master' 2020-10-29 14:05:21 +00:00
nicm
977cf3cf69 Set RGB flag if capabilities are present, GitHub issue 2418. 2020-10-29 13:48:03 +00:00
nicm
07ffed8b6f Fix note for "previous-window" default key binding, from Sebastian
Falbesoner.
2020-10-29 13:47:50 +00:00
nicm
7ffb414299 Client could be NULL in select-window (for example in .tmux.conf), do
not set latest session if so. GitHub issue 2429 from Han Boetes.
2020-10-29 13:47:40 +00:00
nicm
3c298b98ce SIGQUIT handler needs to be cleared before fork like the others,
reported by Simon Andersson.
2020-10-29 13:47:24 +00:00
nicm
b33a302235 Do not require that there be no other clients before loading the config,
being the first client is enough. GitHub issue 2438.
2020-10-28 10:09:10 +00:00
Thomas Adam
20e89605c9 Merge branch 'obsd-master' 2020-10-26 20:01:18 +00:00
nicm
31ed29e551 SIGQUIT handler needs to be cleared before fork like the others,
reported by Simon Andersson.
2020-10-26 19:00:37 +00:00
Thomas Adam
9a5b2c93a7 Merge branch 'obsd-master' 2020-10-19 10:01:18 +01:00
nicm
d8cda9286f Client could be NULL in select-window (for example in .tmux.conf), do
not set latest session if so. GitHub issue 2429 from Han Boetes.
2020-10-19 06:39:28 +00:00
Thomas Adam
6125800876 Merge branch 'obsd-master' 2020-10-13 12:01:20 +01:00
nicm
4c8706d399 Fix note for "previous-window" default key binding, from Sebastian
Falbesoner.
2020-10-13 10:15:23 +00:00
Thomas Adam
9ab81e1879 Merge branch 'obsd-master' 2020-10-13 10:01:19 +01:00
nicm
d603dbdef0 Set RGB flag if capabilities are present, GitHub issue 2418. 2020-10-13 07:29:24 +00:00
Thomas Adam
30601d11a8 Merge branch 'obsd-master' 2020-10-09 22:01:22 +01:00
tim
4dc76e084b Escape ! in Ql
OK jmc@ nicm@, agreement from schwarze@
2020-10-09 19:12:36 +00:00
Thomas Adam
7ca0b9ddfa Merge branch 'obsd-master' 2020-10-07 10:01:19 +01:00
Nicholas Marriott
991d5a9c74 Add compat for getdtablesize, GitHub issue 2406. 2020-10-07 09:39:43 +01:00
nicm
3afcc6faac Allow fnmatch(3) wildcards in update-environment, GitHub issue 2397. 2020-10-07 08:23:55 +00:00
Thomas Adam
57168f3f59 Merge branch 'obsd-master' 2020-10-06 10:01:20 +01:00
nicm
7e319756d2 Fix a last minute change in previous. 2020-10-06 07:36:42 +00:00
nicm
e369f64669 Add a state struct to store working state during format expansion
instead of modiyfing the format tree.

Use this to disable nested job expansion so that the result of #() is
not expanded again. Reported by Chas J Owens IV, GitHub issue 2390.
2020-10-06 07:36:05 +00:00
Nicholas Marriott
680e7a382f glibc's malloc is very bad about returning memory from the kernel, add a call
to its malloc_trim to prompt it to do so. Reported by Sarunas Valaskevicius.
2020-10-06 08:18:42 +01:00
Thomas Adam
847a061e31 Merge branch 'obsd-master' 2020-10-05 14:01:19 +01:00
nicm
8d9ea1b97c Trim "s from process names; also fix a default format in man page. 2020-10-05 11:04:40 +00:00
Thomas Adam
f5b7ebc540 Merge branch 'obsd-master' 2020-10-05 12:01:23 +01:00
nicm
1479e32e1a Tidy the resize code, merge some common bits and add some comments. From
"Mike" in GitHub issue 2392.
2020-10-05 10:00:51 +00:00
nicm
c8f3736b07 Use the setal capability as well as (tmux's) Setulc. 2020-10-05 09:53:01 +00:00
Nicholas Marriott
92a2e7411f Link to install wiki page. 2020-10-01 09:01:42 +01:00
Nicholas Marriott
9ec68db74f Correct break-pane default format, from Gregory Pakosz. 2020-09-30 14:17:27 +01:00
Nicholas Marriott
f43e3e5b4f Next version. 2020-09-30 13:36:58 +01:00
Nicholas Marriott
86433c6fb5 Merge tag '3.2-rc' into master
3.2-rc
2020-09-30 13:36:26 +01:00
Nicholas Marriott
cf8ef63c4a Fix some warnings, GitHub issue 2382. 2020-09-30 13:35:51 +01:00
nicm
ec9e03d09a Old Terminal.app versions do not respond correctly to secondary DA,
instead responding with the primary DA response. Ignore it. Reported by
Dave Vandervies.
2020-09-30 13:33:02 +01:00
Nicholas Marriott
3bece648bd Trim "s from process names, from Gregory Pakosz. 2020-09-30 13:27:50 +01:00
nicm
68c2d5c48d Escape+Up and the other arrow keys should be kept as Escape+Up and not
converted to M-Up. Do not give them the implied meta flag so they don't
match the M-Up entry in the output key tree. Fixes problem with vi
reported by jsing@.
2020-09-30 13:27:43 +01:00
Nicholas Marriott
f70eda3817 Check if UNIX 03 is needed for CMSG_DATA, for newer Solaris. From Eric N Vander
Weele.
2020-09-30 13:27:35 +01:00
Nicholas Marriott
a880237141 Also pkg-config. 2020-09-30 13:27:25 +01:00
Nicholas Marriott
9d597390ca Mention build dependencies, based on a change from Mateusz Urbanek. 2020-09-30 13:27:21 +01:00
Nicholas Marriott
5f50e7d942 Trim "s from process names, from Gregory Pakosz. 2020-09-30 13:26:31 +01:00
Nicholas Marriott
4f638c0e31 Check if UNIX 03 is needed for CMSG_DATA, for newer Solaris. From Eric N Vander
Weele.
2020-09-25 10:04:52 +01:00
Nicholas Marriott
e2e5169f84 Also pkg-config. 2020-09-25 09:43:35 +01:00
Nicholas Marriott
ebf27f6900 Mention build dependencies, based on a change from Mateusz Urbanek. 2020-09-25 09:41:41 +01:00
Thomas Adam
476c185997 Merge branch 'obsd-master' 2020-09-23 18:01:17 +01:00
nicm
f2dfc2759e Escape+Up and the other arrow keys should be kept as Escape+Up and not
converted to M-Up. Do not give them the implied meta flag so they don't
match the M-Up entry in the output key tree. Fixes problem with vi
reported by jsing@.
2020-09-23 14:57:33 +00:00
Thomas Adam
dc0c3aa391 Merge branch 'obsd-master' 2020-09-22 18:01:18 +01:00
nicm
d6680b9474 Move a sentence to the right command. 2020-09-22 15:45:20 +00:00
Thomas Adam
859a4c3460 Merge branch 'obsd-master' 2020-09-22 10:01:17 +01:00
nicm
b9392d5cb1 Do not wrap at end of text when positioning at end of match because the
length may include trailing spaces.
2020-09-22 08:41:27 +00:00
Thomas Adam
a34ceb1074 Merge branch 'obsd-master' 2020-09-22 08:01:18 +01:00
nicm
51909a107f Resize screen to the correct size (borders need to be taken off). 2020-09-22 06:44:52 +00:00
nicm
86d6ac2f06 Fix warnings on some platforms with %llx and add a new message to handle
64-bit client flags.
2020-09-22 05:23:34 +00:00
Thomas Adam
ca5afb34bf Merge branch 'obsd-master' 2020-09-18 14:01:19 +01:00
nicm
88b66e9e28 Free buffer earlier to avoid confusing some compilers, GitHub issue
2382.
2020-09-18 11:23:29 +00:00
nicm
ed946dccc7 Some other warnings, GitHub issue 2382. 2020-09-18 11:20:59 +00:00
Thomas Adam
eea85fb4c7 Merge branch 'obsd-master' 2020-09-16 22:01:18 +01:00
nicm
3206869ea5 Add -q flag to unbind-key to hide errors, GitHub issue 2381. 2020-09-16 19:12:59 +00:00
Thomas Adam
c3e1b841f9 Merge branch 'obsd-master' 2020-09-16 20:01:19 +01:00
nicm
869c0e860f Fix some warnings, GitHub issue 2382. 2020-09-16 18:37:55 +00:00
Thomas Adam
3c1f34c208 Merge branch 'obsd-master' 2020-09-08 12:01:17 +01:00
nicm
1fed7e84a3 Allow -N without a command to change or add a note to an existing key. 2020-09-08 10:19:19 +00:00
Thomas Adam
634a2bb647 Merge branch 'obsd-master' 2020-09-04 14:01:18 +01:00
nicm
9b45ba82fd calloc cb data so the client is NULL. 2020-09-04 12:24:25 +00:00
Nicholas Marriott
233d14f4da Hide warnings due to Apple's stupidity with __dead, reported by Kurtis Rader. 2020-09-04 08:37:11 +01:00
Thomas Adam
2e931d4994 Merge branch 'obsd-master' 2020-09-03 14:01:18 +01:00
nicm
eadf18b9fa Do not free old session working directory until after expanding the new
one because it may be needed.
2020-09-03 12:47:33 +00:00
Thomas Adam
cbbf5febff Merge branch 'obsd-master' 2020-09-02 20:01:17 +01:00
nicm
e538bef757 Check started flag before looking for capability. 2020-09-02 17:19:58 +00:00
Thomas Adam
fc9ecdc665 Merge branch 'obsd-master' 2020-09-02 16:01:20 +01:00
nicm
37b1600d9c Add a -w flag to set- and load-buffer to send to clipboard using OSC 52.
GitHub issue 2363.
2020-09-02 13:46:35 +00:00
Thomas Adam
a0fee328bf Merge branch 'obsd-master' 2020-09-01 12:01:20 +01:00
nicm
60860aced8 Add -F to set-environment and source-file; GitHub issue 2359. 2020-09-01 09:19:01 +00:00
nicm
b2a262e353 Only print below number when there is enough space. 2020-09-01 08:50:14 +00:00
Thomas Adam
b895ffbf37 Merge branch 'obsd-master' 2020-08-27 10:01:20 +01:00
nicm
2ab289980a Add pane_last format, GitHub issue 2353. 2020-08-27 06:55:54 +00:00
Thomas Adam
655134f77c Merge branch 'obsd-master' 2020-08-25 14:01:19 +01:00
nicm
20fcdcfea1 Allow colour to be spelt as color, from Boris Verkhovsky. GitHub issue
2317.
2020-08-25 11:35:32 +00:00
Thomas Adam
aa084bb49e Merge branch 'obsd-master' 2020-08-24 08:01:17 +01:00
nicm
e4a4fcfc90 Old Terminal.app versions do not respond correctly to secondary DA,
instead responding with the primary DA response. Ignore it. Reported by
Dave Vandervies.
2020-08-24 05:23:30 +00:00
nicm
43e3e53908 Do not run off end of string when stripping delays, reported by Dave
Vandervies.
2020-08-24 05:22:28 +00:00
Thomas Adam
769ae10658 Merge branch 'obsd-master' 2020-08-20 20:01:19 +01:00
nicm
d0957529ed Add n: modifier to get length of a format, also automatically expand
variable name arguments again if they contain a #{.
2020-08-20 16:57:40 +00:00
Thomas Adam
5a55d1390a Merge branch 'obsd-master' 2020-08-19 10:01:19 +01:00
nicm
d8b6560cbf Set alert flag for the current window if the session is unattached.
GitHub issues 1182 and 2299. From Eric Garver.
2020-08-19 07:15:42 +00:00
nicm
f08bfa7cd1 Respond to colour requests if a colour is available, from Michal Goral. 2020-08-19 06:37:23 +00:00
Thomas Adam
93eb2c8c53 Merge branch 'obsd-master' 2020-08-07 10:01:19 +01:00
nicm
212c0c1f72 Do not force line width to grid width because it may need to be larger
to accomodate a wide character. GitHub issue 2336.
2020-08-07 07:02:57 +00:00
Thomas Adam
9f0973b711 Merge branch 'obsd-master' 2020-08-05 12:01:21 +01:00
nicm
df7fbcd7a5 Change searching to behave more like emacs and so that regex searching
doesn't overlap when searching forwards.
2020-08-05 09:11:09 +00:00
Thomas Adam
8d7e127b17 Merge branch 'obsd-master' 2020-08-04 12:01:18 +01:00
nicm
82c65e3f37 Also ignore SIGQUIT so it can't be used to kill the client when locked. 2020-08-04 08:50:01 +00:00
Thomas Adam
98aa835079 Merge branch 'obsd-master' 2020-07-30 10:01:18 +01:00
nicm
944177eec3 Trim newline from ctime, from Thomas Adam. 2020-07-30 07:32:52 +00:00
Thomas Adam
2fdd5fa507 Merge branch 'obsd-master' 2020-07-27 10:01:21 +01:00
nicm
40e65c5115 Add a -d option to display-message to set delay, from theonekeyg at
gmail dot com in GitHub issue 2322.
2020-07-27 08:03:10 +00:00
Thomas Adam
90158b5977 Merge branch 'obsd-master' 2020-07-24 10:01:19 +01:00
Nicholas Marriott
31bc4c4346 3.2-rc version. 2020-07-24 08:38:34 +01:00
nicm
d329b035ce Add a hook when the pane title changed. 2020-07-24 07:05:37 +00:00
Thomas Adam
1f19355fb0 Merge branch 'obsd-master' 2020-07-23 16:01:17 +01:00
nicm
112b0f417c Check all lists if option not found already. 2020-07-23 14:17:56 +00:00
Thomas Adam
e0d984597b Merge branch 'obsd-master' 2020-07-22 08:01:18 +01:00
nicm
1f5e520def Correct checks for window borders. 2020-07-22 06:21:46 +00:00
Thomas Adam
90de0c1a9b Merge branch 'obsd-master' 2020-07-21 08:01:19 +01:00
nicm
743ab5728d Fix show-buffer when run from inside tmux, GitHub issue 2314. 2020-07-21 05:24:33 +00:00
Thomas Adam
70a674dde1 Merge branch 'obsd-master' 2020-07-18 06:01:20 +01:00
daniel
3b089fc69f Properly escape a backslash.
Found by CompCert which notes that \E is not a valid escape sequence.

ok nicm@
2020-07-18 02:53:47 +00:00
Thomas Adam
ab8d685302 Merge branch 'obsd-master' 2020-07-15 14:01:18 +01:00
nicm
5e008eefaa Renumber after killing windows for choose-tree. 2020-07-15 11:03:17 +00:00
Thomas Adam
c973801f92 Merge branch 'obsd-master' 2020-07-15 12:01:19 +01:00
nicm
8f1179d656 Handle padding cells correctly when searching, GitHub issue 2301. 2020-07-15 10:09:54 +00:00
Thomas Adam
405b71e016 Merge branch 'obsd-master' 2020-07-13 12:01:17 +01:00
nicm
468be2a37f Do not dereference NULL environment variable value, GitHub issue 2304. 2020-07-13 10:10:10 +00:00
Thomas Adam
7d6723b5f7 Merge branch 'obsd-master' 2020-07-13 10:01:18 +01:00
nicm
f26b7b7788 Clarify /tmp permissions and use, GitHub issue 2300. 2020-07-13 07:04:17 +00:00
Nicholas Marriott
a5f99e14c6 Update version. 2020-07-06 14:07:11 +01:00
Nicholas Marriott
b30989a964 Pull 3.2-rc up to master. 2020-07-06 14:03:33 +01:00
Thomas Adam
aa4f3a9b3d Merge branch 'obsd-master' 2020-07-06 12:01:22 +01:00
nicm
2aa177d102 Do not eliminate redundant clears, the code is wrong and doing it
correctly wouldn't be worth it. GitHub issue 2298.
2020-07-06 10:07:02 +00:00
nicm
66d5e5de7a Add a way for control mode clients to subscribe to a format and be
notified of changes rather than having to poll. GitHub issue 2242.
2020-07-06 09:14:20 +00:00
Thomas Adam
af82094439 Merge branch 'obsd-master' 2020-07-06 10:01:19 +01:00
nicm
2bf612a806 Always send xterm-style keys for M-Left and M-Right. GitHub issue 2296. 2020-07-06 07:27:39 +00:00
Thomas Adam
c0d9eaff9b Merge branch 'obsd-master' 2020-07-04 16:01:20 +01:00
nicm
1e42689661 kill-window -a cannot just walk the list of windows because if
renumber-windows is on, the window it wants to keep could be moved.
Change to renumber afterwards and also behave better if the window is
linked into the session twice. GitHub issue 2287.
2020-07-04 14:24:02 +00:00
Nicholas Marriott
a109e839d1 Fix version. 2020-07-03 12:03:25 +01:00
Nicholas Marriott
6b01eac774 Merge branch '3.2-rc' 2020-07-03 12:03:07 +01:00
nicm
5661346c41 Missing word, from annihilannic at hotmail dot com, GitHub issue 2288. 2020-07-03 12:02:52 +01:00
nicm
0d0fc13aaa Check if client is NULL before using it, GitHub issue 2295. 2020-07-03 12:02:46 +01:00
bket
83868ceb1a Replace TAILQ concatenation loop with TAILQ_CONCAT
As a result remove unneeded variables

OK @nicm
2020-07-03 12:02:37 +01:00
Thomas Adam
0fa306d73c Merge branch 'obsd-master' 2020-07-03 10:01:20 +01:00
nicm
43e1577b5d Missing word, from annihilannic at hotmail dot com, GitHub issue 2288. 2020-07-03 07:07:50 +00:00
nicm
2b1e8d06e1 Check if client is NULL before using it, GitHub issue 2295. 2020-07-03 07:00:12 +00:00
Thomas Adam
a284664e71 Merge branch 'obsd-master' 2020-06-29 18:01:18 +01:00
bket
2a9bdb700d Replace TAILQ concatenation loop with TAILQ_CONCAT
As a result remove unneeded variables

OK @nicm
2020-06-29 15:53:28 +00:00
nicm
629ba1b838 Check for no pane border status line separately from top/bottom. 2020-06-29 09:20:39 +01:00
nicm
c9b4d5a4a5 Fix 0x Unicode character parsing, GitHub issue 2286. 2020-06-29 09:20:32 +01:00
nicm
6cacaa94a5 Silently ignore -a or -b if the window index doesn't exist and create
using that index (this is how it used to work), reported by Romain
Francoise.
2020-06-29 09:20:25 +01:00
Thomas Adam
332aca754b Merge branch 'obsd-master' 2020-06-27 12:01:18 +01:00
nicm
b6aeb86c20 Check for no pane border status line separately from top/bottom. 2020-06-27 10:23:10 +00:00
nicm
74df7071ad Fix 0x Unicode character parsing, GitHub issue 2286. 2020-06-27 10:19:59 +00:00
Thomas Adam
04a1a84bb8 Merge branch 'obsd-master' 2020-06-25 12:01:17 +01:00
nicm
f69bdda950 Silently ignore -a or -b if the window index doesn't exist and create
using that index (this is how it used to work), reported by Romain
Francoise.
2020-06-25 08:56:02 +00:00
nicm
43295bd4a5 Correctly redraw pane border bottom line when the status line is on and
at the bottom, reported by Kaushal Modi.
2020-06-23 16:32:40 +01:00
nicm
e215a566a4 Use xvasprintf not vasprintf. 2020-06-23 16:32:40 +01:00
Thomas Adam
2a2ebf315f Merge branch 'obsd-master' 2020-06-23 16:01:18 +01:00
nicm
5340bf556e Correctly redraw pane border bottom line when the status line is on and
at the bottom, reported by Kaushal Modi.
2020-06-23 14:10:43 +00:00
Thomas Adam
1f515663d1 Merge branch 'obsd-master' 2020-06-23 08:01:18 +01:00
nicm
2964dde903 Use xvasprintf not vasprintf. 2020-06-23 05:23:26 +00:00
Nicholas Marriott
e450416c93 3.2-rc. 2020-06-22 12:55:10 +01:00
Nicholas Marriott
b730083d7a Add to CHANGES. 2020-06-22 12:53:43 +01:00
Nicholas Marriott
3a1fc7315c Add getline compat. 2020-06-18 21:01:55 +01:00
Nicholas Marriott
3df68d6b00 Fix regress test for am. 2020-06-18 21:01:45 +01:00
Thomas Adam
6c437d45ac Merge branch 'obsd-master' 2020-06-18 12:01:22 +01:00
nicm
068b92b051 The redraw callback could be fired with a NULL pane if it updates while
in a mode, problem reported by Martin Vahlensieck.
2020-06-18 08:41:56 +00:00
nicm
2372b0fdc6 Add a flag to make a client wait for an empty line before exiting in
control mode to avoid stray commands ending up in the shell.
2020-06-18 08:34:22 +00:00
Thomas Adam
eb448daa1a Merge branch 'obsd-master' 2020-06-16 10:01:21 +01:00
nicm
1bf9555e4f d and D keys to reset to default in customize mode. 2020-06-16 08:18:34 +00:00
nicm
afe4ea4250 Correctly move to previous line when looking for previous word, from
Derry Jing.
2020-06-16 07:28:57 +00:00
Thomas Adam
824efe7be4 Merge branch 'obsd-master' 2020-06-13 12:01:20 +01:00
nicm
1c78155e70 Add -b flags to insert a window before (like the existing -a for after)
to break-pane, move-window, new-window. GitHub issue 2261.
2020-06-13 09:05:53 +00:00
Thomas Adam
4000052d92 Merge branch 'obsd-master' 2020-06-12 12:01:17 +01:00
nicm
d52ac7d027 Do not wait on shutdown for commands started with run -b. 2020-06-12 10:31:12 +00:00
Thomas Adam
bd3fb2fb10 Merge branch 'obsd-master' 2020-06-12 10:01:19 +01:00
nicm
d8d7769104 Check if a pane needs to be paused when output is written rather than
just when it is queued.
2020-06-12 08:35:01 +00:00
nicm
4c3bdc5a36 move-pane also defaults to marked pane now, reported by Ben Challenor. 2020-06-12 07:52:38 +00:00
nicm
cf63465eb0 Fix quoting with newlines and single quotes. 2020-06-12 07:10:43 +00:00
Thomas Adam
b5c86fdc0c Merge branch 'obsd-master' 2020-06-11 22:01:23 +01:00
nicm
63c2ed1483 Add some formats for search in copy mode (search_present, search_match).
GitHub issue 2268.
2020-06-11 19:43:34 +00:00
Thomas Adam
2e5b496053 Merge branch 'obsd-master' 2020-06-11 14:01:19 +01:00
Thomas Adam
e8c99496cd Merge branch 'obsd-master' 2020-06-11 12:01:19 +01:00
nicm
cf13d1e110 Fix a crash when completing sessions, from Anindya Mukherjee. 2020-06-11 10:56:19 +00:00
nicm
50ee41423f Add a -A option to pause a pane manually. 2020-06-11 09:55:47 +00:00
Thomas Adam
ea4425b9bd Merge branch 'obsd-master' 2020-06-10 10:01:20 +01:00
nicm
23d79cfda8 Instead of a buffer size limit on each pane, set a limit of 300 seconds
of data for each client in control mode.
2020-06-10 07:27:10 +00:00
Thomas Adam
8b673cc4f2 Merge branch 'obsd-master' 2020-06-10 08:01:19 +01:00
nicm
fddcad6957 When the pause-after flag is set, send an alternative %extended-output
form instead of %output with the age of the output.
2020-06-10 06:23:43 +00:00
Thomas Adam
208d9449b7 Merge branch 'obsd-master' 2020-06-09 12:01:18 +01:00
nicm
fee585ea14 Include width in error message. 2020-06-09 10:37:00 +00:00
Thomas Adam
30eaf885c4 Merge branch 'obsd-master' 2020-06-09 10:01:17 +01:00
nicm
c60389acbf It is not sensible to store pointers into an array we are going to
realloc (duh), use two trees instead.
2020-06-09 08:34:33 +00:00
Thomas Adam
9ffdcc7656 Merge branch 'obsd-master' 2020-06-06 14:01:17 +01:00
nicm
a4a3d89598 Use bitshifts instead of a union for encoding UTF-8 into 32 bits, which
is more friendly to GCC3.

Reported by and ok aoyama@.
2020-06-06 12:38:32 +00:00
Nicholas Marriott
0d8ba2e57f Add to CHANGES. 2020-06-05 14:56:55 +01:00
Thomas Adam
92c8cc17c3 Merge branch 'obsd-master' 2020-06-05 14:01:19 +01:00
nicm
d919fa1ed0 Change how panes are resized so that the code is clearer and if the pane
is resized multiple times during one event loop, it is forced to resize
at the end. Also don't zoom/unzoom in switch-client if the pane hasn't
changed. GitHub issue 2260.
2020-06-05 11:20:51 +00:00
Thomas Adam
47a5afe5bf Merge branch 'obsd-master' 2020-06-05 12:01:18 +01:00
nicm
03b2998abe Do not take the address of a potentially unaligned member. 2020-06-05 09:35:41 +00:00
nicm
c908d2039f Fix various confusion about am vs xenl. 2020-06-05 09:32:15 +00:00
Thomas Adam
a06cf900c7 Merge branch 'obsd-master' 2020-06-05 10:01:22 +01:00
nicm
4e5e2c19d0 Now that we mostly only search visible text, the rate limit on repeating
search does not seem to be necessary, remove it for the moment.
2020-06-05 07:44:42 +00:00
nicm
c586208991 Add support for pausing a pane when the output buffered for a control
mode client gets too far behind. The pause-after flag with a time is set
on the pane with refresh-client -f and a paused pane may be resumed with
refresh-client -A. GitHub issue 2217.
2020-06-05 07:33:57 +00:00
Thomas Adam
976cf6c60f Merge branch 'obsd-master' 2020-06-05 00:01:19 +01:00
nicm
d9cd493d09 Reset wrapped flag when clearing or moving lines, GitHub issue 2215. 2020-06-04 21:41:31 +00:00
nicm
2154e1f4fb Search marks outside the visible text are not useful, so there is no
point in allocating a big buffer to store them - just allocate the
visible text size, and ignore any outside.
2020-06-04 21:40:27 +00:00
Thomas Adam
8b43fcd82b Merge branch 'obsd-master' 2020-06-04 22:01:17 +01:00
nicm
c4732af006 Some improvements to performance of searching:
- Do not allow searches to be repeated at intervals of less than 50
  milliseconds, to prevent a huge queue of repeat key presses blocking
  up everything for ages.

- If the search text hasn't changed, the match count can't have changed
  and there is no need to do a full search, so only search the visible
  text. This includes both scrolling and repeating the search.

- Do not redraw twice when jumping to the search location.

GitHub issue 2258.
2020-06-04 20:41:57 +00:00
Thomas Adam
c8bddfba2b Merge branch 'obsd-master' 2020-06-04 18:01:17 +01:00
nicm
4403afe29c A } can go on the same line as a command. 2020-06-04 16:06:01 +00:00
Thomas Adam
81ba6477ff Merge branch 'obsd-master' 2020-06-04 12:01:20 +01:00
Nicholas Marriott
23a3742dc8 Update CHANGES. 2020-06-04 11:43:11 +01:00
nicm
4ea3370316 Shorten some long lines. 2020-06-04 10:36:28 +00:00
nicm
a9bf5367da Correct respawn-* - they don't always use the creation command. 2020-06-04 10:34:40 +00:00
nicm
dc74d2e054 Make the -no-clear command variants not clear the search marks either. 2020-06-04 10:24:14 +00:00
Thomas Adam
b0a6025897 Merge branch 'obsd-master' 2020-06-04 10:01:20 +01:00
nicm
d3c5202f50 Allow strings to span multiple lines - newlines and any leading
whitespace are removed, as well as any following comments that couldn't
be part of a format. This allows long formats or other strings to be
annotated and indented.
2020-06-04 08:30:44 +00:00
nicm
b3782d2dc8 Instead of using a custom parse function to process {}, treat it as a
set of statements and parse with yacc, then convert back to a string as
the last step. This means the rules are consistent inside and outside
{}, %if and friends work at the right time, and the final result isn't
littered with unnecessary newlines.
2020-06-04 07:12:05 +00:00
Thomas Adam
f837dcdd58 Merge branch 'obsd-master' 2020-06-03 18:01:17 +01:00
nicm
3f6af4156f Make paste -p the default for ], GitHub issue 2248. 2020-06-03 16:35:40 +00:00
Thomas Adam
62c0617d79 Merge branch 'obsd-master' 2020-06-03 00:01:20 +01:00
Thomas Adam
3d5decb305 Merge branch 'obsd-master' 2020-06-02 22:01:20 +01:00
nicm
4694e9a2b6 Move the code to set up a padding cell into grid.c. 2020-06-02 20:51:46 +00:00
nicm
2a4d4bda2b Allow UTF-8 characters of width 0 to be stored, it is useful to be able
to put padding cells in as width 0.
2020-06-02 20:10:23 +00:00
nicm
f5366ff828 Missing ; in previous. 2020-06-02 19:16:46 +00:00
nicm
5fbae8c8c6 Fire copy-pipe command even if there is no text, means it works if it
has side effects.
2020-06-02 19:10:26 +00:00
Thomas Adam
ebe866c378 Merge branch 'obsd-master' 2020-06-02 20:01:18 +01:00
nicm
7e501f1993 UTF-8 keys need to be big endian so the size bits are at the top. 2020-06-02 17:17:44 +00:00
Thomas Adam
049ccb4a4b Merge branch 'obsd-master' 2020-06-02 14:01:17 +01:00
nicm
822ee4e0a6 Fail rather than fatal on UTF-8 width 0. 2020-06-02 11:29:00 +00:00
Thomas Adam
31a51cae1d Merge branch 'obsd-master' 2020-06-02 11:29:48 +01:00
nicm
f3931497f8 Use CLOCK_MONOTONIC for timer measurement and add a timestamp to control
mode %output blocks.
2020-06-02 08:17:27 +00:00
nicm
563b7331da Remove blocks from queue when pane disappears. 2020-06-01 21:08:05 +00:00
nicm
8339702d47 Check the right thing for maximum client buffer size. 2020-06-01 20:58:42 +00:00
nicm
9819470058 Change format callback to return value rather than storing it in the entry. 2020-06-01 19:39:25 +00:00
Thomas Adam
191a836560 Merge branch 'obsd-master' 2020-06-01 18:01:18 +01:00
nicm
674ec410b7 Try without cursor/keypad flags if a key doesn't exist, and limit ctrl
key translation to ASCII keys. Fixes send-keys, GitHub issue 2247.
2020-06-01 16:09:35 +00:00
Thomas Adam
91e40de2da Merge branch 'obsd-master' 2020-06-01 12:01:20 +01:00
nicm
a54a88edd6 Instead of sending all data to control mode clients as fast as possible,
add a limit of how much data will be sent to the client and try to use
it for panes with some degree of fairness. GitHub issue 2217, with
George Nachman.
2020-06-01 09:43:00 +00:00
Thomas Adam
5ef790a6c4 Merge branch 'obsd-master' 2020-05-29 16:01:19 +01:00
nicm
175e45005f Add -i to find-window to ignore case. 2020-05-29 13:42:13 +00:00
Nicholas Marriott
ce6b3a539d utf8proc_unicode_version is too new. 2020-05-28 08:41:56 +01:00
Thomas Adam
86159fca82 Merge branch 'obsd-master' 2020-05-27 16:01:18 +01:00
nicm
bda2a0282a Fix ASCII keys with send-keys -l. 2020-05-27 14:45:35 +00:00
Thomas Adam
38ce6adab6 Merge branch 'obsd-master' 2020-05-27 08:01:19 +01:00
nicm
f336599a3a Make padding cell a valid character. 2020-05-27 06:23:23 +00:00
Thomas Adam
fd8652ceda Merge branch 'obsd-master' 2020-05-26 16:01:19 +01:00
nicm
2ced370bee Tweak some out of date bits, reported by bcgraham. 2020-05-26 13:19:21 +00:00
Thomas Adam
a4cb700269 Merge branch 'obsd-master' 2020-05-26 14:02:15 +01:00
nicm
ff6f2ff6d9 Return new character properly when converting to data. 2020-05-26 12:50:03 +00:00
nicm
392b381d1c Apply -n when only one pane in the window. 2020-05-26 09:01:03 +00:00
nicm
370f0bb98d Remove leftover debug logging and fix comparison. 2020-05-26 08:56:48 +00:00
nicm
ca0166f26f Do not try to use the last marked pane if it is invalid. 2020-05-26 08:47:50 +00:00
nicm
ea610a3119 Pass the stdout file descriptor from the client as well as stdin and use
them for control clients directly instead of passing everything via the
client.
2020-05-26 08:41:47 +00:00
Nicholas Marriott
bc2e0cf7ff Remove bad merge. 2020-05-26 08:54:05 +01:00
Nicholas Marriott
d73fcfc176 Put the fix back for wcwidth() failing. 2020-05-26 08:49:36 +01:00
Thomas Adam
967e5f8be3 Merge branch 'obsd-master' 2020-05-26 08:42:55 +01:00
Nicholas Marriott
fd4d3e8793 Set IUTF8 again when it exists. 2020-05-26 06:15:57 +01:00
nicm
6f03e49e68 Use the internal representation for UTF-8 keys instead of wchar_t and
drop some code only needed for that.
2020-05-25 18:57:24 +00:00
nicm
35779d655d Fix definition of padding cells so they are not extended cells. 2020-05-25 18:55:36 +00:00
nicm
49ec074271 Tidy up new UTF-8 code and make it more generic. 2020-05-25 18:19:29 +00:00
nicm
dc893405e1 Fix some error strings, from Kris Katterjohn. 2020-05-25 18:17:14 +00:00
Thomas Adam
b34af611a5 Merge branch 'obsd-master' 2020-05-25 18:01:20 +01:00
nicm
bbfb44e9b2 Make some data types consistent. 2020-05-25 15:02:25 +00:00
Thomas Adam
32ce468b22 Merge branch 'obsd-master' 2020-05-25 14:01:19 +01:00
nicm
4589297e43 Do not attempt to divide by zero when working out copy position. 2020-05-25 12:12:58 +00:00
nicm
26e8e467e8 Include title for the width of the menu. 2020-05-25 11:59:50 +00:00
Thomas Adam
bb5a1925ab Merge branch 'obsd-master' 2020-05-25 12:01:19 +01:00
nicm
3a5219c6d0 Instead of storing all UTF-8 characters in the extended cell which means
that 14 bytes are wasted for each character in the BMP, only store
characters of three bytes or less in the cell itself and store others
(outside the BMP or with combining characters) in a separate global
tree. Can reduce grid memory use for heavy Unicode users by around 30%.
2020-05-25 09:32:10 +00:00
Thomas Adam
e16191dbfc Merge branch 'obsd-master' 2020-05-24 16:01:20 +01:00
nicm
14a9fd58d5 Remove leftover call to control_free_offsets and do not use for
non-control clients.
2020-05-24 14:45:00 +00:00
Thomas Adam
aeefd585a0 Merge branch 'obsd-master' 2020-05-24 12:01:21 +01:00
nicm
18aab90959 Give control code its own state struct. 2020-05-24 09:40:17 +00:00
nicm
6c82982711 Now the tty has a pointer back to the client there is no point (and a
bit confusing) in it keeping a copy of the fd as well. Remove it.
2020-05-24 09:13:06 +00:00
Thomas Adam
e71c5efd58 Merge branch 'obsd-master' 2020-05-22 18:01:20 +01:00
Nicholas Marriott
2ac6cc2633 Put headers back how they were. 2020-05-22 17:34:30 +01:00
Nicholas Marriott
a48cc458a6 Maybe this is better. 2020-05-22 17:27:07 +01:00
Nicholas Marriott
1fdacba111 Think Solaris needs term.h here. 2020-05-22 17:24:42 +01:00
Nicholas Marriott
b3e5a99c8f And tweak again. 2020-05-22 17:22:03 +01:00
Nicholas Marriott
6ae26a6b54 Fix utf8proc version logging. 2020-05-22 17:20:35 +01:00
Nicholas Marriott
87a59efc94 Log ncurses and utf8proc versions. 2020-05-22 17:14:35 +01:00
nicm
033d6472cb FocusIn keys can also update the latest client, like normal keys. 2020-05-22 15:43:38 +00:00
nicm
a06a0e1392 xterm* can have focus too. 2020-05-22 15:08:38 +00:00
Thomas Adam
d48f0e114e Merge branch 'obsd-master' 2020-05-22 13:40:33 +01:00
nicm
9a0763c3a0 Move client offset stuff into control.c since only control clients will
need it.
2020-05-22 11:07:04 +00:00
Thomas Adam
2420bd8584 spawn.c: fix up bad merge 2020-05-21 09:02:36 +01:00
Thomas Adam
40126ee96c Merge branch 'obsd-master' 2020-05-21 08:55:31 +01:00
nicm
31e3f2d530 Support code for control mode flow control: allow clients to have
separate offsets (used and acknowleged) into the pane buffers; turn off
reading from panes when no clients can accept the data; and add a -A
flag to refresh-client to let clients turn receiving a pane on and off.
2020-05-21 07:24:13 +00:00
Nicholas Marriott
98a18d064a Fix a regression test, size is not updated until end of event loop. 2020-05-21 08:20:37 +01:00
Thomas Adam
5ac5cd995e Merge branch 'obsd-master' 2020-05-20 10:01:19 +01:00
nicm
6bde1c1837 Fix a couple more places where the key flags need to be masked off. 2020-05-20 07:11:45 +00:00
Thomas Adam
fa835339fd Merge branch 'obsd-master' 2020-05-20 08:01:18 +01:00
nicm
b53e60f4c6 Remove a redundant if statement. 2020-05-20 06:18:22 +00:00
nicm
2a9e2b556a Key strings need to include the cursor and keypad flags now since the
output key lookup expects them already set.
2020-05-20 06:13:09 +00:00
Thomas Adam
fb9e53ba19 Merge branch 'obsd-master' 2020-05-19 14:01:17 +01:00
Nicholas Marriott
e10f5a72ce Add FreeBSD CI, from Jan Beich. 2020-05-19 12:34:34 +01:00
nicm
8425084b8a Some other ctrl keys need to be translated with extended keys on. 2020-05-19 10:59:09 +00:00
Nicholas Marriott
dc56b3cd32 No paths.h. 2020-05-16 20:27:00 +01:00
Thomas Adam
2bc05db54f remove vis.h: portable doesn't need this 2020-05-16 18:42:53 +01:00
Thomas Adam
bd87f6bf00 Merge branch 'obsd-master' 2020-05-16 18:36:35 +01:00
nicm
574a9e4b6c Move lazy resize from the pane to the window, there is no point in
resizing the window unless it is the current window, and if we do and
don't resize the pane until later there are problems if the size changes
from A to B then back to A.
2020-05-16 16:50:55 +00:00
nicm
844b363baf On select-window, make this client the latest client for the window. 2020-05-16 16:45:55 +00:00
nicm
0ab82d9531 Add a terminal feature for enable/disable extended keys (supported by
xterm and mintty) and add an option to make tmux send it. Only forward
extended keys if the application has requested them, even though we use
the CSI u sequence and xterm uses CSI 27 ~ - this is what mintty does as
well.
2020-05-16 16:44:54 +00:00
nicm
292b335ca5 Separate key flags and modifiers, log key flags, make the "xterm" flag
more explicit and fix M- keys with a leading escape.
2020-05-16 16:35:13 +00:00
nicm
e2a26740b9 Add an option to set the pane border lines style from a choice of single
lines (ACS or UTF-8), double or heavy (UTF-8), simple (plain ASCII) or
number (the pane numbers). Lines that won't work on a non-UTF-8 terminal
are translated back into ACS when they are output.
2020-05-16 16:26:34 +00:00
nicm
ecbdcc256f Add screen write flags instead of individual bits and fix line length
calculation with padding.
2020-05-16 16:22:01 +00:00
nicm
303d342d5f Add a client flag 'active-pane' which stores the active pane in the
client and allows it to be changed independently from the real active
pane stored in the window. This is can be used with session groups which
allow an independent current window (although it would be nice to have a
flag for this too and remove session groups). The client active pane is
only really useful interactively, many things (hooks, window-style,
zooming) still use the window active pane.
2020-05-16 16:20:59 +00:00
nicm
c914abfa19 Expand target from client and use it to expand the prompt. 2020-05-16 16:16:07 +00:00
nicm
72984c4834 Move editor stuff to common code in popup.c. 2020-05-16 16:13:09 +00:00
nicm
ff8dd150e0 Add a mark in copy mode. Set with set-mark command (bound to 'X') by
default and the mark and cursor position are swapped with 'jump-to-mark'
(bound to M-x). The line containing the mark is shown in
copy-mode-mark-style with the horizontal position in reverse.

From Anindya Mukherjee in GitHub issue 2209.
2020-05-16 16:10:28 +00:00
nicm
dceb6a15d0 Add a -D flag to ask tmux not to daemonize, useful both for running a
debugger (lldb does not have follow-fork-mode) and for running with a
managed supervisor init system. GitHub issue 2190.
2020-05-16 16:07:55 +00:00
nicm
126bacb473 Do not loop forever when search finds an empty match, GitHub issue 2203. 2020-05-16 16:03:57 +00:00
nicm
592f141dee Fix next-matching-bracket logic, from Chris Barber. 2020-05-16 16:03:30 +00:00
nicm
d67245c734 Add a customize mode where keys and options may be browsed and changed,
includes adding a brief description of each option. Bound to "C" by
default.
2020-05-16 16:02:24 +00:00
nicm
472d77fd0f Support embedded styles in the display-message message, GitHub issue
2206.
2020-05-16 15:54:20 +00:00
nicm
6ea6d46d0a Store and restore cursor position when copy mode is resized, from
Anindya Mukherjee.
2020-05-16 15:49:20 +00:00
nicm
daa95810b5 Allow a custom time format to be given to the t format modifier. 2020-05-16 15:48:35 +00:00
nicm
367b4e4e0f Change message log to be per server rather than per client and include
every command that is run.
2020-05-16 15:47:22 +00:00
nicm
4de0bd4c5c Add M-+ and M-- to expand and collapse all items in tree mode. 2020-05-16 15:46:01 +00:00
nicm
cf9baddd6f Change the existing client flags for control mode to apply for any
client, use the same mechanism for the read-only flag and add an
ignore-size flag.

refresh-client -F has become -f (-F stays for backwards compatibility)
and attach-session and switch-client now have -f flags also. A new
format "client_flags" lists the flags and is shown by list-clients by
default.

This separates the read-only flag from "ignore size" behaviour (new
ignore-size) flag - both behaviours are useful in different
circumstances.

attach -r and switchc -r remain and set or toggle both flags together.
2020-05-16 15:45:29 +00:00
nicm
469eda7e44 Only redraw popup on the client it belongs to. 2020-05-16 15:41:54 +00:00
nicm
4e053685df Export TERM_PROGRAM and TERM_PROGRAM_VERSION like various other
terminals.
2020-05-16 15:40:44 +00:00
nicm
beb214bcb3 Add formats for after hook command arguments. 2020-05-16 15:40:04 +00:00
nicm
d056144aa1 Try to search the entire history first for up to 200 ms so a search
count can be shown. If it takes too long, search the visible text only.
2020-05-16 15:38:14 +00:00
nicm
3fb4d4df43 Do not need to work out status line offset, we already have it. 2020-05-16 15:36:57 +00:00
nicm
2df75aa117 Use VIS_CSTYLE for paste buffers also. 2020-05-16 15:35:19 +00:00
nicm
9605b080f6 Do not hoke into struct window_pane from the tty code and instead set
everything up in tty_ctx. Provide a way to initialize the tty_ctx from a
callback and use it to let popups draw directly through input_parse in
the same way as panes do, rather than forcing a full redraw on every
change.
2020-05-16 15:34:08 +00:00
nicm
379ca54c80 Rename and tidy some stuff in struct tty_ctx. 2020-05-16 15:27:08 +00:00
nicm
edeb81ba9e Add -e for new-session to set environment variables. 2020-05-16 15:25:24 +00:00
nicm
78595457f9 Add 'e' key in buffer mode to open the buffer in an editor. 2020-05-16 15:24:28 +00:00
nicm
a3cbc014c3 Use formats for status-style and message-style. 2020-05-16 15:19:04 +00:00
nicm
58fb81d19a Complete partial window indexes properly. 2020-05-16 15:18:17 +00:00
nicm
463864f5a2 Add -W and -T flags to command-prompt to only complete a window and a
target, also complete aliases.
2020-05-16 15:16:36 +00:00
nicm
2391fe23ab Copy mode search improvements:
- Add styles for the search marking styles (copy-mode-match-style and
  copy-mode-current-match-style).

- Show the current match (the one with the cursor on it) in a different style.

- Copying without a selection will copy the current match if there is one.
2020-05-16 15:11:52 +00:00
nicm
80e52545a0 Improve command prompt completion:
- Show a menu with completions if there are multiple.

- Don't complete argument stuff (options, layouts) at start of text.

- For -t and -s, if there is no : then complete sessions but if there is
  a :, show a menu of all windows in the session rather than trying to
  complete the window name which is a bit useless if there are
  duplicates.
2020-05-16 15:06:03 +00:00
nicm
f03b61131b Drop having a separate type for style options and make them all strings,
which allows formats to be expanded. Any styles without a '#{' are still
validated when they are set but any with a '#{' are not. Formats are not
expanded usefully in many cases yet, that will be changed later.

To make this work, a few other changes:

- set-option -a with a style option automatically appends a ",".

- OSC 10 and 11 don't set the window-style option anymore, instead the
  fg and bg are stored in the pane struct and act as the defaults that
  can be overridden by window-style.

- status-fg and -bg now override status-style instead of trying to keep
  them in sync.
2020-05-16 15:01:30 +00:00
nicm
0487029fc5 Call format_defaults_window for panes as well. 2020-05-16 14:55:38 +00:00
nicm
5bf96c2f2c Use a grid cell not a style for the pane style. 2020-05-16 14:53:23 +00:00
nicm
428137d876 Instead of forbidding invalid session names, sanitize them like window
names.
2020-05-16 14:49:50 +00:00
nicm
7dbe623156 Instead of having a default set of terminals in terminal-overrides that
get XT added and using that as a marker for xterm(1)-like, assume that
if the terminfo(5) entry already has XT or the clear capability starts
with CSI then the terminal is VT100-like and it should be safe to send
DA requests. The DA responses trigger additional features being added.
2020-05-16 14:46:14 +00:00
nicm
21a39c997b Do not redraw or update mode if nothing has changed. 2020-05-16 14:42:06 +00:00
nicm
aebeeec1e9 Add feature and capabilities for focus reporting. Also document AX and
XT even though they aren't tmux's, and add some bits for rxvt.
2020-05-16 14:39:40 +00:00
nicm
26312a7774 Move terminal features into a single file. 2020-05-16 14:30:17 +00:00
nicm
a29196ca6a Build list of paths and weed out duplicates before loading configs, and
add TMUX_SOCK like TMUX_PATH for the socket directory.
2020-05-16 14:26:33 +00:00
nicm
4e0a718666 Add extension terminfo(5) capabilities for margins. 2020-05-16 14:22:51 +00:00
nicm
41dec585df Response is iTerm2 not not ITerm2. 2020-05-16 14:18:39 +00:00
nicm
9dd58470e4 Remove support for iTerm2's DSR 1337 extension and use the CSI > q
extension now supported by a few different terminals.
2020-05-16 14:16:25 +00:00
nicm
471f697423 Add an attribute for ACS. 2020-05-16 14:13:37 +00:00
nicm
0dd1944206 Tweak the default choose modes formats:
- Only show pane title if it is not default and not empty.
- Add a prettier time format and use that instead of long ctime().
- Remove clutter and change the order.
2020-05-16 14:10:29 +00:00
Nicholas Marriott
57fe03dc5a Move lazy resize from the pane to the window, there is no point in resizing the
window unless it is the current window, and if we do and don't resize the pane
until later there are problems if the size changes from A to B then back to A.
2020-05-16 14:57:36 +01:00
Nicholas Marriott
53c84fd4aa If the application has not requested extended keys, then C-1 sends 1 not
nothing.
2020-05-16 07:39:22 +01:00
Nicholas Marriott
740f047a85 Need to update features after all the sequences come in. 2020-05-16 07:32:46 +01:00
Nicholas Marriott
c2167c5ee8 On select-window, make this client the latest client for the window. 2020-05-15 22:52:55 +01:00
Nicholas Marriott
e8ca5a4c7d List needs to be sorted. 2020-05-15 19:17:56 +01:00
Nicholas Marriott
67090dd91d XTerm not xterm. 2020-05-15 19:10:06 +01:00
Nicholas Marriott
401f197750 Er, misread this and it is not needed. 2020-05-15 18:58:13 +01:00
Nicholas Marriott
ca60aabab5 Translate special CSI u keys on input. 2020-05-15 18:25:44 +01:00
Nicholas Marriott
7317a0865c Get == and != the right way round. 2020-05-15 17:49:58 +01:00
Nicholas Marriott
0b828b91a5 Only send XDA on 0. 2020-05-15 17:49:07 +01:00
Nicholas Marriott
dcf537519f Fix default values for new escape sequences. 2020-05-15 17:48:21 +01:00
Nicholas Marriott
c364a7142c Only forward extended keys if the application has requested them, even though
we use the CSI u sequence and xterm uses CSI 27 ~ - this is what mintty does as
well.
2020-05-15 17:40:24 +01:00
Nicholas Marriott
3a4f3ee087 Mask off flags bits in menu keys. 2020-05-15 16:17:20 +01:00
Nicholas Marriott
6d92b99dbc Add a terminal feature for enable/disable extended keys (supported by xterm and
mintty) and add an option to make tmux send it.
2020-05-15 16:15:24 +01:00
Nicholas Marriott
e6b17e77db C-M-S keys need the implied flag also. 2020-05-15 15:11:08 +01:00
Nicholas Marriott
e23c73457a Stop at end of buffer. 2020-05-15 15:05:49 +01:00
Nicholas Marriott
3e60ab1caf Send conventional \033 sequences for keys with just Meta even if they came in
as an extended CSI u key sequence. It is much more useful for applications that
don't understand CSI u to receive \033> for M-S-. rather than \033[62;3u.
2020-05-15 13:15:12 +01:00
Nicholas Marriott
7501e297dd Send CSI u sequences for any keys that do not have a defined sequence already -
this should only be similar sequences sent by the terminal outside tmux if
enabled.
2020-05-15 12:39:37 +01:00
Nicholas Marriott
340fd691cb Separate key flags and modifiers, log key flags, make the "xterm" flag more
explicit and fix M- keys with a leading escape.
2020-05-15 12:16:41 +01:00
Nicholas Marriott
031d4864a9 Rename KEYC_ESCAPE to KEYC_META. 2020-05-15 11:24:30 +01:00
Nicholas Marriott
2cf967ee67 Always set xterm flag. 2020-05-15 11:20:12 +01:00
Nicholas Marriott
e95b644139 Recognise extended key sequences on input (both the forms xterm offers). 2020-05-15 11:09:32 +01:00
Nicholas Marriott
5ee4d991b6 xterm-keys has been on by default for 5 years and all other modern terminals
use these key sequences by default. Merge the code into the main tty and input
tree processing (convering the latter to use a tree rather than a table at the
same time) and make the option a no-op.
2020-05-15 10:31:54 +01:00
Nicholas Marriott
c4d8100b2f Draw outside correctly with pane numbers. 2020-05-14 16:58:14 +01:00
Nicholas Marriott
bef70132ac Check if outside the window before checking if on the border so that cells that
are outside in one direction but not the other are not given the wrong type.
2020-05-14 16:53:04 +01:00
Nicholas Marriott
31621036ad Add an option to set the pane border lines style from a choice of single lines
(ACS or UTF-8), double or heavy (UTF-8), simple (plain ASCII) or number (the
pane numbers). Lines that won't work on a non-UTF-8 terminal are translated
back into ACS when they are output.
2020-05-14 16:49:08 +01:00
Nicholas Marriott
97c8374855 Tweak CHANGES. 2020-05-14 14:07:26 +01:00
Nicholas Marriott
4dc0f3ee6b Update CHANGES. 2020-05-14 14:01:32 +01:00
Nicholas Marriott
09a66451ce Add screen write flags instead of individual bits and fix line length
calculation with padding.
2020-05-14 13:18:05 +01:00
Nicholas Marriott
0bdbf47ef9 Add a client flag 'active-pane' which stores the active pane in the client and
allows it to be changed independently from the real active pane stored in the
window. This is can be used with session groups which allow an independent
current window (although it would be nice to have a flag for this too and
remove session groups). The client active pane is only really useful
interactively, many things (hooks, window-style, zooming) still use the window
active pane.
2020-05-14 11:18:19 +01:00
Nicholas Marriott
12eceaf2b3 Expand target from client and use it to expand the prompt. 2020-05-14 10:35:26 +01:00
Nicholas Marriott
09a2246b00 Use safe loop for freeing client files. 2020-05-13 21:11:46 +01:00
Nicholas Marriott
e6d9f3f90c Add -Z to customize-mode binding. 2020-05-13 20:58:42 +01:00
Nicholas Marriott
3f55d05386 Tidy up border redrawing, fix some errors in how the window border connects
with panes.
2020-05-13 17:49:37 +01:00
Nicholas Marriott
4cb1d3d7a9 Move editor stuff to common code in popup.c. 2020-05-13 06:58:07 +01:00
Nicholas Marriott
6214cd0726 Add a mark in copy mode. Set with set-mark command (bound to 'X') by default
and the mark and cursor position are swapped with 'jump-to-mark' (bound to
M-x). The line containing the mark is shown in copy-mode-mark-style with the
horizontal position in reverse.

From Anindya Mukherjee in GitHub issue 2209.
2020-05-13 06:29:57 +01:00
Thomas Adam
9d44df9da9 Merge branch 'master' of github.com:tmux/tmux 2020-05-13 01:15:31 +01:00
Thomas Adam
212cf53ea9 Merge branch 'obsd-master' 2020-05-13 01:05:04 +01:00
Nicholas Marriott
ba20e46bdc Do not log NULL text. 2020-05-12 10:36:31 +01:00
Nicholas Marriott
8d238491d0 Show default key bindings in customize mode. 2020-05-12 10:22:38 +01:00
Nicholas Marriott
5a34f51d33 Include key bindings in customize mode. 2020-05-12 08:57:55 +01:00
Nicholas Marriott
c489bf0a1e Support embedded styles in the display-message message, GitHub issue 2206. 2020-05-11 09:18:35 +01:00
Nicholas Marriott
8502517d30 Add to CHANGES. 2020-05-10 17:06:31 +01:00
Nicholas Marriott
0070313e28 Fix comparison of tty name. 2020-05-10 16:57:33 +01:00
Nicholas Marriott
d01e7aac89 Add a -D flag to ask tmux not to daemonize, useful both for running a debugger
(lldb does not have follow-fork-mode) and for running with a managed supervisor
init system. GitHub issue 2190.
2020-05-10 16:52:46 +01:00
Nicholas Marriott
5fa377d927 Do not loop forever when search finds an empty match, GitHub issue 2203. 2020-05-10 10:01:20 +01:00
Nicholas Marriott
79a9a7b931 Fix next-matching-bracket logic, from Chris Barber. 2020-05-09 16:15:08 +01:00
Nicholas Marriott
532d06c399 Initialize return code in case something mysterious happens. 2020-05-09 16:08:13 +01:00
Nicholas Marriott
013d857ef8 Wrap all lines in customize mode, not just the description. 2020-05-09 15:29:14 +01:00
Nicholas Marriott
690d72adb3 Remove unused variables. 2020-05-09 14:38:00 +01:00
Nicholas Marriott
ca18990826 Fix some warnings, from Jan Polensky. 2020-05-09 14:33:25 +01:00
Nicholas Marriott
5e97d79eb1 Fix some customize mode drawing nits. 2020-05-08 22:09:31 +01:00
Nicholas Marriott
a61cbf1c33 Add a customize mode where options may be browsed and changed, includes adding
a brief description of each option. Bound to "C" by default.
2020-05-08 19:10:09 +01:00
nicm
aa7dccf8e1 imsg.h needs uio.h, pointed out by deraadt 2020-05-08 14:15:11 +00:00
Nicholas Marriott
708e9bc072 Allow a custom time format to be given to the t format modifier. 2020-05-07 11:04:43 +01:00
Nicholas Marriott
b0fa36734e Fix pretty time function to actually work and allow time format to be applied
to any string that is suitable.
2020-05-07 09:55:06 +01:00
Nicholas Marriott
63e17d8cad Do not use client if NULL, from Thomas Adam. 2020-05-07 05:55:42 +01:00
Nicholas Marriott
66ecb1dff4 Update CHANGES. 2020-05-06 15:48:27 +01:00
Nicholas Marriott
7a95e9bf7e Change message log to be per server rather than per client and include every
command that is run.
2020-05-06 13:43:22 +01:00
Nicholas Marriott
c80fc6bf9e Add M-+ and M-- to expand and collapse all items in tree mode. 2020-05-05 16:33:58 +01:00
Nicholas Marriott
2f89d2e7d8 Change the existing client flags for control mode to apply for any client, use
the same mechanism for the read-only flag and add an ignore-size flag.

refresh-client -F has become -f (-F stays for backwards compatibility) and
attach-session and switch-client now have -f flags also. A new format
"client_flags" lists the flags and is shown by list-clients by default.

This separates the read-only flag from "ignore size" behaviour (new
ignore-size) flag - both behaviours are useful in different circumstances.

attach -r and switchc -r remain and set or toggle both flags together.
2020-05-05 15:42:20 +01:00
Nicholas Marriott
deacfedc65 Remove an extra space in clients output. 2020-05-05 13:34:53 +01:00
Nicholas Marriott
32c134f5a9 Wrap a line. 2020-05-05 12:39:20 +01:00
Nicholas Marriott
23b4e1b9d8 pane_path is not #T, from Chris Rawnsley. 2020-05-05 11:35:33 +01:00
Nicholas Marriott
e810f15272 Store and restore cursor position when copy mode is resized, from Anindya
Mukherjee.
2020-05-05 10:20:57 +01:00
Nicholas Marriott
1f6c00f8ef Only redraw popup on the client it belongs to. 2020-05-05 10:02:47 +01:00
Nicholas Marriott
63390d2dd6 Export TERM_PROGRAM and TERM_PROGRAM_VERSION like various other terminals. 2020-05-05 06:31:14 +01:00
Nicholas Marriott
9991a14e81 Add formats for after hook command arguments. 2020-05-05 06:19:29 +01:00
Nicholas Marriott
fc13e9bc2b Turn off cursor in menus again. 2020-05-04 17:37:03 +01:00
Nicholas Marriott
a08f1c8c59 Merge branch '3.1b-rc' 2020-05-04 09:14:36 +01:00
Nicholas Marriott
c89ed7c092 Try to search the entire history first for up to 200 ms so a search count can
be shown. If it takes too long, search the visible text only.
2020-05-03 15:58:29 +01:00
Nicholas Marriott
e7aeb77bd9 Use the cursor position not the current position when working out which marks
are current.
2020-05-03 15:44:38 +01:00
Nicholas Marriott
cb09705df3 Need musl-gcc for static also. 2020-05-03 12:37:38 +01:00
Nicholas Marriott
4fcbd6700f Add musl builds. 2020-05-03 12:33:47 +01:00
Nicholas Marriott
ff5e3d1a88 Ugh, enable not with. 2020-05-03 12:20:08 +01:00
Nicholas Marriott
fbc8fca067 Use termcap instead. 2020-05-03 12:18:04 +01:00
Nicholas Marriott
1cfa6b0d5c Try w/o database. 2020-05-03 12:12:47 +01:00
Nicholas Marriott
b203f7f19f Better ncurses URL and some other fixes. 2020-05-03 12:03:50 +01:00
Nicholas Marriott
97d490204b Add build of everything. 2020-05-03 11:47:28 +01:00
Nicholas Marriott
55901367d0 Add more stuff. 2020-05-03 11:16:30 +01:00
Nicholas Marriott
ff250aa30e Fix exclude. 2020-05-03 11:12:51 +01:00
Nicholas Marriott
955d9d22b9 Add static build. 2020-05-03 11:09:36 +01:00
Nicholas Marriott
daef6f6b67 Merge branch '3.1b-rc' 2020-05-03 10:49:35 +01:00
Nicholas Marriott
d9a4449307 Do not need to work out status line offset, we already have it. 2020-05-02 16:44:31 +01:00
Nicholas Marriott
af69289e0e Clamping to area needs to use the offset without the status line, since that is
where the window offsets are based.
2020-05-02 16:17:44 +01:00
Nicholas Marriott
cb1131a294 menu_mode_cb needs to return a screen also. 2020-05-02 15:15:52 +01:00
Nicholas Marriott
e078f975c5 Update CHANGES. 2020-05-01 18:24:20 +01:00
Nicholas Marriott
bf84359dfb Use VIS_CSTYLE for paste buffers also. 2020-05-01 17:59:13 +01:00
Nicholas Marriott
1fa9bcc183 Turn off overlay check when we know we are inside. 2020-05-01 17:55:08 +01:00
Nicholas Marriott
3f1fc9cde3 Get the whole overlay screen not just the mode so cursor changes are included. 2020-05-01 17:30:28 +01:00
Nicholas Marriott
8110c7a25f Do not hoke into struct window_pane from the tty code and instead set
everything up in tty_ctx. Provide a way to initialize the tty_ctx from a
callback and use it to let popups draw directly through input_parse in the same
way as panes do, rather than forcing a full redraw on every change.
2020-05-01 17:01:36 +01:00
Nicholas Marriott
dbebdb2d36 Rename tty_pane_full_width to tty_full_width. 2020-05-01 13:22:08 +01:00
Nicholas Marriott
93dca5ab3f Move size to tty_ctx. 2020-05-01 13:19:05 +01:00
Nicholas Marriott
5ce194f15d Rename some tty_ctx members. 2020-05-01 13:01:55 +01:00
Nicholas Marriott
af21e76fdb Add -e for new-session. 2020-05-01 12:01:58 +01:00
Nicholas Marriott
ec61aa3025 Solaris at least does not have _PATH_VI. 2020-05-01 09:11:56 +01:00
Nicholas Marriott
5c888e168e Typo in man page. 2020-05-01 09:05:56 +01:00
Nicholas Marriott
cc19203be2 Add 'e' key in buffer mode to open the buffer in an editor. 2020-05-01 09:02:44 +01:00
Thomas Adam
7af5817245 Merge branch 'obsd-master' 2020-04-30 16:01:27 +01:00
Nicholas Marriott
3d33a19102 Merge tag '3.1b'
3.1b
2020-04-30 15:21:47 +01:00
Nicholas Marriott
8e01221d02 Allow formats for message-style. 2020-04-30 14:59:58 +01:00
Nicholas Marriott
272f3dbf2e Use format for status-style. 2020-04-30 14:56:46 +01:00
nicm
048f1ff18a Do not remove the automatic-rename option from the global set, only from
the window (it must stay in the global set or tmux will crash). GitHub
issue 2188.
2020-04-30 13:31:22 +00:00
Nicholas Marriott
66bab1f6cf Complete partial window indexes properly. 2020-04-30 13:05:21 +01:00
Nicholas Marriott
25487757bc Add -W and -T flags to command-prompt to only complete a window and a target. 2020-04-30 12:02:21 +01:00
Nicholas Marriott
5af6943940 Complete aliases as well as commands. 2020-04-29 19:55:20 +01:00
Nicholas Marriott
7324442b42 Add to CHANGES. 2020-04-29 19:48:26 +01:00
Nicholas Marriott
6f700904a9 Copy mode search improvements:
- Add styles for the search marking styles (copy-mode-match-style and
  copy-mode-current-match-style).

- Show the current match (the one with the cursor on it) in a different style.

- Copying without a selection will copy the current match if there is one.
2020-04-29 18:08:21 +01:00
Nicholas Marriott
881b8e9bb5 Handle cells outside any pane correctly. 2020-04-29 16:50:20 +01:00
Nicholas Marriott
a9743fa047 Did not mean to commit this bit. 2020-04-29 15:27:38 +01:00
Nicholas Marriott
04033add19 Close menu on backspace with TAB flag. 2020-04-29 15:26:49 +01:00
Nicholas Marriott
d9fa122fd2 Do not want -O0 by default. 2020-04-29 15:21:15 +01:00
Nicholas Marriott
fe601e5417 Update CHANGES. 2020-04-29 15:19:39 +01:00
Nicholas Marriott
b06235c345 Improve command prompt completion:
- Show a menu with completions if there are multiple.

- Don't complete argument stuff (options, layouts) at start of text.

- For -t and -s, if there is no : then complete sessions but if there is a :,
  show a menu of all windows in the session rather than trying to complete the
  window name which is a bit useless if there are duplicates.

Lots of scope for being more sophisticated left here.
2020-04-29 13:56:10 +01:00
Nicholas Marriott
7c52d702e4 Remove an unnecessary comma. 2020-04-29 08:59:20 +01:00
Nicholas Marriott
3d76748161 Need to redraw borders now when some things change. Also change default so that
the active border colour is different in a mode or with synchronize-panes on.
2020-04-29 08:55:21 +01:00
Nicholas Marriott
2d151d8ca5 Apply format to pane status line also. 2020-04-29 08:24:09 +01:00
Nicholas Marriott
24316bed49 Apply a format when redrawing pane borders. 2020-04-29 08:21:29 +01:00
Nicholas Marriott
c1acfb4341 Start with style initialized to default. 2020-04-28 17:27:07 +01:00
Nicholas Marriott
1f8256fc50 Drop having a separate type for style options and make them all strings, which
allows formats to be expanded. Any styles without a '#{' are still validated
when they are set but any with a '#{' are not. Formats are not expanded
usefully in many cases yet, that will be changed later.

To make this work, a few other changes:

- set-option -a with a style option automatically appends a ",".

- OSC 10 and 11 don't set the window-style option anymore, instead the fg and
  bg are stored in the pane struct and act as the defaults that can be
  overridden by window-style.

- status-fg and -bg now override status-style instead of trying to keep them in
  sync.
2020-04-28 13:50:07 +01:00
Nicholas Marriott
a43a156846 Call format_defaults_window for panes as well. 2020-04-28 10:53:35 +01:00
Nicholas Marriott
79b4d83952 Use a grid cell not a style for the pane style. 2020-04-27 15:15:12 +01:00
Nicholas Marriott
c30e765c7b Add some additional format helper functions. 2020-04-27 14:33:17 +01:00
Thomas Adam
e62db55713 Merge branch 'obsd-master' 2020-04-27 10:01:27 +01:00
Nicholas Marriott
266bbba484 Merge branch '3.1a-rc' 2020-04-27 09:39:17 +01:00
nicm
1574126e8a Do not close the stdout file descriptor in control mode as it will be
needed for printing the exit messages. Fixes a bug when detaching with
iTerm2.
2020-04-27 08:35:09 +00:00
Nicholas Marriott
5811dd7ceb Do not close stdout file descriptor in control mode since it will be needed for
printing the exit messages.
2020-04-27 09:33:46 +01:00
Nicholas Marriott
f3d6d4e802 CUD is not a requirement and tweak some comments. 2020-04-24 16:47:38 +01:00
Nicholas Marriott
9b571dacee Instead of forbidding invalid session names, sanitize them. 2020-04-24 16:40:10 +01:00
Nicholas Marriott
527f66ed23 Instead of having a default set of terminals in terminal-overrides that get XT
added and using that as a marker for xterm(1)-like, assume that if the
terminfo(5) entry already has XT or the clear capability starts with CSI then
the terminal is VT100-like and it should be safe to send DA requests. The DA
responses trigger additional features being added.

This is all to detect extensions if terminfo(5) is wrong or inadequate. If it
fails, tmux will just fall back to using the capabilities in the terminfo(5)
entry alone.
2020-04-24 15:52:44 +01:00
Nicholas Marriott
e67d65064e rxvt needs XT also for the moment. 2020-04-24 14:20:33 +01:00
Nicholas Marriott
c107708bcc Focus reporting no longer under XT. 2020-04-24 14:20:17 +01:00
Nicholas Marriott
a477c03ad5 Do not update mode until actually drawing something. 2020-04-24 12:14:53 +01:00
Nicholas Marriott
ae73fd363b Do not redraw at all if nothing has changed. 2020-04-24 11:56:44 +01:00
Nicholas Marriott
bb107d2979 All of this stuff can be const. 2020-04-24 07:47:16 +01:00
Nicholas Marriott
61550ac2e0 Add feature and capabilities for focus reporting. Also document AX and XT even
though they aren't tmux's.
2020-04-24 07:37:11 +01:00
Nicholas Marriott
5d69b9c4a7 Add a feature for bracketed paste. 2020-04-24 07:13:02 +01:00
Nicholas Marriott
2d8fd35de2 Add a feature for strikethrough. 2020-04-24 06:51:15 +01:00
Nicholas Marriott
8650f44340 Move terminal features into a single file. 2020-04-24 06:40:51 +01:00
Thomas Adam
ca13208b6b Merge branch 'obsd-master' 2020-04-24 00:01:27 +01:00
jmc
18886cb510 ce examples of "Ar arg Ar arg" with "Ar arg arg" and stop the spread; 2020-04-23 21:28:09 +00:00
Nicholas Marriott
d1c1e05ea7 Update CHANGES. 2020-04-23 18:27:27 +01:00
Nicholas Marriott
d53e1fedd5 Add TMUX_SOCK like TMUX_PATH for the socket directory. 2020-04-23 18:15:02 +01:00
Nicholas Marriott
0d3fdae7b6 Build list of paths and weed out duplicates before loading configs. 2020-04-23 17:56:45 +01:00
Nicholas Marriott
f87be8d052 Add XDG_CONFIG home to the configuration search paths. 2020-04-23 17:27:39 +01:00
Nicholas Marriott
351c5423f0 time.h is needed. 2020-04-23 16:55:20 +01:00
Nicholas Marriott
ac91635f82 Add extension terminfo(5) capabilities for margins. 2020-04-23 12:12:02 +01:00
Nicholas Marriott
0c73dbb7e1 Response is iTerm2 not not ITerm2. 2020-04-23 12:12:02 +01:00
Thomas Adam
5653bc8287 Merge branch 'obsd-master' 2020-04-23 12:01:26 +01:00
nicm
766b425d05 Overrides need to be applied both before and after features in case they
change flags used to detect a feature.
2020-04-23 10:22:53 +00:00
Nicholas Marriott
c74572da92 Remove support for iTerm2's DSR 1337 extension and use the CSI > q extension
now supported by a few different terminals.
2020-04-23 10:29:03 +01:00
Thomas Adam
e94a15b3d6 Merge branch 'obsd-master' 2020-04-23 10:01:26 +01:00
Nicholas Marriott
1a612a5936 Add an attribute for ACS. 2020-04-23 07:15:17 +01:00
nicm
e25fa4ba1b Fix a couple of memory leaks, one when creating a new pane and one when
adding formats onto the queue item.
2020-04-23 05:48:42 +00:00
nicm
906dfe9f5c Fix a couple of memory leaks, one when creating a new pane and one when
adding formats onto the queue item.
2020-04-23 05:48:42 +00:00
Nicholas Marriott
106e5d07be Tweak the default choose modes formats:
- Only show pane title if it is not default and not empty.
- Add a prettier time format and use that instead of long ctime().
- Remove clutter and change the order.
2020-04-23 06:30:15 +01:00
Thomas Adam
63f2034f29 Merge branch 'obsd-master' 2020-04-23 04:01:30 +01:00
Thomas Adam
cf5f93b2b3 Merge branch 'obsd-master' 2020-04-23 02:01:33 +01:00
nicm
e46cf86d30 Improve join-pane, move-pane and break-pane:
- There is no need for join-pane and move-pane to be different.
- break-pane can just behave like move-window if the source has only one
  pane, instead of failing.
- Add -a to break-pane like move-window.

Also add missing man page bits for previous window-tree.c changes.

GitHub issue 2176.
2020-04-22 21:15:33 +00:00
nicm
950af33636 Improve join-pane, move-pane and break-pane:
- There is no need for join-pane and move-pane to be different.
- break-pane can just behave like move-window if the source has only one
  pane, instead of failing.
- Add -a to break-pane like move-window.

Also add missing man page bits for previous window-tree.c changes.

GitHub issue 2176.
2020-04-22 21:15:33 +00:00
Thomas Adam
4a31eedc26 Merge branch 'obsd-master' 2020-04-22 22:01:35 +01:00
nicm
4b21fd2ed1 Indicate the marked pane in choose mode in reverse and add key to set
and clear it (m and M) and a key to jump to the starting pane (H).
2020-04-22 21:01:28 +00:00
nicm
899b3d2436 Indicate the marked pane in choose mode in reverse and add key to set
and clear it (m and M) and a key to jump to the starting pane (H).
2020-04-22 21:01:28 +00:00
nicm
662728d6c7 Add a session_marked format like window_marked. 2020-04-22 20:47:00 +00:00
Thomas Adam
b4a21b5d80 Merge branch 'obsd-master' 2020-04-22 14:01:33 +01:00
Nicholas Marriott
bb31776dd3 Merge branch '3.1-rc' 2020-04-22 13:00:43 +01:00
Nicholas Marriott
ecb6db6b6a Update CHANGES. 2020-04-22 12:59:10 +01:00
Nicholas Marriott
d4826aa1aa Nope, OS X kqueue is still broken...
This reverts commit 94c90385d2e728a4d37a25ce78b55b2ffeb429f9.
2020-04-22 12:18:11 +01:00
Nicholas Marriott
df1bce40f0 Call the event_init wrapper again. 2020-04-22 12:09:25 +01:00
Thomas Adam
8ae3915cc2 Merge branch 'obsd-master' 2020-04-22 12:01:38 +01:00
nicm
4b5a16567a Update the cursor position when deleting lines from screens without
history, GitHub issue 2173.
2020-04-22 08:48:44 +00:00
nicm
b72498c4ff Update the cursor position when deleting lines from screens without
history, GitHub issue 2173.
2020-04-22 08:48:44 +00:00
nicm
5935100181 Change so main-pane-width and height can be given as a percentage. 2020-04-22 06:57:13 +00:00
nicm
de5163a634 Change so main-pane-width and height can be given as a percentage. 2020-04-22 06:57:13 +00:00
Thomas Adam
dd5299841a Merge branch 'obsd-master' 2020-04-21 16:01:30 +01:00
nicm
445dfa8512 Move the background colour to clear with (if any) up as well as the data
when scrolling, redraw problem reported by sthen@.
2020-04-21 13:48:56 +00:00
Thomas Adam
291b85746f Merge branch 'obsd-master' 2020-04-21 14:01:25 +01:00
Thomas Adam
2cbca7ce16 Merge branch 'obsd-master' 2020-04-21 12:01:35 +01:00
nicm
9a60d41db4 256 and RGB features can imply AX (for aixterm colours). 2020-04-21 10:37:11 +00:00
nicm
bd91015b13 256 and RGB features can imply AX (for aixterm colours). 2020-04-21 10:37:11 +00:00
Thomas Adam
985bc0ee4a Merge branch 'obsd-master' 2020-04-21 08:01:30 +01:00
nicm
18671a27b6 Turn off the block flag to reset the state or the cursor will not be
moved back to the right place.
2020-04-21 06:34:13 +00:00
nicm
57bd6e0447 Turn off the block flag to reset the state or the cursor will not be
moved back to the right place.
2020-04-21 06:34:13 +00:00
nicm
d524cb64e7 Do not clear client pane redraw flags until the redraw actually happens. 2020-04-21 06:32:40 +00:00
nicm
d0b8f5340e Do not clear client pane redraw flags until the redraw actually happens. 2020-04-21 06:32:40 +00:00
nicm
1cabccbb2b xterm* needs XT also. 2020-04-21 05:26:13 +00:00
Thomas Adam
32c3fe40eb Merge branch 'obsd-master' 2020-04-20 17:43:20 +01:00
Thomas Adam
c706aadf52 Merge branch 'obsd-master' 2020-04-20 17:42:29 +01:00
nicm
4a5182e665 Always start sync for output in panes that are not the active pane. 2020-04-20 15:49:05 +00:00
nicm
117ec1b2e6 Apply terminal-overrides after terminal detection, it always takes
precedence.
2020-04-20 15:37:32 +00:00
nicm
2083a6ea20 Change how sync works to always send the end sequence after all output
is done when we are returning to the event loop (since we always move
the cursor at that point). Also a man fix from jmc.
2020-04-20 14:59:31 +00:00
nicm
135bb1edee Change the Sync capability to be a string instead of a flag. 2020-04-20 13:38:48 +00:00
nicm
c91b4b2e14 Tidy up the terminal detection and feature code and add named sets of
terminal features, each of which are defined in one place and map to a
builtin set of terminfo(5) capabilities. Features can be specified based
on TERM with a new terminal-features option or with the -T flag when
running tmux. tmux will also detect a few common terminals from the DA
and DSR responses.

This is intended to make it easier to configure tmux's use of
terminfo(5) even in the presence of outdated ncurses(3) or terminfo(5)
databases or for features which do not yet have a terminfo(5) entry.
Instead of having to grok terminfo(5) capability names and what they
should be set to in the terminal-overrides option, the user can
hopefully just give tmux a feature name and let it do the right thing.

The terminal-overrides option remains both for backwards compatibility
and to allow tweaks of individual capabilities.

tmux already did much of this already, this makes it tidier and simpler
to configure.
2020-04-20 13:25:36 +00:00
Thomas Adam
3898d4e7c8 Merge branch 'obsd-master' 2020-04-20 12:01:32 +01:00
nicm
86862c976a Also redraw panes which aren't pane 0. Problem reported by tb@. 2020-04-20 09:07:55 +00:00
Thomas Adam
b1be668a3e Merge branch 'obsd-master' 2020-04-20 08:01:31 +01:00
nicm
b846ec2665 Only trim blank lines when the source pane is not the target pane,
otherwise the cursor moves which is a bit strange.
2020-04-20 06:08:37 +00:00
nicm
4bc0a83d51 Need to check for pane redrawing even if just the window flag is set
(the pane flag may not have been previously set to avoid looping the
windows).
2020-04-20 06:07:39 +00:00
Thomas Adam
8c9bbc3749 Merge branch 'obsd-master' 2020-04-19 00:01:31 +01:00
nicm
62ff5e4b01 The PANE_REDRAW flag bit might be needed by other panes so we can't
clear it on the first redraw, and it can't be set when we are finished
or they would be redrawn again, so if the redraw is deferred for a
client, copy the redraw flag into a separate set of bits just for that
client.
2020-04-18 21:35:32 +00:00
Thomas Adam
7da5418758 Merge branch 'obsd-master' 2020-04-18 20:01:29 +01:00
nicm
100db552d1 A resize can realloc so cannot cache the value of the list pointer. 2020-04-18 17:20:25 +00:00
Thomas Adam
2b83ee5557 Merge branch 'obsd-master' 2020-04-18 18:01:28 +01:00
nicm
deffef6f13 Reset background colour on scrolled line. 2020-04-18 15:22:05 +00:00
nicm
ea5fdd5331 There is no point in keeping a bunch of different text buffers for each
line when writing, we only need one as big as the line width - there
can't be any more text than that since newer will overwrite older.
2020-04-18 15:12:28 +00:00
Thomas Adam
2ccf15e5d8 Merge branch 'obsd-master' 2020-04-18 16:01:34 +01:00
nicm
4a93294152 Use size_t not u_int for the bytes counters and fix a const missing. 2020-04-18 14:21:39 +00:00
Thomas Adam
d55510ebc8 Merge branch 'obsd-master' 2020-04-18 12:01:31 +01:00
Nicholas Marriott
94c90385d2 Apple appear to have fixed kqueue in some OS X version (will wonder never
cease!) so use it since it appears to be faster.
2020-04-18 11:45:49 +01:00
Thomas Adam
e1799ed7c8 Merge branch 'obsd-master' 2020-04-18 10:01:31 +01:00
nicm
c87595326c Use peek line function instead of hoking in the array directly. 2020-04-18 09:00:31 +00:00
nicm
b0a37e7514 Bring back previons fix to only redraw panes that need it after a redraw
is deferred, but clear the pane flags when they are actually redrawn
rather than every time.
2020-04-18 07:32:53 +00:00
nicm
e153b928ff Add formats for pane written/skipped bytes for debugging. 2020-04-18 07:19:28 +00:00
Thomas Adam
349617a818 Merge branch 'obsd-master' 2020-04-18 08:01:37 +01:00
nicm
baf1fca273 Only update mode when actually going to redraw something. 2020-04-18 06:52:36 +00:00
nicm
1d2bd864f2 Add a flag to protect against nested syncs and add some extra logging to
redrawing.
2020-04-18 06:20:50 +00:00
nicm
d94bdf7420 Revert previous, there is still a problem. 2020-04-18 06:15:07 +00:00
nicm
5289d4ed13 When a redraw is deferred because the terminal hasn't finished reading
the data from the last one, other panes could update while waiting, so
we set the flag to redraw them all when the new redraw actually
happened. But this means a lot of redrawing panes unnecessarily if they
haven't changed - so instead set a flag to say "at least one pane needs
to be redrawed" then look at the invidual pane flags to see which ones
need it.
2020-04-18 06:10:15 +00:00
Thomas Adam
87d79e6d36 Merge branch 'obsd-master' 2020-04-18 00:01:30 +01:00
nicm
a7a9460d27 Set mode properly before and after redrawing, and don't bother
calculating cursor position if it won't be used.
2020-04-17 22:16:28 +00:00
nicm
a877a5d8c9 Do not move the cursor to the existing y position if it is invalid, go
home instead.
2020-04-17 21:33:18 +00:00
Thomas Adam
857fca1095 Merge branch 'obsd-master' 2020-04-17 18:01:30 +01:00
nicm
bbd6e899a8 There is no point allocating a new item and putting it on the list when
the whole line is cleared line, there is never any point in doing it
more than once. Instead store the background colour alone.
2020-04-17 15:44:58 +00:00
Thomas Adam
7a21e911e1 Merge branch 'obsd-master' 2020-04-17 16:01:33 +01:00
nicm
282a7a8d96 Make sure the cursor position is still on screen after we have trimmed
empty lines. Also improve some log messages.
2020-04-17 14:06:42 +00:00
Thomas Adam
abeb31dd3d Merge branch 'obsd-master' 2020-04-17 12:01:30 +01:00
nicm
7f2925a01d Support the application escape sequence mintty (means tmux doesn't have
to delay to wait for Escape).
2020-04-17 09:06:10 +00:00
Thomas Adam
413c4cfd1b Merge branch 'obsd-master' 2020-04-17 10:01:38 +01:00
nicm
5aba26f2cb Add a copy-command option and change copy-pipe and friends to pipe to it
if used without arguments, allows all copy key bindings to be changed to
pipe with one option.
2020-04-17 08:03:22 +00:00
Thomas Adam
2846be326a Merge branch 'obsd-master' 2020-04-17 00:01:35 +01:00
nicm
5f18844b32 Return to sending sync around clears. 2020-04-16 21:46:43 +00:00
nicm
d8433add47 Do not need to set up a tty context for clearing lines now. 2020-04-16 21:16:24 +00:00
nicm
d90ca7ecd6 Collect up line clears like text within the available data so we don't
need to flush everything.
2020-04-16 20:32:51 +00:00
Thomas Adam
9edef17698 Merge branch 'obsd-master' 2020-04-16 20:01:31 +01:00
nicm
c1b015f24e Log what caused a flush for better visibility on what could be improved. 2020-04-16 17:24:28 +00:00
nicm
9311ed049b Start menu with top item selected if no mouse, GitHub issue 2169. 2020-04-16 17:20:23 +00:00
Thomas Adam
21eb2ba419 Merge branch 'obsd-master' 2020-04-16 18:01:32 +01:00
nicm
2e347d6a38 Only start and stop sync for operations like clear and scroll where
there is a better chance more data will be on the way.
2020-04-16 16:13:56 +00:00
nicm
363d950ac0 Send secondary device attributes instead of primary which gives us a bit
more useful information on some terminals.
2020-04-16 15:14:25 +00:00
Thomas Adam
5e38d26257 Merge branch 'obsd-master' 2020-04-16 16:01:35 +01:00
nicm
5ec80bd249 Move the UTF-8 flag to terminal flags. 2020-04-16 14:25:35 +00:00
nicm
4744aa43af Add a helper function to get the terminal flags. 2020-04-16 14:03:51 +00:00
nicm
b2443aa2f9 Add support for the iTerm2 sychronized updates escape sequence which
drastically reduces flickering.
2020-04-16 13:35:24 +00:00
Nicholas Marriott
b3cadf8260 Fix sys_signame check. 2020-04-16 10:15:33 +01:00
Nicholas Marriott
1aa2845026 Check for sys_signame. 2020-04-16 10:08:16 +01:00
Thomas Adam
dd66ede38b Merge branch 'obsd-master' 2020-04-16 10:01:33 +01:00
nicm
a2e47b5279 Show signal name when process exits rather than number. 2020-04-16 07:28:36 +00:00
Thomas Adam
3aa1e5810c Merge branch 'obsd-master' 2020-04-16 08:01:26 +01:00
nicm
b6dfca9b4d Don't miss the last line off the screen when writing after resize, from
Anindya Mukherjee.
2020-04-16 05:22:08 +00:00
Thomas Adam
8dc06446ec Merge branch 'obsd-master' 2020-04-15 22:01:31 +01:00
nicm
fc1855f514 Clear the selection and repeat the search on refresh same as resize. 2020-04-15 19:06:49 +00:00
Thomas Adam
6d6309014e Merge branch 'obsd-master' 2020-04-15 20:01:27 +01:00
nicm
53a29a2ffa Instead of fixing with the cursor position when the copied screen is
created, resize it and let the resize/reflow code fix it up and return
it. Solves various problems with cursor position and resizing when in
copy mode. With Anindya Mukherjee.
2020-04-15 17:50:02 +00:00
Thomas Adam
ebeb457385 Merge branch 'obsd-master' 2020-04-15 18:01:27 +01:00
nicm
1e72f5ea43 Use mode-style for selected items, like choose modes. GitHub issue 2166. 2020-04-15 16:11:23 +00:00
Thomas Adam
fe1778e377 Merge branch 'obsd-master' 2020-04-15 16:01:27 +01:00
nicm
c7883d5c87 Use grid_empty_line rather than memset when adding new lines on resize.
Also remove some old test code.
2020-04-15 12:59:20 +00:00
Nicholas Marriott
c2c9b77f14 Do not use the command if the kernel didn't return the full size. 2020-04-15 13:04:53 +01:00
Thomas Adam
533c5ee7ad Merge branch 'obsd-master' 2020-04-14 22:01:27 +01:00
nicm
b9a00cbe8a Leave the cursor above empty lines. 2020-04-14 19:07:10 +00:00
nicm
e11295f42d Adjust cursor and scroll positions when entering copy mode so that the
cursor line is still visible even if the source and target panes are
different heights.
2020-04-14 18:33:01 +00:00
Thomas Adam
c68291f627 Merge branch 'obsd-master' 2020-04-14 16:01:27 +01:00
nicm
1ef9a69f4f Send keys when they are complete not before (!= vs ==). 2020-04-14 13:22:05 +00:00
Thomas Adam
6d9b3704f5 Merge branch 'obsd-master' 2020-04-14 08:01:33 +01:00
nicm
63ec791854 Provide an accessor for the running queue item and use it to not let
hooks recurse.
2020-04-14 06:00:52 +00:00
Thomas Adam
653a159225 Merge branch 'obsd-master' 2020-04-14 00:01:41 +01:00
Thomas Adam
2159ff3256 Merge branch 'obsd-master' 2020-04-13 22:01:30 +01:00
nicm
fc83517913 Missed a few warnings in previous. 2020-04-13 20:54:15 +00:00
nicm
3f7f9a0e20 Make client -c and -t handling common in cmd-queue.c and try to be
clearer about whether the client is the target client (must have a
session) or not.
2020-04-13 20:51:57 +00:00
nicm
187277eaad Add helpers for the simple case of parse string and add to command queue. 2020-04-13 18:59:41 +00:00
Thomas Adam
acc00cd13a Merge branch 'obsd-master' 2020-04-13 18:01:43 +01:00
nicm
34804f2709 When parsing strings, put all commands in one group even if there are
newlines. This means that for example bind q { a \n b } and bind q "a ;
b" are the same. Also log commands in different groups separated by ;;
rather than ; (a command list like this should never be user visible).
2020-04-13 16:19:37 +00:00
nicm
3f86d6d460 When adding a list of commands to the queue, instead of automatically
creating a new state for each group of commands, require the caller to
create one and use it for all the commands in the list. This means the
current target works even with list with multiple groups (which can
happen if they are defined with newlines).
2020-04-13 15:55:51 +00:00
Thomas Adam
0a11f1607b Merge branch 'obsd-master' 2020-04-13 16:01:46 +01:00
nicm
adb76fd1ce Move cmdq_state into cmd-queue.c. 2020-04-13 14:46:04 +00:00
nicm
9a65102bfc Rename cmdq_shared to cmdq_state which will better reflect what it is
(going to be) used for.
2020-04-13 14:04:25 +00:00
nicm
77d5b0cc53 Store a key event not a mouse event in the shared data. 2020-04-13 13:42:35 +00:00
nicm
53d6b94e8a Move the NOHOOKS flag into the shared flags. 2020-04-13 13:32:09 +00:00
Thomas Adam
8f2b5d714a Merge branch 'obsd-master' 2020-04-13 14:01:45 +01:00
nicm
04cdd03525 Also move cmdq_item and cmdq_list into cmd-queue.c (this is to make its
use more clearly defined and preparation for some future work).
2020-04-13 10:59:58 +00:00
Thomas Adam
b117c3b812 Merge branch 'obsd-master' 2020-04-13 10:30:00 +01:00
nicm
c20eb0c0ae Make struct cmd local to cmd.c and move it out of tmux.h. 2020-04-13 08:26:27 +00:00
nicm
9cbe9675ea Change so that the appropriate hooks for windows and panes belong to
pane/window options rather than all being session options. This is
useful for example to create a pane that is automatically closed on some
condition. From Anindya Mukherjee.
2020-04-13 07:25:33 +00:00
nicm
ad38ef6ff4 Print empty arguments properly. 2020-04-12 20:54:28 +00:00
nicm
de6b30a51c Mention RGB, pointed out by Jody Frankowski. 2020-04-12 20:16:36 +00:00
nicm
da4034944d Add a -f filter argument to the list commands like choose-tree. 2020-04-12 08:36:18 +00:00
nicm
756591b4ca Add a -f filter argument to the list commands like choose-tree. 2020-04-12 08:36:18 +00:00
nicm
70534cfde6 Clarify a couple of style options. 2020-04-12 08:13:41 +00:00
nicm
1c433f1354 Remove unused define, also a man fix from jmc. 2020-04-10 20:53:54 +00:00
nicm
c0602f357d Now that copy mode copies the pane content rather than keeping a
reference to it, it isn't necessary that the pane in copy mode is the
same as the one copying from. Add a -s flag to copy-mode to specify a
different pane for the source content. This means it is possible to view
two places in a pane's history at the same time in different panes, or
copy from a pane's history into an editor or shell in the same pane.

From Anindya Mukherjee.
2020-04-10 07:44:26 +00:00
nicm
a1fc8f8b23 More style nits. 2020-04-09 15:35:27 +00:00
Thomas Adam
52e3d960e7 Merge branch 'obsd-master' 2020-04-09 16:01:45 +01:00
nicm
26f5dfbe46 Fix history-bottom to use the right line when working out the length. 2020-04-09 14:30:28 +00:00
nicm
e9e5facb0e Some minor style nits. 2020-04-09 14:23:34 +00:00
nicm
b0b07fb585 Tweak how the default size is worked out so it is more obvious. 2020-04-09 13:57:18 +00:00
nicm
886fdb1f7e A couple of other redundant checks/assignments. 2020-04-09 13:56:46 +00:00
nicm
5288801d3e Do not try to use the client if the item containing it is NULL. 2020-04-09 13:54:38 +00:00
nicm
315961faec Some more, and use of wp->window before wp NULL check in format.c. 2020-04-09 13:53:50 +00:00
nicm
b96ac80901 Some unnecessary assignments and unused variables. 2020-04-09 13:52:31 +00:00
nicm
c4d0089edb Pass correct flags to fnmatch. 2020-04-09 13:49:21 +00:00
Thomas Adam
916c3787d7 Merge branch 'obsd-master' 2020-04-09 14:01:32 +01:00
Thomas Adam
9e0e860031 Merge branch 'obsd-master' 2020-04-09 13:41:59 +01:00
nicm
0e8710f507 Wait until the initial command sequence is done before sending a device
attributes request and other bits that prompt a reply from the terminal.
This means that stray relies are not left on the terminal if the command
has attached and then immediately detached and tmux will not be around
to receive them. Prompted by a problem report from espie@.
2020-04-09 12:16:16 +00:00
nicm
ff135b34a4 Mention paste at same place as copy, suggested by John Boyle. 2020-04-09 06:28:55 +00:00
nicm
5d0eb619f1 Restore pane_current_path format from portable tmux, it is no longer
used by default and is very useful.
2020-04-08 11:26:07 +00:00
nicm
d388dbdea9 Pass the cmd item to format expansion so that mouse formats work. 2020-04-08 10:58:09 +00:00
Thomas Adam
6a2f32b4fd Merge branch 'obsd-master' 2020-04-07 16:01:29 +01:00
nicm
1c8f7c1f7a Do not restore history flag if it was never set. 2020-04-07 13:55:24 +00:00
nicm
eff881b15a Do not send mouse events if the program has not requested them. 2020-04-07 13:38:30 +00:00
nicm
a2efdb21a8 Limit size to 1x1 (total size 3x3). 2020-04-07 13:33:00 +00:00
Thomas Adam
8fa0b0cd26 Merge branch 'obsd-master' 2020-04-06 20:01:33 +01:00
nicm
77b827f879 Change copy mode to make copy of the pane history so it does not need to
freeze updates (which does not play nicely with some applications, a
longstanding problem) and will allow some other changes later. From
Anindya Mukherjee.
2020-04-06 17:51:34 +00:00
Nicholas Marriott
0953b994ff Merge branch '3.1-rc' 2020-04-06 16:17:34 +01:00
Thomas Adam
71ab50eddd Merge branch 'obsd-master' 2020-04-06 04:01:42 +01:00
nicm
fccce69cf0 Add an argument to list-commands to show only a single command. 2020-04-05 08:40:31 +00:00
nicm
832b8a8cf5 Use new window and new pane as well for -P to new-session or new-window. 2020-04-03 13:54:31 +00:00
nicm
c9b9b0c7c3 Stop logging the entire command queue every time we add something,
spotted by tb & sthen.
2020-04-03 12:59:22 +00:00
nicm
b65eab5505 Check previous line rather than an extra line, from Anindya Mukherjee. 2020-04-03 05:18:02 +00:00
Thomas Adam
450315aa74 Merge branch 'obsd-master' 2020-04-02 20:01:26 +01:00
nicm
a20d96000e Only search the visible part of the history when marking (highlighting)
search terms, much faster than searching the whole history.
2020-04-02 17:03:10 +00:00
Thomas Adam
9bcf5c0b90 Merge branch 'obsd-master' 2020-04-02 08:01:29 +01:00
nicm
90f4e149c1 Add a W position to display-menu -y to use the line above (or below) the
status line containing the window list. Leave S meaning above (or below)
all status lines. GitHub issue 2145.
2020-04-02 05:35:15 +00:00
Thomas Adam
7e6db00dd2 Merge branch 'obsd-master' 2020-04-01 14:01:25 +01:00
nicm
05a15215c5 Do not ignore triple-click and send to pane. 2020-04-01 11:47:44 +00:00
Thomas Adam
66db12db31 Merge branch 'obsd-master' 2020-04-01 12:01:27 +01:00
nicm
567b27e10a Add a 10 second timeout to prevent searches taking too much time, from
Anindya Mukherjee.
2020-04-01 09:36:37 +00:00
Nicholas Marriott
faf2ed48fb Merge branch '3.1-rc' 2020-04-01 10:10:48 +01:00
nicm
dd2fdcda79 Support mouse in popups. 2020-04-01 09:05:27 +00:00
Thomas Adam
e54d4e7fe0 Merge branch 'obsd-master' 2020-04-01 10:01:30 +01:00
Nicholas Marriott
0ced25ce50 Fix configure.ac. 2020-04-01 09:30:29 +01:00
Nicholas Marriott
1d4cdbc227 Merge branch '3.1-rc' 2020-04-01 09:30:12 +01:00
Nicholas Marriott
b8356c650a Update CHANGES. 2020-04-01 09:29:02 +01:00
nicm
cd30633d10 Do not go down the regex search path (which is expensive because we need
to convert the grid data into a string for regexec and reverse it to
find the grid position) if the search string does not contain any regex
special characters.
2020-04-01 08:07:05 +00:00
nicm
b66d62d2d0 Do not go down the regex search path (which is expensive because we need
to convert the grid data into a string for regexec and reverse it to
find the grid position) if the search string does not contain any regex
special characters.
2020-04-01 08:07:05 +00:00
nicm
c129ed3233 Use a comparison to check for wrap and avoid an expensive modulus. 2020-04-01 07:52:07 +00:00
nicm
46092f2760 Use a comparison to check for wrap and avoid an expensive modulus. 2020-04-01 07:52:07 +00:00
nicm
89d2a20e56 Performance improvements for regex searching, most notably:
- Use the grid data directly instead of copying it.

- Special case the most typical one byte character cells and use memcmp
  for multiple bytes instead of a handrolled loop.

- Hoist regcomp out of the loop into the calling functions.

GitHub issue 2143.

Also a man page from from jmc@.
2020-04-01 07:35:10 +00:00
nicm
46ed81fc45 Performance improvements for regex searching, most notably:
- Use the grid data directly instead of copying it.

- Special case the most typical one byte character cells and use memcmp
  for multiple bytes instead of a handrolled loop.

- Hoist regcomp out of the loop into the calling functions.

GitHub issue 2143.

Also a man page from from jmc@.
2020-04-01 07:35:10 +00:00
Thomas Adam
bb6630af31 Merge branch 'obsd-master' 2020-04-01 00:01:25 +01:00
Thomas Adam
dfd29977e0 Merge branch 'obsd-master' 2020-03-31 20:01:34 +01:00
nicm
38f1546a66 Add a way to mark environment variables as "hidden" so they can be used
by tmux but are not passed into the environment of new panes.
2020-03-31 17:14:40 +00:00
nicm
cc8b41f294 Add a way to mark environment variables as "hidden" so they can be used
by tmux but are not passed into the environment of new panes.
2020-03-31 17:14:40 +00:00
nicm
e221ef203c Add a -T flag to resize-pane to trim lines below the cursor, moving
lines out of the history. GitHub issue 2134.
2020-03-31 17:13:20 +00:00
nicm
e6cddcf752 Add a -T flag to resize-pane to trim lines below the cursor, moving
lines out of the history. GitHub issue 2134.
2020-03-31 17:13:20 +00:00
nicm
e6d1b6770c Add non-regex search variants to avoid the performance cost for people
with large histories or long lines.
2020-03-31 16:53:23 +00:00
nicm
2624edde46 Add non-regex search variants to avoid the performance cost for people
with large histories or long lines.
2020-03-31 16:53:23 +00:00
Thomas Adam
0bb1a50b88 Merge branch 'obsd-master' 2020-03-31 16:01:29 +01:00
nicm
2ca95840d1 Add session_path from Chris Ruegge in GitHub issue 2142. 2020-03-31 11:58:05 +00:00
nicm
2a4714e76b Add session_path from Chris Ruegge in GitHub issue 2142. 2020-03-31 11:58:05 +00:00
nicm
0dd4977d5c Add a "second click" key type which is fired for the second click of a
double click, even if the timer hasn't expired to confirm it isn't
actually a triple click. Provides a way for people who don't care about
triple clicks or can make their commands have no side effects to avoid
the double click timer delay.
2020-03-31 11:38:35 +00:00
nicm
01b3bb8e2c Add a "second click" key type which is fired for the second click of a
double click, even if the timer hasn't expired to confirm it isn't
actually a triple click. Provides a way for people who don't care about
triple clicks or can make their commands have no side effects to avoid
the double click timer delay.
2020-03-31 11:38:35 +00:00
Thomas Adam
c9cd8f9b5d Merge branch 'obsd-master' 2020-03-31 10:01:29 +01:00
nicm
3bbd66c013 Move alternate screen into the screen rather than the pane. 2020-03-31 07:00:34 +00:00
nicm
eedf059d00 Detach reply escape sequences from the pane so they work in popups. 2020-03-31 06:35:38 +00:00
Thomas Adam
588865152a Merge branch 'obsd-master' 2020-03-30 18:01:28 +01:00
nicm
1fb504d0d5 Tweak key numbers to avoid some special keys crossing over with modifier bits. 2020-03-30 16:16:48 +00:00
nicm
34de379c7d Add to rather than replace flags with -c. 2020-03-30 15:49:23 +00:00
Nicholas Marriott
a46916b452 Tweak text. 2020-03-30 14:18:29 +01:00
Nicholas Marriott
df633c527d Add to CHANGES. 2020-03-30 14:17:58 +01:00
Thomas Adam
aa264ae568 Merge branch 'obsd-master' 2020-03-30 12:01:25 +01:00
Thomas Adam
ecde339f59 Merge branch 'obsd-master' 2020-03-30 10:01:27 +01:00
nicm
c713b65b9e Do not check flags after the popup struct has been freed. 2020-03-30 07:42:44 +00:00
nicm
586cafff0f Do not check flags after the popup struct has been freed. 2020-03-30 07:42:44 +00:00
Thomas Adam
5aa9e425b4 Merge branch 'obsd-master' 2020-03-28 16:01:24 +00:00
Thomas Adam
374f5ea60c Merge branch 'obsd-master' 2020-03-28 14:01:28 +00:00
Thomas Adam
88ca500546 Merge branch 'obsd-master' 2020-03-28 10:01:27 +00:00
nicm
6d0376a679 Change default position for menu and popup to centre rather than top left. 2020-03-28 09:55:30 +00:00
nicm
8036d0f834 Change default position for menu and popup to centre rather than top left. 2020-03-28 09:55:30 +00:00
nicm
852a2f2e1f Make two -E only close popup automatically if the command exited with 0. 2020-03-28 09:51:12 +00:00
nicm
593fddf84b Make two -E only close popup automatically if the command exited with 0. 2020-03-28 09:51:12 +00:00
nicm
4346098e97 Fix how popup height is calculated to take embedded newlines into account. 2020-03-28 09:39:44 +00:00
nicm
e0b17e796b Add formats for top paste buffer by default. Also a tmux.1 fix from jmc. 2020-03-28 09:39:27 +00:00
Thomas Adam
f986539e3c Merge branch 'master' of github.com:tmux/tmux 2020-03-26 11:12:18 +00:00
Thomas Adam
8a57d14f4b Merge branch 'obsd-master' 2020-03-26 11:11:37 +00:00
Nicholas Marriott
75a93207d4 Update capture-pane test, from Johannes Altmanninger. 2020-03-26 10:16:05 +00:00
nicm
55b14cdc6a Add support for overlay popup boxes to show text or output temporarily
above the normal layout. These work similarly to menus and are created
with the display-popup command.
2020-03-24 08:09:43 +00:00
nicm
8a838b0372 Add support for overlay popup boxes to show text or output temporarily
above the normal layout. These work similarly to menus and are created
with the display-popup command.
2020-03-24 08:09:43 +00:00
Thomas Adam
f652d777a6 Merge branch 'obsd-master' 2020-03-21 16:01:25 +00:00
Thomas Adam
5123bb7db4 Merge branch 'obsd-master' 2020-03-21 14:01:27 +00:00
nicm
edca27ae45 AIX colours are always stored as 90-97, not 100-107. From Johannes
Altmanninger.
2020-03-21 13:51:30 +00:00
nicm
af6ae35900 Set end position correctly, GitHub issue 2129 from Anindya Mukherjee. 2020-03-21 13:19:56 +00:00
nicm
8828b958f0 Break code to convert an argument as a percentage into a common function. 2020-03-21 13:16:15 +00:00
nicm
5aeab5ab40 Preserve exit status from run-shell and pass to the client. 2020-03-21 13:15:38 +00:00
Thomas Adam
c6d4baa4e5 Merge branch 'obsd-master' 2020-03-20 22:01:26 +00:00
nicm
9a55f65702 Fix select-word when not on a word, from Anindya Mukherjee. 2020-03-20 20:12:39 +00:00
Thomas Adam
e4efd59fe0 Merge branch 'obsd-master' 2020-03-20 20:01:34 +00:00
nicm
1a4e64ba69 Apply same menu items to view mode like copy mode. 2020-03-20 18:35:53 +00:00
nicm
7c25f22074 Similarly, disable zoom if only one pane. 2020-03-20 18:22:37 +00:00
nicm
b66501df0c Put swap down back in the right place. 2020-03-20 18:20:58 +00:00
nicm
4d6805284b Disable swap entries if nothing to swap with. 2020-03-20 18:19:22 +00:00
nicm
68cf61aa46 Still want the per-mode menus outside copy mode. 2020-03-20 18:11:56 +00:00
nicm
005cd48620 Oops, typo in key binding. 2020-03-20 18:05:22 +00:00
Thomas Adam
9894e50c42 Merge branch 'obsd-master' 2020-03-20 18:01:25 +00:00
nicm
06c3079d66 Make the mouse_word and mouse_line formats work in copy mode and enable
the default pane menu in copy mode.
2020-03-20 17:59:39 +00:00
nicm
7bbca49395 Fix positioning of menu in choose modes and a couple of keys in tree mode. 2020-03-20 17:26:14 +00:00
Thomas Adam
5b71943f89 Merge branch 'obsd-master' 2020-03-20 14:01:26 +00:00
nicm
a3ff5a9e25 select_word_end needs to forward no_reset flag or select-word selects
too much.
2020-03-20 13:12:04 +00:00
Thomas Adam
159e648ccb Merge branch 'obsd-master' 2020-03-20 08:01:26 +00:00
nicm
c3e96cce4e Another fix to make other-end forget the selection mode, from Anindya Mukherjee. 2020-03-20 06:09:19 +00:00
Thomas Adam
35c4897d8f Merge branch 'obsd-master' 2020-03-19 16:01:29 +00:00
nicm
74ed17d41b Little bit of tidying. 2020-03-19 14:23:58 +00:00
Nicholas Marriott
c15396459b No util.h. 2020-03-19 14:06:37 +00:00
nicm
de34436d4c Change input path so it doesn't require a pane. 2020-03-19 14:03:48 +00:00
Thomas Adam
17e4f2394a Merge branch 'obsd-master' 2020-03-19 14:01:31 +00:00
nicm
ce61bf931b Do not set the history flag if there is no history. 2020-03-19 13:46:10 +00:00
nicm
e8273a993e Add a flag to run a background process in a pty as well, not used for
anything yet.
2020-03-19 13:43:18 +00:00
nicm
581ed718e7 Add C position for terminal centre with display-menu -x and -y. 2020-03-19 13:32:49 +00:00
nicm
2cd8ea7680 Various fixes to copying with select-word and select-line, including
making it consistent with keys and with the mouse, and using other-end.
From Anindya Mukherjee.
2020-03-19 13:28:52 +00:00
Thomas Adam
7595b22e72 Merge branch 'obsd-master' 2020-03-18 10:01:26 +00:00
nicm
7b0e688a96 Break position calculation into a helper function. 2020-03-18 09:13:49 +00:00
Thomas Adam
18cfd9befa Merge branch 'obsd-master' 2020-03-17 18:01:27 +00:00
Nicholas Marriott
76f373ab35 Merge branch '3.1-rc' 2020-03-17 16:17:09 +00:00
Nicholas Marriott
80f20b8e4e getopt varies too much between platforms, and we already use compat/getopt.c
for Linux so just use it everywhere.
2020-03-17 16:07:06 +00:00
nicm
bd0342b0a7 getopt is not required to set optarg to NULL when there is no argument
and some do not, so set it explicitly each time.
2020-03-17 16:02:38 +00:00
Thomas Adam
5717633cf5 Merge branch 'obsd-master' 2020-03-17 14:01:25 +00:00
nicm
1ddc128860 Do not return early if no bits changed because may still need to change the style. 2020-03-17 12:20:12 +00:00
Thomas Adam
0610f66fa9 Merge branch 'obsd-master' 2020-03-17 12:01:28 +00:00
nicm
115bb33257 Ignore default-shell (and use /bin/sh) if it invalid not just if it is
tmux itself, also refuse to set the option to something invalid in the
first place. GitHub issue 2120.
2020-03-17 11:10:12 +00:00
Thomas Adam
71eb965dd9 Merge branch 'obsd-master' 2020-03-16 20:01:24 +00:00
nicm
fb396286ff Do not attempt to close a NULL pane when failing to create a new one. 2020-03-16 18:08:39 +00:00
Thomas Adam
c18a46cf56 Merge branch 'obsd-master' 2020-03-16 16:01:26 +00:00
Nicholas Marriott
62c646ac32 Add couple of CHANGES tweaks. 2020-03-16 15:13:35 +00:00
Nicholas Marriott
372841f70a Add to CHANGES. 2020-03-16 15:12:20 +00:00
Nicholas Marriott
69eff51538 Add. 2020-03-16 15:11:34 +00:00
nicm
7021757c9d Adjust selection correctly when scrolling, from Anindya Mukherjee. 2020-03-16 14:17:56 +00:00
Thomas Adam
cae2dfc95a Merge branch 'obsd-master' 2020-03-16 12:01:26 +00:00
nicm
37b7a29cca VTE treats each mouse mode bit as independent, so turning off 1000
doesn't also turn off 1001, so don't rely on that behaviour. GitHub
issue 2116.
2020-03-16 10:49:06 +00:00
Thomas Adam
45be93f604 Merge branch 'obsd-master' 2020-03-16 10:01:27 +00:00
nicm
7cae4e8e89 Turn off mouse mode 1003 as well as the rest when exiting. 2020-03-16 09:18:47 +00:00
nicm
7815b30c7d Terminate the output buffer for control mode output - it is now used as
a string. GitHub issue 2114.
2020-03-16 09:12:44 +00:00
nicm
9abeff7f0b FIx type for %u, from Thomas Adam. 2020-03-16 08:23:24 +00:00
Thomas Adam
f584fe1b00 Merge branch 'obsd-master' 2020-03-16 08:01:27 +00:00
nicm
d162ff48f3 Send mouse down event immediately rather than waiting for double click
to finish which would now mean it was out of order. Reported by Mark
Kelly.
2020-03-16 06:12:42 +00:00
Thomas Adam
55aeaffb1a Merge branch 'obsd-master' 2020-03-15 22:01:27 +00:00
nicm
882d0b785d Reset selection flag when clearing or stopping selection, from Mark
Kelly.
2020-03-15 20:44:19 +00:00
nicm
fa3871b1be Fix C-Space key string. 2020-03-15 20:35:52 +00:00
Thomas Adam
c859748210 Merge branch 'obsd-master' 2020-03-13 08:01:24 +00:00
nicm
fa36e9bc88 Do not add a reference to the session if no session is present. 2020-03-13 06:19:33 +00:00
Thomas Adam
c91a0948e3 Merge branch 'obsd-master' 2020-03-12 16:01:28 +00:00
Thomas Adam
6385bd1e08 Merge branch 'obsd-master' 2020-03-12 14:01:29 +00:00
nicm
6571dd50f8 Tidy up the default mouse key bindings and:
- Add double and triple click bindings to copy a word or line outside
  copy mode. The text is selected for a short period to show what has
  been copied. This is in line with the existing mouse selection where
  the text is copied and the selection is cleared when the mouse button
  is released.

- Change the existing double and triple click bindings in copy mode to
  behave in the same way.

- Add a button 2 binding to paste the top buffer.
2020-03-12 13:48:32 +00:00
nicm
516f6099fc Add a -d flag to run-shell to wait for delay before running the command,
also allow run-shell to accept no command to just delay.
2020-03-12 13:25:45 +00:00
nicm
7863445e5d Add a copy-mode -H flag to hide the position marker in the top right. 2020-03-12 13:19:20 +00:00
nicm
f7bc753442 Change how double and triple clicks works so that one or the other is
fired - a double click is no longer triggered on the way to a triple
click.
2020-03-12 13:16:16 +00:00
Thomas Adam
5625c62044 Merge branch 'obsd-master' 2020-03-12 12:01:25 +00:00
Thomas Adam
1a2e66f345 Merge branch 'obsd-master' 2020-03-12 10:01:25 +00:00
nicm
b8b48e2e37 Add C-g to cancel command prompt with vi(1) keys as well as emacs, and q
in command mode.
2020-03-12 09:49:43 +00:00
nicm
2a5702a936 When the server socket is given by the user with -S, create it with
umask 177 instead of 117 because it may not be in a safe directory like
the default directory in /tmp. The user can chmod it more open after it
is created if they want.
2020-03-12 09:26:34 +00:00
Thomas Adam
39dc809751 Merge branch 'obsd-master' 2020-03-11 20:01:26 +00:00
nicm
4eba98313c Start a new selection if outside the existing selection after a word has
been selected. From Anindya Mukherjee.
2020-03-11 18:46:42 +00:00
Nicholas Marriott
e4898de98d Only need one lm. 2020-03-11 18:41:14 +00:00
Thomas Adam
256f7e8f38 Merge branch 'master' of github.com:tmux/tmux 2020-03-11 17:24:42 +00:00
Thomas Adam
e512a3642a Merge branch 'obsd-master'
Also add a check for -lm via AC_SEARCH_LIBS in configure.ac for
portablility fixes.
2020-03-11 17:23:38 +00:00
Nicholas Marriott
6d9beccb41 Will need fmod. 2020-03-11 16:33:55 +00:00
Nicholas Marriott
8d1d7fd775 Lock much more quickly. 2020-03-11 14:41:25 +00:00
nicm
c820585dd0 Add some number operators for formats, from Tyler Culp. 2020-03-11 14:17:55 +00:00
Nicholas Marriott
07bf5cbd27 3.2 next. 2020-03-11 06:41:13 +00:00
223 changed files with 46934 additions and 12443 deletions

View File

@ -29,7 +29,7 @@ uname -sp && tmux -V && echo $TERM
Also include:
- Your platform (Linux, OS X, or whatever).
- Your platform (Linux, macOS, or whatever).
- A brief description of the problem with steps to reproduce.
@ -37,7 +37,8 @@ Also include:
- Your terminal, and `$TERM` inside and outside of tmux.
- Logs from tmux (see below).
- Logs from tmux (see below). Please attach logs to the issue directly rather
than using a download site or pastebin. Put in a zip file if necessary.
- At most one or two screenshots, if helpful.
@ -76,3 +77,8 @@ The log files are:
- `tmux-out*.log`: output log file.
Please attach the log files to your issue.
## What does it mean if an issue is closed?
All it means is that work on the issue is not planned for the near future. See
the issue's comments to find out if contributions would be welcome.

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1 @@
blank_issues_enabled: false

View File

@ -1,3 +1,12 @@
---
name: Use this issue template
about: Please read https://github.com/tmux/tmux/blob/master/.github/CONTRIBUTING.md
title: ''
labels: ''
assignees: ''
---
### Issue description
Please read https://github.com/tmux/tmux/blob/master/.github/CONTRIBUTING.md

16
.github/README.md vendored
View File

@ -4,7 +4,7 @@ tmux is a terminal multiplexer: it enables a number of terminals to be created,
accessed, and controlled from a single screen. tmux may be detached from a
screen and continue running in the background, then later reattached.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris.
## Dependencies
@ -14,8 +14,17 @@ page](https://github.com/libevent/libevent/releases/latest).
It also depends on [ncurses](https://www.gnu.org/software/ncurses/), available
from [this page](https://invisible-mirror.net/archives/ncurses/).
To build tmux, a C compiler (for example gcc or clang), make, pkg-config and a
suitable yacc (yacc or bison) are needed.
## Installation
### Binary packages
Some platforms provide binary packages for tmux, although these are sometimes
out of date. Examples are listed on
[this page](https://github.com/tmux/tmux/wiki/Installing).
### From release tarball
To build and install tmux from a release tarball, use:
@ -28,6 +37,9 @@ sudo make install
tmux can use the utempter library to update utmp(5), if it is installed - run
configure with `--enable-utempter` to enable this.
For more detailed instructions on building and installing tmux, see
[this page](https://github.com/tmux/tmux/wiki/Installing).
### From version control
To get and build the latest from version control - note that this requires
@ -67,7 +79,7 @@ A small example configuration is in `example_tmux.conf`.
And a bash(1) completion file at:
https://github.com/imomaliev/tmux-bash-completion
https://github.com/scop/bash-completion/blob/main/completions/tmux
For debugging, run tmux with `-v` or `-vv` to generate server and client log
files in the current directory.

10
.github/lock.yml vendored
View File

@ -1,10 +0,0 @@
daysUntilLock: 180
skipCreatedBefore: false
exemptLabels: []
lockLabel: false
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
setLockReason: false
#only: issues

24
.github/travis/before-install.sh vendored Normal file
View File

@ -0,0 +1,24 @@
#!/bin/sh
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
sudo apt-get update -qq
sudo apt-get -y install bison \
autotools-dev \
libncurses5-dev \
libevent-dev \
pkg-config \
libutempter-dev \
build-essential
if [ "$BUILD" = "musl" -o "$BUILD" = "musl-static" ]; then
sudo apt-get -y install musl-dev \
musl-tools
fi
fi
if [ "$TRAVIS_OS_NAME" = "freebsd" ]; then
sudo pkg install -y \
automake \
libevent \
pkgconf
fi

38
.github/travis/build-all.sh vendored Normal file
View File

@ -0,0 +1,38 @@
#!/bin/sh
BUILD=$PWD/build
LIBEVENT=https://github.com/libevent/libevent/releases/download/release-2.1.11-stable/libevent-2.1.11-stab\
le.tar.gz
NCURSES=https://ftp.gnu.org/gnu/ncurses/ncurses-6.2.tar.gz
wget -4q $LIBEVENT || exit 1
tar -zxf libevent-*.tar.gz || exit 1
(cd libevent-*/ &&
./configure --prefix=$BUILD \
--enable-shared \
--disable-libevent-regress \
--disable-samples &&
make && make install) || exit 1
wget -4q $NCURSES || exit 1
tar -zxf ncurses-*.tar.gz || exit 1
(cd ncurses-*/ &&
CPPFLAGS=-P ./configure --prefix=$BUILD \
--with-shared \
--with-termlib \
--without-ada \
--without-cxx \
--without-manpages \
--without-progs \
--without-tests \
--without-tack \
--disable-database \
--enable-termcap \
--enable-pc-files \
--with-pkg-config-libdir=$BUILD/lib/pkgconfig &&
make && make install) || exit 1
sh autogen.sh || exit 1
PKG_CONFIG_PATH=$BUILD/lib/pkgconfig ./configure --prefix=$BUILD "$@"
make && make install || (cat config.log; exit 1)

25
.github/travis/build.sh vendored Normal file
View File

@ -0,0 +1,25 @@
#!/bin/sh
sh autogen.sh || exit 1
case "$BUILD" in
static)
./configure --enable-static || exit 1
exec make
;;
all)
sh $(dirname $0)/build-all.sh
exec make
;;
musl)
CC=musl-gcc sh $(dirname $0)/build-all.sh
exec make
;;
musl-static)
CC=musl-gcc sh $(dirname $0)/build-all.sh --enable-static
exec make
;;
*)
./configure || exit 1
exec make
;;
esac

34
.github/workflows/lock.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: 'Lock Threads'
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
permissions:
issues: write
pull-requests: write
discussions: write
concurrency:
group: lock-threads
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v5
with:
github-token: ${{ github.token }}
issue-inactive-days: '30'
issue-comment: >
This issue has been automatically locked since there
has not been any recent activity after it was closed.
pr-inactive-days: '60'
pr-comment: >
This pull request has been automatically locked since there
has not been any recent activity after it was closed.
discussion-inactive-days: '60'
discussion-comment: >
This discussion has been automatically locked since there
has not been any recent activity after it was closed.

35
.gitignore vendored
View File

@ -1,21 +1,24 @@
*.o
*~
*.diff
*.patch
*.core
core
tags
*.dSYM
*.diff
*.o
*.patch
*.swp
*~
.deps/
compat/.dirstamp
aclocal.m4
autom4te.cache/
config.log
config.status
etc/
tmux
.dirstamp
Makefile
Makefile.in
configure
tmux.1.*
*.dSYM
aclocal.m4
autom4te.cache/
cmd-parse.c
compat/.dirstamp
config.log
config.status
configure
core
etc/
fuzz/*-fuzzer
tags
tmux
tmux.1.*

View File

@ -2,15 +2,87 @@ language: c
os:
- linux
- freebsd
- osx
compiler:
- gcc
- clang
arch:
- amd64
- arm64
env:
- BUILD=
- BUILD=static
- BUILD=all
- BUILD=musl
- BUILD=musl-static
jobs:
exclude:
# Static builds are broken on OS X (by Apple)
- os: osx
compiler: gcc
env: BUILD=static
- os: osx
compiler: clang
env: BUILD=static
# No musl on FreeBSD
- os: freebsd
compiler: gcc
env: BUILD=musl
- os: freebsd
compiler: clang
env: BUILD=musl
- os: freebsd
compiler: gcc
env: BUILD=musl-static
- os: freebsd
compiler: clang
env: BUILD=musl-static
# No musl on OS X
- os: osx
compiler: gcc
env: BUILD=musl
- os: osx
compiler: clang
env: BUILD=musl
- os: osx
compiler: gcc
env: BUILD=musl-static
- os: osx
compiler: clang
env: BUILD=musl-static
# arm64 doesn't link ncurses
- os: linux
compiler: gcc
arch: arm64
env: BUILD=all
- os: linux
compiler: clang
arch: arm64
env: BUILD=all
- os: linux
compiler: gcc
arch: arm64
env: BUILD=musl
- os: linux
compiler: clang
arch: arm64
env: BUILD=musl
- os: linux
compiler: gcc
arch: arm64
env: BUILD=musl-static
- os: linux
compiler: clang
arch: arm64
env: BUILD=musl-static
before_install:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -y install bison autotools-dev libncurses5-dev libevent-dev pkg-config libutempter-dev build-essential; fi
- sh .github/travis/before-install.sh
script:
- ./autogen.sh && ./configure && make
- sh .github/travis/build.sh

772
CHANGES
View File

@ -1,3 +1,771 @@
CHANGES FROM 3.4 TO 3.5
* Revamp extended keys support to more closely match xterm and support mode 2
as well as mode 1. This is a substantial change to key handling which changes
tmux to always request mode 2 from parent terminal, changes to an unambiguous
internal representation of keys, and adds an option (extended-keys-format) to
control the format similar to the xterm(1) formatOtherKeys resource.
* Clear an overlay (popup or menu) when command prompt is entered.
* Add copy-mode -d flag to scroll a page down if in copy mode already (matching
-e).
* Display hyperlinks in copy mode and add copy_cursor_hyperlink format to get
the hyperlink under the cursor.
* Add a prefix timeout option.
* Mouse move keys are not useful as key bindings because we do not turn them on
unless the application requests them. Ignore them so they do not cause the
prefix to be canceled
* Add search_count and search_count_partial formats in copy mode.
* Do not reset mouse pane if clicked on status line,
* Add mirrored versions of the main-horizontal and main-vertical layouts where
the main pane is bottom or right instead of top or left.
* Allow REP to work with Unicode characters.
* Fix size calculation of terminators for clipboard escape sequences.
* Treat CRLF as LF in config files where it is easy to do so.
* The Linux console has some bugs with bright colours, so add some workarounds
for it.
* If built with systemd, remove some environment variables it uses.
* Adjust the logic when deleting last buffer to better preserve the selection:
if selecting the element below the deleted one fails (because as the last
one), select the one above it instead.
* Add --enable-jemalloc to build with jemalloc memory allocator (since glibc
malloc is so poor).
* Add a way (refresh-client -r) for control mode clients to provide OSC 10 and
11 responses to tmux so they can set the default foreground and background
colours.
* Add N to search backwards in tree modes.
* Use default-shell for command prompt, #() and popups.
* Revert part of a change intended to improve search performance by skipping
parts of lines already searched, but which in fact skipped the ends of lines
altogether.
* Add a command-error hook when a command fails.
* Add an option allow-set-title to forbid applications from changing the pane
title.
* Correct handling of mouse up events (don't ignore all but the last released
button), and always process down event for double click.
* Fix a crash if focusing a pane that is exiting.
* Pick newest session (as documented) when looking for next session for
detach-on-destroy.
* Reduce default escape-time to 10 milliseconds.
* Add display-menu -M to always turn mouse on in a menu.
* Look for feature code 21 for DECSLRM and 28 for DECFRA in the device
attributes and also accept level 1.
* Fix crash if built with SIXEL and the SIXEL colour register is invalid; also
remove SIXEL images before reflow.
* Do not notify window-layout-changed if the window is about to be destroyed.
* Do not consider a selection present if it is empty for the selection_active
and selection_present format variables.
* Fix split-window -p.
CHANGES FROM 3.3a TO 3.4
* Add options keep-last and keep-group to destroy-unattached to keep the last
session whether in a group.
* Don't allow paste-buffer into dead panes.
* Add -t to source-file.
* Rewrite combined character handling to be more consistent and to support
newer Unicode combined characters.
* Add basic support for SIXEL if built with --enable-sixel.
* Add a session, pane and user mouse range types for the status line and add
format variables for mouse_status_line and mouse_status_range so they can be
associated with different commands in the key bindings.
* Add flag (-o) to next-prompt/previous-prompt to go to OSC 133 command output.
* Add options and flags for menu styles (menu-style, menu-border-style) similar
to those existing for popups.
* Add support for marking lines with a shell prompt based on the OSC 133 extension.
* Check for libterminfo for NetBSD.
* Add "us" to styles for underscore colour.
* Add flags (-c and -y) to change the confirm key and default behaviour of
confirm-before.
* Use ncurses' new tparm_s function (added in 6.4-20230424) instead of tparm so
it does not object to string arguments in c apabilities it doesn't already
know. Also ignore errors from tparm if using previous ncurses versions.
* Set default lock command to vlock on Linux if present at build time.
* Discard mouse sequences that have the right form but actually are invalid.
* Add support for spawning panes in separate cgroups with systemd and a
configure flag (--disable-cgroups) to turn off.
* Add a format (pane_unseen_changes) to show if there are unseen changes while
in a mode.
* Remove old buffer when renaming rather than complaining.
* Add an L modifier like P, W, S to loop over clients.
* Add -f to list-clients like the other list commands.
* Extend display-message to work for control clients.
* Add a flag to display-menu to select the manu item selected when the menu is
open.
* Have tmux recognise pasted text wrapped in bracket paste sequences, rather
than only forwarding them to the program inside.
* Have client return 1 if process is interrupted to an input pane.
* Query the client terminal for foreground and background colours and if OSC 10
or 11 is received but no colour has been set inside tmux, return the colour
from the first attached client.
* Add send-keys -K to handle keys directly as if typed (so look up in key
table).
* Process escape sequences in show-buffer.
* Add a -l flag to display-message to disable format expansion.
* Add paste-buffer-deleted notification and fix name of paste-buffer-changed.
* Do not attempt to connect to the socket as a client if systemd is active.
* Add scroll-top and scroll-bottom commands to scroll so cursor is at top or
bottom.
* Add a -T flag to capture-pane to stop at the last used cell instead of the
full width. Restore the previous behaviour by making it default to off unless
-J is used.
* Add message-line option to control where message and prompt go.
* Notification when a paste buffer is deleted.
* Add a Nobr terminfo(5) capability to tell tmux the terminal does not use bright
colours for bold.
* Change g and G to go to top and bottom in menus.
* Add a third state "all" to allow-passthrough to work even in invisible panes.
* Add support for OSC 8 hyperlinks.
* Store the time lines are scrolled into history and display in copy mode.
* Add a %config-error reply to control mode for configuration file errors since
reporting them in view mode is useless.
* A new feature flag (ignorefkeys) to ignore terminfo(5) function key
definitions for rxvt.
* Pass through first argument to OSC 52 (which clipboards to set) if the
application provides it.
* Expand arguments to send-keys, capture-pane, split-window, join-pane where it
makes sense to do so.
* Ignore named buffers when choosing a buffer if one is not specified by the user.
CHANGES FROM 3.3 TO 3.3a
* Do not crash when run-shell produces output from a config file.
* Do not unintentionally turn off all mouse mode when button mode is also
present.
CHANGES FROM 3.2a TO 3.3
* Add an ACL list for users connecting to the tmux socket. Users may be
forbidden from attaching, forced to attach read-only, or allowed to attach
read-write. A new command, server-access, configures the list. File system
permissions must still be configured manually.
* Emit window-layout-changed on swap-pane.
* Better error reporting when applying custom layouts.
* Handle ANSI escape sequences in run-shell output.
* Add pane_start_path to match start_command.
* Set PWD so shells have a hint about the real path.
* Do not allow pipe-pane on dead panes.
* Do not report mouse positions (incorrectly) above the maximum of 223 in
normal mouse mode.
* Add an option (default off) to control the passthrough escape sequence.
* Support more mouse buttons when the terminal sends them.
* Add a window-resized hook which is fired when the window is actually resized
which may be later than the client resize.
* Add next_session_id format with the next session ID.
* Add formats for client and server UID and user.
* Add argument to refresh-client -l to forward clipboard to a pane.
* Add remain-on-exit-format to set text shown when pane is dead.
* With split-window -f use percentages of window size not pane size.
* Add an option (fill-character) to set the character used for unused areas of
a client.
* Add an option (scroll-on-clear) to control if tmux scrolls into history on
clear.
* Add a capability for OSC 7 and use it similarly to how the title is set (and
controlled by the same set-titles option).
* Add support for systemd socket activation (where systemd creates the Unix
domain socket for tmux rather than tmux creating it). Build with
--enable-systemd.
* Add an option (pane-border-indicators) to select how the active pane is shown
on the pane border (colour, arrows or both).
* Support underscore styles with capture-pane -e.
* Make pane-border-format a pane option rather than window.
* Respond to OSC 4 queries
* Fix g/G keys in modes to do the same thing as copy mode (and vi).
* Bump the time terminals have to respond to device attributes queries to three
seconds.
* If automatic-rename is off, allow the rename escape sequence to set an empty
name.
* Trim menu item text more intelligently.
* Add cursor-style and cursor-colour options to set the default cursor style
and colour.
* Accept some useful and non-conflicting emacs keys in vi normal mode at the
command prompt.
* Add a format modifier (c) to force a colour to RGB.
* Add -s and -S to display-popup to set styles, -b to set lines and -T to set
popup title. New popup-border-lines, popup-border-style and popup-style
options set the defaults.
* Add -e flag to set an environment variable for a popup.
* Make send-keys without arguments send the key it is bound to (if bound to a
key).
* Try to leave terminal cursor at the right position even when tmux is drawing
its own cursor or selection (such as at the command prompt and in choose
mode) for people using screen readers and similar which can make use of it.
* Change so that {} is converted to tmux commands immediately when parsed. This
means it must contain valid tmux commands. For commands which expand %% and
%%%, this now only happens within string arguments. Use of nested aliases
inside {} is now forbidden. Processing of commands given in quotes remains
the same.
* Disable evports on SunOS since they are broken.
* Do not expand the file given with tmux -f so it can contain :s.
* Bump FORMAT_LOOP_LIMIT and add a log message when hit.
* Add a terminal feature for the mouse (since FreeBSD termcap does not have kmous).
* Forbid empty session names.
* Improve error reporting when the tmux /tmp directory cannot be created or
used.
* Give #() commands a one second grace period where the output is empty before
telling the user they aren't doing anything ("not ready").
* When building, pick default-terminal from the first of tmux-256color, tmux,
screen-256color, screen that is available on the build system (--with-TERM
can override).
* Do not close popups on resize, instead adjust them to fit.
* Add a client-active hook.
* Make window-linked and window-unlinked window options.
* Do not configure on macOS without the user making a choice about utf8proc
(either --enable-utf8proc or --disable-utf8proc).
* Do not freeze output in panes when a popup is open, let them continue to
redraw.
* Add pipe variants of the line copy commands.
* Change copy-line and copy-end-of-line not to cancel and add -and-cancel
variants, like the other copy commands.
* Support the OSC palette-setting sequences in popups.
* Add a pane-colours array option to specify the defaults palette.
* Add support for Unicode zero-width joiner.
* Make newline a style delimiter as well so they can cross multiple lines for
readability in configuration files.
* Change focus to be driven by events rather than scanning panes so the
ordering of in and out is consistent.
* Add display-popup -B to open a popup without a border.
* Add a menu for popups that can be opened with button three outside the popup
or on the left or top border. Resizing now only works on the right and bottom
borders or when using Meta. The menu allows a popup to be closed, expanded to
the full size of the client, centered in the client or changed into a pane.
* Make command-prompt and confirm-before block by default (like run-shell). A
new -b flags runs them in the background as before. Also set return code for
confirm-before.
* Change cursor style handling so tmux understands which sequences contain
blinking and sets the flag appropriately, means that it works whether cnorm
disables blinking or not. This now matches xterm's behaviour.
* More accurate vi(1) word navigation in copy mode and on the status line. This
changes the meaning of the word-separators option: setting it to the empty
string is equivalent to the previous behavior.
* Add -F for command-prompt and use it to fix "Rename" on the window menu.
* Add different command histories for different types of prompts ("command",
"search" etc).
CHANGES FROM 3.2 TO 3.2a
* Add an "always" value for the "extended-keys" option; if set then tmux will
forward extended keys to applications even if they do not request them.
* Add a "mouse" terminal feature so tmux can enable the mouse on terminals
where it is known to be supported even if terminfo(5) says otherwise.
* Do not expand the filename given to -f so it can contain colons.
* Fixes for problems with extended keys and modifiers, scroll region,
source-file, cross compiling, format modifiers and other minor issues.
CHANGES FROM 3.1c TO 3.2
* Add a flag to disable keys to close a message.
* Permit shortcut keys in buffer, client, tree modes to be configured with a
format (-K flag to choose-buffer, choose-client, choose-tree).
* Add a current_file format for the config file being parsed.
* When display-message used in config file, show the message after the config
file finishes.
* Add client-detached notification in control mode.
* Improve performance of format evaluation.
* Make jump command support UTF-8 in copy mode.
* Support X11 colour names and other colour formats for OSC 10 and 11.
* Add "pipe" variants of "copy-pipe" commands which do not copy.
* Include "focused" in client flags.
* Send Unicode directional isolate characters around horizontal pane borders if
the terminal supports UTF-8 and an extension terminfo(5) capability "Bidi" is
present.
* Add a -S flag to new-window to make it select the existing window if one
with the given name already exists rather than failing with an error.
* Add a format modifier to check if a window or session name exists (N/w or
N/s).
* Add compat clock_gettime for older macOS.
* Add a no-detached choice to detach-on-destroy which detaches only if there
are no other detached sessions to switch to.
* Add rectangle-on and rectangle-off copy mode commands.
* Change so that window_flags escapes # automatically. A new format
window_raw_flags contains the old unescaped version.
* Add -N flag to never start server even if command would normally do so.
* With incremental search, start empty and only repeat the previous search if
the user tries to search again with an empty prompt.
* Add a value for remain-on-exit that only keeps the pane if the program
failed.
* Add a -C flag to run-shell to use a tmux command rather than a shell command.
* Do not list user options with show-hooks.
* Remove current match indicator in copy mode which can't work anymore since we
only search the visible region.
* Make synchronize-panes a pane option and add -U flag to set-option to unset
an option on all panes.
* Make replacement of ##s consistent when drawing formats, whether followed by
[ or not. Add a flag (e) to the q: format modifier to double up #s.
* Add -N flag to display-panes to ignore keys.
* Change how escaping is processed for formats so that ## and # can be used in
styles.
* Add a 'w' format modifier for string width.
* Add support for Haiku.
* Expand menu and popup -x and -y as formats.
* Add numeric comparisons for formats.
* Fire focus events even when the pane is in a mode.
* Add -O flag to display-menu to not automatically close when all mouse buttons
are released.
* Allow fnmatch(3) wildcards in update-environment.
* Disable nested job expansion so that the result of #() is not expanded again.
* Use the setal capability as well as (tmux's) Setulc.
* Add -q flag to unbind-key to hide errors.
* Allow -N without a command to change or add a note to an existing key.
* Add a -w flag to set- and load-buffer to send to clipboard using OSC 52.
* Add -F to set-environment and source-file.
* Allow colour to be spelt as color in various places.
* Add n: modifier to get length of a format.
* Respond to OSC colour requests if a colour is available.
* Add a -d option to display-message to set delay.
* Add a way for control mode clients to subscribe to a format and be notified
of changes rather than having to poll.
* Add some formats for search in copy mode (search_present, search_match).
* Do not wait on shutdown for commands started with run -b.
* Add -b flags to insert a window before (like the existing -a for after) to
break-pane, move-window, new-window.
* Make paste -p the default for ].
* Add support for pausing a pane when the output buffered for a control mode
client gets too far behind. The pause-after flag with a time is set on the
pane with refresh-client -f and a paused pane may be resumed with
refresh-client -A.
* Allow strings in configuration files to span multiple lines - newlines and
any leading whitespace are removed, as well as any following comments that
couldn't be part of a format. This allows long formats or other strings to be
annotated and indented.
* Instead of using a custom parse function to process {} in configuration
files, treat as a set of statements the same as outside {} and convert back
to a string as the last step. This means the rules are consistent inside and
outside {}, %if and friends work at the right time, and the final result
isn't littered with unnecessary newlines.
* Add support for extended keys - both xterm(1)'s CSI 27 ~ sequence and the
libtickit CSI u sequence are accepted; only the latter is output. tmux will
only attempt to use these if the extended-keys option is on and it can detect
that the terminal outside supports them (or is told it does with the
"extkeys" terminal feature).
* Add an option to set the pane border lines style from a choice of single
lines (ACS or UTF-8), double or heavy (UTF-8), simple (plain ASCII) or number
(the pane numbers). Lines that won't work on a non-UTF-8 terminal are
translated back into ACS when they are output.
* Make focus events update the latest client (like a key press).
* Store UTF-8 characters differently to reduce memory use.
* Fix break-pane -n when only one pane in the window.
* Instead of sending all data to control mode clients as fast as possible, add
a limit of how much data will be sent to the client and try to use it for
panes with some degree of fairness.
* Add an active-pane client flag (set with attach-session -f, new-session -f
or refresh-client -f). This allows a client to have an independent active
pane for interactive use (the window client pane is still used for many
things however).
* Add a mark to copy mode, this is set with the set-mark command (bound to X)
and appears with the entire line shown using copy-mode-mark-style and the
marked character in reverse. The jump-to-mark command (bound to M-x) swaps
the mark and the cursor positions.
* Add a -D flag to make the tmux server run in the foreground and not as a
daemon.
* Do not loop forever in copy mode when search finds an empty match.
* Fix the next-matching-bracket logic when using vi(1) keys.
* Add a customize mode where options may be browsed and changed, includes
adding a brief description of each option. Bound to C-b C by default.
* Change message log (C-b ~) so there is one for the server rather than one per
client and it remains after detach, and make it useful by logging every
command.
* Add M-+ and M-- to tree mode to expand and collapse all.
* Change the existing client flags for control mode to apply for any client,
use the same mechanism for the read-only flag and add an ignore-size flag.
refresh-client -F has become -f (-F stays for backwards compatibility) and
attach-session and switch-client now have -f flags also. A new format
client_flags lists the flags and is shown by list-clients by default.
This separates the read-only flag from "ignore size" behaviour (new
ignore-size) flag - both behaviours are useful in different circumstances.
attach -r and switchc -r remain and set or toggle both flags together.
* Store and restore cursor position when copy mode is resized.
* Export TERM_PROGRAM and TERM_PROGRAM_VERSION like various other terminals.
* Add formats for after hook command arguments: hook_arguments with all the
arguments together; hook_argument_0, hook_argument_1 and so on with
individual arguments; hook_flag_X if flag -X is present; hook_flag_X_0,
hook_flag_X_1 and so on if -X appears multiple times.
* Try to search the entire history first for up to 200 ms so a search count can
be shown. If it takes too long, search the visible text only.
* Use VIS_CSTYLE for paste buffers also (show \012 as \n).
* Change default formats for tree mode, client mode and buffer mode to be more
compact and remove some clutter.
* Add a key (e) in buffer mode to open the buffer in an editor. The buffer
contents is updated when the editor exits.
* Add -e flag for new-session to set environment variables, like the same flag
for new-window.
* Improve search match marking in copy mode. Two new options
copy-mode-match-style and copy-mode-current-match-style to set the style for
matches and for the current match respectively. Also a change so that if a
copy key is pressed with no selection, the current match (if any) is copied.
* Sanitize session names like window names instead of forbidding invalid ones.
* Check if the clear terminfo(5) capability starts with CSI and if so then
assume the terminal is VT100-like, rather than relying on the XT capability.
* Improve command prompt tab completion and add menus both for strings and -t
and -s (when used without a trailing space). command-prompt has additional
flags for only completing a window (-W) and a target (-T), allowing C-b ' to
only show windows and C-b . only targets.
* Change all the style options to string options so they can support formats.
Change pane-active-border-style to use this to change the border colour when
in a mode or with synchronize-panes on. This also implies a few minor changes
to existing behaviour:
- set-option -a with a style option automatically inserts a comma between the
old value and appended text.
- OSC 10 and 11 no longer set the window-style option, instead they store the
colour internally in the pane data and it is used as the default when the
option is evaluated.
- status-fg and -bg now override status-style instead of the option values
being changed.
* Add extension terminfo(5) capabilities for margins and focus reporting.
* Try $XDG_CONFIG_HOME/tmux/tmux.conf as well as ~/.config/tmux/tmux.conf for
configuration file (the search paths are in TMUX_CONF in Makefile.am).
* Remove the DSR 1337 iTerm2 extension and replace by the extended device
attributes sequence (CSI > q) supported by more terminals.
* Add a -s flag to copy-mode to specify a different pane for the source
content. This means it is possible to view two places in a pane's history at
the same time in different panes, or view the history while still using the
pane. Pressing r refreshes the content from the source pane.
* Add an argument to list-commands to show only a single command.
* Change copy mode to make copy of the pane history so it does not need to
freeze the pane.
* Restore pane_current_path format from portable tmux on OpenBSD.
* Wait until the initial command sequence is done before sending a device
attributes request and other bits that prompt a reply from the terminal. This
means that stray replies are not left on the terminal if the command has
attached and then immediately detached and tmux will not be around to receive
them.
* Add a -f filter argument to the list commands like choose-tree.
* Move specific hooks for panes to pane options and windows for window options
rather than all hooks being session options. These hooks are now window options:
window-layout-changed
window-linked
window-pane-changed
window-renamed
window-unlinked
And these are now pane options:
pane-died
pane-exited
pane-focus-in
pane-focus-out
pane-mode-changed
pane-set-clipboard
Any existing configurations using these hooks on a session rather than
globally (that is, set-hook or set-option without -g) may need to be changed.
* Show signal names when a process exits with remain-on-exit on platforms which
have a way to get them.
* Start menu with top item selected if no mouse and use mode-style for the
selected item.
* Add a copy-command option and change copy-pipe and friends to pipe to it if
used without arguments, allows all the default copy key bindings to be
changed to pipe with one option rather than needing to change each key
binding individually.
* Tidy up the terminal detection and feature code and add named sets of
terminal features, each of which are defined in one place and map to a
builtin set of terminfo(5) capabilities. Features can be specified based on
TERM with a new terminal-features option or with the -T flag when running
tmux. tmux will also detect a few common terminals from the DA and DSR
responses.
This is intended to make it easier to configure tmux's use of terminfo(5)
even in the presence of outdated ncurses(3) or terminfo(5) databases or for
features which do not yet have a terminfo(5) entry. Instead of having to grok
terminfo(5) capability names and what they should be set to in the
terminal-overrides option, the user can hopefully just give tmux a feature
name and let it do the right thing.
The terminal-overrides option remains both for backwards compatibility and to
allow tweaks of individual capabilities.
* Support mintty's application escape sequence (means tmux doesn't have to
delay to wait for Escape, so no need to reduce escape-time when using
mintty).
* Change so main-pane-width and height can be given as a percentage.
* Support for the iTerm2 synchronized updates feature (allows the terminal to
avoid unnecessary drawing while output is still in progress).
* Make the mouse_word and mouse_line formats work in copy mode and enable the
default pane menu in copy mode.
* Add a -T flag to resize-pane to trim lines below the cursor, moving lines out
of the history.
* Add a way to mark environment variables as "hidden" so they can be used by
tmux (for example in formats) but are not set in the environment for new
panes. set-environment and show-environment have a new -h flag and there is a
new %hidden statement for the configuration file.
* Change default position for display-menu -x and -y to centre rather than top
left.
* Add support for per-client transient popups, similar to menus but which are
connected to an external command (like a pane). These are created with new
command display-popup.
* Change double and triple click bindings so that only one is fired (previously
double click was fired on the way to triple click). Also add default double
and triple click bindings to copy the word or line under the cursor and
change the existing bindings in copy mode to do the same.
* Add a default binding for button 2 to paste.
* Add -d flag to run-shell to delay before running the command and allow it to
be used without a command so it just delays.
* Add C-g to cancel command prompt with vi keys as well as emacs, and q in
command mode.
* When the server socket is given with -S, create it with umask 177 instead of
117 (because it may not be in a safe directory like the default directory in
/tmp).
* Add a copy-mode -H flag to hide the position marker in the top right.
* Add number operators for formats (+, -, *, / and m),
CHANGED FROM 3.1b TO 3.1c
* Do not write after the end of the array and overwrite the stack when
colon-separated SGR sequences contain empty arguments.
CHANGES FROM 3.1a TO 3.1b
* Fix build on systems without sys/queue.h.
@ -736,7 +1504,7 @@ Incompatible Changes
bind -Tcopy-mode C-r command-prompt -i -p'search up' "send -X search-backward-incremental '%%'"
There are also some new commmands available with send -X, such as
There are also some new commands available with send -X, such as
copy-pipe-and-cancel.
* set-remain-on-exit has gone -- can be achieved with hooks instead.
* Hooks: before hooks have been removed and only a selection of commands now
@ -2712,7 +3480,7 @@ The list of older changes is below.
* (nicm) -n on new-session is now -s, and -n is now the initial window name.
This was documented but not implemented :-/.
* (nicm) kill-window command, bound to & by default (because it should be hard
to hit accidently).
to hit accidentally).
* (nicm) bell-style option with three choices: "none" completely ignore bell;
"any" pass through a bell in any window to current; "current" ignore bells
except in current window. This applies only to the bell terminal signal,

View File

@ -1,5 +1,3 @@
# Makefile.am
# Obvious program stuff.
bin_PROGRAMS = tmux
CLEANFILES = tmux.1.mdoc tmux.1.man cmd-parse.c
@ -12,8 +10,10 @@ dist_EXTRA_tmux_SOURCES = compat/*.[ch]
# Preprocessor flags.
AM_CPPFLAGS += @XOPEN_DEFINES@ \
-DTMUX_VERSION="\"@VERSION@\"" \
-DTMUX_CONF="\"$(sysconfdir)/tmux.conf:~/.tmux.conf:~/.config/tmux/tmux.conf\""
-DTMUX_VERSION='"@VERSION@"' \
-DTMUX_CONF='"$(sysconfdir)/tmux.conf:~/.tmux.conf:$$XDG_CONFIG_HOME/tmux/tmux.conf:~/.config/tmux/tmux.conf"' \
-DTMUX_LOCK_CMD='"@DEFAULT_LOCK_CMD@"' \
-DTMUX_TERM='"@DEFAULT_TERM@"'
# Additional object files.
LDADD = $(LIBOBJS)
@ -28,7 +28,10 @@ AM_CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
AM_CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
AM_CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
AM_CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign -Wno-attributes
AM_CFLAGS += -Wno-unused-result
AM_CFLAGS += -Wno-unused-result -Wno-format-y2k
if IS_DARWIN
AM_CFLAGS += -Wno-deprecated-declarations -Wno-cast-align -Wno-macro-redefined
endif
AM_CPPFLAGS += -DDEBUG
endif
AM_CPPFLAGS += -iquote.
@ -58,6 +61,16 @@ if IS_NETBSD
AM_CPPFLAGS += -D_OPENBSD_SOURCE
endif
# Set flags for Haiku.
if IS_HAIKU
AM_CPPFLAGS += -D_BSD_SOURCE
endif
# Set flags for Cygwin.
if IS_CYGWIN
AM_CPPFLAGS += -DTMUX_SOCK_PERM=0
endif
# List of sources.
dist_tmux_SOURCES = \
alerts.c \
@ -114,12 +127,14 @@ dist_tmux_SOURCES = \
cmd-select-pane.c \
cmd-select-window.c \
cmd-send-keys.c \
cmd-server-access.c \
cmd-set-buffer.c \
cmd-set-environment.c \
cmd-set-option.c \
cmd-show-environment.c \
cmd-show-messages.c \
cmd-show-options.c \
cmd-show-prompt-history.c \
cmd-source-file.c \
cmd-split-window.c \
cmd-swap-pane.c \
@ -136,8 +151,10 @@ dist_tmux_SOURCES = \
file.c \
format.c \
format-draw.c \
grid-reader.c \
grid-view.c \
grid.c \
hyperlinks.c \
input-keys.c \
input.c \
job.c \
@ -154,12 +171,14 @@ dist_tmux_SOURCES = \
options-table.c \
options.c \
paste.c \
popup.c \
proc.c \
regsub.c \
resize.c \
screen-redraw.c \
screen-write.c \
screen.c \
server-acl.c \
server-client.c \
server-fn.c \
server.c \
@ -169,20 +188,23 @@ dist_tmux_SOURCES = \
style.c \
tmux.c \
tmux.h \
tmux-protocol.h \
tty-acs.c \
tty-features.c \
tty-keys.c \
tty-term.c \
tty.c \
utf8-combined.c \
utf8.c \
window-buffer.c \
window-client.c \
window-clock.c \
window-copy.c \
window-customize.c \
window-tree.c \
window.c \
xmalloc.c \
xmalloc.h \
xterm-keys.c
xmalloc.h
nodist_tmux_SOURCES = osdep-@PLATFORM@.c
# Add compat file for forkpty.
@ -190,11 +212,27 @@ if NEED_FORKPTY
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
endif
# Add compat file for systemd.
if HAVE_SYSTEMD
nodist_tmux_SOURCES += compat/systemd.c
endif
# Add compat file for utf8proc.
if HAVE_UTF8PROC
nodist_tmux_SOURCES += compat/utf8proc.c
endif
# Enable sixel support.
if ENABLE_SIXEL
dist_tmux_SOURCES += image.c image-sixel.c
endif
if NEED_FUZZING
check_PROGRAMS = fuzz/input-fuzzer
fuzz_input_fuzzer_LDFLAGS = $(FUZZING_LIBS)
fuzz_input_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
endif
# Install tmux.1 in the right format.
install-exec-hook:
if test x@MANFORMAT@ = xmdoc; then \

16
README
View File

@ -4,7 +4,7 @@ tmux is a terminal multiplexer: it enables a number of terminals to be created,
accessed, and controlled from a single screen. tmux may be detached from a
screen and continue running in the background, then later reattached.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris.
* Dependencies
@ -16,6 +16,9 @@ It also depends on ncurses, available from:
https://invisible-mirror.net/archives/ncurses/
To build tmux, a C compiler (for example gcc or clang), make, pkg-config and a
suitable yacc (yacc or bison) are needed.
* Installation
To build and install tmux from a release tarball, use:
@ -33,6 +36,7 @@ autoconf, automake and pkg-config:
$ cd tmux
$ sh autogen.sh
$ ./configure && make
$ sudo make install
* Contributing
@ -52,9 +56,17 @@ source tree with:
A small example configuration is in example_tmux.conf.
Other documentation is available in the wiki:
https://github.com/tmux/tmux/wiki
Also see the tmux FAQ at:
https://github.com/tmux/tmux/wiki/FAQ
A bash(1) completion file is at:
https://github.com/imomaliev/tmux-bash-completion
https://github.com/scop/bash-completion/blob/main/completions/tmux
For debugging, run tmux with -v and -vv to generate server and client log files
in the current directory.

View File

@ -3,7 +3,7 @@ tmuxへようこそ!
tmuxはターミナルマルチプレクサーです。複数のターミナルを一つのスクリーン内に作成し、操作することができます。
バックグラウンドで処理を実行中に一度スクリーンから離れて後から復帰することも可能です。
OpenBSD、FreeBSD、NetBSD、Linux、OS X、Solarisで実行できます。
OpenBSD、FreeBSD、NetBSD、Linux、macOS、Solarisで実行できます。
tmuxはlibevent 2.x.に依存します。 下記からダウンロードしてください。
@ -38,7 +38,7 @@ tmuxのドキュメントについてはtmux.1マニュアルをご覧くださ
サンプル設定は本リポジトリのexample_tmux.confに
また、bash-completionファイルは下記にあります。
https://github.com/imomaliev/tmux-bash-completion
https://github.com/scop/bash-completion/blob/main/completions/tmux
「-v」や「-vv」を指定することでデバッグモードでの起動が可能です。カレントディレクトリにサーバーやクライアントのログファイルが生成されます。

32
SYNCING
View File

@ -1,17 +1,17 @@
Preamble
========
Tmux portable relies on repositories "tmux" and "tmux-openbsd".
Tmux portable relies on repositories "tmux" and "tmux-obsd".
Here's a description of them:
* "tmux" is the portable version, the one which contains code for other
operating systems, and autotools, etc., which isn't found or needed in the
OpenBSD base system.
* "tmux-openbsd" is the version of tmux in OpenBSD base system which provides
* "tmux-obsd" is the version of tmux in OpenBSD base system which provides
the basis of the portable tmux version.
Note: The "tmux-openbsd" repository is actually handled by "git cvsimport"
Note: The "tmux-obsd" repository is actually handled by "git cvsimport"
running at 15 minute intervals, so a commit made to OpenBSD's tmux CVS
repository will take at least that long to appear in this git repository.
(It might take longer, depending on the CVS mirror used to import the
@ -34,11 +34,11 @@ this information has ever been set before.
Cloning repositories
====================
This involves having both tmux and tmux-openbsd cloned, as in:
This involves having both tmux and tmux-obsd cloned, as in:
% cd /some/where/useful
% git clone https://github.com/tmux/tmux.git
% git clone https://github.com/ThomasAdam/tmux-openbsd.git
% git clone https://github.com/ThomasAdam/tmux-obsd.git
Note that you do not need additional checkouts to manage the sync -- an
existing clone of either repositories will suffice. So if you already have
@ -47,30 +47,30 @@ these checkouts existing, skip that.
Adding in git-remotes
=====================
Because the portable "tmux" git repository and the "tmux-openbsd"
Because the portable "tmux" git repository and the "tmux-obsd"
repository do not inherently share any history between each other, the
history has been faked between them. This "faking of history" is something
which has to be told to git for the purposes of comparing the "tmux" and
"tmux-openbsd" repositories for syncing. To do this, we must reference the
clone of the "tmux-openbsd" repository from the "tmux" repository, as
"tmux-obsd" repositories for syncing. To do this, we must reference the
clone of the "tmux-obsd" repository from the "tmux" repository, as
shown by the following command:
% cd /path/to/tmux
% git remote add obsd-tmux file:///path/to/tmux-openbsd
% git remote add obsd-tmux file:///path/to/tmux-obsd
So that now, the remote "obsd-tmux" can be used to reference branches and
commits from the "tmux-openbsd" repository, but from the context of the
commits from the "tmux-obsd" repository, but from the context of the
portable "tmux" repository, which makes sense because it's the "tmux"
repository which will have the updates applied to them.
Fetching updates
================
To ensure the latest commits from "tmux-openbsd" can be found from within
"tmux", we have to ensure the "master" branch from "tmux-openbsd" is
To ensure the latest commits from "tmux-obsd" can be found from within
"tmux", we have to ensure the "master" branch from "tmux-obsd" is
up-to-date first, and then reference that update in "tmux", as in:
% cd /path/to/tmux-openbsd
% cd /path/to/tmux-obsd
% git checkout master
% git pull
@ -82,9 +82,9 @@ Then back in "tmux":
Creating the necessary branches
===============================
Now that "tmux" can see commits and branches from "tmux-openbsd" by way
Now that "tmux" can see commits and branches from "tmux-obsd" by way
of the remote name "obsd-tmux", we can now create the master branch from
"tmux-openbsd" in the "tmux" repository:
"tmux-obsd" in the "tmux" repository:
% git checkout -b obsd-master obsd-tmux/master
@ -92,7 +92,7 @@ Adding in the fake history points
=================================
To tie both the "master" branch from "tmux" and the "obsd-master"
branch from "tmux-openbsd" together, the fake history points added to the
branch from "tmux-obsd" together, the fake history points added to the
"tmux" repository need to be added. To do this, we must add an
additional refspec line, as in:

View File

@ -18,7 +18,6 @@
#include <sys/types.h>
#include <event.h>
#include <stdlib.h>
#include "tmux.h"
@ -200,7 +199,7 @@ alerts_check_bell(struct window *w)
* not check WINLINK_BELL).
*/
s = wl->session;
if (s->curw != wl) {
if (s->curw != wl || s->attached == 0) {
wl->flags |= WINLINK_BELL;
server_status_session(s);
}
@ -236,7 +235,7 @@ alerts_check_activity(struct window *w)
if (wl->flags & WINLINK_ACTIVITY)
continue;
s = wl->session;
if (s->curw != wl) {
if (s->curw != wl || s->attached == 0) {
wl->flags |= WINLINK_ACTIVITY;
server_status_session(s);
}
@ -272,7 +271,7 @@ alerts_check_silence(struct window *w)
if (wl->flags & WINLINK_SILENCE)
continue;
s = wl->session;
if (s->curw != wl) {
if (s->curw != wl || s->attached == 0) {
wl->flags |= WINLINK_SILENCE;
server_status_session(s);
}
@ -315,9 +314,12 @@ alerts_set_message(struct winlink *wl, const char *type, const char *option)
tty_putcode(&c->tty, TTYC_BEL);
if (visual == VISUAL_OFF)
continue;
if (c->session->curw == wl)
status_message_set(c, "%s in current window", type);
else
status_message_set(c, "%s in window %d", type, wl->idx);
if (c->session->curw == wl) {
status_message_set(c, -1, 1, 0, 0,
"%s in current window", type);
} else {
status_message_set(c, -1, 1, 0, 0,
"%s in window %d", type, wl->idx);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,8 @@ attributes_tostring(int attr)
if (attr == 0)
return ("none");
len = xsnprintf(buf, sizeof buf, "%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",
(attr & GRID_ATTR_CHARSET) ? "acs," : "",
(attr & GRID_ATTR_BRIGHT) ? "bright," : "",
(attr & GRID_ATTR_DIM) ? "dim," : "",
(attr & GRID_ATTR_UNDERSCORE) ? "underscore," : "",
@ -62,6 +63,7 @@ attributes_fromstring(const char *str)
const char *name;
int attr;
} table[] = {
{ "acs", GRID_ATTR_CHARSET },
{ "bright", GRID_ATTR_BRIGHT },
{ "bold", GRID_ATTR_BRIGHT },
{ "dim", GRID_ATTR_DIM },

128
cfg.c
View File

@ -27,12 +27,15 @@
#include "tmux.h"
struct client *cfg_client;
static char *cfg_file;
int cfg_finished;
static char **cfg_causes;
static u_int cfg_ncauses;
static struct cmdq_item *cfg_item;
int cfg_quiet = 1;
char **cfg_files;
u_int cfg_nfiles;
static enum cmd_retval
cfg_client_done(__unused struct cmdq_item *item, __unused void *data)
{
@ -48,8 +51,7 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data)
return (CMD_RETURN_NORMAL);
cfg_finished = 1;
if (!RB_EMPTY(&sessions))
cfg_show_causes(RB_MIN(sessions, &sessions));
cfg_show_causes(NULL);
if (cfg_item != NULL)
cmdq_continue(cfg_item);
@ -59,52 +61,12 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data)
return (CMD_RETURN_NORMAL);
}
void
set_cfg_file(const char *path)
{
free(cfg_file);
cfg_file = xstrdup(path);
}
static char *
expand_cfg_file(const char *path, const char *home)
{
char *expanded, *name;
const char *end;
struct environ_entry *value;
if (strncmp(path, "~/", 2) == 0) {
if (home == NULL)
return (NULL);
xasprintf(&expanded, "%s%s", home, path + 1);
return (expanded);
}
if (*path == '$') {
end = strchr(path, '/');
if (end == NULL)
name = xstrdup(path + 1);
else
name = xstrndup(path + 1, end - path - 1);
value = environ_find(global_environ, name);
free(name);
if (value == NULL)
return (NULL);
if (end == NULL)
end = "";
xasprintf(&expanded, "%s%s", value->value, end);
return (expanded);
}
return (xstrdup(path));
}
void
start_cfg(void)
{
const char *home = find_home();
struct client *c;
char *path, *copy, *next, *expanded;
u_int i;
int flags = 0;
/*
* Configuration files are loaded without a client, so commands are run
@ -122,33 +84,23 @@ start_cfg(void)
cmdq_append(c, cfg_item);
}
if (cfg_file == NULL) {
path = copy = xstrdup(TMUX_CONF);
while ((next = strsep(&path, ":")) != NULL) {
expanded = expand_cfg_file(next, home);
if (expanded == NULL) {
log_debug("couldn't expand %s", next);
continue;
}
log_debug("expanded %s to %s", next, expanded);
load_cfg(expanded, c, NULL, CMD_PARSE_QUIET, NULL);
free(expanded);
}
free(copy);
} else
load_cfg(cfg_file, c, NULL, 0, NULL);
if (cfg_quiet)
flags = CMD_PARSE_QUIET;
for (i = 0; i < cfg_nfiles; i++)
load_cfg(cfg_files[i], c, NULL, NULL, flags, NULL);
cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL));
}
int
load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
struct cmdq_item **new_item)
load_cfg(const char *path, struct client *c, struct cmdq_item *item,
struct cmd_find_state *current, int flags, struct cmdq_item **new_item)
{
FILE *f;
struct cmd_parse_input pi;
struct cmd_parse_result *pr;
struct cmdq_item *new_item0;
struct cmdq_state *state;
if (new_item != NULL)
*new_item = NULL;
@ -170,8 +122,6 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
pr = cmd_parse_from_file(f, &pi);
fclose(f);
if (pr->status == CMD_PARSE_EMPTY)
return (0);
if (pr->status == CMD_PARSE_ERROR) {
cfg_add_cause("%s", pr->error);
free(pr->error);
@ -182,12 +132,19 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
return (0);
}
new_item0 = cmdq_get_command(pr->cmdlist, NULL, NULL, 0);
if (item != NULL)
state = cmdq_copy_state(cmdq_get_state(item), current);
else
state = cmdq_new_state(NULL, NULL, 0);
cmdq_add_format(state, "current_file", "%s", pi.file);
new_item0 = cmdq_get_command(pr->cmdlist, state);
if (item != NULL)
new_item0 = cmdq_insert_after(item, new_item0);
else
new_item0 = cmdq_append(NULL, new_item0);
cmd_list_free(pr->cmdlist);
cmdq_free_state(state);
if (new_item != NULL)
*new_item = new_item0;
@ -196,12 +153,13 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
int
load_cfg_from_buffer(const void *buf, size_t len, const char *path,
struct client *c, struct cmdq_item *item, int flags,
struct cmdq_item **new_item)
struct client *c, struct cmdq_item *item, struct cmd_find_state *current,
int flags, struct cmdq_item **new_item)
{
struct cmd_parse_input pi;
struct cmd_parse_result *pr;
struct cmdq_item *new_item0;
struct cmdq_state *state;
if (new_item != NULL)
*new_item = NULL;
@ -216,8 +174,6 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
pi.c = c;
pr = cmd_parse_from_buffer(buf, len, &pi);
if (pr->status == CMD_PARSE_EMPTY)
return (0);
if (pr->status == CMD_PARSE_ERROR) {
cfg_add_cause("%s", pr->error);
free(pr->error);
@ -228,12 +184,19 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
return (0);
}
new_item0 = cmdq_get_command(pr->cmdlist, NULL, NULL, 0);
if (item != NULL)
state = cmdq_copy_state(cmdq_get_state(item), current);
else
state = cmdq_new_state(NULL, NULL, 0);
cmdq_add_format(state, "current_file", "%s", pi.file);
new_item0 = cmdq_get_command(pr->cmdlist, state);
if (item != NULL)
new_item0 = cmdq_insert_after(item, new_item0);
else
new_item0 = cmdq_append(NULL, new_item0);
cmd_list_free(pr->cmdlist);
cmdq_free_state(state);
if (new_item != NULL)
*new_item = new_item0;
@ -273,22 +236,41 @@ cfg_print_causes(struct cmdq_item *item)
void
cfg_show_causes(struct session *s)
{
struct client *c = TAILQ_FIRST(&clients);
struct window_pane *wp;
struct window_mode_entry *wme;
u_int i;
if (s == NULL || cfg_ncauses == 0)
if (cfg_ncauses == 0)
return;
if (c != NULL && (c->flags & CLIENT_CONTROL)) {
for (i = 0; i < cfg_ncauses; i++) {
control_write(c, "%%config-error %s", cfg_causes[i]);
free(cfg_causes[i]);
}
goto out;
}
if (s == NULL) {
if (c != NULL && c->session != NULL)
s = c->session;
else
s = RB_MIN(sessions, &sessions);
}
if (s == NULL || s->attached == 0) /* wait for an attached session */
return;
wp = s->curw->window->active;
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode != &window_view_mode)
window_pane_set_mode(wp, &window_view_mode, NULL, NULL);
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL);
for (i = 0; i < cfg_ncauses; i++) {
window_copy_add(wp, "%s", cfg_causes[i]);
window_copy_add(wp, 0, "%s", cfg_causes[i]);
free(cfg_causes[i]);
}
out:
free(cfg_causes);
cfg_causes = NULL;
cfg_ncauses = 0;

525
client.c
View File

@ -18,12 +18,12 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <errno.h>
#include <event.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
@ -34,7 +34,8 @@
static struct tmuxproc *client_proc;
static struct tmuxpeer *client_peer;
static int client_flags;
static uint64_t client_flags;
static int client_suspended;
static enum {
CLIENT_EXIT_NONE,
CLIENT_EXIT_DETACHED,
@ -44,11 +45,13 @@ static enum {
CLIENT_EXIT_LOST_SERVER,
CLIENT_EXIT_EXITED,
CLIENT_EXIT_SERVER_EXITED,
CLIENT_EXIT_MESSAGE_PROVIDED
} client_exitreason = CLIENT_EXIT_NONE;
static int client_exitflag;
static int client_exitval;
static enum msgtype client_exittype;
static const char *client_exitsession;
static char *client_exitmessage;
static const char *client_execshell;
static const char *client_execcmd;
static int client_attached;
@ -56,8 +59,10 @@ static struct client_files client_files = RB_INITIALIZER(&client_files);
static __dead void client_exec(const char *,const char *);
static int client_get_lock(char *);
static int client_connect(struct event_base *, const char *, int);
static void client_send_identify(const char *, const char *);
static int client_connect(struct event_base *, const char *,
uint64_t);
static void client_send_identify(const char *, const char *,
char **, u_int, const char *, int);
static void client_signal(int);
static void client_dispatch(struct imsg *, void *);
static void client_dispatch_attached(struct imsg *);
@ -97,7 +102,7 @@ client_get_lock(char *lockfile)
/* Connect client to server. */
static int
client_connect(struct event_base *base, const char *path, int start_server)
client_connect(struct event_base *base, const char *path, uint64_t flags)
{
struct sockaddr_un sa;
size_t size;
@ -122,7 +127,9 @@ retry:
log_debug("connect failed: %s", strerror(errno));
if (errno != ECONNREFUSED && errno != ENOENT)
goto failed;
if (!start_server)
if (flags & CLIENT_NOSTARTSERVER)
goto failed;
if (~flags & CLIENT_STARTSERVER)
goto failed;
close(fd);
@ -154,7 +161,7 @@ retry:
close(lockfd);
return (-1);
}
fd = server_start(client_proc, base, lockfd, lockfile);
fd = server_start(client_proc, flags, base, lockfd, lockfile);
}
if (locked && lockfd >= 0) {
@ -206,6 +213,8 @@ client_exit_message(void)
return ("exited");
case CLIENT_EXIT_SERVER_EXITED:
return ("server exited");
case CLIENT_EXIT_MESSAGE_PROVIDED:
return (client_exitmessage);
}
return ("unknown reason");
}
@ -214,76 +223,71 @@ client_exit_message(void)
static void
client_exit(void)
{
struct client_file *cf;
size_t left;
int waiting = 0;
RB_FOREACH (cf, client_files, &client_files) {
if (cf->event == NULL)
continue;
left = EVBUFFER_LENGTH(cf->event->output);
if (left != 0) {
waiting++;
log_debug("file %u %zu bytes left", cf->stream, left);
}
}
if (waiting == 0)
if (!file_write_left(&client_files))
proc_exit(client_proc);
}
/* Client main loop. */
int
client_main(struct event_base *base, int argc, char **argv, int flags)
client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
int feat)
{
struct cmd_parse_result *pr;
struct cmd *cmd;
struct msg_command *data;
int cmdflags, fd, i;
const char *ttynam, *cwd;
int fd, i;
const char *ttynam, *termname, *cwd;
pid_t ppid;
enum msgtype msg;
struct termios tio, saved_tio;
size_t size;
/* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
signal(SIGCHLD, SIG_IGN);
/* Save the flags. */
client_flags = flags;
size_t size, linesize = 0;
ssize_t linelen;
char *line = NULL, **caps = NULL, *cause;
u_int ncaps = 0;
struct args_value *values;
/* Set up the initial command. */
cmdflags = 0;
if (shell_command != NULL) {
msg = MSG_SHELL;
cmdflags = CMD_STARTSERVER;
flags |= CLIENT_STARTSERVER;
} else if (argc == 0) {
msg = MSG_COMMAND;
cmdflags = CMD_STARTSERVER;
flags |= CLIENT_STARTSERVER;
} else {
msg = MSG_COMMAND;
/*
* It sucks parsing the command string twice (in client and
* later in server) but it is necessary to get the start server
* flag.
* It's annoying parsing the command string twice (in client
* and later in server) but it is necessary to get the start
* server flag.
*/
pr = cmd_parse_from_arguments(argc, argv, NULL);
values = args_from_vector(argc, argv);
pr = cmd_parse_from_arguments(values, argc, NULL);
if (pr->status == CMD_PARSE_SUCCESS) {
TAILQ_FOREACH(cmd, &pr->cmdlist->list, qentry) {
if (cmd->entry->flags & CMD_STARTSERVER)
cmdflags |= CMD_STARTSERVER;
}
if (cmd_list_any_have(pr->cmdlist, CMD_STARTSERVER))
flags |= CLIENT_STARTSERVER;
cmd_list_free(pr->cmdlist);
} else
free(pr->error);
args_free_values(values, argc);
free(values);
}
/* Create client process structure (starts logging). */
client_proc = proc_start("client");
proc_set_signals(client_proc, client_signal);
/* Save the flags. */
client_flags = flags;
log_debug("flags are %#llx", (unsigned long long)client_flags);
/* Initialize the client socket and start the server. */
fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER);
#ifdef HAVE_SYSTEMD
if (systemd_activated()) {
/* socket-based activation, do not even try to be a client. */
fd = server_start(client_proc, flags, base, 0, NULL);
} else
#endif
fd = client_connect(base, socket_path, client_flags);
if (fd == -1) {
if (errno == ECONNREFUSED) {
fprintf(stderr, "no server running on %s\n",
@ -301,6 +305,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
cwd = "/";
if ((ttynam = ttyname(STDIN_FILENO)) == NULL)
ttynam = "";
if ((termname = getenv("TERM")) == NULL)
termname = "";
/*
* Drop privileges for client. "proc exec" is needed for -c and for
@ -316,6 +322,16 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
NULL) != 0)
fatal("pledge failed");
/* Load terminfo entry if any. */
if (isatty(STDIN_FILENO) &&
*termname != '\0' &&
tty_term_read_list(termname, STDIN_FILENO, &caps, &ncaps,
&cause) != 0) {
fprintf(stderr, "%s\n", cause);
free(cause);
return (1);
}
/* Free stuff that is not used in the client. */
if (ptm_fd != -1)
close(ptm_fd);
@ -346,7 +362,9 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
}
/* Send identify messages. */
client_send_identify(ttynam, cwd);
client_send_identify(ttynam, termname, caps, ncaps, cwd, feat);
tty_term_free_list(caps, ncaps);
proc_flush_peer(client_peer);
/* Send first command. */
if (msg == MSG_COMMAND) {
@ -389,6 +407,11 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
client_exec(client_execshell, client_execcmd);
}
/* Restore streams to blocking. */
setblocking(STDIN_FILENO, 1);
setblocking(STDOUT_FILENO, 1);
setblocking(STDERR_FILENO, 1);
/* Print the exit message, if any, and exit. */
if (client_attached) {
if (client_exitreason != CLIENT_EXIT_NONE)
@ -397,42 +420,66 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
ppid = getppid();
if (client_exittype == MSG_DETACHKILL && ppid > 1)
kill(ppid, SIGHUP);
} else if (client_flags & CLIENT_CONTROLCONTROL) {
} else if (client_flags & CLIENT_CONTROL) {
if (client_exitreason != CLIENT_EXIT_NONE)
printf("%%exit %s\n", client_exit_message());
else
printf("%%exit\n");
fflush(stdout);
if (client_flags & CLIENT_CONTROL_WAITEXIT) {
setvbuf(stdin, NULL, _IOLBF, 0);
for (;;) {
linelen = getline(&line, &linesize, stdin);
if (linelen <= 1)
break;
}
free(line);
}
if (client_flags & CLIENT_CONTROLCONTROL) {
printf("\033\\");
fflush(stdout);
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
}
} else if (client_exitreason != CLIENT_EXIT_NONE)
fprintf(stderr, "%s\n", client_exit_message());
setblocking(STDIN_FILENO, 1);
return (client_exitval);
}
/* Send identify messages to server. */
static void
client_send_identify(const char *ttynam, const char *cwd)
client_send_identify(const char *ttynam, const char *termname, char **caps,
u_int ncaps, const char *cwd, int feat)
{
const char *s;
char **ss;
size_t sslen;
int fd, flags = client_flags;
int fd;
uint64_t flags = client_flags;
pid_t pid;
u_int i;
proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &flags, sizeof flags);
proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &client_flags,
sizeof client_flags);
if ((s = getenv("TERM")) == NULL)
s = "";
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, termname,
strlen(termname) + 1);
proc_send(client_peer, MSG_IDENTIFY_FEATURES, -1, &feat, sizeof feat);
proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam,
strlen(ttynam) + 1);
proc_send(client_peer, MSG_IDENTIFY_CWD, -1, cwd, strlen(cwd) + 1);
for (i = 0; i < ncaps; i++) {
proc_send(client_peer, MSG_IDENTIFY_TERMINFO, -1,
caps[i], strlen(caps[i]) + 1);
}
if ((fd = dup(STDIN_FILENO)) == -1)
fatal("dup failed");
proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0);
if ((fd = dup(STDOUT_FILENO)) == -1)
fatal("dup failed");
proc_send(client_peer, MSG_IDENTIFY_STDOUT, fd, NULL, 0);
pid = getpid();
proc_send(client_peer, MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid);
@ -447,275 +494,14 @@ client_send_identify(const char *ttynam, const char *cwd)
proc_send(client_peer, MSG_IDENTIFY_DONE, -1, NULL, 0);
}
/* File write error callback. */
static void
client_write_error_callback(__unused struct bufferevent *bev,
__unused short what, void *arg)
{
struct client_file *cf = arg;
log_debug("write error file %d", cf->stream);
bufferevent_free(cf->event);
cf->event = NULL;
close(cf->fd);
cf->fd = -1;
if (client_exitflag)
client_exit();
}
/* File write callback. */
static void
client_write_callback(__unused struct bufferevent *bev, void *arg)
{
struct client_file *cf = arg;
if (cf->closed && EVBUFFER_LENGTH(cf->event->output) == 0) {
bufferevent_free(cf->event);
close(cf->fd);
RB_REMOVE(client_files, &client_files, cf);
file_free(cf);
}
if (client_exitflag)
client_exit();
}
/* Open write file. */
static void
client_write_open(void *data, size_t datalen)
{
struct msg_write_open *msg = data;
const char *path;
struct msg_write_ready reply;
struct client_file find, *cf;
const int flags = O_NONBLOCK|O_WRONLY|O_CREAT;
int error = 0;
if (datalen < sizeof *msg)
fatalx("bad MSG_WRITE_OPEN size");
if (datalen == sizeof *msg)
path = "-";
else
path = (const char *)(msg + 1);
log_debug("open write file %d %s", msg->stream, path);
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, &client_files, &find)) == NULL) {
cf = file_create(NULL, msg->stream, NULL, NULL);
RB_INSERT(client_files, &client_files, cf);
} else {
error = EBADF;
goto reply;
}
if (cf->closed) {
error = EBADF;
goto reply;
}
cf->fd = -1;
if (msg->fd == -1)
cf->fd = open(path, msg->flags|flags, 0644);
else {
if (msg->fd != STDOUT_FILENO && msg->fd != STDERR_FILENO)
errno = EBADF;
else {
cf->fd = dup(msg->fd);
if (~client_flags & CLIENT_CONTROL)
close(msg->fd); /* can only be used once */
}
}
if (cf->fd == -1) {
error = errno;
goto reply;
}
cf->event = bufferevent_new(cf->fd, NULL, client_write_callback,
client_write_error_callback, cf);
bufferevent_enable(cf->event, EV_WRITE);
goto reply;
reply:
reply.stream = msg->stream;
reply.error = error;
proc_send(client_peer, MSG_WRITE_READY, -1, &reply, sizeof reply);
}
/* Write to client file. */
static void
client_write_data(void *data, size_t datalen)
{
struct msg_write_data *msg = data;
struct client_file find, *cf;
size_t size = datalen - sizeof *msg;
if (datalen < sizeof *msg)
fatalx("bad MSG_WRITE size");
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, &client_files, &find)) == NULL)
fatalx("unknown stream number");
log_debug("write %zu to file %d", size, cf->stream);
if (cf->event != NULL)
bufferevent_write(cf->event, msg + 1, size);
}
/* Close client file. */
static void
client_write_close(void *data, size_t datalen)
{
struct msg_write_close *msg = data;
struct client_file find, *cf;
if (datalen != sizeof *msg)
fatalx("bad MSG_WRITE_CLOSE size");
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, &client_files, &find)) == NULL)
fatalx("unknown stream number");
log_debug("close file %d", cf->stream);
if (cf->event == NULL || EVBUFFER_LENGTH(cf->event->output) == 0) {
if (cf->event != NULL)
bufferevent_free(cf->event);
if (cf->fd != -1)
close(cf->fd);
RB_REMOVE(client_files, &client_files, cf);
file_free(cf);
}
}
/* File read callback. */
static void
client_read_callback(__unused struct bufferevent *bev, void *arg)
{
struct client_file *cf = arg;
void *bdata;
size_t bsize;
struct msg_read_data *msg;
size_t msglen;
msg = xmalloc(sizeof *msg);
for (;;) {
bdata = EVBUFFER_DATA(cf->event->input);
bsize = EVBUFFER_LENGTH(cf->event->input);
if (bsize == 0)
break;
if (bsize > MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof *msg)
bsize = MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof *msg;
log_debug("read %zu from file %d", bsize, cf->stream);
msglen = (sizeof *msg) + bsize;
msg = xrealloc(msg, msglen);
msg->stream = cf->stream;
memcpy(msg + 1, bdata, bsize);
proc_send(client_peer, MSG_READ, -1, msg, msglen);
evbuffer_drain(cf->event->input, bsize);
}
free(msg);
}
/* File read error callback. */
static void
client_read_error_callback(__unused struct bufferevent *bev,
__unused short what, void *arg)
{
struct client_file *cf = arg;
struct msg_read_done msg;
log_debug("read error file %d", cf->stream);
msg.stream = cf->stream;
msg.error = 0;
proc_send(client_peer, MSG_READ_DONE, -1, &msg, sizeof msg);
bufferevent_free(cf->event);
close(cf->fd);
RB_REMOVE(client_files, &client_files, cf);
file_free(cf);
}
/* Open read file. */
static void
client_read_open(void *data, size_t datalen)
{
struct msg_read_open *msg = data;
const char *path;
struct msg_read_done reply;
struct client_file find, *cf;
const int flags = O_NONBLOCK|O_RDONLY;
int error = 0;
if (datalen < sizeof *msg)
fatalx("bad MSG_READ_OPEN size");
if (datalen == sizeof *msg)
path = "-";
else
path = (const char *)(msg + 1);
log_debug("open read file %d %s", msg->stream, path);
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, &client_files, &find)) == NULL) {
cf = file_create(NULL, msg->stream, NULL, NULL);
RB_INSERT(client_files, &client_files, cf);
} else {
error = EBADF;
goto reply;
}
if (cf->closed) {
error = EBADF;
goto reply;
}
cf->fd = -1;
if (msg->fd == -1)
cf->fd = open(path, flags);
else {
if (msg->fd != STDIN_FILENO)
errno = EBADF;
else {
cf->fd = dup(msg->fd);
if (~client_flags & CLIENT_CONTROL)
close(msg->fd); /* can only be used once */
}
}
if (cf->fd == -1) {
error = errno;
goto reply;
}
cf->event = bufferevent_new(cf->fd, client_read_callback, NULL,
client_read_error_callback, cf);
bufferevent_enable(cf->event, EV_READ);
return;
reply:
reply.stream = msg->stream;
reply.error = error;
proc_send(client_peer, MSG_READ_DONE, -1, &reply, sizeof reply);
}
/* Run command in shell; used for -c. */
static __dead void
client_exec(const char *shell, const char *shellcmd)
{
const char *name, *ptr;
char *argv0;
log_debug("shell %s, command %s", shell, shellcmd);
ptr = strrchr(shell, '/');
if (ptr != NULL && *(ptr + 1) != '\0')
name = ptr + 1;
else
name = shell;
if (client_flags & CLIENT_LOGIN)
xasprintf(&argv0, "-%s", name);
else
xasprintf(&argv0, "%s", name);
argv0 = shell_argv0(shell, !!(client_flags & CLIENT_LOGIN));
setenv("SHELL", shell, 1);
proc_clear_signals(client_proc, 1);
@ -735,11 +521,23 @@ client_signal(int sig)
{
struct sigaction sigact;
int status;
pid_t pid;
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
if (sig == SIGTERM)
log_debug("%s: %s", __func__, strsignal(sig));
if (sig == SIGCHLD) {
for (;;) {
pid = waitpid(WAIT_ANY, &status, WNOHANG);
if (pid == 0)
break;
if (pid == -1) {
if (errno == ECHILD)
break;
log_debug("waitpid failed: %s",
strerror(errno));
}
}
} else if (!client_attached) {
if (sig == SIGTERM || sig == SIGHUP)
proc_exit(client_proc);
} else {
switch (sig) {
@ -749,6 +547,7 @@ client_signal(int sig)
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case SIGTERM:
if (!client_suspended)
client_exitreason = CLIENT_EXIT_TERMINATED;
client_exitval = 1;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
@ -764,18 +563,31 @@ client_signal(int sig)
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
proc_send(client_peer, MSG_WAKEUP, -1, NULL, 0);
client_suspended = 0;
break;
}
}
}
/* Callback for file write error or close. */
static void
client_file_check_cb(__unused struct client *c, __unused const char *path,
__unused int error, __unused int closed, __unused struct evbuffer *buffer,
__unused void *data)
{
if (client_exitflag)
client_exit();
}
/* Callback for client read events. */
static void
client_dispatch(struct imsg *imsg, __unused void *arg)
{
if (imsg == NULL) {
if (!client_exitflag) {
client_exitreason = CLIENT_EXIT_LOST_SERVER;
client_exitval = 1;
}
proc_exit(client_proc);
return;
}
@ -786,13 +598,38 @@ client_dispatch(struct imsg *imsg, __unused void *arg)
client_dispatch_wait(imsg);
}
/* Process an exit message. */
static void
client_dispatch_exit_message(char *data, size_t datalen)
{
int retval;
if (datalen < sizeof retval && datalen != 0)
fatalx("bad MSG_EXIT size");
if (datalen >= sizeof retval) {
memcpy(&retval, data, sizeof retval);
client_exitval = retval;
}
if (datalen > sizeof retval) {
datalen -= sizeof retval;
data += sizeof retval;
client_exitmessage = xmalloc(datalen);
memcpy(client_exitmessage, data, datalen);
client_exitmessage[datalen - 1] = '\0';
client_exitreason = CLIENT_EXIT_MESSAGE_PROVIDED;
}
}
/* Dispatch imsgs when in wait state (before MSG_READY). */
static void
client_dispatch_wait(struct imsg *imsg)
{
char *data;
ssize_t datalen;
int retval;
static int pledge_applied;
/*
@ -815,12 +652,7 @@ client_dispatch_wait(struct imsg *imsg)
switch (imsg->hdr.type) {
case MSG_EXIT:
case MSG_SHUTDOWN:
if (datalen != sizeof retval && datalen != 0)
fatalx("bad MSG_EXIT size");
if (datalen == sizeof retval) {
memcpy(&retval, data, sizeof retval);
client_exitval = retval;
}
client_dispatch_exit_message(data, datalen);
client_exitflag = 1;
client_exit();
break;
@ -841,6 +673,14 @@ client_dispatch_wait(struct imsg *imsg)
client_exitval = 1;
proc_exit(client_proc);
break;
case MSG_FLAGS:
if (datalen != sizeof client_flags)
fatalx("bad MSG_FLAGS string");
memcpy(&client_flags, data, sizeof client_flags);
log_debug("new flags are %#llx",
(unsigned long long)client_flags);
break;
case MSG_SHELL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_SHELL string");
@ -855,16 +695,23 @@ client_dispatch_wait(struct imsg *imsg)
proc_exit(client_proc);
break;
case MSG_READ_OPEN:
client_read_open(data, datalen);
file_read_open(&client_files, client_peer, imsg, 1,
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
NULL);
break;
case MSG_READ_CANCEL:
file_read_cancel(&client_files, imsg);
break;
case MSG_WRITE_OPEN:
client_write_open(data, datalen);
file_write_open(&client_files, client_peer, imsg, 1,
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
NULL);
break;
case MSG_WRITE:
client_write_data(data, datalen);
file_write_data(&client_files, imsg);
break;
case MSG_WRITE_CLOSE:
client_write_close(data, datalen);
file_write_close(&client_files, imsg);
break;
case MSG_OLDSTDERR:
case MSG_OLDSTDIN:
@ -887,6 +734,14 @@ client_dispatch_attached(struct imsg *imsg)
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
switch (imsg->hdr.type) {
case MSG_FLAGS:
if (datalen != sizeof client_flags)
fatalx("bad MSG_FLAGS string");
memcpy(&client_flags, data, sizeof client_flags);
log_debug("new flags are %#llx",
(unsigned long long)client_flags);
break;
case MSG_DETACH:
case MSG_DETACHKILL:
if (datalen == 0 || data[datalen - 1] != '\0')
@ -911,11 +766,10 @@ client_dispatch_attached(struct imsg *imsg)
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case MSG_EXIT:
if (datalen != 0 && datalen != sizeof (int))
fatalx("bad MSG_EXIT size");
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
client_dispatch_exit_message(data, datalen);
if (client_exitreason == CLIENT_EXIT_NONE)
client_exitreason = CLIENT_EXIT_EXITED;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case MSG_EXITED:
if (datalen != 0)
@ -941,6 +795,7 @@ client_dispatch_attached(struct imsg *imsg)
sigact.sa_handler = SIG_DFL;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
client_suspended = 1;
kill(getpid(), SIGTSTP);
break;
case MSG_LOCK:

View File

@ -37,27 +37,29 @@ const struct cmd_entry cmd_attach_session_entry = {
.name = "attach-session",
.alias = "attach",
.args = { "c:dErt:x", 0, 0 },
.usage = "[-dErx] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
.args = { "c:dEf:rt:x", 0, 0, NULL },
.usage = "[-dErx] [-c working-directory] [-f flags] "
CMD_TARGET_SESSION_USAGE,
/* -t is special */
.flags = CMD_STARTSERVER,
.flags = CMD_STARTSERVER|CMD_READONLY,
.exec = cmd_attach_session_exec
};
enum cmd_retval
cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
int xflag, int rflag, const char *cflag, int Eflag)
int xflag, int rflag, const char *cflag, int Eflag, const char *fflag)
{
struct cmd_find_state *current = &item->shared->current;
struct cmd_find_state *current = cmdq_get_current(item);
struct cmd_find_state target;
enum cmd_find_type type;
int flags;
struct client *c = item->client, *c_loop;
struct client *c = cmdq_get_client(item), *c_loop;
struct session *s;
struct winlink *wl;
struct window_pane *wp;
char *cause;
char *cwd, *cause;
enum msgtype msgtype;
if (RB_EMPTY(&sessions)) {
@ -67,6 +69,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
if (c == NULL)
return (CMD_RETURN_NORMAL);
if (server_client_check_nested(c)) {
cmdq_error(item, "sessions should be nested with care, "
"unset $TMUX to force");
@ -80,11 +83,11 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
type = CMD_FIND_SESSION;
flags = CMD_FIND_PREFER_UNATTACHED;
}
if (cmd_find_target(&item->target, item, tflag, type, flags) != 0)
if (cmd_find_target(&target, item, tflag, type, flags) != 0)
return (CMD_RETURN_ERROR);
s = item->target.s;
wl = item->target.wl;
wp = item->target.wp;
s = target.s;
wl = target.wl;
wp = target.wp;
if (wl != NULL) {
if (wp != NULL)
@ -97,9 +100,14 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
}
if (cflag != NULL) {
cwd = format_single(item, cflag, c, s, wl, wp);
free((void *)s->cwd);
s->cwd = format_single(item, cflag, c, s, wl, wp);
s->cwd = cwd;
}
if (fflag)
server_client_set_flags(c, fflag);
if (rflag)
c->flags |= (CLIENT_READONLY|CLIENT_IGNORESIZE);
c->last_session = c->session;
if (c->session != NULL) {
@ -117,25 +125,15 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
if (!Eflag)
environ_update(s->options, c->environ, s->environ);
c->session = s;
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
server_client_set_session(c, s);
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
server_client_set_key_table(c, NULL);
tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
s->curw->window->latest = c;
} else {
if (server_client_open(c, &cause) != 0) {
cmdq_error(item, "open terminal failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (rflag)
c->flags |= CLIENT_READONLY;
if (dflag || xflag) {
if (xflag)
@ -151,25 +149,17 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
if (!Eflag)
environ_update(s->options, c->environ, s->environ);
c->session = s;
server_client_set_session(c, s);
server_client_set_key_table(c, NULL);
tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
s->curw->window->latest = c;
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
notify_client("client-attached", c);
c->flags |= CLIENT_ATTACHED;
}
recalculate_sizes();
alerts_check_session(s);
server_update_socket();
if (cfg_finished)
cfg_show_causes(s);
return (CMD_RETURN_NORMAL);
}
@ -177,9 +167,9 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
static enum cmd_retval
cmd_attach_session_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
return (cmd_attach_session(item, args_get(args, 't'),
args_has(args, 'd'), args_has(args, 'x'), args_has(args, 'r'),
args_get(args, 'c'), args_has(args, 'E')));
args_get(args, 'c'), args_has(args, 'E'), args_get(args, 'f')));
}

View File

@ -27,33 +27,44 @@
* Bind a key to a command.
*/
static enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmdq_item *);
static enum args_parse_type cmd_bind_key_args_parse(struct args *, u_int,
char **);
static enum cmd_retval cmd_bind_key_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_bind_key_entry = {
.name = "bind-key",
.alias = "bind",
.args = { "nrN:T:", 2, -1 },
.args = { "nrN:T:", 1, -1, cmd_bind_key_args_parse },
.usage = "[-nr] [-T key-table] [-N note] key "
"command [arguments]",
"[command [argument ...]]",
.flags = CMD_AFTERHOOK,
.exec = cmd_bind_key_exec
};
static enum args_parse_type
cmd_bind_key_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static enum cmd_retval
cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
key_code key;
const char *tablename, *note;
const char *tablename, *note = args_get(args, 'N');
struct cmd_parse_result *pr;
char **argv = args->argv;
int argc = args->argc, repeat;
int repeat;
struct args_value *value;
u_int count = args_count(args);
key = key_string_lookup_string(argv[0]);
key = key_string_lookup_string(args_string(args, 0));
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(item, "unknown key: %s", argv[0]);
cmdq_error(item, "unknown key: %s", args_string(args, 0));
return (CMD_RETURN_ERROR);
}
@ -65,14 +76,25 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
tablename = "prefix";
repeat = args_has(args, 'r');
if (argc == 2)
pr = cmd_parse_from_string(argv[1], NULL);
else
pr = cmd_parse_from_arguments(argc - 1, argv + 1, NULL);
if (count == 1) {
key_bindings_add(tablename, key, note, repeat, NULL);
return (CMD_RETURN_NORMAL);
}
value = args_value(args, 1);
if (count == 2 && value->type == ARGS_COMMANDS) {
key_bindings_add(tablename, key, note, repeat, value->cmdlist);
value->cmdlist->references++;
return (CMD_RETURN_NORMAL);
}
if (count == 2)
pr = cmd_parse_from_string(args_string(args, 1), NULL);
else {
pr = cmd_parse_from_arguments(args_values(args) + 1, count - 1,
NULL);
}
switch (pr->status) {
case CMD_PARSE_EMPTY:
cmdq_error(item, "empty command");
return (CMD_RETURN_ERROR);
case CMD_PARSE_ERROR:
cmdq_error(item, "%s", pr->error);
free(pr->error);
@ -80,7 +102,6 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
case CMD_PARSE_SUCCESS:
break;
}
note = args_get(args, 'N');
key_bindings_add(tablename, key, note, repeat, pr->cmdlist);
return (CMD_RETURN_NORMAL);
}

View File

@ -34,8 +34,8 @@ const struct cmd_entry cmd_break_pane_entry = {
.name = "break-pane",
.alias = "breakp",
.args = { "dPF:n:s:t:", 0, 0 },
.usage = "[-dP] [-F format] [-n window-name] [-s src-pane] "
.args = { "abdPF:n:s:t:", 0, 0, NULL },
.usage = "[-abdP] [-F format] [-n window-name] [-s src-pane] "
"[-t dst-window]",
.source = { 's', CMD_FIND_PANE, 0 },
@ -48,40 +48,61 @@ const struct cmd_entry cmd_break_pane_entry = {
static enum cmd_retval
cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct cmd_find_state *current = &item->shared->current;
struct client *c = cmd_find_client(item, NULL, 1);
struct winlink *wl = item->source.wl;
struct session *src_s = item->source.s;
struct session *dst_s = item->target.s;
struct window_pane *wp = item->source.wp;
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 cmd_find_state *source = cmdq_get_source(item);
struct client *tc = cmdq_get_target_client(item);
struct winlink *wl = source->wl;
struct session *src_s = source->s;
struct session *dst_s = target->s;
struct window_pane *wp = source->wp;
struct window *w = wl->window;
char *name, *cause;
int idx = item->target.idx;
char *name, *cause, *cp;
int idx = target->idx, before;
const char *template;
char *cp;
if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
cmdq_error(item, "index %d already in use", idx);
return (CMD_RETURN_ERROR);
}
if (window_count_panes(w) == 1) {
cmdq_error(item, "can't break with only one pane");
before = args_has(args, 'b');
if (args_has(args, 'a') || before) {
if (target->wl != NULL)
idx = winlink_shuffle_up(dst_s, target->wl, before);
else
idx = winlink_shuffle_up(dst_s, dst_s->curw, before);
if (idx == -1)
return (CMD_RETURN_ERROR);
}
server_unzoom_window(w);
if (window_count_panes(w) == 1) {
if (server_link_window(src_s, wl, dst_s, idx, 0,
!args_has(args, 'd'), &cause) != 0) {
cmdq_error(item, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'n')) {
window_set_name(w, args_get(args, 'n'));
options_set_number(w->options, "automatic-rename", 0);
}
server_unlink_window(src_s, wl);
return (CMD_RETURN_NORMAL);
}
if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
cmdq_error(item, "index in use: %d", idx);
return (CMD_RETURN_ERROR);
}
TAILQ_REMOVE(&w->panes, wp, entry);
server_client_remove_pane(wp);
window_lost_pane(w, wp);
layout_close_pane(wp);
w = wp->window = window_create(w->sx, w->sy, w->xpixel, w->ypixel);
options_set_parent(wp->options, w->options);
wp->flags |= PANE_STYLECHANGED;
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp;
w->latest = c;
w->latest = tc;
if (!args_has(args, 'n')) {
name = default_window_name(w);
@ -94,11 +115,12 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
layout_init(w, wp);
wp->flags |= PANE_CHANGED;
colour_palette_from_option(&wp->palette, wp->options);
if (idx == -1)
idx = -1 - options_get_number(dst_s->options, "base-index");
wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
if (!args_has(self->args, 'd')) {
if (!args_has(args, 'd')) {
session_select(dst_s, wl->idx);
cmd_find_from_session(current, dst_s, 0);
}
@ -113,7 +135,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)
template = BREAK_PANE_TEMPLATE;
cp = format_single(item, template, c, dst_s, wl, wp);
cp = format_single(item, template, tc, dst_s, wl, wp);
cmdq_print(item, "%s", cp);
free(cp);
}

View File

@ -39,8 +39,8 @@ const struct cmd_entry cmd_capture_pane_entry = {
.name = "capture-pane",
.alias = "capturep",
.args = { "ab:CeE:JNpPqS:t:", 0, 0 },
.usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] "
.args = { "ab:CeE:JMNpPqS:Tt:", 0, 0, NULL },
.usage = "[-aCeJMNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
"[-S start-line] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -53,8 +53,8 @@ const struct cmd_entry cmd_clear_history_entry = {
.name = "clear-history",
.alias = "clearhist",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_PANE_USAGE,
.args = { "Ht:", 0, 0, NULL },
.usage = "[-H] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -80,7 +80,7 @@ cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
size_t linelen;
u_int i;
pending = input_pending(wp);
pending = input_pending(wp->ictx);
if (pending == NULL)
return (xstrdup(""));
@ -109,8 +109,10 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
{
struct grid *gd;
const struct grid_line *gl;
struct screen *s;
struct grid_cell *gc = NULL;
int n, with_codes, escape_c0, join_lines, no_trim;
struct window_mode_entry *wme;
int n, join_lines, flags = 0;
u_int i, sx, top, bottom, tmp;
char *cause, *buf, *line;
const char *Sflag, *Eflag;
@ -118,7 +120,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
sx = screen_size_x(&wp->base);
if (args_has(args, 'a')) {
gd = wp->saved_grid;
gd = wp->base.saved_grid;
if (gd == NULL) {
if (!args_has(args, 'q')) {
cmdq_error(item, "no alternate screen");
@ -126,14 +128,27 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
}
return (xstrdup(""));
}
} else
s = &wp->base;
} else if (args_has(args, 'M')) {
wme = TAILQ_FIRST(&wp->modes);
if (wme != NULL && wme->mode->get_screen != NULL) {
s = wme->mode->get_screen (wme);
gd = s->grid;
} else {
s = &wp->base;
gd = wp->base.grid;
}
} else {
s = &wp->base;
gd = wp->base.grid;
}
Sflag = args_get(args, 'S');
if (Sflag != NULL && strcmp(Sflag, "-") == 0)
top = 0;
else {
n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
n = args_strtonum_and_expand(args, 'S', INT_MIN, SHRT_MAX,
item, &cause);
if (cause != NULL) {
top = gd->hsize;
free(cause);
@ -149,7 +164,8 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
if (Eflag != NULL && strcmp(Eflag, "-") == 0)
bottom = gd->hsize + gd->sy - 1;
else {
n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
n = args_strtonum_and_expand(args, 'E', INT_MIN, SHRT_MAX,
item, &cause);
if (cause != NULL) {
bottom = gd->hsize + gd->sy - 1;
free(cause);
@ -167,15 +183,19 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
top = tmp;
}
with_codes = args_has(args, 'e');
escape_c0 = args_has(args, 'C');
join_lines = args_has(args, 'J');
no_trim = args_has(args, 'N');
if (args_has(args, 'e'))
flags |= GRID_STRING_WITH_SEQUENCES;
if (args_has(args, 'C'))
flags |= GRID_STRING_ESCAPE_SEQUENCES;
if (!join_lines && !args_has(args, 'T'))
flags |= GRID_STRING_EMPTY_CELLS;
if (!join_lines && !args_has(args, 'N'))
flags |= GRID_STRING_TRIM_SPACES;
buf = NULL;
for (i = top; i <= bottom; i++) {
line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
escape_c0, !join_lines && !no_trim);
line = grid_string_cells(gd, 0, i, sx, &gc, flags, s);
linelen = strlen(line);
buf = cmd_capture_pane_append(buf, len, line, linelen);
@ -192,16 +212,18 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
static enum cmd_retval
cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c = item->client;
struct window_pane *wp = item->target.wp;
struct args *args = cmd_get_args(self);
struct client *c = cmdq_get_client(item);
struct window_pane *wp = cmdq_get_target(item)->wp;
char *buf, *cause;
const char *bufname;
size_t len;
if (self->entry == &cmd_clear_history_entry) {
if (cmd_get_entry(self) == &cmd_clear_history_entry) {
window_pane_reset_mode_all(wp);
grid_clear_history(wp->base.grid);
if (args_has(args, 'H'))
screen_reset_hyperlinks(wp->screen);
return (CMD_RETURN_NORMAL);
}
@ -214,15 +236,20 @@ cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
if (args_has(args, 'p')) {
if (len > 0 && buf[len - 1] == '\n')
len--;
if (c->flags & CLIENT_CONTROL)
control_write(c, "%.*s", (int)len, buf);
else {
if (!file_can_print(c)) {
cmdq_error(item, "can't write output to client");
cmdq_error(item, "can't write to client");
free(buf);
return (CMD_RETURN_ERROR);
}
file_print_buffer(c, buf, len);
if (args_has(args, 'P') && len > 0)
file_print(c, "\n");
free(buf);
}
} else {
bufname = NULL;
if (args_has(args, 'b'))

View File

@ -24,15 +24,18 @@
* Enter a mode.
*/
static enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmdq_item *);
static enum args_parse_type cmd_choose_tree_args_parse(struct args *args,
u_int idx, char **cause);
static enum cmd_retval cmd_choose_tree_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_choose_tree_entry = {
.name = "choose-tree",
.alias = NULL,
.args = { "F:Gf:NO:rst:wZ", 0, 1 },
.usage = "[-GNrswZ] [-F format] [-f filter] [-O sort-order] "
CMD_TARGET_PANE_USAGE " [template]",
.args = { "F:f:GK:NO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -44,9 +47,9 @@ const struct cmd_entry cmd_choose_client_entry = {
.name = "choose-client",
.alias = NULL,
.args = { "F:f:NO:rt:Z", 0, 1 },
.usage = "[-NrZ] [-F format] [-f filter] [-O sort-order] "
CMD_TARGET_PANE_USAGE " [template]",
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -58,9 +61,9 @@ const struct cmd_entry cmd_choose_buffer_entry = {
.name = "choose-buffer",
.alias = NULL,
.args = { "F:f:NO:rt:Z", 0, 1 },
.usage = "[-NrZ] [-F format] [-f filter] [-O sort-order] "
CMD_TARGET_PANE_USAGE " [template]",
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -68,24 +71,47 @@ const struct cmd_entry cmd_choose_buffer_entry = {
.exec = cmd_choose_tree_exec
};
const struct cmd_entry cmd_customize_mode_entry = {
.name = "customize-mode",
.alias = NULL,
.args = { "F:f:Nt:yZ", 0, 0, NULL },
.usage = "[-NZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
.flags = 0,
.exec = cmd_choose_tree_exec
};
static enum args_parse_type
cmd_choose_tree_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static enum cmd_retval
cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct window_pane *wp = item->target.wp;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct window_pane *wp = target->wp;
const struct window_mode *mode;
if (self->entry == &cmd_choose_buffer_entry) {
if (paste_get_top(NULL) == NULL)
if (cmd_get_entry(self) == &cmd_choose_buffer_entry) {
if (paste_is_empty())
return (CMD_RETURN_NORMAL);
mode = &window_buffer_mode;
} else if (self->entry == &cmd_choose_client_entry) {
} else if (cmd_get_entry(self) == &cmd_choose_client_entry) {
if (server_client_how_many() == 0)
return (CMD_RETURN_NORMAL);
mode = &window_client_mode;
} else
} else if (cmd_get_entry(self) == &cmd_customize_mode_entry)
mode = &window_customize_mode;
else
mode = &window_tree_mode;
window_pane_set_mode(wp, mode, &item->target, args);
window_pane_set_mode(wp, NULL, mode, target, args);
return (CMD_RETURN_NORMAL);
}

View File

@ -29,6 +29,8 @@
* Prompt for command in client.
*/
static enum args_parse_type cmd_command_prompt_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
struct cmdq_item *);
@ -40,81 +42,112 @@ const struct cmd_entry cmd_command_prompt_entry = {
.name = "command-prompt",
.alias = NULL,
.args = { "1kiI:Np:t:", 0, 1 },
.usage = "[-1kiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
"[template]",
.args = { "1bFkiI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
.usage = "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
" [-T prompt-type] [template]",
.flags = 0,
.flags = CMD_CLIENT_TFLAG,
.exec = cmd_command_prompt_exec
};
struct cmd_command_prompt_cdata {
int flags;
char *inputs;
char *next_input;
char *prompts;
char *next_prompt;
char *template;
int idx;
struct cmd_command_prompt_prompt {
char *input;
char *prompt;
};
struct cmd_command_prompt_cdata {
struct cmdq_item *item;
struct args_command_state *state;
int flags;
enum prompt_type prompt_type;
struct cmd_command_prompt_prompt *prompts;
u_int count;
u_int current;
int argc;
char **argv;
};
static enum args_parse_type
cmd_command_prompt_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static enum cmd_retval
cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
const char *inputs, *prompts;
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct cmd_find_state *target = cmdq_get_target(item);
const char *type, *s, *input;
struct cmd_command_prompt_cdata *cdata;
struct client *c;
char *prompt, *ptr, *input = NULL;
size_t n;
char *tmp, *prompts, *prompt, *next_prompt;
char *inputs = NULL, *next_input;
u_int count = args_count(args);
int wait = !args_has(args, 'b'), space = 1;
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (c->prompt_string != NULL)
if (tc->prompt_string != NULL)
return (CMD_RETURN_NORMAL);
if (args_has(args, 'i'))
wait = 0;
cdata = xcalloc(1, sizeof *cdata);
if (wait)
cdata->item = item;
cdata->state = args_make_commands_prepare(self, item, 0, "%1", wait,
args_has(args, 'F'));
cdata->inputs = NULL;
cdata->next_input = NULL;
cdata->prompts = NULL;
cdata->next_prompt = NULL;
cdata->template = NULL;
cdata->idx = 1;
if (args->argc != 0)
cdata->template = xstrdup(args->argv[0]);
else
cdata->template = xstrdup("%1");
if ((prompts = args_get(args, 'p')) != NULL)
cdata->prompts = xstrdup(prompts);
else if (args->argc != 0) {
n = strcspn(cdata->template, " ,");
xasprintf(&cdata->prompts, "(%.*s) ", (int) n, cdata->template);
} else
cdata->prompts = xstrdup(":");
/* Get first prompt. */
cdata->next_prompt = cdata->prompts;
ptr = strsep(&cdata->next_prompt, ",");
if (prompts == NULL)
prompt = xstrdup(ptr);
else
xasprintf(&prompt, "%s ", ptr);
/* Get initial prompt input. */
if ((inputs = args_get(args, 'I')) != NULL) {
cdata->inputs = xstrdup(inputs);
cdata->next_input = cdata->inputs;
input = strsep(&cdata->next_input, ",");
if ((s = args_get(args, 'p')) == NULL) {
if (count != 0) {
tmp = args_make_commands_get_command(cdata->state);
xasprintf(&prompts, "(%s)", tmp);
free(tmp);
} else {
prompts = xstrdup(":");
space = 0;
}
next_prompt = prompts;
} else
next_prompt = prompts = xstrdup(s);
if ((s = args_get(args, 'I')) != NULL)
next_input = inputs = xstrdup(s);
else
next_input = NULL;
while ((prompt = strsep(&next_prompt, ",")) != NULL) {
cdata->prompts = xreallocarray(cdata->prompts, cdata->count + 1,
sizeof *cdata->prompts);
if (!space)
tmp = xstrdup(prompt);
else
xasprintf(&tmp, "%s ", prompt);
cdata->prompts[cdata->count].prompt = tmp;
if (next_input != NULL) {
input = strsep(&next_input, ",");
if (input == NULL)
input = "";
} else
input = "";
cdata->prompts[cdata->count].input = xstrdup(input);
cdata->count++;
}
free(inputs);
free(prompts);
if ((type = args_get(args, 'T')) != NULL) {
cdata->prompt_type = status_prompt_type(type);
if (cdata->prompt_type == PROMPT_TYPE_INVALID) {
cmdq_error(item, "unknown type: %s", type);
cmd_command_prompt_free(cdata);
return (CMD_RETURN_ERROR);
}
} else
cdata->prompt_type = PROMPT_TYPE_COMMAND;
if (args_has(args, '1'))
cdata->flags |= PROMPT_SINGLE;
@ -124,11 +157,13 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
cdata->flags |= PROMPT_INCREMENTAL;
else if (args_has(args, 'k'))
cdata->flags |= PROMPT_KEY;
status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
cmd_command_prompt_free, cdata, cdata->flags);
free(prompt);
status_prompt_set(tc, target, cdata->prompts[0].prompt,
cdata->prompts[0].input, cmd_command_prompt_callback,
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
if (!wait)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
static int
@ -136,57 +171,57 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
int done)
{
struct cmd_command_prompt_cdata *cdata = data;
struct cmdq_item *new_item;
char *new_template, *prompt, *ptr;
char *input = NULL;
struct cmd_parse_result *pr;
char *error;
struct cmdq_item *item = cdata->item, *new_item;
struct cmd_list *cmdlist;
struct cmd_command_prompt_prompt *prompt;
int argc = 0;
char **argv = NULL;
if (s == NULL)
return (0);
if (done && (cdata->flags & PROMPT_INCREMENTAL))
return (0);
goto out;
new_template = cmd_template_replace(cdata->template, s, cdata->idx);
if (done) {
free(cdata->template);
cdata->template = new_template;
}
/*
* Check if there are more prompts; if so, get its respective input
* and update the prompt data.
*/
if (done && (ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
xasprintf(&prompt, "%s ", ptr);
input = strsep(&cdata->next_input, ",");
status_prompt_update(c, prompt, input);
free(prompt);
cdata->idx++;
if (cdata->flags & PROMPT_INCREMENTAL)
goto out;
cmd_append_argv(&cdata->argc, &cdata->argv, s);
if (++cdata->current != cdata->count) {
prompt = &cdata->prompts[cdata->current];
status_prompt_update(c, prompt->prompt, prompt->input);
return (1);
}
pr = cmd_parse_from_string(new_template, NULL);
switch (pr->status) {
case CMD_PARSE_EMPTY:
new_item = NULL;
break;
case CMD_PARSE_ERROR:
new_item = cmdq_get_error(pr->error);
free(pr->error);
cmdq_append(c, new_item);
break;
case CMD_PARSE_SUCCESS:
new_item = cmdq_get_command(pr->cmdlist, NULL, NULL, 0);
cmd_list_free(pr->cmdlist);
cmdq_append(c, new_item);
break;
}
argc = cdata->argc;
argv = cmd_copy_argv(cdata->argc, cdata->argv);
if (!done)
free(new_template);
cmd_append_argv(&argc, &argv, s);
if (done) {
cmd_free_argv(cdata->argc, cdata->argv);
cdata->argc = argc;
cdata->argv = cmd_copy_argv(argc, argv);
}
cmdlist = args_make_commands(cdata->state, argc, argv, &error);
if (cmdlist == NULL) {
cmdq_append(c, cmdq_get_error(error));
free(error);
} else if (item == NULL) {
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
} else {
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
}
cmd_free_argv(argc, argv);
if (c->prompt_inputcb != cmd_command_prompt_callback)
return (1);
out:
if (item != NULL)
cmdq_continue(item);
return (0);
}
@ -194,9 +229,14 @@ static void
cmd_command_prompt_free(void *data)
{
struct cmd_command_prompt_cdata *cdata = data;
u_int i;
free(cdata->inputs);
for (i = 0; i < cdata->count; i++) {
free(cdata->prompts[i].prompt);
free(cdata->prompts[i].input);
}
free(cdata->prompts);
free(cdata->template);
cmd_free_argv(cdata->argc, cdata->argv);
args_make_commands_free(cdata->state);
free(cdata);
}

View File

@ -28,6 +28,8 @@
* Asks for confirmation before executing a command.
*/
static enum args_parse_type cmd_confirm_before_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_confirm_before_exec(struct cmd *,
struct cmdq_item *);
@ -39,47 +41,80 @@ const struct cmd_entry cmd_confirm_before_entry = {
.name = "confirm-before",
.alias = "confirm",
.args = { "p:t:", 1, 1 },
.usage = "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
.args = { "bc:p:t:y", 1, 1, cmd_confirm_before_args_parse },
.usage = "[-by] [-c confirm-key] [-p prompt] " CMD_TARGET_CLIENT_USAGE
" command",
.flags = 0,
.flags = CMD_CLIENT_TFLAG,
.exec = cmd_confirm_before_exec
};
struct cmd_confirm_before_data {
char *cmd;
struct cmdq_item *item;
struct cmd_list *cmdlist;
u_char confirm_key;
int default_yes;
};
static enum args_parse_type
cmd_confirm_before_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static enum cmd_retval
cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_confirm_before_data *cdata;
struct client *c;
char *cmd, *copy, *new_prompt, *ptr;
const char *prompt;
struct client *tc = cmdq_get_target_client(item);
struct cmd_find_state *target = cmdq_get_target(item);
char *new_prompt;
const char *confirm_key, *prompt, *cmd;
int wait = !args_has(args, 'b');
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
cdata = xcalloc(1, sizeof *cdata);
cdata->cmdlist = args_make_commands_now(self, item, 0, 1);
if (cdata->cmdlist == NULL) {
free(cdata);
return (CMD_RETURN_ERROR);
}
if (wait)
cdata->item = item;
cdata->default_yes = args_has(args, 'y');
if ((confirm_key = args_get(args, 'c')) != NULL) {
if (confirm_key[1] == '\0' &&
confirm_key[0] > 31 &&
confirm_key[0] < 127)
cdata->confirm_key = confirm_key[0];
else {
cmdq_error(item, "invalid confirm key");
free(cdata);
return (CMD_RETURN_ERROR);
}
}
else
cdata->confirm_key = 'y';
if ((prompt = args_get(args, 'p')) != NULL)
xasprintf(&new_prompt, "%s ", prompt);
else {
ptr = copy = xstrdup(args->argv[0]);
cmd = strsep(&ptr, " \t");
xasprintf(&new_prompt, "Confirm '%s'? (y/n) ", cmd);
free(copy);
cmd = cmd_get_entry(cmd_list_first(cdata->cmdlist))->name;
xasprintf(&new_prompt, "Confirm '%s'? (%c/n) ", cmd,
cdata->confirm_key);
}
cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(args->argv[0]);
status_prompt_set(c, new_prompt, NULL,
status_prompt_set(tc, target, new_prompt, NULL,
cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
PROMPT_SINGLE);
PROMPT_SINGLE, PROMPT_TYPE_COMMAND);
free(new_prompt);
if (!wait)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
static int
@ -87,34 +122,34 @@ cmd_confirm_before_callback(struct client *c, void *data, const char *s,
__unused int done)
{
struct cmd_confirm_before_data *cdata = data;
struct cmdq_item *new_item;
struct cmd_parse_result *pr;
struct cmdq_item *item = cdata->item, *new_item;
int retcode = 1;
if (c->flags & CLIENT_DEAD)
return (0);
goto out;
if (s == NULL || *s == '\0')
return (0);
if (tolower((u_char)s[0]) != 'y' || s[1] != '\0')
return (0);
if (s == NULL)
goto out;
if (s[0] != cdata->confirm_key && (s[0] != '\r' || !cdata->default_yes))
goto out;
retcode = 0;
pr = cmd_parse_from_string(cdata->cmd, NULL);
switch (pr->status) {
case CMD_PARSE_EMPTY:
new_item = NULL;
break;
case CMD_PARSE_ERROR:
new_item = cmdq_get_error(pr->error);
free(pr->error);
if (item == NULL) {
new_item = cmdq_get_command(cdata->cmdlist, NULL);
cmdq_append(c, new_item);
break;
case CMD_PARSE_SUCCESS:
new_item = cmdq_get_command(pr->cmdlist, NULL, NULL, 0);
cmd_list_free(pr->cmdlist);
cmdq_append(c, new_item);
break;
} else {
new_item = cmdq_get_command(cdata->cmdlist,
cmdq_get_state(item));
cmdq_insert_after(item, new_item);
}
out:
if (item != NULL) {
if (cmdq_get_client(item) != NULL &&
cmdq_get_client(item)->session == NULL)
cmdq_get_client(item)->retval = retcode;
cmdq_continue(item);
}
return (0);
}
@ -123,6 +158,6 @@ cmd_confirm_before_free(void *data)
{
struct cmd_confirm_before_data *cdata = data;
free(cdata->cmd);
cmd_list_free(cdata->cmdlist);
free(cdata);
}

View File

@ -30,9 +30,10 @@ const struct cmd_entry cmd_copy_mode_entry = {
.name = "copy-mode",
.alias = NULL,
.args = { "eHMt:uq", 0, 0 },
.usage = "[-eHMuq] " CMD_TARGET_PANE_USAGE,
.args = { "deHMqSs:t:u", 0, 0, NULL },
.usage = "[-deHMqSu] [-s src-pane] " CMD_TARGET_PANE_USAGE,
.source = { 's', CMD_FIND_PANE, 0 },
.target = { 't', CMD_FIND_PANE, 0 },
.flags = CMD_AFTERHOOK,
@ -43,7 +44,7 @@ const struct cmd_entry cmd_clock_mode_entry = {
.name = "clock-mode",
.alias = NULL,
.args = { "t:", 0, 0 },
.args = { "t:", 0, 0, NULL },
.usage = CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -55,11 +56,13 @@ const struct cmd_entry cmd_clock_mode_entry = {
static enum cmd_retval
cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct cmdq_shared *shared = item->shared;
struct client *c = item->client;
struct args *args = cmd_get_args(self);
struct key_event *event = cmdq_get_event(item);
struct cmd_find_state *source = cmdq_get_source(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct client *c = cmdq_get_client(item);
struct session *s;
struct window_pane *wp = item->target.wp;
struct window_pane *wp = target->wp, *swp;
if (args_has(args, 'q')) {
window_pane_reset_mode_all(wp);
@ -67,23 +70,34 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
}
if (args_has(args, 'M')) {
if ((wp = cmd_mouse_pane(&shared->mouse, &s, NULL)) == NULL)
if ((wp = cmd_mouse_pane(&event->m, &s, NULL)) == NULL)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
}
if (self->entry == &cmd_clock_mode_entry) {
window_pane_set_mode(wp, &window_clock_mode, NULL, NULL);
if (cmd_get_entry(self) == &cmd_clock_mode_entry) {
window_pane_set_mode(wp, NULL, &window_clock_mode, NULL, NULL);
return (CMD_RETURN_NORMAL);
}
if (!window_pane_set_mode(wp, &window_copy_mode, NULL, args)) {
if (args_has(args, 's'))
swp = source->wp;
else
swp = wp;
if (!window_pane_set_mode(wp, swp, &window_copy_mode, NULL, args)) {
if (args_has(args, 'M'))
window_copy_start_drag(c, &shared->mouse);
window_copy_start_drag(c, &event->m);
}
if (args_has(self->args, 'u'))
if (args_has(args, 'u'))
window_copy_pageup(wp, 0);
if (args_has(args, 'd'))
window_copy_pagedown(wp, 0, args_has(args, 'e'));
if (args_has(args, 'S')) {
window_copy_scroll(wp, c->tty.mouse_slider_mpos, event->m.y,
args_has(args, 'e'));
return (CMD_RETURN_NORMAL);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -33,13 +33,13 @@ const struct cmd_entry cmd_detach_client_entry = {
.name = "detach-client",
.alias = "detach",
.args = { "aE:s:t:P", 0, 0 },
.args = { "aE:s:t:P", 0, 0, NULL },
.usage = "[-aP] [-E shell-command] "
"[-s target-session] " CMD_TARGET_CLIENT_USAGE,
.source = { 's', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
.flags = CMD_READONLY,
.flags = CMD_READONLY|CMD_CLIENT_TFLAG,
.exec = cmd_detach_client_exec
};
@ -47,27 +47,25 @@ const struct cmd_entry cmd_suspend_client_entry = {
.name = "suspend-client",
.alias = "suspendc",
.args = { "t:", 0, 0 },
.args = { "t:", 0, 0, NULL },
.usage = CMD_TARGET_CLIENT_USAGE,
.flags = 0,
.flags = CMD_CLIENT_TFLAG,
.exec = cmd_detach_client_exec
};
static enum cmd_retval
cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c, *cloop;
struct args *args = cmd_get_args(self);
struct cmd_find_state *source = cmdq_get_source(item);
struct client *tc = cmdq_get_target_client(item), *loop;
struct session *s;
enum msgtype msgtype;
const char *cmd = args_get(args, 'E');
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (self->entry == &cmd_suspend_client_entry) {
server_client_suspend(c);
if (cmd_get_entry(self) == &cmd_suspend_client_entry) {
server_client_suspend(tc);
return (CMD_RETURN_NORMAL);
}
@ -77,35 +75,35 @@ cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
msgtype = MSG_DETACH;
if (args_has(args, 's')) {
s = item->source.s;
s = source->s;
if (s == NULL)
return (CMD_RETURN_NORMAL);
TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session == s) {
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->session == s) {
if (cmd != NULL)
server_client_exec(cloop, cmd);
server_client_exec(loop, cmd);
else
server_client_detach(cloop, msgtype);
server_client_detach(loop, msgtype);
}
}
return (CMD_RETURN_STOP);
}
if (args_has(args, 'a')) {
TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session != NULL && cloop != c) {
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->session != NULL && loop != tc) {
if (cmd != NULL)
server_client_exec(cloop, cmd);
server_client_exec(loop, cmd);
else
server_client_detach(cloop, msgtype);
server_client_detach(loop, msgtype);
}
}
return (CMD_RETURN_NORMAL);
}
if (cmd != NULL)
server_client_exec(c, cmd);
server_client_exec(tc, cmd);
else
server_client_detach(c, msgtype);
server_client_detach(tc, msgtype);
return (CMD_RETURN_STOP);
}

View File

@ -27,75 +27,324 @@
* Display a menu on a client.
*/
static enum args_parse_type cmd_display_menu_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_display_menu_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_display_popup_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_display_menu_entry = {
.name = "display-menu",
.alias = "menu",
.args = { "c:t:T:x:y:", 1, -1 },
.usage = "[-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] "
"[-x position] [-y position] name key command ...",
.args = { "b:c:C:H:s:S:MOt:T:x:y:", 1, -1, cmd_display_menu_args_parse },
.usage = "[-MO] [-b border-lines] [-c target-client] "
"[-C starting-choice] [-H selected-style] [-s style] "
"[-S border-style] " CMD_TARGET_PANE_USAGE " [-T title] "
"[-x position] [-y position] name [key] [command] ...",
.target = { 't', CMD_FIND_PANE, 0 },
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG,
.exec = cmd_display_menu_exec
};
const struct cmd_entry cmd_display_popup_entry = {
.name = "display-popup",
.alias = "popup",
.args = { "Bb:Cc:d:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL },
.usage = "[-BCE] [-b border-lines] [-c target-client] "
"[-d start-directory] [-e environment] [-h height] "
"[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE
" [-T title] [-w width] [-x position] [-y position] "
"[shell-command [argument ...]]",
.target = { 't', CMD_FIND_PANE, 0 },
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG,
.exec = cmd_display_popup_exec
};
static enum args_parse_type
cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause)
{
u_int i = 0;
enum args_parse_type type = ARGS_PARSE_STRING;
for (;;) {
type = ARGS_PARSE_STRING;
if (i == idx)
break;
if (*args_string(args, i++) == '\0')
continue;
type = ARGS_PARSE_STRING;
if (i++ == idx)
break;
type = ARGS_PARSE_COMMANDS_OR_STRING;
if (i++ == idx)
break;
}
return (type);
}
static int
cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
{
struct tty *tty = &tc->tty;
struct cmd_find_state *target = cmdq_get_target(item);
struct key_event *event = cmdq_get_event(item);
struct session *s = tc->session;
struct winlink *wl = target->wl;
struct window_pane *wp = target->wp;
struct style_ranges *ranges = NULL;
struct style_range *sr = NULL;
const char *xp, *yp;
char *p;
int top;
u_int line, ox, oy, sx, sy, lines, position;
long n;
struct format_tree *ft;
/*
* Work out the position from the -x and -y arguments. This is the
* bottom-left position.
*/
/* If the popup is too big, stop now. */
if (w > tty->sx || h > tty->sy)
return (0);
/* Create format with mouse position if any. */
ft = format_create_from_target(item);
if (event->m.valid) {
format_add(ft, "popup_mouse_x", "%u", event->m.x);
format_add(ft, "popup_mouse_y", "%u", event->m.y);
}
/*
* If there are any status lines, add this window position and the
* status line position.
*/
top = status_at_line(tc);
if (top != -1) {
lines = status_line_size(tc);
if (top == 0)
top = lines;
else
top = 0;
position = options_get_number(s->options, "status-position");
for (line = 0; line < lines; line++) {
ranges = &tc->status.entries[line].ranges;
TAILQ_FOREACH(sr, ranges, entry) {
if (sr->type != STYLE_RANGE_WINDOW)
continue;
if (sr->argument == (u_int)wl->idx)
break;
}
if (sr != NULL)
break;
}
if (sr != NULL) {
format_add(ft, "popup_window_status_line_x", "%u",
sr->start);
if (position == 0) {
format_add(ft, "popup_window_status_line_y",
"%u", line + 1 + h);
} else {
format_add(ft, "popup_window_status_line_y",
"%u", tty->sy - lines + line);
}
}
if (position == 0)
format_add(ft, "popup_status_line_y", "%u", lines + h);
else {
format_add(ft, "popup_status_line_y", "%u",
tty->sy - lines);
}
} else
top = 0;
/* Popup width and height. */
format_add(ft, "popup_width", "%u", w);
format_add(ft, "popup_height", "%u", h);
/* Position so popup is in the centre. */
n = (long)(tty->sx - 1) / 2 - w / 2;
if (n < 0)
format_add(ft, "popup_centre_x", "%u", 0);
else
format_add(ft, "popup_centre_x", "%ld", n);
n = (tty->sy - 1) / 2 + h / 2;
if (n >= tty->sy)
format_add(ft, "popup_centre_y", "%u", tty->sy - h);
else
format_add(ft, "popup_centre_y", "%ld", n);
/* Position of popup relative to mouse. */
if (event->m.valid) {
n = (long)event->m.x - w / 2;
if (n < 0)
format_add(ft, "popup_mouse_centre_x", "%u", 0);
else
format_add(ft, "popup_mouse_centre_x", "%ld", n);
n = event->m.y - h / 2;
if (n + h >= tty->sy) {
format_add(ft, "popup_mouse_centre_y", "%u",
tty->sy - h);
} else
format_add(ft, "popup_mouse_centre_y", "%ld", n);
n = (long)event->m.y + h;
if (n >= tty->sy)
format_add(ft, "popup_mouse_top", "%u", tty->sy - 1);
else
format_add(ft, "popup_mouse_top", "%ld", n);
n = event->m.y - h;
if (n < 0)
format_add(ft, "popup_mouse_bottom", "%u", 0);
else
format_add(ft, "popup_mouse_bottom", "%ld", n);
}
/* Position in pane. */
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy);
n = top + wp->yoff - oy + h;
if (n >= tty->sy)
format_add(ft, "popup_pane_top", "%u", tty->sy - h);
else
format_add(ft, "popup_pane_top", "%ld", n);
format_add(ft, "popup_pane_bottom", "%u", top + wp->yoff + wp->sy - oy);
format_add(ft, "popup_pane_left", "%u", wp->xoff - ox);
n = (long)wp->xoff + wp->sx - ox - w;
if (n < 0)
format_add(ft, "popup_pane_right", "%u", 0);
else
format_add(ft, "popup_pane_right", "%ld", n);
/* Expand horizontal position. */
xp = args_get(args, 'x');
if (xp == NULL || strcmp(xp, "C") == 0)
xp = "#{popup_centre_x}";
else if (strcmp(xp, "R") == 0)
xp = "#{popup_pane_right}";
else if (strcmp(xp, "P") == 0)
xp = "#{popup_pane_left}";
else if (strcmp(xp, "M") == 0)
xp = "#{popup_mouse_centre_x}";
else if (strcmp(xp, "W") == 0)
xp = "#{popup_window_status_line_x}";
p = format_expand(ft, xp);
n = strtol(p, NULL, 10);
if (n + w >= tty->sx)
n = tty->sx - w;
else if (n < 0)
n = 0;
*px = n;
log_debug("%s: -x: %s = %s = %u (-w %u)", __func__, xp, p, *px, w);
free(p);
/* Expand vertical position */
yp = args_get(args, 'y');
if (yp == NULL || strcmp(yp, "C") == 0)
yp = "#{popup_centre_y}";
else if (strcmp(yp, "P") == 0)
yp = "#{popup_pane_bottom}";
else if (strcmp(yp, "M") == 0)
yp = "#{popup_mouse_top}";
else if (strcmp(yp, "S") == 0)
yp = "#{popup_status_line_y}";
else if (strcmp(yp, "W") == 0)
yp = "#{popup_window_status_line_y}";
p = format_expand(ft, yp);
n = strtol(p, NULL, 10);
if (n < h)
n = 0;
else
n -= h;
if (n + h >= tty->sy)
n = tty->sy - h;
else if (n < 0)
n = 0;
*py = n;
log_debug("%s: -y: %s = %s = %u (-h %u)", __func__, yp, p, *py, h);
free(p);
format_free(ft);
return (1);
}
static enum cmd_retval
cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c;
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct window_pane *wp = item->target.wp;
struct cmd_find_state *fs = &item->target;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct key_event *event = cmdq_get_event(item);
struct client *tc = cmdq_get_target_client(item);
struct menu *menu = NULL;
struct style_range *sr;
struct menu_item menu_item;
const char *xp, *yp, *key;
char *title, *name;
int at, flags, i;
u_int px, py, ox, oy, sx, sy;
const char *key, *name, *value;
const char *style = args_get(args, 's');
const char *border_style = args_get(args, 'S');
const char *selected_style = args_get(args, 'H');
enum box_lines lines = BOX_LINES_DEFAULT;
char *title, *cause;
int flags = 0, starting_choice = 0;
u_int px, py, i, count = args_count(args);
struct options *o = target->s->curw->window->options;
struct options_entry *oe;
if ((c = cmd_find_client(item, args_get(args, 'c'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (c->overlay_draw != NULL)
if (tc->overlay_draw != NULL)
return (CMD_RETURN_NORMAL);
at = status_at_line(c);
if (args_has(args, 'C')) {
if (strcmp(args_get(args, 'C'), "-") == 0)
starting_choice = -1;
else {
starting_choice = args_strtonum(args, 'C', 0, UINT_MAX,
&cause);
if (cause != NULL) {
cmdq_error(item, "starting choice %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
}
if (args_has(args, 'T'))
title = format_single(NULL, args_get(args, 'T'), c, s, wl, wp);
title = format_single_from_target(item, args_get(args, 'T'));
else
title = xstrdup("");
menu = menu_create(title);
free(title);
for (i = 0; i != args->argc; /* nothing */) {
name = args->argv[i++];
for (i = 0; i != count; /* nothing */) {
name = args_string(args, i++);
if (*name == '\0') {
menu_add_item(menu, NULL, item, c, fs);
menu_add_item(menu, NULL, item, tc, target);
continue;
}
if (args->argc - i < 2) {
if (count - i < 2) {
cmdq_error(item, "not enough arguments");
free(title);
menu_free(menu);
return (CMD_RETURN_ERROR);
}
key = args->argv[i++];
key = args_string(args, i++);
menu_item.name = name;
menu_item.key = key_string_lookup_string(key);
menu_item.command = args->argv[i++];
menu_item.command = args_string(args, i++);
menu_add_item(menu, &menu_item, item, c, fs);
menu_add_item(menu, &menu_item, item, tc, target);
}
free(title);
if (menu == NULL) {
cmdq_error(item, "invalid menu arguments");
return (CMD_RETURN_ERROR);
@ -104,75 +353,150 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
menu_free(menu);
return (CMD_RETURN_NORMAL);
}
xp = args_get(args, 'x');
if (xp == NULL)
px = 0;
else if (strcmp(xp, "R") == 0)
px = c->tty.sx - 1;
else if (strcmp(xp, "P") == 0) {
tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
if (wp->xoff >= ox)
px = wp->xoff - ox;
else
px = 0;
} else if (strcmp(xp, "M") == 0 && item->shared->mouse.valid) {
if (item->shared->mouse.x > (menu->width + 4) / 2)
px = item->shared->mouse.x - (menu->width + 4) / 2;
else
px = 0;
if (!cmd_display_menu_get_position(tc, item, args, &px, &py,
menu->width + 4, menu->count + 2)) {
menu_free(menu);
return (CMD_RETURN_NORMAL);
}
else if (strcmp(xp, "W") == 0) {
if (at == -1)
px = 0;
else {
TAILQ_FOREACH(sr, &c->status.entries[0].ranges, entry) {
if (sr->type != STYLE_RANGE_WINDOW)
continue;
if (sr->argument == (u_int)wl->idx)
break;
}
if (sr != NULL)
px = sr->start;
else
px = 0;
}
} else
px = strtoul(xp, NULL, 10);
if (px + menu->width + 4 >= c->tty.sx)
px = c->tty.sx - menu->width - 4;
yp = args_get(args, 'y');
if (yp == NULL)
py = 0;
else if (strcmp(yp, "P") == 0) {
tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
if (wp->yoff + wp->sy >= oy)
py = wp->yoff + wp->sy - oy;
else
py = 0;
} else if (strcmp(yp, "M") == 0 && item->shared->mouse.valid)
py = item->shared->mouse.y + menu->count + 2;
else if (strcmp(yp, "S") == 0) {
if (at == -1)
py = c->tty.sy;
else if (at == 0)
py = status_line_size(c) + menu->count + 2;
else
py = at;
} else
py = strtoul(yp, NULL, 10);
if (py < menu->count + 2)
py = 0;
else
py -= menu->count + 2;
if (py + menu->count + 2 >= c->tty.sy)
py = c->tty.sy - menu->count - 2;
value = args_get(args, 'b');
if (value != NULL) {
oe = options_get(o, "menu-border-lines");
lines = options_find_choice(options_table_entry(oe), value,
&cause);
if (lines == -1) {
cmdq_error(item, "menu-border-lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
flags = 0;
if (!item->shared->mouse.valid)
if (args_has(args, 'O'))
flags |= MENU_STAYOPEN;
if (!event->m.valid && !args_has(args, 'M'))
flags |= MENU_NOMOUSE;
if (menu_display(menu, flags, item, px, py, c, fs, NULL, NULL) != 0)
if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines,
style, selected_style, border_style, target, NULL, NULL) != 0)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
static enum cmd_retval
cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct session *s = target->s;
struct client *tc = cmdq_get_target_client(item);
struct tty *tty = &tc->tty;
const char *value, *shell, *shellcmd = NULL;
const char *style = args_get(args, 's');
const char *border_style = args_get(args, 'S');
char *cwd, *cause = NULL, **argv = NULL, *title;
int flags = 0, argc = 0;
enum box_lines lines = BOX_LINES_DEFAULT;
u_int px, py, w, h, count = args_count(args);
struct args_value *av;
struct environ *env = NULL;
struct options *o = s->curw->window->options;
struct options_entry *oe;
if (args_has(args, 'C')) {
server_client_clear_overlay(tc);
return (CMD_RETURN_NORMAL);
}
if (tc->overlay_draw != NULL)
return (CMD_RETURN_NORMAL);
h = tty->sy / 2;
if (args_has(args, 'h')) {
h = args_percentage(args, 'h', 1, tty->sy, tty->sy, &cause);
if (cause != NULL) {
cmdq_error(item, "height %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
w = tty->sx / 2;
if (args_has(args, 'w')) {
w = args_percentage(args, 'w', 1, tty->sx, tty->sx, &cause);
if (cause != NULL) {
cmdq_error(item, "width %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
if (w > tty->sx)
w = tty->sx;
if (h > tty->sy)
h = tty->sy;
if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h))
return (CMD_RETURN_NORMAL);
value = args_get(args, 'b');
if (args_has(args, 'B'))
lines = BOX_LINES_NONE;
else if (value != NULL) {
oe = options_get(o, "popup-border-lines");
lines = options_find_choice(options_table_entry(oe), value,
&cause);
if (cause != NULL) {
cmdq_error(item, "popup-border-lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
value = args_get(args, 'd');
if (value != NULL)
cwd = format_single_from_target(item, value);
else
cwd = xstrdup(server_client_get_cwd(tc, s));
if (count == 0)
shellcmd = options_get_string(s->options, "default-command");
else if (count == 1)
shellcmd = args_string(args, 0);
if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) {
shellcmd = NULL;
shell = options_get_string(s->options, "default-shell");
if (!checkshell(shell))
shell = _PATH_BSHELL;
cmd_append_argv(&argc, &argv, shell);
} else
args_to_vector(args, &argc, &argv);
if (args_has(args, 'e') >= 1) {
env = environ_create();
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(env, av->string, 0);
av = args_next_value(av);
}
}
if (args_has(args, 'T'))
title = format_single_from_target(item, args_get(args, 'T'));
else
title = xstrdup("");
if (args_has(args, 'E') > 1)
flags |= POPUP_CLOSEEXITZERO;
else if (args_has(args, 'E'))
flags |= POPUP_CLOSEEXIT;
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) {
cmd_free_argv(argc, argv);
if (env != NULL)
environ_free(env);
free(cwd);
free(title);
return (CMD_RETURN_NORMAL);
}
if (env != NULL)
environ_free(env);
free(cwd);
free(title);
cmd_free_argv(argc, argv);
return (CMD_RETURN_WAIT);
}

View File

@ -39,13 +39,13 @@ const struct cmd_entry cmd_display_message_entry = {
.name = "display-message",
.alias = "display",
.args = { "ac:Ipt:F:v", 0, 1 },
.usage = "[-aIpv] [-c target-client] [-F format] "
.args = { "aCc:d:lINpt:F:v", 0, 1, NULL },
.usage = "[-aCIlNpv] [-c target-client] [-d delay] [-F format] "
CMD_TARGET_PANE_USAGE " [message]",
.target = { 't', CMD_FIND_PANE, 0 },
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL,
.exec = cmd_display_message_exec
};
@ -60,33 +60,53 @@ cmd_display_message_each(const char *key, const char *value, void *arg)
static enum cmd_retval
cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c, *target_c;
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct window_pane *wp = item->target.wp;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct client *tc = cmdq_get_target_client(item), *c;
struct session *s = target->s;
struct winlink *wl = target->wl;
struct window_pane *wp = target->wp;
const char *template;
char *msg, *cause;
int delay = -1, flags, Nflag = args_has(args, 'N');
int Cflag = args_has(args, 'C');
struct format_tree *ft;
int flags;
u_int count = args_count(args);
struct evbuffer *evb;
if (args_has(args, 'I')) {
if (window_pane_start_input(wp, item, &cause) != 0) {
if (wp == NULL)
return (CMD_RETURN_NORMAL);
switch (window_pane_start_input(wp, item, &cause)) {
case -1:
cmdq_error(item, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
case 1:
return (CMD_RETURN_NORMAL);
case 0:
return (CMD_RETURN_WAIT);
}
}
if (args_has(args, 'F') && args->argc != 0) {
if (args_has(args, 'F') && count != 0) {
cmdq_error(item, "only one of -F or argument must be given");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'd')) {
delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause);
if (cause != NULL) {
cmdq_error(item, "delay %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
if (count != 0)
template = args_string(args, 0);
else
template = args_get(args, 'F');
if (args->argc != 0)
template = args->argv[0];
if (template == NULL)
template = DISPLAY_MESSAGE_TEMPLATE;
@ -96,28 +116,42 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
* formats too, assuming it matches the session. If it doesn't, use the
* best client for the session.
*/
c = cmd_find_client(item, args_get(args, 'c'), 1);
if (c != NULL && c->session == s)
target_c = c;
if (tc != NULL && tc->session == s)
c = tc;
else if (s != NULL)
c = cmd_find_best_client(s);
else
target_c = cmd_find_best_client(s);
if (args_has(self->args, 'v'))
c = NULL;
if (args_has(args, 'v'))
flags = FORMAT_VERBOSE;
else
flags = 0;
ft = format_create(item->client, item, FORMAT_NONE, flags);
format_defaults(ft, target_c, s, wl, wp);
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, flags);
format_defaults(ft, c, s, wl, wp);
if (args_has(args, 'a')) {
format_each(ft, cmd_display_message_each, item);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'l'))
msg = xstrdup(template);
else
msg = format_expand_time(ft, template);
if (args_has(self->args, 'p'))
if (cmdq_get_client(item) == NULL)
cmdq_error(item, "%s", msg);
else if (args_has(args, 'p'))
cmdq_print(item, "%s", msg);
else if (c != NULL)
status_message_set(c, "%s", msg);
else if (tc != NULL && (tc->flags & CLIENT_CONTROL)) {
evb = evbuffer_new();
if (evb == NULL)
fatalx("out of memory");
evbuffer_add_printf(evb, "%%message %s", msg);
server_client_print(tc, 0, evb);
evbuffer_free(evb);
} else if (tc != NULL)
status_message_set(tc, delay, 0, Nflag, Cflag, "%s", msg);
free(msg);
format_free(ft);

View File

@ -27,6 +27,8 @@
* Display panes on a client.
*/
static enum args_parse_type cmd_display_panes_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_display_panes_exec(struct cmd *,
struct cmdq_item *);
@ -34,18 +36,25 @@ const struct cmd_entry cmd_display_panes_entry = {
.name = "display-panes",
.alias = "displayp",
.args = { "bd:t:", 0, 1 },
.usage = "[-b] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]",
.args = { "bd:Nt:", 0, 1, cmd_display_panes_args_parse },
.usage = "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]",
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
.exec = cmd_display_panes_exec
};
struct cmd_display_panes_data {
struct cmdq_item *item;
char *command;
struct args_command_state *state;
};
static enum args_parse_type
cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static void
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
struct window_pane *wp)
@ -55,11 +64,11 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
struct session *s = c->session;
struct options *oo = s->options;
struct window *w = wp->window;
struct grid_cell gc;
u_int idx, px, py, i, j, xoff, yoff, sx, sy;
struct grid_cell fgc, bgc;
u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy;
int colour, active_colour;
char buf[16], *ptr;
size_t len;
char buf[16], lbuf[16], rbuf[16], *ptr;
size_t len, llen, rlen;
if (wp->xoff + wp->sx <= ctx->ox ||
wp->xoff >= ctx->ox + ctx->sx ||
@ -109,31 +118,50 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
px = sx / 2;
py = sy / 2;
if (window_pane_index(wp, &idx) != 0)
if (window_pane_index(wp, &pane) != 0)
fatalx("index not found");
len = xsnprintf(buf, sizeof buf, "%u", idx);
len = xsnprintf(buf, sizeof buf, "%u", pane);
if (sx < len)
return;
colour = options_get_number(oo, "display-panes-colour");
active_colour = options_get_number(oo, "display-panes-active-colour");
memcpy(&fgc, &grid_default_cell, sizeof fgc);
memcpy(&bgc, &grid_default_cell, sizeof bgc);
if (w->active == wp) {
fgc.fg = active_colour;
bgc.bg = active_colour;
} else {
fgc.fg = colour;
bgc.bg = colour;
}
rlen = xsnprintf(rbuf, sizeof rbuf, "%ux%u", wp->sx, wp->sy);
if (pane > 9 && pane < 35)
llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10));
else
llen = 0;
if (sx < len * 6 || sy < 5) {
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
if (sx >= len + llen + 1) {
len += llen + 1;
tty_cursor(tty, xoff + px - len / 2, yoff + py);
goto draw_text;
tty_putn(tty, buf, len, len);
tty_putn(tty, " ", 1, 1);
tty_putn(tty, lbuf, llen, llen);
} else {
tty_cursor(tty, xoff + px - len / 2, yoff + py);
tty_putn(tty, buf, len, len);
}
goto out;
}
px -= len * 3;
py -= 2;
memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp)
gc.bg = active_colour;
else
gc.bg = colour;
gc.flags |= GRID_FLAG_NOPALETTE;
tty_attributes(tty, &gc, wp);
tty_attributes(tty, &bgc, &grid_default_cell, NULL, NULL);
for (ptr = buf; *ptr != '\0'; ptr++) {
if (*ptr < '0' || *ptr > '9')
continue;
@ -149,27 +177,26 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
px += 6;
}
len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
if (sx < len || sy < 6)
return;
tty_cursor(tty, xoff + sx - len, yoff);
draw_text:
memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp)
gc.fg = active_colour;
else
gc.fg = colour;
gc.flags |= GRID_FLAG_NOPALETTE;
tty_attributes(tty, &gc, wp);
tty_puts(tty, buf);
if (sy <= 6)
goto out;
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
if (rlen != 0 && sx >= rlen) {
tty_cursor(tty, xoff + sx - rlen, yoff);
tty_putn(tty, rbuf, rlen, rlen);
}
if (llen != 0) {
tty_cursor(tty, xoff + sx / 2 + len * 3 - llen - 1,
yoff + py + 5);
tty_putn(tty, lbuf, llen, llen);
}
out:
tty_cursor(tty, 0, 0);
}
static void
cmd_display_panes_draw(struct client *c, struct screen_redraw_ctx *ctx)
cmd_display_panes_draw(struct client *c, __unused void *data,
struct screen_redraw_ctx *ctx)
{
struct window *w = c->session->curw->window;
struct window_pane *wp;
@ -183,55 +210,58 @@ cmd_display_panes_draw(struct client *c, struct screen_redraw_ctx *ctx)
}
static void
cmd_display_panes_free(struct client *c)
cmd_display_panes_free(__unused struct client *c, void *data)
{
struct cmd_display_panes_data *cdata = c->overlay_data;
struct cmd_display_panes_data *cdata = data;
if (cdata->item != NULL)
cmdq_continue(cdata->item);
free(cdata->command);
args_make_commands_free(cdata->state);
free(cdata);
}
static int
cmd_display_panes_key(struct client *c, struct key_event *event)
cmd_display_panes_key(struct client *c, void *data, struct key_event *event)
{
struct cmd_display_panes_data *cdata = c->overlay_data;
struct cmdq_item *new_item;
char *cmd, *expanded;
struct cmd_display_panes_data *cdata = data;
char *expanded, *error;
struct cmdq_item *item = cdata->item, *new_item;
struct cmd_list *cmdlist;
struct window *w = c->session->curw->window;
struct window_pane *wp;
struct cmd_parse_result *pr;
u_int index;
key_code key;
if (event->key < '0' || event->key > '9')
if (event->key >= '0' && event->key <= '9')
index = event->key - '0';
else if ((event->key & KEYC_MASK_MODIFIERS) == 0) {
key = (event->key & KEYC_MASK_KEY);
if (key >= 'a' && key <= 'z')
index = 10 + (key - 'a');
else
return (-1);
} else
return (-1);
wp = window_pane_at_index(w, event->key - '0');
wp = window_pane_at_index(w, index);
if (wp == NULL)
return (1);
window_unzoom(w);
window_unzoom(w, 1);
xasprintf(&expanded, "%%%u", wp->id);
cmd = cmd_template_replace(cdata->command, expanded, 1);
pr = cmd_parse_from_string(cmd, NULL);
switch (pr->status) {
case CMD_PARSE_EMPTY:
new_item = NULL;
break;
case CMD_PARSE_ERROR:
new_item = cmdq_get_error(pr->error);
free(pr->error);
cmdlist = args_make_commands(cdata->state, 1, &expanded, &error);
if (cmdlist == NULL) {
cmdq_append(c, cmdq_get_error(error));
free(error);
} else if (item == NULL) {
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
break;
case CMD_PARSE_SUCCESS:
new_item = cmdq_get_command(pr->cmdlist, NULL, NULL, 0);
cmd_list_free(pr->cmdlist);
cmdq_append(c, new_item);
break;
} else {
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
}
free(cmd);
free(expanded);
return (1);
}
@ -239,18 +269,15 @@ cmd_display_panes_key(struct client *c, struct key_event *event)
static enum cmd_retval
cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c;
struct session *s;
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct session *s = tc->session;
u_int delay;
char *cause;
struct cmd_display_panes_data *cdata;
int wait = !args_has(args, 'b');
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
s = c->session;
if (c->overlay_draw != NULL)
if (tc->overlay_draw != NULL)
return (CMD_RETURN_NORMAL);
if (args_has(args, 'd')) {
@ -263,20 +290,23 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
} else
delay = options_get_number(s->options, "display-panes-time");
cdata = xmalloc(sizeof *cdata);
if (args->argc != 0)
cdata->command = xstrdup(args->argv[0]);
else
cdata->command = xstrdup("select-pane -t '%%'");
if (args_has(args, 'b'))
cdata->item = NULL;
else
cdata = xcalloc(1, sizeof *cdata);
if (wait)
cdata->item = item;
cdata->state = args_make_commands_prepare(self, item, 0,
"select-pane -t \"%%%\"", wait, 0);
server_client_set_overlay(c, delay, cmd_display_panes_draw,
cmd_display_panes_key, cmd_display_panes_free, cdata);
if (args_has(args, 'N')) {
server_client_set_overlay(tc, delay, NULL, NULL,
cmd_display_panes_draw, NULL, cmd_display_panes_free, NULL,
cdata);
} else {
server_client_set_overlay(tc, delay, NULL, NULL,
cmd_display_panes_draw, cmd_display_panes_key,
cmd_display_panes_free, NULL, cdata);
}
if (args_has(args, 'b'))
if (!wait)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}

View File

@ -32,8 +32,8 @@ const struct cmd_entry cmd_find_window_entry = {
.name = "find-window",
.alias = "findw",
.args = { "CNrt:TZ", 1, 1 },
.usage = "[-CNrTZ] " CMD_TARGET_PANE_USAGE " match-string",
.args = { "CiNrt:TZ", 1, 1, NULL },
.usage = "[-CiNrTZ] " CMD_TARGET_PANE_USAGE " match-string",
.target = { 't', CMD_FIND_PANE, 0 },
@ -44,82 +44,73 @@ const struct cmd_entry cmd_find_window_entry = {
static enum cmd_retval
cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args, *new_args;
struct window_pane *wp = item->target.wp;
const char *s = args->argv[0];
char *filter, *argv = { NULL };
struct args *args = cmd_get_args(self), *new_args;
struct cmd_find_state *target = cmdq_get_target(item);
struct window_pane *wp = target->wp;
const char *s = args_string(args, 0), *suffix = "";
const char *star = "*";
struct args_value *filter;
int C, N, T;
C = args_has(args, 'C');
N = args_has(args, 'N');
T = args_has(args, 'T');
if (args_has(args, 'r'))
star = "";
if (args_has(args, 'r') && args_has(args, 'i'))
suffix = "/ri";
else if (args_has(args, 'r'))
suffix = "/r";
else if (args_has(args, 'i'))
suffix = "/i";
if (!C && !N && !T)
C = N = T = 1;
if (!args_has(args, 'r')) {
filter = xcalloc(1, sizeof *filter);
filter->type = ARGS_STRING;
if (C && N && T) {
xasprintf(&filter,
xasprintf(&filter->string,
"#{||:"
"#{C:%s},#{||:#{m:*%s*,#{window_name}},"
"#{m:*%s*,#{pane_title}}}}",
s, s, s);
"#{C%s:%s},#{||:#{m%s:%s%s%s,#{window_name}},"
"#{m%s:%s%s%s,#{pane_title}}}}",
suffix, s, suffix, star, s, star, suffix, star, s, star);
} else if (C && N) {
xasprintf(&filter,
"#{||:#{C:%s},#{m:*%s*,#{window_name}}}",
s, s);
xasprintf(&filter->string,
"#{||:#{C%s:%s},#{m%s:%s%s%s,#{window_name}}}",
suffix, s, suffix, star, s, star);
} else if (C && T) {
xasprintf(&filter,
"#{||:#{C:%s},#{m:*%s*,#{pane_title}}}",
s, s);
xasprintf(&filter->string,
"#{||:#{C%s:%s},#{m%s:%s%s%s,#{pane_title}}}",
suffix, s, suffix, star, s, star);
} else if (N && T) {
xasprintf(&filter,
"#{||:#{m:*%s*,#{window_name}},"
"#{m:*%s*,#{pane_title}}}",
s, s);
} else if (C)
xasprintf(&filter, "#{C:%s}", s);
else if (N)
xasprintf(&filter, "#{m:*%s*,#{window_name}}", s);
else
xasprintf(&filter, "#{m:*%s*,#{pane_title}}", s);
xasprintf(&filter->string,
"#{||:#{m%s:%s%s%s,#{window_name}},"
"#{m%s:%s%s%s,#{pane_title}}}",
suffix, star, s, star, suffix, star, s, star);
} else if (C) {
xasprintf(&filter->string,
"#{C%s:%s}",
suffix, s);
} else if (N) {
xasprintf(&filter->string,
"#{m%s:%s%s%s,#{window_name}}",
suffix, star, s, star);
} else {
if (C && N && T) {
xasprintf(&filter,
"#{||:"
"#{C/r:%s},#{||:#{m/r:%s,#{window_name}},"
"#{m/r:%s,#{pane_title}}}}",
s, s, s);
} else if (C && N) {
xasprintf(&filter,
"#{||:#{C/r:%s},#{m/r:%s,#{window_name}}}",
s, s);
} else if (C && T) {
xasprintf(&filter,
"#{||:#{C/r:%s},#{m/r:%s,#{pane_title}}}",
s, s);
} else if (N && T) {
xasprintf(&filter,
"#{||:#{m/r:%s,#{window_name}},"
"#{m/r:%s,#{pane_title}}}",
s, s);
} else if (C)
xasprintf(&filter, "#{C/r:%s}", s);
else if (N)
xasprintf(&filter, "#{m/r:%s,#{window_name}}", s);
else
xasprintf(&filter, "#{m/r:%s,#{pane_title}}", s);
xasprintf(&filter->string,
"#{m%s:%s%s%s,#{pane_title}}",
suffix, star, s, star);
}
new_args = args_parse("", 1, &argv);
new_args = args_create();
if (args_has(args, 'Z'))
args_set(new_args, 'Z', NULL);
args_set(new_args, 'f', filter);
window_pane_set_mode(wp, &window_tree_mode, &item->target, new_args);
args_set(new_args, 'Z', NULL, 0);
args_set(new_args, 'f', filter, 0);
window_pane_set_mode(wp, NULL, &window_tree_mode, target, new_args);
args_free(new_args);
free(filter);
return (CMD_RETURN_NORMAL);
}

View File

@ -582,7 +582,7 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane)
/* Try special characters. */
if (strcmp(pane, "!") == 0) {
fs->wp = fs->w->last;
fs->wp = TAILQ_FIRST(&fs->w->last_panes);
if (fs->wp == NULL)
return (-1);
return (0);
@ -866,9 +866,20 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
/* If this is an attached client, all done. */
if (c->session != NULL) {
cmd_find_clear_state(fs, flags);
fs->wp = server_client_get_pane(c);
if (fs->wp == NULL) {
cmd_find_from_session(fs, c->session, flags);
return (0);
}
fs->s = c->session;
fs->wl = fs->s->curw;
fs->w = fs->wl->window;
cmd_find_log_state(__func__, fs);
return (0);
}
cmd_find_clear_state(fs, flags);
/*
@ -960,10 +971,11 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED)) {
fs->current = &marked_pane;
log_debug("%s: current is marked pane", __func__);
} else if (cmd_find_valid_state(&item->shared->current)) {
fs->current = &item->shared->current;
} else if (cmd_find_valid_state(cmdq_get_current(item))) {
fs->current = cmdq_get_current(item);
log_debug("%s: current is from queue", __func__);
} else if (cmd_find_from_client(&current, item->client, flags) == 0) {
} else if (cmd_find_from_client(&current, cmdq_get_client(item),
flags) == 0) {
fs->current = &current;
log_debug("%s: current is from client", __func__);
} else {
@ -980,7 +992,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
/* Mouse target is a plain = or {mouse}. */
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
m = &item->shared->mouse;
m = &cmdq_get_event(item)->m;
switch (type) {
case CMD_FIND_PANE:
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
@ -1230,29 +1242,31 @@ no_pane:
static struct client *
cmd_find_current_client(struct cmdq_item *item, int quiet)
{
struct client *c;
struct client *c = NULL, *found;
struct session *s;
struct window_pane *wp;
struct cmd_find_state fs;
if (item->client != NULL && item->client->session != NULL)
return (item->client);
if (item != NULL)
c = cmdq_get_client(item);
if (c != NULL && c->session != NULL)
return (c);
c = NULL;
if ((wp = cmd_find_inside_pane(item->client)) != NULL) {
found = NULL;
if (c != NULL && (wp = cmd_find_inside_pane(c)) != NULL) {
cmd_find_clear_state(&fs, CMD_FIND_QUIET);
fs.w = wp->window;
if (cmd_find_best_session_with_window(&fs) == 0)
c = cmd_find_best_client(fs.s);
found = cmd_find_best_client(fs.s);
} else {
s = cmd_find_best_session(NULL, 0, CMD_FIND_QUIET);
if (s != NULL)
c = cmd_find_best_client(s);
found = cmd_find_best_client(s);
}
if (c == NULL && !quiet)
if (found == NULL && item != NULL && !quiet)
cmdq_error(item, "no current client");
log_debug("%s: no target, return %p", __func__, c);
return (c);
log_debug("%s: no target, return %p", __func__, found);
return (found);
}
/* Find the target client or report an error and return NULL. */

View File

@ -20,6 +20,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@ -29,7 +30,10 @@
* Executes a tmux command if a shell command returns true or false.
*/
static enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmdq_item *);
static enum args_parse_type cmd_if_shell_args_parse(struct args *, u_int,
char **);
static enum cmd_retval cmd_if_shell_exec(struct cmd *,
struct cmdq_item *);
static void cmd_if_shell_callback(struct job *);
static void cmd_if_shell_free(void *);
@ -38,7 +42,7 @@ const struct cmd_entry cmd_if_shell_entry = {
.name = "if-shell",
.alias = "if",
.args = { "bFt:", 2, 3 },
.args = { "bFt:", 2, 3, cmd_if_shell_args_parse },
.usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command "
"[command]",
@ -49,102 +53,75 @@ const struct cmd_entry cmd_if_shell_entry = {
};
struct cmd_if_shell_data {
struct cmd_parse_input input;
char *cmd_if;
char *cmd_else;
struct args_command_state *cmd_if;
struct args_command_state *cmd_else;
struct client *client;
struct cmdq_item *item;
struct mouse_event mouse;
};
static enum args_parse_type
cmd_if_shell_args_parse(__unused struct args *args, u_int idx,
__unused char **cause)
{
if (idx == 1 || idx == 2)
return (ARGS_PARSE_COMMANDS_OR_STRING);
return (ARGS_PARSE_STRING);
}
static enum cmd_retval
cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct mouse_event *m = &item->shared->mouse;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct cmd_if_shell_data *cdata;
char *shellcmd, *cmd;
struct cmdq_item *new_item;
struct cmd_find_state *fs = &item->target;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = fs->s;
struct winlink *wl = fs->wl;
struct window_pane *wp = fs->wp;
struct cmd_parse_input pi;
struct cmd_parse_result *pr;
char *shellcmd;
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct cmd_list *cmdlist;
u_int count = args_count(args);
int wait = !args_has(args, 'b');
shellcmd = format_single(item, args->argv[0], c, s, wl, wp);
shellcmd = format_single_from_target(item, args_string(args, 0));
if (args_has(args, 'F')) {
if (*shellcmd != '0' && *shellcmd != '\0')
cmd = args->argv[1];
else if (args->argc == 3)
cmd = args->argv[2];
else
cmd = NULL;
cmdlist = args_make_commands_now(self, item, 1, 0);
else if (count == 3)
cmdlist = args_make_commands_now(self, item, 2, 0);
else {
free(shellcmd);
if (cmd == NULL)
return (CMD_RETURN_NORMAL);
memset(&pi, 0, sizeof pi);
if (self->file != NULL)
pi.file = self->file;
pi.line = self->line;
pi.item = item;
pi.c = c;
cmd_find_copy_state(&pi.fs, fs);
pr = cmd_parse_from_string(cmd, &pi);
switch (pr->status) {
case CMD_PARSE_EMPTY:
break;
case CMD_PARSE_ERROR:
cmdq_error(item, "%s", pr->error);
free(pr->error);
return (CMD_RETURN_ERROR);
case CMD_PARSE_SUCCESS:
new_item = cmdq_get_command(pr->cmdlist, fs, m, 0);
cmdq_insert_after(item, new_item);
cmd_list_free(pr->cmdlist);
break;
}
free(shellcmd);
if (cmdlist == NULL)
return (CMD_RETURN_ERROR);
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
return (CMD_RETURN_NORMAL);
}
cdata = xcalloc(1, sizeof *cdata);
cdata->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3)
cdata->cmd_else = xstrdup(args->argv[2]);
else
cdata->cmd_else = NULL;
memcpy(&cdata->mouse, m, sizeof cdata->mouse);
cdata->cmd_if = args_make_commands_prepare(self, item, 1, NULL, wait,
0);
if (count == 3) {
cdata->cmd_else = args_make_commands_prepare(self, item, 2,
NULL, wait, 0);
}
if (!args_has(args, 'b'))
cdata->client = item->client;
else
cdata->client = c;
if (wait) {
cdata->client = cmdq_get_client(item);
cdata->item = item;
} else
cdata->client = tc;
if (cdata->client != NULL)
cdata->client->references++;
if (!args_has(args, 'b'))
cdata->item = item;
else
cdata->item = NULL;
memset(&cdata->input, 0, sizeof cdata->input);
if (self->file != NULL)
cdata->input.file = xstrdup(self->file);
cdata->input.line = self->line;
cdata->input.item = cdata->item;
cdata->input.c = c;
if (cdata->input.c != NULL)
cdata->input.c->references++;
cmd_find_copy_state(&cdata->input.fs, fs);
if (job_run(shellcmd, s, server_client_get_cwd(item->client, s), NULL,
cmd_if_shell_callback, cmd_if_shell_free, cdata, 0) == NULL) {
if (job_run(shellcmd, 0, NULL, NULL, s,
server_client_get_cwd(cmdq_get_client(item), s), NULL,
cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1,
-1) == NULL) {
cmdq_error(item, "failed to run command: %s", shellcmd);
free(shellcmd);
free(cdata);
@ -152,7 +129,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
}
free(shellcmd);
if (args_has(args, 'b'))
if (!wait)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
@ -162,39 +139,34 @@ cmd_if_shell_callback(struct job *job)
{
struct cmd_if_shell_data *cdata = job_get_data(job);
struct client *c = cdata->client;
struct mouse_event *m = &cdata->mouse;
struct cmdq_item *new_item = NULL;
char *cmd;
struct cmdq_item *item = cdata->item, *new_item;
struct args_command_state *state;
struct cmd_list *cmdlist;
char *error;
int status;
struct cmd_parse_result *pr;
status = job_get_status(job);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
cmd = cdata->cmd_else;
state = cdata->cmd_else;
else
cmd = cdata->cmd_if;
if (cmd == NULL)
state = cdata->cmd_if;
if (state == NULL)
goto out;
pr = cmd_parse_from_string(cmd, &cdata->input);
switch (pr->status) {
case CMD_PARSE_EMPTY:
break;
case CMD_PARSE_ERROR:
if (cdata->item != NULL)
cmdq_error(cdata->item, "%s", pr->error);
free(pr->error);
break;
case CMD_PARSE_SUCCESS:
new_item = cmdq_get_command(pr->cmdlist, NULL, m, 0);
cmd_list_free(pr->cmdlist);
break;
}
if (new_item != NULL) {
if (cdata->item == NULL)
cmdlist = args_make_commands(state, 0, NULL, &error);
if (cmdlist == NULL) {
if (cdata->item == NULL) {
*error = toupper((u_char)*error);
status_message_set(c, -1, 1, 0, 0, "%s", error);
} else
cmdq_error(cdata->item, "%s", error);
free(error);
} else if (item == NULL) {
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
else
cmdq_insert_after(cdata->item, new_item);
} else {
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
}
out:
@ -210,12 +182,9 @@ cmd_if_shell_free(void *data)
if (cdata->client != NULL)
server_client_unref(cdata->client);
free(cdata->cmd_else);
free(cdata->cmd_if);
if (cdata->input.c != NULL)
server_client_unref(cdata->input.c);
free((void *)cdata->input.file);
if (cdata->cmd_else != NULL)
args_make_commands_free(cdata->cmd_else);
args_make_commands_free(cdata->cmd_if);
free(cdata);
}

View File

@ -35,7 +35,7 @@ const struct cmd_entry cmd_join_pane_entry = {
.name = "join-pane",
.alias = "joinp",
.args = { "bdfhvp:l:s:t:", 0, 0 },
.args = { "bdfhvp:l:s:t:", 0, 0, NULL },
.usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE,
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
@ -49,8 +49,8 @@ const struct cmd_entry cmd_move_pane_entry = {
.name = "move-pane",
.alias = "movep",
.args = { "bdhvp:l:s:t:", 0, 0 },
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
.args = { "bdfhvp:l:s:t:", 0, 0, NULL },
.usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE,
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
.target = { 't', CMD_FIND_PANE, 0 },
@ -62,42 +62,34 @@ const struct cmd_entry cmd_move_pane_entry = {
static enum cmd_retval
cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct cmd_find_state *current = &item->shared->current;
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 cmd_find_state *source = cmdq_get_source(item);
struct session *dst_s;
struct winlink *src_wl, *dst_wl;
struct window *src_w, *dst_w;
struct window_pane *src_wp, *dst_wp;
char *cause, *copy;
const char *errstr, *p;
size_t plen;
int size, percentage, dst_idx, not_same_window;
char *cause = NULL;
int size, dst_idx;
int flags;
enum layout_type type;
struct layout_cell *lc;
u_int curval = 0;
if (self->entry == &cmd_join_pane_entry)
not_same_window = 1;
else
not_same_window = 0;
dst_s = item->target.s;
dst_wl = item->target.wl;
dst_wp = item->target.wp;
dst_s = target->s;
dst_wl = target->wl;
dst_wp = target->wp;
dst_w = dst_wl->window;
dst_idx = dst_wl->idx;
server_unzoom_window(dst_w);
src_wl = item->source.wl;
src_wp = item->source.wp;
src_wl = source->wl;
src_wp = source->wp;
src_w = src_wl->window;
server_unzoom_window(src_w);
if (not_same_window && src_w == dst_w) {
cmdq_error(item, "can't join a pane to its own window");
return (CMD_RETURN_ERROR);
}
if (!not_same_window && src_wp == dst_wp) {
if (src_wp == dst_wp) {
cmdq_error(item, "source and target panes must be different");
return (CMD_RETURN_ERROR);
}
@ -106,42 +98,36 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
size = -1;
if ((p = args_get(args, 'l')) != NULL) {
plen = strlen(p);
if (p[plen - 1] == '%') {
copy = xstrdup(p);
copy[plen - 1] = '\0';
percentage = strtonum(copy, 0, INT_MAX, &errstr);
free(copy);
if (errstr != NULL) {
cmdq_error(item, "percentage %s", errstr);
return (CMD_RETURN_ERROR);
}
/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
size = (dst_wp->sy * percentage) / 100;
curval = dst_w->sy;
else
size = (dst_wp->sx * percentage) / 100;
curval = dst_w->sx;
} else {
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (type == LAYOUT_TOPBOTTOM)
curval = dst_wp->sy;
else
curval = dst_wp->sx;
}
}
size = -1;
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, &cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'l', 0, 100, item,
&cause);
if (cause == NULL)
size = curval * size / 100;
}
if (cause != NULL) {
cmdq_error(item, "size %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
} else if (args_has(args, 'p')) {
percentage = args_strtonum(args, 'p', 0, 100, &cause);
if (cause != NULL) {
cmdq_error(item, "percentage %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (type == LAYOUT_TOPBOTTOM)
size = (dst_wp->sy * percentage) / 100;
else
size = (dst_wp->sx * percentage) / 100;
}
flags = 0;
if (args_has(args, 'b'))
@ -157,14 +143,19 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
layout_close_pane(src_wp);
server_client_remove_pane(src_wp);
window_lost_pane(src_w, src_wp);
TAILQ_REMOVE(&src_w->panes, src_wp, entry);
src_wp->window = dst_w;
options_set_parent(src_wp->options, dst_w->options);
src_wp->flags |= PANE_STYLECHANGED;
src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
if (flags & SPAWN_BEFORE)
TAILQ_INSERT_BEFORE(dst_wp, src_wp, entry);
else
TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
layout_assign_pane(lc, src_wp);
layout_assign_pane(lc, src_wp, 0);
colour_palette_from_option(&src_wp->palette, src_wp->options);
recalculate_sizes();
@ -180,7 +171,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
server_status_session(dst_s);
if (window_count_panes(src_w) == 0)
server_kill_window(src_w);
server_kill_window(src_w, 1);
else
notify_window("window-layout-changed", src_w);
notify_window("window-layout-changed", dst_w);

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_kill_pane_entry = {
.name = "kill-pane",
.alias = "killp",
.args = { "at:", 0, 0 },
.args = { "at:", 0, 0, NULL },
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -44,14 +44,17 @@ const struct cmd_entry cmd_kill_pane_entry = {
static enum cmd_retval
cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct winlink *wl = item->target.wl;
struct window_pane *loopwp, *tmpwp, *wp = item->target.wp;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct winlink *wl = target->wl;
struct window_pane *loopwp, *tmpwp, *wp = target->wp;
if (args_has(self->args, 'a')) {
if (args_has(args, 'a')) {
server_unzoom_window(wl->window);
TAILQ_FOREACH_SAFE(loopwp, &wl->window->panes, entry, tmpwp) {
if (loopwp == wp)
continue;
server_client_remove_pane(loopwp);
layout_close_pane(loopwp);
window_remove_pane(wl->window, loopwp);
}

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_kill_server_entry = {
.name = "kill-server",
.alias = NULL,
.args = { "", 0, 0 },
.args = { "", 0, 0, NULL },
.usage = "",
.flags = 0,
@ -44,7 +44,7 @@ const struct cmd_entry cmd_start_server_entry = {
.name = "start-server",
.alias = "start",
.args = { "", 0, 0 },
.args = { "", 0, 0, NULL },
.usage = "",
.flags = CMD_STARTSERVER,
@ -54,7 +54,7 @@ const struct cmd_entry cmd_start_server_entry = {
static enum cmd_retval
cmd_kill_server_exec(struct cmd *self, __unused struct cmdq_item *item)
{
if (self->entry == &cmd_kill_server_entry)
if (cmd_get_entry(self) == &cmd_kill_server_entry)
kill(getpid(), SIGTERM);
return (CMD_RETURN_NORMAL);

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_kill_session_entry = {
.name = "kill-session",
.alias = NULL,
.args = { "aCt:", 0, 0 },
.args = { "aCt:", 0, 0, NULL },
.usage = "[-aC] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -45,12 +45,11 @@ const struct cmd_entry cmd_kill_session_entry = {
static enum cmd_retval
cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct session *s, *sloop, *stmp;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct session *s = target->s, *sloop, *stmp;
struct winlink *wl;
s = item->target.s;
if (args_has(args, 'C')) {
RB_FOREACH(wl, winlinks, &s->windows) {
wl->window->flags &= ~WINDOW_ALERTFLAGS;

View File

@ -30,7 +30,7 @@ const struct cmd_entry cmd_kill_window_entry = {
.name = "kill-window",
.alias = "killw",
.args = { "at:", 0, 0 },
.args = { "at:", 0, 0, NULL },
.usage = "[-a] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -43,7 +43,7 @@ const struct cmd_entry cmd_unlink_window_entry = {
.name = "unlink-window",
.alias = "unlinkw",
.args = { "kt:", 0, 0 },
.args = { "kt:", 0, 0, NULL },
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -55,27 +55,56 @@ const struct cmd_entry cmd_unlink_window_entry = {
static enum cmd_retval
cmd_kill_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct winlink *wl = item->target.wl, *wl2, *wl3;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct winlink *wl = target->wl, *loop;
struct window *w = wl->window;
struct session *s = item->target.s;
struct session *s = target->s;
u_int found;
if (self->entry == &cmd_unlink_window_entry) {
if (!args_has(self->args, 'k') && !session_is_linked(s, w)) {
if (cmd_get_entry(self) == &cmd_unlink_window_entry) {
if (!args_has(args, 'k') && !session_is_linked(s, w)) {
cmdq_error(item, "window only linked to one session");
return (CMD_RETURN_ERROR);
}
server_unlink_window(s, wl);
} else {
if (args_has(args, 'a')) {
RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
if (wl != wl2)
server_kill_window(wl2->window);
}
} else
server_kill_window(wl->window);
}
recalculate_sizes();
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'a')) {
if (RB_PREV(winlinks, &s->windows, wl) == NULL &&
RB_NEXT(winlinks, &s->windows, wl) == NULL)
return (CMD_RETURN_NORMAL);
/* Kill all windows except the current one. */
do {
found = 0;
RB_FOREACH(loop, winlinks, &s->windows) {
if (loop->window != wl->window) {
server_kill_window(loop->window, 0);
found++;
break;
}
}
} while (found != 0);
/*
* If the current window appears in the session more than once,
* kill it as well.
*/
found = 0;
RB_FOREACH(loop, winlinks, &s->windows) {
if (loop->window == wl->window)
found++;
}
if (found > 1)
server_kill_window(wl->window, 0);
server_renumber_all();
return (CMD_RETURN_NORMAL);
}
server_kill_window(wl->window, 1);
return (CMD_RETURN_NORMAL);
}

View File

@ -36,8 +36,8 @@ const struct cmd_entry cmd_list_buffers_entry = {
.name = "list-buffers",
.alias = "lsb",
.args = { "F:", 0, 0 },
.usage = "[-F format]",
.args = { "F:f:", 0, 0, NULL },
.usage = "[-F format] [-f filter]",
.flags = CMD_AFTERHOOK,
.exec = cmd_list_buffers_exec
@ -46,23 +46,33 @@ const struct cmd_entry cmd_list_buffers_entry = {
static enum cmd_retval
cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct paste_buffer *pb;
struct format_tree *ft;
char *line;
const char *template;
const char *template, *filter;
char *line, *expanded;
int flag;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_BUFFERS_TEMPLATE;
filter = args_get(args, 'f');
pb = NULL;
while ((pb = paste_walk(pb)) != NULL) {
ft = format_create(item->client, item, FORMAT_NONE, 0);
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
format_defaults_paste_buffer(ft, pb);
if (filter != NULL) {
expanded = format_expand(ft, filter);
flag = format_true(expanded);
free(expanded);
} else
flag = 1;
if (flag) {
line = format_expand(ft, template);
cmdq_print(item, "%s", line);
free(line);
}
format_free(ft);
}

View File

@ -31,7 +31,9 @@
#define LIST_CLIENTS_TEMPLATE \
"#{client_name}: #{session_name} " \
"[#{client_width}x#{client_height} #{client_termname}] " \
"#{?client_utf8, (utf8),} #{?client_readonly, (ro),}"
"#{?#{!=:#{client_uid},#{uid}}," \
"[user #{?client_user,#{client_user},#{client_uid},}] ,}" \
"#{?client_flags,(,}#{client_flags}#{?client_flags,),}"
static enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmdq_item *);
@ -39,8 +41,8 @@ const struct cmd_entry cmd_list_clients_entry = {
.name = "list-clients",
.alias = "lsc",
.args = { "F:t:", 0, 0 },
.usage = "[-F format] " CMD_TARGET_SESSION_USAGE,
.args = { "F:f:t:", 0, 0, NULL },
.usage = "[-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -51,34 +53,45 @@ const struct cmd_entry cmd_list_clients_entry = {
static enum cmd_retval
cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct client *c;
struct session *s;
struct format_tree *ft;
const char *template;
const char *template, *filter;
u_int idx;
char *line;
char *line, *expanded;
int flag;
if (args_has(args, 't'))
s = item->target.s;
s = target->s;
else
s = NULL;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_CLIENTS_TEMPLATE;
filter = args_get(args, 'f');
idx = 0;
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == NULL || (s != NULL && s != c->session))
continue;
ft = format_create(item->client, item, FORMAT_NONE, 0);
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
format_add(ft, "line", "%u", idx);
format_defaults(ft, c, NULL, NULL, NULL);
if (filter != NULL) {
expanded = format_expand(ft, filter);
flag = format_true(expanded);
free(expanded);
} else
flag = 1;
if (flag) {
line = format_expand(ft, template);
cmdq_print(item, "%s", line);
free(line);
}
format_free(ft);

View File

@ -36,7 +36,7 @@ const struct cmd_entry cmd_list_keys_entry = {
.name = "list-keys",
.alias = "lsk",
.args = { "1aNP:T:", 0, 1 },
.args = { "1aNP:T:", 0, 1, NULL },
.usage = "[-1aN] [-P prefix-string] [-T key-table] [key]",
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
@ -47,7 +47,7 @@ const struct cmd_entry cmd_list_commands_entry = {
.name = "list-commands",
.alias = "lscm",
.args = { "F:", 0, 1 },
.args = { "F:", 0, 1, NULL },
.usage = "[-F format] [command]",
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
@ -68,11 +68,12 @@ cmd_list_keys_get_width(const char *tablename, key_code only)
while (bd != NULL) {
if ((only != KEYC_UNKNOWN && bd->key != only) ||
KEYC_IS_MOUSE(bd->key) ||
bd->note == NULL) {
bd->note == NULL ||
*bd->note == '\0') {
bd = key_bindings_next(table, bd);
continue;
}
width = utf8_cstrwidth(key_string_lookup_key(bd->key));
width = utf8_cstrwidth(key_string_lookup_key(bd->key, 0));
if (width > keywidth)
keywidth = width;
@ -85,7 +86,7 @@ static int
cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
const char *tablename, u_int keywidth, key_code only, const char *prefix)
{
struct client *c = cmd_find_client(item, NULL, 1);
struct client *tc = cmdq_get_target_client(item);
struct key_table *table;
struct key_binding *bd;
const char *key;
@ -99,21 +100,23 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
while (bd != NULL) {
if ((only != KEYC_UNKNOWN && bd->key != only) ||
KEYC_IS_MOUSE(bd->key) ||
(bd->note == NULL && !args_has(args, 'a'))) {
((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);
key = key_string_lookup_key(bd->key, 0);
if (bd->note == NULL)
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') && c != NULL)
status_message_set(c, "%s%s%s", prefix, tmp, note);
else
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);
@ -133,7 +136,7 @@ cmd_list_keys_get_prefix(struct args *args, key_code *prefix)
*prefix = options_get_number(global_s_options, "prefix");
if (!args_has(args, 'P')) {
if (*prefix != KEYC_NONE)
xasprintf(&s, "%s ", key_string_lookup_key(*prefix));
xasprintf(&s, "%s ", key_string_lookup_key(*prefix, 0));
else
s = xstrdup("");
} else
@ -144,24 +147,26 @@ cmd_list_keys_get_prefix(struct args *args, key_code *prefix)
static enum cmd_retval
cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct key_table *table;
struct key_binding *bd;
const char *tablename, *r;
const char *tablename, *r, *keystr;
char *key, *cp, *tmp, *start, *empty;
key_code prefix, only = KEYC_UNKNOWN;
int repeat, width, tablewidth, keywidth, found = 0;
size_t tmpsize, tmpused, cplen;
if (self->entry == &cmd_list_commands_entry)
if (cmd_get_entry(self) == &cmd_list_commands_entry)
return (cmd_list_keys_commands(self, item));
if (args->argc != 0) {
only = key_string_lookup_string(args->argv[0]);
if ((keystr = args_string(args, 0)) != NULL) {
only = key_string_lookup_string(keystr);
if (only == KEYC_UNKNOWN) {
cmdq_error(item, "invalid key: %s", args->argv[0]);
cmdq_error(item, "invalid key: %s", keystr);
return (CMD_RETURN_ERROR);
}
only &= (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS);
}
tablename = args_get(args, 'T');
@ -219,7 +224,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
bd = key_bindings_next(table, bd);
continue;
}
key = args_escape(key_string_lookup_key(bd->key));
key = args_escape(key_string_lookup_key(bd->key, 0));
if (bd->flags & KEY_BINDING_REPEAT)
repeat = 1;
@ -253,7 +258,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
continue;
}
found = 1;
key = args_escape(key_string_lookup_key(bd->key));
key = args_escape(key_string_lookup_key(bd->key, 0));
if (!repeat)
r = "";
@ -269,7 +274,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
tmpsize *= 2;
tmp = xrealloc(tmp, tmpsize);
}
tmpused = strlcat(tmp, cp, tmpsize);
strlcat(tmp, cp, tmpsize);
tmpused = strlcat(tmp, " ", tmpsize);
free(cp);
@ -279,7 +284,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
tmpsize *= 2;
tmp = xrealloc(tmp, tmpsize);
}
tmpused = strlcat(tmp, cp, tmpsize);
strlcat(tmp, cp, tmpsize);
tmpused = strlcat(tmp, " ", tmpsize);
free(cp);
@ -292,9 +297,15 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
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);
@ -304,42 +315,19 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
out:
if (only != KEYC_UNKNOWN && !found) {
cmdq_error(item, "unknown key: %s", args->argv[0]);
cmdq_error(item, "unknown key: %s", args_string(args, 0));
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
static enum cmd_retval
cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
static void
cmd_list_single_command(const struct cmd_entry *entry, struct format_tree *ft,
const char *template, struct cmdq_item *item)
{
struct args *args = self->args;
const struct cmd_entry **entryp;
const struct cmd_entry *entry;
struct format_tree *ft;
const char *template, *s, *command = NULL;
const char *s;
char *line;
if (args->argc != 0)
command = args->argv[0];
if ((template = args_get(args, 'F')) == NULL) {
template = "#{command_list_name}"
"#{?command_list_alias, (#{command_list_alias}),} "
"#{command_list_usage}";
}
ft = format_create(item->client, item, FORMAT_NONE, 0);
format_defaults(ft, NULL, NULL, NULL, NULL);
for (entryp = cmd_table; *entryp != NULL; entryp++) {
entry = *entryp;
if (command != NULL &&
(strcmp(entry->name, command) != 0 &&
(entry->alias == NULL ||
strcmp(entry->alias, command) != 0)))
continue;
format_add(ft, "command_list_name", "%s", entry->name);
if (entry->alias != NULL)
s = entry->alias;
@ -358,6 +346,41 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
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);
}
}
format_free(ft);
return (CMD_RETURN_NORMAL);
}

View File

@ -38,8 +38,8 @@ const struct cmd_entry cmd_list_panes_entry = {
.name = "list-panes",
.alias = "lsp",
.args = { "asF:t:", 0, 0 },
.usage = "[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
.args = { "asF:f:t:", 0, 0, NULL },
.usage = "[-as] [-F format] [-f filter] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -50,9 +50,10 @@ const struct cmd_entry cmd_list_panes_entry = {
static enum cmd_retval
cmd_list_panes_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct session *s = target->s;
struct winlink *wl = target->wl;
if (args_has(args, 'a'))
cmd_list_panes_server(self, item);
@ -87,12 +88,13 @@ static void
cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
struct cmdq_item *item, int type)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct window_pane *wp;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
const char *template, *filter;
char *line, *expanded;
int flag;
template = args_get(args, 'F');
if (template == NULL) {
@ -120,16 +122,25 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
break;
}
}
filter = args_get(args, 'f');
n = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
ft = format_create(item->client, item, FORMAT_NONE, 0);
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
format_add(ft, "line", "%u", n);
format_defaults(ft, NULL, s, wl, wp);
if (filter != NULL) {
expanded = format_expand(ft, filter);
flag = format_true(expanded);
free(expanded);
} else
flag = 1;
if (flag) {
line = format_expand(ft, template);
cmdq_print(item, "%s", line);
free(line);
}
format_free(ft);
n++;

View File

@ -42,8 +42,8 @@ const struct cmd_entry cmd_list_sessions_entry = {
.name = "list-sessions",
.alias = "ls",
.args = { "F:", 0, 0 },
.usage = "[-F format]",
.args = { "F:f:", 0, 0, NULL },
.usage = "[-F format] [-f filter]",
.flags = CMD_AFTERHOOK,
.exec = cmd_list_sessions_exec
@ -52,25 +52,35 @@ const struct cmd_entry cmd_list_sessions_entry = {
static enum cmd_retval
cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct session *s;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
const char *template, *filter;
char *line, *expanded;
int flag;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_SESSIONS_TEMPLATE;
filter = args_get(args, 'f');
n = 0;
RB_FOREACH(s, sessions, &sessions) {
ft = format_create(item->client, item, FORMAT_NONE, 0);
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
format_add(ft, "line", "%u", n);
format_defaults(ft, NULL, s, NULL, NULL);
if (filter != NULL) {
expanded = format_expand(ft, filter);
flag = format_true(expanded);
free(expanded);
} else
flag = 1;
if (flag) {
line = format_expand(ft, template);
cmdq_print(item, "%s", line);
free(line);
}
format_free(ft);
n++;

View File

@ -28,14 +28,14 @@
*/
#define LIST_WINDOWS_TEMPLATE \
"#{window_index}: #{window_name}#{window_flags} " \
"#{window_index}: #{window_name}#{window_raw_flags} " \
"(#{window_panes} panes) " \
"[#{window_width}x#{window_height}] " \
"[layout #{window_layout}] #{window_id}" \
"#{?window_active, (active),}";
#define LIST_WINDOWS_WITH_SESSION_TEMPLATE \
"#{session_name}:" \
"#{window_index}: #{window_name}#{window_flags} " \
"#{window_index}: #{window_name}#{window_raw_flags} " \
"(#{window_panes} panes) " \
"[#{window_width}x#{window_height}] "
@ -49,8 +49,8 @@ const struct cmd_entry cmd_list_windows_entry = {
.name = "list-windows",
.alias = "lsw",
.args = { "F:at:", 0, 0 },
.usage = "[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
.args = { "F:f:at:", 0, 0, NULL },
.usage = "[-a] [-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -61,12 +61,13 @@ const struct cmd_entry cmd_list_windows_entry = {
static enum cmd_retval
cmd_list_windows_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
if (args_has(args, 'a'))
cmd_list_windows_server(self, item);
else
cmd_list_windows_session(self, item->target.s, item, 0);
cmd_list_windows_session(self, target->s, item, 0);
return (CMD_RETURN_NORMAL);
}
@ -84,12 +85,13 @@ static void
cmd_list_windows_session(struct cmd *self, struct session *s,
struct cmdq_item *item, int type)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct winlink *wl;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
const char *template, *filter;
char *line, *expanded;
int flag;
template = args_get(args, 'F');
if (template == NULL) {
@ -102,16 +104,25 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
break;
}
}
filter = args_get(args, 'f');
n = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
ft = format_create(item->client, item, FORMAT_NONE, 0);
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
format_add(ft, "line", "%u", n);
format_defaults(ft, NULL, s, wl, NULL);
if (filter != NULL) {
expanded = format_expand(ft, filter);
flag = format_true(expanded);
free(expanded);
} else
flag = 1;
if (flag) {
line = format_expand(ft, template);
cmdq_print(item, "%s", line);
free(line);
}
format_free(ft);
n++;

View File

@ -37,14 +37,15 @@ const struct cmd_entry cmd_load_buffer_entry = {
.name = "load-buffer",
.alias = "loadb",
.args = { "b:", 1, 1 },
.usage = CMD_BUFFER_USAGE " path",
.args = { "b:t:w", 1, 1, NULL },
.usage = CMD_BUFFER_USAGE " " CMD_TARGET_CLIENT_USAGE " path",
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG|CMD_CLIENT_CANFAIL,
.exec = cmd_load_buffer_exec
};
struct cmd_load_buffer_data {
struct client *client;
struct cmdq_item *item;
char *name;
};
@ -54,6 +55,7 @@ cmd_load_buffer_done(__unused struct client *c, const char *path, int error,
int closed, struct evbuffer *buffer, void *data)
{
struct cmd_load_buffer_data *cdata = data;
struct client *tc = cdata->client;
struct cmdq_item *item = cdata->item;
void *bdata = EVBUFFER_DATA(buffer);
size_t bsize = EVBUFFER_LENGTH(buffer);
@ -72,7 +74,12 @@ cmd_load_buffer_done(__unused struct client *c, const char *path, int error,
cmdq_error(item, "%s", cause);
free(cause);
free(copy);
}
} else if (tc != NULL &&
tc->session != NULL &&
(~tc->flags & CLIENT_DEAD))
tty_set_selection(&tc->tty, "", copy, bsize);
if (tc != NULL)
server_client_unref(tc);
}
cmdq_continue(item);
@ -83,24 +90,23 @@ cmd_load_buffer_done(__unused struct client *c, const char *path, int error,
static enum cmd_retval
cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct cmd_load_buffer_data *cdata;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct window_pane *wp = item->target.wp;
const char *bufname = args_get(args, 'b');
char *path;
cdata = xmalloc(sizeof *cdata);
cdata = xcalloc(1, sizeof *cdata);
cdata->item = item;
if (bufname != NULL)
cdata->name = xstrdup(bufname);
else
cdata->name = NULL;
if (args_has(args, 'w') && tc != NULL) {
cdata->client = tc;
cdata->client->references++;
}
path = format_single(item, args->argv[0], c, s, wl, wp);
file_read(item->client, path, cmd_load_buffer_done, cdata);
path = format_single_from_target(item, args_string(args, 0));
file_read(cmdq_get_client(item), path, cmd_load_buffer_done, cdata);
free(path);
return (CMD_RETURN_WAIT);

View File

@ -30,7 +30,7 @@ const struct cmd_entry cmd_lock_server_entry = {
.name = "lock-server",
.alias = "lock",
.args = { "", 0, 0 },
.args = { "", 0, 0, NULL },
.usage = "",
.flags = CMD_AFTERHOOK,
@ -41,7 +41,7 @@ const struct cmd_entry cmd_lock_session_entry = {
.name = "lock-session",
.alias = "locks",
.args = { "t:", 0, 0 },
.args = { "t:", 0, 0, NULL },
.usage = CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -54,28 +54,25 @@ const struct cmd_entry cmd_lock_client_entry = {
.name = "lock-client",
.alias = "lockc",
.args = { "t:", 0, 0 },
.args = { "t:", 0, 0, NULL },
.usage = CMD_TARGET_CLIENT_USAGE,
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
.exec = cmd_lock_server_exec
};
static enum cmd_retval
cmd_lock_server_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c;
struct cmd_find_state *target = cmdq_get_target(item);
struct client *tc = cmdq_get_target_client(item);
if (self->entry == &cmd_lock_server_entry)
if (cmd_get_entry(self) == &cmd_lock_server_entry)
server_lock();
else if (self->entry == &cmd_lock_session_entry)
server_lock_session(item->target.s);
else {
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
server_lock_client(c);
}
else if (cmd_get_entry(self) == &cmd_lock_session_entry)
server_lock_session(target->s);
else
server_lock_client(tc);
recalculate_sizes();
return (CMD_RETURN_NORMAL);

View File

@ -32,8 +32,8 @@ const struct cmd_entry cmd_move_window_entry = {
.name = "move-window",
.alias = "movew",
.args = { "adkrs:t:", 0, 0 },
.usage = "[-dkr] " CMD_SRCDST_WINDOW_USAGE,
.args = { "abdkrs:t:", 0, 0, NULL },
.usage = "[-abdkr] " CMD_SRCDST_WINDOW_USAGE,
.source = { 's', CMD_FIND_WINDOW, 0 },
/* -t is special */
@ -46,8 +46,8 @@ const struct cmd_entry cmd_link_window_entry = {
.name = "link-window",
.alias = "linkw",
.args = { "adks:t:", 0, 0 },
.usage = "[-dk] " CMD_SRCDST_WINDOW_USAGE,
.args = { "abdks:t:", 0, 0, NULL },
.usage = "[-abdk] " CMD_SRCDST_WINDOW_USAGE,
.source = { 's', CMD_FIND_WINDOW, 0 },
/* -t is special */
@ -59,49 +59,53 @@ const struct cmd_entry cmd_link_window_entry = {
static enum cmd_retval
cmd_move_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_find_state *source = cmdq_get_source(item);
struct cmd_find_state target;
const char *tflag = args_get(args, 't');
struct session *src;
struct session *src = source->s;
struct session *dst;
struct winlink *wl;
struct winlink *wl = source->wl;
char *cause;
int idx, kflag, dflag, sflag;
int idx, kflag, dflag, sflag, before;
if (args_has(args, 'r')) {
if (cmd_find_target(&item->target, item, tflag,
CMD_FIND_SESSION, CMD_FIND_QUIET) != 0)
if (cmd_find_target(&target, item, tflag, CMD_FIND_SESSION,
CMD_FIND_QUIET) != 0)
return (CMD_RETURN_ERROR);
session_renumber_windows(item->target.s);
session_renumber_windows(target.s);
recalculate_sizes();
server_status_session(item->target.s);
server_status_session(target.s);
return (CMD_RETURN_NORMAL);
}
if (cmd_find_target(&item->target, item, tflag, CMD_FIND_WINDOW,
if (cmd_find_target(&target, item, tflag, CMD_FIND_WINDOW,
CMD_FIND_WINDOW_INDEX) != 0)
return (CMD_RETURN_ERROR);
src = item->source.s;
dst = item->target.s;
wl = item->source.wl;
idx = item->target.idx;
dst = target.s;
idx = target.idx;
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
sflag = args_has(self->args, 's');
kflag = args_has(args, 'k');
dflag = args_has(args, 'd');
sflag = args_has(args, 's');
if (args_has(self->args, 'a')) {
if ((idx = winlink_shuffle_up(dst, dst->curw)) == -1)
before = args_has(args, 'b');
if (args_has(args, 'a') || before) {
if (target.wl != NULL)
idx = winlink_shuffle_up(dst, target.wl, before);
else
idx = winlink_shuffle_up(dst, dst->curw, before);
if (idx == -1)
return (CMD_RETURN_ERROR);
}
if (server_link_window(src, wl, dst, idx, kflag, !dflag,
&cause) != 0) {
cmdq_error(item, "can't link window: %s", cause);
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
cmdq_error(item, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (self->entry == &cmd_move_window_entry)
if (cmd_get_entry(self) == &cmd_move_window_entry)
server_unlink_window(src, wl);
/*

View File

@ -39,10 +39,11 @@ const struct cmd_entry cmd_new_session_entry = {
.name = "new-session",
.alias = "new",
.args = { "Ac:dDEF:n:Ps:t:x:Xy:", 0, -1 },
.usage = "[-AdDEPX] [-c start-directory] [-F format] [-n window-name] "
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
"[-y height] [command]",
.args = { "Ac:dDe:EF:f:n:Ps:t:x:Xy:", 0, -1, NULL },
.usage = "[-AdDEPX] [-c start-directory] [-e environment] [-F format] "
"[-f flags] [-n window-name] [-s session-name] "
CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
"[shell-command [argument ...]]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
@ -54,7 +55,7 @@ const struct cmd_entry cmd_has_session_entry = {
.name = "has-session",
.alias = "has",
.args = { "t:", 0, 0 },
.args = { "t:", 0, 0, NULL },
.usage = CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -66,22 +67,26 @@ const struct cmd_entry cmd_has_session_entry = {
static enum cmd_retval
cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c = item->client;
struct session *s, *as, *groupwith;
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 client *c = cmdq_get_client(item);
struct session *s, *as, *groupwith = NULL;
struct environ *env;
struct options *oo;
struct termios tio, *tiop;
struct session_group *sg;
const char *errstr, *template, *group, *prefix, *tmp;
struct session_group *sg = NULL;
const char *errstr, *template, *group, *tmp;
char *cause, *cwd = NULL, *cp, *newname = NULL;
char *name, *prefix = NULL;
int detached, already_attached, is_control = 0;
u_int sx, sy, dsx, dsy;
struct spawn_context sc;
u_int sx, sy, dsx, dsy, count = args_count(args);
struct spawn_context sc = { 0 };
enum cmd_retval retval;
struct cmd_find_state fs;
struct args_value *av;
if (self->entry == &cmd_has_session_entry) {
if (cmd_get_entry(self) == &cmd_has_session_entry) {
/*
* cmd_find_target() will fail if the session cannot be found,
* so always return success here.
@ -89,28 +94,31 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
if (args_has(args, 't') && (count != 0 || args_has(args, 'n'))) {
cmdq_error(item, "command or window name given with target");
return (CMD_RETURN_ERROR);
}
tmp = args_get(args, 's');
if (tmp != NULL) {
newname = format_single(item, tmp, c, NULL, NULL, NULL);
if (!session_check_name(newname)) {
cmdq_error(item, "bad session name: %s", newname);
goto fail;
name = format_single(item, tmp, c, NULL, NULL, NULL);
newname = session_check_name(name);
if (newname == NULL) {
cmdq_error(item, "invalid session: %s", name);
free(name);
return (CMD_RETURN_ERROR);
}
free(name);
}
if (args_has(args, 'A')) {
if (newname != NULL)
as = session_find(newname);
else
as = item->target.s;
as = target->s;
if (as != NULL) {
retval = cmd_attach_session(item, as->name,
args_has(args, 'D'), args_has(args, 'X'), 0, NULL,
args_has(args, 'E'));
args_has(args, 'E'), args_get(args, 'f'));
free(newname);
return (retval);
}
@ -123,25 +131,23 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
/* Is this going to be part of a session group? */
group = args_get(args, 't');
if (group != NULL) {
groupwith = item->target.s;
if (groupwith == NULL) {
if (!session_check_name(group)) {
cmdq_error(item, "bad group name: %s", group);
goto fail;
}
groupwith = target->s;
if (groupwith == NULL)
sg = session_group_find(group);
} else
else
sg = session_group_contains(groupwith);
if (sg != NULL)
prefix = sg->name;
prefix = xstrdup(sg->name);
else if (groupwith != NULL)
prefix = groupwith->name;
else
prefix = group;
} else {
groupwith = NULL;
sg = NULL;
prefix = NULL;
prefix = xstrdup(groupwith->name);
else {
prefix = session_check_name(group);
if (prefix == NULL) {
cmdq_error(item, "invalid session group: %s",
group);
goto fail;
}
}
}
/* Set -d if no client. */
@ -171,13 +177,16 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
* the terminal as that calls tcsetattr() to prepare for tmux taking
* over.
*/
if (!detached && !already_attached && c->tty.fd != -1) {
if (server_client_check_nested(item->client)) {
if (!detached &&
!already_attached &&
c->fd != -1 &&
(~c->flags & CLIENT_CONTROL)) {
if (server_client_check_nested(cmdq_get_client(item))) {
cmdq_error(item, "sessions should be nested with care, "
"unset $TMUX to force");
goto fail;
}
if (tcgetattr(c->tty.fd, &tio) != 0)
if (tcgetattr(c->fd, &tio) != 0)
fatal("tcgetattr failed");
tiop = &tio;
} else
@ -207,7 +216,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
goto fail;
}
}
}
} else
dsx = 80;
if (args_has(args, 'y')) {
tmp = args_get(args, 'y');
if (strcmp(tmp, "-") == 0) {
@ -222,7 +232,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
goto fail;
}
}
}
} else
dsy = 24;
/* Find new session size. */
if (!detached && !is_control) {
@ -233,14 +244,15 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
} else {
tmp = options_get_string(global_s_options, "default-size");
if (sscanf(tmp, "%ux%u", &sx, &sy) != 2) {
sx = 80;
sy = 24;
}
sx = dsx;
sy = dsy;
} else {
if (args_has(args, 'x'))
sx = dsx;
if (args_has(args, 'y'))
sy = dsy;
}
}
if (sx == 0)
sx = 1;
if (sy == 0)
@ -258,17 +270,21 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
env = environ_create();
if (c != NULL && !args_has(args, 'E'))
environ_update(global_s_options, c->environ, env);
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(env, av->string, 0);
av = args_next_value(av);
}
s = session_create(prefix, newname, cwd, env, oo, tiop);
/* Spawn the initial window. */
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.c = c;
if (!detached)
sc.tc = c;
sc.name = args_get(args, 'n');
sc.argc = args->argc;
sc.argv = args->argv;
args_to_vector(args, &sc.argc, &sc.argv);
sc.idx = -1;
sc.cwd = args_get(args, 'c');
@ -305,30 +321,17 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
* taking this session and needs to get MSG_READY and stay around.
*/
if (!detached) {
if (args_has(args, 'f'))
server_client_set_flags(c, args_get(args, 'f'));
if (!already_attached) {
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
} else if (c->session != NULL)
c->last_session = c->session;
c->session = s;
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
server_client_set_session(c, s);
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
server_client_set_key_table(c, NULL);
tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
}
recalculate_sizes();
server_update_socket();
/*
* If there are still configuration file errors to display, put the new
* session's current window into more mode and display them now.
*/
if (cfg_finished)
cfg_show_causes(s);
/* Print if requested. */
if (args_has(args, 'P')) {
@ -339,20 +342,29 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
free(cp);
}
if (!detached) {
if (!detached)
c->flags |= CLIENT_ATTACHED;
cmd_find_from_session(&item->shared->current, s, 0);
}
if (!args_has(args, 'd'))
cmd_find_from_session(current, s, 0);
cmd_find_from_session(&fs, s, 0);
cmdq_insert_hook(s, item, &fs, "after-new-session");
if (cfg_finished)
cfg_show_causes(s);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
free(cwd);
free(newname);
free(prefix);
return (CMD_RETURN_NORMAL);
fail:
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
free(cwd);
free(newname);
free(prefix);
return (CMD_RETURN_ERROR);
}

View File

@ -38,9 +38,10 @@ const struct cmd_entry cmd_new_window_entry = {
.name = "new-window",
.alias = "neww",
.args = { "ac:de:F:kn:Pt:", 0, -1 },
.usage = "[-adkP] [-c start-directory] [-e environment] [-F format] "
"[-n window-name] " CMD_TARGET_WINDOW_USAGE " [command]",
.args = { "abc:de:F:kn:PSt:", 0, -1, NULL },
.usage = "[-abdkPS] [-c start-directory] [-e environment] [-F format] "
"[-n window-name] " CMD_TARGET_WINDOW_USAGE
" [shell-command [argument ...]]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX },
@ -51,38 +52,70 @@ const struct cmd_entry cmd_new_window_entry = {
static enum cmd_retval
cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct cmd_find_state *current = &item->shared->current;
struct spawn_context sc;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
int idx = item->target.idx;
struct winlink *new_wl;
char *cause = NULL, *cp;
const char *template, *add;
struct args *args = cmd_get_args(self);
struct client *c = cmdq_get_client(item);
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, *new_wl = NULL;
int idx = target->idx, before;
char *cause = NULL, *cp, *expanded;
const char *template, *name;
struct cmd_find_state fs;
struct args_value *value;
struct args_value *av;
if (args_has(args, 'a') && (idx = winlink_shuffle_up(s, wl)) == -1) {
cmdq_error(item, "couldn't get a window index");
/*
* If -S and -n are given and -t is not and a single window with this
* name already exists, select it.
*/
name = args_get(args, 'n');
if (args_has(args, 'S') && name != NULL && target->idx == -1) {
expanded = format_single(item, name, c, s, NULL, NULL);
RB_FOREACH(wl, winlinks, &s->windows) {
if (strcmp(wl->window->name, expanded) != 0)
continue;
if (new_wl == NULL) {
new_wl = wl;
continue;
}
cmdq_error(item, "multiple windows named %s", name);
free(expanded);
return (CMD_RETURN_ERROR);
}
free(expanded);
if (new_wl != NULL) {
if (args_has(args, 'd'))
return (CMD_RETURN_NORMAL);
if (session_set_current(s, new_wl) == 0)
server_redraw_session(s);
if (c != NULL && c->session != NULL)
s->curw->window->latest = c;
recalculate_sizes();
return (CMD_RETURN_NORMAL);
}
}
before = args_has(args, 'b');
if (args_has(args, 'a') || before) {
idx = winlink_shuffle_up(s, wl, before);
if (idx == -1)
idx = target->idx;
}
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.c = c;
sc.tc = tc;
sc.name = args_get(args, 'n');
sc.argc = args->argc;
sc.argv = args->argv;
args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(sc.environ, add);
add = args_next_value(&value);
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(sc.environ, av->string, 0);
av = args_next_value(av);
}
sc.idx = idx;
@ -97,6 +130,9 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
if ((new_wl = spawn_window(&sc, &cause)) == NULL) {
cmdq_error(item, "create window 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 (!args_has(args, 'd') || new_wl == s->curw) {
@ -108,7 +144,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)
template = NEW_WINDOW_TEMPLATE;
cp = format_single(item, template, c, s, new_wl,
cp = format_single(item, template, tc, s, new_wl,
new_wl->window->active);
cmdq_print(item, "%s", cp);
free(cp);
@ -117,6 +153,8 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
cmd_find_from_winlink(&fs, new_wl, 0);
cmdq_insert_hook(s, item, &fs, "after-new-window");
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_NORMAL);
}

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_paste_buffer_entry = {
.name = "paste-buffer",
.alias = "pasteb",
.args = { "db:prs:t:", 0, 0 },
.args = { "db:prs:t:", 0, 0, NULL },
.usage = "[-dpr] [-s separator] " CMD_BUFFER_USAGE " "
CMD_TARGET_PANE_USAGE,
@ -46,13 +46,19 @@ const struct cmd_entry cmd_paste_buffer_entry = {
static enum cmd_retval
cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct window_pane *wp = item->target.wp;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct window_pane *wp = target->wp;
struct paste_buffer *pb;
const char *sepstr, *bufname, *bufdata, *bufend, *line;
size_t seplen, bufsize;
int bracket = args_has(args, 'p');
if (window_pane_exited(wp)) {
cmdq_error(item, "target pane has exited");
return (CMD_RETURN_ERROR);
}
bufname = NULL;
if (args_has(args, 'b'))
bufname = args_get(args, 'b');

View File

@ -43,8 +43,8 @@ const struct cmd_entry cmd_pipe_pane_entry = {
.name = "pipe-pane",
.alias = "pipep",
.args = { "IOot:", 0, 1 },
.usage = "[-IOo] " CMD_TARGET_PANE_USAGE " [command]",
.args = { "IOot:", 0, 1, NULL },
.usage = "[-IOo] " CMD_TARGET_PANE_USAGE " [shell-command]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -55,16 +55,24 @@ const struct cmd_entry cmd_pipe_pane_entry = {
static enum cmd_retval
cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c = cmd_find_client(item, NULL, 1);
struct window_pane *wp = item->target.wp;
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct client *tc = cmdq_get_target_client(item);
struct window_pane *wp = target->wp;
struct session *s = target->s;
struct winlink *wl = target->wl;
struct window_pane_offset *wpo = &wp->pipe_offset;
char *cmd;
int old_fd, pipe_fd[2], null_fd, in, out;
struct format_tree *ft;
sigset_t set, oldset;
/* Do nothing if pane is dead. */
if (window_pane_exited(wp)) {
cmdq_error(item, "target pane has exited");
return (CMD_RETURN_ERROR);
}
/* Destroy the old pipe. */
old_fd = wp->pipe_fd;
if (wp->pipe_fd != -1) {
@ -79,7 +87,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
}
/* If no pipe command, that is enough. */
if (args->argc == 0 || *args->argv[0] == '\0')
if (args_count(args) == 0 || *args_string(args, 0) == '\0')
return (CMD_RETURN_NORMAL);
/*
@ -88,13 +96,13 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
*
* bind ^p pipep -o 'cat >>~/output'
*/
if (args_has(self->args, 'o') && old_fd != -1)
if (args_has(args, 'o') && old_fd != -1)
return (CMD_RETURN_NORMAL);
/* What do we want to do? Neither -I or -O is -O. */
if (args_has(self->args, 'I')) {
if (args_has(args, 'I')) {
in = 1;
out = args_has(self->args, 'O');
out = args_has(args, 'O');
} else {
in = 0;
out = 1;
@ -107,9 +115,9 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
}
/* Expand the command. */
ft = format_create(item->client, item, FORMAT_NONE, 0);
format_defaults(ft, c, s, wl, wp);
cmd = format_expand_time(ft, args->argv[0]);
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
format_defaults(ft, tc, s, wl, wp);
cmd = format_expand_time(ft, args_string(args, 0));
format_free(ft);
/* Fork the child. */
@ -128,7 +136,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
sigprocmask(SIG_SETMASK, &oldset, NULL);
close(pipe_fd[0]);
null_fd = open(_PATH_DEVNULL, O_WRONLY, 0);
null_fd = open(_PATH_DEVNULL, O_WRONLY);
if (out) {
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
_exit(1);
@ -157,10 +165,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
close(pipe_fd[1]);
wp->pipe_fd = pipe_fd[0];
if (wp->fd != -1)
wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
else
wp->pipe_off = 0;
memcpy(wpo, &wp->offset, sizeof *wpo);
setblocking(wp->pipe_fd, 0);
wp->pipe_event = bufferevent_new(wp->pipe_fd,

View File

@ -19,14 +19,77 @@
#include <sys/types.h>
#include <ctype.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
/* Global command queue. */
static struct cmdq_list global_queue = TAILQ_HEAD_INITIALIZER(global_queue);
/* Command queue flags. */
#define CMDQ_FIRED 0x1
#define CMDQ_WAITING 0x2
/* Command queue item type. */
enum cmdq_type {
CMDQ_COMMAND,
CMDQ_CALLBACK,
};
/* Command queue item. */
struct cmdq_item {
char *name;
struct cmdq_list *queue;
struct cmdq_item *next;
struct client *client;
struct client *target_client;
enum cmdq_type type;
u_int group;
u_int number;
time_t time;
int flags;
struct cmdq_state *state;
struct cmd_find_state source;
struct cmd_find_state target;
struct cmd_list *cmdlist;
struct cmd *cmd;
cmdq_cb cb;
void *data;
TAILQ_ENTRY(cmdq_item) entry;
};
TAILQ_HEAD(cmdq_item_list, cmdq_item);
/*
* Command queue state. This is the context for commands on the command queue.
* It holds information about how the commands were fired (the key and flags),
* any additional formats for the commands, and the current default target.
* Multiple commands can share the same state and a command may update the
* default target.
*/
struct cmdq_state {
int references;
int flags;
struct format_tree *formats;
struct key_event event;
struct cmd_find_state current;
};
/* Command queue. */
struct cmdq_list {
struct cmdq_item *item;
struct cmdq_item_list list;
};
/* Get command queue name. */
static const char *
@ -47,9 +110,190 @@ cmdq_name(struct client *c)
static struct cmdq_list *
cmdq_get(struct client *c)
{
if (c == NULL)
return (&global_queue);
return (&c->queue);
static struct cmdq_list *global_queue;
if (c == NULL) {
if (global_queue == NULL)
global_queue = cmdq_new();
return (global_queue);
}
return (c->queue);
}
/* Create a queue. */
struct cmdq_list *
cmdq_new(void)
{
struct cmdq_list *queue;
queue = xcalloc(1, sizeof *queue);
TAILQ_INIT (&queue->list);
return (queue);
}
/* Free a queue. */
void
cmdq_free(struct cmdq_list *queue)
{
if (!TAILQ_EMPTY(&queue->list))
fatalx("queue not empty");
free(queue);
}
/* Get item name. */
const char *
cmdq_get_name(struct cmdq_item *item)
{
return (item->name);
}
/* Get item client. */
struct client *
cmdq_get_client(struct cmdq_item *item)
{
return (item->client);
}
/* Get item target client. */
struct client *
cmdq_get_target_client(struct cmdq_item *item)
{
return (item->target_client);
}
/* Get item state. */
struct cmdq_state *
cmdq_get_state(struct cmdq_item *item)
{
return (item->state);
}
/* Get item target. */
struct cmd_find_state *
cmdq_get_target(struct cmdq_item *item)
{
return (&item->target);
}
/* Get item source. */
struct cmd_find_state *
cmdq_get_source(struct cmdq_item *item)
{
return (&item->source);
}
/* Get state event. */
struct key_event *
cmdq_get_event(struct cmdq_item *item)
{
return (&item->state->event);
}
/* Get state current target. */
struct cmd_find_state *
cmdq_get_current(struct cmdq_item *item)
{
return (&item->state->current);
}
/* Get state flags. */
int
cmdq_get_flags(struct cmdq_item *item)
{
return (item->state->flags);
}
/* Create a new state. */
struct cmdq_state *
cmdq_new_state(struct cmd_find_state *current, struct key_event *event,
int flags)
{
struct cmdq_state *state;
state = xcalloc(1, sizeof *state);
state->references = 1;
state->flags = flags;
if (event != NULL)
memcpy(&state->event, event, sizeof state->event);
else
state->event.key = KEYC_NONE;
if (current != NULL && cmd_find_valid_state(current))
cmd_find_copy_state(&state->current, current);
else
cmd_find_clear_state(&state->current, 0);
return (state);
}
/* Add a reference to a state. */
struct cmdq_state *
cmdq_link_state(struct cmdq_state *state)
{
state->references++;
return (state);
}
/* Make a copy of a state. */
struct cmdq_state *
cmdq_copy_state(struct cmdq_state *state, struct cmd_find_state *current)
{
if (current != NULL)
return (cmdq_new_state(current, &state->event, state->flags));
return (cmdq_new_state(&state->current, &state->event, state->flags));
}
/* Free a state. */
void
cmdq_free_state(struct cmdq_state *state)
{
if (--state->references != 0)
return;
if (state->formats != NULL)
format_free(state->formats);
free(state);
}
/* Add a format to command queue. */
void
cmdq_add_format(struct cmdq_state *state, const char *key, const char *fmt, ...)
{
va_list ap;
char *value;
va_start(ap, fmt);
xvasprintf(&value, fmt, ap);
va_end(ap);
if (state->formats == NULL)
state->formats = format_create(NULL, NULL, FORMAT_NONE, 0);
format_add(state->formats, key, "%s", value);
free(value);
}
/* Add formats to command queue. */
void
cmdq_add_formats(struct cmdq_state *state, struct format_tree *ft)
{
if (state->formats == NULL)
state->formats = format_create(NULL, NULL, FORMAT_NONE, 0);
format_merge(state->formats, ft);
}
/* Merge formats from item. */
void
cmdq_merge_formats(struct cmdq_item *item, struct format_tree *ft)
{
const struct cmd_entry *entry;
if (item->cmd != NULL) {
entry = cmd_get_entry(item->cmd);
format_add(ft, "command", "%s", entry->name);
}
if (item->state->formats != NULL)
format_merge(ft, item->state->formats);
}
/* Append an item. */
@ -68,12 +312,12 @@ cmdq_append(struct client *c, struct cmdq_item *item)
item->client = c;
item->queue = queue;
TAILQ_INSERT_TAIL(queue, item, entry);
TAILQ_INSERT_TAIL(&queue->list, item, entry);
log_debug("%s %s: %s", __func__, cmdq_name(c), item->name);
item = next;
} while (item != NULL);
return (TAILQ_LAST(queue, cmdq_list));
return (TAILQ_LAST(&queue->list, cmdq_item_list));
}
/* Insert an item. */
@ -94,7 +338,7 @@ cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item)
item->client = c;
item->queue = queue;
TAILQ_INSERT_AFTER(queue, after, item, entry);
TAILQ_INSERT_AFTER(&queue->list, after, item, entry);
log_debug("%s %s: %s after %s", __func__, cmdq_name(c),
item->name, after->name);
@ -107,17 +351,25 @@ cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item)
/* Insert a hook. */
void
cmdq_insert_hook(struct session *s, struct cmdq_item *item,
struct cmd_find_state *fs, const char *fmt, ...)
struct cmd_find_state *current, const char *fmt, ...)
{
struct cmdq_state *state = item->state;
struct cmd *cmd = item->cmd;
struct args *args = cmd_get_args(cmd);
struct args_entry *ae;
struct args_value *av;
struct options *oo;
va_list ap;
char *name;
char *name, tmp[32], flag, *arguments;
u_int i;
const char *value;
struct cmdq_item *new_item;
struct cmdq_state *new_state;
struct options_entry *o;
struct options_array_item *a;
struct cmd_list *cmdlist;
if (item->flags & CMDQ_NOHOOKS)
if (item->state->flags & CMDQ_STATE_NOHOOKS)
return;
if (s == NULL)
oo = global_s_options;
@ -135,24 +387,58 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item,
}
log_debug("running hook %s (parent %p)", name, item);
/*
* The hooks get a new state because they should not update the current
* target or formats for any subsequent commands.
*/
new_state = cmdq_new_state(current, &state->event, CMDQ_STATE_NOHOOKS);
cmdq_add_format(new_state, "hook", "%s", name);
arguments = args_print(args);
cmdq_add_format(new_state, "hook_arguments", "%s", arguments);
free(arguments);
for (i = 0; i < args_count(args); i++) {
xsnprintf(tmp, sizeof tmp, "hook_argument_%d", i);
cmdq_add_format(new_state, tmp, "%s", args_string(args, i));
}
flag = args_first(args, &ae);
while (flag != 0) {
value = args_get(args, flag);
if (value == NULL) {
xsnprintf(tmp, sizeof tmp, "hook_flag_%c", flag);
cmdq_add_format(new_state, tmp, "1");
} else {
xsnprintf(tmp, sizeof tmp, "hook_flag_%c", flag);
cmdq_add_format(new_state, tmp, "%s", value);
}
i = 0;
av = args_first_value(args, flag);
while (av != NULL) {
xsnprintf(tmp, sizeof tmp, "hook_flag_%c_%d", flag, i);
cmdq_add_format(new_state, tmp, "%s", av->string);
i++;
av = args_next_value(av);
}
flag = args_next(&ae);
}
a = options_array_first(o);
while (a != NULL) {
cmdlist = options_array_item_value(a)->cmdlist;
if (cmdlist == NULL) {
a = options_array_next(a);
continue;
}
new_item = cmdq_get_command(cmdlist, fs, NULL, CMDQ_NOHOOKS);
cmdq_format(new_item, "hook", "%s", name);
if (cmdlist != NULL) {
new_item = cmdq_get_command(cmdlist, new_state);
if (item != NULL)
item = cmdq_insert_after(item, new_item);
else
item = cmdq_append(NULL, new_item);
}
a = options_array_next(a);
}
cmdq_free_state(new_state);
free(name);
}
@ -167,19 +453,13 @@ cmdq_continue(struct cmdq_item *item)
static void
cmdq_remove(struct cmdq_item *item)
{
if (item->shared != NULL && --item->shared->references == 0) {
if (item->shared->formats != NULL)
format_free(item->shared->formats);
free(item->shared);
}
if (item->client != NULL)
server_client_unref(item->client);
if (item->cmdlist != NULL)
cmd_list_free(item->cmdlist);
cmdq_free_state(item->state);
TAILQ_REMOVE(item->queue, item, entry);
TAILQ_REMOVE(&item->queue->list, item, entry);
free(item->name);
free(item);
@ -202,50 +482,57 @@ cmdq_remove_group(struct cmdq_item *item)
}
}
/* Empty command callback. */
static enum cmd_retval
cmdq_empty_command(__unused struct cmdq_item *item, __unused void *data)
{
return (CMD_RETURN_NORMAL);
}
/* Get a command for the command queue. */
struct cmdq_item *
cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current,
struct mouse_event *m, int flags)
cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state)
{
struct cmdq_item *item, *first = NULL, *last = NULL;
struct cmd *cmd;
struct cmdq_shared *shared = NULL;
u_int group = 0;
const struct cmd_entry *entry;
int created = 0;
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (cmd->group != group) {
shared = xcalloc(1, sizeof *shared);
if (current != NULL)
cmd_find_copy_state(&shared->current, current);
else
cmd_find_clear_state(&shared->current, 0);
if (m != NULL)
memcpy(&shared->mouse, m, sizeof shared->mouse);
group = cmd->group;
if ((cmd = cmd_list_first(cmdlist)) == NULL)
return (cmdq_get_callback(cmdq_empty_command, NULL));
if (state == NULL) {
state = cmdq_new_state(NULL, NULL, 0);
created = 1;
}
while (cmd != NULL) {
entry = cmd_get_entry(cmd);
item = xcalloc(1, sizeof *item);
xasprintf(&item->name, "[%s/%p]", cmd->entry->name, item);
xasprintf(&item->name, "[%s/%p]", entry->name, item);
item->type = CMDQ_COMMAND;
item->group = cmd->group;
item->flags = flags;
item->group = cmd_get_group(cmd);
item->state = cmdq_link_state(state);
item->shared = shared;
item->cmdlist = cmdlist;
item->cmd = cmd;
log_debug("%s: %s group %u", __func__, item->name, item->group);
shared->references++;
cmdlist->references++;
log_debug("%s: %s group %u", __func__, item->name, item->group);
if (first == NULL)
first = item;
if (last != NULL)
last->next = item;
last = item;
cmd = cmd_list_next(cmd);
}
if (created)
cmdq_free_state(state);
return (first);
}
@ -257,11 +544,11 @@ cmdq_find_flag(struct cmdq_item *item, struct cmd_find_state *fs,
const char *value;
if (flag->flag == 0) {
cmd_find_clear_state(fs, 0);
cmd_find_from_client(fs, item->target_client, 0);
return (CMD_RETURN_NORMAL);
}
value = args_get(item->cmd->args, flag->flag);
value = args_get(cmd_get_args(item->cmd), flag->flag);
if (cmd_find_target(fs, item, value, flag->type, flag->flags) != 0) {
cmd_find_clear_state(fs, 0);
return (CMD_RETURN_ERROR);
@ -269,31 +556,89 @@ cmdq_find_flag(struct cmdq_item *item, struct cmd_find_state *fs,
return (CMD_RETURN_NORMAL);
}
/* Add message with command. */
static void
cmdq_add_message(struct cmdq_item *item)
{
struct client *c = item->client;
struct cmdq_state *state = item->state;
const char *key;
char *tmp;
uid_t uid;
struct passwd *pw;
char *user = NULL;
tmp = cmd_print(item->cmd);
if (c != NULL) {
uid = proc_get_peer_uid(c->peer);
if (uid != (uid_t)-1 && uid != getuid()) {
if ((pw = getpwuid(uid)) != NULL)
xasprintf(&user, "[%s]", pw->pw_name);
else
user = xstrdup("[unknown]");
} else
user = xstrdup("");
if (c->session != NULL && state->event.key != KEYC_NONE) {
key = key_string_lookup_key(state->event.key, 0);
server_add_message("%s%s key %s: %s", c->name, user,
key, tmp);
} else {
server_add_message("%s%s command: %s", c->name, user,
tmp);
}
free(user);
} else
server_add_message("command: %s", tmp);
free(tmp);
}
/* Fire command on command queue. */
static enum cmd_retval
cmdq_fire_command(struct cmdq_item *item)
{
struct client *c = item->client;
const char *name = cmdq_name(c);
struct cmdq_shared *shared = item->shared;
const char *name = cmdq_name(item->client);
struct cmdq_state *state = item->state;
struct cmd *cmd = item->cmd;
const struct cmd_entry *entry = cmd->entry;
struct args *args = cmd_get_args(cmd);
const struct cmd_entry *entry = cmd_get_entry(cmd);
struct client *tc, *saved = item->client;
enum cmd_retval retval;
struct cmd_find_state *fsp, fs;
int flags;
int flags, quiet = 0;
char *tmp;
if (cfg_finished)
cmdq_add_message(item);
if (log_get_level() > 1) {
tmp = cmd_print(cmd);
log_debug("%s %s: (%u) %s", __func__, name, item->group, tmp);
free(tmp);
}
flags = !!(shared->flags & CMDQ_SHARED_CONTROL);
flags = !!(state->flags & CMDQ_STATE_CONTROL);
cmdq_guard(item, "begin", flags);
if (item->client == NULL)
item->client = cmd_find_client(item, NULL, 1);
if (entry->flags & CMD_CLIENT_CANFAIL)
quiet = 1;
if (entry->flags & CMD_CLIENT_CFLAG) {
tc = cmd_find_client(item, args_get(args, 'c'), quiet);
if (tc == NULL && !quiet) {
retval = CMD_RETURN_ERROR;
goto out;
}
} else if (entry->flags & CMD_CLIENT_TFLAG) {
tc = cmd_find_client(item, args_get(args, 't'), quiet);
if (tc == NULL && !quiet) {
retval = CMD_RETURN_ERROR;
goto out;
}
} else
tc = cmd_find_client(item, NULL, 1);
item->target_client = tc;
retval = cmdq_find_flag(item, &item->source, &entry->source);
if (retval == CMD_RETURN_ERROR)
goto out;
@ -308,8 +653,8 @@ cmdq_fire_command(struct cmdq_item *item)
if (entry->flags & CMD_AFTERHOOK) {
if (cmd_find_valid_state(&item->target))
fsp = &item->target;
else if (cmd_find_valid_state(&item->shared->current))
fsp = &item->shared->current;
else if (cmd_find_valid_state(&item->state->current))
fsp = &item->state->current;
else if (cmd_find_from_client(&fs, item->client, 0) == 0)
fsp = &fs;
else
@ -318,10 +663,19 @@ cmdq_fire_command(struct cmdq_item *item)
}
out:
item->client = c;
if (retval == CMD_RETURN_ERROR)
item->client = saved;
if (retval == CMD_RETURN_ERROR) {
fsp = NULL;
if (cmd_find_valid_state(&item->target))
fsp = &item->target;
else if (cmd_find_valid_state(&item->state->current))
fsp = &item->state->current;
else if (cmd_find_from_client(&fs, item->client, 0) == 0)
fsp = &fs;
cmdq_insert_hook(fsp != NULL ? fsp->s : NULL, item, fsp,
"command-error");
cmdq_guard(item, "error", flags);
else
} else
cmdq_guard(item, "end", flags);
return (retval);
}
@ -337,7 +691,7 @@ cmdq_get_callback1(const char *name, cmdq_cb cb, void *data)
item->type = CMDQ_CALLBACK;
item->group = 0;
item->flags = 0;
item->state = cmdq_new_state(NULL, NULL, 0);
item->cb = cb;
item->data = data;
@ -371,25 +725,6 @@ cmdq_fire_callback(struct cmdq_item *item)
return (item->cb(item, item->data));
}
/* Add a format to command queue. */
void
cmdq_format(struct cmdq_item *item, const char *key, const char *fmt, ...)
{
struct cmdq_shared *shared = item->shared;
va_list ap;
char *value;
va_start(ap, fmt);
xvasprintf(&value, fmt, ap);
va_end(ap);
if (shared->formats == NULL)
shared->formats = format_create(NULL, NULL, FORMAT_NONE, 0);
format_add(shared->formats, key, "%s", value);
free(value);
}
/* Process next item on command queue. */
u_int
cmdq_next(struct client *c)
@ -401,18 +736,18 @@ cmdq_next(struct client *c)
u_int items = 0;
static u_int number;
if (TAILQ_EMPTY(queue)) {
if (TAILQ_EMPTY(&queue->list)) {
log_debug("%s %s: empty", __func__, name);
return (0);
}
if (TAILQ_FIRST(queue)->flags & CMDQ_WAITING) {
if (TAILQ_FIRST(&queue->list)->flags & CMDQ_WAITING) {
log_debug("%s %s: waiting", __func__, name);
return (0);
}
log_debug("%s %s: enter", __func__, name);
for (;;) {
item = TAILQ_FIRST(queue);
item = queue->item = TAILQ_FIRST(&queue->list);
if (item == NULL)
break;
log_debug("%s %s: %s (%d), flags %x", __func__, name,
@ -462,6 +797,7 @@ cmdq_next(struct client *c)
}
cmdq_remove(item);
}
queue->item = NULL;
log_debug("%s %s: exit (empty)", __func__, name);
return (items);
@ -471,6 +807,19 @@ waiting:
return (items);
}
/* Get running item if any. */
struct cmdq_item *
cmdq_running(struct client *c)
{
struct cmdq_list *queue = cmdq_get(c);
if (queue->item == NULL)
return (NULL);
if (queue->item->flags & CMDQ_WAITING)
return (NULL);
return (queue->item);
}
/* Print a guard line. */
void
cmdq_guard(struct cmdq_item *item, const char *guard, int flags)
@ -480,43 +829,33 @@ cmdq_guard(struct cmdq_item *item, const char *guard, int flags)
u_int number = item->number;
if (c != NULL && (c->flags & CLIENT_CONTROL))
file_print(c, "%%%s %ld %u %d\n", guard, t, number, flags);
control_write(c, "%%%s %ld %u %d", guard, t, number, flags);
}
/* Show message from command. */
void
cmdq_print_data(struct cmdq_item *item, struct evbuffer *evb)
{
server_client_print(item->client, 1, evb);
}
/* Show message from command. */
void
cmdq_print(struct cmdq_item *item, const char *fmt, ...)
{
struct client *c = item->client;
struct window_pane *wp;
struct window_mode_entry *wme;
va_list ap;
char *tmp, *msg;
struct evbuffer *evb;
evb = evbuffer_new();
if (evb == NULL)
fatalx("out of memory");
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
evbuffer_add_vprintf(evb, fmt, ap);
va_end(ap);
log_debug("%s: %s", __func__, msg);
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
if (~c->flags & CLIENT_UTF8) {
tmp = msg;
msg = utf8_sanitize(tmp);
free(tmp);
}
file_print(c, "%s\n", msg);
} else {
wp = c->session->curw->window->active;
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode != &window_view_mode)
window_pane_set_mode(wp, &window_view_mode, NULL, NULL);
window_copy_add(wp, "%s", msg);
}
free(msg);
cmdq_print_data(item, evb);
evbuffer_free(evb);
}
/* Show error from command. */
@ -526,8 +865,9 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...)
struct client *c = item->client;
struct cmd *cmd = item->cmd;
va_list ap;
char *msg;
char *tmp;
char *msg, *tmp;
const char *file;
u_int line;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
@ -535,22 +875,24 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...)
log_debug("%s: %s", __func__, msg);
if (c == NULL)
cfg_add_cause("%s:%u: %s", cmd->file, cmd->line, msg);
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
if (c == NULL) {
cmd_get_source(cmd, &file, &line);
cfg_add_cause("%s:%u: %s", file, line, msg);
} else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
server_add_message("%s message: %s", c->name, msg);
if (~c->flags & CLIENT_UTF8) {
tmp = msg;
msg = utf8_sanitize(tmp);
free(tmp);
}
if (c->flags & CLIENT_CONTROL)
file_print(c, "%s\n", msg);
control_write(c, "%s", msg);
else
file_error(c, "%s\n", msg);
c->retval = 1;
} else {
*msg = toupper((u_char) *msg);
status_message_set(c, "%s", msg);
status_message_set(c, -1, 1, 0, 0, "%s", msg);
}
free(msg);

View File

@ -34,92 +34,86 @@ const struct cmd_entry cmd_refresh_client_entry = {
.name = "refresh-client",
.alias = "refresh",
.args = { "cC:DF:lLRSt:U", 0, 1 },
.usage = "[-cDlLRSU] [-C XxY] [-F flags] " CMD_TARGET_CLIENT_USAGE
.args = { "A:B:cC:Df:r:F:l::LRSt:U", 0, 1, NULL },
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
"[-C XxY] [-f flags] [-r pane:report] " CMD_TARGET_CLIENT_USAGE
" [adjustment]",
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
.exec = cmd_refresh_client_exec
};
static void
cmd_refresh_client_update_subscription(struct client *tc, const char *value)
{
char *copy, *split, *name, *what;
enum control_sub_type subtype;
int subid = -1;
copy = name = xstrdup(value);
if ((split = strchr(copy, ':')) == NULL) {
control_remove_sub(tc, copy);
goto out;
}
*split++ = '\0';
what = split;
if ((split = strchr(what, ':')) == NULL)
goto out;
*split++ = '\0';
if (strcmp(what, "%*") == 0)
subtype = CONTROL_SUB_ALL_PANES;
else if (sscanf(what, "%%%d", &subid) == 1 && subid >= 0)
subtype = CONTROL_SUB_PANE;
else if (strcmp(what, "@*") == 0)
subtype = CONTROL_SUB_ALL_WINDOWS;
else if (sscanf(what, "@%d", &subid) == 1 && subid >= 0)
subtype = CONTROL_SUB_WINDOW;
else
subtype = CONTROL_SUB_SESSION;
control_add_sub(tc, name, subtype, subid, split);
out:
free(copy);
}
static enum cmd_retval
cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
cmd_refresh_client_control_client_size(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c;
struct tty *tty;
struct window *w;
const char *size, *errstr;
char *copy, *next, *s;
u_int x, y, adjust;
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
const char *size = args_get(args, 'C');
u_int w, x, y;
struct client_window *cw;
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
tty = &c->tty;
if (args_has(args, 'c') ||
args_has(args, 'L') ||
args_has(args, 'R') ||
args_has(args, 'U') ||
args_has(args, 'D'))
{
if (args->argc == 0)
adjust = 1;
else {
adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
if (sscanf(size, "@%u:%ux%u", &w, &x, &y) == 3) {
if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
cmdq_error(item, "size too small or too big");
return (CMD_RETURN_ERROR);
}
log_debug("%s: client %s window @%u: size %ux%u", __func__,
tc->name, w, x, y);
cw = server_client_add_client_window(tc, w);
cw->sx = x;
cw->sy = y;
tc->flags |= CLIENT_WINDOWSIZECHANGED;
recalculate_sizes_now(1);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'c'))
c->pan_window = NULL;
else {
w = c->session->curw->window;
if (c->pan_window != w) {
c->pan_window = w;
c->pan_ox = tty->oox;
c->pan_oy = tty->ooy;
if (sscanf(size, "@%u:", &w) == 1) {
cw = server_client_get_client_window(tc, w);
if (cw != NULL) {
log_debug("%s: client %s window @%u: no size", __func__,
tc->name, w);
cw->sx = 0;
cw->sy = 0;
recalculate_sizes_now(1);
}
if (args_has(args, 'L')) {
if (c->pan_ox > adjust)
c->pan_ox -= adjust;
else
c->pan_ox = 0;
} else if (args_has(args, 'R')) {
c->pan_ox += adjust;
if (c->pan_ox > w->sx - tty->osx)
c->pan_ox = w->sx - tty->osx;
} else if (args_has(args, 'U')) {
if (c->pan_oy > adjust)
c->pan_oy -= adjust;
else
c->pan_oy = 0;
} else if (args_has(args, 'D')) {
c->pan_oy += adjust;
if (c->pan_oy > w->sy - tty->osy)
c->pan_oy = w->sy - tty->osy;
}
}
tty_update_client_offset(c);
server_redraw_client(c);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'l')) {
if (c->session != NULL)
tty_putcode_ptr2(&c->tty, TTYC_MS, "", "?");
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'C') || args_has(args, 'F')) {
if (args_has(args, 'C')) {
if (!(c->flags & CLIENT_CONTROL)) {
cmdq_error(item, "not a control client");
return (CMD_RETURN_ERROR);
}
size = args_get(args, 'C');
if (sscanf(size, "%u,%u", &x, &y) != 2 &&
sscanf(size, "%ux%u", &x, &y) != 2) {
cmdq_error(item, "bad size argument");
@ -130,32 +124,212 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "size too small or too big");
return (CMD_RETURN_ERROR);
}
tty_set_size(&c->tty, x, y, 0, 0);
c->flags |= CLIENT_SIZECHANGED;
recalculate_sizes();
}
if (args_has(args, 'F')) {
if (!(c->flags & CLIENT_CONTROL)) {
cmdq_error(item, "not a control client");
return (CMD_RETURN_ERROR);
}
s = copy = xstrdup(args_get(args, 'F'));
while ((next = strsep(&s, ",")) != NULL) {
/* Unknown flags are ignored. */
if (strcmp(next, "no-output") == 0)
c->flags |= CLIENT_CONTROL_NOOUTPUT;
}
free(copy);
}
tty_set_size(&tc->tty, x, y, 0, 0);
tc->flags |= CLIENT_SIZECHANGED;
recalculate_sizes_now(1);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'S')) {
c->flags |= CLIENT_STATUSFORCE;
server_status_client(c);
static void
cmd_refresh_client_update_offset(struct client *tc, const char *value)
{
struct window_pane *wp;
char *copy, *split;
u_int pane;
if (*value != '%')
return;
copy = xstrdup(value);
if ((split = strchr(copy, ':')) == NULL)
goto out;
*split++ = '\0';
if (sscanf(copy, "%%%u", &pane) != 1)
goto out;
wp = window_pane_find_by_id(pane);
if (wp == NULL)
goto out;
if (strcmp(split, "on") == 0)
control_set_pane_on(tc, wp);
else if (strcmp(split, "off") == 0)
control_set_pane_off(tc, wp);
else if (strcmp(split, "continue") == 0)
control_continue_pane(tc, wp);
else if (strcmp(split, "pause") == 0)
control_pause_pane(tc, wp);
out:
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 {
c->flags |= CLIENT_STATUSFORCE;
server_redraw_client(c);
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
cmd_refresh_report(struct tty *tty, const char *value)
{
struct window_pane *wp;
u_int pane;
size_t size = 0;
char *copy, *split;
if (*value != '%')
return;
copy = xstrdup(value);
if ((split = strchr(copy, ':')) == NULL)
goto out;
*split++ = '\0';
if (sscanf(copy, "%%%u", &pane) != 1)
goto out;
wp = window_pane_find_by_id(pane);
if (wp == NULL)
goto out;
tty_keys_colours(tty, split, strlen(split), &size, &wp->control_fg,
&wp->control_bg);
out:
free(copy);
}
static enum cmd_retval
cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct tty *tty = &tc->tty;
struct window *w;
const char *errstr;
u_int adjust;
struct args_value *av;
if (args_has(args, 'c') ||
args_has(args, 'L') ||
args_has(args, 'R') ||
args_has(args, 'U') ||
args_has(args, 'D'))
{
if (args_count(args) == 0)
adjust = 1;
else {
adjust = strtonum(args_string(args, 0), 1, INT_MAX,
&errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
}
}
if (args_has(args, 'c'))
tc->pan_window = NULL;
else {
w = tc->session->curw->window;
if (tc->pan_window != w) {
tc->pan_window = w;
tc->pan_ox = tty->oox;
tc->pan_oy = tty->ooy;
}
if (args_has(args, 'L')) {
if (tc->pan_ox > adjust)
tc->pan_ox -= adjust;
else
tc->pan_ox = 0;
} else if (args_has(args, 'R')) {
tc->pan_ox += adjust;
if (tc->pan_ox > w->sx - tty->osx)
tc->pan_ox = w->sx - tty->osx;
} else if (args_has(args, 'U')) {
if (tc->pan_oy > adjust)
tc->pan_oy -= adjust;
else
tc->pan_oy = 0;
} else if (args_has(args, 'D')) {
tc->pan_oy += adjust;
if (tc->pan_oy > w->sy - tty->osy)
tc->pan_oy = w->sy - tty->osy;
}
}
tty_update_client_offset(tc);
server_redraw_client(tc);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'l'))
return (cmd_refresh_client_clipboard(self, item));
if (args_has(args, 'F')) /* -F is an alias for -f */
server_client_set_flags(tc, args_get(args, 'F'));
if (args_has(args, 'f'))
server_client_set_flags(tc, args_get(args, 'f'));
if (args_has(args, 'r'))
cmd_refresh_report(tty, args_get(args, 'r'));
if (args_has(args, 'A')) {
if (~tc->flags & CLIENT_CONTROL)
goto not_control_client;
av = args_first_value(args, 'A');
while (av != NULL) {
cmd_refresh_client_update_offset(tc, av->string);
av = args_next_value(av);
}
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'B')) {
if (~tc->flags & CLIENT_CONTROL)
goto not_control_client;
av = args_first_value(args, 'B');
while (av != NULL) {
cmd_refresh_client_update_subscription(tc, av->string);
av = args_next_value(av);
}
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'C')) {
if (~tc->flags & CLIENT_CONTROL)
goto not_control_client;
return (cmd_refresh_client_control_client_size(self, item));
}
if (args_has(args, 'S')) {
tc->flags |= CLIENT_STATUSFORCE;
server_status_client(tc);
} else {
tc->flags |= CLIENT_STATUSFORCE;
server_redraw_client(tc);
}
return (CMD_RETURN_NORMAL);
not_control_client:
cmdq_error(item, "not a control client");
return (CMD_RETURN_ERROR);
}

View File

@ -34,7 +34,7 @@ const struct cmd_entry cmd_rename_session_entry = {
.name = "rename-session",
.alias = "rename",
.args = { "t:", 1, 1 },
.args = { "t:", 1, 1, NULL },
.usage = CMD_TARGET_SESSION_USAGE " new-name",
.target = { 't', CMD_FIND_SESSION, 0 },
@ -46,22 +46,23 @@ const struct cmd_entry cmd_rename_session_entry = {
static enum cmd_retval
cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = item->target.s;
char *newname;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct session *s = target->s;
char *newname, *tmp;
newname = format_single(item, args->argv[0], c, s, NULL, NULL);
tmp = format_single_from_target(item, args_string(args, 0));
newname = session_check_name(tmp);
if (newname == NULL) {
cmdq_error(item, "invalid session: %s", tmp);
free(tmp);
return (CMD_RETURN_ERROR);
}
free(tmp);
if (strcmp(newname, s->name) == 0) {
free(newname);
return (CMD_RETURN_NORMAL);
}
if (!session_check_name(newname)) {
cmdq_error(item, "bad session name: %s", newname);
free(newname);
return (CMD_RETURN_ERROR);
}
if (session_find(newname) != NULL) {
cmdq_error(item, "duplicate session: %s", newname);
free(newname);

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_rename_window_entry = {
.name = "rename-window",
.alias = "renamew",
.args = { "t:", 1, 1 },
.args = { "t:", 1, 1, NULL },
.usage = CMD_TARGET_WINDOW_USAGE " new-name",
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -45,16 +45,16 @@ const struct cmd_entry cmd_rename_window_entry = {
static enum cmd_retval
cmd_rename_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct winlink *wl = target->wl;
char *newname;
newname = format_single(item, args->argv[0], c, s, wl, NULL);
newname = format_single_from_target(item, args_string(args, 0));
window_set_name(wl->window, newname);
options_set_number(wl->window->options, "automatic-rename", 0);
server_redraw_window_borders(wl->window);
server_status_window(wl->window);
free(newname);

View File

@ -36,8 +36,8 @@ const struct cmd_entry cmd_resize_pane_entry = {
.name = "resize-pane",
.alias = "resizep",
.args = { "DLMRt:Ux:y:Z", 0, 1 },
.usage = "[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
.args = { "DLMRTt:Ux:y:Z", 0, 1, NULL },
.usage = "[-DLMRTUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
"[adjustment]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -49,102 +49,88 @@ const struct cmd_entry cmd_resize_pane_entry = {
static enum cmd_retval
cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct cmdq_shared *shared = item->shared;
struct window_pane *wp = item->target.wp;
struct winlink *wl = item->target.wl;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct key_event *event = cmdq_get_event(item);
struct window_pane *wp = target->wp;
struct winlink *wl = target->wl;
struct window *w = wl->window;
struct client *c = item->client;
struct session *s = item->target.s;
const char *errstr, *p;
char *cause, *copy;
struct client *c = cmdq_get_client(item);
struct session *s = target->s;
const char *errstr;
char *cause;
u_int adjust;
int x, y, percentage;
size_t plen;
int x, y, status;
struct grid *gd = wp->base.grid;
if (args_has(args, 'T')) {
if (!TAILQ_EMPTY(&wp->modes))
return (CMD_RETURN_NORMAL);
adjust = screen_size_y(&wp->base) - 1 - wp->base.cy;
if (adjust > gd->hsize)
adjust = gd->hsize;
grid_remove_history(gd, adjust);
wp->base.cy += adjust;
wp->flags |= PANE_REDRAW;
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'M')) {
if (cmd_mouse_window(&shared->mouse, &s) == NULL)
if (!event->m.valid || cmd_mouse_window(&event->m, &s) == NULL)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
cmd_resize_pane_mouse_update(c, &shared->mouse);
cmd_resize_pane_mouse_update(c, &event->m);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'Z')) {
if (w->flags & WINDOW_ZOOMED)
window_unzoom(w);
window_unzoom(w, 1);
else
window_zoom(wp);
server_redraw_window(w);
server_status_window(w);
return (CMD_RETURN_NORMAL);
}
server_unzoom_window(w);
if (args->argc == 0)
if (args_count(args) == 0)
adjust = 1;
else {
adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
}
}
if ((p = args_get(args, 'x')) != NULL) {
plen = strlen(p);
if (p[plen - 1] == '%') {
copy = xstrdup(p);
copy[plen - 1] = '\0';
percentage = strtonum(copy, 0, INT_MAX, &errstr);
free(copy);
if (errstr != NULL) {
cmdq_error(item, "width %s", errstr);
return (CMD_RETURN_ERROR);
}
x = (w->sx * percentage) / 100;
if (x < PANE_MINIMUM)
x = PANE_MINIMUM;
if (x > INT_MAX)
x = INT_MAX;
} else {
x = args_strtonum(args, 'x', PANE_MINIMUM, INT_MAX,
&cause);
if (args_has(args, 'x')) {
x = args_percentage(args, 'x', 0, INT_MAX, w->sx, &cause);
if (cause != NULL) {
cmdq_error(item, "width %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x);
}
if ((p = args_get(args, 'y')) != NULL) {
plen = strlen(p);
if (p[plen - 1] == '%') {
copy = xstrdup(p);
copy[plen - 1] = '\0';
percentage = strtonum(copy, 0, INT_MAX, &errstr);
free(copy);
if (errstr != NULL) {
cmdq_error(item, "height %s", errstr);
return (CMD_RETURN_ERROR);
}
y = (w->sy * percentage) / 100;
if (y < PANE_MINIMUM)
y = PANE_MINIMUM;
if (y > INT_MAX)
y = INT_MAX;
}
else {
y = args_strtonum(args, 'y', PANE_MINIMUM, INT_MAX,
&cause);
if (args_has(args, 'y')) {
y = args_percentage(args, 'y', 0, INT_MAX, w->sy, &cause);
if (cause != NULL) {
cmdq_error(item, "height %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
status = options_get_number(w->options, "pane-border-status");
switch (status) {
case PANE_STATUS_TOP:
if (y != INT_MAX && wp->yoff == 1)
y++;
break;
case PANE_STATUS_BOTTOM:
if (y != INT_MAX && wp->yoff + wp->sy == w->sy - 1)
y++;
break;
}
layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
}

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_resize_window_entry = {
.name = "resize-window",
.alias = "resizew",
.args = { "aADLRt:Ux:y:", 0, 1 },
.args = { "aADLRt:Ux:y:", 0, 1, NULL },
.usage = "[-aADLRU] [-x width] [-y height] " CMD_TARGET_WINDOW_USAGE " "
"[adjustment]",
@ -46,19 +46,19 @@ const struct cmd_entry cmd_resize_window_entry = {
static enum cmd_retval
cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct winlink *wl = item->target.wl;
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 session *s = item->target.s;
struct session *s = target->s;
const char *errstr;
char *cause;
u_int adjust, sx, sy;
int xpixel = -1, ypixel = -1;
u_int adjust, sx, sy, xpixel = 0, ypixel = 0;
if (args->argc == 0)
if (args_count(args) == 0)
adjust = 1;
else {
adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
@ -107,7 +107,9 @@ cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item)
}
options_set_number(w->options, "window-size", WINDOW_SIZE_MANUAL);
resize_window(w, sx, sy, xpixel, ypixel);
w->manual_sx = sx;
w->manual_sy = sy;
recalculate_size(w, 1);
return (CMD_RETURN_NORMAL);
}

View File

@ -34,9 +34,9 @@ const struct cmd_entry cmd_respawn_pane_entry = {
.name = "respawn-pane",
.alias = "respawnp",
.args = { "c:e:kt:", 0, -1 },
.args = { "c:e:kt:", 0, -1, NULL },
.usage = "[-k] [-c start-directory] [-e environment] "
CMD_TARGET_PANE_USAGE " [command]",
CMD_TARGET_PANE_USAGE " [shell-command [argument ...]]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -47,32 +47,28 @@ const struct cmd_entry cmd_respawn_pane_entry = {
static enum cmd_retval
cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct spawn_context sc;
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct window_pane *wp = item->target.wp;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct spawn_context sc = { 0 };
struct session *s = target->s;
struct winlink *wl = target->wl;
struct window_pane *wp = target->wp;
char *cause = NULL;
const char *add;
struct args_value *value;
struct args_value *av;
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.wl = wl;
sc.wp0 = wp;
sc.lc = NULL;
sc.name = NULL;
sc.argc = args->argc;
sc.argv = args->argv;
args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(sc.environ, add);
add = args_next_value(&value);
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(sc.environ, av->string, 0);
av = args_next_value(av);
}
sc.idx = -1;
@ -85,12 +81,18 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
if (spawn_pane(&sc, &cause) == NULL) {
cmdq_error(item, "respawn 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);
}
wp->flags |= PANE_REDRAW;
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_NORMAL);
}

View File

@ -34,9 +34,9 @@ const struct cmd_entry cmd_respawn_window_entry = {
.name = "respawn-window",
.alias = "respawnw",
.args = { "c:e:kt:", 0, -1 },
.args = { "c:e:kt:", 0, -1, NULL },
.usage = "[-k] [-c start-directory] [-e environment] "
CMD_TARGET_WINDOW_USAGE " [command]",
CMD_TARGET_WINDOW_USAGE " [shell-command [argument ...]]",
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -47,29 +47,27 @@ const struct cmd_entry cmd_respawn_window_entry = {
static enum cmd_retval
cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct spawn_context sc;
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct args *args = cmd_get_args(self);
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;
char *cause = NULL;
const char *add;
struct args_value *value;
struct args_value *av;
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.wl = wl;
sc.c = cmd_find_client(item, NULL, 1);
sc.tc = tc;
sc.name = NULL;
sc.argc = args->argc;
sc.argv = args->argv;
args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(sc.environ, add);
add = args_next_value(&value);
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(sc.environ, av->string, 0);
av = args_next_value(av);
}
sc.idx = -1;
@ -82,11 +80,16 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
if (spawn_window(&sc, &cause) == NULL) {
cmdq_error(item, "respawn window failed: %s", cause);
free(cause);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_ERROR);
}
server_redraw_window(wl->window);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_NORMAL);
}

View File

@ -31,7 +31,7 @@ const struct cmd_entry cmd_rotate_window_entry = {
.name = "rotate-window",
.alias = "rotatew",
.args = { "Dt:UZ", 0, 0 },
.args = { "Dt:UZ", 0, 0, NULL },
.usage = "[-DUZ] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -43,16 +43,18 @@ const struct cmd_entry cmd_rotate_window_entry = {
static enum cmd_retval
cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct cmd_find_state *current = &item->shared->current;
struct winlink *wl = item->target.wl;
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 winlink *wl = target->wl;
struct window *w = wl->window;
struct window_pane *wp, *wp2;
struct layout_cell *lc;
u_int sx, sy, xoff, yoff;
window_push_zoom(w, args_has(self->args, 'Z'));
window_push_zoom(w, 0, args_has(args, 'Z'));
if (args_has(self->args, 'D')) {
if (args_has(args, 'D')) {
wp = TAILQ_LAST(&w->panes, window_panes);
TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);

View File

@ -20,6 +20,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@ -29,8 +30,12 @@
* Runs a command without a window.
*/
static enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmdq_item *);
static enum args_parse_type cmd_run_shell_args_parse(struct args *, u_int,
char **);
static enum cmd_retval cmd_run_shell_exec(struct cmd *,
struct cmdq_item *);
static void cmd_run_shell_timer(int, short, void *);
static void cmd_run_shell_callback(struct job *);
static void cmd_run_shell_free(void *);
static void cmd_run_shell_print(struct job *, const char *);
@ -39,8 +44,9 @@ const struct cmd_entry cmd_run_shell_entry = {
.name = "run-shell",
.alias = "run",
.args = { "bt:", 1, 1 },
.usage = "[-b] " CMD_TARGET_PANE_USAGE " shell-command",
.args = { "bd:Ct:Es:c:", 0, 1, cmd_run_shell_args_parse },
.usage = "[-bCE] [-c start-directory] [-d delay] " CMD_TARGET_PANE_USAGE
" [shell-command]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -49,11 +55,26 @@ const struct cmd_entry cmd_run_shell_entry = {
};
struct cmd_run_shell_data {
struct client *client;
char *cmd;
struct args_command_state *state;
char *cwd;
struct cmdq_item *item;
struct session *s;
int wp_id;
struct event timer;
int flags;
};
static enum args_parse_type
cmd_run_shell_args_parse(struct args *args, __unused u_int idx,
__unused char **cause)
{
if (args_has(args, 'C'))
return (ARGS_PARSE_COMMANDS_OR_STRING);
return (ARGS_PARSE_STRING);
}
static void
cmd_run_shell_print(struct job *job, const char *msg)
{
@ -69,8 +90,9 @@ cmd_run_shell_print(struct job *job, const char *msg)
cmdq_print(cdata->item, "%s", msg);
return;
}
if (cmd_find_from_nothing(&fs, 0) != 0)
return;
if (cdata->item != NULL && cdata->client != NULL)
wp = server_client_get_pane(cdata->client);
if (wp == NULL && cmd_find_from_nothing(&fs, 0) == 0)
wp = fs.wp;
if (wp == NULL)
return;
@ -78,54 +100,143 @@ cmd_run_shell_print(struct job *job, const char *msg)
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode != &window_view_mode)
window_pane_set_mode(wp, &window_view_mode, NULL, NULL);
window_copy_add(wp, "%s", msg);
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL);
window_copy_add(wp, 1, "%s", msg);
}
static enum cmd_retval
cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct cmd_run_shell_data *cdata;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct window_pane *wp = item->target.wp;
struct client *c = cmdq_get_client(item);
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct window_pane *wp = target->wp;
const char *delay, *cmd;
double d;
struct timeval tv;
char *end;
int wait = !args_has(args, 'b');
if ((delay = args_get(args, 'd')) != NULL) {
d = strtod(delay, &end);
if (*end != '\0') {
cmdq_error(item, "invalid delay time: %s", delay);
return (CMD_RETURN_ERROR);
}
} else if (args_count(args) == 0)
return (CMD_RETURN_NORMAL);
cdata = xcalloc(1, sizeof *cdata);
cdata->cmd = format_single(item, args->argv[0], c, s, wl, wp);
if (!args_has(args, 'C')) {
cmd = args_string(args, 0);
if (cmd != NULL)
cdata->cmd = format_single_from_target(item, cmd);
} else {
cdata->state = args_make_commands_prepare(self, item, 0, NULL,
wait, 1);
}
if (args_has(args, 't') && wp != NULL)
cdata->wp_id = wp->id;
else
cdata->wp_id = -1;
if (!args_has(args, 'b'))
if (wait) {
cdata->client = c;
cdata->item = item;
if (job_run(cdata->cmd, s, server_client_get_cwd(item->client, s), NULL,
cmd_run_shell_callback, cmd_run_shell_free, cdata, 0) == NULL) {
cmdq_error(item, "failed to run command: %s", cdata->cmd);
free(cdata);
return (CMD_RETURN_ERROR);
} else {
cdata->client = tc;
cdata->flags |= JOB_NOWAIT;
}
if (cdata->client != NULL)
cdata->client->references++;
if (args_has(args, 'c'))
cdata->cwd = xstrdup(args_get(args, 'c'));
else
cdata->cwd = xstrdup(server_client_get_cwd(c, s));
if (args_has(args, 'b'))
if (args_has(args, 'E'))
cdata->flags |= JOB_SHOWSTDERR;
cdata->s = s;
if (s != NULL)
session_add_ref(s, __func__);
evtimer_set(&cdata->timer, cmd_run_shell_timer, cdata);
if (delay != NULL) {
timerclear(&tv);
tv.tv_sec = (time_t)d;
tv.tv_usec = (d - (double)tv.tv_sec) * 1000000U;
evtimer_add(&cdata->timer, &tv);
} else
event_active(&cdata->timer, EV_TIMEOUT, 1);
if (!wait)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
static void
cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
{
struct cmd_run_shell_data *cdata = arg;
struct client *c = cdata->client;
const char *cmd = cdata->cmd;
struct cmdq_item *item = cdata->item, *new_item;
struct cmd_list *cmdlist;
char *error;
if (cdata->state == NULL) {
if (cmd == NULL) {
if (cdata->item != NULL)
cmdq_continue(cdata->item);
cmd_run_shell_free(cdata);
return;
}
if (job_run(cmd, 0, NULL, NULL, cdata->s, cdata->cwd, NULL,
cmd_run_shell_callback, cmd_run_shell_free, cdata,
cdata->flags, -1, -1) == NULL)
cmd_run_shell_free(cdata);
return;
}
cmdlist = args_make_commands(cdata->state, 0, NULL, &error);
if (cmdlist == NULL) {
if (cdata->item == NULL) {
*error = toupper((u_char)*error);
status_message_set(c, -1, 1, 0, 0, "%s", error);
} else
cmdq_error(cdata->item, "%s", error);
free(error);
} else if (item == NULL) {
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
} else {
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
}
if (cdata->item != NULL)
cmdq_continue(cdata->item);
cmd_run_shell_free(cdata);
}
static void
cmd_run_shell_callback(struct job *job)
{
struct cmd_run_shell_data *cdata = job_get_data(job);
struct bufferevent *event = job_get_event(job);
struct cmdq_item *item = cdata->item;
char *cmd = cdata->cmd, *msg = NULL, *line;
size_t size;
int retcode, status;
do {
if ((line = evbuffer_readline(event->input)) != NULL) {
line = evbuffer_readln(event->input, NULL, EVBUFFER_EOL_LF);
if (line != NULL) {
cmd_run_shell_print(job, line);
free(line);
}
@ -149,13 +260,19 @@ cmd_run_shell_callback(struct job *job)
} else if (WIFSIGNALED(status)) {
retcode = WTERMSIG(status);
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
}
retcode += 128;
} else
retcode = 0;
if (msg != NULL)
cmd_run_shell_print(job, msg);
free(msg);
if (cdata->item != NULL)
cmdq_continue(cdata->item);
if (item != NULL) {
if (cmdq_get_client(item) != NULL &&
cmdq_get_client(item)->session == NULL)
cmdq_get_client(item)->retval = retcode;
cmdq_continue(item);
}
}
static void
@ -163,6 +280,14 @@ cmd_run_shell_free(void *data)
{
struct cmd_run_shell_data *cdata = data;
evtimer_del(&cdata->timer);
if (cdata->s != NULL)
session_remove_ref(cdata->s, __func__);
if (cdata->client != NULL)
server_client_unref(cdata->client);
if (cdata->state != NULL)
args_make_commands_free(cdata->state);
free(cdata->cwd);
free(cdata->cmd);
free(cdata);
}

View File

@ -37,7 +37,7 @@ const struct cmd_entry cmd_save_buffer_entry = {
.name = "save-buffer",
.alias = "saveb",
.args = { "ab:", 1, 1 },
.args = { "ab:", 1, 1, NULL },
.usage = "[-a] " CMD_BUFFER_USAGE " path",
.flags = CMD_AFTERHOOK,
@ -48,7 +48,7 @@ const struct cmd_entry cmd_show_buffer_entry = {
.name = "show-buffer",
.alias = "showb",
.args = { "b:", 0, 0 },
.args = { "b:", 0, 0, NULL },
.usage = CMD_BUFFER_USAGE,
.flags = CMD_AFTERHOOK,
@ -72,16 +72,14 @@ cmd_save_buffer_done(__unused struct client *c, const char *path, int error,
static enum cmd_retval
cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct window_pane *wp = item->target.wp;
struct args *args = cmd_get_args(self);
struct client *c = cmdq_get_client(item);
struct paste_buffer *pb;
int flags;
const char *bufname = args_get(args, 'b'), *bufdata;
size_t bufsize;
char *path;
struct evbuffer *evb;
if (bufname == NULL) {
if ((pb = paste_get_top(NULL)) == NULL) {
@ -97,15 +95,24 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item)
}
bufdata = paste_buffer_data(pb, &bufsize);
if (self->entry == &cmd_show_buffer_entry)
if (cmd_get_entry(self) == &cmd_show_buffer_entry) {
if (c->session != NULL || (c->flags & CLIENT_CONTROL)) {
evb = evbuffer_new();
if (evb == NULL)
fatalx("out of memory");
evbuffer_add(evb, bufdata, bufsize);
cmdq_print_data(item, evb);
evbuffer_free(evb);
return (CMD_RETURN_NORMAL);
}
path = xstrdup("-");
else
path = format_single(item, args->argv[0], c, s, wl, wp);
if (args_has(self->args, 'a'))
} else
path = format_single_from_target(item, args_string(args, 0));
if (args_has(args, 'a'))
flags = O_APPEND;
else
flags = 0;
file_write(item->client, path, flags, bufdata, bufsize,
flags = O_TRUNC;
file_write(cmdq_get_client(item), path, flags, bufdata, bufsize,
cmd_save_buffer_done, item);
free(path);

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_select_layout_entry = {
.name = "select-layout",
.alias = "selectl",
.args = { "Enopt:", 0, 1 },
.args = { "Enopt:", 0, 1, NULL },
.usage = "[-Enop] " CMD_TARGET_PANE_USAGE " [layout-name]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -46,7 +46,7 @@ const struct cmd_entry cmd_next_layout_entry = {
.name = "next-layout",
.alias = "nextl",
.args = { "t:", 0, 0 },
.args = { "t:", 0, 0, NULL },
.usage = CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -59,7 +59,7 @@ const struct cmd_entry cmd_previous_layout_entry = {
.name = "previous-layout",
.alias = "prevl",
.args = { "t:", 0, 0 },
.args = { "t:", 0, 0, NULL },
.usage = CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -71,20 +71,21 @@ const struct cmd_entry cmd_previous_layout_entry = {
static enum cmd_retval
cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct winlink *wl = item->target.wl;
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 = item->target.wp;
struct window_pane *wp = target->wp;
const char *layoutname;
char *oldlayout;
char *oldlayout, *cause;
int next, previous, layout;
server_unzoom_window(w);
next = self->entry == &cmd_next_layout_entry;
next = (cmd_get_entry(self) == &cmd_next_layout_entry);
if (args_has(args, 'n'))
next = 1;
previous = self->entry == &cmd_previous_layout_entry;
previous = (cmd_get_entry(self) == &cmd_previous_layout_entry);
if (args_has(args, 'p'))
previous = 1;
@ -104,27 +105,28 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
goto changed;
}
if (args_count(args) != 0)
layoutname = args_string(args, 0);
else if (args_has(args, 'o'))
layoutname = oldlayout;
else
layoutname = NULL;
if (!args_has(args, 'o')) {
if (args->argc == 0)
if (layoutname == NULL)
layout = w->lastlayout;
else
layout = layout_set_lookup(args->argv[0]);
layout = layout_set_lookup(layoutname);
if (layout != -1) {
layout_set_select(w, layout);
goto changed;
}
}
if (args->argc != 0)
layoutname = args->argv[0];
else if (args_has(args, 'o'))
layoutname = oldlayout;
else
layoutname = NULL;
if (layoutname != NULL) {
if (layout_parse(w, layoutname) == -1) {
cmdq_error(item, "can't set layout: %s", layoutname);
if (layout_parse(w, layoutname, &cause) == -1) {
cmdq_error(item, "%s: %s", cause, layoutname);
free(cause);
goto error;
}
goto changed;

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_select_pane_entry = {
.name = "select-pane",
.alias = "selectp",
.args = { "DdegLlMmP:RT:t:UZ", 0, 0 }, /* -P and -g deprecated */
.args = { "DdegLlMmP:RT:t:UZ", 0, 0, NULL }, /* -P and -g deprecated */
.usage = "[-DdeLlMmRUZ] [-T title] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -46,7 +46,7 @@ const struct cmd_entry cmd_last_pane_entry = {
.name = "last-pane",
.alias = "lastp",
.args = { "det:Z", 0, 0 },
.args = { "det:Z", 0, 0, NULL },
.usage = "[-deZ] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -83,20 +83,26 @@ cmd_select_pane_redraw(struct window *w)
static enum cmd_retval
cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct cmd_find_state *current = &item->shared->current;
struct client *c = cmd_find_client(item, NULL, 1);
struct winlink *wl = item->target.wl;
struct args *args = cmd_get_args(self);
const struct cmd_entry *entry = cmd_get_entry(self);
struct cmd_find_state *current = cmdq_get_current(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct client *c = cmdq_get_client(item);
struct winlink *wl = target->wl;
struct window *w = wl->window;
struct session *s = item->target.s;
struct window_pane *wp = item->target.wp, *lastwp, *markedwp;
char *pane_title;
struct session *s = target->s;
struct window_pane *wp = target->wp, *activewp, *lastwp, *markedwp;
struct options *oo = wp->options;
char *title;
const char *style;
struct style *sy;
struct options_entry *o;
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
lastwp = w->last;
if (entry == &cmd_last_pane_entry || args_has(args, 'l')) {
/*
* Check for no last pane found in case the other pane was
* spawned without being visited (for example split-window -d).
*/
lastwp = TAILQ_FIRST(&w->last_panes);
if (lastwp == NULL && window_count_panes(w) == 2) {
lastwp = TAILQ_PREV(w->active, window_panes, entry);
if (lastwp == NULL)
@ -106,12 +112,16 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "no last pane");
return (CMD_RETURN_ERROR);
}
if (args_has(self->args, 'e'))
if (args_has(args, 'e')) {
lastwp->flags &= ~PANE_INPUTOFF;
else if (args_has(self->args, 'd'))
server_redraw_window_borders(lastwp->window);
server_status_window(lastwp->window);
} else if (args_has(args, 'd')) {
lastwp->flags |= PANE_INPUTOFF;
else {
if (window_push_zoom(w, args_has(self->args, 'Z')))
server_redraw_window_borders(lastwp->window);
server_status_window(lastwp->window);
} else {
if (window_push_zoom(w, 0, args_has(args, 'Z')))
server_redraw_window(w);
window_redraw_active_switch(w, lastwp);
if (window_set_active_pane(w, lastwp, 1)) {
@ -127,7 +137,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'm') || args_has(args, 'M')) {
if (args_has(args, 'm') && !window_pane_visible(wp))
return (CMD_RETURN_NORMAL);
if (server_check_marked())
lastwp = marked_pane.wp;
else
lastwp = NULL;
if (args_has(args, 'M') || server_is_marked(s, wl, wp))
server_clear_marked();
@ -136,83 +149,94 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
markedwp = marked_pane.wp;
if (lastwp != NULL) {
lastwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|
PANE_THEMECHANGED);
server_redraw_window_borders(lastwp->window);
server_status_window(lastwp->window);
}
if (markedwp != NULL) {
markedwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|
PANE_THEMECHANGED);
server_redraw_window_borders(markedwp->window);
server_status_window(markedwp->window);
}
return (CMD_RETURN_NORMAL);
}
if (args_has(self->args, 'P') || args_has(self->args, 'g')) {
if ((style = args_get(args, 'P')) != NULL) {
o = options_set_style(wp->options, "window-style", 0,
style);
style = args_get(args, 'P');
if (style != NULL) {
o = options_set_string(oo, "window-style", 0, "%s", style);
if (o == NULL) {
cmdq_error(item, "bad style: %s", style);
return (CMD_RETURN_ERROR);
}
options_set_style(wp->options, "window-active-style", 0,
style);
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
}
if (args_has(self->args, 'g')) {
sy = options_get_style(wp->options, "window-style");
cmdq_print(item, "%s", style_tostring(sy));
options_set_string(oo, "window-active-style", 0, "%s", style);
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|PANE_THEMECHANGED);
}
if (args_has(args, 'g')) {
cmdq_print(item, "%s", options_get_string(oo, "window-style"));
return (CMD_RETURN_NORMAL);
}
if (args_has(self->args, 'L')) {
window_push_zoom(w, 1);
if (args_has(args, 'L')) {
window_push_zoom(w, 0, 1);
wp = window_pane_find_left(wp);
window_pop_zoom(w);
} else if (args_has(self->args, 'R')) {
window_push_zoom(w, 1);
} else if (args_has(args, 'R')) {
window_push_zoom(w, 0, 1);
wp = window_pane_find_right(wp);
window_pop_zoom(w);
} else if (args_has(self->args, 'U')) {
window_push_zoom(w, 1);
} else if (args_has(args, 'U')) {
window_push_zoom(w, 0, 1);
wp = window_pane_find_up(wp);
window_pop_zoom(w);
} else if (args_has(self->args, 'D')) {
window_push_zoom(w, 1);
} else if (args_has(args, 'D')) {
window_push_zoom(w, 0, 1);
wp = window_pane_find_down(wp);
window_pop_zoom(w);
}
if (wp == NULL)
return (CMD_RETURN_NORMAL);
if (args_has(self->args, 'e')) {
if (args_has(args, 'e')) {
wp->flags &= ~PANE_INPUTOFF;
return (CMD_RETURN_NORMAL);
}
if (args_has(self->args, 'd')) {
wp->flags |= PANE_INPUTOFF;
return (CMD_RETURN_NORMAL);
}
if (args_has(self->args, 'T')) {
pane_title = format_single(item, args_get(self->args, 'T'),
c, s, wl, wp);
if (screen_set_title(&wp->base, pane_title))
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'd')) {
wp->flags |= PANE_INPUTOFF;
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
free(pane_title);
return (CMD_RETURN_NORMAL);
}
if (wp == w->active)
if (args_has(args, 'T')) {
title = format_single_from_target(item, args_get(args, 'T'));
if (screen_set_title(&wp->base, title)) {
notify_pane("pane-title-changed", wp);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
}
free(title);
return (CMD_RETURN_NORMAL);
if (window_push_zoom(w, args_has(self->args, 'Z')))
}
if (c != NULL && c->session != NULL && (c->flags & CLIENT_ACTIVEPANE))
activewp = server_client_get_pane(c);
else
activewp = w->active;
if (wp == activewp)
return (CMD_RETURN_NORMAL);
if (window_push_zoom(w, 0, args_has(args, 'Z')))
server_redraw_window(w);
window_redraw_active_switch(w, wp);
if (window_set_active_pane(w, wp, 1)) {
if (c != NULL && c->session != NULL && (c->flags & CLIENT_ACTIVEPANE))
server_client_set_pane(c, wp);
else if (window_set_active_pane(w, wp, 1))
cmd_find_from_winlink_pane(current, wl, wp, 0);
cmdq_insert_hook(s, item, current, "after-select-pane");
cmd_select_pane_redraw(w);
}
if (window_pop_zoom(w))
server_redraw_window(w);

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_select_window_entry = {
.name = "select-window",
.alias = "selectw",
.args = { "lnpTt:", 0, 0 },
.args = { "lnpTt:", 0, 0, NULL },
.usage = "[-lnpT] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -46,7 +46,7 @@ const struct cmd_entry cmd_next_window_entry = {
.name = "next-window",
.alias = "next",
.args = { "at:", 0, 0 },
.args = { "at:", 0, 0, NULL },
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -59,7 +59,7 @@ const struct cmd_entry cmd_previous_window_entry = {
.name = "previous-window",
.alias = "prev",
.args = { "at:", 0, 0 },
.args = { "at:", 0, 0, NULL },
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -72,7 +72,7 @@ const struct cmd_entry cmd_last_window_entry = {
.name = "last-window",
.alias = "last",
.args = { "t:", 0, 0 },
.args = { "t:", 0, 0, NULL },
.usage = CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -84,23 +84,26 @@ const struct cmd_entry cmd_last_window_entry = {
static enum cmd_retval
cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct cmd_find_state *current = &item->shared->current;
struct winlink *wl = item->target.wl;
struct session *s = item->target.s;
struct args *args = cmd_get_args(self);
struct client *c = cmdq_get_client(item);
struct cmd_find_state *current = cmdq_get_current(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct winlink *wl = target->wl;
struct session *s = target->s;
int next, previous, last, activity;
next = self->entry == &cmd_next_window_entry;
if (args_has(self->args, 'n'))
next = (cmd_get_entry(self) == &cmd_next_window_entry);
if (args_has(args, 'n'))
next = 1;
previous = self->entry == &cmd_previous_window_entry;
if (args_has(self->args, 'p'))
previous = (cmd_get_entry(self) == &cmd_previous_window_entry);
if (args_has(args, 'p'))
previous = 1;
last = self->entry == &cmd_last_window_entry;
if (args_has(self->args, 'l'))
last = (cmd_get_entry(self) == &cmd_last_window_entry);
if (args_has(args, 'l'))
last = 1;
if (next || previous || last) {
activity = args_has(self->args, 'a');
activity = args_has(args, 'a');
if (next) {
if (session_next(s, activity) != 0) {
cmdq_error(item, "no next window");
@ -125,7 +128,7 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
* If -T and select-window is invoked on same window as
* current, switch to previous window.
*/
if (args_has(self->args, 'T') && wl == s->curw) {
if (args_has(args, 'T') && wl == s->curw) {
if (session_last(s) != 0) {
cmdq_error(item, "no last window");
return (-1);
@ -139,6 +142,8 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
}
cmdq_insert_hook(s, item, current, "after-select-window");
}
if (c != NULL && c->session != NULL)
s->curw->window->latest = c;
recalculate_sizes();
return (CMD_RETURN_NORMAL);

View File

@ -33,13 +33,13 @@ const struct cmd_entry cmd_send_keys_entry = {
.name = "send-keys",
.alias = "send",
.args = { "FHlMN:Rt:X", 0, -1 },
.usage = "[-FHlMRX] [-N repeat-count] " CMD_TARGET_PANE_USAGE
" key ...",
.args = { "c:FHKlMN:Rt:X", 0, -1, NULL },
.usage = "[-FHKlMRX] [-c target-client] [-N repeat-count] "
CMD_TARGET_PANE_USAGE " [key ...]",
.target = { 't', CMD_FIND_PANE, 0 },
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL,
.exec = cmd_send_keys_exec
};
@ -47,7 +47,7 @@ const struct cmd_entry cmd_send_prefix_entry = {
.name = "send-prefix",
.alias = NULL,
.args = { "2t:", 0, 0 },
.args = { "2t:", 0, 0, NULL },
.usage = "[-2] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -57,43 +57,56 @@ const struct cmd_entry cmd_send_prefix_entry = {
};
static struct cmdq_item *
cmd_send_keys_inject_key(struct client *c, struct cmd_find_state *fs,
struct cmdq_item *item, key_code key)
cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
struct args *args, key_code key)
{
struct session *s = fs->s;
struct winlink *wl = fs->wl;
struct window_pane *wp = fs->wp;
struct cmd_find_state *target = cmdq_get_target(item);
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct winlink *wl = target->wl;
struct window_pane *wp = target->wp;
struct window_mode_entry *wme;
struct key_table *table;
struct key_table *table = NULL;
struct key_binding *bd;
struct key_event *event;
wme = TAILQ_FIRST(&fs->wp->modes);
if (args_has(args, 'K')) {
if (tc == NULL)
return (item);
event = xcalloc(1, sizeof *event);
event->key = key|KEYC_SENT;
memset(&event->m, 0, sizeof event->m);
if (server_client_handle_key(tc, event) == 0) {
free(event->buf);
free(event);
}
return (item);
}
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode->key_table == NULL) {
if (options_get_number(fs->wp->window->options, "xterm-keys"))
key |= KEYC_XTERM;
if (window_pane_key(wp, item->client, s, wl, key, NULL) != 0)
if (window_pane_key(wp, tc, s, wl, key, NULL) != 0)
return (NULL);
return (item);
}
table = key_bindings_get_table(wme->mode->key_table(wme), 1);
bd = key_bindings_get(table, key & ~KEYC_XTERM);
bd = key_bindings_get(table, key & ~KEYC_MASK_FLAGS);
if (bd != NULL) {
table->references++;
item = key_bindings_dispatch(bd, item, c, NULL, &item->target);
after = key_bindings_dispatch(bd, after, tc, NULL, target);
key_bindings_unref_table(table);
}
return (item);
return (after);
}
static struct cmdq_item *
cmd_send_keys_inject_string(struct client *c, struct cmd_find_state *fs,
struct cmdq_item *item, struct args *args, int i)
cmd_send_keys_inject_string(struct cmdq_item *item, struct cmdq_item *after,
struct args *args, int i)
{
const char *s = args->argv[i];
struct cmdq_item *new_item;
struct utf8_data *ud, *uc;
wchar_t wc;
const char *s = args_string(args, i);
struct utf8_data *ud, *loop;
utf8_char uc;
key_code key;
char *endptr;
long n;
@ -103,56 +116,67 @@ cmd_send_keys_inject_string(struct client *c, struct cmd_find_state *fs,
n = strtol(s, &endptr, 16);
if (*s =='\0' || n < 0 || n > 0xff || *endptr != '\0')
return (item);
return (cmd_send_keys_inject_key(c, fs, item, KEYC_LITERAL|n));
return (cmd_send_keys_inject_key(item, after, args,
KEYC_LITERAL|n));
}
literal = args_has(args, 'l');
if (!literal) {
key = key_string_lookup_string(s);
if (key != KEYC_NONE && key != KEYC_UNKNOWN) {
new_item = cmd_send_keys_inject_key(c, fs, item, key);
if (new_item != NULL)
return (new_item);
after = cmd_send_keys_inject_key(item, after, args,
key);
if (after != NULL)
return (after);
}
literal = 1;
}
if (literal) {
ud = utf8_fromcstr(s);
for (uc = ud; uc->size != 0; uc++) {
if (utf8_combine(uc, &wc) != UTF8_DONE)
for (loop = ud; loop->size != 0; loop++) {
if (loop->size == 1 && loop->data[0] <= 0x7f)
key = loop->data[0];
else {
if (utf8_from_data(loop, &uc) != UTF8_DONE)
continue;
item = cmd_send_keys_inject_key(c, fs, item, wc);
key = uc;
}
after = cmd_send_keys_inject_key(item, after, args,
key);
}
free(ud);
}
return (item);
return (after);
}
static enum cmd_retval
cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c = cmd_find_client(item, NULL, 1);
struct cmd_find_state *fs = &item->target;
struct window_pane *wp = item->target.wp;
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct mouse_event *m = &item->shared->mouse;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct winlink *wl = target->wl;
struct window_pane *wp = target->wp;
struct key_event *event = cmdq_get_event(item);
struct mouse_event *m = &event->m;
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
int i;
struct cmdq_item *after = item;
key_code key;
u_int np = 1;
u_int i, np = 1;
u_int count = args_count(args);
char *cause = NULL;
if (args_has(args, 'N')) {
np = args_strtonum(args, 'N', 1, UINT_MAX, &cause);
np = args_strtonum_and_expand(args, 'N', 1, UINT_MAX, item,
&cause);
if (cause != NULL) {
cmdq_error(item, "repeat count %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (wme != NULL && (args_has(args, 'X') || args->argc == 0)) {
if (wme == NULL || wme->mode->command == NULL) {
if (wme != NULL && (args_has(args, 'X') || count == 0)) {
if (wme->mode->command == NULL) {
cmdq_error(item, "not in a mode");
return (CMD_RETURN_ERROR);
}
@ -167,7 +191,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
}
if (!m->valid)
m = NULL;
wme->mode->command(wme, c, s, wl, args, m);
wme->mode->command(wme, tc, s, wl, args, m);
return (CMD_RETURN_NORMAL);
}
@ -177,27 +201,38 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "no mouse target");
return (CMD_RETURN_ERROR);
}
window_pane_key(wp, item->client, s, wl, m->key, m);
window_pane_key(wp, tc, s, wl, m->key, m);
return (CMD_RETURN_NORMAL);
}
if (self->entry == &cmd_send_prefix_entry) {
if (cmd_get_entry(self) == &cmd_send_prefix_entry) {
if (args_has(args, '2'))
key = options_get_number(s->options, "prefix2");
else
key = options_get_number(s->options, "prefix");
cmd_send_keys_inject_key(c, fs, item, key);
cmd_send_keys_inject_key(item, item, args, key);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'R')) {
window_pane_reset_palette(wp);
input_reset(wp, 1);
colour_palette_clear(&wp->palette);
input_reset(wp->ictx, 1);
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED|PANE_REDRAW);
}
if (count == 0) {
if (args_has(args, 'N') || args_has(args, 'R'))
return (CMD_RETURN_NORMAL);
for (; np != 0; np--)
cmd_send_keys_inject_key(item, NULL, args, event->key);
return (CMD_RETURN_NORMAL);
}
for (; np != 0; np--) {
for (i = 0; i < args->argc; i++)
item = cmd_send_keys_inject_string(c, fs, item, args, i);
for (i = 0; i < count; i++) {
after = cmd_send_keys_inject_string(item, after, args,
i);
}
}
return (CMD_RETURN_NORMAL);

147
cmd-server-access.c Normal file
View File

@ -0,0 +1,147 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2021 Dallas Lyons <dallasdlyons@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/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "tmux.h"
/*
* Controls access to session.
*/
static enum cmd_retval cmd_server_access_exec(struct cmd *, struct cmdq_item *);
const struct cmd_entry cmd_server_access_entry = {
.name = "server-access",
.alias = NULL,
.args = { "adlrw", 0, 1, NULL },
.usage = "[-adlrw] " CMD_TARGET_PANE_USAGE " [user]",
.flags = CMD_CLIENT_CANFAIL,
.exec = cmd_server_access_exec
};
static enum cmd_retval
cmd_server_access_deny(struct cmdq_item *item, struct passwd *pw)
{
struct client *loop;
struct server_acl_user *user;
uid_t uid;
if ((user = server_acl_user_find(pw->pw_uid)) == NULL) {
cmdq_error(item, "user %s not found", pw->pw_name);
return (CMD_RETURN_ERROR);
}
TAILQ_FOREACH(loop, &clients, entry) {
uid = proc_get_peer_uid(loop->peer);
if (uid == server_acl_get_uid(user)) {
loop->exit_message = xstrdup("access not allowed");
loop->flags |= CLIENT_EXIT;
}
}
server_acl_user_deny(pw->pw_uid);
return (CMD_RETURN_NORMAL);
}
static enum cmd_retval
cmd_server_access_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *c = cmdq_get_target_client(item);
char *name;
struct passwd *pw = NULL;
if (args_has(args, 'l')) {
server_acl_display(item);
return (CMD_RETURN_NORMAL);
}
if (args_count(args) == 0) {
cmdq_error(item, "missing user argument");
return (CMD_RETURN_ERROR);
}
name = format_single(item, args_string(args, 0), c, NULL, NULL, NULL);
if (*name != '\0')
pw = getpwnam(name);
if (pw == NULL) {
cmdq_error(item, "unknown user: %s", name);
return (CMD_RETURN_ERROR);
}
free(name);
if (pw->pw_uid == 0 || pw->pw_uid == getuid()) {
cmdq_error(item, "%s owns the server, can't change access",
pw->pw_name);
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'a') && args_has(args, 'd')) {
cmdq_error(item, "-a and -d cannot be used together");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'w') && args_has(args, 'r')) {
cmdq_error(item, "-r and -w cannot be used together");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'd'))
return (cmd_server_access_deny(item, pw));
if (args_has(args, 'a')) {
if (server_acl_user_find(pw->pw_uid) != NULL) {
cmdq_error(item, "user %s is already added",
pw->pw_name);
return (CMD_RETURN_ERROR);
}
server_acl_user_allow(pw->pw_uid);
/* Do not return - allow -r or -w with -a. */
} else if (args_has(args, 'r') || args_has(args, 'w')) {
/* -r or -w implies -a if user does not exist. */
if (server_acl_user_find(pw->pw_uid) == NULL)
server_acl_user_allow(pw->pw_uid);
}
if (args_has(args, 'w')) {
if (server_acl_user_find(pw->pw_uid) == NULL) {
cmdq_error(item, "user %s not found", pw->pw_name);
return (CMD_RETURN_ERROR);
}
server_acl_user_allow_write(pw->pw_uid);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'r')) {
if (server_acl_user_find(pw->pw_uid) == NULL) {
cmdq_error(item, "user %s not found", pw->pw_name);
return (CMD_RETURN_ERROR);
}
server_acl_user_deny_write(pw->pw_uid);
return (CMD_RETURN_NORMAL);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -33,10 +33,11 @@ const struct cmd_entry cmd_set_buffer_entry = {
.name = "set-buffer",
.alias = "setb",
.args = { "ab:n:", 0, 1 },
.usage = "[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
.args = { "ab:t:n:w", 0, 1, NULL },
.usage = "[-aw] " CMD_BUFFER_USAGE " [-n new-buffer-name] "
CMD_TARGET_CLIENT_USAGE " [data]",
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG|CMD_CLIENT_CANFAIL,
.exec = cmd_set_buffer_exec
};
@ -44,7 +45,7 @@ const struct cmd_entry cmd_delete_buffer_entry = {
.name = "delete-buffer",
.alias = "deleteb",
.args = { "b:", 0, 0 },
.args = { "b:", 0, 0, NULL },
.usage = CMD_BUFFER_USAGE,
.flags = CMD_AFTERHOOK,
@ -54,7 +55,8 @@ const struct cmd_entry cmd_delete_buffer_entry = {
static enum cmd_retval
cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct paste_buffer *pb;
char *bufdata, *cause;
const char *bufname, *olddata;
@ -66,9 +68,14 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
else
pb = paste_get_name(bufname);
if (self->entry == &cmd_delete_buffer_entry) {
if (pb == NULL)
if (cmd_get_entry(self) == &cmd_delete_buffer_entry) {
if (pb == NULL) {
if (bufname != NULL) {
cmdq_error(item, "unknown buffer: %s", bufname);
return (CMD_RETURN_ERROR);
}
pb = paste_get_top(&bufname);
}
if (pb == NULL) {
cmdq_error(item, "no buffer");
return (CMD_RETURN_ERROR);
@ -78,8 +85,13 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
}
if (args_has(args, 'n')) {
if (pb == NULL)
if (pb == NULL) {
if (bufname != NULL) {
cmdq_error(item, "unknown buffer: %s", bufname);
return (CMD_RETURN_ERROR);
}
pb = paste_get_top(&bufname);
}
if (pb == NULL) {
cmdq_error(item, "no buffer");
return (CMD_RETURN_ERROR);
@ -92,11 +104,11 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args->argc != 1) {
if (args_count(args) != 1) {
cmdq_error(item, "no data specified");
return (CMD_RETURN_ERROR);
}
if ((newsize = strlen(args->argv[0])) == 0)
if ((newsize = strlen(args_string(args, 0))) == 0)
return (CMD_RETURN_NORMAL);
bufsize = 0;
@ -109,7 +121,7 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
}
bufdata = xrealloc(bufdata, bufsize + newsize);
memcpy(bufdata + bufsize, args->argv[0], newsize);
memcpy(bufdata + bufsize, args_string(args, 0), newsize);
bufsize += newsize;
if (paste_set(bufdata, bufsize, bufname, &cause) != 0) {
@ -118,6 +130,8 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
free(cause);
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'w') && tc != NULL)
tty_set_selection(&tc->tty, "", bufdata, bufsize);
return (CMD_RETURN_NORMAL);
}

View File

@ -34,8 +34,8 @@ const struct cmd_entry cmd_set_environment_entry = {
.name = "set-environment",
.alias = "setenv",
.args = { "grt:u", 1, 2 },
.usage = "[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
.args = { "Fhgrt:u", 1, 2, NULL },
.usage = "[-Fhgru] " CMD_TARGET_SESSION_USAGE " variable [value]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
@ -46,11 +46,14 @@ const struct cmd_entry cmd_set_environment_entry = {
static enum cmd_retval
cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct environ *env;
const char *name, *value, *target;
const char *name = args_string(args, 0), *value;
const char *tflag;
char *expanded = NULL;
enum cmd_retval retval = CMD_RETURN_NORMAL;
name = args->argv[0];
if (*name == '\0') {
cmdq_error(item, "empty variable name");
return (CMD_RETURN_ERROR);
@ -60,44 +63,57 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
if (args->argc < 2)
if (args_count(args) < 2)
value = NULL;
else
value = args->argv[1];
if (args_has(self->args, 'g'))
value = args_string(args, 1);
if (value != NULL && args_has(args, 'F')) {
expanded = format_single_from_target(item, value);
value = expanded;
}
if (args_has(args, 'g'))
env = global_environ;
else {
if (item->target.s == NULL) {
target = args_get(args, 't');
if (target != NULL)
cmdq_error(item, "no such session: %s", target);
if (target->s == NULL) {
tflag = args_get(args, 't');
if (tflag != NULL)
cmdq_error(item, "no such session: %s", tflag);
else
cmdq_error(item, "no current session");
return (CMD_RETURN_ERROR);
retval = CMD_RETURN_ERROR;
goto out;
}
env = item->target.s->environ;
env = target->s->environ;
}
if (args_has(self->args, 'u')) {
if (args_has(args, 'u')) {
if (value != NULL) {
cmdq_error(item, "can't specify a value with -u");
return (CMD_RETURN_ERROR);
retval = CMD_RETURN_ERROR;
goto out;
}
environ_unset(env, name);
} else if (args_has(self->args, 'r')) {
} else if (args_has(args, 'r')) {
if (value != NULL) {
cmdq_error(item, "can't specify a value with -r");
return (CMD_RETURN_ERROR);
retval = CMD_RETURN_ERROR;
goto out;
}
environ_clear(env, name);
} else {
if (value == NULL) {
cmdq_error(item, "no value specified");
return (CMD_RETURN_ERROR);
}
environ_set(env, name, "%s", value);
retval = CMD_RETURN_ERROR;
goto out;
}
return (CMD_RETURN_NORMAL);
if (args_has(args, 'h'))
environ_set(env, name, ENVIRON_HIDDEN, "%s", value);
else
environ_set(env, name, 0, "%s", value);
}
out:
free(expanded);
return (retval);
}

View File

@ -18,7 +18,6 @@
#include <sys/types.h>
#include <fnmatch.h>
#include <stdlib.h>
#include <string.h>
@ -28,23 +27,17 @@
* Set an option.
*/
static enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmdq_item *);
static int cmd_set_option_set(struct cmd *, struct cmdq_item *,
struct options *, struct options_entry *, const char *);
static int cmd_set_option_flag(struct cmdq_item *,
const struct options_table_entry *, struct options *,
const char *);
static int cmd_set_option_choice(struct cmdq_item *,
const struct options_table_entry *, struct options *,
const char *);
static enum args_parse_type cmd_set_option_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_set_option_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_set_option_entry = {
.name = "set-option",
.alias = "set",
.args = { "aFgopqst:uw", 1, 2 },
.usage = "[-aFgopqsuw] " CMD_TARGET_PANE_USAGE " option [value]",
.args = { "aFgopqst:uUw", 1, 2, cmd_set_option_args_parse },
.usage = "[-aFgopqsuUw] " CMD_TARGET_PANE_USAGE " option [value]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -56,7 +49,7 @@ const struct cmd_entry cmd_set_window_option_entry = {
.name = "set-window-option",
.alias = "setw",
.args = { "aFgoqt:u", 1, 2 },
.args = { "aFgoqt:u", 1, 2, cmd_set_option_args_parse },
.usage = "[-aFgoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
@ -69,41 +62,46 @@ const struct cmd_entry cmd_set_hook_entry = {
.name = "set-hook",
.alias = NULL,
.args = { "agRt:u", 1, 2 },
.usage = "[-agRu] " CMD_TARGET_SESSION_USAGE " hook [command]",
.args = { "agpRt:uw", 1, 2, cmd_set_option_args_parse },
.usage = "[-agpRuw] " CMD_TARGET_PANE_USAGE " hook [command]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
.flags = CMD_AFTERHOOK,
.exec = cmd_set_option_exec
};
static enum args_parse_type
cmd_set_option_args_parse(__unused struct args *args, u_int idx,
__unused char **cause)
{
if (idx == 1)
return (ARGS_PARSE_COMMANDS_OR_STRING);
return (ARGS_PARSE_STRING);
}
static enum cmd_retval
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
int append = args_has(args, 'a');
struct cmd_find_state *fs = &item->target;
struct client *c, *loop;
struct session *s = fs->s;
struct winlink *wl = fs->wl;
struct window *w;
struct window_pane *wp;
struct cmd_find_state *target = cmdq_get_target(item);
struct window_pane *loop;
struct options *oo;
struct options_entry *parent, *o;
char *name, *argument, *value = NULL, *cause;
struct options_entry *parent, *o, *po;
char *name, *argument, *expanded = NULL;
char *cause;
const char *value;
int window, idx, already, error, ambiguous;
int scope;
struct style *sy;
window = (self->entry == &cmd_set_window_option_entry);
window = (cmd_get_entry(self) == &cmd_set_window_option_entry);
/* Expand argument. */
c = cmd_find_client(item, NULL, 1);
argument = format_single(item, args->argv[0], c, s, wl, NULL);
argument = format_single_from_target(item, args_string(args, 0));
/* If set-hook -R, fire the hook straight away. */
if (self->entry == &cmd_set_hook_entry && args_has(args, 'R')) {
if (cmd_get_entry(self) == &cmd_set_hook_entry && args_has(args, 'R')) {
notify_hook(item, argument);
free(argument);
return (CMD_RETURN_NORMAL);
@ -120,15 +118,18 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "invalid option: %s", argument);
goto fail;
}
if (args->argc < 2)
if (args_count(args) < 2)
value = NULL;
else if (args_has(args, 'F'))
value = format_single(item, args->argv[1], c, s, wl, NULL);
else
value = xstrdup(args->argv[1]);
value = args_string(args, 1);
if (value != NULL && args_has(args, 'F')) {
expanded = format_single_from_target(item, value);
value = expanded;
}
/* Get the scope and table for the option .*/
scope = options_scope_from_name(args, window, name, fs, &oo, &cause);
scope = options_scope_from_name(args, window, name, target, &oo,
&cause);
if (scope == OPTIONS_TABLE_NONE) {
if (args_has(args, 'q'))
goto out;
@ -140,7 +141,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
parent = options_get(oo, name);
/* Check that array options and indexes match up. */
if (idx != -1 && (*name == '@' || !options_isarray(parent))) {
if (idx != -1 && (*name == '@' || !options_is_array(parent))) {
cmdq_error(item, "not an array: %s", argument);
goto fail;
}
@ -164,19 +165,22 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
}
/* Change the option. */
if (args_has(args, 'u')) {
if (args_has(args, 'U') && scope == OPTIONS_TABLE_WINDOW) {
TAILQ_FOREACH(loop, &target->w->panes, entry) {
po = options_get_only(loop->options, name);
if (po == NULL)
continue;
if (options_remove_or_default(po, idx, &cause) != 0) {
cmdq_error(item, "%s", cause);
free(cause);
goto fail;
}
}
}
if (args_has(args, 'u') || args_has(args, 'U')) {
if (o == NULL)
goto out;
if (idx == -1) {
if (*name == '@')
options_remove(o);
else if (oo == global_options ||
oo == global_s_options ||
oo == global_w_options)
options_default(oo, options_table_entry(o));
else
options_remove(o);
} else if (options_array_set(o, idx, NULL, 0, &cause) != 0) {
if (options_remove_or_default(o, idx, &cause) != 0) {
cmdq_error(item, "%s", cause);
free(cause);
goto fail;
@ -187,10 +191,15 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
goto fail;
}
options_set_string(oo, name, append, "%s", value);
} else if (idx == -1 && !options_isarray(parent)) {
error = cmd_set_option_set(self, item, oo, parent, value);
if (error != 0)
} else if (idx == -1 && !options_is_array(parent)) {
error = options_from_string(oo, options_table_entry(parent),
options_table_entry(parent)->name, value,
args_has(args, 'a'), &cause);
if (error != 0) {
cmdq_error(item, "%s", cause);
free(cause);
goto fail;
}
} else {
if (value == NULL) {
cmdq_error(item, "empty value");
@ -214,198 +223,17 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
}
}
/* Update timers and so on for various options. */
if (strcmp(name, "automatic-rename") == 0) {
RB_FOREACH(w, windows, &windows) {
if (w->active == NULL)
continue;
if (options_get_number(w->options, "automatic-rename"))
w->active->flags |= PANE_CHANGED;
}
}
if (strcmp(name, "key-table") == 0) {
TAILQ_FOREACH(loop, &clients, entry)
server_client_set_key_table(loop, NULL);
}
if (strcmp(name, "user-keys") == 0) {
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->tty.flags & TTY_OPENED)
tty_keys_build(&loop->tty);
}
}
if (strcmp(name, "status-fg") == 0 || strcmp(name, "status-bg") == 0) {
sy = options_get_style(oo, "status-style");
sy->gc.fg = options_get_number(oo, "status-fg");
sy->gc.bg = options_get_number(oo, "status-bg");
}
if (strcmp(name, "status-style") == 0) {
sy = options_get_style(oo, "status-style");
options_set_number(oo, "status-fg", sy->gc.fg);
options_set_number(oo, "status-bg", sy->gc.bg);
}
if (strcmp(name, "status") == 0 ||
strcmp(name, "status-interval") == 0)
status_timer_start_all();
if (strcmp(name, "monitor-silence") == 0)
alerts_reset_all();
if (strcmp(name, "window-style") == 0 ||
strcmp(name, "window-active-style") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
wp->flags |= PANE_STYLECHANGED;
}
if (strcmp(name, "pane-border-status") == 0) {
RB_FOREACH(w, windows, &windows)
layout_fix_panes(w);
}
RB_FOREACH(s, sessions, &sessions)
status_update_cache(s);
/*
* Update sizes and redraw. May not always be necessary but do it
* anyway.
*/
recalculate_sizes();
TAILQ_FOREACH(loop, &clients, entry) {
if (loop->session != NULL)
server_redraw_client(loop);
}
options_push_changes(name);
out:
free(argument);
free(value);
free(expanded);
free(name);
return (CMD_RETURN_NORMAL);
fail:
free(argument);
free(value);
free(expanded);
free(name);
return (CMD_RETURN_ERROR);
}
static int
cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo,
struct options_entry *parent, const char *value)
{
const struct options_table_entry *oe;
struct args *args = self->args;
int append = args_has(args, 'a');
struct options_entry *o;
long long number;
const char *errstr, *new;
char *old;
key_code key;
oe = options_table_entry(parent);
if (value == NULL &&
oe->type != OPTIONS_TABLE_FLAG &&
oe->type != OPTIONS_TABLE_CHOICE) {
cmdq_error(item, "empty value");
return (-1);
}
switch (oe->type) {
case OPTIONS_TABLE_STRING:
old = xstrdup(options_get_string(oo, oe->name));
options_set_string(oo, oe->name, append, "%s", value);
new = options_get_string(oo, oe->name);
if (oe->pattern != NULL && fnmatch(oe->pattern, new, 0) != 0) {
options_set_string(oo, oe->name, 0, "%s", old);
free(old);
cmdq_error(item, "value is invalid: %s", value);
return (-1);
}
free(old);
return (0);
case OPTIONS_TABLE_NUMBER:
number = strtonum(value, oe->minimum, oe->maximum, &errstr);
if (errstr != NULL) {
cmdq_error(item, "value is %s: %s", errstr, value);
return (-1);
}
options_set_number(oo, oe->name, number);
return (0);
case OPTIONS_TABLE_KEY:
key = key_string_lookup_string(value);
if (key == KEYC_UNKNOWN) {
cmdq_error(item, "bad key: %s", value);
return (-1);
}
options_set_number(oo, oe->name, key);
return (0);
case OPTIONS_TABLE_COLOUR:
if ((number = colour_fromstring(value)) == -1) {
cmdq_error(item, "bad colour: %s", value);
return (-1);
}
options_set_number(oo, oe->name, number);
return (0);
case OPTIONS_TABLE_FLAG:
return (cmd_set_option_flag(item, oe, oo, value));
case OPTIONS_TABLE_CHOICE:
return (cmd_set_option_choice(item, oe, oo, value));
case OPTIONS_TABLE_STYLE:
o = options_set_style(oo, oe->name, append, value);
if (o == NULL) {
cmdq_error(item, "bad style: %s", value);
return (-1);
}
return (0);
case OPTIONS_TABLE_COMMAND:
break;
}
return (-1);
}
static int
cmd_set_option_flag(struct cmdq_item *item,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
int flag;
if (value == NULL || *value == '\0')
flag = !options_get_number(oo, oe->name);
else if (strcmp(value, "1") == 0 ||
strcasecmp(value, "on") == 0 ||
strcasecmp(value, "yes") == 0)
flag = 1;
else if (strcmp(value, "0") == 0 ||
strcasecmp(value, "off") == 0 ||
strcasecmp(value, "no") == 0)
flag = 0;
else {
cmdq_error(item, "bad value: %s", value);
return (-1);
}
options_set_number(oo, oe->name, flag);
return (0);
}
static int
cmd_set_option_choice(struct cmdq_item *item,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
const char **cp;
int n, choice = -1;
if (value == NULL) {
choice = options_get_number(oo, oe->name);
if (choice < 2)
choice = !choice;
} else {
n = 0;
for (cp = oe->choices; *cp != NULL; cp++) {
if (strcmp(*cp, value) == 0)
choice = n;
n++;
}
if (choice == -1) {
cmdq_error(item, "unknown value: %s", value);
return (-1);
}
}
options_set_number(oo, oe->name, choice);
return (0);
}

View File

@ -38,8 +38,8 @@ const struct cmd_entry cmd_show_environment_entry = {
.name = "show-environment",
.alias = "showenv",
.args = { "gst:", 0, 1 },
.usage = "[-gs] " CMD_TARGET_SESSION_USAGE " [name]",
.args = { "hgst:", 0, 1, NULL },
.usage = "[-hgs] " CMD_TARGET_SESSION_USAGE " [variable]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
@ -69,9 +69,15 @@ static void
cmd_show_environment_print(struct cmd *self, struct cmdq_item *item,
struct environ_entry *envent)
{
struct args *args = cmd_get_args(self);
char *escaped;
if (!args_has(self->args, 's')) {
if (!args_has(args, 'h') && (envent->flags & ENVIRON_HIDDEN))
return;
if (args_has(args, 'h') && (~envent->flags & ENVIRON_HIDDEN))
return;
if (!args_has(args, 's')) {
if (envent->value != NULL)
cmdq_print(item, "%s=%s", envent->name, envent->value);
else
@ -91,36 +97,37 @@ cmd_show_environment_print(struct cmd *self, struct cmdq_item *item,
static enum cmd_retval
cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct environ *env;
struct environ_entry *envent;
const char *target;
const char *tflag, *name = args_string(args, 0);
if ((target = args_get(args, 't')) != NULL) {
if (item->target.s == NULL) {
cmdq_error(item, "no such session: %s", target);
if ((tflag = args_get(args, 't')) != NULL) {
if (target->s == NULL) {
cmdq_error(item, "no such session: %s", tflag);
return (CMD_RETURN_ERROR);
}
}
if (args_has(self->args, 'g'))
if (args_has(args, 'g'))
env = global_environ;
else {
if (item->target.s == NULL) {
target = args_get(args, 't');
if (target != NULL)
cmdq_error(item, "no such session: %s", target);
if (target->s == NULL) {
tflag = args_get(args, 't');
if (tflag != NULL)
cmdq_error(item, "no such session: %s", tflag);
else
cmdq_error(item, "no current session");
return (CMD_RETURN_ERROR);
}
env = item->target.s->environ;
env = target->s->environ;
}
if (args->argc != 0) {
envent = environ_find(env, args->argv[0]);
if (name != NULL) {
envent = environ_find(env, name);
if (envent == NULL) {
cmdq_error(item, "unknown variable: %s", args->argv[0]);
cmdq_error(item, "unknown variable: %s", name);
return (CMD_RETURN_ERROR);
}
cmd_show_environment_print(self, item, envent);

View File

@ -18,16 +18,19 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
/*
* Show client message log.
* Show message log.
*/
#define SHOW_MESSAGES_TEMPLATE \
"#{t/p:message_time}: #{message_text}"
static enum cmd_retval cmd_show_messages_exec(struct cmd *,
struct cmdq_item *);
@ -35,29 +38,31 @@ const struct cmd_entry cmd_show_messages_entry = {
.name = "show-messages",
.alias = "showmsgs",
.args = { "JTt:", 0, 0 },
.args = { "JTt:", 0, 0, NULL },
.usage = "[-JT] " CMD_TARGET_CLIENT_USAGE,
.flags = CMD_AFTERHOOK,
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
.exec = cmd_show_messages_exec
};
static int cmd_show_messages_terminals(struct cmdq_item *, int);
static int
cmd_show_messages_terminals(struct cmdq_item *item, int blank)
cmd_show_messages_terminals(struct cmd *self, struct cmdq_item *item, int blank)
{
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct tty_term *term;
u_int i, n;
n = 0;
LIST_FOREACH(term, &tty_terms, entry) {
if (args_has(args, 't') && term != tc->tty.term)
continue;
if (blank) {
cmdq_print(item, "%s", "");
blank = 0;
}
cmdq_print(item, "Terminal %u: %s [references=%u, flags=0x%x]:",
n, term->name, term->references, term->flags);
cmdq_print(item, "Terminal %u: %s for %s, flags=0x%x:", n,
term->name, term->tty->client->name, term->flags);
n++;
for (i = 0; i < tty_term_ncodes(); i++)
cmdq_print(item, "%s", tty_term_describe(term, i));
@ -68,18 +73,15 @@ cmd_show_messages_terminals(struct cmdq_item *item, int blank)
static enum cmd_retval
cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c;
struct args *args = cmd_get_args(self);
struct message_entry *msg;
char *tim;
char *s;
int done, blank;
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
struct format_tree *ft;
done = blank = 0;
if (args_has(args, 'T')) {
blank = cmd_show_messages_terminals(item, blank);
blank = cmd_show_messages_terminals(self, item, blank);
done = 1;
}
if (args_has(args, 'J')) {
@ -89,12 +91,17 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
if (done)
return (CMD_RETURN_NORMAL);
TAILQ_FOREACH(msg, &c->message_log, entry) {
tim = ctime(&msg->msg_time);
*strchr(tim, '\n') = '\0';
ft = format_create_from_target(item);
TAILQ_FOREACH_REVERSE(msg, &message_log, message_list, entry) {
format_add(ft, "message_text", "%s", msg->msg);
format_add(ft, "message_number", "%u", msg->msg_num);
format_add_tv(ft, "message_time", &msg->msg_time);
cmdq_print(item, "%s %s", tim, msg->msg);
s = format_expand(ft, SHOW_MESSAGES_TEMPLATE);
cmdq_print(item, "%s", s);
free(s);
}
format_free(ft);
return (CMD_RETURN_NORMAL);
}

View File

@ -38,7 +38,7 @@ const struct cmd_entry cmd_show_options_entry = {
.name = "show-options",
.alias = "show",
.args = { "AgHpqst:vw", 0, 1 },
.args = { "AgHpqst:vw", 0, 1, NULL },
.usage = "[-AgHpqsvw] " CMD_TARGET_PANE_USAGE " [option]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -51,7 +51,7 @@ const struct cmd_entry cmd_show_window_options_entry = {
.name = "show-window-options",
.alias = "showw",
.args = { "gvt:", 0, 1 },
.args = { "gvt:", 0, 1, NULL },
.usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
@ -64,10 +64,10 @@ const struct cmd_entry cmd_show_hooks_entry = {
.name = "show-hooks",
.alias = NULL,
.args = { "gt:", 0, 1 },
.usage = "[-g] " CMD_TARGET_SESSION_USAGE,
.args = { "gpt:w", 0, 1, NULL },
.usage = "[-gpw] " CMD_TARGET_PANE_USAGE " [hook]",
.target = { 't', CMD_FIND_SESSION, 0 },
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
.flags = CMD_AFTERHOOK,
.exec = cmd_show_options_exec
@ -76,20 +76,18 @@ const struct cmd_entry cmd_show_hooks_entry = {
static enum cmd_retval
cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct cmd_find_state *fs = &item->target;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct options *oo;
char *argument, *name = NULL, *cause;
int window, idx, ambiguous, parent, scope;
struct options_entry *o;
window = (self->entry == &cmd_show_window_options_entry);
window = (cmd_get_entry(self) == &cmd_show_window_options_entry);
if (args->argc == 0) {
scope = options_scope_from_flags(args, window, fs, &oo, &cause);
if (args_count(args) == 0) {
scope = options_scope_from_flags(args, window, target, &oo,
&cause);
if (scope == OPTIONS_TABLE_NONE) {
if (args_has(args, 'q'))
return (CMD_RETURN_NORMAL);
@ -99,22 +97,23 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
}
return (cmd_show_options_all(self, item, scope, oo));
}
argument = format_single(item, args->argv[0], c, s, wl, NULL);
argument = format_single_from_target(item, args_string(args, 0));
name = options_match(argument, &idx, &ambiguous);
if (name == NULL) {
if (args_has(args, 'q'))
goto fail;
goto out;
if (ambiguous)
cmdq_error(item, "ambiguous option: %s", argument);
else
cmdq_error(item, "invalid option: %s", argument);
goto fail;
}
scope = options_scope_from_name(args, window, name, fs, &oo, &cause);
scope = options_scope_from_name(args, window, name, target, &oo,
&cause);
if (scope == OPTIONS_TABLE_NONE) {
if (args_has(args, 'q'))
goto fail;
goto out;
cmdq_error(item, "%s", cause);
free(cause);
goto fail;
@ -127,7 +126,14 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
parent = 0;
if (o != NULL)
cmd_show_options_print(self, item, o, idx, parent);
else if (*name == '@') {
if (args_has(args, 'q'))
goto out;
cmdq_error(item, "invalid option: %s", argument);
goto fail;
}
out:
free(name);
free(argument);
return (CMD_RETURN_NORMAL);
@ -142,6 +148,7 @@ static void
cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
struct options_entry *o, int idx, int parent)
{
struct args *args = cmd_get_args(self);
struct options_array_item *a;
const char *name = options_name(o);
char *value, *tmp = NULL, *escaped;
@ -150,10 +157,10 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
xasprintf(&tmp, "%s[%d]", name, idx);
name = tmp;
} else {
if (options_isarray(o)) {
if (options_is_array(o)) {
a = options_array_first(o);
if (a == NULL) {
if (!args_has(self->args, 'v'))
if (!args_has(args, 'v'))
cmdq_print(item, "%s", name);
return;
}
@ -167,10 +174,10 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
}
}
value = options_tostring(o, idx, 0);
if (args_has(self->args, 'v'))
value = options_to_string(o, idx, 0);
if (args_has(args, 'v'))
cmdq_print(item, "%s", value);
else if (options_isstring(o)) {
else if (options_is_string(o)) {
escaped = args_escape(value);
if (parent)
cmdq_print(item, "%s* %s", name, escaped);
@ -192,6 +199,7 @@ static enum cmd_retval
cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
struct options *oo)
{
struct args *args = cmd_get_args(self);
const struct options_table_entry *oe;
struct options_entry *o;
struct options_array_item *a;
@ -199,28 +207,28 @@ cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
u_int idx;
int parent;
if (cmd_get_entry(self) != &cmd_show_hooks_entry) {
o = options_first(oo);
while (o != NULL) {
if (options_table_entry(o) == NULL)
cmd_show_options_print(self, item, o, -1, 0);
o = options_next(o);
}
}
for (oe = options_table; oe->name != NULL; oe++) {
if (~oe->scope & scope)
continue;
if ((self->entry != &cmd_show_hooks_entry &&
!args_has(self->args, 'H') &&
oe != NULL &&
if ((cmd_get_entry(self) != &cmd_show_hooks_entry &&
!args_has(args, 'H') &&
(oe->flags & OPTIONS_TABLE_IS_HOOK)) ||
(self->entry == &cmd_show_hooks_entry &&
(oe == NULL ||
(~oe->flags & OPTIONS_TABLE_IS_HOOK))))
(cmd_get_entry(self) == &cmd_show_hooks_entry &&
(~oe->flags & OPTIONS_TABLE_IS_HOOK)))
continue;
o = options_get_only(oo, oe->name);
if (o == NULL) {
if (!args_has(self->args, 'A'))
if (!args_has(args, 'A'))
continue;
o = options_get(oo, oe->name);
if (o == NULL)
@ -229,10 +237,10 @@ cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
} else
parent = 0;
if (!options_isarray(o))
if (!options_is_array(o))
cmd_show_options_print(self, item, o, -1, parent);
else if ((a = options_array_first(o)) == NULL) {
if (!args_has(self->args, 'v')) {
if (!args_has(args, 'v')) {
name = options_name(o);
if (parent)
cmdq_print(item, "%s*", name);

108
cmd-show-prompt-history.c Normal file
View File

@ -0,0 +1,108 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2021 Anindya Mukherjee <anindya49@hotmail.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 "tmux.h"
#include <stdlib.h>
/*
* Show or clear prompt history.
*/
static enum cmd_retval cmd_show_prompt_history_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_show_prompt_history_entry = {
.name = "show-prompt-history",
.alias = "showphist",
.args = { "T:", 0, 0, NULL },
.usage = "[-T prompt-type]",
.flags = CMD_AFTERHOOK,
.exec = cmd_show_prompt_history_exec
};
const struct cmd_entry cmd_clear_prompt_history_entry = {
.name = "clear-prompt-history",
.alias = "clearphist",
.args = { "T:", 0, 0, NULL },
.usage = "[-T prompt-type]",
.flags = CMD_AFTERHOOK,
.exec = cmd_show_prompt_history_exec
};
static enum cmd_retval
cmd_show_prompt_history_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
const char *typestr = args_get(args, 'T');
enum prompt_type type;
u_int tidx, hidx;
if (cmd_get_entry(self) == &cmd_clear_prompt_history_entry) {
if (typestr == NULL) {
for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) {
free(status_prompt_hlist[tidx]);
status_prompt_hlist[tidx] = NULL;
status_prompt_hsize[tidx] = 0;
}
} else {
type = status_prompt_type(typestr);
if (type == PROMPT_TYPE_INVALID) {
cmdq_error(item, "invalid type: %s", typestr);
return (CMD_RETURN_ERROR);
}
free(status_prompt_hlist[type]);
status_prompt_hlist[type] = NULL;
status_prompt_hsize[type] = 0;
}
return (CMD_RETURN_NORMAL);
}
if (typestr == NULL) {
for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) {
cmdq_print(item, "History for %s:\n",
status_prompt_type_string(tidx));
for (hidx = 0; hidx < status_prompt_hsize[tidx];
hidx++) {
cmdq_print(item, "%d: %s", hidx + 1,
status_prompt_hlist[tidx][hidx]);
}
cmdq_print(item, "%s", "");
}
} else {
type = status_prompt_type(typestr);
if (type == PROMPT_TYPE_INVALID) {
cmdq_error(item, "invalid type: %s", typestr);
return (CMD_RETURN_ERROR);
}
cmdq_print(item, "History for %s:\n",
status_prompt_type_string(type));
for (hidx = 0; hidx < status_prompt_hsize[type]; hidx++) {
cmdq_print(item, "%d: %s", hidx + 1,
status_prompt_hlist[type][hidx]);
}
cmdq_print(item, "%s", "");
}
return (CMD_RETURN_NORMAL);
}

View File

@ -29,14 +29,19 @@
* Sources a configuration file.
*/
#define CMD_SOURCE_FILE_DEPTH_LIMIT 50
static u_int cmd_source_file_depth;
static enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmdq_item *);
const struct cmd_entry cmd_source_file_entry = {
.name = "source-file",
.alias = "source",
.args = { "nqv", 1, -1 },
.usage = "[-nqv] path ...",
.args = { "t:Fnqv", 1, -1, NULL },
.usage = "[-Fnqv] " CMD_TARGET_PANE_USAGE " path ...",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
.flags = 0,
.exec = cmd_source_file_exec
@ -57,6 +62,16 @@ struct cmd_source_file_data {
static enum cmd_retval
cmd_source_file_complete_cb(struct cmdq_item *item, __unused void *data)
{
struct client *c = cmdq_get_client(item);
if (c == NULL) {
cmd_source_file_depth--;
log_debug("%s: depth now %u", __func__, cmd_source_file_depth);
} else {
c->source_file_depth--;
log_debug("%s: depth now %u", __func__, c->source_file_depth);
}
cfg_print_causes(item);
return (CMD_RETURN_NORMAL);
}
@ -65,14 +80,19 @@ static void
cmd_source_file_complete(struct client *c, struct cmd_source_file_data *cdata)
{
struct cmdq_item *new_item;
u_int i;
if (cfg_finished) {
if (cdata->retval == CMD_RETURN_ERROR && c->session == NULL)
if (cdata->retval == CMD_RETURN_ERROR &&
c != NULL &&
c->session == NULL)
c->retval = 1;
new_item = cmdq_get_callback(cmd_source_file_complete_cb, NULL);
cmdq_insert_after(cdata->after, new_item);
}
for (i = 0; i < cdata->nfiles; i++)
free(cdata->files[i]);
free(cdata->files);
free(cdata);
}
@ -87,6 +107,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
size_t bsize = EVBUFFER_LENGTH(buffer);
u_int n;
struct cmdq_item *new_item;
struct cmd_find_state *target = cmdq_get_target(item);
if (!closed)
return;
@ -95,7 +116,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
cmdq_error(item, "%s: %s", path, strerror(error));
else if (bsize != 0) {
if (load_cfg_from_buffer(bdata, bsize, path, c, cdata->after,
cdata->flags, &new_item) < 0)
target, cdata->flags, &new_item) < 0)
cdata->retval = CMD_RETURN_ERROR;
else if (new_item != NULL)
cdata->after = new_item;
@ -113,7 +134,16 @@ cmd_source_file_done(struct client *c, const char *path, int error,
static void
cmd_source_file_add(struct cmd_source_file_data *cdata, const char *path)
{
char resolved[PATH_MAX];
if (realpath(path, resolved) == NULL) {
log_debug("%s: realpath(\"%s\") failed: %s", __func__,
path, strerror(errno));
} else
path = resolved;
log_debug("%s: %s", __func__, path);
cdata->files = xreallocarray(cdata->files, cdata->nfiles + 1,
sizeof *cdata->files);
cdata->files[cdata->nfiles++] = xstrdup(path);
@ -122,15 +152,31 @@ cmd_source_file_add(struct cmd_source_file_data *cdata, const char *path)
static enum cmd_retval
cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_source_file_data *cdata;
struct client *c = item->client;
struct client *c = cmdq_get_client(item);
enum cmd_retval retval = CMD_RETURN_NORMAL;
char *pattern, *cwd;
char *pattern, *cwd, *expanded = NULL;
const char *path, *error;
glob_t g;
int i, result;
u_int j;
int result;
u_int i, j;
if (c == NULL) {
if (cmd_source_file_depth >= CMD_SOURCE_FILE_DEPTH_LIMIT) {
cmdq_error(item, "too many nested files");
return (CMD_RETURN_ERROR);
}
cmd_source_file_depth++;
log_debug("%s: depth now %u", __func__, cmd_source_file_depth);
} else {
if (c->source_file_depth >= CMD_SOURCE_FILE_DEPTH_LIMIT) {
cmdq_error(item, "too many nested files");
return (CMD_RETURN_ERROR);
}
c->source_file_depth++;
log_debug("%s: depth now %u", __func__, c->source_file_depth);
}
cdata = xcalloc(1, sizeof *cdata);
cdata->item = item;
@ -144,8 +190,13 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
utf8_stravis(&cwd, server_client_get_cwd(c, NULL), VIS_GLOB);
for (i = 0; i < args->argc; i++) {
path = args->argv[i];
for (i = 0; i < args_count(args); i++) {
path = args_string(args, i);
if (args_has(args, 'F')) {
free(expanded);
expanded = format_single_from_target(item, path);
path = expanded;
}
if (strcmp(path, "-") == 0) {
cmd_source_file_add(cdata, "-");
continue;
@ -169,6 +220,7 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "%s: %s", path, error);
retval = CMD_RETURN_ERROR;
}
globfree(&g);
free(pattern);
continue;
}
@ -176,7 +228,9 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
for (j = 0; j < g.gl_pathc; j++)
cmd_source_file_add(cdata, g.gl_pathv[j]);
globfree(&g);
}
free(expanded);
cdata->after = item;
cdata->retval = retval;

View File

@ -39,9 +39,10 @@ const struct cmd_entry cmd_split_window_entry = {
.name = "split-window",
.alias = "splitw",
.args = { "bc:de:fF:hIl:p:Pt:v", 0, -1 },
.usage = "[-bdefhIPv] [-c start-directory] [-e environment] "
"[-F format] [-l size] " CMD_TARGET_PANE_USAGE " [command]",
.args = { "bc:de:fF:hIl:p:Pt:vZ", 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 },
@ -52,72 +53,68 @@ const struct cmd_entry cmd_split_window_entry = {
static enum cmd_retval
cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct cmd_find_state *current = &item->shared->current;
struct spawn_context sc;
struct client *c = cmd_find_client(item, NULL, 1);
struct session *s = item->target.s;
struct winlink *wl = item->target.wl;
struct window_pane *wp = item->target.wp, *new_wp;
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;
enum layout_type type;
struct layout_cell *lc;
struct cmd_find_state fs;
int size, percentage, flags, input;
const char *template, *add, *errstr, *p;
char *cause, *cp, *copy;
size_t plen;
struct args_value *value;
int size, flags, input;
const char *template;
char *cause = NULL, *cp;
struct args_value *av;
u_int count = args_count(args), curval = 0;
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
else
type = LAYOUT_TOPBOTTOM;
if ((p = args_get(args, 'l')) != NULL) {
plen = strlen(p);
if (p[plen - 1] == '%') {
copy = xstrdup(p);
copy[plen - 1] = '\0';
percentage = strtonum(copy, 0, INT_MAX, &errstr);
free(copy);
if (errstr != NULL) {
cmdq_error(item, "percentage %s", errstr);
return (CMD_RETURN_ERROR);
}
if (type == LAYOUT_TOPBOTTOM)
size = (wp->sy * percentage) / 100;
else
size = (wp->sx * percentage) / 100;
} else {
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(item, "lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
} else if (args_has(args, 'p')) {
percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(item, "create pane failed: -p %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (type == LAYOUT_TOPBOTTOM)
size = (wp->sy * percentage) / 100;
else
size = (wp->sx * percentage) / 100;
} else
size = -1;
server_unzoom_window(wp->window);
input = (args_has(args, 'I') && args->argc == 0);
/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = w->sy;
else
curval = w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = wp->sy;
else
curval = wp->sx;
}
}
size = -1;
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, &cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
&cause);
if (cause == NULL)
size = curval * size / 100;
}
if (cause != NULL) {
cmdq_error(item, "size %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
window_push_zoom(wp->window, 1, args_has(args, 'Z'));
input = (args_has(args, 'I') && count == 0);
flags = 0;
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
if (input || (args->argc == 1 && *args->argv[0] == '\0'))
if (input || (count == 1 && *args_string(args, 0) == '\0'))
flags |= SPAWN_EMPTY;
lc = layout_split_pane(wp, type, size, flags);
@ -126,7 +123,6 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.wl = wl;
@ -134,15 +130,13 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
sc.wp0 = wp;
sc.lc = lc;
sc.name = NULL;
sc.argc = args->argc;
sc.argv = args->argv;
args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(sc.environ, add);
add = args_next_value(&value);
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(sc.environ, av->string, 0);
av = args_next_value(av);
}
sc.idx = -1;
@ -151,28 +145,44 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
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 && window_pane_start_input(new_wp, item, &cause) != 0) {
if (input) {
switch (window_pane_start_input(new_wp, item, &cause)) {
case -1:
server_client_remove_pane(new_wp);
layout_close_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 = SPLIT_WINDOW_TEMPLATE;
cp = format_single(item, template, c, s, wl, new_wp);
cp = format_single(item, template, tc, s, wl, new_wp);
cmdq_print(item, "%s", cp);
free(cp);
}
@ -180,6 +190,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
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);

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_swap_pane_entry = {
.name = "swap-pane",
.alias = "swapp",
.args = { "dDs:t:UZ", 0, 0 },
.args = { "dDs:t:UZ", 0, 0, NULL },
.usage = "[-dDUZ] " CMD_SRCDST_PANE_USAGE,
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
@ -45,18 +45,20 @@ const struct cmd_entry cmd_swap_pane_entry = {
static enum cmd_retval
cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_find_state *source = cmdq_get_source(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct window *src_w, *dst_w;
struct window_pane *tmp_wp, *src_wp, *dst_wp;
struct layout_cell *src_lc, *dst_lc;
u_int sx, sy, xoff, yoff;
dst_w = item->target.wl->window;
dst_wp = item->target.wp;
src_w = item->source.wl->window;
src_wp = item->source.wp;
dst_w = target->wl->window;
dst_wp = target->wp;
src_w = source->wl->window;
src_wp = source->wp;
if (window_push_zoom(dst_w, args_has(args, 'Z')))
if (window_push_zoom(dst_w, 0, args_has(args, 'Z')))
server_redraw_window(dst_w);
if (args_has(args, 'D')) {
@ -71,12 +73,15 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
}
if (src_w != dst_w && window_push_zoom(src_w, args_has(args, 'Z')))
if (src_w != dst_w && window_push_zoom(src_w, 0, args_has(args, 'Z')))
server_redraw_window(src_w);
if (src_wp == dst_wp)
goto out;
server_client_remove_pane(src_wp);
server_client_remove_pane(dst_wp);
tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
TAILQ_REMOVE(&dst_w->panes, dst_wp, entry);
TAILQ_REPLACE(&src_w->panes, src_wp, dst_wp, entry);
@ -96,10 +101,10 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
src_wp->window = dst_w;
options_set_parent(src_wp->options, dst_w->options);
src_wp->flags |= PANE_STYLECHANGED;
src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
dst_wp->window = src_w;
options_set_parent(dst_wp->options, src_w->options);
dst_wp->flags |= PANE_STYLECHANGED;
dst_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
sx = src_wp->sx; sy = src_wp->sy;
xoff = src_wp->xoff; yoff = src_wp->yoff;
@ -123,14 +128,20 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
window_set_active_pane(dst_w, src_wp, 1);
}
if (src_w != dst_w) {
if (src_w->last == src_wp)
src_w->last = NULL;
if (dst_w->last == dst_wp)
dst_w->last = NULL;
}
window_pane_stack_remove(&src_w->last_panes, src_wp);
window_pane_stack_remove(&dst_w->last_panes, dst_wp);
colour_palette_from_option(&src_wp->palette, src_wp->options);
colour_palette_from_option(&dst_wp->palette, dst_wp->options);
layout_fix_panes(src_w, NULL);
server_redraw_window(src_w);
}
layout_fix_panes(dst_w, NULL);
server_redraw_window(dst_w);
notify_window("window-layout-changed", src_w);
if (src_w != dst_w)
notify_window("window-layout-changed", dst_w);
out:
if (window_pop_zoom(src_w))
server_redraw_window(src_w);

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_swap_window_entry = {
.name = "swap-window",
.alias = "swapw",
.args = { "ds:t:", 0, 0 },
.args = { "ds:t:", 0, 0, NULL },
.usage = "[-d] " CMD_SRCDST_WINDOW_USAGE,
.source = { 's', CMD_FIND_WINDOW, CMD_FIND_DEFAULT_MARKED },
@ -45,20 +45,20 @@ const struct cmd_entry cmd_swap_window_entry = {
static enum cmd_retval
cmd_swap_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct session *src, *dst;
struct args *args = cmd_get_args(self);
struct cmd_find_state *source = cmdq_get_source(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct session *src = source->s, *dst = target->s;
struct session_group *sg_src, *sg_dst;
struct winlink *wl_src, *wl_dst;
struct winlink *wl_src = source->wl, *wl_dst = target->wl;
struct window *w_src, *w_dst;
wl_src = item->source.wl;
src = item->source.s;
sg_src = session_group_contains(src);
wl_dst = item->target.wl;
dst = item->target.s;
sg_dst = session_group_contains(dst);
if (src != dst && sg_src != NULL && sg_dst != NULL &&
if (src != dst &&
sg_src != NULL &&
sg_dst != NULL &&
sg_src == sg_dst) {
cmdq_error(item, "can't move window, sessions are grouped");
return (CMD_RETURN_ERROR);
@ -77,7 +77,7 @@ cmd_swap_window_exec(struct cmd *self, struct cmdq_item *item)
wl_src->window = w_dst;
TAILQ_INSERT_TAIL(&w_dst->winlinks, wl_src, wentry);
if (args_has(self->args, 'd')) {
if (args_has(args, 'd')) {
session_select(dst, wl_dst->idx);
if (src != dst)
session_select(src, wl_src->idx);

View File

@ -34,24 +34,26 @@ const struct cmd_entry cmd_switch_client_entry = {
.name = "switch-client",
.alias = "switchc",
.args = { "lc:Enpt:rT:Z", 0, 0 },
.args = { "lc:EFnpt:rT:Z", 0, 0, NULL },
.usage = "[-ElnprZ] [-c target-client] [-t target-session] "
"[-T key-table]",
/* -t is special */
.flags = CMD_READONLY,
.flags = CMD_READONLY|CMD_CLIENT_CFLAG,
.exec = cmd_switch_client_exec
};
static enum cmd_retval
cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
struct cmd_find_state *current = cmdq_get_current(item);
struct cmd_find_state target;
const char *tflag = args_get(args, 't');
enum cmd_find_type type;
int flags;
struct client *c;
struct client *tc = cmdq_get_target_client(item);
struct session *s;
struct winlink *wl;
struct window *w;
@ -59,9 +61,6 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
const char *tablename;
struct key_table *table;
if ((c = cmd_find_client(item, args_get(args, 'c'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (tflag != NULL && tflag[strcspn(tflag, ":.%")] != '\0') {
type = CMD_FIND_PANE;
flags = 0;
@ -69,15 +68,18 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
type = CMD_FIND_SESSION;
flags = CMD_FIND_PREFER_UNATTACHED;
}
if (cmd_find_target(&item->target, item, tflag, type, flags) != 0)
if (cmd_find_target(&target, item, tflag, type, flags) != 0)
return (CMD_RETURN_ERROR);
s = item->target.s;
wl = item->target.wl;
w = wl->window;
wp = item->target.wp;
s = target.s;
wl = target.wl;
wp = target.wp;
if (args_has(args, 'r'))
c->flags ^= CLIENT_READONLY;
if (args_has(args, 'r')) {
if (tc->flags & CLIENT_READONLY)
tc->flags &= ~(CLIENT_READONLY|CLIENT_IGNORESIZE);
else
tc->flags |= (CLIENT_READONLY|CLIENT_IGNORESIZE);
}
tablename = args_get(args, 'T');
if (tablename != NULL) {
@ -87,24 +89,24 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
table->references++;
key_bindings_unref_table(c->keytable);
c->keytable = table;
key_bindings_unref_table(tc->keytable);
tc->keytable = table;
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) {
if ((s = session_next_session(tc->session)) == NULL) {
cmdq_error(item, "can't find next session");
return (CMD_RETURN_ERROR);
}
} else if (args_has(args, 'p')) {
if ((s = session_previous_session(c->session)) == NULL) {
if ((s = session_previous_session(tc->session)) == NULL) {
cmdq_error(item, "can't find previous session");
return (CMD_RETURN_ERROR);
}
} else if (args_has(args, 'l')) {
if (c->last_session != NULL && session_alive(c->last_session))
s = c->last_session;
if (tc->last_session != NULL && session_alive(tc->last_session))
s = tc->last_session;
else
s = NULL;
if (s == NULL) {
@ -112,10 +114,11 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
} else {
if (item->client == NULL)
if (cmdq_get_client(item) == NULL)
return (CMD_RETURN_NORMAL);
if (wl != NULL && wp != NULL) {
if (window_push_zoom(w, args_has(self->args, 'Z')))
if (wl != NULL && wp != NULL && wp != wl->window->active) {
w = wl->window;
if (window_push_zoom(w, 0, args_has(args, 'Z')))
server_redraw_window(w);
window_redraw_active_switch(w, wp);
window_set_active_pane(w, wp, 1);
@ -124,30 +127,16 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
}
if (wl != NULL) {
session_set_current(s, wl);
cmd_find_from_session(&item->shared->current, s, 0);
cmd_find_from_session(current, s, 0);
}
}
if (!args_has(args, 'E'))
environ_update(s->options, c->environ, s->environ);
environ_update(s->options, tc->environ, s->environ);
if (c->session != NULL && c->session != s)
c->last_session = c->session;
c->session = s;
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
server_client_set_key_table(c, NULL);
tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_check_unattached();
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
s->curw->window->latest = c;
recalculate_sizes();
alerts_check_session(s);
server_client_set_session(tc, s);
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
server_client_set_key_table(tc, NULL);
return (CMD_RETURN_NORMAL);
}

View File

@ -32,8 +32,8 @@ const struct cmd_entry cmd_unbind_key_entry = {
.name = "unbind-key",
.alias = "unbind",
.args = { "anT:", 0, 1 },
.usage = "[-an] [-T key-table] key",
.args = { "anqT:", 0, 1, NULL },
.usage = "[-anq] [-T key-table] key",
.flags = CMD_AFTERHOOK,
.exec = cmd_unbind_key_exec
@ -42,47 +42,57 @@ const struct cmd_entry cmd_unbind_key_entry = {
static enum cmd_retval
cmd_unbind_key_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct args *args = cmd_get_args(self);
key_code key;
const char *tablename;
const char *tablename, *keystr = args_string(args, 0);
int quiet = args_has(args, 'q');
if (!args_has(args, 'a')) {
if (args->argc != 1) {
cmdq_error(item, "missing key");
return (CMD_RETURN_ERROR);
}
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(item, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
} else {
if (args->argc != 0) {
if (args_has(args, 'a')) {
if (keystr != NULL) {
if (!quiet)
cmdq_error(item, "key given with -a");
return (CMD_RETURN_ERROR);
}
key = KEYC_UNKNOWN;
}
if (key == KEYC_UNKNOWN) {
tablename = args_get(args, 'T');
if (tablename == NULL) {
key_bindings_remove_table("root");
key_bindings_remove_table("prefix");
return (CMD_RETURN_NORMAL);
if (args_has(args, 'n'))
tablename = "root";
else
tablename = "prefix";
}
if (key_bindings_get_table(tablename, 0) == NULL) {
cmdq_error(item, "table %s doesn't exist", tablename);
if (!quiet) {
cmdq_error(item, "table %s doesn't exist" ,
tablename);
}
return (CMD_RETURN_ERROR);
}
key_bindings_remove_table(tablename);
return (CMD_RETURN_NORMAL);
}
if (keystr == NULL) {
if (!quiet)
cmdq_error(item, "missing key");
return (CMD_RETURN_ERROR);
}
key = key_string_lookup_string(keystr);
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
if (!quiet)
cmdq_error(item, "unknown key: %s", keystr);
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'T')) {
tablename = args_get(args, 'T');
if (key_bindings_get_table(tablename, 0) == NULL) {
cmdq_error(item, "table %s doesn't exist", tablename);
if (!quiet) {
cmdq_error(item, "table %s doesn't exist" ,
tablename);
}
return (CMD_RETURN_ERROR);
}
} else if (args_has(args, 'n'))

View File

@ -34,7 +34,7 @@ const struct cmd_entry cmd_wait_for_entry = {
.name = "wait-for",
.alias = "wait",
.args = { "LSU", 1, 1 },
.args = { "LSU", 1, 1, NULL },
.usage = "[-L|-S|-U] channel",
.flags = 0,
@ -120,12 +120,12 @@ cmd_wait_for_remove(struct wait_channel *wc)
static enum cmd_retval
cmd_wait_for_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
const char *name = args->argv[0];
struct wait_channel *wc, wc0;
struct args *args = cmd_get_args(self);
const char *name = args_string(args, 0);
struct wait_channel *wc, find;
wc0.name = name;
wc = RB_FIND(wait_channels, &wait_channels, &wc0);
find.name = name;
wc = RB_FIND(wait_channels, &wait_channels, &find);
if (args_has(args, 'S'))
return (cmd_wait_for_signal(item, name, wc));
@ -167,7 +167,7 @@ static enum cmd_retval
cmd_wait_for_wait(struct cmdq_item *item, const char *name,
struct wait_channel *wc)
{
struct client *c = item->client;
struct client *c = cmdq_get_client(item);
struct wait_item *wi;
if (c == NULL) {
@ -198,7 +198,7 @@ cmd_wait_for_lock(struct cmdq_item *item, const char *name,
{
struct wait_item *wi;
if (item->client == NULL) {
if (cmdq_get_client(item) == NULL) {
cmdq_error(item, "not able to lock");
return (CMD_RETURN_ERROR);
}

279
cmd.c
View File

@ -35,16 +35,18 @@ extern const struct cmd_entry cmd_choose_buffer_entry;
extern const struct cmd_entry cmd_choose_client_entry;
extern const struct cmd_entry cmd_choose_tree_entry;
extern const struct cmd_entry cmd_clear_history_entry;
extern const struct cmd_entry cmd_clear_prompt_history_entry;
extern const struct cmd_entry cmd_clock_mode_entry;
extern const struct cmd_entry cmd_command_prompt_entry;
extern const struct cmd_entry cmd_confirm_before_entry;
extern const struct cmd_entry cmd_copy_mode_entry;
extern const struct cmd_entry cmd_customize_mode_entry;
extern const struct cmd_entry cmd_delete_buffer_entry;
extern const struct cmd_entry cmd_detach_client_entry;
extern const struct cmd_entry cmd_display_menu_entry;
extern const struct cmd_entry cmd_display_message_entry;
extern const struct cmd_entry cmd_display_popup_entry;
extern const struct cmd_entry cmd_display_panes_entry;
extern const struct cmd_entry cmd_down_pane_entry;
extern const struct cmd_entry cmd_find_window_entry;
extern const struct cmd_entry cmd_has_session_entry;
extern const struct cmd_entry cmd_if_shell_entry;
@ -92,6 +94,7 @@ extern const struct cmd_entry cmd_select_pane_entry;
extern const struct cmd_entry cmd_select_window_entry;
extern const struct cmd_entry cmd_send_keys_entry;
extern const struct cmd_entry cmd_send_prefix_entry;
extern const struct cmd_entry cmd_server_access_entry;
extern const struct cmd_entry cmd_set_buffer_entry;
extern const struct cmd_entry cmd_set_environment_entry;
extern const struct cmd_entry cmd_set_hook_entry;
@ -102,6 +105,7 @@ extern const struct cmd_entry cmd_show_environment_entry;
extern const struct cmd_entry cmd_show_hooks_entry;
extern const struct cmd_entry cmd_show_messages_entry;
extern const struct cmd_entry cmd_show_options_entry;
extern const struct cmd_entry cmd_show_prompt_history_entry;
extern const struct cmd_entry cmd_show_window_options_entry;
extern const struct cmd_entry cmd_source_file_entry;
extern const struct cmd_entry cmd_split_window_entry;
@ -112,7 +116,6 @@ extern const struct cmd_entry cmd_swap_window_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_unlink_window_entry;
extern const struct cmd_entry cmd_up_pane_entry;
extern const struct cmd_entry cmd_wait_for_entry;
const struct cmd_entry *cmd_table[] = {
@ -124,14 +127,17 @@ const struct cmd_entry *cmd_table[] = {
&cmd_choose_client_entry,
&cmd_choose_tree_entry,
&cmd_clear_history_entry,
&cmd_clear_prompt_history_entry,
&cmd_clock_mode_entry,
&cmd_command_prompt_entry,
&cmd_confirm_before_entry,
&cmd_copy_mode_entry,
&cmd_customize_mode_entry,
&cmd_delete_buffer_entry,
&cmd_detach_client_entry,
&cmd_display_menu_entry,
&cmd_display_message_entry,
&cmd_display_popup_entry,
&cmd_display_panes_entry,
&cmd_find_window_entry,
&cmd_has_session_entry,
@ -180,6 +186,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_select_window_entry,
&cmd_send_keys_entry,
&cmd_send_prefix_entry,
&cmd_server_access_entry,
&cmd_set_buffer_entry,
&cmd_set_environment_entry,
&cmd_set_hook_entry,
@ -190,6 +197,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_show_hooks_entry,
&cmd_show_messages_entry,
&cmd_show_options_entry,
&cmd_show_prompt_history_entry,
&cmd_show_window_options_entry,
&cmd_source_file_entry,
&cmd_split_window_entry,
@ -204,8 +212,23 @@ const struct cmd_entry *cmd_table[] = {
NULL
};
/* Instance of a command. */
struct cmd {
const struct cmd_entry *entry;
struct args *args;
u_int group;
char *file;
u_int line;
TAILQ_ENTRY(cmd) qentry;
};
TAILQ_HEAD(cmds, cmd);
/* Next group number for new command list. */
static u_int cmd_list_next_group = 1;
/* Log an argument vector. */
void printflike(3, 4)
cmd_log_argv(int argc, char **argv, const char *fmt, ...)
{
@ -222,8 +245,9 @@ cmd_log_argv(int argc, char **argv, const char *fmt, ...)
free(prefix);
}
/* Prepend to an argument vector. */
void
cmd_prepend_argv(int *argc, char ***argv, char *arg)
cmd_prepend_argv(int *argc, char ***argv, const char *arg)
{
char **new_argv;
int i;
@ -238,13 +262,15 @@ cmd_prepend_argv(int *argc, char ***argv, char *arg)
(*argc)++;
}
/* Append to an argument vector. */
void
cmd_append_argv(int *argc, char ***argv, char *arg)
cmd_append_argv(int *argc, char ***argv, const char *arg)
{
*argv = xreallocarray(*argv, (*argc) + 1, sizeof **argv);
(*argv)[(*argc)++] = xstrdup(arg);
}
/* Pack an argument vector up into a buffer. */
int
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
{
@ -267,6 +293,7 @@ cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
return (0);
}
/* Unpack an argument vector from a packed buffer. */
int
cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
{
@ -295,6 +322,7 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
return (0);
}
/* Copy an argument vector, ensuring it is terminated by NULL. */
char **
cmd_copy_argv(int argc, char **argv)
{
@ -311,6 +339,7 @@ cmd_copy_argv(int argc, char **argv)
return (new_argv);
}
/* Free an argument vector. */
void
cmd_free_argv(int argc, char **argv)
{
@ -323,32 +352,67 @@ cmd_free_argv(int argc, char **argv)
free(argv);
}
/* Convert argument vector to a string. */
char *
cmd_stringify_argv(int argc, char **argv)
{
char *buf;
char *buf = NULL, *s;
size_t len = 0;
int i;
size_t len;
if (argc == 0)
return (xstrdup(""));
len = 0;
buf = NULL;
for (i = 0; i < argc; i++) {
len += strlen(argv[i]) + 1;
s = args_escape(argv[i]);
log_debug("%s: %u %s = %s", __func__, i, argv[i], s);
len += strlen(s) + 1;
buf = xrealloc(buf, len);
if (i == 0)
*buf = '\0';
else
strlcat(buf, " ", len);
strlcat(buf, argv[i], len);
strlcat(buf, s, len);
free(s);
}
return (buf);
}
/* Get entry for command. */
const struct cmd_entry *
cmd_get_entry(struct cmd *cmd)
{
return (cmd->entry);
}
/* Get arguments for command. */
struct args *
cmd_get_args(struct cmd *cmd)
{
return (cmd->args);
}
/* Get group for command. */
u_int
cmd_get_group(struct cmd *cmd)
{
return (cmd->group);
}
/* Get file and line for command. */
void
cmd_get_source(struct cmd *cmd, const char **file, u_int *line)
{
if (file != NULL)
*file = cmd->file;
if (line != NULL)
*line = cmd->line;
}
/* Look for an alias for a command. */
char *
cmd_get_alias(const char *name)
{
@ -379,7 +443,8 @@ cmd_get_alias(const char *name)
return (NULL);
}
static const struct cmd_entry *
/* Look up a command entry by name. */
const struct cmd_entry *
cmd_find(const char *name, char **cause)
{
const struct cmd_entry **loop, *entry, *found = NULL;
@ -428,32 +493,34 @@ ambiguous:
return (NULL);
}
/* Parse a single command from an argument vector. */
struct cmd *
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
cmd_parse(struct args_value *values, u_int count, const char *file, u_int line,
char **cause)
{
const struct cmd_entry *entry;
const char *name;
struct cmd *cmd;
struct args *args;
char *error = NULL;
if (argc == 0) {
if (count == 0 || values[0].type != ARGS_STRING) {
xasprintf(cause, "no command");
return (NULL);
}
name = argv[0];
entry = cmd_find(name, cause);
entry = cmd_find(values[0].string, cause);
if (entry == NULL)
return (NULL);
cmd_log_argv(argc, argv, "%s: %s", __func__, entry->name);
args = args_parse(entry->args.template, argc, argv);
if (args == NULL)
goto usage;
if (entry->args.lower != -1 && args->argc < entry->args.lower)
goto usage;
if (entry->args.upper != -1 && args->argc > entry->args.upper)
goto usage;
args = args_parse(&entry->args, values, count, &error);
if (args == NULL && error == NULL) {
xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
return (NULL);
}
if (args == NULL) {
xasprintf(cause, "command %s: %s", entry->name, error);
free(error);
return (NULL);
}
cmd = xcalloc(1, sizeof *cmd);
cmd->entry = entry;
@ -463,31 +530,37 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
cmd->file = xstrdup(file);
cmd->line = line;
cmd->alias = NULL;
cmd->argc = argc;
cmd->argv = cmd_copy_argv(argc, argv);
return (cmd);
usage:
if (args != NULL)
args_free(args);
xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
return (NULL);
}
/* Free a command. */
void
cmd_free(struct cmd *cmd)
{
free(cmd->alias);
cmd_free_argv(cmd->argc, cmd->argv);
free(cmd->file);
args_free(cmd->args);
free(cmd);
}
/* Copy a command. */
struct cmd *
cmd_copy(struct cmd *cmd, int argc, char **argv)
{
struct cmd *new_cmd;
new_cmd = xcalloc(1, sizeof *new_cmd);
new_cmd->entry = cmd->entry;
new_cmd->args = args_copy(cmd->args, argc, argv);
if (cmd->file != NULL)
new_cmd->file = xstrdup(cmd->file);
new_cmd->line = cmd->line;
return (new_cmd);
}
/* Get a command as a string. */
char *
cmd_print(struct cmd *cmd)
{
@ -503,6 +576,7 @@ cmd_print(struct cmd *cmd)
return (out);
}
/* Create a new command list. */
struct cmd_list *
cmd_list_new(void)
{
@ -511,29 +585,39 @@ cmd_list_new(void)
cmdlist = xcalloc(1, sizeof *cmdlist);
cmdlist->references = 1;
cmdlist->group = cmd_list_next_group++;
TAILQ_INIT(&cmdlist->list);
cmdlist->list = xcalloc(1, sizeof *cmdlist->list);
TAILQ_INIT(cmdlist->list);
return (cmdlist);
}
/* Append a command to a command list. */
void
cmd_list_append(struct cmd_list *cmdlist, struct cmd *cmd)
{
cmd->group = cmdlist->group;
TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
TAILQ_INSERT_TAIL(cmdlist->list, cmd, qentry);
}
/* Append all commands from one list to another. */
void
cmd_list_append_all(struct cmd_list *cmdlist, struct cmd_list *from)
{
struct cmd *cmd;
TAILQ_FOREACH(cmd, from->list, qentry)
cmd->group = cmdlist->group;
TAILQ_CONCAT(cmdlist->list, from->list, qentry);
}
/* Move all commands from one command list to another. */
void
cmd_list_move(struct cmd_list *cmdlist, struct cmd_list *from)
{
struct cmd *cmd, *cmd1;
TAILQ_FOREACH_SAFE(cmd, &from->list, qentry, cmd1) {
TAILQ_REMOVE(&from->list, cmd, qentry);
TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
}
TAILQ_CONCAT(cmdlist->list, from->list, qentry);
cmdlist->group = cmd_list_next_group++;
}
/* Free a command list. */
void
cmd_list_free(struct cmd_list *cmdlist)
{
@ -542,37 +626,78 @@ cmd_list_free(struct cmd_list *cmdlist)
if (--cmdlist->references != 0)
return;
TAILQ_FOREACH_SAFE(cmd, &cmdlist->list, qentry, cmd1) {
TAILQ_REMOVE(&cmdlist->list, cmd, qentry);
TAILQ_FOREACH_SAFE(cmd, cmdlist->list, qentry, cmd1) {
TAILQ_REMOVE(cmdlist->list, cmd, qentry);
cmd_free(cmd);
}
free(cmdlist->list);
free(cmdlist);
}
char *
cmd_list_print(struct cmd_list *cmdlist, int escaped)
/* Copy a command list, expanding %s in arguments. */
struct cmd_list *
cmd_list_copy(const struct cmd_list *cmdlist, int argc, char **argv)
{
struct cmd *cmd;
struct cmd_list *new_cmdlist;
struct cmd *new_cmd;
u_int group = cmdlist->group;
char *s;
s = cmd_list_print(cmdlist, 0);
log_debug("%s: %s", __func__, s);
free(s);
new_cmdlist = cmd_list_new();
TAILQ_FOREACH(cmd, cmdlist->list, qentry) {
if (cmd->group != group) {
new_cmdlist->group = cmd_list_next_group++;
group = cmd->group;
}
new_cmd = cmd_copy(cmd, argc, argv);
cmd_list_append(new_cmdlist, new_cmd);
}
s = cmd_list_print(new_cmdlist, 0);
log_debug("%s: %s", __func__, s);
free(s);
return (new_cmdlist);
}
/* Get a command list as a string. */
char *
cmd_list_print(const struct cmd_list *cmdlist, int escaped)
{
struct cmd *cmd, *next;
char *buf, *this;
size_t len;
len = 1;
buf = xcalloc(1, len);
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
TAILQ_FOREACH(cmd, cmdlist->list, qentry) {
this = cmd_print(cmd);
len += strlen(this) + 4;
len += strlen(this) + 6;
buf = xrealloc(buf, len);
strlcat(buf, this, len);
if (TAILQ_NEXT(cmd, qentry) != NULL) {
next = TAILQ_NEXT(cmd, qentry);
if (next != NULL) {
if (cmd->group != next->group) {
if (escaped)
strlcat(buf, " \\;\\; ", len);
else
strlcat(buf, " ;; ", len);
} else {
if (escaped)
strlcat(buf, " \\; ", len);
else
strlcat(buf, " ; ", len);
}
}
free(this);
}
@ -580,6 +705,46 @@ cmd_list_print(struct cmd_list *cmdlist, int escaped)
return (buf);
}
/* Get first command in list. */
struct cmd *
cmd_list_first(struct cmd_list *cmdlist)
{
return (TAILQ_FIRST(cmdlist->list));
}
/* Get next command in list. */
struct cmd *
cmd_list_next(struct cmd *cmd)
{
return (TAILQ_NEXT(cmd, qentry));
}
/* Do all of the commands in this command list have this flag? */
int
cmd_list_all_have(struct cmd_list *cmdlist, int flag)
{
struct cmd *cmd;
TAILQ_FOREACH(cmd, cmdlist->list, qentry) {
if (~cmd->entry->flags & flag)
return (0);
}
return (1);
}
/* Do any of the commands in this command list have this flag? */
int
cmd_list_any_have(struct cmd_list *cmdlist, int flag)
{
struct cmd *cmd;
TAILQ_FOREACH(cmd, cmdlist->list, qentry) {
if (cmd->entry->flags & flag)
return (1);
}
return (0);
}
/* Adjust current mouse position for a pane. */
int
cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
@ -645,10 +810,14 @@ cmd_mouse_pane(struct mouse_event *m, struct session **sp,
if ((wl = cmd_mouse_window(m, sp)) == NULL)
return (NULL);
if (m->wp == -1)
wp = wl->window->active;
else {
if ((wp = window_pane_find_by_id(m->wp)) == NULL)
return (NULL);
if (!window_has_pane(wl->window, wp))
return (NULL);
}
if (wlp != NULL)
*wlp = wl;

828
colour.c
View File

@ -22,6 +22,7 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "tmux.h"
@ -104,6 +105,21 @@ colour_split_rgb(int c, u_char *r, u_char *g, u_char *b)
*b = c & 0xff;
}
/* Force colour to RGB if not already. */
int
colour_force_rgb(int c)
{
if (c & COLOUR_FLAG_RGB)
return (c);
if (c & COLOUR_FLAG_256)
return (colour_256toRGB(c));
if (c >= 0 && c <= 7)
return (colour_256toRGB(c));
if (c >= 90 && c <= 97)
return (colour_256toRGB(8 + c - 90));
return (-1);
}
/* Convert colour to a string. */
const char *
colour_tostring(int c)
@ -111,6 +127,9 @@ colour_tostring(int c)
static char s[32];
u_char r, g, b;
if (c == -1)
return ("none");
if (c & COLOUR_FLAG_RGB) {
colour_split_rgb(c, &r, &g, &b);
xsnprintf(s, sizeof s, "#%02x%02x%02x", r, g, b);
@ -163,6 +182,46 @@ colour_tostring(int c)
return ("invalid");
}
/* Convert background colour to theme. */
enum client_theme
colour_totheme(int c)
{
int r, g, b, brightness;
if (c == -1)
return (THEME_UNKNOWN);
if (c & COLOUR_FLAG_RGB) {
r = (c >> 16) & 0xff;
g = (c >> 8) & 0xff;
b = (c >> 0) & 0xff;
brightness = r + g + b;
if (brightness > 382)
return (THEME_LIGHT);
return (THEME_DARK);
}
if (c & COLOUR_FLAG_256)
return (colour_totheme(colour_256toRGB(c)));
switch (c) {
case 0:
case 90:
return (THEME_DARK);
case 7:
case 97:
return (THEME_LIGHT);
default:
if (c >= 0 && c <= 7)
return (colour_totheme(colour_256toRGB(c)));
if (c >= 90 && c <= 97)
return (colour_totheme(colour_256toRGB(8 + c - 90)));
break;
}
return (THEME_UNKNOWN);
}
/* Convert colour from string. */
int
colour_fromstring(const char *s)
@ -189,6 +248,12 @@ colour_fromstring(const char *s)
return (-1);
return (n | COLOUR_FLAG_256);
}
if (strncasecmp(s, "color", (sizeof "color") - 1) == 0) {
n = strtonum(s + (sizeof "color") - 1, 0, 255, &errstr);
if (errstr != NULL)
return (-1);
return (n | COLOUR_FLAG_256);
}
if (strcasecmp(s, "default") == 0)
return (8);
@ -227,7 +292,7 @@ colour_fromstring(const char *s)
return (96);
if (strcasecmp(s, "brightwhite") == 0 || strcmp(s, "97") == 0)
return (97);
return (-1);
return (colour_byname(s));
}
/* Convert 256 colour to RGB colour. */
@ -329,3 +394,764 @@ colour_256to16(int c)
return (table[c & 0xff]);
}
/* Get colour by X11 colour name. */
int
colour_byname(const char *name)
{
static const struct {
const char *name;
int c;
} colours[] = {
{ "AliceBlue", 0xf0f8ff },
{ "AntiqueWhite", 0xfaebd7 },
{ "AntiqueWhite1", 0xffefdb },
{ "AntiqueWhite2", 0xeedfcc },
{ "AntiqueWhite3", 0xcdc0b0 },
{ "AntiqueWhite4", 0x8b8378 },
{ "BlanchedAlmond", 0xffebcd },
{ "BlueViolet", 0x8a2be2 },
{ "CadetBlue", 0x5f9ea0 },
{ "CadetBlue1", 0x98f5ff },
{ "CadetBlue2", 0x8ee5ee },
{ "CadetBlue3", 0x7ac5cd },
{ "CadetBlue4", 0x53868b },
{ "CornflowerBlue", 0x6495ed },
{ "DarkBlue", 0x00008b },
{ "DarkCyan", 0x008b8b },
{ "DarkGoldenrod", 0xb8860b },
{ "DarkGoldenrod1", 0xffb90f },
{ "DarkGoldenrod2", 0xeead0e },
{ "DarkGoldenrod3", 0xcd950c },
{ "DarkGoldenrod4", 0x8b6508 },
{ "DarkGray", 0xa9a9a9 },
{ "DarkGreen", 0x006400 },
{ "DarkGrey", 0xa9a9a9 },
{ "DarkKhaki", 0xbdb76b },
{ "DarkMagenta", 0x8b008b },
{ "DarkOliveGreen", 0x556b2f },
{ "DarkOliveGreen1", 0xcaff70 },
{ "DarkOliveGreen2", 0xbcee68 },
{ "DarkOliveGreen3", 0xa2cd5a },
{ "DarkOliveGreen4", 0x6e8b3d },
{ "DarkOrange", 0xff8c00 },
{ "DarkOrange1", 0xff7f00 },
{ "DarkOrange2", 0xee7600 },
{ "DarkOrange3", 0xcd6600 },
{ "DarkOrange4", 0x8b4500 },
{ "DarkOrchid", 0x9932cc },
{ "DarkOrchid1", 0xbf3eff },
{ "DarkOrchid2", 0xb23aee },
{ "DarkOrchid3", 0x9a32cd },
{ "DarkOrchid4", 0x68228b },
{ "DarkRed", 0x8b0000 },
{ "DarkSalmon", 0xe9967a },
{ "DarkSeaGreen", 0x8fbc8f },
{ "DarkSeaGreen1", 0xc1ffc1 },
{ "DarkSeaGreen2", 0xb4eeb4 },
{ "DarkSeaGreen3", 0x9bcd9b },
{ "DarkSeaGreen4", 0x698b69 },
{ "DarkSlateBlue", 0x483d8b },
{ "DarkSlateGray", 0x2f4f4f },
{ "DarkSlateGray1", 0x97ffff },
{ "DarkSlateGray2", 0x8deeee },
{ "DarkSlateGray3", 0x79cdcd },
{ "DarkSlateGray4", 0x528b8b },
{ "DarkSlateGrey", 0x2f4f4f },
{ "DarkTurquoise", 0x00ced1 },
{ "DarkViolet", 0x9400d3 },
{ "DeepPink", 0xff1493 },
{ "DeepPink1", 0xff1493 },
{ "DeepPink2", 0xee1289 },
{ "DeepPink3", 0xcd1076 },
{ "DeepPink4", 0x8b0a50 },
{ "DeepSkyBlue", 0x00bfff },
{ "DeepSkyBlue1", 0x00bfff },
{ "DeepSkyBlue2", 0x00b2ee },
{ "DeepSkyBlue3", 0x009acd },
{ "DeepSkyBlue4", 0x00688b },
{ "DimGray", 0x696969 },
{ "DimGrey", 0x696969 },
{ "DodgerBlue", 0x1e90ff },
{ "DodgerBlue1", 0x1e90ff },
{ "DodgerBlue2", 0x1c86ee },
{ "DodgerBlue3", 0x1874cd },
{ "DodgerBlue4", 0x104e8b },
{ "FloralWhite", 0xfffaf0 },
{ "ForestGreen", 0x228b22 },
{ "GhostWhite", 0xf8f8ff },
{ "GreenYellow", 0xadff2f },
{ "HotPink", 0xff69b4 },
{ "HotPink1", 0xff6eb4 },
{ "HotPink2", 0xee6aa7 },
{ "HotPink3", 0xcd6090 },
{ "HotPink4", 0x8b3a62 },
{ "IndianRed", 0xcd5c5c },
{ "IndianRed1", 0xff6a6a },
{ "IndianRed2", 0xee6363 },
{ "IndianRed3", 0xcd5555 },
{ "IndianRed4", 0x8b3a3a },
{ "LavenderBlush", 0xfff0f5 },
{ "LavenderBlush1", 0xfff0f5 },
{ "LavenderBlush2", 0xeee0e5 },
{ "LavenderBlush3", 0xcdc1c5 },
{ "LavenderBlush4", 0x8b8386 },
{ "LawnGreen", 0x7cfc00 },
{ "LemonChiffon", 0xfffacd },
{ "LemonChiffon1", 0xfffacd },
{ "LemonChiffon2", 0xeee9bf },
{ "LemonChiffon3", 0xcdc9a5 },
{ "LemonChiffon4", 0x8b8970 },
{ "LightBlue", 0xadd8e6 },
{ "LightBlue1", 0xbfefff },
{ "LightBlue2", 0xb2dfee },
{ "LightBlue3", 0x9ac0cd },
{ "LightBlue4", 0x68838b },
{ "LightCoral", 0xf08080 },
{ "LightCyan", 0xe0ffff },
{ "LightCyan1", 0xe0ffff },
{ "LightCyan2", 0xd1eeee },
{ "LightCyan3", 0xb4cdcd },
{ "LightCyan4", 0x7a8b8b },
{ "LightGoldenrod", 0xeedd82 },
{ "LightGoldenrod1", 0xffec8b },
{ "LightGoldenrod2", 0xeedc82 },
{ "LightGoldenrod3", 0xcdbe70 },
{ "LightGoldenrod4", 0x8b814c },
{ "LightGoldenrodYellow", 0xfafad2 },
{ "LightGray", 0xd3d3d3 },
{ "LightGreen", 0x90ee90 },
{ "LightGrey", 0xd3d3d3 },
{ "LightPink", 0xffb6c1 },
{ "LightPink1", 0xffaeb9 },
{ "LightPink2", 0xeea2ad },
{ "LightPink3", 0xcd8c95 },
{ "LightPink4", 0x8b5f65 },
{ "LightSalmon", 0xffa07a },
{ "LightSalmon1", 0xffa07a },
{ "LightSalmon2", 0xee9572 },
{ "LightSalmon3", 0xcd8162 },
{ "LightSalmon4", 0x8b5742 },
{ "LightSeaGreen", 0x20b2aa },
{ "LightSkyBlue", 0x87cefa },
{ "LightSkyBlue1", 0xb0e2ff },
{ "LightSkyBlue2", 0xa4d3ee },
{ "LightSkyBlue3", 0x8db6cd },
{ "LightSkyBlue4", 0x607b8b },
{ "LightSlateBlue", 0x8470ff },
{ "LightSlateGray", 0x778899 },
{ "LightSlateGrey", 0x778899 },
{ "LightSteelBlue", 0xb0c4de },
{ "LightSteelBlue1", 0xcae1ff },
{ "LightSteelBlue2", 0xbcd2ee },
{ "LightSteelBlue3", 0xa2b5cd },
{ "LightSteelBlue4", 0x6e7b8b },
{ "LightYellow", 0xffffe0 },
{ "LightYellow1", 0xffffe0 },
{ "LightYellow2", 0xeeeed1 },
{ "LightYellow3", 0xcdcdb4 },
{ "LightYellow4", 0x8b8b7a },
{ "LimeGreen", 0x32cd32 },
{ "MediumAquamarine", 0x66cdaa },
{ "MediumBlue", 0x0000cd },
{ "MediumOrchid", 0xba55d3 },
{ "MediumOrchid1", 0xe066ff },
{ "MediumOrchid2", 0xd15fee },
{ "MediumOrchid3", 0xb452cd },
{ "MediumOrchid4", 0x7a378b },
{ "MediumPurple", 0x9370db },
{ "MediumPurple1", 0xab82ff },
{ "MediumPurple2", 0x9f79ee },
{ "MediumPurple3", 0x8968cd },
{ "MediumPurple4", 0x5d478b },
{ "MediumSeaGreen", 0x3cb371 },
{ "MediumSlateBlue", 0x7b68ee },
{ "MediumSpringGreen", 0x00fa9a },
{ "MediumTurquoise", 0x48d1cc },
{ "MediumVioletRed", 0xc71585 },
{ "MidnightBlue", 0x191970 },
{ "MintCream", 0xf5fffa },
{ "MistyRose", 0xffe4e1 },
{ "MistyRose1", 0xffe4e1 },
{ "MistyRose2", 0xeed5d2 },
{ "MistyRose3", 0xcdb7b5 },
{ "MistyRose4", 0x8b7d7b },
{ "NavajoWhite", 0xffdead },
{ "NavajoWhite1", 0xffdead },
{ "NavajoWhite2", 0xeecfa1 },
{ "NavajoWhite3", 0xcdb38b },
{ "NavajoWhite4", 0x8b795e },
{ "NavyBlue", 0x000080 },
{ "OldLace", 0xfdf5e6 },
{ "OliveDrab", 0x6b8e23 },
{ "OliveDrab1", 0xc0ff3e },
{ "OliveDrab2", 0xb3ee3a },
{ "OliveDrab3", 0x9acd32 },
{ "OliveDrab4", 0x698b22 },
{ "OrangeRed", 0xff4500 },
{ "OrangeRed1", 0xff4500 },
{ "OrangeRed2", 0xee4000 },
{ "OrangeRed3", 0xcd3700 },
{ "OrangeRed4", 0x8b2500 },
{ "PaleGoldenrod", 0xeee8aa },
{ "PaleGreen", 0x98fb98 },
{ "PaleGreen1", 0x9aff9a },
{ "PaleGreen2", 0x90ee90 },
{ "PaleGreen3", 0x7ccd7c },
{ "PaleGreen4", 0x548b54 },
{ "PaleTurquoise", 0xafeeee },
{ "PaleTurquoise1", 0xbbffff },
{ "PaleTurquoise2", 0xaeeeee },
{ "PaleTurquoise3", 0x96cdcd },
{ "PaleTurquoise4", 0x668b8b },
{ "PaleVioletRed", 0xdb7093 },
{ "PaleVioletRed1", 0xff82ab },
{ "PaleVioletRed2", 0xee799f },
{ "PaleVioletRed3", 0xcd6889 },
{ "PaleVioletRed4", 0x8b475d },
{ "PapayaWhip", 0xffefd5 },
{ "PeachPuff", 0xffdab9 },
{ "PeachPuff1", 0xffdab9 },
{ "PeachPuff2", 0xeecbad },
{ "PeachPuff3", 0xcdaf95 },
{ "PeachPuff4", 0x8b7765 },
{ "PowderBlue", 0xb0e0e6 },
{ "RebeccaPurple", 0x663399 },
{ "RosyBrown", 0xbc8f8f },
{ "RosyBrown1", 0xffc1c1 },
{ "RosyBrown2", 0xeeb4b4 },
{ "RosyBrown3", 0xcd9b9b },
{ "RosyBrown4", 0x8b6969 },
{ "RoyalBlue", 0x4169e1 },
{ "RoyalBlue1", 0x4876ff },
{ "RoyalBlue2", 0x436eee },
{ "RoyalBlue3", 0x3a5fcd },
{ "RoyalBlue4", 0x27408b },
{ "SaddleBrown", 0x8b4513 },
{ "SandyBrown", 0xf4a460 },
{ "SeaGreen", 0x2e8b57 },
{ "SeaGreen1", 0x54ff9f },
{ "SeaGreen2", 0x4eee94 },
{ "SeaGreen3", 0x43cd80 },
{ "SeaGreen4", 0x2e8b57 },
{ "SkyBlue", 0x87ceeb },
{ "SkyBlue1", 0x87ceff },
{ "SkyBlue2", 0x7ec0ee },
{ "SkyBlue3", 0x6ca6cd },
{ "SkyBlue4", 0x4a708b },
{ "SlateBlue", 0x6a5acd },
{ "SlateBlue1", 0x836fff },
{ "SlateBlue2", 0x7a67ee },
{ "SlateBlue3", 0x6959cd },
{ "SlateBlue4", 0x473c8b },
{ "SlateGray", 0x708090 },
{ "SlateGray1", 0xc6e2ff },
{ "SlateGray2", 0xb9d3ee },
{ "SlateGray3", 0x9fb6cd },
{ "SlateGray4", 0x6c7b8b },
{ "SlateGrey", 0x708090 },
{ "SpringGreen", 0x00ff7f },
{ "SpringGreen1", 0x00ff7f },
{ "SpringGreen2", 0x00ee76 },
{ "SpringGreen3", 0x00cd66 },
{ "SpringGreen4", 0x008b45 },
{ "SteelBlue", 0x4682b4 },
{ "SteelBlue1", 0x63b8ff },
{ "SteelBlue2", 0x5cacee },
{ "SteelBlue3", 0x4f94cd },
{ "SteelBlue4", 0x36648b },
{ "VioletRed", 0xd02090 },
{ "VioletRed1", 0xff3e96 },
{ "VioletRed2", 0xee3a8c },
{ "VioletRed3", 0xcd3278 },
{ "VioletRed4", 0x8b2252 },
{ "WebGray", 0x808080 },
{ "WebGreen", 0x008000 },
{ "WebGrey", 0x808080 },
{ "WebMaroon", 0x800000 },
{ "WebPurple", 0x800080 },
{ "WhiteSmoke", 0xf5f5f5 },
{ "X11Gray", 0xbebebe },
{ "X11Green", 0x00ff00 },
{ "X11Grey", 0xbebebe },
{ "X11Maroon", 0xb03060 },
{ "X11Purple", 0xa020f0 },
{ "YellowGreen", 0x9acd32 },
{ "alice blue", 0xf0f8ff },
{ "antique white", 0xfaebd7 },
{ "aqua", 0x00ffff },
{ "aquamarine", 0x7fffd4 },
{ "aquamarine1", 0x7fffd4 },
{ "aquamarine2", 0x76eec6 },
{ "aquamarine3", 0x66cdaa },
{ "aquamarine4", 0x458b74 },
{ "azure", 0xf0ffff },
{ "azure1", 0xf0ffff },
{ "azure2", 0xe0eeee },
{ "azure3", 0xc1cdcd },
{ "azure4", 0x838b8b },
{ "beige", 0xf5f5dc },
{ "bisque", 0xffe4c4 },
{ "bisque1", 0xffe4c4 },
{ "bisque2", 0xeed5b7 },
{ "bisque3", 0xcdb79e },
{ "bisque4", 0x8b7d6b },
{ "black", 0x000000 },
{ "blanched almond", 0xffebcd },
{ "blue violet", 0x8a2be2 },
{ "blue", 0x0000ff },
{ "blue1", 0x0000ff },
{ "blue2", 0x0000ee },
{ "blue3", 0x0000cd },
{ "blue4", 0x00008b },
{ "brown", 0xa52a2a },
{ "brown1", 0xff4040 },
{ "brown2", 0xee3b3b },
{ "brown3", 0xcd3333 },
{ "brown4", 0x8b2323 },
{ "burlywood", 0xdeb887 },
{ "burlywood1", 0xffd39b },
{ "burlywood2", 0xeec591 },
{ "burlywood3", 0xcdaa7d },
{ "burlywood4", 0x8b7355 },
{ "cadet blue", 0x5f9ea0 },
{ "chartreuse", 0x7fff00 },
{ "chartreuse1", 0x7fff00 },
{ "chartreuse2", 0x76ee00 },
{ "chartreuse3", 0x66cd00 },
{ "chartreuse4", 0x458b00 },
{ "chocolate", 0xd2691e },
{ "chocolate1", 0xff7f24 },
{ "chocolate2", 0xee7621 },
{ "chocolate3", 0xcd661d },
{ "chocolate4", 0x8b4513 },
{ "coral", 0xff7f50 },
{ "coral1", 0xff7256 },
{ "coral2", 0xee6a50 },
{ "coral3", 0xcd5b45 },
{ "coral4", 0x8b3e2f },
{ "cornflower blue", 0x6495ed },
{ "cornsilk", 0xfff8dc },
{ "cornsilk1", 0xfff8dc },
{ "cornsilk2", 0xeee8cd },
{ "cornsilk3", 0xcdc8b1 },
{ "cornsilk4", 0x8b8878 },
{ "crimson", 0xdc143c },
{ "cyan", 0x00ffff },
{ "cyan1", 0x00ffff },
{ "cyan2", 0x00eeee },
{ "cyan3", 0x00cdcd },
{ "cyan4", 0x008b8b },
{ "dark blue", 0x00008b },
{ "dark cyan", 0x008b8b },
{ "dark goldenrod", 0xb8860b },
{ "dark gray", 0xa9a9a9 },
{ "dark green", 0x006400 },
{ "dark grey", 0xa9a9a9 },
{ "dark khaki", 0xbdb76b },
{ "dark magenta", 0x8b008b },
{ "dark olive green", 0x556b2f },
{ "dark orange", 0xff8c00 },
{ "dark orchid", 0x9932cc },
{ "dark red", 0x8b0000 },
{ "dark salmon", 0xe9967a },
{ "dark sea green", 0x8fbc8f },
{ "dark slate blue", 0x483d8b },
{ "dark slate gray", 0x2f4f4f },
{ "dark slate grey", 0x2f4f4f },
{ "dark turquoise", 0x00ced1 },
{ "dark violet", 0x9400d3 },
{ "deep pink", 0xff1493 },
{ "deep sky blue", 0x00bfff },
{ "dim gray", 0x696969 },
{ "dim grey", 0x696969 },
{ "dodger blue", 0x1e90ff },
{ "firebrick", 0xb22222 },
{ "firebrick1", 0xff3030 },
{ "firebrick2", 0xee2c2c },
{ "firebrick3", 0xcd2626 },
{ "firebrick4", 0x8b1a1a },
{ "floral white", 0xfffaf0 },
{ "forest green", 0x228b22 },
{ "fuchsia", 0xff00ff },
{ "gainsboro", 0xdcdcdc },
{ "ghost white", 0xf8f8ff },
{ "gold", 0xffd700 },
{ "gold1", 0xffd700 },
{ "gold2", 0xeec900 },
{ "gold3", 0xcdad00 },
{ "gold4", 0x8b7500 },
{ "goldenrod", 0xdaa520 },
{ "goldenrod1", 0xffc125 },
{ "goldenrod2", 0xeeb422 },
{ "goldenrod3", 0xcd9b1d },
{ "goldenrod4", 0x8b6914 },
{ "green yellow", 0xadff2f },
{ "green", 0x00ff00 },
{ "green1", 0x00ff00 },
{ "green2", 0x00ee00 },
{ "green3", 0x00cd00 },
{ "green4", 0x008b00 },
{ "honeydew", 0xf0fff0 },
{ "honeydew1", 0xf0fff0 },
{ "honeydew2", 0xe0eee0 },
{ "honeydew3", 0xc1cdc1 },
{ "honeydew4", 0x838b83 },
{ "hot pink", 0xff69b4 },
{ "indian red", 0xcd5c5c },
{ "indigo", 0x4b0082 },
{ "ivory", 0xfffff0 },
{ "ivory1", 0xfffff0 },
{ "ivory2", 0xeeeee0 },
{ "ivory3", 0xcdcdc1 },
{ "ivory4", 0x8b8b83 },
{ "khaki", 0xf0e68c },
{ "khaki1", 0xfff68f },
{ "khaki2", 0xeee685 },
{ "khaki3", 0xcdc673 },
{ "khaki4", 0x8b864e },
{ "lavender blush", 0xfff0f5 },
{ "lavender", 0xe6e6fa },
{ "lawn green", 0x7cfc00 },
{ "lemon chiffon", 0xfffacd },
{ "light blue", 0xadd8e6 },
{ "light coral", 0xf08080 },
{ "light cyan", 0xe0ffff },
{ "light goldenrod yellow", 0xfafad2 },
{ "light goldenrod", 0xeedd82 },
{ "light gray", 0xd3d3d3 },
{ "light green", 0x90ee90 },
{ "light grey", 0xd3d3d3 },
{ "light pink", 0xffb6c1 },
{ "light salmon", 0xffa07a },
{ "light sea green", 0x20b2aa },
{ "light sky blue", 0x87cefa },
{ "light slate blue", 0x8470ff },
{ "light slate gray", 0x778899 },
{ "light slate grey", 0x778899 },
{ "light steel blue", 0xb0c4de },
{ "light yellow", 0xffffe0 },
{ "lime green", 0x32cd32 },
{ "lime", 0x00ff00 },
{ "linen", 0xfaf0e6 },
{ "magenta", 0xff00ff },
{ "magenta1", 0xff00ff },
{ "magenta2", 0xee00ee },
{ "magenta3", 0xcd00cd },
{ "magenta4", 0x8b008b },
{ "maroon", 0xb03060 },
{ "maroon1", 0xff34b3 },
{ "maroon2", 0xee30a7 },
{ "maroon3", 0xcd2990 },
{ "maroon4", 0x8b1c62 },
{ "medium aquamarine", 0x66cdaa },
{ "medium blue", 0x0000cd },
{ "medium orchid", 0xba55d3 },
{ "medium purple", 0x9370db },
{ "medium sea green", 0x3cb371 },
{ "medium slate blue", 0x7b68ee },
{ "medium spring green", 0x00fa9a },
{ "medium turquoise", 0x48d1cc },
{ "medium violet red", 0xc71585 },
{ "midnight blue", 0x191970 },
{ "mint cream", 0xf5fffa },
{ "misty rose", 0xffe4e1 },
{ "moccasin", 0xffe4b5 },
{ "navajo white", 0xffdead },
{ "navy blue", 0x000080 },
{ "navy", 0x000080 },
{ "old lace", 0xfdf5e6 },
{ "olive drab", 0x6b8e23 },
{ "olive", 0x808000 },
{ "orange red", 0xff4500 },
{ "orange", 0xffa500 },
{ "orange1", 0xffa500 },
{ "orange2", 0xee9a00 },
{ "orange3", 0xcd8500 },
{ "orange4", 0x8b5a00 },
{ "orchid", 0xda70d6 },
{ "orchid1", 0xff83fa },
{ "orchid2", 0xee7ae9 },
{ "orchid3", 0xcd69c9 },
{ "orchid4", 0x8b4789 },
{ "pale goldenrod", 0xeee8aa },
{ "pale green", 0x98fb98 },
{ "pale turquoise", 0xafeeee },
{ "pale violet red", 0xdb7093 },
{ "papaya whip", 0xffefd5 },
{ "peach puff", 0xffdab9 },
{ "peru", 0xcd853f },
{ "pink", 0xffc0cb },
{ "pink1", 0xffb5c5 },
{ "pink2", 0xeea9b8 },
{ "pink3", 0xcd919e },
{ "pink4", 0x8b636c },
{ "plum", 0xdda0dd },
{ "plum1", 0xffbbff },
{ "plum2", 0xeeaeee },
{ "plum3", 0xcd96cd },
{ "plum4", 0x8b668b },
{ "powder blue", 0xb0e0e6 },
{ "purple", 0xa020f0 },
{ "purple1", 0x9b30ff },
{ "purple2", 0x912cee },
{ "purple3", 0x7d26cd },
{ "purple4", 0x551a8b },
{ "rebecca purple", 0x663399 },
{ "red", 0xff0000 },
{ "red1", 0xff0000 },
{ "red2", 0xee0000 },
{ "red3", 0xcd0000 },
{ "red4", 0x8b0000 },
{ "rosy brown", 0xbc8f8f },
{ "royal blue", 0x4169e1 },
{ "saddle brown", 0x8b4513 },
{ "salmon", 0xfa8072 },
{ "salmon1", 0xff8c69 },
{ "salmon2", 0xee8262 },
{ "salmon3", 0xcd7054 },
{ "salmon4", 0x8b4c39 },
{ "sandy brown", 0xf4a460 },
{ "sea green", 0x2e8b57 },
{ "seashell", 0xfff5ee },
{ "seashell1", 0xfff5ee },
{ "seashell2", 0xeee5de },
{ "seashell3", 0xcdc5bf },
{ "seashell4", 0x8b8682 },
{ "sienna", 0xa0522d },
{ "sienna1", 0xff8247 },
{ "sienna2", 0xee7942 },
{ "sienna3", 0xcd6839 },
{ "sienna4", 0x8b4726 },
{ "silver", 0xc0c0c0 },
{ "sky blue", 0x87ceeb },
{ "slate blue", 0x6a5acd },
{ "slate gray", 0x708090 },
{ "slate grey", 0x708090 },
{ "snow", 0xfffafa },
{ "snow1", 0xfffafa },
{ "snow2", 0xeee9e9 },
{ "snow3", 0xcdc9c9 },
{ "snow4", 0x8b8989 },
{ "spring green", 0x00ff7f },
{ "steel blue", 0x4682b4 },
{ "tan", 0xd2b48c },
{ "tan1", 0xffa54f },
{ "tan2", 0xee9a49 },
{ "tan3", 0xcd853f },
{ "tan4", 0x8b5a2b },
{ "teal", 0x008080 },
{ "thistle", 0xd8bfd8 },
{ "thistle1", 0xffe1ff },
{ "thistle2", 0xeed2ee },
{ "thistle3", 0xcdb5cd },
{ "thistle4", 0x8b7b8b },
{ "tomato", 0xff6347 },
{ "tomato1", 0xff6347 },
{ "tomato2", 0xee5c42 },
{ "tomato3", 0xcd4f39 },
{ "tomato4", 0x8b3626 },
{ "turquoise", 0x40e0d0 },
{ "turquoise1", 0x00f5ff },
{ "turquoise2", 0x00e5ee },
{ "turquoise3", 0x00c5cd },
{ "turquoise4", 0x00868b },
{ "violet red", 0xd02090 },
{ "violet", 0xee82ee },
{ "web gray", 0x808080 },
{ "web green", 0x008000 },
{ "web grey", 0x808080 },
{ "web maroon", 0x800000 },
{ "web purple", 0x800080 },
{ "wheat", 0xf5deb3 },
{ "wheat1", 0xffe7ba },
{ "wheat2", 0xeed8ae },
{ "wheat3", 0xcdba96 },
{ "wheat4", 0x8b7e66 },
{ "white smoke", 0xf5f5f5 },
{ "white", 0xffffff },
{ "x11 gray", 0xbebebe },
{ "x11 green", 0x00ff00 },
{ "x11 grey", 0xbebebe },
{ "x11 maroon", 0xb03060 },
{ "x11 purple", 0xa020f0 },
{ "yellow green", 0x9acd32 },
{ "yellow", 0xffff00 },
{ "yellow1", 0xffff00 },
{ "yellow2", 0xeeee00 },
{ "yellow3", 0xcdcd00 },
{ "yellow4", 0x8b8b00 }
};
u_int i;
int c;
const char *errstr;
if (strncmp(name, "grey", 4) == 0 || strncmp(name, "gray", 4) == 0) {
if (name[4] == '\0')
return (0xbebebe|COLOUR_FLAG_RGB);
c = strtonum(name + 4, 0, 100, &errstr);
if (errstr != NULL)
return (-1);
c = round(2.55 * c);
if (c < 0 || c > 255)
return (-1);
return (colour_join_rgb(c, c, c));
}
for (i = 0; i < nitems(colours); i++) {
if (strcasecmp(colours[i].name, name) == 0)
return (colours[i].c|COLOUR_FLAG_RGB);
}
return (-1);
}
/* Parse colour from an X11 string. */
int
colour_parseX11(const char *p)
{
double c, m, y, k = 0;
u_int r, g, b;
size_t len = strlen(p);
int colour = -1;
char *copy;
if ((len == 12 && sscanf(p, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3) ||
(len == 7 && sscanf(p, "#%02x%02x%02x", &r, &g, &b) == 3) ||
sscanf(p, "%d,%d,%d", &r, &g, &b) == 3)
colour = colour_join_rgb(r, g, b);
else if ((len == 18 &&
sscanf(p, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3) ||
(len == 13 && sscanf(p, "#%04x%04x%04x", &r, &g, &b) == 3))
colour = colour_join_rgb(r >> 8, g >> 8, b >> 8);
else if ((sscanf(p, "cmyk:%lf/%lf/%lf/%lf", &c, &m, &y, &k) == 4 ||
sscanf(p, "cmy:%lf/%lf/%lf", &c, &m, &y) == 3) &&
c >= 0 && c <= 1 && m >= 0 && m <= 1 &&
y >= 0 && y <= 1 && k >= 0 && k <= 1) {
colour = colour_join_rgb(
(1 - c) * (1 - k) * 255,
(1 - m) * (1 - k) * 255,
(1 - y) * (1 - k) * 255);
} else {
while (len != 0 && *p == ' ') {
p++;
len--;
}
while (len != 0 && p[len - 1] == ' ')
len--;
copy = xstrndup(p, len);
colour = colour_byname(copy);
free(copy);
}
log_debug("%s: %s = %s", __func__, p, colour_tostring(colour));
return (colour);
}
/* Initialize palette. */
void
colour_palette_init(struct colour_palette *p)
{
p->fg = 8;
p->bg = 8;
p->palette = NULL;
p->default_palette = NULL;
}
/* Clear palette. */
void
colour_palette_clear(struct colour_palette *p)
{
if (p != NULL) {
p->fg = 8;
p->bg = 8;
free(p->palette);
p->palette = NULL;
}
}
/* Free a palette. */
void
colour_palette_free(struct colour_palette *p)
{
if (p != NULL) {
free(p->palette);
p->palette = NULL;
free(p->default_palette);
p->default_palette = NULL;
}
}
/* Get a colour from a palette. */
int
colour_palette_get(struct colour_palette *p, int c)
{
if (p == NULL)
return (-1);
if (c >= 90 && c <= 97)
c = 8 + c - 90;
else if (c & COLOUR_FLAG_256)
c &= ~COLOUR_FLAG_256;
else if (c >= 8)
return (-1);
if (p->palette != NULL && p->palette[c] != -1)
return (p->palette[c]);
if (p->default_palette != NULL && p->default_palette[c] != -1)
return (p->default_palette[c]);
return (-1);
}
/* Set a colour in a palette. */
int
colour_palette_set(struct colour_palette *p, int n, int c)
{
u_int i;
if (p == NULL || n > 255)
return (0);
if (c == -1 && p->palette == NULL)
return (0);
if (c != -1 && p->palette == NULL) {
if (p->palette == NULL)
p->palette = xcalloc(256, sizeof *p->palette);
for (i = 0; i < 256; i++)
p->palette[i] = -1;
}
p->palette[n] = c;
return (1);
}
/* Build palette defaults from an option. */
void
colour_palette_from_option(struct colour_palette *p, struct options *oo)
{
struct options_entry *o;
struct options_array_item *a;
u_int i, n;
int c;
if (p == NULL)
return;
o = options_get(oo, "pane-colours");
if ((a = options_array_first(o)) == NULL) {
if (p->default_palette != NULL) {
free(p->default_palette);
p->default_palette = NULL;
}
return;
}
if (p->default_palette == NULL)
p->default_palette = xcalloc(256, sizeof *p->default_palette);
for (i = 0; i < 256; i++)
p->default_palette[i] = -1;
while (a != NULL) {
n = options_array_item_index(a);
if (n < 256) {
c = options_array_item_value(a)->number;
p->default_palette[n] = c;
}
a = options_array_next(a);
}
}

View File

@ -27,10 +27,43 @@
#include <termios.h>
#include <wchar.h>
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/event.h>
#include <event2/event_compat.h>
#include <event2/event_struct.h>
#include <event2/buffer.h>
#include <event2/buffer_compat.h>
#include <event2/bufferevent.h>
#include <event2/bufferevent_struct.h>
#include <event2/bufferevent_compat.h>
#else
#include <event.h>
#ifndef EVBUFFER_EOL_LF
/*
* This doesn't really work because evbuffer_readline is broken, but gets us to
* build with very old (older than 1.4.14) libevent.
*/
#define EVBUFFER_EOL_LF
#define evbuffer_readln(a, b, c) evbuffer_readline(a)
#endif
#endif
#ifdef HAVE_MALLOC_TRIM
#include <malloc.h>
#endif
#ifdef HAVE_UTF8PROC
#include <utf8proc.h>
#endif
#ifndef __GNUC__
#define __attribute__(a)
#endif
#ifdef BROKEN___DEAD
#undef __dead
#endif
#ifndef __unused
#define __unused __attribute__ ((__unused__))
#endif
@ -40,6 +73,9 @@
#ifndef __packed
#define __packed __attribute__ ((__packed__))
#endif
#ifndef __weak
#define __weak __attribute__ ((__weak__))
#endif
#ifndef ECHOPRT
#define ECHOPRT 0
@ -90,10 +126,18 @@ void warnx(const char *, ...);
#define _PATH_DEFPATH "/usr/bin:/bin"
#endif
#ifndef _PATH_VI
#define _PATH_VI "/usr/bin/vi"
#endif
#ifndef __OpenBSD__
#define pledge(s, p) (0)
#endif
#ifndef IMAXBEL
#define IMAXBEL 0
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#else
@ -229,6 +273,13 @@ void warnx(const char *, ...);
#define HOST_NAME_MAX 255
#endif
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC CLOCK_REALTIME
#endif
#ifndef HAVE_FLOCK
#define LOCK_SH 0
#define LOCK_EX 0
@ -246,6 +297,11 @@ void explicit_bzero(void *, size_t);
int getdtablecount(void);
#endif
#ifndef HAVE_GETDTABLESIZE
/* getdtablesize.c */
int getdtablesize(void);
#endif
#ifndef HAVE_CLOSEFROM
/* closefrom.c */
void closefrom(int);
@ -291,6 +347,23 @@ char *strndup(const char *, size_t);
void *memmem(const void *, size_t, const void *, size_t);
#endif
#ifndef HAVE_HTONLL
/* htonll.c */
#undef htonll
uint64_t htonll(uint64_t);
#endif
#ifndef HAVE_NTOHLL
/* ntohll.c */
#undef ntohll
uint64_t ntohll(uint64_t);
#endif
#ifndef HAVE_GETPEEREID
/* getpeereid.c */
int getpeereid(int, uid_t *, gid_t *);
#endif
#ifndef HAVE_DAEMON
/* daemon.c */
int daemon(int, int);
@ -306,6 +379,11 @@ const char *getprogname(void);
void setproctitle(const char *, ...);
#endif
#ifndef HAVE_CLOCK_GETTIME
/* clock_gettime.c */
int clock_gettime(int, struct timespec *);
#endif
#ifndef HAVE_B64_NTOP
/* base64.c */
#undef b64_ntop
@ -337,6 +415,11 @@ int vasprintf(char **, const char *, va_list);
char *fgetln(FILE *, size_t *);
#endif
#ifndef HAVE_GETLINE
/* getline.c */
ssize_t getline(char **, size_t *, FILE *);
#endif
#ifndef HAVE_SETENV
/* setenv.c */
int setenv(const char *, const char *, int);
@ -363,6 +446,13 @@ void *reallocarray(void *, size_t, size_t);
void *recallocarray(void *, size_t, size_t, size_t);
#endif
#ifdef HAVE_SYSTEMD
/* systemd.c */
int systemd_activated(void);
int systemd_create_socket(int, char **);
int systemd_move_to_new_cgroup(char **);
#endif
#ifdef HAVE_UTF8PROC
/* utf8proc.c */
int utf8proc_wcwidth(wchar_t);
@ -370,6 +460,11 @@ int utf8proc_mbtowc(wchar_t *, const char *, size_t);
int utf8proc_wctomb(char *, wchar_t);
#endif
#ifdef NEED_FUZZING
/* tmux.c */
#define main __weak main
#endif
/* getopt.c */
extern int BSDopterr;
extern int BSDoptind;

37
compat/clock_gettime.c Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2021 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 <sys/time.h>
#include "compat.h"
#ifndef TIMEVAL_TO_TIMESPEC
#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
} while (0)
#endif
int
clock_gettime(__unused int clock, struct timespec *ts)
{
struct timeval tv;
gettimeofday(&tv, NULL);
TIMEVAL_TO_TIMESPEC(&tv, ts);
return 0;
}

View File

@ -44,6 +44,9 @@
# include <ndir.h>
# endif
#endif
#if defined(HAVE_LIBPROC_H)
# include <libproc.h>
#endif
#include "compat.h"
@ -55,39 +58,15 @@
__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $";
#endif /* lint */
#ifndef HAVE_FCNTL_CLOSEM
/*
* Close all file descriptors greater than or equal to lowfd.
*/
#ifdef HAVE_FCNTL_CLOSEM
void
closefrom(int lowfd)
{
(void) fcntl(lowfd, F_CLOSEM, 0);
}
#else
void
closefrom(int lowfd)
static void
closefrom_fallback(int lowfd)
{
long fd, maxfd;
#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
char fdpath[PATH_MAX], *endp;
struct dirent *dent;
DIR *dirp;
int len;
/* Check for a /proc/$$/fd directory. */
len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
while ((dent = readdir(dirp)) != NULL) {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
(void) close((int) fd);
}
(void) closedir(dirp);
} else
#endif
{
/*
* Fall back on sysconf() or getdtablesize(). We avoid checking
* resource limits since it is possible to open a file descriptor
@ -104,6 +83,73 @@ closefrom(int lowfd)
for (fd = lowfd; fd < maxfd; fd++)
(void) close((int) fd);
}
#endif /* HAVE_FCNTL_CLOSEM */
#ifdef HAVE_FCNTL_CLOSEM
void
closefrom(int lowfd)
{
(void) fcntl(lowfd, F_CLOSEM, 0);
}
#elif defined(HAVE_LIBPROC_H) && defined(HAVE_PROC_PIDINFO)
void
closefrom(int lowfd)
{
int i, r, sz;
pid_t pid = getpid();
struct proc_fdinfo *fdinfo_buf = NULL;
sz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
if (sz == 0)
return; /* no fds, really? */
else if (sz == -1)
goto fallback;
if ((fdinfo_buf = malloc(sz)) == NULL)
goto fallback;
r = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo_buf, sz);
if (r < 0 || r > sz)
goto fallback;
for (i = 0; i < r / (int)PROC_PIDLISTFD_SIZE; i++) {
if (fdinfo_buf[i].proc_fd >= lowfd)
close(fdinfo_buf[i].proc_fd);
}
free(fdinfo_buf);
return;
fallback:
free(fdinfo_buf);
closefrom_fallback(lowfd);
return;
}
#elif defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
void
closefrom(int lowfd)
{
long fd;
char fdpath[PATH_MAX], *endp;
struct dirent *dent;
DIR *dirp;
int len;
/* Check for a /proc/$$/fd directory. */
len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) {
while ((dent = readdir(dirp)) != NULL) {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
(void) close((int) fd);
}
(void) closedir(dirp);
return;
}
/* /proc/$$/fd strategy failed, fall back to brute force closure */
closefrom_fallback(lowfd);
}
#else
void
closefrom(int lowfd)
{
closefrom_fallback(lowfd);
}
#endif /* !HAVE_FCNTL_CLOSEM */
#endif /* HAVE_CLOSEFROM */

82
compat/forkpty-haiku.c Normal file
View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2008 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 <sys/ioctl.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include "compat.h"
void fatal(const char *, ...);
void fatalx(const char *, ...);
pid_t
forkpty(int *master, char *name, struct termios *tio, struct winsize *ws)
{
int slave = -1;
char *path;
pid_t pid;
if ((*master = open("/dev/ptmx", O_RDWR|O_NOCTTY)) == -1)
return (-1);
if (grantpt(*master) != 0)
goto out;
if (unlockpt(*master) != 0)
goto out;
if ((path = ptsname(*master)) == NULL)
goto out;
if (name != NULL)
strlcpy(name, path, TTY_NAME_MAX);
if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1)
goto out;
switch (pid = fork()) {
case -1:
goto out;
case 0:
close(*master);
setsid();
if (ioctl(slave, TIOCSCTTY, NULL) == -1)
fatal("ioctl failed");
if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1)
fatal("tcsetattr failed");
if (ioctl(slave, TIOCSWINSZ, ws) == -1)
fatal("ioctl failed");
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
if (slave > 2)
close(slave);
return (0);
}
close(slave);
return (pid);
out:
if (*master != -1)
close(*master);
if (slave != -1)
close(slave);
return (-1);
}

29
compat/getdtablesize.c Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2020 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 <unistd.h>
#include "compat.h"
#ifdef HAVE_SYSCONF
int
getdtablesize(void)
{
return (sysconf(_SC_OPEN_MAX));
}
#endif

93
compat/getline.c Normal file
View File

@ -0,0 +1,93 @@
/* $NetBSD: getline.c,v 1.1.1.6 2015/01/02 20:34:27 christos Exp $ */
/* NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* NETBSD ORIGINAL: external/bsd/file/dist/src/getline.c */
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "tmux.h"
static ssize_t
getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
{
char *ptr, *eptr;
if (*buf == NULL || *bufsiz == 0) {
if ((*buf = malloc(BUFSIZ)) == NULL)
return -1;
*bufsiz = BUFSIZ;
}
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
int c = fgetc(fp);
if (c == -1) {
if (feof(fp)) {
ssize_t diff = (ssize_t)(ptr - *buf);
if (diff != 0) {
*ptr = '\0';
return diff;
}
}
return -1;
}
*ptr++ = c;
if (c == delimiter) {
*ptr = '\0';
return ptr - *buf;
}
if (ptr + 2 >= eptr) {
char *nbuf;
size_t nbufsiz = *bufsiz * 2;
ssize_t d = ptr - *buf;
if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
return -1;
*buf = nbuf;
*bufsiz = nbufsiz;
eptr = nbuf + nbufsiz;
ptr = nbuf + d;
}
}
}
ssize_t
getline(char **buf, size_t *bufsiz, FILE *fp)
{
return getdelim(buf, bufsiz, '\n', fp);
}

View File

@ -1,115 +0,0 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */
#include "compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int BSDopterr = 1, /* if error message should be printed */
BSDoptind = 1, /* index into parent argv vector */
BSDoptopt, /* character checked for validity */
BSDoptreset; /* reset getopt */
char *BSDoptarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
BSDgetopt(int nargc, char *const *nargv, const char *ostr)
{
static const char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (ostr == NULL)
return (-1);
if (BSDoptreset || !*place) { /* update scanning pointer */
BSDoptreset = 0;
if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-') { /* found "--" */
if (place[1])
return (BADCH);
++BSDoptind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((BSDoptopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, BSDoptopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (BSDoptopt == (int)'-')
return (-1);
if (!*place)
++BSDoptind;
if (BSDopterr && *ostr != ':')
(void)fprintf(stderr,
"%s: unknown option -- %c\n", getprogname(),
BSDoptopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
BSDoptarg = NULL;
if (!*place)
++BSDoptind;
}
else { /* need an argument */
if (*place) /* no white space */
BSDoptarg = (char *)place;
else if (nargc <= ++BSDoptind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (BSDopterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
getprogname(), BSDoptopt);
return (BADCH);
}
else /* white space */
BSDoptarg = nargv[BSDoptind];
place = EMSG;
++BSDoptind;
}
return (BSDoptopt); /* dump back option letter */
}

577
compat/getopt_long.c Normal file
View File

@ -0,0 +1,577 @@
/* This file is obtained from OpenSSH:
* Repository: https://github.com/openssh/openssh-portable
* Commit: b5b405fee7f3e79d44e2d2971a4b6b4cc53f112e
* File: /openbsd-compat/getopt_long.c */
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt_long.c */
#include "compat.h"
/* The following macro constants are taken from getopt.h of OpenSSH:
* Repository: https://github.com/openssh/openssh-portable
* Commit: b5b405fee7f3e79d44e2d2971a4b6b4cc53f112e
* File: /openbsd-compat/getopt.h
*
* ---- BEGIN - Copyright notice and license of getopt.h ----
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* ---- END ----
*/
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET)
#if 0
#include <err.h>
#include <getopt.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define PRINT_ERROR ((opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
/* return values */
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#define EMSG (char *)""
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
static char *place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(int a, int b)
{
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return (b);
}
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
}
}
}
/*
* parse_long_options --
* Parse long options in argc/argv argument vector.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too)
{
char *current_argv, *has_equal;
size_t current_argv_len;
int i, match;
current_argv = place;
match = -1;
optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
break;
}
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* partial match */
match = i;
else {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return (BADARG);
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
warnx(recargstring,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
--optind;
return (-1);
}
if (PRINT_ERROR)
warnx(illoptstring, current_argv);
optopt = 0;
return (BADCH);
}
if (idx)
*idx = match;
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
return (0);
} else
return (long_options[match].val);
}
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
*/
static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
char *oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;
if (options == NULL)
return (-1);
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
optind = optreset = 1;
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*/
if (posixly_correct == -1 || optreset)
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-')
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
if (*options == '+' || *options == '-')
options++;
optarg = NULL;
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
}
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
if (*place == '-')
place++; /* --foo long option */
else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
return (-1);
if (!*place)
++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = place;
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return (optchar);
}
/*
* getopt --
* Parse argc/argv argument vector.
*
* [eventually this will replace the BSD getopt]
*/
int
getopt(int nargc, char * const *nargv, const char *options)
{
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
}
#if 0
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE));
}
/*
* getopt_long_only --
* Parse argc/argv argument vector.
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY));
}
#endif
#endif /* !defined(HAVE_GETOPT) || !defined(HAVE_OPTRESET) */

57
compat/getpeereid.c Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2022 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 <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#ifdef HAVE_UCRED_H
#include <ucred.h>
#endif
#include "compat.h"
int
getpeereid(int s, uid_t *uid, gid_t *gid)
{
#ifdef HAVE_SO_PEERCRED
struct ucred uc;
int len = sizeof uc;
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &uc, &len) == -1)
return (-1);
*uid = uc.uid;
*gid = uc.gid;
return (0);
#elif defined(HAVE_GETPEERUCRED)
ucred_t *ucred = NULL;
if (getpeerucred(s, &ucred) == -1)
return (-1);
if ((*uid = ucred_geteuid(ucred)) == -1)
return (-1);
if ((*gid = ucred_getrgid(ucred)) == -1)
return (-1);
ucred_free(ucred);
return (0);
#else
*uid = geteuid();
*gid = getegid();
return (0);
#endif
}

31
compat/htonll.c Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2024 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 <arpa/inet.h>
#include <sys/types.h>
#include "compat.h"
uint64_t
htonll(uint64_t v)
{
uint32_t b;
uint32_t t;
b = htonl (v & 0xffffffff);
t = htonl (v >> 32);
return ((uint64_t)b << 32 | t);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
/* $OpenBSD: imsg.c,v 1.16 2017/12/14 09:27:44 kettenis Exp $ */
/* $OpenBSD: imsg.c,v 1.37 2024/11/26 13:57:31 claudio Exp $ */
/*
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@ -21,6 +22,7 @@
#include <sys/uio.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -28,203 +30,288 @@
#include "compat.h"
#include "imsg.h"
int imsg_fd_overhead = 0;
#define IMSG_ALLOW_FDPASS 0x01
#define IMSG_FD_MARK 0x80000000U
static int imsg_get_fd(struct imsgbuf *);
static struct ibuf *imsg_parse_hdr(struct ibuf *, void *, int *);
int
imsgbuf_init(struct imsgbuf *imsgbuf, int fd)
{
imsgbuf->w = msgbuf_new_reader(IMSG_HEADER_SIZE, imsg_parse_hdr,
imsgbuf);
if (imsgbuf->w == NULL)
return (-1);
imsgbuf->pid = getpid();
imsgbuf->maxsize = MAX_IMSGSIZE;
imsgbuf->fd = fd;
imsgbuf->flags = 0;
return (0);
}
void
imsg_init(struct imsgbuf *ibuf, int fd)
imsgbuf_allow_fdpass(struct imsgbuf *imsgbuf)
{
msgbuf_init(&ibuf->w);
memset(&ibuf->r, 0, sizeof(ibuf->r));
ibuf->fd = fd;
ibuf->w.fd = fd;
ibuf->pid = getpid();
TAILQ_INIT(&ibuf->fds);
}
ssize_t
imsg_read(struct imsgbuf *ibuf)
{
struct msghdr msg;
struct cmsghdr *cmsg;
union {
struct cmsghdr hdr;
char buf[CMSG_SPACE(sizeof(int) * 1)];
} cmsgbuf;
struct iovec iov;
ssize_t n = -1;
int fd;
struct imsg_fd *ifd;
memset(&msg, 0, sizeof(msg));
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
return (-1);
again:
if (getdtablecount() + imsg_fd_overhead +
(int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
>= getdtablesize()) {
errno = EAGAIN;
free(ifd);
return (-1);
}
if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
if (errno == EINTR)
goto again;
goto fail;
}
ibuf->r.wpos += n;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
int i;
int j;
/*
* We only accept one file descriptor. Due to C
* padding rules, our control buffer might contain
* more than one fd, and we must close them.
*/
j = ((char *)cmsg + cmsg->cmsg_len -
(char *)CMSG_DATA(cmsg)) / sizeof(int);
for (i = 0; i < j; i++) {
fd = ((int *)CMSG_DATA(cmsg))[i];
if (ifd != NULL) {
ifd->fd = fd;
TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
entry);
ifd = NULL;
} else
close(fd);
}
}
/* we do not handle other ctl data level */
}
fail:
free(ifd);
return (n);
}
ssize_t
imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
{
size_t av, left, datalen;
av = ibuf->r.wpos;
if (IMSG_HEADER_SIZE > av)
return (0);
memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
if (imsg->hdr.len < IMSG_HEADER_SIZE ||
imsg->hdr.len > MAX_IMSGSIZE) {
errno = ERANGE;
return (-1);
}
if (imsg->hdr.len > av)
return (0);
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
if (datalen == 0)
imsg->data = NULL;
else if ((imsg->data = malloc(datalen)) == NULL)
return (-1);
if (imsg->hdr.flags & IMSGF_HASFD)
imsg->fd = imsg_get_fd(ibuf);
else
imsg->fd = -1;
memcpy(imsg->data, ibuf->r.rptr, datalen);
if (imsg->hdr.len < av) {
left = av - imsg->hdr.len;
memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
ibuf->r.wpos = left;
} else
ibuf->r.wpos = 0;
return (datalen + IMSG_HEADER_SIZE);
imsgbuf->flags |= IMSG_ALLOW_FDPASS;
}
int
imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
int fd, const void *data, uint16_t datalen)
imsgbuf_set_maxsize(struct imsgbuf *imsgbuf, uint32_t maxsize)
{
if (maxsize < IMSG_HEADER_SIZE || maxsize & IMSG_FD_MARK) {
errno = EINVAL;
return (-1);
}
imsgbuf->maxsize = maxsize;
return (0);
}
int
imsgbuf_read(struct imsgbuf *imsgbuf)
{
if (imsgbuf->flags & IMSG_ALLOW_FDPASS)
return msgbuf_read(imsgbuf->fd, imsgbuf->w);
else
return ibuf_read(imsgbuf->fd, imsgbuf->w);
}
int
imsgbuf_write(struct imsgbuf *imsgbuf)
{
if (imsgbuf->flags & IMSG_ALLOW_FDPASS)
return msgbuf_write(imsgbuf->fd, imsgbuf->w);
else
return ibuf_write(imsgbuf->fd, imsgbuf->w);
}
int
imsgbuf_flush(struct imsgbuf *imsgbuf)
{
while (imsgbuf_queuelen(imsgbuf) > 0) {
if (imsgbuf_write(imsgbuf) == -1)
return (-1);
}
return (0);
}
void
imsgbuf_clear(struct imsgbuf *imsgbuf)
{
msgbuf_free(imsgbuf->w);
imsgbuf->w = NULL;
}
uint32_t
imsgbuf_queuelen(struct imsgbuf *imsgbuf)
{
return msgbuf_queuelen(imsgbuf->w);
}
ssize_t
imsg_get(struct imsgbuf *imsgbuf, struct imsg *imsg)
{
struct imsg m;
struct ibuf *buf;
if ((buf = msgbuf_get(imsgbuf->w)) == NULL)
return (0);
if (ibuf_get(buf, &m.hdr, sizeof(m.hdr)) == -1)
return (-1);
if (ibuf_size(buf))
m.data = ibuf_data(buf);
else
m.data = NULL;
m.buf = buf;
m.hdr.len &= ~IMSG_FD_MARK;
*imsg = m;
return (ibuf_size(buf) + IMSG_HEADER_SIZE);
}
int
imsg_get_ibuf(struct imsg *imsg, struct ibuf *ibuf)
{
if (ibuf_size(imsg->buf) == 0) {
errno = EBADMSG;
return (-1);
}
return ibuf_get_ibuf(imsg->buf, ibuf_size(imsg->buf), ibuf);
}
int
imsg_get_data(struct imsg *imsg, void *data, size_t len)
{
if (len == 0) {
errno = EINVAL;
return (-1);
}
if (ibuf_size(imsg->buf) != len) {
errno = EBADMSG;
return (-1);
}
return ibuf_get(imsg->buf, data, len);
}
int
imsg_get_fd(struct imsg *imsg)
{
return ibuf_fd_get(imsg->buf);
}
uint32_t
imsg_get_id(struct imsg *imsg)
{
return (imsg->hdr.peerid);
}
size_t
imsg_get_len(struct imsg *imsg)
{
return ibuf_size(imsg->buf);
}
pid_t
imsg_get_pid(struct imsg *imsg)
{
return (imsg->hdr.pid);
}
uint32_t
imsg_get_type(struct imsg *imsg)
{
return (imsg->hdr.type);
}
int
imsg_compose(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
int fd, const void *data, size_t datalen)
{
struct ibuf *wbuf;
if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
return (-1);
if (imsg_add(wbuf, data, datalen) == -1)
return (-1);
wbuf->fd = fd;
imsg_close(ibuf, wbuf);
ibuf_fd_set(wbuf, fd);
imsg_close(imsgbuf, wbuf);
return (1);
}
int
imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
imsg_composev(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
int fd, const struct iovec *iov, int iovcnt)
{
struct ibuf *wbuf;
int i, datalen = 0;
int i;
size_t datalen = 0;
for (i = 0; i < iovcnt; i++)
datalen += iov[i].iov_len;
if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
return (-1);
for (i = 0; i < iovcnt; i++)
if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
return (-1);
wbuf->fd = fd;
imsg_close(ibuf, wbuf);
ibuf_fd_set(wbuf, fd);
imsg_close(imsgbuf, wbuf);
return (1);
}
/* ARGSUSED */
/*
* Enqueue imsg with payload from ibuf buf. fd passing is not possible
* with this function.
*/
int
imsg_compose_ibuf(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id,
pid_t pid, struct ibuf *buf)
{
struct ibuf *hdrbuf = NULL;
struct imsg_hdr hdr;
int save_errno;
if (ibuf_size(buf) + IMSG_HEADER_SIZE > imsgbuf->maxsize) {
errno = ERANGE;
goto fail;
}
hdr.type = type;
hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
hdr.peerid = id;
if ((hdr.pid = pid) == 0)
hdr.pid = imsgbuf->pid;
if ((hdrbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
goto fail;
if (imsg_add(hdrbuf, &hdr, sizeof(hdr)) == -1)
goto fail;
ibuf_close(imsgbuf->w, hdrbuf);
ibuf_close(imsgbuf->w, buf);
return (1);
fail:
save_errno = errno;
ibuf_free(buf);
ibuf_free(hdrbuf);
errno = save_errno;
return (-1);
}
/*
* Forward imsg to another channel. Any attached fd is closed.
*/
int
imsg_forward(struct imsgbuf *imsgbuf, struct imsg *msg)
{
struct ibuf *wbuf;
size_t len;
ibuf_rewind(msg->buf);
ibuf_skip(msg->buf, sizeof(msg->hdr));
len = ibuf_size(msg->buf);
if ((wbuf = imsg_create(imsgbuf, msg->hdr.type, msg->hdr.peerid,
msg->hdr.pid, len)) == NULL)
return (-1);
if (len != 0) {
if (ibuf_add_ibuf(wbuf, msg->buf) == -1) {
ibuf_free(wbuf);
return (-1);
}
}
imsg_close(imsgbuf, wbuf);
return (1);
}
struct ibuf *
imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
uint16_t datalen)
imsg_create(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
size_t datalen)
{
struct ibuf *wbuf;
struct imsg_hdr hdr;
datalen += IMSG_HEADER_SIZE;
if (datalen > MAX_IMSGSIZE) {
if (datalen > imsgbuf->maxsize) {
errno = ERANGE;
return (NULL);
}
hdr.type = type;
hdr.flags = 0;
hdr.peerid = peerid;
hdr.peerid = id;
if ((hdr.pid = pid) == 0)
hdr.pid = ibuf->pid;
if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
hdr.pid = imsgbuf->pid;
if ((wbuf = ibuf_dynamic(datalen, imsgbuf->maxsize)) == NULL) {
return (NULL);
}
if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
@ -234,7 +321,7 @@ imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
}
int
imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
imsg_add(struct ibuf *msg, const void *data, size_t datalen)
{
if (datalen)
if (ibuf_add(msg, data, datalen) == -1) {
@ -245,58 +332,47 @@ imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
}
void
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
imsg_close(struct imsgbuf *imsgbuf, struct ibuf *msg)
{
struct imsg_hdr *hdr;
uint32_t len;
hdr = (struct imsg_hdr *)msg->buf;
hdr->flags &= ~IMSGF_HASFD;
if (msg->fd != -1)
hdr->flags |= IMSGF_HASFD;
hdr->len = (uint16_t)msg->wpos;
ibuf_close(&ibuf->w, msg);
len = ibuf_size(msg);
if (ibuf_fd_avail(msg))
len |= IMSG_FD_MARK;
(void)ibuf_set_h32(msg, offsetof(struct imsg_hdr, len), len);
ibuf_close(imsgbuf->w, msg);
}
void
imsg_free(struct imsg *imsg)
{
freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
ibuf_free(imsg->buf);
}
static int
imsg_get_fd(struct imsgbuf *ibuf)
static struct ibuf *
imsg_parse_hdr(struct ibuf *buf, void *arg, int *fd)
{
int fd;
struct imsg_fd *ifd;
struct imsgbuf *imsgbuf = arg;
struct imsg_hdr hdr;
struct ibuf *b;
uint32_t len;
if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
return (-1);
if (ibuf_get(buf, &hdr, sizeof(hdr)) == -1)
return (NULL);
fd = ifd->fd;
TAILQ_REMOVE(&ibuf->fds, ifd, entry);
free(ifd);
len = hdr.len & ~IMSG_FD_MARK;
return (fd);
if (len < IMSG_HEADER_SIZE || len > imsgbuf->maxsize) {
errno = ERANGE;
return (NULL);
}
if ((b = ibuf_open(len)) == NULL)
return (NULL);
if (hdr.len & IMSG_FD_MARK) {
ibuf_fd_set(b, *fd);
*fd = -1;
}
int
imsg_flush(struct imsgbuf *ibuf)
{
while (ibuf->w.queued)
if (msgbuf_write(&ibuf->w) <= 0)
return (-1);
return (0);
}
void
imsg_clear(struct imsgbuf *ibuf)
{
int fd;
msgbuf_clear(&ibuf->w);
while ((fd = imsg_get_fd(ibuf)) != -1)
close(fd);
return b;
}

View File

@ -1,6 +1,7 @@
/* $OpenBSD: imsg.h,v 1.4 2017/03/24 09:34:12 nicm Exp $ */
/* $OpenBSD: imsg.h,v 1.19 2024/11/26 13:57:31 claudio Exp $ */
/*
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
* Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -21,13 +22,15 @@
#ifndef _IMSG_H_
#define _IMSG_H_
#include <sys/types.h>
#define IBUF_READ_SIZE 65535
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
#define MAX_IMSGSIZE 16384
struct ibuf {
TAILQ_ENTRY(ibuf) entry;
u_char *buf;
unsigned char *buf;
size_t size;
size_t max;
size_t wpos;
@ -35,77 +38,116 @@ struct ibuf {
int fd;
};
struct msgbuf {
TAILQ_HEAD(, ibuf) bufs;
uint32_t queued;
int fd;
};
struct ibuf_read {
u_char buf[IBUF_READ_SIZE];
u_char *rptr;
size_t wpos;
};
struct imsg_fd {
TAILQ_ENTRY(imsg_fd) entry;
int fd;
};
struct msgbuf;
struct imsgbuf {
TAILQ_HEAD(, imsg_fd) fds;
struct ibuf_read r;
struct msgbuf w;
int fd;
struct msgbuf *w;
pid_t pid;
uint32_t maxsize;
int fd;
int flags;
};
#define IMSGF_HASFD 1
struct imsg_hdr {
uint32_t type;
uint16_t len;
uint16_t flags;
uint32_t len;
uint32_t peerid;
uint32_t pid;
};
struct imsg {
struct imsg_hdr hdr;
int fd;
void *data;
struct ibuf *buf;
};
struct iovec;
/* buffer.c */
/* imsg-buffer.c */
struct ibuf *ibuf_open(size_t);
struct ibuf *ibuf_dynamic(size_t, size_t);
int ibuf_add(struct ibuf *, const void *, size_t);
int ibuf_add_ibuf(struct ibuf *, const struct ibuf *);
int ibuf_add_zero(struct ibuf *, size_t);
int ibuf_add_n8(struct ibuf *, uint64_t);
int ibuf_add_n16(struct ibuf *, uint64_t);
int ibuf_add_n32(struct ibuf *, uint64_t);
int ibuf_add_n64(struct ibuf *, uint64_t);
int ibuf_add_h16(struct ibuf *, uint64_t);
int ibuf_add_h32(struct ibuf *, uint64_t);
int ibuf_add_h64(struct ibuf *, uint64_t);
void *ibuf_reserve(struct ibuf *, size_t);
void *ibuf_seek(struct ibuf *, size_t, size_t);
size_t ibuf_size(struct ibuf *);
size_t ibuf_left(struct ibuf *);
int ibuf_set(struct ibuf *, size_t, const void *, size_t);
int ibuf_set_n8(struct ibuf *, size_t, uint64_t);
int ibuf_set_n16(struct ibuf *, size_t, uint64_t);
int ibuf_set_n32(struct ibuf *, size_t, uint64_t);
int ibuf_set_n64(struct ibuf *, size_t, uint64_t);
int ibuf_set_h16(struct ibuf *, size_t, uint64_t);
int ibuf_set_h32(struct ibuf *, size_t, uint64_t);
int ibuf_set_h64(struct ibuf *, size_t, uint64_t);
void *ibuf_data(const struct ibuf *);
size_t ibuf_size(const struct ibuf *);
size_t ibuf_left(const struct ibuf *);
int ibuf_truncate(struct ibuf *, size_t);
void ibuf_rewind(struct ibuf *);
void ibuf_close(struct msgbuf *, struct ibuf *);
int ibuf_write(struct msgbuf *);
void ibuf_from_buffer(struct ibuf *, void *, size_t);
void ibuf_from_ibuf(struct ibuf *, const struct ibuf *);
int ibuf_get(struct ibuf *, void *, size_t);
int ibuf_get_ibuf(struct ibuf *, size_t, struct ibuf *);
int ibuf_get_n8(struct ibuf *, uint8_t *);
int ibuf_get_n16(struct ibuf *, uint16_t *);
int ibuf_get_n32(struct ibuf *, uint32_t *);
int ibuf_get_n64(struct ibuf *, uint64_t *);
int ibuf_get_h16(struct ibuf *, uint16_t *);
int ibuf_get_h32(struct ibuf *, uint32_t *);
int ibuf_get_h64(struct ibuf *, uint64_t *);
char *ibuf_get_string(struct ibuf *, size_t);
int ibuf_skip(struct ibuf *, size_t);
void ibuf_free(struct ibuf *);
void msgbuf_init(struct msgbuf *);
int ibuf_fd_avail(struct ibuf *);
int ibuf_fd_get(struct ibuf *);
void ibuf_fd_set(struct ibuf *, int);
struct msgbuf *msgbuf_new(void);
struct msgbuf *msgbuf_new_reader(size_t,
struct ibuf *(*)(struct ibuf *, void *, int *), void *);
void msgbuf_free(struct msgbuf *);
void msgbuf_clear(struct msgbuf *);
int msgbuf_write(struct msgbuf *);
void msgbuf_drain(struct msgbuf *, size_t);
uint32_t msgbuf_queuelen(struct msgbuf *);
int ibuf_write(int, struct msgbuf *);
int msgbuf_write(int, struct msgbuf *);
int ibuf_read(int, struct msgbuf *);
int msgbuf_read(int, struct msgbuf *);
struct ibuf *msgbuf_get(struct msgbuf *);
/* imsg.c */
void imsg_init(struct imsgbuf *, int);
ssize_t imsg_read(struct imsgbuf *);
int imsgbuf_init(struct imsgbuf *, int);
void imsgbuf_allow_fdpass(struct imsgbuf *imsgbuf);
int imsgbuf_set_maxsize(struct imsgbuf *, uint32_t);
int imsgbuf_read(struct imsgbuf *);
int imsgbuf_write(struct imsgbuf *);
int imsgbuf_flush(struct imsgbuf *);
void imsgbuf_clear(struct imsgbuf *);
uint32_t imsgbuf_queuelen(struct imsgbuf *);
ssize_t imsg_get(struct imsgbuf *, struct imsg *);
int imsg_get_ibuf(struct imsg *, struct ibuf *);
int imsg_get_data(struct imsg *, void *, size_t);
int imsg_get_fd(struct imsg *);
uint32_t imsg_get_id(struct imsg *);
size_t imsg_get_len(struct imsg *);
pid_t imsg_get_pid(struct imsg *);
uint32_t imsg_get_type(struct imsg *);
int imsg_forward(struct imsgbuf *, struct imsg *);
int imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
const void *, uint16_t);
const void *, size_t);
int imsg_composev(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
const struct iovec *, int);
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t);
int imsg_add(struct ibuf *, const void *, uint16_t);
int imsg_compose_ibuf(struct imsgbuf *, uint32_t, uint32_t, pid_t,
struct ibuf *);
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, size_t);
int imsg_add(struct ibuf *, const void *, size_t);
void imsg_close(struct imsgbuf *, struct ibuf *);
void imsg_free(struct imsg *);
int imsg_flush(struct imsgbuf *);
void imsg_clear(struct imsgbuf *);
#endif

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