1#![expect(rustdoc::broken_intra_doc_links, reason = "github markdown callout")]
15#![doc = include_str!("../README.md")]
16#![allow(
17 non_camel_case_types,
18 clippy::manual_range_contains,
19 clippy::too_many_arguments,
20 reason = "won't fix: match upstream"
21)]
22#![allow(clippy::missing_safety_doc, reason = "currently using too much unsafe")]
23#![allow(unused)] #![allow(unpredictable_function_pointer_comparisons)] #![warn(clippy::multiple_crate_versions)]
28#![warn(clippy::shadow_same)]
29#![allow(clippy::shadow_unrelated)] #![allow(clippy::shadow_reuse)] pub(crate) use std::sync::atomic;
33
34mod compat;
35use compat::vis_flags;
36use compat::{strtonum, strtonum_};
37
38mod ncurses_;
39use ncurses_::*;
40
41pub(crate) mod libc;
42pub(crate) use libc::errno;
43pub(crate) use libc::*;
44pub(crate) use libc::{free_, memcpy_, memcpy__, strcaseeq_, streq_};
45
46#[cfg(feature = "sixel")]
47mod image_;
48#[cfg(feature = "sixel")]
49mod image_sixel;
50#[cfg(feature = "sixel")]
51use image_sixel::sixel_image;
52
53#[cfg(feature = "utempter")]
54mod utempter;
55
56use core::{
57 ffi::{
58 CStr, c_int, c_long, c_longlong, c_short, c_uchar, c_uint, c_ulonglong, c_ushort, c_void,
59 },
60 mem::{ManuallyDrop, MaybeUninit, size_of, zeroed},
61 ops::ControlFlow,
62 ptr::{NonNull, null, null_mut},
63};
64use std::sync::atomic::AtomicU32;
65
66mod event_;
68use event_::*;
69
70use crate::compat::{
71 RB_GENERATE,
72 queue::{
73 Entry, ListEntry, list_entry, list_head, tailq_entry, tailq_first, tailq_foreach,
74 tailq_head, tailq_next,
75 },
76 tree::{GetEntry, rb_entry, rb_head},
77};
78
79unsafe extern "C" {
80 static mut environ: *mut *mut u8;
81 fn strsep(_: *mut *mut u8, _delim: *const u8) -> *mut u8;
82}
83
84#[inline]
85const fn transmute_ptr<T>(value: Option<NonNull<T>>) -> *mut T {
86 match value {
87 Some(ptr) => ptr.as_ptr(),
88 None => null_mut(),
89 }
90}
91
92use compat::imsg::imsg; type wchar_t = core::ffi::c_int;
95#[cfg(target_os = "linux")]
96unsafe extern "C" {
97 static mut stdin: *mut FILE;
98 static mut stdout: *mut FILE;
99 static mut stderr: *mut FILE;
100}
101#[cfg(target_os = "macos")]
102unsafe extern "C" {
103 #[link_name = "__stdinp"]
104 static mut stdin: *mut FILE;
105
106 #[link_name = "__stdoutp"]
107 static mut stdout: *mut FILE;
108
109 #[link_name = "__stderrp"]
110 static mut stderr: *mut FILE;
111}
112
113type bitstr_t = u8;
116
117unsafe fn bit_alloc(nbits: u32) -> *mut u8 {
118 unsafe { libc::calloc(nbits.div_ceil(8) as usize, 1).cast() }
119}
120unsafe fn bit_set(bits: *mut u8, i: u32) {
121 unsafe {
122 let byte_index = i / 8;
123 let bit_index = i % 8;
124 *bits.add(byte_index as usize) |= 1 << bit_index;
125 }
126}
127
128#[inline]
129unsafe fn bit_clear(bits: *mut u8, i: u32) {
130 unsafe {
131 let byte_index = i / 8;
132 let bit_index = i % 8;
133 *bits.add(byte_index as usize) &= !(1 << bit_index);
134 }
135}
136
137unsafe fn bit_nclear(bits: *mut u8, start: u32, stop: u32) {
139 unsafe {
140 for i in start..=stop {
142 bit_clear(bits, i);
143 }
144 }
145}
146
147unsafe fn bit_test(bits: *const u8, i: u32) -> bool {
148 unsafe {
149 let byte_index = i / 8;
150 let bit_index = i % 8;
151 (*bits.add(byte_index as usize) & (1 << bit_index)) != 0
152 }
153}
154
155const TTY_NAME_MAX: usize = 32;
156
157struct discr_alerts_entry;
159struct discr_all_entry;
160struct discr_by_uri_entry;
161struct discr_by_inner_entry;
162struct discr_data_entry;
163struct discr_entry;
164struct discr_gentry;
165struct discr_index_entry;
166struct discr_name_entry;
167struct discr_pending_entry;
168struct discr_sentry;
169struct discr_time_entry;
170struct discr_tree_entry;
171struct discr_wentry;
172
173const _PATH_TTY: *const u8 = c!("/dev/tty");
175
176const _PATH_BSHELL: *const u8 = c!("/bin/sh");
177const _PATH_BSHELL_STR: &str = "/bin/sh";
178
179const _PATH_DEFPATH: *const u8 = c!("/usr/bin:/bin");
180const _PATH_DEV: *const u8 = c!("/dev/");
181const _PATH_DEVNULL: *const u8 = c!("/dev/null");
182const _PATH_VI: &str = "/usr/bin/vi";
183
184const SIZEOF_PATH_DEV: usize = 6;
185
186macro_rules! env_or {
187 ($key:literal, $default:expr) => {
188 match std::option_env!($key) {
189 Some(value) => value,
190 None => $default,
191 }
192 };
193}
194
195const TMUX_VERSION: &str = env_or!("TMUX_VERSION", env!("CARGO_PKG_VERSION"));
196const TMUX_CONF: &str = env_or!(
197 "TMUX_CONF",
198 "/etc/tmux.conf:~/.tmux.conf:$XDG_CONFIG_HOME/tmux/tmux.conf:~/.config/tmux/tmux.conf"
199);
200const TMUX_SOCK: &str = env_or!("TMUX_SOCK", "$TMUX_TMPDIR:/tmp/");
201const TMUX_TERM: &str = env_or!("TMUX_TERM", "screen");
202const TMUX_LOCK_CMD: &str = env_or!("TMUX_LOCK_CMD", "lock -np");
203
204const PANE_MINIMUM: u32 = 1;
206
207const NAME_INTERVAL: libc::suseconds_t = 500000;
209
210const DEFAULT_XPIXEL: u32 = 16;
212const DEFAULT_YPIXEL: u32 = 32;
213
214#[repr(i32)]
216#[derive(Copy, Clone, num_enum::TryFromPrimitive)]
217enum alert_option {
218 ALERT_NONE,
219 ALERT_ANY,
220 ALERT_CURRENT,
221 ALERT_OTHER,
222}
223
224#[repr(i32)]
226#[derive(Copy, Clone, Eq, PartialEq, num_enum::TryFromPrimitive)]
227enum visual_option {
228 VISUAL_OFF,
229 VISUAL_ON,
230 VISUAL_BOTH,
231}
232
233const KEYC_NONE: c_ulonglong = 0x000ff000000000;
235const KEYC_UNKNOWN: c_ulonglong = 0x000fe000000000;
236
237const KEYC_BASE: c_ulonglong = 0x0000000010e000;
240const KEYC_USER: c_ulonglong = 0x0000000010f000;
241const KEYC_USER_END: c_ulonglong = KEYC_USER + KEYC_NUSER;
242
243const KEYC_META: c_ulonglong = 0x00100000000000;
245const KEYC_CTRL: c_ulonglong = 0x00200000000000;
246const KEYC_SHIFT: c_ulonglong = 0x00400000000000;
247
248const KEYC_LITERAL: c_ulonglong = 0x01000000000000;
250const KEYC_KEYPAD: c_ulonglong = 0x02000000000000;
251const KEYC_CURSOR: c_ulonglong = 0x04000000000000;
252const KEYC_IMPLIED_META: c_ulonglong = 0x08000000000000;
253const KEYC_BUILD_MODIFIERS: c_ulonglong = 0x10000000000000;
254const KEYC_VI: c_ulonglong = 0x20000000000000;
255const KEYC_SENT: c_ulonglong = 0x40000000000000;
256
257const KEYC_MASK_MODIFIERS: c_ulonglong = 0x00f00000000000;
259const KEYC_MASK_FLAGS: c_ulonglong = 0xff000000000000;
260const KEYC_MASK_KEY: c_ulonglong = 0x000fffffffffff;
261
262const KEYC_NUSER: c_ulonglong = 1000;
263
264#[allow(non_snake_case)]
265#[inline(always)]
266fn KEYC_IS_MOUSE(key: key_code) -> bool {
267 const KEYC_MOUSE: c_ulonglong = keyc::KEYC_MOUSE as c_ulonglong;
268 const KEYC_BSPACE: c_ulonglong = keyc::KEYC_BSPACE as c_ulonglong;
269
270 (key & KEYC_MASK_KEY) >= KEYC_MOUSE && (key & KEYC_MASK_KEY) < KEYC_BSPACE
271}
272
273#[allow(non_snake_case)]
274#[inline(always)]
275fn KEYC_IS_UNICODE(key: key_code) -> bool {
276 let masked = key & KEYC_MASK_KEY;
277
278 const KEYC_BASE_END: c_ulonglong = keyc::KEYC_BASE_END as c_ulonglong;
279 masked > 0x7f
280 && (masked < KEYC_BASE || masked >= KEYC_BASE_END)
281 && (masked < KEYC_USER || masked >= KEYC_USER_END)
282}
283
284const KEYC_CLICK_TIMEOUT: i32 = 300;
285
286type key_code = core::ffi::c_ulonglong;
289
290#[repr(u64)]
294#[derive(Copy, Clone)]
295enum c0 {
296 C0_NUL,
297 C0_SOH,
298 C0_STX,
299 C0_ETX,
300 C0_EOT,
301 C0_ENQ,
302 C0_ASC,
303 C0_BEL,
304 C0_BS,
305 C0_HT,
306 C0_LF,
307 C0_VT,
308 C0_FF,
309 C0_CR,
310 C0_SO,
311 C0_SI,
312 C0_DLE,
313 C0_DC1,
314 C0_DC2,
315 C0_DC3,
316 C0_DC4,
317 C0_NAK,
318 C0_SYN,
319 C0_ETB,
320 C0_CAN,
321 C0_EM,
322 C0_SUB,
323 C0_ESC,
324 C0_FS,
325 C0_GS,
326 C0_RS,
327 C0_US,
328}
329
330include!("keyc_mouse_key.rs");
342
343#[repr(u32)]
345#[derive(Copy, Clone, num_enum::TryFromPrimitive)]
346enum tty_code_code {
347 TTYC_ACSC,
348 TTYC_AM,
349 TTYC_AX,
350 TTYC_BCE,
351 TTYC_BEL,
352 TTYC_BIDI,
353 TTYC_BLINK,
354 TTYC_BOLD,
355 TTYC_CIVIS,
356 TTYC_CLEAR,
357 TTYC_CLMG,
358 TTYC_CMG,
359 TTYC_CNORM,
360 TTYC_COLORS,
361 TTYC_CR,
362 TTYC_CS,
363 TTYC_CSR,
364 TTYC_CUB,
365 TTYC_CUB1,
366 TTYC_CUD,
367 TTYC_CUD1,
368 TTYC_CUF,
369 TTYC_CUF1,
370 TTYC_CUP,
371 TTYC_CUU,
372 TTYC_CUU1,
373 TTYC_CVVIS,
374 TTYC_DCH,
375 TTYC_DCH1,
376 TTYC_DIM,
377 TTYC_DL,
378 TTYC_DL1,
379 TTYC_DSBP,
380 TTYC_DSEKS,
381 TTYC_DSFCS,
382 TTYC_DSMG,
383 TTYC_E3,
384 TTYC_ECH,
385 TTYC_ED,
386 TTYC_EL,
387 TTYC_EL1,
388 TTYC_ENACS,
389 TTYC_ENBP,
390 TTYC_ENEKS,
391 TTYC_ENFCS,
392 TTYC_ENMG,
393 TTYC_FSL,
394 TTYC_HLS,
395 TTYC_HOME,
396 TTYC_HPA,
397 TTYC_ICH,
398 TTYC_ICH1,
399 TTYC_IL,
400 TTYC_IL1,
401 TTYC_INDN,
402 TTYC_INVIS,
403 TTYC_KCBT,
404 TTYC_KCUB1,
405 TTYC_KCUD1,
406 TTYC_KCUF1,
407 TTYC_KCUU1,
408 TTYC_KDC2,
409 TTYC_KDC3,
410 TTYC_KDC4,
411 TTYC_KDC5,
412 TTYC_KDC6,
413 TTYC_KDC7,
414 TTYC_KDCH1,
415 TTYC_KDN2,
416 TTYC_KDN3,
417 TTYC_KDN4,
418 TTYC_KDN5,
419 TTYC_KDN6,
420 TTYC_KDN7,
421 TTYC_KEND,
422 TTYC_KEND2,
423 TTYC_KEND3,
424 TTYC_KEND4,
425 TTYC_KEND5,
426 TTYC_KEND6,
427 TTYC_KEND7,
428 TTYC_KF1,
429 TTYC_KF10,
430 TTYC_KF11,
431 TTYC_KF12,
432 TTYC_KF13,
433 TTYC_KF14,
434 TTYC_KF15,
435 TTYC_KF16,
436 TTYC_KF17,
437 TTYC_KF18,
438 TTYC_KF19,
439 TTYC_KF2,
440 TTYC_KF20,
441 TTYC_KF21,
442 TTYC_KF22,
443 TTYC_KF23,
444 TTYC_KF24,
445 TTYC_KF25,
446 TTYC_KF26,
447 TTYC_KF27,
448 TTYC_KF28,
449 TTYC_KF29,
450 TTYC_KF3,
451 TTYC_KF30,
452 TTYC_KF31,
453 TTYC_KF32,
454 TTYC_KF33,
455 TTYC_KF34,
456 TTYC_KF35,
457 TTYC_KF36,
458 TTYC_KF37,
459 TTYC_KF38,
460 TTYC_KF39,
461 TTYC_KF4,
462 TTYC_KF40,
463 TTYC_KF41,
464 TTYC_KF42,
465 TTYC_KF43,
466 TTYC_KF44,
467 TTYC_KF45,
468 TTYC_KF46,
469 TTYC_KF47,
470 TTYC_KF48,
471 TTYC_KF49,
472 TTYC_KF5,
473 TTYC_KF50,
474 TTYC_KF51,
475 TTYC_KF52,
476 TTYC_KF53,
477 TTYC_KF54,
478 TTYC_KF55,
479 TTYC_KF56,
480 TTYC_KF57,
481 TTYC_KF58,
482 TTYC_KF59,
483 TTYC_KF6,
484 TTYC_KF60,
485 TTYC_KF61,
486 TTYC_KF62,
487 TTYC_KF63,
488 TTYC_KF7,
489 TTYC_KF8,
490 TTYC_KF9,
491 TTYC_KHOM2,
492 TTYC_KHOM3,
493 TTYC_KHOM4,
494 TTYC_KHOM5,
495 TTYC_KHOM6,
496 TTYC_KHOM7,
497 TTYC_KHOME,
498 TTYC_KIC2,
499 TTYC_KIC3,
500 TTYC_KIC4,
501 TTYC_KIC5,
502 TTYC_KIC6,
503 TTYC_KIC7,
504 TTYC_KICH1,
505 TTYC_KIND,
506 TTYC_KLFT2,
507 TTYC_KLFT3,
508 TTYC_KLFT4,
509 TTYC_KLFT5,
510 TTYC_KLFT6,
511 TTYC_KLFT7,
512 TTYC_KMOUS,
513 TTYC_KNP,
514 TTYC_KNXT2,
515 TTYC_KNXT3,
516 TTYC_KNXT4,
517 TTYC_KNXT5,
518 TTYC_KNXT6,
519 TTYC_KNXT7,
520 TTYC_KPP,
521 TTYC_KPRV2,
522 TTYC_KPRV3,
523 TTYC_KPRV4,
524 TTYC_KPRV5,
525 TTYC_KPRV6,
526 TTYC_KPRV7,
527 TTYC_KRI,
528 TTYC_KRIT2,
529 TTYC_KRIT3,
530 TTYC_KRIT4,
531 TTYC_KRIT5,
532 TTYC_KRIT6,
533 TTYC_KRIT7,
534 TTYC_KUP2,
535 TTYC_KUP3,
536 TTYC_KUP4,
537 TTYC_KUP5,
538 TTYC_KUP6,
539 TTYC_KUP7,
540 TTYC_MS,
541 TTYC_NOBR,
542 TTYC_OL,
543 TTYC_OP,
544 TTYC_RECT,
545 TTYC_REV,
546 TTYC_RGB,
547 TTYC_RI,
548 TTYC_RIN,
549 TTYC_RMACS,
550 TTYC_RMCUP,
551 TTYC_RMKX,
552 TTYC_SE,
553 TTYC_SETAB,
554 TTYC_SETAF,
555 TTYC_SETAL,
556 TTYC_SETRGBB,
557 TTYC_SETRGBF,
558 TTYC_SETULC,
559 TTYC_SETULC1,
560 TTYC_SGR0,
561 TTYC_SITM,
562 TTYC_SMACS,
563 TTYC_SMCUP,
564 TTYC_SMKX,
565 TTYC_SMOL,
566 TTYC_SMSO,
567 TTYC_SMUL,
568 TTYC_SMULX,
569 TTYC_SMXX,
570 TTYC_SXL,
571 TTYC_SS,
572 TTYC_SWD,
573 TTYC_SYNC,
574 TTYC_TC,
575 TTYC_TSL,
576 TTYC_U8,
577 TTYC_VPA,
578 TTYC_XT,
579}
580
581const WHITESPACE: *const u8 = c!(" ");
582
583#[repr(i32)]
584#[derive(Copy, Clone, Eq, PartialEq, num_enum::TryFromPrimitive)]
585enum modekey {
586 MODEKEY_EMACS = 0,
587 MODEKEY_VI = 1,
588}
589
590bitflags::bitflags! {
591 #[repr(transparent)]
593 #[derive(Copy, Clone, Eq, PartialEq)]
594 struct mode_flag : i32 {
595 const MODE_CURSOR = 0x1;
596 const MODE_INSERT = 0x2;
597 const MODE_KCURSOR = 0x4;
598 const MODE_KKEYPAD = 0x8;
599 const MODE_WRAP = 0x10;
600 const MODE_MOUSE_STANDARD = 0x20;
601 const MODE_MOUSE_BUTTON = 0x40;
602 const MODE_CURSOR_BLINKING = 0x80;
603 const MODE_MOUSE_UTF8 = 0x100;
604 const MODE_MOUSE_SGR = 0x200;
605 const MODE_BRACKETPASTE = 0x400;
606 const MODE_FOCUSON = 0x800;
607 const MODE_MOUSE_ALL = 0x1000;
608 const MODE_ORIGIN = 0x2000;
609 const MODE_CRLF = 0x4000;
610 const MODE_KEYS_EXTENDED = 0x8000;
611 const MODE_CURSOR_VERY_VISIBLE = 0x10000;
612 const MODE_CURSOR_BLINKING_SET = 0x20000;
613 const MODE_KEYS_EXTENDED_2 = 0x40000;
614 }
615}
616
617const ALL_MODES: i32 = 0xffffff;
618const ALL_MOUSE_MODES: mode_flag = mode_flag::MODE_MOUSE_STANDARD
619 .union(mode_flag::MODE_MOUSE_BUTTON)
620 .union(mode_flag::MODE_MOUSE_ALL);
621const MOTION_MOUSE_MODES: mode_flag = mode_flag::MODE_MOUSE_BUTTON.union(mode_flag::MODE_MOUSE_ALL);
622const CURSOR_MODES: mode_flag = mode_flag::MODE_CURSOR
623 .union(mode_flag::MODE_CURSOR_BLINKING)
624 .union(mode_flag::MODE_CURSOR_VERY_VISIBLE);
625const EXTENDED_KEY_MODES: mode_flag =
626 mode_flag::MODE_KEYS_EXTENDED.union(mode_flag::MODE_KEYS_EXTENDED_2);
627
628const MOUSE_PARAM_MAX: u32 = 0xff;
630const MOUSE_PARAM_UTF8_MAX: u32 = 0x7ff;
631const MOUSE_PARAM_BTN_OFF: u32 = 0x20;
632const MOUSE_PARAM_POS_OFF: u32 = 0x21;
633
634type utf8_char = c_uint;
636
637const UTF8_SIZE: usize = 21;
641
642#[repr(C)]
643#[derive(Copy, Clone)]
644struct utf8_data {
645 data: [c_uchar; UTF8_SIZE],
646
647 have: c_uchar,
648 size: c_uchar,
649
650 width: c_uchar,
652}
653
654impl utf8_data {
655 const fn new<const N: usize>(
656 data: [u8; N],
657 have: c_uchar,
658 size: c_uchar,
659 width: c_uchar,
660 ) -> Self {
661 if N >= UTF8_SIZE {
662 panic!("invalid size");
663 }
664
665 let mut padded_data = [0u8; UTF8_SIZE];
666 let mut i = 0usize;
667 while i < N {
668 padded_data[i] = data[i];
669 i += 1;
670 }
671
672 Self {
673 data: padded_data,
674 have,
675 size,
676 width,
677 }
678 }
679}
680
681#[repr(i32)]
682#[derive(Copy, Clone, Eq, PartialEq)]
683enum utf8_state {
684 UTF8_MORE,
685 UTF8_DONE,
686 UTF8_ERROR,
687}
688
689const COLOUR_FLAG_256: i32 = 0x01000000;
691const COLOUR_FLAG_RGB: i32 = 0x02000000;
692
693#[allow(non_snake_case)]
695#[inline]
696fn COLOUR_DEFAULT(c: i32) -> bool {
697 c == 8 || c == 9
698}
699
700#[repr(C)]
702#[derive(Copy, Clone)]
703struct colour_palette {
704 fg: i32,
705 bg: i32,
706
707 palette: *mut i32,
708 default_palette: *mut i32,
709}
710
711bitflags::bitflags! {
713 #[repr(transparent)]
715 #[derive(Copy, Clone, Eq, PartialEq)]
716 struct grid_attr : u16 {
717 const GRID_ATTR_BRIGHT = 0x1;
718 const GRID_ATTR_DIM = 0x2;
719 const GRID_ATTR_UNDERSCORE = 0x4;
720 const GRID_ATTR_BLINK = 0x8;
721 const GRID_ATTR_REVERSE = 0x10;
722 const GRID_ATTR_HIDDEN = 0x20;
723 const GRID_ATTR_ITALICS = 0x40;
724 const GRID_ATTR_CHARSET = 0x80; const GRID_ATTR_STRIKETHROUGH = 0x100;
726 const GRID_ATTR_UNDERSCORE_2 = 0x200;
727 const GRID_ATTR_UNDERSCORE_3 = 0x400;
728 const GRID_ATTR_UNDERSCORE_4 = 0x800;
729 const GRID_ATTR_UNDERSCORE_5 = 0x1000;
730 const GRID_ATTR_OVERLINE = 0x2000;
731 }
732}
733
734const GRID_ATTR_ALL_UNDERSCORE: grid_attr = grid_attr::GRID_ATTR_UNDERSCORE
736 .union(grid_attr::GRID_ATTR_UNDERSCORE_2)
737 .union(grid_attr::GRID_ATTR_UNDERSCORE_3)
738 .union(grid_attr::GRID_ATTR_UNDERSCORE_4)
739 .union(grid_attr::GRID_ATTR_UNDERSCORE_5);
740
741bitflags::bitflags! {
742 #[repr(transparent)]
744 #[derive(Copy, Clone, Eq, PartialEq)]
745 struct grid_flag : u8 {
746 const FG256 = 0x1;
747 const BG256 = 0x2;
748 const PADDING = 0x4;
749 const EXTENDED = 0x8;
750 const SELECTED = 0x10;
751 const NOPALETTE = 0x20;
752 const CLEARED = 0x40;
753 }
754}
755
756bitflags::bitflags! {
758 #[repr(transparent)]
759 #[derive(Copy, Clone, Eq, PartialEq)]
760 struct grid_line_flag: i32 {
761 const WRAPPED = 1 << 0; const EXTENDED = 1 << 1; const DEAD = 1 << 2; const START_PROMPT = 1 << 3; const START_OUTPUT = 1 << 4; }
767}
768
769bitflags::bitflags! {
771 #[repr(transparent)]
772 #[derive(Copy, Clone, Eq, PartialEq)]
773 struct grid_string_flags: i32 {
774 const GRID_STRING_WITH_SEQUENCES = 0x1;
775 const GRID_STRING_ESCAPE_SEQUENCES = 0x2;
776 const GRID_STRING_TRIM_SPACES = 0x4;
777 const GRID_STRING_USED_ONLY = 0x8;
778 const GRID_STRING_EMPTY_CELLS = 0x10;
779 }
780}
781
782#[repr(i32)]
784#[derive(Copy, Clone, Eq, PartialEq)]
785enum cell_type {
786 CELL_INSIDE = 0,
787 CELL_TOPBOTTOM = 1,
788 CELL_LEFTRIGHT = 2,
789 CELL_TOPLEFT = 3,
790 CELL_TOPRIGHT = 4,
791 CELL_BOTTOMLEFT = 5,
792 CELL_BOTTOMRIGHT = 6,
793 CELL_TOPJOIN = 7,
794 CELL_BOTTOMJOIN = 8,
795 CELL_LEFTJOIN = 9,
796 CELL_RIGHTJOIN = 10,
797 CELL_JOIN = 11,
798 CELL_OUTSIDE = 12,
799}
800use cell_type::*; const CELL_BORDERS: [u8; 13] = [
804 b' ', b'x', b'q', b'l', b'k', b'm', b'j', b'w', b'v', b't', b'u', b'n', b'~',
805];
806const SIMPLE_BORDERS: [u8; 13] = [
807 b' ', b'|', b'-', b'+', b'+', b'+', b'+', b'+', b'+', b'+', b'+', b'+', b'.',
808];
809const PADDED_BORDERS: [u8; 13] = [b' '; 13];
810
811#[repr(C)]
813#[derive(Copy, Clone)]
814struct grid_cell {
815 data: utf8_data,
816 attr: grid_attr,
817 flags: grid_flag,
818 fg: i32,
819 bg: i32,
820 us: i32,
821 link: u32,
822}
823
824impl grid_cell {
825 const fn new(
826 data: utf8_data,
827 attr: grid_attr,
828 flags: grid_flag,
829 fg: i32,
830 bg: i32,
831 us: i32,
832 link: u32,
833 ) -> Self {
834 Self {
835 data,
836 attr,
837 flags,
838 fg,
839 bg,
840 us,
841 link,
842 }
843 }
844}
845
846#[repr(C)]
848struct grid_extd_entry {
849 data: utf8_char,
850 attr: u16,
851 flags: u8,
852 fg: i32,
853 bg: i32,
854 us: i32,
855 link: u32,
856}
857
858#[derive(Copy, Clone)]
859#[repr(C, align(4))]
860struct grid_cell_entry_data {
861 attr: c_uchar,
862 fg: c_uchar,
863 bg: c_uchar,
864 data: c_uchar,
865}
866
867#[repr(C)]
868union grid_cell_entry_union {
869 offset: u32,
870 data: grid_cell_entry_data,
871}
872
873#[repr(C)]
874struct grid_cell_entry {
875 union_: grid_cell_entry_union,
876 flags: grid_flag,
877}
878
879#[repr(C)]
881struct grid_line {
882 celldata: *mut grid_cell_entry,
883 cellused: u32,
884 cellsize: u32,
885
886 extddata: *mut grid_extd_entry,
887 extdsize: u32,
888
889 flags: grid_line_flag,
890 time: time_t,
891}
892
893const GRID_HISTORY: i32 = 0x1; #[repr(C)]
897struct grid {
898 flags: i32,
899
900 sx: u32,
901 sy: u32,
902
903 hscrolled: u32,
904 hsize: u32,
905 hlimit: u32,
906
907 linedata: *mut grid_line,
908}
909
910#[repr(C)]
912struct grid_reader {
913 gd: *mut grid,
914 cx: u32,
915 cy: u32,
916}
917
918#[repr(i32)]
920#[derive(Copy, Clone, Eq, PartialEq)]
921enum style_align {
922 STYLE_ALIGN_DEFAULT,
923 STYLE_ALIGN_LEFT,
924 STYLE_ALIGN_CENTRE,
925 STYLE_ALIGN_RIGHT,
926 STYLE_ALIGN_ABSOLUTE_CENTRE,
927}
928
929#[repr(i32)]
931#[derive(Copy, Clone, Eq, PartialEq)]
932enum style_list {
933 STYLE_LIST_OFF,
934 STYLE_LIST_ON,
935 STYLE_LIST_FOCUS,
936 STYLE_LIST_LEFT_MARKER,
937 STYLE_LIST_RIGHT_MARKER,
938}
939
940#[repr(i32)]
942#[derive(Copy, Clone, Eq, PartialEq)]
943enum style_range_type {
944 STYLE_RANGE_NONE,
945 STYLE_RANGE_LEFT,
946 STYLE_RANGE_RIGHT,
947 STYLE_RANGE_PANE,
948 STYLE_RANGE_WINDOW,
949 STYLE_RANGE_SESSION,
950 STYLE_RANGE_USER,
951}
952
953crate::compat::impl_tailq_entry!(style_range, entry, tailq_entry<style_range>);
954#[repr(C)]
956struct style_range {
957 type_: style_range_type,
958 argument: u32,
959 string: [u8; 16],
960 start: u32,
961 end: u32,
963
964 entry: tailq_entry<style_range>,
966}
967type style_ranges = tailq_head<style_range>;
968
969#[repr(i32)]
971#[derive(Copy, Clone, Eq, PartialEq)]
972enum style_default_type {
973 STYLE_DEFAULT_BASE,
974 STYLE_DEFAULT_PUSH,
975 STYLE_DEFAULT_POP,
976}
977
978#[repr(C)]
980#[derive(Copy, Clone)]
981struct style {
982 gc: grid_cell,
983 ignore: i32,
984
985 fill: i32,
986 align: style_align,
987 list: style_list,
988
989 range_type: style_range_type,
990 range_argument: u32,
991 range_string: [u8; 16],
992
993 default_type: style_default_type,
994}
995
996#[cfg(feature = "sixel")]
997crate::compat::impl_tailq_entry!(image, all_entry, tailq_entry<image>);
998#[cfg(feature = "sixel")]
999crate::compat::impl_tailq_entry!(image, entry, tailq_entry<image>);
1000#[cfg(feature = "sixel")]
1001#[repr(C)]
1002#[derive(Copy, Clone)]
1003struct image {
1004 s: *mut screen,
1005 data: *mut sixel_image,
1006 fallback: *mut u8,
1007 px: u32,
1008 py: u32,
1009 sx: u32,
1010 sy: u32,
1011
1012 all_entry: tailq_entry<image>,
1013 entry: tailq_entry<image>,
1014}
1015
1016#[cfg(feature = "sixel")]
1017type images = tailq_head<image>;
1018
1019#[repr(i32)]
1021#[derive(Copy, Clone, Eq, PartialEq)]
1022enum screen_cursor_style {
1023 SCREEN_CURSOR_DEFAULT,
1024 SCREEN_CURSOR_BLOCK,
1025 SCREEN_CURSOR_UNDERLINE,
1026 SCREEN_CURSOR_BAR,
1027}
1028
1029#[repr(C)]
1031#[derive(Clone)]
1032struct screen {
1033 title: *mut u8,
1034 path: *mut u8,
1035 titles: *mut screen_titles,
1036
1037 grid: *mut grid,
1039
1040 cx: u32,
1042 cy: u32,
1044
1045 cstyle: screen_cursor_style,
1047 default_cstyle: screen_cursor_style,
1048 ccolour: i32,
1050 default_ccolour: i32,
1052
1053 rupper: u32,
1055 rlower: u32,
1057
1058 mode: mode_flag,
1059 default_mode: mode_flag,
1060
1061 saved_cx: u32,
1062 saved_cy: u32,
1063 saved_grid: *mut grid,
1064 saved_cell: grid_cell,
1065 saved_flags: i32,
1066
1067 tabs: *mut bitstr_t,
1068 sel: *mut screen_sel,
1069
1070 #[cfg(feature = "sixel")]
1071 images: images,
1072
1073 write_list: *mut screen_write_cline,
1074
1075 hyperlinks: *mut hyperlinks,
1076}
1077
1078const SCREEN_WRITE_SYNC: i32 = 0x1;
1079
1080type screen_write_init_ctx_cb = Option<unsafe fn(*mut screen_write_ctx, *mut tty_ctx)>;
1082#[repr(C)]
1083struct screen_write_ctx {
1084 wp: *mut window_pane,
1085 s: *mut screen,
1086
1087 flags: i32,
1088
1089 init_ctx_cb: screen_write_init_ctx_cb,
1090
1091 arg: *mut c_void,
1092
1093 item: *mut screen_write_citem,
1094 scrolled: u32,
1095 bg: u32,
1096}
1097
1098#[repr(i32)]
1100#[derive(Copy, Clone, Default, Eq, PartialEq, num_enum::TryFromPrimitive)]
1101enum box_lines {
1102 #[default]
1103 BOX_LINES_DEFAULT = -1,
1104 BOX_LINES_SINGLE,
1105 BOX_LINES_DOUBLE,
1106 BOX_LINES_HEAVY,
1107 BOX_LINES_SIMPLE,
1108 BOX_LINES_ROUNDED,
1109 BOX_LINES_PADDED,
1110 BOX_LINES_NONE,
1111}
1112
1113#[repr(i32)]
1115#[derive(Copy, Clone, Default, Eq, PartialEq, num_enum::TryFromPrimitive)]
1116enum pane_lines {
1117 #[default]
1118 PANE_LINES_SINGLE,
1119 PANE_LINES_DOUBLE,
1120 PANE_LINES_HEAVY,
1121 PANE_LINES_SIMPLE,
1122 PANE_LINES_NUMBER,
1123}
1124
1125macro_rules! define_error_unit {
1126 ($error_type:ident) => {
1127 #[derive(Debug)]
1128 struct $error_type;
1129 impl ::std::error::Error for $error_type {}
1130 impl ::std::fmt::Display for $error_type {
1131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1132 write!(f, "{self:?}")
1133 }
1134 }
1135 };
1136}
1137
1138#[repr(i32)]
1139#[derive(Copy, Clone, num_enum::TryFromPrimitive)]
1140enum pane_border_indicator {
1141 PANE_BORDER_OFF,
1142 PANE_BORDER_COLOUR,
1143 PANE_BORDER_ARROWS,
1144 PANE_BORDER_BOTH,
1145}
1146
1147const WINDOW_PANE_NO_MODE: i32 = 0;
1149const WINDOW_PANE_COPY_MODE: i32 = 1;
1150const WINDOW_PANE_VIEW_MODE: i32 = 2;
1151
1152#[repr(C)]
1154struct screen_redraw_ctx {
1155 c: *mut client,
1156
1157 statuslines: u32,
1158 statustop: i32,
1159
1160 pane_status: pane_status,
1161 pane_lines: pane_lines,
1162
1163 no_pane_gc: grid_cell,
1164 no_pane_gc_set: i32,
1165
1166 sx: u32,
1167 sy: u32,
1168 ox: u32,
1169 oy: u32,
1170}
1171
1172unsafe fn screen_size_x(s: *const screen) -> u32 {
1173 unsafe { (*(*s).grid).sx }
1174}
1175unsafe fn screen_size_y(s: *const screen) -> u32 {
1176 unsafe { (*(*s).grid).sy }
1177}
1178unsafe fn screen_hsize(s: *const screen) -> u32 {
1179 unsafe { (*(*s).grid).hsize }
1180}
1181unsafe fn screen_hlimit(s: *const screen) -> u32 {
1182 unsafe { (*(*s).grid).hlimit }
1183}
1184
1185#[repr(C)]
1187struct menu_item {
1188 name: SyncCharPtr,
1189 key: key_code,
1190 command: SyncCharPtr,
1191}
1192impl menu_item {
1193 const fn new(name: &'static CStr, key: key_code, command: *const u8) -> Self {
1194 Self {
1195 name: SyncCharPtr::new(name),
1196 key,
1197 command: SyncCharPtr(command),
1198 }
1199 }
1200}
1201
1202#[repr(C)]
1203struct menu {
1204 title: *const u8,
1205 items: *mut menu_item,
1206 count: u32,
1207 width: u32,
1208}
1209type menu_choice_cb = Option<unsafe fn(*mut menu, u32, key_code, *mut c_void)>;
1210
1211#[expect(clippy::type_complexity)]
1212#[repr(C)]
1215struct window_mode {
1216 name: SyncCharPtr,
1217 default_format: SyncCharPtr,
1218
1219 init: unsafe fn(NonNull<window_mode_entry>, *mut cmd_find_state, *mut args) -> *mut screen,
1220 free: unsafe fn(NonNull<window_mode_entry>),
1221 resize: unsafe fn(NonNull<window_mode_entry>, u32, u32),
1222 update: Option<unsafe fn(NonNull<window_mode_entry>)>,
1223 key: Option<
1224 unsafe fn(
1225 NonNull<window_mode_entry>,
1226 *mut client,
1227 *mut session,
1228 *mut winlink,
1229 key_code,
1230 *mut mouse_event,
1231 ),
1232 >,
1233
1234 key_table: Option<unsafe fn(*mut window_mode_entry) -> *const u8>,
1235 command: Option<
1236 unsafe fn(
1237 NonNull<window_mode_entry>,
1238 *mut client,
1239 *mut session,
1240 *mut winlink,
1241 *mut args,
1242 *mut mouse_event,
1243 ),
1244 >,
1245 formats: Option<unsafe fn(*mut window_mode_entry, *mut format_tree)>,
1246}
1247
1248crate::compat::impl_tailq_entry!(window_mode_entry, entry, tailq_entry<window_mode_entry>);
1250#[repr(C)]
1251struct window_mode_entry {
1252 wp: *mut window_pane,
1253 swp: *mut window_pane,
1254
1255 mode: *const window_mode,
1256 data: *mut c_void,
1257
1258 screen: *mut screen,
1259 prefix: u32,
1260
1261 entry: tailq_entry<window_mode_entry>,
1263}
1264
1265#[repr(C)]
1267#[derive(Copy, Clone)]
1268struct window_pane_offset {
1269 used: usize,
1270}
1271
1272crate::compat::impl_tailq_entry!(window_pane_resize, entry, tailq_entry<window_pane_resize>);
1274#[repr(C)]
1275struct window_pane_resize {
1276 sx: u32,
1277 sy: u32,
1278
1279 osx: u32,
1280 osy: u32,
1281
1282 entry: tailq_entry<window_pane_resize>,
1283}
1284type window_pane_resizes = tailq_head<window_pane_resize>;
1285
1286bitflags::bitflags! {
1287 #[repr(transparent)]
1288 #[derive(Copy, Clone, Eq, PartialEq)]
1289 struct window_pane_flags : i32 {
1290 const PANE_REDRAW = 0x1;
1291 const PANE_DROP = 0x2;
1292 const PANE_FOCUSED = 0x4;
1293 const PANE_VISITED = 0x8;
1294 const PANE_INPUTOFF = 0x40;
1297 const PANE_CHANGED = 0x80;
1298 const PANE_EXITED = 0x100;
1299 const PANE_STATUSREADY = 0x200;
1300 const PANE_STATUSDRAWN = 0x400;
1301 const PANE_EMPTY = 0x800;
1302 const PANE_STYLECHANGED = 0x1000;
1303 const PANE_UNSEENCHANGES = 0x2000;
1304 }
1305}
1306
1307#[repr(C)]
1309struct window_pane {
1310 id: u32,
1311 active_point: u32,
1312
1313 window: *mut window,
1314 options: *mut options,
1315
1316 layout_cell: *mut layout_cell,
1317 saved_layout_cell: *mut layout_cell,
1318
1319 sx: u32,
1320 sy: u32,
1321
1322 xoff: u32,
1323 yoff: u32,
1324
1325 flags: window_pane_flags,
1326
1327 argc: i32,
1328 argv: *mut *mut u8,
1329 shell: *mut u8,
1330 cwd: *mut u8,
1331
1332 pid: pid_t,
1333 tty: [u8; TTY_NAME_MAX],
1334 status: i32,
1335 dead_time: timeval,
1336
1337 fd: i32,
1338 event: *mut bufferevent,
1339
1340 offset: window_pane_offset,
1341 base_offset: usize,
1342
1343 resize_queue: window_pane_resizes,
1344 resize_timer: event,
1345
1346 ictx: *mut input_ctx,
1347
1348 cached_gc: grid_cell,
1349 cached_active_gc: grid_cell,
1350 palette: colour_palette,
1351
1352 pipe_fd: i32,
1353 pipe_event: *mut bufferevent,
1354 pipe_offset: window_pane_offset,
1355
1356 screen: *mut screen,
1357 base: screen,
1358
1359 status_screen: screen,
1360 status_size: usize,
1361
1362 modes: tailq_head<window_mode_entry>,
1363
1364 searchstr: *mut u8,
1365 searchregex: i32,
1366
1367 border_gc_set: i32,
1368 border_gc: grid_cell,
1369
1370 control_bg: i32,
1371 control_fg: i32,
1372
1373 entry: tailq_entry<window_pane>,
1375 sentry: tailq_entry<window_pane>,
1377 tree_entry: rb_entry<window_pane>,
1378}
1379type window_panes = tailq_head<window_pane>;
1380type window_pane_tree = rb_head<window_pane>;
1381
1382impl Entry<window_pane, discr_entry> for window_pane {
1383 unsafe fn entry(this: *mut Self) -> *mut tailq_entry<window_pane> {
1384 unsafe { &raw mut (*this).entry }
1385 }
1386}
1387impl Entry<window_pane, discr_sentry> for window_pane {
1388 unsafe fn entry(this: *mut Self) -> *mut tailq_entry<window_pane> {
1389 unsafe { &raw mut (*this).sentry }
1390 }
1391}
1392
1393bitflags::bitflags! {
1394 #[repr(transparent)]
1395 #[derive(Copy, Clone, Eq, PartialEq)]
1396 struct window_flag: i32 {
1397 const BELL = 0x1;
1398 const ACTIVITY = 0x2;
1399 const SILENCE = 0x4;
1400 const ZOOMED = 0x8;
1401 const WASZOOMED = 0x10;
1402 const RESIZE = 0x20;
1403 }
1404}
1405const WINDOW_ALERTFLAGS: window_flag = window_flag::BELL
1406 .union(window_flag::ACTIVITY)
1407 .union(window_flag::SILENCE);
1408
1409#[repr(C)]
1411struct window {
1412 id: u32,
1413 latest: *mut c_void,
1414
1415 name: *mut u8,
1416 name_event: event,
1417 name_time: timeval,
1418
1419 alerts_timer: event,
1420 offset_timer: event,
1421
1422 activity_time: timeval,
1423
1424 active: *mut window_pane,
1425 last_panes: window_panes,
1426 panes: window_panes,
1427
1428 lastlayout: i32,
1429 layout_root: *mut layout_cell,
1430 saved_layout_root: *mut layout_cell,
1431 old_layout: *mut u8,
1432
1433 sx: u32,
1434 sy: u32,
1435 manual_sx: u32,
1436 manual_sy: u32,
1437 xpixel: u32,
1438 ypixel: u32,
1439
1440 new_sx: u32,
1441 new_sy: u32,
1442 new_xpixel: u32,
1443 new_ypixel: u32,
1444
1445 fill_character: *mut utf8_data,
1446 flags: window_flag,
1447
1448 alerts_queued: i32,
1449 alerts_entry: tailq_entry<window>,
1450
1451 options: *mut options,
1452
1453 references: u32,
1454 winlinks: tailq_head<winlink>,
1455 entry: rb_entry<window>,
1456}
1457type windows = rb_head<window>;
1458impl crate::compat::queue::Entry<window, discr_alerts_entry> for window {
1461 unsafe fn entry(this: *mut Self) -> *mut tailq_entry<window> {
1462 unsafe { &raw mut (*this).alerts_entry }
1463 }
1464}
1465
1466bitflags::bitflags! {
1467 #[repr(transparent)]
1468 #[derive(Copy, Clone, Eq, PartialEq)]
1469 struct winlink_flags: i32 {
1470 const WINLINK_BELL = 0x1;
1471 const WINLINK_ACTIVITY = 0x2;
1472 const WINLINK_SILENCE = 0x4;
1473 const WINLINK_VISITED = 0x8;
1474 }
1475}
1476const WINLINK_ALERTFLAGS: winlink_flags = winlink_flags::WINLINK_BELL
1477 .union(winlink_flags::WINLINK_ACTIVITY)
1478 .union(winlink_flags::WINLINK_SILENCE);
1479
1480#[repr(C)]
1481#[derive(Copy, Clone)]
1482struct winlink {
1483 idx: i32,
1484 session: *mut session,
1485 window: *mut window,
1486
1487 flags: winlink_flags,
1488
1489 entry: rb_entry<winlink>,
1490
1491 wentry: tailq_entry<winlink>,
1492 sentry: tailq_entry<winlink>,
1493}
1494
1495impl crate::compat::queue::Entry<winlink, discr_wentry> for winlink {
1496 unsafe fn entry(this: *mut Self) -> *mut tailq_entry<winlink> {
1497 unsafe { &raw mut (*this).wentry }
1498 }
1499}
1500
1501impl crate::compat::queue::Entry<winlink, discr_sentry> for winlink {
1502 unsafe fn entry(this: *mut Self) -> *mut tailq_entry<winlink> {
1503 unsafe { &raw mut (*this).sentry }
1504 }
1505}
1506
1507type winlinks = rb_head<winlink>;
1508type winlink_stack = tailq_head<winlink>;
1510#[repr(i32)]
1514#[derive(Copy, Clone, Eq, PartialEq, num_enum::TryFromPrimitive)]
1515enum window_size_option {
1516 WINDOW_SIZE_LARGEST,
1517 WINDOW_SIZE_SMALLEST,
1518 WINDOW_SIZE_MANUAL,
1519 WINDOW_SIZE_LATEST,
1520}
1521
1522#[repr(i32)]
1524#[derive(Copy, Clone, Eq, PartialEq, num_enum::TryFromPrimitive)]
1525enum pane_status {
1526 PANE_STATUS_OFF,
1527 PANE_STATUS_TOP,
1528 PANE_STATUS_BOTTOM,
1529}
1530
1531#[repr(i32)]
1533#[derive(Copy, Clone, Eq, PartialEq)]
1534enum layout_type {
1535 LAYOUT_LEFTRIGHT,
1536 LAYOUT_TOPBOTTOM,
1537 LAYOUT_WINDOWPANE,
1538}
1539
1540type layout_cells = tailq_head<layout_cell>;
1542
1543crate::compat::impl_tailq_entry!(layout_cell, entry, tailq_entry<layout_cell>);
1545#[repr(C)]
1546struct layout_cell {
1547 type_: layout_type,
1548
1549 parent: *mut layout_cell,
1550
1551 sx: u32,
1552 sy: u32,
1553
1554 xoff: u32,
1555 yoff: u32,
1556
1557 wp: *mut window_pane,
1558 cells: layout_cells,
1559
1560 entry: tailq_entry<layout_cell>,
1561}
1562
1563const ENVIRON_HIDDEN: i32 = 0x1;
1564
1565#[repr(C)]
1567struct environ_entry {
1568 name: Option<NonNull<u8>>,
1569 value: Option<NonNull<u8>>,
1570
1571 flags: i32,
1572 entry: rb_entry<environ_entry>,
1573}
1574
1575#[repr(C)]
1577struct session_group {
1578 name: *const u8,
1579 sessions: tailq_head<session>,
1580
1581 entry: rb_entry<session_group>,
1582}
1583type session_groups = rb_head<session_group>;
1584
1585const SESSION_PASTING: i32 = 0x1;
1586const SESSION_ALERTED: i32 = 0x2;
1587
1588#[repr(C)]
1589struct session {
1590 id: u32,
1591 name: *mut u8,
1592 cwd: *mut u8,
1593
1594 creation_time: timeval,
1595 last_attached_time: timeval,
1596 activity_time: timeval,
1597 last_activity_time: timeval,
1598
1599 lock_timer: event,
1600
1601 curw: *mut winlink,
1602 lastw: winlink_stack,
1603 windows: winlinks,
1604
1605 statusat: i32,
1606 statuslines: u32,
1607
1608 options: *mut options,
1609
1610 flags: i32,
1611
1612 attached: u32,
1613
1614 tio: *mut termios,
1615
1616 environ: *mut environ,
1617
1618 references: i32,
1619
1620 gentry: tailq_entry<session>,
1621 entry: rb_entry<session>,
1622}
1623type sessions = rb_head<session>;
1624crate::compat::impl_tailq_entry!(session, gentry, tailq_entry<session>);
1625
1626const MOUSE_MASK_BUTTONS: u32 = 195;
1627const MOUSE_MASK_SHIFT: u32 = 4;
1628const MOUSE_MASK_META: u32 = 8;
1629const MOUSE_MASK_CTRL: u32 = 16;
1630const MOUSE_MASK_DRAG: u32 = 32;
1631const MOUSE_MASK_MODIFIERS: u32 = MOUSE_MASK_SHIFT | MOUSE_MASK_META | MOUSE_MASK_CTRL;
1632
1633const MOUSE_WHEEL_UP: u32 = 64;
1635const MOUSE_WHEEL_DOWN: u32 = 65;
1636
1637const MOUSE_BUTTON_1: u32 = 0;
1639const MOUSE_BUTTON_2: u32 = 1;
1640const MOUSE_BUTTON_3: u32 = 2;
1641const MOUSE_BUTTON_6: u32 = 66;
1642const MOUSE_BUTTON_7: u32 = 67;
1643const MOUSE_BUTTON_8: u32 = 128;
1644const MOUSE_BUTTON_9: u32 = 129;
1645const MOUSE_BUTTON_10: u32 = 130;
1646const MOUSE_BUTTON_11: u32 = 131;
1647
1648#[allow(non_snake_case)]
1650#[inline]
1651fn MOUSE_BUTTONS(b: u32) -> u32 {
1652 b & MOUSE_MASK_BUTTONS
1653}
1654#[allow(non_snake_case)]
1655#[inline]
1656fn MOUSE_WHEEL(b: u32) -> bool {
1657 ((b) & MOUSE_MASK_BUTTONS) == MOUSE_WHEEL_UP || ((b) & MOUSE_MASK_BUTTONS) == MOUSE_WHEEL_DOWN
1658}
1659#[allow(non_snake_case)]
1660#[inline]
1661fn MOUSE_DRAG(b: u32) -> bool {
1662 b & MOUSE_MASK_DRAG != 0
1663}
1664#[allow(non_snake_case)]
1665#[inline]
1666fn MOUSE_RELEASE(b: u32) -> bool {
1667 b & MOUSE_MASK_BUTTONS == 3
1668}
1669
1670#[repr(C)]
1672#[derive(Copy, Clone)]
1673struct mouse_event {
1674 valid: i32,
1675 ignore: i32,
1676
1677 key: key_code,
1678
1679 statusat: i32,
1680 statuslines: u32,
1681
1682 x: u32,
1683 y: u32,
1684 b: u32,
1685
1686 lx: u32,
1687 ly: u32,
1688 lb: u32,
1689
1690 ox: u32,
1691 oy: u32,
1692
1693 s: i32,
1694 w: i32,
1695 wp: i32,
1696
1697 sgr_type: u32,
1698 sgr_b: u32,
1699}
1700
1701#[repr(C)]
1703struct key_event {
1704 key: key_code,
1705 m: mouse_event,
1706}
1707
1708bitflags::bitflags! {
1709 #[repr(transparent)]
1710 #[derive(Copy, Clone)]
1711 struct term_flags: i32 {
1712 const TERM_256COLOURS = 0x1;
1713 const TERM_NOAM = 0x2;
1714 const TERM_DECSLRM = 0x4;
1715 const TERM_DECFRA = 0x8;
1716 const TERM_RGBCOLOURS = 0x10;
1717 const TERM_VT100LIKE = 0x20;
1718 const TERM_SIXEL = 0x40;
1719 }
1720}
1721
1722#[repr(C)]
1724struct tty_term {
1725 name: *mut u8,
1726 tty: *mut tty,
1727 features: i32,
1728
1729 acs: [[u8; 2]; c_uchar::MAX as usize + 1],
1730
1731 codes: *mut tty_code,
1732
1733 flags: term_flags,
1734
1735 entry: list_entry<tty_term>,
1736}
1737type tty_terms = list_head<tty_term>;
1738impl ListEntry<tty_term, discr_entry> for tty_term {
1739 unsafe fn field(this: *mut Self) -> *mut list_entry<tty_term> {
1740 unsafe { &raw mut (*this).entry }
1741 }
1742}
1743
1744bitflags::bitflags! {
1745 #[repr(transparent)]
1746 #[derive(Copy, Clone)]
1747 struct tty_flags: i32 {
1748 const TTY_NOCURSOR = 0x1;
1749 const TTY_FREEZE = 0x2;
1750 const TTY_TIMER = 0x4;
1751 const TTY_NOBLOCK = 0x8;
1752 const TTY_STARTED = 0x10;
1753 const TTY_OPENED = 0x20;
1754 const TTY_OSC52QUERY = 0x40;
1755 const TTY_BLOCK = 0x80;
1756 const TTY_HAVEDA = 0x100; const TTY_HAVEXDA = 0x200;
1758 const TTY_SYNCING = 0x400;
1759 const TTY_HAVEDA2 = 0x800; }
1761}
1762const TTY_ALL_REQUEST_FLAGS: tty_flags = tty_flags::TTY_HAVEDA
1763 .union(tty_flags::TTY_HAVEDA2)
1764 .union(tty_flags::TTY_HAVEXDA);
1765
1766#[repr(C)]
1768struct tty {
1769 client: *mut client,
1770 start_timer: event,
1771 clipboard_timer: event,
1772 last_requests: time_t,
1773
1774 sx: u32,
1775 sy: u32,
1776
1777 xpixel: u32,
1778 ypixel: u32,
1779
1780 cx: u32,
1781 cy: u32,
1782 cstyle: screen_cursor_style,
1783 ccolour: i32,
1784
1785 oflag: i32,
1786 oox: u32,
1787 ooy: u32,
1788 osx: u32,
1789 osy: u32,
1790
1791 mode: mode_flag,
1792 fg: i32,
1793 bg: i32,
1794
1795 rlower: u32,
1796 rupper: u32,
1797
1798 rleft: u32,
1799 rright: u32,
1800
1801 event_in: event,
1802 in_: *mut evbuffer,
1803 event_out: event,
1804 out: *mut evbuffer,
1805 timer: event,
1806 discarded: usize,
1807
1808 tio: termios,
1809
1810 cell: grid_cell,
1811 last_cell: grid_cell,
1812
1813 flags: tty_flags,
1814
1815 term: *mut tty_term,
1816
1817 mouse_last_x: u32,
1818 mouse_last_y: u32,
1819 mouse_last_b: u32,
1820 mouse_drag_flag: i32,
1821 mouse_drag_update: Option<unsafe fn(*mut client, *mut mouse_event)>,
1822 mouse_drag_release: Option<unsafe fn(*mut client, *mut mouse_event)>,
1823
1824 key_timer: event,
1825 key_tree: *mut tty_key,
1826}
1827
1828type tty_ctx_redraw_cb = Option<unsafe fn(*const tty_ctx)>;
1829type tty_ctx_set_client_cb = Option<unsafe fn(*mut tty_ctx, *mut client) -> i32>;
1830
1831#[repr(C)]
1832struct tty_ctx {
1833 s: *mut screen,
1834
1835 redraw_cb: tty_ctx_redraw_cb,
1836 set_client_cb: tty_ctx_set_client_cb,
1837 arg: *mut c_void,
1838
1839 cell: *const grid_cell,
1840 wrapped: i32,
1841
1842 num: u32,
1843 ptr: *mut c_void,
1844 ptr2: *mut c_void,
1845
1846 allow_invisible_panes: i32,
1847
1848 ocx: u32,
1854 ocy: u32,
1855
1856 orupper: u32,
1857 orlower: u32,
1858
1859 xoff: u32,
1861 yoff: u32,
1862 rxoff: u32,
1863 ryoff: u32,
1864 sx: u32,
1865 sy: u32,
1866
1867 bg: u32,
1869
1870 defaults: grid_cell,
1872 palette: *const colour_palette,
1873
1874 bigger: i32,
1876 wox: u32,
1877 woy: u32,
1878 wsx: u32,
1879 wsy: u32,
1880}
1881
1882crate::compat::impl_tailq_entry!(message_entry, entry, tailq_entry<message_entry>);
1884#[repr(C)]
1886struct message_entry {
1887 msg: *mut u8,
1888 msg_num: u32,
1889 msg_time: timeval,
1890
1891 entry: tailq_entry<message_entry>,
1893}
1894type message_list = tailq_head<message_entry>;
1895
1896#[repr(i32)]
1898#[derive(Copy, Clone, Eq, PartialEq)]
1899enum args_type {
1900 ARGS_NONE,
1901 ARGS_STRING,
1902 ARGS_COMMANDS,
1903}
1904
1905#[repr(C)]
1906union args_value_union {
1907 string: *mut u8,
1908 cmdlist: *mut cmd_list,
1909}
1910
1911crate::compat::impl_tailq_entry!(args_value, entry, tailq_entry<args_value>);
1913#[repr(C)]
1915struct args_value {
1916 type_: args_type,
1917 union_: args_value_union,
1918 cached: *mut u8,
1919 entry: tailq_entry<args_value>,
1921}
1922type args_tree = rb_head<args_entry>;
1923
1924#[repr(C)]
1926#[derive(Copy, Clone, Eq, PartialEq)]
1927enum args_parse_type {
1928 ARGS_PARSE_INVALID,
1929 ARGS_PARSE_STRING,
1930 ARGS_PARSE_COMMANDS_OR_STRING,
1931 ARGS_PARSE_COMMANDS,
1932}
1933
1934type args_parse_cb = Option<unsafe fn(*mut args, u32, *mut *mut u8) -> args_parse_type>;
1935#[repr(C)]
1936struct args_parse {
1937 template: SyncCharPtr,
1938 lower: i32,
1939 upper: i32,
1940 cb: args_parse_cb,
1941}
1942
1943impl args_parse {
1944 const fn new(template: &'static CStr, lower: i32, upper: i32, cb: args_parse_cb) -> Self {
1945 Self {
1946 template: SyncCharPtr::new(template),
1947 lower,
1948 upper,
1949 cb,
1950 }
1951 }
1952}
1953
1954#[repr(C)]
1956#[derive(Copy, Clone, Default)]
1957enum cmd_find_type {
1958 #[default]
1959 CMD_FIND_PANE,
1960 CMD_FIND_WINDOW,
1961 CMD_FIND_SESSION,
1962}
1963
1964#[repr(C)]
1965#[derive(Copy, Clone)]
1966struct cmd_find_state {
1967 flags: i32,
1968 current: *mut cmd_find_state,
1969
1970 s: *mut session,
1971 wl: *mut winlink,
1972 w: *mut window,
1973 wp: *mut window_pane,
1974 idx: i32,
1975}
1976
1977const CMD_FIND_PREFER_UNATTACHED: i32 = 0x1;
1979const CMD_FIND_QUIET: i32 = 0x2;
1980const CMD_FIND_WINDOW_INDEX: i32 = 0x4;
1981const CMD_FIND_DEFAULT_MARKED: i32 = 0x8;
1982const CMD_FIND_EXACT_SESSION: i32 = 0x10;
1983const CMD_FIND_EXACT_WINDOW: i32 = 0x20;
1984const CMD_FIND_CANFAIL: i32 = 0x40;
1985
1986#[repr(C)]
1988struct cmd_list {
1989 references: i32,
1990 group: u32,
1991 list: *mut cmds,
1992}
1993
1994#[repr(i32)]
1996#[derive(Copy, Clone, Eq, PartialEq)]
1997enum cmd_retval {
1998 CMD_RETURN_ERROR = -1,
1999 CMD_RETURN_NORMAL = 0,
2000 CMD_RETURN_WAIT,
2001 CMD_RETURN_STOP,
2002}
2003
2004#[repr(i32)]
2006#[derive(Copy, Clone, Default, Eq, PartialEq)]
2007enum cmd_parse_status {
2008 #[default]
2009 CMD_PARSE_ERROR,
2010 CMD_PARSE_SUCCESS,
2011}
2012
2013type cmd_parse_result = Result<*mut cmd_list , *mut u8 >;
2014
2015bitflags::bitflags! {
2016 #[repr(transparent)]
2017 #[derive(Copy, Clone, Eq, PartialEq)]
2018 struct cmd_parse_input_flags: i32 {
2019 const CMD_PARSE_QUIET = 0x1;
2020 const CMD_PARSE_PARSEONLY = 0x2;
2021 const CMD_PARSE_NOALIAS = 0x4;
2022 const CMD_PARSE_VERBOSE = 0x8;
2023 const CMD_PARSE_ONEGROUP = 0x10;
2024 }
2025}
2026
2027#[repr(transparent)]
2028struct AtomicCmdParseInputFlags(std::sync::atomic::AtomicI32);
2029impl From<cmd_parse_input_flags> for AtomicCmdParseInputFlags {
2030 fn from(value: cmd_parse_input_flags) -> Self {
2031 Self(std::sync::atomic::AtomicI32::new(value.bits()))
2032 }
2033}
2034impl AtomicCmdParseInputFlags {
2035 fn intersects(&self, rhs: cmd_parse_input_flags) -> bool {
2036 cmd_parse_input_flags::from_bits(self.0.load(std::sync::atomic::Ordering::SeqCst))
2037 .unwrap()
2038 .intersects(rhs)
2039 }
2040}
2041impl std::ops::BitOrAssign<cmd_parse_input_flags> for &AtomicCmdParseInputFlags {
2042 fn bitor_assign(&mut self, rhs: cmd_parse_input_flags) {
2043 self.0
2044 .fetch_or(rhs.bits(), std::sync::atomic::Ordering::SeqCst);
2045 }
2046}
2047impl std::ops::BitAndAssign<cmd_parse_input_flags> for &AtomicCmdParseInputFlags {
2048 fn bitand_assign(&mut self, rhs: cmd_parse_input_flags) {
2049 self.0
2050 .fetch_and(rhs.bits(), std::sync::atomic::Ordering::SeqCst);
2051 }
2052}
2053
2054#[repr(C)]
2055struct cmd_parse_input<'a> {
2056 flags: AtomicCmdParseInputFlags,
2057
2058 file: Option<&'a str>,
2059 line: AtomicU32, item: *mut cmdq_item,
2062 c: *mut client,
2063 fs: cmd_find_state,
2064}
2065
2066bitflags::bitflags! {
2068 #[repr(transparent)]
2069 #[derive(Copy, Clone, Eq, PartialEq)]
2070 struct cmdq_state_flags: i32 {
2071 const CMDQ_STATE_REPEAT = 0x1;
2072 const CMDQ_STATE_CONTROL = 0x2;
2073 const CMDQ_STATE_NOHOOKS = 0x4;
2074 }
2075}
2076
2077type cmdq_cb = Option<unsafe fn(*mut cmdq_item, *mut c_void) -> cmd_retval>;
2079
2080#[repr(C)]
2082#[derive(Copy, Clone, Default)]
2083struct cmd_entry_flag {
2084 flag: u8,
2085 type_: cmd_find_type,
2086 flags: i32,
2087}
2088
2089impl cmd_entry_flag {
2090 const fn new(flag: u8, type_: cmd_find_type, flags: i32) -> Self {
2091 Self { flag, type_, flags }
2092 }
2093
2094 const fn zeroed() -> Self {
2095 Self {
2096 flag: b'\0',
2097 type_: cmd_find_type::CMD_FIND_PANE,
2098 flags: 0,
2099 }
2100 }
2101}
2102
2103bitflags::bitflags! {
2104 #[repr(transparent)]
2105 #[derive(Copy, Clone, Eq, PartialEq)]
2106 struct cmd_flag: i32 {
2107 const CMD_STARTSERVER = 0x1;
2108 const CMD_READONLY = 0x2;
2109 const CMD_AFTERHOOK = 0x4;
2110 const CMD_CLIENT_CFLAG = 0x8;
2111 const CMD_CLIENT_TFLAG = 0x10;
2112 const CMD_CLIENT_CANFAIL = 0x20;
2113 }
2114}
2115
2116#[repr(C)]
2118struct cmd_entry {
2119 name: SyncCharPtr,
2120 alias: SyncCharPtr,
2121
2122 args: args_parse,
2123 usage: SyncCharPtr,
2124
2125 source: cmd_entry_flag,
2126 target: cmd_entry_flag,
2127
2128 flags: cmd_flag,
2129
2130 exec: unsafe fn(*mut cmd, *mut cmdq_item) -> cmd_retval,
2131}
2132
2133const STATUS_LINES_LIMIT: usize = 5;
2135#[repr(C)]
2136struct status_line_entry {
2137 expanded: *mut u8,
2138 ranges: style_ranges,
2139}
2140#[repr(C)]
2141struct status_line {
2142 timer: event,
2143
2144 screen: screen,
2145 active: *mut screen,
2146 references: c_int,
2147
2148 style: grid_cell,
2149 entries: [status_line_entry; STATUS_LINES_LIMIT],
2150}
2151
2152const PROMPT_NTYPES: u32 = 4;
2154#[repr(u32)]
2155#[derive(Copy, Clone, Eq, PartialEq, num_enum::TryFromPrimitive)]
2156enum prompt_type {
2157 PROMPT_TYPE_COMMAND,
2158 PROMPT_TYPE_SEARCH,
2159 PROMPT_TYPE_TARGET,
2160 PROMPT_TYPE_WINDOW_TARGET,
2161 PROMPT_TYPE_INVALID = 0xff,
2162}
2163
2164type client_file_cb = Option<unsafe fn(*mut client, *mut u8, i32, i32, *mut evbuffer, *mut c_void)>;
2166#[repr(C)]
2167struct client_file {
2168 c: *mut client,
2169 peer: *mut tmuxpeer,
2170 tree: *mut client_files,
2171
2172 references: i32,
2173 stream: i32,
2174
2175 path: *mut u8,
2176 buffer: *mut evbuffer,
2177 event: *mut bufferevent,
2178
2179 fd: i32,
2180 error: i32,
2181 closed: i32,
2182
2183 cb: client_file_cb,
2184 data: *mut c_void,
2185
2186 entry: rb_entry<client_file>,
2187}
2188type client_files = rb_head<client_file>;
2189RB_GENERATE!(client_files, client_file, entry, discr_entry, file_cmp);
2190
2191#[repr(C)]
2193struct client_window {
2194 window: u32,
2195 pane: *mut window_pane,
2196
2197 sx: u32,
2198 sy: u32,
2199
2200 entry: rb_entry<client_window>,
2201}
2202type client_windows = rb_head<client_window>;
2203RB_GENERATE!(
2204 client_windows,
2205 client_window,
2206 entry,
2207 discr_entry,
2208 server_client_window_cmp
2209);
2210
2211const OVERLAY_MAX_RANGES: usize = 3;
2213#[repr(C)]
2214struct overlay_ranges {
2215 px: [u32; OVERLAY_MAX_RANGES],
2216 nx: [u32; OVERLAY_MAX_RANGES],
2217}
2218
2219type prompt_input_cb = Option<unsafe fn(*mut client, NonNull<c_void>, *const u8, i32) -> i32>;
2220type prompt_free_cb = Option<unsafe fn(NonNull<c_void>)>;
2221type overlay_check_cb =
2222 Option<unsafe fn(*mut client, *mut c_void, u32, u32, u32, *mut overlay_ranges)>;
2223type overlay_mode_cb =
2224 Option<unsafe fn(*mut client, *mut c_void, *mut u32, *mut u32) -> *mut screen>;
2225type overlay_draw_cb = Option<unsafe fn(*mut client, *mut c_void, *mut screen_redraw_ctx)>;
2226type overlay_key_cb = Option<unsafe fn(*mut client, *mut c_void, *mut key_event) -> i32>;
2227type overlay_free_cb = Option<unsafe fn(*mut client, *mut c_void)>;
2228type overlay_resize_cb = Option<unsafe fn(*mut client, *mut c_void)>;
2229
2230bitflags::bitflags! {
2231 #[repr(transparent)]
2232 #[derive(Copy, Clone, Eq, PartialEq)]
2233 struct client_flag: u64 {
2234 const TERMINAL = 0x0000000001u64;
2235 const LOGIN = 0x0000000002u64;
2236 const EXIT = 0x0000000004u64;
2237 const REDRAWWINDOW = 0x0000000008u64;
2238 const REDRAWSTATUS = 0x0000000010u64;
2239 const REPEAT = 0x0000000020u64;
2240 const SUSPENDED = 0x0000000040u64;
2241 const ATTACHED = 0x0000000080u64;
2242 const EXITED = 0x0000000100u64;
2243 const DEAD = 0x0000000200u64;
2244 const REDRAWBORDERS = 0x0000000400u64;
2245 const READONLY = 0x0000000800u64;
2246 const NOSTARTSERVER = 0x0000001000u64;
2247 const CONTROL = 0x0000002000u64;
2248 const CONTROLCONTROL = 0x0000004000u64;
2249 const FOCUSED = 0x0000008000u64;
2250 const UTF8 = 0x0000010000u64;
2251 const IGNORESIZE = 0x0000020000u64;
2252 const IDENTIFIED = 0x0000040000u64;
2253 const STATUSFORCE = 0x0000080000u64;
2254 const DOUBLECLICK = 0x0000100000u64;
2255 const TRIPLECLICK = 0x0000200000u64;
2256 const SIZECHANGED = 0x0000400000u64;
2257 const STATUSOFF = 0x0000800000u64;
2258 const REDRAWSTATUSALWAYS = 0x0001000000u64;
2259 const REDRAWOVERLAY = 0x0002000000u64;
2260 const CONTROL_NOOUTPUT = 0x0004000000u64;
2261 const DEFAULTSOCKET = 0x0008000000u64;
2262 const STARTSERVER = 0x0010000000u64;
2263 const REDRAWPANES = 0x0020000000u64;
2264 const NOFORK = 0x0040000000u64;
2265 const ACTIVEPANE = 0x0080000000u64;
2266 const CONTROL_PAUSEAFTER = 0x0100000000u64;
2267 const CONTROL_WAITEXIT = 0x0200000000u64;
2268 const WINDOWSIZECHANGED = 0x0400000000u64;
2269 const CLIPBOARDBUFFER = 0x0800000000u64;
2270 const BRACKETPASTING = 0x1000000000u64;
2271 }
2272}
2273
2274const CLIENT_ALLREDRAWFLAGS: client_flag = client_flag::REDRAWWINDOW
2275 .union(client_flag::REDRAWSTATUS)
2276 .union(client_flag::REDRAWSTATUSALWAYS)
2277 .union(client_flag::REDRAWBORDERS)
2278 .union(client_flag::REDRAWOVERLAY)
2279 .union(client_flag::REDRAWPANES);
2280const CLIENT_UNATTACHEDFLAGS: client_flag = client_flag::DEAD
2281 .union(client_flag::SUSPENDED)
2282 .union(client_flag::EXIT);
2283const CLIENT_NODETACHFLAGS: client_flag = client_flag::DEAD.union(client_flag::EXIT);
2284const CLIENT_NOSIZEFLAGS: client_flag = client_flag::DEAD
2285 .union(client_flag::SUSPENDED)
2286 .union(client_flag::EXIT);
2287
2288const PROMPT_SINGLE: i32 = 0x1;
2289const PROMPT_NUMERIC: i32 = 0x2;
2290const PROMPT_INCREMENTAL: i32 = 0x4;
2291const PROMPT_NOFORMAT: i32 = 0x8;
2292const PROMPT_KEY: i32 = 0x8;
2293
2294crate::compat::impl_tailq_entry!(client, entry, tailq_entry<client>);
2296#[repr(C)]
2298struct client {
2299 name: *const u8,
2300 peer: *mut tmuxpeer,
2301 queue: *mut cmdq_list,
2302
2303 windows: client_windows,
2304
2305 control_state: *mut control_state,
2306 pause_age: c_uint,
2307
2308 pid: pid_t,
2309 fd: c_int,
2310 out_fd: c_int,
2311 event: event,
2312 retval: c_int,
2313
2314 creation_time: timeval,
2315 activity_time: timeval,
2316
2317 environ: *mut environ,
2318 jobs: *mut format_job_tree,
2319
2320 title: *mut u8,
2321 path: *mut u8,
2322 cwd: *const u8,
2323
2324 term_name: *mut u8,
2325 term_features: c_int,
2326 term_type: *mut u8,
2327 term_caps: *mut *mut u8,
2328 term_ncaps: c_uint,
2329
2330 ttyname: *mut u8,
2331 tty: tty,
2332
2333 written: usize,
2334 discarded: usize,
2335 redraw: usize,
2336
2337 repeat_timer: event,
2338
2339 click_timer: event,
2340 click_button: c_uint,
2341 click_event: mouse_event,
2342
2343 status: status_line,
2344
2345 flags: client_flag,
2346
2347 exit_type: exit_type,
2348 exit_msgtype: msgtype,
2349 exit_session: *mut u8,
2350 exit_message: *mut u8,
2351
2352 keytable: *mut key_table,
2353
2354 redraw_panes: u64,
2355
2356 message_ignore_keys: c_int,
2357 message_ignore_styles: c_int,
2358 message_string: *mut u8,
2359 message_timer: event,
2360
2361 prompt_string: *mut u8,
2362 prompt_buffer: *mut utf8_data,
2363 prompt_last: *mut u8,
2364 prompt_index: usize,
2365 prompt_inputcb: prompt_input_cb,
2366 prompt_freecb: prompt_free_cb,
2367 prompt_data: *mut c_void,
2368 prompt_hindex: [c_uint; 4],
2369 prompt_mode: prompt_mode,
2370 prompt_saved: *mut utf8_data,
2371
2372 prompt_flags: c_int,
2373 prompt_type: prompt_type,
2374 prompt_cursor: c_int,
2375
2376 session: *mut session,
2377 last_session: *mut session,
2378
2379 references: c_int,
2380
2381 pan_window: *mut c_void,
2382 pan_ox: c_uint,
2383 pan_oy: c_uint,
2384
2385 overlay_check: overlay_check_cb,
2386 overlay_mode: overlay_mode_cb,
2387 overlay_draw: overlay_draw_cb,
2388 overlay_key: overlay_key_cb,
2389 overlay_free: overlay_free_cb,
2390 overlay_resize: overlay_resize_cb,
2391 overlay_data: *mut c_void,
2392 overlay_timer: event,
2393
2394 files: client_files,
2395
2396 clipboard_panes: *mut c_uint,
2397 clipboard_npanes: c_uint,
2398
2399 entry: tailq_entry<client>,
2401}
2402type clients = tailq_head<client>;
2403
2404#[repr(i32)]
2406enum control_sub_type {
2407 CONTROL_SUB_SESSION,
2408 CONTROL_SUB_PANE,
2409 CONTROL_SUB_ALL_PANES,
2410 CONTROL_SUB_WINDOW,
2411 CONTROL_SUB_ALL_WINDOWS,
2412}
2413
2414const KEY_BINDING_REPEAT: i32 = 0x1;
2415
2416#[repr(C)]
2418struct key_binding {
2419 key: key_code,
2420 cmdlist: *mut cmd_list,
2421 note: *mut u8,
2422
2423 flags: i32,
2424
2425 entry: rb_entry<key_binding>,
2426}
2427type key_bindings = rb_head<key_binding>;
2428
2429#[repr(C)]
2430struct key_table {
2431 name: *mut u8,
2432 activity_time: timeval,
2433 key_bindings: key_bindings,
2434 default_key_bindings: key_bindings,
2435
2436 references: u32,
2437
2438 entry: rb_entry<key_table>,
2439}
2440type key_tables = rb_head<key_table>;
2441
2442type options_array = rb_head<options_array_item>;
2444
2445#[repr(C)]
2446#[derive(Copy, Clone)]
2447union options_value {
2448 string: *mut u8,
2449 number: c_longlong,
2450 style: style,
2451 array: options_array,
2452 cmdlist: *mut cmd_list,
2453}
2454
2455#[repr(i32)]
2457#[derive(Clone, Copy, PartialEq, Eq)]
2458enum options_table_type {
2459 OPTIONS_TABLE_STRING,
2460 OPTIONS_TABLE_NUMBER,
2461 OPTIONS_TABLE_KEY,
2462 OPTIONS_TABLE_COLOUR,
2463 OPTIONS_TABLE_FLAG,
2464 OPTIONS_TABLE_CHOICE,
2465 OPTIONS_TABLE_COMMAND,
2466}
2467
2468const OPTIONS_TABLE_NONE: i32 = 0;
2469const OPTIONS_TABLE_SERVER: i32 = 0x1;
2470const OPTIONS_TABLE_SESSION: i32 = 0x2;
2471const OPTIONS_TABLE_WINDOW: i32 = 0x4;
2472const OPTIONS_TABLE_PANE: i32 = 0x8;
2473
2474const OPTIONS_TABLE_IS_ARRAY: i32 = 0x1;
2475const OPTIONS_TABLE_IS_HOOK: i32 = 0x2;
2476const OPTIONS_TABLE_IS_STYLE: i32 = 0x4;
2477
2478#[repr(C)]
2479struct options_table_entry {
2480 name: *const u8,
2481 alternative_name: *mut u8,
2482 type_: options_table_type,
2483 scope: i32,
2484 flags: i32,
2485 minimum: u32,
2486 maximum: u32,
2487
2488 choices: *const *const u8,
2489
2490 default_str: Option<&'static str>,
2491 default_num: c_longlong,
2492 default_arr: *const *const u8,
2493
2494 separator: *const u8,
2495 pattern: *const u8,
2496
2497 text: *const u8,
2498 unit: *const u8,
2499}
2500
2501#[repr(C)]
2502struct options_name_map {
2503 from: *const u8,
2504 to: *const u8,
2505}
2506impl options_name_map {
2507 const fn new(from: *const u8, to: *const u8) -> Self {
2508 Self { from, to }
2509 }
2510}
2511
2512const CMD_TARGET_PANE_USAGE: &CStr = c"[-t target-pane]";
2514const CMD_TARGET_WINDOW_USAGE: &CStr = c"[-t target-window]";
2515const CMD_TARGET_SESSION_USAGE: &CStr = c"[-t target-session]";
2516const CMD_TARGET_CLIENT_USAGE: &CStr = c"[-t target-client]";
2517const CMD_SRCDST_PANE_USAGE: &CStr = c"[-s src-pane] [-t dst-pane]";
2518const CMD_SRCDST_WINDOW_USAGE: &CStr = c"[-s src-window] [-t dst-window]";
2519const CMD_SRCDST_SESSION_USAGE: &CStr = c"[-s src-session] [-t dst-session]";
2520const CMD_SRCDST_CLIENT_USAGE: &CStr = c"[-s src-client] [-t dst-client]";
2521const CMD_BUFFER_USAGE: &CStr = c"[-b buffer-name]";
2522
2523const SPAWN_KILL: i32 = 0x1;
2524const SPAWN_DETACHED: i32 = 0x2;
2525const SPAWN_RESPAWN: i32 = 0x4;
2526const SPAWN_BEFORE: i32 = 0x8;
2527const SPAWN_NONOTIFY: i32 = 0x10;
2528const SPAWN_FULLSIZE: i32 = 0x20;
2529const SPAWN_EMPTY: i32 = 0x40;
2530const SPAWN_ZOOM: i32 = 0x80;
2531
2532#[repr(C)]
2534struct spawn_context {
2535 item: *mut cmdq_item,
2536
2537 s: *mut session,
2538 wl: *mut winlink,
2539 tc: *mut client,
2540
2541 wp0: *mut window_pane,
2542 lc: *mut layout_cell,
2543
2544 name: *const u8,
2545 argv: *mut *mut u8,
2546 argc: i32,
2547 environ: *mut environ,
2548
2549 idx: i32,
2550 cwd: *const u8,
2551
2552 flags: i32,
2553}
2554
2555#[repr(C)]
2557struct mode_tree_sort_criteria {
2558 field: u32,
2559 reversed: i32,
2560}
2561
2562const WINDOW_MINIMUM: u32 = PANE_MINIMUM;
2563const WINDOW_MAXIMUM: u32 = 10_000;
2564
2565#[repr(i32)]
2566enum exit_type {
2567 CLIENT_EXIT_RETURN,
2568 CLIENT_EXIT_SHUTDOWN,
2569 CLIENT_EXIT_DETACH,
2570}
2571
2572#[repr(i32)]
2573#[derive(Copy, Clone, Eq, PartialEq)]
2574enum prompt_mode {
2575 PROMPT_ENTRY,
2576 PROMPT_COMMAND,
2577}
2578
2579mod tmux;
2580
2581pub use crate::tmux::tmux_main;
2582
2583use crate::tmux::{
2584 GLOBAL_ENVIRON, GLOBAL_OPTIONS, GLOBAL_S_OPTIONS, GLOBAL_W_OPTIONS, PTM_FD, SHELL_COMMAND,
2585 SOCKET_PATH, START_TIME, checkshell, find_cwd, find_home, get_timer, getversion, setblocking,
2586 shell_argv0,
2587};
2588
2589mod proc;
2590use crate::proc::{
2591 proc_add_peer, proc_clear_signals, proc_exit, proc_flush_peer, proc_fork_and_daemon,
2592 proc_get_peer_uid, proc_kill_peer, proc_loop, proc_remove_peer, proc_send, proc_set_signals,
2593 proc_start, proc_toggle_log, tmuxpeer, tmuxproc,
2594};
2595
2596mod cfg_;
2597use crate::cfg_::{
2598 CFG_CLIENT, CFG_FILES, CFG_FINISHED, CFG_NFILES, CFG_QUIET, cfg_print_causes, cfg_show_causes,
2599 load_cfg, load_cfg_from_buffer, start_cfg,
2600};
2601
2602mod paste;
2603use crate::paste::{
2604 paste_add, paste_buffer, paste_buffer_created, paste_buffer_data, paste_buffer_data_,
2605 paste_buffer_name, paste_buffer_order, paste_free, paste_get_name, paste_get_top,
2606 paste_is_empty, paste_make_sample, paste_rename, paste_replace, paste_set, paste_walk,
2607};
2608
2609mod format;
2610use crate::format::format_add;
2611use crate::format::{
2612 FORMAT_NONE, FORMAT_PANE, FORMAT_WINDOW, format_add_cb, format_add_tv, format_cb,
2613 format_create, format_create_defaults, format_create_from_state, format_create_from_target,
2614 format_defaults, format_defaults_pane, format_defaults_paste_buffer, format_defaults_window,
2615 format_each, format_expand, format_expand_time, format_flags, format_free, format_get_pane,
2616 format_grid_hyperlink, format_grid_line, format_grid_word, format_job_tree, format_log_debug,
2617 format_lost_client, format_merge, format_pretty_time, format_single, format_single_from_state,
2618 format_single_from_target, format_skip, format_tidy_jobs, format_tree, format_true,
2619};
2620
2621mod format_draw_;
2622use crate::format_draw_::{format_draw, format_trim_left, format_trim_right, format_width};
2623
2624mod notify;
2625use crate::notify::{
2626 notify_client, notify_hook, notify_pane, notify_paste_buffer, notify_session,
2627 notify_session_window, notify_window, notify_winlink,
2628};
2629
2630mod options_;
2631use crate::options_::options_set_string;
2632use crate::options_::{
2633 options, options_array_assign, options_array_clear, options_array_first, options_array_get,
2634 options_array_item, options_array_item_index, options_array_item_value, options_array_next,
2635 options_array_set, options_create, options_default, options_default_to_string, options_empty,
2636 options_entry, options_first, options_free, options_from_string, options_get,
2637 options_get_number, options_get_number_, options_get_only, options_get_parent,
2638 options_get_string, options_get_string_, options_is_array, options_is_string, options_match,
2639 options_match_get, options_name, options_next, options_owner, options_parse, options_parse_get,
2640 options_push_changes, options_remove_or_default, options_scope_from_flags,
2641 options_scope_from_name, options_set_number, options_set_parent, options_string_to_style,
2642 options_table_entry, options_to_string,
2643};
2644
2645mod options_table;
2646use crate::options_table::{OPTIONS_OTHER_NAMES, OPTIONS_TABLE};
2647
2648bitflags::bitflags! {
2649 #[repr(transparent)]
2650 #[derive(Copy, Clone, Eq, PartialEq)]
2651 struct job_flag: i32 {
2652 const JOB_NOWAIT = 1;
2653 const JOB_KEEPWRITE = 2;
2654 const JOB_PTY = 4;
2655 const JOB_DEFAULTSHELL = 8;
2656 }
2657}
2658mod job_;
2659use crate::job_::{
2660 job, job_check_died, job_complete_cb, job_free, job_free_cb, job_get_data, job_get_event,
2661 job_get_status, job_kill_all, job_print_summary, job_resize, job_run, job_still_running,
2662 job_transfer, job_update_cb,
2663};
2664
2665mod environ_;
2666use crate::environ_::{
2667 environ, environ_clear, environ_copy, environ_create, environ_find, environ_first,
2668 environ_for_session, environ_free, environ_next, environ_push, environ_put, environ_unset,
2669 environ_update,
2670};
2671use crate::environ_::{environ_log, environ_set};
2672
2673mod tty_;
2674use crate::tty_::{
2675 tty_attributes, tty_cell, tty_clipboard_query, tty_close, tty_cmd_alignmenttest, tty_cmd_cell,
2676 tty_cmd_cells, tty_cmd_clearcharacter, tty_cmd_clearendofline, tty_cmd_clearendofscreen,
2677 tty_cmd_clearline, tty_cmd_clearscreen, tty_cmd_clearstartofline, tty_cmd_clearstartofscreen,
2678 tty_cmd_deletecharacter, tty_cmd_deleteline, tty_cmd_insertcharacter, tty_cmd_insertline,
2679 tty_cmd_linefeed, tty_cmd_rawstring, tty_cmd_reverseindex, tty_cmd_scrolldown,
2680 tty_cmd_scrollup, tty_cmd_setselection, tty_cmd_syncstart, tty_create_log, tty_cursor,
2681 tty_default_colours, tty_draw_line, tty_free, tty_init, tty_margin_off, tty_open, tty_putc,
2682 tty_putcode, tty_putcode_i, tty_putcode_ii, tty_putcode_iii, tty_putcode_s, tty_putcode_ss,
2683 tty_putn, tty_puts, tty_raw, tty_region_off, tty_repeat_requests, tty_reset, tty_resize,
2684 tty_send_requests, tty_set_path, tty_set_selection, tty_set_size, tty_set_title, tty_start_tty,
2685 tty_stop_tty, tty_sync_end, tty_sync_start, tty_update_client_offset, tty_update_features,
2686 tty_update_mode, tty_update_window_offset, tty_window_bigger, tty_window_offset, tty_write,
2687};
2688
2689mod tty_term_;
2690use crate::tty_term_::{
2691 TTY_TERMS, tty_code, tty_term_apply, tty_term_apply_overrides, tty_term_create,
2692 tty_term_describe, tty_term_flag, tty_term_free, tty_term_free_list, tty_term_has,
2693 tty_term_ncodes, tty_term_number, tty_term_read_list, tty_term_string, tty_term_string_i,
2694 tty_term_string_ii, tty_term_string_iii, tty_term_string_s, tty_term_string_ss,
2695};
2696
2697mod tty_features;
2698use crate::tty_features::{
2699 tty_add_features, tty_apply_features, tty_default_features, tty_get_features,
2700};
2701
2702mod tty_acs;
2703use crate::tty_acs::{
2704 tty_acs_double_borders, tty_acs_get, tty_acs_heavy_borders, tty_acs_needed,
2705 tty_acs_reverse_get, tty_acs_rounded_borders,
2706};
2707
2708mod tty_keys;
2709use crate::tty_keys::{tty_key, tty_keys_build, tty_keys_colours, tty_keys_free, tty_keys_next};
2710
2711mod arguments;
2712
2713unsafe fn args_has_(args: *mut args, flag: char) -> bool {
2715 debug_assert!(flag.is_ascii());
2716 unsafe { args_has(args, flag as u8) != 0 }
2717}
2718
2719unsafe fn args_get_(args: *mut args, flag: char) -> *const u8 {
2721 debug_assert!(flag.is_ascii());
2722 unsafe { args_get(args, flag as u8) }
2723}
2724
2725use crate::arguments::{
2726 args, args_command_state, args_copy, args_count, args_create, args_entry, args_escape,
2727 args_first, args_first_value, args_free, args_free_value, args_free_values, args_from_vector,
2728 args_get, args_has, args_make_commands, args_make_commands_free,
2729 args_make_commands_get_command, args_make_commands_now, args_make_commands_prepare, args_next,
2730 args_next_value, args_parse, args_percentage, args_percentage_and_expand, args_print, args_set,
2731 args_string, args_string_percentage, args_string_percentage_and_expand, args_strtonum,
2732 args_strtonum_and_expand, args_to_vector, args_value, args_values,
2733};
2734
2735mod cmd_;
2736use crate::cmd_::cmd_log_argv;
2737use crate::cmd_::{
2738 CMD_TABLE, cmd, cmd_append_argv, cmd_copy, cmd_copy_argv, cmd_free, cmd_free_argv,
2739 cmd_get_alias, cmd_get_args, cmd_get_entry, cmd_get_group, cmd_get_source, cmd_list_all_have,
2740 cmd_list_any_have, cmd_list_append, cmd_list_append_all, cmd_list_copy, cmd_list_first,
2741 cmd_list_free, cmd_list_move, cmd_list_new, cmd_list_next, cmd_list_print, cmd_mouse_at,
2742 cmd_mouse_pane, cmd_mouse_window, cmd_pack_argv, cmd_parse, cmd_print, cmd_stringify_argv,
2743 cmd_template_replace, cmd_unpack_argv, cmds,
2744};
2745
2746use crate::cmd_::cmd_attach_session::cmd_attach_session;
2747
2748use crate::cmd_::cmd_find::{
2749 cmd_find_best_client, cmd_find_clear_state, cmd_find_client, cmd_find_copy_state,
2750 cmd_find_empty_state, cmd_find_from_client, cmd_find_from_mouse, cmd_find_from_nothing,
2751 cmd_find_from_pane, cmd_find_from_session, cmd_find_from_session_window, cmd_find_from_window,
2752 cmd_find_from_winlink, cmd_find_from_winlink_pane, cmd_find_target, cmd_find_valid_state,
2753};
2754
2755mod cmd_parse;
2756use crate::cmd_parse::{
2757 cmd_parse_and_append, cmd_parse_and_insert, cmd_parse_command, cmd_parse_from_arguments,
2758 cmd_parse_from_buffer, cmd_parse_from_file, cmd_parse_from_string, cmd_parse_state, *,
2759};
2760
2761use crate::cmd_::cmd_queue::{
2762 cmdq_add_format, cmdq_add_formats, cmdq_append, cmdq_continue, cmdq_copy_state, cmdq_error,
2763 cmdq_free, cmdq_free_state, cmdq_get_callback, cmdq_get_callback1, cmdq_get_client,
2764 cmdq_get_command, cmdq_get_current, cmdq_get_error, cmdq_get_event, cmdq_get_flags,
2765 cmdq_get_name, cmdq_get_source, cmdq_get_state, cmdq_get_target, cmdq_get_target_client,
2766 cmdq_guard, cmdq_insert_after, cmdq_insert_hook, cmdq_item, cmdq_link_state, cmdq_list,
2767 cmdq_merge_formats, cmdq_new, cmdq_new_state, cmdq_next, cmdq_print, cmdq_print_data,
2768 cmdq_running, cmdq_state,
2769};
2770
2771use crate::cmd_::cmd_wait_for::cmd_wait_for_flush;
2772
2773mod client_;
2774use crate::client_::client_main;
2775
2776mod key_bindings_;
2777use crate::key_bindings_::{
2778 key_bindings_add, key_bindings_dispatch, key_bindings_first, key_bindings_first_table,
2779 key_bindings_get, key_bindings_get_default, key_bindings_get_table, key_bindings_init,
2780 key_bindings_next, key_bindings_next_table, key_bindings_remove, key_bindings_remove_table,
2781 key_bindings_reset, key_bindings_reset_table, key_bindings_unref_table,
2782};
2783
2784mod key_string;
2785use crate::key_string::{key_string_lookup_key, key_string_lookup_string};
2786
2787mod alerts;
2788use crate::alerts::{alerts_check_session, alerts_queue, alerts_reset_all};
2789
2790mod file;
2791use crate::file::{
2792 file_can_print, file_cancel, file_cmp, file_create_with_client, file_create_with_peer,
2793 file_error, file_fire_done, file_fire_read, file_free, file_print, file_print_buffer,
2794 file_push, file_read, file_read_cancel, file_read_data, file_read_done, file_read_open,
2795 file_vprint, file_write, file_write_close, file_write_data, file_write_left, file_write_open,
2796 file_write_ready,
2797};
2798
2799mod server;
2800use crate::server::{
2801 CLIENTS, CURRENT_TIME, MARKED_PANE, MESSAGE_LOG, SERVER_PROC, server_add_accept,
2802 server_add_message, server_check_marked, server_clear_marked, server_create_socket,
2803 server_is_marked, server_set_marked, server_start, server_update_socket,
2804};
2805
2806mod server_client;
2807use crate::server_client::{
2808 server_client_add_client_window, server_client_check_nested, server_client_clear_overlay,
2809 server_client_create, server_client_detach, server_client_exec,
2810 server_client_get_client_window, server_client_get_cwd, server_client_get_flags,
2811 server_client_get_key_table, server_client_get_pane, server_client_handle_key,
2812 server_client_how_many, server_client_loop, server_client_lost, server_client_open,
2813 server_client_overlay_range, server_client_print, server_client_remove_pane,
2814 server_client_set_flags, server_client_set_key_table, server_client_set_overlay,
2815 server_client_set_pane, server_client_set_session, server_client_suspend, server_client_unref,
2816 server_client_window_cmp,
2817};
2818
2819mod server_fn;
2820use crate::server_fn::{
2821 server_check_unattached, server_destroy_pane, server_destroy_session, server_kill_pane,
2822 server_kill_window, server_link_window, server_lock, server_lock_client, server_lock_session,
2823 server_redraw_client, server_redraw_session, server_redraw_session_group, server_redraw_window,
2824 server_redraw_window_borders, server_renumber_all, server_renumber_session,
2825 server_status_client, server_status_session, server_status_session_group, server_status_window,
2826 server_unlink_window, server_unzoom_window,
2827};
2828
2829mod status;
2830use crate::status::{
2831 STATUS_PROMPT_HLIST, STATUS_PROMPT_HSIZE, status_at_line, status_free, status_get_range,
2832 status_init, status_line_size, status_message_clear, status_message_redraw, status_message_set,
2833 status_prompt_clear, status_prompt_key, status_prompt_load_history, status_prompt_redraw,
2834 status_prompt_save_history, status_prompt_set, status_prompt_type, status_prompt_type_string,
2835 status_prompt_update, status_redraw, status_timer_start, status_timer_start_all,
2836 status_update_cache,
2837};
2838
2839mod resize;
2840use crate::resize::{
2841 default_window_size, recalculate_size, recalculate_sizes, recalculate_sizes_now, resize_window,
2842};
2843
2844mod input;
2845use crate::input::{
2846 input_ctx, input_free, input_init, input_parse_buffer, input_parse_pane, input_parse_screen,
2847 input_pending, input_reply_clipboard, input_reset,
2848};
2849
2850mod input_keys;
2851use crate::input_keys::{input_key, input_key_build, input_key_get_mouse, input_key_pane};
2852
2853mod colour;
2854use crate::colour::{
2855 colour_256to16, colour_byname, colour_find_rgb, colour_force_rgb, colour_fromstring,
2856 colour_fromstring_, colour_join_rgb, colour_palette_clear, colour_palette_free,
2857 colour_palette_from_option, colour_palette_get, colour_palette_init, colour_palette_set,
2858 colour_parse_x11, colour_split_rgb, colour_tostring,
2859};
2860
2861mod attributes;
2862use crate::attributes::{attributes_fromstring, attributes_tostring};
2863
2864mod grid_;
2865use crate::grid_::{
2866 GRID_DEFAULT_CELL, grid_adjust_lines, grid_cells_equal, grid_cells_look_equal, grid_clear,
2867 grid_clear_history, grid_clear_lines, grid_collect_history, grid_compare, grid_create,
2868 grid_destroy, grid_duplicate_lines, grid_empty_line, grid_get_cell, grid_get_line,
2869 grid_line_length, grid_move_cells, grid_move_lines, grid_peek_line, grid_reflow,
2870 grid_remove_history, grid_scroll_history, grid_scroll_history_region, grid_set_cell,
2871 grid_set_cells, grid_set_padding, grid_string_cells, grid_unwrap_position, grid_wrap_position,
2872};
2873
2874mod grid_reader_;
2875use crate::grid_reader_::{
2876 grid_reader_cursor_back_to_indentation, grid_reader_cursor_down,
2877 grid_reader_cursor_end_of_line, grid_reader_cursor_jump, grid_reader_cursor_jump_back,
2878 grid_reader_cursor_left, grid_reader_cursor_next_word, grid_reader_cursor_next_word_end,
2879 grid_reader_cursor_previous_word, grid_reader_cursor_right, grid_reader_cursor_start_of_line,
2880 grid_reader_cursor_up, grid_reader_get_cursor, grid_reader_in_set, grid_reader_line_length,
2881 grid_reader_start,
2882};
2883
2884mod grid_view;
2885use crate::grid_view::{
2886 grid_view_clear, grid_view_clear_history, grid_view_delete_cells, grid_view_delete_lines,
2887 grid_view_delete_lines_region, grid_view_get_cell, grid_view_insert_cells,
2888 grid_view_insert_lines, grid_view_insert_lines_region, grid_view_scroll_region_down,
2889 grid_view_scroll_region_up, grid_view_set_cell, grid_view_set_cells, grid_view_set_padding,
2890 grid_view_string_cells,
2891};
2892
2893mod screen_write;
2894use crate::screen_write::{
2895 screen_write_alignmenttest, screen_write_alternateoff, screen_write_alternateon,
2896 screen_write_backspace, screen_write_box, screen_write_carriagereturn, screen_write_cell,
2897 screen_write_citem, screen_write_clearcharacter, screen_write_clearendofline,
2898 screen_write_clearendofscreen, screen_write_clearhistory, screen_write_clearline,
2899 screen_write_clearscreen, screen_write_clearstartofline, screen_write_clearstartofscreen,
2900 screen_write_cline, screen_write_collect_add, screen_write_collect_end,
2901 screen_write_cursordown, screen_write_cursorleft, screen_write_cursormove,
2902 screen_write_cursorright, screen_write_cursorup, screen_write_deletecharacter,
2903 screen_write_deleteline, screen_write_fast_copy, screen_write_free_list,
2904 screen_write_fullredraw, screen_write_hline, screen_write_insertcharacter,
2905 screen_write_insertline, screen_write_linefeed, screen_write_make_list, screen_write_menu,
2906 screen_write_mode_clear, screen_write_mode_set, screen_write_preview, screen_write_putc,
2907 screen_write_rawstring, screen_write_reset, screen_write_reverseindex, screen_write_scrolldown,
2908 screen_write_scrollregion, screen_write_scrollup, screen_write_setselection,
2909 screen_write_start, screen_write_start_callback, screen_write_start_pane, screen_write_stop,
2910 screen_write_vline,
2911};
2912use crate::screen_write::{
2913 screen_write_nputs, screen_write_puts, screen_write_strlen, screen_write_text,
2914 screen_write_vnputs, screen_write_vnputs_,
2915};
2916
2917mod screen_redraw;
2918use crate::screen_redraw::{screen_redraw_pane, screen_redraw_screen};
2919
2920mod screen_;
2921use crate::screen_::{
2922 screen_alternate_off, screen_alternate_on, screen_check_selection, screen_clear_selection,
2923 screen_free, screen_hide_selection, screen_init, screen_mode_to_string, screen_pop_title,
2924 screen_push_title, screen_reinit, screen_reset_hyperlinks, screen_reset_tabs, screen_resize,
2925 screen_resize_cursor, screen_sel, screen_select_cell, screen_set_cursor_colour,
2926 screen_set_cursor_style, screen_set_path, screen_set_selection, screen_set_title,
2927 screen_titles,
2928};
2929
2930mod window_;
2931use crate::window_::{
2932 ALL_WINDOW_PANES, WINDOWS, window_add_pane, window_add_ref, window_cmp, window_count_panes,
2933 window_create, window_destroy_panes, window_find_by_id, window_find_by_id_str,
2934 window_find_string, window_get_active_at, window_has_pane, window_lost_pane,
2935 window_pane_at_index, window_pane_cmp, window_pane_default_cursor, window_pane_destroy_ready,
2936 window_pane_exited, window_pane_find_by_id, window_pane_find_by_id_str, window_pane_find_down,
2937 window_pane_find_left, window_pane_find_right, window_pane_find_up, window_pane_get_new_data,
2938 window_pane_index, window_pane_key, window_pane_mode, window_pane_next_by_number,
2939 window_pane_previous_by_number, window_pane_reset_mode, window_pane_reset_mode_all,
2940 window_pane_resize, window_pane_search, window_pane_send_resize, window_pane_set_event,
2941 window_pane_set_mode, window_pane_stack_push, window_pane_stack_remove,
2942 window_pane_start_input, window_pane_update_focus, window_pane_update_used_data,
2943 window_pane_visible, window_pop_zoom, window_printable_flags, window_push_zoom,
2944 window_redraw_active_switch, window_remove_pane, window_remove_ref, window_resize,
2945 window_set_active_pane, window_set_fill_character, window_set_name, window_unzoom,
2946 window_update_activity, window_update_focus, window_zoom, winlink_add, winlink_clear_flags,
2947 winlink_cmp, winlink_count, winlink_find_by_index, winlink_find_by_window,
2948 winlink_find_by_window_id, winlink_next, winlink_next_by_number, winlink_previous,
2949 winlink_previous_by_number, winlink_remove, winlink_set_window, winlink_shuffle_up,
2950 winlink_stack_push, winlink_stack_remove,
2951};
2952
2953mod layout;
2954use crate::layout::{
2955 layout_assign_pane, layout_close_pane, layout_count_cells, layout_create_cell,
2956 layout_destroy_cell, layout_fix_offsets, layout_fix_panes, layout_free, layout_free_cell,
2957 layout_init, layout_make_leaf, layout_make_node, layout_print_cell, layout_resize,
2958 layout_resize_adjust, layout_resize_layout, layout_resize_pane, layout_resize_pane_to,
2959 layout_search_by_border, layout_set_size, layout_split_pane, layout_spread_cell,
2960 layout_spread_out,
2961};
2962
2963mod layout_custom;
2964use crate::layout_custom::{layout_dump, layout_parse};
2965
2966mod layout_set;
2967use crate::layout_set::{
2968 layout_set_lookup, layout_set_next, layout_set_previous, layout_set_select,
2969};
2970
2971mod mode_tree;
2972use crate::mode_tree::{
2973 mode_tree_add, mode_tree_build, mode_tree_build_cb, mode_tree_collapse_current,
2974 mode_tree_count_tagged, mode_tree_data, mode_tree_down, mode_tree_draw,
2975 mode_tree_draw_as_parent, mode_tree_draw_cb, mode_tree_each_cb, mode_tree_each_tagged,
2976 mode_tree_expand, mode_tree_expand_current, mode_tree_free, mode_tree_get_current,
2977 mode_tree_get_current_name, mode_tree_height_cb, mode_tree_item, mode_tree_key,
2978 mode_tree_key_cb, mode_tree_menu_cb, mode_tree_no_tag, mode_tree_remove, mode_tree_resize,
2979 mode_tree_run_command, mode_tree_search_cb, mode_tree_set_current, mode_tree_start,
2980 mode_tree_up, mode_tree_zoom,
2981};
2982
2983mod window_buffer;
2984use crate::window_buffer::WINDOW_BUFFER_MODE;
2985
2986mod window_tree;
2987use crate::window_tree::WINDOW_TREE_MODE;
2988
2989mod window_clock;
2990use crate::window_clock::{WINDOW_CLOCK_MODE, WINDOW_CLOCK_TABLE};
2991
2992mod window_client;
2993use crate::window_client::WINDOW_CLIENT_MODE;
2994
2995mod window_copy;
2996use crate::window_copy::window_copy_add;
2997use crate::window_copy::{
2998 WINDOW_COPY_MODE, WINDOW_VIEW_MODE, window_copy_get_line, window_copy_get_word,
2999 window_copy_pagedown, window_copy_pageup, window_copy_start_drag, window_copy_vadd,
3000};
3001
3002mod window_customize;
3003use crate::window_customize::WINDOW_CUSTOMIZE_MODE;
3004
3005mod names;
3006use crate::names::{check_window_name, default_window_name, parse_window_name};
3007
3008mod control;
3009use crate::control::control_write;
3010use crate::control::{
3011 control_add_sub, control_all_done, control_continue_pane, control_discard, control_pane_offset,
3012 control_pause_pane, control_ready, control_remove_sub, control_reset_offsets,
3013 control_set_pane_off, control_set_pane_on, control_start, control_state, control_stop,
3014 control_write_output,
3015};
3016
3017mod control_notify;
3018use crate::control_notify::{
3019 control_notify_client_detached, control_notify_client_session_changed,
3020 control_notify_pane_mode_changed, control_notify_paste_buffer_changed,
3021 control_notify_paste_buffer_deleted, control_notify_session_closed,
3022 control_notify_session_created, control_notify_session_renamed,
3023 control_notify_session_window_changed, control_notify_window_layout_changed,
3024 control_notify_window_linked, control_notify_window_pane_changed,
3025 control_notify_window_renamed, control_notify_window_unlinked,
3026};
3027
3028mod session_;
3029use crate::session_::{
3030 NEXT_SESSION_ID, SESSIONS, session_add_ref, session_alive, session_attach, session_check_name,
3031 session_cmp, session_create, session_destroy, session_detach, session_find, session_find_by_id,
3032 session_find_by_id_str, session_group_add, session_group_attached_count,
3033 session_group_contains, session_group_count, session_group_find, session_group_new,
3034 session_group_synchronize_from, session_group_synchronize_to, session_has, session_is_linked,
3035 session_last, session_next, session_next_session, session_previous, session_previous_session,
3036 session_remove_ref, session_renumber_windows, session_select, session_set_current,
3037 session_update_activity,
3038};
3039
3040mod utf8;
3041use crate::utf8::{
3042 utf8_append, utf8_build_one, utf8_copy, utf8_cstrhas, utf8_cstrwidth, utf8_from_data,
3043 utf8_fromcstr, utf8_fromwc, utf8_in_table, utf8_isvalid, utf8_open, utf8_padcstr,
3044 utf8_rpadcstr, utf8_sanitize, utf8_set, utf8_stravis, utf8_stravisx, utf8_strlen, utf8_strvis,
3045 utf8_strwidth, utf8_to_data, utf8_tocstr, utf8_towc,
3046};
3047
3048mod osdep;
3049use crate::osdep::{osdep_event_init, osdep_get_cwd, osdep_get_name};
3050
3051mod utf8_combined;
3052use crate::utf8_combined::{utf8_has_zwj, utf8_is_modifier, utf8_is_vs, utf8_is_zwj};
3053
3054unsafe extern "C" {
3056 unsafe fn get_proc_name(_: c_int, _: *mut u8) -> *mut u8;
3057 unsafe fn get_proc_cwd(_: c_int) -> *mut u8;
3058}
3059
3060#[macro_use] mod log;
3062use crate::log::{fatal, fatalx, log_add_level, log_close, log_get_level, log_open, log_toggle};
3063use crate::log::{fatalx_, log_debug};
3064
3065const MENU_NOMOUSE: i32 = 0x1;
3066const MENU_TAB: i32 = 0x2;
3067const MENU_STAYOPEN: i32 = 0x4;
3068mod menu_;
3069use crate::menu_::{
3070 menu_add_item, menu_add_items, menu_check_cb, menu_create, menu_data, menu_display,
3071 menu_draw_cb, menu_free, menu_free_cb, menu_key_cb, menu_mode_cb, menu_prepare,
3072};
3073
3074const POPUP_CLOSEEXIT: i32 = 0x1;
3075const POPUP_CLOSEEXITZERO: i32 = 0x2;
3076const POPUP_INTERNAL: i32 = 0x4;
3077mod popup;
3078use crate::popup::{popup_close_cb, popup_display, popup_editor, popup_finish_edit_cb};
3079
3080mod style_;
3081use crate::style_::{style_add, style_apply, style_copy, style_parse, style_set, style_tostring};
3082
3083mod spawn;
3084use crate::spawn::{spawn_pane, spawn_window};
3085
3086mod regsub;
3087use crate::regsub::regsub;
3088
3089unsafe extern "C" {}
3091unsafe extern "C" {}
3093
3094mod server_acl;
3095use crate::server_acl::{
3096 server_acl_display, server_acl_get_uid, server_acl_init, server_acl_join, server_acl_user,
3097 server_acl_user_allow, server_acl_user_allow_write, server_acl_user_deny,
3098 server_acl_user_deny_write, server_acl_user_find,
3099};
3100
3101mod hyperlinks_;
3102use crate::hyperlinks_::{
3103 hyperlinks, hyperlinks_copy, hyperlinks_free, hyperlinks_get, hyperlinks_init, hyperlinks_put,
3104 hyperlinks_reset, hyperlinks_uri,
3105};
3106
3107mod xmalloc;
3108use crate::xmalloc::{format_nul, xsnprintf_};
3109use crate::xmalloc::{
3110 xcalloc, xcalloc_, xcalloc1, xmalloc, xmalloc_, xrealloc, xrealloc_, xreallocarray_, xstrdup,
3111 xstrdup_, xstrdup__, xstrdup___,
3112};
3113
3114mod tmux_protocol;
3115use crate::tmux_protocol::{
3116 PROTOCOL_VERSION, msg_command, msg_read_cancel, msg_read_data, msg_read_done, msg_read_open,
3117 msg_write_close, msg_write_data, msg_write_open, msg_write_ready, msgtype,
3118};
3119
3120unsafe extern "C-unwind" {
3121 fn vsnprintf(_: *mut u8, _: usize, _: *const u8, _: ...) -> c_int;
3122 fn vasprintf(_: *mut *mut u8, _: *const u8, _: ...) -> c_int;
3123}
3124
3125unsafe impl Sync for SyncCharPtr {}
3126#[repr(transparent)]
3127#[derive(Copy, Clone)]
3128struct SyncCharPtr(*const u8);
3129impl SyncCharPtr {
3130 const fn new(value: &'static CStr) -> Self {
3131 Self(value.as_ptr().cast())
3132 }
3133 const fn from_ptr(value: *const u8) -> Self {
3134 Self(value)
3135 }
3136 const fn null() -> Self {
3137 Self(null())
3138 }
3139 const fn as_ptr(&self) -> *const u8 {
3140 self.0
3141 }
3142 const fn is_null(&self) -> bool {
3143 self.0.is_null()
3144 }
3145}
3146
3147unsafe fn _s(ptr: impl ToU8Ptr) -> DisplayCStrPtr {
3148 DisplayCStrPtr(ptr.to_u8_ptr())
3149}
3150trait ToU8Ptr {
3151 fn to_u8_ptr(self) -> *const u8;
3152}
3153impl ToU8Ptr for *mut u8 {
3154 fn to_u8_ptr(self) -> *const u8 {
3155 self.cast()
3156 }
3157}
3158impl ToU8Ptr for *const u8 {
3159 fn to_u8_ptr(self) -> *const u8 {
3160 self
3161 }
3162}
3163impl ToU8Ptr for *mut i8 {
3164 fn to_u8_ptr(self) -> *const u8 {
3165 self.cast()
3166 }
3167}
3168impl ToU8Ptr for *const i8 {
3169 fn to_u8_ptr(self) -> *const u8 {
3170 self.cast()
3171 }
3172}
3173impl ToU8Ptr for SyncCharPtr {
3174 fn to_u8_ptr(self) -> *const u8 {
3175 self.as_ptr()
3176 }
3177}
3178#[repr(transparent)]
3181struct DisplayCStrPtr(*const u8);
3182impl DisplayCStrPtr {
3183 unsafe fn from_raw(s: *const u8) -> Self {
3184 Self(s)
3185 }
3186}
3187impl std::fmt::Display for DisplayCStrPtr {
3188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3189 if self.0.is_null() {
3190 return f.write_str("(null)");
3191 }
3192
3193 let len = if let Some(width) = f.precision() {
3196 unsafe { libc::strnlen(self.0, width) }
3197 } else if let Some(width) = f.width() {
3198 unsafe { libc::strnlen(self.0, width) }
3199 } else {
3200 unsafe { libc::strlen(self.0) }
3201 };
3202
3203 let s: &[u8] = unsafe { std::slice::from_raw_parts(self.0, len) };
3204 let s = std::str::from_utf8(s).unwrap_or("%s-invalid-utf8");
3205 f.write_str(s)
3206 }
3207}
3208
3209macro_rules! function_name {
3212 () => {{
3213 fn f() {}
3214 fn type_name_of<T>(_: T) -> &'static str {
3215 std::any::type_name::<T>()
3216 }
3217 let name = type_name_of(f);
3218
3219 match &name[..name.len() - 3].rfind(':') {
3221 Some(pos) => &name[pos + 1..name.len() - 3],
3222 None => &name[..name.len() - 3],
3223 }
3224 }};
3225}
3226pub(crate) use function_name;
3227
3228const fn concat_array<const N: usize, const M: usize, const O: usize, T: Copy>(
3229 a1: [T; N],
3230 a2: [T; M],
3231) -> [T; O] {
3232 let mut out: [MaybeUninit<T>; O] = [MaybeUninit::uninit(); O];
3233
3234 let mut i: usize = 0;
3235 while i < a1.len() {
3236 out[i].write(a1[i]);
3237 i += 1;
3238 }
3239 while i < a1.len() + a2.len() {
3240 out[i].write(a2[i - a1.len()]);
3241 i += 1;
3242 }
3243
3244 assert!(a1.len() + a2.len() == out.len());
3245 assert!(i == out.len());
3246
3247 unsafe { std::mem::transmute_copy(&out) }
3248 }
3251
3252pub(crate) fn i32_to_ordering(value: i32) -> std::cmp::Ordering {
3253 match value {
3254 ..0 => std::cmp::Ordering::Less,
3255 0 => std::cmp::Ordering::Equal,
3256 1.. => std::cmp::Ordering::Greater,
3257 }
3258}
3259
3260pub(crate) unsafe fn cstr_to_str<'a>(ptr: *const u8) -> &'a str {
3261 unsafe {
3262 let len = libc::strlen(ptr);
3263
3264 let bytes = std::slice::from_raw_parts(ptr.cast::<u8>(), len);
3265
3266 std::str::from_utf8(bytes).expect("bad cstr_to_str")
3267 }
3268}
3269
3270macro_rules! c {
3273 ($s:literal) => {{
3274 const S: &str = concat!($s, "\0");
3275 #[allow(unused_unsafe)]
3276 unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(S.as_bytes()) }
3277 .as_ptr()
3278 .cast::<u8>()
3279 }};
3280}
3281pub(crate) use c;