use std::ffi::CString;
use std::os::raw::c_char;
use std::ffi::CStr;
use std::mem::size_of;
use std::os::raw::{c_int,c_void};
use newt_sys::*;
#[doc(no_inline)]
pub use crate::asm::win_menu_new;
#[doc(no_inline)]
pub use crate::asm::win_entries_new;
#[derive(Default)]
pub struct WinEntry {
pub(crate) text: CString,
pub(crate) value: String,
pub(crate) flags: c_int
}
impl WinEntry {
pub fn new(text: &str, value: &str, flags: i32) -> WinEntry {
WinEntry {
text: CString::new(text).unwrap(),
value: String::from(value),
flags
}
}
pub fn value(&self) -> &str {
self.value.as_str()
}
}
pub(crate) struct WinEntryBuf<'a> {
#[allow(dead_code)]
values_text: Vec<CString>,
entries: &'a mut [WinEntry],
entries_buf: *mut newtWinEntry,
values_buf: *mut *mut c_char
}
impl<'a> WinEntryBuf<'a> {
pub fn new(entries: &'a mut [WinEntry]) -> WinEntryBuf<'a> {
unsafe {
let entries_len = entries.len();
let mut values_text = Vec::with_capacity(entries_len);
let size = size_of::<newtWinEntry>() * (entries_len + 1);
let entries_buf = libc::malloc(size) as *mut newtWinEntry;
libc::memset(entries_buf as *mut c_void, 0, size);
let size = size_of::<*mut c_char>() * (entries_len);
let values_buf = libc::malloc(size) as *mut *mut c_char;
libc::memset(values_buf as *mut c_void, 0, size);
for (i, entry) in entries.iter().enumerate() {
let entry_buf = entries_buf.add(i);
let value_buf = values_buf.add(i);
let value = CString::new(entry.value.as_str()).unwrap();
*value_buf = value.as_ptr() as *mut c_char;
(*entry_buf).text = entry.text.as_ptr() as *mut c_char;
(*entry_buf).value = value_buf;
(*entry_buf).flags = entry.flags;
values_text.push(value);
}
WinEntryBuf { values_text, entries, entries_buf, values_buf }
}
}
pub fn as_mut_ptr(&mut self) -> *mut newtWinEntry {
self.entries_buf
}
}
impl<'a> Drop for WinEntryBuf<'a> {
fn drop(&mut self) {
unsafe {
for (i, entry) in self.entries.iter_mut().enumerate() {
let buf = self.entries_buf.add(i);
let value = CStr::from_ptr(*(*buf).value).to_str().unwrap();
entry.value = String::from(value);
libc::free(*(*buf).value as *mut c_void);
}
libc::free(self.entries_buf as *mut c_void);
libc::free(self.values_buf as *mut c_void);
}
}
}
#[allow(clippy::too_many_arguments)]
pub fn win_menu(title: &str, text: &str, suggested_width: i32, flex_down: i32,
flex_up: i32, max_list_height: i32, items: &[&str],
buttons: &[&str]) -> (i32, i32)
{
unsafe {
win_menu_new(
title,
text,
suggested_width,
flex_down,
flex_up,
max_list_height,
items,
buttons
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn win_entries(title: &str, text: &str, suggested_width: i32, flex_down: i32,
flex_up: i32, data_width: i32, entries: &mut [WinEntry],
buttons: &[&str]) -> i32
{
unsafe {
win_entries_new(
title,
text,
suggested_width,
flex_down,
flex_up,
data_width,
entries,
buttons
)
}
}