1use std::io::Write;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub struct Color (pub u8, pub u8, pub u8);
5
6#[derive(Debug, Clone)]
7pub struct Terminal {
8 width: usize,
9 height: usize,
10
11 ch: Box<[char]>,
12 fg: Box<[Color]>,
13 bg: Box<[Color]>
14}
15
16impl Terminal {
17 pub fn new() -> Self {
18 let mut win_size: libc::winsize = unsafe {std::mem::zeroed()};
19 unsafe {libc::ioctl(libc::STDOUT_FILENO, libc::TIOCGWINSZ, &mut win_size)};
20
21 let columns = win_size.ws_col as usize;
22 let rows = win_size.ws_row as usize;
23
24
25 let mut ch_buf = Vec::new();
26 ch_buf.resize(columns*rows, ' ');
27
28
29 let mut fg_buf = Vec::new();
30 fg_buf.resize(columns*rows, Color(0, 0, 0));
31
32 let mut bg_buf = Vec::new();
33 bg_buf.resize(columns*rows, Color(0, 0, 0));
34
35
36 Self {
37 width: columns,
38 height: rows,
39 ch: ch_buf.into_boxed_slice(),
40 fg: fg_buf.into_boxed_slice(),
41 bg: bg_buf.into_boxed_slice()
42 }
43 }
44
45 pub fn set_char(&mut self, x: usize, y: usize, ch: char) {
46 if !self.is_valid_coords(x, y) {return};
47 self.ch[y*self.width+x] = ch;
48 }
49
50 pub fn set_color_char(&mut self, x: usize, y: usize, ch: char, fg: Color, bg: Color) {
51 if !self.is_valid_coords(x, y) {return};
52 self.ch[y*self.width+x] = ch;
53 self.fg[y*self.width+x] = fg;
54 self.bg[y*self.width+x] = bg;
55 }
56
57 pub fn set_fg(&mut self, x: usize, y: usize, color: Color) {
58 if !self.is_valid_coords(x, y) {return};
59 self.fg[y*self.width+x] = color;
60 }
61
62 pub fn set_bg(&mut self, x: usize, y: usize, color: Color) {
63 if !self.is_valid_coords(x, y) {return};
64 self.bg[y*self.width+x] = color;
65 }
66
67 pub fn clear(&mut self, fg: Color, bg: Color) {
68 for y in 0..self.height {
69 for x in 0..self.width {
70 self.ch[y*self.width+x] = ' ';
71 self.fg[y*self.width+x] = fg;
72 self.bg[y*self.width+x] = bg;
73 }
74 }
75 }
76
77 pub fn display(&self) {
78 let mut output = String::new();
79
80 for y in 0..self.height {
81 for x in 0..self.width {
82 let fg = self.fg[y*self.width+x];
83 let bg = self.bg[y*self.width+x];
84
85 output += format!("\x1b[38;2;{};{};{}m\x1b[48;2;{};{};{}m{}", fg.0, fg.1, fg.2, bg.0, bg.1, bg.2, self.ch[y*self.width+x]).as_str();
86 }
87 if y < self.height-1 {output += "\n"};
88 }
89
90 print!("{}\x1b[m", output);
91
92 let _ = std::io::stdout().flush();
93 }
94
95 fn is_valid_coords(&self, x: usize, y: usize) -> bool {
96 x < self.width && y < self.height
97 }
98}