rust: big refactor

- move tests to their own submodules
- move functions reimplementations to reimplemented submodule.
- remove types submodules and move them to their parent.
- add more NcPlane & Notcurses methods
- rename NcChar back to NcEgc, and NcCharBackstop tp NcEgcBackstop
- add ncpile_top & ncpile_bottom functions.
- fix Notcurses stdplane(_mut) methods
- make cell_load_char not return anything since it was always 1.
pull/1178/head
joseLuís 4 years ago
parent e5306f6197
commit 01e4f7de5a

@ -304,9 +304,11 @@ pub use bindgen::{
#[doc(inline)]
pub use bindgen::{
// functions
ncpile_bottom,
ncpile_create,
ncpile_rasterize,
ncpile_render,
ncpile_top,
};
// ncplane ---------------------------------------------------------------------

@ -0,0 +1,87 @@
//! `NcCell` methods and associated functions.
pub use crate::{
cell_load, cstring, NcCell, NcChannelPair, NcEgcBackstop, NcPlane, NcStyleMask, NCRESULT_ERR,
};
use crate::{cell_extract, NcEgc};
/// # `NcCell` Constructors
impl NcCell {
/// New NcCell, expects a [char], [NcStyleMask] and [NcChannelPair].
#[inline]
pub const fn with_all(ch: char, stylemask: NcStyleMask, channels: NcChannelPair) -> Self {
NcCell {
gcluster: ch as u32,
gcluster_backstop: 0 as NcEgcBackstop,
reserved: 0,
stylemask,
channels,
}
}
/// New NcCell, expects a 7-bit [char].
#[inline]
pub const fn with_7bitchar(ch: char) -> Self {
Self::with_all(ch, 0 as NcStyleMask, 0 as NcChannelPair)
}
/// New NcCell, expects an [NcPlane] and a utf-8 [char].
#[inline]
pub fn with_char(plane: &mut NcPlane, ch: char) -> Self {
let mut cell = Self::new();
let result = unsafe { cell_load(plane, &mut cell, cstring![ch.to_string()]) };
debug_assert_ne![NCRESULT_ERR, result];
cell
}
/// New NcCell, expects an [NcPlane] and a &[str].
#[inline]
pub fn with_str(plane: &mut NcPlane, string: &str) -> Self {
let mut cell = Self::new();
let result = unsafe { cell_load(plane, &mut cell, cstring![string]) };
debug_assert_ne![NCRESULT_ERR, result];
cell
}
/// New NcCell, blank.
#[inline]
pub const fn new() -> Self {
Self::with_7bitchar(0 as char)
}
}
/// # `NcCell` Methods
impl NcCell {
/// Saves the [NcStyleMask] and the [NcChannelPair], and returns the [NcEgc]
/// (the three elements of an NcCell).
pub fn extract(
&mut self,
plane: &mut NcPlane,
styles: &mut NcStyleMask,
channels: &mut NcChannelPair,
) -> NcEgc {
cell_extract(plane, self, styles, channels)
}
/// Saves the [NcChannelPair] of the NcCell.
// not in the C API
pub fn channels(&mut self, plane: &mut NcPlane, channels: &mut NcChannelPair) {
let mut _styles = 0;
let _char = cell_extract(plane, self, &mut _styles, channels);
}
/// Saves the [NcStyleMask] of the NcCell.
// not in the C API
pub fn styles(&mut self, plane: &mut NcPlane, styles: &mut NcStyleMask) {
let mut _channels = 0;
let _char = cell_extract(plane, self, styles, &mut _channels);
}
/// Returns the [NcEgc] of the NcCell.
// not in the C API
pub fn egc(&mut self, plane: &mut NcPlane) -> NcEgc {
let (mut _styles, mut _channels) = (0, 0);
cell_extract(plane, self, &mut _styles, &mut _channels)
}
}

@ -1,4 +1,4 @@
//! [NcCell] `cell*_*` static functions reimplementations
//! `NcCell`
// functions already exported by bindgen : 6
// -----------------------------------------
@ -9,498 +9,384 @@
// cells_double_box
// cells_rounded_box
//
// static inline functions total: 42
// ------------------------------------------ (implement / remaining)
// functions manually reimplemented: 42
// ------------------------------------------
// (X) wont: 2
// (+) done: 40 / 0
// (W) wrap: 1 / 39
// (#) test: 26 / 14
// ------------------------------------------
//# cell_bchannel
//# cell_bg_alpha
//# cell_bg_default_p
//# cell_bg_palindex
//# cell_bg_palindex_p
//# cell_bg_rgb
//# cell_bg_rgb8
//+ cellcmp
//+ cell_double_wide_p
//+ cell_extract
//# cell_fchannel
//# cell_fg_alpha
//# cell_fg_default_p
//# cell_fg_palindex
//# cell_fg_palindex_p
//# cell_fg_rgb
//# cell_fg_rgb8
//+ cell_init
//+ cell_load_char
//+ cell_prime
//# cell_set_bchannel
//# cell_set_bg_alpha
//# cell_set_bg_default
//# cell_set_bg_palindex
//# cell_set_bg_rgb
//# cell_set_bg_rgb8
//X cell_set_bg_rgb8_clipped // unneeded
//# cell_set_fchannel
//# cell_set_fg_alpha
//# cell_set_fg_default
//# cell_set_fg_palindex
//# cell_set_fg_rgb
//# cell_set_fg_rgb8
//X cell_set_fg_rgb8_clipped // unneeded
//+ cells_load_box
//+ cell_strdup
//+ cell_styles
//+ cell_styles_off
//+ cell_styles_on
//+ cell_styles_set
//+ cell_wide_left_p
//+ cell_wide_right_p
// # cell_bchannel
// # cell_bg_alpha
// # cell_bg_default_p
// # cell_bg_palindex
// # cell_bg_palindex_p
// # cell_bg_rgb
// # cell_bg_rgb8
// + cellcmp
// + cell_double_wide_p
//W+ cell_extract
// # cell_fchannel
// # cell_fg_alpha
// # cell_fg_default_p
// # cell_fg_palindex
// # cell_fg_palindex_p
// # cell_fg_rgb
// # cell_fg_rgb8
// + cell_init
// + cell_load_char
// + cell_prime
// # cell_set_bchannel
// # cell_set_bg_alpha
// # cell_set_bg_default
// # cell_set_bg_palindex
// # cell_set_bg_rgb
// # cell_set_bg_rgb8
// X cell_set_bg_rgb8_clipped // unneeded
// # cell_set_fchannel
// # cell_set_fg_alpha
// # cell_set_fg_default
// # cell_set_fg_palindex
// # cell_set_fg_rgb
// # cell_set_fg_rgb8
// X cell_set_fg_rgb8_clipped // unneeded
// + cells_load_box
// + cell_strdup
// + cell_styles
// + cell_styles_off
// + cell_styles_on
// + cell_styles_set
// + cell_wide_left_p
// + cell_wide_right_p
#[cfg(test)]
mod tests;
mod types;
pub use types::{
NcCell, NcChar, NcCharBackstop, NcStyleMask, NCCELL_ALPHA_BLEND, NCCELL_ALPHA_HIGHCONTRAST,
NCCELL_ALPHA_OPAQUE, NCCELL_ALPHA_TRANSPARENT, NCCELL_BGDEFAULT_MASK, NCCELL_BG_ALPHA_MASK,
NCCELL_BG_PALETTE, NCCELL_BG_RGB_MASK, NCCELL_FGDEFAULT_MASK, NCCELL_FG_ALPHA_MASK,
NCCELL_FG_PALETTE, NCCELL_FG_RGB_MASK, NCCELL_NOBACKGROUND_MASK, NCCELL_WIDEASIAN_MASK,
NCSTYLE_BLINK, NCSTYLE_BOLD, NCSTYLE_DIM, NCSTYLE_INVIS, NCSTYLE_ITALIC, NCSTYLE_MASK,
NCSTYLE_NONE, NCSTYLE_PROTECT, NCSTYLE_REVERSE, NCSTYLE_STANDOUT, NCSTYLE_STRUCK,
NCSTYLE_UNDERLINE,
};
mod wrapped;
pub use wrapped::*;
use libc::strcmp;
use crate::{
cell_extended_gcluster, cell_load, cell_release, channels_bchannel, channels_bg_alpha,
channels_bg_default_p, channels_bg_palindex_p, channels_bg_rgb, channels_bg_rgb8,
channels_fchannel, channels_fg_alpha, channels_fg_default_p, channels_fg_palindex_p,
channels_fg_rgb, channels_fg_rgb8, channels_set_bchannel, channels_set_bg_alpha,
channels_set_bg_default, channels_set_bg_rgb, channels_set_bg_rgb8, channels_set_fchannel,
channels_set_fg_alpha, channels_set_fg_default, channels_set_fg_rgb, channels_set_fg_rgb8,
NcAlphaBits, NcChannel, NcChannelPair, NcColor, NcPaletteIndex, NcPlane, NcResult, NcRgb,
NCRESULT_ERR, NCRESULT_OK,
};
/// Same as [cell_load], plus blasts the styling with 'style' and 'channels'.
///
/// - Breaks the UTF-8 string in 'gcluster' down, setting up the cell 'cell'.
/// - Returns the number of bytes copied out of 'gcluster', or -1 on failure.
/// - The styling of the cell is left untouched, but any resources are released.
/// - Blasts the styling with 'style' and 'channels'.
///
#[allow(unused_unsafe)]
pub unsafe fn cell_prime(
plane: &mut NcPlane,
cell: &mut NcCell,
gcluster: NcChar,
style: NcStyleMask,
channels: NcChannelPair,
) -> NcResult {
cell.stylemask = style;
cell.channels = channels;
unsafe { cell_load(plane, cell, gcluster as u32 as *const i8) }
}
/// Loads up six cells with the [NcChar]s necessary to draw a box.
///
/// Returns [NCRESULT_OK] on success, [NCRESULT_ERR] on error.
///
/// On error, any [NcCell]s this function might have loaded before the error
/// are [cell_release]d. There must be at least six [NcChar]s in gcluster.
///
#[allow(unused_unsafe)]
pub unsafe fn cells_load_box(
plane: &mut NcPlane,
style: NcStyleMask,
channels: NcChannelPair,
ul: &mut NcCell,
ur: &mut NcCell,
ll: &mut NcCell,
lr: &mut NcCell,
hl: &mut NcCell,
vl: &mut NcCell,
gcluster: NcChar,
) -> NcResult {
// mutable copy for pointer arithmetics:
let mut gclu = gcluster as u32 as *const i8;
let mut ulen: NcResult;
ulen = unsafe { cell_prime(plane, ul, gcluster, style, channels) };
if ulen > 0 {
gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, ur, gcluster, style, channels) };
if ulen > 0 {
gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, ll, gcluster, style, channels) };
if ulen > 0 {
gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, lr, gcluster, style, channels) };
if ulen > 0 {
gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, hl, gcluster, style, channels) };
if ulen > 0 {
let _gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, vl, gcluster, style, channels) };
if ulen > 0 {
return NCRESULT_OK;
}
unsafe {
cell_release(plane, hl);
}
}
unsafe {
cell_release(plane, lr);
}
}
unsafe {
cell_release(plane, ll);
}
}
unsafe {
cell_release(plane, ur);
}
}
unsafe {
cell_release(plane, ul);
}
}
NCRESULT_ERR
}
/// Initializes (zeroes out) an [NcCell].
#[inline]
pub fn cell_init(cell: &mut NcCell) {
*cell = unsafe { core::mem::zeroed() }
}
/// Sets *just* the specified [NcStyleMask] bits for an [NcCell],
/// whether they're actively supported or not.
#[inline]
pub fn cell_styles_set(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask = stylebits & NCSTYLE_MASK as u16;
}
/// Extracts the [NcStyleMask] bits from an [NcCell].
#[inline]
pub fn cell_styles(cell: &NcCell) -> NcStyleMask {
cell.stylemask
}
/// Adds the specified [NcStyleMask] bits to an [NcCell]'s existing spec.,
/// whether they're actively supported or not.
#[inline]
pub fn cell_styles_on(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask |= stylebits & NCSTYLE_MASK as u16;
}
/// Removes the specified [NcStyleMask] bits from an [NcCell]'s existing spec.
#[inline]
pub fn cell_styles_off(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask &= !(stylebits & NCSTYLE_MASK as u16);
}
/// Indicates to use the "default color" for the **foreground** [NcChannel]
/// of an [NcCell].
#[inline]
pub fn cell_set_fg_default(cell: &mut NcCell) {
channels_set_fg_default(&mut cell.channels);
}
/// Indicates to use the "default color" for the **background** [NcChannel]
/// of an [NcCell].
#[inline]
pub fn cell_set_bg_default(cell: &mut NcCell) {
channels_set_bg_default(&mut cell.channels);
}
/// Sets the foreground [NcAlphaBits] of an [NcCell].
#[inline]
pub fn cell_set_fg_alpha(cell: &mut NcCell, alpha: NcAlphaBits) {
channels_set_fg_alpha(&mut cell.channels, alpha);
}
/// Sets the background [NcAlphaBits] of an [NcCell].
#[inline]
pub fn cell_set_bg_alpha(cell: &mut NcCell, alpha: NcAlphaBits) {
channels_set_bg_alpha(&mut cell.channels, alpha);
}
/// Does the [NcCell] contain an East Asian Wide codepoint?
// NOTE: remove casting when fixed:
// https://github.com/rust-lang/rust-bindgen/issues/1875
#[inline]
pub fn cell_double_wide_p(cell: &NcCell) -> bool {
(cell.channels & NCCELL_WIDEASIAN_MASK as NcChannelPair) != 0
}
/// Is this the right half of a wide character?
#[inline]
pub fn cell_wide_right_p(cell: &NcCell) -> bool {
cell_double_wide_p(cell) && cell.gcluster == 0
}
/// Is this the left half of a wide character?
#[inline]
pub fn cell_wide_left_p(cell: &NcCell) -> bool {
cell_double_wide_p(cell) && cell.gcluster != 0
}
/// Copies the UTF8-encoded [NcChar] out of the cell, whether simple
/// or complex.
///
/// The result is not tied to the [NcPlane], and persists
/// across erases and destruction.
#[inline]
pub fn cell_strdup(plane: &NcPlane, cell: &NcCell) -> NcChar {
core::char::from_u32(unsafe { libc::strdup(cell_extended_gcluster(plane, cell)) } as i32 as u32)
.expect("wrong char")
// unsafer option B (maybe faster, TODO: bench)
// unsafe {
// core::char::from_u32_unchecked(libc::strdup(cell_extended_gcluster(plane, cell)) as i32 as u32)
// }
}
/// Saves the [NcStyleMask] and [NcChannelPair] and returns the [NcChar]
/// (the three elements of an [NcCell].
#[inline]
pub fn cell_extract(
plane: &NcPlane,
cell: &NcCell,
stylemask: &mut NcStyleMask,
channels: &mut NcChannelPair,
) -> NcChar {
if *stylemask != 0 {
*stylemask = cell.stylemask;
}
if *channels != 0 {
*channels = cell.channels;
}
cell_strdup(plane, cell)
}
/// Returns true if the two cells are distinct [NcChar]s, attributes, or channels
///
/// The actual egcpool index needn't be the same--indeed, the planes needn't even
/// be the same. Only the expanded NcChar must be equal. The NcChar must be bit-equal;
// NOTE: FIXME: it would probably be better to test whether they're Unicode-equal
#[inline]
pub fn cellcmp(plane1: &NcPlane, cell1: &NcCell, plane2: &NcPlane, cell2: &NcCell) -> bool {
if cell1.stylemask != cell2.stylemask {
return true;
}
if cell1.channels != cell2.channels {
return true;
}
unsafe {
strcmp(
cell_extended_gcluster(plane1, cell1),
cell_extended_gcluster(plane2, cell2),
) != 0
}
}
/// Loads a 7-bit char into the [NcCell].
// NOTE: remove casting for NCCELL_WIDEASIAN_MASK when fixed: https://github.com/rust-lang/rust-bindgen/issues/1875
#[inline]
pub fn cell_load_char(plane: &mut NcPlane, cell: &mut NcCell, ch: NcChar) -> i32 {
unsafe {
cell_release(plane, cell);
}
cell.channels &= !(NCCELL_WIDEASIAN_MASK as NcChannelPair | NCCELL_NOBACKGROUND_MASK);
cell.gcluster = ch as u32;
1
}
/// Extracts the 32-bit background [NcChannel] from an [NcCell].
#[inline]
pub fn cell_bchannel(cell: &NcCell) -> NcChannel {
channels_bchannel(cell.channels)
}
/// Extracts the 32-bit foreground [NcChannel] from an [NcCell].
#[inline]
pub fn cell_fchannel(cell: &NcCell) -> NcChannel {
channels_fchannel(cell.channels)
}
/// Sets the 32-bit background [NcChannel] of an [NcCell] and returns its new
/// [NcChannelPair].
#[inline]
pub fn cell_set_bchannel(cell: &mut NcCell, channel: NcChannel) -> NcChannelPair {
channels_set_bchannel(&mut cell.channels, channel)
}
/// Sets the 32-bit foreground [NcChannel] of an [NcCell] and returns its new
/// [NcChannelPair].
#[inline]
pub fn cell_set_fchannel(cell: &mut NcCell, channel: NcChannel) -> NcChannelPair {
channels_set_fchannel(&mut cell.channels, channel)
}
/// Extracts the foreground [NcRgb] 24-bit value from an [NcCell]
/// (shifted to LSBs).
#[inline]
pub fn cell_fg_rgb(cell: &NcCell) -> NcRgb {
channels_fg_rgb(cell.channels)
}
/// Extracts the background [NcRgb] 24-bit value from an [NcCell]
/// (shifted to LSBs).
#[inline]
pub fn cell_bg_rgb(cell: &NcCell) -> NcRgb {
channels_bg_rgb(cell.channels)
}
/// Extracts the foreground [NcAlphaBits] from an [NcCell] (shifted to LSBs).
#[inline]
pub fn cell_fg_alpha(cell: &NcCell) -> NcAlphaBits {
channels_fg_alpha(cell.channels)
}
/// Extracts the background [NcAlphaBits] from an [NcCell] (shifted to LSBs).
#[inline]
pub fn cell_bg_alpha(cell: &NcCell) -> NcAlphaBits {
channels_bg_alpha(cell.channels)
}
/// Extracts the foreground [NcRgb] 24-bit value from an [NcCell] and saves it
/// split into three [NcColor] 8-bit components. Also returns the corresponding
/// [NcChannel] (which can have some extra bits set).
#[inline]
pub fn cell_fg_rgb8(
cell: &NcCell,
red: &mut NcColor,
green: &mut NcColor,
blue: &mut NcColor,
) -> NcChannel {
channels_fg_rgb8(cell.channels, red, green, blue)
}
/// Extracts the background [NcRgb] 24-bit value from an [NcCell] and saves it
/// split into three [NcColor] 8-bit components. Also returns the corresponding
/// [NcChannel] (which can have some extra bits set).
#[inline]
pub fn cell_bg_rgb8(
cell: &NcCell,
red: &mut NcColor,
green: &mut NcColor,
blue: &mut NcColor,
) -> NcChannel {
channels_bg_rgb8(cell.channels, red, green, blue)
}
/// Sets the RGB [NcColor] components for the foreground [NcChannel] of an
/// [NcCell], and marks it as not using the default color.
#[inline]
pub fn cell_set_fg_rgb8(cell: &mut NcCell, red: NcColor, green: NcColor, blue: NcColor) {
channels_set_fg_rgb8(&mut cell.channels, red, green, blue);
}
/// Sets the 24-bit [NcRgb] value for the foreground [NcChannel] of an
/// [NcCell], and marks it as not using the default color.
#[inline]
pub fn cell_set_fg_rgb(cell: &mut NcCell, rgb: NcRgb) {
channels_set_fg_rgb(&mut cell.channels, rgb);
}
/// Sets an [NcCell]'s foreground [NcPaletteIndex].
///
/// Also sets [NCCELL_FG_PALETTE] and [NCCELL_ALPHA_OPAQUE],
/// and clears out [NCCELL_FGDEFAULT_MASK].
///
// NOTE: unlike the original C function, this one can't fail
#[inline]
pub fn cell_set_fg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
cell.channels |= NCCELL_FGDEFAULT_MASK;
cell.channels |= NCCELL_FG_PALETTE;
cell_set_fg_alpha(cell, NCCELL_ALPHA_OPAQUE);
cell.channels &= 0xff000000ffffffff as NcChannelPair;
cell.channels |= (index as NcChannelPair) << 32;
}
/// Returns the [NcPaletteIndex] of the foreground [NcChannel] of the
/// [NcCell]
#[inline]
pub fn cell_fg_palindex(cell: &NcCell) -> NcPaletteIndex {
((cell.channels & 0xff00000000 as NcChannelPair) >> 32) as NcPaletteIndex
}
/// Sets the [NcColor] 8-bit RGB components of the background [NcChannel]
/// of the [NcCell], and marks it as not using the "default color".
#[inline]
pub fn cell_set_bg_rgb8(cell: &mut NcCell, red: NcColor, green: NcColor, blue: NcColor) {
channels_set_bg_rgb8(&mut cell.channels, red, green, blue);
}
/// Sets the [NcRgb] 24-bit value for the background [NcChannel] of this
/// [NcCell], and marks it as not using the default color.
#[inline]
pub fn cell_set_bg_rgb(cell: &mut NcCell, rgb: NcRgb) {
channels_set_bg_rgb(&mut cell.channels, rgb);
}
/// Sets an [NcCell]'s background [NcPaletteIndex].
///
/// Also sets [NCCELL_BG_PALETTE] and [NCCELL_ALPHA_OPAQUE],
/// and clears out [NCCELL_BGDEFAULT_MASK].
///
// NOTE: unlike the original C function, this one can't fail
#[inline]
pub fn cell_set_bg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
cell.channels |= NCCELL_BGDEFAULT_MASK as NcChannelPair;
cell.channels |= NCCELL_BG_PALETTE as NcChannelPair;
cell_set_bg_alpha(cell, NCCELL_ALPHA_OPAQUE);
cell.channels &= 0xffffffffff000000;
cell.channels |= index as NcChannelPair;
}
/// Returns the [NcPaletteIndex] of the background [NcChannel] of the [NcCell]
#[inline]
pub fn cell_bg_palindex(cell: &NcCell) -> NcPaletteIndex {
(cell.channels & 0xff) as NcPaletteIndex
}
/// Is the foreground [NcChannel] of this [NcCell] using the
/// "default foreground color"?
#[inline]
pub fn cell_fg_default_p(cell: &NcCell) -> bool {
channels_fg_default_p(cell.channels)
}
/// Is the foreground [NcChannel] of this [NcCell] using an
/// [NcPaletteIndex] [indexed][NcPaletteIndex] [NcPalette][crate::NcPalette] color?
#[inline]
pub fn cell_fg_palindex_p(cell: &NcCell) -> bool {
channels_fg_palindex_p(cell.channels)
}
/// Is the background [NcChannel] of this [NcCell] using the
/// "default background color"?
///
/// The "default background color" must generally be used to take advantage of
/// terminal-effected transparency.
#[inline]
pub fn cell_bg_default_p(cell: &NcCell) -> bool {
channels_bg_default_p(cell.channels)
}
/// Is the background [NcChannel] of this [NcCell] using an
/// [NcPaletteIndex] [indexed][NcPaletteIndex] [NcPalette][crate::NcPalette] color?
#[inline]
pub fn cell_bg_palindex_p(cell: &NcCell) -> bool {
channels_bg_palindex_p(cell.channels)
}
mod test;
mod methods;
mod reimplemented;
pub use reimplemented::*;
// NcCell
/// A coordinate on an [`NcPlane`] storing 128 bits of data
///
/// An `NcCell` corresponds to a single character cell on some [`NcPlane`],
/// which can be occupied by a single [`NcEgc`] grapheme cluster (some root
/// spacing glyph, along with possible combining characters, which might span
/// multiple columns).
///
/// At any `NcCell`, we can have a theoretically arbitrarily long UTF-8 string,
/// a foreground color, a background color, and an [`NcStyleMask`] attribute set.
///
/// Valid grapheme cluster contents include:
///
/// - A NUL terminator,
/// - A single [control character](https://en.wikipedia.org/wiki/Control_character),
/// followed by a NUL terminator,
/// - At most one [spacing
/// character](https://en.wikipedia.org/wiki/Graphic_character#Spacing_character),
/// followed by zero or more nonspacing characters, followed by a NUL terminator.
///
/// ## Diagram
///
/// ```txt
/// NcCell: 128 bits structure comprised of the following 5 elements:
///
/// GCLUSTER GCLUSTER GCLUSTER GCLUSTER 1. NcEgc
/// 00000000 ~~~~~~~~ 11111111 11111111 2. NcEgcBackstop + 3. reserved + 4. NcStyleMask
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB 5. NcChannelPair
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB |
///
/// 1. (32b) Extended Grapheme Cluster, presented either as:
///
/// 1.1. An NcEgc of up to 4 bytes:
/// UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU
///
/// 1.2. A `0x01` in the first byte, plus 3 bytes with a 24b address to an egcpool:
/// 00000001 IIIIIIII IIIIIIII IIIIIIII
///
/// 2. (8b) Backstop (zero)
/// 00000000
///
/// 3. (8b) reserved (ought to be zero)
/// ~~~~~~~~
///
/// 4. (16b) NcStyleMask
/// 11111111 11111111
///
/// 5. (64b) NcChannelPair
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB|~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
///
/// `type in C: cell (struct)`
///
/// ## Size
///
/// Multi-column characters can only have a single style/color throughout.
/// [`wcwidth()`](https://www.man7.org/linux/man-pages/man3/wcwidth.3.html)
/// is not reliable. It's just quoting whether or not the [`NcEgc`]
/// contains a "Wide Asian" double-width character.
/// This is set for some things, like most emoji, and not set for
/// other things, like cuneiform.
///
/// Each cell occupies 16 static bytes (128 bits). The surface is thus ~1.6MB
/// for a (pretty large) 500x200 terminal. At 80x43, it's less than 64KB.
/// Dynamic requirements (the egcpool) can add up to 16MB to an ncplane, but
/// such large pools are unlikely in common use.
///
/// ## Alpha Compositing
///
/// We implement some small alpha compositing. Foreground and background both
/// have two bits of inverted alpha. The actual grapheme written to a cell is
/// the topmost non-zero grapheme.
///
/// - If its alpha is 00 ([`NCCELL_ALPHA_OPAQUE`]) its foreground color is used unchanged.
///
/// - If its alpha is 10 ([`NCCELL_ALPHA_TRANSPARENT`]) its foreground color is derived
/// entirely from cells underneath it.
///
/// - If its alpha is 01 ([`NCCELL_ALPHA_BLEND`]) the result will be a composite.
///
/// Likewise for the background. If the bottom of a coordinate's zbuffer is
/// reached with a cumulative alpha of zero, the default is used. In this way,
/// a terminal configured with transparent background can be supported through
/// multiple occluding ncplanes.
///
/// A foreground alpha of 11 ([`NCCELL_ALPHA_HIGHCONTRAST`]) requests high-contrast
/// text (relative to the computed background).
/// A background alpha of 11 is currently forbidden.
///
/// ## Precedence
///
/// - Default color takes precedence over palette or RGB, and cannot be used with
/// transparency.
/// - Indexed palette takes precedence over RGB. It cannot meaningfully set
/// transparency, but it can be mixed into a cascading color.
/// - RGB is used if neither default terminal colors nor palette indexing are in
/// play, and fully supports all transparency options.
///
pub type NcCell = crate::bindings::bindgen::cell;
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color will be a composite between
/// its color and the `NcCell`s' corresponding colors underneath it
pub const NCCELL_ALPHA_BLEND: u32 = crate::bindings::bindgen::CELL_ALPHA_BLEND;
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground color will be high-contrast (relative to the
/// computed background). Background cannot be highcontrast
pub const NCCELL_ALPHA_HIGHCONTRAST: u32 = crate::bindings::bindgen::CELL_ALPHA_HIGHCONTRAST;
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color is used unchanged
pub const NCCELL_ALPHA_OPAQUE: u32 = crate::bindings::bindgen::CELL_ALPHA_OPAQUE;
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color is derived entirely from the
/// `NcCell`s underneath it
pub const NCCELL_ALPHA_TRANSPARENT: u32 = crate::bindings::bindgen::CELL_ALPHA_TRANSPARENT;
/// If this bit is set, we are *not* using the default background color
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BGDEFAULT_MASK: u32 = crate::bindings::bindgen::CELL_BGDEFAULT_MASK;
/// Extract these bits to get the background alpha mask
/// ([`NcAlphaBits`])
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_ALPHA_MASK: u32 = crate::bindings::bindgen::CELL_BG_ALPHA_MASK;
/// If this bit *and* [`NCCELL_BGDEFAULT_MASK`] are set, we're using a
/// palette-indexed background color
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_PALETTE: u32 = crate::bindings::bindgen::CELL_BG_PALETTE;
/// Extract these bits to get the background [`NcRgb`][crate::NcRgb] value
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_RGB_MASK: u32 = crate::bindings::bindgen::CELL_BG_RGB_MASK;
/// If this bit is set, we are *not* using the default foreground color
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BGDEFAULT_MASK`];
pub const NCCELL_FGDEFAULT_MASK: u64 = crate::bindings::bindgen::CELL_FGDEFAULT_MASK;
/// Extract these bits to get the foreground alpha mask
/// ([`NcAlphaBits`])
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_ALPHA_MASK`];
pub const NCCELL_FG_ALPHA_MASK: u64 = crate::bindings::bindgen::CELL_FG_ALPHA_MASK;
/// If this bit *and* [`NCCELL_FGDEFAULT_MASK`] are set, we're using a
/// palette-indexed background color
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_PALETTE`];
pub const NCCELL_FG_PALETTE: u64 = crate::bindings::bindgen::CELL_FG_PALETTE;
/// Extract these bits to get the foreground [`NcRgb`][crate::NcRgb] value
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_RGB_MASK`];
pub const NCCELL_FG_RGB_MASK: u64 = crate::bindings::bindgen::CELL_FG_RGB_MASK;
/// Indicates the glyph is entirely foreground
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
pub const NCCELL_NOBACKGROUND_MASK: u64 = crate::bindings::bindgen::CELL_NOBACKGROUND_MASK;
/// If this bit is set, the cell is part of a multicolumn glyph.
///
/// Whether a cell is the left or right side of the glyph can be determined
/// by checking whether ->gcluster is zero.
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
pub const NCCELL_WIDEASIAN_MASK: u64 = crate::bindings::bindgen::CELL_WIDEASIAN_MASK as u64;
// NcEgc
//
/// Extended Grapheme Cluster. A 32-bit [`char`]-like type
///
/// This 32 bit char, together with the associated plane's associated egcpool,
/// completely define this cell's `NcEgc`. Unless the `NcEgc` requires more than
/// four bytes to encode as UTF-8, it will be inlined here:
///
/// ## Diagram 1
///
/// ```txt
/// UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU
/// extended grapheme cluster <= 4bytes
/// ```
///
/// `type in C: uint32_t`
///
/// If more than four bytes are required, it will be spilled into the egcpool.
/// In either case, there's a NUL-terminated string available without copying,
/// because (1) the egcpool is all NUL-terminated sequences and (2) the fifth
/// byte of this struct (the GClusterBackStop field, see below) is
/// guaranteed to be zero, as are any unused bytes in gcluster.
///
/// A spilled `NcEgc` is indicated by the value `0x01iiiiii`. This cannot alias a
/// true supra-ASCII NcEgc, because UTF-8 only encodes bytes <= 0x80 when they
/// are single-byte ASCII-derived values. The `iiiiii` is interpreted as a 24-bit
/// index into the egcpool (which may thus be up to 16MB):
///
/// ## Diagram 2
///
/// ```txt
/// 00000001 iiiiiiii iiiiiiii iiiiiiii
/// sign 24bit index to egcpool
/// ```
/// `type in C: uint32_t`
///
/// The cost of this scheme is that the character 0x01 (`SOH`) cannot be encoded
/// in a cell, and therefore it must not be allowed through the API.
///
/// -----
/// NOTE that even if the `NcEgc` is <= 4 bytes and inlined, is still interpreted as
/// a NUL-terminated char * (technically, &cell->gcluster is treated as a char*).
/// If it is more than 4 bytes, cell->gcluster has a first byte of 0x01,
/// and the remaining 24 bits are an index into the plane's egcpool,
/// which is carved into NUL-terminated chunks of arbitrary length.
///
/// ## Links
///
/// - [Grapheme Cluster
/// Boundaries](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
///
///
pub type NcEgc = char;
// NcEgcBackStop
/// An `u8` always at zero, part of the [`NcCell`] struct
///
/// ## Diagram
///
/// ```txt
/// 00000000
/// ```
///
/// `type in C: uint_8t`
///
pub type NcEgcBackstop = u8;
// NcStyleMask
///
/// An `u16` of `NCSTYLE_*` boolean styling attribute flags
///
/// ## Attributes
///
/// - [`NCSTYLE_BLINK`]
/// - [`NCSTYLE_BOLD`]
/// - [`NCSTYLE_DIM`]
/// - [`NCSTYLE_INVIS`]
/// - [`NCSTYLE_ITALIC`]
/// - [`NCSTYLE_MASK`]
/// - [`NCSTYLE_NONE`]
/// - [`NCSTYLE_PROTECT`]
/// - [`NCSTYLE_REVERSE`]
/// - [`NCSTYLE_STANDOUT`]
/// - [`NCSTYLE_STRUCK`]
/// - [`NCSTYLE_UNDERLINE`]
///
///
/// ## Diagram
///
/// ```txt
/// 11111111 11111111
/// ```
///
/// `type in C: uint16_t`
///
pub type NcStyleMask = u16;
///
pub const NCSTYLE_BLINK: u16 = crate::bindings::bindgen::NCSTYLE_BLINK as u16;
///
pub const NCSTYLE_BOLD: u16 = crate::bindings::bindgen::NCSTYLE_BOLD as u16;
///
pub const NCSTYLE_DIM: u16 = crate::bindings::bindgen::NCSTYLE_DIM as u16;
///
pub const NCSTYLE_INVIS: u16 = crate::bindings::bindgen::NCSTYLE_INVIS as u16;
///
pub const NCSTYLE_ITALIC: u16 = crate::bindings::bindgen::NCSTYLE_ITALIC as u16;
///
pub const NCSTYLE_MASK: u16 = crate::bindings::bindgen::NCSTYLE_MASK as u16;
///
pub const NCSTYLE_NONE: u16 = crate::bindings::bindgen::NCSTYLE_NONE as u16;
///
pub const NCSTYLE_PROTECT: u16 = crate::bindings::bindgen::NCSTYLE_PROTECT as u16;
///
pub const NCSTYLE_REVERSE: u16 = crate::bindings::bindgen::NCSTYLE_REVERSE as u16;
///
pub const NCSTYLE_STANDOUT: u16 = crate::bindings::bindgen::NCSTYLE_STANDOUT as u16;
///
pub const NCSTYLE_STRUCK: u16 = crate::bindings::bindgen::NCSTYLE_STRUCK as u16;
///
pub const NCSTYLE_UNDERLINE: u16 = crate::bindings::bindgen::NCSTYLE_UNDERLINE as u16;

