Skip to main content

uncurses/ansi/
winop.rs

1//! XTWINOPS window-operation requests and reports.
2//!
3//! ## Category
4//!
5//! XTWINOPS is the CSI `t` family for window and text-area operations such as
6//! resizing and querying pixel or cell dimensions.
7//!
8//! ## CSI format
9//!
10//! The generic shape is `ESC [ op [;arg...] t`. Operation numbers are decimal;
11//! additional parameters are operation-specific.
12//!
13//! ## Mode interaction
14//!
15//! XTWINOPS requests are not enabled by a mode in this module. Related in-band
16//! resize notifications are controlled separately by
17//! [`Mode::IN_BAND_RESIZE`](crate::ansi::mode::Mode::IN_BAND_RESIZE).
18
19use std::io::{self, Write};
20
21pub mod op {
22    //! Common XTWINOPS operation numbers.
23    //!
24    //! Each value is the first `Ps` parameter in an XTWINOPS `CSI ... t`
25    //! sequence. Pass one as the `p` argument to [`write_window_op`](crate::ansi::winop::write_window_op); any
26    //! extra `Ps` parameters are operation-specific. These constants only
27    //! name window operation numbers; they do not enable terminal modes.
28    /// Operation `4`: resize the window in pixels with arguments `height ; width`, yielding `ESC [ 4 ; <height> ; <width> t`.
29    pub const RESIZE_WINDOW: u16 = 4;
30    /// Operation `14`: request window pixel size with `ESC [ 14 t`; replies use operation `4` with height and width.
31    pub const REQUEST_WINDOW_SIZE: u16 = 14;
32    /// Operation `16`: request character-cell pixel size with `ESC [ 16 t`; replies use operation `6` with height and width.
33    pub const REQUEST_CELL_SIZE: u16 = 16;
34    /// Operation `18`: request text-area size in cells with `ESC [ 18 t`; replies use operation `8` with rows and columns.
35    pub const REQUEST_TEXT_AREA_SIZE: u16 = 18;
36}
37
38/// Request window pixel size: exact bytes `ESC [ 14 t` (`b"\x1b[14t"`).
39///
40/// A compatible terminal replies with `ESC [ 4 ; <height> ; <width> t`.
41pub const REQUEST_WINDOW_PIXEL_SIZE: &[u8] = b"\x1b[14t";
42
43/// Request character-cell pixel size: exact bytes `ESC [ 16 t` (`b"\x1b[16t"`).
44///
45/// A compatible terminal replies with `ESC [ 6 ; <height> ; <width> t`.
46pub const REQUEST_CELL_PIXEL_SIZE: &[u8] = b"\x1b[16t";
47
48/// Encode a generic XTWINOPS sequence.
49///
50/// `p` is the operation number and `ps` are additional decimal parameters. `p == 0` emits nothing; otherwise the format is `ESC [ <p> [;<ps>...] t`.
51pub fn write_window_op<W: Write>(w: &mut W, p: u16, ps: &[u16]) -> io::Result<()> {
52    if p == 0 {
53        return Ok(());
54    }
55    w.write_all(b"\x1b[")?;
56    write!(w, "{p}")?;
57    for v in ps {
58        write!(w, ";{v}")?;
59    }
60    w.write_all(b"t")
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn test_request_cell_size() {
69        let mut buf = Vec::new();
70        write_window_op(&mut buf, op::REQUEST_CELL_SIZE, &[]).unwrap();
71        assert_eq!(buf, b"\x1b[16t");
72    }
73
74    #[test]
75    fn test_resize() {
76        let mut buf = Vec::new();
77        write_window_op(&mut buf, op::RESIZE_WINDOW, &[480, 800]).unwrap();
78        assert_eq!(buf, b"\x1b[4;480;800t");
79    }
80}