use std::io::Write;
use bitflags::bitflags;
use crossterm::{self, queue};
use log::trace;
#[cfg(not(feature = "docsrs"))]
include!(concat!(env!("OUT_DIR"), "/colors.rs"));
#[cfg(feature = "docsrs")]
pub static COLORS: &str =
r##"[{"error": "Feature `docsrs` is enabled. COLORS json not available."}]"##;
fn convert_string_to_c_char(string: String) -> *mut libc::c_char {
let c_string = match std::ffi::CString::new(string.as_bytes()) {
Ok(c_string) => c_string,
Err(_) => {
set_last_error(anyhow::anyhow!("Unable to convert {} to CString", &string));
return std::ptr::null_mut();
}
};
let string_len = c_string.as_bytes_with_nul().len();
let addr = unsafe {
let addr = libc::malloc(string_len) as *mut libc::c_char;
if addr.is_null() {
set_last_error(anyhow::anyhow!("Unable to malloc for {}", &string));
return std::ptr::null_mut();
}
addr
};
unsafe {
std::ptr::copy_nonoverlapping(c_string.as_ptr(), addr, string_len);
}
addr
}
pub trait CUnwrapper<T> {
fn c_unwrap(self) -> T;
}
impl<T> CUnwrapper<T> for anyhow::Result<T>
where
T: Default,
{
fn c_unwrap(self) -> T {
match self {
Ok(t) => {
RESULT.with(|r| {
*r.borrow_mut() = 0;
});
take_last_error();
t
}
Err(err) => {
RESULT.with(|r| {
*r.borrow_mut() = -1;
});
set_last_error(err);
T::default()
}
}
}
}
impl<T> CUnwrapper<T> for Result<T, std::io::Error>
where
T: Default,
{
fn c_unwrap(self) -> T {
match self {
Ok(t) => {
RESULT.with(|r| {
*r.borrow_mut() = 0;
});
take_last_error();
t
}
Err(err) => {
RESULT.with(|r| {
*r.borrow_mut() = -1;
});
set_last_error(err.into());
T::default()
}
}
}
}
thread_local! {
static LAST_ERROR: std::cell::RefCell<Option<anyhow::Error>> = std::cell::RefCell::new(None);
static RESULT: std::cell::RefCell<libc::c_int> = std::cell::RefCell::new(0);
static USE_STDOUT: std::cell::RefCell<bool> = std::cell::RefCell::new(std::env::var("LIBCROSSTERM_OUTPUT").unwrap_or_default() == "stdout");
}
macro_rules! r {
() => {
RESULT.with(|r| r.borrow().clone())
};
}
macro_rules! io {
() => {
if USE_STDOUT.with(|r| *r.borrow()) {
Box::new(std::io::stdout()) as Box<dyn Write>
} else {
Box::new(std::io::stderr()) as Box<dyn Write>
}
};
}
fn set_last_error(err: anyhow::Error) {
trace!("Set last error");
LAST_ERROR.with(|e| {
*e.borrow_mut() = Some(err);
});
}
pub fn take_last_error() -> Option<anyhow::Error> {
LAST_ERROR.with(|prev| prev.borrow_mut().take())
}
#[no_mangle]
pub extern "C" fn crossterm_has_error() -> bool {
LAST_ERROR.with(|prev| prev.borrow().is_some())
}
#[no_mangle]
pub extern "C" fn crossterm_clear_last_error() {
let _ = take_last_error();
}
pub fn error_message() -> Option<String> {
LAST_ERROR.with(|prev| prev.borrow().as_ref().map(|e| format!("{:#}", e)))
}
#[no_mangle]
pub extern "C" fn crossterm_last_error_length() -> libc::c_int {
LAST_ERROR.with(|prev| match *prev.borrow() {
Some(ref err) => format!("{:#}", err).len() as libc::c_int + 1,
None => 0,
})
}
#[no_mangle]
pub extern "C" fn crossterm_last_error_message() -> *const libc::c_char {
let last_error = take_last_error().unwrap_or(anyhow::anyhow!(
"No error message found. Check library documentation for more information."
));
let string = format!("{:#}", last_error);
convert_string_to_c_char(string)
}
#[no_mangle]
pub extern "C" fn crossterm_free_c_char(s: *mut libc::c_char) -> libc::c_int {
if !s.is_null() {
unsafe {
libc::free(s as *mut libc::c_void);
}
0
} else {
set_last_error(anyhow::anyhow!("Received null pointer to free"));
-1
}
}
#[repr(C)]
pub enum MediaKeyCode {
Play,
Pause,
PlayPause,
Reverse,
Stop,
FastForward,
Rewind,
TrackNext,
TrackPrevious,
Record,
LowerVolume,
RaiseVolume,
MuteVolume,
}
#[repr(C)]
pub enum ModifierKeyCode {
LeftShift,
LeftControl,
LeftAlt,
LeftSuper,
LeftHyper,
LeftMeta,
RightShift,
RightControl,
RightAlt,
RightSuper,
RightHyper,
RightMeta,
IsoLevel3Shift,
IsoLevel5Shift,
}
#[repr(C)]
pub enum KeyCode {
Backspace,
Enter,
Left,
Right,
Up,
Down,
Home,
End,
PageUp,
PageDown,
Tab,
BackTab,
Delete,
Insert,
F(u8),
Char(char),
Null,
Esc,
CapsLock,
ScrollLock,
NumLock,
PrintScreen,
Pause,
Menu,
KeypadBegin,
Media(MediaKeyCode),
Modifier(ModifierKeyCode),
}
bitflags! {
#[repr(C)]
pub struct KeyModifiers: u8 {
const SHIFT = 0b0000_0001;
const CONTROL = 0b0000_0010;
const ALT = 0b0000_0100;
const SUPER = 0b0000_1000;
const HYPER = 0b0001_0000;
const META = 0b0010_0000;
const NONE = 0b0000_0000;
}
}
#[repr(C)]
pub enum KeyEventKind {
Press,
Repeat,
Release,
}
bitflags! {
#[repr(C)]
pub struct KeyEventState: u8 {
const KEYPAD = 0b0000_0001;
const CAPS_LOCK = 0b0000_1000;
const NUM_LOCK = 0b0000_1000;
const NONE = 0b0000_0000;
}
}
#[repr(C)]
pub struct KeyEvent {
pub code: KeyCode,
pub modifiers: KeyModifiers,
pub kind: KeyEventKind,
pub state: KeyEventState,
}
#[repr(C)]
pub enum MouseEventKind {
Down(MouseButton),
Up(MouseButton),
Drag(MouseButton),
Moved,
ScrollDown,
ScrollUp,
}
#[repr(C)]
pub enum MouseButton {
Left,
Right,
Middle,
}
#[repr(C)]
pub struct MouseEvent {
pub kind: MouseEventKind,
pub col: u16,
pub row: u16,
pub modifiers: KeyModifiers,
}
#[repr(C)]
pub enum Event {
FocusGained,
FocusLost,
Key(KeyEvent),
Mouse(MouseEvent),
Paste(*const libc::c_char),
Resize(u16, u16),
}
#[no_mangle]
pub extern "C" fn crossterm_event_poll(secs: u64, nanos: u32) -> libc::c_int {
let r = crossterm::event::poll(std::time::Duration::new(secs, nanos)).c_unwrap();
if crossterm_has_error() {
r!()
} else {
r.into()
}
}
#[no_mangle]
pub extern "C" fn crossterm_event_read() -> *const libc::c_char {
let json_value = match crossterm::event::read() {
Ok(evt) => serde_json::to_value(&evt).unwrap_or_else(|e| {
serde_json::json!({
"error": format!("Unable to convert event {:?} to JSON: {:?}", evt, e),
})
}),
Err(e) => serde_json::json!({
"error": format!("Something went wrong with crossterm_event_read(): {:?}", e),
}),
};
let json_string = serde_json::to_string(&json_value).unwrap_or_else(|e| {
serde_json::json!({
"error": format!("Unable to convert JSON value to string: {:?}", e),
})
.to_string()
});
convert_string_to_c_char(json_string)
}
#[no_mangle]
pub extern "C" fn crossterm_use_stdout() {
USE_STDOUT.with(|io| {
*io.borrow_mut() = true;
});
}
#[no_mangle]
pub extern "C" fn crossterm_use_stderr() {
USE_STDOUT.with(|io| {
*io.borrow_mut() = false;
});
}
#[no_mangle]
pub extern "C" fn crossterm_sleep(seconds: f64) {
let duration = std::time::Duration::from_nanos((seconds * 1e9).round() as u64);
std::thread::sleep(duration);
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_position_set(col: u16, row: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveTo(col, row)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_position(col: &mut u16, row: &mut u16) -> libc::c_int {
let (c, r) = crossterm::cursor::position().c_unwrap();
*col = c;
*row = r;
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_to(col: u16, row: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveTo(col, row)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_to_next_line(n: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveToNextLine(n)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_to_previous_line(n: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveToPreviousLine(n)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_to_column(col: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveToColumn(col)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_to_row(row: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveToRow(row)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_up(rows: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveUp(rows)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_right(cols: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveRight(cols)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_down(rows: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveDown(rows)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_move_left(cols: u16) -> libc::c_int {
queue!(io!(), crossterm::cursor::MoveLeft(cols)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_save_position() -> libc::c_int {
queue!(io!(), crossterm::cursor::SavePosition).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_restore_position() -> libc::c_int {
queue!(io!(), crossterm::cursor::RestorePosition).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_hide() -> libc::c_int {
queue!(io!(), crossterm::cursor::Hide).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_show() -> libc::c_int {
queue!(io!(), crossterm::cursor::Show).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_enable_blinking() -> libc::c_int {
queue!(io!(), crossterm::cursor::EnableBlinking).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_disable_blinking() -> libc::c_int {
queue!(io!(), crossterm::cursor::DisableBlinking).c_unwrap();
r!()
}
#[repr(C)]
#[derive(Clone, Copy)]
pub enum CursorStyle {
DefaultUserShape,
BlinkingBlock,
SteadyBlock,
BlinkingUnderScore,
SteadyUnderScore,
BlinkingBar,
SteadyBar,
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_style(cursor_style: CursorStyle) -> libc::c_int {
let cs = match cursor_style {
CursorStyle::DefaultUserShape => crossterm::cursor::SetCursorStyle::DefaultUserShape,
CursorStyle::BlinkingBlock => crossterm::cursor::SetCursorStyle::BlinkingBlock,
CursorStyle::SteadyBlock => crossterm::cursor::SetCursorStyle::SteadyBlock,
CursorStyle::BlinkingUnderScore => crossterm::cursor::SetCursorStyle::BlinkingUnderScore,
CursorStyle::SteadyUnderScore => crossterm::cursor::SetCursorStyle::SteadyUnderScore,
CursorStyle::BlinkingBar => crossterm::cursor::SetCursorStyle::BlinkingBar,
CursorStyle::SteadyBar => crossterm::cursor::SetCursorStyle::SteadyBar,
};
queue!(io!(), cs).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_style_default_user_shape() -> libc::c_int {
queue!(io!(), crossterm::cursor::SetCursorStyle::DefaultUserShape).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_style_blinking_block() -> libc::c_int {
queue!(io!(), crossterm::cursor::SetCursorStyle::BlinkingBlock).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_style_steady_block() -> libc::c_int {
queue!(io!(), crossterm::cursor::SetCursorStyle::SteadyBlock).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_style_blinking_underscore() -> libc::c_int {
queue!(io!(), crossterm::cursor::SetCursorStyle::BlinkingUnderScore).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_style_steady_underscore() -> libc::c_int {
queue!(io!(), crossterm::cursor::SetCursorStyle::SteadyUnderScore).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_style_blinking_bar() -> libc::c_int {
queue!(io!(), crossterm::cursor::SetCursorStyle::BlinkingBar).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_cursor_style_steady_bar() -> libc::c_int {
queue!(io!(), crossterm::cursor::SetCursorStyle::SteadyBar).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_event_enable_mouse_capture() -> libc::c_int {
queue!(io!(), crossterm::event::EnableMouseCapture).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_event_disable_mouse_capture() -> libc::c_int {
queue!(io!(), crossterm::event::DisableMouseCapture).c_unwrap();
r!()
}
#[repr(u8)]
pub enum KeyboardEnhancementFlags {
DisambiguateEscapeCodes = 0b0000_0001,
ReportEventTypes = 0b0000_0010,
ReportAlternateKeys = 0b0000_0100,
ReportAllKeysAsEscapeCodes = 0b0000_1000,
}
#[no_mangle]
pub extern "C" fn crossterm_event_push_keyboard_enhancement_flags(flags: u8) -> libc::c_int {
let flags = crossterm::event::KeyboardEnhancementFlags::from_bits(flags).unwrap();
queue!(io!(), crossterm::event::PushKeyboardEnhancementFlags(flags)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_event_pop_keyboard_enhancement_flags() -> libc::c_int {
queue!(io!(), crossterm::event::PopKeyboardEnhancementFlags).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_event_enable_focus_change() -> libc::c_int {
queue!(io!(), crossterm::event::EnableFocusChange).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_event_disable_focus_change() -> libc::c_int {
queue!(io!(), crossterm::event::DisableFocusChange).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_event_enable_bracketed_paste() -> libc::c_int {
queue!(io!(), crossterm::event::EnableBracketedPaste).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_event_disable_bracketed_paste() -> libc::c_int {
queue!(io!(), crossterm::event::DisableBracketedPaste).c_unwrap();
r!()
}
#[repr(C)]
pub enum Attribute {
Reset,
Bold,
Dim,
Italic,
Underlined,
DoubleUnderlined,
Undercurled,
Underdotted,
Underdashed,
SlowBlink,
RapidBlink,
Reverse,
Hidden,
CrossedOut,
Fraktur,
NoBold,
NormalIntensity,
NoItalic,
NoUnderline,
NoBlink,
NoReverse,
NoHidden,
NotCrossedOut,
Framed,
Encircled,
OverLined,
NotFramedOrEncircled,
NotOverLined,
}
impl From<Attribute> for crossterm::style::Attribute {
fn from(value: Attribute) -> Self {
match value {
Attribute::Reset => crossterm::style::Attribute::Reset,
Attribute::Bold => crossterm::style::Attribute::Bold,
Attribute::Dim => crossterm::style::Attribute::Dim,
Attribute::Italic => crossterm::style::Attribute::Italic,
Attribute::Underlined => crossterm::style::Attribute::Underlined,
Attribute::DoubleUnderlined => crossterm::style::Attribute::DoubleUnderlined,
Attribute::Undercurled => crossterm::style::Attribute::Undercurled,
Attribute::Underdotted => crossterm::style::Attribute::Underdotted,
Attribute::Underdashed => crossterm::style::Attribute::Underdashed,
Attribute::SlowBlink => crossterm::style::Attribute::SlowBlink,
Attribute::RapidBlink => crossterm::style::Attribute::RapidBlink,
Attribute::Reverse => crossterm::style::Attribute::Reverse,
Attribute::Hidden => crossterm::style::Attribute::Hidden,
Attribute::CrossedOut => crossterm::style::Attribute::CrossedOut,
Attribute::Fraktur => crossterm::style::Attribute::Fraktur,
Attribute::NoBold => crossterm::style::Attribute::NoBold,
Attribute::NormalIntensity => crossterm::style::Attribute::NormalIntensity,
Attribute::NoItalic => crossterm::style::Attribute::NoItalic,
Attribute::NoUnderline => crossterm::style::Attribute::NoUnderline,
Attribute::NoBlink => crossterm::style::Attribute::NoBlink,
Attribute::NoReverse => crossterm::style::Attribute::NoReverse,
Attribute::NoHidden => crossterm::style::Attribute::NoHidden,
Attribute::NotCrossedOut => crossterm::style::Attribute::NotCrossedOut,
Attribute::Framed => crossterm::style::Attribute::Framed,
Attribute::Encircled => crossterm::style::Attribute::Encircled,
Attribute::OverLined => crossterm::style::Attribute::OverLined,
Attribute::NotFramedOrEncircled => crossterm::style::Attribute::NotFramedOrEncircled,
Attribute::NotOverLined => crossterm::style::Attribute::NotOverLined,
}
}
}
#[repr(C)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct Attributes(u32);
#[no_mangle]
pub extern "C" fn crossterm_style_attribute(attr: Attribute) -> libc::c_int {
queue!(io!(), crossterm::style::SetAttribute(attr.into())).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_reset() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Reset.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_bold() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Bold.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_dim() -> libc::c_int {
queue!(io!(), crossterm::style::SetAttribute(Attribute::Dim.into())).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_italic() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Italic.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_underlined() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Underlined.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_double_underlined() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::DoubleUnderlined.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_undercurled() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Undercurled.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_underdotted() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Underdotted.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_underdashed() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Underdashed.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_slow_blink() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::SlowBlink.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_rapid_blink() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::RapidBlink.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_reverse() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Reverse.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_hidden() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Hidden.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_crossed_out() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::CrossedOut.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_fraktur() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::Fraktur.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_no_bold() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::NoBold.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_normal_intensity() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::NormalIntensity.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_no_italic() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::NoItalic.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_no_underline() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::NoUnderline.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_no_blink() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::NoBlink.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_no_reverse() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::NoReverse.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_no_hidden() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::NoHidden.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_attribute_not_crossed_out() -> libc::c_int {
queue!(
io!(),
crossterm::style::SetAttribute(Attribute::NotCrossedOut.into())
)
.c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_print_char(c: u32) -> libc::c_int {
if let Some(ch) = std::char::from_u32(c) {
queue!(io!(), crossterm::style::Print(ch)).c_unwrap();
r!()
} else {
set_last_error(anyhow::anyhow!("Unable to convert {} to valid char", c));
-1
}
}
#[no_mangle]
pub unsafe extern "C" fn crossterm_style_print_string(s: *const libc::c_char) -> libc::c_int {
if s.is_null() {
RESULT.with(|r| {
*r.borrow_mut() = -1;
});
set_last_error(anyhow::anyhow!("Received null pointer for print string"));
return r!();
};
let c_str: &std::ffi::CStr = std::ffi::CStr::from_ptr(s);
if let Ok(string) = c_str.to_str() {
queue!(io!(), crossterm::style::Print(string)).c_unwrap();
r!()
} else {
RESULT.with(|r| {
*r.borrow_mut() = -1;
});
set_last_error(anyhow::anyhow!(
"Received invalid UTF-8 string for print string"
));
r!()
}
}
#[no_mangle]
pub unsafe extern "C" fn crossterm_style_print(s: *const libc::c_char) -> libc::c_int {
crossterm_style_print_string(s)
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum Color {
Reset,
Black,
DarkGrey,
Red,
DarkRed,
Green,
DarkGreen,
Yellow,
DarkYellow,
Blue,
DarkBlue,
Magenta,
DarkMagenta,
Cyan,
DarkCyan,
White,
Grey,
Rgb { r: u8, g: u8, b: u8 },
AnsiValue(u8),
}
impl From<Color> for crossterm::style::Color {
fn from(color: Color) -> Self {
match color {
Color::Reset => crossterm::style::Color::Reset,
Color::Black => crossterm::style::Color::Black,
Color::DarkGrey => crossterm::style::Color::DarkGrey,
Color::Red => crossterm::style::Color::Red,
Color::DarkRed => crossterm::style::Color::DarkRed,
Color::Green => crossterm::style::Color::Green,
Color::DarkGreen => crossterm::style::Color::DarkGreen,
Color::Yellow => crossterm::style::Color::Yellow,
Color::DarkYellow => crossterm::style::Color::DarkYellow,
Color::Blue => crossterm::style::Color::Blue,
Color::DarkBlue => crossterm::style::Color::DarkBlue,
Color::Magenta => crossterm::style::Color::Magenta,
Color::DarkMagenta => crossterm::style::Color::DarkMagenta,
Color::Cyan => crossterm::style::Color::Cyan,
Color::DarkCyan => crossterm::style::Color::DarkCyan,
Color::White => crossterm::style::Color::White,
Color::Grey => crossterm::style::Color::Grey,
Color::Rgb { r, g, b } => crossterm::style::Color::Rgb { r, g, b },
Color::AnsiValue(v) => crossterm::style::Color::AnsiValue(v),
}
}
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color(color: Color) -> libc::c_int {
queue!(io!(), crossterm::style::SetBackgroundColor(color.into())).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_rgb(r: u8, g: u8, b: u8) -> libc::c_int {
crossterm_style_background_color(Color::Rgb { r, g, b })
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_ansi(value: u8) -> libc::c_int {
crossterm_style_background_color(Color::AnsiValue(value))
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_reset() -> libc::c_int {
crossterm_style_background_color(Color::Reset)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_black() -> libc::c_int {
crossterm_style_background_color(Color::Black)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_dark_grey() -> libc::c_int {
crossterm_style_background_color(Color::DarkGrey)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_red() -> libc::c_int {
crossterm_style_background_color(Color::Red)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_dark_red() -> libc::c_int {
crossterm_style_background_color(Color::DarkRed)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_green() -> libc::c_int {
crossterm_style_background_color(Color::Green)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_dark_green() -> libc::c_int {
crossterm_style_background_color(Color::DarkGreen)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_yellow() -> libc::c_int {
crossterm_style_background_color(Color::Yellow)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_dark_yellow() -> libc::c_int {
crossterm_style_background_color(Color::DarkYellow)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_blue() -> libc::c_int {
crossterm_style_background_color(Color::Blue)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_dark_blue() -> libc::c_int {
crossterm_style_background_color(Color::DarkBlue)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_magenta() -> libc::c_int {
crossterm_style_background_color(Color::Magenta)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_dark_magenta() -> libc::c_int {
crossterm_style_background_color(Color::DarkMagenta)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_cyan() -> libc::c_int {
crossterm_style_background_color(Color::Cyan)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_dark_cyan() -> libc::c_int {
crossterm_style_background_color(Color::DarkCyan)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_white() -> libc::c_int {
crossterm_style_background_color(Color::White)
}
#[no_mangle]
pub extern "C" fn crossterm_style_background_color_grey() -> libc::c_int {
crossterm_style_background_color(Color::Grey)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color(color: Color) -> libc::c_int {
queue!(io!(), crossterm::style::SetForegroundColor(color.into())).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_rgb(r: u8, g: u8, b: u8) -> libc::c_int {
crossterm_style_foreground_color(Color::Rgb { r, g, b })
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_ansi(value: u8) -> libc::c_int {
crossterm_style_foreground_color(Color::AnsiValue(value))
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_reset() -> libc::c_int {
crossterm_style_foreground_color(Color::Reset)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_black() -> libc::c_int {
crossterm_style_foreground_color(Color::Black)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_dark_grey() -> libc::c_int {
crossterm_style_foreground_color(Color::DarkGrey)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_red() -> libc::c_int {
crossterm_style_foreground_color(Color::Red)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_dark_red() -> libc::c_int {
crossterm_style_foreground_color(Color::DarkRed)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_green() -> libc::c_int {
crossterm_style_foreground_color(Color::Green)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_dark_green() -> libc::c_int {
crossterm_style_foreground_color(Color::DarkGreen)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_yellow() -> libc::c_int {
crossterm_style_foreground_color(Color::Yellow)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_dark_yellow() -> libc::c_int {
crossterm_style_foreground_color(Color::DarkYellow)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_blue() -> libc::c_int {
crossterm_style_foreground_color(Color::Blue)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_dark_blue() -> libc::c_int {
crossterm_style_foreground_color(Color::DarkBlue)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_magenta() -> libc::c_int {
crossterm_style_foreground_color(Color::Magenta)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_dark_magenta() -> libc::c_int {
crossterm_style_foreground_color(Color::DarkMagenta)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_cyan() -> libc::c_int {
crossterm_style_foreground_color(Color::Cyan)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_dark_cyan() -> libc::c_int {
crossterm_style_foreground_color(Color::DarkCyan)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_white() -> libc::c_int {
crossterm_style_foreground_color(Color::White)
}
#[no_mangle]
pub extern "C" fn crossterm_style_foreground_color_grey() -> libc::c_int {
crossterm_style_foreground_color(Color::Grey)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color(color: Color) -> libc::c_int {
queue!(io!(), crossterm::style::SetUnderlineColor(color.into())).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_rgb(r: u8, g: u8, b: u8) -> libc::c_int {
crossterm_style_underline_color(Color::Rgb { r, g, b })
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_ansi(value: u8) -> libc::c_int {
crossterm_style_underline_color(Color::AnsiValue(value))
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_reset() -> libc::c_int {
crossterm_style_underline_color(Color::Reset)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_black() -> libc::c_int {
crossterm_style_underline_color(Color::Black)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_dark_grey() -> libc::c_int {
crossterm_style_underline_color(Color::DarkGrey)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_red() -> libc::c_int {
crossterm_style_underline_color(Color::Red)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_dark_red() -> libc::c_int {
crossterm_style_underline_color(Color::DarkRed)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_green() -> libc::c_int {
crossterm_style_underline_color(Color::Green)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_dark_green() -> libc::c_int {
crossterm_style_underline_color(Color::DarkGreen)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_yellow() -> libc::c_int {
crossterm_style_underline_color(Color::Yellow)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_dark_yellow() -> libc::c_int {
crossterm_style_underline_color(Color::DarkYellow)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_blue() -> libc::c_int {
crossterm_style_underline_color(Color::Blue)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_dark_blue() -> libc::c_int {
crossterm_style_underline_color(Color::DarkBlue)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_magenta() -> libc::c_int {
crossterm_style_underline_color(Color::Magenta)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_dark_magenta() -> libc::c_int {
crossterm_style_underline_color(Color::DarkMagenta)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_cyan() -> libc::c_int {
crossterm_style_underline_color(Color::Cyan)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_dark_cyan() -> libc::c_int {
crossterm_style_underline_color(Color::DarkCyan)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_white() -> libc::c_int {
crossterm_style_underline_color(Color::White)
}
#[no_mangle]
pub extern "C" fn crossterm_style_underline_color_grey() -> libc::c_int {
crossterm_style_underline_color(Color::Grey)
}
#[no_mangle]
pub extern "C" fn crossterm_style_reset_color() -> libc::c_int {
queue!(io!(), crossterm::style::ResetColor).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_colors() -> *const libc::c_char {
convert_string_to_c_char(COLORS.to_string())
}
#[no_mangle]
pub fn crossterm_terminal_is_raw_mode_enabled() -> bool {
crossterm::terminal::is_raw_mode_enabled().c_unwrap()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_disable_raw_mode() -> libc::c_int {
crossterm::terminal::disable_raw_mode().c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_enable_raw_mode() -> libc::c_int {
crossterm::terminal::enable_raw_mode().c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_size(width: &mut u16, height: &mut u16) -> libc::c_int {
let (w, h) = crossterm::terminal::size().c_unwrap();
*width = w;
*height = h;
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_size_set(cols: u16, rows: u16) -> libc::c_int {
queue!(io!(), crossterm::terminal::SetSize(cols, rows)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_disable_line_wrap() -> libc::c_int {
queue!(io!(), crossterm::terminal::DisableLineWrap).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_enable_line_wrap() -> libc::c_int {
queue!(io!(), crossterm::terminal::EnableLineWrap).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_enter_alternate_screen() -> libc::c_int {
queue!(io!(), crossterm::terminal::EnterAlternateScreen).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_leave_alternate_screen() -> libc::c_int {
queue!(io!(), crossterm::terminal::LeaveAlternateScreen).c_unwrap();
r!()
}
#[repr(C)]
pub enum ClearType {
All,
Purge,
FromCursorDown,
FromCursorUp,
CurrentLine,
UntilNewLine,
}
impl From<ClearType> for crossterm::terminal::ClearType {
fn from(value: ClearType) -> Self {
match value {
ClearType::All => crossterm::terminal::ClearType::All,
ClearType::Purge => crossterm::terminal::ClearType::Purge,
ClearType::FromCursorDown => crossterm::terminal::ClearType::FromCursorDown,
ClearType::FromCursorUp => crossterm::terminal::ClearType::FromCursorUp,
ClearType::CurrentLine => crossterm::terminal::ClearType::CurrentLine,
ClearType::UntilNewLine => crossterm::terminal::ClearType::UntilNewLine,
}
}
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_scroll_up(n: libc::c_ushort) -> libc::c_int {
queue!(io!(), crossterm::terminal::ScrollUp(n)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_scroll_down(n: libc::c_ushort) -> libc::c_int {
queue!(io!(), crossterm::terminal::ScrollDown(n)).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_clear(ct: ClearType) -> libc::c_int {
queue!(io!(), crossterm::terminal::Clear(ct.into())).c_unwrap();
r!()
}
#[no_mangle]
pub unsafe extern "C" fn crossterm_terminal_title(title: *const libc::c_char) -> libc::c_int {
if title.is_null() {
RESULT.with(|r| {
*r.borrow_mut() = -1;
});
set_last_error(anyhow::anyhow!("Received null pointer for title string"));
return r!();
};
let c_str: &std::ffi::CStr = std::ffi::CStr::from_ptr(title);
if let Ok(string) = c_str.to_str() {
queue!(io!(), crossterm::terminal::SetTitle(string)).c_unwrap();
r!()
} else {
RESULT.with(|r| {
*r.borrow_mut() = -1;
});
set_last_error(anyhow::anyhow!("Received invalid UTF-8 string for title"));
r!()
}
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_begin_synchronized_update() -> libc::c_int {
queue!(io!(), crossterm::terminal::BeginSynchronizedUpdate).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_end_synchronized_update() -> libc::c_int {
queue!(io!(), crossterm::terminal::EndSynchronizedUpdate).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_terminal_ring_bell() -> libc::c_int {
queue!(io!(), crossterm::style::Print("\x07")).c_unwrap();
r!()
}
#[no_mangle]
pub extern "C" fn crossterm_flush() -> libc::c_int {
if let Err(err) = io!().flush() {
set_last_error(anyhow::anyhow!(err))
}
r!()
}