@ -0,0 +1,434 @@
//! `cell*_*` reimplemented functions.
use libc::strcmp;
use crate::{
cell_extended_gcluster, cell_load, cell_release, channels_bchannel, channels_bg_alpha,
channels_bg_default_p, channels_bg_palindex_p, channels_bg_rgb, channels_bg_rgb8,
channels_fchannel, channels_fg_alpha, channels_fg_default_p, channels_fg_palindex_p,
channels_fg_rgb, channels_fg_rgb8, channels_set_bchannel, channels_set_bg_alpha,
channels_set_bg_default, channels_set_bg_rgb, channels_set_bg_rgb8, channels_set_fchannel,
channels_set_fg_alpha, channels_set_fg_default, channels_set_fg_rgb, channels_set_fg_rgb8,
NcAlphaBits, NcCell, NcChannel, NcChannelPair, NcColor, NcEgc, NcPaletteIndex, NcPlane,
NcResult, NcRgb, NcStyleMask, NCCELL_ALPHA_OPAQUE, NCCELL_BGDEFAULT_MASK, NCCELL_BG_PALETTE,
NCCELL_FGDEFAULT_MASK, NCCELL_FG_PALETTE, NCCELL_NOBACKGROUND_MASK, NCCELL_WIDEASIAN_MASK,
NCRESULT_ERR, NCRESULT_OK, NCSTYLE_MASK,
};
/// Same as [cell_load], plus blasts the styling with 'style' and 'channels'.
///
/// - Breaks the UTF-8 string in 'gcluster' down, setting up the cell 'cell'.
/// - Returns the number of bytes copied out of 'gcluster', or -1 on failure.
/// - The styling of the cell is left untouched, but any resources are released.
/// - Blasts the styling with 'style' and 'channels'.
///
#[allow(unused_unsafe)]
pub unsafe fn cell_prime(
plane: &mut NcPlane,
cell: &mut NcCell,
gcluster: NcEgc,
style: NcStyleMask,
channels: NcChannelPair,
) -> NcResult {
cell.stylemask = style;
cell.channels = channels;
unsafe { cell_load(plane, cell, gcluster as u32 as *const i8) }
}
/// Loads up six cells with the [NcEgc]s necessary to draw a box.
///
/// Returns [NCRESULT_OK] on success, [NCRESULT_ERR] on error.
///
/// On error, any [NcCell]s this function might have loaded before the error
/// are [cell_release]d. There must be at least six [NcEgc]s in gcluster.
///
#[allow(unused_unsafe)]
pub unsafe fn cells_load_box(
plane: &mut NcPlane,
style: NcStyleMask,
channels: NcChannelPair,
ul: &mut NcCell,
ur: &mut NcCell,
ll: &mut NcCell,
lr: &mut NcCell,
hl: &mut NcCell,
vl: &mut NcCell,
gcluster: NcEgc,
) -> NcResult {
// mutable copy for pointer arithmetics:
let mut gclu = gcluster as u32 as *const i8;
let mut ulen: NcResult;
ulen = unsafe { cell_prime(plane, ul, gcluster, style, channels) };
if ulen > 0 {
gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, ur, gcluster, style, channels) };
if ulen > 0 {
gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, ll, gcluster, style, channels) };
if ulen > 0 {
gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, lr, gcluster, style, channels) };
if ulen > 0 {
gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, hl, gcluster, style, channels) };
if ulen > 0 {
let _gclu = unsafe { gclu.offset(ulen as isize) };
ulen = unsafe { cell_prime(plane, vl, gcluster, style, channels) };
if ulen > 0 {
return NCRESULT_OK;
}
unsafe {
cell_release(plane, hl);
}
}
unsafe {
cell_release(plane, lr);
}
}
unsafe {
cell_release(plane, ll);
}
}
unsafe {
cell_release(plane, ur);
}
}
unsafe {
cell_release(plane, ul);
}
}
NCRESULT_ERR
}
/// Initializes (zeroes out) an [NcCell].
#[inline]
pub fn cell_init(cell: &mut NcCell) {
*cell = unsafe { core::mem::zeroed() }
}
/// Sets *just* the specified [NcStyleMask] bits for an [NcCell],
/// whether they're actively supported or not.
#[inline]
pub fn cell_styles_set(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask = stylebits & NCSTYLE_MASK as u16;
}
/// Extracts the [NcStyleMask] bits from an [NcCell].
#[inline]
pub fn cell_styles(cell: &NcCell) -> NcStyleMask {
cell.stylemask
}
/// Adds the specified [NcStyleMask] bits to an [NcCell]'s existing spec.,
/// whether they're actively supported or not.
#[inline]
pub fn cell_styles_on(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask |= stylebits & NCSTYLE_MASK as u16;
}
/// Removes the specified [NcStyleMask] bits from an [NcCell]'s existing spec.
#[inline]
pub fn cell_styles_off(cell: &mut NcCell, stylebits: NcStyleMask) {
cell.stylemask &= !(stylebits & NCSTYLE_MASK as u16);
}
/// Indicates to use the "default color" for the **foreground** [NcChannel]
/// of an [NcCell].
#[inline]
pub fn cell_set_fg_default(cell: &mut NcCell) {
channels_set_fg_default(&mut cell.channels);
}
/// Indicates to use the "default color" for the **background** [NcChannel]
/// of an [NcCell].
#[inline]
pub fn cell_set_bg_default(cell: &mut NcCell) {
channels_set_bg_default(&mut cell.channels);
}
/// Sets the foreground [NcAlphaBits] of an [NcCell].
#[inline]
pub fn cell_set_fg_alpha(cell: &mut NcCell, alpha: NcAlphaBits) {
channels_set_fg_alpha(&mut cell.channels, alpha);
}
/// Sets the background [NcAlphaBits] of an [NcCell].
#[inline]
pub fn cell_set_bg_alpha(cell: &mut NcCell, alpha: NcAlphaBits) {
channels_set_bg_alpha(&mut cell.channels, alpha);
}
/// Does the [NcCell] contain an East Asian Wide codepoint?
// NOTE: remove casting when fixed:
// https://github.com/rust-lang/rust-bindgen/issues/1875
#[inline]
pub fn cell_double_wide_p(cell: &NcCell) -> bool {
(cell.channels & NCCELL_WIDEASIAN_MASK as NcChannelPair) != 0
}
/// Is this the right half of a wide character?
#[inline]
pub fn cell_wide_right_p(cell: &NcCell) -> bool {
cell_double_wide_p(cell) && cell.gcluster == 0
}
/// Is this the left half of a wide character?
#[inline]
pub fn cell_wide_left_p(cell: &NcCell) -> bool {
cell_double_wide_p(cell) && cell.gcluster != 0
}
/// Copies the UTF8-encoded [NcEgc] out of the cell, whether simple
/// or complex.
///
/// The result is not tied to the [NcPlane], and persists
/// across erases and destruction.
#[inline]
pub fn cell_strdup(plane: &NcPlane, cell: &NcCell) -> NcEgc {
core::char::from_u32(unsafe { libc::strdup(cell_extended_gcluster(plane, cell)) } as i32 as u32)
.expect("wrong char")
// unsafer option B (maybe faster, TODO: bench)
// unsafe {
// core::char::from_u32_unchecked(libc::strdup(cell_extended_gcluster(plane, cell)) as i32 as u32)
// }
}
/// Saves the [NcStyleMask] and the [NcChannelPair], and returns the [NcEgc]
/// (the three elements of an [NcCell]).
#[inline]
pub fn cell_extract(
plane: &NcPlane,
cell: &NcCell,
stylemask: &mut NcStyleMask,
channels: &mut NcChannelPair,
) -> NcEgc {
if *stylemask != 0 {
*stylemask = cell.stylemask;
}
if *channels != 0 {
*channels = cell.channels;
}
cell_strdup(plane, cell)
}
/// Returns true if the two cells are distinct [NcEgc]s, attributes, or channels
///
/// The actual egcpool index needn't be the same--indeed, the planes needn't even
/// be the same. Only the expanded NcEgc must be equal. The NcEgc must be bit-equal;
// NOTE: FIXME: it would probably be better to test whether they're Unicode-equal
#[inline]
pub fn cellcmp(plane1: &NcPlane, cell1: &NcCell, plane2: &NcPlane, cell2: &NcCell) -> bool {
if cell1.stylemask != cell2.stylemask {
return true;
}
if cell1.channels != cell2.channels {
return true;
}
unsafe {
strcmp(
cell_extended_gcluster(plane1, cell1),
cell_extended_gcluster(plane2, cell2),
) != 0
}
}
/// Loads a 7-bit char into the [NcCell].
// NOTE: Unlike the original C function this doesn't return anything.
// REMINDER: remove casting for NCCELL_WIDEASIAN_MASK when fixed: https://github.com/rust-lang/rust-bindgen/issues/1875
#[inline]
pub fn cell_load_char(plane: &mut NcPlane, cell: &mut NcCell, ch: NcEgc) /* -> i32 */
{
unsafe {
cell_release(plane, cell);
}
cell.channels &= !(NCCELL_WIDEASIAN_MASK as NcChannelPair | NCCELL_NOBACKGROUND_MASK);
cell.gcluster = ch as u32;
}
/// Extracts the 32-bit background [NcChannel] from an [NcCell].
#[inline]
pub fn cell_bchannel(cell: &NcCell) -> NcChannel {
channels_bchannel(cell.channels)
}
/// Extracts the 32-bit foreground [NcChannel] from an [NcCell].
#[inline]
pub fn cell_fchannel(cell: &NcCell) -> NcChannel {
channels_fchannel(cell.channels)
}
/// Sets the 32-bit background [NcChannel] of an [NcCell] and returns its new
/// [NcChannelPair].
#[inline]
pub fn cell_set_bchannel(cell: &mut NcCell, channel: NcChannel) -> NcChannelPair {
channels_set_bchannel(&mut cell.channels, channel)
}
/// Sets the 32-bit foreground [NcChannel] of an [NcCell] and returns its new
/// [NcChannelPair].
#[inline]
pub fn cell_set_fchannel(cell: &mut NcCell, channel: NcChannel) -> NcChannelPair {
channels_set_fchannel(&mut cell.channels, channel)
}
/// Extracts the foreground [NcRgb] 24-bit value from an [NcCell]
/// (shifted to LSBs).
#[inline]
pub fn cell_fg_rgb(cell: &NcCell) -> NcRgb {
channels_fg_rgb(cell.channels)
}
/// Extracts the background [NcRgb] 24-bit value from an [NcCell]
/// (shifted to LSBs).
#[inline]
pub fn cell_bg_rgb(cell: &NcCell) -> NcRgb {
channels_bg_rgb(cell.channels)
}
/// Extracts the foreground [NcAlphaBits] from an [NcCell] (shifted to LSBs).
#[inline]
pub fn cell_fg_alpha(cell: &NcCell) -> NcAlphaBits {
channels_fg_alpha(cell.channels)
}
/// Extracts the background [NcAlphaBits] from an [NcCell] (shifted to LSBs).
#[inline]
pub fn cell_bg_alpha(cell: &NcCell) -> NcAlphaBits {
channels_bg_alpha(cell.channels)
}
/// Extracts the foreground [NcRgb] 24-bit value from an [NcCell] and saves it
/// split into three [NcColor] 8-bit components. Also returns the corresponding
/// [NcChannel] (which can have some extra bits set).
#[inline]
pub fn cell_fg_rgb8(
cell: &NcCell,
red: &mut NcColor,
green: &mut NcColor,
blue: &mut NcColor,
) -> NcChannel {
channels_fg_rgb8(cell.channels, red, green, blue)
}
/// Extracts the background [NcRgb] 24-bit value from an [NcCell] and saves it
/// split into three [NcColor] 8-bit components. Also returns the corresponding
/// [NcChannel] (which can have some extra bits set).
#[inline]
pub fn cell_bg_rgb8(
cell: &NcCell,
red: &mut NcColor,
green: &mut NcColor,
blue: &mut NcColor,
) -> NcChannel {
channels_bg_rgb8(cell.channels, red, green, blue)
}
/// Sets the RGB [NcColor] components for the foreground [NcChannel] of an
/// [NcCell], and marks it as not using the default color.
#[inline]
pub fn cell_set_fg_rgb8(cell: &mut NcCell, red: NcColor, green: NcColor, blue: NcColor) {
channels_set_fg_rgb8(&mut cell.channels, red, green, blue);
}
/// Sets the 24-bit [NcRgb] value for the foreground [NcChannel] of an
/// [NcCell], and marks it as not using the default color.
#[inline]
pub fn cell_set_fg_rgb(cell: &mut NcCell, rgb: NcRgb) {
channels_set_fg_rgb(&mut cell.channels, rgb);
}
/// Sets an [NcCell]'s foreground [NcPaletteIndex].
///
/// Also sets [NCCELL_FG_PALETTE] and [NCCELL_ALPHA_OPAQUE],
/// and clears out [NCCELL_FGDEFAULT_MASK].
///
// NOTE: unlike the original C function, this one can't fail
#[inline]
pub fn cell_set_fg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
cell.channels |= NCCELL_FGDEFAULT_MASK;
cell.channels |= NCCELL_FG_PALETTE;
cell_set_fg_alpha(cell, NCCELL_ALPHA_OPAQUE);
cell.channels &= 0xff000000ffffffff as NcChannelPair;
cell.channels |= (index as NcChannelPair) << 32;
}
/// Returns the [NcPaletteIndex] of the foreground [NcChannel] of the
/// [NcCell]
#[inline]
pub fn cell_fg_palindex(cell: &NcCell) -> NcPaletteIndex {
((cell.channels & 0xff00000000 as NcChannelPair) >> 32) as NcPaletteIndex
}
/// Sets the [NcColor] 8-bit RGB components of the background [NcChannel]
/// of the [NcCell], and marks it as not using the "default color".
#[inline]
pub fn cell_set_bg_rgb8(cell: &mut NcCell, red: NcColor, green: NcColor, blue: NcColor) {
channels_set_bg_rgb8(&mut cell.channels, red, green, blue);
}
/// Sets the [NcRgb] 24-bit value for the background [NcChannel] of this
/// [NcCell], and marks it as not using the default color.
#[inline]
pub fn cell_set_bg_rgb(cell: &mut NcCell, rgb: NcRgb) {
channels_set_bg_rgb(&mut cell.channels, rgb);
}
/// Sets an [NcCell]'s background [NcPaletteIndex].
///
/// Also sets [NCCELL_BG_PALETTE] and [NCCELL_ALPHA_OPAQUE],
/// and clears out [NCCELL_BGDEFAULT_MASK].
///
// NOTE: unlike the original C function, this one can't fail
#[inline]
pub fn cell_set_bg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
cell.channels |= NCCELL_BGDEFAULT_MASK as NcChannelPair;
cell.channels |= NCCELL_BG_PALETTE as NcChannelPair;
cell_set_bg_alpha(cell, NCCELL_ALPHA_OPAQUE);
cell.channels &= 0xffffffffff000000;
cell.channels |= index as NcChannelPair;
}
/// Returns the [NcPaletteIndex] of the background [NcChannel] of the [NcCell]
#[inline]
pub fn cell_bg_palindex(cell: &NcCell) -> NcPaletteIndex {
(cell.channels & 0xff) as NcPaletteIndex
}
/// Is the foreground [NcChannel] of this [NcCell] using the
/// "default foreground color"?
#[inline]
pub fn cell_fg_default_p(cell: &NcCell) -> bool {
channels_fg_default_p(cell.channels)
}
/// Is the foreground [NcChannel] of this [NcCell] using an
/// [NcPaletteIndex] [indexed][NcPaletteIndex] [NcPalette][crate::NcPalette] color?
#[inline]
pub fn cell_fg_palindex_p(cell: &NcCell) -> bool {
channels_fg_palindex_p(cell.channels)
}
/// Is the background [NcChannel] of this [NcCell] using the
/// "default background color"?
///
/// The "default background color" must generally be used to take advantage of
/// terminal-effected transparency.
#[inline]
pub fn cell_bg_default_p(cell: &NcCell) -> bool {
channels_bg_default_p(cell.channels)
}
/// Is the background [NcChannel] of this [NcCell] using an
/// [NcPaletteIndex] [indexed][NcPaletteIndex] [NcPalette][crate::NcPalette] color?
#[inline]
pub fn cell_bg_palindex_p(cell: &NcCell) -> bool {
channels_bg_palindex_p(cell.channels)
}

