Skip to content

Instantly share code, notes, and snippets.

@cretz
Created February 13, 2016 07:45
Show Gist options
  • Save cretz/4586b6afa140a13c4b2f to your computer and use it in GitHub Desktop.
Save cretz/4586b6afa140a13c4b2f to your computer and use it in GitHub Desktop.
Simple PDCurses Window Movement in Rust
extern crate libc;
use libc::{c_ulong, c_int, c_char};
use std::ffi::{CString};
#[allow(non_camel_case_types)]
pub type c_bool = ::libc::c_uchar;
pub type Chtype = c_ulong;
pub type Window = *mut i8;
pub type CharP = *const c_char;
trait ToCStr {
fn to_c_str(&self) -> CString;
}
impl <'a>ToCStr for &'a str {
fn to_c_str(&self) -> CString {
CString::new(*self).unwrap()
}
}
// From: https://github.com/rust-lang/rfcs/issues/1010#issuecomment-169712438
macro_rules! finally {
($contents:block) => {
struct A;
impl Drop for A {
fn drop(&mut self) {
{ $contents };
}
}
let a = A;
};
}
#[link(name = "pdcurses", kind = "static")]
extern {
fn initscr() -> Window;
fn endwin() -> c_int;
fn noecho() -> c_int;
fn cbreak() -> c_int;
fn curs_set(_: c_int) -> c_int;
fn waddstr(_: Window, _: CharP) -> c_int;
fn wnoutrefresh(_: Window) -> c_int;
fn getmaxx(_: Window) -> c_int;
fn getmaxy(_: Window) -> c_int;
fn newwin(_: c_int, _: c_int, _: c_int, _: c_int) -> Window;
fn keypad(_: Window, _: c_bool) -> c_int;
fn werase(_: Window) -> c_int;
fn mvwin(_: Window, _: c_int, _: c_int) -> c_int;
#[link_name="box"]
fn box_(_: Window, _: Chtype, _: Chtype) -> c_int;
fn doupdate() -> c_int;
fn wgetch(_: Window) -> c_int;
}
const ERR: i32 = -1;
const VLINE: Chtype = '|' as Chtype;
const HLINE: Chtype = '-' as Chtype;
const KEY_Q: c_int = 'q' as c_int;
const KEY_DOWN: i32 = 0x102;
const KEY_UP: i32 = 0x103;
const KEY_LEFT: i32 = 0x104;
const KEY_RIGHT: i32 = 0x105;
fn main() {
// From: https://github.com/rthornton128/goncurses/blob/master/examples/window/window.go
unsafe {
let stdscr = initscr();
finally! {{ unsafe { endwin(); } }}
assert!(!stdscr.is_null());
noecho();
cbreak();
assert!(curs_set(0) != ERR);
waddstr(stdscr, "Use arrow keys to move the window. Press 'q' to exit".to_c_str().as_ptr());
wnoutrefresh(stdscr);
let (rows, cols) = (getmaxy(stdscr), getmaxx(stdscr));
let (height, width) = (5, 10);
let (mut y, mut x) = ((rows - height) / 2, (cols - width) / 2);
let win = newwin(height, width, y, x);
assert!(!win.is_null());
assert!(keypad(win, true as c_bool) != ERR);
loop {
werase(win);
wnoutrefresh(win);
mvwin(win, y, x);
box_(win, VLINE, HLINE);
wnoutrefresh(win);
assert!(doupdate() != ERR);
match wgetch(win) {
KEY_Q => break,
KEY_LEFT if x > 0 => x -= 1,
KEY_RIGHT if x < cols - width => x += 1,
KEY_UP if y > 1 => y -= 1,
KEY_DOWN if y < rows - height => y += 1,
_ => (),
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment