rust: add all NcDirect methods.

- add missing ncdirect_* static inline functions.
- update Notcurses.getc().
- add NcTime constructor.
- add NcSigSet type + constructor.
- minor fixes.
pull/1253/head
joseLuís 4 years ago
parent 7d53abc1b1
commit 3c8328c9cc

@ -168,6 +168,9 @@ pub use ffi::{
ncdirect_render_image,
ncdirect_rounded_box,
ncdirect_stop,
ncdirect_styles_off,
ncdirect_styles_on,
ncdirect_styles_set,
ncdirect_vline_interp,
};
@ -723,24 +726,22 @@ pub use ffi::{
};
// sig -------------------------------------------------------------------------
pub(crate) use ffi::sigset_t;
#[doc(inline)]
pub use ffi::{
// structs
//sigaction,
// functions
sigaddset,
sigdelset,
sigemptyset,
sigfillset,
sigismember,
sigpending,
sigprocmask,
sigsuspend,
};
//
// already wrapped:
//
// // structs
// sigset_t,
// sigaction,
//
// // functions
// sigaddset,
// sigdelset,
// sigemptyset,
// sigfillset,
// sigismember,
// sigpending,
// sigprocmask,
// sigsuspend,
// fade callback ---------------------------------------------------------------
//

@ -1,29 +1,514 @@
//! `NcDirect` methods and associated functions.
use crate::{ncdirect_init, NcDirect, NcDirectFlags};
use core::ptr::{null, null_mut};
use crate::ffi::sigset_t;
use crate::{
cstring, NcAlign, NcBlitter, NcChannelPair, NcColor, NcDimension, NcDirect, NcDirectFlags,
NcEgc, NcInput, NcPaletteIndex, NcResult, NcRgb, NcScale, NcStyleMask, NcTime, NCRESULT_ERR,
NCRESULT_OK,
};
/// # `NcDirect` constructors and destructors
impl NcDirect {
/// A simple ncdirect_init() wrapper using the default options.
/// New NcDirect with the default options.
///
/// Initialize a direct-mode notcurses context on the tty.
/// Initializes a direct-mode notcurses context on the tty.
///
/// Direct mode supports a limited subset of notcurses routines,
/// and neither supports nor requires notcurses_render(). This can be
/// used to add color and styling to text in the standard output paradigm.
/// and neither supports nor requires
/// [notcurses_render()][crate::notcurses_render]. This can be used to add
/// color and styling to text in the standard output paradigm.
///
/// *C style function: [ncdirect_init()][crate::ncdirect_init].*
//
// Returns NULL on error, including any failure initializing terminfo.
// TODO: Returns NULL on error, including any failure initializing terminfo.
pub fn new<'a>() -> &'a mut NcDirect {
Self::with_flags(0)
}
/// A simple ncdirect_init() wrapper with optional flags.
/// New NcDirect with optional flags.
///
/// `flags` is a bitmask over:
/// - NCDIRECT_OPTION_INHIBIT_CBREAK
/// - NCDIRECT_OPTION_INHIBIT_SETLOCALE
/// - [NCDIRECT_OPTION_INHIBIT_CBREAK][crate::NCDIRECT_OPTION_INHIBIT_CBREAK]
/// - [NCDIRECT_OPTION_INHIBIT_SETLOCALE][crate::NCDIRECT_OPTION_INHIBIT_SETLOCALE]
///
/// *C style function: [ncdirect_init()][crate::ncdirect_init].*
pub fn with_flags<'a>(flags: NcDirectFlags) -> &'a mut NcDirect {
unsafe { &mut *ncdirect_init(null(), null_mut(), flags) }
unsafe { &mut *crate::ncdirect_init(null(), null_mut(), flags) }
}
/// Releases this NcDirect and any associated resources.
///
/// *C style function: [ncdirect_stop()][crate::ncdirect_stop].*
pub fn stop(&mut self) -> NcResult {
unsafe { crate::ncdirect_stop(self) }
}
}
/// ## NcDirect methods: clear, flush, render_image
impl NcDirect {
/// Clears the screen.
///
/// *C style function: [ncdirect_clear()][crate::ncdirect_clear].*
pub fn clear(&mut self) -> NcResult {
unsafe { crate::ncdirect_clear(self) }
}
/// Forces a flush.
///
/// *C style function: [ncdirect_flush()][crate::ncdirect_flush].*
pub fn flush(&self) -> NcResult {
unsafe { crate::ncdirect_flush(self) }
}
/// Displays an image using the specified blitter and scaling.
///
/// The image may be arbitrarily many rows -- the output will scroll -- but
/// will only occupy the column of the cursor, and those to the right.
///
///
/// *C style function: [ncdirect_render_image()][crate::ncdirect_render_image].*
//
// TODO:
// The render/raster process can be split by using
// [render_frame()][#method.render_frame] and
// [raster_frame()][#method.raster_frame].
pub fn render_image(
&mut self,
filename: &str,
align: NcAlign,
blitter: NcBlitter,
scale: NcScale,
) -> NcResult {
unsafe { crate::ncdirect_render_image(self, cstring![filename], align, blitter, scale) }
}
}
/// ## NcDirect methods: `NcPaletteIndex`, `NcRgb`, `NcStyleMask` & default color
impl NcDirect {
/// Sets the foreground [NcPaletteIndex].
///
/// *C style function: [ncdirect_fg_palindex()][crate::ncdirect_fg_palindex].*
pub fn fg_palindex(&mut self, index: NcPaletteIndex) -> NcResult {
unsafe { crate::ncdirect_fg_palindex(self, index as i32) }
}
/// Sets the background [NcPaletteIndex].
///
/// *C style function: [ncdirect_bg_palindex()][crate::ncdirect_bg_palindex].*
pub fn bg_palindex(&mut self, index: NcPaletteIndex) -> NcResult {
unsafe { crate::ncdirect_bg_palindex(self, index as i32) }
}
/// Returns the number of simultaneous colors claimed to be supported,
/// or 1 if there is no color support.
///
/// Note that several terminal emulators advertise more colors than they
/// actually support, downsampling internally.
///
/// *C style function: [ncdirect_palette_size()][crate::ncdirect_palette_size].*
pub fn palette_size(&self) -> u32 {
unsafe { crate::ncdirect_palette_size(self) }
}
/// Sets the foreground [NcRgb].
///
/// *C style function: [ncdirect_fg_rgb()][crate::ncdirect_fg_rgb].*
pub fn fg_rgb(&mut self, rgb: NcRgb) -> NcResult {
unsafe { crate::ncdirect_fg_rgb(self, rgb) }
}
/// Sets the background [NcRgb].
///
/// *C style function: [ncdirect_bg_rgb()][crate::ncdirect_bg_rgb].*
pub fn bg_rgb(&mut self, rgb: NcRgb) -> NcResult {
unsafe { crate::ncdirect_bg_rgb(self, rgb) }
}
/// Sets the foreground [NcColor] components.
///
/// *C style function: [ncdirect_fg_rgb8()][crate::ncdirect_fg_rgb8].*
pub fn fg_rgb8(&mut self, red: NcColor, green: NcColor, blue: NcColor) -> NcResult {
crate::ncdirect_fg_rgb8(self, red, green, blue)
}
/// Sets the background [NcColor] components.
///
/// *C style function: [ncdirect_bg_rgb()][crate::ncdirect_bg_rgb].*
pub fn bg_rgb8(&mut self, red: NcColor, green: NcColor, blue: NcColor) -> NcResult {
crate::ncdirect_fg_rgb8(self, red, green, blue)
}
/// Removes the specified styles.
///
/// *C style function: [ncdirect_styles_off()][crate::ncdirect_styles_off].*
pub fn styles_off(&mut self, stylebits: NcStyleMask) -> NcResult {
unsafe { crate::ncdirect_styles_off(self, stylebits.into()) }
}
/// Adds the specified styles.
///
/// *C style function: [ncdirect_styles_on()][crate::ncdirect_styles_on].*
pub fn styles_on(&mut self, stylebits: NcStyleMask) -> NcResult {
unsafe { crate::ncdirect_styles_on(self, stylebits.into()) }
}
/// Sets just the specified styles.
///
/// *C style function: [ncdirect_styles_set()][crate::ncdirect_styles_set].*
pub fn styles_set(&mut self, stylebits: NcStyleMask) -> NcResult {
unsafe { crate::ncdirect_styles_set(self, stylebits.into()) }
}
/// Indicates to use the "default color" for the foreground.
///
/// *C style function: [ncdirect_fg_default()][crate::ncdirect_fg_default].*
pub fn fg_default(&mut self) -> NcResult {
unsafe { crate::ncdirect_fg_default(self) }
}
/// Indicates to use the "default color" for the background.
///
/// *C style function: [ncdirect_bg_default()][crate::ncdirect_bg_default].*
pub fn bg_default(&mut self) -> NcResult {
unsafe { crate::ncdirect_bg_default(self) }
}
}
/// ## NcDirect methods: capabilities, cursor, dimensions
impl NcDirect {
/// Can we load images?
///
/// Requires being built against FFmpeg/OIIO.
///
/// *C style function: [ncdirect_canopen_images()][crate::ncdirect_canopen_images].*
pub fn canopen_images(&self) -> bool {
unsafe { crate::ncdirect_canopen_images(self) }
}
/// Is our encoding UTF-8?
///
/// Requires LANG being set to a UTF8 locale.
///
/// *C style function: [ncdirect_canutf8()][crate::ncdirect_canutf8].*
pub fn canutf8(&self) -> bool {
unsafe { crate::ncdirect_canutf8(self) }
}
/// Disables the terminal's cursor, if supported.
///
/// *C style function: [ncdirect_cursor_disable()][crate::ncdirect_cursor_disable].*
pub fn cursor_disable(&mut self) -> NcResult {
unsafe { crate::ncdirect_cursor_disable(self) }
}
/// Enables the terminal's cursor, if supported.
///
/// *C style function: [ncdirect_cursor_enable()][crate::ncdirect_cursor_enable].*
pub fn cursor_enable(&mut self) -> NcResult {
unsafe { crate::ncdirect_cursor_enable(self) }
}
/// Moves the cursor down, `num` rows.
///
/// *C style function: [ncdirect_cursor_down()][crate::ncdirect_cursor_down].*
pub fn cursor_down(&mut self, num: NcDimension) -> NcResult {
unsafe { crate::ncdirect_cursor_down(self, num as i32) }
}
/// Moves the cursor left, `num` columns.
///
/// *C style function: [ncdirect_cursor_left()][crate::ncdirect_cursor_left].*
pub fn cursor_left(&mut self, num: NcDimension) -> NcResult {
unsafe { crate::ncdirect_cursor_left(self, num as i32) }
}
/// Moves the cursor right, `num` columns.
///
/// *C style function: [ncdirect_cursor_right()][crate::ncdirect_cursor_right].*
pub fn cursor_right(&mut self, num: NcDimension) -> NcResult {
unsafe { crate::ncdirect_cursor_right(self, num as i32) }
}
/// Moves the cursor up, `num` rows.
///
/// *C style function: [ncdirect_cursor_up()][crate::ncdirect_cursor_up].*
pub fn cursor_up(&mut self, num: NcDimension) -> NcResult {
unsafe { crate::ncdirect_cursor_up(self, num as i32) }
}
/// Moves the cursor in direct mode to the specified row, column.
///
/// *C style function: [ncdirect_cursor_move_yx()][crate::ncdirect_cursor_move_yx].*
pub fn cursor_move_yx(&mut self, y: NcDimension, x: NcDimension) -> NcResult {
unsafe { crate::ncdirect_cursor_move_yx(self, y as i32, x as i32) }
}
/// Moves the cursor in direct mode to the specified row.
///
/// *(No equivalent C style function)*
pub fn cursor_move_y(&mut self, y: NcDimension) -> NcResult {
unsafe { crate::ncdirect_cursor_move_yx(self, y as i32, -1) }
}
/// Moves the cursor in direct mode to the specified column.
///
/// *(No equivalent C style function)*
pub fn cursor_move_x(&mut self, x: NcDimension) -> NcResult {
unsafe { crate::ncdirect_cursor_move_yx(self, -1, x as i32) }
}
/// Gets the cursor position, when supported.
///
/// This requires writing to the terminal, and then reading from it.
/// If the terminal doesn't reply, or doesn't reply in a way we understand,
/// the results might be deleterious.
///
/// *C style function: [ncdirect_cursor_yx()][crate::ncdirect_cursor_yx].*
pub fn cursor_yx(&mut self) -> Option<(NcDimension, NcDimension)> {
let (mut y, mut x) = (0, 0);
let res = unsafe { crate::ncdirect_cursor_yx(self, &mut y, &mut x) };
if res == NCRESULT_OK {
return Some((y as NcDimension, x as NcDimension));
}
None
}
/// Pushes the cursor location to the terminal's stack.
///
/// The depth of this stack, and indeed its existence, is terminal-dependent.
///
/// *C style function: [ncdirect_cursor_push()][crate::ncdirect_cursor_push].*
pub fn cursor_push(&mut self) -> NcResult {
unsafe { crate::ncdirect_cursor_push(self) }
}
/// Pops the cursor location from the terminal's stack.
///
/// The depth of this stack, and indeed its existence, is terminal-dependent.
///
/// *C style function: [ncdirect_cursor_pop()][crate::ncdirect_cursor_pop].*
pub fn cursor_pop(&mut self) -> NcResult {
unsafe { crate::ncdirect_cursor_pop(self) }
}
/// Gets the current number of rows.
///
/// *C style function: [ncdirect_dim_y()][crate::ncdirect_dim_y].*
pub fn cursor_dim_y(&self) -> NcDimension {
unsafe { crate::ncdirect_dim_y(self) as NcDimension }
}
/// Gets the current number of columns.
///
/// *C style function: [ncdirect_dim_x()][crate::ncdirect_dim_x].*
pub fn cursor_dim_x(&self) -> NcDimension {
unsafe { crate::ncdirect_dim_x(self) as NcDimension }
}
}
/// ## NcDirect methods: I/O
impl NcDirect {
/// Returns a [char] representing a single unicode point.
///
/// If an event is processed, the return value is the `id` field from that
/// event.
///
/// Provide a None `time` to block at length, a `time` of 0 for non-blocking
/// operation, and otherwise a timespec to bound blocking.
///
/// Signals in sigmask (less several we handle internally) will be atomically
/// masked and unmasked per [ppoll(2)](https://linux.die.net/man/2/ppoll).
///
/// `*sigmask` should generally contain all signals.
///
/// *C style function: [ncdirect_getc()][crate::ncdirect_getc].*
//
// CHECK returns 0 on a timeout.
pub fn getc(
&mut self,
time: Option<NcTime>,
sigmask: Option<&mut sigset_t>,
input: Option<&mut NcInput>,
) -> Option<char> {
let ntime;
if let Some(time) = time {
ntime = &time as *const _;
} else {
ntime = null();
}
let nsigmask;
if let Some(sigmask) = sigmask {
nsigmask = sigmask as *mut _;
} else {
nsigmask = null_mut() as *mut _;
}
let ninput;
if let Some(input) = input {
ninput = input as *mut _;
} else {
ninput = null_mut();
}
let c = unsafe {
core::char::from_u32_unchecked(crate::ncdirect_getc(self, ntime, nsigmask, ninput))
};
if c as u32 as i32 == NCRESULT_ERR {
return None;
}
Some(c)
}
///
/// *C style function: [ncdirect_getc_nblock()][crate::ncdirect_getc_nblock].*
pub fn getc_nblock(&mut self, input: &mut NcInput) -> char {
crate::ncdirect_getc_nblock(self, input)
}
///
/// *C style function: [ncdirect_getc_nblocking()][crate::ncdirect_getc_nblocking].*
pub fn getc_nblocking(&mut self, input: &mut NcInput) -> char {
crate::ncdirect_getc_nblocking(self, input)
}
/// Get a file descriptor suitable for input event poll()ing.
///
/// When this descriptor becomes available, you can call
/// [getc_nblock()][NcDirect#method.getc_nblock], and input ought be ready.
///
/// This file descriptor is not necessarily the file descriptor associated
/// with stdin (but it might be!).
///
/// *C style function: [ncdirect_inputready_fd()][crate::ncdirect_inputready_fd].*
pub fn inputready_fd(&mut self) -> NcResult {
unsafe { crate::ncdirect_inputready_fd(self) }
}
/// Outputs the `string` according to the `channels`.
///
/// Note that it does not explicitly flush output buffers, so it will not
/// necessarily be immediately visible.
///
/// *C style function: [ncdirect_putstr()][crate::ncdirect_putstr].*
pub fn putstr(&mut self, channels: NcChannelPair, string: &str) -> NcResult {
unsafe { crate::ncdirect_putstr(self, channels, cstring![string]) }
}
/// Draws a box with its upper-left corner at the current cursor position,
/// having dimensions `ylen` * `xlen`.
///
/// See NcPlane.[box()][crate::NcPlane#method.box] for more information.
///
/// The minimum box size is 2x2, and it cannot be drawn off-screen.
///
/// `wchars` is an array of 6 characters: UL, UR, LL, LR, HL, VL.
///
/// *C style function: [ncdirect_box()][crate::ncdirect_box].*
// TODO: CHECK, specially wchars.
pub fn r#box(
&mut self,
ul: NcChannelPair,
ur: NcChannelPair,
ll: NcChannelPair,
lr: NcChannelPair,
wchars: &[char; 6],
y_len: NcDimension,
x_len: NcDimension,
ctlword: u32,
) -> NcResult {
unsafe {
let wchars = core::mem::transmute(wchars);
crate::ncdirect_box(
self,
ul,
ur,
ll,
lr,
wchars,
y_len as i32,
x_len as i32,
ctlword,
)
}
}
/// NcDirect.[box()][NcDirect#method.box] with the double box-drawing characters.
///
/// *C style function: [ncdirect_double_box()][crate::ncdirect_double_box].*
pub fn double_box(
&mut self,
ul: NcChannelPair,
ur: NcChannelPair,
ll: NcChannelPair,
lr: NcChannelPair,
y_len: NcDimension,
x_len: NcDimension,
ctlword: u32,
) -> NcResult {
unsafe {
crate::ncdirect_double_box(self, ul, ur, ll, lr, y_len as i32, x_len as i32, ctlword)
}
}
/// NcDirect.[box()][NcDirect#method.box] with the rounded box-drawing characters.
///
/// *C style function: [ncdirect_rounded_box()][crate::ncdirect_rounded_box].*
pub fn rounded_box(
&mut self,
ul: NcChannelPair,
ur: NcChannelPair,
ll: NcChannelPair,
lr: NcChannelPair,
y_len: NcDimension,
x_len: NcDimension,
ctlword: u32,
) -> NcResult {
unsafe {
crate::ncdirect_rounded_box(self, ul, ur, ll, lr, y_len as i32, x_len as i32, ctlword)
}
}
/// Draws horizontal lines using the specified [NcChannelPair]s, interpolating
/// between them as we go.
///
/// All lines start at the current cursor position.
///
/// The [NcEgc] at `egc` may not use more than one column.
///
/// For a horizontal line, `len` cannot exceed the screen width minus the
/// cursor's offset.
///
/// *C style function: [ncdirect_hline_interp()][crate::ncdirect_hline_interp].*
#[inline]
pub fn hline_interp(
&mut self,
egc: &NcEgc,
len: NcDimension,
h1: NcChannelPair,
h2: NcChannelPair,
) -> NcResult {
unsafe { crate::ncdirect_hline_interp(self, &(*egc as i8), len as i32, h1, h2) }
}
/// Draws horizontal lines using the specified [NcChannelPair]s, interpolating
/// between them as we go.
///
/// All lines start at the current cursor position.
///
/// The [NcEgc] at `egc` may not use more than one column.
///
/// For a vertical line, `len` may be as long as you'd like; the screen
/// will scroll as necessary.
///
/// *C style function: [ncdirect_vline_interp()][crate::ncdirect_vline_interp].*
#[inline]
pub fn vline_interp(
&mut self,
egc: &NcEgc,
len: NcDimension,
h1: NcChannelPair,
h2: NcChannelPair,
) -> NcResult {
unsafe { crate::ncdirect_vline_interp(self, &(*egc as i8), len as i32, h1, h2) }
}
}

@ -2,52 +2,66 @@
// functions already exported by bindgen : 38
// ------------------------------------------
// (W) wrap: 1 / 37
// (#) test: 0 / 38
// (X) wont: 1
// (#) test: 0
// (W) wrap: 37 / 0
// ------------------------------------------
// ncdirect_bg_default
// ncdirect_bg_palindex
// ncdirect_bg_rgb
// ncdirect_box
// ncdirect_canopen_images
// ncdirect_canutf8
// ncdirect_clear
// ncdirect_cursor_disable
// ncdirect_cursor_down
// ncdirect_cursor_enable
// ncdirect_cursor_left
// ncdirect_cursor_move_yx
// ncdirect_cursor_pop
// ncdirect_cursor_push
// ncdirect_cursor_right
// ncdirect_cursor_up
// ncdirect_cursor_yx
// ncdirect_dim_x
// ncdirect_dim_y
// ncdirect_double_box
// ncdirect_fg_default
// ncdirect_fg_palindex
// ncdirect_fg_rgb
// ncdirect_flush
// ncdirect_getc
// ncdirect_hline_interp
//W ncdirect_init
// ncdirect_inputready_fd
// ncdirect_palette_size
// ncdirect_printf_aligned
// ncdirect_putstr
// ncdirect_render_image
// ncdirect_rounded_box
// ncdirect_stop
// ncdirect_styles_off
// ncdirect_styles_on
// ncdirect_styles_set
// ncdirect_vline_interp
//W ncdirect_bg_default
//W ncdirect_bg_palindex
//W ncdirect_bg_rgb
//W ncdirect_box
//W ncdirect_canopen_images
//W ncdirect_canutf8
//W ncdirect_clear
//W ncdirect_cursor_disable
//W ncdirect_cursor_down
//W ncdirect_cursor_enable
//W ncdirect_cursor_left
//W ncdirect_cursor_move_yx
//W ncdirect_cursor_pop
//W ncdirect_cursor_push
//W ncdirect_cursor_right
//W ncdirect_cursor_up
//W ncdirect_cursor_yx
//W ncdirect_dim_x
//W ncdirect_dim_y
//W ncdirect_double_box
//W ncdirect_fg_default
//W ncdirect_fg_palindex
//W ncdirect_fg_rgb
//W ncdirect_flush
//W ncdirect_getc
//W ncdirect_hline_interp
//W ncdirect_init
//W ncdirect_inputready_fd
//W ncdirect_palette_size
// X ncdirect_printf_aligned
//W ncdirect_putstr
//W ncdirect_render_image
//W ncdirect_rounded_box
//W ncdirect_stop
//W ncdirect_styles_off
//W ncdirect_styles_on
//W ncdirect_styles_set
//W ncdirect_vline_interp
//
// functions manually reimplemented: 4
// ------------------------------------------
// (+) done: 4 / 0
// (W) wrap: 4 / 0
// (#) test: 0
// ------------------------------------------
//W+ ncdirect_bg_rgb8
//W+ ncdirect_fg_rgb8
//W+ ncdirect_getc_nblock
//W+ ncdirect_getc_nblocking
#[cfg(test)]
mod test;
mod methods;
mod reimplemented;
pub use reimplemented::*;
/// Minimal notcurses instances for styling text
pub type NcDirect = crate::bindings::ffi::ncdirect;