@ -0,0 +1,15 @@
//! Test `NcCell` methods and associated functions.
use crate::NcCell;
use serial_test::serial;
#[test]
#[serial]
fn constructors() {
let _c1 = NcCell::new();
let _c2 = NcCell::with_7bitchar('C');
let _c3 = NcCell::with_all('c', 0, 0);
}

@ -0,0 +1,7 @@
//! `NcCell` tests
#[cfg(test)]
mod methods;
#[cfg(test)]
mod reimplemented;

@ -1,18 +1,8 @@
//! [`NcCell`] tests
use crate::NcCell;
//! Test `cell*_*` reimplemented functions
use serial_test::serial;
#[test]
#[serial]
fn constructors() {
let _c1 = NcCell::new();
let _c2 = NcCell::with_7bitchar('C');
let _c3 = NcCell::with_all('c', 0, 0);
}
use crate::NcCell;
#[test]
#[serial]

@ -1,327 +0,0 @@
#[allow(unused_imports)] // for docblocks
use crate::{NcAlphaBits, NcChannel, NcPlane};
// NcCell
/// A coordinate on an [`NcPlane`] storing 128 bits of data
///
/// An `NcCell` corresponds to a single character cell on some [`NcPlane`],
/// which can be occupied by a single [`NcChar`] grapheme cluster (some root
/// spacing glyph, along with possible combining characters, which might span
/// multiple columns).
///
/// At any `NcCell`, we can have a theoretically arbitrarily long UTF-8 string,
/// a foreground color, a background color, and an [`NcStyleMask`] attribute set.
///
/// Valid grapheme cluster contents include:
///
/// - A NUL terminator,
/// - A single [control character](https://en.wikipedia.org/wiki/Control_character),
/// followed by a NUL terminator,
/// - At most one [spacing
/// character](https://en.wikipedia.org/wiki/Graphic_character#Spacing_character),
/// followed by zero or more nonspacing characters, followed by a NUL terminator.
///
/// ## Diagram
///
/// ```txt
/// NcCell: 128 bits structure comprised of the following 5 elements:
///
/// GCLUSTER GCLUSTER GCLUSTER GCLUSTER 1. NcChar
/// 00000000 ~~~~~~~~ 11111111 11111111 2. NcCharBackstop + 3. reserved + 4. NcStyleMask
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB 5. NcChannelPair
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB |
///
/// 1. (32b) Extended Grapheme Cluster, presented either as:
///
/// 1.1. An NcChar of up to 4 bytes:
/// UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU
///
/// 1.2. A `0x01` in the first byte, plus 3 bytes with a 24b address to an egcpool:
/// 00000001 IIIIIIII IIIIIIII IIIIIIII
///
/// 2. (8b) Backstop (zero)
/// 00000000
///
/// 3. (8b) reserved (ought to be zero)
/// ~~~~~~~~
///
/// 4. (16b) NcStyleMask
/// 11111111 11111111
///
/// 5. (64b) NcChannelPair
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB|~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
///
/// `type in C: cell (struct)`
///
/// ## Size
///
/// Multi-column characters can only have a single style/color throughout.
/// [`wcwidth()`](https://www.man7.org/linux/man-pages/man3/wcwidth.3.html)
/// is not reliable. It's just quoting whether or not the [`NcChar`]
/// contains a "Wide Asian" double-width character.
/// This is set for some things, like most emoji, and not set for
/// other things, like cuneiform.
///
/// Each cell occupies 16 static bytes (128 bits). The surface is thus ~1.6MB
/// for a (pretty large) 500x200 terminal. At 80x43, it's less than 64KB.
/// Dynamic requirements (the egcpool) can add up to 16MB to an ncplane, but
/// such large pools are unlikely in common use.
///
/// ## Alpha Compositing
///
/// We implement some small alpha compositing. Foreground and background both
/// have two bits of inverted alpha. The actual grapheme written to a cell is
/// the topmost non-zero grapheme.
///
/// - If its alpha is 00 ([`NCCELL_ALPHA_OPAQUE`]) its foreground color is used unchanged.
///
/// - If its alpha is 10 ([`NCCELL_ALPHA_TRANSPARENT`]) its foreground color is derived
/// entirely from cells underneath it.
///
/// - If its alpha is 01 ([`NCCELL_ALPHA_BLEND`]) the result will be a composite.
///
/// Likewise for the background. If the bottom of a coordinate's zbuffer is
/// reached with a cumulative alpha of zero, the default is used. In this way,
/// a terminal configured with transparent background can be supported through
/// multiple occluding ncplanes.
///
/// A foreground alpha of 11 ([`NCCELL_ALPHA_HIGHCONTRAST`]) requests high-contrast
/// text (relative to the computed background).
/// A background alpha of 11 is currently forbidden.
///
/// ## Precedence
///
/// - Default color takes precedence over palette or RGB, and cannot be used with
/// transparency.
/// - Indexed palette takes precedence over RGB. It cannot meaningfully set
/// transparency, but it can be mixed into a cascading color.
/// - RGB is used if neither default terminal colors nor palette indexing are in
/// play, and fully supports all transparency options.
///
pub type NcCell = crate::bindings::bindgen::cell;
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color will be a composite between
/// its color and the `NcCell`s' corresponding colors underneath it
pub const NCCELL_ALPHA_BLEND: u32 = crate::bindings::bindgen::CELL_ALPHA_BLEND;
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground color will be high-contrast (relative to the
/// computed background). Background cannot be highcontrast
pub const NCCELL_ALPHA_HIGHCONTRAST: u32 = crate::bindings::bindgen::CELL_ALPHA_HIGHCONTRAST;
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color is used unchanged
pub const NCCELL_ALPHA_OPAQUE: u32 = crate::bindings::bindgen::CELL_ALPHA_OPAQUE;
/// [`NcAlphaBits`] bits indicating
/// [`NcCell`]'s foreground or background color is derived entirely from the
/// `NcCell`s underneath it
pub const NCCELL_ALPHA_TRANSPARENT: u32 = crate::bindings::bindgen::CELL_ALPHA_TRANSPARENT;
/// If this bit is set, we are *not* using the default background color
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BGDEFAULT_MASK: u32 = crate::bindings::bindgen::CELL_BGDEFAULT_MASK;
/// Extract these bits to get the background alpha mask
/// ([`NcAlphaBits`])
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_ALPHA_MASK: u32 = crate::bindings::bindgen::CELL_BG_ALPHA_MASK;
/// If this bit *and* [`NCCELL_BGDEFAULT_MASK`] are set, we're using a
/// palette-indexed background color
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_PALETTE: u32 = crate::bindings::bindgen::CELL_BG_PALETTE;
/// Extract these bits to get the background [`NcRgb`][crate::NcRgb] value
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: This can also be used against a single [`NcChannel`]
pub const NCCELL_BG_RGB_MASK: u32 = crate::bindings::bindgen::CELL_BG_RGB_MASK;
/// If this bit is set, we are *not* using the default foreground color
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BGDEFAULT_MASK`];
pub const NCCELL_FGDEFAULT_MASK: u64 = crate::bindings::bindgen::CELL_FGDEFAULT_MASK;
/// Extract these bits to get the foreground alpha mask
/// ([`NcAlphaBits`])
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_ALPHA_MASK`];
pub const NCCELL_FG_ALPHA_MASK: u64 = crate::bindings::bindgen::CELL_FG_ALPHA_MASK;
/// If this bit *and* [`NCCELL_FGDEFAULT_MASK`] are set, we're using a
/// palette-indexed background color
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_PALETTE`];
pub const NCCELL_FG_PALETTE: u64 = crate::bindings::bindgen::CELL_FG_PALETTE;
/// Extract these bits to get the foreground [`NcRgb`][crate::NcRgb] value
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
///
/// NOTE: When working with a single [`NcChannel`] use [`NCCELL_BG_RGB_MASK`];
pub const NCCELL_FG_RGB_MASK: u64 = crate::bindings::bindgen::CELL_FG_RGB_MASK;
/// Indicates the glyph is entirely foreground
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
pub const NCCELL_NOBACKGROUND_MASK: u64 = crate::bindings::bindgen::CELL_NOBACKGROUND_MASK;
/// If this bit is set, the cell is part of a multicolumn glyph.
///
/// Whether a cell is the left or right side of the glyph can be determined
/// by checking whether ->gcluster is zero.
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
pub const NCCELL_WIDEASIAN_MASK: u64 = crate::bindings::bindgen::CELL_WIDEASIAN_MASK as u64;
// NcChar
//
/// Extended Grapheme Cluster. A 32-bit [`char`]-like type
///
/// This 32 bit char, together with the associated plane's associated egcpool,
/// completely define this cell's `NcChar`. Unless the `NcChar` requires more than
/// four bytes to encode as UTF-8, it will be inlined here:
///
/// ## Diagram 1
///
/// ```txt
/// UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU
/// extended grapheme cluster <= 4bytes
/// ```
///
/// `type in C: uint32_t`
///
/// If more than four bytes are required, it will be spilled into the egcpool.
/// In either case, there's a NUL-terminated string available without copying,
/// because (1) the egcpool is all NUL-terminated sequences and (2) the fifth
/// byte of this struct (the GClusterBackStop field, see below) is
/// guaranteed to be zero, as are any unused bytes in gcluster.
///
/// A spilled `NcChar` is indicated by the value `0x01iiiiii`. This cannot alias a
/// true supra-ASCII NcChar, because UTF-8 only encodes bytes <= 0x80 when they
/// are single-byte ASCII-derived values. The `iiiiii` is interpreted as a 24-bit
/// index into the egcpool (which may thus be up to 16MB):
///
/// ## Diagram 2
///
/// ```txt
/// 00000001 iiiiiiii iiiiiiii iiiiiiii
/// sign 24bit index to egcpool
/// ```
/// `type in C: uint32_t`
///
/// The cost of this scheme is that the character 0x01 (`SOH`) cannot be encoded
/// in a cell, and therefore it must not be allowed through the API.
///
/// -----
/// NOTE that even if the `NcChar` is <= 4 bytes and inlined, is still interpreted as
/// a NUL-terminated char * (technically, &cell->gcluster is treated as a char*).
/// If it is more than 4 bytes, cell->gcluster has a first byte of 0x01,
/// and the remaining 24 bits are an index into the plane's egcpool,
/// which is carved into NUL-terminated chunks of arbitrary length.
///
/// ## Links
///
/// - [Grapheme Cluster
/// Boundaries](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
///
///
pub type NcChar = char;
// NcCharBackStop
/// An `u8` always at zero, part of the [`NcCell`] struct
///
/// ## Diagram
///
/// ```txt
/// 00000000
/// ```
///
/// `type in C: uint_8t`
///
pub type NcCharBackstop = u8;
// NcStyleMask
///
/// An `u16` of `NCSTYLE_*` boolean styling attribute flags
///
/// ## Attributes
///
/// - [`NCSTYLE_BLINK`]
/// - [`NCSTYLE_BOLD`]
/// - [`NCSTYLE_DIM`]
/// - [`NCSTYLE_INVIS`]
/// - [`NCSTYLE_ITALIC`]
/// - [`NCSTYLE_MASK`]
/// - [`NCSTYLE_NONE`]
/// - [`NCSTYLE_PROTECT`]
/// - [`NCSTYLE_REVERSE`]
/// - [`NCSTYLE_STANDOUT`]
/// - [`NCSTYLE_STRUCK`]
/// - [`NCSTYLE_UNDERLINE`]
///
///
/// ## Diagram
///
/// ```txt
/// 11111111 11111111
/// ```
///
/// `type in C: uint16_t`
///
pub type NcStyleMask = u16;
///
pub const NCSTYLE_BLINK: u16 = crate::bindings::bindgen::NCSTYLE_BLINK as u16;
///
pub const NCSTYLE_BOLD: u16 = crate::bindings::bindgen::NCSTYLE_BOLD as u16;
///
pub const NCSTYLE_DIM: u16 = crate::bindings::bindgen::NCSTYLE_DIM as u16;
///
pub const NCSTYLE_INVIS: u16 = crate::bindings::bindgen::NCSTYLE_INVIS as u16;
///
pub const NCSTYLE_ITALIC: u16 = crate::bindings::bindgen::NCSTYLE_ITALIC as u16;
///
pub const NCSTYLE_MASK: u16 = crate::bindings::bindgen::NCSTYLE_MASK as u16;
///
pub const NCSTYLE_NONE: u16 = crate::bindings::bindgen::NCSTYLE_NONE as u16;
///
pub const NCSTYLE_PROTECT: u16 = crate::bindings::bindgen::NCSTYLE_PROTECT as u16;
///
pub const NCSTYLE_REVERSE: u16 = crate::bindings::bindgen::NCSTYLE_REVERSE as u16;
///
pub const NCSTYLE_STANDOUT: u16 = crate::bindings::bindgen::NCSTYLE_STANDOUT as u16;
///
pub const NCSTYLE_STRUCK: u16 = crate::bindings::bindgen::NCSTYLE_STRUCK as u16;
///
pub const NCSTYLE_UNDERLINE: u16 = crate::bindings::bindgen::NCSTYLE_UNDERLINE as u16;

@ -1,47 +0,0 @@
//! Handy [NcCell] constructors
pub use crate::{NcCell, NcPlane, NcChannelPair, NcCharBackstop, NcStyleMask, cell_load, NCRESULT_ERR, cstring};
impl NcCell {
/// New NcCell, expects a [char], [NcStyleMask] and [NcChannelPair].
#[inline]
pub const fn with_all(ch: char, stylemask: NcStyleMask, channels: NcChannelPair) -> Self {
NcCell {
gcluster: ch as u32,
gcluster_backstop: 0 as NcCharBackstop,
reserved: 0,
stylemask,
channels,
}
}
/// New NcCell, expects a 7-bit [char].
///
/// See also `with_char`.
#[inline]
pub const fn with_7bitchar(ch: char) -> Self {
Self::with_all(ch, 0 as NcStyleMask, 0 as NcChannelPair)
}
/// New NcCell, expects an [NcPlane] and a utf-8 [char].
///
/// See also `with_7bitchar`.
#[inline]
pub fn with_char(plane: &mut NcPlane, ch: char) -> Self {
let mut cell = Self::new();
let result = unsafe {
cell_load(plane,
&mut cell,
cstring![ch.to_string()],
)
};
debug_assert_ne![NCRESULT_ERR, result];
cell
}
/// New NcCell, blank.
#[inline]
pub const fn new() -> Self {
Self::with_7bitchar(0 as char)
}
}

