appcui 0.4.8

A feature-rich and cross-platform TUI/CUI framework for Rust, enabling modern terminal-based applications on Windows, Linux, and macOS. Includes built-in UI components like buttons, menus, list views, tree views, checkboxes, and more. Perfect for building fast and interactive CLI tools and text-based interfaces.
Documentation
use super::api;
use super::constants;
use super::structs::*;
use crate::graphics::{Point, Size};

#[derive(Clone)]
pub(super) struct OriginalScreen {
    stdout: HANDLE,
    size: Size,
    pos: Point,
    data: Vec<CHAR_INFO>,
    cursor_pos: COORD,
}

impl OriginalScreen {
    pub(super) fn new(stdout: HANDLE, size: Size, x: i32, y: i32, cursor_pos: COORD) -> Option<Self> {
        let sz = size.width as usize * size.height as usize;
        let mut v: Vec<CHAR_INFO> = Vec::with_capacity(sz);
        v.fill(CHAR_INFO { code: 0, attr: 0 });
        let mut sr = SMALL_RECT {
            left: x as i16,
            top: y as i16,
            right: ((x + size.width as i32) - 1) as i16,
            bottom: ((y + size.height as i32) - 1) as i16,
        };
        unsafe {
            if api::ReadConsoleOutputW(
                stdout,
                v.as_mut_ptr(),
                COORD {
                    x: size.width as i16,
                    y: size.height as i16,
                },
                COORD { x: 0, y: 0 },
                &mut sr,
            ) == constants::FALSE
            {
                return None;
            }
        }
        Some(Self {
            stdout,
            size,
            pos: Point::new(x, y),
            data: v,
            cursor_pos,
        })
    }
    pub(super) fn restore(self) {
        let sr = SMALL_RECT {
            left: self.pos.x as i16,
            top: self.pos.y as i16,
            right: ((self.pos.x + self.size.width as i32) - 1) as i16,
            bottom: ((self.pos.y + self.size.height as i32) - 1) as i16,
        };
        unsafe {
            api::WriteConsoleOutputW(
                self.stdout,
                self.data.as_ptr(),
                COORD {
                    x: self.size.width as i16,
                    y: self.size.height as i16,
                },
                COORD { x: 0, y: 0 },
                &sr,
            );
            api::SetConsoleCursorPosition(self.stdout, self.cursor_pos);
            let ci = CONSOLE_CURSOR_INFO { size: 10, visible: constants::TRUE };
            api::SetConsoleCursorInfo(self.stdout, &ci);
        }
    }
}