@ -0,0 +1,70 @@
//! `ncdirect_*` reimplemented functions.
use core::ptr::null;
use crate::{NcColor, NcDirect, NcInput, NcResult, NcRgb, NcSignalSet, NcTime};
///
/// If no event is ready, returns 0.
///
/// *Method: NcDirect.[getc_nblock()][NcDirect#method.getc_nblock].*
//
// `input` may be NULL if the caller is uninterested in event details.
#[inline]
pub fn ncdirect_getc_nblock(nc: &mut NcDirect, input: &mut NcInput) -> char {
unsafe {
let mut sigmask = NcSignalSet::new();
sigmask.fillset();
let ts = NcTime::new();
core::char::from_u32_unchecked(crate::ncdirect_getc(nc, &ts, &mut sigmask, input))
}
}
/// 'input' may be NULL if the caller is uninterested in event details.
/// Blocks until an event is processed or a signal is received.
///
/// *Method: NcDirect.[getc_nblocking()][NcDirect#method.getc_nblocking].*
#[inline]
pub fn ncdirect_getc_nblocking(nc: &mut NcDirect, input: &mut NcInput) -> char {
unsafe {
let mut sigmask = NcSignalSet::new();
sigmask.emptyset();
core::char::from_u32_unchecked(crate::ncdirect_getc(nc, null(), &mut sigmask, input))
}
}
/// Sets the foreground [NcColor] components.
///
/// *Method: NcDirect.[fg_rgb8()][NcDirect#method.getc_fg_rgb8].*
#[inline]
pub fn ncdirect_fg_rgb8(
ncd: &mut NcDirect,
red: NcColor,
green: NcColor,
blue: NcColor,
) -> NcResult {
unsafe {
crate::ncdirect_fg_rgb(
ncd,
(red as NcRgb) << 16 + (green as NcRgb) << 8 + blue as NcRgb,
)
}
}
/// Sets the background [NcColor] components.
///
/// *Method: NcDirect.[bg_rgb8()][NcDirect#method.getc_bg_rgb8].*
#[inline]
pub fn ncdirect_bg_rgb8(
ncd: &mut NcDirect,
red: NcColor,
green: NcColor,
blue: NcColor,
) -> NcResult {
unsafe {
crate::ncdirect_bg_rgb(
ncd,
(red as NcRgb) << 16 + (green as NcRgb) << 8 + blue as NcRgb,
)
}
}