@ -1,4 +1,4 @@
//! [`NcChannel`] & [`NcChannelPair`] `channel*_*` static fn reimplementations
//! `NcChannel*`
// -----------------------------------------------------------------------------
// - The channel components are u8 instead of u32.
@ -13,367 +13,227 @@
// - `channels_set_bg_rgb8_clipped()`
// -----------------------------------------------------------------------------
//
// functions already exported by bindgen : 0
// functions manually reimplemented: 39
// ------------------------------------------
//
// static inline functions total: 39
// ------------------------------------------ (implement / remaining)
// (X) wont: 3
// (+) done: 34 / 2
// (W) wrap: 0 / 36
// (#) test: 19 / 17
// ------------------------------------------
//# channel_alpha
//# channel_b
//# channel_default_p
//# channel_g
//# channel_palindex_p
//# channel_r
//# channel_rgb8
//# channels_bchannel
//+ channels_bg_alpha
//+ channels_bg_default_p
//# channels_bg_palindex_p
//+ channels_bg_rgb
//+ channels_bg_rgb8
//# channels_combine
//+ channel_set
//# channel_set_alpha
//# channel_set_default
//# channel_set_rgb8
//X channel_set_rgb_clipped
//# channels_fchannel
//+ channels_fg_alpha
//+ channels_fg_default_p
//# channels_fg_palindex_p
//+ channels_fg_rgb
//+ channels_fg_rgb8
//# channels_set_bchannel
//+ channels_set_bg_alpha
//+ channels_set_bg_default
//# channels_set_bg_palindex
//+ channels_set_bg_rgb
//+ channels_set_bg_rgb8
//X channels_set_bg_rgb8_clipped
//# channels_set_fchannel
//+ channels_set_fg_alpha
//+ channels_set_fg_default
//# channels_set_fg_palindex
//+ channels_set_fg_rgb
//+ channels_set_fg_rgb8
//X channels_set_fg_rgb8_clipped
// # channel_alpha
// # channel_b
// # channel_default_p
// # channel_g
// # channel_palindex_p
// # channel_r
// # channel_rgb8
// # channels_bchannel
// + channels_bg_alpha
// + channels_bg_default_p
// # channels_bg_palindex_p
// + channels_bg_rgb
// + channels_bg_rgb8
// # channels_combine
// + channel_set
// # channel_set_alpha
// # channel_set_default
// # channel_set_rgb8
// X channel_set_rgb_clipped
// # channels_fchannel
// + channels_fg_alpha
// + channels_fg_default_p
// # channels_fg_palindex_p
// + channels_fg_rgb
// + channels_fg_rgb8
// # channels_set_bchannel
// + channels_set_bg_alpha
// + channels_set_bg_default
// # channels_set_bg_palindex
// + channels_set_bg_rgb
// + channels_set_bg_rgb8
// X channels_set_bg_rgb8_clipped
// # channels_set_fchannel
// + channels_set_fg_alpha
// + channels_set_fg_default
// # channels_set_fg_palindex
// + channels_set_fg_rgb
// + channels_set_fg_rgb8
// X channels_set_fg_rgb8_clipped
#[cfg(test)]
mod tests;
mod types;
pub use types::{
NcAlphaBits, NcBlitSet, NcChannel, NcChannelPair, NcColor, NcFadeCtx, NcPalette,
NcPaletteIndex, NcPixel, NcRgb, NCCHANNEL_ALPHA_MASK,
};
use crate::{
NCCELL_ALPHA_HIGHCONTRAST, NCCELL_ALPHA_OPAQUE, NCCELL_BGDEFAULT_MASK, NCCELL_BG_PALETTE,
NCCELL_BG_RGB_MASK, NCCELL_FGDEFAULT_MASK, NCCELL_FG_PALETTE,
};
/// Extracts the [NcColor] 8-bit red component from a 32-bit [NcChannel].
#[inline]
pub const fn channel_r(channel: NcChannel) -> NcColor {
((channel & 0xff0000) >> 16) as NcColor
}
/// Extracts the [NcColor] 8-bit green component from a 32-bit [NcChannel].
#[inline]
pub const fn channel_g(channel: NcChannel) -> NcColor {
((channel & 0x00ff00) >> 8) as NcColor
}
/// Extracts the [NcColor] 8-bit blue component from a 32-bit [NcChannel].
#[inline]
pub const fn channel_b(channel: NcChannel) -> NcColor {
(channel & 0x0000ff) as NcColor
}
/// Extracts the three [NcColor] 8-bit RGB components from a 32-bit [NcChannel].
#[inline]
pub fn channel_rgb8(
channel: NcChannel,
r: &mut NcColor,
g: &mut NcColor,
b: &mut NcColor,
) -> NcChannel {
*r = channel_r(channel);
*g = channel_g(channel);
*b = channel_b(channel);
channel
}
/// Sets the three [NcColor] 8-bit components of a 32-bit [NcChannel], and marks
/// it as not using the "default color". Retain the other bits unchanged.
#[inline]
pub fn channel_set_rgb8(channel: &mut NcChannel, r: NcColor, g: NcColor, b: NcColor) {
let rgb: NcRgb = (r as NcChannel) << 16 | (g as NcChannel) << 8 | (b as NcChannel);
*channel = (*channel & !NCCELL_BG_RGB_MASK) | NCCELL_BGDEFAULT_MASK | rgb;
}
/// Sets the [NcRgb] 24-bit RGB value of a 32-bit [NcChannel], and marks it as
/// not using the "default color". Retain the other bits unchanged.
#[inline]
pub fn channel_set(channel: &mut NcChannel, rgb: NcRgb) {
*channel = (*channel & !NCCELL_BG_RGB_MASK) | NCCELL_BGDEFAULT_MASK | (rgb & 0x00ffffff);
}
/// Extracts the [NcAlphaBits] 2-bit component from a 32-bit [NcChannel].
#[inline]
pub fn channel_alpha(channel: NcChannel) -> NcAlphaBits {
channel & NCCHANNEL_ALPHA_MASK
}
/// Sets the [NcAlphaBits] 2-bit component of a 32-bit [NcChannel].
#[inline]
pub fn channel_set_alpha(channel: &mut NcChannel, alpha: NcAlphaBits) {
let alpha_clean = alpha & NCCHANNEL_ALPHA_MASK;
*channel = alpha_clean | (*channel & !NCCHANNEL_ALPHA_MASK);
if alpha != NCCELL_ALPHA_OPAQUE {
// indicate that we are *not* using the default background color
*channel |= NCCELL_BGDEFAULT_MASK;
}
}
/// Is this [NcChannel] using the "default color" rather than RGB/palette-indexed?
#[inline]
pub fn channel_default_p(channel: NcChannel) -> bool {
(channel & NCCELL_BGDEFAULT_MASK) == 0
}
/// Is this [NcChannel] using palette-indexed color rather than RGB?
#[inline]
pub fn channel_palindex_p(channel: NcChannel) -> bool {
!(channel_default_p(channel) && (channel & NCCELL_BG_PALETTE) == 0)
}
/// Marks an [NcChannel] as using its "default color", which also marks it opaque.
#[inline]
pub fn channel_set_default(channel: &mut NcChannel) -> NcChannel {
*channel &= !(NCCELL_BGDEFAULT_MASK | NCCELL_ALPHA_HIGHCONTRAST);
*channel
}
/// Extracts the 32-bit background [NcChannel] from a [NcChannelPair].
#[inline]
pub fn channels_bchannel(channels: NcChannelPair) -> NcChannel {
(channels & 0xffffffff_u64) as NcChannel
}
/// Extracts the 32-bit foreground [NcChannel] from an [NcChannelPair].
#[inline]
pub fn channels_fchannel(channels: NcChannelPair) -> NcChannel {
channels_bchannel(channels >> 32)
}
/// Sets the 32-bit background [NcChannel] of an [NcChannelPair].
#[inline]
pub fn channels_set_bchannel(channels: &mut NcChannelPair, bchannel: NcChannel) -> NcChannelPair {
*channels = (*channels & 0xffffffff00000000_u64) | bchannel as u64;
*channels
}
/// Sets the 32-bit foreground [NcChannel] of an [NcChannelPair].
#[inline]
pub fn channels_set_fchannel(channels: &mut NcChannelPair, fchannel: NcChannel) -> NcChannelPair {
*channels = (*channels & 0xffffffff_u64) | (fchannel as u64) << 32;
*channels
}
/// Combines two [NcChannel]s into a [NcChannelPair].
#[inline]
pub fn channels_combine(fchannel: NcChannel, bchannel: NcChannel) -> NcChannelPair {
let mut channels: NcChannelPair = 0;
channels_set_fchannel(&mut channels, fchannel);
channels_set_bchannel(&mut channels, bchannel);
channels
}
mod test;
/// Extracts the foreground [NcRgb] 24-bit value from an [NcChannelPair],
/// shifted to LSBs.
#[inline]
pub fn channels_fg_rgb(channels: NcChannelPair) -> NcChannel {
channels_fchannel(channels) & NCCELL_BG_RGB_MASK
}
mod reimplemented;
pub use reimplemented::*;
/// Extracts the background [NcRgb] 24-bit value from an [NcChannelPair],
/// shifted to LSBs.
#[inline]
pub fn channels_bg_rgb(channels: NcChannelPair) -> NcChannel {
channels_bchannel(channels) & NCCELL_BG_RGB_MASK
}
/// Extracts the foreground [NcAlphabits] from an [NcChannelPair], shifted to LSBs.
#[inline]
pub fn channels_fg_alpha(channels: NcChannelPair) -> NcAlphaBits {
channel_alpha(channels_fchannel(channels))
}
/// Extracts the background [NcAlphabits] from an [NcChannelPair], shifted to LSBs.
#[inline]
pub fn channels_bg_alpha(channels: NcChannelPair) -> NcAlphaBits {
channel_alpha(channels_bchannel(channels))
}
/// Extracts the foreground [NcRgb] 24-bit value from an [NcChannelPair], and
/// saves it split into three [NcColor] 8-bit components. Also returns the
/// corresponding [NcChannel] (which can have some extra bits set).
#[inline]
pub fn channels_fg_rgb8(
channels: NcChannelPair,
r: &mut NcColor,
g: &mut NcColor,
b: &mut NcColor,
) -> NcChannel {
channel_rgb8(channels_fchannel(channels), r, g, b)
}
/// Extracts the background [NcRgb] 24-bit value from an [NcChannelPair], and
/// saves it split into three [NcColor] 8-bit components. Also returns the
/// corresponding [NcChannel] (which can have some extra bits set).
#[inline]
pub fn channels_bg_rgb8(
channels: NcChannelPair,
r: &mut NcColor,
g: &mut NcColor,
b: &mut NcColor,
) -> NcChannel {
channel_rgb8(channels_bchannel(channels), r, g, b)
}
/// Sets the RGB [NcColor] components for the foreground [NcChannel] of an
/// [NcChannelPair] 64-bit variable, and marks it as not using the "default color".
#[inline]
pub fn channels_set_fg_rgb8(channels: &mut NcChannelPair, r: NcColor, g: NcColor, b: NcColor) {
let mut channel = channels_fchannel(*channels);
channel_set_rgb8(&mut channel, r, g, b);
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
}
/// Sets the [NcRgb] 24-bit value for the foreground [NcChannel] of an
/// [NcChannelPair] 64-bit variable, and marks it as not using the "default color".
#[inline]
pub fn channels_set_fg_rgb(channels: &mut NcChannelPair, rgb: NcRgb) {
let mut channel = channels_fchannel(*channels);
channel_set(&mut channel, rgb);
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
}
/// Sets the RGB [NcColor] components for the background [NcChannel] of an
/// [NcChannelPair] 64-bit variable, and marks it as not using the "default color".
#[inline]
pub fn channels_set_bg_rgb8(channels: &mut NcChannelPair, r: NcColor, g: NcColor, b: NcColor) {
let mut channel = channels_bchannel(*channels);
channel_set_rgb8(&mut channel, r, g, b);
channels_set_bchannel(channels, channel);
}
/// Sets the [NcRgb] 24-bit value for the background [NcChannel] of an
/// [NcChannelPair] 64-bit variable, and marks it as not using the "default color".
#[inline]
pub fn channels_set_bg_rgb(channels: &mut NcChannelPair, rgb: NcRgb) {
let mut channel = channels_bchannel(*channels);
channel_set(&mut channel, rgb);
channels_set_bchannel(channels, channel);
}
/// Sets the [NcAlphaBits] of the foreground [NcChannel] of an [NcChannelPair].
#[inline]
pub fn channels_set_fg_alpha(channels: &mut NcChannelPair, alpha: NcAlphaBits) {
let mut channel = channels_fchannel(*channels);
channel_set_alpha(&mut channel, alpha);
*channels = (channel as NcChannelPair) << 32 | *channels & 0xffffffff_u64;
}
/// Sets the [NcAlphaBits] of the background [NcChannel] of an [NcChannelPair].
#[inline]
pub fn channels_set_bg_alpha(channels: &mut NcChannelPair, alpha: NcAlphaBits) {
let mut alpha_clean = alpha;
if alpha == NCCELL_ALPHA_HIGHCONTRAST {
// forbidden for background alpha, so makes it opaque
alpha_clean = NCCELL_ALPHA_OPAQUE;
}
let mut channel = channels_bchannel(*channels);
channel_set_alpha(&mut channel, alpha_clean);
channels_set_bchannel(channels, channel);
}
/// Is the foreground of an [NcChannelPair] using the "default foreground color"?
#[inline]
pub fn channels_fg_default_p(channels: NcChannelPair) -> bool {
channel_default_p(channels_fchannel(channels))
}
// NcChannel
//
/// 32 bits of context-dependent info
/// containing RGB + 2 bits of alpha + extra
///
/// It is:
/// - a 24-bit [`NcRgb`] value
/// - plus 8 bits divided in:
/// - 2 bits of [`NcAlphaBits`]
/// - 6 bits of context-dependent info
///
/// The context details are documented in [`NcChannelPair`]
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
/// `type in C: channel (uint32_t)`
///
pub type NcChannel = u32;
/// Is the foreground of an [NcChannelPair] using an [indexed][NcPaletteIndex]
/// [NcPalette][crate::NcPalette] color?
#[inline]
pub fn channels_fg_palindex_p(channels: NcChannelPair) -> bool {
channel_palindex_p(channels_fchannel(channels))
}
/// Extract these bits to get a channel's alpha value
pub const NCCHANNEL_ALPHA_MASK: u32 = crate::bindings::bindgen::CHANNEL_ALPHA_MASK;
/// Is the background using the "default background color"? The "default
/// background color" must generally be used to take advantage of
/// terminal-effected transparency.
#[inline]
pub fn channels_bg_default_p(channels: NcChannelPair) -> bool {
channel_default_p(channels_bchannel(channels))
}
// NcAlphaBits
//
/// 2 bits of alpha (surrounded by context dependent bits).
/// It is part of an [`NcChannel`].
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~ -------- -------- --------
/// ```
///
/// `type in C: no data type`
///
pub type NcAlphaBits = u32;
/// Is the background of an [NcChannelPair] using an [indexed][NcPaletteIndex]
/// [NcPalette][crate::NcPalette] color?
#[inline]
pub fn channels_bg_palindex_p(channels: NcChannelPair) -> bool {
channel_palindex_p(channels_bchannel(channels))
}
// NcChannelPair
//
/// 64 bits containing a foreground and background [`NcChannel`]
///
/// At render time, both 24-bit [`NcRgb`] values are quantized down to terminal
/// capabilities, if necessary. There's a clear path to 10-bit support should
/// we one day need it.
///
/// ## Default Color
///
/// The "default color" is best explained by
/// [color(3NCURSES)](https://manpages.debian.org/stretch/ncurses-doc/color.3ncurses.en.html).
/// Ours is the same concept.
///
/// **Until the "not default color" bit is set, any color you load will be ignored.**
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB|~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB
/// ↑↑↑↑↑↑↑↑↑↑↑↑ foreground ↑↑↑↑↑↑↑↑↑↑↑|↑↑↑↑↑↑↑↑↑↑↑↑ background ↑↑↑↑↑↑↑↑↑↑↑
/// ```
///
/// Detailed info (specially on the context-dependent bits on each
/// [`NcChannel`]'s 4th byte):
///
/// ```txt
/// ~foreground channel~
/// NCCELL_WIDEASIAN_MASK: part of a wide glyph ↓bits view↓ ↓hex mask↓
/// 1······· ········ ········ ········ ········ ········ ········ ········ = 8······· ········
///
/// NCCELL_FGDEFAULT_MASK: foreground is NOT "default color"
/// ·1······ ········ ········ ········ ········ ········ ········ ········ = 4······· ········
///
/// NCCELL_FG_ALPHA_MASK: foreground alpha (2bits)
/// ··11···· ········ ········ ········ ········ ········ ········ ········ = 3······· ········
///
/// NCCELL_FG_PALETTE: foreground uses palette index
/// ····1··· ········ ········ ········ ········ ········ ········ ········ = ·8······ ········
///
/// NCCELL_NOBACKGROUND_MASK: glyph is entirely foreground
/// ·····1·· ········ ········ ········ ········ ········ ········ ········ = ·4······ ········
///
/// reserved, must be 0
/// ······00 ········ ········ ········ ········ ········ ········ ········ = ·3······ ········
///
/// NCCELL_FG_RGB_MASK: foreground in 3x8 RGB (rrggbb)
/// ········ 11111111 11111111 11111111 ········ ········ ········ ········ = ··FFFFFF ········
/// ```
/// ```txt
/// ~background channel~
/// reserved, must be 0 ↓bits view↓ ↓hex mask↓
/// ········ ········ ········ ········ 0······· ········ ········ ········ = ········ 8·······
///
/// NCCELL_BGDEFAULT_MASK: background is NOT "default color"
/// ········ ········ ········ ········ ·1······ ········ ········ ········ = ········ 4·······
///
/// NCCELL_BG_ALPHA_MASK: background alpha (2 bits)
/// ········ ········ ········ ········ ··11···· ········ ········ ········ = ········ 3·······
///
/// NCCELL_BG_PALETTE: background uses palette index
/// ········ ········ ········ ········ ····1··· ········ ········ ········ = ········ ·8······
///
/// reserved, must be 0
/// ········ ········ ········ ········ ·····000 ········ ········ ········ = ········ ·7······
///
/// NCCELL_BG_RGB_MASK: background in 3x8 RGB (rrggbb)
/// 0········ ········ ········ ········ ········11111111 11111111 11111111 = ········ ··FFFFFF
/// ```
/// `type in C: channels (uint64_t)`
///
/// ## `NcCell` Mask Flags
///
/// - [`NCCELL_BGDEFAULT_MASK`][crate::NCCELL_BGDEFAULT_MASK]
/// - [`NCCELL_BG_ALPHA_MASK`][crate::NCCELL_BG_ALPHA_MASK]
/// - [`NCCELL_BG_PALETTE`][crate::NCCELL_BG_PALETTE]
/// - [`NCCELL_BG_RGB_MASK`][crate::NCCELL_BG_RGB_MASK]
/// - [`NCCELL_FGDEFAULT_MASK`][crate::NCCELL_FGDEFAULT_MASK]
/// - [`NCCELL_FG_ALPHA_MASK`][crate::NCCELL_FG_ALPHA_MASK]
/// - [`NCCELL_FG_PALETTE`][crate::NCCELL_FG_PALETTE]
/// - [`NCCELL_FG_RGB_MASK`][crate::NCCELL_FG_RGB_MASK]
/// - [`NCCELL_NOBACKGROUND_MASK`][crate::NCCELL_NOBACKGROUND_MASK]
/// - [`NCCELL_WIDEASIAN_MASK`][crate::NCCELL_WIDEASIAN_MASK]
///
pub type NcChannelPair = u64;
/// Sets an [NcCell]'s background [NcPaletteIndex].
///
/// Also sets [NCCELL_BG_PALETTE] and [NCCELL_ALPHA_OPAQUE],
/// and clears out [NCCELL_BGDEFAULT_MASK].
#[inline]
pub fn channels_set_bg_palindex(channels: &mut NcChannelPair, index: NcPaletteIndex) {
*channels |= NCCELL_BGDEFAULT_MASK as NcChannelPair;
*channels |= NCCELL_BG_PALETTE as NcChannelPair;
channels_set_bg_alpha(channels, NCCELL_ALPHA_OPAQUE);
*channels &= 0xffffffffff000000;
*channels |= index as NcChannelPair;
}
// NcRgb
//
/// 24 bits broken into 3x 8bpp channels.
///
/// Unlike with [`NcChannel`], operations involving `NcRgb` ignores the last 4th byte
///
/// ## Diagram
///
/// ```txt
/// -------- RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
///
/// `type in C: no data type`
///
pub type NcRgb = u32;
/// Sets an [NcCell]'s foreground [NcPaletteIndex].
///
/// Also sets [NCCELL_FG_PALETTE] and [NCCELL_ALPHA_OPAQUE],
/// and clears out [NCCELL_FGDEFAULT_MASK].
#[inline]
pub fn channels_set_fg_palindex(channels: &mut NcChannelPair, index: NcPaletteIndex) {
*channels |= NCCELL_FGDEFAULT_MASK;
*channels |= NCCELL_FG_PALETTE as NcChannelPair;
channels_set_fg_alpha(channels, NCCELL_ALPHA_OPAQUE);
*channels &= 0xff000000ffffffff as NcChannelPair;
*channels |= (index as NcChannelPair) << 32;
}
// NcColor
//
/// 8 bits representing a R/G/B color or alpha channel
///
/// ## Diagram
///
/// ```txt
/// CCCCCCCC (1 Byte)
/// ```
///
/// `type in C: no data type`
///
pub type NcColor = u8;
/// Marks the foreground of an [NcChannelPair] as using its "default color",
/// and returns the new [NcChannelPair].
#[inline]
pub fn channels_set_fg_default(channels: &mut NcChannelPair) -> NcChannelPair {
let mut channel = channels_fchannel(*channels);
channel_set_default(&mut channel);
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
*channels
}
/// Context for a palette fade operation
pub type NcFadeCtx = crate::bindings::bindgen::ncfadectx;
/// Marks the background of an [NcChannelPair] as using its "default color",
/// and returns the new [NcChannelPair].
#[inline]
pub fn channels_set_bg_default(channels: &mut NcChannelPair) -> NcChannelPair {
let mut channel = channels_bchannel(*channels);
channel_set_default(&mut channel);
channels_set_bchannel(channels, channel);
*channels
}
/// the [NcEgc][crate::NcEgc] which form the various levels of a given geometry.
///
/// If the geometry is wide, things are arranged with the rightmost side
/// increasing most quickly, i.e. it can be indexed as height arrays of
/// 1 + height glyphs.
/// i.e. The first five braille EGCs are all 0 on the left,
/// [0..4] on the right.
///
/// `type in C: blitset (struct)`
///
pub type NcBlitSet = crate::bindings::bindgen::blitset;

@ -0,0 +1,309 @@
//! `channel*_*` reimplemented functions.
use crate::{
NcAlphaBits, NcChannel, NcChannelPair, NcColor, NcPaletteIndex, NcRgb,
NCCELL_ALPHA_HIGHCONTRAST, NCCELL_ALPHA_OPAQUE, NCCELL_BGDEFAULT_MASK, NCCELL_BG_PALETTE,
NCCELL_BG_RGB_MASK, NCCELL_FGDEFAULT_MASK, NCCELL_FG_PALETTE, NCCHANNEL_ALPHA_MASK,
};
/// Extracts the [NcColor] 8-bit red component from a 32-bit [NcChannel].
#[inline]
pub const fn channel_r(channel: NcChannel) -> NcColor {
((channel & 0xff0000) >> 16) as NcColor
}
/// Extracts the [NcColor] 8-bit green component from a 32-bit [NcChannel].
#[inline]
pub const fn channel_g(channel: NcChannel) -> NcColor {
((channel & 0x00ff00) >> 8) as NcColor
}
/// Extracts the [NcColor] 8-bit blue component from a 32-bit [NcChannel].
#[inline]
pub const fn channel_b(channel: NcChannel) -> NcColor {
(channel & 0x0000ff) as NcColor
}
/// Extracts the three [NcColor] 8-bit RGB components from a 32-bit [NcChannel].
#[inline]
pub fn channel_rgb8(
channel: NcChannel,
r: &mut NcColor,
g: &mut NcColor,
b: &mut NcColor,
) -> NcChannel {
*r = channel_r(channel);
*g = channel_g(channel);
*b = channel_b(channel);
channel
}
/// Sets the three [NcColor] 8-bit components of a 32-bit [NcChannel], and marks
/// it as not using the "default color". Retain the other bits unchanged.
#[inline]
pub fn channel_set_rgb8(channel: &mut NcChannel, r: NcColor, g: NcColor, b: NcColor) {
let rgb: NcRgb = (r as NcChannel) << 16 | (g as NcChannel) << 8 | (b as NcChannel);
*channel = (*channel & !NCCELL_BG_RGB_MASK) | NCCELL_BGDEFAULT_MASK | rgb;
}
/// Sets the [NcRgb] 24-bit RGB value of a 32-bit [NcChannel], and marks it as
/// not using the "default color". Retain the other bits unchanged.
#[inline]
pub fn channel_set(channel: &mut NcChannel, rgb: NcRgb) {
*channel = (*channel & !NCCELL_BG_RGB_MASK) | NCCELL_BGDEFAULT_MASK | (rgb & 0x00ffffff);
}
/// Extracts the [NcAlphaBits] 2-bit component from a 32-bit [NcChannel].
#[inline]
pub fn channel_alpha(channel: NcChannel) -> NcAlphaBits {
channel & NCCHANNEL_ALPHA_MASK
}
/// Sets the [NcAlphaBits] 2-bit component of a 32-bit [NcChannel].
#[inline]
pub fn channel_set_alpha(channel: &mut NcChannel, alpha: NcAlphaBits) {
let alpha_clean = alpha & NCCHANNEL_ALPHA_MASK;
*channel = alpha_clean | (*channel & !NCCHANNEL_ALPHA_MASK);
if alpha != NCCELL_ALPHA_OPAQUE {
// indicate that we are *not* using the default background color
*channel |= NCCELL_BGDEFAULT_MASK;
}
}
/// Is this [NcChannel] using the "default color" rather than RGB/palette-indexed?
#[inline]
pub fn channel_default_p(channel: NcChannel) -> bool {
(channel & NCCELL_BGDEFAULT_MASK) == 0
}
/// Is this [NcChannel] using palette-indexed color rather than RGB?
#[inline]
pub fn channel_palindex_p(channel: NcChannel) -> bool {
!(channel_default_p(channel) && (channel & NCCELL_BG_PALETTE) == 0)
}
/// Marks an [NcChannel] as using its "default color", which also marks it opaque.
#[inline]
pub fn channel_set_default(channel: &mut NcChannel) -> NcChannel {
*channel &= !(NCCELL_BGDEFAULT_MASK | NCCELL_ALPHA_HIGHCONTRAST);
*channel
}
/// Extracts the 32-bit background [NcChannel] from a [NcChannelPair].
#[inline]
pub fn channels_bchannel(channels: NcChannelPair) -> NcChannel {
(channels & 0xffffffff_u64) as NcChannel
}
/// Extracts the 32-bit foreground [NcChannel] from an [NcChannelPair].
#[inline]
pub fn channels_fchannel(channels: NcChannelPair) -> NcChannel {
channels_bchannel(channels >> 32)
}
/// Sets the 32-bit background [NcChannel] of an [NcChannelPair].
#[inline]
pub fn channels_set_bchannel(channels: &mut NcChannelPair, bchannel: NcChannel) -> NcChannelPair {
*channels = (*channels & 0xffffffff00000000_u64) | bchannel as u64;
*channels
}
/// Sets the 32-bit foreground [NcChannel] of an [NcChannelPair].
#[inline]
pub fn channels_set_fchannel(channels: &mut NcChannelPair, fchannel: NcChannel) -> NcChannelPair {
*channels = (*channels & 0xffffffff_u64) | (fchannel as u64) << 32;
*channels
}
/// Combines two [NcChannel]s into a [NcChannelPair].
#[inline]
pub fn channels_combine(fchannel: NcChannel, bchannel: NcChannel) -> NcChannelPair {
let mut channels: NcChannelPair = 0;
channels_set_fchannel(&mut channels, fchannel);
channels_set_bchannel(&mut channels, bchannel);
channels
}
/// Extracts the foreground [NcRgb] 24-bit value from an [NcChannelPair],
/// shifted to LSBs.
#[inline]
pub fn channels_fg_rgb(channels: NcChannelPair) -> NcChannel {
channels_fchannel(channels) & NCCELL_BG_RGB_MASK
}
/// Extracts the background [NcRgb] 24-bit value from an [NcChannelPair],
/// shifted to LSBs.
#[inline]
pub fn channels_bg_rgb(channels: NcChannelPair) -> NcChannel {
channels_bchannel(channels) & NCCELL_BG_RGB_MASK
}
/// Extracts the foreground [NcAlphabits] from an [NcChannelPair], shifted to LSBs.
#[inline]
pub fn channels_fg_alpha(channels: NcChannelPair) -> NcAlphaBits {
channel_alpha(channels_fchannel(channels))
}
/// Extracts the background [NcAlphabits] from an [NcChannelPair], shifted to LSBs.
#[inline]
pub fn channels_bg_alpha(channels: NcChannelPair) -> NcAlphaBits {
channel_alpha(channels_bchannel(channels))
}
/// Extracts the foreground [NcRgb] 24-bit value from an [NcChannelPair], and
/// saves it split into three [NcColor] 8-bit components. Also returns the
/// corresponding [NcChannel] (which can have some extra bits set).
#[inline]
pub fn channels_fg_rgb8(
channels: NcChannelPair,
r: &mut NcColor,
g: &mut NcColor,
b: &mut NcColor,
) -> NcChannel {
channel_rgb8(channels_fchannel(channels), r, g, b)
}
/// Extracts the background [NcRgb] 24-bit value from an [NcChannelPair], and
/// saves it split into three [NcColor] 8-bit components. Also returns the
/// corresponding [NcChannel] (which can have some extra bits set).
#[inline]
pub fn channels_bg_rgb8(
channels: NcChannelPair,
r: &mut NcColor,
g: &mut NcColor,
b: &mut NcColor,
) -> NcChannel {
channel_rgb8(channels_bchannel(channels), r, g, b)
}
/// Sets the RGB [NcColor] components for the foreground [NcChannel] of an
/// [NcChannelPair] 64-bit variable, and marks it as not using the "default color".
#[inline]
pub fn channels_set_fg_rgb8(channels: &mut NcChannelPair, r: NcColor, g: NcColor, b: NcColor) {
let mut channel = channels_fchannel(*channels);
channel_set_rgb8(&mut channel, r, g, b);
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
}
/// Sets the [NcRgb] 24-bit value for the foreground [NcChannel] of an
/// [NcChannelPair] 64-bit variable, and marks it as not using the "default color".
#[inline]
pub fn channels_set_fg_rgb(channels: &mut NcChannelPair, rgb: NcRgb) {
let mut channel = channels_fchannel(*channels);
channel_set(&mut channel, rgb);
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
}
/// Sets the RGB [NcColor] components for the background [NcChannel] of an
/// [NcChannelPair] 64-bit variable, and marks it as not using the "default color".
#[inline]
pub fn channels_set_bg_rgb8(channels: &mut NcChannelPair, r: NcColor, g: NcColor, b: NcColor) {
let mut channel = channels_bchannel(*channels);
channel_set_rgb8(&mut channel, r, g, b);
channels_set_bchannel(channels, channel);
}
/// Sets the [NcRgb] 24-bit value for the background [NcChannel] of an
/// [NcChannelPair] 64-bit variable, and marks it as not using the "default color".
#[inline]
pub fn channels_set_bg_rgb(channels: &mut NcChannelPair, rgb: NcRgb) {
let mut channel = channels_bchannel(*channels);
channel_set(&mut channel, rgb);
channels_set_bchannel(channels, channel);
}
/// Sets the [NcAlphaBits] of the foreground [NcChannel] of an [NcChannelPair].
#[inline]
pub fn channels_set_fg_alpha(channels: &mut NcChannelPair, alpha: NcAlphaBits) {
let mut channel = channels_fchannel(*channels);
channel_set_alpha(&mut channel, alpha);
*channels = (channel as NcChannelPair) << 32 | *channels & 0xffffffff_u64;
}
/// Sets the [NcAlphaBits] of the background [NcChannel] of an [NcChannelPair].
#[inline]
pub fn channels_set_bg_alpha(channels: &mut NcChannelPair, alpha: NcAlphaBits) {
let mut alpha_clean = alpha;
if alpha == NCCELL_ALPHA_HIGHCONTRAST {
// forbidden for background alpha, so makes it opaque
alpha_clean = NCCELL_ALPHA_OPAQUE;
}
let mut channel = channels_bchannel(*channels);
channel_set_alpha(&mut channel, alpha_clean);
channels_set_bchannel(channels, channel);
}
/// Is the foreground of an [NcChannelPair] using the "default foreground color"?
#[inline]
pub fn channels_fg_default_p(channels: NcChannelPair) -> bool {
channel_default_p(channels_fchannel(channels))
}
/// Is the foreground of an [NcChannelPair] using an [indexed][NcPaletteIndex]
/// [NcPalette][crate::NcPalette] color?
#[inline]
pub fn channels_fg_palindex_p(channels: NcChannelPair) -> bool {
channel_palindex_p(channels_fchannel(channels))
}
/// Is the background using the "default background color"? The "default
/// background color" must generally be used to take advantage of
/// terminal-effected transparency.
#[inline]
pub fn channels_bg_default_p(channels: NcChannelPair) -> bool {
channel_default_p(channels_bchannel(channels))
}
/// Is the background of an [NcChannelPair] using an [indexed][NcPaletteIndex]
/// [NcPalette][crate::NcPalette] color?
#[inline]
pub fn channels_bg_palindex_p(channels: NcChannelPair) -> bool {
channel_palindex_p(channels_bchannel(channels))
}
/// Sets an [NcCell]'s background [NcPaletteIndex].
///
/// Also sets [NCCELL_BG_PALETTE] and [NCCELL_ALPHA_OPAQUE],
/// and clears out [NCCELL_BGDEFAULT_MASK].
#[inline]
pub fn channels_set_bg_palindex(channels: &mut NcChannelPair, index: NcPaletteIndex) {
*channels |= NCCELL_BGDEFAULT_MASK as NcChannelPair;
*channels |= NCCELL_BG_PALETTE as NcChannelPair;
channels_set_bg_alpha(channels, NCCELL_ALPHA_OPAQUE);
*channels &= 0xffffffffff000000;
*channels |= index as NcChannelPair;
}
/// Sets an [NcCell]'s foreground [NcPaletteIndex].
///
/// Also sets [NCCELL_FG_PALETTE] and [NCCELL_ALPHA_OPAQUE],
/// and clears out [NCCELL_FGDEFAULT_MASK].
#[inline]
pub fn channels_set_fg_palindex(channels: &mut NcChannelPair, index: NcPaletteIndex) {
*channels |= NCCELL_FGDEFAULT_MASK;
*channels |= NCCELL_FG_PALETTE as NcChannelPair;
channels_set_fg_alpha(channels, NCCELL_ALPHA_OPAQUE);
*channels &= 0xff000000ffffffff as NcChannelPair;
*channels |= (index as NcChannelPair) << 32;
}
/// Marks the foreground of an [NcChannelPair] as using its "default color",
/// and returns the new [NcChannelPair].
#[inline]
pub fn channels_set_fg_default(channels: &mut NcChannelPair) -> NcChannelPair {
let mut channel = channels_fchannel(*channels);
channel_set_default(&mut channel);
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
*channels
}
/// Marks the background of an [NcChannelPair] as using its "default color",
/// and returns the new [NcChannelPair].
#[inline]
pub fn channels_set_bg_default(channels: &mut NcChannelPair) -> NcChannelPair {
let mut channel = channels_bchannel(*channels);
channel_set_default(&mut channel);
channels_set_bchannel(channels, channel);
*channels
}

