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