@ -128,6 +128,7 @@ mod palette;
mod pixel;
mod plane;
mod resizecb;
mod signal;
mod stats;
mod time;
mod visual;
@ -149,6 +150,7 @@ pub use pixel::*;
pub use plane::*;
pub use r#box::*;
pub use resizecb::*;
pub use signal::*;
pub use stats::*;
pub use time::*;
pub use visual::*;

@ -4,10 +4,10 @@ use core::ptr::{null, null_mut};
use std::ffi::CStr;
use crate::{
cstring, notcurses_init, sigset_t, NcAlign, NcBlitter, NcChannelPair, NcDimension, NcEgc,
NcFile, NcInput, NcLogLevel, NcPlane, NcResult, NcScale, NcStats, NcStyleMask, NcTime,
cstring, notcurses_init, NcAlign, NcBlitter, NcChannelPair, NcDimension, NcEgc, NcFile,
NcInput, NcLogLevel, NcPlane, NcResult, NcScale, NcSignalSet, NcStats, NcStyleMask, NcTime,
Notcurses, NotcursesOptions, NCOPTION_NO_ALTERNATE_SCREEN, NCOPTION_SUPPRESS_BANNERS,
NCRESULT_OK,
NCRESULT_ERR, NCRESULT_OK,
};
/// # `NotcursesOptions` Constructors
@ -261,10 +261,52 @@ impl Notcurses {
}
}
/// Returns a [char] representing a single unicode point.
///
/// If an event is processed, the return value is the `id` field from that
/// event.
///
/// Provide a None `time` to block at length, a `time` of 0 for non-blocking
/// operation, and otherwise a timespec to bound blocking.
///
/// Signals in sigmask (less several we handle internally) will be atomically
/// masked and unmasked per [ppoll(2)](https://linux.die.net/man/2/ppoll).
///
/// `*sigmask` should generally contain all signals.
///
/// *C style function: [notcurses_getc()][crate::notcurses_getc].*
pub fn getc(&mut self, time: &NcTime, sigmask: &mut sigset_t, input: &mut NcInput) -> char {
unsafe { core::char::from_u32_unchecked(crate::notcurses_getc(self, time, sigmask, input)) }
pub fn getc(
&mut self,
time: Option<NcTime>,
sigmask: Option<&mut NcSignalSet>,
input: Option<&mut NcInput>,
) -> Option<char> {
let ntime;
if let Some(time) = time {
ntime = &time as *const _;
} else {
ntime = null();
}
let nsigmask;
if let Some(sigmask) = sigmask {
nsigmask = sigmask as *mut _;
} else {
nsigmask = null_mut() as *mut _;
}
let ninput;
if let Some(input) = input {
ninput = input as *mut _;
} else {
ninput = null_mut();
}
let c = unsafe {
core::char::from_u32_unchecked(crate::notcurses_getc(self, ntime, nsigmask, ninput))
};
if c as u32 as i32 == NCRESULT_ERR {
return None;
}
Some(c)
}
///
@ -464,7 +506,7 @@ impl Notcurses {
crate::notcurses_stddim_yx(nc, y, x)
}
/// [stdplane_const()][#method.stdplane_const], plus free
/// [stdplane_const()][Notcurses#method.stdplane_const], plus free
/// bonus dimensions written to non-NULL y/x!
///
/// *C style function: [notcurses_stddim_yx()][crate::notcurses_stddim_yx].*

@ -3,13 +3,10 @@
use core::ptr::null;
use crate::{
NcAlign, NcDimension, NcInput, NcOffset, NcPlane, NcTime, Notcurses, NCALIGN_CENTER,
NCALIGN_LEFT, NCALIGN_RIGHT, NCRESULT_MAX,
NcAlign, NcDimension, NcInput, NcOffset, NcPlane, NcSignalSet, NcTime, Notcurses,
NCALIGN_CENTER, NCALIGN_LEFT, NCALIGN_RIGHT, NCRESULT_MAX,
};
// can't use libc::sigset_t with notcurses_getc(()
use crate::bindings::{sigemptyset, sigfillset, sigset_t};
/// Returns the offset into `availcols` at which `cols` ought be output given
/// the requirements of `align`.
///
@ -43,8 +40,8 @@ pub fn notcurses_align(availcols: NcDimension, align: NcAlign, cols: NcDimension
#[inline]
pub fn notcurses_getc_nblock(nc: &mut Notcurses, input: &mut NcInput) -> char {
unsafe {
let mut sigmask = sigset_t { __val: [0; 16] };
sigfillset(&mut sigmask);
let mut sigmask = NcSignalSet::new();
sigmask.fillset();
let ts = NcTime {
tv_sec: 0,
tv_nsec: 0,
@ -61,8 +58,8 @@ pub fn notcurses_getc_nblock(nc: &mut Notcurses, input: &mut NcInput) -> char {
#[inline]
pub fn notcurses_getc_nblocking(nc: &mut Notcurses, input: &mut NcInput) -> char {
unsafe {
let mut sigmask = sigset_t { __val: [0; 16] };
sigemptyset(&mut sigmask);
let mut sigmask = NcSignalSet::new();
sigmask.emptyset();
core::char::from_u32_unchecked(crate::notcurses_getc(nc, null(), &mut sigmask, input))
}
}

@ -9,7 +9,7 @@ use crate::{
NcResult, NcRgb, NcStyleMask, NcTime, Notcurses, NCRESULT_OK,
};
/// # `NcPlaneOptions` Constructors
/// # NcPlaneOptions Constructors
impl NcPlaneOptions {
/// New NcPlaneOptions using the horizontal x.
pub fn new(y: NcOffset, x: NcOffset, rows: NcDimension, cols: NcDimension) -> Self {
@ -1380,7 +1380,7 @@ impl NcPlane {
crate::ncplane_box_sized(self, ul, ur, ll, lr, hline, vline, y_len, x_len, boxmask)
}
///
/// NcPlane.[box()][NcPlane#method.box] with the double box-drawing characters.
///
/// *C style function: [ncplane_double_box()][crate::ncplane_double_box].*
#[inline]

@ -0,0 +1,63 @@
//! `NcSigSet`
use crate::NcResult;
/// A wrapper over
/// [sigset_t](https://www.gnu.org/software/libc/manual/html_node/Signal-Sets.html).
//
// Expected by [`notcurses_getc`], [`notcurses_getc_nblock`],
// [`ncdirect_getc`] & [`ncdirect_getc_nblock`], that can't use libc::sigset_t
pub type NcSignalSet = crate::bindings::ffi::sigset_t;
impl NcSignalSet {
/// New NcSignalSet.
pub fn new() -> Self {
Self { __val: [0; 16] }
}
/// Adds `signum` to this set.
pub fn addset(&mut self, signum: i32) -> NcResult {
unsafe { crate::bindings::ffi::sigaddset(self, signum) }
}
/// Removes `signum` from this set.
pub fn delset(&mut self, signum: i32) -> NcResult {
unsafe { crate::bindings::ffi::sigdelset(self, signum) }
}
/// Clears all signals from this set.
pub fn emptyset(&mut self) -> NcResult {
unsafe { crate::bindings::ffi::sigemptyset(self) }
}
/// Sets all signals in this set.
pub fn fillset(&mut self) -> NcResult {
unsafe { crate::bindings::ffi::sigfillset(self) }
}
/// Is `signum` a member of this set?
pub fn ismember(&self, signum: i32) -> bool {
if unsafe { crate::bindings::ffi::sigismember(self, signum) } == 1 {
return true;
}
false
}
/// Puts in this set all signals that are blocked and waiting to be delivered.
pub fn pending(&mut self) -> NcResult {
unsafe { crate::bindings::ffi::sigpending(self) }
}
/// Gets and/or changes the set of blocked signals.
//
// https://linux.die.net/man/2/sigprocmask
pub fn procmask(how: i32, set: &NcSignalSet, old_set: &mut NcSignalSet) -> NcResult {
unsafe { crate::bindings::ffi::sigprocmask(how, set, old_set) }
}
/// Changes the set of blocked signals to the ones in this set,
/// waits until a signal arrives, and restores the set of blocked signals.
pub fn suspend(&self) -> NcResult {
unsafe { crate::bindings::ffi::sigsuspend(self) }
}
}

@ -4,3 +4,12 @@
// Expected by [`notcurses_getc`] & [`notcurses_getc_nblock`], that can't use
// libc::timespec
pub type NcTime = crate::bindings::ffi::timespec;
impl NcTime {
pub fn new() -> Self {
Self {
tv_sec: 0,
tv_nsec: 0,
}
}
}

Loading…
Cancel
Save