use std::{ptr, fmt, hash::{Hash, Hasher}};
use ncursesw::{
form, form::{FIELD, FIELDTYPE},
shims::bindings::{
TYPE_ALPHA, TYPE_ALNUM, TYPE_ENUM, TYPE_INTEGER, TYPE_NUMERIC, TYPE_REGEXP, TYPE_IPV4,
va_list
}
};
use crate::NCurseswWinError;
lazy_static! {
pub static ref FIELDTYPE_ALPHA: FieldType = FieldType::_from(unsafe { TYPE_ALPHA }, false);
pub static ref FIELDTYPE_ALNUM: FieldType = FieldType::_from(unsafe { TYPE_ALNUM }, false);
pub static ref FIELDTYPE_ENUM: FieldType = FieldType::_from(unsafe { TYPE_ENUM }, false);
pub static ref FIELDTYPE_INTEGER: FieldType = FieldType::_from(unsafe { TYPE_INTEGER }, false);
pub static ref FIELDTYPE_NUMERIC: FieldType = FieldType::_from(unsafe { TYPE_NUMERIC }, false);
pub static ref FIELDTYPE_REGEXP: FieldType = FieldType::_from(unsafe { TYPE_REGEXP }, false);
pub static ref FIELDTYPE_IPV4: FieldType = FieldType::_from(unsafe { TYPE_IPV4 }, false);
}
pub struct FieldType {
handle: FIELDTYPE, free_on_drop: bool
}
impl FieldType {
pub(in crate::form) fn _from(handle: FIELDTYPE, free_on_drop: bool) -> Self {
assert!(!handle.is_null(), "FieldType::_from() : handle.is_null()");
Self { handle, free_on_drop }
}
pub(in crate::form) fn _handle(&self) -> FIELDTYPE {
self.handle
}
}
impl FieldType {
pub fn new(
field_check: unsafe extern "C" fn(_: FIELD, _: *const libc::c_void) -> bool,
char_check: unsafe extern "C" fn(_: i32, _: *const libc::c_void) -> bool
) -> result!(Self)
{
Ok(Self::_from(form::new_fieldtype(field_check, char_check)?, true))
}
#[deprecated(since = "0.4.1", note = "Use FieldType::new() instead")]
pub fn new_fieldtype(
field_check: unsafe extern "C" fn(_: FIELD, _: *const libc::c_void) -> bool,
char_check: unsafe extern "C" fn(_: i32, _: *const libc::c_void) -> bool
) -> result!(Self)
{
Self::new(field_check, char_check)
}
pub fn link_fieldtype(&self, fieldtype: &Self) -> result!(Self) {
Ok(Self::_from(form::link_fieldtype(self.handle, fieldtype._handle())?, true))
}
pub fn set_fieldtype_arg(
&self,
make_arg: unsafe extern "C" fn(_: *mut va_list) -> *mut libc::c_void,
copy_arg: Option<unsafe extern "C" fn(_: *const libc::c_void) -> *mut libc::c_void>,
free_arg: Option<unsafe extern "C" fn(_: *mut libc::c_void)>
) -> result!(())
{
Ok(form::set_fieldtype_arg(self.handle, make_arg, copy_arg, free_arg)?)
}
pub fn set_fieldtype_choice(
&self,
next_choice: unsafe extern "C" fn(_: FIELD, _: *const libc::c_void) -> bool,
prev_choice: unsafe extern "C" fn(_: FIELD, _: *const libc::c_void) -> bool
) -> result!(())
{
Ok(form::set_fieldtype_choice(self.handle, next_choice, prev_choice)?)
}
}
impl Drop for FieldType {
fn drop(&mut self) {
if self.free_on_drop {
if let Err(source) = form::free_fieldtype(self.handle) {
panic!("{} @ {:?}", source, self)
}
}
}
}
unsafe impl Send for FieldType { } unsafe impl Sync for FieldType { }
impl PartialEq for FieldType {
fn eq(&self, rhs: &Self) -> bool {
ptr::eq(self.handle, rhs.handle)
}
}
impl Eq for FieldType { }
impl Hash for FieldType {
fn hash<H: Hasher>(&self, state: &mut H) {
self.handle.hash(state);
}
}
impl AsRef<FieldType> for FieldType {
fn as_ref(&self) -> &Self {
self
}
}
impl AsMut<FieldType> for FieldType {
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl Clone for FieldType {
fn clone(&self) -> Self {
Self { handle: self.handle.clone(), free_on_drop: false }
}
}
impl fmt::Debug for FieldType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "FieldType {{ handle: {:p}, free_on_drop: {} }}", self.handle, self.free_on_drop)
}
}