use core::libc::{c_char,c_int,c_long}; /// The default colors available on a terminal emulator. #[deriving(Eq)] pub enum Color { ColorBlack = 0, ColorRed, ColorGreen, ColorYellow, ColorBlue, ColorMagenta, ColorCyan, ColorWhite, } /** * Initialize the terminfo database. * * This must be called before any functions from this module are used. The * current terminal is determined by looking at the `TERM` environment * variable. */ pub fn init () { unsafe { c::setupterm(ptr::null(), 1, ptr::null()) }; } macro_rules! def_escape( ($name:ident -> $escape:expr) => ( pub fn $name () -> ~str { let attr = $escape; match escape(attr) { Some(e) => e, None => fail!(fmt!("%s is not supported on this terminal", attr)), } } ); ($name:ident -> $escape:expr, $ty1:ident) => ( pub fn $name (p1: $ty1) -> ~str { let attr = $escape; match escape1(attr, p1 as int) { Some(e) => e, None => fail!(fmt!("%s is not supported on this terminal", attr)), } } ); ($name:ident -> $escape:expr, $ty1:ident, $ty2:ident) => ( pub fn $name (p1: $ty1, p2: $ty2) -> ~str { let attr = $escape; match escape2(attr, p1 as int, p2 as int) { Some(e) => e, None => fail!(fmt!("%s is not supported on this terminal", attr)), } } ); ) // XXX macros can't take attributes yet (including documentation), so change // these to /// once that is fixed // The terminal escape to clear the screen. def_escape!(clear_screen -> "clear") // The terminal escape to set the foreground color to `p1`. def_escape!(set_a_foreground -> "setaf", Color) // The terminal escape to set the background color to `p1`. def_escape!(set_a_background -> "setab", Color) // The terminal escape to reset the foreground and background colors. def_escape!(orig_pair -> "op") // The terminal escape to reset all attributes. def_escape!(exit_attribute_mode -> "sgr0") // The terminal escape to move the cursor to the top left of the screen. def_escape!(cursor_home -> "home") // The terminal escape to move the cursor to (`p1`, `p2`). def_escape!(cursor_address -> "cup", uint, uint) // The terminal escape to enable underline mode. def_escape!(enter_underline_mode -> "smul") // The terminal escape to disable underline mode. def_escape!(exit_underline_mode -> "rmul") // The terminal escape to enable standout mode. def_escape!(enter_standout_mode -> "smso") // The terminal escape to disable standout mode. def_escape!(exit_standout_mode -> "rmso") // The terminal escape to enable reverse video mode. def_escape!(enter_reverse_mode -> "rev") // The terminal escape to enable bold mode. def_escape!(enter_bold_mode -> "bold") // The terminal escape to enable blink mode. def_escape!(enter_blink_mode -> "blink") // The terminal escape to make the cursor invisible. def_escape!(cursor_invisible -> "civis") // The terminal escape to make the cursor visible. def_escape!(cursor_normal -> "cnorm") // The terminal escape to enable the alternate screen. def_escape!(enter_ca_mode -> "smcup") // The terminal escape to disable the alternate screen. def_escape!(exit_ca_mode -> "rmcup") // The terminal escape to enter keypad mode. def_escape!(keypad_xmit -> "smkx") // The terminal escape to leave keypad mode. def_escape!(keypad_local -> "rmkx") // The terminal escape generated by the backspace key. def_escape!(key_backspace -> "kbs") // The terminal escape generated by the return key. def_escape!(carriage_return -> "cr") // The terminal escape generated by the tab key. def_escape!(tab -> "ht") // The terminal escape generated by the up arrow key. def_escape!(key_up -> "kcuu1") // The terminal escape generated by the down arrow key. def_escape!(key_down -> "kcud1") // The terminal escape generated by the left arrow key. def_escape!(key_left -> "kcub1") // The terminal escape generated by the right arrow key. def_escape!(key_right -> "kcuf1") // The terminal escape generated by the home key. def_escape!(key_home -> "khome") // The terminal escape generated by the end key. def_escape!(key_end -> "kend") // The terminal escape generated by the insert key. def_escape!(key_ic -> "kich1") // The terminal escape generated by the delete key. def_escape!(key_dc -> "kdch1") // The terminal escape generated by the F1 key. def_escape!(key_f1 -> "kf1") // The terminal escape generated by the F2 key. def_escape!(key_f2 -> "kf2") // The terminal escape generated by the F3 key. def_escape!(key_f3 -> "kf3") // The terminal escape generated by the F4 key. def_escape!(key_f4 -> "kf4") // The terminal escape generated by the F5 key. def_escape!(key_f5 -> "kf5") // The terminal escape generated by the F6 key. def_escape!(key_f6 -> "kf6") // The terminal escape generated by the F7 key. def_escape!(key_f7 -> "kf7") // The terminal escape generated by the F8 key. def_escape!(key_f8 -> "kf8") // The terminal escape generated by the F9 key. def_escape!(key_f9 -> "kf9") // The terminal escape generated by the F10 key. def_escape!(key_f10 -> "kf10") // The terminal escape generated by the F11 key. def_escape!(key_f11 -> "kf11") // The terminal escape generated by the F12 key. def_escape!(key_f12 -> "kf12") /// The terminal escape generated by the F<`n`> key. pub fn key_f (n: uint) -> ~str { let attr = fmt!("kf%?", n); match escape(attr) { Some(e) => e, None => fail!(fmt!("%s is not supported on this terminal", attr)), } } /// The terminal escape corresponding to the `name` terminfo capability. pub fn escape (name: &str) -> Option<~str> { do str::as_c_str(name) |c_name| { unsafe { let e = tigetstr(c_name); if e == ptr::null() { None } else { Some(str::raw::from_c_str(e)) } } } } /** * The terminal escape corresponding to the `name` terminfo capability. * * This capability must take one parameter, which should be passed as `p1`. */ pub fn escape1 (name: &str, p1: int) -> Option<~str> { do str::as_c_str(name) |c_name| { unsafe { let e = tigetstr(c_name); if e == ptr::null() { None } else { Some(str::raw::from_c_str(tparm1(e, p1))) } } } } /** * The terminal escape corresponding to the `name` terminfo capability. * * This capability must take two parameters, which should be passed as `p1` * and `p2`. */ pub fn escape2 (name: &str, p1: int, p2: int) -> Option<~str> { do str::as_c_str(name) |c_name| { unsafe { let e = tigetstr(c_name); if e == ptr::null() { None } else { Some(str::raw::from_c_str(tparm2(e, p1, p2))) } } } } unsafe fn tigetstr (name: *c_char) -> *c_char { let c_out = c::tigetstr(name); if c_out as int == -1 { fail!(fmt!("%s is not a terminal capability", unsafe { str::raw::from_c_str(name) })); } c_out } unsafe fn tparm1 (name: *c_char, p1: int) -> *c_char { let ret = c::tparm(name, p1 as c_long, 0, 0, 0, 0, 0, 0, 0, 0); if ret == ptr::null() { fail!(fmt!("Couldn't assemble parameters with %s %d", unsafe { str::raw::from_c_str(name) }, p1)); } ret } unsafe fn tparm2 (name: *c_char, p1: int, p2: int) -> *c_char { let ret = c::tparm(name, p1 as c_long, p2 as c_long, 0, 0, 0, 0, 0, 0, 0); if ret == ptr::null() { fail!(fmt!("Couldn't assemble parameters with %s %d %d", unsafe { str::raw::from_c_str(name) }, p1, p2)); } ret } #[link_name = "curses"] extern mod c { fn setupterm (term: *c_char, fd: c_int, errret: *c_int) -> c_int; fn tigetstr (s: *c_char) -> *c_char; fn tparm (s: *c_char, a1: c_long, a2: c_long, a3: c_long, a4: c_long, a5: c_long, a6: c_long, a7: c_long, a8: c_long, a9: c_long) -> *c_char; }