Skip to content

Commit

Permalink
some \0 aka nul bytes in &str are deleted ...
Browse files Browse the repository at this point in the history
...before sending the &str to ncurses backend,
this is done for cursive's print_at() and print_at_rep() only!
otherwise, nothing would get printed, silently.

Why delete \0 instead of replace with eg. space?
this explains it best:
gyscos#778 (comment)

This also fixes warnings about unused Result.

Closes: gyscos#780
  • Loading branch information
correabuscar committed May 25, 2024
1 parent 1b633da commit aeb182e
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions cursive/src/backends/curses/n.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use ncurses;
use log::{debug, warn};
use ncurses::mmask_t;

use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::ffi::CString;
use std::fs::File;
Expand Down Expand Up @@ -398,22 +399,53 @@ impl backend::Backend for Backend {
ncurses::refresh();
}

fn print_at(&self, pos: Vec2, text: &str) {
ncurses::mvaddstr(pos.y as i32, pos.x as i32, text);
fn print_at<'a>(&self, pos: Vec2, text: &'a str) {
// Remove '\0' from &str or else nothing would get printed
// As for why delete instead of replace with eg. space, see:
// https://github.com/gyscos/cursive/pull/778#discussion_r1613859129
let text = &delete_nuls(text);
let len = text.len() as i32;
// Ignore the value to avoid warning: unused `Result` that must be used
let _ = ncurses::mvaddnstr(pos.y as i32, pos.x as i32, text.as_ref(), len);
}

fn print_at_rep(&self, pos: Vec2, repetitions: usize, text: &str) {
// Remove '\0' from &str or else nothing would get printed
let text = &delete_nuls(text);
let len = text.len() as i32;
if repetitions > 0 {
ncurses::mvaddstr(pos.y as i32, pos.x as i32, text);
let _ = ncurses::mvaddnstr(pos.y as i32, pos.x as i32, text, len);
let mut dupes_left = repetitions - 1;
while dupes_left > 0 {
ncurses::addstr(text);
let _ = ncurses::addnstr(text, len);
dupes_left -= 1;
}
}
}
}

#[inline(always)]
fn delete_nuls<'a>(text: &'a str) -> Cow<'a, str> {
let text: Cow<'a, str> = if text.contains('\0') {
Cow::Owned(text.replace('\0', ""))
} else {
Cow::Borrowed(text)
};
text
}

#[test]
fn test_print_at_rep_nul_char_in_string() {
let text = "Some\0thing with \0nul\0s\0 in \0it";
let expected = "Something with nuls in it";
assert_eq!(expected, delete_nuls(text));

let backend = Backend::init().unwrap();
// These don't panic, they replace the \0-es with nothing
backend.print_at(Vec2::new(10, 10), "abc\0de\0f");
backend.print_at_rep(Vec2::new(10, 10), 10, "abc\0de\0f");
}

/// Returns the Key enum corresponding to the given ncurses event.
fn get_mouse_button(bare_event: i32) -> MouseButton {
match bare_event {
Expand Down

0 comments on commit aeb182e

Please sign in to comment.