diff --git a/rust/examples/poc-cjkscroll.rs b/rust/examples/poc-cjkscroll.rs index aa9b67310..c15908f14 100644 --- a/rust/examples/poc-cjkscroll.rs +++ b/rust/examples/poc-cjkscroll.rs @@ -23,9 +23,7 @@ fn main() -> NcResult<()> { wc = '\u{4e00}'; } - if nc.render() == NCRESULT_ERR { - break; - } + nc.render()?; } nc.stop()?; Ok(()) diff --git a/rust/src/direct/methods.rs b/rust/src/direct/methods.rs index a61e4a772..d30d28c2a 100644 --- a/rust/src/direct/methods.rs +++ b/rust/src/direct/methods.rs @@ -5,8 +5,8 @@ use core::ptr::{null, null_mut}; use crate::ffi::sigset_t; use crate::{ cstring, error, NcAlign, NcBlitter, NcChannelPair, NcColor, NcDimension, NcDirect, - NcDirectFlags, NcEgc, NcError, NcInput, NcPaletteIndex, NcResult, NcRgb, NcScale, NcStyleMask, - NcTime, NCRESULT_ERR, + NcDirectFlags, NcEgc, NcError, NcInput, NcPaletteIndex, NcPlane, NcResult, NcRgb, NcScale, + NcStyleMask, NcTime, NCRESULT_ERR, }; /// # `NcDirect` constructors and destructors @@ -48,7 +48,7 @@ impl NcDirect { } } -/// ## NcDirect methods: clear, flush, render_image +/// ## NcDirect methods: clear, flush, render impl NcDirect { /// Clears the screen. /// @@ -64,18 +64,63 @@ impl NcDirect { error![unsafe { crate::ncdirect_flush(self) }] } + /// Takes the result of [render_frame()][NcDirect#method.render_frame] + /// and writes it to the output. + /// + /// The `align`, `blitter`, and `scale` arguments must be the same as those + /// passed to render_frame(). + /// + /// *C style function: [ncdirect_render_image()][crate::ncdirect_render_image].* + pub fn raster_frame( + &mut self, + faken: &mut NcPlane, + align: NcAlign, + blitter: NcBlitter, + scale: NcScale, + ) -> NcResult<()> { + error![ + unsafe { crate::ncdirect_raster_frame(self, faken, align, blitter, scale) }, + (), + "Rastering frame" + ] + } + + /// Renders an image using the specified blitter and scaling, + /// but do not write the result. + /// + /// The image may be arbitrarily many rows -- the output will scroll -- + /// but will only occupy the column of the cursor, and those to the right. + /// + /// To actually write (and free) this, invoke ncdirect_raster_frame(). + /// and writes it to the output. + /// + /// The `align`, `blitter`, and `scale` arguments must be the same as those + /// passed to render_frame(). + /// + /// *C style function: [ncdirect_render_image()][crate::ncdirect_render_image].* + pub fn render_frame<'a>( + &mut self, + filename: &str, + blitter: NcBlitter, + scale: NcScale, + ) -> NcResult<&'a mut NcPlane> { + let res = unsafe { crate::ncdirect_render_frame(self, cstring![filename], blitter, scale) }; + if res == null_mut() { + return Err(NcError::with_msg(NCRESULT_ERR, "Rendering frame")); + } + Ok(unsafe { &mut *res }) + } + /// Displays an image using the specified blitter and scaling. /// /// The image may be arbitrarily many rows -- the output will scroll -- but /// will only occupy the column of the cursor, and those to the right. /// + /// The render/raster process can be split by using + /// [render_frame()][#method.render_frame] and + /// [raster_frame()][#method.raster_frame]. /// /// *C style function: [ncdirect_render_image()][crate::ncdirect_render_image].* - // - // TODO: - // The render/raster process can be split by using - // [render_frame()][#method.render_frame] and - // [raster_frame()][#method.raster_frame]. pub fn render_image( &mut self, filename: &str, diff --git a/rust/src/direct/mod.rs b/rust/src/direct/mod.rs index c42c57ec1..602395604 100644 --- a/rust/src/direct/mod.rs +++ b/rust/src/direct/mod.rs @@ -37,6 +37,8 @@ //W ncdirect_palette_size // X ncdirect_printf_aligned //W ncdirect_putstr +//W ncdirect_raster_frame +//W ncdirect_render_frame //W ncdirect_render_image //W ncdirect_rounded_box //W ncdirect_stop diff --git a/rust/src/notcurses/methods.rs b/rust/src/notcurses/methods.rs index 74a40f76f..a7e83b3c7 100644 --- a/rust/src/notcurses/methods.rs +++ b/rust/src/notcurses/methods.rs @@ -5,9 +5,9 @@ use std::ffi::CStr; use crate::{ cstring, error, notcurses_init, NcAlign, NcBlitter, NcChannelPair, NcDimension, NcEgc, NcError, - NcFile, NcInput, NcIntResult, NcLogLevel, NcPlane, NcResult, NcScale, NcSignalSet, NcStats, - NcStyleMask, NcTime, Notcurses, NotcursesOptions, NCOPTION_NO_ALTERNATE_SCREEN, - NCOPTION_SUPPRESS_BANNERS, NCRESULT_ERR, NCRESULT_OK, + NcFile, NcInput, NcLogLevel, NcPlane, NcResult, NcScale, NcSignalSet, NcStats, NcStyleMask, + NcTime, Notcurses, NotcursesOptions, NCOPTION_NO_ALTERNATE_SCREEN, NCOPTION_SUPPRESS_BANNERS, + NCRESULT_ERR, }; /// # `NotcursesOptions` Constructors @@ -130,8 +130,8 @@ impl Notcurses { /// [NCALIGN_UNALIGNED][crate::NCALIGN_UNALIGNED] or invalid [NcAlign]. /// /// *C style function: [notcurses_align()][crate::notcurses_align].* - pub fn align(availcols: NcDimension, align: NcAlign, cols: NcDimension) -> NcIntResult { - crate::notcurses_align(availcols, align, cols) + pub fn align(availcols: NcDimension, align: NcAlign, cols: NcDimension) -> NcResult<()> { + error![crate::notcurses_align(availcols, align, cols)] } /// Retrieves the current contents of the specified [NcCell][crate::NcCell] @@ -230,8 +230,8 @@ impl Notcurses { /// Immediate effect (no need for a call to notcurses_render()). /// /// *C style function: [notcurses_cursor_disable()][crate::notcurses_cursor_disable].* - pub fn cursor_disable(&mut self) -> NcIntResult { - unsafe { crate::notcurses_cursor_disable(self) } + pub fn cursor_disable(&mut self) -> NcResult<()> { + error![unsafe { crate::notcurses_cursor_disable(self) }] } /// Enables the terminal's cursor, if supported, placing it at `y`, `x`. @@ -240,8 +240,8 @@ impl Notcurses { /// It is an error if `y`, `x` lies outside the standard plane. /// /// *C style function: [notcurses_cursor_enable()][crate::notcurses_cursor_enable].* - pub fn cursor_enable(&mut self, y: NcDimension, x: NcDimension) -> NcIntResult { - unsafe { crate::notcurses_cursor_enable(self, y as i32, x as i32) } + pub fn cursor_enable(&mut self, y: NcDimension, x: NcDimension) -> NcResult<()> { + error![unsafe { crate::notcurses_cursor_enable(self, y as i32, x as i32) }] } /// Dumps Notcurses state to the supplied `debugfp`. @@ -284,7 +284,7 @@ impl Notcurses { time: Option, sigmask: Option<&mut NcSignalSet>, input: Option<&mut NcInput>, - ) -> Option { + ) -> NcResult { let ntime; if let Some(time) = time { ntime = &time as *const _; @@ -308,9 +308,9 @@ impl Notcurses { core::char::from_u32_unchecked(crate::notcurses_getc(self, ntime, nsigmask, ninput)) }; if c as u32 as i32 == NCRESULT_ERR { - return None; + return Err(NcError::new(NCRESULT_ERR)); } - Some(c) + Ok(c) } /// @@ -334,20 +334,19 @@ impl Notcurses { /// with stdin (but it might be!). /// /// *C style function: [notcurses_inputready_fd()][crate::notcurses_inputready_fd].* - pub fn inputready_fd(&mut self) -> NcIntResult { - unsafe { crate::notcurses_inputready_fd(self) } + pub fn inputready_fd(&mut self) -> NcResult<()> { + error![unsafe { crate::notcurses_inputready_fd(self) }] } /// Returns an [NcBlitter] from a string representation. /// /// *C style function: [notcurses_lex_blitter()][crate::notcurses_lex_blitter].* - pub fn lex_blitter(op: &str) -> Option { + pub fn lex_blitter(op: &str) -> NcResult { let mut blitter = 0; - let res = unsafe { crate::notcurses_lex_blitter(cstring![op], &mut blitter) }; - if res == NCRESULT_OK { - return Some(blitter); - } - None + error![ + unsafe { crate::notcurses_lex_blitter(cstring![op], &mut blitter) }, + blitter, "Invalid blitter name" + ] } /// Lexes a margin argument according to the standard Notcurses definition. @@ -356,36 +355,35 @@ impl Notcurses { /// or there can be four numbers separated by commas. /// /// *C style function: [notcurses_lex_margins()][crate::notcurses_lex_margins].* - pub fn lex_margins(op: &str, options: &mut NotcursesOptions) -> NcIntResult { - unsafe { crate::notcurses_lex_margins(cstring![op], options) } + pub fn lex_margins(op: &str, options: &mut NotcursesOptions) -> NcResult<()> { + error![unsafe { crate::notcurses_lex_margins(cstring![op], options) }] } /// Returns an [NcScale] from a string representation. /// /// *C style function: [notcurses_lex_scalemode()][crate::notcurses_lex_scalemode].* - pub fn lex_scalemode(op: &str) -> Option { + pub fn lex_scalemode(op: &str) -> NcResult { let mut scalemode = 0; - let res = unsafe { crate::notcurses_lex_scalemode(cstring![op], &mut scalemode) }; - if res == NCRESULT_OK { - return Some(scalemode); - } - None + error![ + unsafe { crate::notcurses_lex_scalemode(cstring![op], &mut scalemode) }, + scalemode + ] } /// Disables signals originating from the terminal's line discipline, i.e. /// SIGINT (^C), SIGQUIT (^), and SIGTSTP (^Z). They are enabled by default. /// /// *C style function: [notcurses_linesigs_disable()][crate::notcurses_linesigs_disable].* - pub fn linesigs_disable(&mut self) -> NcIntResult { - unsafe { crate::notcurses_linesigs_disable(self) } + pub fn linesigs_disable(&mut self) -> NcResult<()> { + error![unsafe { crate::notcurses_linesigs_disable(self) }] } /// Restores signals originating from the terminal's line discipline, i.e. /// SIGINT (^C), SIGQUIT (^), and SIGTSTP (^Z), if disabled. /// /// *C style function: [notcurses_linesigs_enable()][crate::notcurses_linesigs_enable].* - pub fn linesigs_enable(&mut self) -> NcIntResult { - unsafe { crate::notcurses_linesigs_enable(self) } + pub fn linesigs_enable(&mut self) -> NcResult<()> { + error![unsafe { crate::notcurses_linesigs_enable(self) }] } /// Disables mouse events. @@ -393,8 +391,8 @@ impl Notcurses { /// Any events in the input queue can still be delivered. /// /// *C style function: [notcurses_mouse_disable()][crate::notcurses_mouse_disable].* - pub fn mouse_disable(&mut self) -> NcIntResult { - unsafe { crate::notcurses_mouse_disable(self) } + pub fn mouse_disable(&mut self) -> NcResult<()> { + error![unsafe { crate::notcurses_mouse_disable(self) }] } /// Enable the mouse in "button-event tracking" mode with focus detection @@ -404,8 +402,8 @@ impl Notcurses { /// published to [getc()][Notcurses#method.getc]. /// /// *C style function: [notcurses_mouse_enable()][crate::notcurses_mouse_enable].* - pub fn mouse_enable(&mut self) -> NcIntResult { - unsafe { crate::notcurses_mouse_enable(self) } + pub fn mouse_enable(&mut self) -> NcResult<()> { + error![unsafe { crate::notcurses_mouse_enable(self) }] } /// Returns the number of simultaneous colors claimed to be supported, @@ -429,16 +427,19 @@ impl Notcurses { /// /// *C style function: [notcurses_refresh()][crate::notcurses_refresh].* // - // TODO: try returning Result<(NcDimension, NcDimension), NcIntResult> - pub fn refresh(&mut self, y: &mut NcDimension, x: &mut NcDimension) -> NcIntResult { - unsafe { crate::notcurses_refresh(self, &mut (*y as i32), &mut (*x as i32)) } + pub fn refresh(&mut self) -> NcResult<(NcDimension, NcDimension)> { + let (mut y, mut x) = (0, 0); + error![ + unsafe { crate::notcurses_refresh(self, &mut y, &mut x) }, + (y as NcDimension, x as NcDimension) + ] } /// Renders and rasterizes the standard pile in one shot. Blocking call. /// /// *C style function: [notcurses_render()][crate::notcurses_render].* - pub fn render(&mut self) -> NcIntResult { - unsafe { crate::notcurses_render(self) } + pub fn render(&mut self) -> NcResult<()> { + error![unsafe { crate::notcurses_render(self) }] } /// Performs the rendering and rasterization portion of @@ -453,10 +454,10 @@ impl Notcurses { /// *C style function: [notcurses_render_to_buffer()][crate::notcurses_render_to_buffer].* // // CHECK that this works. - pub fn render_to_buffer(&mut self, buffer: &mut Vec) -> NcIntResult { + pub fn render_to_buffer(&mut self, buffer: &mut Vec) -> NcResult<()> { let mut len = buffer.len() as u64; let mut buf = buffer.as_mut_ptr() as *mut i8; - unsafe { crate::notcurses_render_to_buffer(self, &mut buf, &mut len) } + error![unsafe { crate::notcurses_render_to_buffer(self, &mut buf, &mut len) }] } /// Writes the last rendered frame, in its entirety, to 'fp'. @@ -465,8 +466,8 @@ impl Notcurses { /// nothing will be written. /// /// *C style function: [notcurses_render_to_file()][crate::notcurses_render_to_file].* - pub fn render_to_file(&mut self, fp: &mut NcFile) -> NcIntResult { - unsafe { crate::notcurses_render_to_file(self, fp.as_nc_ptr()) } + pub fn render_to_file(&mut self, fp: &mut NcFile) -> NcResult<()> { + error![unsafe { crate::notcurses_render_to_file(self, fp.as_nc_ptr()) }] } /// Acquires an atomic snapshot of the Notcurses object's stats.