Merge branch 'master' of github.com:dankamongmen/notcurses

This commit is contained in:
nick black 2020-11-17 01:28:27 -05:00
commit fd52a5c49e
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
12 changed files with 761 additions and 202 deletions

View File

@ -21,8 +21,6 @@ keywords = ["tui", "cli", "terminal", "ncurses", "ffi"]
[dependencies]
libc = {version = "0.2.80", default-features = false}
cty = "0.2.1"
cstr_core = "0.2.2"
libc-print = "0.1.14"
[build-dependencies]
bindgen = ">= 0.55.1"

View File

@ -1,42 +1,60 @@
//! Example 'direct-cursor'
//!
//! Explore cursor functions in direct mode
//!
use std::thread::sleep;
use std::time::Duration;
use std::ffi::CString;
use cstr_core::CString;
/// utility macro: sleep for $s seconds
macro_rules! sleep {
($s:expr) => {
sleep(Duration::new($s, 0));
};
}
use libnotcurses_sys as nc;
/// utility macro: convert the String $s to *mut CString
macro_rules! cstring {
($s:expr) => {
CString::new($s).unwrap().as_ptr();
}
}
use libnotcurses_sys::*;
fn main() {
unsafe {
let ncd = nc::NcDirect::new();
let ncd = NcDirect::new();
let cols = nc::ncdirect_dim_x(ncd);
let rows = nc::ncdirect_dim_y(ncd);
let cols = ncdirect_dim_x(ncd);
let rows = ncdirect_dim_y(ncd);
println!("terminal size (rows, cols): {}, {}", rows, cols);
// show current coordinates
let (mut cy, mut cx) = (0,0);
nc::ncdirect_cursor_yx(ncd, &mut cy, &mut cx);
nc::ncdirect_putstr(ncd, 0, CString::new(format!("({},{})\n", cy, cx)).unwrap().as_ptr());
let (mut cy, mut cx) = (0, 0);
ncdirect_cursor_yx(ncd, &mut cy, &mut cx);
ncdirect_putstr(ncd, 0, cstring![format!(" ({},{})\n", cy, cx)],
);
// Write HELLO WORLD in steps
sleep![1];
sleep(Duration::new(1, 0));
ncdirect_putstr(ncd, 0, cstring!["HELLO"]);
ncdirect_flush(ncd);
nc::ncdirect_putstr(ncd, 0, CString::new("HELLO").unwrap().as_ptr());
nc::ncdirect_flush(ncd);
sleep![1];
sleep(Duration::new(1, 0));
ncdirect_putstr(ncd, 0, cstring!["HELLO"]);
ncdirect_flush(ncd);
nc::ncdirect_putstr(ncd, 0, CString::new(" WORLD").unwrap().as_ptr());
nc::ncdirect_flush(ncd);
sleep(Duration::new(1, 0));
sleep![2];
// show current coordinates
nc::ncdirect_cursor_yx(ncd, &mut cy, &mut cx);
nc::ncdirect_putstr(ncd, 0, CString::new(format!(" ({},{})\n", cy, cx)).unwrap().as_ptr());
ncdirect_cursor_yx(ncd, &mut cy, &mut cx);
ncdirect_putstr( ncd, 0, cstring![format!(" ({},{})\n", cy, cx)],
);
sleep(Duration::new(1, 0));
nc::ncdirect_stop(ncd);
sleep![1];
ncdirect_stop(ncd);
}
}

View File

@ -1,31 +1,36 @@
use cstr_core::CString;
//! Example 'direct-image'
//!
//! Explore image rendering in direct mode
use libnotcurses_sys as nc;
use std::ffi::CString;
// This time we are gonna use the notcurses library through the `sys` namespace
use libnotcurses_sys as sys;
fn main() {
unsafe {
let ncd = nc::NcDirect::new();
let ncd = sys::NcDirect::new();
render_image(&mut *ncd, nc::NCBLIT_1x1);
render_image(&mut *ncd, nc::NCBLIT_2x1);
render_image(&mut *ncd, nc::NCBLIT_BRAILLE);
render_image(&mut *ncd, sys::NCBLIT_1x1);
render_image(&mut *ncd, sys::NCBLIT_2x1);
render_image(&mut *ncd, sys::NCBLIT_BRAILLE);
nc::ncdirect_stop(ncd);
sys::ncdirect_stop(ncd);
}
}
fn render_image(ncd: &mut nc::NcDirect, blit: nc::NcBlitter) {
fn render_image(ncd: &mut sys::NcDirect, blit: sys::NcBlitter) {
unsafe {
if nc::ncdirect_render_image(
if sys::ncdirect_render_image(
ncd,
CString::new("image-16x16.png").unwrap().as_ptr(),
nc::NCALIGN_CENTER,
sys::NCALIGN_CENTER,
blit,
nc::NCSCALE_NONE,
sys::NCSCALE_NONE,
) != 0
{
panic!("ERR: ncdirect_render_image. \
Make sure you are running this example from the examples folder");
panic!("ERR: ncdirect_render_image. Make sure \
you are running this example from the examples folder");
}
}
}

View File

@ -1,18 +1,31 @@
//use cstr_core::CString;
use std::thread::sleep;
use std::time::Duration;
use std::ffi::CString;
use libnotcurses_sys as nc;
/// utility macro: sleep for $s seconds
macro_rules! sleep {
($s:expr) => {
sleep(Duration::new($s, 0));
};
}
fn main() {
unsafe {
// let options = nc::NotcursesOptions::new();
// let app = nc::Notcurses::with_options(&options);
let app = nc::Notcurses::new();
nc::notcurses_stop(app);
/// utility macro: convert the String $s to *mut CString
macro_rules! cstring {
($s:expr) => {
CString::new($s).unwrap().as_ptr();
}
}
use libnotcurses_sys::*;
fn main() {
unsafe {
let nc = Notcurses::new();
println!("WIP");
sleep![2];
notcurses_stop(nc);
}
}

View File

@ -1,7 +1,6 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![no_std]
#![allow(clippy::too_many_arguments)]
pub mod bindings;

View File

@ -1,44 +1,44 @@
// functions already exported by bindgen : 36
// ------------------------------------------
// 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)
@ -65,7 +65,7 @@ use crate::{
notcurses_stdplane_const,
types::{
NcAlign, NcInput, NcLogLevel, NcPlane, Notcurses, NotcursesOptions, NCALIGN_CENTER,
NCALIGN_LEFT, NCOPTION_SUPPRESS_BANNERS,
NCALIGN_LEFT, NCOPTION_SUPPRESS_BANNERS, NCOPTION_NO_ALTERNATE_SCREEN,
},
};
@ -149,6 +149,19 @@ impl Notcurses {
&mut *notcurses_init(&NotcursesOptions::new(), null_mut())
}
/// `Notcurses` simple constructor without an alternate screen
pub unsafe fn without_altscreen<'a>() -> &'a mut Notcurses {
let options = NotcursesOptions::with_flags(NCOPTION_NO_ALTERNATE_SCREEN);
&mut *notcurses_init(&options, null_mut())
}
/// `Notcurses` simple constructor without an alternate screen
pub unsafe fn without_altscreen_nor_banners<'a>() -> &'a mut Notcurses {
let options = NotcursesOptions::with_flags(
NCOPTION_NO_ALTERNATE_SCREEN | NCOPTION_SUPPRESS_BANNERS);
&mut *notcurses_init(&options, null_mut())
}
/// `Notcurses` constructor with options
pub unsafe fn with_options<'a>(options: &NotcursesOptions) -> &'a mut Notcurses {
&mut *notcurses_init(options, null_mut())
@ -217,12 +230,133 @@ pub fn notcurses_term_dim_yx(nc: &Notcurses, rows: &mut i32, cols: &mut i32) {
#[cfg(test)]
mod test {
// use super::nc;
// use serial_test::serial;
use serial_test::serial;
use std::io::Read;
use crate::{notcurses_stop, Notcurses, NcFile};
/*
#[test]
#[serial]
fn () {
}
*/
// Test the bindgen functions ----------------------------------------------
#[test]
#[serial]
#[ignore]
// FIXME: always return null
fn notcurses_at_yx() {
unsafe {
let nc = Notcurses::new();
let mut sm = 0;
let mut ch = 0;
let res = crate::notcurses_at_yx(nc, 0, 0, &mut sm, &mut ch);
notcurses_stop(nc);
assert![!res.is_null()];
//print!("[{}] ", res);
}
}
#[test]
#[serial]
fn notcurses_debug() {
unsafe {
let nc = Notcurses::new();
let mut _p: *mut i8 = &mut 0;
let mut _size: *mut usize = &mut 0;
let mut file = NcFile::from_libc(libc::open_memstream(&mut _p, _size));
crate::notcurses_debug(nc, file.as_nc_ptr());
notcurses_stop(nc);
let mut string1 = String::new();
let _result = file.read_to_string(&mut string1);
let string2 = " ************************** notcurses debug state *****************************";
assert_eq![&string1[0..string2.len()], &string2[..]];
}
}
#[test]
#[serial]
fn notcurses_canchangecolor() {
unsafe {
let nc = Notcurses::new();
let res = crate::notcurses_canchangecolor(nc);
notcurses_stop(nc);
print!("[{}] ", res);
}
}
#[test]
#[serial]
fn notcurses_canfade() {
unsafe {
let nc = Notcurses::new();
let res = crate::notcurses_canfade(nc);
notcurses_stop(nc);
print!("[{}] ", res);
}
}
#[test]
#[serial]
fn notcurses_canopen_images() {
unsafe {
let nc = Notcurses::new();
let res = crate::notcurses_canopen_images(nc);
notcurses_stop(nc);
print!("[{}] ", res);
}
}
#[test]
#[serial]
fn notcurses_canopen_videos() {
unsafe {
let nc = Notcurses::new();
let res = crate::notcurses_canopen_videos(nc);
notcurses_stop(nc);
print!("[{}] ", res);
}
}
#[test]
#[serial]
fn notcurses_cansixel() {
unsafe {
let nc = Notcurses::new();
let res = crate::notcurses_cansixel(nc);
notcurses_stop(nc);
print!("[{}] ", res);
}
}
#[test]
#[serial]
fn notcurses_cantruecolor() {
unsafe {
let nc = Notcurses::new();
let res = crate::notcurses_cantruecolor(nc);
notcurses_stop(nc);
print!("[{}] ", res);
}
}
#[test]
#[serial]
fn notcurses_canutf8() {
unsafe {
let nc = Notcurses::new();
let res = crate::notcurses_canutf8(nc);
notcurses_stop(nc);
print!("[{}] ", res);
}
}
}

View File

@ -1,102 +1,102 @@
// functions already exported by bindgen : 97
// ------------------------------------------
// ncplane_above
// ncplane_at_cursor
// ncplane_at_yx
// ncplane_base
// ncplane_below
// ncplane_box
// ncplane_center_abs
// ncplane_channels
// ncplane_contents
// ncplane_create
// ncplane_cursor_move_yx
// ncplane_cursor_yx
// ncplane_destroy
// ncplane_dim_yx
// ncplane_dup
// ncplane_erase
// ncplane_fadein
// ncplane_fadein_iteration
// ncplane_fadeout
// ncplane_fadeout_iteration
// ncplane_format
// ncplane_gradient
// ncplane_greyscale
// ncplane_highgradient
// ncplane_highgradient_sized
// ncplane_hline_interp
// ncplane_home
// ncplane_mergedown
// ncplane_mergedown_simple
// ncplane_move_above
// ncplane_move_below
// ncplane_move_bottom
// ncplane_move_top
// ncplane_move_yx
// ncplane_new
// ncplane_notcurses
// ncplane_notcurses_const
// ncplane_off_styles
// ncplane_on_styles
// ncplane_parent
// ncplane_parent_const
// ncplane_polyfill_yx
// ncplane_pulse
// ncplane_putchar_stained
// ncplane_putc_yx
// ncplane_putegc_stained
// ncplane_putegc_yx
// ncplane_putnstr_aligned
// ncplane_putnstr_yx
// ncplane_putstr_aligned
// ncplane_putstr_stained
// ncplane_putstr_yx
// ncplane_puttext
// ncplane_putwegc_stained
// ncplane_putwstr_stained
// ncplane_qrcode
// ncplane_reparent
// ncplane_resize
// ncplane_resize_realign
// ncplane_rgba
// ncplane_rotate_ccw
// ncplane_rotate_cw
// ncplane_set_base
// ncplane_set_base_cell
// ncplane_set_bchannel
// ncplane_set_bg_alpha
// ncplane_set_bg_default
// ncplane_set_bg_palindex
// ncplane_set_bg_rgb
// ncplane_set_bg_rgb8
// ncplane_set_bg_rgb8_clipped
// ncplane_set_channels
// ncplane_set_fchannel
// ncplane_set_fg_alpha
// ncplane_set_fg_default
// ncplane_set_fg_palindex
// ncplane_set_fg_rgb
// ncplane_set_fg_rgb8
// ncplane_set_fg_rgb8_clipped
// ncplane_set_scrolling
// ncplane_set_styles
// ncplane_set_userptr
// ncplane_stain
// ncplane_styles
// ncplane_styles_off
// ncplane_styles_on
// ncplane_styles_set
// ncplane_translate
// ncplane_translate_abs
// ncplane_userptr
// ncplane_vline_interp
// ncplane_vprintf_aligned
// ncplane_vprintf_stained
// ncplane_vprintf_yx
// ncplane_x
// ncplane_y
// ncplane_yx
// ncplane_above
// ncplane_at_cursor
// ncplane_at_yx
// ncplane_base
// ncplane_below
// ncplane_box
// ncplane_center_abs
// ncplane_channels
// ncplane_contents
// ncplane_create
// ncplane_cursor_move_yx
// ncplane_cursor_yx
// ncplane_destroy
// ncplane_dim_yx
// ncplane_dup
// ncplane_erase
// ncplane_fadein
// ncplane_fadein_iteration
// ncplane_fadeout
// ncplane_fadeout_iteration
// ncplane_format
// ncplane_gradient
// ncplane_greyscale
// ncplane_highgradient
// ncplane_highgradient_sized
// ncplane_hline_interp
// ncplane_home
// ncplane_mergedown
// ncplane_mergedown_simple
// ncplane_move_above
// ncplane_move_below
// ncplane_move_bottom
// ncplane_move_top
// ncplane_move_yx
// ncplane_new
// ncplane_notcurses
// ncplane_notcurses_const
// ncplane_off_styles
// ncplane_on_styles
// ncplane_parent
// ncplane_parent_const
// ncplane_polyfill_yx
// ncplane_pulse
// ncplane_putchar_stained
// ncplane_putc_yx
// ncplane_putegc_stained
// ncplane_putegc_yx
// ncplane_putnstr_aligned
// ncplane_putnstr_yx
// ncplane_putstr_aligned
// ncplane_putstr_stained
// ncplane_putstr_yx
// ncplane_puttext
// ncplane_putwegc_stained
// ncplane_putwstr_stained
// ncplane_qrcode
// ncplane_reparent
// ncplane_resize
// ncplane_resize_realign
// ncplane_rgba
// ncplane_rotate_ccw
// ncplane_rotate_cw
// ncplane_set_base
// ncplane_set_base_cell
// ncplane_set_bchannel
// ncplane_set_bg_alpha
// ncplane_set_bg_default
// ncplane_set_bg_palindex
// ncplane_set_bg_rgb
// ncplane_set_bg_rgb8
// ncplane_set_bg_rgb8_clipped
// ncplane_set_channels
// ncplane_set_fchannel
// ncplane_set_fg_alpha
// ncplane_set_fg_default
// ncplane_set_fg_palindex
// ncplane_set_fg_rgb
// ncplane_set_fg_rgb8
// ncplane_set_fg_rgb8_clipped
// ncplane_set_scrolling
// ncplane_set_styles
// ncplane_set_userptr
// ncplane_stain
// ncplane_styles
// ncplane_styles_off
// ncplane_styles_on
// ncplane_styles_set
// ncplane_translate
// ncplane_translate_abs
// ncplane_userptr
// ncplane_vline_interp
// ncplane_vprintf_aligned
// ncplane_vprintf_stained
// ncplane_vprintf_yx
// ncplane_x
// ncplane_y
// ncplane_yx
//
// static inline functions total: 42
// ------------------------------------------ (implement / remaining)
@ -149,10 +149,11 @@
//
// NOTE: TODO: Still remains all the ncplane_printf* functions/macros (at the end)
use core::ffi::c_void;
use core::ptr::null_mut;
use cstr_core::CString;
use core::{
ffi::c_void,
ptr::{null, null_mut},
};
use std::ffi::CString;
use libc::free;
use crate::{
@ -163,13 +164,58 @@ use crate::{
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_vline_interp,
ncplane_vprintf_yx, notcurses_align,
ncplane_vprintf_yx, notcurses_align, ncplane_create,
types::{
AlphaBits, Cell, Channel, Channels, Color, EgcBackstop, IntResult, NcAlign, NcPlane,
StyleMask,
StyleMask, NcPlaneOptions, NcPlaneOptionHoriz, NcHoriz, NCPLANE_OPTION_HORALIGNED,
},
};
// Constructors ----------------------------------------------------------------
impl NcPlaneOptions {
/// `NcPlaneOptions` simple constructor with horizontal x
pub fn new(y: i32, x: i32, rows: u32, cols: u32) -> Self {
Self::with_all_options(y, NcHoriz::x(x), rows, cols, 0)
}
/// `NcPlaneOptions` simple constructor with horizontal alignment
pub fn new_halign(y: i32, align: NcAlign, rows: u32, cols: u32) -> Self {
Self::with_all_options(y, NcHoriz::align(align), rows, cols, NCPLANE_OPTION_HORALIGNED)
}
/// `NcplaneOptions` constructor
pub fn with_all_options(y: i32, horiz: NcHoriz, rows: u32, cols: u32, flags: u64) -> Self {
NcPlaneOptions {
y,
horiz: {
match horiz {
NcHoriz::x(data) => NcPlaneOptionHoriz {x: data},
NcHoriz::align(data) => NcPlaneOptionHoriz {align: data},
}
},
rows: rows as i32,
cols: cols as i32,
userptr: null_mut(),
name: null(),
resizecb: None,
flags,
}
}
}
impl NcPlane {
/// `NcPlane` constructor
pub unsafe fn new<'a>(bound_to: &mut NcPlane, options: &NcPlaneOptions) -> &'a mut NcPlane {
&mut *ncplane_create(bound_to, options)
}
}
// Static Functions ------------------------------------------------------------
/// 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'.

339
rust/src/types/file.rs Normal file
View File

@ -0,0 +1,339 @@
//! Wrapper for libc::FILE, both as used by notcurses and the libc crate
//!
//! The interface is largely based on the implementation of the
//! [cfile-rs crate](https://github.com/jkarns275/cfile) by Joshua Karns
use core::ptr::{null_mut, NonNull};
use std::{
// ffi::CString,
io::{Error, ErrorKind, Read, Seek, SeekFrom},
};
pub use libc::{
c_long, c_void, fclose, feof, fread, fseek, ftell, FILE as LIBC_FILE, SEEK_CUR, SEEK_END,
SEEK_SET,
};
pub use crate::bindgen::_IO_FILE as NC_FILE;
/// Intended to be passed into the CFile::open method.
/// It will open the file in a way that will allow reading and writing,
/// including overwriting old data.
/// It will not create the file if it does not exist.
pub static RANDOM_ACCESS_MODE: &'static str = "rb+";
/// Intended to be passed into the CFile::open method.
/// It will open the file in a way that will allow reading and writing,
/// including overwriting old data
pub static UPDATE: &'static str = "rb+";
/// Intended to be passed into the CFile::open method.
/// It will only allow reading.
pub static READ_ONLY: &'static str = "r";
/// Intended to be passed into the CFile::open method.
/// It will only allow writing.
pub static WRITE_ONLY: &'static str = "w";
/// Intended to be passed into the CFile::open method.
/// It will only allow data to be appended to the end of the file.
pub static APPEND_ONLY: &'static str = "a";
/// Intended to be passed into the CFile::open method.
/// It will allow data to be appended to the end of the file, and data to be
/// read from the file. It will create the file if it doesn't exist.
pub static APPEND_READ: &'static str = "a+";
/// Intended to be passed into the CFile::open method.
/// It will open the file in a way that will allow reading and writing,
/// including overwriting old data. It will create the file if it doesn't exist
pub static TRUNCATE_RANDOM_ACCESS_MODE: &'static str = "wb+";
/// A utility function to pull the current value of errno and put it into an
/// Error::Errno
fn get_error<T>() -> Result<T, Error> {
Err(Error::last_os_error())
}
/// A wrapper struct around libc::FILE for
///
/// The notcurses FILE type `NC_FILE` is imported through bindgen as a struct,
/// while the equivalent Rust libc::FILE (`LIBC_FILE`) is an opaque enum.
/// Several methods are provided to convert back and forth between both types,
/// to allow both rust libc operations and notcurses file operations on it.
#[derive(Debug)]
pub struct NcFile {
file_ptr: NonNull<LIBC_FILE>,
}
impl NcFile {
// constructors --
/// `NcFile` constructor from a file produced by notcurses
pub fn from_nc(file: *mut NC_FILE) -> Self {
NcFile {
file_ptr: unsafe { NonNull::new_unchecked(NcFile::nc2libc(file)) },
}
}
/// `NcFile` constructor from a file produced by the libc crate
pub fn from_libc(file: *mut LIBC_FILE) -> Self {
NcFile {
file_ptr: unsafe { NonNull::new_unchecked(file) },
}
}
// methods --
/// Returns the file pointer in the format expected by libc
#[inline]
pub fn as_libc_ptr(&self) -> *mut LIBC_FILE {
self.file_ptr.as_ptr()
}
/// Returns the file pointer in the format expected by notcurses
#[inline]
pub fn as_nc_ptr(&self) -> *mut NC_FILE {
Self::libc2nc(self.file_ptr.as_ptr())
}
/// Returns the current position in the file.
///
/// # Errors
/// On error Error::Errno(errno) is returned.
pub fn current_pos(&self) -> Result<u64, Error> {
unsafe {
let pos = ftell(self.as_libc_ptr());
if pos != -1 {
Ok(pos as u64)
} else {
get_error()
}
}
}
/// Reads the file from start to end. Convenience method
///
#[inline]
pub fn read_all(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error> {
let _ = self.seek(SeekFrom::Start(0));
self.read_to_end(buf)
}
// private methods --
/// Converts a file pointer from the struct notcurses uses to the
/// opaque enum type libc expects
#[inline]
fn nc2libc(file: *mut NC_FILE) -> *mut LIBC_FILE {
file as *mut _ as *mut LIBC_FILE
}
/// Converts a file pointer from the libc opaque enum format to the struct
/// expected by notcurses
#[inline]
fn libc2nc(file: *mut LIBC_FILE) -> *mut NC_FILE {
file as *mut _ as *mut NC_FILE
}
/// A utility function to expand a vector without increasing its capacity
/// more than it needs to be expanded.
fn expand_buffer(buff: &mut Vec<u8>, by: usize) {
if buff.capacity() < buff.len() + by {
buff.reserve(by);
}
for _ in 0..by {
buff.push(0u8);
}
}
}
impl Read for NcFile {
/// Reads exactly the number of bytes required to fill buf.
///
/// # Errors
/// If the end of the file is reached before buf is filled,
/// Err(EndOfFile(bytes_read)) will be returned. The data that was read
/// before that will still have been placed into buf.
///
/// Upon some other error, Err(Errno(errno)) will be returned.
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
unsafe {
let result = fread(
buf.as_ptr() as *mut c_void,
1,
buf.len(),
self.as_libc_ptr(),
);
if result != buf.len() {
match get_error::<u8>() {
Err(err) => {
if err.kind() == ErrorKind::UnexpectedEof {
Ok(result)
} else {
Err(err)
}
}
Ok(_) => panic!("This is impossible"),
}
} else {
Ok(result)
}
}
}
/// Reads the entire file starting from the current_position
/// expanding buf as needed.
///
/// On a successful read, this function will return Ok(bytes_read).
///
/// # Errors
/// If an error occurs during reading, some varient of error will be returned.
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error> {
let pos = self.current_pos();
let _ = self.seek(SeekFrom::End(0));
let end = self.current_pos();
match pos {
Ok(cur_pos) => match end {
Ok(end_pos) => {
if end_pos == cur_pos {
return Ok(0);
}
let to_read = (end_pos - cur_pos) as usize;
if buf.len() < to_read {
let to_reserve = to_read - buf.len();
Self::expand_buffer(buf, to_reserve);
}
let _ = self.seek(SeekFrom::Start(cur_pos as u64));
match self.read_exact(buf) {
Ok(()) => Ok(to_read),
Err(e) => Err(e),
}
}
Err(e) => Err(e),
},
Err(e) => Err(e),
}
}
/// Reads the entire file from the beginning and stores it in a string
///
/// On a successful read, this function will return Ok(bytes_read).
///
/// # Errors
/// If an error occurs during reading, some varient of error will be returned.
fn read_to_string(&mut self, strbuf: &mut String) -> Result<usize, Error> {
let mut bytes_read = 0_usize;
let mut buffer = vec![0u8];
let result = self.read_all(&mut buffer);
if let Ok(bytes) = result {
bytes_read = bytes;
}
if let Err(e) = result {
return Err(e);
}
let result = std::str::from_utf8(&buffer);
if let Ok(strslice) = result {
*strbuf = strslice.to_string();
Ok(bytes_read)
} else {
get_error()
}
}
/// Reads exactly the number of bytes required to fill buf.
///
/// # Errors
/// If the end of the file is reached before buf is filled,
/// Err(EndOfFile(bytes_read)) will be returned. The data that was read
/// before that will still have been placed into buf.
///
/// Upon some other error, Err(Errno(errno)) will be returned.
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error> {
unsafe {
let result = fread(
buf.as_ptr() as *mut c_void,
1,
buf.len(),
self.as_libc_ptr(),
);
if result == buf.len() {
Ok(())
} else {
// Check if we hit the end of the file
if feof(self.as_libc_ptr()) != 0 {
get_error()
} else {
get_error()
}
}
}
}
}
impl Seek for NcFile {
/// Changes the current position in the file using the SeekFrom enum.
///
/// To set relative to the beginning of the file (i.e. index is 0 + offset):
/// ```ignore
/// SeekFrom::Start(offset)
/// ```
/// To set relative to the end of the file (i.e. index is file_lenth - 1 - offset):
/// ```ignore
/// SeekFrom::End(offset)
/// ```
/// To set relative to the current position:
/// ```ignore
/// SeekFrom::End(offset)
/// ```
/// # Errors
/// On error Error::Errno(errno) is returned.
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error> {
unsafe {
let result = match pos {
SeekFrom::Start(from) => fseek(self.as_libc_ptr(), from as c_long, SEEK_SET),
SeekFrom::End(from) => fseek(self.as_libc_ptr(), from as c_long, SEEK_END),
SeekFrom::Current(delta) => fseek(self.as_libc_ptr(), delta as c_long, SEEK_CUR),
};
if result == 0 {
self.current_pos()
} else {
get_error()
}
}
}
}
impl Drop for NcFile {
/// Ensures the file stream is closed before abandoning the data.
fn drop(&mut self) {
let _ = unsafe {
if !(self.as_libc_ptr()).is_null() {
let res = fclose(self.as_libc_ptr());
if res == 0 {
self.file_ptr = NonNull::new_unchecked(null_mut::<LIBC_FILE>());
Ok(())
} else {
get_error()
}
} else {
Ok(())
}
};
}
}
// /// A utility function that creates a "buffer" of len bytes.
// // TODO: NcBuffer::new(size) .expand()?
// pub fn buffer(len: usize) -> Vec<u8> {
// vec![0u8; len]
// }

View File

@ -15,6 +15,7 @@
mod cell;
mod channel;
mod file;
mod misc;
mod plane;
mod terminal;
@ -30,14 +31,15 @@ pub use channel::{
AlphaBits, BlitSet, Channel, Channels, Color, NcFadeCtx, NcPixel, Palette, PaletteIndex, Rgb,
CHANNEL_ALPHA_MASK,
};
pub use file::{NcFile, LIBC_FILE, NC_FILE};
pub use misc::{
IntResult, BPREFIXCOLUMNS, BPREFIXSTRLEN, IPREFIXCOLUMNS, IPREFIXSTRLEN, PREFIXCOLUMNS,
PREFIXSTRLEN,
};
pub use plane::{
NCBLIT_1x1, NCBLIT_2x1, NCBLIT_2x2, NCBLIT_3x2, NCBLIT_4x1, NCBLIT_8x1, NcAlign, NcBlitter,
NcFdPlane, NcFdPlaneOptions, NcPlane, NcPlaneOptionHoriz, NcPlaneOptions, NcScale, NcVisual,
NcVisualOptions, NCALIGN_CENTER, NCALIGN_LEFT, NCALIGN_RIGHT, NCALIGN_UNALIGNED,
NcFdPlane, NcFdPlaneOptions, NcHoriz, NcPlane, NcPlaneOptionHoriz, NcPlaneOptions, NcScale,
NcVisual, NcVisualOptions, NCALIGN_CENTER, NCALIGN_LEFT, NCALIGN_RIGHT, NCALIGN_UNALIGNED,
NCBLIT_BRAILLE, NCBLIT_DEFAULT, NCBLIT_SIXEL, NCPLANE_OPTION_HORALIGNED, NCSCALE_NONE,
NCSCALE_SCALE, NCSCALE_STRETCH, NCVISUAL_OPTION_BLEND, NCVISUAL_OPTION_NODEGRADE,
};

View File

@ -13,7 +13,7 @@ pub type NcPlane = crate::ncplane;
pub type NcPlaneOptions = crate::ncplane_options;
/// Horizontal alignment relative to the parent plane. Use 'align' instead of 'x'.
pub const NCPLANE_OPTION_HORALIGNED: u32 = crate::bindings::NCPLANE_OPTION_HORALIGNED;
pub const NCPLANE_OPTION_HORALIGNED: u64 = crate::bindings::NCPLANE_OPTION_HORALIGNED as u64;
/// The `horiz` union field of [`NcPlaneOptions`](type.NcPlaneOptions)
///
@ -24,6 +24,12 @@ pub const NCPLANE_OPTION_HORALIGNED: u32 = crate::bindings::NCPLANE_OPTION_HORAL
///
pub type NcPlaneOptionHoriz = crate::ncplane_options__bindgen_ty_1;
/// This enum is a wrapper over the C `horiz` union, for the `NcPlaneOption` constructor
pub enum NcHoriz {
x(i32),
align(NcAlign),
}
/// I/O wrapper to dump file descriptor to [`NcPlane`](type.NcPlane.html)
///
/// `type in C: ncfdplane (struct)`

View File

@ -14,7 +14,7 @@
// ncmenu_selected
// ncmenu_unroll
use cstr_core::CString;
use std::ffi::CString;
use crate::{
ncmenu_create,

View File

@ -1,7 +1,6 @@
use core::ptr::{null, null_mut};
use cstr_core::{CStr, CString};
use std::ffi::{CStr, CString};
use libc_print::*;
use serial_test::serial; // serialize tests w/ nc::notcurses_init()
use libnotcurses_sys as nc;
@ -15,7 +14,7 @@ fn get_notcurses_version() {
CStr::from_ptr(s)
};
let r_str = c_str.to_str().unwrap();
libc_println!("rust-bound notcurses v{}", r_str);
println!("rust-bound notcurses v{}", r_str);
}
#[test]