crossterm/
lib.rs

1use std::io::Write;
2
3use bitflags::bitflags;
4use crossterm::{self, queue};
5use log::trace;
6
7#[cfg(not(feature = "docsrs"))]
8include!(concat!(env!("OUT_DIR"), "/colors.rs"));
9#[cfg(feature = "docsrs")]
10pub static COLORS: &str =
11    r##"[{"error": "Feature `docsrs` is enabled. COLORS json not available."}]"##;
12
13fn convert_string_to_c_char(string: String) -> *mut libc::c_char {
14    // Convert the String to a CString
15    let c_string = match std::ffi::CString::new(string.as_bytes()) {
16        Ok(c_string) => c_string,
17        Err(_) => {
18            set_last_error(anyhow::anyhow!("Unable to convert {} to CString", &string));
19            return std::ptr::null_mut();
20        }
21    };
22
23    // Allocate space for the string
24    let string_len = c_string.as_bytes_with_nul().len();
25    let addr = unsafe {
26        let addr = libc::malloc(string_len) as *mut libc::c_char;
27        if addr.is_null() {
28            set_last_error(anyhow::anyhow!("Unable to malloc for {}", &string));
29            return std::ptr::null_mut();
30        }
31        addr
32    };
33
34    // Copy the string into the allocated space
35    unsafe {
36        std::ptr::copy_nonoverlapping(c_string.as_ptr(), addr, string_len);
37    }
38    addr
39}
40
41// ensure that we always set a C exception instead of `panic`ing
42pub trait CUnwrapper<T> {
43    fn c_unwrap(self) -> T;
44}
45
46impl<T> CUnwrapper<T> for anyhow::Result<T>
47where
48    T: Default,
49{
50    fn c_unwrap(self) -> T {
51        match self {
52            Ok(t) => {
53                RESULT.with(|r| {
54                    *r.borrow_mut() = 0;
55                });
56                take_last_error();
57                t
58            }
59            Err(err) => {
60                RESULT.with(|r| {
61                    *r.borrow_mut() = -1;
62                });
63                set_last_error(err);
64                T::default()
65            }
66        }
67    }
68}
69
70impl<T> CUnwrapper<T> for Result<T, std::io::Error>
71where
72    T: Default,
73{
74    fn c_unwrap(self) -> T {
75        match self {
76            Ok(t) => {
77                RESULT.with(|r| {
78                    *r.borrow_mut() = 0;
79                });
80                take_last_error();
81                t
82            }
83            Err(err) => {
84                RESULT.with(|r| {
85                    *r.borrow_mut() = -1;
86                });
87                set_last_error(err.into());
88                T::default()
89            }
90        }
91    }
92}
93
94thread_local! {
95  static LAST_ERROR: std::cell::RefCell<Option<anyhow::Error>> = std::cell::RefCell::new(None);
96  static RESULT: std::cell::RefCell<libc::c_int> = std::cell::RefCell::new(0);
97  static USE_STDOUT: std::cell::RefCell<bool> = std::cell::RefCell::new(std::env::var("LIBCROSSTERM_OUTPUT").unwrap_or_default() == "stdout");
98}
99
100macro_rules! r {
101    () => {
102        RESULT.with(|r| r.borrow().clone())
103    };
104}
105
106macro_rules! io {
107    () => {
108        if USE_STDOUT.with(|r| *r.borrow()) {
109            Box::new(std::io::stdout()) as Box<dyn Write>
110        } else {
111            Box::new(std::io::stderr()) as Box<dyn Write>
112        }
113    };
114}
115
116fn set_last_error(err: anyhow::Error) {
117    trace!("Set last error");
118    LAST_ERROR.with(|e| {
119        *e.borrow_mut() = Some(err);
120    });
121}
122
123/// Take the most recent error, clearing `LAST_ERROR` in the process.
124pub fn take_last_error() -> Option<anyhow::Error> {
125    LAST_ERROR.with(|prev| prev.borrow_mut().take())
126}
127
128/// Check whether error has been set.
129#[no_mangle]
130pub extern "C" fn crossterm_has_error() -> bool {
131    LAST_ERROR.with(|prev| prev.borrow().is_some())
132}
133
134#[no_mangle]
135pub extern "C" fn crossterm_clear_last_error() {
136    let _ = take_last_error();
137}
138
139/// Peek at the most recent error and get its error message as a Rust `String`.
140pub fn error_message() -> Option<String> {
141    LAST_ERROR.with(|prev| prev.borrow().as_ref().map(|e| format!("{:#}", e)))
142}
143
144/// Calculate the number of bytes in the last error's error message including a
145/// trailing `null` character. If there are no recent error, then this returns
146/// `0`.
147#[no_mangle]
148pub extern "C" fn crossterm_last_error_length() -> libc::c_int {
149    LAST_ERROR.with(|prev| match *prev.borrow() {
150        Some(ref err) => format!("{:#}", err).len() as libc::c_int + 1,
151        None => 0,
152    })
153}
154
155/// Return most recent error message into a UTF-8 string buffer.
156///
157/// Null character is stored in the last location of buffer.
158/// Caller is responsible for memory associated with string buffer.
159/// Use [`crossterm_free_c_char`] to free data.
160#[no_mangle]
161pub extern "C" fn crossterm_last_error_message() -> *const libc::c_char {
162    let last_error = take_last_error().unwrap_or(anyhow::anyhow!(
163        "No error message found. Check library documentation for more information."
164    ));
165    let string = format!("{:#}", last_error);
166    convert_string_to_c_char(string)
167}
168
169/// Frees data behind pointer to UTF-8 string allocated by this crate
170///
171/// Null character is stored in the last location of buffer.
172#[no_mangle]
173pub extern "C" fn crossterm_free_c_char(s: *mut libc::c_char) -> libc::c_int {
174    if !s.is_null() {
175        unsafe {
176            libc::free(s as *mut libc::c_void);
177        }
178        0
179    } else {
180        set_last_error(anyhow::anyhow!("Received null pointer to free"));
181        -1
182    }
183}
184
185/// Represents a media key (as part of [`KeyCode::Media`]).
186#[repr(C)]
187pub enum MediaKeyCode {
188    /// Play media key.
189    Play,
190    /// Pause media key.
191    Pause,
192    /// Play/Pause media key.
193    PlayPause,
194    /// Reverse media key.
195    Reverse,
196    /// Stop media key.
197    Stop,
198    /// Fast-forward media key.
199    FastForward,
200    /// Rewind media key.
201    Rewind,
202    /// Next-track media key.
203    TrackNext,
204    /// Previous-track media key.
205    TrackPrevious,
206    /// Record media key.
207    Record,
208    /// Lower-volume media key.
209    LowerVolume,
210    /// Raise-volume media key.
211    RaiseVolume,
212    /// Mute media key.
213    MuteVolume,
214}
215
216/// Represents a modifier key (as part of [`KeyCode::Modifier`]).
217#[repr(C)]
218pub enum ModifierKeyCode {
219    /// Left Shift key.
220    LeftShift,
221    /// Left Control key.
222    LeftControl,
223    /// Left Alt key.
224    LeftAlt,
225    /// Left Super key.
226    LeftSuper,
227    /// Left Hyper key.
228    LeftHyper,
229    /// Left Meta key.
230    LeftMeta,
231    /// Right Shift key.
232    RightShift,
233    /// Right Control key.
234    RightControl,
235    /// Right Alt key.
236    RightAlt,
237    /// Right Super key.
238    RightSuper,
239    /// Right Hyper key.
240    RightHyper,
241    /// Right Meta key.
242    RightMeta,
243    /// Iso Level3 Shift key.
244    IsoLevel3Shift,
245    /// Iso Level5 Shift key.
246    IsoLevel5Shift,
247}
248
249/// Represents a key.
250#[repr(C)]
251pub enum KeyCode {
252    /// Backspace key.
253    Backspace,
254    /// Enter key.
255    Enter,
256    /// Left arrow key.
257    Left,
258    /// Right arrow key.
259    Right,
260    /// Up arrow key.
261    Up,
262    /// Down arrow key.
263    Down,
264    /// Home key.
265    Home,
266    /// End key.
267    End,
268    /// Page up key.
269    PageUp,
270    /// Page down key.
271    PageDown,
272    /// Tab key.
273    Tab,
274    /// Shift + Tab key.
275    BackTab,
276    /// Delete key.
277    Delete,
278    /// Insert key.
279    Insert,
280    /// F key.
281    ///
282    /// `KeyCode::F(1)` represents F1 key, etc.
283    F(u8),
284    /// A character.
285    ///
286    /// `KeyCode::Char('c')` represents `c` character, etc.
287    Char(char),
288    /// Null.
289    Null,
290    /// Escape key.
291    Esc,
292    /// Caps Lock key.
293    ///
294    /// **Note:** this key can only be read if
295    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
296    /// [`PushKeyboardEnhancementFlags`].
297    CapsLock,
298    /// Scroll Lock key.
299    ///
300    /// **Note:** this key can only be read if
301    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
302    /// [`PushKeyboardEnhancementFlags`].
303    ScrollLock,
304    /// Num Lock key.
305    ///
306    /// **Note:** this key can only be read if
307    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
308    /// [`PushKeyboardEnhancementFlags`].
309    NumLock,
310    /// Print Screen key.
311    ///
312    /// **Note:** this key can only be read if
313    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
314    /// [`PushKeyboardEnhancementFlags`].
315    PrintScreen,
316    /// Pause key.
317    ///
318    /// **Note:** this key can only be read if
319    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
320    /// [`PushKeyboardEnhancementFlags`].
321    Pause,
322    /// Menu key.
323    ///
324    /// **Note:** this key can only be read if
325    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
326    /// [`PushKeyboardEnhancementFlags`].
327    Menu,
328    /// The "Begin" key (often mapped to the 5 key when Num Lock is turned on).
329    ///
330    /// **Note:** this key can only be read if
331    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
332    /// [`PushKeyboardEnhancementFlags`].
333    KeypadBegin,
334    /// A media key.
335    ///
336    /// **Note:** these keys can only be read if
337    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
338    /// [`PushKeyboardEnhancementFlags`].
339    Media(MediaKeyCode),
340    /// A modifier key.
341    ///
342    /// **Note:** these keys can only be read if **both**
343    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] and
344    /// [`KeyboardEnhancementFlags::REPORT_ALL_KEYS_AS_ESCAPE_CODES`] have been enabled with
345    /// [`PushKeyboardEnhancementFlags`].
346    Modifier(ModifierKeyCode),
347}
348
349bitflags! {
350    /// Represents key modifiers (shift, control, alt, etc.).
351    ///
352    /// **Note:** `SUPER`, `HYPER`, and `META` can only be read if
353    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
354    /// [`PushKeyboardEnhancementFlags`].
355    #[repr(C)]
356    pub struct KeyModifiers: u8 {
357        const SHIFT = 0b0000_0001;
358        const CONTROL = 0b0000_0010;
359        const ALT = 0b0000_0100;
360        const SUPER = 0b0000_1000;
361        const HYPER = 0b0001_0000;
362        const META = 0b0010_0000;
363        const NONE = 0b0000_0000;
364    }
365}
366
367/// Represents a keyboard event kind.
368#[repr(C)]
369pub enum KeyEventKind {
370    Press,
371    Repeat,
372    Release,
373}
374
375bitflags! {
376    /// Represents extra state about the key event.
377    ///
378    /// **Note:** This state can only be read if
379    /// [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
380    /// [`crossterm_event_push_keyboard_enhancement_flags`].
381    #[repr(C)]
382    pub struct KeyEventState: u8 {
383        /// The key event origins from the keypad.
384        const KEYPAD = 0b0000_0001;
385        /// Caps Lock was enabled for this key event.
386        ///
387        /// **Note:** this is set for the initial press of Caps Lock itself.
388        const CAPS_LOCK = 0b0000_1000;
389        /// Num Lock was enabled for this key event.
390        ///
391        /// **Note:** this is set for the initial press of Num Lock itself.
392        const NUM_LOCK = 0b0000_1000;
393        const NONE = 0b0000_0000;
394    }
395}
396
397/// Represents a key event.
398#[repr(C)]
399pub struct KeyEvent {
400    /// The key itself.
401    pub code: KeyCode,
402    /// Additional key modifiers.
403    pub modifiers: KeyModifiers,
404    /// Kind of event.
405    ///
406    /// Only set if:
407    /// - Unix: [`KeyboardEnhancementFlags::REPORT_EVENT_TYPES`] has been enabled with [`crossterm_event_push_keyboard_enhancement_flags`].
408    /// - Windows: always
409    pub kind: KeyEventKind,
410    /// Keyboard state.
411    ///
412    /// Only set if [`KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES`] has been enabled with
413    /// [`PushKeyboardEnhancementFlags`].
414    pub state: KeyEventState,
415}
416
417/// A mouse event kind.
418///
419/// # Platform-specific Notes
420///
421/// ## Mouse Buttons
422///
423/// Some platforms/terminals do not report mouse button for the
424/// `MouseEventKind::Up` and `MouseEventKind::Drag` events. `MouseButton::Left`
425/// is returned if we don't know which button was used.
426#[repr(C)]
427pub enum MouseEventKind {
428    /// Pressed mouse button. Contains the button that was pressed.
429    Down(MouseButton),
430    /// Released mouse button. Contains the button that was released.
431    Up(MouseButton),
432    /// Moved the mouse cursor while pressing the contained mouse button.
433    Drag(MouseButton),
434    /// Moved the mouse cursor while not pressing a mouse button.
435    Moved,
436    /// Scrolled mouse wheel downwards (towards the user).
437    ScrollDown,
438    /// Scrolled mouse wheel upwards (away from the user).
439    ScrollUp,
440}
441
442/// Represents a mouse button.
443#[repr(C)]
444pub enum MouseButton {
445    /// Left mouse button.
446    Left,
447    /// Right mouse button.
448    Right,
449    /// Middle mouse button.
450    Middle,
451}
452
453/// Represents a mouse event.
454///
455/// # Platform-specific Notes
456///
457/// ## Mouse Buttons
458///
459/// Some platforms/terminals do not report mouse button for the
460/// `MouseEventKind::Up` and `MouseEventKind::Drag` events. `MouseButton::Left`
461/// is returned if we don't know which button was used.
462///
463/// ## Key Modifiers
464///
465/// Some platforms/terminals does not report all key modifiers
466/// combinations for all mouse event types. For example - macOS reports
467/// `Ctrl` + left mouse button click as a right mouse button click.
468#[repr(C)]
469pub struct MouseEvent {
470    /// The kind of mouse event that was caused.
471    pub kind: MouseEventKind,
472    /// The col that the event occurred on.
473    pub col: u16,
474    /// The row that the event occurred on.
475    pub row: u16,
476    /// The key modifiers active when the event occurred.
477    pub modifiers: KeyModifiers,
478}
479
480/// Represents an event.
481#[repr(C)]
482pub enum Event {
483    /// The terminal gained focus
484    FocusGained,
485    /// The terminal lost focus
486    FocusLost,
487    /// A single key event with additional pressed modifiers.
488    Key(KeyEvent),
489    /// A single mouse event with additional pressed modifiers.
490    Mouse(MouseEvent),
491    /// A string that was pasted into the terminal. Only emitted if bracketed paste has been
492    /// enabled.
493    Paste(*const libc::c_char),
494    /// An resize event with new dimensions after resize (cols, rows).
495    /// **Note** that resize events can occur in batches.
496    Resize(u16, u16),
497}
498
499/// Checks if there is an [`Event`] available.
500///
501/// Returns `1` if an [`Event`] is available, it returns `0` if no [`Event`] is available, returns -1 if error has occurred.
502///
503/// When it returns `1`, that guarantees that subsequent call to the [`crossterm_event_read`] function
504/// won't block.
505///
506/// # Arguments
507///
508/// * `timeout_secs` - maximum waiting time for event availability
509/// * `timeout_nanos` - maximum waiting time for event availability
510#[no_mangle]
511pub extern "C" fn crossterm_event_poll(secs: u64, nanos: u32) -> libc::c_int {
512    let r = crossterm::event::poll(std::time::Duration::new(secs, nanos)).c_unwrap();
513    if crossterm_has_error() {
514        r!()
515    } else {
516        r.into()
517    }
518}
519
520/// Reads a single [`Event`] as a UTF-8 JSON string.
521/// If error occurs during read, error will be returned as a UTF-8 JSON string.
522///
523/// This function blocks until an [`Event`] is available.
524/// Combine it with the [`crossterm_event_poll`] function to get non-blocking reads.
525///
526/// Caller is responsible for memory associated with string buffer.
527/// Use [`crossterm_free_c_char`] to free data.
528#[no_mangle]
529pub extern "C" fn crossterm_event_read() -> *const libc::c_char {
530    let json_value = match crossterm::event::read() {
531        Ok(evt) => serde_json::to_value(&evt).unwrap_or_else(|e| {
532            serde_json::json!({
533                "error": format!("Unable to convert event {:?} to JSON: {:?}", evt, e),
534            })
535        }),
536        Err(e) => serde_json::json!({
537            "error": format!("Something went wrong with crossterm_event_read(): {:?}", e),
538        }),
539    };
540
541    let json_string = serde_json::to_string(&json_value).unwrap_or_else(|e| {
542        serde_json::json!({
543            "error": format!("Unable to convert JSON value to string: {:?}", e),
544        })
545        .to_string()
546    });
547    convert_string_to_c_char(json_string)
548}
549
550/// Use `std::io::stdout()` for all commands
551#[no_mangle]
552pub extern "C" fn crossterm_use_stdout() {
553    USE_STDOUT.with(|io| {
554        *io.borrow_mut() = true;
555    });
556}
557
558/// Use `std::io::stderr()` for all commands
559#[no_mangle]
560pub extern "C" fn crossterm_use_stderr() {
561    USE_STDOUT.with(|io| {
562        *io.borrow_mut() = false;
563    });
564}
565
566/// Sleeps for n seconds where n is the argument to this function
567#[no_mangle]
568pub extern "C" fn crossterm_sleep(seconds: f64) {
569    let duration = std::time::Duration::from_nanos((seconds * 1e9).round() as u64);
570    std::thread::sleep(duration);
571}
572
573/// Set cursor position (col, row)
574///
575/// # Notes
576/// * Top left cell is represented as `0,0`.
577#[no_mangle]
578pub extern "C" fn crossterm_cursor_position_set(col: u16, row: u16) -> libc::c_int {
579    queue!(io!(), crossterm::cursor::MoveTo(col, row)).c_unwrap();
580    r!()
581}
582
583/// Get cursor position (col, row)
584///
585/// # Notes
586/// * Top left cell is represented as `0,0`.
587#[no_mangle]
588pub extern "C" fn crossterm_cursor_position(col: &mut u16, row: &mut u16) -> libc::c_int {
589    let (c, r) = crossterm::cursor::position().c_unwrap();
590    *col = c;
591    *row = r;
592    r!()
593}
594
595/// Moves the terminal cursor to the given position (col, row).
596///
597/// # Notes
598/// * Top left cell is represented as `0,0`.
599#[no_mangle]
600pub extern "C" fn crossterm_cursor_move_to(col: u16, row: u16) -> libc::c_int {
601    queue!(io!(), crossterm::cursor::MoveTo(col, row)).c_unwrap();
602    r!()
603}
604
605/// Moves the terminal cursor down the given number of lines and moves it to the first col.
606///
607/// # Notes
608/// * This command is 1 based, meaning `crossterm_cursor_move_to_next_line(1)` moves to the next line.
609/// * Most terminals default 0 argument to 1.
610#[no_mangle]
611pub extern "C" fn crossterm_cursor_move_to_next_line(n: u16) -> libc::c_int {
612    queue!(io!(), crossterm::cursor::MoveToNextLine(n)).c_unwrap();
613    r!()
614}
615
616/// Moves the terminal cursor up the given number of lines and moves it to the first col.
617#[no_mangle]
618pub extern "C" fn crossterm_cursor_move_to_previous_line(n: u16) -> libc::c_int {
619    queue!(io!(), crossterm::cursor::MoveToPreviousLine(n)).c_unwrap();
620    r!()
621}
622
623/// Moves the terminal cursor to the given col on the current row.
624#[no_mangle]
625pub extern "C" fn crossterm_cursor_move_to_column(col: u16) -> libc::c_int {
626    queue!(io!(), crossterm::cursor::MoveToColumn(col)).c_unwrap();
627    r!()
628}
629
630/// Moves the terminal cursor to the given row on the current col.
631#[no_mangle]
632pub extern "C" fn crossterm_cursor_move_to_row(row: u16) -> libc::c_int {
633    queue!(io!(), crossterm::cursor::MoveToRow(row)).c_unwrap();
634    r!()
635}
636
637/// Moves the terminal cursor a given number of rows up.
638#[no_mangle]
639pub extern "C" fn crossterm_cursor_move_up(rows: u16) -> libc::c_int {
640    queue!(io!(), crossterm::cursor::MoveUp(rows)).c_unwrap();
641    r!()
642}
643
644/// Moves the terminal cursor a given number of cols to the right.
645#[no_mangle]
646pub extern "C" fn crossterm_cursor_move_right(cols: u16) -> libc::c_int {
647    queue!(io!(), crossterm::cursor::MoveRight(cols)).c_unwrap();
648    r!()
649}
650
651/// Moves the terminal cursor a given number of rows down.
652#[no_mangle]
653pub extern "C" fn crossterm_cursor_move_down(rows: u16) -> libc::c_int {
654    queue!(io!(), crossterm::cursor::MoveDown(rows)).c_unwrap();
655    r!()
656}
657
658/// Moves the terminal cursor a given number of cols to the left.
659#[no_mangle]
660pub extern "C" fn crossterm_cursor_move_left(cols: u16) -> libc::c_int {
661    queue!(io!(), crossterm::cursor::MoveLeft(cols)).c_unwrap();
662    r!()
663}
664
665/// Saves the current terminal cursor position.
666#[no_mangle]
667pub extern "C" fn crossterm_cursor_save_position() -> libc::c_int {
668    queue!(io!(), crossterm::cursor::SavePosition).c_unwrap();
669    r!()
670}
671
672/// Restores the saved terminal cursor position.
673#[no_mangle]
674pub extern "C" fn crossterm_cursor_restore_position() -> libc::c_int {
675    queue!(io!(), crossterm::cursor::RestorePosition).c_unwrap();
676    r!()
677}
678
679/// Hides the terminal cursor.
680#[no_mangle]
681pub extern "C" fn crossterm_cursor_hide() -> libc::c_int {
682    queue!(io!(), crossterm::cursor::Hide).c_unwrap();
683    r!()
684}
685
686/// Shows the terminal cursor.
687#[no_mangle]
688pub extern "C" fn crossterm_cursor_show() -> libc::c_int {
689    queue!(io!(), crossterm::cursor::Show).c_unwrap();
690    r!()
691}
692
693/// Enables blinking of the terminal cursor.
694#[no_mangle]
695pub extern "C" fn crossterm_cursor_enable_blinking() -> libc::c_int {
696    queue!(io!(), crossterm::cursor::EnableBlinking).c_unwrap();
697    r!()
698}
699
700/// Disables blinking of the terminal cursor.
701#[no_mangle]
702pub extern "C" fn crossterm_cursor_disable_blinking() -> libc::c_int {
703    queue!(io!(), crossterm::cursor::DisableBlinking).c_unwrap();
704    r!()
705}
706
707/// Style of the cursor.
708/// It uses two types of escape codes, one to control blinking, and the other the shape.
709#[repr(C)]
710#[derive(Clone, Copy)]
711pub enum CursorStyle {
712    /// Default cursor shape configured by the user.
713    DefaultUserShape,
714    /// A blinking block cursor shape (â– ).
715    BlinkingBlock,
716    /// A non blinking block cursor shape (inverse of `BlinkingBlock`).
717    SteadyBlock,
718    /// A blinking underscore cursor shape(_).
719    BlinkingUnderScore,
720    /// A non blinking underscore cursor shape (inverse of `BlinkingUnderScore`).
721    SteadyUnderScore,
722    /// A blinking cursor bar shape (|)
723    BlinkingBar,
724    /// A steady cursor bar shape (inverse of `BlinkingBar`).
725    SteadyBar,
726}
727
728/// Sets the style of the cursor.
729#[no_mangle]
730pub extern "C" fn crossterm_cursor_style(cursor_style: CursorStyle) -> libc::c_int {
731    let cs = match cursor_style {
732        CursorStyle::DefaultUserShape => crossterm::cursor::SetCursorStyle::DefaultUserShape,
733        CursorStyle::BlinkingBlock => crossterm::cursor::SetCursorStyle::BlinkingBlock,
734        CursorStyle::SteadyBlock => crossterm::cursor::SetCursorStyle::SteadyBlock,
735        CursorStyle::BlinkingUnderScore => crossterm::cursor::SetCursorStyle::BlinkingUnderScore,
736        CursorStyle::SteadyUnderScore => crossterm::cursor::SetCursorStyle::SteadyUnderScore,
737        CursorStyle::BlinkingBar => crossterm::cursor::SetCursorStyle::BlinkingBar,
738        CursorStyle::SteadyBar => crossterm::cursor::SetCursorStyle::SteadyBar,
739    };
740    queue!(io!(), cs).c_unwrap();
741    r!()
742}
743
744/// Sets the style of the cursor to default user shape.
745#[no_mangle]
746pub extern "C" fn crossterm_cursor_style_default_user_shape() -> libc::c_int {
747    queue!(io!(), crossterm::cursor::SetCursorStyle::DefaultUserShape).c_unwrap();
748    r!()
749}
750
751/// Sets the style of the cursor to a blinking block.
752#[no_mangle]
753pub extern "C" fn crossterm_cursor_style_blinking_block() -> libc::c_int {
754    queue!(io!(), crossterm::cursor::SetCursorStyle::BlinkingBlock).c_unwrap();
755    r!()
756}
757
758/// Sets the style of the cursor to a steady block.
759#[no_mangle]
760pub extern "C" fn crossterm_cursor_style_steady_block() -> libc::c_int {
761    queue!(io!(), crossterm::cursor::SetCursorStyle::SteadyBlock).c_unwrap();
762    r!()
763}
764
765/// Sets the style of the cursor to a blinking underscore.
766#[no_mangle]
767pub extern "C" fn crossterm_cursor_style_blinking_underscore() -> libc::c_int {
768    queue!(io!(), crossterm::cursor::SetCursorStyle::BlinkingUnderScore).c_unwrap();
769    r!()
770}
771
772/// Sets the style of the cursor to a steady underscore.
773#[no_mangle]
774pub extern "C" fn crossterm_cursor_style_steady_underscore() -> libc::c_int {
775    queue!(io!(), crossterm::cursor::SetCursorStyle::SteadyUnderScore).c_unwrap();
776    r!()
777}
778
779/// Sets the style of the cursor to a blinking bar.
780#[no_mangle]
781pub extern "C" fn crossterm_cursor_style_blinking_bar() -> libc::c_int {
782    queue!(io!(), crossterm::cursor::SetCursorStyle::BlinkingBar).c_unwrap();
783    r!()
784}
785
786/// Sets the style of the cursor to a steady bar.
787#[no_mangle]
788pub extern "C" fn crossterm_cursor_style_steady_bar() -> libc::c_int {
789    queue!(io!(), crossterm::cursor::SetCursorStyle::SteadyBar).c_unwrap();
790    r!()
791}
792
793/// Enable mouse event capturing.
794#[no_mangle]
795pub extern "C" fn crossterm_event_enable_mouse_capture() -> libc::c_int {
796    queue!(io!(), crossterm::event::EnableMouseCapture).c_unwrap();
797    r!()
798}
799
800/// Disable mouse event capturing.
801#[no_mangle]
802pub extern "C" fn crossterm_event_disable_mouse_capture() -> libc::c_int {
803    queue!(io!(), crossterm::event::DisableMouseCapture).c_unwrap();
804    r!()
805}
806
807/// Represents special flags that tell compatible terminals to add extra information to keyboard events.
808///
809/// See <https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement> for more information.
810///
811/// Alternate keys and Unicode codepoints are not yet supported by crossterm.
812#[repr(u8)]
813pub enum KeyboardEnhancementFlags {
814    /// Represent Escape and modified keys using CSI-u sequences, so they can be unambiguously
815    /// read.
816    DisambiguateEscapeCodes = 0b0000_0001,
817    /// Add extra events with [`KeyEvent.kind`] set to [`KeyEventKind::Repeat`] or
818    /// [`KeyEventKind::Release`] when keys are autorepeated or released.
819    ReportEventTypes = 0b0000_0010,
820    // Send [alternate keycodes](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#key-codes)
821    // in addition to the base keycode. The alternate keycode overrides the base keycode in
822    // resulting `KeyEvent`s.
823    ReportAlternateKeys = 0b0000_0100,
824    /// Represent all keyboard events as CSI-u sequences. This is required to get repeat/release
825    /// events for plain-text keys.
826    ReportAllKeysAsEscapeCodes = 0b0000_1000,
827}
828
829/// Enables the [kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/),
830/// which adds extra information to keyboard events and removes ambiguity for modifier keys.
831/// It should be paired with [`crossterm_pop_keyboard_enhancement_flags`] at the end of execution.
832#[no_mangle]
833pub extern "C" fn crossterm_event_push_keyboard_enhancement_flags(flags: u8) -> libc::c_int {
834    let flags = crossterm::event::KeyboardEnhancementFlags::from_bits(flags).unwrap();
835    queue!(io!(), crossterm::event::PushKeyboardEnhancementFlags(flags)).c_unwrap();
836    r!()
837}
838
839/// Disables extra kinds of keyboard events.
840#[no_mangle]
841pub extern "C" fn crossterm_event_pop_keyboard_enhancement_flags() -> libc::c_int {
842    queue!(io!(), crossterm::event::PopKeyboardEnhancementFlags).c_unwrap();
843    r!()
844}
845
846/// Enable focus event emission.
847///
848/// It should be paired with [`crossterm_event_disable_focus_change`] at the end of execution.
849///
850/// Focus events can be captured with [`crossterm_event_read`].
851#[no_mangle]
852pub extern "C" fn crossterm_event_enable_focus_change() -> libc::c_int {
853    queue!(io!(), crossterm::event::EnableFocusChange).c_unwrap();
854    r!()
855}
856
857/// Disable focus event emission.
858#[no_mangle]
859pub extern "C" fn crossterm_event_disable_focus_change() -> libc::c_int {
860    queue!(io!(), crossterm::event::DisableFocusChange).c_unwrap();
861    r!()
862}
863
864/// Enables [bracketed paste mode](https://en.wikipedia.org/wiki/Bracketed-paste).
865///
866/// It should be paired with [`crossterm_event_disable_bracketed_paste`] at the end of execution.
867///
868/// This is not supported in older Windows terminals without
869/// [virtual terminal sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences).
870#[no_mangle]
871pub extern "C" fn crossterm_event_enable_bracketed_paste() -> libc::c_int {
872    queue!(io!(), crossterm::event::EnableBracketedPaste).c_unwrap();
873    r!()
874}
875
876/// Disables bracketed paste mode.
877#[no_mangle]
878pub extern "C" fn crossterm_event_disable_bracketed_paste() -> libc::c_int {
879    queue!(io!(), crossterm::event::DisableBracketedPaste).c_unwrap();
880    r!()
881}
882
883#[repr(C)]
884pub enum Attribute {
885    /// Resets all the attributes.
886    Reset,
887    /// Increases the text intensity.
888    Bold,
889    /// Decreases the text intensity.
890    Dim,
891    /// Emphasises the text.
892    Italic,
893    /// Underlines the text.
894    Underlined,
895    /// Double underlines the text.
896    DoubleUnderlined,
897    /// Undercurls the text.
898    Undercurled,
899    /// Underdots the text.
900    Underdotted,
901    /// Underdashes the text.
902    Underdashed,
903    /// Makes the text blinking (< 150 per minute).
904    SlowBlink,
905    /// Makes the text blinking (>= 150 per minute).
906    RapidBlink,
907    /// Swaps foreground and background colors.
908    Reverse,
909    /// Hides the text (also known as Conceal).
910    Hidden,
911    /// Crosses the text.
912    CrossedOut,
913    /// Sets the [Fraktur](https://en.wikipedia.org/wiki/Fraktur) typeface.
914    ///
915    /// Mostly used for [mathematical alphanumeric symbols](https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols).
916    Fraktur,
917    /// Turns off the `Bold` attribute. - Inconsistent - Prefer to use NormalIntensity
918    NoBold,
919    /// Switches the text back to normal intensity (no bold, italic).
920    NormalIntensity,
921    /// Turns off the `Italic` attribute.
922    NoItalic,
923    /// Turns off the `Underlined` attribute.
924    NoUnderline,
925    /// Turns off the text blinking (`SlowBlink` or `RapidBlink`).
926    NoBlink,
927    /// Turns off the `Reverse` attribute.
928    NoReverse,
929    /// Turns off the `Hidden` attribute.
930    NoHidden,
931    /// Turns off the `CrossedOut` attribute.
932    NotCrossedOut,
933    /// Makes the text framed.
934    Framed,
935    /// Makes the text encircled.
936    Encircled,
937    /// Draws a line at the top of the text.
938    OverLined,
939    /// Turns off the `Frame` and `Encircled` attributes.
940    NotFramedOrEncircled,
941    /// Turns off the `OverLined` attribute.
942    NotOverLined,
943}
944
945impl From<Attribute> for crossterm::style::Attribute {
946    fn from(value: Attribute) -> Self {
947        match value {
948            Attribute::Reset => crossterm::style::Attribute::Reset,
949            Attribute::Bold => crossterm::style::Attribute::Bold,
950            Attribute::Dim => crossterm::style::Attribute::Dim,
951            Attribute::Italic => crossterm::style::Attribute::Italic,
952            Attribute::Underlined => crossterm::style::Attribute::Underlined,
953            Attribute::DoubleUnderlined => crossterm::style::Attribute::DoubleUnderlined,
954            Attribute::Undercurled => crossterm::style::Attribute::Undercurled,
955            Attribute::Underdotted => crossterm::style::Attribute::Underdotted,
956            Attribute::Underdashed => crossterm::style::Attribute::Underdashed,
957            Attribute::SlowBlink => crossterm::style::Attribute::SlowBlink,
958            Attribute::RapidBlink => crossterm::style::Attribute::RapidBlink,
959            Attribute::Reverse => crossterm::style::Attribute::Reverse,
960            Attribute::Hidden => crossterm::style::Attribute::Hidden,
961            Attribute::CrossedOut => crossterm::style::Attribute::CrossedOut,
962            Attribute::Fraktur => crossterm::style::Attribute::Fraktur,
963            Attribute::NoBold => crossterm::style::Attribute::NoBold,
964            Attribute::NormalIntensity => crossterm::style::Attribute::NormalIntensity,
965            Attribute::NoItalic => crossterm::style::Attribute::NoItalic,
966            Attribute::NoUnderline => crossterm::style::Attribute::NoUnderline,
967            Attribute::NoBlink => crossterm::style::Attribute::NoBlink,
968            Attribute::NoReverse => crossterm::style::Attribute::NoReverse,
969            Attribute::NoHidden => crossterm::style::Attribute::NoHidden,
970            Attribute::NotCrossedOut => crossterm::style::Attribute::NotCrossedOut,
971            Attribute::Framed => crossterm::style::Attribute::Framed,
972            Attribute::Encircled => crossterm::style::Attribute::Encircled,
973            Attribute::OverLined => crossterm::style::Attribute::OverLined,
974            Attribute::NotFramedOrEncircled => crossterm::style::Attribute::NotFramedOrEncircled,
975            Attribute::NotOverLined => crossterm::style::Attribute::NotOverLined,
976        }
977    }
978}
979
980/// a bitset for all possible attributes
981#[repr(C)]
982#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
983pub struct Attributes(u32);
984
985/// Sets an attribute.
986///
987/// See [`Attribute`] for more info.
988#[no_mangle]
989pub extern "C" fn crossterm_style_attribute(attr: Attribute) -> libc::c_int {
990    queue!(io!(), crossterm::style::SetAttribute(attr.into())).c_unwrap();
991    r!()
992}
993
994/// Sets the `Reset` attribute.
995#[no_mangle]
996pub extern "C" fn crossterm_style_attribute_reset() -> libc::c_int {
997    queue!(
998        io!(),
999        crossterm::style::SetAttribute(Attribute::Reset.into())
1000    )
1001    .c_unwrap();
1002    r!()
1003}
1004
1005/// Sets the `Bold` attribute.
1006#[no_mangle]
1007pub extern "C" fn crossterm_style_attribute_bold() -> libc::c_int {
1008    queue!(
1009        io!(),
1010        crossterm::style::SetAttribute(Attribute::Bold.into())
1011    )
1012    .c_unwrap();
1013    r!()
1014}
1015
1016/// Sets the `Dim` attribute.
1017#[no_mangle]
1018pub extern "C" fn crossterm_style_attribute_dim() -> libc::c_int {
1019    queue!(io!(), crossterm::style::SetAttribute(Attribute::Dim.into())).c_unwrap();
1020    r!()
1021}
1022
1023/// Sets the `Italic` attribute.
1024#[no_mangle]
1025pub extern "C" fn crossterm_style_attribute_italic() -> libc::c_int {
1026    queue!(
1027        io!(),
1028        crossterm::style::SetAttribute(Attribute::Italic.into())
1029    )
1030    .c_unwrap();
1031    r!()
1032}
1033
1034/// Sets the `Underlined` attribute.
1035#[no_mangle]
1036pub extern "C" fn crossterm_style_attribute_underlined() -> libc::c_int {
1037    queue!(
1038        io!(),
1039        crossterm::style::SetAttribute(Attribute::Underlined.into())
1040    )
1041    .c_unwrap();
1042    r!()
1043}
1044
1045/// Sets the `DoubleUnderlined` attribute.
1046#[no_mangle]
1047pub extern "C" fn crossterm_style_attribute_double_underlined() -> libc::c_int {
1048    queue!(
1049        io!(),
1050        crossterm::style::SetAttribute(Attribute::DoubleUnderlined.into())
1051    )
1052    .c_unwrap();
1053    r!()
1054}
1055
1056/// Sets the `Undercurled` attribute.
1057#[no_mangle]
1058pub extern "C" fn crossterm_style_attribute_undercurled() -> libc::c_int {
1059    queue!(
1060        io!(),
1061        crossterm::style::SetAttribute(Attribute::Undercurled.into())
1062    )
1063    .c_unwrap();
1064    r!()
1065}
1066
1067/// Sets the `Underdotted` attribute.
1068#[no_mangle]
1069pub extern "C" fn crossterm_style_attribute_underdotted() -> libc::c_int {
1070    queue!(
1071        io!(),
1072        crossterm::style::SetAttribute(Attribute::Underdotted.into())
1073    )
1074    .c_unwrap();
1075    r!()
1076}
1077
1078/// Sets the `Underdashed` attribute.
1079#[no_mangle]
1080pub extern "C" fn crossterm_style_attribute_underdashed() -> libc::c_int {
1081    queue!(
1082        io!(),
1083        crossterm::style::SetAttribute(Attribute::Underdashed.into())
1084    )
1085    .c_unwrap();
1086    r!()
1087}
1088
1089/// Sets the `SlowBlink` attribute.
1090#[no_mangle]
1091pub extern "C" fn crossterm_style_attribute_slow_blink() -> libc::c_int {
1092    queue!(
1093        io!(),
1094        crossterm::style::SetAttribute(Attribute::SlowBlink.into())
1095    )
1096    .c_unwrap();
1097    r!()
1098}
1099
1100/// Sets the `RapidBlink` attribute.
1101#[no_mangle]
1102pub extern "C" fn crossterm_style_attribute_rapid_blink() -> libc::c_int {
1103    queue!(
1104        io!(),
1105        crossterm::style::SetAttribute(Attribute::RapidBlink.into())
1106    )
1107    .c_unwrap();
1108    r!()
1109}
1110
1111/// Sets the `Reverse` attribute.
1112#[no_mangle]
1113pub extern "C" fn crossterm_style_attribute_reverse() -> libc::c_int {
1114    queue!(
1115        io!(),
1116        crossterm::style::SetAttribute(Attribute::Reverse.into())
1117    )
1118    .c_unwrap();
1119    r!()
1120}
1121
1122/// Sets the `Hidden` attribute.
1123#[no_mangle]
1124pub extern "C" fn crossterm_style_attribute_hidden() -> libc::c_int {
1125    queue!(
1126        io!(),
1127        crossterm::style::SetAttribute(Attribute::Hidden.into())
1128    )
1129    .c_unwrap();
1130    r!()
1131}
1132
1133/// Sets the `CrossedOut` attribute.
1134#[no_mangle]
1135pub extern "C" fn crossterm_style_attribute_crossed_out() -> libc::c_int {
1136    queue!(
1137        io!(),
1138        crossterm::style::SetAttribute(Attribute::CrossedOut.into())
1139    )
1140    .c_unwrap();
1141    r!()
1142}
1143
1144/// Sets the `Fraktur` attribute.
1145#[no_mangle]
1146pub extern "C" fn crossterm_style_attribute_fraktur() -> libc::c_int {
1147    queue!(
1148        io!(),
1149        crossterm::style::SetAttribute(Attribute::Fraktur.into())
1150    )
1151    .c_unwrap();
1152    r!()
1153}
1154
1155/// Sets the `NoBold` attribute.
1156#[no_mangle]
1157pub extern "C" fn crossterm_style_attribute_no_bold() -> libc::c_int {
1158    queue!(
1159        io!(),
1160        crossterm::style::SetAttribute(Attribute::NoBold.into())
1161    )
1162    .c_unwrap();
1163    r!()
1164}
1165
1166/// Sets the `NormalIntensity` attribute.
1167#[no_mangle]
1168pub extern "C" fn crossterm_style_attribute_normal_intensity() -> libc::c_int {
1169    queue!(
1170        io!(),
1171        crossterm::style::SetAttribute(Attribute::NormalIntensity.into())
1172    )
1173    .c_unwrap();
1174    r!()
1175}
1176
1177/// Sets the `NoItalic` attribute.
1178#[no_mangle]
1179pub extern "C" fn crossterm_style_attribute_no_italic() -> libc::c_int {
1180    queue!(
1181        io!(),
1182        crossterm::style::SetAttribute(Attribute::NoItalic.into())
1183    )
1184    .c_unwrap();
1185    r!()
1186}
1187
1188/// Sets the `NoUnderline` attribute.
1189#[no_mangle]
1190pub extern "C" fn crossterm_style_attribute_no_underline() -> libc::c_int {
1191    queue!(
1192        io!(),
1193        crossterm::style::SetAttribute(Attribute::NoUnderline.into())
1194    )
1195    .c_unwrap();
1196    r!()
1197}
1198
1199/// Sets the `NoBlink` attribute.
1200#[no_mangle]
1201pub extern "C" fn crossterm_style_attribute_no_blink() -> libc::c_int {
1202    queue!(
1203        io!(),
1204        crossterm::style::SetAttribute(Attribute::NoBlink.into())
1205    )
1206    .c_unwrap();
1207    r!()
1208}
1209
1210/// Sets the `NoReverse` attribute.
1211#[no_mangle]
1212pub extern "C" fn crossterm_style_attribute_no_reverse() -> libc::c_int {
1213    queue!(
1214        io!(),
1215        crossterm::style::SetAttribute(Attribute::NoReverse.into())
1216    )
1217    .c_unwrap();
1218    r!()
1219}
1220
1221/// Sets the `NoHidden` attribute.
1222#[no_mangle]
1223pub extern "C" fn crossterm_style_attribute_no_hidden() -> libc::c_int {
1224    queue!(
1225        io!(),
1226        crossterm::style::SetAttribute(Attribute::NoHidden.into())
1227    )
1228    .c_unwrap();
1229    r!()
1230}
1231
1232/// Sets the `NotCrossedOut` attribute.
1233#[no_mangle]
1234pub extern "C" fn crossterm_style_attribute_not_crossed_out() -> libc::c_int {
1235    queue!(
1236        io!(),
1237        crossterm::style::SetAttribute(Attribute::NotCrossedOut.into())
1238    )
1239    .c_unwrap();
1240    r!()
1241}
1242
1243/// Print char to stdout
1244#[no_mangle]
1245pub extern "C" fn crossterm_style_print_char(c: u32) -> libc::c_int {
1246    if let Some(ch) = std::char::from_u32(c) {
1247        queue!(io!(), crossterm::style::Print(ch)).c_unwrap();
1248        r!()
1249    } else {
1250        set_last_error(anyhow::anyhow!("Unable to convert {} to valid char", c));
1251        -1
1252    }
1253}
1254
1255/// Print string to stdout
1256///
1257/// # Safety
1258///
1259/// This function takes a raw pointer as argument. As such, the caller must ensure that:
1260/// - The `title` pointer points to a valid null-terminated string.
1261/// - This function borrows a slice to a valid null-terminated string and the memory referenced by `title` won't be deallocated or modified for the duration of the function call..
1262/// - The `title` pointer is correctly aligned and `title` points to an initialized memory.
1263///
1264/// If these conditions are not met, the behavior is undefined.
1265#[no_mangle]
1266pub unsafe extern "C" fn crossterm_style_print_string(s: *const libc::c_char) -> libc::c_int {
1267    if s.is_null() {
1268        RESULT.with(|r| {
1269            *r.borrow_mut() = -1;
1270        });
1271        set_last_error(anyhow::anyhow!("Received null pointer for print string"));
1272        return r!();
1273    };
1274    let c_str: &std::ffi::CStr = std::ffi::CStr::from_ptr(s);
1275    if let Ok(string) = c_str.to_str() {
1276        queue!(io!(), crossterm::style::Print(string)).c_unwrap();
1277        r!()
1278    } else {
1279        RESULT.with(|r| {
1280            *r.borrow_mut() = -1;
1281        });
1282        set_last_error(anyhow::anyhow!(
1283            "Received invalid UTF-8 string for print string"
1284        ));
1285        r!()
1286    }
1287}
1288
1289/// Print string to stdout
1290///
1291/// # Safety
1292///
1293/// This function takes a raw pointer as argument. As such, the caller must ensure that:
1294/// - The `title` pointer points to a valid null-terminated string.
1295/// - This function borrows a slice to a valid null-terminated string and the memory referenced by `title` won't be deallocated or modified for the duration of the function call..
1296/// - The `title` pointer is correctly aligned and `title` points to an initialized memory.
1297///
1298/// If these conditions are not met, the behavior is undefined.
1299#[no_mangle]
1300pub unsafe extern "C" fn crossterm_style_print(s: *const libc::c_char) -> libc::c_int {
1301    crossterm_style_print_string(s)
1302}
1303
1304#[repr(C)]
1305#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
1306pub enum Color {
1307    /// Resets the terminal color.
1308    Reset,
1309    /// Black color.
1310    Black,
1311    /// Dark grey color.
1312    DarkGrey,
1313    /// Light red color.
1314    Red,
1315    /// Dark red color.
1316    DarkRed,
1317    /// Light green color.
1318    Green,
1319    /// Dark green color.
1320    DarkGreen,
1321    /// Light yellow color.
1322    Yellow,
1323    /// Dark yellow color.
1324    DarkYellow,
1325    /// Light blue color.
1326    Blue,
1327    /// Dark blue color.
1328    DarkBlue,
1329    /// Light magenta color.
1330    Magenta,
1331    /// Dark magenta color.
1332    DarkMagenta,
1333    /// Light cyan color.
1334    Cyan,
1335    /// Dark cyan color.
1336    DarkCyan,
1337    /// White color.
1338    White,
1339    /// Grey color.
1340    Grey,
1341    /// An RGB color. See [RGB color model](https://en.wikipedia.org/wiki/RGB_color_model) for more info.
1342    ///
1343    /// Most UNIX terminals and Windows 10 supported only.
1344    Rgb { r: u8, g: u8, b: u8 },
1345    /// An ANSI color. See [256 colors - cheat sheet](https://jonasjacek.github.io/colors/) for more info.
1346    ///
1347    /// Most UNIX terminals and Windows 10 supported only.
1348    AnsiValue(u8),
1349}
1350
1351impl From<Color> for crossterm::style::Color {
1352    fn from(color: Color) -> Self {
1353        match color {
1354            Color::Reset => crossterm::style::Color::Reset,
1355            Color::Black => crossterm::style::Color::Black,
1356            Color::DarkGrey => crossterm::style::Color::DarkGrey,
1357            Color::Red => crossterm::style::Color::Red,
1358            Color::DarkRed => crossterm::style::Color::DarkRed,
1359            Color::Green => crossterm::style::Color::Green,
1360            Color::DarkGreen => crossterm::style::Color::DarkGreen,
1361            Color::Yellow => crossterm::style::Color::Yellow,
1362            Color::DarkYellow => crossterm::style::Color::DarkYellow,
1363            Color::Blue => crossterm::style::Color::Blue,
1364            Color::DarkBlue => crossterm::style::Color::DarkBlue,
1365            Color::Magenta => crossterm::style::Color::Magenta,
1366            Color::DarkMagenta => crossterm::style::Color::DarkMagenta,
1367            Color::Cyan => crossterm::style::Color::Cyan,
1368            Color::DarkCyan => crossterm::style::Color::DarkCyan,
1369            Color::White => crossterm::style::Color::White,
1370            Color::Grey => crossterm::style::Color::Grey,
1371            Color::Rgb { r, g, b } => crossterm::style::Color::Rgb { r, g, b },
1372            Color::AnsiValue(v) => crossterm::style::Color::AnsiValue(v),
1373        }
1374    }
1375}
1376
1377/// Sets the the background color.
1378///
1379/// See [`Color`] for more info.
1380#[no_mangle]
1381pub extern "C" fn crossterm_style_background_color(color: Color) -> libc::c_int {
1382    queue!(io!(), crossterm::style::SetBackgroundColor(color.into())).c_unwrap();
1383    r!()
1384}
1385
1386/// Sets the the background color in RGB.
1387#[no_mangle]
1388pub extern "C" fn crossterm_style_background_color_rgb(r: u8, g: u8, b: u8) -> libc::c_int {
1389    crossterm_style_background_color(Color::Rgb { r, g, b })
1390}
1391
1392/// Sets the the background color to an ANSI value.
1393#[no_mangle]
1394pub extern "C" fn crossterm_style_background_color_ansi(value: u8) -> libc::c_int {
1395    crossterm_style_background_color(Color::AnsiValue(value))
1396}
1397
1398/// Sets the the background color to Reset.
1399#[no_mangle]
1400pub extern "C" fn crossterm_style_background_color_reset() -> libc::c_int {
1401    crossterm_style_background_color(Color::Reset)
1402}
1403
1404/// Sets the the background color to Black.
1405#[no_mangle]
1406pub extern "C" fn crossterm_style_background_color_black() -> libc::c_int {
1407    crossterm_style_background_color(Color::Black)
1408}
1409
1410/// Sets the the background color to DarkGrey.
1411#[no_mangle]
1412pub extern "C" fn crossterm_style_background_color_dark_grey() -> libc::c_int {
1413    crossterm_style_background_color(Color::DarkGrey)
1414}
1415
1416/// Sets the the background color to Red.
1417#[no_mangle]
1418pub extern "C" fn crossterm_style_background_color_red() -> libc::c_int {
1419    crossterm_style_background_color(Color::Red)
1420}
1421
1422/// Sets the the background color to DarkRed.
1423#[no_mangle]
1424pub extern "C" fn crossterm_style_background_color_dark_red() -> libc::c_int {
1425    crossterm_style_background_color(Color::DarkRed)
1426}
1427
1428/// Sets the the background color to Green.
1429#[no_mangle]
1430pub extern "C" fn crossterm_style_background_color_green() -> libc::c_int {
1431    crossterm_style_background_color(Color::Green)
1432}
1433
1434/// Sets the the background color to DarkGreen.
1435#[no_mangle]
1436pub extern "C" fn crossterm_style_background_color_dark_green() -> libc::c_int {
1437    crossterm_style_background_color(Color::DarkGreen)
1438}
1439
1440/// Sets the the background color to Yellow.
1441#[no_mangle]
1442pub extern "C" fn crossterm_style_background_color_yellow() -> libc::c_int {
1443    crossterm_style_background_color(Color::Yellow)
1444}
1445
1446/// Sets the the background color to DarkYellow.
1447#[no_mangle]
1448pub extern "C" fn crossterm_style_background_color_dark_yellow() -> libc::c_int {
1449    crossterm_style_background_color(Color::DarkYellow)
1450}
1451
1452/// Sets the the background color to Blue.
1453#[no_mangle]
1454pub extern "C" fn crossterm_style_background_color_blue() -> libc::c_int {
1455    crossterm_style_background_color(Color::Blue)
1456}
1457
1458/// Sets the the background color to DarkBlue.
1459#[no_mangle]
1460pub extern "C" fn crossterm_style_background_color_dark_blue() -> libc::c_int {
1461    crossterm_style_background_color(Color::DarkBlue)
1462}
1463
1464/// Sets the the background color to Magenta.
1465#[no_mangle]
1466pub extern "C" fn crossterm_style_background_color_magenta() -> libc::c_int {
1467    crossterm_style_background_color(Color::Magenta)
1468}
1469
1470/// Sets the the background color to DarkMagenta.
1471#[no_mangle]
1472pub extern "C" fn crossterm_style_background_color_dark_magenta() -> libc::c_int {
1473    crossterm_style_background_color(Color::DarkMagenta)
1474}
1475
1476/// Sets the the background color to Cyan.
1477#[no_mangle]
1478pub extern "C" fn crossterm_style_background_color_cyan() -> libc::c_int {
1479    crossterm_style_background_color(Color::Cyan)
1480}
1481
1482/// Sets the the background color to DarkCyan.
1483#[no_mangle]
1484pub extern "C" fn crossterm_style_background_color_dark_cyan() -> libc::c_int {
1485    crossterm_style_background_color(Color::DarkCyan)
1486}
1487
1488/// Sets the the background color to White.
1489#[no_mangle]
1490pub extern "C" fn crossterm_style_background_color_white() -> libc::c_int {
1491    crossterm_style_background_color(Color::White)
1492}
1493
1494/// Sets the the background color to Grey.
1495#[no_mangle]
1496pub extern "C" fn crossterm_style_background_color_grey() -> libc::c_int {
1497    crossterm_style_background_color(Color::Grey)
1498}
1499
1500/// Sets the the foreground color.
1501///
1502/// See [`Color`] for more info.
1503#[no_mangle]
1504pub extern "C" fn crossterm_style_foreground_color(color: Color) -> libc::c_int {
1505    queue!(io!(), crossterm::style::SetForegroundColor(color.into())).c_unwrap();
1506    r!()
1507}
1508
1509/// Sets the the foreground color in RGB.
1510#[no_mangle]
1511pub extern "C" fn crossterm_style_foreground_color_rgb(r: u8, g: u8, b: u8) -> libc::c_int {
1512    crossterm_style_foreground_color(Color::Rgb { r, g, b })
1513}
1514
1515/// Sets the the foreground color to an ANSI value.
1516#[no_mangle]
1517pub extern "C" fn crossterm_style_foreground_color_ansi(value: u8) -> libc::c_int {
1518    crossterm_style_foreground_color(Color::AnsiValue(value))
1519}
1520
1521/// Sets the the foreground color to Reset.
1522#[no_mangle]
1523pub extern "C" fn crossterm_style_foreground_color_reset() -> libc::c_int {
1524    crossterm_style_foreground_color(Color::Reset)
1525}
1526
1527/// Sets the the foreground color to Black.
1528#[no_mangle]
1529pub extern "C" fn crossterm_style_foreground_color_black() -> libc::c_int {
1530    crossterm_style_foreground_color(Color::Black)
1531}
1532
1533/// Sets the the foreground color to DarkGrey.
1534#[no_mangle]
1535pub extern "C" fn crossterm_style_foreground_color_dark_grey() -> libc::c_int {
1536    crossterm_style_foreground_color(Color::DarkGrey)
1537}
1538
1539/// Sets the the foreground color to Red.
1540#[no_mangle]
1541pub extern "C" fn crossterm_style_foreground_color_red() -> libc::c_int {
1542    crossterm_style_foreground_color(Color::Red)
1543}
1544
1545/// Sets the the foreground color to DarkRed.
1546#[no_mangle]
1547pub extern "C" fn crossterm_style_foreground_color_dark_red() -> libc::c_int {
1548    crossterm_style_foreground_color(Color::DarkRed)
1549}
1550
1551/// Sets the the foreground color to Green.
1552#[no_mangle]
1553pub extern "C" fn crossterm_style_foreground_color_green() -> libc::c_int {
1554    crossterm_style_foreground_color(Color::Green)
1555}
1556
1557/// Sets the the foreground color to DarkGreen.
1558#[no_mangle]
1559pub extern "C" fn crossterm_style_foreground_color_dark_green() -> libc::c_int {
1560    crossterm_style_foreground_color(Color::DarkGreen)
1561}
1562
1563/// Sets the the foreground color to Yellow.
1564#[no_mangle]
1565pub extern "C" fn crossterm_style_foreground_color_yellow() -> libc::c_int {
1566    crossterm_style_foreground_color(Color::Yellow)
1567}
1568
1569/// Sets the the foreground color to DarkYellow.
1570#[no_mangle]
1571pub extern "C" fn crossterm_style_foreground_color_dark_yellow() -> libc::c_int {
1572    crossterm_style_foreground_color(Color::DarkYellow)
1573}
1574
1575/// Sets the the foreground color to Blue.
1576#[no_mangle]
1577pub extern "C" fn crossterm_style_foreground_color_blue() -> libc::c_int {
1578    crossterm_style_foreground_color(Color::Blue)
1579}
1580
1581/// Sets the the foreground color to DarkBlue.
1582#[no_mangle]
1583pub extern "C" fn crossterm_style_foreground_color_dark_blue() -> libc::c_int {
1584    crossterm_style_foreground_color(Color::DarkBlue)
1585}
1586
1587/// Sets the the foreground color to Magenta.
1588#[no_mangle]
1589pub extern "C" fn crossterm_style_foreground_color_magenta() -> libc::c_int {
1590    crossterm_style_foreground_color(Color::Magenta)
1591}
1592
1593/// Sets the the foreground color to DarkMagenta.
1594#[no_mangle]
1595pub extern "C" fn crossterm_style_foreground_color_dark_magenta() -> libc::c_int {
1596    crossterm_style_foreground_color(Color::DarkMagenta)
1597}
1598
1599/// Sets the the foreground color to Cyan.
1600#[no_mangle]
1601pub extern "C" fn crossterm_style_foreground_color_cyan() -> libc::c_int {
1602    crossterm_style_foreground_color(Color::Cyan)
1603}
1604
1605/// Sets the the foreground color to DarkCyan.
1606#[no_mangle]
1607pub extern "C" fn crossterm_style_foreground_color_dark_cyan() -> libc::c_int {
1608    crossterm_style_foreground_color(Color::DarkCyan)
1609}
1610
1611/// Sets the the foreground color to White.
1612#[no_mangle]
1613pub extern "C" fn crossterm_style_foreground_color_white() -> libc::c_int {
1614    crossterm_style_foreground_color(Color::White)
1615}
1616
1617/// Sets the the foreground color to Grey.
1618#[no_mangle]
1619pub extern "C" fn crossterm_style_foreground_color_grey() -> libc::c_int {
1620    crossterm_style_foreground_color(Color::Grey)
1621}
1622
1623/// Sets the the underline color.
1624///
1625/// See [`Color`] for more info.
1626#[no_mangle]
1627pub extern "C" fn crossterm_style_underline_color(color: Color) -> libc::c_int {
1628    queue!(io!(), crossterm::style::SetUnderlineColor(color.into())).c_unwrap();
1629    r!()
1630}
1631
1632/// Sets the the underline color in RGB.
1633#[no_mangle]
1634pub extern "C" fn crossterm_style_underline_color_rgb(r: u8, g: u8, b: u8) -> libc::c_int {
1635    crossterm_style_underline_color(Color::Rgb { r, g, b })
1636}
1637
1638/// Sets the the underline color to an ANSI value.
1639#[no_mangle]
1640pub extern "C" fn crossterm_style_underline_color_ansi(value: u8) -> libc::c_int {
1641    crossterm_style_underline_color(Color::AnsiValue(value))
1642}
1643
1644/// Sets the the underline color to Reset.
1645#[no_mangle]
1646pub extern "C" fn crossterm_style_underline_color_reset() -> libc::c_int {
1647    crossterm_style_underline_color(Color::Reset)
1648}
1649
1650/// Sets the the underline color to Black.
1651#[no_mangle]
1652pub extern "C" fn crossterm_style_underline_color_black() -> libc::c_int {
1653    crossterm_style_underline_color(Color::Black)
1654}
1655
1656/// Sets the the underline color to DarkGrey.
1657#[no_mangle]
1658pub extern "C" fn crossterm_style_underline_color_dark_grey() -> libc::c_int {
1659    crossterm_style_underline_color(Color::DarkGrey)
1660}
1661
1662/// Sets the the underline color to Red.
1663#[no_mangle]
1664pub extern "C" fn crossterm_style_underline_color_red() -> libc::c_int {
1665    crossterm_style_underline_color(Color::Red)
1666}
1667
1668/// Sets the the underline color to DarkRed.
1669#[no_mangle]
1670pub extern "C" fn crossterm_style_underline_color_dark_red() -> libc::c_int {
1671    crossterm_style_underline_color(Color::DarkRed)
1672}
1673
1674/// Sets the the underline color to Green.
1675#[no_mangle]
1676pub extern "C" fn crossterm_style_underline_color_green() -> libc::c_int {
1677    crossterm_style_underline_color(Color::Green)
1678}
1679
1680/// Sets the the underline color to DarkGreen.
1681#[no_mangle]
1682pub extern "C" fn crossterm_style_underline_color_dark_green() -> libc::c_int {
1683    crossterm_style_underline_color(Color::DarkGreen)
1684}
1685
1686/// Sets the the underline color to Yellow.
1687#[no_mangle]
1688pub extern "C" fn crossterm_style_underline_color_yellow() -> libc::c_int {
1689    crossterm_style_underline_color(Color::Yellow)
1690}
1691
1692/// Sets the the underline color to DarkYellow.
1693#[no_mangle]
1694pub extern "C" fn crossterm_style_underline_color_dark_yellow() -> libc::c_int {
1695    crossterm_style_underline_color(Color::DarkYellow)
1696}
1697
1698/// Sets the the underline color to Blue.
1699#[no_mangle]
1700pub extern "C" fn crossterm_style_underline_color_blue() -> libc::c_int {
1701    crossterm_style_underline_color(Color::Blue)
1702}
1703
1704/// Sets the the underline color to DarkBlue.
1705#[no_mangle]
1706pub extern "C" fn crossterm_style_underline_color_dark_blue() -> libc::c_int {
1707    crossterm_style_underline_color(Color::DarkBlue)
1708}
1709
1710/// Sets the the underline color to Magenta.
1711#[no_mangle]
1712pub extern "C" fn crossterm_style_underline_color_magenta() -> libc::c_int {
1713    crossterm_style_underline_color(Color::Magenta)
1714}
1715
1716/// Sets the the underline color to DarkMagenta.
1717#[no_mangle]
1718pub extern "C" fn crossterm_style_underline_color_dark_magenta() -> libc::c_int {
1719    crossterm_style_underline_color(Color::DarkMagenta)
1720}
1721
1722/// Sets the the underline color to Cyan.
1723#[no_mangle]
1724pub extern "C" fn crossterm_style_underline_color_cyan() -> libc::c_int {
1725    crossterm_style_underline_color(Color::Cyan)
1726}
1727
1728/// Sets the the underline color to DarkCyan.
1729#[no_mangle]
1730pub extern "C" fn crossterm_style_underline_color_dark_cyan() -> libc::c_int {
1731    crossterm_style_underline_color(Color::DarkCyan)
1732}
1733
1734/// Sets the the underline color to White.
1735#[no_mangle]
1736pub extern "C" fn crossterm_style_underline_color_white() -> libc::c_int {
1737    crossterm_style_underline_color(Color::White)
1738}
1739
1740/// Sets the the underline color to Grey.
1741#[no_mangle]
1742pub extern "C" fn crossterm_style_underline_color_grey() -> libc::c_int {
1743    crossterm_style_underline_color(Color::Grey)
1744}
1745
1746/// Resets the colors back to default.
1747#[no_mangle]
1748pub extern "C" fn crossterm_style_reset_color() -> libc::c_int {
1749    queue!(io!(), crossterm::style::ResetColor).c_unwrap();
1750    r!()
1751}
1752
1753/// Returns colors as a UTF-8 JSON string.
1754///
1755/// Null character is stored in the last location of buffer.
1756/// Caller is responsible for memory associated with string buffer.
1757/// Use [`crossterm_free_c_char`] to free data.
1758#[no_mangle]
1759pub extern "C" fn crossterm_colors() -> *const libc::c_char {
1760    convert_string_to_c_char(COLORS.to_string())
1761}
1762
1763/// Tells whether the raw mode is enabled.
1764///
1765/// Check error message to see if this function failed
1766#[no_mangle]
1767pub fn crossterm_terminal_is_raw_mode_enabled() -> bool {
1768    crossterm::terminal::is_raw_mode_enabled().c_unwrap()
1769}
1770
1771/// Disables raw mode.
1772#[no_mangle]
1773pub extern "C" fn crossterm_terminal_disable_raw_mode() -> libc::c_int {
1774    crossterm::terminal::disable_raw_mode().c_unwrap();
1775    r!()
1776}
1777
1778/// Enables raw mode.
1779#[no_mangle]
1780pub extern "C" fn crossterm_terminal_enable_raw_mode() -> libc::c_int {
1781    crossterm::terminal::enable_raw_mode().c_unwrap();
1782    r!()
1783}
1784
1785/// Get terminal size
1786#[no_mangle]
1787pub extern "C" fn crossterm_terminal_size(width: &mut u16, height: &mut u16) -> libc::c_int {
1788    let (w, h) = crossterm::terminal::size().c_unwrap();
1789    *width = w;
1790    *height = h;
1791    r!()
1792}
1793
1794/// Sets the terminal buffer size `(cols, rows)`.
1795#[no_mangle]
1796pub extern "C" fn crossterm_terminal_size_set(cols: u16, rows: u16) -> libc::c_int {
1797    queue!(io!(), crossterm::terminal::SetSize(cols, rows)).c_unwrap();
1798    r!()
1799}
1800
1801/// Disables line wrapping.
1802#[no_mangle]
1803pub extern "C" fn crossterm_terminal_disable_line_wrap() -> libc::c_int {
1804    queue!(io!(), crossterm::terminal::DisableLineWrap).c_unwrap();
1805    r!()
1806}
1807
1808/// Enables line wrapping.
1809#[no_mangle]
1810pub extern "C" fn crossterm_terminal_enable_line_wrap() -> libc::c_int {
1811    queue!(io!(), crossterm::terminal::EnableLineWrap).c_unwrap();
1812    r!()
1813}
1814
1815/// Enters alternate screen.
1816#[no_mangle]
1817pub extern "C" fn crossterm_terminal_enter_alternate_screen() -> libc::c_int {
1818    queue!(io!(), crossterm::terminal::EnterAlternateScreen).c_unwrap();
1819    r!()
1820}
1821
1822/// Leaves alternate screen.
1823#[no_mangle]
1824pub extern "C" fn crossterm_terminal_leave_alternate_screen() -> libc::c_int {
1825    queue!(io!(), crossterm::terminal::LeaveAlternateScreen).c_unwrap();
1826    r!()
1827}
1828
1829/// Different ways to clear the terminal buffer.
1830#[repr(C)]
1831pub enum ClearType {
1832    /// All cells.
1833    All,
1834    /// All plus history
1835    Purge,
1836    /// All cells from the cursor position downwards.
1837    FromCursorDown,
1838    /// All cells from the cursor position upwards.
1839    FromCursorUp,
1840    /// All cells at the cursor row.
1841    CurrentLine,
1842    /// All cells from the cursor position until the new line.
1843    UntilNewLine,
1844}
1845
1846impl From<ClearType> for crossterm::terminal::ClearType {
1847    fn from(value: ClearType) -> Self {
1848        match value {
1849            ClearType::All => crossterm::terminal::ClearType::All,
1850            ClearType::Purge => crossterm::terminal::ClearType::Purge,
1851            ClearType::FromCursorDown => crossterm::terminal::ClearType::FromCursorDown,
1852            ClearType::FromCursorUp => crossterm::terminal::ClearType::FromCursorUp,
1853            ClearType::CurrentLine => crossterm::terminal::ClearType::CurrentLine,
1854            ClearType::UntilNewLine => crossterm::terminal::ClearType::UntilNewLine,
1855        }
1856    }
1857}
1858
1859/// Scroll up command.
1860#[no_mangle]
1861pub extern "C" fn crossterm_terminal_scroll_up(n: libc::c_ushort) -> libc::c_int {
1862    queue!(io!(), crossterm::terminal::ScrollUp(n)).c_unwrap();
1863    r!()
1864}
1865
1866/// Scroll down command.
1867#[no_mangle]
1868pub extern "C" fn crossterm_terminal_scroll_down(n: libc::c_ushort) -> libc::c_int {
1869    queue!(io!(), crossterm::terminal::ScrollDown(n)).c_unwrap();
1870    r!()
1871}
1872
1873/// Clear screen command.
1874#[no_mangle]
1875pub extern "C" fn crossterm_terminal_clear(ct: ClearType) -> libc::c_int {
1876    queue!(io!(), crossterm::terminal::Clear(ct.into())).c_unwrap();
1877    r!()
1878}
1879
1880/// Sets terminal title.
1881///
1882/// # Safety
1883///
1884/// This function takes a raw pointer as argument. As such, the caller must ensure that:
1885/// - The `title` pointer points to a valid null-terminated string.
1886/// - This function borrows a slice to a valid null-terminated string and the memory referenced by `title` won't be deallocated or modified for the duration of the function call..
1887/// - The `title` pointer is correctly aligned and `title` points to an initialized memory.
1888///
1889/// If these conditions are not met, the behavior is undefined.
1890#[no_mangle]
1891pub unsafe extern "C" fn crossterm_terminal_title(title: *const libc::c_char) -> libc::c_int {
1892    if title.is_null() {
1893        RESULT.with(|r| {
1894            *r.borrow_mut() = -1;
1895        });
1896        set_last_error(anyhow::anyhow!("Received null pointer for title string"));
1897        return r!();
1898    };
1899    let c_str: &std::ffi::CStr = std::ffi::CStr::from_ptr(title);
1900    if let Ok(string) = c_str.to_str() {
1901        queue!(io!(), crossterm::terminal::SetTitle(string)).c_unwrap();
1902        r!()
1903    } else {
1904        RESULT.with(|r| {
1905            *r.borrow_mut() = -1;
1906        });
1907        set_last_error(anyhow::anyhow!("Received invalid UTF-8 string for title"));
1908        r!()
1909    }
1910}
1911
1912/// Instructs the terminal emulator to begin a synchronized frame.
1913///
1914/// # Notes
1915///
1916/// * Commands must be executed/queued for execution otherwise they do nothing.
1917/// * Use [`crossterm_terminal_end_synchronized_update`] command to leave the entered alternate screen.
1918///
1919/// When rendering the screen of the terminal, the Emulator usually iterates through each visible grid cell and
1920/// renders its current state. With applications updating the screen a at higher frequency this can cause tearing.
1921///
1922/// This mode attempts to mitigate that.
1923///
1924/// When the synchronization mode is enabled following render calls will keep rendering the last rendered state.
1925/// The terminal Emulator keeps processing incoming text and sequences. When the synchronized update mode is disabled
1926/// again the renderer may fetch the latest screen buffer state again, effectively avoiding the tearing effect
1927/// by unintentionally rendering in the middle a of an application screen update.
1928#[no_mangle]
1929pub extern "C" fn crossterm_terminal_begin_synchronized_update() -> libc::c_int {
1930    queue!(io!(), crossterm::terminal::BeginSynchronizedUpdate).c_unwrap();
1931    r!()
1932}
1933
1934/// Instructs the terminal to end a synchronized frame.
1935///
1936/// # Notes
1937///
1938/// * Commands must be executed/queued for execution otherwise they do nothing.
1939/// * Use [`crossterm_terminal_begin_synchronized_update`] to enter the alternate screen.
1940///
1941/// When rendering the screen of the terminal, the Emulator usually iterates through each visible grid cell and
1942/// renders its current state. With applications updating the screen a at higher frequency this can cause tearing.
1943///
1944/// This mode attempts to mitigate that.
1945///
1946/// When the synchronization mode is enabled following render calls will keep rendering the last rendered state.
1947/// The terminal Emulator keeps processing incoming text and sequences. When the synchronized update mode is disabled
1948/// again the renderer may fetch the latest screen buffer state again, effectively avoiding the tearing effect
1949/// by unintentionally rendering in the middle a of an application screen update.
1950#[no_mangle]
1951pub extern "C" fn crossterm_terminal_end_synchronized_update() -> libc::c_int {
1952    queue!(io!(), crossterm::terminal::EndSynchronizedUpdate).c_unwrap();
1953    r!()
1954}
1955
1956/// Instructs the terminal to send a bell.
1957#[no_mangle]
1958pub extern "C" fn crossterm_terminal_ring_bell() -> libc::c_int {
1959    queue!(io!(), crossterm::style::Print("\x07")).c_unwrap();
1960    r!()
1961}
1962
1963/// Flush the stdout stream, ensuring that all intermediately buffered contents reach their destination.
1964///
1965/// It is considered an error if not all bytes could be written due to I/O errors or EOF being reached.
1966#[no_mangle]
1967pub extern "C" fn crossterm_flush() -> libc::c_int {
1968    if let Err(err) = io!().flush() {
1969        set_last_error(anyhow::anyhow!(err))
1970    }
1971    r!()
1972}