use std::ffi::c_void; use crate::bindings; use crate::util; pub struct Menu { ptr: *mut bindings::Menuwidget, data: *mut bindings::Menudata, } pub struct Data { items: Vec, } pub struct Item { text: String, hotkey: i32, func: Option, } pub enum KeyResult { Handled, Ignored, Quit, Called, } impl Menu { pub fn new(lefttop: (u32, u32), data: Data) -> Menu { unsafe { let mdata = util::malloc::(1); let mitems = util::malloc::(data.items.len()); (*mdata).nitems = data.items.len() as i32; (*mdata).items = mitems; for i in 0..data.items.len() { (*mitems.add(i)).text = util::strdup(&data.items[i].text); (*mitems.add(i)).hotkey = data.items[i].hotkey; (*mitems.add(i)).func = data.items[i].func; } Menu { ptr: bindings::menu_make( lefttop.0 as i32, lefttop.1 as i32, mdata), data: mdata, } } } pub fn redraw(&self) { unsafe { bindings::menu_redraw(self.ptr); } } pub fn handle_key(&mut self, key: i32) -> KeyResult { match unsafe { bindings::menu_handlekey(self.ptr, key) } { bindings::Menukey_MENUKEY_HANDLED => KeyResult::Handled, bindings::Menukey_MENUKEY_IGNORED => KeyResult::Ignored, bindings::Menukey_MENUKEY_QUIT => KeyResult::Quit, bindings::Menukey_MENUKEY_CALLED => KeyResult::Called, _ => panic!("Invalid Menukey received from termio"), } } } impl Drop for Menu { fn drop(&mut self) { unsafe { bindings::menu_destroy(self.ptr); let nitems = (*self.data).nitems as usize; let mitems = (*self.data).items; for i in 0..nitems { libc::free((*mitems.add(i)).text as *mut c_void); } libc::free(mitems as *mut c_void); libc::free(self.data as *mut c_void); } } }