mirror of
https://github.com/tmux/tmux.git
synced 2026-09-17 10:34:46 +00:00
Compare commits
295 Commits
local_wind
...
floating_p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a91d5601e | ||
|
|
7de5eb1254 | ||
|
|
9e0ca948bf | ||
|
|
8e070f1a34 | ||
|
|
6ec0afe5f7 | ||
|
|
41e731fc51 | ||
|
|
19c8da04d0 | ||
|
|
8925000c42 | ||
|
|
568c99be4e | ||
|
|
69fc42afc9 | ||
|
|
19843cd826 | ||
|
|
4eb96fc144 | ||
|
|
3d396f13ed | ||
|
|
7d8401d707 | ||
|
|
c3aac57dda | ||
|
|
5602571c01 | ||
|
|
c04236052c | ||
|
|
584cafa284 | ||
|
|
8a4a150a1a | ||
|
|
de41b93b73 | ||
|
|
4aa1dd3ae8 | ||
|
|
be33d01663 | ||
|
|
fdcb93a467 | ||
|
|
c54f7ec95e | ||
|
|
f8448764e2 | ||
|
|
f71e81c483 | ||
|
|
9bd53b8565 | ||
|
|
dde9dda1a4 | ||
|
|
55c8b0c2a7 | ||
|
|
fd1fca51fa | ||
|
|
00620b57eb | ||
|
|
bba9f38636 | ||
|
|
9c37acd002 | ||
|
|
195a9b357a | ||
|
|
cd4c4bf723 | ||
|
|
e244be2540 | ||
|
|
5dad31b06e | ||
|
|
64ded18960 | ||
|
|
4dd496790a | ||
|
|
db9e782d50 | ||
|
|
d4869ebdc5 | ||
|
|
d1fe0d449b | ||
|
|
e2b52abd47 | ||
|
|
f58eb4dc0e | ||
|
|
8497b588a2 | ||
|
|
57641f67dd | ||
|
|
b675c2149c | ||
|
|
4fbc30267c | ||
|
|
2a830aa567 | ||
|
|
84229d4735 | ||
|
|
e370ce5a00 | ||
|
|
2a1ad05671 | ||
|
|
7568bff8e6 | ||
|
|
6766c8ec1d | ||
|
|
2955c1fdc7 | ||
|
|
45e9e541a4 | ||
|
|
b2ac4475cc | ||
|
|
a7952492c1 | ||
|
|
0b1089e105 | ||
|
|
6b3bdaff97 | ||
|
|
7c908bca7a | ||
|
|
90ede52728 | ||
|
|
17974ea7a0 | ||
|
|
25852623f0 | ||
|
|
446aa08286 | ||
|
|
12b3cc3750 | ||
|
|
6dd288d459 | ||
|
|
d8547fc721 | ||
|
|
68fdc4fcbe | ||
|
|
398cb6fb4a | ||
|
|
7302549903 | ||
|
|
e971bc79d6 | ||
|
|
650ad28f12 | ||
|
|
2637477eea | ||
|
|
e5c69afa98 | ||
|
|
ec901e9e31 | ||
|
|
d814529285 | ||
|
|
82dc3d57f2 | ||
|
|
3f77cb95c5 | ||
|
|
68e9ff797c | ||
|
|
97ee6e2587 | ||
|
|
e0215480cd | ||
|
|
bd33d9c47d | ||
|
|
3a025d39db | ||
|
|
1ed454d102 | ||
|
|
52250d518d | ||
|
|
bfa2ff2bdf | ||
|
|
c62b27f014 | ||
|
|
20cf0d3ea9 | ||
|
|
02caf7ce4a | ||
|
|
e1c7367a2e | ||
|
|
fc4641c5a5 | ||
|
|
8f9e2c7db2 | ||
|
|
46be03d88e | ||
|
|
f9bd5eb79e | ||
|
|
d89a4ab3df | ||
|
|
57b18d8a18 | ||
|
|
95465ca03a | ||
|
|
6513808720 | ||
|
|
6c1773542d | ||
|
|
c60422241b | ||
|
|
92dcb22e92 | ||
|
|
f75b1e5f07 | ||
|
|
fb9e47d8c9 | ||
|
|
43ae6e0a6b | ||
|
|
724d6d7c95 | ||
|
|
95c20aef20 | ||
|
|
791f77b879 | ||
|
|
a6986864db | ||
|
|
30866d06d5 | ||
|
|
8b474429b7 | ||
|
|
91b4e02805 | ||
|
|
e65e653ea5 | ||
|
|
29a1a1f8b0 | ||
|
|
71de737ee8 | ||
|
|
55fbacb469 | ||
|
|
2a6aac4c14 | ||
|
|
4fd8431ad0 | ||
|
|
d3e8dd3623 | ||
|
|
1fa6ebacf4 | ||
|
|
8fa822207d | ||
|
|
52ad3c8425 | ||
|
|
e5abcd217c | ||
|
|
4a0118aea1 | ||
|
|
90a748f7fb | ||
|
|
2434653867 | ||
|
|
1def587884 | ||
|
|
c56bc9ed05 | ||
|
|
2a9ba51907 | ||
|
|
406ae3d8a6 | ||
|
|
8a674265f3 | ||
|
|
ed43033c39 | ||
|
|
0a7b008b21 | ||
|
|
f8e908b89c | ||
|
|
2695c5305e | ||
|
|
55fdfef9d1 | ||
|
|
2f6da393e2 | ||
|
|
57b17bbb70 | ||
|
|
7c23da598d | ||
|
|
b7cc218a03 | ||
|
|
0ae8019e7f | ||
|
|
c3fc0229e5 | ||
|
|
76196b8ffa | ||
|
|
fd4e683151 | ||
|
|
2b05d8531d | ||
|
|
8e966688a7 | ||
|
|
c4ec9234e9 | ||
|
|
2e0eabbf0a | ||
|
|
1b2435fab6 | ||
|
|
1ff3dafe4e | ||
|
|
6b16e93f1b | ||
|
|
b7467a3110 | ||
|
|
4224ecd2ab | ||
|
|
e18c10d340 | ||
|
|
0719dcf2e7 | ||
|
|
3400a312dd | ||
|
|
b2f9144e10 | ||
|
|
a74f173902 | ||
|
|
a1cd68e3f8 | ||
|
|
eec2c19ad1 | ||
|
|
05fdd04262 | ||
|
|
3e36ddbceb | ||
|
|
0a55e5ca54 | ||
|
|
a7ad0c4434 | ||
|
|
271bac5347 | ||
|
|
914ffc8887 | ||
|
|
7a4e35e317 | ||
|
|
1bc85cb59e | ||
|
|
f992c68fd8 | ||
|
|
4bb7a86753 | ||
|
|
950194fb63 | ||
|
|
b528fc438c | ||
|
|
811604a663 | ||
|
|
4232bf9e2f | ||
|
|
8a3620e438 | ||
|
|
1408861511 | ||
|
|
44229e8af6 | ||
|
|
d002323de2 | ||
|
|
999c7246c3 | ||
|
|
c10a597bf0 | ||
|
|
75ed7b27c6 | ||
|
|
ef01e9daf8 | ||
|
|
866cb2d16f | ||
|
|
6a62d49720 | ||
|
|
f201d246fd | ||
|
|
0328fe44e4 | ||
|
|
bb85983a29 | ||
|
|
4341d6a095 | ||
|
|
10a9ce1ed2 | ||
|
|
943490cfa1 | ||
|
|
7e6bbc63ab | ||
|
|
0d195698f8 | ||
|
|
08fd890a89 | ||
|
|
ab0081294c | ||
|
|
c42a939e98 | ||
|
|
6c9e2f7e6c | ||
|
|
992f04f328 | ||
|
|
8a90fce476 | ||
|
|
e928e80a42 | ||
|
|
28c04b21f6 | ||
|
|
46427f1dd7 | ||
|
|
528e856566 | ||
|
|
14a934d412 | ||
|
|
0faed7aeb5 | ||
|
|
8e6450c8fc | ||
|
|
6898e26a7a | ||
|
|
e2cf40ef99 | ||
|
|
96515c9f47 | ||
|
|
96e18faa93 | ||
|
|
476c6e89ad | ||
|
|
b46a96d454 | ||
|
|
f67cf7d053 | ||
|
|
2ad0f4a9e7 | ||
|
|
1ec9ca497b | ||
|
|
dd5d0f4f0c | ||
|
|
d1a6ce8e7f | ||
|
|
b22537e8a4 | ||
|
|
a25c14d472 | ||
|
|
7730d38339 | ||
|
|
58e498c9d3 | ||
|
|
35485f2b5e | ||
|
|
b108653f02 | ||
|
|
25f72cf240 | ||
|
|
d1df8dcccc | ||
|
|
a50d00aa47 | ||
|
|
34add944f2 | ||
|
|
95f85efc49 | ||
|
|
f2f6a05e2c | ||
|
|
bd442a27ee | ||
|
|
73c0eb96c3 | ||
|
|
6a4a4a432b | ||
|
|
263529e886 | ||
|
|
818797ff08 | ||
|
|
d263dbe9dd | ||
|
|
67319ad9d9 | ||
|
|
2591df66cc | ||
|
|
2ac78bccb5 | ||
|
|
47de44001e | ||
|
|
eaa467618b | ||
|
|
ac01f15bfe | ||
|
|
5df5217e2e | ||
|
|
a6ec2b76c2 | ||
|
|
bc01b300c4 | ||
|
|
c8d4d8cb66 | ||
|
|
315202b007 | ||
|
|
7194fdca38 | ||
|
|
31d0945059 | ||
|
|
466e79d572 | ||
|
|
3bb4f72a4b | ||
|
|
329e9d54ab | ||
|
|
9c45dd693b | ||
|
|
cc671e4495 | ||
|
|
61ca158de1 | ||
|
|
7e0038c691 | ||
|
|
04792d0656 | ||
|
|
6c5cc40039 | ||
|
|
6b462474f0 | ||
|
|
9a061a2fee | ||
|
|
6dd552d689 | ||
|
|
34e858ea05 | ||
|
|
39d2839e37 | ||
|
|
7980d00e8c | ||
|
|
25ce5b4281 | ||
|
|
0cd3ab6299 | ||
|
|
28d038fb16 | ||
|
|
10dc308e6b | ||
|
|
6344bab6cc | ||
|
|
984fbacccf | ||
|
|
cc83ca6628 | ||
|
|
04fc6ea11b | ||
|
|
8a9e2fccbd | ||
|
|
cc1324e2d9 | ||
|
|
b2226d1608 | ||
|
|
8ce0af3fc9 | ||
|
|
b315a6c3d1 | ||
|
|
baf642b7d2 | ||
|
|
8db76e9057 | ||
|
|
e3b7bf9b31 | ||
|
|
38724f2e86 | ||
|
|
65fc09fac9 | ||
|
|
3197b715b3 | ||
|
|
26362dfc72 | ||
|
|
275781ce45 | ||
|
|
72dbbfedce | ||
|
|
a6c6eabb5a | ||
|
|
379e4d976c | ||
|
|
a6514e2656 | ||
|
|
032af23e18 | ||
|
|
b5f9293014 | ||
|
|
a37db55689 | ||
|
|
1b959d0eff | ||
|
|
ce03f1abea | ||
|
|
5faf41b695 | ||
|
|
7634daa834 | ||
|
|
968f439672 |
4
.github/workflows/lock.yml
vendored
4
.github/workflows/lock.yml
vendored
@@ -16,10 +16,8 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
action:
|
action:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'tmux/tmux'
|
|
||||||
timeout-minutes: 10
|
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@89ae32b08ed1a541efecbab17912962a5e38981c # v6
|
- uses: dessant/lock-threads@v6
|
||||||
with:
|
with:
|
||||||
github-token: ${{ github.token }}
|
github-token: ${{ github.token }}
|
||||||
issue-inactive-days: '30'
|
issue-inactive-days: '30'
|
||||||
|
|||||||
35
.github/workflows/regress.yml
vendored
35
.github/workflows/regress.yml
vendored
@@ -16,8 +16,7 @@ jobs:
|
|||||||
regress:
|
regress:
|
||||||
name: ${{ matrix.name }}
|
name: ${{ matrix.name }}
|
||||||
runs-on: ${{ matrix.runner }}
|
runs-on: ${{ matrix.runner }}
|
||||||
if: github.repository == 'tmux/tmux'
|
timeout-minutes: 45
|
||||||
timeout-minutes: 300
|
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -26,21 +25,16 @@ jobs:
|
|||||||
- name: ubuntu-24.04-x64
|
- name: ubuntu-24.04-x64
|
||||||
runner: ubuntu-24.04
|
runner: ubuntu-24.04
|
||||||
make: make
|
make: make
|
||||||
configure: --enable-utf8proc --enable-asan
|
# - name: ubuntu-24.04-arm64
|
||||||
#- name: ubuntu-24.04-arm64
|
# runner: ubuntu-24.04-arm
|
||||||
# runner: ubuntu-24.04-arm
|
# make: make
|
||||||
# make: make
|
# - name: macos-26-arm64
|
||||||
# configure: --enable-utf8proc --enable-asan
|
# runner: macos-26
|
||||||
- name: macos-26-arm64
|
# make: gmake
|
||||||
runner: macos-26
|
|
||||||
make: gmake
|
|
||||||
configure: --enable-utf8proc --enable-asan
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: dependencies
|
- name: dependencies
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
@@ -64,7 +58,6 @@ jobs:
|
|||||||
automake \
|
automake \
|
||||||
bison \
|
bison \
|
||||||
libevent \
|
libevent \
|
||||||
jemalloc \
|
|
||||||
make \
|
make \
|
||||||
ncurses \
|
ncurses \
|
||||||
utf8proc \
|
utf8proc \
|
||||||
@@ -72,19 +65,11 @@ jobs:
|
|||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
sh autogen.sh
|
sh autogen.sh
|
||||||
./configure ${{ matrix.configure }}
|
./configure --enable-utf8proc
|
||||||
${{ matrix.make }} -j"$(getconf _NPROCESSORS_ONLN)"
|
${{ matrix.make }} -j"$(getconf _NPROCESSORS_ONLN)"
|
||||||
|
|
||||||
- name: test
|
- name: test
|
||||||
run: |
|
run: |
|
||||||
cd regress
|
cd regress
|
||||||
${{ matrix.make }}
|
${{ matrix.make }}
|
||||||
|
|
||||||
- name: logs
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
||||||
with:
|
|
||||||
name: regress-logs-${{ matrix.name }}
|
|
||||||
path: regress/logs/*.log
|
|
||||||
if-no-files-found: ignore
|
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,7 +21,6 @@ configure
|
|||||||
core
|
core
|
||||||
etc/
|
etc/
|
||||||
fuzz/*-fuzzer
|
fuzz/*-fuzzer
|
||||||
regress/logs/
|
|
||||||
tags
|
tags
|
||||||
tmux
|
tmux
|
||||||
tmux.1.*
|
tmux.1.*
|
||||||
|
|||||||
179
CHANGES
179
CHANGES
@@ -1,182 +1,3 @@
|
|||||||
CHANGES FROM 3.7c TO 3.8
|
|
||||||
|
|
||||||
* Many improvements to floating panes:
|
|
||||||
|
|
||||||
- new-pane and split-window can now set the title with -T and border lines
|
|
||||||
with -B, and new-pane -W waits for the pane command to exit;
|
|
||||||
|
|
||||||
- dragging with Ctrl now creates a new floating pane;
|
|
||||||
|
|
||||||
- modal panes may be created with new-pane -O; a window can have one modal
|
|
||||||
pane and it prevents interaction with the other panes while it is active.
|
|
||||||
A modal pane is now used for the editor in buffer mode;
|
|
||||||
|
|
||||||
- move-pane and resize-pane can now move and resize floating panes, including
|
|
||||||
mouse dragging;
|
|
||||||
|
|
||||||
- split-window in a floating pane creates a new floating pane that does not
|
|
||||||
overlap the active pane, if possible;
|
|
||||||
|
|
||||||
- break-pane can float a tiled pane, join-pane can tile a floating pane, and
|
|
||||||
swap-pane works with floating panes;
|
|
||||||
|
|
||||||
- choose-tree -h and choose-client -h hide the pane containing the mode, and
|
|
||||||
-k for choose commands kills the pane when the mode exits, which is useful
|
|
||||||
for modes in floating panes;
|
|
||||||
|
|
||||||
- pane-border-status has top-floating and bottom-floating, and there are new
|
|
||||||
default bindings under C-b g for common move and resize operations;
|
|
||||||
|
|
||||||
- floating panes are unzoomed before creation to avoid a crash.
|
|
||||||
|
|
||||||
* Add support for themes and improve default colours:
|
|
||||||
|
|
||||||
- tmux now has builtin light and dark colour themes for terminals with 256 or
|
|
||||||
more colours; a new theme option controls whether tmux detects the terminal
|
|
||||||
theme, uses terminal colours, or forces light or dark (set to terminal for
|
|
||||||
the old colours);
|
|
||||||
|
|
||||||
- styles can use new theme colour names such as themeblack, themewhite and
|
|
||||||
themegreen, and colours in styles are expanded as formats;
|
|
||||||
|
|
||||||
- the terminal's own theme is reported to panes instead of being guessed from
|
|
||||||
the background, and inferred more accurately when theme reporting is not
|
|
||||||
supported (Ayman Bagabas, issue 5343);
|
|
||||||
|
|
||||||
- tree-mode-selection-style has been added, tree mode selection styling now
|
|
||||||
covers the whole line, and built-in modes use improved theme colours.
|
|
||||||
|
|
||||||
* Improvements to customize mode:
|
|
||||||
|
|
||||||
- hooks and environment variables are now shown;
|
|
||||||
|
|
||||||
- e opens the selected value in an editor;
|
|
||||||
|
|
||||||
- C toggles showing only changed items;
|
|
||||||
|
|
||||||
- array item keys can now be changed.
|
|
||||||
|
|
||||||
* Hooks (and control mode notifications) are now handled internally by using
|
|
||||||
events, each of which may carry keys and values as a payload. The control
|
|
||||||
mode subscriptions mechanism has been extended to allow general-purpose
|
|
||||||
"monitors" which check a format every second and trigger a hook when it
|
|
||||||
changes or becomes true:
|
|
||||||
|
|
||||||
- set-hook -B adds a monitor hook using the same subscription syntax as
|
|
||||||
refresh-client -B, and show-hooks -B lists them. -T runs the hook only when
|
|
||||||
the format is true;
|
|
||||||
|
|
||||||
- wait-for -E waits for hooks, notifications or user events, and set-hook -E
|
|
||||||
fires an event immediately;
|
|
||||||
|
|
||||||
- hooks have additional keys available. wait-for -v can be used to see the
|
|
||||||
keys sent with a hook event;
|
|
||||||
|
|
||||||
- new hooks to cover areas including client create and destroy, pane
|
|
||||||
activity, pane mode and prompt changes, pane movement and resizing, session
|
|
||||||
group changes and window creation, close and zoom;
|
|
||||||
|
|
||||||
- OSC 133 escape sequences now trigger events: pane-command-started,
|
|
||||||
pane-command-finished and pane-shell-prompt.
|
|
||||||
|
|
||||||
* Add switch-mode, a fast switcher bound by default to Tab for windows and BTab
|
|
||||||
(S-Tab) for sessions.
|
|
||||||
|
|
||||||
* Pane scrollbars now support auto-hide. This replaces the previous modal
|
|
||||||
behaviour where the pane was resized. With auto-hide, the scrollbar appears
|
|
||||||
while scrolling or while hovered and disappears after pane-scrollbars-timeout
|
|
||||||
(Michael Grant).
|
|
||||||
|
|
||||||
* Extend the fill-character option so both inside and outside the window can be
|
|
||||||
changed.
|
|
||||||
|
|
||||||
* Change set-option and set-hooks to use formats and add a -F flag to each.
|
|
||||||
|
|
||||||
* Add a #{A/count:frames} modifier to show a series of frames as an animation
|
|
||||||
in the status line (issue 5412 from Fernando Daciuk).
|
|
||||||
|
|
||||||
* Change command templates so %% is escaped for single quotes while %1 remains
|
|
||||||
unquoted, preventing single quotes in session or target names from
|
|
||||||
terminating quoted command sections (reported by Aliz Hammond).
|
|
||||||
|
|
||||||
* display-panes is now a mode rather than an overlay, and can be run inside
|
|
||||||
another pane. The -b flag has been removed.
|
|
||||||
|
|
||||||
* Add new-window -E, respawn-pane -E and respawn-window -E as more convenient
|
|
||||||
methods to create an empty pane (rather than using '' for the command).
|
|
||||||
|
|
||||||
* Menus now belong to the window, so appear on all clients.
|
|
||||||
|
|
||||||
* Dragging over an existing copy mode selection now adjusts it (Michael Grant).
|
|
||||||
|
|
||||||
* Rectangle selection in copy mode may extend past the end of the current line
|
|
||||||
to match vi's virtualedit=block behaviour (Mark Kelly, issue 5227).
|
|
||||||
|
|
||||||
* With mode-keys set to vi, scrolling in copy mode now keeps the cursor in the
|
|
||||||
same position relative to the text (Arseniy Simonov, issue 5216).
|
|
||||||
|
|
||||||
* Copy mode no longer exits at the bottom while a selection is in progress
|
|
||||||
(issue 5349).
|
|
||||||
|
|
||||||
* Add style attributes for dimming colours (dim=) and for hyperlinks (link= and
|
|
||||||
nolink) (issues 4842 and 4280 from Moritz Angermann).
|
|
||||||
|
|
||||||
* New format modifiers: O: loops over options, V: loops over environments,
|
|
||||||
the I modifier reports client terminal information, t/d gives a time
|
|
||||||
difference in seconds, c/f and c/b emit colours, and the m operator supports
|
|
||||||
multiple terms and fuzzy matching.
|
|
||||||
|
|
||||||
* Add or improve format variables including client_colours,
|
|
||||||
pane_start_command_list, window_manual_width, window_manual_height,
|
|
||||||
pane_last_output_time, pane_modal_flag and window_modal_pane.
|
|
||||||
|
|
||||||
* Add additional pane sort orders, and a z sort order for choose-tree so
|
|
||||||
floating panes can be sorted by z-index.
|
|
||||||
|
|
||||||
* Add -f filters to kill-pane -a, kill-window -a and kill-session -a (issue
|
|
||||||
4782).
|
|
||||||
|
|
||||||
* Allow server ACLs to use groups as well as users (issue 4917).
|
|
||||||
|
|
||||||
* The mouse option now defaults to on.
|
|
||||||
|
|
||||||
* Fix send-keys -K so keys are inserted in the correct place in the input
|
|
||||||
queue, like keys from key bindings (issue 3476).
|
|
||||||
|
|
||||||
* Fix control mode clients hanging on exit if pty data was still queued (Ben
|
|
||||||
Maurer, issue 5356), and avoid sending notifications to clients which are
|
|
||||||
already exiting (Ben Maurer, issue 5357).
|
|
||||||
|
|
||||||
* Fix grouped sessions sometimes being left as unusable command targets while
|
|
||||||
they are being killed (Bryce Miller, issue 5180).
|
|
||||||
|
|
||||||
* Fix choose mode filtering when more than one pane exists (issue 5326), and
|
|
||||||
fix an infinite loop in customize mode when a filter does not match.
|
|
||||||
|
|
||||||
* Fix regsub when the pattern is anchored at the start (issue 5341).
|
|
||||||
|
|
||||||
* Fix redraw issues around synchronized updates, copy mode, tabs, padding,
|
|
||||||
status lines, menus, popups, wide characters and floating panes. This
|
|
||||||
includes fixes for flicker with alternate screen applications and scrollbars
|
|
||||||
(Michael Grant, issue 5351; Noam Stolero, issue 5350; Aung Myo Kyaw, issue
|
|
||||||
5098).
|
|
||||||
|
|
||||||
* Do not crash looking for the next or previous session (issue 5344), or when
|
|
||||||
no client is available.
|
|
||||||
|
|
||||||
CHANGES FROM 3.7b TO 3.7c
|
|
||||||
|
|
||||||
* Build with jemalloc on macOS to avoid what appears to be a bug in calloc
|
|
||||||
(issue 5385).
|
|
||||||
|
|
||||||
* Fix scrollbar initial state so they appear on new windows (issue 5339).
|
|
||||||
|
|
||||||
* Check time periodically in loops rather than every one (issue 5367).
|
|
||||||
|
|
||||||
* Use message-style again as default for message-format.
|
|
||||||
|
|
||||||
* Unzoom before creating floating panes to avoid a crash.
|
|
||||||
|
|
||||||
CHANGES FROM 3.7a TO 3.7b
|
CHANGES FROM 3.7a TO 3.7b
|
||||||
|
|
||||||
* Fix so that the end of a synchronized update again triggers a redraw.
|
* Fix so that the end of a synchronized update again triggers a redraw.
|
||||||
|
|||||||
23
Makefile.am
23
Makefile.am
@@ -4,7 +4,7 @@ CLEANFILES = tmux.1.mdoc tmux.1.man cmd-parse.c
|
|||||||
|
|
||||||
# Distribution tarball options.
|
# Distribution tarball options.
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
CHANGES README COPYING example_tmux.conf \
|
CHANGES README README.ja COPYING example_tmux.conf \
|
||||||
osdep-*.c mdoc2man.awk tmux.1
|
osdep-*.c mdoc2man.awk tmux.1
|
||||||
dist_EXTRA_tmux_SOURCES = compat/*.[ch]
|
dist_EXTRA_tmux_SOURCES = compat/*.[ch]
|
||||||
|
|
||||||
@@ -13,8 +13,7 @@ AM_CPPFLAGS += @XOPEN_DEFINES@ \
|
|||||||
-DTMUX_VERSION='"@VERSION@"' \
|
-DTMUX_VERSION='"@VERSION@"' \
|
||||||
-DTMUX_CONF='"$(sysconfdir)/tmux.conf:~/.tmux.conf:$$XDG_CONFIG_HOME/tmux/tmux.conf:~/.config/tmux/tmux.conf"' \
|
-DTMUX_CONF='"$(sysconfdir)/tmux.conf:~/.tmux.conf:$$XDG_CONFIG_HOME/tmux/tmux.conf:~/.config/tmux/tmux.conf"' \
|
||||||
-DTMUX_LOCK_CMD='"@DEFAULT_LOCK_CMD@"' \
|
-DTMUX_LOCK_CMD='"@DEFAULT_LOCK_CMD@"' \
|
||||||
-DTMUX_TERM='"@DEFAULT_TERM@"' \
|
-DTMUX_TERM='"@DEFAULT_TERM@"'
|
||||||
-DTMUX_MOUSE=1
|
|
||||||
|
|
||||||
# Additional object files.
|
# Additional object files.
|
||||||
LDADD = $(LIBOBJS)
|
LDADD = $(LIBOBJS)
|
||||||
@@ -43,8 +42,7 @@ AM_CPPFLAGS += -DDEBUG
|
|||||||
endif
|
endif
|
||||||
AM_CPPFLAGS += -iquote.
|
AM_CPPFLAGS += -iquote.
|
||||||
if IS_ASAN
|
if IS_ASAN
|
||||||
AM_CPPFLAGS += -DASAN
|
AM_CFLAGS += -fsanitize=address
|
||||||
AM_CFLAGS += -fsanitize=address -fno-omit-frame-pointer
|
|
||||||
AM_LDFLAGS += -fsanitize=address
|
AM_LDFLAGS += -fsanitize=address
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@@ -85,7 +83,6 @@ endif
|
|||||||
|
|
||||||
# List of sources.
|
# List of sources.
|
||||||
dist_tmux_SOURCES = \
|
dist_tmux_SOURCES = \
|
||||||
active.c \
|
|
||||||
alerts.c \
|
alerts.c \
|
||||||
arguments.c \
|
arguments.c \
|
||||||
attributes.c \
|
attributes.c \
|
||||||
@@ -102,8 +99,10 @@ dist_tmux_SOURCES = \
|
|||||||
cmd-detach-client.c \
|
cmd-detach-client.c \
|
||||||
cmd-display-menu.c \
|
cmd-display-menu.c \
|
||||||
cmd-display-message.c \
|
cmd-display-message.c \
|
||||||
|
cmd-display-panes.c \
|
||||||
cmd-find-window.c \
|
cmd-find-window.c \
|
||||||
cmd-find.c \
|
cmd-find.c \
|
||||||
|
cmd-hide-pane.c \
|
||||||
cmd-if-shell.c \
|
cmd-if-shell.c \
|
||||||
cmd-join-pane.c \
|
cmd-join-pane.c \
|
||||||
cmd-kill-pane.c \
|
cmd-kill-pane.c \
|
||||||
@@ -161,16 +160,13 @@ dist_tmux_SOURCES = \
|
|||||||
control-notify.c \
|
control-notify.c \
|
||||||
control.c \
|
control.c \
|
||||||
environ.c \
|
environ.c \
|
||||||
events-payload.c \
|
|
||||||
events.c \
|
|
||||||
file.c \
|
file.c \
|
||||||
format-draw.c \
|
|
||||||
format.c \
|
format.c \
|
||||||
|
format-draw.c \
|
||||||
fuzzy.c \
|
fuzzy.c \
|
||||||
grid-reader.c \
|
grid-reader.c \
|
||||||
grid-view.c \
|
grid-view.c \
|
||||||
grid.c \
|
grid.c \
|
||||||
hooks.c \
|
|
||||||
hyperlinks.c \
|
hyperlinks.c \
|
||||||
input-keys.c \
|
input-keys.c \
|
||||||
input.c \
|
input.c \
|
||||||
@@ -183,15 +179,15 @@ dist_tmux_SOURCES = \
|
|||||||
log.c \
|
log.c \
|
||||||
menu.c \
|
menu.c \
|
||||||
mode-tree.c \
|
mode-tree.c \
|
||||||
monitor.c \
|
|
||||||
names.c \
|
names.c \
|
||||||
|
notify.c \
|
||||||
options-table.c \
|
options-table.c \
|
||||||
options.c \
|
options.c \
|
||||||
paste.c \
|
paste.c \
|
||||||
popup.c \
|
popup.c \
|
||||||
proc.c \
|
proc.c \
|
||||||
prompt-history.c \
|
|
||||||
prompt.c \
|
prompt.c \
|
||||||
|
prompt-history.c \
|
||||||
regsub.c \
|
regsub.c \
|
||||||
resize.c \
|
resize.c \
|
||||||
screen-redraw.c \
|
screen-redraw.c \
|
||||||
@@ -206,9 +202,9 @@ dist_tmux_SOURCES = \
|
|||||||
spawn.c \
|
spawn.c \
|
||||||
status.c \
|
status.c \
|
||||||
style.c \
|
style.c \
|
||||||
tmux-protocol.h \
|
|
||||||
tmux.c \
|
tmux.c \
|
||||||
tmux.h \
|
tmux.h \
|
||||||
|
tmux-protocol.h \
|
||||||
tty-acs.c \
|
tty-acs.c \
|
||||||
tty-draw.c \
|
tty-draw.c \
|
||||||
tty-features.c \
|
tty-features.c \
|
||||||
@@ -223,7 +219,6 @@ dist_tmux_SOURCES = \
|
|||||||
window-clock.c \
|
window-clock.c \
|
||||||
window-copy.c \
|
window-copy.c \
|
||||||
window-customize.c \
|
window-customize.c \
|
||||||
window-panes.c \
|
|
||||||
window-switch.c \
|
window-switch.c \
|
||||||
window-tree.c \
|
window-tree.c \
|
||||||
window-visible.c \
|
window-visible.c \
|
||||||
|
|||||||
62
README.ja
Normal file
62
README.ja
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
tmuxへようこそ!
|
||||||
|
|
||||||
|
tmuxはターミナルマルチプレクサーです。複数のターミナルを一つのスクリーン内に作成し、操作することができます。
|
||||||
|
バックグラウンドで処理を実行中に一度スクリーンから離れて後から復帰することも可能です。
|
||||||
|
|
||||||
|
OpenBSD、FreeBSD、NetBSD、Linux、macOS、Solarisで実行できます。
|
||||||
|
|
||||||
|
tmuxはlibevent 2.x.に依存します。 下記からダウンロードしてください。
|
||||||
|
|
||||||
|
http://libevent.org
|
||||||
|
|
||||||
|
また、ncursesも必要です。こちらからどうぞ。
|
||||||
|
|
||||||
|
http://invisible-island.net/ncurses/
|
||||||
|
|
||||||
|
tarballでのtmuxのビルドとインストール方法。
|
||||||
|
|
||||||
|
$ ./configure && make
|
||||||
|
$ sudo make install
|
||||||
|
|
||||||
|
tmuxはutmp(5)をアップデートするためにutempterを使うことができます。もしインストール済みであればオプション「--enable-utempter」をつけて実行してください。
|
||||||
|
|
||||||
|
リポジトリから最新バージョンを手に入れるためには下記を実行。
|
||||||
|
|
||||||
|
$ git clone https://github.com/tmux/tmux.git
|
||||||
|
$ cd tmux
|
||||||
|
$ sh autogen.sh
|
||||||
|
$ ./configure && make
|
||||||
|
|
||||||
|
(ビルドのためにはlibevent、ncurses libraries、headersに加えて、C compiler、make、autoconf、automake、pkg-configが必要です。)
|
||||||
|
|
||||||
|
詳しい情報はhttp://git-scm.comをご覧ください。修正はメール<tmux-users@googlegroups.com>宛、もしくはhttps://github.com/tmux/tmux/issuesにて受け付けています。
|
||||||
|
|
||||||
|
tmuxのドキュメントについてはtmux.1マニュアルをご覧ください。こちらのコマンドで参照可能です。
|
||||||
|
|
||||||
|
$ nroff -mdoc tmux.1|less
|
||||||
|
|
||||||
|
サンプル設定は本リポジトリのexample_tmux.confに
|
||||||
|
また、bash-completionファイルは下記にあります。
|
||||||
|
|
||||||
|
https://github.com/scop/bash-completion/blob/main/completions/tmux
|
||||||
|
|
||||||
|
「-v」や「-vv」を指定することでデバッグモードでの起動が可能です。カレントディレクトリにサーバーやクライアントのログファイルが生成されます。
|
||||||
|
|
||||||
|
議論やバグレポート用のメーリングリストにはこちらから参加可能です。
|
||||||
|
|
||||||
|
https://groups.google.com/forum/#!forum/tmux-users
|
||||||
|
|
||||||
|
gitコミットについての連絡先
|
||||||
|
|
||||||
|
https://groups.google.com/forum/#!forum/tmux-git
|
||||||
|
|
||||||
|
購読は<tmux-users+subscribe@googlegroups.com>までメールをお願いします。
|
||||||
|
|
||||||
|
バグレポートや機能追加(特にコードへの貢献)は大歓迎です。こちらにご連絡ください。
|
||||||
|
|
||||||
|
tmux-users@googlegroups.com
|
||||||
|
|
||||||
|
本ファイル、CHANGES、 FAQ、SYNCINGそしてTODOはISC licenseで保護されています。
|
||||||
|
その他のファイルのライセンスや著作権については、ファイルの上部に明記されています。
|
||||||
|
|
||||||
|
-- Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -1 +0,0 @@
|
|||||||
Please report security issues to nicholas.marriott@gmail.com.
|
|
||||||
173
SYNCING
Normal file
173
SYNCING
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
Preamble
|
||||||
|
========
|
||||||
|
|
||||||
|
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-obsd" is the version of tmux in OpenBSD base system which provides
|
||||||
|
the basis of the portable tmux version.
|
||||||
|
|
||||||
|
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
|
||||||
|
OpenBSD code).
|
||||||
|
|
||||||
|
If you've never used git before, git tracks meta-data about the committer
|
||||||
|
and the author, as part of a commit, hence:
|
||||||
|
|
||||||
|
% git config [--global] user.name "Your name"
|
||||||
|
% git config [--global] user.email "you@yourdomain.com"
|
||||||
|
|
||||||
|
Note that, if you already have this in the global ~/.gitconfig option, then
|
||||||
|
this will be used. Setting this per-repository would involve not using the
|
||||||
|
"--global" flag above. If you wish to use the same credentials always,
|
||||||
|
pass the "--global" option, as shown.
|
||||||
|
|
||||||
|
This is a one-off operation once the repository has been cloned, assuming
|
||||||
|
this information has ever been set before.
|
||||||
|
|
||||||
|
Cloning repositories
|
||||||
|
====================
|
||||||
|
|
||||||
|
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-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
|
||||||
|
these checkouts existing, skip that.
|
||||||
|
|
||||||
|
Adding in git-remotes
|
||||||
|
=====================
|
||||||
|
|
||||||
|
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-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-obsd
|
||||||
|
|
||||||
|
So that now, the remote "obsd-tmux" can be used to reference branches and
|
||||||
|
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-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-obsd
|
||||||
|
% git checkout master
|
||||||
|
% git pull
|
||||||
|
|
||||||
|
Then back in "tmux":
|
||||||
|
|
||||||
|
% cd /path/to/tmux
|
||||||
|
% git fetch obsd-tmux
|
||||||
|
|
||||||
|
Creating the necessary branches
|
||||||
|
===============================
|
||||||
|
|
||||||
|
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-obsd" in the "tmux" repository:
|
||||||
|
|
||||||
|
% git checkout -b obsd-master obsd-tmux/master
|
||||||
|
|
||||||
|
Adding in the fake history points
|
||||||
|
=================================
|
||||||
|
|
||||||
|
To tie both the "master" branch from "tmux" and the "obsd-master"
|
||||||
|
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:
|
||||||
|
|
||||||
|
% cd /path/to/tmux
|
||||||
|
% git config --add remote.origin.fetch '+refs/replace/*:refs/replace/*'
|
||||||
|
% git fetch origin
|
||||||
|
|
||||||
|
Performing the Sync
|
||||||
|
===================
|
||||||
|
|
||||||
|
Make sure the "master" branch is checked out:
|
||||||
|
|
||||||
|
% git checkout master
|
||||||
|
|
||||||
|
The following will show commits on OpenBSD not yet synched with "tmux":
|
||||||
|
|
||||||
|
% git log master..obsd-master
|
||||||
|
|
||||||
|
From there, merge the result in, fixing up any conflicts which might arise.
|
||||||
|
|
||||||
|
% git merge obsd-master
|
||||||
|
|
||||||
|
Then ensure things look correct by BUILDING the result of that sync:
|
||||||
|
|
||||||
|
% make clean && ./autogen.sh && ./configure && make
|
||||||
|
|
||||||
|
Compare the git merge result with what's on origin/master -- that is, check
|
||||||
|
which commits you're about to push:
|
||||||
|
|
||||||
|
% git log origin/master..master
|
||||||
|
|
||||||
|
And if happy:
|
||||||
|
|
||||||
|
% git push origin master
|
||||||
|
|
||||||
|
Keeping an eye on libutil in OpenBSD
|
||||||
|
====================================
|
||||||
|
|
||||||
|
A lot of the compat/ code in tmux comes from libutil, especially imsg.
|
||||||
|
Sometimes the API can change, etc., which might cause interesting problems
|
||||||
|
trying to run the portable version of tmux. It's worth checking
|
||||||
|
periodically for any changes to libutil in OpenBSD and syncing those files
|
||||||
|
to compat/ as and when appropriate.
|
||||||
|
|
||||||
|
Release tmux for next version
|
||||||
|
=============================
|
||||||
|
|
||||||
|
1. Update and commit README and CHANGES. The former should be checked for
|
||||||
|
anything outdated and updated with a list of things that might break
|
||||||
|
upgrades and the latter should mention all the major changes since
|
||||||
|
the last version.
|
||||||
|
|
||||||
|
2. Make sure configure.ac has the new version number.
|
||||||
|
|
||||||
|
3. Tag with:
|
||||||
|
|
||||||
|
% git tag -a 2.X
|
||||||
|
|
||||||
|
Where "2.X" is the next version.
|
||||||
|
|
||||||
|
Push the tag out with:
|
||||||
|
|
||||||
|
% git push --tags
|
||||||
|
|
||||||
|
4. Build the tarball with 'make dist'.
|
||||||
|
|
||||||
|
5. Check the tarball. If it's good, go here to select the tag just pushed:
|
||||||
|
|
||||||
|
https://github.com/tmux/tmux/tags
|
||||||
|
|
||||||
|
Click the "Add release notes", upload the tarball and add a link in the
|
||||||
|
description field to the CHANGES file.
|
||||||
|
|
||||||
|
6. Clone the tmux.github.io repository, and change the RELEASE version in the
|
||||||
|
Makefile. Commit it, and run 'make' to replace %%RELEASE%%. Push the
|
||||||
|
result out.
|
||||||
|
|
||||||
|
7. Change version back to master in configure.ac.
|
||||||
234
SYNCING.md
234
SYNCING.md
@@ -1,234 +0,0 @@
|
|||||||
# Preamble
|
|
||||||
|
|
||||||
tmux portable is maintained from two repositories:
|
|
||||||
|
|
||||||
* `tmux` is the portable repository. It contains the portability layer,
|
|
||||||
autotools build files, regression tests, documentation, and code needed for
|
|
||||||
platforms outside OpenBSD.
|
|
||||||
* `tmux-openbsd-cutover` is the OpenBSD tmux import repository. Its `master`
|
|
||||||
branch is the OpenBSD tmux history after the OpenBSD Git cutover. Portable
|
|
||||||
merges this branch when importing OpenBSD changes.
|
|
||||||
|
|
||||||
To create the commits in the tmux-openbsd-cutover repo, the source repo is the
|
|
||||||
Github mirror of OpenBSD's src repo:
|
|
||||||
|
|
||||||
```text
|
|
||||||
https://github.com/openbsd/src.git
|
|
||||||
```
|
|
||||||
|
|
||||||
The update automation filters the OpenBSD source tree to `usr.bin/tmux/`,
|
|
||||||
publishes that filtered history as `openbsd-git` in the cutover repository,
|
|
||||||
cherry-picks new filtered commits onto cutover `master`, then merges cutover
|
|
||||||
`master` into portable `master`.
|
|
||||||
|
|
||||||
If you've never used git before, configure your identity before committing:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git config [--global] user.name "Your name"
|
|
||||||
git config [--global] user.email "you@yourdomain.com"
|
|
||||||
```
|
|
||||||
|
|
||||||
# Repository layout
|
|
||||||
|
|
||||||
The usual local layout is:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd /some/where/useful
|
|
||||||
git clone https://github.com/tmux/tmux.git tmux-portable
|
|
||||||
git clone https://github.com/ThomasAdam/tmux-obsd.git tmux-openbsd-cutover
|
|
||||||
```
|
|
||||||
|
|
||||||
The exact directory names do not matter, but the examples below use:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/path/to/tmux-portable
|
|
||||||
/path/to/tmux-openbsd-cutover
|
|
||||||
```
|
|
||||||
|
|
||||||
The cutover repository has three important branches:
|
|
||||||
|
|
||||||
* `master` is the branch portable consumes. It should contain tmux source
|
|
||||||
only, not automation files.
|
|
||||||
* `openbsd-git` is the raw filtered OpenBSD tmux branch generated from
|
|
||||||
OpenBSD src `master`.
|
|
||||||
* `automation` is an orphan branch containing the GitHub Actions workflow. It
|
|
||||||
is separate so that workflow files are not merged into portable.
|
|
||||||
|
|
||||||
# Adding the OpenBSD remote to portable
|
|
||||||
|
|
||||||
In the portable repository, add the cutover repository as a remote:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd /path/to/tmux-portable
|
|
||||||
git remote add tmux-openbsd /path/to/tmux-openbsd-cutover
|
|
||||||
git config remote.tmux-openbsd.tagOpt --no-tags
|
|
||||||
```
|
|
||||||
|
|
||||||
If the remote already exists, update it instead:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git remote set-url tmux-openbsd /path/to/tmux-openbsd-cutover
|
|
||||||
git config remote.tmux-openbsd.tagOpt --no-tags
|
|
||||||
```
|
|
||||||
|
|
||||||
Fetch the cutover master branch explicitly:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git fetch --no-tags tmux-openbsd master:refs/remotes/tmux-openbsd/master
|
|
||||||
```
|
|
||||||
|
|
||||||
# Automated syncing
|
|
||||||
|
|
||||||
The normal sync is performed by the GitHub Actions workflow in the
|
|
||||||
`automation` branch of the cutover repository. That workflow:
|
|
||||||
|
|
||||||
1. Fetches or clones OpenBSD src using a blobless clone.
|
|
||||||
2. Filters `usr.bin/tmux/` into a local `tmux-openbsd` branch.
|
|
||||||
3. Updates `tmux-openbsd-cutover/openbsd-git`.
|
|
||||||
4. Cherry-picks new `openbsd-git` commits onto cutover `master`.
|
|
||||||
5. Merges cutover `master` into portable `master`.
|
|
||||||
6. Pushes the changed repositories.
|
|
||||||
|
|
||||||
The workflow deliberately runs from the orphan `automation` branch but checks
|
|
||||||
out cutover `master` as the branch to update. This keeps `.github/` out of
|
|
||||||
cutover `master`, so portable does not import workflow files when it merges
|
|
||||||
OpenBSD changes.
|
|
||||||
|
|
||||||
# Manual portable merge
|
|
||||||
|
|
||||||
If the workflow fails while merging into portable, do the merge locally and
|
|
||||||
push the result.
|
|
||||||
|
|
||||||
Start from an up-to-date portable master:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd /path/to/tmux-portable
|
|
||||||
git fetch origin
|
|
||||||
git checkout master
|
|
||||||
git pull --ff-only origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
Fetch the cutover branch:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git remote add tmux-openbsd /path/to/tmux-openbsd-cutover 2>/dev/null || true
|
|
||||||
git config remote.tmux-openbsd.tagOpt --no-tags
|
|
||||||
git fetch --no-tags tmux-openbsd master:refs/remotes/tmux-openbsd/master
|
|
||||||
```
|
|
||||||
|
|
||||||
Merge it:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git merge --no-ff --log refs/remotes/tmux-openbsd/master
|
|
||||||
```
|
|
||||||
|
|
||||||
Resolve conflicts by deciding whether portable or OpenBSD owns the file.
|
|
||||||
|
|
||||||
Useful commands:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git checkout --ours path/to/file
|
|
||||||
git add path/to/file
|
|
||||||
```
|
|
||||||
|
|
||||||
This keeps the portable version of a conflicted file.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git checkout --theirs path/to/file
|
|
||||||
git add path/to/file
|
|
||||||
```
|
|
||||||
|
|
||||||
This takes the OpenBSD/cutover version of a conflicted file.
|
|
||||||
|
|
||||||
Before committing, inspect the result:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git status
|
|
||||||
git diff --check
|
|
||||||
git diff --cached --stat
|
|
||||||
```
|
|
||||||
|
|
||||||
Then finish and publish:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git commit
|
|
||||||
git push origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
If the merge attempt is wrong, abort it:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git merge --abort
|
|
||||||
```
|
|
||||||
|
|
||||||
After pushing a manually resolved merge, rerun the workflow. It should either
|
|
||||||
no-op or continue from the now-merged portable state.
|
|
||||||
|
|
||||||
# Manual cutover update
|
|
||||||
|
|
||||||
Normally this is handled by the workflow. If it must be done manually, update
|
|
||||||
`openbsd-git` in the cutover repository from a filtered OpenBSD src checkout,
|
|
||||||
then cherry-pick the new filtered commits onto cutover `master`.
|
|
||||||
|
|
||||||
The important range is:
|
|
||||||
|
|
||||||
```text
|
|
||||||
origin/openbsd-git..openbsd-git
|
|
||||||
```
|
|
||||||
|
|
||||||
where `origin/openbsd-git` is the previously published filtered OpenBSD tmux
|
|
||||||
branch and `openbsd-git` is the newly generated filtered branch.
|
|
||||||
|
|
||||||
In the cutover repository:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd /path/to/tmux-openbsd-cutover
|
|
||||||
git checkout master
|
|
||||||
git cherry-pick origin/openbsd-git..openbsd-git
|
|
||||||
git push origin master openbsd-git
|
|
||||||
```
|
|
||||||
|
|
||||||
Do not put workflow files on cutover `master`; keep them on the orphan
|
|
||||||
`automation` branch.
|
|
||||||
|
|
||||||
# Keeping an eye on libutil in OpenBSD
|
|
||||||
|
|
||||||
A lot of the `compat/` code in tmux comes from OpenBSD libraries, especially
|
|
||||||
imsg. Sometimes APIs change in OpenBSD in ways that require corresponding
|
|
||||||
portable changes. It is worth checking periodically for relevant OpenBSD
|
|
||||||
libutil changes and syncing those files into `compat/` as appropriate.
|
|
||||||
|
|
||||||
# Release tmux for next version
|
|
||||||
|
|
||||||
1. Update and commit README and CHANGES. The former should be checked for
|
|
||||||
anything outdated and updated with a list of things that might break
|
|
||||||
upgrades and the latter should mention all the major changes since the last
|
|
||||||
version.
|
|
||||||
2. Make sure `configure.ac` has the new version number.
|
|
||||||
3. Tag with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
% git tag -a 2.X
|
|
||||||
```
|
|
||||||
|
|
||||||
Where `2.X` is the next version.
|
|
||||||
|
|
||||||
Push the tag out with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
% git push --tags
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Build the tarball with `make dist`.
|
|
||||||
5. Check the tarball. If it is good, go here to select the tag just pushed:
|
|
||||||
|
|
||||||
```text
|
|
||||||
https://github.com/tmux/tmux/tags
|
|
||||||
```
|
|
||||||
|
|
||||||
Click "Add release notes", upload the tarball and add a link in the
|
|
||||||
description field to the CHANGES file.
|
|
||||||
6. Clone the tmux.github.io repository, and change the RELEASE version in the
|
|
||||||
Makefile. Commit it, and run `make` to replace `%%RELEASE%%`. Push the
|
|
||||||
result out.
|
|
||||||
7. Change version back to master in `configure.ac`.
|
|
||||||
449
active.c
449
active.c
@@ -1,449 +0,0 @@
|
|||||||
/* $OpenBSD$ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/* Local last-window stack entry. */
|
|
||||||
struct active_window_entry {
|
|
||||||
u_int window;
|
|
||||||
TAILQ_ENTRY(active_window_entry) entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Local last-window stack. */
|
|
||||||
TAILQ_HEAD(active_window_stack, active_window_entry);
|
|
||||||
|
|
||||||
/* Per-client and per-session local active window state. */
|
|
||||||
struct active_window {
|
|
||||||
struct client *client;
|
|
||||||
struct session *session;
|
|
||||||
|
|
||||||
u_int window;
|
|
||||||
struct active_window_stack lastw;
|
|
||||||
|
|
||||||
RB_ENTRY(active_window) entry;
|
|
||||||
};
|
|
||||||
RB_HEAD(active_windows, active_window);
|
|
||||||
|
|
||||||
static int
|
|
||||||
active_window_cmp(struct active_window *aw1, struct active_window *aw2)
|
|
||||||
{
|
|
||||||
uintptr_t c1 = (uintptr_t)aw1->client;
|
|
||||||
uintptr_t c2 = (uintptr_t)aw2->client;
|
|
||||||
uintptr_t s1 = (uintptr_t)aw1->session;
|
|
||||||
uintptr_t s2 = (uintptr_t)aw2->session;
|
|
||||||
|
|
||||||
if (c1 < c2)
|
|
||||||
return (-1);
|
|
||||||
if (c1 > c2)
|
|
||||||
return (1);
|
|
||||||
if (s1 < s2)
|
|
||||||
return (-1);
|
|
||||||
if (s1 > s2)
|
|
||||||
return (1);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
RB_GENERATE_STATIC(active_windows, active_window, entry, active_window_cmp);
|
|
||||||
|
|
||||||
static struct active_window *active_get(struct client *, struct session *);
|
|
||||||
static struct active_window *active_add(struct client *, struct session *,
|
|
||||||
struct winlink *);
|
|
||||||
static void active_free(struct active_window *);
|
|
||||||
static struct winlink *active_resolve(struct active_window *);
|
|
||||||
static void active_stack_remove(struct active_window_stack *, u_int);
|
|
||||||
static void active_stack_push(struct active_window_stack *, u_int);
|
|
||||||
static void active_changed(struct client *, struct session *,
|
|
||||||
struct winlink *, struct winlink *);
|
|
||||||
|
|
||||||
/* All local active window states. */
|
|
||||||
static struct active_windows active_windows = RB_INITIALIZER(&active_windows);
|
|
||||||
|
|
||||||
/* Find local active window state for a client and session. */
|
|
||||||
static struct active_window *
|
|
||||||
active_get(struct client *c, struct session *s)
|
|
||||||
{
|
|
||||||
struct active_window aw;
|
|
||||||
|
|
||||||
if (c == NULL || s == NULL)
|
|
||||||
return (NULL);
|
|
||||||
aw.client = c;
|
|
||||||
aw.session = s;
|
|
||||||
return (RB_FIND(active_windows, &active_windows, &aw));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add local active window state for a client and session. */
|
|
||||||
static struct active_window *
|
|
||||||
active_add(struct client *c, struct session *s, struct winlink *wl)
|
|
||||||
{
|
|
||||||
struct active_window *aw;
|
|
||||||
|
|
||||||
aw = active_get(c, s);
|
|
||||||
if (aw == NULL) {
|
|
||||||
aw = xcalloc(1, sizeof *aw);
|
|
||||||
aw->client = c;
|
|
||||||
aw->session = s;
|
|
||||||
TAILQ_INIT(&aw->lastw);
|
|
||||||
RB_INSERT(active_windows, &active_windows, aw);
|
|
||||||
}
|
|
||||||
if (wl != NULL)
|
|
||||||
aw->window = wl->window->id;
|
|
||||||
return (aw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free local active window state. */
|
|
||||||
static void
|
|
||||||
active_free(struct active_window *aw)
|
|
||||||
{
|
|
||||||
struct active_window_entry *awe;
|
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&aw->lastw)) {
|
|
||||||
awe = TAILQ_FIRST(&aw->lastw);
|
|
||||||
TAILQ_REMOVE(&aw->lastw, awe, entry);
|
|
||||||
free(awe);
|
|
||||||
}
|
|
||||||
RB_REMOVE(active_windows, &active_windows, aw);
|
|
||||||
free(aw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Resolve local active window state to a valid winlink. */
|
|
||||||
static struct winlink *
|
|
||||||
active_resolve(struct active_window *aw)
|
|
||||||
{
|
|
||||||
struct winlink *wl, *next;
|
|
||||||
u_int window;
|
|
||||||
|
|
||||||
if (aw == NULL || aw->session->curw == NULL)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
wl = winlink_find_by_window_id(&aw->session->windows, aw->window);
|
|
||||||
if (wl != NULL)
|
|
||||||
return (wl);
|
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(&aw->lastw)) {
|
|
||||||
window = TAILQ_FIRST(&aw->lastw)->window;
|
|
||||||
|
|
||||||
next = winlink_find_by_window_id(&aw->session->windows, window);
|
|
||||||
active_stack_remove(&aw->lastw, window);
|
|
||||||
if (next != NULL) {
|
|
||||||
aw->window = next->window->id;
|
|
||||||
return (next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aw->window = aw->session->curw->window->id;
|
|
||||||
return (aw->session->curw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove a window from a local last-window stack. */
|
|
||||||
static void
|
|
||||||
active_stack_remove(struct active_window_stack *stack, u_int window)
|
|
||||||
{
|
|
||||||
struct active_window_entry *awe, *awe1;
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(awe, stack, entry, awe1) {
|
|
||||||
if (awe->window == window) {
|
|
||||||
TAILQ_REMOVE(stack, awe, entry);
|
|
||||||
free(awe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Push a window onto a local last-window stack. */
|
|
||||||
static void
|
|
||||||
active_stack_push(struct active_window_stack *stack, u_int window)
|
|
||||||
{
|
|
||||||
struct active_window_entry *awe;
|
|
||||||
|
|
||||||
active_stack_remove(stack, window);
|
|
||||||
awe = xcalloc(1, sizeof *awe);
|
|
||||||
awe->window = window;
|
|
||||||
TAILQ_INSERT_HEAD(stack, awe, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify the server that a client's effective window changed. */
|
|
||||||
static void
|
|
||||||
active_changed(struct client *c, struct session *s, struct winlink *wl,
|
|
||||||
struct winlink *old)
|
|
||||||
{
|
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
|
|
||||||
if (wl == NULL || wl == old)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (options_get_number(global_options, "focus-events")) {
|
|
||||||
if (old != NULL)
|
|
||||||
window_update_focus(old->window);
|
|
||||||
window_update_focus(wl->window);
|
|
||||||
}
|
|
||||||
winlink_clear_flags(wl);
|
|
||||||
window_update_activity(wl->window);
|
|
||||||
tty_update_window_offset(wl->window);
|
|
||||||
|
|
||||||
if (c != NULL && c->session == s)
|
|
||||||
wl->window->latest = c;
|
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
cmd_find_from_winlink(&fs, wl, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
event_payload_set_client(ep, "client", c);
|
|
||||||
event_payload_set_session(ep, "session", s);
|
|
||||||
event_payload_set_window(ep, "window", wl->window);
|
|
||||||
event_payload_set_window(ep, "new_window", wl->window);
|
|
||||||
event_payload_set_int(ep, "window_index", wl->idx);
|
|
||||||
event_payload_set_int(ep, "new_window_index", wl->idx);
|
|
||||||
if (old != NULL) {
|
|
||||||
event_payload_set_window(ep, "old_window", old->window);
|
|
||||||
event_payload_set_int(ep, "old_window_index", old->idx);
|
|
||||||
}
|
|
||||||
events_fire("client-window-changed", ep);
|
|
||||||
|
|
||||||
if (c != NULL) {
|
|
||||||
c->flags |= CLIENT_REDRAWWINDOW|CLIENT_REDRAWSTATUS|
|
|
||||||
CLIENT_REDRAWBORDERS;
|
|
||||||
tty_update_client_offset(c);
|
|
||||||
status_update_cache(s);
|
|
||||||
}
|
|
||||||
recalculate_sizes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return if a client has local window selection for a session. */
|
|
||||||
int
|
|
||||||
active_is_local_window(struct client *c, struct session *s)
|
|
||||||
{
|
|
||||||
return (active_get(c, s) != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make a client use local or shared window selection for a session. */
|
|
||||||
void
|
|
||||||
active_set_local_window(struct client *c, struct session *s,
|
|
||||||
enum active_window_mode mode)
|
|
||||||
{
|
|
||||||
struct active_window *aw;
|
|
||||||
struct winlink *wl, *old;
|
|
||||||
|
|
||||||
if (c == NULL || s == NULL || s->curw == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
old = active_get_effective_winlink(c, s);
|
|
||||||
if (mode == ACTIVE_LOCAL) {
|
|
||||||
active_add(c, s, old);
|
|
||||||
if (c != NULL && c->session == s)
|
|
||||||
c->flags |= CLIENT_REDRAWSTATUS;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aw = active_get(c, s);
|
|
||||||
if (aw != NULL) {
|
|
||||||
active_free(aw);
|
|
||||||
wl = active_get_effective_winlink(c, s);
|
|
||||||
active_changed(c, s, wl, old);
|
|
||||||
if (c != NULL && c->session == s)
|
|
||||||
c->flags |= CLIENT_REDRAWSTATUS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the effective winlink for a client and session. */
|
|
||||||
struct winlink *
|
|
||||||
active_get_effective_winlink(struct client *c, struct session *s)
|
|
||||||
{
|
|
||||||
struct active_window *aw;
|
|
||||||
|
|
||||||
if (s == NULL)
|
|
||||||
return (NULL);
|
|
||||||
aw = active_get(c, s);
|
|
||||||
if (aw != NULL)
|
|
||||||
return (active_resolve(aw));
|
|
||||||
return (s->curw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the effective window for a client and session. */
|
|
||||||
struct window *
|
|
||||||
active_get_effective_window(struct client *c, struct session *s)
|
|
||||||
{
|
|
||||||
struct winlink *wl;
|
|
||||||
|
|
||||||
wl = active_get_effective_winlink(c, s);
|
|
||||||
if (wl == NULL)
|
|
||||||
return (NULL);
|
|
||||||
return (wl->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select a winlink for a client and session. */
|
|
||||||
int
|
|
||||||
active_select_window(struct client *c, struct session *s, struct winlink *wl)
|
|
||||||
{
|
|
||||||
struct active_window *aw;
|
|
||||||
struct winlink *old;
|
|
||||||
int changed;
|
|
||||||
|
|
||||||
if (wl == NULL)
|
|
||||||
return (-1);
|
|
||||||
aw = active_get(c, s);
|
|
||||||
if (aw == NULL)
|
|
||||||
return (session_set_current(s, wl));
|
|
||||||
|
|
||||||
old = active_resolve(aw);
|
|
||||||
if (old == wl)
|
|
||||||
return (1);
|
|
||||||
if (old != NULL)
|
|
||||||
active_stack_push(&aw->lastw, old->window->id);
|
|
||||||
active_stack_remove(&aw->lastw, wl->window->id);
|
|
||||||
aw->window = wl->window->id;
|
|
||||||
changed = (old != wl);
|
|
||||||
active_changed(c, s, wl, old);
|
|
||||||
return (changed ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select a window by index. */
|
|
||||||
int
|
|
||||||
active_select_window_index(struct client *c, struct session *s, int idx)
|
|
||||||
{
|
|
||||||
struct winlink *wl;
|
|
||||||
|
|
||||||
wl = winlink_find_by_index(&s->windows, idx);
|
|
||||||
return (active_select_window(c, s, wl));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the next window. */
|
|
||||||
int
|
|
||||||
active_next_window(struct client *c, struct session *s, int alert)
|
|
||||||
{
|
|
||||||
struct winlink *wl;
|
|
||||||
|
|
||||||
wl = active_get_effective_winlink(c, s);
|
|
||||||
if (wl == NULL)
|
|
||||||
return (-1);
|
|
||||||
do {
|
|
||||||
wl = winlink_next(wl);
|
|
||||||
if (wl == NULL)
|
|
||||||
wl = RB_MIN(winlinks, &s->windows);
|
|
||||||
if (!alert || (wl->flags & WINLINK_ALERTFLAGS))
|
|
||||||
return (active_select_window(c, s, wl));
|
|
||||||
} while (wl != active_get_effective_winlink(c, s));
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the previous window. */
|
|
||||||
int
|
|
||||||
active_previous_window(struct client *c, struct session *s, int alert)
|
|
||||||
{
|
|
||||||
struct winlink *wl;
|
|
||||||
|
|
||||||
wl = active_get_effective_winlink(c, s);
|
|
||||||
if (wl == NULL)
|
|
||||||
return (-1);
|
|
||||||
do {
|
|
||||||
wl = winlink_previous(wl);
|
|
||||||
if (wl == NULL)
|
|
||||||
wl = RB_MAX(winlinks, &s->windows);
|
|
||||||
if (!alert || (wl->flags & WINLINK_ALERTFLAGS))
|
|
||||||
return (active_select_window(c, s, wl));
|
|
||||||
} while (wl != active_get_effective_winlink(c, s));
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the last window. */
|
|
||||||
int
|
|
||||||
active_last_window(struct client *c, struct session *s)
|
|
||||||
{
|
|
||||||
struct active_window *aw;
|
|
||||||
struct winlink *wl;
|
|
||||||
u_int window;
|
|
||||||
|
|
||||||
aw = active_get(c, s);
|
|
||||||
if (aw == NULL)
|
|
||||||
return (session_last(s));
|
|
||||||
while (!TAILQ_EMPTY(&aw->lastw)) {
|
|
||||||
window = TAILQ_FIRST(&aw->lastw)->window;
|
|
||||||
|
|
||||||
wl = winlink_find_by_window_id(&s->windows, window);
|
|
||||||
if (wl != NULL)
|
|
||||||
return (active_select_window(c, s, wl));
|
|
||||||
active_stack_remove(&aw->lastw, window);
|
|
||||||
}
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove all state for a client. */
|
|
||||||
void
|
|
||||||
active_remove_client(struct client *c)
|
|
||||||
{
|
|
||||||
struct active_window *aw, *aw1;
|
|
||||||
|
|
||||||
RB_FOREACH_SAFE(aw, active_windows, &active_windows, aw1) {
|
|
||||||
if (aw->client == c)
|
|
||||||
active_free(aw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove all state for a session. */
|
|
||||||
void
|
|
||||||
active_remove_session(struct session *s)
|
|
||||||
{
|
|
||||||
struct active_window *aw, *aw1;
|
|
||||||
|
|
||||||
RB_FOREACH_SAFE(aw, active_windows, &active_windows, aw1) {
|
|
||||||
if (aw->session == s)
|
|
||||||
active_free(aw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove a window from all local state. */
|
|
||||||
void
|
|
||||||
active_remove_window(struct window *w)
|
|
||||||
{
|
|
||||||
struct active_window *aw;
|
|
||||||
|
|
||||||
RB_FOREACH(aw, active_windows, &active_windows) {
|
|
||||||
active_stack_remove(&aw->lastw, w->id);
|
|
||||||
if (aw->window == w->id && aw->session->curw != NULL)
|
|
||||||
aw->window = aw->session->curw->window->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return if this winlink is the effective winlink. */
|
|
||||||
int
|
|
||||||
active_is_effective_window(struct client *c, struct session *s,
|
|
||||||
struct winlink *wl)
|
|
||||||
{
|
|
||||||
return (wl != NULL && wl == active_get_effective_winlink(c, s));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return if this winlink is the last effective winlink. */
|
|
||||||
int
|
|
||||||
active_is_last_window(struct client *c, struct session *s, struct winlink *wl)
|
|
||||||
{
|
|
||||||
struct active_window *aw;
|
|
||||||
struct active_window_entry *awe;
|
|
||||||
|
|
||||||
if (wl == NULL)
|
|
||||||
return (0);
|
|
||||||
aw = active_get(c, s);
|
|
||||||
if (aw == NULL)
|
|
||||||
return (wl == TAILQ_FIRST(&s->lastw));
|
|
||||||
TAILQ_FOREACH(awe, &aw->lastw, entry) {
|
|
||||||
if (winlink_find_by_window_id(&s->windows, awe->window) == NULL)
|
|
||||||
continue;
|
|
||||||
return (wl->window->id == awe->window);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
10
alerts.c
10
alerts.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: alerts.c,v 1.35 2026/07/10 13:38:45 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -205,7 +205,7 @@ alerts_check_bell(struct window *w)
|
|||||||
}
|
}
|
||||||
if (!alerts_action_applies(wl, "bell-action"))
|
if (!alerts_action_applies(wl, "bell-action"))
|
||||||
continue;
|
continue;
|
||||||
events_fire_winlink("alert-bell", wl);
|
notify_winlink("alert-bell", wl);
|
||||||
|
|
||||||
if (s->flags & SESSION_ALERTED)
|
if (s->flags & SESSION_ALERTED)
|
||||||
continue;
|
continue;
|
||||||
@@ -241,7 +241,7 @@ alerts_check_activity(struct window *w)
|
|||||||
}
|
}
|
||||||
if (!alerts_action_applies(wl, "activity-action"))
|
if (!alerts_action_applies(wl, "activity-action"))
|
||||||
continue;
|
continue;
|
||||||
events_fire_winlink("alert-activity", wl);
|
notify_winlink("alert-activity", wl);
|
||||||
|
|
||||||
if (s->flags & SESSION_ALERTED)
|
if (s->flags & SESSION_ALERTED)
|
||||||
continue;
|
continue;
|
||||||
@@ -277,7 +277,7 @@ alerts_check_silence(struct window *w)
|
|||||||
}
|
}
|
||||||
if (!alerts_action_applies(wl, "silence-action"))
|
if (!alerts_action_applies(wl, "silence-action"))
|
||||||
continue;
|
continue;
|
||||||
events_fire_winlink("alert-silence", wl);
|
notify_winlink("alert-silence", wl);
|
||||||
|
|
||||||
if (s->flags & SESSION_ALERTED)
|
if (s->flags & SESSION_ALERTED)
|
||||||
continue;
|
continue;
|
||||||
@@ -314,7 +314,7 @@ alerts_set_message(struct winlink *wl, const char *type, const char *option)
|
|||||||
tty_putcode(&c->tty, TTYC_BEL);
|
tty_putcode(&c->tty, TTYC_BEL);
|
||||||
if (visual == VISUAL_OFF)
|
if (visual == VISUAL_OFF)
|
||||||
continue;
|
continue;
|
||||||
if (active_get_effective_winlink(c, c->session) == wl) {
|
if (c->session->curw == wl) {
|
||||||
status_message_set(c, -1, 1, 0, 0,
|
status_message_set(c, -1, 1, 0, 0,
|
||||||
"%s in current window", type);
|
"%s in current window", type);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: arguments.c,v 1.67 2026/08/25 06:04:33 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -762,6 +762,8 @@ args_make_commands_now(struct cmd *self, struct cmdq_item *item, u_int idx,
|
|||||||
cmdq_error(item, "%s", error);
|
cmdq_error(item, "%s", error);
|
||||||
free(error);
|
free(error);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
cmdlist->references++;
|
||||||
args_make_commands_free(state);
|
args_make_commands_free(state);
|
||||||
return (cmdlist);
|
return (cmdlist);
|
||||||
}
|
}
|
||||||
@@ -825,10 +827,8 @@ args_make_commands(struct args_command_state *state, int argc, char **argv,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (state->cmdlist != NULL) {
|
if (state->cmdlist != NULL) {
|
||||||
if (argc == 0) {
|
if (argc == 0)
|
||||||
state->cmdlist->references++;
|
|
||||||
return (state->cmdlist);
|
return (state->cmdlist);
|
||||||
}
|
|
||||||
return (cmd_list_copy(state->cmdlist, argc, argv));
|
return (cmd_list_copy(state->cmdlist, argc, argv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: attributes.c,v 1.13 2026/07/02 08:51:05 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
|
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
|
||||||
|
|||||||
19
cfg.c
19
cfg.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cfg.c,v 1.91 2026/08/03 13:38:42 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -223,15 +223,13 @@ cfg_print_causes(struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct client *c = cmdq_get_client(item);
|
struct client *c = cmdq_get_client(item);
|
||||||
u_int i;
|
u_int i;
|
||||||
char *cause;
|
|
||||||
|
|
||||||
for (i = 0; i < cfg_ncauses; i++) {
|
for (i = 0; i < cfg_ncauses; i++) {
|
||||||
cause = cfg_causes[i];
|
|
||||||
if (c != NULL && (c->flags & CLIENT_CONTROL))
|
if (c != NULL && (c->flags & CLIENT_CONTROL))
|
||||||
control_notify_write(c, "%%config-error %s", cause);
|
control_write(c, "%%config-error %s", cfg_causes[i]);
|
||||||
else
|
else
|
||||||
cmdq_print(item, "%s", cause);
|
cmdq_print(item, "%s", cfg_causes[i]);
|
||||||
free(cause);
|
free(cfg_causes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(cfg_causes);
|
free(cfg_causes);
|
||||||
@@ -246,16 +244,14 @@ cfg_show_causes(struct session *s)
|
|||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct window_mode_entry *wme;
|
struct window_mode_entry *wme;
|
||||||
u_int i;
|
u_int i;
|
||||||
char *cause;
|
|
||||||
|
|
||||||
if (cfg_ncauses == 0)
|
if (cfg_ncauses == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c != NULL && (c->flags & CLIENT_CONTROL)) {
|
if (c != NULL && (c->flags & CLIENT_CONTROL)) {
|
||||||
for (i = 0; i < cfg_ncauses; i++) {
|
for (i = 0; i < cfg_ncauses; i++) {
|
||||||
cause = cfg_causes[i];
|
control_write(c, "%%config-error %s", cfg_causes[i]);
|
||||||
control_notify_write(c, "%%config-error %s", cause);
|
free(cfg_causes[i]);
|
||||||
free(cause);
|
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -272,8 +268,7 @@ cfg_show_causes(struct session *s)
|
|||||||
|
|
||||||
wme = TAILQ_FIRST(&wp->modes);
|
wme = TAILQ_FIRST(&wp->modes);
|
||||||
if (wme == NULL || wme->mode != &window_view_mode)
|
if (wme == NULL || wme->mode != &window_view_mode)
|
||||||
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL,
|
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL);
|
||||||
NULL);
|
|
||||||
for (i = 0; i < cfg_ncauses; i++) {
|
for (i = 0; i < cfg_ncauses; i++) {
|
||||||
window_copy_add(wp, 0, "%s", cfg_causes[i]);
|
window_copy_add(wp, 0, "%s", cfg_causes[i]);
|
||||||
free(cfg_causes[i]);
|
free(cfg_causes[i]);
|
||||||
|
|||||||
37
client.c
37
client.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: client.c,v 1.168 2026/08/17 20:14:31 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -239,8 +239,9 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
|||||||
pid_t ppid;
|
pid_t ppid;
|
||||||
enum msgtype msg;
|
enum msgtype msg;
|
||||||
struct termios tio, saved_tio;
|
struct termios tio, saved_tio;
|
||||||
size_t size;
|
size_t size, linesize = 0;
|
||||||
char **caps = NULL, *cause;
|
ssize_t linelen;
|
||||||
|
char *line = NULL, **caps = NULL, *cause;
|
||||||
u_int ncaps = 0;
|
u_int ncaps = 0;
|
||||||
struct args_value *values;
|
struct args_value *values;
|
||||||
|
|
||||||
@@ -276,7 +277,7 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
|||||||
proc_set_signals(client_proc, client_signal);
|
proc_set_signals(client_proc, client_signal);
|
||||||
|
|
||||||
/* Save the flags. */
|
/* Save the flags. */
|
||||||
client_flags = flags|CLIENT_WRITE_ACK;
|
client_flags = flags;
|
||||||
log_debug("flags are %#llx", (unsigned long long)client_flags);
|
log_debug("flags are %#llx", (unsigned long long)client_flags);
|
||||||
|
|
||||||
/* Initialize the client socket and start the server. */
|
/* Initialize the client socket and start the server. */
|
||||||
@@ -406,6 +407,11 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
|||||||
client_exec(client_execshell, client_execcmd);
|
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. */
|
/* Print the exit message, if any, and exit. */
|
||||||
if (client_attached) {
|
if (client_attached) {
|
||||||
if (client_exitreason != CLIENT_EXIT_NONE)
|
if (client_exitreason != CLIENT_EXIT_NONE)
|
||||||
@@ -420,8 +426,15 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
|||||||
else
|
else
|
||||||
printf("%%exit\n");
|
printf("%%exit\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
if (client_flags & CLIENT_CONTROL_WAITEXIT)
|
if (client_flags & CLIENT_CONTROL_WAITEXIT) {
|
||||||
control_wait_exit(STDIN_FILENO);
|
setvbuf(stdin, NULL, _IOLBF, 0);
|
||||||
|
for (;;) {
|
||||||
|
linelen = getline(&line, &linesize, stdin);
|
||||||
|
if (linelen <= 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
if (client_flags & CLIENT_CONTROLCONTROL) {
|
if (client_flags & CLIENT_CONTROLCONTROL) {
|
||||||
printf("\033\\");
|
printf("\033\\");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@@ -429,12 +442,6 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
|||||||
}
|
}
|
||||||
} else if (client_exitreason != CLIENT_EXIT_NONE)
|
} else if (client_exitreason != CLIENT_EXIT_NONE)
|
||||||
fprintf(stderr, "%s\n", client_exit_message());
|
fprintf(stderr, "%s\n", client_exit_message());
|
||||||
|
|
||||||
/* Restore the streams to blocking. */
|
|
||||||
setblocking(STDIN_FILENO, 1);
|
|
||||||
setblocking(STDOUT_FILENO, 1);
|
|
||||||
setblocking(STDERR_FILENO, 1);
|
|
||||||
|
|
||||||
return (client_exitval);
|
return (client_exitval);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,9 +719,6 @@ client_dispatch_wait(struct imsg *imsg)
|
|||||||
fprintf(stderr, "server version is too old for client\n");
|
fprintf(stderr, "server version is too old for client\n");
|
||||||
proc_exit(client_proc);
|
proc_exit(client_proc);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
log_debug("unknown message type %u", imsg->hdr.type);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -801,8 +805,5 @@ client_dispatch_attached(struct imsg *imsg)
|
|||||||
system(data);
|
system(data);
|
||||||
proc_send(client_peer, MSG_UNLOCK, -1, NULL, 0);
|
proc_send(client_peer, MSG_UNLOCK, -1, NULL, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
log_debug("unknown message type %u", imsg->hdr.type);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-attach-session.c,v 1.91 2026/07/10 13:38:45 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -93,7 +93,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
|||||||
if (wl != NULL) {
|
if (wl != NULL) {
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
window_set_active_pane(wp->window, wp, 1);
|
window_set_active_pane(wp->window, wp, 1);
|
||||||
active_select_window(c, s, wl);
|
session_set_current(s, wl);
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
||||||
else
|
else
|
||||||
@@ -163,7 +163,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
|||||||
|
|
||||||
if (~c->flags & CLIENT_CONTROL)
|
if (~c->flags & CLIENT_CONTROL)
|
||||||
proc_send(c->peer, MSG_READY, -1, NULL, 0);
|
proc_send(c->peer, MSG_READY, -1, NULL, 0);
|
||||||
events_fire_client("client-attached", c);
|
notify_client("client-attached", c);
|
||||||
c->flags |= CLIENT_ATTACHED;
|
c->flags |= CLIENT_ATTACHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-bind-key.c,v 1.47 2025/04/09 07:03:04 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-break-pane.c,v 1.76 2026/08/17 07:04:45 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -51,26 +51,32 @@ cmd_break_pane_float(struct cmdq_item *item, struct args *args,
|
|||||||
struct window *w, struct window_pane *wp)
|
struct window *w, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
struct layout_cell *lc = wp->layout_cell;
|
struct layout_cell *lc = wp->layout_cell;
|
||||||
|
u_int sx = lc->saved_sx, sy = lc->saved_sy;
|
||||||
|
int ox = lc->saved_xoff, oy = lc->saved_yoff;
|
||||||
char *cause = NULL;
|
char *cause = NULL;
|
||||||
enum pane_lines lines = window_get_pane_lines(w);
|
enum pane_lines lines = window_get_pane_lines(w);
|
||||||
struct layout_geometry *fg = &lc->fg;
|
|
||||||
|
|
||||||
if (window_pane_is_floating(wp)) {
|
if (window_pane_is_floating(wp)) {
|
||||||
cmdq_error(item, "pane is already floating");
|
cmdq_error(item, "pane is already floating");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
if (window_pane_is_hidden(wp)) {
|
||||||
|
cmdq_error(item, "can't float a hidden pane");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
if (w->flags & WINDOW_ZOOMED) {
|
if (w->flags & WINDOW_ZOOMED) {
|
||||||
cmdq_error(item, "can't float a pane while window is zoomed");
|
cmdq_error(item, "can't float a pane while window is zoomed");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layout_floating_args_parse(item, args, lines, w, fg, &cause) != 0) {
|
if (layout_floating_args_parse(item, args, lines, w, &sx, &sy, &ox, &oy,
|
||||||
|
&cause) != 0) {
|
||||||
cmdq_error(item, "failed to float pane: %s", cause);
|
cmdq_error(item, "failed to float pane: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
layout_remove_tile(w, lc);
|
layout_remove_tile(w, lc);
|
||||||
layout_set_size(lc, fg->sx, fg->sy, fg->xoff, fg->yoff);
|
layout_set_size(lc, sx, sy, ox, oy);
|
||||||
|
|
||||||
lc->flags |= LAYOUT_CELL_FLOATING;
|
lc->flags |= LAYOUT_CELL_FLOATING;
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||||
@@ -80,7 +86,7 @@ cmd_break_pane_float(struct cmdq_item *item, struct args *args,
|
|||||||
window_set_active_pane(w, wp, 1);
|
window_set_active_pane(w, wp, 1);
|
||||||
layout_fix_offsets(w);
|
layout_fix_offsets(w);
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
events_fire_window("window-layout-changed", w);
|
notify_window("window-layout-changed", w);
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
@@ -93,25 +99,16 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_find_state *current = cmdq_get_current(item);
|
struct cmd_find_state *current = cmdq_get_current(item);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct cmd_find_state *source = cmdq_get_source(item);
|
struct cmd_find_state *source = cmdq_get_source(item);
|
||||||
struct client *c = cmdq_get_client(item);
|
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
struct client *ac;
|
|
||||||
struct winlink *wl = source->wl;
|
struct winlink *wl = source->wl;
|
||||||
struct winlink *current_wl;
|
|
||||||
struct session *src_s = source->s;
|
struct session *src_s = source->s;
|
||||||
struct session *dst_s = target->s;
|
struct session *dst_s = target->s;
|
||||||
struct window_pane *wp = source->wp;
|
struct window_pane *wp = source->wp;
|
||||||
struct window *w = wl->window, *old_w = w;
|
struct window *w = wl->window;
|
||||||
char *cause, *cp;
|
char *newname, *cause, *cp;
|
||||||
int idx = target->idx, before, old_idx = wl->idx;
|
int idx = target->idx, before;
|
||||||
int detached, local;
|
|
||||||
const char *template, *name = args_get(args, 'n');
|
const char *template, *name = args_get(args, 'n');
|
||||||
|
|
||||||
if (wp == w->modal) {
|
|
||||||
cmdq_error(item, "pane is modal");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args_has(args, 'W'))
|
if (args_has(args, 'W'))
|
||||||
return (cmd_break_pane_float(item, args, w, wp));
|
return (cmd_break_pane_float(item, args, w, wp));
|
||||||
|
|
||||||
@@ -121,18 +118,11 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
before = args_has(args, 'b');
|
before = args_has(args, 'b');
|
||||||
ac = tc;
|
|
||||||
if (ac == NULL || ac->session != dst_s)
|
|
||||||
ac = c;
|
|
||||||
detached = args_has(args, 'd');
|
|
||||||
local = (!detached && active_is_local_window(ac, dst_s));
|
|
||||||
if (args_has(args, 'a') || before) {
|
if (args_has(args, 'a') || before) {
|
||||||
if (target->wl != NULL)
|
if (target->wl != NULL)
|
||||||
idx = winlink_shuffle_up(dst_s, target->wl, before);
|
idx = winlink_shuffle_up(dst_s, target->wl, before);
|
||||||
else {
|
else
|
||||||
current_wl = active_get_effective_winlink(ac, dst_s);
|
idx = winlink_shuffle_up(dst_s, dst_s->curw, before);
|
||||||
idx = winlink_shuffle_up(dst_s, current_wl, before);
|
|
||||||
}
|
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
@@ -140,7 +130,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (window_count_panes(w, 1) == 1) {
|
if (window_count_panes(w, 1) == 1) {
|
||||||
if (server_link_window(src_s, wl, dst_s, idx, 0,
|
if (server_link_window(src_s, wl, dst_s, idx, 0,
|
||||||
!detached && !local, &cause) != 0) {
|
!args_has(args, 'd'), &cause) != 0) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
@@ -153,14 +143,6 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
wl = winlink_find_by_window(&dst_s->windows, w);
|
wl = winlink_find_by_window(&dst_s->windows, w);
|
||||||
if (wl == NULL)
|
if (wl == NULL)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
if (local) {
|
|
||||||
active_select_window(ac, dst_s, wl);
|
|
||||||
if (ac != NULL && ac->session == dst_s)
|
|
||||||
cmd_find_from_client(current, ac, 0);
|
|
||||||
if (ac != NULL && ac->session == dst_s)
|
|
||||||
server_redraw_client(ac);
|
|
||||||
}
|
|
||||||
window_fire_pane_moved(wp, old_w, old_idx, w, wl->idx);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
|
if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
|
||||||
@@ -175,7 +157,6 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
layout_close_pane(wp);
|
layout_close_pane(wp);
|
||||||
|
|
||||||
w = wp->window = window_create(w->sx, w->sy, w->xpixel, w->ypixel);
|
w = wp->window = window_create(w->sx, w->sy, w->xpixel, w->ypixel);
|
||||||
window_add_ref(w, __func__);
|
|
||||||
options_set_parent(wp->options, w->options);
|
options_set_parent(wp->options, w->options);
|
||||||
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
|
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
|
||||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||||
@@ -183,37 +164,25 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
w->active = wp;
|
w->active = wp;
|
||||||
w->latest = tc;
|
w->latest = tc;
|
||||||
|
|
||||||
free(w->name);
|
if (name == NULL) {
|
||||||
if (name == NULL)
|
newname = default_window_name(w);
|
||||||
w->name = default_window_name(w);
|
window_set_name(w, newname, 0);
|
||||||
else {
|
free(newname);
|
||||||
w->name = clean_name(name, 0);
|
} else {
|
||||||
|
window_set_name(w, name, 0);
|
||||||
options_set_number(w->options, "automatic-rename", 0);
|
options_set_number(w->options, "automatic-rename", 0);
|
||||||
}
|
}
|
||||||
window_set_fill_cells(w);
|
|
||||||
|
|
||||||
if (idx == -1)
|
|
||||||
idx = -1 - options_get_number(dst_s->options, "base-index");
|
|
||||||
wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
|
|
||||||
|
|
||||||
layout_init(w, wp);
|
layout_init(w, wp);
|
||||||
wp->flags |= PANE_CHANGED;
|
wp->flags |= PANE_CHANGED;
|
||||||
colour_palette_from_option(&wp->palette, wp->options);
|
colour_palette_from_option(&wp->palette, wp->options);
|
||||||
|
|
||||||
window_remove_ref(w, __func__);
|
if (idx == -1)
|
||||||
events_fire_window("window-created", w);
|
idx = -1 - options_get_number(dst_s->options, "base-index");
|
||||||
window_fire_pane_moved(wp, old_w, old_idx, w, wl->idx);
|
wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
|
||||||
if (!detached) {
|
if (!args_has(args, 'd')) {
|
||||||
if (local)
|
session_select(dst_s, wl->idx);
|
||||||
active_select_window(ac, dst_s, wl);
|
cmd_find_from_session(current, dst_s, 0);
|
||||||
else
|
|
||||||
session_select(dst_s, wl->idx);
|
|
||||||
if (local && ac != NULL && ac->session == dst_s)
|
|
||||||
cmd_find_from_client(current, ac, 0);
|
|
||||||
else
|
|
||||||
cmd_find_from_session(current, dst_s, 0);
|
|
||||||
if (local && ac != NULL && ac->session == dst_s)
|
|
||||||
server_redraw_client(ac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server_redraw_session(src_s);
|
server_redraw_session(src_s);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-capture-pane.c,v 1.68 2026/07/20 11:16:33 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
|
* Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
|
||||||
@@ -134,7 +134,6 @@ cmd_capture_pane_grid(struct window_pane *wp, size_t *len)
|
|||||||
struct screen *s = &wp->base;
|
struct screen *s = &wp->base;
|
||||||
struct grid *gd = s->grid;
|
struct grid *gd = s->grid;
|
||||||
struct grid_line *gl;
|
struct grid_line *gl;
|
||||||
struct osc133_data *od;
|
|
||||||
char *buf = xstrdup(""), *line;
|
char *buf = xstrdup(""), *line;
|
||||||
char p[11];
|
char p[11];
|
||||||
u_int yy, xx, total = gd->hsize + gd->sy;
|
u_int yy, xx, total = gd->hsize + gd->sy;
|
||||||
@@ -150,20 +149,9 @@ cmd_capture_pane_grid(struct window_pane *wp, size_t *len)
|
|||||||
snprintf(p, sizeof p, "-");
|
snprintf(p, sizeof p, "-");
|
||||||
else
|
else
|
||||||
snprintf(p, sizeof p, "%u", yy - gd->hsize);
|
snprintf(p, sizeof p, "%u", yy - gd->hsize);
|
||||||
od = &gl->osc133_data;
|
xasprintf(&line, "\tL %u (%s) flags=%s[%x] %u/%u\n", yy,
|
||||||
if (gl->flags & GRID_LINE_OSC133_FLAGS) {
|
p, grid_line_flags_string(gl->flags), gl->flags,
|
||||||
xasprintf(&line, "\tL %u (%s) flags=%s[%x] "
|
gl->cellused, gl->cellsize);
|
||||||
"%u/%u osc133=%u,%u,%u,%u,%u\n", yy, p,
|
|
||||||
grid_line_flags_string(gl->flags), gl->flags,
|
|
||||||
gl->cellused, gl->cellsize, od->prompt_col,
|
|
||||||
od->cmd_col, od->out_start_col,
|
|
||||||
od->out_end_col, od->exit_status);
|
|
||||||
} else {
|
|
||||||
xasprintf(&line, "\tL %u (%s) flags=%s[%x] "
|
|
||||||
"%u/%u\n", yy, p,
|
|
||||||
grid_line_flags_string(gl->flags), gl->flags,
|
|
||||||
gl->cellused, gl->cellsize);
|
|
||||||
}
|
|
||||||
buf = cmd_capture_pane_append(buf, len, line, strlen(line));
|
buf = cmd_capture_pane_append(buf, len, line, strlen(line));
|
||||||
free(line);
|
free(line);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-choose-tree.c,v 1.58 2026/07/14 17:17:17 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
|
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
|
||||||
@@ -97,21 +97,6 @@ const struct cmd_entry cmd_switch_mode_entry = {
|
|||||||
.exec = cmd_choose_tree_exec
|
.exec = cmd_choose_tree_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct cmd_entry cmd_display_panes_entry = {
|
|
||||||
.name = "display-panes",
|
|
||||||
.alias = "displayp",
|
|
||||||
|
|
||||||
.args = { "d:kNs:t:Z", 0, 1, cmd_choose_tree_args_parse },
|
|
||||||
.usage = "[-kNZ] [-d duration] [-s source-window] "
|
|
||||||
CMD_TARGET_PANE_USAGE " [template]",
|
|
||||||
|
|
||||||
.source = { 's', CMD_FIND_WINDOW, 0 },
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
|
||||||
.exec = cmd_choose_tree_exec
|
|
||||||
};
|
|
||||||
|
|
||||||
static enum args_parse_type
|
static enum args_parse_type
|
||||||
cmd_choose_tree_args_parse(__unused struct args *args, __unused u_int idx,
|
cmd_choose_tree_args_parse(__unused struct args *args, __unused u_int idx,
|
||||||
__unused char **cause)
|
__unused char **cause)
|
||||||
@@ -146,11 +131,9 @@ cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
mode = &window_customize_mode;
|
mode = &window_customize_mode;
|
||||||
else if (cmd_get_entry(self) == &cmd_switch_mode_entry)
|
else if (cmd_get_entry(self) == &cmd_switch_mode_entry)
|
||||||
mode = &window_switch_mode;
|
mode = &window_switch_mode;
|
||||||
else if (cmd_get_entry(self) == &cmd_display_panes_entry)
|
|
||||||
mode = &window_panes_mode;
|
|
||||||
else
|
else
|
||||||
mode = &window_tree_mode;
|
mode = &window_tree_mode;
|
||||||
|
|
||||||
window_pane_set_mode(wp, NULL, mode, item, target, args);
|
window_pane_set_mode(wp, NULL, mode, target, args);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-command-prompt.c,v 1.76 2026/08/25 06:04:33 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -242,11 +242,9 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
|
|||||||
} else if (item == NULL) {
|
} else if (item == NULL) {
|
||||||
new_item = cmdq_get_command(cmdlist, NULL);
|
new_item = cmdq_get_command(cmdlist, NULL);
|
||||||
cmdq_append(c, new_item);
|
cmdq_append(c, new_item);
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
} else {
|
} else {
|
||||||
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
||||||
cmdq_insert_after(item, new_item);
|
cmdq_insert_after(item, new_item);
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
}
|
}
|
||||||
cmd_free_argv(argc, argv);
|
cmd_free_argv(argc, argv);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-confirm-before.c,v 1.61 2026/06/24 10:55:39 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-copy-mode.c,v 1.54 2026/07/14 17:17:17 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -30,8 +30,8 @@ const struct cmd_entry cmd_copy_mode_entry = {
|
|||||||
.name = "copy-mode",
|
.name = "copy-mode",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "dekHMqSs:t:u", 0, 0, NULL },
|
.args = { "deHMqSs:t:u", 0, 0, NULL },
|
||||||
.usage = "[-dekHMqSu] [-s src-pane] " CMD_TARGET_PANE_USAGE,
|
.usage = "[-deHMqSu] [-s src-pane] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.source = { 's', CMD_FIND_PANE, 0 },
|
.source = { 's', CMD_FIND_PANE, 0 },
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
@@ -79,8 +79,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_clock_mode_entry) {
|
if (cmd_get_entry(self) == &cmd_clock_mode_entry) {
|
||||||
window_pane_set_mode(wp, NULL, &window_clock_mode, item, NULL,
|
window_pane_set_mode(wp, NULL, &window_clock_mode, NULL, NULL);
|
||||||
NULL);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,8 +90,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
line_numbers = 1;
|
line_numbers = 1;
|
||||||
if (event != NULL && KEYC_IS_MOUSE(event->key))
|
if (event != NULL && KEYC_IS_MOUSE(event->key))
|
||||||
line_numbers = 0;
|
line_numbers = 0;
|
||||||
if (!window_pane_set_mode(wp, swp, &window_copy_mode, item, NULL,
|
if (!window_pane_set_mode(wp, swp, &window_copy_mode, NULL, args)) {
|
||||||
args)) {
|
|
||||||
window_copy_set_line_numbers(wp, line_numbers);
|
window_copy_set_line_numbers(wp, line_numbers);
|
||||||
if (args_has(args, 'M'))
|
if (args_has(args, 'M'))
|
||||||
window_copy_start_drag(c, &event->m);
|
window_copy_start_drag(c, &event->m);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-detach-client.c,v 1.39 2026/05/22 15:22:43 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-display-menu.c,v 1.53 2026/08/31 07:46:55 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -92,7 +92,7 @@ cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
cmd_display_menu_get_popup_pos(struct client *tc, struct cmdq_item *item,
|
cmd_display_menu_get_pos(struct client *tc, struct cmdq_item *item,
|
||||||
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
||||||
{
|
{
|
||||||
struct tty *tty = &tc->tty;
|
struct tty *tty = &tc->tty;
|
||||||
@@ -126,10 +126,6 @@ cmd_display_menu_get_popup_pos(struct client *tc, struct cmdq_item *item,
|
|||||||
format_add(ft, "popup_mouse_y", "%u", event->m.y);
|
format_add(ft, "popup_mouse_y", "%u", event->m.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Position of the previous menu, for -x/-y L. */
|
|
||||||
format_add(ft, "popup_last_x", "%u", target->w->menu_last_px);
|
|
||||||
format_add(ft, "popup_last_y", "%u", target->w->menu_last_py + h);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there are any status lines, add this window position and the
|
* If there are any status lines, add this window position and the
|
||||||
* status line position.
|
* status line position.
|
||||||
@@ -242,8 +238,6 @@ cmd_display_menu_get_popup_pos(struct client *tc, struct cmdq_item *item,
|
|||||||
xp = "#{popup_pane_left}";
|
xp = "#{popup_pane_left}";
|
||||||
else if (strcmp(xp, "M") == 0)
|
else if (strcmp(xp, "M") == 0)
|
||||||
xp = "#{popup_mouse_centre_x}";
|
xp = "#{popup_mouse_centre_x}";
|
||||||
else if (strcmp(xp, "L") == 0)
|
|
||||||
xp = "#{popup_last_x}";
|
|
||||||
else if (strcmp(xp, "W") == 0)
|
else if (strcmp(xp, "W") == 0)
|
||||||
xp = "#{popup_window_status_line_x}";
|
xp = "#{popup_window_status_line_x}";
|
||||||
p = format_expand(ft, xp);
|
p = format_expand(ft, xp);
|
||||||
@@ -264,8 +258,6 @@ cmd_display_menu_get_popup_pos(struct client *tc, struct cmdq_item *item,
|
|||||||
yp = "#{popup_pane_bottom}";
|
yp = "#{popup_pane_bottom}";
|
||||||
else if (strcmp(yp, "M") == 0)
|
else if (strcmp(yp, "M") == 0)
|
||||||
yp = "#{popup_mouse_top}";
|
yp = "#{popup_mouse_top}";
|
||||||
else if (strcmp(yp, "L") == 0)
|
|
||||||
yp = "#{popup_last_y}";
|
|
||||||
else if (strcmp(yp, "S") == 0)
|
else if (strcmp(yp, "S") == 0)
|
||||||
yp = "#{popup_status_line_y}";
|
yp = "#{popup_status_line_y}";
|
||||||
else if (strcmp(yp, "W") == 0)
|
else if (strcmp(yp, "W") == 0)
|
||||||
@@ -288,184 +280,6 @@ cmd_display_menu_get_popup_pos(struct client *tc, struct cmdq_item *item,
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
cmd_display_menu_get_menu_pos(struct client *tc, struct cmdq_item *item,
|
|
||||||
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
|
|
||||||
{
|
|
||||||
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 *window = target->w;
|
|
||||||
struct window_pane *wp = target->wp;
|
|
||||||
struct style_ranges *ranges = NULL;
|
|
||||||
struct style_range *sr = NULL;
|
|
||||||
const char *xp, *yp;
|
|
||||||
char *p;
|
|
||||||
u_int line, ox, oy, sx, sy, lines, position;
|
|
||||||
long n, max_x, max_y, mouse_x = 0, mouse_y = 0;
|
|
||||||
struct format_tree *ft;
|
|
||||||
|
|
||||||
max_x = window->sx > w ? window->sx - w : 0;
|
|
||||||
max_y = window->sy > h ? window->sy - h : 0;
|
|
||||||
|
|
||||||
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy);
|
|
||||||
|
|
||||||
ft = format_create_from_target(item);
|
|
||||||
if (event->m.valid) {
|
|
||||||
mouse_x = event->m.x + ox;
|
|
||||||
if (event->m.statusat == 0) {
|
|
||||||
if (event->m.y >= event->m.statuslines)
|
|
||||||
mouse_y = event->m.y - event->m.statuslines + oy;
|
|
||||||
else
|
|
||||||
mouse_y = oy;
|
|
||||||
} else if (event->m.statusat > 0 &&
|
|
||||||
event->m.y >= (u_int)event->m.statusat) {
|
|
||||||
mouse_y = oy + sy - 1;
|
|
||||||
} else
|
|
||||||
mouse_y = event->m.y + oy;
|
|
||||||
format_add(ft, "popup_mouse_x", "%ld", mouse_x);
|
|
||||||
format_add(ft, "popup_mouse_y", "%ld", mouse_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
format_add(ft, "popup_last_x", "%u", window->menu_last_px);
|
|
||||||
format_add(ft, "popup_last_y", "%u", window->menu_last_py + h);
|
|
||||||
|
|
||||||
lines = status_line_size(tc);
|
|
||||||
position = options_get_number(s->options, "status-position");
|
|
||||||
if (status_at_line(tc) != -1 && lines != 0) {
|
|
||||||
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 + ox);
|
|
||||||
if (position == 0) {
|
|
||||||
format_add(ft, "popup_window_status_line_y",
|
|
||||||
"%u", h);
|
|
||||||
} else {
|
|
||||||
format_add(ft, "popup_window_status_line_y",
|
|
||||||
"%u", window->sy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (position == 0)
|
|
||||||
format_add(ft, "popup_status_line_y", "%u", h);
|
|
||||||
else
|
|
||||||
format_add(ft, "popup_status_line_y", "%u", window->sy);
|
|
||||||
}
|
|
||||||
|
|
||||||
format_add(ft, "popup_width", "%u", w);
|
|
||||||
format_add(ft, "popup_height", "%u", h);
|
|
||||||
|
|
||||||
n = ((long)window->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 = ((long)window->sy - 1) / 2 + h / 2;
|
|
||||||
if (n >= window->sy)
|
|
||||||
format_add(ft, "popup_centre_y", "%ld", max_y);
|
|
||||||
else
|
|
||||||
format_add(ft, "popup_centre_y", "%ld", n);
|
|
||||||
|
|
||||||
if (event->m.valid) {
|
|
||||||
n = mouse_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 = mouse_y - h / 2;
|
|
||||||
if (n + h >= window->sy)
|
|
||||||
format_add(ft, "popup_mouse_centre_y", "%ld", max_y);
|
|
||||||
else
|
|
||||||
format_add(ft, "popup_mouse_centre_y", "%ld", n);
|
|
||||||
n = mouse_y + h;
|
|
||||||
if (n >= window->sy)
|
|
||||||
format_add(ft, "popup_mouse_top", "%u", window->sy - 1);
|
|
||||||
else
|
|
||||||
format_add(ft, "popup_mouse_top", "%ld", n);
|
|
||||||
n = mouse_y - h;
|
|
||||||
if (n < 0)
|
|
||||||
format_add(ft, "popup_mouse_bottom", "%u", 0);
|
|
||||||
else
|
|
||||||
format_add(ft, "popup_mouse_bottom", "%ld", n);
|
|
||||||
}
|
|
||||||
|
|
||||||
n = wp->yoff + h;
|
|
||||||
if (n >= window->sy)
|
|
||||||
format_add(ft, "popup_pane_top", "%ld", max_y);
|
|
||||||
else
|
|
||||||
format_add(ft, "popup_pane_top", "%ld", n);
|
|
||||||
format_add(ft, "popup_pane_bottom", "%u", wp->yoff + wp->sy);
|
|
||||||
format_add(ft, "popup_pane_left", "%u", wp->xoff);
|
|
||||||
n = (long)wp->xoff + wp->sx - w;
|
|
||||||
if (n < 0)
|
|
||||||
format_add(ft, "popup_pane_right", "%u", 0);
|
|
||||||
else
|
|
||||||
format_add(ft, "popup_pane_right", "%ld", n);
|
|
||||||
|
|
||||||
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, "L") == 0)
|
|
||||||
xp = "#{popup_last_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 < 0)
|
|
||||||
n = 0;
|
|
||||||
if (n > max_x)
|
|
||||||
n = max_x;
|
|
||||||
*px = n;
|
|
||||||
log_debug("%s: -x: %s = %s = %u (-w %u)", __func__, xp, p, *px, w);
|
|
||||||
free(p);
|
|
||||||
|
|
||||||
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, "L") == 0)
|
|
||||||
yp = "#{popup_last_y}";
|
|
||||||
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 < 0)
|
|
||||||
n = 0;
|
|
||||||
if (n > max_y)
|
|
||||||
n = max_y;
|
|
||||||
*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
|
static enum cmd_retval
|
||||||
cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
@@ -483,9 +297,13 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
char *title, *cause = NULL;
|
char *title, *cause = NULL;
|
||||||
int flags = 0, starting_choice = 0;
|
int flags = 0, starting_choice = 0;
|
||||||
u_int px, py, i, count = args_count(args);
|
u_int px, py, i, count = args_count(args);
|
||||||
struct options *o = target->w->options;
|
struct options *o = target->s->curw->window->options;
|
||||||
struct options_entry *oe;
|
struct options_entry *oe;
|
||||||
|
|
||||||
|
|
||||||
|
if (tc->overlay_draw != NULL)
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
if (args_has(args, 'C')) {
|
if (args_has(args, 'C')) {
|
||||||
if (strcmp(args_get(args, 'C'), "-") == 0)
|
if (strcmp(args_get(args, 'C'), "-") == 0)
|
||||||
starting_choice = -1;
|
starting_choice = -1;
|
||||||
@@ -531,8 +349,8 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
if (menu->count == 0)
|
if (menu->count == 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (!cmd_display_menu_get_menu_pos(tc, item, args, &px, &py,
|
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, menu->width + 4,
|
||||||
menu->width + 4, menu->count + 2))
|
menu->count + 2))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
value = args_get(args, 'b');
|
value = args_get(args, 'b');
|
||||||
@@ -553,7 +371,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines,
|
if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines,
|
||||||
style, selected_style, border_style, target, NULL, NULL) != 0)
|
style, selected_style, border_style, target, NULL, NULL) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_WAIT);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
menu_free(menu);
|
menu_free(menu);
|
||||||
@@ -584,15 +402,13 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
u_int px, py, w, h, count = args_count(args);
|
u_int px, py, w, h, count = args_count(args);
|
||||||
struct args_value *av;
|
struct args_value *av;
|
||||||
struct environ *env = NULL;
|
struct environ *env = NULL;
|
||||||
struct options *o = target->w->options;
|
struct options *o = s->curw->window->options;
|
||||||
struct options_entry *oe;
|
struct options_entry *oe;
|
||||||
|
|
||||||
if (args_has(args, 'C')) {
|
if (args_has(args, 'C')) {
|
||||||
server_client_clear_overlay(tc);
|
server_client_clear_overlay(tc);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
if (tc->flags & CLIENT_CONTROL)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
if (!modify && tc->overlay_draw != NULL)
|
if (!modify && tc->overlay_draw != NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
@@ -621,8 +437,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
w = tty->sx;
|
w = tty->sx;
|
||||||
if (h > tty->sy)
|
if (h > tty->sy)
|
||||||
h = tty->sy;
|
h = tty->sy;
|
||||||
if (!cmd_display_menu_get_popup_pos(tc, item, args, &px, &py,
|
if (!cmd_display_menu_get_pos(tc, item, args, &px, &py, w, h))
|
||||||
w, h))
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
value = args_get(args, 'd');
|
value = args_get(args, 'd');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-display-message.c,v 1.65 2026/02/23 08:46:57 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
|
|||||||
393
cmd-display-panes.c
Normal file
393
cmd-display-panes.c
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_display_panes_entry = {
|
||||||
|
.name = "display-panes",
|
||||||
|
.alias = "displayp",
|
||||||
|
|
||||||
|
.args = { "bd:Nt:", 0, 1, cmd_display_panes_args_parse },
|
||||||
|
.usage = "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]",
|
||||||
|
|
||||||
|
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
|
||||||
|
.exec = cmd_display_panes_exec
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmd_display_panes_data {
|
||||||
|
struct cmdq_item *item;
|
||||||
|
struct args_command_state *state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmd_display_panes_ctx {
|
||||||
|
struct client *c;
|
||||||
|
int ox;
|
||||||
|
int oy;
|
||||||
|
u_int sx;
|
||||||
|
u_int sy;
|
||||||
|
u_int statuslines;
|
||||||
|
int statustop;
|
||||||
|
};
|
||||||
|
|
||||||
|
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_put(struct cmd_display_panes_ctx *ctx,
|
||||||
|
struct window_pane *wp, u_int cx, u_int cy, const char *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct client *c = ctx->c;
|
||||||
|
struct tty *tty = &c->tty;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
u_int i, j;
|
||||||
|
|
||||||
|
r = window_visible_ranges(wp, ctx->ox + cx, ctx->oy + cy, len, NULL);
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
for (j = ri->px; j < ri->px + ri->nx; j++) {
|
||||||
|
tty_cursor(tty, j - ctx->ox, cy);
|
||||||
|
tty_putn(tty, &buf[j - ri->px], 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_display_panes_draw_format(struct cmd_display_panes_ctx *ctx,
|
||||||
|
struct window_pane *wp, u_int xoff, u_int yoff, u_int sx,
|
||||||
|
const struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
struct client *c = ctx->c;
|
||||||
|
struct tty *tty = &c->tty;
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct screen *sc = wp->screen, screen;
|
||||||
|
struct screen_write_ctx sctx;
|
||||||
|
struct visible_ranges *r;
|
||||||
|
struct visible_range *ri;
|
||||||
|
const char *format;
|
||||||
|
char *expanded;
|
||||||
|
u_int i, px = ctx->ox + xoff;
|
||||||
|
|
||||||
|
format = options_get_string(s->options, "display-panes-format");
|
||||||
|
expanded = format_single(NULL, format, c, s, s->curw, wp);
|
||||||
|
|
||||||
|
screen_init(&screen, sx, 1, 0);
|
||||||
|
screen_write_start(&sctx, &screen);
|
||||||
|
screen_write_fast_copy(&sctx, sc, 0, sc->grid->hsize, sx, 1);
|
||||||
|
screen_write_cursormove(&sctx, 0, 0, 0);
|
||||||
|
format_draw(&sctx, gc, sx, expanded, NULL, 0);
|
||||||
|
screen_write_stop(&sctx);
|
||||||
|
free(expanded);
|
||||||
|
|
||||||
|
r = window_visible_ranges(wp, px, wp->yoff, sx, NULL);
|
||||||
|
for (i = 0; i < r->used; i++) {
|
||||||
|
ri = &r->ranges[i];
|
||||||
|
tty_draw_line(tty, &screen, ri->px - px, 0, ri->nx,
|
||||||
|
ri->px - ctx->ox, yoff, NULL);
|
||||||
|
}
|
||||||
|
screen_free(&screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_display_panes_draw_pane(struct cmd_display_panes_ctx *ctx,
|
||||||
|
struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct client *c = ctx->c;
|
||||||
|
struct tty *tty = &c->tty;
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct options *oo = s->options;
|
||||||
|
struct window *w = wp->window;
|
||||||
|
struct grid_cell fgc, bgc;
|
||||||
|
u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy;
|
||||||
|
u_int cx, cy;
|
||||||
|
const char *name;
|
||||||
|
struct format_tree *ft;
|
||||||
|
char buf[16], lbuf[16], *ptr;
|
||||||
|
size_t len, llen;
|
||||||
|
|
||||||
|
if (wp->xoff + (int)wp->sx <= ctx->ox ||
|
||||||
|
wp->xoff >= ctx->ox + (int)ctx->sx ||
|
||||||
|
wp->yoff + (int)wp->sy <= ctx->oy ||
|
||||||
|
wp->yoff >= ctx->oy + (int)ctx->sy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
|
||||||
|
/* All visible. */
|
||||||
|
xoff = wp->xoff - ctx->ox;
|
||||||
|
sx = wp->sx;
|
||||||
|
} else if (wp->xoff < ctx->ox &&
|
||||||
|
wp->xoff + wp->sx > ctx->ox + ctx->sx) {
|
||||||
|
/* Both left and right not visible. */
|
||||||
|
xoff = 0;
|
||||||
|
sx = ctx->sx;
|
||||||
|
} else if (wp->xoff < ctx->ox) {
|
||||||
|
/* Left not visible. */
|
||||||
|
xoff = 0;
|
||||||
|
sx = wp->sx - (ctx->ox - wp->xoff);
|
||||||
|
} else {
|
||||||
|
/* Right not visible. */
|
||||||
|
xoff = wp->xoff - ctx->ox;
|
||||||
|
sx = wp->sx - xoff;
|
||||||
|
}
|
||||||
|
if (wp->yoff >= ctx->oy && wp->yoff + wp->sy <= ctx->oy + ctx->sy) {
|
||||||
|
/* All visible. */
|
||||||
|
yoff = wp->yoff - ctx->oy;
|
||||||
|
sy = wp->sy;
|
||||||
|
} else if (wp->yoff < ctx->oy &&
|
||||||
|
wp->yoff + wp->sy > ctx->oy + ctx->sy) {
|
||||||
|
/* Both top and bottom not visible. */
|
||||||
|
yoff = 0;
|
||||||
|
sy = ctx->sy;
|
||||||
|
} else if (wp->yoff < ctx->oy) {
|
||||||
|
/* Top not visible. */
|
||||||
|
yoff = 0;
|
||||||
|
sy = wp->sy - (ctx->oy - wp->yoff);
|
||||||
|
} else {
|
||||||
|
/* Bottom not visible. */
|
||||||
|
yoff = wp->yoff - ctx->oy;
|
||||||
|
sy = wp->sy - yoff;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->statustop)
|
||||||
|
yoff += ctx->statuslines;
|
||||||
|
px = sx / 2;
|
||||||
|
py = sy / 2;
|
||||||
|
|
||||||
|
if (window_pane_index(wp, &pane) != 0)
|
||||||
|
fatalx("index not found");
|
||||||
|
len = xsnprintf(buf, sizeof buf, "%u", pane);
|
||||||
|
|
||||||
|
if (sx < len)
|
||||||
|
return;
|
||||||
|
if (w->active == wp)
|
||||||
|
name = "display-panes-active-colour";
|
||||||
|
else
|
||||||
|
name = "display-panes-colour";
|
||||||
|
ft = format_create_defaults(NULL, c, s, NULL, wp);
|
||||||
|
style_apply(&fgc, oo, name, ft);
|
||||||
|
format_free(ft);
|
||||||
|
|
||||||
|
memcpy(&bgc, &grid_default_cell, sizeof bgc);
|
||||||
|
bgc.bg = fgc.fg;
|
||||||
|
|
||||||
|
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, NULL);
|
||||||
|
if (sx >= len + llen + 1) {
|
||||||
|
len += llen + 1;
|
||||||
|
cx = xoff + px - len / 2;
|
||||||
|
cy = yoff + py;
|
||||||
|
cmd_display_panes_put(ctx, wp, cx, cy, buf, len);
|
||||||
|
cx += len;
|
||||||
|
cmd_display_panes_put(ctx, wp, cx, cy, " ", 1);
|
||||||
|
cx++;
|
||||||
|
cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen);
|
||||||
|
} else {
|
||||||
|
cx = xoff + px - len / 2;
|
||||||
|
cy = yoff + py;
|
||||||
|
cmd_display_panes_put(ctx, wp, cx, cy, buf, len);
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
px -= len * 3;
|
||||||
|
py -= 2;
|
||||||
|
|
||||||
|
tty_attributes(tty, &bgc, NULL);
|
||||||
|
for (ptr = buf; *ptr != '\0'; ptr++) {
|
||||||
|
if (*ptr < '0' || *ptr > '9')
|
||||||
|
continue;
|
||||||
|
idx = *ptr - '0';
|
||||||
|
|
||||||
|
for (j = 0; j < 5; j++) {
|
||||||
|
for (i = px; i < px + 5; i++) {
|
||||||
|
if (!window_clock_table[idx][j][i - px])
|
||||||
|
continue;
|
||||||
|
cx = xoff + i;
|
||||||
|
cy = yoff + py + j;
|
||||||
|
cmd_display_panes_put(ctx, wp, cx, cy, " ", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
px += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sy <= 6)
|
||||||
|
goto out;
|
||||||
|
cmd_display_panes_draw_format(ctx, wp, xoff, yoff, sx, &fgc);
|
||||||
|
if (llen != 0) {
|
||||||
|
tty_attributes(tty, &fgc, NULL);
|
||||||
|
cx = xoff + sx / 2 + len * 3 - llen - 1;
|
||||||
|
cy = yoff + py + 5;
|
||||||
|
cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
tty_cursor(tty, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_display_panes_draw(struct client *c, __unused void *data)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct window *w = s->curw->window;
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct cmd_display_panes_ctx ctx;
|
||||||
|
u_int lines;
|
||||||
|
|
||||||
|
log_debug("%s: %s @%u", __func__, c->name, w->id);
|
||||||
|
|
||||||
|
memset(&ctx, 0, sizeof ctx);
|
||||||
|
ctx.c = c;
|
||||||
|
tty_window_offset(&c->tty, &ctx.ox, &ctx.oy, &ctx.sx, &ctx.sy);
|
||||||
|
if (options_get_number(s->options, "status-position") == 0) {
|
||||||
|
lines = status_line_size(c);
|
||||||
|
if (c->message_string != NULL || c->prompt != NULL)
|
||||||
|
lines = (lines == 0 ? 1 : lines);
|
||||||
|
ctx.statuslines = lines;
|
||||||
|
ctx.statustop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||||
|
if (window_pane_is_visible(wp))
|
||||||
|
cmd_display_panes_draw_pane(&ctx, wp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_display_panes_free(__unused struct client *c, void *data)
|
||||||
|
{
|
||||||
|
struct cmd_display_panes_data *cdata = data;
|
||||||
|
|
||||||
|
if (cdata->item != NULL)
|
||||||
|
cmdq_continue(cdata->item);
|
||||||
|
args_make_commands_free(cdata->state);
|
||||||
|
free(cdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmd_display_panes_key(struct client *c, void *data, struct key_event *event)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
u_int index;
|
||||||
|
key_code key;
|
||||||
|
|
||||||
|
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, index);
|
||||||
|
if (wp == NULL)
|
||||||
|
return (1);
|
||||||
|
window_unzoom(w, 1);
|
||||||
|
|
||||||
|
xasprintf(&expanded, "%%%u", wp->id);
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
||||||
|
cmdq_insert_after(item, new_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(expanded);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
|
{
|
||||||
|
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 (tc->overlay_draw != NULL)
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
delay = options_get_number(s->options, "display-panes-time");
|
||||||
|
|
||||||
|
cdata = xcalloc(1, sizeof *cdata);
|
||||||
|
if (wait)
|
||||||
|
cdata->item = item;
|
||||||
|
cdata->state = args_make_commands_prepare(self, item, 0,
|
||||||
|
"select-pane -t \"%%%\"", wait, 0);
|
||||||
|
|
||||||
|
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 (!wait)
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
return (CMD_RETURN_WAIT);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-find-window.c,v 1.57 2026/07/14 17:17:17 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -109,8 +109,7 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
args_set(new_args, 'Z', NULL, 0);
|
args_set(new_args, 'Z', NULL, 0);
|
||||||
args_set(new_args, 'f', filter, 0);
|
args_set(new_args, 'f', filter, 0);
|
||||||
|
|
||||||
window_pane_set_mode(wp, NULL, &window_tree_mode, item, target,
|
window_pane_set_mode(wp, NULL, &window_tree_mode, target, new_args);
|
||||||
new_args);
|
|
||||||
args_free(new_args);
|
args_free(new_args);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
93
cmd-find.c
93
cmd-find.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-find.c,v 1.87 2026/07/17 12:42:51 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -884,13 +884,13 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
|
|||||||
if (c->session != NULL) {
|
if (c->session != NULL) {
|
||||||
cmd_find_clear_state(fs, flags);
|
cmd_find_clear_state(fs, flags);
|
||||||
|
|
||||||
fs->wl = active_get_effective_winlink(c, c->session);
|
fs->wp = server_client_get_pane(c);
|
||||||
fs->wp = fs->wl->window->active;
|
|
||||||
if (fs->wp == NULL) {
|
if (fs->wp == NULL) {
|
||||||
cmd_find_from_session(fs, c->session, flags);
|
cmd_find_from_session(fs, c->session, flags);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
fs->s = c->session;
|
fs->s = c->session;
|
||||||
|
fs->wl = fs->s->curw;
|
||||||
fs->w = fs->wl->window;
|
fs->w = fs->wl->window;
|
||||||
|
|
||||||
cmd_find_log_state(__func__, fs);
|
cmd_find_log_state(__func__, fs);
|
||||||
@@ -931,57 +931,6 @@ unknown_pane:
|
|||||||
return (cmd_find_from_nothing(fs, flags));
|
return (cmd_find_from_nothing(fs, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find state from mouse target. */
|
|
||||||
static int
|
|
||||||
cmd_find_target_from_mouse(struct cmd_find_state *fs, struct cmdq_item *item,
|
|
||||||
enum cmd_find_type type)
|
|
||||||
{
|
|
||||||
struct mouse_event *m = &cmdq_get_event(item)->m;
|
|
||||||
struct client *c = cmdq_get_client(item);
|
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case CMD_FIND_PANE:
|
|
||||||
if (m->s != -1 && m->w == -1 && m->wp == -1 &&
|
|
||||||
(fs->s = session_find_by_id(m->s)) != NULL) {
|
|
||||||
if (tc != NULL && tc->session == fs->s)
|
|
||||||
fs->wl = active_get_effective_winlink(tc, fs->s);
|
|
||||||
else if (c != NULL && c->session == fs->s)
|
|
||||||
fs->wl = active_get_effective_winlink(c, fs->s);
|
|
||||||
else
|
|
||||||
fs->wl = fs->s->curw;
|
|
||||||
if (fs->wl != NULL) {
|
|
||||||
fs->w = fs->wl->window;
|
|
||||||
fs->wp = fs->w->active;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
|
|
||||||
if (fs->wp != NULL) {
|
|
||||||
fs->w = fs->wl->window;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case CMD_FIND_WINDOW:
|
|
||||||
case CMD_FIND_SESSION:
|
|
||||||
fs->wl = cmd_mouse_window(m, &fs->s);
|
|
||||||
if (fs->s != NULL && m->w == -1 &&
|
|
||||||
tc != NULL && tc->session == fs->s)
|
|
||||||
fs->wl = active_get_effective_winlink(tc, fs->s);
|
|
||||||
else if (fs->s != NULL && m->w == -1 &&
|
|
||||||
c != NULL && c->session == fs->s)
|
|
||||||
fs->wl = active_get_effective_winlink(c, fs->s);
|
|
||||||
if (fs->wl == NULL && fs->s != NULL)
|
|
||||||
fs->wl = fs->s->curw;
|
|
||||||
if (fs->wl != NULL) {
|
|
||||||
fs->w = fs->wl->window;
|
|
||||||
fs->wp = fs->w->active;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (fs->wp == NULL ? -1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Split target into pieces and resolve for the given type. Fills in the given
|
* Split target into pieces and resolve for the given type. Fills in the given
|
||||||
* state. Returns 0 on success or -1 on error.
|
* state. Returns 0 on success or -1 on error.
|
||||||
@@ -990,6 +939,7 @@ int
|
|||||||
cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
||||||
const char *target, enum cmd_find_type type, int flags)
|
const char *target, enum cmd_find_type type, int flags)
|
||||||
{
|
{
|
||||||
|
struct mouse_event *m;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct cmd_find_state current;
|
struct cmd_find_state current;
|
||||||
char *colon, *period, *copy = NULL, tmp[256];
|
char *colon, *period, *copy = NULL, tmp[256];
|
||||||
@@ -1044,15 +994,20 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
|||||||
} else if (cmd_find_from_client(¤t, cmdq_get_client(item),
|
} else if (cmd_find_from_client(¤t, cmdq_get_client(item),
|
||||||
flags) == 0) {
|
flags) == 0) {
|
||||||
fs->current = ¤t;
|
fs->current = ¤t;
|
||||||
|
/* No active pane, window empty, return the window instead. */
|
||||||
|
if (current.wp == NULL) {
|
||||||
|
type = CMD_FIND_WINDOW;
|
||||||
|
}
|
||||||
log_debug("%s: current is from client", __func__);
|
log_debug("%s: current is from client", __func__);
|
||||||
} else {
|
} else {
|
||||||
if (~flags & CMD_FIND_QUIET)
|
if (~flags & CMD_FIND_QUIET)
|
||||||
cmdq_error(item, "no current target");
|
cmdq_error(item, "no current target");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (!cmd_find_valid_state(fs->current))
|
if (!cmd_find_valid_state(fs->current))
|
||||||
fatalx("invalid current find state");
|
fatalx("invalid current find state");
|
||||||
|
*/
|
||||||
/* An empty or NULL target is the current. */
|
/* An empty or NULL target is the current. */
|
||||||
if (target == NULL || *target == '\0')
|
if (target == NULL || *target == '\0')
|
||||||
goto current;
|
goto current;
|
||||||
@@ -1065,15 +1020,35 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
|||||||
cmdq_error(item, "no current client");
|
cmdq_error(item, "no current client");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
fs->wl = active_get_effective_winlink(c, c->session);
|
fs->wl = c->session->curw;
|
||||||
fs->wp = fs->wl->window->active;
|
fs->wp = c->session->curw->window->active;
|
||||||
fs->w = fs->wl->window;
|
fs->w = c->session->curw->window;
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mouse target is a plain = or {mouse}. */
|
/* Mouse target is a plain = or {mouse}. */
|
||||||
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
|
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
|
||||||
if (cmd_find_target_from_mouse(fs, item, type) != 0) {
|
m = &cmdq_get_event(item)->m;
|
||||||
|
switch (type) {
|
||||||
|
case CMD_FIND_PANE:
|
||||||
|
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
|
||||||
|
if (fs->wp != NULL) {
|
||||||
|
fs->w = fs->wl->window;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case CMD_FIND_WINDOW:
|
||||||
|
case CMD_FIND_SESSION:
|
||||||
|
fs->wl = cmd_mouse_window(m, &fs->s);
|
||||||
|
if (fs->wl == NULL && fs->s != NULL)
|
||||||
|
fs->wl = fs->s->curw;
|
||||||
|
if (fs->wl != NULL) {
|
||||||
|
fs->w = fs->wl->window;
|
||||||
|
fs->wp = fs->w->active;
|
||||||
|
}
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
if (fs->wp == NULL) {
|
||||||
if (~flags & CMD_FIND_QUIET)
|
if (~flags & CMD_FIND_QUIET)
|
||||||
cmdq_error(item, "no mouse target");
|
cmdq_error(item, "no mouse target");
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
213
cmd-hide-pane.c
Normal file
213
cmd-hide-pane.c
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2026 Michael Grant <mgrant@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hide or show panes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static enum cmd_retval cmd_hide_pane_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
static enum cmd_retval cmd_show_pane_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_hide_pane_entry = {
|
||||||
|
.name = "hide-pane",
|
||||||
|
.alias = "hidep",
|
||||||
|
|
||||||
|
.args = { "at:", 0, 1, NULL },
|
||||||
|
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
|
.flags = CMD_AFTERHOOK,
|
||||||
|
.exec = cmd_hide_pane_exec
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_show_pane_entry = {
|
||||||
|
.name = "show-pane",
|
||||||
|
.alias = "showp",
|
||||||
|
|
||||||
|
.args = { "at:", 0, 1, NULL },
|
||||||
|
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
|
.flags = CMD_AFTERHOOK,
|
||||||
|
.exec = cmd_show_pane_exec
|
||||||
|
};
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_hide_pane_hide(struct window *w, struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct window_pane *wpp = NULL;
|
||||||
|
struct layout_cell *lc = wp->layout_cell;
|
||||||
|
|
||||||
|
if (window_pane_is_hidden(wp))
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
if (wp == w->active) {
|
||||||
|
/* Find previous active pane. */
|
||||||
|
TAILQ_FOREACH(wpp, &w->last_panes, sentry) {
|
||||||
|
if (wpp != wp && window_pane_is_visible(wpp))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wpp == NULL) {
|
||||||
|
TAILQ_FOREACH(wpp, &w->z_index, zentry) {
|
||||||
|
if (wpp != wp &&
|
||||||
|
window_pane_is_visible(wpp))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lc->flags |= LAYOUT_CELL_HIDDEN;
|
||||||
|
|
||||||
|
layout_remove_tile(w, lc);
|
||||||
|
layout_fix_offsets(w);
|
||||||
|
layout_fix_panes(w, NULL);
|
||||||
|
|
||||||
|
window_pane_stack_remove(&w->last_panes, wp);
|
||||||
|
if (wpp != NULL) {
|
||||||
|
window_set_active_pane(w, wpp, 1);
|
||||||
|
} else if (wp == w->active) {
|
||||||
|
/* No visible previous active pane; null active pane
|
||||||
|
* to show dots background. */
|
||||||
|
w->active = NULL;
|
||||||
|
if (options_get_number(global_options, "focus-events"))
|
||||||
|
window_pane_update_focus(wp);
|
||||||
|
notify_window("window-pane-changed", w);
|
||||||
|
notify_window("window-layout-changed", w);
|
||||||
|
server_redraw_window(w);
|
||||||
|
} else {
|
||||||
|
notify_window("window-layout-changed", w);
|
||||||
|
server_redraw_window(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_hide_pane_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 winlink *wl = target->wl;
|
||||||
|
struct window *w = wl->window;
|
||||||
|
struct window_pane *wp, *active_pane = w->active;
|
||||||
|
u_int id;
|
||||||
|
char *cause = NULL;
|
||||||
|
enum cmd_retval rv;
|
||||||
|
|
||||||
|
window_unzoom(w, 1);
|
||||||
|
|
||||||
|
if (args_has(args, 'a')) {
|
||||||
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
|
if (!window_pane_is_visible(wp) || wp == active_pane)
|
||||||
|
continue;
|
||||||
|
rv = cmd_hide_pane_hide(w, wp);
|
||||||
|
if (rv != CMD_RETURN_NORMAL)
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
} else {
|
||||||
|
wp = target->wp;
|
||||||
|
if (wp == NULL) {
|
||||||
|
id = args_strtonum_and_expand(args, 't', 0, INT_MAX,
|
||||||
|
item, &cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "%s target pane", cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
wp = window_pane_find_by_id(id);
|
||||||
|
}
|
||||||
|
if (wp == NULL) {
|
||||||
|
cmdq_error(item, "No target pane to hide.");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
return (cmd_hide_pane_hide(w, wp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_hide_pane_show(struct window *w, struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct layout_cell *lc = wp->layout_cell;
|
||||||
|
|
||||||
|
if (!window_pane_is_hidden(wp))
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
lc->flags &= ~LAYOUT_CELL_HIDDEN;
|
||||||
|
|
||||||
|
layout_insert_tile(w, lc);
|
||||||
|
layout_fix_offsets(w);
|
||||||
|
layout_fix_panes(w, NULL);
|
||||||
|
|
||||||
|
window_set_active_pane(w, wp, 1);
|
||||||
|
|
||||||
|
notify_window("window-layout-changed", w);
|
||||||
|
server_redraw_window(w);
|
||||||
|
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cmd_show_pane_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 winlink *wl = target->wl;
|
||||||
|
struct window *w = wl->window;
|
||||||
|
struct window_pane *wp;
|
||||||
|
u_int id;
|
||||||
|
char *cause = NULL;
|
||||||
|
enum cmd_retval rv;
|
||||||
|
|
||||||
|
window_unzoom(w, 1);
|
||||||
|
|
||||||
|
if (args_has(args, 'a')) {
|
||||||
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
|
if (!window_pane_is_visible(wp))
|
||||||
|
continue;
|
||||||
|
rv = cmd_hide_pane_show(w, wp);
|
||||||
|
if (rv != CMD_RETURN_NORMAL)
|
||||||
|
return (rv);
|
||||||
|
}
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
} else {
|
||||||
|
wp = target->wp;
|
||||||
|
if (wp == NULL) {
|
||||||
|
id = args_strtonum_and_expand(args, 't', 0, INT_MAX,
|
||||||
|
item, &cause);
|
||||||
|
if (cause != NULL) {
|
||||||
|
cmdq_error(item, "%s target pane", cause);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
wp = window_pane_find_by_id(id);
|
||||||
|
}
|
||||||
|
if (wp == NULL) {
|
||||||
|
cmdq_error(item, "No target pane to show.");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
return (cmd_hide_pane_show(w, wp));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-if-shell.c,v 1.87 2026/08/25 06:04:33 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -98,7 +98,6 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
||||||
cmdq_insert_after(item, new_item);
|
cmdq_insert_after(item, new_item);
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,11 +164,9 @@ cmd_if_shell_callback(struct job *job)
|
|||||||
} else if (item == NULL) {
|
} else if (item == NULL) {
|
||||||
new_item = cmdq_get_command(cmdlist, NULL);
|
new_item = cmdq_get_command(cmdlist, NULL);
|
||||||
cmdq_append(c, new_item);
|
cmdq_append(c, new_item);
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
} else {
|
} else {
|
||||||
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
||||||
cmdq_insert_after(item, new_item);
|
cmdq_insert_after(item, new_item);
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|||||||
132
cmd-join-pane.c
132
cmd-join-pane.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-join-pane.c,v 1.74 2026/08/03 20:29:52 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
|
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
|
||||||
@@ -71,9 +71,8 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
|
|||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct layout_cell *lc = wp->layout_cell;
|
struct layout_cell *lc = wp->layout_cell;
|
||||||
struct window_pane *owp;
|
struct window_pane *owp;
|
||||||
int wx = w->sx, wy = w->sy;
|
int wx = w->sx, wy = w->sy, px = lc->sx;
|
||||||
int px = lc->g.sx, py = lc->g.sy;
|
int py = lc->sy, xoff = lc->xoff, yoff = lc->yoff;
|
||||||
int xoff = lc->g.xoff, yoff = lc->g.yoff;
|
|
||||||
int border = 1;
|
int border = 1;
|
||||||
|
|
||||||
if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE)
|
if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE)
|
||||||
@@ -181,13 +180,12 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xoff != lc->g.xoff || yoff != lc->g.yoff) {
|
if (xoff != lc->xoff || yoff != lc->yoff) {
|
||||||
lc->g.xoff = xoff;
|
lc->xoff = xoff;
|
||||||
lc->g.yoff = yoff;
|
lc->yoff = yoff;
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
}
|
}
|
||||||
redraw_invalidate_scene(w);
|
notify_window("window-layout-changed", w);
|
||||||
events_fire_window("window-layout-changed", w);
|
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
@@ -202,7 +200,7 @@ cmd_join_pane_move(struct cmdq_item *item, struct args *args,
|
|||||||
const char *errstr, *argval;
|
const char *errstr, *argval;
|
||||||
const char flags[] = { 'U', 'D', 'L', 'R' };
|
const char flags[] = { 'U', 'D', 'L', 'R' };
|
||||||
char *cause = NULL, flag;
|
char *cause = NULL, flag;
|
||||||
int xoff = lc->g.xoff, yoff = lc->g.yoff, adjust;
|
int xoff = lc->xoff, yoff = lc->yoff, adjust;
|
||||||
u_int i;
|
u_int i;
|
||||||
enum pane_lines lines = window_pane_get_pane_lines(wp);
|
enum pane_lines lines = window_pane_get_pane_lines(wp);
|
||||||
|
|
||||||
@@ -253,11 +251,11 @@ cmd_join_pane_move(struct cmdq_item *item, struct args *args,
|
|||||||
xoff += adjust;
|
xoff += adjust;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xoff != lc->g.xoff || yoff != lc->g.yoff) {
|
if (xoff != lc->xoff || yoff != lc->yoff) {
|
||||||
lc->g.xoff = xoff;
|
lc->xoff = xoff;
|
||||||
lc->g.yoff = yoff;
|
lc->yoff = yoff;
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
events_fire_window("window-layout-changed", w);
|
notify_window("window-layout-changed", w);
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,8 +319,8 @@ cmd_join_pane_mouse_move(struct client *c, struct mouse_event *m)
|
|||||||
ly = m->statusat - 1;
|
ly = m->statusat - 1;
|
||||||
|
|
||||||
if (x != lx || y != ly) {
|
if (x != lx || y != ly) {
|
||||||
lc->g.xoff += x - lx;
|
lc->xoff += x - lx;
|
||||||
lc->g.yoff += y - ly;
|
lc->yoff += y - ly;
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
server_redraw_window_borders(w);
|
server_redraw_window_borders(w);
|
||||||
@@ -359,8 +357,7 @@ cmd_join_pane_zindex(struct cmdq_item *item, struct winlink *wl,
|
|||||||
else
|
else
|
||||||
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
||||||
|
|
||||||
redraw_invalidate_scene(w);
|
notify_window("window-layout-changed", w);
|
||||||
events_fire_window("window-layout-changed", w);
|
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
@@ -376,21 +373,21 @@ cmd_join_pane_tile(struct cmdq_item *item, struct args *args, struct window *w,
|
|||||||
cmdq_error(item, "pane is not floating");
|
cmdq_error(item, "pane is not floating");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
if (window_pane_is_hidden(wp)) {
|
||||||
|
cmdq_error(item, "can't tile a hidden pane");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
if (w->flags & WINDOW_ZOOMED) {
|
if (w->flags & WINDOW_ZOOMED) {
|
||||||
cmdq_error(item, "can't tile a pane while window is zoomed");
|
cmdq_error(item, "can't tile a pane while window is zoomed");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
lc->fg.sx = lc->g.sx;
|
layout_save_size(lc);
|
||||||
lc->fg.sy = lc->g.sy;
|
lc->flags &= ~LAYOUT_CELL_FLOATING;
|
||||||
lc->fg.xoff = lc->g.xoff;
|
if (layout_insert_tile(w, lc) == 0) {
|
||||||
lc->fg.yoff = lc->g.yoff;
|
|
||||||
|
|
||||||
if (layout_insert_tile(w, lc) != 0) {
|
|
||||||
cmdq_error(item, "no space for a new pane");
|
cmdq_error(item, "no space for a new pane");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
lc->flags &= ~LAYOUT_CELL_FLOATING;
|
|
||||||
|
|
||||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||||
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
||||||
@@ -399,8 +396,7 @@ cmd_join_pane_tile(struct cmdq_item *item, struct args *args, struct window *w,
|
|||||||
window_set_active_pane(w, wp, 1);
|
window_set_active_pane(w, wp, 1);
|
||||||
layout_fix_offsets(w);
|
layout_fix_offsets(w);
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
redraw_invalidate_scene(w);
|
notify_window("window-layout-changed", w);
|
||||||
events_fire_window("window-layout-changed", w);
|
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
@@ -413,84 +409,68 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_find_state *current = cmdq_get_current(item);
|
struct cmd_find_state *current = cmdq_get_current(item);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct cmd_find_state *source = cmdq_get_source(item);
|
struct cmd_find_state *source = cmdq_get_source(item);
|
||||||
struct client *c = cmdq_get_client(item);
|
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
|
||||||
struct client *ac;
|
|
||||||
struct session *dst_s;
|
struct session *dst_s;
|
||||||
struct winlink *src_wl, *dst_wl;
|
struct winlink *src_wl, *dst_wl;
|
||||||
struct window *src_w, *dst_w;
|
struct window *src_w, *dst_w;
|
||||||
struct window_pane *src_wp, *dst_wp;
|
struct window_pane *src_wp, *dst_wp;
|
||||||
const char *s;
|
const char *s;
|
||||||
char *cause = NULL;
|
char *cause = NULL;
|
||||||
int flags = 0, dst_idx, local;
|
int flags = 0, dst_idx;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc, *src_lc;
|
||||||
|
|
||||||
dst_s = target->s;
|
dst_s = target->s;
|
||||||
dst_wl = target->wl;
|
dst_wl = target->wl;
|
||||||
dst_wp = target->wp;
|
dst_wp = target->wp;
|
||||||
dst_w = dst_wl->window;
|
dst_w = dst_wl->window;
|
||||||
dst_idx = dst_wl->idx;
|
dst_idx = dst_wl->idx;
|
||||||
ac = tc;
|
server_unzoom_window(dst_w);
|
||||||
if (ac == NULL || ac->session != dst_s)
|
|
||||||
ac = c;
|
|
||||||
local = active_is_local_window(ac, dst_s);
|
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_move_pane_entry) {
|
if (cmd_get_entry(self) == &cmd_move_pane_entry) {
|
||||||
if (args_has(args, 'M'))
|
if (args_has(args, 'M'))
|
||||||
return (cmd_join_pane_mouse_update(item));
|
return (cmd_join_pane_mouse_update(item));
|
||||||
if (args_has(args, 'P') ||
|
if (!window_pane_is_floating(dst_wp)) {
|
||||||
args_has(args, 'z') ||
|
cmdq_error(item, "pane is not floating");
|
||||||
args_has(args, 'X') ||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
if ((s = args_get(args, 'P')) != NULL)
|
||||||
|
return (cmd_join_pane_place(item, dst_wl, dst_wp, s));
|
||||||
|
if ((s = args_get(args, 'z')) != NULL)
|
||||||
|
return (cmd_join_pane_zindex(item, dst_wl, dst_wp, s));
|
||||||
|
if (args_has(args, 'X') ||
|
||||||
args_has(args, 'Y') ||
|
args_has(args, 'Y') ||
|
||||||
args_has(args, 'U') ||
|
args_has(args, 'U') ||
|
||||||
args_has(args, 'D') ||
|
args_has(args, 'D') ||
|
||||||
args_has(args, 'L') ||
|
args_has(args, 'L') ||
|
||||||
args_has(args, 'R')) {
|
args_has(args, 'R'))
|
||||||
if (!window_pane_is_floating(dst_wp)) {
|
|
||||||
cmdq_error(item, "pane is not floating");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
server_unzoom_window(dst_w);
|
|
||||||
if ((s = args_get(args, 'P')) != NULL)
|
|
||||||
return (cmd_join_pane_place(item, dst_wl, dst_wp, s));
|
|
||||||
if ((s = args_get(args, 'z')) != NULL)
|
|
||||||
return (cmd_join_pane_zindex(item, dst_wl, dst_wp, s));
|
|
||||||
return (cmd_join_pane_move(item, args, dst_wl, dst_wp));
|
return (cmd_join_pane_move(item, args, dst_wl, dst_wp));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
src_wl = source->wl;
|
src_wl = source->wl;
|
||||||
src_wp = source->wp;
|
src_wp = source->wp;
|
||||||
|
src_lc = src_wp->layout_cell;
|
||||||
src_w = src_wl->window;
|
src_w = src_wl->window;
|
||||||
|
|
||||||
if (src_wp == src_w->modal || dst_wp == dst_w->modal) {
|
|
||||||
cmdq_error(item, "pane is modal");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
server_unzoom_window(dst_w);
|
|
||||||
server_unzoom_window(src_w);
|
server_unzoom_window(src_w);
|
||||||
|
|
||||||
|
if (!args_has(args, 't') && window_pane_is_floating(src_wp))
|
||||||
|
return (cmd_join_pane_tile(item, args, src_w, src_wp));
|
||||||
|
|
||||||
if (src_wp == dst_wp) {
|
if (src_wp == dst_wp) {
|
||||||
if (window_pane_is_floating(src_wp))
|
|
||||||
return (cmd_join_pane_tile(item, args, src_w, src_wp));
|
|
||||||
cmdq_error(item, "source and target panes must be different");
|
cmdq_error(item, "source and target panes must be different");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'h'))
|
|
||||||
flags |= SPAWN_HORIZONTAL;
|
|
||||||
if (args_has(args, 'b'))
|
|
||||||
flags |= SPAWN_BEFORE;
|
|
||||||
if (args_has(args, 'f'))
|
|
||||||
flags |= SPAWN_FULLSIZE;
|
|
||||||
|
|
||||||
lc = layout_get_tiled_cell(item, args, dst_w, dst_wp, flags, &cause);
|
lc = layout_get_tiled_cell(item, args, dst_w, dst_wp, flags, &cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "size or position %s", cause);
|
cmdq_error(item, "size or position %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
if (window_pane_is_floating(src_wp)) {
|
||||||
|
lc->saved_sx = src_lc->sx;
|
||||||
|
lc->saved_sy = src_lc->sy;
|
||||||
|
lc->saved_xoff = src_lc->xoff;
|
||||||
|
lc->saved_yoff = src_lc->yoff;
|
||||||
|
}
|
||||||
|
|
||||||
layout_close_pane(src_wp);
|
layout_close_pane(src_wp);
|
||||||
|
|
||||||
@@ -519,27 +499,17 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (!args_has(args, 'd')) {
|
if (!args_has(args, 'd')) {
|
||||||
window_set_active_pane(dst_w, src_wp, 1);
|
window_set_active_pane(dst_w, src_wp, 1);
|
||||||
if (local)
|
session_select(dst_s, dst_idx);
|
||||||
active_select_window(ac, dst_s, dst_wl);
|
cmd_find_from_session(current, dst_s, 0);
|
||||||
else
|
server_redraw_session(dst_s);
|
||||||
session_select(dst_s, dst_idx);
|
|
||||||
if (local && ac != NULL && ac->session == dst_s)
|
|
||||||
cmd_find_from_client(current, ac, 0);
|
|
||||||
else
|
|
||||||
cmd_find_from_session(current, dst_s, 0);
|
|
||||||
if (local && ac != NULL && ac->session == dst_s)
|
|
||||||
server_redraw_client(ac);
|
|
||||||
else
|
|
||||||
server_redraw_session(dst_s);
|
|
||||||
} else
|
} else
|
||||||
server_status_session(dst_s);
|
server_status_session(dst_s);
|
||||||
|
|
||||||
window_fire_pane_moved(src_wp, src_w, src_wl->idx, dst_w, dst_idx);
|
|
||||||
if (window_count_panes(src_w, 1) == 0)
|
if (window_count_panes(src_w, 1) == 0)
|
||||||
server_kill_window(src_w, 1);
|
server_kill_window(src_w, 1);
|
||||||
else
|
else
|
||||||
events_fire_window("window-layout-changed", src_w);
|
notify_window("window-layout-changed", src_w);
|
||||||
events_fire_window("window-layout-changed", dst_w);
|
notify_window("window-layout-changed", dst_w);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-kill-pane.c,v 1.34 2026/06/09 21:22:22 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-kill-server.c,v 1.20 2021/08/21 10:22:39 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-kill-session.c,v 1.31 2026/06/09 12:57:40 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-kill-window.c,v 1.30 2026/06/09 12:57:40 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-list-buffers.c,v 1.41 2026/02/27 08:25:12 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-list-clients.c,v 1.42 2026/02/27 08:25:12 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-list-commands.c,v 1.15 2026/02/24 08:22:13 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-list-keys.c,v 1.78 2026/07/01 13:12:17 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-list-panes.c,v 1.40 2026/06/01 14:01:09 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-list-sessions.c,v 1.36 2026/02/27 08:25:12 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-list-windows.c,v 1.50 2026/02/27 08:25:12 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-load-buffer.c,v 1.66 2025/10/28 07:32:26 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-lock-server.c,v 1.31 2021/08/21 10:22:39 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-move-window.c,v 1.34 2021/08/21 10:22:39 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -62,15 +62,12 @@ cmd_move_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *source = cmdq_get_source(item);
|
struct cmd_find_state *source = cmdq_get_source(item);
|
||||||
struct cmd_find_state target;
|
struct cmd_find_state target;
|
||||||
struct client *c = cmdq_get_client(item);
|
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
|
||||||
struct client *ac;
|
|
||||||
const char *tflag = args_get(args, 't');
|
const char *tflag = args_get(args, 't');
|
||||||
struct session *src = source->s;
|
struct session *src = source->s;
|
||||||
struct session *dst;
|
struct session *dst;
|
||||||
struct winlink *wl = source->wl, *dstwl, *current_wl;
|
struct winlink *wl = source->wl;
|
||||||
char *cause;
|
char *cause;
|
||||||
int idx, kflag, dflag, sflag, before, local;
|
int idx, kflag, dflag, sflag, before;
|
||||||
|
|
||||||
if (args_has(args, 'r')) {
|
if (args_has(args, 'r')) {
|
||||||
if (cmd_find_target(&target, item, tflag, CMD_FIND_SESSION,
|
if (cmd_find_target(&target, item, tflag, CMD_FIND_SESSION,
|
||||||
@@ -93,37 +90,23 @@ cmd_move_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
dflag = args_has(args, 'd');
|
dflag = args_has(args, 'd');
|
||||||
sflag = args_has(args, 's');
|
sflag = args_has(args, 's');
|
||||||
|
|
||||||
ac = tc;
|
|
||||||
if (ac == NULL || ac->session != dst)
|
|
||||||
ac = c;
|
|
||||||
local = (!dflag && active_is_local_window(ac, dst));
|
|
||||||
|
|
||||||
before = args_has(args, 'b');
|
before = args_has(args, 'b');
|
||||||
if (args_has(args, 'a') || before) {
|
if (args_has(args, 'a') || before) {
|
||||||
if (target.wl != NULL)
|
if (target.wl != NULL)
|
||||||
idx = winlink_shuffle_up(dst, target.wl, before);
|
idx = winlink_shuffle_up(dst, target.wl, before);
|
||||||
else {
|
else
|
||||||
current_wl = active_get_effective_winlink(ac, dst);
|
idx = winlink_shuffle_up(dst, dst->curw, before);
|
||||||
idx = winlink_shuffle_up(dst, current_wl, before);
|
|
||||||
}
|
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server_link_window(src, wl, dst, idx, kflag, !dflag && !local,
|
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
|
||||||
&cause) != 0) {
|
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
dstwl = winlink_find_by_window(&dst->windows, wl->window);
|
|
||||||
if (cmd_get_entry(self) == &cmd_move_window_entry)
|
if (cmd_get_entry(self) == &cmd_move_window_entry)
|
||||||
server_unlink_window(src, wl);
|
server_unlink_window(src, wl);
|
||||||
if (local && dstwl != NULL) {
|
|
||||||
active_select_window(ac, dst, dstwl);
|
|
||||||
if (ac != NULL && ac->session == dst)
|
|
||||||
server_redraw_client(ac);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Renumber the winlinks in the src session only, the destination
|
* Renumber the winlinks in the src session only, the destination
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-new-session.c,v 1.152 2026/07/10 13:38:45 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -325,7 +325,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
session_group_synchronize_to(s);
|
session_group_synchronize_to(s);
|
||||||
session_select(s, RB_MIN(winlinks, &s->windows)->idx);
|
session_select(s, RB_MIN(winlinks, &s->windows)->idx);
|
||||||
}
|
}
|
||||||
events_fire_session("session-created", s);
|
notify_session("session-created", s);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the client to the new session. If a command client exists, it is
|
* Set the client to the new session. If a command client exists, it is
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-new-window.c,v 1.103 2026/07/08 08:07:42 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -38,8 +38,8 @@ const struct cmd_entry cmd_new_window_entry = {
|
|||||||
.name = "new-window",
|
.name = "new-window",
|
||||||
.alias = "neww",
|
.alias = "neww",
|
||||||
|
|
||||||
.args = { "abc:de:EF:kn:PSt:", 0, -1, NULL },
|
.args = { "abc:de:F:kn:PSt:", 0, -1, NULL },
|
||||||
.usage = "[-abdEkPS] [-c start-directory] [-e environment] [-F format] "
|
.usage = "[-abdkPS] [-c start-directory] [-e environment] [-F format] "
|
||||||
"[-n window-name] " CMD_TARGET_WINDOW_USAGE
|
"[-n window-name] " CMD_TARGET_WINDOW_USAGE
|
||||||
" [shell-command [argument ...]]",
|
" [shell-command [argument ...]]",
|
||||||
|
|
||||||
@@ -58,23 +58,14 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct spawn_context sc = { 0 };
|
struct spawn_context sc = { 0 };
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
struct client *ac;
|
|
||||||
struct session *s = target->s;
|
struct session *s = target->s;
|
||||||
struct winlink *wl = target->wl, *new_wl = NULL;
|
struct winlink *wl = target->wl, *new_wl = NULL;
|
||||||
int idx = target->idx, before, count = args_count(args);
|
int idx = target->idx, before;
|
||||||
int detached, local;
|
|
||||||
char *cause = NULL, *cp, *expanded, *wname = NULL;
|
char *cause = NULL, *cp, *expanded, *wname = NULL;
|
||||||
const char *template, *name;
|
const char *template, *name;
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
struct args_value *av;
|
struct args_value *av;
|
||||||
|
|
||||||
if (args_has(args, 'E') &&
|
|
||||||
count != 0 &&
|
|
||||||
(count != 1 || *args_string(args, 0) != '\0')) {
|
|
||||||
cmdq_error(item, "command cannot be given for empty pane");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If -S and -n are given and -t is not and a single window with this
|
* If -S and -n are given and -t is not and a single window with this
|
||||||
* name already exists, select it.
|
* name already exists, select it.
|
||||||
@@ -109,15 +100,10 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
free(wname);
|
free(wname);
|
||||||
if (args_has(args, 'd'))
|
if (args_has(args, 'd'))
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
if (active_select_window(c, s, new_wl) == 0) {
|
if (session_set_current(s, new_wl) == 0)
|
||||||
if (active_is_local_window(c, s) && c != NULL &&
|
server_redraw_session(s);
|
||||||
c->session == s)
|
|
||||||
server_redraw_client(c);
|
|
||||||
else
|
|
||||||
server_redraw_session(s);
|
|
||||||
}
|
|
||||||
if (c != NULL && c->session != NULL)
|
if (c != NULL && c->session != NULL)
|
||||||
active_get_effective_window(c, s)->latest = c;
|
s->curw->window->latest = c;
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
@@ -147,16 +133,8 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
sc.idx = idx;
|
sc.idx = idx;
|
||||||
sc.cwd = args_get(args, 'c');
|
sc.cwd = args_get(args, 'c');
|
||||||
|
|
||||||
ac = tc;
|
|
||||||
if (ac == NULL || ac->session != s)
|
|
||||||
ac = c;
|
|
||||||
detached = args_has(args, 'd');
|
|
||||||
local = (!detached && active_is_local_window(ac, s));
|
|
||||||
|
|
||||||
sc.flags = 0;
|
sc.flags = 0;
|
||||||
if (args_has(args, 'E') || (count == 1 && *args_string(args, 0) == '\0'))
|
if (args_has(args, 'd'))
|
||||||
sc.flags |= SPAWN_EMPTY;
|
|
||||||
if (detached || local)
|
|
||||||
sc.flags |= SPAWN_DETACHED;
|
sc.flags |= SPAWN_DETACHED;
|
||||||
if (args_has(args, 'k'))
|
if (args_has(args, 'k'))
|
||||||
sc.flags |= SPAWN_KILL;
|
sc.flags |= SPAWN_KILL;
|
||||||
@@ -166,13 +144,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (local) {
|
if (!args_has(args, 'd') || new_wl == s->curw) {
|
||||||
if (active_select_window(ac, s, new_wl) == 0)
|
|
||||||
cmd_find_from_winlink(current, new_wl, 0);
|
|
||||||
if (ac != NULL && ac->session == s)
|
|
||||||
server_redraw_client(ac);
|
|
||||||
server_status_session_group(s);
|
|
||||||
} else if (!detached || new_wl == s->curw) {
|
|
||||||
cmd_find_from_winlink(current, new_wl, 0);
|
cmd_find_from_winlink(current, new_wl, 0);
|
||||||
server_redraw_session_group(s);
|
server_redraw_session_group(s);
|
||||||
} else
|
} else
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-parse.y,v 1.59 2026/08/31 07:51:56 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -802,7 +802,6 @@ cmd_parse_expand_alias(struct cmd_parse_command *cmd,
|
|||||||
if (last == NULL) {
|
if (last == NULL) {
|
||||||
pr->status = CMD_PARSE_SUCCESS;
|
pr->status = CMD_PARSE_SUCCESS;
|
||||||
pr->cmdlist = cmd_list_new();
|
pr->cmdlist = cmd_list_new();
|
||||||
cmd_parse_free_commands(cmds);
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,7 +814,6 @@ cmd_parse_expand_alias(struct cmd_parse_command *cmd,
|
|||||||
pi->flags |= CMD_PARSE_NOALIAS;
|
pi->flags |= CMD_PARSE_NOALIAS;
|
||||||
cmd_parse_build_commands(cmds, pi, pr);
|
cmd_parse_build_commands(cmds, pi, pr);
|
||||||
pi->flags &= ~CMD_PARSE_NOALIAS;
|
pi->flags &= ~CMD_PARSE_NOALIAS;
|
||||||
cmd_parse_free_commands(cmds);
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-paste-buffer.c,v 1.44 2026/03/04 07:19:32 tb Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-pipe-pane.c,v 1.64 2026/07/27 14:25:46 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -194,13 +194,9 @@ static void
|
|||||||
cmd_pipe_pane_read_callback(__unused struct bufferevent *bufev, void *data)
|
cmd_pipe_pane_read_callback(__unused struct bufferevent *bufev, void *data)
|
||||||
{
|
{
|
||||||
struct window_pane *wp = data;
|
struct window_pane *wp = data;
|
||||||
struct evbuffer *evb;
|
struct evbuffer *evb = wp->pipe_event->input;
|
||||||
size_t available;
|
size_t available;
|
||||||
|
|
||||||
if (wp->pipe_event == NULL)
|
|
||||||
return;
|
|
||||||
evb = wp->pipe_event->input;
|
|
||||||
|
|
||||||
available = EVBUFFER_LENGTH(evb);
|
available = EVBUFFER_LENGTH(evb);
|
||||||
log_debug("%%%u pipe read %zu", wp->id, available);
|
log_debug("%%%u pipe read %zu", wp->id, available);
|
||||||
|
|
||||||
|
|||||||
92
cmd-queue.c
92
cmd-queue.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-queue.c,v 1.123 2026/08/24 20:34:26 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -147,13 +147,6 @@ cmdq_get_name(struct cmdq_item *item)
|
|||||||
return (item->name);
|
return (item->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get item command. */
|
|
||||||
struct cmd *
|
|
||||||
cmdq_get_cmd(struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
return (item->cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get item client. */
|
/* Get item client. */
|
||||||
struct client *
|
struct client *
|
||||||
cmdq_get_client(struct cmdq_item *item)
|
cmdq_get_client(struct cmdq_item *item)
|
||||||
@@ -357,53 +350,74 @@ cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item)
|
|||||||
|
|
||||||
/* Insert a hook. */
|
/* Insert a hook. */
|
||||||
void
|
void
|
||||||
cmdq_insert_hook(__unused struct session *s, struct cmdq_item *item,
|
cmdq_insert_hook(struct session *s, struct cmdq_item *item,
|
||||||
struct cmd_find_state *current, const char *fmt, ...)
|
struct cmd_find_state *current, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
struct cmdq_state *state = item->state;
|
||||||
struct cmd *cmd = item->cmd;
|
struct cmd *cmd = item->cmd;
|
||||||
struct args *args = cmd_get_args(cmd);
|
struct args *args = cmd_get_args(cmd);
|
||||||
struct args_entry *ae;
|
struct args_entry *ae;
|
||||||
struct args_value *av;
|
struct args_value *av;
|
||||||
struct event_payload *ep;
|
struct options *oo;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char *name, tmp[32], flag, *arguments;
|
char *name, tmp[32], flag, *arguments;
|
||||||
u_int i;
|
u_int i;
|
||||||
const char *value;
|
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->state->flags & CMDQ_STATE_NOHOOKS)
|
if (item->state->flags & CMDQ_STATE_NOHOOKS)
|
||||||
return;
|
return;
|
||||||
|
if (s == NULL)
|
||||||
|
oo = global_s_options;
|
||||||
|
else
|
||||||
|
oo = s->options;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
xvasprintf(&name, fmt, ap);
|
xvasprintf(&name, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
ep = event_payload_create();
|
o = options_get(oo, name);
|
||||||
if (current != NULL)
|
if (o == NULL) {
|
||||||
event_payload_set_target(ep, current);
|
free(name);
|
||||||
event_payload_set_pointer(ep, "_cmdq_item", item, NULL, NULL);
|
return;
|
||||||
|
}
|
||||||
|
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);
|
arguments = args_print(args);
|
||||||
event_payload_set_string(ep, "arguments", "%s", arguments);
|
cmdq_add_format(new_state, "hook_arguments", "%s", arguments);
|
||||||
free(arguments);
|
free(arguments);
|
||||||
|
|
||||||
for (i = 0; i < args_count(args); i++) {
|
for (i = 0; i < args_count(args); i++) {
|
||||||
xsnprintf(tmp, sizeof tmp, "argument_%u", i);
|
xsnprintf(tmp, sizeof tmp, "hook_argument_%d", i);
|
||||||
event_payload_set_string(ep, tmp, "%s", args_string(args, i));
|
cmdq_add_format(new_state, tmp, "%s", args_string(args, i));
|
||||||
}
|
}
|
||||||
flag = args_first(args, &ae);
|
flag = args_first(args, &ae);
|
||||||
while (flag != 0) {
|
while (flag != 0) {
|
||||||
value = args_get(args, flag);
|
value = args_get(args, flag);
|
||||||
xsnprintf(tmp, sizeof tmp, "flag_%c", flag);
|
if (value == NULL) {
|
||||||
if (value == NULL)
|
xsnprintf(tmp, sizeof tmp, "hook_flag_%c", flag);
|
||||||
event_payload_set_string(ep, tmp, "1");
|
cmdq_add_format(new_state, tmp, "1");
|
||||||
else
|
} else {
|
||||||
event_payload_set_string(ep, tmp, "%s", value);
|
xsnprintf(tmp, sizeof tmp, "hook_flag_%c", flag);
|
||||||
|
cmdq_add_format(new_state, tmp, "%s", value);
|
||||||
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
av = args_first_value(args, flag);
|
av = args_first_value(args, flag);
|
||||||
while (av != NULL) {
|
while (av != NULL) {
|
||||||
xsnprintf(tmp, sizeof tmp, "flag_%c_%u", flag, i);
|
xsnprintf(tmp, sizeof tmp, "hook_flag_%c_%d", flag, i);
|
||||||
event_payload_set_string(ep, tmp, "%s", av->string);
|
cmdq_add_format(new_state, tmp, "%s", av->string);
|
||||||
i++;
|
i++;
|
||||||
av = args_next_value(av);
|
av = args_next_value(av);
|
||||||
}
|
}
|
||||||
@@ -411,7 +425,20 @@ cmdq_insert_hook(__unused struct session *s, struct cmdq_item *item,
|
|||||||
flag = args_next(&ae);
|
flag = args_next(&ae);
|
||||||
}
|
}
|
||||||
|
|
||||||
events_fire(name, ep);
|
a = options_array_first(o);
|
||||||
|
while (a != NULL) {
|
||||||
|
cmdlist = options_array_item_value(a)->cmdlist;
|
||||||
|
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);
|
free(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -802,7 +829,7 @@ cmdq_guard(struct cmdq_item *item, const char *guard, int flags)
|
|||||||
u_int number = item->number;
|
u_int number = item->number;
|
||||||
|
|
||||||
if (c != NULL && (c->flags & CLIENT_CONTROL))
|
if (c != NULL && (c->flags & CLIENT_CONTROL))
|
||||||
control_write_guard(c, guard, t, number, flags);
|
control_write(c, "%%%s %ld %u %d", guard, t, number, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show message from command. */
|
/* Show message from command. */
|
||||||
@@ -850,18 +877,7 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...)
|
|||||||
|
|
||||||
if (c == NULL) {
|
if (c == NULL) {
|
||||||
cmd_get_source(cmd, &file, &line);
|
cmd_get_source(cmd, &file, &line);
|
||||||
if (!cfg_finished) {
|
cfg_add_cause("%s:%u: %s", file, line, msg);
|
||||||
if (file != NULL)
|
|
||||||
cfg_add_cause("%s:%u: %s", file, line, msg);
|
|
||||||
else
|
|
||||||
cfg_add_cause("%s", msg);
|
|
||||||
} else {
|
|
||||||
if (file != NULL) {
|
|
||||||
server_add_message("message: %s:%u: %s", file,
|
|
||||||
line, msg);
|
|
||||||
} else
|
|
||||||
server_add_message("message: %s", msg);
|
|
||||||
}
|
|
||||||
} else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
|
} else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
|
||||||
server_add_message("%s message: %s", c->name, msg);
|
server_add_message("%s message: %s", c->name, msg);
|
||||||
if (~c->flags & CLIENT_UTF8) {
|
if (~c->flags & CLIENT_UTF8) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-refresh-client.c,v 1.55 2026/07/17 08:37:29 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -46,17 +46,36 @@ const struct cmd_entry cmd_refresh_client_entry = {
|
|||||||
static void
|
static void
|
||||||
cmd_refresh_client_update_subscription(struct client *tc, const char *value)
|
cmd_refresh_client_update_subscription(struct client *tc, const char *value)
|
||||||
{
|
{
|
||||||
char *name, *format;
|
char *copy, *split, *name, *what;
|
||||||
enum monitor_type type;
|
enum control_sub_type subtype;
|
||||||
int id;
|
int subid = -1;
|
||||||
|
|
||||||
if (monitor_parse(value, &name, &type, &id, &format) != 0) {
|
copy = name = xstrdup(value);
|
||||||
control_remove_sub(tc, value);
|
if ((split = strchr(copy, ':')) == NULL) {
|
||||||
return;
|
control_remove_sub(tc, copy);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
control_add_sub(tc, name, type, id, format);
|
*split++ = '\0';
|
||||||
free(name);
|
|
||||||
free(format);
|
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
|
static enum cmd_retval
|
||||||
@@ -66,6 +85,7 @@ cmd_refresh_client_control_client_size(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct client *tc = cmdq_get_target_client(item);
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
const char *size = args_get(args, 'C');
|
const char *size = args_get(args, 'C');
|
||||||
u_int w, x, y;
|
u_int w, x, y;
|
||||||
|
struct client_window *cw;
|
||||||
|
|
||||||
if (sscanf(size, "@%u:%ux%u", &w, &x, &y) == 3) {
|
if (sscanf(size, "@%u:%ux%u", &w, &x, &y) == 3) {
|
||||||
if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
|
if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
|
||||||
@@ -75,16 +95,22 @@ cmd_refresh_client_control_client_size(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
log_debug("%s: client %s window @%u: size %ux%u", __func__,
|
log_debug("%s: client %s window @%u: size %ux%u", __func__,
|
||||||
tc->name, w, x, y);
|
tc->name, w, x, y);
|
||||||
control_set_window_size(tc, w, x, y);
|
cw = server_client_add_client_window(tc, w);
|
||||||
|
cw->sx = x;
|
||||||
|
cw->sy = y;
|
||||||
tc->flags |= CLIENT_WINDOWSIZECHANGED;
|
tc->flags |= CLIENT_WINDOWSIZECHANGED;
|
||||||
recalculate_sizes_now(1);
|
recalculate_sizes_now(1);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
if (sscanf(size, "@%u:", &w) == 1) {
|
if (sscanf(size, "@%u:", &w) == 1) {
|
||||||
log_debug("%s: client %s window @%u: no size", __func__,
|
cw = server_client_get_client_window(tc, w);
|
||||||
tc->name, w);
|
if (cw != NULL) {
|
||||||
control_clear_window_size(tc, w);
|
log_debug("%s: client %s window @%u: no size", __func__,
|
||||||
recalculate_sizes_now(1);
|
tc->name, w);
|
||||||
|
cw->sx = 0;
|
||||||
|
cw->sy = 0;
|
||||||
|
recalculate_sizes_now(1);
|
||||||
|
}
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +229,7 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'c'))
|
if (args_has(args, 'c'))
|
||||||
tc->pan_window = NULL;
|
tc->pan_window = NULL;
|
||||||
else {
|
else {
|
||||||
w = active_get_effective_window(tc, tc->session);
|
w = tc->session->curw->window;
|
||||||
if (tc->pan_window != w) {
|
if (tc->pan_window != w) {
|
||||||
tc->pan_window = w;
|
tc->pan_window = w;
|
||||||
tc->pan_ox = tty->oox;
|
tc->pan_ox = tty->oox;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-rename-session.c,v 1.39 2026/07/10 13:38:45 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -49,8 +49,6 @@ cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct session *s = target->s;
|
struct session *s = target->s;
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
char *newname, *tmp;
|
char *newname, *tmp;
|
||||||
|
|
||||||
tmp = format_single_from_target(item, args_string(args, 0));
|
tmp = format_single_from_target(item, args_string(args, 0));
|
||||||
@@ -71,20 +69,13 @@ cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
cmd_find_from_session(&fs, s, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
event_payload_set_session(ep, "session", s);
|
|
||||||
event_payload_set_string(ep, "old_name", "%s", s->name);
|
|
||||||
event_payload_set_string(ep, "new_name", "%s", newname);
|
|
||||||
|
|
||||||
RB_REMOVE(sessions, &sessions, s);
|
RB_REMOVE(sessions, &sessions, s);
|
||||||
free(s->name);
|
free(s->name);
|
||||||
s->name = newname;
|
s->name = newname;
|
||||||
RB_INSERT(sessions, &sessions, s);
|
RB_INSERT(sessions, &sessions, s);
|
||||||
|
|
||||||
server_status_session(s);
|
server_status_session(s);
|
||||||
events_fire("session-renamed", ep);
|
notify_session("session-renamed", s);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-rename-window.c,v 1.30 2026/06/29 18:17:28 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-resize-pane.c,v 1.68 2026/08/31 07:44:39 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -92,7 +92,6 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
server_unzoom_window(w);
|
server_unzoom_window(w);
|
||||||
lc = wp->layout_cell; /* may have been replaced by unzoom */
|
|
||||||
|
|
||||||
if (args_has(args, 'x')) {
|
if (args_has(args, 'x')) {
|
||||||
x = args_percentage(args, 'x', 0, PANE_MAXIMUM, w->sx, &cause);
|
x = args_percentage(args, 'x', 0, PANE_MAXIMUM, w->sx, &cause);
|
||||||
@@ -183,7 +182,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (lc->parent != NULL)
|
if (lc->parent != NULL)
|
||||||
layout_fix_offsets(w);
|
layout_fix_offsets(w);
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
events_fire_window("window-layout-changed", w);
|
notify_window("window-layout-changed", w);
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
@@ -271,10 +270,10 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
|||||||
|
|
||||||
if ((lx == left || lx == left + 1) && ly == wp->yoff - 1) {
|
if ((lx == left || lx == left + 1) && ly == wp->yoff - 1) {
|
||||||
/* Top left corner. */
|
/* Top left corner. */
|
||||||
new_sx = lc->g.sx + (lx - x);
|
new_sx = lc->sx + (lx - x);
|
||||||
if (new_sx < PANE_MINIMUM)
|
if (new_sx < PANE_MINIMUM)
|
||||||
new_sx = PANE_MINIMUM;
|
new_sx = PANE_MINIMUM;
|
||||||
new_sy = lc->g.sy + (ly - y);
|
new_sy = lc->sy + (ly - y);
|
||||||
if (new_sy < PANE_MINIMUM)
|
if (new_sy < PANE_MINIMUM)
|
||||||
new_sy = PANE_MINIMUM;
|
new_sy = PANE_MINIMUM;
|
||||||
new_xoff = x + 1; /* because mouse is on border at xoff - 1 */
|
new_xoff = x + 1; /* because mouse is on border at xoff - 1 */
|
||||||
@@ -284,65 +283,65 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
|||||||
} else if ((lx == right + 1 || lx == right) &&
|
} else if ((lx == right + 1 || lx == right) &&
|
||||||
ly == wp->yoff - 1) {
|
ly == wp->yoff - 1) {
|
||||||
/* Top right corner. */
|
/* Top right corner. */
|
||||||
new_sx = x - lc->g.xoff;
|
new_sx = x - lc->xoff;
|
||||||
if (new_sx < PANE_MINIMUM)
|
if (new_sx < PANE_MINIMUM)
|
||||||
new_sx = PANE_MINIMUM;
|
new_sx = PANE_MINIMUM;
|
||||||
new_sy = lc->g.sy + (ly - y);
|
new_sy = lc->sy + (ly - y);
|
||||||
if (new_sy < PANE_MINIMUM)
|
if (new_sy < PANE_MINIMUM)
|
||||||
new_sy = PANE_MINIMUM;
|
new_sy = PANE_MINIMUM;
|
||||||
new_yoff = y + 1;
|
new_yoff = y + 1;
|
||||||
layout_set_size(lc, new_sx, new_sy, lc->g.xoff, new_yoff);
|
layout_set_size(lc, new_sx, new_sy, lc->xoff, new_yoff);
|
||||||
resizes++;
|
resizes++;
|
||||||
} else if ((lx == left || lx == left + 1) &&
|
} else if ((lx == left || lx == left + 1) &&
|
||||||
ly == wp->yoff + sy) {
|
ly == wp->yoff + sy) {
|
||||||
/* Bottom left corner. */
|
/* Bottom left corner. */
|
||||||
new_sx = lc->g.sx + (lx - x);
|
new_sx = lc->sx + (lx - x);
|
||||||
if (new_sx < PANE_MINIMUM)
|
if (new_sx < PANE_MINIMUM)
|
||||||
new_sx = PANE_MINIMUM;
|
new_sx = PANE_MINIMUM;
|
||||||
new_sy = y - lc->g.yoff;
|
new_sy = y - lc->yoff;
|
||||||
if (new_sy < PANE_MINIMUM)
|
if (new_sy < PANE_MINIMUM)
|
||||||
return;
|
return;
|
||||||
new_xoff = x + 1;
|
new_xoff = x + 1;
|
||||||
layout_set_size(lc, new_sx, new_sy, new_xoff, lc->g.yoff);
|
layout_set_size(lc, new_sx, new_sy, new_xoff, lc->yoff);
|
||||||
resizes++;
|
resizes++;
|
||||||
} else if ((lx == right + 1 || lx == right) &&
|
} else if ((lx == right + 1 || lx == right) &&
|
||||||
ly == wp->yoff + sy) {
|
ly == wp->yoff + sy) {
|
||||||
/* Bottom right corner. */
|
/* Bottom right corner. */
|
||||||
new_sx = x - lc->g.xoff;
|
new_sx = x - lc->xoff;
|
||||||
if (new_sx < PANE_MINIMUM)
|
if (new_sx < PANE_MINIMUM)
|
||||||
new_sx = PANE_MINIMUM;
|
new_sx = PANE_MINIMUM;
|
||||||
new_sy = y - lc->g.yoff;
|
new_sy = y - lc->yoff;
|
||||||
if (new_sy < PANE_MINIMUM)
|
if (new_sy < PANE_MINIMUM)
|
||||||
new_sy = PANE_MINIMUM;
|
new_sy = PANE_MINIMUM;
|
||||||
layout_set_size(lc, new_sx, new_sy, lc->g.xoff, lc->g.yoff);
|
layout_set_size(lc, new_sx, new_sy, lc->xoff, lc->yoff);
|
||||||
resizes++;
|
resizes++;
|
||||||
} else if (lx == right) {
|
} else if (lx == right) {
|
||||||
/* Right border. */
|
/* Right border. */
|
||||||
new_sx = x - lc->g.xoff;
|
new_sx = x - lc->xoff;
|
||||||
if (new_sx < PANE_MINIMUM)
|
if (new_sx < PANE_MINIMUM)
|
||||||
return;
|
return;
|
||||||
layout_set_size(lc, new_sx, lc->g.sy, lc->g.xoff, lc->g.yoff);
|
layout_set_size(lc, new_sx, lc->sy, lc->xoff, lc->yoff);
|
||||||
resizes++;
|
resizes++;
|
||||||
} else if (lx == left) {
|
} else if (lx == left) {
|
||||||
/* Left border. */
|
/* Left border. */
|
||||||
new_sx = lc->g.sx + (lx - x);
|
new_sx = lc->sx + (lx - x);
|
||||||
if (new_sx < PANE_MINIMUM)
|
if (new_sx < PANE_MINIMUM)
|
||||||
return;
|
return;
|
||||||
new_xoff = x + 1;
|
new_xoff = x + 1;
|
||||||
layout_set_size(lc, new_sx, lc->g.sy, new_xoff, lc->g.yoff);
|
layout_set_size(lc, new_sx, lc->sy, new_xoff, lc->yoff);
|
||||||
resizes++;
|
resizes++;
|
||||||
} else if (ly == wp->yoff + sy) {
|
} else if (ly == wp->yoff + sy) {
|
||||||
/* Bottom border. */
|
/* Bottom border. */
|
||||||
new_sy = y - lc->g.yoff;
|
new_sy = y - lc->yoff;
|
||||||
if (new_sy < PANE_MINIMUM)
|
if (new_sy < PANE_MINIMUM)
|
||||||
return;
|
return;
|
||||||
layout_set_size(lc, lc->g.sx, new_sy, lc->g.xoff, lc->g.yoff);
|
layout_set_size(lc, lc->sx, new_sy, lc->xoff, lc->yoff);
|
||||||
resizes++;
|
resizes++;
|
||||||
} else if (ly == wp->yoff - 1) {
|
} else if (ly == wp->yoff - 1) {
|
||||||
/* Top border (move instead of resize). */
|
/* Top border (move instead of resize). */
|
||||||
new_xoff = lc->g.xoff + (x - lx);
|
new_xoff = lc->xoff + (x - lx);
|
||||||
new_yoff = y + 1;
|
new_yoff = y + 1;
|
||||||
layout_set_size(lc, lc->g.sx, lc->g.sy, new_xoff, new_yoff);
|
layout_set_size(lc, lc->sx, lc->sy, new_xoff, new_yoff);
|
||||||
resizes++;
|
resizes++;
|
||||||
}
|
}
|
||||||
if (resizes != 0) {
|
if (resizes != 0) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-resize-window.c,v 1.10 2023/06/30 13:19:32 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2018 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-respawn-pane.c,v 1.40 2026/07/03 16:09:49 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -34,8 +34,8 @@ const struct cmd_entry cmd_respawn_pane_entry = {
|
|||||||
.name = "respawn-pane",
|
.name = "respawn-pane",
|
||||||
.alias = "respawnp",
|
.alias = "respawnp",
|
||||||
|
|
||||||
.args = { "c:e:Ekt:", 0, -1, NULL },
|
.args = { "c:e:kt:", 0, -1, NULL },
|
||||||
.usage = "[-Ek] [-c start-directory] [-e environment] "
|
.usage = "[-k] [-c start-directory] [-e environment] "
|
||||||
CMD_TARGET_PANE_USAGE " [shell-command [argument ...]]",
|
CMD_TARGET_PANE_USAGE " [shell-command [argument ...]]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
@@ -75,8 +75,6 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
sc.cwd = args_get(args, 'c');
|
sc.cwd = args_get(args, 'c');
|
||||||
|
|
||||||
sc.flags = SPAWN_RESPAWN;
|
sc.flags = SPAWN_RESPAWN;
|
||||||
if (args_has(args, 'E'))
|
|
||||||
sc.flags |= SPAWN_EMPTY;
|
|
||||||
if (args_has(args, 'k'))
|
if (args_has(args, 'k'))
|
||||||
sc.flags |= SPAWN_KILL;
|
sc.flags |= SPAWN_KILL;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-respawn-window.c,v 1.51 2026/07/03 16:09:49 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -34,8 +34,8 @@ const struct cmd_entry cmd_respawn_window_entry = {
|
|||||||
.name = "respawn-window",
|
.name = "respawn-window",
|
||||||
.alias = "respawnw",
|
.alias = "respawnw",
|
||||||
|
|
||||||
.args = { "c:e:Ekt:", 0, -1, NULL },
|
.args = { "c:e:kt:", 0, -1, NULL },
|
||||||
.usage = "[-Ek] [-c start-directory] [-e environment] "
|
.usage = "[-k] [-c start-directory] [-e environment] "
|
||||||
CMD_TARGET_WINDOW_USAGE " [shell-command [argument ...]]",
|
CMD_TARGET_WINDOW_USAGE " [shell-command [argument ...]]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
@@ -74,8 +74,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
sc.cwd = args_get(args, 'c');
|
sc.cwd = args_get(args, 'c');
|
||||||
|
|
||||||
sc.flags = SPAWN_RESPAWN;
|
sc.flags = SPAWN_RESPAWN;
|
||||||
if (args_has(args, 'E'))
|
|
||||||
sc.flags |= SPAWN_EMPTY;
|
|
||||||
if (args_has(args, 'k'))
|
if (args_has(args, 'k'))
|
||||||
sc.flags |= SPAWN_KILL;
|
sc.flags |= SPAWN_KILL;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-rotate-window.c,v 1.34 2026/06/22 08:47:45 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-run-shell.c,v 1.94 2026/08/25 06:04:33 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -79,10 +79,7 @@ static void
|
|||||||
cmd_run_shell_print(struct job *job, const char *msg)
|
cmd_run_shell_print(struct job *job, const char *msg)
|
||||||
{
|
{
|
||||||
struct cmd_run_shell_data *cdata = job_get_data(job);
|
struct cmd_run_shell_data *cdata = job_get_data(job);
|
||||||
struct client *c;
|
|
||||||
struct session *s;
|
|
||||||
struct window_pane *wp = NULL;
|
struct window_pane *wp = NULL;
|
||||||
struct window *w;
|
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
struct window_mode_entry *wme;
|
struct window_mode_entry *wme;
|
||||||
|
|
||||||
@@ -93,12 +90,8 @@ cmd_run_shell_print(struct job *job, const char *msg)
|
|||||||
cmdq_print(cdata->item, "%s", msg);
|
cmdq_print(cdata->item, "%s", msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
c = cdata->client;
|
if (cdata->item != NULL && cdata->client != NULL)
|
||||||
if (c != NULL && c->session != NULL) {
|
wp = server_client_get_pane(cdata->client);
|
||||||
s = c->session;
|
|
||||||
w = active_get_effective_window(c, s);
|
|
||||||
wp = w->active;
|
|
||||||
}
|
|
||||||
if (wp == NULL && cmd_find_from_nothing(&fs, 0) == 0)
|
if (wp == NULL && cmd_find_from_nothing(&fs, 0) == 0)
|
||||||
wp = fs.wp;
|
wp = fs.wp;
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
@@ -107,8 +100,7 @@ cmd_run_shell_print(struct job *job, const char *msg)
|
|||||||
|
|
||||||
wme = TAILQ_FIRST(&wp->modes);
|
wme = TAILQ_FIRST(&wp->modes);
|
||||||
if (wme == NULL || wme->mode != &window_view_mode)
|
if (wme == NULL || wme->mode != &window_view_mode)
|
||||||
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL,
|
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL);
|
||||||
NULL);
|
|
||||||
window_copy_add(wp, 1, "%s", msg);
|
window_copy_add(wp, 1, "%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,11 +232,9 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
|
|||||||
} else if (item == NULL) {
|
} else if (item == NULL) {
|
||||||
new_item = cmdq_get_command(cmdlist, NULL);
|
new_item = cmdq_get_command(cmdlist, NULL);
|
||||||
cmdq_append(c, new_item);
|
cmdq_append(c, new_item);
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
} else {
|
} else {
|
||||||
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
|
||||||
cmdq_insert_after(item, new_item);
|
cmdq_insert_after(item, new_item);
|
||||||
cmd_list_free(cmdlist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cdata->item != NULL)
|
if (cdata->item != NULL)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-save-buffer.c,v 1.57 2025/10/28 07:32:26 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-select-layout.c,v 1.43 2026/07/10 13:38:45 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -139,7 +139,7 @@ changed:
|
|||||||
free(oldlayout);
|
free(oldlayout);
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
events_fire_window("window-layout-changed", w);
|
notify_window("window-layout-changed", w);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-select-pane.c,v 1.78 2026/08/20 09:19:24 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -68,11 +68,10 @@ cmd_select_pane_redraw(struct window *w)
|
|||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (c->session == NULL || (c->flags & CLIENT_CONTROL))
|
if (c->session == NULL || (c->flags & CLIENT_CONTROL))
|
||||||
continue;
|
continue;
|
||||||
if (active_get_effective_window(c, c->session) == w &&
|
if (c->session->curw->window == w && tty_window_bigger(&c->tty))
|
||||||
tty_window_bigger(&c->tty))
|
|
||||||
server_redraw_client(c);
|
server_redraw_client(c);
|
||||||
else {
|
else {
|
||||||
if (active_get_effective_window(c, c->session) == w)
|
if (c->session->curw->window == w)
|
||||||
c->flags |= CLIENT_REDRAWBORDERS;
|
c->flags |= CLIENT_REDRAWBORDERS;
|
||||||
if (session_has(c->session, w))
|
if (session_has(c->session, w))
|
||||||
c->flags |= CLIENT_REDRAWSTATUS;
|
c->flags |= CLIENT_REDRAWSTATUS;
|
||||||
@@ -81,69 +80,6 @@ cmd_select_pane_redraw(struct window *w)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_select_pane_marked_pane(struct cmd *self, struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
struct args *args = cmd_get_args(self);
|
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
struct winlink *wl = target->wl;
|
|
||||||
struct window_pane *wp = target->wp, *lwp = NULL, *mwp;
|
|
||||||
struct session *s = target->s;
|
|
||||||
|
|
||||||
if (args_has(args, 'm') && !window_pane_is_visible(wp))
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
if (server_check_marked())
|
|
||||||
lwp = marked_pane.wp;
|
|
||||||
|
|
||||||
if (args_has(args, 'M') || server_is_marked(s, wl, wp))
|
|
||||||
server_clear_marked();
|
|
||||||
else
|
|
||||||
server_set_marked(s, wl, wp);
|
|
||||||
mwp = marked_pane.wp;
|
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
if (mwp != NULL)
|
|
||||||
cmd_find_from_pane(&fs, mwp, 0);
|
|
||||||
else if (lwp != NULL)
|
|
||||||
cmd_find_from_pane(&fs, lwp, 0);
|
|
||||||
else
|
|
||||||
cmd_find_from_pane(&fs, wp, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
if (mwp != NULL) {
|
|
||||||
event_payload_set_pane(ep, "pane", mwp);
|
|
||||||
event_payload_set_pane(ep, "new_pane", mwp);
|
|
||||||
event_payload_set_window(ep, "window", mwp->window);
|
|
||||||
} else if (lwp != NULL) {
|
|
||||||
event_payload_set_pane(ep, "pane", lwp);
|
|
||||||
event_payload_set_window(ep, "window", lwp->window);
|
|
||||||
} else {
|
|
||||||
event_payload_set_pane(ep, "pane", wp);
|
|
||||||
event_payload_set_window(ep, "window", wp->window);
|
|
||||||
}
|
|
||||||
if (lwp != NULL)
|
|
||||||
event_payload_set_pane(ep, "old_pane", lwp);
|
|
||||||
event_payload_set_int(ep, "marked", mwp != NULL);
|
|
||||||
events_fire("marked-pane-changed", ep);
|
|
||||||
|
|
||||||
if (lwp != NULL) {
|
|
||||||
lwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|PANE_THEMECHANGED);
|
|
||||||
server_redraw_window_borders(lwp->window);
|
|
||||||
server_status_window(lwp->window);
|
|
||||||
}
|
|
||||||
if (mwp != NULL) {
|
|
||||||
mwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|PANE_THEMECHANGED);
|
|
||||||
server_redraw_window_borders(mwp->window);
|
|
||||||
server_status_window(mwp->window);
|
|
||||||
}
|
|
||||||
if (window_pane_is_floating(wp)) {
|
|
||||||
window_redraw_active_switch(wp->window, wp);
|
|
||||||
window_set_active_pane(wp->window, wp, 1);
|
|
||||||
}
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
@@ -151,17 +87,15 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
const struct cmd_entry *entry = cmd_get_entry(self);
|
const struct cmd_entry *entry = cmd_get_entry(self);
|
||||||
struct cmd_find_state *current = cmdq_get_current(item);
|
struct cmd_find_state *current = cmdq_get_current(item);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct event_payload *ep;
|
struct client *c = cmdq_get_client(item);
|
||||||
struct cmd_find_state fs;
|
|
||||||
struct winlink *wl = target->wl;
|
struct winlink *wl = target->wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct session *s = target->s;
|
struct session *s = target->s;
|
||||||
struct window_pane *wp = target->wp, *lastwp;
|
struct window_pane *wp = target->wp, *activewp, *lastwp, *markedwp;
|
||||||
struct options *oo = wp->options;
|
struct options *oo = wp->options;
|
||||||
char *title;
|
char *title;
|
||||||
const char *style;
|
const char *style;
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
int visible, Zflag = args_has(args, 'Z');
|
|
||||||
|
|
||||||
if (entry == &cmd_last_pane_entry || args_has(args, 'l')) {
|
if (entry == &cmd_last_pane_entry || args_has(args, 'l')) {
|
||||||
/*
|
/*
|
||||||
@@ -187,25 +121,51 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
server_redraw_window_borders(lastwp->window);
|
server_redraw_window_borders(lastwp->window);
|
||||||
server_status_window(lastwp->window);
|
server_status_window(lastwp->window);
|
||||||
} else {
|
} else {
|
||||||
if (w->modal != NULL && lastwp != w->modal)
|
if (window_push_zoom(w, 0, args_has(args, 'Z')))
|
||||||
visible = 1;
|
|
||||||
else
|
|
||||||
visible = window_pane_is_visible(lastwp);
|
|
||||||
if (!visible && window_push_zoom(w, 0, Zflag))
|
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
window_redraw_active_switch(w, lastwp);
|
window_redraw_active_switch(w, lastwp);
|
||||||
if (window_set_active_pane(w, lastwp, 1)) {
|
if (window_set_active_pane(w, lastwp, 1)) {
|
||||||
cmd_find_from_winlink(current, wl, 0);
|
cmd_find_from_winlink(current, wl, 0);
|
||||||
cmd_select_pane_redraw(w);
|
cmd_select_pane_redraw(w);
|
||||||
}
|
}
|
||||||
if (!visible && window_pop_zoom(w))
|
if (window_pop_zoom(w))
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
}
|
}
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(args, 'm') || args_has(args, 'M'))
|
if (args_has(args, 'm') || args_has(args, 'M')) {
|
||||||
return (cmd_select_pane_marked_pane(self, item));
|
if (args_has(args, 'm') && !window_pane_is_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();
|
||||||
|
else
|
||||||
|
server_set_marked(s, wl, wp);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if (window_pane_is_floating(wp)) {
|
||||||
|
window_redraw_active_switch(w, wp);
|
||||||
|
window_set_active_pane(w, wp, 1);
|
||||||
|
}
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
style = args_get(args, 'P');
|
style = args_get(args, 'P');
|
||||||
if (style != NULL) {
|
if (style != NULL) {
|
||||||
@@ -258,13 +218,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'T')) {
|
if (args_has(args, 'T')) {
|
||||||
title = format_single_from_target(item, args_get(args, 'T'));
|
title = format_single_from_target(item, args_get(args, 'T'));
|
||||||
if (screen_set_title(&wp->base, title, 0)) {
|
if (screen_set_title(&wp->base, title, 0)) {
|
||||||
ep = event_payload_create();
|
notify_pane("pane-title-changed", wp);
|
||||||
cmd_find_from_pane(&fs, wp, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
event_payload_set_pane(ep, "pane", wp);
|
|
||||||
event_payload_set_window(ep, "window", wp->window);
|
|
||||||
event_payload_set_string(ep, "new_title", "%s", title);
|
|
||||||
events_fire("pane-title-changed", ep);
|
|
||||||
server_redraw_window_borders(wp->window);
|
server_redraw_window_borders(wp->window);
|
||||||
server_status_window(wp->window);
|
server_status_window(wp->window);
|
||||||
}
|
}
|
||||||
@@ -272,20 +226,22 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wp == w->active)
|
if (c != NULL && c->session != NULL && (c->flags & CLIENT_ACTIVEPANE))
|
||||||
return (CMD_RETURN_NORMAL);
|
activewp = server_client_get_pane(c);
|
||||||
if (w->modal != NULL && wp != w->modal)
|
|
||||||
visible = 1;
|
|
||||||
else
|
else
|
||||||
visible = window_pane_is_visible(wp);
|
activewp = w->active;
|
||||||
if (!visible && window_push_zoom(w, 0, Zflag))
|
if (wp == activewp)
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
if (window_push_zoom(w, 0, args_has(args, 'Z')))
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
window_redraw_active_switch(w, wp);
|
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);
|
cmd_find_from_winlink_pane(current, wl, wp, 0);
|
||||||
cmdq_insert_hook(s, item, current, "after-select-pane");
|
cmdq_insert_hook(s, item, current, "after-select-pane");
|
||||||
cmd_select_pane_redraw(w);
|
cmd_select_pane_redraw(w);
|
||||||
if (!visible && window_pop_zoom(w))
|
if (window_pop_zoom(w))
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-select-window.c,v 1.30 2021/08/21 10:22:39 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -33,8 +33,8 @@ const struct cmd_entry cmd_select_window_entry = {
|
|||||||
.name = "select-window",
|
.name = "select-window",
|
||||||
.alias = "selectw",
|
.alias = "selectw",
|
||||||
|
|
||||||
.args = { "LlSnpTt:", 0, 0, NULL },
|
.args = { "lnpTt:", 0, 0, NULL },
|
||||||
.usage = "[-LlnpST] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-lnpT] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
@@ -88,9 +88,8 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct client *c = cmdq_get_client(item);
|
struct client *c = cmdq_get_client(item);
|
||||||
struct cmd_find_state *current = cmdq_get_current(item);
|
struct cmd_find_state *current = cmdq_get_current(item);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct winlink *wl = target->wl, *current_wl;
|
struct winlink *wl = target->wl;
|
||||||
struct session *s = target->s;
|
struct session *s = target->s;
|
||||||
enum active_window_mode mode;
|
|
||||||
int next, previous, last, activity;
|
int next, previous, last, activity;
|
||||||
|
|
||||||
next = (cmd_get_entry(self) == &cmd_next_window_entry);
|
next = (cmd_get_entry(self) == &cmd_next_window_entry);
|
||||||
@@ -103,104 +102,48 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'l'))
|
if (args_has(args, 'l'))
|
||||||
last = 1;
|
last = 1;
|
||||||
|
|
||||||
if (args_has(args, 'L') || args_has(args, 'S')) {
|
|
||||||
if (c == NULL || c->session == NULL) {
|
|
||||||
cmdq_error(item, "no current client");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if (args_has(args, 'S'))
|
|
||||||
mode = ACTIVE_SHARED;
|
|
||||||
else
|
|
||||||
mode = ACTIVE_LOCAL;
|
|
||||||
active_set_local_window(c, s, mode);
|
|
||||||
if (!next &&
|
|
||||||
!previous &&
|
|
||||||
!last &&
|
|
||||||
!args_has(args, 't') &&
|
|
||||||
!args_has(args, 'T')) {
|
|
||||||
if (current->s == s) {
|
|
||||||
if (c->session == s)
|
|
||||||
cmd_find_from_client(current, c, 0);
|
|
||||||
else
|
|
||||||
cmd_find_from_session(current, s, 0);
|
|
||||||
}
|
|
||||||
if (c->session == s)
|
|
||||||
server_redraw_client(c);
|
|
||||||
else
|
|
||||||
server_redraw_session(s);
|
|
||||||
cmdq_insert_hook(s, item, current, "after-select-window");
|
|
||||||
recalculate_sizes();
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (active_is_local_window(c, s))
|
|
||||||
mode = ACTIVE_LOCAL;
|
|
||||||
else
|
|
||||||
mode = ACTIVE_SHARED;
|
|
||||||
if (next || previous || last) {
|
if (next || previous || last) {
|
||||||
activity = args_has(args, 'a');
|
activity = args_has(args, 'a');
|
||||||
if (next) {
|
if (next) {
|
||||||
if (active_next_window(c, s, activity) != 0) {
|
if (session_next(s, activity) != 0) {
|
||||||
cmdq_error(item, "no next window");
|
cmdq_error(item, "no next window");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
} else if (previous) {
|
} else if (previous) {
|
||||||
if (active_previous_window(c, s, activity) != 0) {
|
if (session_previous(s, activity) != 0) {
|
||||||
cmdq_error(item, "no previous window");
|
cmdq_error(item, "no previous window");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (active_last_window(c, s) != 0) {
|
if (session_last(s) != 0) {
|
||||||
cmdq_error(item, "no last window");
|
cmdq_error(item, "no last window");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mode == ACTIVE_LOCAL && c != NULL && c->session == s)
|
cmd_find_from_session(current, s, 0);
|
||||||
cmd_find_from_client(current, c, 0);
|
server_redraw_session(s);
|
||||||
else
|
|
||||||
cmd_find_from_session(current, s, 0);
|
|
||||||
if (mode == ACTIVE_LOCAL && c != NULL && c->session == s)
|
|
||||||
server_redraw_client(c);
|
|
||||||
else
|
|
||||||
server_redraw_session(s);
|
|
||||||
cmdq_insert_hook(s, item, current, "after-select-window");
|
cmdq_insert_hook(s, item, current, "after-select-window");
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* If -T and select-window is invoked on same window as
|
* If -T and select-window is invoked on same window as
|
||||||
* current, switch to previous window.
|
* current, switch to previous window.
|
||||||
*/
|
*/
|
||||||
current_wl = active_get_effective_winlink(c, s);
|
if (args_has(args, 'T') && wl == s->curw) {
|
||||||
if (args_has(args, 'T') && wl == current_wl) {
|
if (session_last(s) != 0) {
|
||||||
if (active_last_window(c, s) != 0) {
|
|
||||||
cmdq_error(item, "no last window");
|
cmdq_error(item, "no last window");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if (current->s == s) {
|
if (current->s == s)
|
||||||
if (mode == ACTIVE_LOCAL && c != NULL &&
|
|
||||||
c->session == s)
|
|
||||||
cmd_find_from_client(current, c, 0);
|
|
||||||
else
|
|
||||||
cmd_find_from_session(current, s, 0);
|
|
||||||
}
|
|
||||||
if (mode == ACTIVE_LOCAL && c != NULL && c->session == s)
|
|
||||||
server_redraw_client(c);
|
|
||||||
else
|
|
||||||
server_redraw_session(s);
|
|
||||||
} else if (active_select_window(c, s, wl) == 0) {
|
|
||||||
if (mode == ACTIVE_LOCAL && c != NULL && c->session == s)
|
|
||||||
cmd_find_from_client(current, c, 0);
|
|
||||||
else
|
|
||||||
cmd_find_from_session(current, s, 0);
|
cmd_find_from_session(current, s, 0);
|
||||||
if (mode == ACTIVE_LOCAL && c != NULL && c->session == s)
|
server_redraw_session(s);
|
||||||
server_redraw_client(c);
|
} else if (session_select(s, wl->idx) == 0) {
|
||||||
else
|
cmd_find_from_session(current, s, 0);
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
}
|
}
|
||||||
cmdq_insert_hook(s, item, current, "after-select-window");
|
cmdq_insert_hook(s, item, current, "after-select-window");
|
||||||
}
|
}
|
||||||
if (c != NULL && c->session != NULL)
|
if (c != NULL && c->session != NULL)
|
||||||
active_get_effective_window(c, s)->latest = c;
|
s->curw->window->latest = c;
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-send-keys.c,v 1.81 2026/06/11 19:13:34 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-server-access.c,v 1.6 2026/06/09 12:58:40 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 Dallas Lyons <dallasdlyons@gmail.com>
|
* Copyright (c) 2021 Dallas Lyons <dallasdlyons@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-set-buffer.c,v 1.38 2026/08/24 07:05:23 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -100,7 +100,6 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
free(bufname);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,10 +107,8 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "no data specified");
|
cmdq_error(item, "no data specified");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((newsize = strlen(args_string(args, 0))) == 0) {
|
if ((newsize = strlen(args_string(args, 0))) == 0)
|
||||||
free(bufname);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
|
||||||
|
|
||||||
if (args_has(args, 'a') && pb != NULL) {
|
if (args_has(args, 'a') && pb != NULL) {
|
||||||
olddata = paste_buffer_data(pb, &bufsize);
|
olddata = paste_buffer_data(pb, &bufsize);
|
||||||
@@ -130,7 +127,6 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'w') && tc != NULL)
|
if (args_has(args, 'w') && tc != NULL)
|
||||||
tty_set_selection(&tc->tty, "", bufdata, bufsize);
|
tty_set_selection(&tc->tty, "", bufdata, bufsize);
|
||||||
|
|
||||||
free(bufname);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-set-environment.c,v 1.29 2025/04/09 06:27:43 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
196
cmd-set-option.c
196
cmd-set-option.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-set-option.c,v 1.146 2026/07/10 15:20:06 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -31,10 +31,6 @@ static enum args_parse_type cmd_set_option_args_parse(struct args *,
|
|||||||
u_int, char **);
|
u_int, char **);
|
||||||
static enum cmd_retval cmd_set_option_exec(struct cmd *,
|
static enum cmd_retval cmd_set_option_exec(struct cmd *,
|
||||||
struct cmdq_item *);
|
struct cmdq_item *);
|
||||||
static enum cmd_retval cmd_set_hook_event_exec(struct cmd *,
|
|
||||||
struct cmdq_item *);
|
|
||||||
static enum cmd_retval cmd_set_hook_monitor_exec(struct cmdq_item *,
|
|
||||||
struct args *, int);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_set_option_entry = {
|
const struct cmd_entry cmd_set_option_entry = {
|
||||||
.name = "set-option",
|
.name = "set-option",
|
||||||
@@ -66,9 +62,8 @@ const struct cmd_entry cmd_set_hook_entry = {
|
|||||||
.name = "set-hook",
|
.name = "set-hook",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "agpERTt:uB:w", 0, 2, cmd_set_option_args_parse },
|
.args = { "agpRt:uw", 1, 2, cmd_set_option_args_parse },
|
||||||
.usage = "[-agpERTuw] [-B name:what:format] " CMD_TARGET_PANE_USAGE " "
|
.usage = "[-agpRuw] " CMD_TARGET_PANE_USAGE " hook [command]",
|
||||||
"[hook] [command]",
|
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
@@ -77,152 +72,14 @@ const struct cmd_entry cmd_set_hook_entry = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static enum args_parse_type
|
static enum args_parse_type
|
||||||
cmd_set_option_args_parse(struct args *args, u_int idx,
|
cmd_set_option_args_parse(__unused struct args *args, u_int idx,
|
||||||
__unused char **cause)
|
__unused char **cause)
|
||||||
{
|
{
|
||||||
if (args_has(args, 'B'))
|
|
||||||
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
|
||||||
if (idx == 1)
|
if (idx == 1)
|
||||||
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
return (ARGS_PARSE_COMMANDS_OR_STRING);
|
||||||
return (ARGS_PARSE_STRING);
|
return (ARGS_PARSE_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_set_hook_event_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 event_payload *ep;
|
|
||||||
struct client *c;
|
|
||||||
char *argument;
|
|
||||||
|
|
||||||
if (args_count(args) == 0) {
|
|
||||||
cmdq_error(item, "missing argument");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if (args_count(args) != 1) {
|
|
||||||
cmdq_error(item, "too many arguments");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
argument = format_single_from_target(item, args_string(args, 0));
|
|
||||||
if (*argument != '@') {
|
|
||||||
cmdq_error(item, "event name must start with @");
|
|
||||||
free(argument);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
event_payload_set_target(ep, target);
|
|
||||||
c = cmdq_get_client(item);
|
|
||||||
if (c != NULL)
|
|
||||||
event_payload_set_client(ep, "client", c);
|
|
||||||
if (target->s != NULL)
|
|
||||||
event_payload_set_session(ep, "session", target->s);
|
|
||||||
if (target->w != NULL)
|
|
||||||
event_payload_set_window(ep, "window", target->w);
|
|
||||||
if (target->wl != NULL)
|
|
||||||
event_payload_set_int(ep, "window_index", target->wl->idx);
|
|
||||||
else if (target->idx != -1)
|
|
||||||
event_payload_set_int(ep, "window_index", target->idx);
|
|
||||||
if (target->wp != NULL)
|
|
||||||
event_payload_set_pane(ep, "pane", target->wp);
|
|
||||||
events_fire(argument, ep);
|
|
||||||
free(argument);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_set_hook_monitor_exec(struct cmdq_item *item, struct args *args, int window)
|
|
||||||
{
|
|
||||||
struct cmd_find_state *target = cmdq_get_target(item), fs;
|
|
||||||
struct options *oo;
|
|
||||||
struct options_entry *o;
|
|
||||||
struct session *s = NULL;
|
|
||||||
char *cause = NULL, *name = NULL, *format = NULL;
|
|
||||||
char *expanded = NULL, *newvalue = NULL;
|
|
||||||
const char *value, *old;
|
|
||||||
enum monitor_type type;
|
|
||||||
int id, scope, flags = 0;
|
|
||||||
|
|
||||||
if (args_count(args) > 1) {
|
|
||||||
cmdq_error(item, "too many arguments");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
value = args_get(args, 'B');
|
|
||||||
if (args_has(args, 'u')) {
|
|
||||||
if (monitor_parse(value, &name, &type, &id, &format) != 0)
|
|
||||||
name = xstrdup(value);
|
|
||||||
free(format);
|
|
||||||
format = NULL;
|
|
||||||
} else {
|
|
||||||
if (monitor_parse(value, &name, &type, &id, &format) != 0) {
|
|
||||||
cmdq_error(item, "invalid subscription: %s", value);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*name != '@') {
|
|
||||||
cmdq_error(item, "monitor hook name must start with @");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
scope = options_scope_from_name(args, window, name, target, &oo,
|
|
||||||
&cause);
|
|
||||||
if (scope == OPTIONS_TABLE_NONE) {
|
|
||||||
cmdq_error(item, "%s", cause);
|
|
||||||
free(cause);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
cmd_find_copy_state(&fs, target);
|
|
||||||
|
|
||||||
if (args_has(args, 'u')) {
|
|
||||||
hooks_monitor_remove(oo, name);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args_count(args) != 0) {
|
|
||||||
value = args_string(args, 0);
|
|
||||||
if (args_has(args, 'F')) {
|
|
||||||
expanded = format_single_from_target(item, value);
|
|
||||||
value = expanded;
|
|
||||||
}
|
|
||||||
o = options_get_only(oo, name);
|
|
||||||
if (!args_has(args, 'o') || o == NULL) {
|
|
||||||
if (args_has(args, 'a') && o != NULL) {
|
|
||||||
old = options_get_string(oo, name);
|
|
||||||
xasprintf(&newvalue, "%s%s", old, value);
|
|
||||||
value = newvalue;
|
|
||||||
}
|
|
||||||
options_set_string(oo, name, 0, "%s", value);
|
|
||||||
options_push_changes(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oo != global_options &&
|
|
||||||
oo != global_s_options &&
|
|
||||||
oo != global_w_options)
|
|
||||||
s = target->s;
|
|
||||||
if (args_has(args, 'T'))
|
|
||||||
flags |= MONITOR_NOTIFY_TRUE;
|
|
||||||
hooks_monitor_add(item, oo, name, type, id, format, flags, &fs, s);
|
|
||||||
|
|
||||||
out:
|
|
||||||
free(newvalue);
|
|
||||||
free(expanded);
|
|
||||||
free(name);
|
|
||||||
free(format);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
free(newvalue);
|
|
||||||
free(expanded);
|
|
||||||
free(name);
|
|
||||||
free(format);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
@@ -232,34 +89,26 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct window_pane *loop;
|
struct window_pane *loop;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
struct options_entry *parent, *o, *po;
|
struct options_entry *parent, *o, *po;
|
||||||
char *name, *argument, *cause;
|
char *name, *argument, *expanded = NULL;
|
||||||
char *expanded = NULL, *array_key = NULL;
|
char *cause;
|
||||||
const char *value;
|
const char *value;
|
||||||
int window, already, error, ambiguous;
|
int window, idx, already, error, ambiguous;
|
||||||
int scope;
|
int scope;
|
||||||
|
|
||||||
window = (cmd_get_entry(self) == &cmd_set_window_option_entry);
|
window = (cmd_get_entry(self) == &cmd_set_window_option_entry);
|
||||||
if (cmd_get_entry(self) == &cmd_set_hook_entry && args_has(args, 'E'))
|
|
||||||
return (cmd_set_hook_event_exec(self, item));
|
|
||||||
if (cmd_get_entry(self) == &cmd_set_hook_entry && args_has(args, 'B'))
|
|
||||||
return (cmd_set_hook_monitor_exec(item, args, window));
|
|
||||||
if (args_count(args) == 0) {
|
|
||||||
cmdq_error(item, "missing argument");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expand argument. */
|
/* Expand argument. */
|
||||||
argument = format_single_from_target(item, args_string(args, 0));
|
argument = format_single_from_target(item, args_string(args, 0));
|
||||||
|
|
||||||
/* If set-hook -R, fire the hook straight away. */
|
/* If set-hook -R, fire the hook straight away. */
|
||||||
if (cmd_get_entry(self) == &cmd_set_hook_entry && args_has(args, 'R')) {
|
if (cmd_get_entry(self) == &cmd_set_hook_entry && args_has(args, 'R')) {
|
||||||
hooks_run(item, argument);
|
notify_hook(item, argument);
|
||||||
free(argument);
|
free(argument);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse option name and array key. */
|
/* Parse option name and index. */
|
||||||
name = options_match(argument, &array_key, &ambiguous);
|
name = options_match(argument, &idx, &ambiguous);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
if (args_has(args, 'q'))
|
if (args_has(args, 'q'))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -291,23 +140,21 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
o = options_get_only(oo, name);
|
o = options_get_only(oo, name);
|
||||||
parent = options_get(oo, name);
|
parent = options_get(oo, name);
|
||||||
|
|
||||||
/* Check that array options and keys match up. */
|
/* Check that array options and indexes match up. */
|
||||||
if (array_key != NULL && (*name == '@' || !options_is_array(parent))) {
|
if (idx != -1 && (*name == '@' || !options_is_array(parent))) {
|
||||||
cmdq_error(item, "not an array: %s", argument);
|
cmdq_error(item, "not an array: %s", argument);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* With -o, check this option is not already set. */
|
/* With -o, check this option is not already set. */
|
||||||
if (!args_has(args, 'u') && args_has(args, 'o')) {
|
if (!args_has(args, 'u') && args_has(args, 'o')) {
|
||||||
if (array_key == NULL)
|
if (idx == -1)
|
||||||
already = (o != NULL);
|
already = (o != NULL);
|
||||||
else {
|
else {
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
already = 0;
|
already = 0;
|
||||||
else if (options_array_get(o, array_key) != NULL)
|
|
||||||
already = 1;
|
|
||||||
else
|
else
|
||||||
already = 0;
|
already = (options_array_get(o, idx) != NULL);
|
||||||
}
|
}
|
||||||
if (already) {
|
if (already) {
|
||||||
if (args_has(args, 'q'))
|
if (args_has(args, 'q'))
|
||||||
@@ -323,8 +170,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
po = options_get_only(loop->options, name);
|
po = options_get_only(loop->options, name);
|
||||||
if (po == NULL)
|
if (po == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (options_remove_or_default(po, array_key,
|
if (options_remove_or_default(po, idx, &cause) != 0) {
|
||||||
&cause) != 0) {
|
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -334,7 +180,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'u') || args_has(args, 'U')) {
|
if (args_has(args, 'u') || args_has(args, 'U')) {
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
if (options_remove_or_default(o, array_key, &cause) != 0) {
|
if (options_remove_or_default(o, idx, &cause) != 0) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -345,9 +191,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
options_set_string(oo, name, append, "%s", value);
|
options_set_string(oo, name, append, "%s", value);
|
||||||
if (cmd_get_entry(self) == &cmd_set_hook_entry)
|
} else if (idx == -1 && !options_is_array(parent)) {
|
||||||
hooks_add_event(name);
|
|
||||||
} else if (array_key == NULL && !options_is_array(parent)) {
|
|
||||||
error = options_from_string(oo, options_table_entry(parent),
|
error = options_from_string(oo, options_table_entry(parent),
|
||||||
options_table_entry(parent)->name, value,
|
options_table_entry(parent)->name, value,
|
||||||
args_has(args, 'a'), &cause);
|
args_has(args, 'a'), &cause);
|
||||||
@@ -363,7 +207,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
o = options_empty(oo, options_table_entry(parent));
|
o = options_empty(oo, options_table_entry(parent));
|
||||||
if (array_key == NULL) {
|
if (idx == -1) {
|
||||||
if (!append)
|
if (!append)
|
||||||
options_array_clear(o);
|
options_array_clear(o);
|
||||||
if (options_array_assign(o, value, &cause) != 0) {
|
if (options_array_assign(o, value, &cause) != 0) {
|
||||||
@@ -371,7 +215,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
} else if (options_array_set(o, array_key, value, append,
|
} else if (options_array_set(o, idx, value, append,
|
||||||
&cause) != 0) {
|
&cause) != 0) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
@@ -385,13 +229,11 @@ out:
|
|||||||
free(argument);
|
free(argument);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
free(name);
|
free(name);
|
||||||
free(array_key);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
free(argument);
|
free(argument);
|
||||||
free(expanded);
|
free(expanded);
|
||||||
free(name);
|
free(name);
|
||||||
free(array_key);
|
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-show-environment.c,v 1.29 2025/04/09 06:27:43 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-show-messages.c,v 1.37 2025/11/18 08:37:54 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-show-options.c,v 1.76 2026/07/27 19:15:58 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -27,23 +27,10 @@
|
|||||||
* Show options.
|
* Show options.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SHOW_OPTIONS_TEMPLATE \
|
|
||||||
"#{?option_value_only," \
|
|
||||||
"#{option_value}," \
|
|
||||||
"#{option_name}#{?option_has_array_key," \
|
|
||||||
"[#{option_array_key}],}" \
|
|
||||||
"#{?option_is_parent,*,}" \
|
|
||||||
"#{?option_has_value, " \
|
|
||||||
"#{?option_is_string,#{q/a:option_value},#{option_value}},}}"
|
|
||||||
#define SHOW_HOOKS_MONITOR_TEMPLATE \
|
|
||||||
"#{option_name}:#{hook_monitor_target}:#{hook_monitor_format}"
|
|
||||||
|
|
||||||
static enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
|
||||||
static void cmd_show_options_print(struct cmd *, struct cmdq_item *,
|
static void cmd_show_options_print(struct cmd *, struct cmdq_item *,
|
||||||
struct options_entry *, const char *, int);
|
struct options_entry *, int, int);
|
||||||
static void cmd_show_hooks_print_monitor(struct cmd *,
|
|
||||||
struct cmdq_item *, struct options_entry *);
|
|
||||||
static enum cmd_retval cmd_show_options_all(struct cmd *, struct cmdq_item *,
|
static enum cmd_retval cmd_show_options_all(struct cmd *, struct cmdq_item *,
|
||||||
int, struct options *);
|
int, struct options *);
|
||||||
|
|
||||||
@@ -51,8 +38,8 @@ const struct cmd_entry cmd_show_options_entry = {
|
|||||||
.name = "show-options",
|
.name = "show-options",
|
||||||
.alias = "show",
|
.alias = "show",
|
||||||
|
|
||||||
.args = { "AgF:Hpqst:vw", 0, 1, NULL },
|
.args = { "AgHpqst:vw", 0, 1, NULL },
|
||||||
.usage = "[-AgHpqsvw] [-F format] " CMD_TARGET_PANE_USAGE " [option]",
|
.usage = "[-AgHpqsvw] " CMD_TARGET_PANE_USAGE " [option]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
@@ -64,8 +51,8 @@ const struct cmd_entry cmd_show_window_options_entry = {
|
|||||||
.name = "show-window-options",
|
.name = "show-window-options",
|
||||||
.alias = "showw",
|
.alias = "showw",
|
||||||
|
|
||||||
.args = { "F:gvt:", 0, 1, NULL },
|
.args = { "gvt:", 0, 1, NULL },
|
||||||
.usage = "[-gv] [-F format] " CMD_TARGET_WINDOW_USAGE " [option]",
|
.usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
@@ -77,8 +64,8 @@ const struct cmd_entry cmd_show_hooks_entry = {
|
|||||||
.name = "show-hooks",
|
.name = "show-hooks",
|
||||||
.alias = NULL,
|
.alias = NULL,
|
||||||
|
|
||||||
.args = { "BF:gpt:w", 0, 1, NULL },
|
.args = { "gpt:w", 0, 1, NULL },
|
||||||
.usage = "[-Bgpw] [-F format] " CMD_TARGET_PANE_USAGE " [hook]",
|
.usage = "[-gpw] " CMD_TARGET_PANE_USAGE " [hook]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
@@ -93,8 +80,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
char *argument, *name = NULL, *cause;
|
char *argument, *name = NULL, *cause;
|
||||||
char *array_key = NULL;
|
int window, idx, ambiguous, parent, scope;
|
||||||
int window, ambiguous, parent, print_parent, scope;
|
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
|
|
||||||
window = (cmd_get_entry(self) == &cmd_show_window_options_entry);
|
window = (cmd_get_entry(self) == &cmd_show_window_options_entry);
|
||||||
@@ -109,20 +95,11 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
if (cmd_get_entry(self) == &cmd_show_hooks_entry &&
|
|
||||||
args_has(args, 'B')) {
|
|
||||||
o = options_first(oo);
|
|
||||||
while (o != NULL) {
|
|
||||||
cmd_show_hooks_print_monitor(self, item, o);
|
|
||||||
o = options_next(o);
|
|
||||||
}
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
return (cmd_show_options_all(self, item, scope, oo));
|
return (cmd_show_options_all(self, item, scope, oo));
|
||||||
}
|
}
|
||||||
argument = format_single_from_target(item, args_string(args, 0));
|
argument = format_single_from_target(item, args_string(args, 0));
|
||||||
|
|
||||||
name = options_match(argument, &array_key, &ambiguous);
|
name = options_match(argument, &idx, &ambiguous);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
if (args_has(args, 'q'))
|
if (args_has(args, 'q'))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -147,20 +124,9 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
parent = 1;
|
parent = 1;
|
||||||
} else
|
} else
|
||||||
parent = 0;
|
parent = 0;
|
||||||
if (o != NULL) {
|
if (o != NULL)
|
||||||
if (cmd_get_entry(self) == &cmd_show_hooks_entry &&
|
cmd_show_options_print(self, item, o, idx, parent);
|
||||||
args_has(args, 'B'))
|
else if (*name == '@') {
|
||||||
cmd_show_hooks_print_monitor(self, item, o);
|
|
||||||
else {
|
|
||||||
print_parent = parent;
|
|
||||||
if (array_key == NULL && options_is_array(o) &&
|
|
||||||
options_array_first(o) == NULL) {
|
|
||||||
print_parent = 0;
|
|
||||||
}
|
|
||||||
cmd_show_options_print(self, item, o, array_key,
|
|
||||||
print_parent);
|
|
||||||
}
|
|
||||||
} else if (*name == '@') {
|
|
||||||
if (args_has(args, 'q'))
|
if (args_has(args, 'q'))
|
||||||
goto out;
|
goto out;
|
||||||
cmdq_error(item, "invalid option: %s", argument);
|
cmdq_error(item, "invalid option: %s", argument);
|
||||||
@@ -169,171 +135,64 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
free(name);
|
free(name);
|
||||||
free(array_key);
|
|
||||||
free(argument);
|
free(argument);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
free(name);
|
free(name);
|
||||||
free(array_key);
|
|
||||||
free(argument);
|
free(argument);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
|
cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
|
||||||
struct options_entry *o, const char *array_key, int parent)
|
struct options_entry *o, int idx, int parent)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct options_array_item *a;
|
struct options_array_item *a;
|
||||||
struct format_tree *ft;
|
const char *name = options_name(o);
|
||||||
const char *name = options_name(o);
|
char *value, *tmp = NULL, *escaped;
|
||||||
const char *template = args_get(args, 'F');
|
|
||||||
char *value, *line;
|
|
||||||
struct timeval tv = { 0 };
|
|
||||||
u_int fire_count;
|
|
||||||
time_t fire_time;
|
|
||||||
int is_hook = 0, is_user = 0;
|
|
||||||
int has_value = 1;
|
|
||||||
const struct options_table_entry *oe = options_table_entry(o);
|
|
||||||
|
|
||||||
if (array_key != NULL)
|
if (idx != -1) {
|
||||||
value = options_to_string(o, array_key, 0);
|
xasprintf(&tmp, "%s[%d]", name, idx);
|
||||||
else if (options_is_array(o)) {
|
name = tmp;
|
||||||
a = options_array_first(o);
|
} else {
|
||||||
if (a != NULL) {
|
if (options_is_array(o)) {
|
||||||
|
a = options_array_first(o);
|
||||||
|
if (a == NULL) {
|
||||||
|
if (!args_has(args, 'v'))
|
||||||
|
cmdq_print(item, "%s", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (a != NULL) {
|
while (a != NULL) {
|
||||||
array_key = options_array_item_key(a);
|
idx = options_array_item_index(a);
|
||||||
cmd_show_options_print(self, item, o, array_key,
|
cmd_show_options_print(self, item, o, idx,
|
||||||
parent);
|
parent);
|
||||||
a = options_array_next(a);
|
a = options_array_next(a);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (template == NULL && args_has(args, 'v'))
|
|
||||||
return;
|
|
||||||
value = xstrdup("");
|
|
||||||
has_value = 0;
|
|
||||||
} else
|
|
||||||
value = options_to_string(o, NULL, 0);
|
|
||||||
|
|
||||||
if (template == NULL)
|
|
||||||
template = SHOW_OPTIONS_TEMPLATE;
|
|
||||||
|
|
||||||
if (oe != NULL && (oe->flags & OPTIONS_TABLE_IS_HOOK))
|
|
||||||
is_hook = 1;
|
|
||||||
else if (oe == NULL)
|
|
||||||
is_user = 1;
|
|
||||||
|
|
||||||
ft = format_create_from_target(item);
|
|
||||||
format_add(ft, "option_name", "%s", name);
|
|
||||||
format_add(ft, "option_value", "%s", value);
|
|
||||||
format_add(ft, "option_value_only", "%d", args_has(args, 'v'));
|
|
||||||
format_add(ft, "option_is_parent", "%d", parent);
|
|
||||||
format_add(ft, "option_is_array", "%d", options_is_array(o));
|
|
||||||
format_add(ft, "option_is_string", "%d", options_is_string(o));
|
|
||||||
format_add(ft, "option_is_hook", "%d", is_hook);
|
|
||||||
format_add(ft, "option_is_user", "%d", is_user);
|
|
||||||
format_add(ft, "option_has_value", "%d", has_value);
|
|
||||||
if (cmd_get_entry(self) == &cmd_show_hooks_entry) {
|
|
||||||
fire_count = options_get_fire_count(o);
|
|
||||||
format_add(ft, "hook_fire_count", "%u", fire_count);
|
|
||||||
|
|
||||||
fire_time = options_get_fire_time(o);
|
|
||||||
if (fire_time != 0) {
|
|
||||||
tv.tv_sec = fire_time;
|
|
||||||
format_add_tv(ft, "hook_fire_time", &tv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (array_key != NULL) {
|
|
||||||
format_add(ft, "option_array_key", "%s", array_key);
|
value = options_to_string(o, idx, 0);
|
||||||
format_add(ft, "option_has_array_key", "1");
|
if (args_has(args, 'v'))
|
||||||
|
cmdq_print(item, "%s", value);
|
||||||
|
else if (options_is_string(o)) {
|
||||||
|
escaped = args_escape(value);
|
||||||
|
if (parent)
|
||||||
|
cmdq_print(item, "%s* %s", name, escaped);
|
||||||
|
else
|
||||||
|
cmdq_print(item, "%s %s", name, escaped);
|
||||||
|
free(escaped);
|
||||||
} else {
|
} else {
|
||||||
format_add(ft, "option_array_key", "%s", "");
|
if (parent)
|
||||||
format_add(ft, "option_has_array_key", "0");
|
cmdq_print(item, "%s* %s", name, value);
|
||||||
|
else
|
||||||
|
cmdq_print(item, "%s %s", name, value);
|
||||||
}
|
}
|
||||||
line = format_expand(ft, template);
|
|
||||||
format_free(ft);
|
|
||||||
|
|
||||||
cmdq_print(item, "%s", line);
|
|
||||||
free(line);
|
|
||||||
free(value);
|
free(value);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
free(tmp);
|
||||||
cmd_show_hooks_print_monitor(struct cmd *self, struct cmdq_item *item,
|
|
||||||
struct options_entry *o)
|
|
||||||
{
|
|
||||||
struct args *args = cmd_get_args(self);
|
|
||||||
struct format_tree *ft;
|
|
||||||
enum monitor_type type;
|
|
||||||
const char *template = args_get(args, 'F'), *format;
|
|
||||||
char *value, *target, *line;
|
|
||||||
struct timeval tv = { 0 };
|
|
||||||
u_int fire_count;
|
|
||||||
time_t fire_time;
|
|
||||||
int id;
|
|
||||||
|
|
||||||
value = hooks_monitor_to_string(o);
|
|
||||||
if (value == NULL)
|
|
||||||
return;
|
|
||||||
if (!hooks_monitor_get(o, &type, &id, &format)) {
|
|
||||||
free(value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (template == NULL)
|
|
||||||
template = SHOW_HOOKS_MONITOR_TEMPLATE;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case MONITOR_SESSION:
|
|
||||||
target = xstrdup("");
|
|
||||||
break;
|
|
||||||
case MONITOR_PANE:
|
|
||||||
xasprintf(&target, "%%%d", id);
|
|
||||||
break;
|
|
||||||
case MONITOR_ALL_PANES:
|
|
||||||
target = xstrdup("%*");
|
|
||||||
break;
|
|
||||||
case MONITOR_WINDOW:
|
|
||||||
xasprintf(&target, "@%d", id);
|
|
||||||
break;
|
|
||||||
case MONITOR_ALL_WINDOWS:
|
|
||||||
target = xstrdup("@*");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ft = format_create_from_target(item);
|
|
||||||
format_add(ft, "option_name", "%s", options_name(o));
|
|
||||||
format_add(ft, "option_value", "%s", value);
|
|
||||||
format_add(ft, "option_value_only", "%d", 0);
|
|
||||||
format_add(ft, "option_is_parent", "%d", 0);
|
|
||||||
format_add(ft, "option_is_array", "%d", 0);
|
|
||||||
format_add(ft, "option_is_string", "%d", 1);
|
|
||||||
format_add(ft, "option_is_hook", "%d", 1);
|
|
||||||
format_add(ft, "option_is_user", "%d", 1);
|
|
||||||
format_add(ft, "option_has_value", "%d", 1);
|
|
||||||
format_add(ft, "option_array_key", "%s", "");
|
|
||||||
format_add(ft, "option_has_array_key", "0");
|
|
||||||
|
|
||||||
format_add(ft, "hook_monitor_target", "%s", target);
|
|
||||||
format_add(ft, "hook_monitor_format", "%s", format);
|
|
||||||
|
|
||||||
fire_count = hooks_monitor_get_fire_count(o);
|
|
||||||
format_add(ft, "hook_fire_count", "%u", fire_count);
|
|
||||||
|
|
||||||
fire_time = hooks_monitor_get_fire_time(o);
|
|
||||||
if (fire_time != 0) {
|
|
||||||
tv.tv_sec = fire_time;
|
|
||||||
format_add_tv(ft, "hook_fire_time", &tv);
|
|
||||||
}
|
|
||||||
|
|
||||||
line = format_expand(ft, template);
|
|
||||||
format_free(ft);
|
|
||||||
|
|
||||||
cmdq_print(item, "%s", line);
|
|
||||||
free(line);
|
|
||||||
free(target);
|
|
||||||
free(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
@@ -343,29 +202,18 @@ cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
|
|||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
const struct options_table_entry *oe;
|
const struct options_table_entry *oe;
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
|
struct options_array_item *a;
|
||||||
const char *name;
|
const char *name;
|
||||||
int parent, is_user_hook;
|
u_int idx;
|
||||||
|
int parent;
|
||||||
|
|
||||||
o = options_first(oo);
|
if (cmd_get_entry(self) != &cmd_show_hooks_entry) {
|
||||||
while (o != NULL) {
|
o = options_first(oo);
|
||||||
if (options_table_entry(o) == NULL) {
|
while (o != NULL) {
|
||||||
name = options_name(o);
|
if (options_table_entry(o) == NULL)
|
||||||
is_user_hook = 0;
|
cmd_show_options_print(self, item, o, -1, 0);
|
||||||
if (*name == '@') {
|
o = options_next(o);
|
||||||
if (hooks_is_event(name) ||
|
|
||||||
options_get_monitor_data(o) != NULL) {
|
|
||||||
is_user_hook = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cmd_get_entry(self) != &cmd_show_hooks_entry) {
|
|
||||||
if (!is_user_hook || args_has(args, 'H')) {
|
|
||||||
cmd_show_options_print(self, item, o,
|
|
||||||
NULL, 0);
|
|
||||||
}
|
|
||||||
} else if (is_user_hook)
|
|
||||||
cmd_show_options_print(self, item, o, NULL, 0);
|
|
||||||
}
|
}
|
||||||
o = options_next(o);
|
|
||||||
}
|
}
|
||||||
for (oe = options_table; oe->name != NULL; oe++) {
|
for (oe = options_table; oe->name != NULL; oe++) {
|
||||||
if (~oe->scope & scope)
|
if (~oe->scope & scope)
|
||||||
@@ -389,7 +237,24 @@ cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
|
|||||||
} else
|
} else
|
||||||
parent = 0;
|
parent = 0;
|
||||||
|
|
||||||
cmd_show_options_print(self, item, o, NULL, parent);
|
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(args, 'v')) {
|
||||||
|
name = options_name(o);
|
||||||
|
if (parent)
|
||||||
|
cmdq_print(item, "%s*", name);
|
||||||
|
else
|
||||||
|
cmdq_print(item, "%s", name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (a != NULL) {
|
||||||
|
idx = options_array_item_index(a);
|
||||||
|
cmd_show_options_print(self, item, o, idx,
|
||||||
|
parent);
|
||||||
|
a = options_array_next(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-show-prompt-history.c,v 1.5 2026/06/25 11:39:11 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 Anindya Mukherjee <anindya49@hotmail.com>
|
* Copyright (c) 2021 Anindya Mukherjee <anindya49@hotmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-source-file.c,v 1.63 2026/08/18 08:05:05 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
|
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
|
||||||
@@ -50,7 +50,6 @@ const struct cmd_entry cmd_source_file_entry = {
|
|||||||
|
|
||||||
struct cmd_source_file_data {
|
struct cmd_source_file_data {
|
||||||
struct cmdq_item *item;
|
struct cmdq_item *item;
|
||||||
struct client *client;
|
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
struct cmdq_item *after;
|
struct cmdq_item *after;
|
||||||
@@ -61,24 +60,10 @@ struct cmd_source_file_data {
|
|||||||
u_int nfiles;
|
u_int nfiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_source_file_free_data(struct cmd_source_file_data *cdata)
|
|
||||||
{
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
for (i = 0; i < cdata->nfiles; i++)
|
|
||||||
free(cdata->files[i]);
|
|
||||||
free(cdata->files);
|
|
||||||
if (cdata->client != NULL)
|
|
||||||
server_client_unref(cdata->client);
|
|
||||||
free(cdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_source_file_complete_cb(struct cmdq_item *item, void *data)
|
cmd_source_file_complete_cb(struct cmdq_item *item, __unused void *data)
|
||||||
{
|
{
|
||||||
struct cmd_source_file_data *cdata = data;
|
struct client *c = cmdq_get_client(item);
|
||||||
struct client *c = cdata->client;
|
|
||||||
|
|
||||||
if (c == NULL) {
|
if (c == NULL) {
|
||||||
cmd_source_file_depth--;
|
cmd_source_file_depth--;
|
||||||
@@ -89,36 +74,36 @@ cmd_source_file_complete_cb(struct cmdq_item *item, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg_print_causes(item);
|
cfg_print_causes(item);
|
||||||
cmd_source_file_free_data(cdata);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_source_file_complete(struct cmd_source_file_data *cdata)
|
cmd_source_file_complete(struct client *c, struct cmd_source_file_data *cdata)
|
||||||
{
|
{
|
||||||
struct client *c = cdata->client;
|
|
||||||
struct cmdq_item *new_item;
|
struct cmdq_item *new_item;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
if (!cfg_finished) {
|
if (cfg_finished) {
|
||||||
cmd_source_file_free_data(cdata);
|
if (cdata->retval == CMD_RETURN_ERROR &&
|
||||||
return;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cdata->retval == CMD_RETURN_ERROR &&
|
for (i = 0; i < cdata->nfiles; i++)
|
||||||
c != NULL &&
|
free(cdata->files[i]);
|
||||||
c->session == NULL)
|
free(cdata->files);
|
||||||
c->retval = 1;
|
free(cdata);
|
||||||
new_item = cmdq_get_callback(cmd_source_file_complete_cb, cdata);
|
|
||||||
cmdq_insert_after(cdata->after, new_item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_source_file_done(__unused struct client *oc, const char *path,
|
cmd_source_file_done(struct client *c, const char *path, int error,
|
||||||
int error, int closed, struct evbuffer *buffer, void *data)
|
int closed, struct evbuffer *buffer, void *data)
|
||||||
{
|
{
|
||||||
struct cmd_source_file_data *cdata = data;
|
struct cmd_source_file_data *cdata = data;
|
||||||
struct cmdq_item *item = cdata->item;
|
struct cmdq_item *item = cdata->item;
|
||||||
struct client *c = cdata->client;
|
|
||||||
void *bdata = EVBUFFER_DATA(buffer);
|
void *bdata = EVBUFFER_DATA(buffer);
|
||||||
size_t bsize = EVBUFFER_LENGTH(buffer);
|
size_t bsize = EVBUFFER_LENGTH(buffer);
|
||||||
u_int n;
|
u_int n;
|
||||||
@@ -142,7 +127,7 @@ cmd_source_file_done(__unused struct client *oc, const char *path,
|
|||||||
if (n < cdata->nfiles)
|
if (n < cdata->nfiles)
|
||||||
file_read(c, cdata->files[n], cmd_source_file_done, cdata);
|
file_read(c, cdata->files[n], cmd_source_file_done, cdata);
|
||||||
else {
|
else {
|
||||||
cmd_source_file_complete(cdata);
|
cmd_source_file_complete(c, cdata);
|
||||||
cmdq_continue(item);
|
cmdq_continue(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,9 +187,6 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
cdata = xcalloc(1, sizeof *cdata);
|
cdata = xcalloc(1, sizeof *cdata);
|
||||||
cdata->item = item;
|
cdata->item = item;
|
||||||
cdata->client = c;
|
|
||||||
if (c != NULL)
|
|
||||||
c->references++;
|
|
||||||
|
|
||||||
if (args_has(args, 'q'))
|
if (args_has(args, 'q'))
|
||||||
cdata->flags |= CMD_PARSE_QUIET;
|
cdata->flags |= CMD_PARSE_QUIET;
|
||||||
@@ -267,7 +249,7 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
file_read(c, cdata->files[0], cmd_source_file_done, cdata);
|
file_read(c, cdata->files[0], cmd_source_file_done, cdata);
|
||||||
retval = CMD_RETURN_WAIT;
|
retval = CMD_RETURN_WAIT;
|
||||||
} else
|
} else
|
||||||
cmd_source_file_complete(cdata);
|
cmd_source_file_complete(c, cdata);
|
||||||
|
|
||||||
free(cwd);
|
free(cwd);
|
||||||
return (retval);
|
return (retval);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-split-window.c,v 1.150 2026/08/20 09:19:24 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -33,15 +33,13 @@
|
|||||||
#define SPLIT_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
|
#define SPLIT_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
|
||||||
|
|
||||||
static enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmdq_item *);
|
||||||
static void cmd_split_window_mouse_resize(struct client *,
|
|
||||||
struct mouse_event *);
|
|
||||||
|
|
||||||
const struct cmd_entry cmd_new_pane_entry = {
|
const struct cmd_entry cmd_new_pane_entry = {
|
||||||
.name = "new-pane",
|
.name = "new-pane",
|
||||||
.alias = "newp",
|
.alias = "newp",
|
||||||
|
|
||||||
.args = { "AbB:Cc:de:EfF:hIkl:KLMm:Op:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
.args = { "bB:c:de:EfF:hIkl:Lm:p:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
||||||
.usage = "[-AbCdefhIkKLMOPvWZ] [-B border-lines] "
|
.usage = "[-bdefhIklPvWZ] [-B border-lines] "
|
||||||
"[-c start-directory] [-e environment] "
|
"[-c start-directory] [-e environment] "
|
||||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||||
"[-s style] [-S active-border-style] "
|
"[-s style] [-S active-border-style] "
|
||||||
@@ -59,12 +57,12 @@ const struct cmd_entry cmd_split_window_entry = {
|
|||||||
.name = "split-window",
|
.name = "split-window",
|
||||||
.alias = "splitw",
|
.alias = "splitw",
|
||||||
|
|
||||||
.args = { "bB:c:de:EfF:hIkl:m:p:PR:s:S:t:T:vWZ", 0, -1, NULL },
|
.args = { "bc:de:EfF:hIkl:m:p:PR:s:S:t:T:vWZ", 0, -1, NULL },
|
||||||
.usage = "[-bdefhIklPvWZ] [-B border-lines] [-c start-directory] "
|
.usage = "[-bdefhIklPvWZ] [-c start-directory] [-e environment] "
|
||||||
"[-e environment] [-F format] [-l size] [-m message] "
|
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||||
"[-p percentage] [-s style] [-S active-border-style] "
|
"[-s style] [-S active-border-style] "
|
||||||
"[-R inactive-border-style] [-T title] "
|
"[-R inactive-border-style] [-T title] " CMD_TARGET_PANE_USAGE " "
|
||||||
CMD_TARGET_PANE_USAGE " [shell-command [argument ...]]",
|
"[shell-command [argument ...]]",
|
||||||
|
|
||||||
.target = { 't', CMD_FIND_PANE, 0 },
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
@@ -83,13 +81,10 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct session *s = target->s;
|
struct session *s = target->s;
|
||||||
struct winlink *wl = target->wl;
|
struct winlink *wl = target->wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct window_pane *wp = target->wp, *new_wp = NULL;
|
struct window_pane *wp = target->wp, *new_wp;
|
||||||
struct layout_cell *lc = NULL;
|
struct layout_cell *lc = NULL;
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
struct key_event *event = cmdq_get_event(item);
|
|
||||||
int input, empty, is_floating, flags = 0;
|
int input, empty, is_floating, flags = 0;
|
||||||
int restore_zoom = 0;
|
|
||||||
const char *template, *style, *value;
|
const char *template, *style, *value;
|
||||||
char *cause = NULL, *cp, *title;
|
char *cause = NULL, *cp, *title;
|
||||||
const struct options_table_entry *oe;
|
const struct options_table_entry *oe;
|
||||||
@@ -97,57 +92,19 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
enum pane_lines lines;
|
enum pane_lines lines;
|
||||||
u_int count = args_count(args);
|
u_int count = args_count(args);
|
||||||
|
|
||||||
if (window_active_pane_is_over_zoom(w))
|
|
||||||
restore_zoom = 1;
|
|
||||||
|
|
||||||
if (cmd_get_entry(self) == &cmd_new_pane_entry)
|
if (cmd_get_entry(self) == &cmd_new_pane_entry)
|
||||||
is_floating = !args_has(args, 'L');
|
is_floating = !args_has(args, 'L');
|
||||||
else {
|
else
|
||||||
if (!window_pane_is_visible(wp))
|
|
||||||
restore_zoom = 0;
|
|
||||||
if (!restore_zoom)
|
|
||||||
window_unzoom(w, 1);
|
|
||||||
is_floating = window_pane_is_floating(wp);
|
is_floating = window_pane_is_floating(wp);
|
||||||
flags |= SPAWN_SPLIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args_has(args, 'O')) {
|
flags = is_floating ? SPAWN_FLOATING : 0;
|
||||||
if (!is_floating) {
|
|
||||||
cmdq_error(item, "modal pane must be floating");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if (w->modal != NULL) {
|
|
||||||
cmdq_error(item, "window already has a modal pane");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args_has(args, 'M') && is_floating) {
|
|
||||||
if (event == NULL || !event->m.valid || tc == NULL)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_floating)
|
|
||||||
flags |= SPAWN_FLOATING;
|
|
||||||
if (args_has(args, 'h'))
|
|
||||||
flags |= SPAWN_HORIZONTAL;
|
|
||||||
if (args_has(args, 'b'))
|
if (args_has(args, 'b'))
|
||||||
flags |= SPAWN_BEFORE;
|
flags |= SPAWN_BEFORE;
|
||||||
if (args_has(args, 'f'))
|
if (args_has(args, 'f'))
|
||||||
flags |= SPAWN_FULLSIZE;
|
flags |= SPAWN_FULLSIZE;
|
||||||
if (args_has(args, 'd'))
|
|
||||||
flags |= SPAWN_DETACHED;
|
|
||||||
if (args_has(args, 'Z'))
|
|
||||||
flags |= SPAWN_ZOOM;
|
|
||||||
if (args_has(args, 'O'))
|
|
||||||
flags |= SPAWN_MODAL|SPAWN_FLOATOVERZOOM;
|
|
||||||
if (is_floating && args_has(args, 'A'))
|
|
||||||
flags |= SPAWN_FLOATOVERZOOM;
|
|
||||||
if ((w->flags & WINDOW_ZOOMED) && (flags & SPAWN_FLOATOVERZOOM))
|
|
||||||
restore_zoom = 1;
|
|
||||||
|
|
||||||
input = args_has(args, 'I');
|
input = args_has(args, 'I');
|
||||||
if (input || (count == 1 && *args_string(args, 0) == '\0'))
|
if (input)
|
||||||
empty = 1;
|
empty = 1;
|
||||||
else
|
else
|
||||||
empty = args_has(args, 'E');
|
empty = args_has(args, 'E');
|
||||||
@@ -172,16 +129,13 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SPAWN_FLOATING) {
|
if (is_floating)
|
||||||
lc = layout_get_floating_cell(item, args, lines, w, wp, flags,
|
lc = layout_get_floating_cell(item, args, lines, w, wp, &cause);
|
||||||
&cause);
|
else
|
||||||
} else
|
|
||||||
lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
|
lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
|
||||||
if (cause != NULL) {
|
if (cause != NULL) {
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
if (restore_zoom)
|
|
||||||
window_pop_zoom(w);
|
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,22 +157,18 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
sc.idx = -1;
|
sc.idx = -1;
|
||||||
sc.cwd = args_get(args, 'c');
|
sc.cwd = args_get(args, 'c');
|
||||||
|
|
||||||
sc.flags = flags;
|
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) {
|
if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
|
||||||
cmdq_error(item, "create pane failed: %s", cause);
|
cmdq_error(item, "create pane failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
/*
|
|
||||||
* spawn_pane has already torn the half-built pane down (its
|
|
||||||
* fork-failure path removes the pane and destroys the layout
|
|
||||||
* cell), so new_wp is NULL and there is nothing for fail to do.
|
|
||||||
*/
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (args_has(args, 'K') && args_has(args, 'O'))
|
|
||||||
new_wp->flags |= PANE_CAPTUREALLKEYS;
|
|
||||||
if (args_has(args, 'C') && args_has(args, 'O'))
|
|
||||||
new_wp->flags |= PANE_CLOSEONCLICK;
|
|
||||||
|
|
||||||
style = args_get(args, 's');
|
style = args_get(args, 's');
|
||||||
if (style != NULL) {
|
if (style != NULL) {
|
||||||
@@ -262,19 +212,17 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'T')) {
|
if (args_has(args, 'T')) {
|
||||||
title = format_single_from_target(item, args_get(args, 'T'));
|
title = format_single_from_target(item, args_get(args, 'T'));
|
||||||
screen_set_title(&new_wp->base, title, 0);
|
screen_set_title(&new_wp->base, title, 0);
|
||||||
ep = event_payload_create();
|
notify_pane("pane-title-changed", new_wp);
|
||||||
cmd_find_from_pane(&fs, new_wp, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
event_payload_set_pane(ep, "pane", new_wp);
|
|
||||||
event_payload_set_window(ep, "window", new_wp->window);
|
|
||||||
event_payload_set_string(ep, "new_title", "%s", title);
|
|
||||||
events_fire("pane-title-changed", ep);
|
|
||||||
free(title);
|
free(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input) {
|
if (input) {
|
||||||
switch (window_pane_start_input(new_wp, item, &cause)) {
|
switch (window_pane_start_input(new_wp, item, &cause)) {
|
||||||
case -1:
|
case -1:
|
||||||
|
server_client_remove_pane(new_wp);
|
||||||
|
if (!is_floating)
|
||||||
|
layout_close_pane(new_wp);
|
||||||
|
window_remove_pane(wp->window, new_wp);
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -283,24 +231,15 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (~flags & SPAWN_DETACHED)
|
if (!args_has(args, 'd'))
|
||||||
cmd_find_from_winlink_pane(current, wl, new_wp, 0);
|
cmd_find_from_winlink_pane(current, wl, new_wp, 0);
|
||||||
|
|
||||||
if (restore_zoom) {
|
if (!is_floating) {
|
||||||
window_pop_zoom(wp->window);
|
|
||||||
server_redraw_window(wp->window);
|
|
||||||
} else if ((~flags & SPAWN_FLOATING) && !args_has(args, 'O')) {
|
|
||||||
window_pop_zoom(wp->window);
|
window_pop_zoom(wp->window);
|
||||||
server_redraw_window(wp->window);
|
server_redraw_window(wp->window);
|
||||||
}
|
}
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
|
|
||||||
if (args_has(args, 'M') && is_floating) {
|
|
||||||
tc->tty.mouse_last_pane = new_wp->id;
|
|
||||||
tc->tty.mouse_drag_update = cmd_split_window_mouse_resize;
|
|
||||||
cmd_split_window_mouse_resize(tc, &event->m);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args_has(args, 'P')) {
|
if (args_has(args, 'P')) {
|
||||||
if ((template = args_get(args, 'F')) == NULL)
|
if ((template = args_get(args, 'F')) == NULL)
|
||||||
template = SPLIT_WINDOW_TEMPLATE;
|
template = SPLIT_WINDOW_TEMPLATE;
|
||||||
@@ -330,93 +269,11 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
/*
|
|
||||||
* If the pane was spawned before we failed, tear it down here; this
|
|
||||||
* also destroys its layout cell. spawn_pane's own failure path has
|
|
||||||
* already done this, so new_wp is NULL in that case.
|
|
||||||
*/
|
|
||||||
if (new_wp != NULL) {
|
|
||||||
server_client_remove_pane(new_wp);
|
|
||||||
if (!is_floating)
|
|
||||||
layout_close_pane(new_wp);
|
|
||||||
window_remove_pane(wp->window, new_wp);
|
|
||||||
}
|
|
||||||
if (restore_zoom || (~flags & SPAWN_FLOATING))
|
|
||||||
window_pop_zoom(wp->window);
|
|
||||||
if (sc.argv != NULL)
|
if (sc.argv != NULL)
|
||||||
cmd_free_argv(sc.argc, sc.argv);
|
cmd_free_argv(sc.argc, sc.argv);
|
||||||
environ_free(sc.environ);
|
environ_free(sc.environ);
|
||||||
|
layout_destroy_cell(w, lc, &w->layout_root);
|
||||||
|
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_split_window_mouse_resize(struct client *c, struct mouse_event *m)
|
|
||||||
{
|
|
||||||
struct window_pane *wp;
|
|
||||||
struct window *w;
|
|
||||||
struct layout_cell *lc;
|
|
||||||
enum pane_lines lines;
|
|
||||||
u_int sx, sy;
|
|
||||||
int x, y, xoff, yoff, border;
|
|
||||||
|
|
||||||
if (c->tty.mouse_last_pane == -1)
|
|
||||||
return;
|
|
||||||
wp = window_pane_find_by_id(c->tty.mouse_last_pane);
|
|
||||||
if (wp == NULL || !window_pane_is_floating(wp)) {
|
|
||||||
c->tty.mouse_drag_update = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
w = wp->window;
|
|
||||||
lc = wp->layout_cell;
|
|
||||||
|
|
||||||
x = m->x + m->ox;
|
|
||||||
y = m->y + m->oy;
|
|
||||||
if (m->statusat == 0 && y >= (int)m->statuslines)
|
|
||||||
y -= m->statuslines;
|
|
||||||
else if (m->statusat > 0 && y >= m->statusat)
|
|
||||||
y = m->statusat - 1;
|
|
||||||
|
|
||||||
lines = window_pane_get_pane_lines(wp);
|
|
||||||
border = (lines != PANE_LINES_NONE);
|
|
||||||
|
|
||||||
if (x >= (int)c->tty.mouse_drag_x) {
|
|
||||||
xoff = c->tty.mouse_drag_x + border;
|
|
||||||
sx = x - c->tty.mouse_drag_x + 1;
|
|
||||||
} else {
|
|
||||||
sx = c->tty.mouse_drag_x - x + 1;
|
|
||||||
xoff = c->tty.mouse_drag_x - sx + 1;
|
|
||||||
if (border)
|
|
||||||
xoff++;
|
|
||||||
}
|
|
||||||
if (y >= (int)c->tty.mouse_drag_y) {
|
|
||||||
yoff = c->tty.mouse_drag_y + border;
|
|
||||||
sy = y - c->tty.mouse_drag_y + 1;
|
|
||||||
} else {
|
|
||||||
sy = c->tty.mouse_drag_y - y + 1;
|
|
||||||
yoff = c->tty.mouse_drag_y - sy + 1;
|
|
||||||
if (border)
|
|
||||||
yoff++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (border) {
|
|
||||||
if (sx <= 2)
|
|
||||||
sx = PANE_MINIMUM;
|
|
||||||
else
|
|
||||||
sx -= 2;
|
|
||||||
if (sy <= 2)
|
|
||||||
sy = PANE_MINIMUM;
|
|
||||||
else
|
|
||||||
sy -= 2;
|
|
||||||
}
|
|
||||||
if (sx < PANE_MINIMUM)
|
|
||||||
sx = PANE_MINIMUM;
|
|
||||||
if (sy < PANE_MINIMUM)
|
|
||||||
sy = PANE_MINIMUM;
|
|
||||||
|
|
||||||
layout_set_size(lc, sx, sy, xoff, yoff);
|
|
||||||
layout_fix_panes(w, NULL);
|
|
||||||
server_redraw_window(w);
|
|
||||||
server_redraw_window_borders(w);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-swap-pane.c,v 1.55 2026/07/15 13:02:33 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -42,22 +42,6 @@ const struct cmd_entry cmd_swap_pane_entry = {
|
|||||||
.exec = cmd_swap_pane_exec
|
.exec = cmd_swap_pane_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct window_pane *
|
|
||||||
cmd_swap_pane_next_tiled_pane(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
while (wp != NULL && !layout_cell_is_tiled(wp->layout_cell))
|
|
||||||
wp = TAILQ_NEXT(wp, entry);
|
|
||||||
return (wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct window_pane *
|
|
||||||
cmd_swap_pane_prev_tiled_pane(struct window_pane *wp)
|
|
||||||
{
|
|
||||||
while (wp != NULL && !layout_cell_is_tiled(wp->layout_cell))
|
|
||||||
wp = TAILQ_PREV(wp, window_panes, entry);
|
|
||||||
return (wp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
@@ -68,47 +52,25 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct window_pane *tmp_wp, *src_wp, *dst_wp;
|
struct window_pane *tmp_wp, *src_wp, *dst_wp;
|
||||||
struct layout_cell *src_lc, *dst_lc;
|
struct layout_cell *src_lc, *dst_lc;
|
||||||
u_int sx, sy, xoff, yoff;
|
u_int sx, sy, xoff, yoff;
|
||||||
int src_idx, dst_idx;
|
|
||||||
|
|
||||||
dst_w = target->wl->window;
|
dst_w = target->wl->window;
|
||||||
dst_wp = target->wp;
|
dst_wp = target->wp;
|
||||||
dst_idx = target->wl->idx;
|
|
||||||
src_w = source->wl->window;
|
src_w = source->wl->window;
|
||||||
src_wp = source->wp;
|
src_wp = source->wp;
|
||||||
src_idx = source->wl->idx;
|
|
||||||
|
|
||||||
if (src_wp == src_w->modal || dst_wp == dst_w->modal) {
|
|
||||||
cmdq_error(item, "pane is modal");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window_push_zoom(dst_w, 0, args_has(args, 'Z')))
|
if (window_push_zoom(dst_w, 0, args_has(args, 'Z')))
|
||||||
server_redraw_window(dst_w);
|
server_redraw_window(dst_w);
|
||||||
|
|
||||||
if (args_has(args, 'D')) {
|
if (args_has(args, 'D')) {
|
||||||
if (window_pane_is_floating(dst_wp)) {
|
|
||||||
cmdq_error(item, "cannot swap down on floating pane");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
src_w = dst_w;
|
src_w = dst_w;
|
||||||
src_wp = TAILQ_NEXT(dst_wp, entry);
|
src_wp = TAILQ_NEXT(dst_wp, entry);
|
||||||
src_wp = cmd_swap_pane_next_tiled_pane(src_wp);
|
if (src_wp == NULL)
|
||||||
if (src_wp == NULL) {
|
|
||||||
src_wp = TAILQ_FIRST(&dst_w->panes);
|
src_wp = TAILQ_FIRST(&dst_w->panes);
|
||||||
src_wp = cmd_swap_pane_next_tiled_pane(src_wp);
|
|
||||||
}
|
|
||||||
} else if (args_has(args, 'U')) {
|
} else if (args_has(args, 'U')) {
|
||||||
if (window_pane_is_floating(dst_wp)) {
|
|
||||||
cmdq_error(item, "cannot swap up on floating pane");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
src_w = dst_w;
|
src_w = dst_w;
|
||||||
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
|
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
|
||||||
src_wp = cmd_swap_pane_prev_tiled_pane(src_wp);
|
if (src_wp == NULL)
|
||||||
if (src_wp == NULL) {
|
|
||||||
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
|
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
|
||||||
src_wp = cmd_swap_pane_prev_tiled_pane(src_wp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_w != dst_w && window_push_zoom(src_w, 0, args_has(args, 'Z')))
|
if (src_w != dst_w && window_push_zoom(src_w, 0, args_has(args, 'Z')))
|
||||||
@@ -188,13 +150,9 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
redraw_invalidate_scene(dst_w);
|
redraw_invalidate_scene(dst_w);
|
||||||
server_redraw_window(dst_w);
|
server_redraw_window(dst_w);
|
||||||
|
|
||||||
if (src_w != dst_w) {
|
notify_window("window-layout-changed", src_w);
|
||||||
window_fire_pane_moved(src_wp, src_w, src_idx, dst_w, dst_idx);
|
|
||||||
window_fire_pane_moved(dst_wp, dst_w, dst_idx, src_w, src_idx);
|
|
||||||
}
|
|
||||||
events_fire_window("window-layout-changed", src_w);
|
|
||||||
if (src_w != dst_w)
|
if (src_w != dst_w)
|
||||||
events_fire_window("window-layout-changed", dst_w);
|
notify_window("window-layout-changed", dst_w);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (window_pop_zoom(src_w))
|
if (window_pop_zoom(src_w))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-swap-window.c,v 1.30 2026/07/27 08:03:01 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -38,7 +38,7 @@ const struct cmd_entry cmd_swap_window_entry = {
|
|||||||
.source = { 's', CMD_FIND_WINDOW, CMD_FIND_DEFAULT_MARKED },
|
.source = { 's', CMD_FIND_WINDOW, CMD_FIND_DEFAULT_MARKED },
|
||||||
.target = { 't', CMD_FIND_WINDOW, 0 },
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = 0,
|
||||||
.exec = cmd_swap_window_exec
|
.exec = cmd_swap_window_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -48,14 +48,10 @@ cmd_swap_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
struct cmd_find_state *source = cmdq_get_source(item);
|
struct cmd_find_state *source = cmdq_get_source(item);
|
||||||
struct cmd_find_state *target = cmdq_get_target(item);
|
struct cmd_find_state *target = cmdq_get_target(item);
|
||||||
struct client *c = cmdq_get_client(item);
|
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
|
||||||
struct client *ac;
|
|
||||||
struct session *src = source->s, *dst = target->s;
|
struct session *src = source->s, *dst = target->s;
|
||||||
struct session_group *sg_src, *sg_dst;
|
struct session_group *sg_src, *sg_dst;
|
||||||
struct winlink *wl_src = source->wl, *wl_dst = target->wl;
|
struct winlink *wl_src = source->wl, *wl_dst = target->wl;
|
||||||
struct window *w_src, *w_dst;
|
struct window *w_src, *w_dst;
|
||||||
int local_src, local_dst;
|
|
||||||
|
|
||||||
sg_src = session_group_contains(src);
|
sg_src = session_group_contains(src);
|
||||||
sg_dst = session_group_contains(dst);
|
sg_dst = session_group_contains(dst);
|
||||||
@@ -83,22 +79,10 @@ cmd_swap_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (marked_pane.wl == wl_src)
|
if (marked_pane.wl == wl_src)
|
||||||
marked_pane.wl = wl_dst;
|
marked_pane.wl = wl_dst;
|
||||||
ac = tc;
|
|
||||||
if (ac == NULL)
|
|
||||||
ac = c;
|
|
||||||
local_dst = active_is_local_window(ac, dst);
|
|
||||||
local_src = active_is_local_window(ac, src);
|
|
||||||
if (args_has(args, 'd')) {
|
if (args_has(args, 'd')) {
|
||||||
if (local_dst)
|
session_select(dst, wl_dst->idx);
|
||||||
active_select_window(ac, dst, wl_dst);
|
if (src != dst)
|
||||||
else
|
session_select(src, wl_src->idx);
|
||||||
session_select(dst, wl_dst->idx);
|
|
||||||
if (src != dst) {
|
|
||||||
if (local_src)
|
|
||||||
active_select_window(ac, src, wl_src);
|
|
||||||
else
|
|
||||||
session_select(src, wl_src->idx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
session_group_synchronize_from(src);
|
session_group_synchronize_from(src);
|
||||||
server_redraw_session_group(src);
|
server_redraw_session_group(src);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-switch-client.c,v 1.75 2026/08/20 09:19:24 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -53,12 +53,11 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct cmd_find_state target;
|
struct cmd_find_state target;
|
||||||
const char *tflag = args_get(args, 't');
|
const char *tflag = args_get(args, 't');
|
||||||
enum cmd_find_type type;
|
enum cmd_find_type type;
|
||||||
int flags, visible, window_target;
|
int flags;
|
||||||
int Zflag = args_has(args, 'Z');
|
|
||||||
struct client *c = cmdq_get_client(item);
|
struct client *c = cmdq_get_client(item);
|
||||||
struct client *tc = cmdq_get_target_client(item);
|
struct client *tc = cmdq_get_target_client(item);
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct winlink *wl, *current_wl;
|
struct winlink *wl;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
const char *tablename;
|
const char *tablename;
|
||||||
@@ -66,13 +65,8 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct sort_criteria sort_crit;
|
struct sort_criteria sort_crit;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
|
|
||||||
window_target = 0;
|
if (tflag != NULL &&
|
||||||
if (tflag != NULL) {
|
(tflag[strcspn(tflag, ":.%")] != '\0' || strcmp(tflag, "=") == 0)) {
|
||||||
if (tflag[strcspn(tflag, ":.%")] != '\0' ||
|
|
||||||
strcmp(tflag, "=") == 0)
|
|
||||||
window_target = 1;
|
|
||||||
}
|
|
||||||
if (window_target) {
|
|
||||||
type = CMD_FIND_PANE;
|
type = CMD_FIND_PANE;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -143,27 +137,18 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
} else {
|
} else {
|
||||||
if (cmdq_get_client(item) == NULL)
|
if (cmdq_get_client(item) == NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
if (window_target && wl != NULL && wp != NULL &&
|
if (wl != NULL && wp != NULL && wp != wl->window->active) {
|
||||||
wp != wl->window->active) {
|
|
||||||
w = wl->window;
|
w = wl->window;
|
||||||
if (w->modal != NULL && wp != w->modal)
|
if (window_push_zoom(w, 0, args_has(args, 'Z')))
|
||||||
visible = 1;
|
|
||||||
else
|
|
||||||
visible = window_pane_is_visible(wp);
|
|
||||||
if (!visible && window_push_zoom(w, 0, Zflag))
|
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
window_redraw_active_switch(w, wp);
|
window_redraw_active_switch(w, wp);
|
||||||
window_set_active_pane(w, wp, 1);
|
window_set_active_pane(w, wp, 1);
|
||||||
if (!visible && window_pop_zoom(w))
|
if (window_pop_zoom(w))
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
}
|
}
|
||||||
if (window_target && wl != NULL) {
|
if (wl != NULL) {
|
||||||
active_select_window(tc, s, wl);
|
session_set_current(s, wl);
|
||||||
if (active_is_local_window(tc, s)) {
|
cmd_find_from_session(current, s, 0);
|
||||||
current_wl = active_get_effective_winlink(tc, s);
|
|
||||||
cmd_find_from_winlink(current, current_wl, 0);
|
|
||||||
} else
|
|
||||||
cmd_find_from_session(current, s, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-unbind-key.c,v 1.34 2021/08/21 10:22:39 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
261
cmd-wait-for.c
261
cmd-wait-for.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-wait-for.c,v 1.23 2026/07/10 13:38:45 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -34,8 +34,8 @@ const struct cmd_entry cmd_wait_for_entry = {
|
|||||||
.name = "wait-for",
|
.name = "wait-for",
|
||||||
.alias = "wait",
|
.alias = "wait",
|
||||||
|
|
||||||
.args = { "EF:LSUlvw:", 1, 1, NULL },
|
.args = { "LSU", 1, 1, NULL },
|
||||||
.usage = "[-ELSUlv] [-F format] [-w waiter] name",
|
.usage = "[-L|-S|-U] channel",
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_wait_for_exec
|
.exec = cmd_wait_for_exec
|
||||||
@@ -46,17 +46,6 @@ struct wait_item {
|
|||||||
TAILQ_ENTRY(wait_item) entry;
|
TAILQ_ENTRY(wait_item) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wait_event_item {
|
|
||||||
struct cmdq_item *item;
|
|
||||||
struct events_sink *sink;
|
|
||||||
char *name;
|
|
||||||
char *filter;
|
|
||||||
int verbose;
|
|
||||||
TAILQ_ENTRY(wait_event_item) entry;
|
|
||||||
};
|
|
||||||
static TAILQ_HEAD(, wait_event_item) wait_event_items =
|
|
||||||
TAILQ_HEAD_INITIALIZER(wait_event_items);
|
|
||||||
|
|
||||||
struct wait_channel {
|
struct wait_channel {
|
||||||
const char *name;
|
const char *name;
|
||||||
int locked;
|
int locked;
|
||||||
@@ -87,28 +76,9 @@ static enum cmd_retval cmd_wait_for_lock(struct cmdq_item *, const char *,
|
|||||||
struct wait_channel *);
|
struct wait_channel *);
|
||||||
static enum cmd_retval cmd_wait_for_unlock(struct cmdq_item *, const char *,
|
static enum cmd_retval cmd_wait_for_unlock(struct cmdq_item *, const char *,
|
||||||
struct wait_channel *);
|
struct wait_channel *);
|
||||||
static enum cmd_retval cmd_wait_for_event(struct cmdq_item *, const char *,
|
|
||||||
struct args *);
|
|
||||||
static void cmd_wait_for_event_cb(const char *,
|
|
||||||
struct event_payload *, void *);
|
|
||||||
static void cmd_wait_for_event_free(struct wait_event_item *);
|
|
||||||
static enum cmd_retval cmd_wait_for_event_list(struct cmdq_item *,
|
|
||||||
const char *);
|
|
||||||
static enum cmd_retval cmd_wait_for_event_wake(struct cmdq_item *,
|
|
||||||
const char *, struct args *);
|
|
||||||
static enum cmd_retval cmd_wait_for_list(struct cmdq_item *,
|
|
||||||
struct wait_channel *);
|
|
||||||
static enum cmd_retval cmd_wait_for_wake(struct cmdq_item *, const char *,
|
|
||||||
struct args *, struct wait_channel *);
|
|
||||||
|
|
||||||
static struct wait_channel *cmd_wait_for_add(const char *);
|
static struct wait_channel *cmd_wait_for_add(const char *);
|
||||||
static void cmd_wait_for_remove(struct wait_channel *);
|
static void cmd_wait_for_remove(struct wait_channel *);
|
||||||
static void cmd_wait_for_remove_empty(
|
|
||||||
struct wait_channel *);
|
|
||||||
static const char *cmd_wait_for_item_client_name(
|
|
||||||
struct cmdq_item *);
|
|
||||||
static const char *cmd_wait_for_client_name(
|
|
||||||
struct wait_event_item *);
|
|
||||||
|
|
||||||
static struct wait_channel *
|
static struct wait_channel *
|
||||||
cmd_wait_for_add(const char *name)
|
cmd_wait_for_add(const char *name)
|
||||||
@@ -147,53 +117,16 @@ cmd_wait_for_remove(struct wait_channel *wc)
|
|||||||
free(wc);
|
free(wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_wait_for_remove_empty(struct wait_channel *wc)
|
|
||||||
{
|
|
||||||
if (wc->locked || wc->woken)
|
|
||||||
return;
|
|
||||||
if (!TAILQ_EMPTY(&wc->waiters) || !TAILQ_EMPTY(&wc->lockers))
|
|
||||||
return;
|
|
||||||
|
|
||||||
log_debug("remove empty wait channel %s", wc->name);
|
|
||||||
|
|
||||||
RB_REMOVE(wait_channels, &wait_channels, wc);
|
|
||||||
|
|
||||||
free((void *)wc->name);
|
|
||||||
free(wc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
cmd_wait_for_item_client_name(struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
struct client *c = cmdq_get_client(item);
|
|
||||||
|
|
||||||
if (c == NULL || c->name == NULL)
|
|
||||||
return ("");
|
|
||||||
return (c->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
cmd_wait_for_client_name(struct wait_event_item *wei)
|
|
||||||
{
|
|
||||||
return (cmd_wait_for_item_client_name(wei->item));
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_wait_for_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_wait_for_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = cmd_get_args(self);
|
struct args *args = cmd_get_args(self);
|
||||||
const char *name = args_string(args, 0);
|
const char *name = args_string(args, 0);
|
||||||
struct wait_channel *wc, find = { .name = name };
|
struct wait_channel *wc, find;
|
||||||
|
|
||||||
if (args_has(args, 'E'))
|
|
||||||
return (cmd_wait_for_event(item, name, args));
|
|
||||||
|
|
||||||
|
find.name = name;
|
||||||
wc = RB_FIND(wait_channels, &wait_channels, &find);
|
wc = RB_FIND(wait_channels, &wait_channels, &find);
|
||||||
if (args_has(args, 'l'))
|
|
||||||
return (cmd_wait_for_list(item, wc));
|
|
||||||
if (args_has(args, 'w'))
|
|
||||||
return (cmd_wait_for_wake(item, name, args, wc));
|
|
||||||
if (args_has(args, 'S'))
|
if (args_has(args, 'S'))
|
||||||
return (cmd_wait_for_signal(item, name, wc));
|
return (cmd_wait_for_signal(item, name, wc));
|
||||||
if (args_has(args, 'L'))
|
if (args_has(args, 'L'))
|
||||||
@@ -203,179 +136,6 @@ cmd_wait_for_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (cmd_wait_for_wait(item, name, wc));
|
return (cmd_wait_for_wait(item, name, wc));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_wait_for_event_print(struct wait_event_item *wei, struct event_payload *ep)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
const char *key;
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
epi = event_payload_first(ep);
|
|
||||||
while (epi != NULL) {
|
|
||||||
key = event_payload_item_name(epi);
|
|
||||||
if (*key != '_') {
|
|
||||||
value = event_payload_item_print(epi);
|
|
||||||
cmdq_print(wei->item, "%s=%s", key, value);
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
epi = event_payload_next(epi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_wait_for_event_cb(__unused const char *name, struct event_payload *ep,
|
|
||||||
void *item_data)
|
|
||||||
{
|
|
||||||
struct wait_event_item *wei = item_data;
|
|
||||||
struct format_tree *ft;
|
|
||||||
char *expanded;
|
|
||||||
int flag;
|
|
||||||
|
|
||||||
if (wei->verbose)
|
|
||||||
cmd_wait_for_event_print(wei, ep);
|
|
||||||
|
|
||||||
if (wei->filter != NULL) {
|
|
||||||
ft = format_create(cmdq_get_client(wei->item), wei->item,
|
|
||||||
FORMAT_NONE, FORMAT_NOJOBS);
|
|
||||||
event_payload_add_formats(ep, ft, NULL);
|
|
||||||
expanded = format_expand(ft, wei->filter);
|
|
||||||
flag = format_true(expanded);
|
|
||||||
free(expanded);
|
|
||||||
format_free(ft);
|
|
||||||
|
|
||||||
if (!flag)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAILQ_REMOVE(&wait_event_items, wei, entry);
|
|
||||||
cmdq_continue(wei->item);
|
|
||||||
cmd_wait_for_event_free(wei);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_wait_for_event_free(struct wait_event_item *wei)
|
|
||||||
{
|
|
||||||
events_remove_sink(wei->sink);
|
|
||||||
free(wei->name);
|
|
||||||
free(wei->filter);
|
|
||||||
free(wei);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_wait_for_event(struct cmdq_item *item, const char *name, struct args *args)
|
|
||||||
{
|
|
||||||
struct wait_event_item *wei;
|
|
||||||
const char *filter = args_get(args, 'F');
|
|
||||||
|
|
||||||
if (!hooks_valid_event_name(name)) {
|
|
||||||
cmdq_error(item, "invalid event: %s", name);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
if (args_has(args, 'l'))
|
|
||||||
return (cmd_wait_for_event_list(item, name));
|
|
||||||
if (args_has(args, 'w'))
|
|
||||||
return (cmd_wait_for_event_wake(item, name, args));
|
|
||||||
|
|
||||||
if (cmdq_get_client(item) == NULL) {
|
|
||||||
cmdq_error(item, "not able to wait");
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
wei = xcalloc(1, sizeof *wei);
|
|
||||||
wei->item = item;
|
|
||||||
wei->name = xstrdup(name);
|
|
||||||
wei->filter = (filter != NULL ? xstrdup(filter) : NULL);
|
|
||||||
wei->verbose = args_has(args, 'v');
|
|
||||||
wei->sink = events_add_sink(name, cmd_wait_for_event_cb, wei);
|
|
||||||
TAILQ_INSERT_TAIL(&wait_event_items, wei, entry);
|
|
||||||
|
|
||||||
return (CMD_RETURN_WAIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_wait_for_event_list(struct cmdq_item *item, const char *name)
|
|
||||||
{
|
|
||||||
struct wait_event_item *wei;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wei, &wait_event_items, entry) {
|
|
||||||
if (strcmp(wei->name, name) == 0)
|
|
||||||
cmdq_print(item, "%s", cmd_wait_for_client_name(wei));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_wait_for_event_wake(struct cmdq_item *item, const char *name,
|
|
||||||
struct args *args)
|
|
||||||
{
|
|
||||||
struct wait_event_item *wei, *wei1;
|
|
||||||
const char *client_name = args_get(args, 'w');
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(wei, &wait_event_items, entry, wei1) {
|
|
||||||
if (strcmp(wei->name, name) != 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp(cmd_wait_for_client_name(wei), client_name) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
TAILQ_REMOVE(&wait_event_items, wei, entry);
|
|
||||||
cmdq_continue(wei->item);
|
|
||||||
cmd_wait_for_event_free(wei);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdq_error(item, "waiter %s not found", client_name);
|
|
||||||
return (CMD_RETURN_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_wait_for_list(struct cmdq_item *item, struct wait_channel *wc)
|
|
||||||
{
|
|
||||||
struct wait_item *wi;
|
|
||||||
|
|
||||||
if (wc == NULL)
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(wi, &wc->waiters, entry)
|
|
||||||
cmdq_print(item, "%s", cmd_wait_for_item_client_name(wi->item));
|
|
||||||
TAILQ_FOREACH(wi, &wc->lockers, entry)
|
|
||||||
cmdq_print(item, "%s", cmd_wait_for_item_client_name(wi->item));
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_wait_for_wake(__unused struct cmdq_item *item, const char *name,
|
|
||||||
struct args *args, struct wait_channel *wc)
|
|
||||||
{
|
|
||||||
struct wait_item *wi, *wi1;
|
|
||||||
const char *client_name = args_get(args, 'w');
|
|
||||||
|
|
||||||
if (wc != NULL) {
|
|
||||||
TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
|
|
||||||
name = cmd_wait_for_item_client_name(wi->item);
|
|
||||||
if (strcmp(name, client_name) != 0)
|
|
||||||
continue;
|
|
||||||
cmdq_continue(wi->item);
|
|
||||||
TAILQ_REMOVE(&wc->waiters, wi, entry);
|
|
||||||
free(wi);
|
|
||||||
cmd_wait_for_remove_empty(wc);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
TAILQ_FOREACH_SAFE(wi, &wc->lockers, entry, wi1) {
|
|
||||||
name = cmd_wait_for_item_client_name(wi->item);
|
|
||||||
if (strcmp(name, client_name) != 0)
|
|
||||||
continue;
|
|
||||||
cmdq_continue(wi->item);
|
|
||||||
TAILQ_REMOVE(&wc->lockers, wi, entry);
|
|
||||||
free(wi);
|
|
||||||
cmd_wait_for_remove_empty(wc);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_wait_for_signal(__unused struct cmdq_item *item, const char *name,
|
cmd_wait_for_signal(__unused struct cmdq_item *item, const char *name,
|
||||||
struct wait_channel *wc)
|
struct wait_channel *wc)
|
||||||
@@ -485,13 +245,6 @@ cmd_wait_for_flush(void)
|
|||||||
{
|
{
|
||||||
struct wait_channel *wc, *wc1;
|
struct wait_channel *wc, *wc1;
|
||||||
struct wait_item *wi, *wi1;
|
struct wait_item *wi, *wi1;
|
||||||
struct wait_event_item *wei, *wei1;
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(wei, &wait_event_items, entry, wei1) {
|
|
||||||
TAILQ_REMOVE(&wait_event_items, wei, entry);
|
|
||||||
cmdq_continue(wei->item);
|
|
||||||
cmd_wait_for_event_free(wei);
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) {
|
RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) {
|
||||||
TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
|
TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
|
||||||
|
|||||||
61
cmd.c
61
cmd.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd.c,v 1.189 2026/07/17 08:29:34 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -69,6 +69,7 @@ extern const struct cmd_entry cmd_load_buffer_entry;
|
|||||||
extern const struct cmd_entry cmd_lock_client_entry;
|
extern const struct cmd_entry cmd_lock_client_entry;
|
||||||
extern const struct cmd_entry cmd_lock_server_entry;
|
extern const struct cmd_entry cmd_lock_server_entry;
|
||||||
extern const struct cmd_entry cmd_lock_session_entry;
|
extern const struct cmd_entry cmd_lock_session_entry;
|
||||||
|
extern const struct cmd_entry cmd_hide_pane_entry;
|
||||||
extern const struct cmd_entry cmd_move_pane_entry;
|
extern const struct cmd_entry cmd_move_pane_entry;
|
||||||
extern const struct cmd_entry cmd_move_window_entry;
|
extern const struct cmd_entry cmd_move_window_entry;
|
||||||
extern const struct cmd_entry cmd_new_pane_entry;
|
extern const struct cmd_entry cmd_new_pane_entry;
|
||||||
@@ -106,6 +107,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_hooks_entry;
|
||||||
extern const struct cmd_entry cmd_show_messages_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_options_entry;
|
||||||
|
extern const struct cmd_entry cmd_show_pane_entry;
|
||||||
extern const struct cmd_entry cmd_show_prompt_history_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_show_window_options_entry;
|
||||||
extern const struct cmd_entry cmd_source_file_entry;
|
extern const struct cmd_entry cmd_source_file_entry;
|
||||||
@@ -163,6 +165,7 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_lock_client_entry,
|
&cmd_lock_client_entry,
|
||||||
&cmd_lock_server_entry,
|
&cmd_lock_server_entry,
|
||||||
&cmd_lock_session_entry,
|
&cmd_lock_session_entry,
|
||||||
|
&cmd_hide_pane_entry,
|
||||||
&cmd_move_pane_entry,
|
&cmd_move_pane_entry,
|
||||||
&cmd_move_window_entry,
|
&cmd_move_window_entry,
|
||||||
&cmd_new_pane_entry,
|
&cmd_new_pane_entry,
|
||||||
@@ -200,6 +203,7 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_show_hooks_entry,
|
&cmd_show_hooks_entry,
|
||||||
&cmd_show_messages_entry,
|
&cmd_show_messages_entry,
|
||||||
&cmd_show_options_entry,
|
&cmd_show_options_entry,
|
||||||
|
&cmd_show_pane_entry,
|
||||||
&cmd_show_prompt_history_entry,
|
&cmd_show_prompt_history_entry,
|
||||||
&cmd_show_window_options_entry,
|
&cmd_show_window_options_entry,
|
||||||
&cmd_source_file_entry,
|
&cmd_source_file_entry,
|
||||||
@@ -832,27 +836,20 @@ cmd_mouse_pane(struct mouse_event *m, struct session **sp,
|
|||||||
if (!window_has_pane(wl->window, wp))
|
if (!window_has_pane(wl->window, wp))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (wl->window->modal != NULL && wp != wl->window->modal)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if (wlp != NULL)
|
if (wlp != NULL)
|
||||||
*wlp = wl;
|
*wlp = wl;
|
||||||
return (wp);
|
return (wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Replace the first %% or %idx in template by s. */
|
||||||
* Replace the first %% or any %idx in template by s. %% is intended for use in
|
|
||||||
* single quotes, so ' is escaped. %%% and %idx% are for double quotes, so a
|
|
||||||
* list of special characters is escaped. %idx is left unescaped.
|
|
||||||
*/
|
|
||||||
char *
|
char *
|
||||||
cmd_template_replace(const char *template, const char *s, int idx)
|
cmd_template_replace(const char *template, const char *s, int idx)
|
||||||
{
|
{
|
||||||
char ch, *buf;
|
char ch, *buf;
|
||||||
const char *ptr, *cp, dquote[] = "\"\\$;~";
|
const char *ptr, *cp, quote[] = "\"\\$;~";
|
||||||
int replaced;
|
int replaced, quoted;
|
||||||
size_t len, slen;
|
size_t len;
|
||||||
enum { NQ, SQ, DQ } quote;
|
|
||||||
|
|
||||||
if (strchr(template, '%') == NULL)
|
if (strchr(template, '%') == NULL)
|
||||||
return (xstrdup(template));
|
return (xstrdup(template));
|
||||||
@@ -866,52 +863,30 @@ cmd_template_replace(const char *template, const char *s, int idx)
|
|||||||
while (*ptr != '\0') {
|
while (*ptr != '\0') {
|
||||||
switch (ch = *ptr++) {
|
switch (ch = *ptr++) {
|
||||||
case '%':
|
case '%':
|
||||||
if (*ptr >= '1' && *ptr <= '9' && *ptr - '0' == idx) {
|
if (*ptr < '1' || *ptr > '9' || *ptr - '0' != idx) {
|
||||||
ptr++;
|
|
||||||
quote = NQ;
|
|
||||||
if (*ptr == '%') {
|
|
||||||
quote = DQ;
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (*ptr != '%' || replaced)
|
if (*ptr != '%' || replaced)
|
||||||
break;
|
break;
|
||||||
replaced = 1;
|
replaced = 1;
|
||||||
ptr++;
|
|
||||||
quote = SQ;
|
|
||||||
if (*ptr == '%') {
|
|
||||||
quote = DQ;
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ptr++;
|
||||||
|
|
||||||
slen = strlen(s);
|
quoted = (*ptr == '%');
|
||||||
if (slen >= SIZE_MAX / 4 ||
|
if (quoted)
|
||||||
len > SIZE_MAX - (slen * 4) - 1)
|
ptr++;
|
||||||
fatalx("argument too long");
|
|
||||||
buf = xrealloc(buf, len + (slen * 4) + 1);
|
buf = xrealloc(buf, len + (strlen(s) * 3) + 1);
|
||||||
for (cp = s; *cp != '\0'; cp++) {
|
for (cp = s; *cp != '\0'; cp++) {
|
||||||
if (quote == SQ && *cp == '\'') {
|
if (quoted && strchr(quote, *cp) != NULL)
|
||||||
buf[len++] = '\'';
|
|
||||||
buf[len++] = '\\';
|
|
||||||
buf[len++] = '\'';
|
|
||||||
buf[len++] = '\'';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (quote == DQ && strchr(dquote, *cp) != NULL)
|
|
||||||
buf[len++] = '\\';
|
buf[len++] = '\\';
|
||||||
buf[len++] = *cp;
|
buf[len++] = *cp;
|
||||||
}
|
}
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (len > SIZE_MAX - 2)
|
|
||||||
fatalx("argument too long");
|
|
||||||
buf = xrealloc(buf, len + 2);
|
buf = xrealloc(buf, len + 2);
|
||||||
buf[len++] = ch;
|
buf[len++] = ch;
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("%s: %s -> %s", __func__, template, buf);
|
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
|
|||||||
16
colour.c
16
colour.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: colour.c,v 1.35 2026/07/06 14:29:10 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -1294,8 +1294,7 @@ colour_palette_from_option(struct colour_palette *p, struct options *oo)
|
|||||||
{
|
{
|
||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
struct options_array_item *a;
|
struct options_array_item *a;
|
||||||
union options_value *ov;
|
u_int i, n;
|
||||||
u_int i;
|
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
@@ -1313,11 +1312,12 @@ colour_palette_from_option(struct colour_palette *p, struct options *oo)
|
|||||||
p->default_palette = xcalloc(256, sizeof *p->default_palette);
|
p->default_palette = xcalloc(256, sizeof *p->default_palette);
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
p->default_palette[i] = -1;
|
p->default_palette[i] = -1;
|
||||||
for (i = 0; i < 256; i++) {
|
while (a != NULL) {
|
||||||
ov = options_array_getv(o, "%u", i);
|
n = options_array_item_index(a);
|
||||||
if (ov != NULL) {
|
if (n < 256) {
|
||||||
c = ov->number;
|
c = options_array_item_value(a)->number;
|
||||||
p->default_palette[i] = c;
|
p->default_palette[n] = c;
|
||||||
}
|
}
|
||||||
|
a = options_array_next(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
compat.h
5
compat.h
@@ -410,6 +410,11 @@ int asprintf(char **, const char *, ...);
|
|||||||
int vasprintf(char **, const char *, va_list);
|
int vasprintf(char **, const char *, va_list);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_FGETLN
|
||||||
|
/* fgetln.c */
|
||||||
|
char *fgetln(FILE *, size_t *);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GETLINE
|
#ifndef HAVE_GETLINE
|
||||||
/* getline.c */
|
/* getline.c */
|
||||||
ssize_t getline(char **, size_t *, FILE *);
|
ssize_t getline(char **, size_t *, FILE *);
|
||||||
|
|||||||
61
compat/fgetln.c
Normal file
61
compat/fgetln.c
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Joerg Jung <jung@openbsd.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* portable fgetln() version, NOT reentrant
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
char *
|
||||||
|
fgetln(FILE *fp, size_t *len)
|
||||||
|
{
|
||||||
|
static char *buf = NULL;
|
||||||
|
static size_t bufsz = 0;
|
||||||
|
size_t r = 0;
|
||||||
|
char *p;
|
||||||
|
int c, e;
|
||||||
|
|
||||||
|
if (!fp || !len) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!buf) {
|
||||||
|
if (!(buf = calloc(1, BUFSIZ)))
|
||||||
|
return NULL;
|
||||||
|
bufsz = BUFSIZ;
|
||||||
|
}
|
||||||
|
while ((c = getc(fp)) != EOF) {
|
||||||
|
buf[r++] = c;
|
||||||
|
if (r == bufsz) {
|
||||||
|
if (!(p = reallocarray(buf, 2, bufsz))) {
|
||||||
|
e = errno;
|
||||||
|
free(buf);
|
||||||
|
errno = e;
|
||||||
|
buf = NULL, bufsz = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
buf = p, bufsz = 2 * bufsz;
|
||||||
|
}
|
||||||
|
if (c == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (*len = r) ? buf : NULL;
|
||||||
|
}
|
||||||
@@ -74,14 +74,8 @@ getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
|
|||||||
}
|
}
|
||||||
if (ptr + 2 >= eptr) {
|
if (ptr + 2 >= eptr) {
|
||||||
char *nbuf;
|
char *nbuf;
|
||||||
size_t nbufsiz;
|
size_t nbufsiz = *bufsiz * 2;
|
||||||
ssize_t d = ptr - *buf;
|
ssize_t d = ptr - *buf;
|
||||||
|
|
||||||
if (*bufsiz > SIZE_MAX / 2) {
|
|
||||||
errno = EOVERFLOW;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
nbufsiz = *bufsiz * 2;
|
|
||||||
if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
|
if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
*buf = nbuf;
|
*buf = nbuf;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ getpeereid(int s, uid_t *uid, gid_t *gid)
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_SO_PEERCRED
|
#ifdef HAVE_SO_PEERCRED
|
||||||
struct ucred uc;
|
struct ucred uc;
|
||||||
socklen_t len = sizeof uc;
|
int len = sizeof uc;
|
||||||
|
|
||||||
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &uc, &len) == -1)
|
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &uc, &len) == -1)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|||||||
146
configure.ac
146
configure.ac
@@ -1,6 +1,6 @@
|
|||||||
# configure.ac
|
# configure.ac
|
||||||
|
|
||||||
AC_INIT([tmux], next-3.8)
|
AC_INIT([tmux], next-3.7)
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
|
|
||||||
AC_CONFIG_AUX_DIR(etc)
|
AC_CONFIG_AUX_DIR(etc)
|
||||||
@@ -76,7 +76,9 @@ AM_CONDITIONAL(IS_OPTIMIZED, test "x$enable_optimizations" = xyes)
|
|||||||
# Is this --enable-asan?
|
# Is this --enable-asan?
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
asan,
|
asan,
|
||||||
AS_HELP_STRING(--enable-asan, enable ASAN build flags)
|
AS_HELP_STRING(--enable-asan, enable ASAN build flags),
|
||||||
|
,
|
||||||
|
enable_asan=no
|
||||||
)
|
)
|
||||||
AM_CONDITIONAL(IS_ASAN, test "x$enable_asan" = xyes)
|
AM_CONDITIONAL(IS_ASAN, test "x$enable_asan" = xyes)
|
||||||
|
|
||||||
@@ -175,6 +177,7 @@ AC_REPLACE_FUNCS([ \
|
|||||||
clock_gettime \
|
clock_gettime \
|
||||||
closefrom \
|
closefrom \
|
||||||
explicit_bzero \
|
explicit_bzero \
|
||||||
|
fgetln \
|
||||||
freezero \
|
freezero \
|
||||||
getdtablecount \
|
getdtablecount \
|
||||||
getdtablesize \
|
getdtablesize \
|
||||||
@@ -238,7 +241,6 @@ AC_LIBOBJ(getopt_long)
|
|||||||
|
|
||||||
# Look for libevent. Try libevent_core or libevent with pkg-config first then
|
# Look for libevent. Try libevent_core or libevent with pkg-config first then
|
||||||
# look for the library.
|
# look for the library.
|
||||||
libevent_version=off
|
|
||||||
PKG_CHECK_MODULES(
|
PKG_CHECK_MODULES(
|
||||||
LIBEVENT_CORE,
|
LIBEVENT_CORE,
|
||||||
[libevent_core >= 2],
|
[libevent_core >= 2],
|
||||||
@@ -247,8 +249,6 @@ PKG_CHECK_MODULES(
|
|||||||
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$LIBEVENT_CORE_LIBS $LIBS"
|
LIBS="$LIBEVENT_CORE_LIBS $LIBS"
|
||||||
found_libevent=yes
|
found_libevent=yes
|
||||||
libevent_version=`$PKG_CONFIG --modversion libevent_core 2>/dev/null`
|
|
||||||
test "x$libevent_version" = x && libevent_version=on
|
|
||||||
],
|
],
|
||||||
found_libevent=no
|
found_libevent=no
|
||||||
)
|
)
|
||||||
@@ -261,8 +261,6 @@ if test x$found_libevent = xno; then
|
|||||||
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$LIBEVENT_LIBS $LIBS"
|
LIBS="$LIBEVENT_LIBS $LIBS"
|
||||||
found_libevent=yes
|
found_libevent=yes
|
||||||
libevent_version=`$PKG_CONFIG --modversion libevent 2>/dev/null`
|
|
||||||
test "x$libevent_version" = x && libevent_version=on
|
|
||||||
],
|
],
|
||||||
found_libevent=no
|
found_libevent=no
|
||||||
)
|
)
|
||||||
@@ -271,8 +269,7 @@ if test x$found_libevent = xno; then
|
|||||||
AC_SEARCH_LIBS(
|
AC_SEARCH_LIBS(
|
||||||
event_init,
|
event_init,
|
||||||
[event_core event event-1.4],
|
[event_core event event-1.4],
|
||||||
[found_libevent=yes
|
found_libevent=yes,
|
||||||
libevent_version=on],
|
|
||||||
found_libevent=no
|
found_libevent=no
|
||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
@@ -299,7 +296,6 @@ fi
|
|||||||
|
|
||||||
# Look for ncurses or curses. Try pkg-config first then directly for the
|
# Look for ncurses or curses. Try pkg-config first then directly for the
|
||||||
# library.
|
# library.
|
||||||
ncurses_version=off
|
|
||||||
PKG_CHECK_MODULES(
|
PKG_CHECK_MODULES(
|
||||||
LIBTINFOW,
|
LIBTINFOW,
|
||||||
tinfow,
|
tinfow,
|
||||||
@@ -308,8 +304,6 @@ PKG_CHECK_MODULES(
|
|||||||
CPPFLAGS="$LIBTINFOW_CFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$LIBTINFOW_CFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$LIBTINFOW_LIBS $LIBS"
|
LIBS="$LIBTINFOW_LIBS $LIBS"
|
||||||
found_ncurses=yes
|
found_ncurses=yes
|
||||||
ncurses_version=`$PKG_CONFIG --modversion tinfow 2>/dev/null`
|
|
||||||
test "x$ncurses_version" = x && ncurses_version=on
|
|
||||||
],
|
],
|
||||||
found_ncurses=no
|
found_ncurses=no
|
||||||
)
|
)
|
||||||
@@ -322,8 +316,6 @@ if test "x$found_ncurses" = xno; then
|
|||||||
CPPFLAGS="$LIBTINFO_CFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$LIBTINFO_CFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$LIBTINFO_LIBS $LIBS"
|
LIBS="$LIBTINFO_LIBS $LIBS"
|
||||||
found_ncurses=yes
|
found_ncurses=yes
|
||||||
ncurses_version=`$PKG_CONFIG --modversion tinfo 2>/dev/null`
|
|
||||||
test "x$ncurses_version" = x && ncurses_version=on
|
|
||||||
],
|
],
|
||||||
found_ncurses=no
|
found_ncurses=no
|
||||||
)
|
)
|
||||||
@@ -337,8 +329,6 @@ if test "x$found_ncurses" = xno; then
|
|||||||
CPPFLAGS="$LIBNCURSESW_CFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$LIBNCURSESW_CFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$LIBNCURSESW_LIBS $LIBS"
|
LIBS="$LIBNCURSESW_LIBS $LIBS"
|
||||||
found_ncurses=yes
|
found_ncurses=yes
|
||||||
ncurses_version=`$PKG_CONFIG --modversion ncursesw 2>/dev/null`
|
|
||||||
test "x$ncurses_version" = x && ncurses_version=on
|
|
||||||
],
|
],
|
||||||
found_ncurses=no
|
found_ncurses=no
|
||||||
)
|
)
|
||||||
@@ -352,8 +342,6 @@ if test "x$found_ncurses" = xno; then
|
|||||||
CPPFLAGS="$LIBNCURSES_CFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$LIBNCURSES_CFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$LIBNCURSES_LIBS $LIBS"
|
LIBS="$LIBNCURSES_LIBS $LIBS"
|
||||||
found_ncurses=yes
|
found_ncurses=yes
|
||||||
ncurses_version=`$PKG_CONFIG --modversion ncurses 2>/dev/null`
|
|
||||||
test "x$ncurses_version" = x && ncurses_version=on
|
|
||||||
],
|
],
|
||||||
found_ncurses=no
|
found_ncurses=no
|
||||||
)
|
)
|
||||||
@@ -362,8 +350,7 @@ if test "x$found_ncurses" = xno; then
|
|||||||
AC_SEARCH_LIBS(
|
AC_SEARCH_LIBS(
|
||||||
setupterm,
|
setupterm,
|
||||||
[tinfow tinfo terminfo ncursesw ncurses],
|
[tinfow tinfo terminfo ncursesw ncurses],
|
||||||
[found_ncurses=yes
|
found_ncurses=yes,
|
||||||
ncurses_version=on],
|
|
||||||
found_ncurses=no
|
found_ncurses=no
|
||||||
)
|
)
|
||||||
if test "x$found_ncurses" = xyes; then
|
if test "x$found_ncurses" = xyes; then
|
||||||
@@ -393,7 +380,6 @@ else
|
|||||||
LIBS="$LIBS -lcurses"
|
LIBS="$LIBS -lcurses"
|
||||||
CPPFLAGS="$CPPFLAGS -DHAVE_CURSES_H"
|
CPPFLAGS="$CPPFLAGS -DHAVE_CURSES_H"
|
||||||
AC_DEFINE(HAVE_CURSES_H)
|
AC_DEFINE(HAVE_CURSES_H)
|
||||||
ncurses_version=on
|
|
||||||
else
|
else
|
||||||
AC_MSG_ERROR("curses not found")
|
AC_MSG_ERROR("curses not found")
|
||||||
fi
|
fi
|
||||||
@@ -404,7 +390,6 @@ AC_CHECK_FUNCS([ \
|
|||||||
])
|
])
|
||||||
|
|
||||||
# Look for utempter.
|
# Look for utempter.
|
||||||
utempter_version=off
|
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
utempter,
|
utempter,
|
||||||
AS_HELP_STRING(--enable-utempter, use utempter if it is installed)
|
AS_HELP_STRING(--enable-utempter, use utempter if it is installed)
|
||||||
@@ -421,34 +406,17 @@ if test "x$enable_utempter" = xyes; then
|
|||||||
fi
|
fi
|
||||||
if test "x$enable_utempter" = xyes; then
|
if test "x$enable_utempter" = xyes; then
|
||||||
AC_DEFINE(HAVE_UTEMPTER)
|
AC_DEFINE(HAVE_UTEMPTER)
|
||||||
utempter_version=on
|
|
||||||
else
|
else
|
||||||
AC_MSG_ERROR("utempter not found")
|
AC_MSG_ERROR("utempter not found")
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Look for utf8proc.
|
# Look for utf8proc.
|
||||||
utf8proc_version=off
|
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
utf8proc,
|
utf8proc,
|
||||||
AS_HELP_STRING(--enable-utf8proc, use utf8proc if it is installed)
|
AS_HELP_STRING(--enable-utf8proc, use utf8proc if it is installed)
|
||||||
)
|
)
|
||||||
try_utf8proc=no
|
|
||||||
require_utf8proc=no
|
|
||||||
if test "x$enable_utf8proc" = xyes; then
|
if test "x$enable_utf8proc" = xyes; then
|
||||||
try_utf8proc=yes
|
|
||||||
elif test "x$enable_utf8proc" = x; then
|
|
||||||
case "$host_os" in
|
|
||||||
*darwin*)
|
|
||||||
try_utf8proc=yes
|
|
||||||
require_utf8proc=yes
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
if test "x$try_utf8proc" = xyes; then
|
|
||||||
SAVED_AM_CPPFLAGS="$AM_CPPFLAGS"
|
|
||||||
SAVED_OLD_CPPFLAGS="$CPPFLAGS"
|
|
||||||
SAVED_LIBS="$LIBS"
|
|
||||||
PKG_CHECK_MODULES(
|
PKG_CHECK_MODULES(
|
||||||
LIBUTF8PROC,
|
LIBUTF8PROC,
|
||||||
libutf8proc,
|
libutf8proc,
|
||||||
@@ -456,10 +424,7 @@ if test "x$try_utf8proc" = xyes; then
|
|||||||
AM_CPPFLAGS="$LIBUTF8PROC_CFLAGS $AM_CPPFLAGS"
|
AM_CPPFLAGS="$LIBUTF8PROC_CFLAGS $AM_CPPFLAGS"
|
||||||
CPPFLAGS="$LIBUTF8PROC_CFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$LIBUTF8PROC_CFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$LIBUTF8PROC_LIBS $LIBS"
|
LIBS="$LIBUTF8PROC_LIBS $LIBS"
|
||||||
utf8proc_version=`$PKG_CONFIG --modversion libutf8proc 2>/dev/null`
|
]
|
||||||
test "x$utf8proc_version" = x && utf8proc_version=on
|
|
||||||
],
|
|
||||||
[:]
|
|
||||||
)
|
)
|
||||||
AC_CHECK_HEADER(utf8proc.h, enable_utf8proc=yes, enable_utf8proc=no)
|
AC_CHECK_HEADER(utf8proc.h, enable_utf8proc=yes, enable_utf8proc=no)
|
||||||
if test "x$enable_utf8proc" = xyes; then
|
if test "x$enable_utf8proc" = xyes; then
|
||||||
@@ -472,23 +437,13 @@ if test "x$try_utf8proc" = xyes; then
|
|||||||
fi
|
fi
|
||||||
if test "x$enable_utf8proc" = xyes; then
|
if test "x$enable_utf8proc" = xyes; then
|
||||||
AC_DEFINE(HAVE_UTF8PROC)
|
AC_DEFINE(HAVE_UTF8PROC)
|
||||||
test "x$utf8proc_version" = xoff && utf8proc_version=on
|
|
||||||
else
|
else
|
||||||
AM_CPPFLAGS="$SAVED_AM_CPPFLAGS"
|
AC_MSG_ERROR("utf8proc not found")
|
||||||
CPPFLAGS="$SAVED_OLD_CPPFLAGS"
|
|
||||||
LIBS="$SAVED_LIBS"
|
|
||||||
utf8proc_version=off
|
|
||||||
if test "x$require_utf8proc" = xyes; then
|
|
||||||
enable_utf8proc=
|
|
||||||
else
|
|
||||||
AC_MSG_ERROR("utf8proc not found")
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(HAVE_UTF8PROC, [test "x$enable_utf8proc" = xyes])
|
AM_CONDITIONAL(HAVE_UTF8PROC, [test "x$enable_utf8proc" = xyes])
|
||||||
|
|
||||||
# Check for systemd support.
|
# Check for systemd support.
|
||||||
systemd_version=off
|
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
systemd,
|
systemd,
|
||||||
AS_HELP_STRING(--enable-systemd, enable systemd integration)
|
AS_HELP_STRING(--enable-systemd, enable systemd integration)
|
||||||
@@ -502,8 +457,6 @@ if test x"$enable_systemd" = xyes; then
|
|||||||
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$SYSTEMD_LIBS $LIBS"
|
LIBS="$SYSTEMD_LIBS $LIBS"
|
||||||
found_systemd=yes
|
found_systemd=yes
|
||||||
systemd_version=`$PKG_CONFIG --modversion libsystemd 2>/dev/null`
|
|
||||||
test "x$systemd_version" = x && systemd_version=on
|
|
||||||
],
|
],
|
||||||
found_systemd=no
|
found_systemd=no
|
||||||
)
|
)
|
||||||
@@ -628,34 +581,11 @@ if test "x$found_malloc_trim" = xyes; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Build against jemalloc if requested.
|
# Build against jemalloc if requested.
|
||||||
jemalloc_version=off
|
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
jemalloc,
|
jemalloc,
|
||||||
AS_HELP_STRING(--enable-jemalloc, use jemalloc if it is installed)
|
AS_HELP_STRING(--enable-jemalloc, use jemalloc if it is installed)
|
||||||
)
|
)
|
||||||
try_jemalloc=no
|
|
||||||
require_jemalloc=no
|
|
||||||
if test "x$enable_asan" = xyes && test "x$enable_jemalloc" = xyes; then
|
|
||||||
AC_MSG_ERROR([--enable-asan and --enable-jemalloc cannot be used together])
|
|
||||||
fi
|
|
||||||
if test "x$enable_jemalloc" = xyes; then
|
if test "x$enable_jemalloc" = xyes; then
|
||||||
try_jemalloc=yes
|
|
||||||
elif test "x$enable_jemalloc" = x; then
|
|
||||||
case "$host_os" in
|
|
||||||
*darwin*)
|
|
||||||
if test "x$enable_asan" = xyes; then
|
|
||||||
enable_jemalloc=no
|
|
||||||
else
|
|
||||||
try_jemalloc=yes
|
|
||||||
require_jemalloc=yes
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
if test "x$try_jemalloc" = xyes; then
|
|
||||||
SAVED_AM_CPPFLAGS="$AM_CPPFLAGS"
|
|
||||||
SAVED_OLD_CPPFLAGS="$CPPFLAGS"
|
|
||||||
SAVED_LIBS="$LIBS"
|
|
||||||
PKG_CHECK_MODULES(
|
PKG_CHECK_MODULES(
|
||||||
JEMALLOC,
|
JEMALLOC,
|
||||||
jemalloc,
|
jemalloc,
|
||||||
@@ -663,26 +593,9 @@ if test "x$try_jemalloc" = xyes; then
|
|||||||
AM_CPPFLAGS="$JEMALLOC_CFLAGS $AM_CPPFLAGS"
|
AM_CPPFLAGS="$JEMALLOC_CFLAGS $AM_CPPFLAGS"
|
||||||
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
|
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
|
||||||
LIBS="$LIBS $JEMALLOC_LIBS"
|
LIBS="$LIBS $JEMALLOC_LIBS"
|
||||||
jemalloc_version=`$PKG_CONFIG --modversion jemalloc 2>/dev/null`
|
|
||||||
test "x$jemalloc_version" = x && jemalloc_version=on
|
|
||||||
],
|
],
|
||||||
enable_jemalloc=no
|
AC_MSG_ERROR("jemalloc not found")
|
||||||
)
|
)
|
||||||
if test "x$enable_jemalloc" = xno; then
|
|
||||||
AM_CPPFLAGS="$SAVED_AM_CPPFLAGS"
|
|
||||||
CPPFLAGS="$SAVED_OLD_CPPFLAGS"
|
|
||||||
LIBS="$SAVED_LIBS"
|
|
||||||
jemalloc_version=off
|
|
||||||
if test "x$require_jemalloc" = xyes; then
|
|
||||||
enable_jemalloc=
|
|
||||||
else
|
|
||||||
AC_MSG_ERROR("jemalloc not found")
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
enable_jemalloc=yes
|
|
||||||
AC_DEFINE(HAVE_JEMALLOC)
|
|
||||||
test "x$jemalloc_version" = xoff && jemalloc_version=on
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for CMSG_DATA. On some platforms like HP-UX this requires UNIX 95
|
# Check for CMSG_DATA. On some platforms like HP-UX this requires UNIX 95
|
||||||
@@ -1029,20 +942,6 @@ case "$host_os" in
|
|||||||
AC_MSG_NOTICE([])
|
AC_MSG_NOTICE([])
|
||||||
AC_MSG_ERROR([must give --enable-utf8proc or --disable-utf8proc])
|
AC_MSG_ERROR([must give --enable-utf8proc or --disable-utf8proc])
|
||||||
fi
|
fi
|
||||||
#
|
|
||||||
# macOS calloc(3) does not appear to always zero memory correctly,
|
|
||||||
# so complain and suggest using jemalloc instead.
|
|
||||||
#
|
|
||||||
if test "x$enable_jemalloc" = x; then
|
|
||||||
AC_MSG_NOTICE([])
|
|
||||||
AC_MSG_NOTICE([ macOS calloc(3) appears not to correctly])
|
|
||||||
AC_MSG_NOTICE([ zero allocations in some circumstances;])
|
|
||||||
AC_MSG_NOTICE([ to avoid this, configuring with])
|
|
||||||
AC_MSG_NOTICE([ --enable-jemalloc is recommended. To build])
|
|
||||||
AC_MSG_NOTICE([ without anyway, use --disable-jemalloc])
|
|
||||||
AC_MSG_NOTICE([])
|
|
||||||
AC_MSG_ERROR([must give --enable-jemalloc or --disable-jemalloc])
|
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
*dragonfly*)
|
*dragonfly*)
|
||||||
AC_MSG_RESULT(dragonfly)
|
AC_MSG_RESULT(dragonfly)
|
||||||
@@ -1130,31 +1029,6 @@ AC_MSG_CHECKING(lock-command)
|
|||||||
AC_MSG_RESULT($DEFAULT_LOCK_CMD)
|
AC_MSG_RESULT($DEFAULT_LOCK_CMD)
|
||||||
AC_SUBST(DEFAULT_LOCK_CMD)
|
AC_SUBST(DEFAULT_LOCK_CMD)
|
||||||
|
|
||||||
# Print a summary.
|
|
||||||
AC_MSG_NOTICE([])
|
|
||||||
if test "x$enable_asan" = xyes; then
|
|
||||||
AC_MSG_NOTICE([ASAN: on])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ASAN: off])
|
|
||||||
fi
|
|
||||||
if test "x$enable_sixel" = xyes; then
|
|
||||||
AC_MSG_NOTICE([SIXEL: on])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([SIXEL: off])
|
|
||||||
fi
|
|
||||||
if test "x$enable_debug" = xyes; then
|
|
||||||
AC_MSG_NOTICE([debug: on])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([debug: off])
|
|
||||||
fi
|
|
||||||
AC_MSG_NOTICE([jemalloc: $jemalloc_version])
|
|
||||||
AC_MSG_NOTICE([libevent: $libevent_version])
|
|
||||||
AC_MSG_NOTICE([ncurses: $ncurses_version])
|
|
||||||
AC_MSG_NOTICE([systemd: $systemd_version])
|
|
||||||
AC_MSG_NOTICE([utempter: $utempter_version])
|
|
||||||
AC_MSG_NOTICE([utf8proc: $utf8proc_version])
|
|
||||||
AC_MSG_NOTICE([])
|
|
||||||
|
|
||||||
# Save our CFLAGS/CPPFLAGS/LDFLAGS for the Makefile and restore the old user
|
# Save our CFLAGS/CPPFLAGS/LDFLAGS for the Makefile and restore the old user
|
||||||
# variables.
|
# variables.
|
||||||
AC_SUBST(AM_CPPFLAGS)
|
AC_SUBST(AM_CPPFLAGS)
|
||||||
|
|||||||
335
control-notify.c
335
control-notify.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: control-notify.c,v 1.38 2026/08/03 13:38:42 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -23,58 +23,31 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/* Should this client be sent events? */
|
|
||||||
#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
|
#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
|
||||||
((c) != NULL && \
|
((c) != NULL && ((c)->flags & CLIENT_CONTROL) && \
|
||||||
((c)->flags & CLIENT_CONTROL) && \
|
|
||||||
(~(c)->flags & CLIENT_EXIT) && \
|
|
||||||
(c)->control_state != NULL)
|
(c)->control_state != NULL)
|
||||||
|
|
||||||
/* Notify control clients that pane mode changed. */
|
void
|
||||||
static void
|
control_notify_pane_mode_changed(int pane)
|
||||||
control_pane_mode_changed_cb(__unused const char *name,
|
|
||||||
struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct window_pane *wp;
|
struct client *c;
|
||||||
struct client *c;
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
wp = event_payload_get_pane(ep, "pane");
|
|
||||||
if (wp != NULL) {
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
|
||||||
continue;
|
|
||||||
control_notify_write(c, "%%pane-mode-changed %%%u",
|
|
||||||
wp->id);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = event_payload_print(ep, "pane");
|
|
||||||
if (value == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
continue;
|
continue;
|
||||||
control_notify_write(c, "%%pane-mode-changed %s", value);
|
|
||||||
|
control_write(c, "%%pane-mode-changed %%%u", pane);
|
||||||
}
|
}
|
||||||
free(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that window layout changed. */
|
void
|
||||||
static void
|
control_notify_window_layout_changed(struct window *w)
|
||||||
control_window_layout_changed_cb(__unused const char *name,
|
|
||||||
struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window *w = event_payload_get_window(ep, "window");
|
const char *template;
|
||||||
const char *template;
|
char *cp;
|
||||||
char *cp;
|
|
||||||
|
|
||||||
if (w == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
template = "%layout-change #{window_id} #{window_layout} "
|
template = "%layout-change #{window_id} #{window_layout} "
|
||||||
"#{window_visible_layout} #{window_raw_flags}";
|
"#{window_visible_layout} #{window_raw_flags}";
|
||||||
@@ -94,116 +67,91 @@ control_window_layout_changed_cb(__unused const char *name,
|
|||||||
continue;
|
continue;
|
||||||
s = c->session;
|
s = c->session;
|
||||||
if (winlink_find_by_window_id(&s->windows, w->id) != NULL)
|
if (winlink_find_by_window_id(&s->windows, w->id) != NULL)
|
||||||
control_notify_write(c, "%s", cp);
|
control_write(c, "%s", cp);
|
||||||
}
|
}
|
||||||
free(cp);
|
free(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that window pane changed. */
|
void
|
||||||
static void
|
control_notify_window_pane_changed(struct window *w)
|
||||||
control_window_pane_changed_cb(__unused const char *name,
|
|
||||||
struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct window *w = event_payload_get_window(ep, "window");
|
|
||||||
|
|
||||||
if (w == NULL || w->active == NULL)
|
if (w->active == NULL)
|
||||||
return;
|
return;
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
control_notify_write(c, "%%window-pane-changed @%u %%%u", w->id,
|
control_write(c, "%%window-pane-changed @%u %%%u", w->id,
|
||||||
w->active->id);
|
w->active->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that a window was unlinked. */
|
void
|
||||||
static void
|
control_notify_window_unlinked(__unused struct session *s, struct window *w)
|
||||||
control_window_unlinked_cb(__unused const char *name, struct event_payload *ep,
|
|
||||||
__unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *cs;
|
struct session *cs;
|
||||||
struct window *w = event_payload_get_window(ep, "window");
|
|
||||||
|
|
||||||
if (w == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||||
continue;
|
continue;
|
||||||
cs = c->session;
|
cs = c->session;
|
||||||
|
|
||||||
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
|
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
|
||||||
control_notify_write(c, "%%window-close @%u", w->id);
|
control_write(c, "%%window-close @%u", w->id);
|
||||||
else {
|
else
|
||||||
control_notify_write(c, "%%unlinked-window-close @%u",
|
control_write(c, "%%unlinked-window-close @%u", w->id);
|
||||||
w->id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that a window was linked. */
|
void
|
||||||
static void
|
control_notify_window_linked(__unused struct session *s, struct window *w)
|
||||||
control_window_linked_cb(__unused const char *name, struct event_payload *ep,
|
|
||||||
__unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *cs;
|
struct session *cs;
|
||||||
struct window *w = event_payload_get_window(ep, "window");
|
|
||||||
|
|
||||||
if (w == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||||
continue;
|
continue;
|
||||||
cs = c->session;
|
cs = c->session;
|
||||||
|
|
||||||
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
|
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
|
||||||
control_notify_write(c, "%%window-add @%u", w->id);
|
control_write(c, "%%window-add @%u", w->id);
|
||||||
else {
|
else
|
||||||
control_notify_write(c, "%%unlinked-window-add @%u",
|
control_write(c, "%%unlinked-window-add @%u", w->id);
|
||||||
w->id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that a window was renamed. */
|
void
|
||||||
static void
|
control_notify_window_renamed(struct window *w)
|
||||||
control_window_renamed_cb(__unused const char *name, struct event_payload *ep,
|
|
||||||
__unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *cs;
|
struct session *cs;
|
||||||
struct window *w = event_payload_get_window(ep, "window");
|
|
||||||
|
|
||||||
if (w == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||||
continue;
|
continue;
|
||||||
cs = c->session;
|
cs = c->session;
|
||||||
|
|
||||||
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
|
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL) {
|
||||||
control_notify_write(c, "%%window-renamed @%u %s",
|
control_write(c, "%%window-renamed @%u %s", w->id,
|
||||||
w->id, w->name);
|
w->name);
|
||||||
} else {
|
} else {
|
||||||
control_notify_write(c,
|
control_write(c, "%%unlinked-window-renamed @%u %s",
|
||||||
"%%unlinked-window-renamed @%u %s", w->id, w->name);
|
w->id, w->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that a client changed session. */
|
void
|
||||||
static void
|
control_notify_client_session_changed(struct client *cc)
|
||||||
control_client_session_changed_cb(__unused const char *name,
|
|
||||||
struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *cc = event_payload_get_client(ep, "client");
|
struct client *c;
|
||||||
struct client *c;
|
struct session *s;
|
||||||
struct session *s;
|
|
||||||
|
|
||||||
if (cc == NULL || cc->session == NULL)
|
if (cc->session == NULL)
|
||||||
return;
|
return;
|
||||||
s = cc->session;
|
s = cc->session;
|
||||||
|
|
||||||
@@ -212,107 +160,68 @@ control_client_session_changed_cb(__unused const char *name,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (cc == c) {
|
if (cc == c) {
|
||||||
control_notify_write(c, "%%session-changed $%u %s",
|
control_write(c, "%%session-changed $%u %s", s->id,
|
||||||
s->id, s->name);
|
s->name);
|
||||||
} else {
|
} else {
|
||||||
control_notify_write(c,
|
control_write(c, "%%client-session-changed %s $%u %s",
|
||||||
"%%client-session-changed %s $%u %s", cc->name,
|
cc->name, s->id, s->name);
|
||||||
s->id, s->name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that a client changed its effective window. */
|
void
|
||||||
static void
|
control_notify_client_detached(struct client *cc)
|
||||||
control_client_window_changed_cb(__unused const char *name,
|
|
||||||
struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *cc = event_payload_get_client(ep, "client");
|
struct client *c;
|
||||||
struct session *s = event_payload_get_session(ep, "session");
|
|
||||||
struct window *w = event_payload_get_window(ep, "window");
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if (cc == NULL || s == NULL || w == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
if (CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
continue;
|
control_write(c, "%%client-detached %s", cc->name);
|
||||||
|
|
||||||
control_write(c, "%%client-window-changed %s $%u @%u",
|
|
||||||
cc->name, s->id, w->id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that a client detached. */
|
void
|
||||||
static void
|
control_notify_session_renamed(struct session *s)
|
||||||
control_client_detached_cb(__unused const char *name, struct event_payload *ep,
|
|
||||||
__unused void *sink_data)
|
|
||||||
{
|
|
||||||
struct client *cc = event_payload_get_client(ep, "client");
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if (cc == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
|
||||||
continue;
|
|
||||||
control_notify_write(c, "%%client-detached %s", cc->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify control clients that a session was renamed. */
|
|
||||||
static void
|
|
||||||
control_session_renamed_cb(__unused const char *name, struct event_payload *ep,
|
|
||||||
__unused void *sink_data)
|
|
||||||
{
|
|
||||||
struct session *s = event_payload_get_session(ep, "session");
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if (s == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
|
||||||
continue;
|
|
||||||
control_notify_write(c, "%%session-renamed $%u %s", s->id,
|
|
||||||
s->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify control clients that sessions changed. */
|
|
||||||
static void
|
|
||||||
control_session_created_cb(__unused const char *name,
|
|
||||||
__unused struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
continue;
|
continue;
|
||||||
control_notify_write(c, "%%sessions-changed");
|
|
||||||
|
control_write(c, "%%session-renamed $%u %s", s->id, s->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that sessions changed. */
|
void
|
||||||
static void
|
control_notify_session_created(__unused struct session *s)
|
||||||
control_session_closed_cb(__unused const char *name,
|
|
||||||
__unused struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
continue;
|
continue;
|
||||||
control_notify_write(c, "%%sessions-changed");
|
|
||||||
|
control_write(c, "%%sessions-changed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that the current window changed. */
|
void
|
||||||
static void
|
control_notify_session_closed(__unused struct session *s)
|
||||||
control_session_window_changed_cb(__unused const char *name,
|
{
|
||||||
struct event_payload *ep, __unused void *sink_data)
|
struct client *c;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
control_write(c, "%%sessions-changed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
control_notify_session_window_changed(struct session *s)
|
||||||
{
|
{
|
||||||
struct session *s = event_payload_get_session(ep, "session");
|
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -320,78 +229,40 @@ control_session_window_changed_cb(__unused const char *name,
|
|||||||
* session has been destroyed (which sets curw to NULL) but is kept
|
* session has been destroyed (which sets curw to NULL) but is kept
|
||||||
* alive by the notification's reference. Skip the notification.
|
* alive by the notification's reference. Skip the notification.
|
||||||
*/
|
*/
|
||||||
if (s == NULL || s->curw == NULL)
|
if (s->curw == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
continue;
|
continue;
|
||||||
control_notify_write(c, "%%session-window-changed $%u @%u",
|
|
||||||
s->id, s->curw->window->id);
|
control_write(c, "%%session-window-changed $%u @%u", s->id,
|
||||||
|
s->curw->window->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify control clients that a paste buffer changed. */
|
|
||||||
static void
|
|
||||||
control_paste_buffer_changed_cb(__unused const char *name,
|
|
||||||
struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
|
||||||
const char *pbname = event_payload_get_string(ep, "paste_buffer");
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if (pbname == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
|
||||||
continue;
|
|
||||||
control_notify_write(c, "%%paste-buffer-changed %s", pbname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify control clients that a paste buffer was deleted. */
|
|
||||||
static void
|
|
||||||
control_paste_buffer_deleted_cb(__unused const char *name,
|
|
||||||
struct event_payload *ep, __unused void *sink_data)
|
|
||||||
{
|
|
||||||
const char *pbname = event_payload_get_string(ep, "paste_buffer");
|
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
if (pbname == NULL)
|
|
||||||
return;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
|
||||||
continue;
|
|
||||||
control_notify_write(c, "%%paste-buffer-deleted %s", pbname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build control event sinks. */
|
|
||||||
void
|
void
|
||||||
control_build_events(void)
|
control_notify_paste_buffer_changed(const char *name)
|
||||||
{
|
{
|
||||||
/* Control event sink callbacks. */
|
struct client *c;
|
||||||
static struct {
|
|
||||||
const char *name;
|
|
||||||
events_cb cb;
|
|
||||||
} events[] = {
|
|
||||||
{ "pane-mode-changed", control_pane_mode_changed_cb },
|
|
||||||
{ "window-layout-changed", control_window_layout_changed_cb },
|
|
||||||
{ "window-pane-changed", control_window_pane_changed_cb },
|
|
||||||
{ "window-unlinked", control_window_unlinked_cb },
|
|
||||||
{ "window-linked", control_window_linked_cb },
|
|
||||||
{ "window-renamed", control_window_renamed_cb },
|
|
||||||
{ "client-session-changed", control_client_session_changed_cb },
|
|
||||||
{ "client-window-changed", control_client_window_changed_cb },
|
|
||||||
{ "client-detached", control_client_detached_cb },
|
|
||||||
{ "session-renamed", control_session_renamed_cb },
|
|
||||||
{ "session-created", control_session_created_cb },
|
|
||||||
{ "session-closed", control_session_closed_cb },
|
|
||||||
{ "session-window-changed", control_session_window_changed_cb },
|
|
||||||
{ "paste-buffer-changed", control_paste_buffer_changed_cb },
|
|
||||||
{ "paste-buffer-deleted", control_paste_buffer_deleted_cb }
|
|
||||||
};
|
|
||||||
u_int i;
|
|
||||||
|
|
||||||
for (i = 0; i < nitems(events); i++)
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
events_add_sink(events[i].name, events[i].cb, NULL);
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
control_write(c, "%%paste-buffer-changed %s", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
control_notify_paste_buffer_deleted(const char *name)
|
||||||
|
{
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
control_write(c, "%%paste-buffer-deleted %s", name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
754
control.c
754
control.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: control.c,v 1.66 2026/08/18 07:43:44 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -19,9 +19,6 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <event.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -53,17 +50,6 @@ struct control_block {
|
|||||||
TAILQ_ENTRY(control_block) all_entry;
|
TAILQ_ENTRY(control_block) all_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* A notification line deferred because it was generated while a command's
|
|
||||||
* %begin/%end guard block was open. Notifications must never appear inside a
|
|
||||||
* guard block, so they are held here and flushed once the block closes.
|
|
||||||
*/
|
|
||||||
struct control_line {
|
|
||||||
char *line;
|
|
||||||
|
|
||||||
TAILQ_ENTRY(control_line) entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Control client pane. */
|
/* Control client pane. */
|
||||||
struct control_pane {
|
struct control_pane {
|
||||||
u_int pane;
|
u_int pane;
|
||||||
@@ -89,20 +75,45 @@ struct control_pane {
|
|||||||
};
|
};
|
||||||
RB_HEAD(control_panes, control_pane);
|
RB_HEAD(control_panes, control_pane);
|
||||||
|
|
||||||
/* Control client window size. */
|
/* Subscription pane. */
|
||||||
struct control_window {
|
struct control_sub_pane {
|
||||||
u_int window;
|
u_int pane;
|
||||||
u_int sx;
|
u_int idx;
|
||||||
u_int sy;
|
char *last;
|
||||||
|
|
||||||
RB_ENTRY(control_window) entry;
|
RB_ENTRY(control_sub_pane) entry;
|
||||||
};
|
};
|
||||||
RB_HEAD(control_windows, control_window);
|
RB_HEAD(control_sub_panes, control_sub_pane);
|
||||||
|
|
||||||
|
/* Subscription window. */
|
||||||
|
struct control_sub_window {
|
||||||
|
u_int window;
|
||||||
|
u_int idx;
|
||||||
|
char *last;
|
||||||
|
|
||||||
|
RB_ENTRY(control_sub_window) entry;
|
||||||
|
};
|
||||||
|
RB_HEAD(control_sub_windows, control_sub_window);
|
||||||
|
|
||||||
|
/* Control client subscription. */
|
||||||
|
struct control_sub {
|
||||||
|
char *name;
|
||||||
|
char *format;
|
||||||
|
|
||||||
|
enum control_sub_type type;
|
||||||
|
u_int id;
|
||||||
|
|
||||||
|
char *last;
|
||||||
|
struct control_sub_panes panes;
|
||||||
|
struct control_sub_windows windows;
|
||||||
|
|
||||||
|
RB_ENTRY(control_sub) entry;
|
||||||
|
};
|
||||||
|
RB_HEAD(control_subs, control_sub);
|
||||||
|
|
||||||
/* Control client state. */
|
/* Control client state. */
|
||||||
struct control_state {
|
struct control_state {
|
||||||
struct control_panes panes;
|
struct control_panes panes;
|
||||||
struct control_windows windows;
|
|
||||||
|
|
||||||
TAILQ_HEAD(, control_pane) pending_list;
|
TAILQ_HEAD(, control_pane) pending_list;
|
||||||
u_int pending_count;
|
u_int pending_count;
|
||||||
@@ -112,14 +123,8 @@ struct control_state {
|
|||||||
struct bufferevent *read_event;
|
struct bufferevent *read_event;
|
||||||
struct bufferevent *write_event;
|
struct bufferevent *write_event;
|
||||||
|
|
||||||
struct monitor_set *subs;
|
struct control_subs subs;
|
||||||
|
struct event subs_timer;
|
||||||
/*
|
|
||||||
* Depth of open %begin/%end guard blocks and notifications deferred
|
|
||||||
* until the outermost block closes.
|
|
||||||
*/
|
|
||||||
int guard_depth;
|
|
||||||
TAILQ_HEAD(, control_line) deferred;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Low and high watermarks. */
|
/* Low and high watermarks. */
|
||||||
@@ -149,17 +154,74 @@ control_pane_cmp(struct control_pane *cp1, struct control_pane *cp2)
|
|||||||
}
|
}
|
||||||
RB_GENERATE_STATIC(control_panes, control_pane, entry, control_pane_cmp);
|
RB_GENERATE_STATIC(control_panes, control_pane, entry, control_pane_cmp);
|
||||||
|
|
||||||
/* Compare control windows. */
|
/* Compare client subs. */
|
||||||
static int
|
static int
|
||||||
control_window_cmp(struct control_window *cw1, struct control_window *cw2)
|
control_sub_cmp(struct control_sub *csub1, struct control_sub *csub2)
|
||||||
{
|
{
|
||||||
if (cw1->window < cw2->window)
|
return (strcmp(csub1->name, csub2->name));
|
||||||
|
}
|
||||||
|
RB_GENERATE_STATIC(control_subs, control_sub, entry, control_sub_cmp);
|
||||||
|
|
||||||
|
/* Compare client subscription panes. */
|
||||||
|
static int
|
||||||
|
control_sub_pane_cmp(struct control_sub_pane *csp1,
|
||||||
|
struct control_sub_pane *csp2)
|
||||||
|
{
|
||||||
|
if (csp1->pane < csp2->pane)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (cw1->window > cw2->window)
|
if (csp1->pane > csp2->pane)
|
||||||
|
return (1);
|
||||||
|
if (csp1->idx < csp2->idx)
|
||||||
|
return (-1);
|
||||||
|
if (csp1->idx > csp2->idx)
|
||||||
return (1);
|
return (1);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
RB_GENERATE_STATIC(control_windows, control_window, entry, control_window_cmp);
|
RB_GENERATE_STATIC(control_sub_panes, control_sub_pane, entry,
|
||||||
|
control_sub_pane_cmp);
|
||||||
|
|
||||||
|
/* Compare client subscription windows. */
|
||||||
|
static int
|
||||||
|
control_sub_window_cmp(struct control_sub_window *csw1,
|
||||||
|
struct control_sub_window *csw2)
|
||||||
|
{
|
||||||
|
if (csw1->window < csw2->window)
|
||||||
|
return (-1);
|
||||||
|
if (csw1->window > csw2->window)
|
||||||
|
return (1);
|
||||||
|
if (csw1->idx < csw2->idx)
|
||||||
|
return (-1);
|
||||||
|
if (csw1->idx > csw2->idx)
|
||||||
|
return (1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
RB_GENERATE_STATIC(control_sub_windows, control_sub_window, entry,
|
||||||
|
control_sub_window_cmp);
|
||||||
|
|
||||||
|
/* Free a subscription. */
|
||||||
|
static void
|
||||||
|
control_free_sub(struct control_state *cs, struct control_sub *csub)
|
||||||
|
{
|
||||||
|
struct control_sub_pane *csp, *csp1;
|
||||||
|
struct control_sub_window *csw, *csw1;
|
||||||
|
|
||||||
|
RB_FOREACH_SAFE(csp, control_sub_panes, &csub->panes, csp1) {
|
||||||
|
RB_REMOVE(control_sub_panes, &csub->panes, csp);
|
||||||
|
free(csp->last);
|
||||||
|
free(csp);
|
||||||
|
}
|
||||||
|
RB_FOREACH_SAFE(csw, control_sub_windows, &csub->windows, csw1) {
|
||||||
|
RB_REMOVE(control_sub_windows, &csub->windows, csw);
|
||||||
|
free(csw->last);
|
||||||
|
free(csw);
|
||||||
|
}
|
||||||
|
free(csub->last);
|
||||||
|
|
||||||
|
RB_REMOVE(control_subs, &cs->subs, csub);
|
||||||
|
free(csub->name);
|
||||||
|
free(csub->format);
|
||||||
|
free(csub);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free a block. */
|
/* Free a block. */
|
||||||
static void
|
static void
|
||||||
@@ -202,66 +264,6 @@ control_add_pane(struct client *c, struct window_pane *wp)
|
|||||||
return (cp);
|
return (cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get window for this client. */
|
|
||||||
static struct control_window *
|
|
||||||
control_get_window(struct client *c, u_int window)
|
|
||||||
{
|
|
||||||
struct control_state *cs = c->control_state;
|
|
||||||
struct control_window cw = { .window = window };
|
|
||||||
|
|
||||||
if (cs == NULL)
|
|
||||||
return (NULL);
|
|
||||||
return (RB_FIND(control_windows, &cs->windows, &cw));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set window size for this client. */
|
|
||||||
void
|
|
||||||
control_set_window_size(struct client *c, u_int window, u_int sx, u_int sy)
|
|
||||||
{
|
|
||||||
struct control_state *cs = c->control_state;
|
|
||||||
struct control_window *cw;
|
|
||||||
|
|
||||||
if (cs == NULL)
|
|
||||||
return;
|
|
||||||
cw = control_get_window(c, window);
|
|
||||||
if (cw == NULL) {
|
|
||||||
cw = xcalloc(1, sizeof *cw);
|
|
||||||
cw->window = window;
|
|
||||||
RB_INSERT(control_windows, &cs->windows, cw);
|
|
||||||
}
|
|
||||||
cw->sx = sx;
|
|
||||||
cw->sy = sy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get window size for this client. */
|
|
||||||
int
|
|
||||||
control_get_window_size(struct client *c, u_int window, u_int *sx, u_int *sy)
|
|
||||||
{
|
|
||||||
struct control_window *cw;
|
|
||||||
|
|
||||||
if ((cw = control_get_window(c, window)) == NULL)
|
|
||||||
return (0);
|
|
||||||
*sx = cw->sx;
|
|
||||||
*sy = cw->sy;
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear window size for this client. */
|
|
||||||
void
|
|
||||||
control_clear_window_size(struct client *c, u_int window)
|
|
||||||
{
|
|
||||||
struct control_state *cs = c->control_state;
|
|
||||||
struct control_window *cw;
|
|
||||||
|
|
||||||
if (cs == NULL)
|
|
||||||
return;
|
|
||||||
cw = control_get_window(c, window);
|
|
||||||
if (cw != NULL) {
|
|
||||||
RB_REMOVE(control_windows, &cs->windows, cw);
|
|
||||||
free(cw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Discard output for a pane. */
|
/* Discard output for a pane. */
|
||||||
static void
|
static void
|
||||||
control_discard_pane(struct client *c, struct control_pane *cp)
|
control_discard_pane(struct client *c, struct control_pane *cp)
|
||||||
@@ -370,7 +372,7 @@ control_continue_pane(struct client *c, struct window_pane *wp)
|
|||||||
cp->flags &= ~CONTROL_PANE_PAUSED;
|
cp->flags &= ~CONTROL_PANE_PAUSED;
|
||||||
memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
|
memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
|
||||||
memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
|
memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
|
||||||
control_notify_write(c, "%%continue %%%u", wp->id);
|
control_write(c, "%%continue %%%u", wp->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,139 +386,52 @@ control_pause_pane(struct client *c, struct window_pane *wp)
|
|||||||
if (~cp->flags & CONTROL_PANE_PAUSED) {
|
if (~cp->flags & CONTROL_PANE_PAUSED) {
|
||||||
cp->flags |= CONTROL_PANE_PAUSED;
|
cp->flags |= CONTROL_PANE_PAUSED;
|
||||||
control_discard_pane(c, cp);
|
control_discard_pane(c, cp);
|
||||||
control_notify_write(c, "%%pause %%%u", wp->id);
|
control_write(c, "%%pause %%%u", wp->id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Write a line. */
|
||||||
* Reset a pane after its buffer has been replaced: drop any output still
|
static void printflike(2, 0)
|
||||||
* queued from the old buffer and start again from the pane's own offset.
|
control_vwrite(struct client *c, const char *fmt, va_list ap)
|
||||||
*/
|
|
||||||
void
|
|
||||||
control_reset_pane(struct client *c, struct window_pane *wp)
|
|
||||||
{
|
{
|
||||||
struct control_pane *cp;
|
struct control_state *cs = c->control_state;
|
||||||
|
char *s;
|
||||||
|
|
||||||
if (c->control_state == NULL)
|
xvasprintf(&s, fmt, ap);
|
||||||
return;
|
log_debug("%s: %s: writing line: %s", __func__, c->name, s);
|
||||||
cp = control_get_pane(c, wp);
|
|
||||||
if (cp == NULL)
|
bufferevent_write(cs->write_event, s, strlen(s));
|
||||||
return;
|
bufferevent_write(cs->write_event, "\n", 1);
|
||||||
control_discard_pane(c, cp);
|
|
||||||
memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
|
bufferevent_enable(cs->write_event, EV_WRITE);
|
||||||
memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write an already-formatted line, queueing it behind %output if needed. */
|
/* Write a line. */
|
||||||
static void
|
void
|
||||||
control_write_line(struct client *c, char *line)
|
control_write(struct client *c, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct control_state *cs = c->control_state;
|
struct control_state *cs = c->control_state;
|
||||||
struct control_block *cb;
|
struct control_block *cb;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
if (TAILQ_EMPTY(&cs->all_blocks)) {
|
if (TAILQ_EMPTY(&cs->all_blocks)) {
|
||||||
log_debug("%s: %s: writing line: %s", __func__, c->name, line);
|
control_vwrite(c, fmt, ap);
|
||||||
bufferevent_write(cs->write_event, line, strlen(line));
|
va_end(ap);
|
||||||
bufferevent_write(cs->write_event, "\n", 1);
|
|
||||||
bufferevent_enable(cs->write_event, EV_WRITE);
|
|
||||||
free(line);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cb = xcalloc(1, sizeof *cb);
|
cb = xcalloc(1, sizeof *cb);
|
||||||
cb->line = line;
|
xvasprintf(&cb->line, fmt, ap);
|
||||||
TAILQ_INSERT_TAIL(&cs->all_blocks, cb, all_entry);
|
TAILQ_INSERT_TAIL(&cs->all_blocks, cb, all_entry);
|
||||||
cb->t = get_timer();
|
cb->t = get_timer();
|
||||||
|
|
||||||
log_debug("%s: %s: storing line: %s", __func__, c->name, cb->line);
|
log_debug("%s: %s: storing line: %s", __func__, c->name, cb->line);
|
||||||
bufferevent_enable(cs->write_event, EV_WRITE);
|
bufferevent_enable(cs->write_event, EV_WRITE);
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush notifications that were deferred while a guard block was open. */
|
|
||||||
static void
|
|
||||||
control_flush_deferred(struct client *c)
|
|
||||||
{
|
|
||||||
struct control_state *cs = c->control_state;
|
|
||||||
struct control_line *cl, *cl1;
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(cl, &cs->deferred, entry, cl1) {
|
|
||||||
TAILQ_REMOVE(&cs->deferred, cl, entry);
|
|
||||||
control_write_line(c, cl->line);
|
|
||||||
free(cl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write a line of command output or error text. This is a sink for arbitrary
|
|
||||||
* user-controlled text (command output, capture-pane, error messages), so it
|
|
||||||
* must never try to interpret the content: guard tracking is done only in
|
|
||||||
* control_write_guard.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
control_write(struct client *c, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
char *line;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
xvasprintf(&line, fmt, ap);
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
control_write_line(c, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write a %begin, %end or %error guard around a command's output. This is the
|
|
||||||
* only place guard lines are produced, so the block depth is maintained here;
|
|
||||||
* when the outermost block closes any deferred notifications are flushed after
|
|
||||||
* it. "guard" is always one of the fixed strings from cmdq_guard, never user
|
|
||||||
* text.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
control_write_guard(struct client *c, const char *guard, long t, u_int number,
|
|
||||||
int flags)
|
|
||||||
{
|
|
||||||
struct control_state *cs = c->control_state;
|
|
||||||
char *line;
|
|
||||||
|
|
||||||
if (strcmp(guard, "begin") == 0)
|
|
||||||
cs->guard_depth++;
|
|
||||||
|
|
||||||
xasprintf(&line, "%%%s %ld %u %d", guard, t, number, flags);
|
|
||||||
control_write_line(c, line);
|
|
||||||
|
|
||||||
if (strcmp(guard, "begin") != 0 && cs->guard_depth > 0 &&
|
|
||||||
--cs->guard_depth == 0)
|
|
||||||
control_flush_deferred(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write a notification line. Notifications must never appear inside a command's
|
|
||||||
* %begin/%end guard block, so if one is open the line is deferred until it
|
|
||||||
* closes.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
control_notify_write(struct client *c, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
struct control_state *cs = c->control_state;
|
|
||||||
struct control_line *cl;
|
|
||||||
va_list ap;
|
|
||||||
char *line;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
xvasprintf(&line, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (cs->guard_depth == 0) {
|
|
||||||
control_write_line(c, line);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug("%s: %s: deferring notification: %s", __func__, c->name,
|
|
||||||
line);
|
|
||||||
cl = xcalloc(1, sizeof *cl);
|
|
||||||
cl->line = line;
|
|
||||||
TAILQ_INSERT_TAIL(&cs->deferred, cl, entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check age for this pane. */
|
/* Check age for this pane. */
|
||||||
@@ -543,7 +458,7 @@ control_check_age(struct client *c, struct window_pane *wp,
|
|||||||
return (0);
|
return (0);
|
||||||
cp->flags |= CONTROL_PANE_PAUSED;
|
cp->flags |= CONTROL_PANE_PAUSED;
|
||||||
control_discard_pane(c, cp);
|
control_discard_pane(c, cp);
|
||||||
control_notify_write(c, "%%pause %%%u", wp->id);
|
control_write(c, "%%pause %%%u", wp->id);
|
||||||
} else {
|
} else {
|
||||||
if (age < CONTROL_MAXIMUM_AGE)
|
if (age < CONTROL_MAXIMUM_AGE)
|
||||||
return (0);
|
return (0);
|
||||||
@@ -566,7 +481,7 @@ control_write_output(struct client *c, struct window_pane *wp)
|
|||||||
if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
|
if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (c->flags & (CONTROL_IGNORE_FLAGS|CLIENT_EXIT)) {
|
if (c->flags & CONTROL_IGNORE_FLAGS) {
|
||||||
cp = control_get_pane(c, wp);
|
cp = control_get_pane(c, wp);
|
||||||
if (cp != NULL)
|
if (cp != NULL)
|
||||||
goto ignore;
|
goto ignore;
|
||||||
@@ -676,53 +591,6 @@ control_all_done(struct client *c)
|
|||||||
return (EVBUFFER_LENGTH(cs->write_event->output) == 0);
|
return (EVBUFFER_LENGTH(cs->write_event->output) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Wait for the terminal to send an empty line or close, used by a control
|
|
||||||
* client after printing %exit so a wrapping terminal (such as iTerm2) can
|
|
||||||
* finish reading.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
control_wait_exit(int fd)
|
|
||||||
{
|
|
||||||
struct pollfd pfd;
|
|
||||||
struct evbuffer *evb;
|
|
||||||
char *line;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
evb = evbuffer_new();
|
|
||||||
if (evb == NULL)
|
|
||||||
fatalx("out of memory");
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
line = evbuffer_readln(evb, NULL, EVBUFFER_EOL_LF);
|
|
||||||
if (line != NULL) {
|
|
||||||
if (*line == '\0') { /* empty line, stop */
|
|
||||||
free(line);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free(line);
|
|
||||||
continue; /* drain buffered lines first */
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&pfd, 0, sizeof pfd);
|
|
||||||
pfd.fd = fd;
|
|
||||||
pfd.events = POLLIN;
|
|
||||||
if (poll(&pfd, 1, INFTIM) == -1) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = evbuffer_read(evb, fd, -1);
|
|
||||||
if (n == 0)
|
|
||||||
break;
|
|
||||||
if (n == -1 && errno != EAGAIN && errno != EINTR)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
evbuffer_free(evb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush all blocks until output. */
|
/* Flush all blocks until output. */
|
||||||
static void
|
static void
|
||||||
control_flush_all_blocks(struct client *c)
|
control_flush_all_blocks(struct client *c)
|
||||||
@@ -898,33 +766,6 @@ control_write_callback(__unused struct bufferevent *bufev, void *data)
|
|||||||
bufferevent_disable(cs->write_event, EV_WRITE);
|
bufferevent_disable(cs->write_event, EV_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a subscription change. */
|
|
||||||
static void
|
|
||||||
control_sub_change(struct monitor_change *change, __unused void *data)
|
|
||||||
{
|
|
||||||
struct client *c = change->c;
|
|
||||||
struct session *s = change->s;
|
|
||||||
struct winlink *wl = change->wl;
|
|
||||||
struct window_pane *wp = change->wp;
|
|
||||||
struct window *w;
|
|
||||||
|
|
||||||
if (wp != NULL) {
|
|
||||||
w = wp->window;
|
|
||||||
control_notify_write(c,
|
|
||||||
"%%subscription-changed %s $%u @%u %u %%%u : %s",
|
|
||||||
change->name, s->id, w->id, wl->idx, wp->id, change->value);
|
|
||||||
} else if (wl != NULL) {
|
|
||||||
w = wl->window;
|
|
||||||
control_notify_write(c,
|
|
||||||
"%%subscription-changed %s $%u @%u %u - : %s",
|
|
||||||
change->name, s->id, w->id, wl->idx, change->value);
|
|
||||||
} else {
|
|
||||||
control_notify_write(c,
|
|
||||||
"%%subscription-changed %s $%u - - - : %s",
|
|
||||||
change->name, s->id, change->value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize for control mode. */
|
/* Initialize for control mode. */
|
||||||
void
|
void
|
||||||
control_start(struct client *c)
|
control_start(struct client *c)
|
||||||
@@ -940,11 +781,9 @@ control_start(struct client *c)
|
|||||||
|
|
||||||
cs = c->control_state = xcalloc(1, sizeof *cs);
|
cs = c->control_state = xcalloc(1, sizeof *cs);
|
||||||
RB_INIT(&cs->panes);
|
RB_INIT(&cs->panes);
|
||||||
RB_INIT(&cs->windows);
|
|
||||||
TAILQ_INIT(&cs->pending_list);
|
TAILQ_INIT(&cs->pending_list);
|
||||||
TAILQ_INIT(&cs->all_blocks);
|
TAILQ_INIT(&cs->all_blocks);
|
||||||
TAILQ_INIT(&cs->deferred);
|
RB_INIT(&cs->subs);
|
||||||
cs->subs = monitor_create_client(c, control_sub_change, NULL);
|
|
||||||
|
|
||||||
cs->read_event = bufferevent_new(c->fd, control_read_callback,
|
cs->read_event = bufferevent_new(c->fd, control_read_callback,
|
||||||
control_write_callback, control_error_callback, c);
|
control_write_callback, control_error_callback, c);
|
||||||
@@ -987,48 +826,27 @@ control_discard(struct client *c)
|
|||||||
bufferevent_disable(cs->read_event, EV_READ);
|
bufferevent_disable(cs->read_event, EV_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discard all tmux-owned queued control blocks and stop writing. */
|
|
||||||
void
|
|
||||||
control_discard_all(struct client *c)
|
|
||||||
{
|
|
||||||
struct control_state *cs = c->control_state;
|
|
||||||
struct control_block *cb, *cb1;
|
|
||||||
|
|
||||||
control_discard(c);
|
|
||||||
TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1)
|
|
||||||
control_free_block(cs, cb);
|
|
||||||
bufferevent_disable(cs->write_event, EV_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stop control mode. */
|
/* Stop control mode. */
|
||||||
void
|
void
|
||||||
control_stop(struct client *c)
|
control_stop(struct client *c)
|
||||||
{
|
{
|
||||||
struct control_state *cs = c->control_state;
|
struct control_state *cs = c->control_state;
|
||||||
struct control_block *cb, *cb1;
|
struct control_block *cb, *cb1;
|
||||||
struct control_window *cw, *cw1;
|
struct control_sub *csub, *csub1;
|
||||||
struct control_line *cl, *cl1;
|
|
||||||
|
|
||||||
if (cs == NULL)
|
if (cs == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
monitor_destroy(cs->subs);
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(cl, &cs->deferred, entry, cl1) {
|
|
||||||
TAILQ_REMOVE(&cs->deferred, cl, entry);
|
|
||||||
free(cl->line);
|
|
||||||
free(cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (~c->flags & CLIENT_CONTROLCONTROL)
|
if (~c->flags & CLIENT_CONTROLCONTROL)
|
||||||
bufferevent_free(cs->write_event);
|
bufferevent_free(cs->write_event);
|
||||||
bufferevent_free(cs->read_event);
|
bufferevent_free(cs->read_event);
|
||||||
|
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1)
|
||||||
|
control_free_sub(cs, csub);
|
||||||
|
if (evtimer_initialized(&cs->subs_timer))
|
||||||
|
evtimer_del(&cs->subs_timer);
|
||||||
|
|
||||||
control_reset_offsets(c);
|
control_reset_offsets(c);
|
||||||
RB_FOREACH_SAFE(cw, control_windows, &cs->windows, cw1) {
|
|
||||||
RB_REMOVE(control_windows, &cs->windows, cw);
|
|
||||||
free(cw);
|
|
||||||
}
|
|
||||||
TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1)
|
TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1)
|
||||||
control_free_block(cs, cb);
|
control_free_block(cs, cb);
|
||||||
|
|
||||||
@@ -1036,14 +854,313 @@ control_stop(struct client *c)
|
|||||||
free(cs);
|
free(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check session subscription. */
|
||||||
|
static void
|
||||||
|
control_check_subs_session(struct client *c, struct control_sub *csub,
|
||||||
|
struct format_tree *ft)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
value = format_expand(ft, csub->format);
|
||||||
|
|
||||||
|
if (csub->last != NULL && strcmp(value, csub->last) == 0) {
|
||||||
|
free(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
control_write(c,
|
||||||
|
"%%subscription-changed %s $%u - - - : %s",
|
||||||
|
csub->name, s->id, value);
|
||||||
|
free(csub->last);
|
||||||
|
csub->last = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check pane subscription. */
|
||||||
|
static void
|
||||||
|
control_check_subs_pane(struct client *c, struct control_sub *csub)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct window *w;
|
||||||
|
struct winlink *wl;
|
||||||
|
struct format_tree *ft;
|
||||||
|
char *value;
|
||||||
|
struct control_sub_pane *csp, find;
|
||||||
|
|
||||||
|
wp = window_pane_find_by_id(csub->id);
|
||||||
|
if (wp == NULL || wp->fd == -1)
|
||||||
|
return;
|
||||||
|
w = wp->window;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(wl, &w->winlinks, wentry) {
|
||||||
|
if (wl->session != s)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ft = format_create_defaults(NULL, c, s, wl, wp);
|
||||||
|
value = format_expand(ft, csub->format);
|
||||||
|
format_free(ft);
|
||||||
|
|
||||||
|
find.pane = wp->id;
|
||||||
|
find.idx = wl->idx;
|
||||||
|
|
||||||
|
csp = RB_FIND(control_sub_panes, &csub->panes, &find);
|
||||||
|
if (csp == NULL) {
|
||||||
|
csp = xcalloc(1, sizeof *csp);
|
||||||
|
csp->pane = wp->id;
|
||||||
|
csp->idx = wl->idx;
|
||||||
|
RB_INSERT(control_sub_panes, &csub->panes, csp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (csp->last != NULL && strcmp(value, csp->last) == 0) {
|
||||||
|
free(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
control_write(c,
|
||||||
|
"%%subscription-changed %s $%u @%u %u %%%u : %s",
|
||||||
|
csub->name, s->id, w->id, wl->idx, wp->id, value);
|
||||||
|
free(csp->last);
|
||||||
|
csp->last = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check all-panes subscription for a pane. */
|
||||||
|
static void
|
||||||
|
control_check_subs_all_panes_one(struct client *c, struct control_sub *csub,
|
||||||
|
struct format_tree *ft, struct winlink *wl, struct window_pane *wp)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct window *w = wl->window;
|
||||||
|
char *value;
|
||||||
|
struct control_sub_pane *csp, find;
|
||||||
|
|
||||||
|
value = format_expand(ft, csub->format);
|
||||||
|
|
||||||
|
find.pane = wp->id;
|
||||||
|
find.idx = wl->idx;
|
||||||
|
|
||||||
|
csp = RB_FIND(control_sub_panes, &csub->panes, &find);
|
||||||
|
if (csp == NULL) {
|
||||||
|
csp = xcalloc(1, sizeof *csp);
|
||||||
|
csp->pane = wp->id;
|
||||||
|
csp->idx = wl->idx;
|
||||||
|
RB_INSERT(control_sub_panes, &csub->panes, csp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (csp->last != NULL && strcmp(value, csp->last) == 0) {
|
||||||
|
free(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
control_write(c,
|
||||||
|
"%%subscription-changed %s $%u @%u %u %%%u : %s",
|
||||||
|
csub->name, s->id, w->id, wl->idx, wp->id, value);
|
||||||
|
free(csp->last);
|
||||||
|
csp->last = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check window subscription. */
|
||||||
|
static void
|
||||||
|
control_check_subs_window(struct client *c, struct control_sub *csub)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct window *w;
|
||||||
|
struct winlink *wl;
|
||||||
|
struct format_tree *ft;
|
||||||
|
char *value;
|
||||||
|
struct control_sub_window *csw, find;
|
||||||
|
|
||||||
|
w = window_find_by_id(csub->id);
|
||||||
|
if (w == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(wl, &w->winlinks, wentry) {
|
||||||
|
if (wl->session != s)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ft = format_create_defaults(NULL, c, s, wl, NULL);
|
||||||
|
value = format_expand(ft, csub->format);
|
||||||
|
format_free(ft);
|
||||||
|
|
||||||
|
find.window = w->id;
|
||||||
|
find.idx = wl->idx;
|
||||||
|
|
||||||
|
csw = RB_FIND(control_sub_windows, &csub->windows, &find);
|
||||||
|
if (csw == NULL) {
|
||||||
|
csw = xcalloc(1, sizeof *csw);
|
||||||
|
csw->window = w->id;
|
||||||
|
csw->idx = wl->idx;
|
||||||
|
RB_INSERT(control_sub_windows, &csub->windows, csw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (csw->last != NULL && strcmp(value, csw->last) == 0) {
|
||||||
|
free(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
control_write(c,
|
||||||
|
"%%subscription-changed %s $%u @%u %u - : %s",
|
||||||
|
csub->name, s->id, w->id, wl->idx, value);
|
||||||
|
free(csw->last);
|
||||||
|
csw->last = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check all-windows subscription for a window. */
|
||||||
|
static void
|
||||||
|
control_check_subs_all_windows_one(struct client *c, struct control_sub *csub,
|
||||||
|
struct format_tree *ft, struct winlink *wl)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct window *w = wl->window;
|
||||||
|
char *value;
|
||||||
|
struct control_sub_window *csw, find;
|
||||||
|
|
||||||
|
value = format_expand(ft, csub->format);
|
||||||
|
|
||||||
|
find.window = w->id;
|
||||||
|
find.idx = wl->idx;
|
||||||
|
|
||||||
|
csw = RB_FIND(control_sub_windows, &csub->windows, &find);
|
||||||
|
if (csw == NULL) {
|
||||||
|
csw = xcalloc(1, sizeof *csw);
|
||||||
|
csw->window = w->id;
|
||||||
|
csw->idx = wl->idx;
|
||||||
|
RB_INSERT(control_sub_windows, &csub->windows, csw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (csw->last != NULL && strcmp(value, csw->last) == 0) {
|
||||||
|
free(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
control_write(c,
|
||||||
|
"%%subscription-changed %s $%u @%u %u - : %s",
|
||||||
|
csub->name, s->id, w->id, wl->idx, value);
|
||||||
|
free(csw->last);
|
||||||
|
csw->last = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check subscriptions timer. */
|
||||||
|
static void
|
||||||
|
control_check_subs_timer(__unused int fd, __unused short events, void *data)
|
||||||
|
{
|
||||||
|
struct client *c = data;
|
||||||
|
struct control_state *cs = c->control_state;
|
||||||
|
struct control_sub *csub, *csub1;
|
||||||
|
struct session *s = c->session;
|
||||||
|
struct format_tree *ft;
|
||||||
|
struct winlink *wl;
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct timeval tv = { .tv_sec = 1 };
|
||||||
|
int have_session = 0, have_all_panes = 0;
|
||||||
|
int have_all_windows = 0;
|
||||||
|
|
||||||
|
log_debug("%s: timer fired", __func__);
|
||||||
|
evtimer_add(&cs->subs_timer, &tv);
|
||||||
|
|
||||||
|
if (s == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Find which subscription types are present. */
|
||||||
|
RB_FOREACH(csub, control_subs, &cs->subs) {
|
||||||
|
switch (csub->type) {
|
||||||
|
case CONTROL_SUB_SESSION:
|
||||||
|
have_session = 1;
|
||||||
|
break;
|
||||||
|
case CONTROL_SUB_ALL_PANES:
|
||||||
|
have_all_panes = 1;
|
||||||
|
break;
|
||||||
|
case CONTROL_SUB_ALL_WINDOWS:
|
||||||
|
have_all_windows = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check session subscriptions. */
|
||||||
|
if (have_session) {
|
||||||
|
ft = format_create_defaults(NULL, c, s, NULL, NULL);
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
|
||||||
|
if (csub->type == CONTROL_SUB_SESSION)
|
||||||
|
control_check_subs_session(c, csub, ft);
|
||||||
|
}
|
||||||
|
format_free(ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check pane and window subscriptions. */
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs, csub1) {
|
||||||
|
switch (csub->type) {
|
||||||
|
case CONTROL_SUB_PANE:
|
||||||
|
control_check_subs_pane(c, csub);
|
||||||
|
break;
|
||||||
|
case CONTROL_SUB_WINDOW:
|
||||||
|
control_check_subs_window(c, csub);
|
||||||
|
break;
|
||||||
|
case CONTROL_SUB_SESSION:
|
||||||
|
case CONTROL_SUB_ALL_PANES:
|
||||||
|
case CONTROL_SUB_ALL_WINDOWS:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check all-panes subscriptions. */
|
||||||
|
if (have_all_panes) {
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||||
|
ft = format_create_defaults(NULL, c, s, wl, wp);
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs,
|
||||||
|
csub1) {
|
||||||
|
if (csub->type != CONTROL_SUB_ALL_PANES)
|
||||||
|
continue;
|
||||||
|
control_check_subs_all_panes_one(c,
|
||||||
|
csub, ft, wl, wp);
|
||||||
|
}
|
||||||
|
format_free(ft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check all-windows subscriptions. */
|
||||||
|
if (have_all_windows) {
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
ft = format_create_defaults(NULL, c, s, wl, NULL);
|
||||||
|
RB_FOREACH_SAFE(csub, control_subs, &cs->subs,
|
||||||
|
csub1) {
|
||||||
|
if (csub->type != CONTROL_SUB_ALL_WINDOWS)
|
||||||
|
continue;
|
||||||
|
control_check_subs_all_windows_one(c, csub, ft,
|
||||||
|
wl);
|
||||||
|
}
|
||||||
|
format_free(ft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Add a subscription. */
|
/* Add a subscription. */
|
||||||
void
|
void
|
||||||
control_add_sub(struct client *c, const char *name, enum monitor_type type,
|
control_add_sub(struct client *c, const char *name, enum control_sub_type type,
|
||||||
int id, const char *format)
|
int id, const char *format)
|
||||||
{
|
{
|
||||||
struct control_state *cs = c->control_state;
|
struct control_state *cs = c->control_state;
|
||||||
|
struct control_sub *csub, find;
|
||||||
|
struct timeval tv = { .tv_sec = 1 };
|
||||||
|
|
||||||
monitor_add(cs->subs, name, type, id, format, MONITOR_NOTIFY_INITIAL);
|
find.name = (char *)name;
|
||||||
|
if ((csub = RB_FIND(control_subs, &cs->subs, &find)) != NULL)
|
||||||
|
control_free_sub(cs, csub);
|
||||||
|
|
||||||
|
csub = xcalloc(1, sizeof *csub);
|
||||||
|
csub->name = xstrdup(name);
|
||||||
|
csub->type = type;
|
||||||
|
csub->id = id;
|
||||||
|
csub->format = xstrdup(format);
|
||||||
|
RB_INSERT(control_subs, &cs->subs, csub);
|
||||||
|
|
||||||
|
RB_INIT(&csub->panes);
|
||||||
|
RB_INIT(&csub->windows);
|
||||||
|
|
||||||
|
if (!evtimer_initialized(&cs->subs_timer))
|
||||||
|
evtimer_set(&cs->subs_timer, control_check_subs_timer, c);
|
||||||
|
if (!evtimer_pending(&cs->subs_timer, NULL))
|
||||||
|
evtimer_add(&cs->subs_timer, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove a subscription. */
|
/* Remove a subscription. */
|
||||||
@@ -1051,6 +1168,11 @@ void
|
|||||||
control_remove_sub(struct client *c, const char *name)
|
control_remove_sub(struct client *c, const char *name)
|
||||||
{
|
{
|
||||||
struct control_state *cs = c->control_state;
|
struct control_state *cs = c->control_state;
|
||||||
|
struct control_sub *csub, find;
|
||||||
|
|
||||||
monitor_remove(cs->subs, name);
|
find.name = (char *)name;
|
||||||
|
if ((csub = RB_FIND(control_subs, &cs->subs, &find)) != NULL)
|
||||||
|
control_free_sub(cs, csub);
|
||||||
|
if (RB_EMPTY(&cs->subs))
|
||||||
|
evtimer_del(&cs->subs_timer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: environ.c,v 1.31 2026/06/13 20:07:30 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
672
events-payload.c
672
events-payload.c
@@ -1,672 +0,0 @@
|
|||||||
/* $OpenBSD: events-payload.c,v 1.1 2026/07/10 13:38:45 nicm Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF 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 <event.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/* Event payload item. */
|
|
||||||
struct event_payload_item {
|
|
||||||
char *name;
|
|
||||||
enum event_payload_type type;
|
|
||||||
|
|
||||||
union {
|
|
||||||
char *string;
|
|
||||||
time_t time;
|
|
||||||
int number;
|
|
||||||
u_int unsigned_number;
|
|
||||||
struct client *client;
|
|
||||||
struct session *session;
|
|
||||||
struct window *window;
|
|
||||||
struct window_pane *pane;
|
|
||||||
struct {
|
|
||||||
void *ptr;
|
|
||||||
event_payload_free_cb free_cb;
|
|
||||||
event_payload_print_cb print_cb;
|
|
||||||
} pointer;
|
|
||||||
};
|
|
||||||
|
|
||||||
RB_ENTRY(event_payload_item) entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
RB_HEAD(event_payload_tree, event_payload_item);
|
|
||||||
|
|
||||||
struct event_payload {
|
|
||||||
struct event_payload_tree items;
|
|
||||||
struct cmd_find_state target;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
event_payload_cmp(struct event_payload_item *epi1,
|
|
||||||
struct event_payload_item *epi2)
|
|
||||||
{
|
|
||||||
return (strcmp(epi1->name, epi2->name));
|
|
||||||
}
|
|
||||||
RB_GENERATE_STATIC(event_payload_tree, event_payload_item, entry,
|
|
||||||
event_payload_cmp);
|
|
||||||
|
|
||||||
/* Find an item. */
|
|
||||||
static struct event_payload_item *
|
|
||||||
event_payload_find(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item find = { .name = (char *)name };
|
|
||||||
|
|
||||||
return (RB_FIND(event_payload_tree, &ep->items, &find));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free the target in a payload. */
|
|
||||||
static void
|
|
||||||
event_payload_free_target(struct event_payload *ep)
|
|
||||||
{
|
|
||||||
struct cmd_find_state *target = &ep->target;
|
|
||||||
|
|
||||||
if (target->s != NULL)
|
|
||||||
session_remove_ref(target->s, __func__);
|
|
||||||
if (target->w != NULL)
|
|
||||||
window_remove_ref(target->w, __func__);
|
|
||||||
if (target->wp != NULL)
|
|
||||||
window_pane_remove_ref(target->wp, __func__);
|
|
||||||
|
|
||||||
cmd_find_clear_state(target, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free the value in an item. */
|
|
||||||
static void
|
|
||||||
event_payload_free_value(struct event_payload_item *epi)
|
|
||||||
{
|
|
||||||
switch (epi->type) {
|
|
||||||
case EVENT_PAYLOAD_STRING:
|
|
||||||
free(epi->string);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_CLIENT:
|
|
||||||
server_client_unref(epi->client);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_SESSION:
|
|
||||||
session_remove_ref(epi->session, __func__);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_WINDOW:
|
|
||||||
window_remove_ref(epi->window, __func__);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_PANE:
|
|
||||||
window_pane_remove_ref(epi->pane, __func__);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_POINTER:
|
|
||||||
if (epi->pointer.free_cb != NULL)
|
|
||||||
epi->pointer.free_cb(epi->pointer.ptr);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_INT:
|
|
||||||
case EVENT_PAYLOAD_UINT:
|
|
||||||
case EVENT_PAYLOAD_TIME:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set an item. */
|
|
||||||
static void
|
|
||||||
event_payload_set_item(struct event_payload *ep, const char *name,
|
|
||||||
struct event_payload_item *new)
|
|
||||||
{
|
|
||||||
struct event_payload_item *old;
|
|
||||||
|
|
||||||
new->name = xstrdup(name);
|
|
||||||
old = RB_INSERT(event_payload_tree, &ep->items, new);
|
|
||||||
if (old != NULL) {
|
|
||||||
RB_REMOVE(event_payload_tree, &ep->items, old);
|
|
||||||
event_payload_free_value(old);
|
|
||||||
free(old->name);
|
|
||||||
free(old);
|
|
||||||
RB_INSERT(event_payload_tree, &ep->items, new);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create an event payload. */
|
|
||||||
struct event_payload *
|
|
||||||
event_payload_create(void)
|
|
||||||
{
|
|
||||||
struct event_payload *ep;
|
|
||||||
|
|
||||||
ep = xcalloc(1, sizeof *ep);
|
|
||||||
RB_INIT(&ep->items);
|
|
||||||
cmd_find_clear_state(&ep->target, 0);
|
|
||||||
return (ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free an event payload. */
|
|
||||||
void
|
|
||||||
event_payload_free(struct event_payload *ep)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi, *epi1;
|
|
||||||
|
|
||||||
if (ep != NULL) {
|
|
||||||
RB_FOREACH_SAFE(epi, event_payload_tree, &ep->items, epi1) {
|
|
||||||
RB_REMOVE(event_payload_tree, &ep->items, epi);
|
|
||||||
event_payload_free_value(epi);
|
|
||||||
free(epi->name);
|
|
||||||
free(epi);
|
|
||||||
}
|
|
||||||
event_payload_free_target(ep);
|
|
||||||
free(ep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the target. */
|
|
||||||
void
|
|
||||||
event_payload_set_target(struct event_payload *ep, struct cmd_find_state *fs)
|
|
||||||
{
|
|
||||||
struct cmd_find_state *target = &ep->target;
|
|
||||||
|
|
||||||
event_payload_free_target(ep);
|
|
||||||
|
|
||||||
if (fs->s != NULL) {
|
|
||||||
session_add_ref(fs->s, __func__);
|
|
||||||
target->s = fs->s;
|
|
||||||
}
|
|
||||||
if (fs->wl != NULL) {
|
|
||||||
target->idx = fs->wl->idx;
|
|
||||||
if (target->s == NULL) {
|
|
||||||
session_add_ref(fs->wl->session, __func__);
|
|
||||||
target->s = fs->wl->session;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
target->idx = -1;
|
|
||||||
if (fs->w != NULL) {
|
|
||||||
window_add_ref(fs->w, __func__);
|
|
||||||
target->w = fs->w;
|
|
||||||
} else if (fs->wl != NULL) {
|
|
||||||
window_add_ref(fs->wl->window, __func__);
|
|
||||||
target->w = fs->wl->window;
|
|
||||||
}
|
|
||||||
if (fs->wp != NULL) {
|
|
||||||
window_pane_add_ref(fs->wp, __func__);
|
|
||||||
target->wp = fs->wp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the target. */
|
|
||||||
int
|
|
||||||
event_payload_get_target(struct event_payload *ep, struct cmd_find_state *fs)
|
|
||||||
{
|
|
||||||
struct cmd_find_state *t = &ep->target;
|
|
||||||
struct winlink *wl = NULL;
|
|
||||||
int flags = fs->flags;
|
|
||||||
|
|
||||||
if (t->idx != -1 &&
|
|
||||||
t->s != NULL &&
|
|
||||||
t->w != NULL &&
|
|
||||||
session_alive(t->s)) {
|
|
||||||
wl = winlink_find_by_index(&t->s->windows, t->idx);
|
|
||||||
if (wl != NULL && wl->window != t->w)
|
|
||||||
wl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_find_clear_state(fs, flags);
|
|
||||||
fs->s = t->s;
|
|
||||||
fs->w = t->w;
|
|
||||||
fs->wp = t->wp;
|
|
||||||
fs->wl = wl;
|
|
||||||
fs->idx = (wl != NULL ? wl->idx : -1);
|
|
||||||
if (cmd_find_valid_state(fs))
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
if (wl != NULL &&
|
|
||||||
t->wp != NULL &&
|
|
||||||
window_has_pane(wl->window, t->wp)) {
|
|
||||||
cmd_find_from_winlink_pane(fs, wl, t->wp, flags);
|
|
||||||
if (cmd_find_valid_state(fs))
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t->wp != NULL &&
|
|
||||||
cmd_find_from_pane(fs, t->wp, flags) == 0 &&
|
|
||||||
cmd_find_valid_state(fs))
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
if (wl != NULL) {
|
|
||||||
cmd_find_from_winlink(fs, wl, flags);
|
|
||||||
if (cmd_find_valid_state(fs))
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t->s != NULL &&
|
|
||||||
t->w != NULL &&
|
|
||||||
session_alive(t->s) &&
|
|
||||||
cmd_find_from_session_window(fs, t->s, t->w, flags) == 0 &&
|
|
||||||
cmd_find_valid_state(fs))
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
if (t->s != NULL && session_alive(t->s)) {
|
|
||||||
cmd_find_from_session(fs, t->s, flags);
|
|
||||||
if (cmd_find_valid_state(fs))
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd_find_from_nothing(fs, flags) == 0)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
cmd_find_clear_state(fs, flags);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a string item. */
|
|
||||||
void
|
|
||||||
event_payload_set_string(struct event_payload *ep, const char *name,
|
|
||||||
const char *fmt, ...)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_STRING;
|
|
||||||
xvasprintf(&epi->string, fmt, ap);
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a time item. */
|
|
||||||
void
|
|
||||||
event_payload_set_time(struct event_payload *ep, const char *name,
|
|
||||||
time_t value)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_TIME;
|
|
||||||
epi->time = value;
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a number item. */
|
|
||||||
void
|
|
||||||
event_payload_set_int(struct event_payload *ep, const char *name, int value)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_INT;
|
|
||||||
epi->number = value;
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set an unsigned number item. */
|
|
||||||
void
|
|
||||||
event_payload_set_uint(struct event_payload *ep, const char *name, u_int value)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_UINT;
|
|
||||||
epi->unsigned_number = value;
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a client item. */
|
|
||||||
void
|
|
||||||
event_payload_set_client(struct event_payload *ep, const char *name,
|
|
||||||
struct client *c)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
c->references++;
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_CLIENT;
|
|
||||||
epi->client = c;
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a session item. */
|
|
||||||
void
|
|
||||||
event_payload_set_session(struct event_payload *ep, const char *name,
|
|
||||||
struct session *s)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
session_add_ref(s, __func__);
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_SESSION;
|
|
||||||
epi->session = s;
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a window item. */
|
|
||||||
void
|
|
||||||
event_payload_set_window(struct event_payload *ep, const char *name,
|
|
||||||
struct window *w)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
window_add_ref(w, __func__);
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_WINDOW;
|
|
||||||
epi->window = w;
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a pane item. */
|
|
||||||
void
|
|
||||||
event_payload_set_pane(struct event_payload *ep, const char *name,
|
|
||||||
struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
window_pane_add_ref(wp, __func__);
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_PANE;
|
|
||||||
epi->pane = wp;
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set a pointer item. */
|
|
||||||
void
|
|
||||||
event_payload_set_pointer(struct event_payload *ep, const char *name,
|
|
||||||
void *ptr, event_payload_free_cb free_cb, event_payload_print_cb print_cb)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = xcalloc(1, sizeof *epi);
|
|
||||||
epi->type = EVENT_PAYLOAD_POINTER;
|
|
||||||
epi->pointer.ptr = ptr;
|
|
||||||
epi->pointer.free_cb = free_cb;
|
|
||||||
epi->pointer.print_cb = print_cb;
|
|
||||||
event_payload_set_item(ep, name, epi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a string item. */
|
|
||||||
const char *
|
|
||||||
event_payload_get_string(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_STRING)
|
|
||||||
return (NULL);
|
|
||||||
return (epi->string);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print a payload item. */
|
|
||||||
static void
|
|
||||||
event_payload_add_item(struct event_payload_item *epi, struct evbuffer *evb)
|
|
||||||
{
|
|
||||||
switch (epi->type) {
|
|
||||||
case EVENT_PAYLOAD_STRING:
|
|
||||||
evbuffer_add_printf(evb, "%s", epi->string);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_TIME:
|
|
||||||
evbuffer_add_printf(evb, "%lld", (long long)epi->time);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_INT:
|
|
||||||
evbuffer_add_printf(evb, "%d", epi->number);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_UINT:
|
|
||||||
evbuffer_add_printf(evb, "%u", epi->unsigned_number);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_CLIENT:
|
|
||||||
evbuffer_add_printf(evb, "%s", epi->client->name);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_SESSION:
|
|
||||||
evbuffer_add_printf(evb, "$%u", epi->session->id);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_WINDOW:
|
|
||||||
evbuffer_add_printf(evb, "@%u", epi->window->id);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_PANE:
|
|
||||||
evbuffer_add_printf(evb, "%%%u", epi->pane->id);
|
|
||||||
break;
|
|
||||||
case EVENT_PAYLOAD_POINTER:
|
|
||||||
if (epi->pointer.print_cb != NULL)
|
|
||||||
epi->pointer.print_cb(epi->pointer.ptr, evb);
|
|
||||||
else
|
|
||||||
evbuffer_add_printf(evb, "%p", epi->pointer.ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print a payload item. */
|
|
||||||
char *
|
|
||||||
event_payload_item_print(struct event_payload_item *epi)
|
|
||||||
{
|
|
||||||
struct evbuffer *evb;
|
|
||||||
char *value = NULL;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
evb = evbuffer_new();
|
|
||||||
if (evb == NULL)
|
|
||||||
fatalx("out of memory");
|
|
||||||
event_payload_add_item(epi, evb);
|
|
||||||
if ((size = EVBUFFER_LENGTH(evb)) != 0)
|
|
||||||
value = xmemdup(EVBUFFER_DATA(evb), size);
|
|
||||||
else
|
|
||||||
value = xstrdup("");
|
|
||||||
evbuffer_free(evb);
|
|
||||||
return (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print an item value. */
|
|
||||||
char *
|
|
||||||
event_payload_print(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL)
|
|
||||||
return (NULL);
|
|
||||||
return (event_payload_item_print(epi));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add payload items as formats. */
|
|
||||||
void
|
|
||||||
event_payload_add_formats(struct event_payload *ep, struct format_tree *ft,
|
|
||||||
const char *prefix)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
char *name, *value;
|
|
||||||
const char *key;
|
|
||||||
|
|
||||||
if (prefix == NULL)
|
|
||||||
prefix = "";
|
|
||||||
|
|
||||||
RB_FOREACH(epi, event_payload_tree, &ep->items) {
|
|
||||||
key = epi->name;
|
|
||||||
if (*key == '_')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
value = event_payload_item_print(epi);
|
|
||||||
xasprintf(&name, "%s%s", prefix, key);
|
|
||||||
format_add(ft, name, "%s", value);
|
|
||||||
free(name);
|
|
||||||
free(value);
|
|
||||||
|
|
||||||
if (epi->type == EVENT_PAYLOAD_SESSION) {
|
|
||||||
xasprintf(&name, "%s%s_name", prefix, key);
|
|
||||||
format_add(ft, name, "%s", epi->session->name);
|
|
||||||
free(name);
|
|
||||||
} else if (epi->type == EVENT_PAYLOAD_WINDOW) {
|
|
||||||
xasprintf(&name, "%s%s_name", prefix, key);
|
|
||||||
format_add(ft, name, "%s", epi->window->name);
|
|
||||||
free(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the first payload item. */
|
|
||||||
struct event_payload_item *
|
|
||||||
event_payload_first(struct event_payload *ep)
|
|
||||||
{
|
|
||||||
return (RB_MIN(event_payload_tree, &ep->items));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the next payload item. */
|
|
||||||
struct event_payload_item *
|
|
||||||
event_payload_next(struct event_payload_item *epi)
|
|
||||||
{
|
|
||||||
return (RB_NEXT(event_payload_tree, , epi));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a payload item name. */
|
|
||||||
const char *
|
|
||||||
event_payload_item_name(struct event_payload_item *epi)
|
|
||||||
{
|
|
||||||
return (epi->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a payload item type. */
|
|
||||||
enum event_payload_type
|
|
||||||
event_payload_item_type(struct event_payload_item *epi)
|
|
||||||
{
|
|
||||||
return (epi->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Log a payload. */
|
|
||||||
void
|
|
||||||
event_payload_log(struct event_payload *ep, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
struct evbuffer *evb;
|
|
||||||
va_list ap;
|
|
||||||
char *prefix;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
xvasprintf(&prefix, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
evb = evbuffer_new();
|
|
||||||
if (evb == NULL)
|
|
||||||
fatalx("out of memory");
|
|
||||||
if (ep != NULL) {
|
|
||||||
RB_FOREACH(epi, event_payload_tree, &ep->items) {
|
|
||||||
if (EVBUFFER_LENGTH(evb) != 0)
|
|
||||||
evbuffer_add_printf(evb, ", ");
|
|
||||||
evbuffer_add_printf(evb, "%s=", epi->name);
|
|
||||||
event_payload_add_item(epi, evb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log_debug("%s%.*s", prefix, (int)EVBUFFER_LENGTH(evb),
|
|
||||||
(char *)EVBUFFER_DATA(evb));
|
|
||||||
evbuffer_free(evb);
|
|
||||||
free(prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a time item. */
|
|
||||||
time_t
|
|
||||||
event_payload_get_time(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_TIME)
|
|
||||||
return (0);
|
|
||||||
return (epi->time);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a number item. */
|
|
||||||
int
|
|
||||||
event_payload_get_int(struct event_payload *ep, const char *name, int *value)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_INT)
|
|
||||||
return (-1);
|
|
||||||
*value = epi->number;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get an unsigned number item. */
|
|
||||||
int
|
|
||||||
event_payload_get_uint(struct event_payload *ep, const char *name, u_int *value)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_UINT)
|
|
||||||
return (-1);
|
|
||||||
*value = epi->unsigned_number;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a client item. */
|
|
||||||
struct client *
|
|
||||||
event_payload_get_client(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_CLIENT)
|
|
||||||
return (NULL);
|
|
||||||
return (epi->client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a session item. */
|
|
||||||
struct session *
|
|
||||||
event_payload_get_session(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_SESSION)
|
|
||||||
return (NULL);
|
|
||||||
return (epi->session);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a window item. */
|
|
||||||
struct window *
|
|
||||||
event_payload_get_window(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_WINDOW)
|
|
||||||
return (NULL);
|
|
||||||
return (epi->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a pane item. */
|
|
||||||
struct window_pane *
|
|
||||||
event_payload_get_pane(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_PANE)
|
|
||||||
return (NULL);
|
|
||||||
return (epi->pane);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a pointer item. */
|
|
||||||
void *
|
|
||||||
event_payload_get_pointer(struct event_payload *ep, const char *name)
|
|
||||||
{
|
|
||||||
struct event_payload_item *epi;
|
|
||||||
|
|
||||||
epi = event_payload_find(ep, name);
|
|
||||||
if (epi == NULL || epi->type != EVENT_PAYLOAD_POINTER)
|
|
||||||
return (NULL);
|
|
||||||
return (epi->pointer.ptr);
|
|
||||||
}
|
|
||||||
199
events.c
199
events.c
@@ -1,199 +0,0 @@
|
|||||||
/* $OpenBSD: events.c,v 1.1 2026/07/10 13:38:45 nicm Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
|
||||||
|
|
||||||
/* Event sink. */
|
|
||||||
struct events_sink {
|
|
||||||
char *name;
|
|
||||||
events_cb cb;
|
|
||||||
void *data;
|
|
||||||
int dead;
|
|
||||||
u_int generation;
|
|
||||||
|
|
||||||
TAILQ_ENTRY(events_sink) entry;
|
|
||||||
};
|
|
||||||
|
|
||||||
TAILQ_HEAD(events_sinks, events_sink);
|
|
||||||
static struct events_sinks events_sinks = TAILQ_HEAD_INITIALIZER(events_sinks);
|
|
||||||
|
|
||||||
static u_int events_dispatching;
|
|
||||||
static u_int events_generation;
|
|
||||||
|
|
||||||
/* Free an event sink. */
|
|
||||||
static void
|
|
||||||
events_free_sink(struct events_sink *es)
|
|
||||||
{
|
|
||||||
TAILQ_REMOVE(&events_sinks, es, entry);
|
|
||||||
free(es->name);
|
|
||||||
free(es);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free dead event sinks. */
|
|
||||||
static void
|
|
||||||
events_free_dead(void)
|
|
||||||
{
|
|
||||||
struct events_sink *es, *es1;
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(es, &events_sinks, entry, es1) {
|
|
||||||
if (es->dead)
|
|
||||||
events_free_sink(es);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add an event sink. */
|
|
||||||
struct events_sink *
|
|
||||||
events_add_sink(const char *name, events_cb cb, void *data)
|
|
||||||
{
|
|
||||||
struct events_sink *es;
|
|
||||||
|
|
||||||
es = xcalloc(1, sizeof *es);
|
|
||||||
es->name = xstrdup(name);
|
|
||||||
es->cb = cb;
|
|
||||||
es->data = data;
|
|
||||||
es->generation = ++events_generation;
|
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&events_sinks, es, entry);
|
|
||||||
return (es);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove an event sink. */
|
|
||||||
void
|
|
||||||
events_remove_sink(struct events_sink *es)
|
|
||||||
{
|
|
||||||
if (es != NULL && !es->dead) {
|
|
||||||
if (events_dispatching != 0)
|
|
||||||
es->dead = 1;
|
|
||||||
else
|
|
||||||
events_free_sink(es);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fire an event. */
|
|
||||||
void
|
|
||||||
events_fire(const char *name, struct event_payload *ep)
|
|
||||||
{
|
|
||||||
struct events_sink *es;
|
|
||||||
u_int generation = events_generation;
|
|
||||||
|
|
||||||
event_payload_set_string(ep, "event", "%s", name);
|
|
||||||
|
|
||||||
if (log_get_level() != 0)
|
|
||||||
event_payload_log(ep, "%s: %s: ", __func__, name);
|
|
||||||
|
|
||||||
events_dispatching++;
|
|
||||||
TAILQ_FOREACH(es, &events_sinks, entry) {
|
|
||||||
if (es->dead || es->generation > generation)
|
|
||||||
continue;
|
|
||||||
if (strcmp(es->name, name) == 0)
|
|
||||||
es->cb(name, ep, es->data);
|
|
||||||
}
|
|
||||||
if (--events_dispatching == 0)
|
|
||||||
events_free_dead();
|
|
||||||
event_payload_free(ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fire a client event. */
|
|
||||||
void
|
|
||||||
events_fire_client(const char *name, struct client *c)
|
|
||||||
{
|
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
cmd_find_from_client(&fs, c, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
event_payload_set_client(ep, "client", c);
|
|
||||||
if (fs.s != NULL)
|
|
||||||
event_payload_set_session(ep, "session", fs.s);
|
|
||||||
if (fs.w != NULL)
|
|
||||||
event_payload_set_window(ep, "window", fs.w);
|
|
||||||
if (fs.wl != NULL)
|
|
||||||
event_payload_set_int(ep, "window_index", fs.wl->idx);
|
|
||||||
else if (fs.idx != -1)
|
|
||||||
event_payload_set_int(ep, "window_index", fs.idx);
|
|
||||||
if (fs.wp != NULL)
|
|
||||||
event_payload_set_pane(ep, "pane", fs.wp);
|
|
||||||
events_fire(name, ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fire a session event. */
|
|
||||||
void
|
|
||||||
events_fire_session(const char *name, struct session *s)
|
|
||||||
{
|
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
if (session_alive(s)) {
|
|
||||||
cmd_find_from_session(&fs, s, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
}
|
|
||||||
event_payload_set_session(ep, "session", s);
|
|
||||||
events_fire(name, ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fire a window event. */
|
|
||||||
void
|
|
||||||
events_fire_window(const char *name, struct window *w)
|
|
||||||
{
|
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
cmd_find_from_window(&fs, w, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
event_payload_set_window(ep, "window", w);
|
|
||||||
events_fire(name, ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fire a pane event. */
|
|
||||||
void
|
|
||||||
events_fire_pane(const char *name, struct window_pane *wp)
|
|
||||||
{
|
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
cmd_find_from_pane(&fs, wp, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
event_payload_set_pane(ep, "pane", wp);
|
|
||||||
event_payload_set_window(ep, "window", wp->window);
|
|
||||||
events_fire(name, ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fire a winlink event. */
|
|
||||||
void
|
|
||||||
events_fire_winlink(const char *name, struct winlink *wl)
|
|
||||||
{
|
|
||||||
struct event_payload *ep;
|
|
||||||
struct cmd_find_state fs;
|
|
||||||
|
|
||||||
ep = event_payload_create();
|
|
||||||
cmd_find_from_winlink(&fs, wl, 0);
|
|
||||||
event_payload_set_target(ep, &fs);
|
|
||||||
event_payload_set_session(ep, "session", wl->session);
|
|
||||||
event_payload_set_window(ep, "window", wl->window);
|
|
||||||
event_payload_set_int(ep, "window_index", wl->idx);
|
|
||||||
events_fire(name, ep);
|
|
||||||
}
|
|
||||||
87
file.c
87
file.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: file.c,v 1.22 2026/08/17 07:56:56 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -185,7 +185,6 @@ file_can_print(struct client *c)
|
|||||||
{
|
{
|
||||||
if (c == NULL ||
|
if (c == NULL ||
|
||||||
(c->flags & CLIENT_ATTACHED) ||
|
(c->flags & CLIENT_ATTACHED) ||
|
||||||
(c->flags & CLIENT_DEAD) ||
|
|
||||||
(c->flags & CLIENT_CONTROL))
|
(c->flags & CLIENT_CONTROL))
|
||||||
return (0);
|
return (0);
|
||||||
return (1);
|
return (1);
|
||||||
@@ -502,8 +501,7 @@ file_push(struct client_file *cf)
|
|||||||
} else if (cf->stream > 2) {
|
} else if (cf->stream > 2) {
|
||||||
close.stream = cf->stream;
|
close.stream = cf->stream;
|
||||||
proc_send(cf->peer, MSG_WRITE_CLOSE, -1, &close, sizeof close);
|
proc_send(cf->peer, MSG_WRITE_CLOSE, -1, &close, sizeof close);
|
||||||
if (cf->c == NULL || (~cf->c->flags & CLIENT_WRITE_ACK))
|
file_fire_done(cf);
|
||||||
file_fire_done(cf);
|
|
||||||
}
|
}
|
||||||
free(msg);
|
free(msg);
|
||||||
}
|
}
|
||||||
@@ -528,48 +526,14 @@ file_write_left(struct client_files *files)
|
|||||||
return (waiting != 0);
|
return (waiting != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finish writing a client file. */
|
|
||||||
static void
|
|
||||||
file_write_finished(struct client_file *cf)
|
|
||||||
{
|
|
||||||
struct msg_write_done msg;
|
|
||||||
|
|
||||||
if (cf->event != NULL) {
|
|
||||||
bufferevent_free(cf->event);
|
|
||||||
cf->event = NULL;
|
|
||||||
}
|
|
||||||
if (cf->fd != -1) {
|
|
||||||
if (close(cf->fd) != 0 && cf->error == 0)
|
|
||||||
cf->error = errno;
|
|
||||||
cf->fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.stream = cf->stream;
|
|
||||||
msg.error = cf->error;
|
|
||||||
proc_send(cf->peer, MSG_WRITE_DONE, -1, &msg, sizeof msg);
|
|
||||||
|
|
||||||
if (cf->cb != NULL)
|
|
||||||
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
|
|
||||||
file_free(cf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Client file write error callback. */
|
/* Client file write error callback. */
|
||||||
static void
|
static void
|
||||||
file_write_error_callback(__unused struct bufferevent *bev, short what,
|
file_write_error_callback(__unused struct bufferevent *bev, __unused short what,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
struct client_file *cf = arg;
|
struct client_file *cf = arg;
|
||||||
int error;
|
|
||||||
|
|
||||||
if (what & EVBUFFER_ERROR)
|
|
||||||
error = errno;
|
|
||||||
else
|
|
||||||
error = EIO;
|
|
||||||
if (error == 0)
|
|
||||||
error = EIO;
|
|
||||||
|
|
||||||
log_debug("write error file %d", cf->stream);
|
log_debug("write error file %d", cf->stream);
|
||||||
cf->error = error;
|
|
||||||
|
|
||||||
bufferevent_free(cf->event);
|
bufferevent_free(cf->event);
|
||||||
cf->event = NULL;
|
cf->event = NULL;
|
||||||
@@ -577,9 +541,7 @@ file_write_error_callback(__unused struct bufferevent *bev, short what,
|
|||||||
close(cf->fd);
|
close(cf->fd);
|
||||||
cf->fd = -1;
|
cf->fd = -1;
|
||||||
|
|
||||||
if (cf->closed)
|
if (cf->cb != NULL)
|
||||||
file_write_finished(cf);
|
|
||||||
else if (cf->cb != NULL)
|
|
||||||
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
|
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,10 +553,15 @@ file_write_callback(__unused struct bufferevent *bev, void *arg)
|
|||||||
|
|
||||||
log_debug("write check file %d", cf->stream);
|
log_debug("write check file %d", cf->stream);
|
||||||
|
|
||||||
if (cf->closed && EVBUFFER_LENGTH(cf->event->output) == 0)
|
if (cf->cb != NULL)
|
||||||
file_write_finished(cf);
|
|
||||||
else if (cf->cb != NULL)
|
|
||||||
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
|
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
|
||||||
|
|
||||||
|
if (cf->closed && EVBUFFER_LENGTH(cf->event->output) == 0) {
|
||||||
|
bufferevent_free(cf->event);
|
||||||
|
close(cf->fd);
|
||||||
|
RB_REMOVE(client_files, cf->tree, cf);
|
||||||
|
file_free(cf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a file write open message (client). */
|
/* Handle a file write open message (client). */
|
||||||
@@ -695,10 +662,14 @@ file_write_close(struct client_files *files, struct imsg *imsg)
|
|||||||
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
|
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
|
||||||
fatalx("unknown stream number");
|
fatalx("unknown stream number");
|
||||||
log_debug("close file %d", cf->stream);
|
log_debug("close file %d", cf->stream);
|
||||||
cf->closed = 1;
|
|
||||||
|
|
||||||
if (cf->event == NULL || EVBUFFER_LENGTH(cf->event->output) == 0) {
|
if (cf->event == NULL || EVBUFFER_LENGTH(cf->event->output) == 0) {
|
||||||
file_write_finished(cf);
|
if (cf->event != NULL)
|
||||||
|
bufferevent_free(cf->event);
|
||||||
|
if (cf->fd != -1)
|
||||||
|
close(cf->fd);
|
||||||
|
RB_REMOVE(client_files, files, cf);
|
||||||
|
file_free(cf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,28 +828,6 @@ file_write_ready(struct client_files *files, struct imsg *imsg)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a write done message (server). */
|
|
||||||
int
|
|
||||||
file_write_done(struct client_files *files, struct imsg *imsg)
|
|
||||||
{
|
|
||||||
struct msg_write_done *msg = imsg->data;
|
|
||||||
size_t msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
|
||||||
struct client_file find, *cf;
|
|
||||||
|
|
||||||
if (msglen != sizeof *msg)
|
|
||||||
return (-1);
|
|
||||||
find.stream = msg->stream;
|
|
||||||
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
|
|
||||||
return (0);
|
|
||||||
if (cf->c == NULL || (~cf->c->flags & CLIENT_WRITE_ACK))
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
log_debug("file %d write done", cf->stream);
|
|
||||||
cf->error = msg->error;
|
|
||||||
file_fire_done(cf);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle read data message (server). */
|
/* Handle read data message (server). */
|
||||||
int
|
int
|
||||||
file_read_data(struct client_files *files, struct imsg *imsg)
|
file_read_data(struct client_files *files, struct imsg *imsg)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: format-draw.c,v 1.34 2026/07/21 07:20:18 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -958,7 +958,7 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
|
|||||||
if (srs != NULL) {
|
if (srs != NULL) {
|
||||||
if (fr != NULL && !format_is_type(fr, &sy)) {
|
if (fr != NULL && !format_is_type(fr, &sy)) {
|
||||||
if (s[current].cx != fr->start) {
|
if (s[current].cx != fr->start) {
|
||||||
fr->end = s[current].cx;
|
fr->end = s[current].cx + 1;
|
||||||
TAILQ_INSERT_TAIL(&frs, fr, entry);
|
TAILQ_INSERT_TAIL(&frs, fr, entry);
|
||||||
} else
|
} else
|
||||||
free(fr);
|
free(fr);
|
||||||
|
|||||||
2
fuzzy.c
2
fuzzy.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: fuzzy.c,v 1.1 2026/06/26 14:40:30 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: grid-reader.c,v 1.11 2026/07/29 17:42:56 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Anindya Mukherjee <anindya49@hotmail.com>
|
* Copyright (c) 2020 Anindya Mukherjee <anindya49@hotmail.com>
|
||||||
@@ -54,8 +54,11 @@ grid_reader_cursor_right(struct grid_reader *gr, int wrap, int all, int onemore)
|
|||||||
px = gr->gd->sx;
|
px = gr->gd->sx;
|
||||||
else if (onemore)
|
else if (onemore)
|
||||||
px = grid_reader_line_length(gr);
|
px = grid_reader_line_length(gr);
|
||||||
else
|
else {
|
||||||
px = grid_line_limit(gr->gd, gr->cy);
|
px = grid_reader_line_length(gr);
|
||||||
|
if (px != 0)
|
||||||
|
px--;
|
||||||
|
}
|
||||||
|
|
||||||
if (wrap && gr->cx >= px && gr->cy < gr->gd->hsize + gr->gd->sy - 1) {
|
if (wrap && gr->cx >= px && gr->cy < gr->gd->hsize + gr->gd->sy - 1) {
|
||||||
grid_reader_cursor_start_of_line(gr, 0);
|
grid_reader_cursor_start_of_line(gr, 0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: grid-view.c,v 1.39 2026/08/03 12:58:53 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -47,9 +47,9 @@ grid_view_set_cell(struct grid *gd, u_int px, u_int py,
|
|||||||
|
|
||||||
/* Set padding. */
|
/* Set padding. */
|
||||||
void
|
void
|
||||||
grid_view_set_padding(struct grid *gd, u_int px, u_int py, int bg)
|
grid_view_set_padding(struct grid *gd, u_int px, u_int py)
|
||||||
{
|
{
|
||||||
grid_set_padding(gd, grid_view_x(gd, px), grid_view_y(gd, py), bg);
|
grid_set_padding(gd, grid_view_x(gd, px), grid_view_y(gd, py));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set cells. */
|
/* Set cells. */
|
||||||
|
|||||||
128
grid.c
128
grid.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: grid.c,v 1.158 2026/09/01 12:49:49 nicm Exp $ */
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -60,6 +60,21 @@ static const struct grid_cell_entry grid_cleared_entry = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
static void
|
||||||
|
grid_check_lines(struct grid *gd)
|
||||||
|
{
|
||||||
|
u_int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < gd->hsize + gd->sy; i++) {
|
||||||
|
for (j = i + 1; j < gd->hsize + gd->sy; j++) {
|
||||||
|
if (gd->linedata[i].celldata != NULL)
|
||||||
|
assert(gd->linedata[i].celldata != gd->linedata[j].celldata);
|
||||||
|
if (gd->linedata[i].extddata != NULL)
|
||||||
|
assert(gd->linedata[i].extddata != gd->linedata[j].extddata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grid_check_is_clear(struct grid *gd)
|
grid_check_is_clear(struct grid *gd)
|
||||||
{
|
{
|
||||||
@@ -89,6 +104,11 @@ grid_check_is_clear(struct grid *gd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
static void
|
||||||
|
grid_check_lines(__unused struct grid *gd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grid_check_is_clear(__unused struct grid *gd)
|
grid_check_is_clear(__unused struct grid *gd)
|
||||||
{
|
{
|
||||||
@@ -233,25 +253,6 @@ grid_get_line(struct grid *gd, u_int line)
|
|||||||
return (&gd->linedata[line]);
|
return (&gd->linedata[line]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get line time. */
|
|
||||||
time_t
|
|
||||||
grid_line_time(const struct grid_line *gl)
|
|
||||||
{
|
|
||||||
if (gl->time == 0)
|
|
||||||
return (0);
|
|
||||||
return (start_time.tv_sec + gl->time - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set line time. */
|
|
||||||
static void
|
|
||||||
grid_line_set_time(struct grid_line *gl)
|
|
||||||
{
|
|
||||||
if (current_time == 0)
|
|
||||||
gl->time = 0;
|
|
||||||
else
|
|
||||||
gl->time = current_time - start_time.tv_sec + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust number of lines. */
|
/* Adjust number of lines. */
|
||||||
void
|
void
|
||||||
grid_adjust_lines(struct grid *gd, u_int lines)
|
grid_adjust_lines(struct grid *gd, u_int lines)
|
||||||
@@ -385,9 +386,6 @@ grid_create(u_int sx, u_int sy, u_int hlimit)
|
|||||||
if (gd->sy != 0)
|
if (gd->sy != 0)
|
||||||
gd->linedata = xcalloc(gd->sy, sizeof *gd->linedata);
|
gd->linedata = xcalloc(gd->sy, sizeof *gd->linedata);
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
assert(gd->hsize == 0);
|
|
||||||
#endif
|
|
||||||
grid_check_is_clear(gd);
|
grid_check_is_clear(gd);
|
||||||
return (gd);
|
return (gd);
|
||||||
}
|
}
|
||||||
@@ -505,9 +503,11 @@ grid_scroll_history(struct grid *gd, u_int bg)
|
|||||||
|
|
||||||
gd->hscrolled++;
|
gd->hscrolled++;
|
||||||
grid_compact_line(&gd->linedata[gd->hsize]);
|
grid_compact_line(&gd->linedata[gd->hsize]);
|
||||||
grid_line_set_time(&gd->linedata[gd->hsize]);
|
gd->linedata[gd->hsize].time = current_time;
|
||||||
gd->hsize++;
|
gd->hsize++;
|
||||||
gd->scroll_added++;
|
gd->scroll_added++;
|
||||||
|
|
||||||
|
grid_check_lines(gd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the history. */
|
/* Clear the history. */
|
||||||
@@ -547,7 +547,7 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower, u_int bg)
|
|||||||
|
|
||||||
/* Move the line into the history. */
|
/* Move the line into the history. */
|
||||||
memcpy(gl_history, gl_upper, sizeof *gl_history);
|
memcpy(gl_history, gl_upper, sizeof *gl_history);
|
||||||
grid_line_set_time(gl_history);
|
gl_history->time = current_time;
|
||||||
|
|
||||||
/* Then move the region up and clear the bottom line. */
|
/* Then move the region up and clear the bottom line. */
|
||||||
memmove(gl_upper, gl_upper + 1, (lower - upper) * sizeof *gl_upper);
|
memmove(gl_upper, gl_upper + 1, (lower - upper) * sizeof *gl_upper);
|
||||||
@@ -557,6 +557,8 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower, u_int bg)
|
|||||||
gd->hscrolled++;
|
gd->hscrolled++;
|
||||||
gd->hsize++;
|
gd->hsize++;
|
||||||
gd->scroll_added++;
|
gd->scroll_added++;
|
||||||
|
|
||||||
|
grid_check_lines(gd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand line to fit to cell. */
|
/* Expand line to fit to cell. */
|
||||||
@@ -682,13 +684,9 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
|||||||
|
|
||||||
/* Set padding at position. */
|
/* Set padding at position. */
|
||||||
void
|
void
|
||||||
grid_set_padding(struct grid *gd, u_int px, u_int py, int bg)
|
grid_set_padding(struct grid *gd, u_int px, u_int py)
|
||||||
{
|
{
|
||||||
struct grid_cell gc;
|
grid_set_cell(gd, px, py, &grid_padding_cell);
|
||||||
|
|
||||||
memcpy(&gc, &grid_padding_cell, sizeof gc);
|
|
||||||
gc.bg = bg;
|
|
||||||
grid_set_cell(gd, px, py, &gc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set cells at position. */
|
/* Set cells at position. */
|
||||||
@@ -822,6 +820,8 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny, u_int bg)
|
|||||||
}
|
}
|
||||||
if (py != 0 && (py < dy || py >= dy + ny))
|
if (py != 0 && (py < dy || py >= dy + ny))
|
||||||
gd->linedata[py - 1].flags &= ~GRID_LINE_WRAPPED;
|
gd->linedata[py - 1].flags &= ~GRID_LINE_WRAPPED;
|
||||||
|
|
||||||
|
grid_check_lines(gd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move a group of cells. */
|
/* Move a group of cells. */
|
||||||
@@ -1311,6 +1311,8 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
|
|||||||
sy++;
|
sy++;
|
||||||
dy++;
|
dy++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grid_check_lines(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark line as dead. */
|
/* Mark line as dead. */
|
||||||
@@ -1607,6 +1609,8 @@ grid_reflow(struct grid *gd, u_int sx)
|
|||||||
gd->linedata = target->linedata;
|
gd->linedata = target->linedata;
|
||||||
free(target);
|
free(target);
|
||||||
gd->scroll_generation++;
|
gd->scroll_generation++;
|
||||||
|
|
||||||
|
grid_check_lines(gd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert to position based on wrapped lines. */
|
/* Convert to position based on wrapped lines. */
|
||||||
@@ -1635,7 +1639,7 @@ grid_wrap_position(struct grid *gd, u_int px, u_int py, u_int *wx, u_int *wy)
|
|||||||
void
|
void
|
||||||
grid_unwrap_position(struct grid *gd, u_int *px, u_int *py, u_int wx, u_int wy)
|
grid_unwrap_position(struct grid *gd, u_int *px, u_int *py, u_int wx, u_int wy)
|
||||||
{
|
{
|
||||||
u_int yy, ay = 0, ey = gd->hsize + gd->sy - 1;
|
u_int yy, ay = 0;
|
||||||
|
|
||||||
for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) {
|
for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) {
|
||||||
if (ay == wy)
|
if (ay == wy)
|
||||||
@@ -1649,7 +1653,7 @@ grid_unwrap_position(struct grid *gd, u_int *px, u_int *py, u_int wx, u_int wy)
|
|||||||
* until we find the end or the line now containing wx.
|
* until we find the end or the line now containing wx.
|
||||||
*/
|
*/
|
||||||
if (wx == UINT_MAX) {
|
if (wx == UINT_MAX) {
|
||||||
while (yy < ey && gd->linedata[yy].flags & GRID_LINE_WRAPPED)
|
while (gd->linedata[yy].flags & GRID_LINE_WRAPPED)
|
||||||
yy++;
|
yy++;
|
||||||
wx = gd->linedata[yy].cellused;
|
wx = gd->linedata[yy].cellused;
|
||||||
} else {
|
} else {
|
||||||
@@ -1685,55 +1689,27 @@ grid_line_length(struct grid *gd, u_int py)
|
|||||||
return (px);
|
return (px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get last position on line, not including padding. */
|
|
||||||
u_int
|
|
||||||
grid_line_limit(struct grid *gd, u_int py)
|
|
||||||
{
|
|
||||||
struct grid_cell gc;
|
|
||||||
u_int px;
|
|
||||||
|
|
||||||
px = grid_line_length(gd, py);
|
|
||||||
if (px == 0)
|
|
||||||
return (0);
|
|
||||||
px--;
|
|
||||||
while (px > 0) {
|
|
||||||
grid_get_cell(gd, px, py, &gc);
|
|
||||||
if (~gc.flags & GRID_FLAG_PADDING)
|
|
||||||
break;
|
|
||||||
px--;
|
|
||||||
}
|
|
||||||
return (px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if character is in set. */
|
/* Check if character is in set. */
|
||||||
int
|
int
|
||||||
grid_in_set(struct grid *gd, u_int px, u_int py, const char *set)
|
grid_in_set(struct grid *gd, u_int px, u_int py, const char *set)
|
||||||
{
|
{
|
||||||
struct grid_cell gc, tmp_gc;
|
struct grid_cell gc, tmp_gc;
|
||||||
u_int pxx;
|
u_int pxx;
|
||||||
int has_tab, has_space;
|
|
||||||
|
|
||||||
has_tab = (strchr(set, '\t') != NULL);
|
|
||||||
has_space = (strchr(set, ' ') != NULL);
|
|
||||||
|
|
||||||
grid_get_cell(gd, px, py, &gc);
|
grid_get_cell(gd, px, py, &gc);
|
||||||
if (gc.flags & GRID_FLAG_PADDING) {
|
if (strchr(set, '\t')) {
|
||||||
if (!has_tab && !has_space)
|
if (gc.flags & GRID_FLAG_PADDING) {
|
||||||
return (0);
|
pxx = px;
|
||||||
pxx = px;
|
do
|
||||||
do
|
grid_get_cell(gd, --pxx, py, &tmp_gc);
|
||||||
grid_get_cell(gd, --pxx, py, &tmp_gc);
|
while (pxx > 0 && tmp_gc.flags & GRID_FLAG_PADDING);
|
||||||
while (pxx > 0 && tmp_gc.flags & GRID_FLAG_PADDING);
|
if (tmp_gc.flags & GRID_FLAG_TAB)
|
||||||
if (((has_tab || has_space) &&
|
return (tmp_gc.data.width - (px - pxx));
|
||||||
(tmp_gc.flags & GRID_FLAG_TAB)) ||
|
} else if (gc.flags & GRID_FLAG_TAB)
|
||||||
(has_space && utf8_has_whitespace(&tmp_gc.data)))
|
return (gc.data.width);
|
||||||
return (tmp_gc.data.width - (px - pxx));
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
if ((has_tab || has_space) && (gc.flags & GRID_FLAG_TAB))
|
if (gc.flags & GRID_FLAG_PADDING)
|
||||||
return (gc.data.width);
|
return (0);
|
||||||
if (has_space && utf8_has_whitespace(&gc.data))
|
|
||||||
return (gc.data.width == 0 ? 1 : gc.data.width);
|
|
||||||
return (utf8_cstrhas(set, &gc.data));
|
return (utf8_cstrhas(set, &gc.data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1752,14 +1728,8 @@ grid_line_flags_string(int flags)
|
|||||||
strlcat(s, "DEAD,", sizeof s);
|
strlcat(s, "DEAD,", sizeof s);
|
||||||
if (flags & GRID_LINE_START_PROMPT)
|
if (flags & GRID_LINE_START_PROMPT)
|
||||||
strlcat(s, "START_PROMPT,", sizeof s);
|
strlcat(s, "START_PROMPT,", sizeof s);
|
||||||
if (flags & GRID_LINE_SECOND_PROMPT)
|
|
||||||
strlcat(s, "SECOND_PROMPT,", sizeof s);
|
|
||||||
if (flags & GRID_LINE_START_COMMAND)
|
|
||||||
strlcat(s, "START_COMMAND,", sizeof s);
|
|
||||||
if (flags & GRID_LINE_START_OUTPUT)
|
if (flags & GRID_LINE_START_OUTPUT)
|
||||||
strlcat(s, "START_OUTPUT,", sizeof s);
|
strlcat(s, "START_OUTPUT,", sizeof s);
|
||||||
if (flags & GRID_LINE_END_OUTPUT)
|
|
||||||
strlcat(s, "END_OUTPUT,", sizeof s);
|
|
||||||
if (flags & GRID_LINE_HYPERLINK)
|
if (flags & GRID_LINE_HYPERLINK)
|
||||||
strlcat(s, "HYPERLINK,", sizeof s);
|
strlcat(s, "HYPERLINK,", sizeof s);
|
||||||
if (*s == '\0')
|
if (*s == '\0')
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user