diff --git a/rust/examples/direct-cursor.rs b/rust/examples/direct-cursor.rs index 1394b5b5f..a859fdcd9 100644 --- a/rust/examples/direct-cursor.rs +++ b/rust/examples/direct-cursor.rs @@ -7,7 +7,7 @@ use libnotcurses_sys as nc; fn main() { unsafe { - let ncd = nc::ncdirect_new(); + let ncd = nc::NcDirect::new(); let cols = nc::ncdirect_dim_x(ncd); let rows = nc::ncdirect_dim_y(ncd); diff --git a/rust/examples/direct-image.rs b/rust/examples/direct-image.rs index 5ed1fb17a..06135a3c4 100644 --- a/rust/examples/direct-image.rs +++ b/rust/examples/direct-image.rs @@ -4,7 +4,7 @@ use libnotcurses_sys as nc; fn main() { unsafe { - let ncd = nc::ncdirect_new(); + let ncd = nc::NcDirect::new(); render_image(&mut *ncd, nc::NCBLIT_1x1); render_image(&mut *ncd, nc::NCBLIT_2x1); diff --git a/rust/examples/full-text.rs b/rust/examples/full-text.rs index fee13c995..2e436a7ba 100644 --- a/rust/examples/full-text.rs +++ b/rust/examples/full-text.rs @@ -1,7 +1,18 @@ //use cstr_core::CString; -//use libnotcurses_sys as nc; +use libnotcurses_sys as nc; fn main() { + + unsafe { + // let options = nc::NotcursesOptions::new(); + // let app = nc::Notcurses::with_options(&options); + + let app = nc::Notcurses::new(); + + + + nc::notcurses_stop(app); + } } diff --git a/rust/src/bindings.rs b/rust/src/bindings.rs index 6b00be952..49afec482 100644 --- a/rust/src/bindings.rs +++ b/rust/src/bindings.rs @@ -27,7 +27,6 @@ pub mod bindgen { #[doc(inline)] pub use bindgen::{ // structs - _IO_FILE, __va_list_tag, timespec, }; @@ -618,6 +617,15 @@ pub(crate) use bindgen::{ // structs notcurses, notcurses_options, + + // constants + 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, }; #[doc(inline)] @@ -662,15 +670,6 @@ pub use bindgen::{ notcurses_ucs32_to_utf8, notcurses_version, notcurses_version_components, - - // constants - 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, }; // palette --------------------------------------------------------------------- diff --git a/rust/src/cells.rs b/rust/src/cells.rs index 0f9bf8d4d..531838fc9 100644 --- a/rust/src/cells.rs +++ b/rust/src/cells.rs @@ -66,8 +66,7 @@ use crate::{ 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, types::{ - AlphaBits, Cell, Channel, Channels, Color, Egc, IntResult, NcPlane, - PaletteIndex, StyleMask, + AlphaBits, Cell, Channel, Channels, Color, Egc, IntResult, NcPlane, PaletteIndex, StyleMask, }, CELL_ALPHA_OPAQUE, CELL_BGDEFAULT_MASK, CELL_BG_PALETTE, CELL_FGDEFAULT_MASK, CELL_FG_PALETTE, CELL_NOBACKGROUND_MASK, CELL_WIDEASIAN_MASK, NCSTYLE_MASK, diff --git a/rust/src/direct.rs b/rust/src/direct.rs index b032dcdab..9692af08a 100644 --- a/rust/src/direct.rs +++ b/rust/src/direct.rs @@ -40,34 +40,44 @@ // ncdirect_vline_interp use crate::{ - bindgen::_IO_FILE, ncdirect_init, types::{NcDirect, NcDirectFlags}, }; +use core::ptr::{null, null_mut}; -extern "C" { - fn libc_stdout() -> *mut _IO_FILE; -} +impl NcDirect { + /// A simple ncdirect_init() wrapper using the default options. + /// + /// Initialize a direct-mode notcurses context on the tty. + /// + /// Direct mode supports a limited subset of notcurses routines, + /// and neither supports nor requires notcurses_render(). This can be + /// used to add color and styling to text in the standard output paradigm. + // + // Returns NULL on error, including any failure initializing terminfo. + pub unsafe fn new<'a>() -> &'a mut NcDirect { + Self::with_flags(0) + } -/// A simple ncdirect_init() wrapper using the default options. -/// -/// Initialize a direct-mode notcurses context on the tty. -/// -/// Direct mode supports a limited subset of notcurses routines, -/// and neither supports nor requires notcurses_render(). This can be -/// used to add color and styling to text in the standard output paradigm. -/// -/// Returns NULL on error, including any failure initializing terminfo. -pub unsafe fn ncdirect_new() -> *mut NcDirect { - ncdirect_with_flags(0) + /// A simple ncdirect_init() wrapper with optional flags. + /// + /// `flags` is a bitmask over: + /// - NCDIRECT_OPTION_INHIBIT_CBREAK + /// - NCDIRECT_OPTION_INHIBIT_SETLOCALE + /// + pub unsafe fn with_flags<'a>(flags: NcDirectFlags) -> &'a mut NcDirect { + &mut *ncdirect_init(null(), null_mut(), flags) + } } -/// A simple ncdirect_init() wrapper with optional flags. -/// -/// `flags` is a bitmask over: -/// - NCDIRECT_OPTION_INHIBIT_CBREAK -/// - NCDIRECT_OPTION_INHIBIT_SETLOCALE -/// -pub unsafe fn ncdirect_with_flags(flags: NcDirectFlags) -> *mut NcDirect { - ncdirect_init(core::ptr::null(), libc_stdout(), flags) -} +// Explicitly implementing both `Drop` and `Copy` trait on a type is currently +// disallowed (rustc --explain E0184) +// https://github.com/rust-lang/rust/issues/20126 +// +// impl Drop for NcDirect { +// fn drop(&mut self) { +// unsafe { +// ncdirect_stop(self); +// } +// } +// } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index aee6fde34..69057554c 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -26,6 +26,7 @@ mod palette; mod pixel; mod plane; mod visual; +mod widgets; pub use cells::*; pub use channel::*; @@ -38,3 +39,4 @@ pub use palette::*; pub use pixel::*; pub use plane::*; pub use visual::*; +pub use widgets::*; diff --git a/rust/src/macros.rs b/rust/src/macros.rs index 7108f4b88..0a9e11f73 100644 --- a/rust/src/macros.rs +++ b/rust/src/macros.rs @@ -1,5 +1,4 @@ #[allow(unused_imports)] - use crate::Cell; #[macro_export] diff --git a/rust/src/notcurses.rs b/rust/src/notcurses.rs index 8daff9f82..2b6b447a8 100644 --- a/rust/src/notcurses.rs +++ b/rust/src/notcurses.rs @@ -52,7 +52,7 @@ // notcurses_stddim_yx_const //+ notcurses_term_dim_yx -use core::ptr::null; +use core::ptr::{null, null_mut}; use crate::{ // NOTE: can't use libc::timespec nor libc::sigset_t @@ -60,13 +60,87 @@ use crate::{ bindings::{sigemptyset, sigfillset, sigset_t, timespec}, ncplane_dim_yx, notcurses_getc, + notcurses_init, notcurses_stdplane, notcurses_stdplane_const, - types::{NcAlign, NcInput, NcPlane, Notcurses}, + types::{NcAlign, NcInput, NcLogLevel, NcPlane, Notcurses, NotcursesOptions}, NCALIGN_CENTER, NCALIGN_LEFT, }; +impl NotcursesOptions { + /// Simple `NotcursesOptions` constructor + pub fn new() -> Self { + Self::with_all_options(0, 0, 0, 0, 0, 0) + } + + /// `NotcursesOptions` constructor with customizable margins + pub fn with_margins(top: i32, right: i32, bottom: i32, left: i32) -> Self { + Self::with_all_options(0, top, right, bottom, left, 0) + } + + /// `NotcursesOptions` constructor with customizable flags + pub fn with_flags(flags: u64) -> Self { + Self::with_all_options(0, 0, 0, 0, 0, flags) + } + + /// `NotcursesOptions` constructor with all the options available + /// + /// ## Arguments + /// + /// - loglevel + /// + /// Progressively higher log levels result in more logging to stderr. By + /// default, nothing is printed to stderr once fullscreen service begins. + /// + /// - margin_t, margin_r, margin_b, margin_l + /// + /// Desirable margins (top, right, bottom, left). + /// + /// If all are 0 (default), we will render to the entirety of the screen. + /// If the screen is too small, we do what we can. + /// Absolute coordinates are relative to the rendering area + /// ((0, 0) is always the origin of the rendering area). + /// + /// - flags + /// + /// General flags; see NCOPTION_*. This is expressed as a bitfield so that + /// future options can be added without reshaping the struct. + /// Undefined bits must be set to 0. + /// + pub fn with_all_options( + loglevel: NcLogLevel, + margin_t: i32, + margin_r: i32, + margin_b: i32, + margin_l: i32, + flags: u64, + ) -> Self { + Self { + termtype: null(), + renderfp: null_mut(), + loglevel, + margin_t, + margin_r, + margin_b, + margin_l, + flags, + } + } +} + +impl Notcurses { + /// `Notcurses` simple constructor + pub unsafe fn new<'a>() -> &'a mut Notcurses { + &mut *notcurses_init(&NotcursesOptions::new(), null_mut()) + } + + /// `Notcurses` constructor with options + pub unsafe fn with_options(options: &NotcursesOptions) -> &mut Notcurses { + &mut *notcurses_init(options, null_mut()) + } +} + /// 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 { @@ -127,11 +201,6 @@ pub fn notcurses_term_dim_yx(nc: &Notcurses, rows: &mut i32, cols: &mut i32) { } } -// TODO -// pub unsafe fn notcurses_new() -> *mut Notcurses { -// notcurses_init(core::ptr::null(), libc_stdout()) -// } - #[cfg(test)] mod test { // use super::nc; diff --git a/rust/src/types.rs b/rust/src/types.rs index f3ec3b9f5..99cca5b88 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -332,7 +332,6 @@ pub type NcFdPlane = crate::ncfdplane; /// `type in C: ncplane_options (struct)` pub type NcFdPlaneOptions = crate::ncfdplane_options; - /// Palette structure consisting of an array of 256 [`Channel`](type.Channel.html)s /// /// Some terminals only support 256 colors, but allow the full @@ -475,10 +474,56 @@ pub type Notcurses = crate::bindings::notcurses; /// Options struct for [`Notcurses`](type.Notcurses.html) pub type NotcursesOptions = crate::bindings::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::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::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::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::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::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::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::NCOPTION_VERIFY_SIXEL as u64; + /// Context for a palette fade operation pub type NcFadeCtx = crate::ncfadectx; - // Widgets /// `type in C: ncmenu (struct)` diff --git a/rust/src/widgets/mod.rs b/rust/src/widgets/mod.rs new file mode 100644 index 000000000..39e1ff785 --- /dev/null +++ b/rust/src/widgets/mod.rs @@ -0,0 +1,5 @@ +//! Widgets +//! + +mod reader; +pub use reader::*; diff --git a/rust/src/widgets/reader.rs b/rust/src/widgets/reader.rs new file mode 100644 index 000000000..2cca0b805 --- /dev/null +++ b/rust/src/widgets/reader.rs @@ -0,0 +1,52 @@ +// 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 +// ------------------------------------------- + +use crate::{ + ncreader_create, + types::{NcPlane, NcReader, NcReaderOptions}, +}; + +/// `NcReader` constructor (wraps `ncreader_create`) +/// +/// NcReader provides freeform input in a (possibly multiline) region, supporting +/// optional readline keybindings. takes ownership of its plane, destroying it +/// on any error (ncreader_destroy() otherwise destroys the ncplane). +impl NcReader { + /// Simple `NcReader` 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, + } + } +} diff --git a/rust/tests/notcurses.rs b/rust/tests/notcurses.rs index d28aaf25c..3ed1e232f 100644 --- a/rust/tests/notcurses.rs +++ b/rust/tests/notcurses.rs @@ -31,7 +31,7 @@ fn create_notcurses_context() { margin_r: 0, margin_b: 0, margin_l: 0, - flags: (nc::NCOPTION_NO_ALTERNATE_SCREEN | nc::NCOPTION_INHIBIT_SETLOCALE) as u64, + flags: (nc::types::NCOPTION_NO_ALTERNATE_SCREEN | nc::types::NCOPTION_INHIBIT_SETLOCALE), }; let nc = nc::notcurses_init(&opts, null_mut()); nc::notcurses_stop(nc);