diff --git a/rust/src/cells/mod.rs b/rust/src/cells/mod.rs index badb0c299..6de28453f 100644 --- a/rust/src/cells/mod.rs +++ b/rust/src/cells/mod.rs @@ -72,8 +72,8 @@ pub use types::{ NCSTYLE_UNDERLINE, }; -mod constructors; -pub use constructors::*; +mod wrapped; +pub use wrapped::*; use libc::strcmp; diff --git a/rust/src/cells/constructors.rs b/rust/src/cells/wrapped.rs similarity index 75% rename from rust/src/cells/constructors.rs rename to rust/src/cells/wrapped.rs index ff127b705..7881d5937 100644 --- a/rust/src/cells/constructors.rs +++ b/rust/src/cells/wrapped.rs @@ -3,8 +3,7 @@ pub use crate::{NcCell, NcChannelPair, NcCharBackstop, NcStyleMask}; impl NcCell { - /// [NcCell] constructor expecting [char], [NcStyleMask] and - /// [NcChannelPair] + /// New NcCell, expects a [char], [NcStyleMask] and [NcChannelPair]. #[inline] pub const fn new(ch: char, stylemask: NcStyleMask, channels: NcChannelPair) -> Self { NcCell { @@ -16,13 +15,13 @@ impl NcCell { } } - /// [NcCell] simple constructor just expecting a [char] + /// New NcCell, expects a [char]. #[inline] pub const fn with_char(ch: char) -> Self { Self::new(ch, 0 as NcStyleMask, 0 as NcChannelPair) } - /// [NcCell] simple constructor for an empty cell + /// New NcCell, blank. #[inline] pub const fn new_blank() -> Self { Self::with_char(0 as char) diff --git a/rust/src/direct/mod.rs b/rust/src/direct/mod.rs index 7c277ab37..527e82025 100644 --- a/rust/src/direct/mod.rs +++ b/rust/src/direct/mod.rs @@ -49,5 +49,5 @@ pub use types::{ NcDirect, NcDirectFlags, NCDIRECT_OPTION_INHIBIT_CBREAK, NCDIRECT_OPTION_INHIBIT_SETLOCALE, }; -mod constructors; -pub use constructors::*; +mod wrapped; +pub use wrapped::*; diff --git a/rust/src/direct/constructors.rs b/rust/src/direct/wrapped.rs similarity index 100% rename from rust/src/direct/constructors.rs rename to rust/src/direct/wrapped.rs diff --git a/rust/src/notcurses/mod.rs b/rust/src/notcurses/mod.rs index 8eb4c1662..c3e67c956 100644 --- a/rust/src/notcurses/mod.rs +++ b/rust/src/notcurses/mod.rs @@ -14,7 +14,7 @@ // notcurses_cursor_disable // notcurses_cursor_enable //# notcurses_debug -// notcurses_drop_planes +//# notcurses_drop_planes // notcurses_getc //# notcurses_init // notcurses_inputready_fd @@ -47,7 +47,7 @@ // (+) implement : 6 / 0 // (#) unit tests: 0 / 6 // ----------------------------------------- -//+ notcurses_align +//# notcurses_align //+ notcurses_getc_blocking //+ notcurses_getc_nblock //+ notcurses_stddim_yx @@ -66,8 +66,8 @@ pub use types::{ NCOPTION_SUPPRESS_BANNERS, NCOPTION_VERIFY_SIXEL, }; -mod constructors; -pub use constructors::*; +mod wrapped; +pub use wrapped::*; use core::ptr::null; diff --git a/rust/src/notcurses/tests.rs b/rust/src/notcurses/tests.rs index 4cbf239a5..7b7639c61 100644 --- a/rust/src/notcurses/tests.rs +++ b/rust/src/notcurses/tests.rs @@ -5,6 +5,19 @@ use std::io::Read; use crate::{notcurses_stop, NcFile, Notcurses}; +#[test] +#[serial] +fn notcurses_align() { + unsafe { + let nc = Notcurses::new(); + assert_eq![0, crate::notcurses_align(30, crate::NCALIGN_LEFT, 20)]; + assert_eq![5, crate::notcurses_align(30, crate::NCALIGN_CENTER, 20)]; + assert_eq![10, crate::notcurses_align(30, crate::NCALIGN_RIGHT, 20)]; + assert_eq![10, crate::notcurses_align(30, crate::NCALIGN_UNALIGNED, 20)]; + notcurses_stop(nc); + } +} + #[test] #[serial] fn notcurses_canchangecolor() { @@ -82,6 +95,22 @@ fn notcurses_canutf8() { } } +#[test] +#[serial] +fn notcurses_drop_planes() { + unsafe { + let nc = Notcurses::new(); + let stdplane = crate::notcurses_stdplane(nc); + let plane1 = crate::NcPlane::new_bound(&mut *stdplane, 0, 0, 10, 10); + let _plane2 = crate::NcPlane::new_bound(&mut *plane1, 0, 0, 10, 10); + + crate::notcurses_drop_planes(nc); + // TODO: CHECK that planes are really dropped. + + notcurses_stop(nc); + } +} + #[test] #[serial] fn notcurses_init() { diff --git a/rust/src/notcurses/constructors.rs b/rust/src/notcurses/wrapped.rs similarity index 61% rename from rust/src/notcurses/constructors.rs rename to rust/src/notcurses/wrapped.rs index aac33d0f3..8a56c15cc 100644 --- a/rust/src/notcurses/constructors.rs +++ b/rust/src/notcurses/wrapped.rs @@ -6,24 +6,28 @@ use crate::{ notcurses_init, NcLogLevel, Notcurses, NotcursesOptions, NCOPTION_NO_ALTERNATE_SCREEN, NCOPTION_SUPPRESS_BANNERS, }; +use crate::{ + notcurses_stdplane, NcPlane, notcurses_stop, NcResult, notcurses_render, +}; +/// # `NotcursesOptions` Constructors impl NotcursesOptions { - /// Simple `NotcursesOptions` constructor + /// New NotcursesOptions. pub fn new() -> Self { Self::with_all_options(0, 0, 0, 0, 0, 0) } - /// `NotcursesOptions` constructor with customizable margins + /// New NotcursesOptions, with 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 + /// New NotcursesOptions, with 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 + /// New NotcursesOptions, with all the options. /// /// ## Arguments /// @@ -75,33 +79,55 @@ impl NotcursesOptions { } } +/// # `Notcurses` Constructors impl Notcurses { - /// `Notcurses` simple constructor with clean output - pub unsafe fn new<'a>() -> &'a mut Notcurses { + /// Simple constructor with clean output + pub fn new<'a>() -> &'a mut Notcurses { let options = NotcursesOptions::with_flags(NCOPTION_SUPPRESS_BANNERS); - &mut *notcurses_init(&options, null_mut()) + unsafe { &mut *notcurses_init(&options, null_mut()) } } - /// `Notcurses` simple constructor, showing banners - pub unsafe fn with_banners<'a>() -> &'a mut Notcurses { - &mut *notcurses_init(&NotcursesOptions::new(), null_mut()) + /// Simple constructor, showing banners + pub fn with_banners<'a>() -> &'a mut Notcurses { + unsafe { &mut *notcurses_init(&NotcursesOptions::new(), null_mut()) } } - /// `Notcurses` simple constructor without an alternate screen - pub unsafe fn without_altscreen<'a>() -> &'a mut Notcurses { + /// Simple constructor without an alternate screen + pub fn without_altscreen<'a>() -> &'a mut Notcurses { let options = NotcursesOptions::with_flags(NCOPTION_NO_ALTERNATE_SCREEN); - &mut *notcurses_init(&options, null_mut()) + unsafe { &mut *notcurses_init(&options, null_mut()) } } - /// `Notcurses` simple constructor without an alternate screen - pub unsafe fn without_altscreen_nor_banners<'a>() -> &'a mut Notcurses { + /// Simple constructor without an alternate screen + pub 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()) + unsafe { &mut *notcurses_init(&options, null_mut()) } + } + + /// Constructor with all the options + pub fn with_options<'a>(options: &NotcursesOptions) -> &'a mut Notcurses { + unsafe { &mut *notcurses_init(options, null_mut()) } + } +} + +/// # `Notcurses` methods +impl Notcurses { + + /// + pub fn stdplane_mut(&mut self) -> NcPlane { + unsafe { *notcurses_stdplane(self) } + //notcurses_stdplane_const //??? } - /// `Notcurses` constructor with options - pub unsafe fn with_options<'a>(options: &NotcursesOptions) -> &'a mut Notcurses { - &mut *notcurses_init(options, null_mut()) + /// + pub fn stop(&mut self) -> NcResult { + unsafe { notcurses_stop(self) } } + + /// + pub fn render(&mut self) -> NcResult { + unsafe { notcurses_render(self) } + } + } diff --git a/rust/src/plane/mod.rs b/rust/src/plane/mod.rs index 42efba56b..26f41ef64 100644 --- a/rust/src/plane/mod.rs +++ b/rust/src/plane/mod.rs @@ -172,8 +172,8 @@ pub use types::{ NCVISUAL_OPTION_BLEND, NCVISUAL_OPTION_NODEGRADE, }; -mod constructors; -pub use constructors::*; +mod wrapped; +pub use wrapped::*; use core::{ffi::c_void, ptr::null_mut}; use libc::free; @@ -519,13 +519,13 @@ pub fn ncplane_putegc(plane: &mut NcPlane, gcluster: i8, sbytes: &mut i32) -> Nc /// #[inline] -pub fn ncplane_putstr(plane: &mut NcPlane, gclustarr: &[u8]) -> NcResult { +pub fn ncplane_putstr(plane: &mut NcPlane, string: &str) -> NcResult { unsafe { ncplane_putstr_yx( plane, -1, -1, - CString::new(gclustarr).expect("Bad string").as_ptr(), + CString::new(string.as_bytes()).expect("Bad string").as_ptr(), ) } } diff --git a/rust/src/plane/constructors.rs b/rust/src/plane/wrapped.rs similarity index 51% rename from rust/src/plane/constructors.rs rename to rust/src/plane/wrapped.rs index bc91829d7..7b0a1db2d 100644 --- a/rust/src/plane/constructors.rs +++ b/rust/src/plane/wrapped.rs @@ -2,26 +2,33 @@ use core::ptr::{null, null_mut}; +// for constructors use crate::{ ncpile_create, ncplane_create, notcurses_term_dim_yx, NcAlign, NcPlane, NcPlaneOptions, Notcurses, NCPLANE_OPTION_HORALIGNED, }; +// for methods +use crate::{ + NcCell, NcResult, ncplane_cursor_yx, ncplane_dim_yx, ncplane_erase, ncplane_putc, ncplane_putc_yx, +}; + +/// # `NcPlaneOptions` Constructors impl NcPlaneOptions { - /// [`NcPlaneOptions`] simple constructor with horizontal x + /// New NcPlaneOptions using the horizontal x. pub fn new(y: i32, x: i32, rows: u32, cols: u32) -> Self { Self::with_flags(y, x, rows, cols, 0) } - /// [`NcPlaneOptions`] simple constructor with horizontal alignment + /// New NcPlaneOptions with horizontal alignment. pub fn new_halign(y: i32, align: NcAlign, rows: u32, cols: u32) -> Self { Self::with_flags(y, align as i32, rows, cols, NCPLANE_OPTION_HORALIGNED) } - /// [`NcPlaneOptions`] constructor + /// New NcPlaneOptions, with flags. /// - /// Note: If you use`NCPLANE_OPTION_HORALIGNED` flag, you must provide - /// the `NcAlign` value as the `x` parameter, casted to `i32`. + /// Note: If you use [NCPLANE_OPTION_HORALIGNED] flag, you must provide + /// the [NcAlign] value to the `x` parameter, casted to `i32`. pub fn with_flags(y: i32, x: i32, rows: u32, cols: u32, flags: u64) -> Self { NcPlaneOptions { y, @@ -36,8 +43,9 @@ impl NcPlaneOptions { } } +/// # `NcPlane` Constructors impl NcPlane { - /// [`NcPlane`] constructor + /// New NcPlane. /// /// The returned plane will be the top, bottom, and root of this new pile. pub unsafe fn new<'a>( @@ -51,7 +59,7 @@ impl NcPlane { &mut *ncpile_create(nc, &options) } - /// [`NcPlane`] constructor, expecting an [`NcPlaneOptions`] struct + /// New NcPlane, expects an [NcPlaneOptions] struct. /// /// The returned plane will be the top, bottom, and root of this new pile. pub unsafe fn with_options<'a>( @@ -61,7 +69,7 @@ impl NcPlane { &mut *ncpile_create(nc, options) } - /// [`NcPlane`] constructor, bound to another plane + /// New NcPlane, bound to another NcPlane. pub unsafe fn new_bound<'a>( bound_to: &mut NcPlane, y: i32, @@ -73,8 +81,7 @@ impl NcPlane { &mut *ncplane_create(bound_to, &options) } - /// [`NcPlane`] constructor, bound to another plane, - /// expecting an [`NcPlaneOptions`] struct + /// New NcPlane, bound to another plane, expects an [NcPlaneOptions] struct. /// /// The returned plane will be the top, bottom, and root of this new pile. pub unsafe fn with_options_bound<'a>( @@ -84,10 +91,9 @@ impl NcPlane { &mut *ncpile_create(nc, options) } - /// [`NcPlane`] constructor, with the same dimensions of the terminal. + /// New NcPlane, with the same dimensions of the terminal. /// /// The returned plane will be the top, bottom, and root of this new pile. - // FIXME BUG pub unsafe fn new_termsize<'a>(nc: &mut Notcurses) -> &'a mut NcPlane { let (mut trows, mut tcols) = (0, 0); notcurses_term_dim_yx(nc, &mut trows, &mut tcols); @@ -95,3 +101,58 @@ impl NcPlane { &mut *ncpile_create(nc, &NcPlaneOptions::new(0, 0, trows as u32, tcols as u32)) } } + +/// # `NcPlane` Methods +impl NcPlane { + /// Returns the current position of the cursor within the [NcPlane]. + /// + /// Unlike [ncplane_cursor_yx] which uses `i32`, this uses [u32]. + // + // NOTE: y and/or x may be NULL. + // 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)}; + (y as u32, x as u32) + } + + /// Returns the current row of the cursor within the [NcPlane]. + pub fn cursor_y(&self) -> u32 { + self.cursor_yx().0 + } + + /// Returns the current column of the cursor within the [NcPlane]. + pub fn cursor_x(&self) -> u32 { + self.cursor_yx().1 + } + + /// Return the dimensions of this [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)}; + (y as u32, x as u32) + } + + /// Return the rows of this [NcPlane]. + pub fn dim_y(&self) -> u32 { + self.dim_yx().0 + } + + /// Return the columns of this [NcPlane]. + pub fn dim_x(&self) -> u32 { + self.dim_yx().1 + } + + /// + // FIXME segfaults + 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) -> NcResult { + // unsafe { ncplane_putc(self) } + // } +}