extern crate pancurses; extern crate rand; use pancurses::*; use rand::Rng; const AUS_MAP: [&str; 13] = [ " A ", " AA AA ", " N.T. AAAAA AAAA ", " AAAAAAAAAAA AAAAAAAA ", " AAAAAAAAAAAAAAAAAAAAAAAAA Qld.", " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ", " AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ", " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ", " AAAAAAAAAAAAAAAAAAAAAAAAA N.S.W.", "W.A. AAAAAAAAA AAAAAA Vic.", " AAA S.A. AA", " A Tas.", "", ]; const MESSAGES: [&str; 6] = [ "Hello from the Land Down Under", "The Land of crocs, and a big Red Rock", "Where the sunflower runs along the highways", "The dusty red roads lead one to loneliness", "Blue sky in the morning and", "Freezing nights and twinkling stars", ]; fn main() { let main_window = initscr(); start_color(); use_default_colors(); cbreak(); noecho(); curs_set(0); // Refresh stdscr so that reading from it will not cause it to overwrite the other windows // that are being created main_window.refresh(); // Create a drawing window let width = 48; let height = 15; let win = newwin( height, width, (main_window.get_max_y() - height) / 2, (main_window.get_max_x() - width) / 2, ); loop { init_pair(1, COLOR_WHITE, COLOR_BLUE); win.bkgd(COLOR_PAIR(1)); win.erase(); init_pair(2, COLOR_RED, COLOR_RED); win.attrset(ColorPair(2)); win.draw_box(' ', ' '); win.refresh(); win.attrset(Attribute::Normal); // Do random output of a character let mut ch = 'a'; main_window.nodelay(true); let mut rng = rand::thread_rng(); for i in 0..5000 { let x = (rng.gen::() % (width - 2)).abs() + 1; let y = (rng.gen::() % (height - 2)).abs() + 1; assert!(x != 0); assert!(y != 0); win.mvaddch(y, x, ch); win.refresh(); if main_window.getch().is_some() { break; } if i == 2000 { ch = 'b'; init_pair(3, COLOR_CYAN, COLOR_YELLOW); win.attrset(ColorPair(3)); } } main_window.nodelay(false); sub_win_test(&main_window, &win).unwrap(); // Erase and draw green window init_pair(4, COLOR_YELLOW, COLOR_GREEN); win.bkgd(COLOR_PAIR(4)); win.attrset(Attribute::Bold); win.erase(); win.refresh(); // Draw RED bounding box win.attrset(ColorPair(2)); win.draw_box(' ', ' '); win.refresh(); // Display Australia map win.attrset(Attribute::Bold); for (i, s) in AUS_MAP.iter().enumerate() { win.mvaddstr(i as i32 + 1, 8, s); win.refresh(); napms(100); } init_pair(5, COLOR_BLUE, COLOR_WHITE); win.attrset(ColorPair(5) | Attribute::Blink); win.mvaddstr(height - 2, 3, " pancurses - Linux, Win32"); win.refresh(); // Draw running messages init_pair(6, COLOR_BLACK, COLOR_WHITE); win.attrset(ColorPair(6)); let w = width - 2; win.nodelay(true); // jbuhler's re-hacked scrolling messages for message in &MESSAGES { let msg_len = message.len() as i32; let mut visbuf = String::with_capacity(w as usize); let mut stop = false; for i in (0..w + msg_len).rev() { visbuf.clear(); for visbuf_i in 0..visbuf.capacity() { let i = i - msg_len as i32; let char_index = visbuf_i as i32 - i; let ch = if char_index >= 0 && char_index < message.len() as i32 { let char_index = char_index as usize; message[char_index..char_index + 1].chars().next().unwrap_or(' ') } else { ' ' }; visbuf.push(ch); } win.mvaddstr(height / 2, 1, &visbuf); win.refresh(); if win.getch().is_some() { flushinp(); stop = true; break; } napms(100); } if stop { break; } } // Draw running 'A's across in RED init_pair(7, COLOR_RED, COLOR_GREEN); win.attron(ColorPair(7)); let mut save: [chtype; 80] = [0; 80]; for (index, pos) in (2..width - 4).enumerate() { let ch = win.mvinch(5, pos); save[index] = ch; let ch = ch & 0x7F; win.mvaddch(5, pos, ch); } win.refresh(); // Put a message up; wait for a key let i = height - 2; win.attrset(ColorPair(5)); win.mvaddstr(i, 3, " Type a key to continue or ESC to quit "); win.refresh(); if wait_for_user(&main_window) { break; } // Restore the old line win.attrset(Attribute::Normal); for (index, pos) in (2..width - 4).enumerate() { win.mvaddch(5, pos, save[index]); } win.refresh(); bouncing_balls(&main_window, &win, &mut rng); // bouncing_balls() leaves a keystroke in the queue if wait_for_user(&main_window) { break; } } endwin(); } fn wait_for_user(main_window: &Window) -> bool { main_window.nodelay(true); half_delay(50); let ch = main_window.getch(); main_window.nodelay(false); nocbreak(); // Reset the halfdelay() value cbreak(); matches!(ch, Some(Input::Character('\x1B'))) } fn sub_win_test(main_window: &Window, win: &Window) -> Result<(), i32> { win.attrset(Attribute::Normal); let (h, w) = win.get_max_yx(); let (by, bx) = win.get_beg_yx(); let sw = w / 3; let sh = h / 3; let swin1 = win.derwin(sh, sw, 3, 5)?; let swin2 = win.subwin(sh, sw, by + 4, bx + 8)?; let swin3 = win.subwin(sh, sw, by + 5, bx + 11)?; init_pair(8, COLOR_RED, COLOR_BLUE); swin1.bkgd(COLOR_PAIR(8)); swin1.erase(); swin1.mvaddstr(0, 3, "Sub-window 1"); swin1.refresh(); init_pair(9, COLOR_CYAN, COLOR_MAGENTA); swin2.bkgd(COLOR_PAIR(9)); swin2.erase(); swin2.mvaddstr(0, 3, "Sub-window 2"); swin2.refresh(); init_pair(10, COLOR_YELLOW, COLOR_GREEN); swin3.bkgd(COLOR_PAIR(10)); swin3.erase(); swin3.mvaddstr(0, 3, "Sub-window 3"); swin3.refresh(); swin1.delwin(); swin2.delwin(); swin3.delwin(); wait_for_user(main_window); Ok(()) } fn bouncing_balls(main_window: &Window, win: &Window, rng: &mut T) { curs_set(0); win.bkgd(COLOR_PAIR(1)); win.refresh(); win.attrset(Attribute::Normal); init_pair(11, COLOR_RED, COLOR_GREEN); init_pair(12, COLOR_BLUE, COLOR_RED); init_pair(13, COLOR_YELLOW, COLOR_WHITE); let ball1 = 'O' as chtype | COLOR_PAIR(11); let ball2 = '*' as chtype | COLOR_PAIR(12); let ball3 = '@' as chtype | COLOR_PAIR(13); let (h, w) = win.get_max_yx(); let mut x1 = 2 + (rng.gen::() % (w - 4)).abs(); let mut y1 = 2 + (rng.gen::() % (h - 4)).abs(); let mut x2 = 2 + (rng.gen::() % (w - 4)).abs(); let mut y2 = 2 + (rng.gen::() % (h - 4)).abs(); let mut x3 = 2 + (rng.gen::() % (w - 4)).abs(); let mut y3 = 2 + (rng.gen::() % (h - 4)).abs(); let mut xd1 = 1; let mut yd1 = 1; let mut xd2 = 1; let mut yd2 = -1; let mut xd3 = -1; let mut yd3 = 1; main_window.nodelay(true); let mut c = main_window.getch(); while c.is_none() { x1 += xd1; if x1 <= 1 || x1 >= w - 2 { xd1 *= -1; } y1 += yd1; if y1 <= 1 || y1 >= h - 2 { yd1 *= -1; } x2 += xd2; if x2 <= 1 || x2 >= w - 2 { xd2 *= -1; } y2 += yd2; if y2 <= 1 || y2 >= h - 2 { yd2 *= -1; } x3 += xd3; if x3 <= 1 || x3 >= w - 2 { xd3 *= -1; } y3 += yd3; if y3 <= 1 || y3 >= h - 2 { yd3 *= -1; } let c1 = win.mvinch(y1, x1); let c2 = win.mvinch(y2, x2); let c3 = win.mvinch(y3, x3); win.mvaddch(y1, x1, ball1); win.mvaddch(y2, x2, ball2); win.mvaddch(y3, x3, ball3); win.mv(0, 0); win.refresh(); win.mvaddch(y1, x1, c1); win.mvaddch(y2, x2, c2); win.mvaddch(y3, x3, c3); napms(150); c = main_window.getch(); } main_window.nodelay(false); c.map(|c| main_window.ungetch(&c)); }