@ -0,0 +1,10 @@
//! Test `NcChannel*` methods and associated functions.
// use crate::{NcChannel, NcChannelPair};
//
// use serial_test::serial;
//
// #[test]
// #[serial]
// fn () {
// }

@ -0,0 +1,7 @@
//! `NcChannel*` tests.
#[cfg(test)]
mod methods;
#[cfg(test)]
mod reimplemented;

@ -1,12 +1,12 @@
//! [`NcChannel`] & [`NcChannelPair`] tests
//! Test `channel*_*` reimplemented functions.
use serial_test::serial;
use crate::{
NcChannel, NcChannelPair, NCCELL_ALPHA_BLEND, NCCELL_ALPHA_HIGHCONTRAST, NCCELL_ALPHA_OPAQUE,
NCCELL_ALPHA_TRANSPARENT,
};
use serial_test::serial;
#[test]
#[serial]
fn channel_r() {

@ -1,211 +0,0 @@
#[allow(unused_imports)] // for docblocks
use crate::NcChar;
// NcChannel
//
/// 32 bits of context-dependent info
/// containing RGB + 2 bits of alpha + extra
///
/// It is:
/// - a 24-bit [`NcRgb`] value
/// - plus 8 bits divided in:
/// - 2 bits of [`NcAlphaBits`]
/// - 6 bits of context-dependent info
///
/// The context details are documented in [`NcChannelPair`]
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
/// `type in C: channel (uint32_t)`
///
pub type NcChannel = u32;
/// Extract these bits to get a channel's alpha value
pub const NCCHANNEL_ALPHA_MASK: u32 = crate::bindings::bindgen::CHANNEL_ALPHA_MASK;
// NcAlphaBits
//
/// 2 bits of alpha (surrounded by context dependent bits).
/// It is part of an [`NcChannel`].
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~ -------- -------- --------
/// ```
///
/// `type in C: no data type`
///
pub type NcAlphaBits = u32;
// NcChannelPair
//
/// 64 bits containing a foreground and background [`NcChannel`]
///
/// At render time, both 24-bit [`NcRgb`] values are quantized down to terminal
/// capabilities, if necessary. There's a clear path to 10-bit support should
/// we one day need it.
///
/// ## Default Color
///
/// The "default color" is best explained by
/// [color(3NCURSES)](https://manpages.debian.org/stretch/ncurses-doc/color.3ncurses.en.html).
/// Ours is the same concept.
///
/// **Until the "not default color" bit is set, any color you load will be ignored.**
///
/// ## Diagram
///
/// ```txt
/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB|~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB
/// ↑↑↑↑↑↑↑↑↑↑↑↑ foreground ↑↑↑↑↑↑↑↑↑↑↑|↑↑↑↑↑↑↑↑↑↑↑↑ background ↑↑↑↑↑↑↑↑↑↑↑
/// ```
///
/// Detailed info (specially on the context-dependent bits on each
/// [`NcChannel`]'s 4th byte):
///
/// ```txt
/// ~foreground channel~
/// NCCELL_WIDEASIAN_MASK: part of a wide glyph ↓bits view↓ ↓hex mask↓
/// 1······· ········ ········ ········ ········ ········ ········ ········ = 8······· ········
///
/// NCCELL_FGDEFAULT_MASK: foreground is NOT "default color"
/// ·1······ ········ ········ ········ ········ ········ ········ ········ = 4······· ········
///
/// NCCELL_FG_ALPHA_MASK: foreground alpha (2bits)
/// ··11···· ········ ········ ········ ········ ········ ········ ········ = 3······· ········
///
/// NCCELL_FG_PALETTE: foreground uses palette index
/// ····1··· ········ ········ ········ ········ ········ ········ ········ = ·8······ ········
///
/// NCCELL_NOBACKGROUND_MASK: glyph is entirely foreground
/// ·····1·· ········ ········ ········ ········ ········ ········ ········ = ·4······ ········
///
/// reserved, must be 0
/// ······00 ········ ········ ········ ········ ········ ········ ········ = ·3······ ········
///
/// NCCELL_FG_RGB_MASK: foreground in 3x8 RGB (rrggbb)
/// ········ 11111111 11111111 11111111 ········ ········ ········ ········ = ··FFFFFF ········
/// ```
/// ```txt
/// ~background channel~
/// reserved, must be 0 ↓bits view↓ ↓hex mask↓
/// ········ ········ ········ ········ 0······· ········ ········ ········ = ········ 8·······
///
/// NCCELL_BGDEFAULT_MASK: background is NOT "default color"
/// ········ ········ ········ ········ ·1······ ········ ········ ········ = ········ 4·······
///
/// NCCELL_BG_ALPHA_MASK: background alpha (2 bits)
/// ········ ········ ········ ········ ··11···· ········ ········ ········ = ········ 3·······
///
/// NCCELL_BG_PALETTE: background uses palette index
/// ········ ········ ········ ········ ····1··· ········ ········ ········ = ········ ·8······
///
/// reserved, must be 0
/// ········ ········ ········ ········ ·····000 ········ ········ ········ = ········ ·7······
///
/// NCCELL_BG_RGB_MASK: background in 3x8 RGB (rrggbb)
/// 0········ ········ ········ ········ ········11111111 11111111 11111111 = ········ ··FFFFFF
/// ```
/// `type in C: channels (uint64_t)`
///
/// ## `NcCell` Mask Flags
///
/// - [`NCCELL_BGDEFAULT_MASK`][crate::NCCELL_BGDEFAULT_MASK]
/// - [`NCCELL_BG_ALPHA_MASK`][crate::NCCELL_BG_ALPHA_MASK]
/// - [`NCCELL_BG_PALETTE`][crate::NCCELL_BG_PALETTE]
/// - [`NCCELL_BG_RGB_MASK`][crate::NCCELL_BG_RGB_MASK]
/// - [`NCCELL_FGDEFAULT_MASK`][crate::NCCELL_FGDEFAULT_MASK]
/// - [`NCCELL_FG_ALPHA_MASK`][crate::NCCELL_FG_ALPHA_MASK]
/// - [`NCCELL_FG_PALETTE`][crate::NCCELL_FG_PALETTE]
/// - [`NCCELL_FG_RGB_MASK`][crate::NCCELL_FG_RGB_MASK]
/// - [`NCCELL_NOBACKGROUND_MASK`][crate::NCCELL_NOBACKGROUND_MASK]
/// - [`NCCELL_WIDEASIAN_MASK`][crate::NCCELL_WIDEASIAN_MASK]
///
pub type NcChannelPair = u64;
// NcRgb
//
/// 24 bits broken into 3x 8bpp channels.
///
/// Unlike with [`NcChannel`], operations involving `NcRgb` ignores the last 4th byte
///
/// ## Diagram
///
/// ```txt
/// -------- RRRRRRRR GGGGGGGG BBBBBBBB
/// ```
///
/// `type in C: no data type`
///
pub type NcRgb = u32;
// NcColor
//
/// 8 bits representing a R/G/B color or alpha channel
///
/// ## Diagram
///
/// ```txt
/// CCCCCCCC (1 Byte)
/// ```
///
/// `type in C: no data type`
///
pub type NcColor = u8;
// NcPixel (RGBA)
/// 32 bits broken into RGB + 8-bit alpha
///
/// NcPixel has 8 bits of alpha, more or less linear, contributing
/// directly to the usual alpha blending equation.
///
/// We map the 8 bits of alpha to 2 bits of alpha via a level function:
/// https://nick-black.com/dankwiki/index.php?title=Notcurses#Transparency.2FContrasting
///
/// ## Diagram
///
/// ```txt
/// AAAAAAAA GGGGGGGG BBBBBBBB RRRRRRRR
/// ```
/// `type in C: ncpixel (uint32_t)`
///
// NOTE: the order of the colors is different than in NcChannel.
pub type NcPixel = u32;
/// NcPalette structure consisting of an array of 256 [`NcChannel`]s.
///
/// See also [NcPaletteIndex].
///
/// Some terminals only support 256 colors, but allow the full
/// palette to be specified with arbitrary RGB colors. In all cases, it's more
/// performant to use indexed colors, since it's much less data to write to the
/// terminal. If you can limit yourself to 256 colors, that's probably best.
///
/// `type in C: ncpalette256 (struct)`
///
pub type NcPalette = crate::bindings::bindgen::palette256;
/// 8-bit value used for indexing into a [`NcPalette`]
///
pub type NcPaletteIndex = u8;
/// Context for a palette fade operation
pub type NcFadeCtx = crate::bindings::bindgen::ncfadectx;
/// the [`NcChar`] which form the various levels
/// of a given geometry.
///
/// If the geometry is wide, things are arranged with the rightmost side
/// increasing most quickly, i.e. it can be indexed as height arrays of
/// 1 + height glyphs.
/// i.e. The first five braille EGCs are all 0 on the left,
/// [0..4] on the right.
///
/// `type in C: blitset (struct)`
///
pub type NcBlitSet = crate::bindings::bindgen::blitset;

@ -1,3 +1,5 @@
//! `NcDirect` methods and associated functions.
use crate::{ncdirect_init, NcDirect, NcDirectFlags};
use core::ptr::{null, null_mut};
@ -26,9 +28,9 @@ impl NcDirect {
}
}
// Explicitly implementing both `Drop` and `Copy` trait on a type is currently
// disallowed (rustc --explain E0184)
// https://github.com/rust-lang/rust/issues/20126
// NOTE: Explicitly implementing both `Drop` and `Copy` trait on a type is
// currently disallowed (rustc --explain E0184)
// See: https://github.com/rust-lang/rust/issues/20126
//
// impl Drop for NcDirect {
// fn drop(&mut self) {

@ -1,53 +1,74 @@
//! `NcDirect`
// functions already exported by bindgen : 38
// ------------------------------------------ (done / remaining)
// (#) unit tests: 0 / 38
// ------------------------------------------
// 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
// ncdirect_init // wrapped at _new() & _with_flags()
// 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) wrap: 1 / 37
// (#) test: 0 / 38
// ------------------------------------------
// 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
#[cfg(test)]
mod tests;
mod test;
mod methods;
/// Minimal notcurses instances for styling text
pub type NcDirect = crate::bindings::bindgen::ncdirect;
/// Flags (options) for [`NcDirect`]
pub type NcDirectFlags = u64;
mod types;
pub use types::{
NcDirect, NcDirectFlags, NCDIRECT_OPTION_INHIBIT_CBREAK, NCDIRECT_OPTION_INHIBIT_SETLOCALE,
};
/// Flag that avoids placing the terminal into cbreak mode
/// (disabling echo and line buffering)
///
pub const NCDIRECT_OPTION_INHIBIT_CBREAK: NcDirectFlags =
crate::bindings::bindgen::NCDIRECT_OPTION_INHIBIT_CBREAK as NcDirectFlags;
mod wrapped;
pub use wrapped::*;
/// Flag that avoids calling setlocale(LC_ALL, NULL)
///
/// If the result is either "C" or "POSIX", it will print a
/// diagnostic to stderr, and then call setlocale(LC_ALL, "").
///
/// This will attempt to set the locale based off the LANG
/// environment variable. Your program should call setlocale(3)
/// itself, usually as one of the first lines.
///
pub const NCDIRECT_OPTION_INHIBIT_SETLOCALE: NcDirectFlags =
crate::bindings::bindgen::NCDIRECT_OPTION_INHIBIT_SETLOCALE as NcDirectFlags;

@ -1,25 +0,0 @@
//! Types related with `NcDirect`
/// Minimal notcurses instances for styling text
pub type NcDirect = crate::bindings::bindgen::ncdirect;
/// Flags (options) for [`NcDirect`]
pub type NcDirectFlags = u64;
/// Flag that avoids placing the terminal into cbreak mode
/// (disabling echo and line buffering)
///
pub const NCDIRECT_OPTION_INHIBIT_CBREAK: NcDirectFlags =
crate::bindings::bindgen::NCDIRECT_OPTION_INHIBIT_CBREAK as NcDirectFlags;
/// Flag that avoids calling setlocale(LC_ALL, NULL)
///
/// If the result is either "C" or "POSIX", it will print a
/// diagnostic to stderr, and then call setlocale(LC_ALL, "").
///
/// This will attempt to set the locale based off the LANG
/// environment variable. Your program should call setlocale(3)
/// itself, usually as one of the first lines.
///
pub const NCDIRECT_OPTION_INHIBIT_SETLOCALE: NcDirectFlags =
crate::bindings::bindgen::NCDIRECT_OPTION_INHIBIT_SETLOCALE as NcDirectFlags;

@ -1,12 +1,11 @@
// functions already exported by bindgen : 0
// -----------------------------------------
//
// static inline functions total: 1
// ------------------------------------------ (done / remaining)
//! `NcInput`
// functions manually reimplemented: 1
// ------------------------------------------
// (+) done: 1 / 0
// (#) test: 0 / 1
// ------------------------------------------
//+ ncinput_equal_p
// + ncinput_equal_p
/// Reads and decodes input events
///
@ -16,7 +15,7 @@
/// To exit, generate EOF (usually Ctrl+d).
pub type NcInput = crate::bindings::bindgen::ncinput;
/// Compare two ncinput structs for data equality by doing a field-by-field
/// Compares two ncinput structs for data equality by doing a field-by-field
/// comparison for equality (excepting seqnum).
///
/// Returns true if the two are data-equivalent.
@ -31,6 +30,7 @@ pub fn ncinput_equal_p(n1: NcInput, n2: NcInput) -> bool {
true
}
/// New `NcInput`.
impl NcInput {
pub fn new() -> NcInput {
NcInput {

@ -1,13 +1,10 @@
// functions already exported by bindgen : 0
// functions manually reimplemented: 2
// ------------------------------------------
//
// static inline functions total: 2
// ------------------------------------------ (done / remaining)
// (+) done: 2 / 0
// (#) test: 0 / 2
// ------------------------------------------
//+ nckey_mouse_p
//+ nckey_supppuab_p
// + nckey_mouse_p
// + nckey_supppuab_p
use crate::{NCKEY_BUTTON1, NCKEY_RELEASE};
@ -26,15 +23,3 @@ pub fn nckey_supppuab_p(w: u32) -> bool {
pub fn nckey_mouse_p(r: u32) -> bool {
r >= NCKEY_BUTTON1 && r <= NCKEY_RELEASE
}
#[cfg(test)]
mod test {
// use super::nc;
// use serial_test::serial;
/*
#[test]
#[serial]
fn () {
}
*/
}

@ -17,7 +17,6 @@
#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case)]
#![allow(clippy::too_many_arguments)]
mod bindings;
#[doc(inline)]
pub use bindings::*;

@ -1,5 +1,7 @@
//! Macros
// General Utility Macros ------------------------------------------------------
/// Sleeps for $ms milliseconds
#[macro_export]
macro_rules! sleep {
@ -13,5 +15,5 @@ macro_rules! sleep {
macro_rules! cstring {
($s:expr) => {
std::ffi::CString::new($s).unwrap().as_ptr();
}
};
}

@ -1,4 +1,4 @@
//! Handy [`Notcurses`] and [`NotcursesOptions`] constructors
//! `Notcurses*` methods and associated functions.
use core::ptr::{null, null_mut};
@ -7,7 +7,8 @@ use crate::{
NCOPTION_SUPPRESS_BANNERS,
};
use crate::{
notcurses_stdplane, NcPlane, notcurses_stop, NcResult, notcurses_render,
notcurses_render, notcurses_stdplane, notcurses_stdplane_const, notcurses_stop, NcPlane,
NcResult,
};
/// # `NotcursesOptions` Constructors
@ -113,21 +114,34 @@ impl Notcurses {
/// # `Notcurses` methods
impl Notcurses {
// reference, ... I need an NcPlane from this...
// pub fn stdplane_mut2(&mut self) -> *mut NcPlane {
// unsafe { notcurses_stdplane(self) }
// }
///
pub fn stdplane_mut(&mut self) -> NcPlane {
unsafe { *notcurses_stdplane(self) }
//notcurses_stdplane_const //???
/// Returns a mutable reference to the standard [NcPlane] for this terminal.
///
/// The standard plane always exists, and its origin is always at the
/// uppermost, leftmost cell.
pub fn stdplane_mut<'a>(&mut self) -> &'a mut NcPlane {
unsafe { &mut *notcurses_stdplane(self) }
}
/// Returns a reference to the standard [NcPlane] for this terminal.
///
/// The standard plane always exists, and its origin is always at the
/// uppermost, leftmost cell.
pub fn stdplane<'a>(&self) -> &'a NcPlane {
unsafe { &*notcurses_stdplane_const(self) }
}
///
///
pub fn stop(&mut self) -> NcResult {
unsafe { notcurses_stop(self) }
}
///
///
pub fn render(&mut self) -> NcResult {
unsafe { notcurses_render(self) }
}
}

@ -1,159 +1,173 @@
//! `Notcurses`
// functions already exported by bindgen : 39
// ----------------------------------------- (done / remaining)
// ------------------------------------------
// (#) unit tests: 10 / 29
// ------------------------------------------
// notcurses_at_yx
// notcurses_bottom
//# notcurses_canchangecolor
//# notcurses_canfade
//# notcurses_canopen_images
//# notcurses_canopen_videos
//# notcurses_cansixel
//# notcurses_cantruecolor
//# notcurses_canutf8
// notcurses_cursor_disable
// notcurses_cursor_enable
//# notcurses_debug
//# notcurses_drop_planes
// notcurses_getc
//# notcurses_init
// notcurses_inputready_fd
// notcurses_lex_blitter
// notcurses_lex_margins
// notcurses_lex_scalemode
// notcurses_mouse_disable
// notcurses_mouse_enable
// notcurses_palette_size
// notcurses_refresh
// notcurses_render
// notcurses_render_to_buffer
// notcurses_render_to_file
// notcurses_stats
// notcurses_stats_alloc
// notcurses_stats_reset
// notcurses_stdplane
// notcurses_stdplane_const
//# notcurses_stop
// notcurses_str_blitter
// notcurses_str_scalemode
// notcurses_supported_styles
// notcurses_top
// notcurses_ucs32_to_utf8
// notcurses_version
// notcurses_version_components
// notcurses_at_yx
// notcurses_bottom
// # notcurses_canchangecolor
// # notcurses_canfade
// # notcurses_canopen_images
// # notcurses_canopen_videos
// # notcurses_cansixel
// # notcurses_cantruecolor
// # notcurses_canutf8
// notcurses_cursor_disable
// notcurses_cursor_enable
// # notcurses_debug
// # notcurses_drop_planes
// notcurses_getc
// # notcurses_init
// notcurses_inputready_fd
// notcurses_lex_blitter
// notcurses_lex_margins
// notcurses_lex_scalemode
// notcurses_mouse_disable
// notcurses_mouse_enable
// notcurses_palette_size
// notcurses_refresh
// notcurses_render
// notcurses_render_to_buffer
// notcurses_render_to_file
// notcurses_stats
// notcurses_stats_alloc
// notcurses_stats_reset
// notcurses_stdplane
// notcurses_stdplane_const
// # notcurses_stop
// notcurses_str_blitter
// notcurses_str_scalemode
// notcurses_supported_styles
// notcurses_top
// notcurses_ucs32_to_utf8
// notcurses_version
// notcurses_version_components
//
// static inline functions total: 6
// ----------------------------------------- (done / remaining)
// functions manually reimplemented: 6
// -----------------------------------------
// (+) implement : 6 / 0
// (#) unit tests: 0 / 6
// -----------------------------------------
//# notcurses_align
//+ notcurses_getc_blocking
//+ notcurses_getc_nblock
//+ notcurses_stddim_yx
//+ notcurses_stddim_yx_const
//+ notcurses_term_dim_yx
// # notcurses_align
// + notcurses_getc_blocking
// + notcurses_getc_nblock
// + notcurses_stddim_yx
// + notcurses_stddim_yx_const
// + notcurses_term_dim_yx
#[cfg(test)]
mod tests;
mod types;
pub use types::{
NcLogLevel, Notcurses, NotcursesOptions, NCLOGLEVEL_DEBUG, NCLOGLEVEL_ERROR, NCLOGLEVEL_FATAL,
NCLOGLEVEL_INFO, NCLOGLEVEL_PANIC, NCLOGLEVEL_SILENT, NCLOGLEVEL_TRACE, NCLOGLEVEL_VERBOSE,
NCLOGLEVEL_WARNING, NCOPTION_INHIBIT_SETLOCALE, NCOPTION_NO_ALTERNATE_SCREEN,
NCOPTION_NO_FONT_CHANGES, NCOPTION_NO_QUIT_SIGHANDLERS, NCOPTION_NO_WINCH_SIGHANDLER,
NCOPTION_SUPPRESS_BANNERS, NCOPTION_VERIFY_SIXEL,
};
mod wrapped;
pub use wrapped::*;
use core::ptr::null;
use crate::{
// NOTE: can't use libc::sigset_t with notcurses_getc(()
bindings::{sigemptyset, sigfillset, sigset_t},
ncplane_dim_yx,
notcurses_getc,
notcurses_stdplane,
notcurses_stdplane_const,
NcAlign,
NcInput,
NcPlane,
NcTime,
NCALIGN_CENTER,
NCALIGN_LEFT,
};
/// return the offset into 'availcols' at which 'cols' ought be output given the requirements of 'align'
#[inline]
pub fn notcurses_align(availcols: i32, align: NcAlign, cols: i32) -> i32 {
if align == NCALIGN_LEFT {
return 0;
}
if cols > availcols {
return 0;
}
if align == NCALIGN_CENTER {
return (availcols - cols) / 2;
}
availcols - cols // NCALIGN_RIGHT
}
/// 'input' may be NULL if the caller is uninterested in event details.
/// If no event is ready, returns 0.
// TODO: use pakr-signals
#[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 ts = NcTime {
tv_sec: 0,
tv_nsec: 0,
};
core::char::from_u32_unchecked(notcurses_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.
#[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);
core::char::from_u32_unchecked(notcurses_getc(nc, null(), &mut sigmask, input))
}
}
/// notcurses_stdplane(), plus free bonus dimensions written to non-NULL y/x!
#[inline]
pub fn notcurses_stddim_yx(nc: &mut Notcurses, y: &mut i32, x: &mut i32) -> NcPlane {
unsafe {
let s = notcurses_stdplane(nc);
ncplane_dim_yx(s, y, x);
*s
}
}
/// notcurses_stdplane_const(), plus free bonus dimensions written to non-NULL y/x!
#[inline]
pub fn notcurses_stddim_yx_const(nc: &Notcurses, y: &mut i32, x: &mut i32) -> NcPlane {
unsafe {
let s = notcurses_stdplane_const(nc);
ncplane_dim_yx(s, y, x);
*s
}
}
/// Return our current idea of the terminal dimensions in rows and cols.
#[inline]
pub fn notcurses_term_dim_yx(nc: &Notcurses, rows: &mut u32, cols: &mut u32) {
unsafe {
let mut irows = *rows as i32;
let mut icols = *cols as i32;
ncplane_dim_yx(notcurses_stdplane_const(nc), &mut irows, &mut icols);
}
}
mod test;
mod methods;
mod reimplemented;
pub use reimplemented::*;
/// The main struct of the (full mode) TUI library
///
/// Notcurses builds atop the terminfo abstraction layer to
/// provide reasonably portable vivid character displays.
///
pub type Notcurses = crate::bindings::bindgen::notcurses;
/// Options struct for [`Notcurses`]
pub type NotcursesOptions = crate::bindings::bindgen::notcurses_options;
/// Do not call setlocale()
///
/// notcurses_init() will call setlocale() to inspect the current locale. If
/// that locale is "C" or "POSIX", it will call setlocale(LC_ALL, "") to set
/// the locale according to the LANG environment variable. Ideally, this will
/// result in UTF8 being enabled, even if the client app didn't call
/// setlocale() itself. Unless you're certain that you're invoking setlocale()
/// prior to notcurses_init(), you should not set this bit. Even if you are
/// invoking setlocale(), this behavior shouldn't be an issue unless you're
/// doing something weird (setting a locale not based on LANG).
pub const NCOPTION_INHIBIT_SETLOCALE: u64 =
crate::bindings::bindgen::NCOPTION_INHIBIT_SETLOCALE as u64;
/// Do not enter alternate mode.
///
/// If smcup/rmcup capabilities are indicated, Notcurses defaults to making use
/// of the "alternate screen". This flag inhibits use of smcup/rmcup.
pub const NCOPTION_NO_ALTERNATE_SCREEN: u64 =
crate::bindings::bindgen::NCOPTION_NO_ALTERNATE_SCREEN as u64;
/// Do not modify the font.
///
/// Notcurses might attempt to change the font slightly, to support certain
/// glyphs (especially on the Linux console). If this is set, no such
/// modifications will be made. Note that font changes will not affect anything
/// but the virtual console/terminal in which Notcurses is running.
pub const NCOPTION_NO_FONT_CHANGES: u64 = crate::bindings::bindgen::NCOPTION_NO_FONT_CHANGES as u64;
/// Do not handle SIG{ING, SEGV, ABRT, QUIT}
///
/// We typically install a signal handler for SIG{INT, SEGV, ABRT, QUIT} that
/// restores the screen, and then calls the old signal handler. Set to inhibit
/// registration of these signal handlers.
pub const NCOPTION_NO_QUIT_SIGHANDLERS: u64 =
crate::bindings::bindgen::NCOPTION_NO_QUIT_SIGHANDLERS as u64;
/// Do not handle SIGWINCH
///
/// We typically install a signal handler for SIGWINCH that generates a resize
/// event in the notcurses_getc() queue. Set to inhibit this handler
pub const NCOPTION_NO_WINCH_SIGHANDLER: u64 =
crate::bindings::bindgen::NCOPTION_NO_WINCH_SIGHANDLER as u64;
/// Do not print banners
///
/// Notcurses typically prints version info in notcurses_init() and performance
/// info in notcurses_stop(). This inhibits that output.
pub const NCOPTION_SUPPRESS_BANNERS: u64 =
crate::bindings::bindgen::NCOPTION_SUPPRESS_BANNERS as u64;
/// Test for Sixel support
///
/// Checking for Sixel support requires writing an escape, and then reading an
/// inline reply from the terminal. Since this can interact poorly with actual
/// user input, it's not done unless Sixel will actually be used. Set this flag
/// to unconditionally test for Sixel support in notcurses_init().
pub const NCOPTION_VERIFY_SIXEL: u64 = crate::bindings::bindgen::NCOPTION_VERIFY_SIXEL as u64;
// NcLogLevel ------------------------------------------------------------------
/// Log level for [`NotcursesOptions`]
///
/// These log levels consciously map cleanly to those of libav; Notcurses itself
/// does not use this full granularity. The log level does not affect the opening
/// and closing banners, which can be disabled via the `NotcursesOptions`
/// `NCOPTION_SUPPRESS_BANNERS`.
/// Note that if stderr is connected to the same terminal on which we're
/// rendering, any kind of logging will disrupt the output.
pub type NcLogLevel = crate::bindings::bindgen::ncloglevel_e;
/// this is honestly a bit much
pub const NCLOGLEVEL_DEBUG: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_DEBUG;
/// we can't keep doin' this, but we can do other things
pub const NCLOGLEVEL_ERROR: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_ERROR;
/// we're hanging around, but we've had a horrible fault
pub const NCLOGLEVEL_FATAL: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_FATAL;
/// "detailed information
pub const NCLOGLEVEL_INFO: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_INFO;
/// print diagnostics immediately related to crashing
pub const NCLOGLEVEL_PANIC: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_PANIC;
/// default. print nothing once fullscreen service begins
pub const NCLOGLEVEL_SILENT: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_SILENT;
/// there's probably a better way to do what you want
pub const NCLOGLEVEL_TRACE: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_TRACE;
/// "detailed information
pub const NCLOGLEVEL_VERBOSE: NcLogLevel =
crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_VERBOSE;
/// you probably don't want what's happening to happen
pub const NCLOGLEVEL_WARNING: NcLogLevel =
crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_WARNING;

@ -0,0 +1,100 @@
//! `notcurses_*` reimplemented functions.
// pub use types::{
// NcLogLevel, Notcurses, NotcursesOptions, NCLOGLEVEL_DEBUG, NCLOGLEVEL_ERROR, NCLOGLEVEL_FATAL,
// NCLOGLEVEL_INFO, NCLOGLEVEL_PANIC, NCLOGLEVEL_SILENT, NCLOGLEVEL_TRACE, NCLOGLEVEL_VERBOSE,
// NCLOGLEVEL_WARNING, NCOPTION_INHIBIT_SETLOCALE, NCOPTION_NO_ALTERNATE_SCREEN,
// NCOPTION_NO_FONT_CHANGES, NCOPTION_NO_QUIT_SIGHANDLERS, NCOPTION_NO_WINCH_SIGHANDLER,
// NCOPTION_SUPPRESS_BANNERS, NCOPTION_VERIFY_SIXEL,
// };
//
use core::ptr::null;
use crate::{
// NOTE: can't use libc::sigset_t with notcurses_getc(()
bindings::{sigemptyset, sigfillset, sigset_t},
ncplane_dim_yx,
notcurses_getc,
notcurses_stdplane,
notcurses_stdplane_const,
NcAlign,
NcInput,
NcPlane,
NcTime,
Notcurses,
NCALIGN_CENTER,
NCALIGN_LEFT,
};
/// return the offset into 'availcols' at which 'cols' ought be output given the requirements of 'align'
#[inline]
pub fn notcurses_align(availcols: i32, align: NcAlign, cols: i32) -> i32 {
if align == NCALIGN_LEFT {
return 0;
}
if cols > availcols {
return 0;
}
if align == NCALIGN_CENTER {
return (availcols - cols) / 2;
}
availcols - cols // NCALIGN_RIGHT
}
/// 'input' may be NULL if the caller is uninterested in event details.
/// If no event is ready, returns 0.
// TODO: use pakr-signals
#[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 ts = NcTime {
tv_sec: 0,
tv_nsec: 0,
};
core::char::from_u32_unchecked(notcurses_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.
#[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);
core::char::from_u32_unchecked(notcurses_getc(nc, null(), &mut sigmask, input))
}
}
/// notcurses_stdplane(), plus free bonus dimensions written to non-NULL y/x!
#[inline]
pub fn notcurses_stddim_yx(nc: &mut Notcurses, y: &mut i32, x: &mut i32) -> NcPlane {
unsafe {
let s = notcurses_stdplane(nc);
ncplane_dim_yx(s, y, x);
*s
}
}
/// notcurses_stdplane_const(), plus free bonus dimensions written to non-NULL y/x!
#[inline]
pub fn notcurses_stddim_yx_const(nc: &Notcurses, y: &mut i32, x: &mut i32) -> NcPlane {
unsafe {
let s = notcurses_stdplane_const(nc);
ncplane_dim_yx(s, y, x);
*s
}
}
/// Return our current idea of the terminal dimensions in rows and cols.
#[inline]
pub fn notcurses_term_dim_yx(nc: &Notcurses, rows: &mut u32, cols: &mut u32) {
unsafe {
let mut irows = *rows as i32;
let mut icols = *cols as i32;
ncplane_dim_yx(notcurses_stdplane_const(nc), &mut irows, &mut icols);
}
}

@ -0,0 +1,4 @@
//! Test `Notcurses` methods and associated functions.
// use crate::Notcurses;
// use serial_test::serial;

@ -0,0 +1,7 @@
//! `Notcurses` tests.
#[cfg(test)]
mod methods;
#[cfg(test)]
mod reimplemented;

@ -1,4 +1,4 @@
//! [`Notcurses`] tests
//! Test `notcurses_*` reimplemented functions.
use serial_test::serial;
use std::io::Read;

@ -1,110 +0,0 @@
//! Types related with `Notcurses`
/// The main struct of the (full mode) TUI library
///
/// Notcurses builds atop the terminfo abstraction layer to
/// provide reasonably portable vivid character displays.
///
pub type Notcurses = crate::bindings::bindgen::notcurses;
/// Options struct for [`Notcurses`]
pub type NotcursesOptions = crate::bindings::bindgen::notcurses_options;
/// Do not call setlocale()
///
/// notcurses_init() will call setlocale() to inspect the current locale. If
/// that locale is "C" or "POSIX", it will call setlocale(LC_ALL, "") to set
/// the locale according to the LANG environment variable. Ideally, this will
/// result in UTF8 being enabled, even if the client app didn't call
/// setlocale() itself. Unless you're certain that you're invoking setlocale()
/// prior to notcurses_init(), you should not set this bit. Even if you are
/// invoking setlocale(), this behavior shouldn't be an issue unless you're
/// doing something weird (setting a locale not based on LANG).
pub const NCOPTION_INHIBIT_SETLOCALE: u64 =
crate::bindings::bindgen::NCOPTION_INHIBIT_SETLOCALE as u64;
/// Do not enter alternate mode.
///
/// If smcup/rmcup capabilities are indicated, Notcurses defaults to making use
/// of the "alternate screen". This flag inhibits use of smcup/rmcup.
pub const NCOPTION_NO_ALTERNATE_SCREEN: u64 =
crate::bindings::bindgen::NCOPTION_NO_ALTERNATE_SCREEN as u64;
/// Do not modify the font.
///
/// Notcurses might attempt to change the font slightly, to support certain
/// glyphs (especially on the Linux console). If this is set, no such
/// modifications will be made. Note that font changes will not affect anything
/// but the virtual console/terminal in which Notcurses is running.
pub const NCOPTION_NO_FONT_CHANGES: u64 = crate::bindings::bindgen::NCOPTION_NO_FONT_CHANGES as u64;
/// Do not handle SIG{ING, SEGV, ABRT, QUIT}
///
/// We typically install a signal handler for SIG{INT, SEGV, ABRT, QUIT} that
/// restores the screen, and then calls the old signal handler. Set to inhibit
/// registration of these signal handlers.
pub const NCOPTION_NO_QUIT_SIGHANDLERS: u64 =
crate::bindings::bindgen::NCOPTION_NO_QUIT_SIGHANDLERS as u64;
/// Do not handle SIGWINCH
///
/// We typically install a signal handler for SIGWINCH that generates a resize
/// event in the notcurses_getc() queue. Set to inhibit this handler
pub const NCOPTION_NO_WINCH_SIGHANDLER: u64 =
crate::bindings::bindgen::NCOPTION_NO_WINCH_SIGHANDLER as u64;
/// Do not print banners
///
/// Notcurses typically prints version info in notcurses_init() and performance
/// info in notcurses_stop(). This inhibits that output.
pub const NCOPTION_SUPPRESS_BANNERS: u64 =
crate::bindings::bindgen::NCOPTION_SUPPRESS_BANNERS as u64;
/// Test for Sixel support
///
/// Checking for Sixel support requires writing an escape, and then reading an
/// inline reply from the terminal. Since this can interact poorly with actual
/// user input, it's not done unless Sixel will actually be used. Set this flag
/// to unconditionally test for Sixel support in notcurses_init().
pub const NCOPTION_VERIFY_SIXEL: u64 = crate::bindings::bindgen::NCOPTION_VERIFY_SIXEL as u64;
// NcLogLevel ------------------------------------------------------------------
/// Log level for [`NotcursesOptions`]
///
/// These log levels consciously map cleanly to those of libav; Notcurses itself
/// does not use this full granularity. The log level does not affect the opening
/// and closing banners, which can be disabled via the `NotcursesOptions`
/// `NCOPTION_SUPPRESS_BANNERS`.
/// Note that if stderr is connected to the same terminal on which we're
/// rendering, any kind of logging will disrupt the output.
pub type NcLogLevel = crate::bindings::bindgen::ncloglevel_e;
/// this is honestly a bit much
pub const NCLOGLEVEL_DEBUG: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_DEBUG;
/// we can't keep doin' this, but we can do other things
pub const NCLOGLEVEL_ERROR: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_ERROR;
/// we're hanging around, but we've had a horrible fault
pub const NCLOGLEVEL_FATAL: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_FATAL;
/// "detailed information
pub const NCLOGLEVEL_INFO: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_INFO;
/// print diagnostics immediately related to crashing
pub const NCLOGLEVEL_PANIC: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_PANIC;
/// default. print nothing once fullscreen service begins
pub const NCLOGLEVEL_SILENT: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_SILENT;
/// there's probably a better way to do what you want
pub const NCLOGLEVEL_TRACE: NcLogLevel = crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_TRACE;
/// "detailed information
pub const NCLOGLEVEL_VERBOSE: NcLogLevel =
crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_VERBOSE;
/// you probably don't want what's happening to happen
pub const NCLOGLEVEL_WARNING: NcLogLevel =
crate::bindings::bindgen::ncloglevel_e_NCLOGLEVEL_WARNING;

@ -0,0 +1,42 @@
//! `NcPalette*`
// -----------------------------------------------------------------------------
// Now none of these functions can't fail and therefore don't return errors.
// -----------------------------------------------------------------------------
//
// functions already exported by bindgen : 3
// -----------------------------------------
// (#) unit tests: 0 / 3
// -----------------------------------------
// palette256_free
// palette256_new
// palette256_use
//
// functions manually reimplemented: 3
// -----------------------------------------
// (+) implement : 3 / 0
// (#) unit tests: 0 / 3
// -----------------------------------------
// + palette256_get_rgb
// + palette256_set
// + palette256_set_rgb
pub mod reimplemented;
pub use reimplemented::*;
/// NcPalette structure consisting of an array of 256 [`NcChannel`]s.
///
/// See also [NcPaletteIndex].
///
/// Some terminals only support 256 colors, but allow the full
/// palette to be specified with arbitrary RGB colors. In all cases, it's more
/// performant to use indexed colors, since it's much less data to write to the
/// terminal. If you can limit yourself to 256 colors, that's probably best.
///
/// `type in C: ncpalette256 (struct)`
///
pub type NcPalette = crate::bindings::bindgen::palette256;
/// 8-bit value used for indexing into a [`NcPalette`]
///
pub type NcPaletteIndex = u8;

@ -1,21 +1,4 @@
// -----------------------------------------------------------------------------
// Now none of these functions can't fail and therefore don't return errors.
// -----------------------------------------------------------------------------
//
// functions already exported by bindgen : 3
// -----------------------------------------
// palette256_free
// palette256_new
// palette256_use
//
// static inline functions total: 3
// ----------------------------------------- (done / remaining)
// (+) implement : 3 / 0
// (#) unit tests: 0 / 3
// -----------------------------------------
//+ palette256_get_rgb
//+ palette256_set
//+ palette256_set_rgb
//! `palette256_*` reimplemented functions.
use crate::{
channel_rgb8, channel_set, channel_set_rgb8, NcChannel, NcColor, NcPalette, NcPaletteIndex,
@ -51,15 +34,3 @@ pub fn palette256_get_rgb(
) -> NcChannel {
channel_rgb8(palette.chans[idx as usize], red, green, blue)
}
#[cfg(test)]
mod test {
// use super::nc;
// use serial_test::serial;
/*
#[test]
#[serial]
fn () {
}
*/
}

@ -7,34 +7,42 @@
//
// - NOTE: None of the functions can't fail anymore and don't have to return an error.
//
//
// functions already exported by bindgen : 0
// -----------------------------------------
//
// static inline functions total: 10
// ------------------------------------------ (done / remaining)
// functions manually reimplemented: 10
// ------------------------------------------
// (+) implement : 10 / 0
// (#) unit tests: 0 / 10
// ------------------------------------------
//+ ncpixel
//+ ncpixel_a
//+ ncpixel_b
//+ ncpixel_g
//+ ncpixel_r
//+ ncpixel_set_a
//+ ncpixel_set_b
//+ ncpixel_set_g
//+ ncpixel_set_r
//+ ncpixel_set_rgb
// + ncpixel
// + ncpixel_a
// + ncpixel_b
// + ncpixel_g
// + ncpixel_r
// + ncpixel_set_a
// + ncpixel_set_b
// + ncpixel_set_g
// + ncpixel_set_r
// + ncpixel_set_rgb
use crate::{NcColor, NcPixel};
use crate::NcColor;
// NcPixel Structure:
//
// 0xff000000 8 bit Alpha
// 0x00ff0000 8 bit Green
// 0x0000ff00 8 bit Blue
// 0x000000ff 8 bit Red
// NcPixel (RGBA)
/// 32 bits broken into RGB + 8-bit alpha
///
/// NcPixel has 8 bits of alpha, more or less linear, contributing
/// directly to the usual alpha blending equation.
///
/// We map the 8 bits of alpha to 2 bits of alpha via a level function:
/// https://nick-black.com/dankwiki/index.php?title=Notcurses#Transparency.2FContrasting
///
/// ## Diagram
///
/// ```txt
/// AAAAAAAA GGGGGGGG BBBBBBBB RRRRRRRR
/// ```
/// `type in C: ncpixel (uint32_t)`
///
// NOTE: the order of the colors is different than in NcChannel.
pub type NcPixel = u32;
/// Get an RGB pixel from RGB values
pub fn ncpixel(r: NcColor, g: NcColor, b: NcColor) -> NcPixel {
@ -87,15 +95,3 @@ pub fn ncpixel_set_rgb(pixel: &mut NcPixel, red: NcColor, green: NcColor, blue:
ncpixel_set_g(pixel, green);
ncpixel_set_b(pixel, blue);
}
#[cfg(test)]
mod test {
// use super::nc;
// use serial_test::serial;
/*
#[test]
#[serial]
fn () {
}
*/
}

@ -1,4 +1,4 @@
//! Handy [`NcPlane`] and [`NcPlaneOptions`] constructors
//! `NcPlane*` methods and associated functions.
use core::ptr::{null, null_mut};
@ -10,7 +10,8 @@ use crate::{
// for methods
use crate::{
NcCell, NcResult, ncplane_cursor_yx, ncplane_dim_yx, ncplane_erase, ncplane_putc, ncplane_putc_yx,
ncpile_bottom, ncpile_top, ncplane_cursor_yx, ncplane_dim_yx, ncplane_erase, ncplane_putc,
ncplane_putc_yx, NcCell, NcResult,
};
/// # `NcPlaneOptions` Constructors
@ -104,6 +105,11 @@ impl NcPlane {
/// # `NcPlane` Methods
impl NcPlane {
/// Returns the bottommost [NcPlane] of the pile that contains this [NnPlane].
pub fn bottom<'a>(&mut self) -> &'a mut NcPlane {
unsafe { &mut *ncpile_bottom(self) }
}
/// Returns the current position of the cursor within the [NcPlane].
///
/// Unlike [ncplane_cursor_yx] which uses `i32`, this uses [u32].
@ -112,7 +118,7 @@ impl NcPlane {
// FIXME: CHECK for NULL and return Some() or None.
pub fn cursor_yx(&self) -> (u32, u32) {
let (mut y, mut x) = (0, 0);
unsafe {ncplane_cursor_yx(self, &mut y, &mut x)};
unsafe { ncplane_cursor_yx(self, &mut y, &mut x) };
(y as u32, x as u32)
}
@ -131,7 +137,7 @@ impl NcPlane {
/// Unlike [ncplane_dim_yx] which uses `i32`, this uses [u32].
pub fn dim_yx(&self) -> (u32, u32) {
let (mut y, mut x) = (0, 0);
unsafe {ncplane_dim_yx(self, &mut y, &mut x)};
unsafe { ncplane_dim_yx(self, &mut y, &mut x) };
(y as u32, x as u32)
}
@ -158,9 +164,14 @@ impl NcPlane {
pub fn putc_yx(&mut self, y: i32, x: i32, cell: &NcCell) -> NcResult {
unsafe { ncplane_putc_yx(self, y, x, cell) }
}
///
pub fn putc(&mut self, cell: &NcCell) -> NcResult {
ncplane_putc(self, cell)
}
/// Returns the topmost [NcPlane] of the pile that contains this [NnPlane].
pub fn top<'a>(&mut self) -> &'a mut NcPlane {
unsafe { &mut *ncpile_top(self) }
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,644 @@
//! `ncplane_*` reimplemented functions.
use core::{ffi::c_void, ptr::null_mut};
use libc::free;
use std::ffi::CString;
use crate::{
bindgen::__va_list_tag, cell_load, cell_release, cells_double_box, cells_rounded_box,
channels_bchannel, channels_bg_alpha, channels_bg_default_p, channels_bg_rgb, channels_bg_rgb8,
channels_fchannel, channels_fg_alpha, channels_fg_default_p, channels_fg_rgb, channels_fg_rgb8,
ncplane_at_cursor, ncplane_at_yx, ncplane_box, ncplane_channels, ncplane_cursor_move_yx,
ncplane_cursor_yx, ncplane_dim_yx, ncplane_gradient, ncplane_hline_interp, ncplane_putc_yx,
ncplane_putegc_yx, ncplane_putnstr_yx, ncplane_putstr_yx, ncplane_resize, ncplane_styles,
ncplane_vline_interp, ncplane_vprintf_yx, notcurses_align, NcAlign, NcAlphaBits, NcCell,
NcChannel, NcChannelPair, NcColor, NcPlane, NcResult, NcStyleMask, NCRESULT_ERR, NCRESULT_OK,
};
/// Return the column at which 'cols' columns ought start in order to be aligned
/// according to 'align' within ncplane 'n'. Returns INT_MAX on invalid 'align'.
/// Undefined behavior on negative 'cols'.
//
// NOTE: [leave cols as i32](https://github.com/dankamongmen/notcurses/issues/904)
#[inline]
pub fn ncplane_align(plane: &NcPlane, align: NcAlign, cols: i32) -> i32 {
notcurses_align(ncplane_dim_x(plane), align, cols)
}
/// Retrieve the current contents of the cell under the cursor into 'cell'.
/// This cell is invalidated if the associated plane is destroyed.
#[inline]
pub fn ncplane_at_cursor_cell(plane: &mut NcPlane, cell: &mut NcCell) -> NcResult {
let mut egc = unsafe { ncplane_at_cursor(plane, &mut cell.stylemask, &mut cell.channels) };
if egc.is_null() {
return NCRESULT_ERR;
}
let result: NcResult = unsafe { cell_load(plane, cell, egc) };
if result != NCRESULT_OK {
unsafe {
free(&mut egc as *mut _ as *mut c_void);
}
}
result
}
/// Retrieve the current contents of the specified cell into 'cell'.
/// This cell is invalidated if the associated plane is destroyed.
#[inline]
pub fn ncplane_at_yx_cell(plane: &mut NcPlane, y: i32, x: i32, cell: &mut NcCell) -> NcResult {
let mut egc = unsafe { ncplane_at_yx(plane, y, x, &mut cell.stylemask, &mut cell.channels) };
if egc.is_null() {
return NCRESULT_ERR;
}
let channels = cell.channels; // need to preserve wide flag
let result: NcResult = unsafe { cell_load(plane, cell, egc) };
cell.channels = channels;
unsafe {
free(&mut egc as *mut _ as *mut c_void);
}
result
}
/// Draw a box with its upper-left corner at the current cursor position, having
/// dimensions 'ylen'x'xlen'. See ncplane_box() for more information. The
/// minimum box size is 2x2, and it cannot be drawn off-screen.
#[inline]
pub fn ncplane_box_sized(
plane: &mut NcPlane,
ul: &NcCell,
ur: &NcCell,
ll: &NcCell,
lr: &NcCell,
hline: &NcCell,
vline: &NcCell,
ylen: i32,
xlen: i32,
ctlword: u32,
) -> NcResult {
let (mut y, mut x) = (0, 0);
unsafe {
ncplane_cursor_yx(plane, &mut y, &mut x);
ncplane_box(
plane,
ul,
ur,
ll,
lr,
hline,
vline,
y + ylen - 1,
x + xlen - 1,
ctlword,
)
}
}
///
#[inline]
pub fn ncplane_dim_x(plane: &NcPlane) -> i32 {
unsafe {
let mut x = 0;
ncplane_dim_yx(plane, null_mut(), &mut x);
x
}
}
///
#[inline]
pub fn ncplane_dim_y(plane: &NcPlane) -> i32 {
unsafe {
let mut y = 0;
ncplane_dim_yx(plane, &mut y, null_mut());
y
}
}
///
#[inline]
pub fn ncplane_double_box(
plane: &mut NcPlane,
stylemask: NcStyleMask,
channels: NcChannelPair,
ystop: i32,
xstop: i32,
ctlword: u32,
) -> NcResult {
#[allow(unused_assignments)]
let mut ret = NCRESULT_OK;
let mut ul = NcCell::new();
let mut ur = NcCell::new();
let mut ll = NcCell::new();
let mut lr = NcCell::new();
let mut hl = NcCell::new();
let mut vl = NcCell::new();
unsafe {
ret = cells_double_box(
plane,
stylemask as u32,
channels,
&mut ul,
&mut ur,
&mut ll,
&mut lr,
&mut hl,
&mut vl,
);
if ret == NCRESULT_OK {
ret = ncplane_box(plane, &ul, &ur, &ll, &lr, &hl, &vl, ystop, xstop, ctlword);
}
cell_release(plane, &mut ul);
cell_release(plane, &mut ur);
cell_release(plane, &mut ll);
cell_release(plane, &mut lr);
cell_release(plane, &mut hl);
cell_release(plane, &mut vl);
}
ret
}
///
#[inline]
pub fn ncplane_double_box_sized(
plane: &mut NcPlane,
stylemask: NcStyleMask,
channels: NcChannelPair,
ylen: i32,
xlen: i32,
ctlword: u32,
) -> NcResult {
let (mut y, mut x) = (0, 0);
unsafe {
ncplane_cursor_yx(plane, &mut y, &mut x);
}
ncplane_double_box(
plane,
stylemask,
channels,
y + ylen - 1,
x + xlen - 1,
ctlword,
)
}
/// On error, return the negative number of cells drawn.
#[inline]
pub fn ncplane_hline(plane: &mut NcPlane, cell: &NcCell, len: i32) -> i32 {
unsafe { ncplane_hline_interp(plane, cell, len, cell.channels, cell.channels) }
}
///
#[inline]
pub fn ncplane_perimeter(
plane: &mut NcPlane,
ul: &NcCell,
ur: &NcCell,
ll: &NcCell,
lr: &NcCell,
hline: &NcCell,
vline: &NcCell,
ctlword: u32,
) -> NcResult {
unsafe {
ncplane_cursor_move_yx(plane, 0, 0);
let (mut dimy, mut dimx) = (0, 0);
ncplane_dim_yx(plane, &mut dimy, &mut dimx);
ncplane_box_sized(plane, ul, ur, ll, lr, hline, vline, dimy, dimx, ctlword)
}
}
///
#[inline]
pub fn ncplane_perimeter_double(
plane: &mut NcPlane,
stylemask: NcStyleMask,
channels: NcChannelPair,
ctlword: u32,
) -> NcResult {
if unsafe { ncplane_cursor_move_yx(plane, 0, 0) } != NCRESULT_OK {
return NCRESULT_ERR;
}
let (mut dimy, mut dimx) = (0, 0);
unsafe {
ncplane_dim_yx(plane, &mut dimy, &mut dimx);
}
let mut ul = NcCell::new();
let mut ur = NcCell::new();
let mut ll = NcCell::new();
let mut lr = NcCell::new();
let mut hl = NcCell::new();
let mut vl = NcCell::new();
if unsafe {
cells_double_box(
plane,
stylemask as u32,
channels,
&mut ul,
&mut ur,
&mut ll,
&mut lr,
&mut hl,
&mut vl,
)
} != NCRESULT_OK
{
return NCRESULT_ERR;
}
let ret = ncplane_box_sized(plane, &ul, &ur, &ll, &lr, &hl, &vl, dimy, dimx, ctlword);
unsafe {
cell_release(plane, &mut ul);
cell_release(plane, &mut ur);
cell_release(plane, &mut ll);
cell_release(plane, &mut lr);
cell_release(plane, &mut hl);
cell_release(plane, &mut vl);
}
ret
}
///
#[inline]
pub fn ncplane_perimeter_rounded(
plane: &mut NcPlane,
stylemask: NcStyleMask,
channels: NcChannelPair,
ctlword: u32,
) -> NcResult {
if unsafe { ncplane_cursor_move_yx(plane, 0, 0) } != NCRESULT_OK {
return NCRESULT_ERR;
}
let (mut dimy, mut dimx) = (0, 0);
unsafe {
ncplane_dim_yx(plane, &mut dimy, &mut dimx);
}
let mut ul = NcCell::new();
let mut ur = NcCell::new();
let mut ll = NcCell::new();
let mut lr = NcCell::new();
let mut hl = NcCell::new();
let mut vl = NcCell::new();
if unsafe {
cells_rounded_box(
plane,
stylemask as u32,
channels,
&mut ul,
&mut ur,
&mut ll,
&mut lr,
&mut hl,
&mut vl,
)
} != NCRESULT_OK
{
return NCRESULT_ERR;
}
let ret = ncplane_box_sized(plane, &ul, &ur, &ll, &lr, &hl, &vl, dimy, dimx, ctlword);
unsafe {
cell_release(plane, &mut ul);
cell_release(plane, &mut ur);
cell_release(plane, &mut ll);
cell_release(plane, &mut lr);
cell_release(plane, &mut hl);
cell_release(plane, &mut vl);
}
ret
}
/// Call ncplane_putc_yx() for the current cursor location.
#[inline]
pub fn ncplane_putc(plane: &mut NcPlane, cell: &NcCell) -> NcResult {
unsafe { ncplane_putc_yx(plane, -1, -1, cell) }
}
/// Call ncplane_putchar_yx() at the current cursor location.
#[inline]
pub fn ncplane_putchar(plane: &mut NcPlane, c: char) -> NcResult {
ncplane_putchar_yx(plane, -1, -1, c)
}
/// Replace the EGC underneath us, but retain the styling. The current styling
/// of the plane will not be changed.
///
/// Replace the cell at the specified coordinates with the provided 7-bit char
/// 'c'. Advance the cursor by 1. On success, returns 1. On failure, returns -1.
/// This works whether the underlying char is signed or unsigned.
#[inline]
// TODO: test char is < 8bit (currently 32bit)
pub fn ncplane_putchar_yx(plane: &mut NcPlane, y: i32, x: i32, c: char) -> NcResult {
unsafe {
let ce = NcCell::with_all(c, ncplane_styles(plane), ncplane_channels(plane));
ncplane_putc_yx(plane, y, x, &ce)
}
}
/// Call ncplane_putegc() at the current cursor location.
#[inline]
pub fn ncplane_putegc(plane: &mut NcPlane, gcluster: i8, sbytes: &mut i32) -> NcResult {
unsafe { ncplane_putegc_yx(plane, -1, -1, &gcluster, sbytes) }
}
///
#[inline]
pub fn ncplane_putstr(plane: &mut NcPlane, string: &str) -> NcResult {
unsafe {
ncplane_putstr_yx(
plane,
-1,
-1,
CString::new(string.as_bytes())
.expect("Bad string")
.as_ptr(),
)
}
}
///
#[inline]
pub fn ncplane_putnstr(plane: &mut NcPlane, size: u64, gclustarr: &[u8]) -> NcResult {
unsafe {
ncplane_putnstr_yx(
plane,
-1,
-1,
size,
CString::new(gclustarr).expect("Bad string").as_ptr(),
)
}
}
/// Resize the plane, retaining what data we can (everything, unless we're
/// shrinking in some dimension). Keep the origin where it is.
#[inline]
pub fn ncplane_resize_simple(plane: &mut NcPlane, ylen: i32, xlen: i32) -> NcResult {
let (mut oldy, mut oldx) = (0, 0);
unsafe {
ncplane_dim_yx(plane, &mut oldy, &mut oldx);
}
let keepleny = {
if oldy > ylen {
ylen
} else {
oldy
}
};
let keeplenx = {
if oldx > xlen {
xlen
} else {
oldx
}
};
unsafe { ncplane_resize(plane, 0, 0, keepleny, keeplenx, 0, 0, ylen, xlen) }
}
///
/// On error, return the negative number of cells drawn.
#[inline]
pub fn ncplane_vline(plane: &mut NcPlane, cell: &NcCell, len: i32) -> i32 {
unsafe { ncplane_vline_interp(plane, cell, len, cell.channels, cell.channels) }
}
///
#[inline]
pub fn ncplane_vprintf(plane: &mut NcPlane, format: &str, ap: &mut __va_list_tag) -> NcResult {
unsafe {
ncplane_vprintf_yx(
plane,
-1,
-1,
CString::new(format).expect("Bad string").as_ptr(),
ap,
)
}
}
/// Draw a gradient with its upper-left corner at the current cursor position,
/// having dimensions 'ylen'x'xlen'. See ncplane_gradient for more information.
/// static inline int
// XXX receive cells as u32? https://github.com/dankamongmen/notcurses/issues/920
#[inline]
pub fn ncplane_gradient_sized(
plane: &mut NcPlane,
egc: &[u8],
stylemask: NcStyleMask,
ul: u64,
ur: u64,
ll: u64,
lr: u64,
ylen: i32,
xlen: i32,
) -> NcResult {
if ylen < 1 || xlen < 1 {
return NCRESULT_ERR;
}
let (mut y, mut x) = (0, 0);
unsafe {
ncplane_cursor_yx(plane, &mut y, &mut x);
ncplane_gradient(
plane,
CString::new(egc).expect("Bad EGC").as_ptr(),
stylemask as u32,
ul,
ur,
ll,
lr,
y + ylen - 1,
x + xlen - 1,
)
}
}
/// Extract the 32-bit working foreground channel from an ncplane.
#[inline]
pub fn ncplane_fchannel(plane: &NcPlane) -> NcChannel {
channels_fchannel(unsafe { ncplane_channels(plane) })
}
/// Extract the 32-bit working background channel from an ncplane.
#[inline]
pub fn ncplane_bchannel(plane: &NcPlane) -> NcChannel {
channels_bchannel(unsafe { ncplane_channels(plane) })
}
/// Extract 24 bits of working foreground RGB from an ncplane, shifted to LSBs.
#[inline]
pub fn ncplane_fg_rgb(plane: &NcPlane) -> NcChannel {
channels_fg_rgb(unsafe { ncplane_channels(plane) })
}
/// Extract 24 bits of working background RGB from an ncplane, shifted to LSBs.
#[inline]
pub fn ncplane_bg_rgb(plane: &NcPlane) -> NcChannel {
channels_bg_rgb(unsafe { ncplane_channels(plane) })
}
/// Extract 2 bits of foreground alpha from 'struct ncplane', shifted to LSBs.
#[inline]
pub fn ncplane_fg_alpha(plane: &NcPlane) -> NcAlphaBits {
channels_fg_alpha(unsafe { ncplane_channels(plane) })
}
/// Extract 2 bits of background alpha from 'struct ncplane', shifted to LSBs.
#[inline]
pub fn ncplane_bg_alpha(plane: &NcPlane) -> NcAlphaBits {
channels_bg_alpha(unsafe { ncplane_channels(plane) })
}
/// Is the plane's foreground using the "default foreground color"?
#[inline]
pub fn ncplane_fg_default_p(plane: &NcPlane) -> bool {
channels_fg_default_p(unsafe { ncplane_channels(plane) })
}
/// Is the plane's background using the "default background color"?
#[inline]
pub fn ncplane_bg_default_p(plane: &NcPlane) -> bool {
channels_bg_default_p(unsafe { ncplane_channels(plane) })
}
/// Extract 24 bits of foreground RGB from a plane, split into components.
#[inline]
pub fn ncplane_fg_rgb8(
plane: &NcPlane,
red: &mut NcColor,
green: &mut NcColor,
blue: &mut NcColor,
) -> NcChannel {
channels_fg_rgb8(unsafe { ncplane_channels(plane) }, red, green, blue)
}
/// Extract 24 bits of background RGB from a plane, split into components.
#[inline]
pub fn ncplane_bg_rgb8(
plane: &NcPlane,
red: &mut NcColor,
green: &mut NcColor,
blue: &mut NcColor,
) -> NcChannel {
channels_bg_rgb8(unsafe { ncplane_channels(plane) }, red, green, blue)
}
///
#[inline]
pub fn ncplane_rounded_box(
plane: &mut NcPlane,
stylemask: NcStyleMask,
channels: NcChannelPair,
ystop: i32,
xstop: i32,
ctlword: u32,
) -> NcResult {
#[allow(unused_assignments)]
let mut ret = NCRESULT_OK;
let mut ul = NcCell::new();
let mut ur = NcCell::new();
let mut ll = NcCell::new();
let mut lr = NcCell::new();
let mut hl = NcCell::new();
let mut vl = NcCell::new();
unsafe {
ret = cells_rounded_box(
plane,
stylemask as u32,
channels,
&mut ul,
&mut ur,
&mut ll,
&mut lr,
&mut hl,
&mut vl,
);
if ret == NCRESULT_OK {
ret = ncplane_box(plane, &ul, &ur, &ll, &lr, &hl, &vl, ystop, xstop, ctlword);
}
cell_release(plane, &mut ul);
cell_release(plane, &mut ur);
cell_release(plane, &mut ll);
cell_release(plane, &mut lr);
cell_release(plane, &mut hl);
cell_release(plane, &mut vl);
}
ret
}
///
#[inline]
pub fn ncplane_rounded_box_sized(
plane: &mut NcPlane,
stylemask: NcStyleMask,
channels: NcChannelPair,
ylen: i32,
xlen: i32,
ctlword: u32,
) -> NcResult {
let (mut y, mut x) = (0, 0);
unsafe {
ncplane_cursor_yx(plane, &mut y, &mut x);
}
ncplane_rounded_box(
plane,
stylemask,
channels,
y + ylen - 1,
x + xlen - 1,
ctlword,
)
}
// static inline int
// ncplane_printf(struct ncplane* n, const char* format, ...)
// __attribute__ ((format (printf, 2, 3)));
// static inline int
// ncplane_printf(struct ncplane* n, const char* format, ...){
// va_list va;
// va_start(va, format);
// int ret = ncplane_vprintf(n, format, va);
// va_end(va);
// return ret;
// }
// static inline int
// ncplane_printf_yx(struct ncplane* n, int y, int x, const char* format, ...)
// __attribute__ ((format (printf, 4, 5)));
// static inline int
// ncplane_printf_yx(struct ncplane* n, int y, int x, const char* format, ...){
// va_list va;
// va_start(va, format);
// int ret = ncplane_vprintf_yx(n, y, x, format, va);
// va_end(va);
// return ret;
// }
// static inline int
// ncplane_printf_aligned(struct ncplane* n, int y, ncalign_e align,
// const char* format, ...)
// __attribute__ ((format (printf, 4, 5)));
// static inline int
// ncplane_printf_aligned(struct ncplane* n, int y, ncalign_e align, const char* format, ...){
// va_list va;
// va_start(va, format);
// int ret = ncplane_vprintf_aligned(n, y, align, format, va);
// va_end(va);
// return ret;
// }
// static inline int
// ncplane_printf_stained(struct ncplane* n, const char* format, ...)
// __attribute__ ((format (printf, 2, 3)));
// static inline int
// ncplane_printf_stained(struct ncplane* n, const char* format, ...){
// va_list va;
// va_start(va, format);
// int ret = ncplane_vprintf_stained(n, format, va);
// va_end(va);
// return ret;
// }

@ -0,0 +1,4 @@
//! Test `NcPlane` methods and associated functions.
// use crate::NcPlane;
// use serial_test::serial;

@ -0,0 +1,7 @@
//! `NcPlane` tests.
#[cfg(test)]
mod methods;
#[cfg(test)]
mod reimplemented;

@ -1,4 +1,4 @@
//! [`NcPlane`] tests
//! Test `ncplane_*` reimplemented functions.
use crate::{notcurses_stop, NcPlane, NcPlaneOptions, Notcurses, NCRESULT_OK};
use serial_test::serial;
@ -233,3 +233,25 @@ fn ncplane_erase() {
notcurses_stop(nc);
}
}
// #[test]
// #[serial]
// fn ncplane_at_cursor() {
// unsafe {
// let nc = Notcurses::new();
// let plane = NcPlane::new(nc, 0, 0, 20, 20);
//
// notcurses_stop(nc);
// }
// }
//
// #[test]
// #[serial]
// fn ncplane_at_cursor_cell() {
// unsafe {
// let nc = Notcurses::new();
// let plane = NcPlane::new(nc, 0, 0, 20, 20);
//
// notcurses_stop(nc);
// }
// }

@ -1,156 +0,0 @@
#[allow(unused_imports)] // for docblocks
use crate::NCCELL_ALPHA_BLEND;
// NcPlane
/// Fundamental drawing surface.
///
/// Unites a:
/// - CellMatrix
/// - EgcPool
///
/// `type in C: ncplane (struct)`
///
///
/// ## Piles
///
/// A single notcurses context is made up of one or more piles.
///
/// A pile is a set of one or more ncplanes, including the partial orderings
/// made up of their binding and z-axis pointers.
///
/// A pile has a top and bottom ncplane (this might be a single plane),
/// and one or more root planes (planes which are bound to themselves).
///
/// Multiple threads can concurrently operate on distinct piles, even changing
/// one while rendering another.
///
/// Each plane is part of one and only one pile. By default, a plane is part of
/// the same pile containing that plane to which it is bound.
///
/// If ncpile_create is used in the place of ncplane_create, the returned plane
/// becomes the root plane, top, and bottom of a new pile. As a root plane,
/// it is bound to itself.
///
/// A new pile can also be created by reparenting a plane to itself,
/// though if the plane is already a root plane, this is a no-op.
///
/// When a plane is moved to a different pile (whether new or preexisting),
/// any planes which were bound to it are rebound to its previous parent.
/// If the plane was a root plane of some pile, any bound planes become root
/// planes. The new plane is placed immediately atop its new parent on its new
/// pile's z-axis. When ncplane_reparent_family() is used, all planes bound to
/// the reparented plane are moved along with it. Their relative z-order is maintained.
///
pub type NcPlane = crate::bindings::bindgen::ncplane;
/// Options struct for [`NcPlane`]
pub type NcPlaneOptions = crate::bindings::bindgen::ncplane_options;
/// Horizontal alignment relative to the parent plane. Set alignment in 'x'.
pub const NCPLANE_OPTION_HORALIGNED: u64 =
crate::bindings::bindgen::NCPLANE_OPTION_HORALIGNED as u64;
/// I/O wrapper to dump file descriptor to [`NcPlane`]
///
/// `type in C: ncfdplane (struct)`
pub type NcFdPlane = crate::bindings::bindgen::ncfdplane;
/// Options struct for [`NcFdPlane`]
///
/// `type in C: ncplane_options (struct)`
pub type NcFdPlaneOptions = crate::bindings::bindgen::ncfdplane_options;
/// Alignment within a plane or terminal.
/// Left/right-justified, or centered.
pub type NcAlign = crate::bindings::bindgen::ncalign_e;
/// Left alignment within an [`NcPlane`] or terminal.
pub const NCALIGN_LEFT: NcAlign = crate::bindings::bindgen::ncalign_e_NCALIGN_LEFT;
/// Right alignment within an [`NcPlane`] or terminal.
pub const NCALIGN_RIGHT: NcAlign = crate::bindings::bindgen::ncalign_e_NCALIGN_RIGHT;
/// Center alignment within an [`NcPlane`] or terminal.
pub const NCALIGN_CENTER: NcAlign = crate::bindings::bindgen::ncalign_e_NCALIGN_CENTER;
/// Do not align an [`NcPlane`] or terminal.
pub const NCALIGN_UNALIGNED: NcAlign = crate::bindings::bindgen::ncalign_e_NCALIGN_UNALIGNED;
/// Blitter Mode (`NCBLIT_*`)
///
/// We never blit full blocks, but instead spaces (more efficient) with the
/// background set to the desired foreground.
///
/// ## Modes
///
/// - [`NCBLIT_1x1`]
/// - [`NCBLIT_2x1`]
/// - [`NCBLIT_2x2`]
/// - [`NCBLIT_3x2`]
/// - [`NCBLIT_4x1`]
/// - [`NCBLIT_8x1`]
/// - [`NCBLIT_BRAILLE`]
/// - [`NCBLIT_DEFAULT`]
/// - [`NCBLIT_SIXEL`]
///
pub type NcBlitter = crate::bindings::bindgen::ncblitter_e;
/// [`NcBlitter`] mode using: space, compatible with ASCII
pub const NCBLIT_1x1: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_1x1;
/// [`NcBlitter`] mode using: halves + 1x1 (space)
/// ▄▀
pub const NCBLIT_2x1: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_2x1;
/// [`NcBlitter`] mode using: quadrants + 2x1
/// ▗▐ ▖▀▟▌▙
pub const NCBLIT_2x2: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_2x2;
/// [`NcBlitter`] mode using: sextants
/// 🬀🬁🬂🬃🬄🬅🬆🬇🬈🬉🬊🬋🬌🬍🬎🬏🬐🬑🬒🬓🬔🬕🬖🬗🬘🬙🬚🬛🬜🬝🬞🬟🬠🬡🬢🬣🬤🬥🬦🬧🬨🬩🬪🬫🬬🬭🬮🬯🬰🬱🬲🬳🬴🬵🬶🬷🬸🬹🬺🬻
pub const NCBLIT_3x2: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_3x2;
/// [`NcBlitter`] mode using: four vertical levels
/// █▆▄▂
pub const NCBLIT_4x1: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_4x1;
/// [`NcBlitter`] mode using: eight vertical levels
/// █▇▆▅▄▃▂▁
pub const NCBLIT_8x1: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_8x1;
/// [`NcBlitter`] mode using: 4 rows, 2 cols (braille)
/// ⡀⡄⡆⡇⢀⣀⣄⣆⣇⢠⣠⣤⣦⣧⢰⣰⣴⣶⣷⢸⣸⣼⣾⣿
pub const NCBLIT_BRAILLE: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_BRAILLE;
/// [`NcBlitter`] mode where the blitter is automatically chosen
pub const NCBLIT_DEFAULT: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_DEFAULT;
/// [`NcBlitter`] mode (not yet implemented)
pub const NCBLIT_SIXEL: NcBlitter = crate::bindings::bindgen::ncblitter_e_NCBLIT_SIXEL;
/// How to scale an [`NcVisual`] during rendering
///
/// - NCSCALE_NONE will apply no scaling.
/// - NCSCALE_SCALE scales a visual to the plane's size,
/// maintaining aspect ratio.
/// - NCSCALE_STRETCH stretches and scales the image in an
/// attempt to fill the entirety of the plane.
///
pub type NcScale = crate::bindings::bindgen::ncscale_e;
/// Maintain original size
pub const NCSCALE_NONE: NcScale = crate::bindings::bindgen::ncscale_e_NCSCALE_NONE;
/// Maintain aspect ratio
pub const NCSCALE_SCALE: NcScale = crate::bindings::bindgen::ncscale_e_NCSCALE_SCALE;
/// Throw away aspect ratio
pub const NCSCALE_STRETCH: NcScale = crate::bindings::bindgen::ncscale_e_NCSCALE_STRETCH;
/// A visual bit of multimedia opened with LibAV|OIIO
pub type NcVisual = crate::bindings::bindgen::ncvisual;
/// Options struct for [`NcVisual`]
pub type NcVisualOptions = crate::bindings::bindgen::ncvisual_options;
/// Use [`NCCELL_ALPHA_BLEND`] with visual
pub const NCVISUAL_OPTION_BLEND: u32 = crate::bindings::bindgen::NCVISUAL_OPTION_BLEND;
/// Fail rather than degrade
pub const NCVISUAL_OPTION_NODEGRADE: u32 = crate::bindings::bindgen::NCVISUAL_OPTION_NODEGRADE;

@ -1,29 +1,33 @@
//! `ncvisual`
// functions already exported by bindgen : 17
// -----------------------------------------
// ncvisual_at_yx
// ncvisual_decode
// ncvisual_decode_loop
// ncvisual_destroy
// ncvisual_from_bgra
// ncvisual_from_file
// ncvisual_from_plane
// ncvisual_from_rgba
// ncvisual_geom
// ncvisual_polyfill_yx
// ncvisual_render
// ncvisual_resize
// ncvisual_rotate
// ncvisual_set_yx
// ncvisual_simple_streamer
// ncvisual_stream
// ncvisual_subtitle
// (#) test: 0 / 17
// -----------------------------------------
// ncvisual_at_yx
// ncvisual_decode
// ncvisual_decode_loop
// ncvisual_destroy
// ncvisual_from_bgra
// ncvisual_from_file
// ncvisual_from_plane
// ncvisual_from_rgba
// ncvisual_geom
// ncvisual_polyfill_yx
// ncvisual_render
// ncvisual_resize
// ncvisual_rotate
// ncvisual_set_yx
// ncvisual_simple_streamer
// ncvisual_stream
// ncvisual_subtitle
//
// static inline functions total: 1
// ------------------------------------------ (done / remaining)
// functions manually reimplemented: 1
// ------------------------------------------
// (+) done: 1 / 0
// (#) test: 0 / 1
// ------------------------------------------
// ncvisual_default_blitter
// + ncvisual_default_blitter
use crate::{NCBLIT_1x1, NCBLIT_2x1, NCBLIT_2x2, NcBlitter, NcScale, NCSCALE_STRETCH};
@ -41,15 +45,3 @@ pub fn ncvisual_default_blitter(utf8: bool, scale: NcScale) -> NcBlitter {
}
NCBLIT_1x1
}
#[cfg(test)]
mod test {
// use super::nc;
// use serial_test::serial;
/*
#[test]
#[serial]
fn () {
}
*/
}

@ -0,0 +1,85 @@
//! `NcMenu*` methods and associated functions.
use std::ffi::CString;
use crate::{
ncmenu_create, NcChannelPair, NcInput, NcMenu, NcMenuItem, NcMenuOptions, NcMenuSection,
NcPlane,
};
impl NcMenu {
/// `NcMenu` simple constructor
pub unsafe fn new<'a>(plane: &mut NcPlane) -> &'a mut Self {
Self::with_options(plane, &NcMenuOptions::new())
}
/// `NcMenu` constructor with options
pub unsafe fn with_options<'a>(plane: &mut NcPlane, options: &NcMenuOptions) -> &'a mut Self {
&mut *ncmenu_create(plane, options)
}
}
impl NcMenuOptions {
/// `NcMenuOptions` simple constructor
pub fn new() -> Self {
Self::with_options(&mut [], 0, 0, 0, 0)
}
/// `NcMenuOptions` width options
pub fn with_options(
sections: &mut [NcMenuSection],
count: u32,
headerc: NcChannelPair,
sectionc: NcChannelPair,
flags: u64,
) -> Self {
Self {
// array of 'sectioncount' `MenuSection`s
sections: sections as *mut _ as *mut NcMenuSection, /// XXX TEST
// must be positive TODO
sectioncount: count as i32,
// styling for header
headerchannels: headerc,
// styling for sections
sectionchannels: sectionc,
// flag word of NCMENU_OPTION_*
flags: flags,
}
}
}
impl NcMenuItem {
/// `NcMenuItem` simple constructor
pub fn new(mut desc: i8, shortcut: NcInput) -> Self {
Self {
// utf-8 menu item, NULL for horizontal separator
desc: &mut desc,
// ´NcInput´ shortcut, all should be distinct
shortcut,
}
}
}
impl NcMenuSection {
/// `NcMenuSection` simple constructor
pub fn new(name: &str, itemcount: i32, items: &mut [NcMenuItem], shortcut: NcInput) -> Self {
Self {
// utf-8 name string
name: CString::new(name).expect("Bad string").as_ptr() as *mut i8,
//
itemcount,
// array of itemcount `NcMenuItem`s
items: items as *mut _ as *mut NcMenuItem,
// shortcut, will be underlined if present in name
shortcut,
}
}
}

@ -2,101 +2,49 @@
// functions already exported by bindgen : 13
// ------------------------------------------
// ncmenu_create
// ncmenu_destroy
// ncmenu_item_set_status
// ncmenu_mouse_selected
// ncmenu_nextitem
// ncmenu_nextsection
// ncmenu_offer_input
// ncmenu_plane
// ncmenu_previtem
// ncmenu_prevsection
// ncmenu_rollup
// ncmenu_selected
// ncmenu_unroll
mod types;
pub use types::{NcMenu, NcMenuItem, NcMenuOptions, NcMenuSection};
pub use types::{NCMENU_OPTION_BOTTOM, NCMENU_OPTION_HIDING};
use std::ffi::CString;
use crate::{ncmenu_create, NcChannelPair, NcInput, NcPlane};
impl NcMenu {
/// `NcMenu` simple constructor
pub unsafe fn new<'a>(plane: &mut NcPlane) -> &'a mut Self {
Self::with_options(plane, &NcMenuOptions::new())
}
/// `NcMenu` constructor with options
pub unsafe fn with_options<'a>(plane: &mut NcPlane, options: &NcMenuOptions) -> &'a mut Self {
&mut *ncmenu_create(plane, options)
}
}
impl NcMenuOptions {
/// `NcMenuOptions` simple constructor
pub fn new() -> Self {
Self::with_options(&mut [], 0, 0, 0, 0)
}
/// `NcMenuOptions` width options
pub fn with_options(
sections: &mut [NcMenuSection],
count: u32,
headerc: NcChannelPair,
sectionc: NcChannelPair,
flags: u64,
) -> Self {
Self {
// array of 'sectioncount' `MenuSection`s
sections: sections as *mut _ as *mut NcMenuSection, /// XXX TEST
// must be positive TODO
sectioncount: count as i32,
// styling for header
headerchannels: headerc,
// styling for sections
sectionchannels: sectionc,
// flag word of NCMENU_OPTION_*
flags: flags,
}
}
}
impl NcMenuItem {
/// `NcMenuItem` simple constructor
pub fn new(mut desc: i8, shortcut: NcInput) -> Self {
Self {
// utf-8 menu item, NULL for horizontal separator
desc: &mut desc,
// ´NcInput´ shortcut, all should be distinct
shortcut,
}
}
}
impl NcMenuSection {
/// `NcMenuSection` simple constructor
pub fn new(name: &str, itemcount: i32, items: &mut [NcMenuItem], shortcut: NcInput) -> Self {
Self {
// utf-8 name string
name: CString::new(name).expect("Bad string").as_ptr() as *mut i8,
//
itemcount,
// array of itemcount `NcMenuItem`s
items: items as *mut _ as *mut NcMenuItem,
// shortcut, will be underlined if present in name
shortcut,
}
}
}
// ncmenu_create
// ncmenu_destroy
// ncmenu_item_set_status
// ncmenu_mouse_selected
// ncmenu_nextitem
// ncmenu_nextsection
// ncmenu_offer_input
// ncmenu_plane
// ncmenu_previtem
// ncmenu_prevsection
// ncmenu_rollup
// ncmenu_selected
// ncmenu_unroll
mod methods;
/// menus on the top or bottom rows
///
/// A notcurses instance supports menu bars on the top or bottom row of the true
/// screen.
///
/// A menu is composed of sections, which are in turn composed of items.
/// Either no sections are visible, and the menu is rolled up, or exactly one
/// section is unrolled.
///
/// `ncmenu_rollup` places an `NcMenu` in the rolled up state.
/// `ncmenu_unroll` rolls up any unrolled section and unrolls the specified one.
/// `ncmenu_destroy` removes a menu bar, and frees all associated resources.
///
/// `type in C: ncmenu (struct)`
pub type NcMenu = crate::bindings::bindgen::ncmenu;
/// Options struct for [`NcMenu`]
pub type NcMenuOptions = crate::bindings::bindgen::ncmenu_options;
/// Item for [`NcMenu`]
pub type NcMenuItem = crate::bindings::bindgen::ncmenu_item;
/// Section for [`NcMenu`]
pub type NcMenuSection = crate::bindings::bindgen::ncmenu_section;
/// Bottom row (as opposed to top row)
pub const NCMENU_OPTION_BOTTOM: u32 = crate::bindings::bindgen::NCMENU_OPTION_BOTTOM;
/// Hide the menu when not unrolled
pub const NCMENU_OPTION_HIDING: u32 = crate::bindings::bindgen::NCMENU_OPTION_HIDING;

@ -1,32 +0,0 @@
//! `NcMenu` widget types
/// menus on the top or bottom rows
///
/// A notcurses instance supports menu bars on the top or bottom row of the true
/// screen.
///
/// A menu is composed of sections, which are in turn composed of items.
/// Either no sections are visible, and the menu is rolled up, or exactly one
/// section is unrolled.
///
/// `ncmenu_rollup` places an `NcMenu` in the rolled up state.
/// `ncmenu_unroll` rolls up any unrolled section and unrolls the specified one.
/// `ncmenu_destroy` removes a menu bar, and frees all associated resources.
///
/// `type in C: ncmenu (struct)`
pub type NcMenu = crate::bindings::bindgen::ncmenu;
/// Options struct for [`NcMenu`]
pub type NcMenuOptions = crate::bindings::bindgen::ncmenu_options;
/// Item for [`NcMenu`]
pub type NcMenuItem = crate::bindings::bindgen::ncmenu_item;
/// Section for [`NcMenu`]
pub type NcMenuSection = crate::bindings::bindgen::ncmenu_section;
/// Bottom row (as opposed to top row)
pub const NCMENU_OPTION_BOTTOM: u32 = crate::bindings::bindgen::NCMENU_OPTION_BOTTOM;
/// Hide the menu when not unrolled
pub const NCMENU_OPTION_HIDING: u32 = crate::bindings::bindgen::NCMENU_OPTION_HIDING;

@ -1,5 +1,4 @@
//! Widgets
//!
mod menu;
mod multiselector;

@ -1,4 +1,10 @@
//! `NcSelector` widget
//! `NcMultiSelector` widget.
mod types;
pub use types::{NcMultiSelector, NcMultiSelectorItem, NcMultiSelectorOptions};
/// high-level widget for selecting items from a set
pub type NcMultiSelector = crate::bindings::bindgen::ncmultiselector;
/// an item for [`NcMultiSelector`]
pub type NcMultiSelectorItem = crate::bindings::bindgen::ncmselector_item;
/// Options structure for [`NcMultiSelector`]
pub type NcMultiSelectorOptions = crate::bindings::bindgen::ncmultiselector_options;

@ -1,10 +0,0 @@
//! `NcMultiSelector` widget types
/// high-level widget for selecting items from a set
pub type NcMultiSelector = crate::bindings::bindgen::ncmultiselector;
/// an item for [`NcMultiSelector`]
pub type NcMultiSelectorItem = crate::bindings::bindgen::ncmselector_item;
/// Options structure for [`NcMultiSelector`]
pub type NcMultiSelectorOptions = crate::bindings::bindgen::ncmultiselector_options;

@ -1,8 +1,27 @@
//! `NcPlot[F|U]64` widget
mod types;
pub use types::{NcPlotF64, NcPlotOptions, NcPlotU64};
pub use types::{
NCPLOT_OPTION_DETECTMAXONLY, NCPLOT_OPTION_EXPONENTIALD, NCPLOT_OPTION_LABELTICKSD,
NCPLOT_OPTION_NODEGRADE, NCPLOT_OPTION_VERTICALI,
};
//! `NcPlot[F|U]64` widget.
/// A histogram, bound to an [`NcPlane`][crate::NcPlane]
/// (uses non-negative `f64`s)
pub type NcPlotF64 = crate::bindings::bindgen::ncdplot;
/// A histogram, bound to an [`NcPlane`][crate::NcPlane] (uses `u64`s)
pub type NcPlotU64 = crate::bindings::bindgen::ncuplot;
/// Options struct for
/// [`NcPlotF64`] or [`NcPlotU64`]
pub type NcPlotOptions = crate::bindings::bindgen::ncplot_options;
/// Use domain detection only for max
pub const NCPLOT_OPTION_DETECTMAXONLY: u32 = crate::bindings::bindgen::NCPLOT_OPTION_DETECTMAXONLY;
/// Exponential dependent axis
pub const NCPLOT_OPTION_EXPONENTIALD: u32 = crate::bindings::bindgen::NCPLOT_OPTION_EXPONENTIALD;
/// Show labels for dependent axis
pub const NCPLOT_OPTION_LABELTICKSD: u32 = crate::bindings::bindgen::NCPLOT_OPTION_LABELTICKSD;
/// Use domain detection only for max
pub const NCPLOT_OPTION_NODEGRADE: u32 = crate::bindings::bindgen::NCPLOT_OPTION_NODEGRADE;
/// Independent axis is vertical
pub const NCPLOT_OPTION_VERTICALI: u32 = crate::bindings::bindgen::NCPLOT_OPTION_VERTICALI;

@ -1,27 +0,0 @@
//! `NcPlot[F|U]64` widget types
/// A histogram, bound to an [`NcPlane`][crate::NcPlane]
/// (uses non-negative `f64`s)
pub type NcPlotF64 = crate::bindings::bindgen::ncdplot;
/// A histogram, bound to an [`NcPlane`][crate::NcPlane] (uses `u64`s)
pub type NcPlotU64 = crate::bindings::bindgen::ncuplot;
/// Options struct for
/// [`NcPlotF64`] or [`NcPlotU64`]
pub type NcPlotOptions = crate::bindings::bindgen::ncplot_options;
/// Use domain detection only for max
pub const NCPLOT_OPTION_DETECTMAXONLY: u32 = crate::bindings::bindgen::NCPLOT_OPTION_DETECTMAXONLY;
/// Exponential dependent axis
pub const NCPLOT_OPTION_EXPONENTIALD: u32 = crate::bindings::bindgen::NCPLOT_OPTION_EXPONENTIALD;
/// Show labels for dependent axis
pub const NCPLOT_OPTION_LABELTICKSD: u32 = crate::bindings::bindgen::NCPLOT_OPTION_LABELTICKSD;
/// Use domain detection only for max
pub const NCPLOT_OPTION_NODEGRADE: u32 = crate::bindings::bindgen::NCPLOT_OPTION_NODEGRADE;
/// Independent axis is vertical
pub const NCPLOT_OPTION_VERTICALI: u32 = crate::bindings::bindgen::NCPLOT_OPTION_VERTICALI;

@ -0,0 +1,29 @@
//! `NcReader*` methods and associated functions.
use crate::{ncreader_create, NcPlane, NcReader, NcReaderOptions};
impl NcReader {
/// `NcReader` simple constructor
pub unsafe fn new<'a>(plane: &mut NcPlane) -> &'a mut Self {
Self::with_options(plane, &NcReaderOptions::new())
}
/// `NcReader` constructor with options
pub unsafe fn with_options<'a>(plane: &mut NcPlane, options: &NcReaderOptions) -> &'a mut Self {
&mut *ncreader_create(plane, options)
}
}
impl NcReaderOptions {
/// `NcReaderOptions` simple constructor
pub fn new() -> Self {
Self {
// channels used for input
tchannels: 0,
// attributes used for input
tattrword: 0,
// bitfield of NCREADER_OPTION_*
flags: 0,
}
}
}

@ -1,53 +1,48 @@
//! `NcReader` widget
//! `NcReader` widget.
// functions already exported by bindgen : 11
// ------------------------------------------
// ncreader_clear
// ncreader_contents
// ncreader_create
// ncreader_destroy
// ncreader_move_down
// ncreader_move_left
// ncreader_move_right
// ncreader_move_up
// ncreader_offer_input
// ncreader_plane
// ncreader_write_egc
//
// static inline functions total: 0
// -------------------------------------------
mod types;
pub use types::{NcReader, NcReaderOptions};
pub use types::{
NCREADER_OPTION_CURSOR, NCREADER_OPTION_HORSCROLL, NCREADER_OPTION_NOCMDKEYS,
NCREADER_OPTION_VERSCROLL,
};
use crate::{ncreader_create, NcPlane};
impl NcReader {
/// `NcReader` simple constructor
pub unsafe fn new<'a>(plane: &mut NcPlane) -> &'a mut Self {
Self::with_options(plane, &NcReaderOptions::new())
}
/// `NcReader` constructor with options
pub unsafe fn with_options<'a>(plane: &mut NcPlane, options: &NcReaderOptions) -> &'a mut Self {
&mut *ncreader_create(plane, options)
}
}
impl NcReaderOptions {
/// `NcReaderOptions` simple constructor
pub fn new() -> Self {
Self {
// channels used for input
tchannels: 0,
// attributes used for input
tattrword: 0,
// bitfield of NCREADER_OPTION_*
flags: 0,
}
}
}
// ncreader_clear
// ncreader_contents
// ncreader_create
// ncreader_destroy
// ncreader_move_down
// ncreader_move_left
// ncreader_move_right
// ncreader_move_up
// ncreader_offer_input
// ncreader_plane
// ncreader_write_egc
mod methods;
/// Provides a freeform input in a (possibly multiline) region
///
/// Supports optional readline keybindings (opt out using
/// NCREADER_OPTION_NOCMDKEYS flag)
///
/// Takes ownership of its [`NcPlane`], destroying it on any
/// error (`ncreader_destroy`() otherwise destroys the ncplane).
///
/// `type in C: ncreader (struct)`
///
pub type NcReader = crate::bindings::bindgen::ncreader;
/// Options struct for [`NcReader`]
///
/// `type in C: ncreader_options (struct)`
///
pub type NcReaderOptions = crate::bindings::bindgen::ncreader_options;
/// Make the terminal cursor visible across the lifetime of the ncreader, and
/// have the ncreader manage the cursor's placement.
pub const NCREADER_OPTION_CURSOR: u32 = crate::bindings::bindgen::NCREADER_OPTION_CURSOR;
/// Enable horizontal scrolling. Virtual lines can then grow arbitrarily long.
pub const NCREADER_OPTION_HORSCROLL: u32 = crate::bindings::bindgen::NCREADER_OPTION_HORSCROLL;
/// Disable all editing shortcuts. By default, emacs-style keys are available.
pub const NCREADER_OPTION_NOCMDKEYS: u32 = crate::bindings::bindgen::NCREADER_OPTION_NOCMDKEYS;
/// Enable vertical scrolling. You can then use arbitrarily many virtual lines.
pub const NCREADER_OPTION_VERSCROLL: u32 = crate::bindings::bindgen::NCREADER_OPTION_VERSCROLL;

@ -1,32 +0,0 @@
//! ´NcReader´ widget types
/// Provides a freeform input in a (possibly multiline) region
///
/// Supports optional readline keybindings (opt out using
/// NCREADER_OPTION_NOCMDKEYS flag)
///
/// Takes ownership of its [`NcPlane`], destroying it on any
/// error (`ncreader_destroy`() otherwise destroys the ncplane).
///
/// `type in C: ncreader (struct)`
///
pub type NcReader = crate::bindings::bindgen::ncreader;
/// Options struct for [`NcReader`]
///
/// `type in C: ncreader_options (struct)`
///
pub type NcReaderOptions = crate::bindings::bindgen::ncreader_options;
/// Make the terminal cursor visible across the lifetime of the ncreader, and
/// have the ncreader manage the cursor's placement.
pub const NCREADER_OPTION_CURSOR: u32 = crate::bindings::bindgen::NCREADER_OPTION_CURSOR;
/// Enable horizontal scrolling. Virtual lines can then grow arbitrarily long.
pub const NCREADER_OPTION_HORSCROLL: u32 = crate::bindings::bindgen::NCREADER_OPTION_HORSCROLL;
/// Disable all editing shortcuts. By default, emacs-style keys are available.
pub const NCREADER_OPTION_NOCMDKEYS: u32 = crate::bindings::bindgen::NCREADER_OPTION_NOCMDKEYS;
/// Enable vertical scrolling. You can then use arbitrarily many virtual lines.
pub const NCREADER_OPTION_VERSCROLL: u32 = crate::bindings::bindgen::NCREADER_OPTION_VERSCROLL;

@ -1,6 +1,32 @@
//! `NcReel` widget
//!
//! `NcReel` widget.
mod types;
pub use types::{NcReel, NcReelOptions, NcTablet};
pub use types::{NCREEL_OPTION_CIRCULAR, NCREEL_OPTION_INFINITESCROLL};
/// A wheel with `NcTablet`s on the outside
///
/// An `NcReel` is projected onto the 2d rendering area, showing some portion of
/// the `NcReel`, and zero or more `NcTablet`s.
///
/// An `NcReel` is a `Notcurses` region devoted to displaying zero or more
/// line-oriented, contained `NcTablet`s between which the user may navigate.
///
/// If at least one `NcTablet`s exists, there is a "focused tablet".
/// As much of the focused tablet as is possible is always displayed.
///
/// If there is space left over, other tablets are included in the display.
/// Tablets can come and go at any time, and can grow or shrink at any time.
pub type NcReel = crate::bindings::bindgen::ncreel;
/// Options struct for [`NcReel`]
pub type NcReelOptions = crate::bindings::bindgen::ncreel_options;
/// Visual tablet for [`NcReel`]
pub type NcTablet = crate::bindings::bindgen::nctablet;
/// is navigation circular (does moving down from the last tablet move to the
/// first, and vice versa)? only meaningful when infinitescroll is true. if
/// infinitescroll is false, this must be false.
pub const NCREEL_OPTION_CIRCULAR: u32 = crate::bindings::bindgen::NCREEL_OPTION_CIRCULAR;
/// is scrolling infinite (can one move down or up forever, or is an end
/// reached?). if true, 'circular' specifies how to handle the special case of
/// an incompletely-filled reel.
pub const NCREEL_OPTION_INFINITESCROLL: u32 =
crate::bindings::bindgen::NCREEL_OPTION_INFINITESCROLL;

@ -1,30 +0,0 @@
/// A wheel with `NcTablet`s on the outside
///
/// An `NcReel` is projected onto the 2d rendering area, showing some portion of
/// the `NcReel`, and zero or more `NcTablet`s.
///
/// An `NcReel` is a `Notcurses` region devoted to displaying zero or more
/// line-oriented, contained `NcTablet`s between which the user may navigate.
///
/// If at least one `NcTablet`s exists, there is a "focused tablet".
/// As much of the focused tablet as is possible is always displayed.
///
/// If there is space left over, other tablets are included in the display.
/// Tablets can come and go at any time, and can grow or shrink at any time.
pub type NcReel = crate::bindings::bindgen::ncreel;
/// Options struct for [`NcReel`]
pub type NcReelOptions = crate::bindings::bindgen::ncreel_options;
/// Visual tablet for [`NcReel`]
pub type NcTablet = crate::bindings::bindgen::nctablet;
/// is navigation circular (does moving down from the last tablet move to the
/// first, and vice versa)? only meaningful when infinitescroll is true. if
/// infinitescroll is false, this must be false.
pub const NCREEL_OPTION_CIRCULAR: u32 = crate::bindings::bindgen::NCREEL_OPTION_CIRCULAR;
/// is scrolling infinite (can one move down or up forever, or is an end
/// reached?). if true, 'circular' specifies how to handle the special case of
/// an incompletely-filled reel.
pub const NCREEL_OPTION_INFINITESCROLL: u32 =
crate::bindings::bindgen::NCREEL_OPTION_INFINITESCROLL;

@ -1,5 +1,10 @@
//! `NcSelector` widget
//!
//! `NcSelector` widget.
mod types;
pub use types::{NcSelector, NcSelectorItem, NcSelectorOptions};
/// high-level widget for selecting one item from a set
pub type NcSelector = crate::bindings::bindgen::ncselector;
/// an item for [`NcSelector`]
pub type NcSelectorItem = crate::bindings::bindgen::ncselector_item;
/// Options structur for [`NcSelector`]
pub type NcSelectorOptions = crate::bindings::bindgen::ncselector_options;

@ -1,10 +0,0 @@
//! `NcSelector` types
/// high-level widget for selecting one item from a set
pub type NcSelector = crate::bindings::bindgen::ncselector;
/// an item for [`NcSelector`]
pub type NcSelectorItem = crate::bindings::bindgen::ncselector_item;
/// Options structur for [`NcSelector`]
pub type NcSelectorOptions = crate::bindings::bindgen::ncselector_options;
Loading…
Cancel
Save