use std::convert::TryInto;
use std::error::Error;
use std::ffi::CString;
use std::os::raw::{c_char,c_int,c_void};
use std::{char,ptr};
use newt_sys::*;
use crate::component::Component;
use crate::widgets::{Entry,Form};
use crate::Callback;
use crate::callbacks::DestroyCallback;
use crate::callbacks::EntryFilter;
use crate::callbacks::HelpCallback;
use crate::callbacks::SuspendCallback;
use crate::data::Data;
use crate::private::Child;
pub fn malloc_failure() -> ! {
panic!("memory allocation failed");
}
pub unsafe
fn c_ptr_array_to_boxed_slice<D>(ptr: *const *const c_void, numitems: i32)
-> Box<[D]> where D: Data
{
let mut vec: Vec<D> = Vec::with_capacity(numitems as usize);
if !ptr.is_null() && numitems > 0 {
let mut count = 0;
let mut p = ptr;
while count < numitems {
vec.push(D::newt_from_ptr(*p));
p = p.add(std::mem::size_of::<c_void>());
count += 1;
}
}
vec.into_boxed_slice()
}
pub fn char_to_c_char(ch: char) -> c_char {
let result: Result<c_char, Box<dyn Error>> =
match TryInto::<u8>::try_into(ch) {
Ok(ch) => match TryInto::<c_char>::try_into(ch) {
Ok(ch) => Ok(ch),
Err(e) => Err(Box::new(e))
},
Err(e) => Err(Box::new(e))
};
match result {
Ok(ch) => ch,
Err(e) => panic!("cannot convert `char` {} to `c_char: {}`", ch, e)
}
}
pub fn char_slice_to_cstring(slice: &[char]) -> CString {
let len = slice.len();
let mut vec: Vec<u8> = Vec::with_capacity(len);
for ch in slice.iter() {
vec.push(char_to_c_char(*ch) as u8);
}
let string = String::from_utf8_lossy(vec.as_slice());
CString::new(string.into_owned()).unwrap()
}
unsafe extern "C"
fn callback<'a, F, T>(co: newtComponent, data: *mut c_void)
where
F: 'a + FnMut(&dyn Component, Option<&T>),
T: 'a
{
let cb = &mut *(data as *mut Callback<'a, F, T>);
cb.call(co);
}
unsafe extern "C"
fn destroy_callback<'a, F, T>(co: newtComponent, data: *mut c_void)
where
F: 'a + FnMut(&dyn Component, Option<&T>),
T: 'a
{
let cb = &mut *(data as *mut DestroyCallback<'a, F, T>);
cb.call(co);
newt_unset_destroy_callback(co);
}
unsafe extern "C"
fn help_callback<F, T>(co: newtComponent, data: *mut c_void)
where
F: FnMut(&Form, Option<&T>)
{
if data.is_null() { return; };
let cb = &mut *(data as *mut HelpCallback<F, T>);
let form = Form::new_co(co);
form.add_to_parent().unwrap();
cb.call(&form);
}
unsafe extern "C"
fn suspend_callback<F, T>(data: *mut c_void)
where
F: FnMut(Option<&T>)
{
let cb = &mut *(data as *mut SuspendCallback<F, T>);
cb.call();
}
unsafe extern "C"
fn entry_filter<'a, F, T>(
entry: newtComponent,
data: *mut c_void,
ch: c_int,
cursor: c_int
) -> i32
where
F: 'a + FnMut(&Entry, Option<&T>, char, i32) -> char,
T: 'a
{
let cb = &mut *(data as *mut EntryFilter<'a, F, T>);
let ch = char::from_u32(ch as u32).unwrap();
cb.call(entry, ch, cursor) as i32
}
pub unsafe fn newt_set_callback<'a, F, T>(
co: newtComponent,
cb: &Callback<'a, F, T>
)
where
F: 'a + FnMut(&dyn Component, Option<&T>),
T: 'a
{
let c_ptr = cb as *const _ as *mut c_void;
newtComponentAddCallback(co, Some(callback::<F, T>), c_ptr);
}
pub unsafe fn newt_unset_callback(co: &dyn Component)
{
newtComponentAddCallback(co.co(), None, ptr::null_mut());
}
pub unsafe fn newt_set_destroy_callback<'a, F, T>
(co: newtComponent,
cb: &DestroyCallback<'a, F, T>)
where
F: 'a + FnMut(&dyn Component, Option<&T>),
T: 'a
{
let c_ptr = cb as *const _ as *mut c_void;
newtComponentAddDestroyCallback(co, Some(destroy_callback::<F, T>), c_ptr);
}
pub unsafe fn newt_unset_destroy_callback(co: newtComponent)
{
newtComponentAddDestroyCallback(co, None, ptr::null_mut());
}
pub unsafe fn newt_init_help_callback<F, T>()
where
F: FnMut(&Form, Option<&T>)
{
newtSetHelpCallback(Some(help_callback::<F, T>));
}
pub unsafe fn newt_set_suspend_callback<F, T>(cb: &SuspendCallback<F, T>)
where
F: FnMut(Option<&T>)
{
let c_ptr = cb as *const _ as *mut c_void;
newtSetSuspendCallback(Some(suspend_callback::<F, T>), c_ptr);
}
pub unsafe fn newt_unset_suspend_callback()
{
newtSetSuspendCallback(None, ptr::null_mut());
}
pub unsafe fn newt_entry_set_filter<'a, F, T>(
co: newtComponent,
cb: &EntryFilter<'a, F, T>
)
where
F: 'a + FnMut(&Entry, Option<&T>, char, i32) -> char,
T: 'a
{
let c_ptr = cb as *const _ as *mut c_void;
newtEntrySetFilter(co, Some(entry_filter::<F, T>), c_ptr)
}