ansi parser: PtyView to display cursor & scrolling

This commit is contained in:
Michael Sippel 2021-11-18 17:47:29 +01:00
parent 4ab20be1c5
commit ef1a477d4a
Signed by: senvas
GPG key ID: F96CF119C34B64A6

View file

@ -8,30 +8,45 @@ use {
std::io::Read, std::io::Read,
//async_std::{io::{Read, ReadExt}}, //async_std::{io::{Read, ReadExt}},
crate::{ crate::{
core::{InnerViewPort, OuterViewPort}, core::{View, InnerViewPort, OuterViewPort, ViewPort, Observer, ObserverBroadcast},
projection::ProjectionHelper,
terminal::{ terminal::{
TerminalAtom, TerminalAtom,
TerminalStyle, TerminalStyle,
TerminalView TerminalView
}, },
index::buffer::IndexBuffer singleton::{
SingletonBuffer,
SingletonView
},
index::{
buffer::IndexBuffer,
IndexView,
IndexArea
}
}, },
cgmath::Point2, cgmath::{Vector2, Point2},
vte::{Params, Parser, Perform} vte::{Params, Parser, Perform}
}; };
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, port: InnerViewPort<dyn TerminalView>) { pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, port: InnerViewPort<dyn TerminalView>) {
let mut statemachine = Parser::new(); let mut statemachine = Parser::new();
let buf_port = ViewPort::new();
let size_port = ViewPort::<dyn SingletonView<Item = Vector2<i16>>>::new();
let cursor_port = ViewPort::<dyn SingletonView<Item = Point2<i16>>>::new();
let offset_port = ViewPort::<dyn SingletonView<Item = Vector2<i16>>>::new();
let mut performer = PerfAtom { let mut performer = PerfAtom {
cursor: Point2::new(0, 0), buf: IndexBuffer::new(buf_port.inner()),
style: TerminalStyle::default(), size: SingletonBuffer::new(Vector2::new(120, 40), size_port.inner()),
invert: false, offset: SingletonBuffer::new(Vector2::new(0, 0), offset_port.inner()),
term_width: 120, cursor: SingletonBuffer::new(Point2::new(0, 0), cursor_port.inner()),
cursty: TerminalStyle::default(),
cursor_save: Point2::new(0, 0), curinv: false,
cursav: Point2::new(0, 0),
buf: IndexBuffer::new(port),
colors: ColorPalett { colors: ColorPalett {
black: (1, 1, 1), black: (1, 1, 1),
@ -42,7 +57,16 @@ pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, port: InnerViewPort<
magenta: (118, 38, 113), magenta: (118, 38, 113),
cyan: (44, 181, 233), cyan: (44, 181, 233),
white: (204, 204, 204) white: (204, 204, 204)
} },
pty_proj: PtyView::new(
buf_port.outer(),
cursor_port.outer().map(|x| Some(x)),
offset_port.outer().map(|x| Some(x)),
size_port.outer().map(|x| Some(x)),
port
)
}; };
let mut buf = [0; 2048]; let mut buf = [0; 2048];
@ -63,6 +87,22 @@ pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, port: InnerViewPort<
} }
} }
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
enum TTYColor {
Rgb(u8, u8, u8),
// 3-Bit/4-Bit colors
Black, LightBlack,
Red, LightRed,
Green, LightGreen,
Yellow, LightYellow,
Blue, LightBlue,
Magenta,LightMagenta,
Cyan, LightCyan,
White, LightWhite,
}
struct ColorPalett { struct ColorPalett {
black: (u8, u8, u8), black: (u8, u8, u8),
red: (u8, u8, u8), red: (u8, u8, u8),
@ -71,84 +111,279 @@ struct ColorPalett {
blue: (u8, u8, u8), blue: (u8, u8, u8),
magenta: (u8, u8, u8), magenta: (u8, u8, u8),
cyan: (u8, u8, u8), cyan: (u8, u8, u8),
white: (u8, u8, u8) white: (u8, u8, u8),
} }
impl ColorPalett {
fn get_rgb(&self, col: &TTYColor) -> (u8, u8, u8) {
match col {
TTYColor::Rgb(r,g,b) => (*r,*g,*b),
TTYColor::Black | TTYColor::LightBlack => self.black,
TTYColor::Red | TTYColor::LightRed => self.red,
TTYColor::Green | TTYColor::LightGreen => self.green,
TTYColor::Yellow | TTYColor::LightYellow => self.yellow,
TTYColor::Blue | TTYColor::LightBlue => self.blue,
TTYColor::Magenta | TTYColor::LightMagenta => self.magenta,
TTYColor::Cyan | TTYColor::LightCyan => self.cyan,
TTYColor::White | TTYColor::LightWhite => self.white,
}
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
/// Display Cursor & scrolling
struct PtyView {
buf: Arc<dyn IndexView<Point2<i16>, Item = TerminalAtom>>,
curpos: Arc<dyn SingletonView<Item = Option<Point2<i16>>>>,
offset: Arc<dyn SingletonView<Item = Option<Vector2<i16>>>>,
size: Arc<dyn SingletonView<Item = Option<Vector2<i16>>>>,
old_offset: Vector2<i16>,
old_curpos: Point2<i16>,
old_size: Vector2<i16>,
max_pt: Point2<i16>,
cast: Arc<RwLock<ObserverBroadcast<dyn TerminalView>>>,
proj_helper: ProjectionHelper<usize, Self>
}
impl View for PtyView {
type Msg = IndexArea<Point2<i16>>;
}
impl IndexView<Point2<i16>> for PtyView {
type Item = TerminalAtom;
fn get(&self, pt: &Point2<i16>) -> Option<TerminalAtom> {
let atom = self.buf.get(&(pt + self.old_offset));
if self.old_curpos == *pt {
if let Some(mut a) = atom {
let bg_col = a.style.fg_color.unwrap_or((255,255,255));
let fg_col = a.style.bg_color.unwrap_or((0,0,0));
a.style.fg_color = Some(fg_col);
a.style.bg_color = Some(bg_col);
Some(a)
} else {
Some(TerminalAtom::new(' ', TerminalStyle::bg_color((255, 255, 255))))
}
} else {
atom
}
}
fn area(&self) -> IndexArea<Point2<i16>> {
IndexArea::Range(Point2::new(0, 0) ..= Point2::new(
std::cmp::max(self.old_curpos.x, self.max_pt.x),
std::cmp::max(self.old_curpos.y, self.max_pt.y)
))
}
}
impl PtyView {
fn new(
buf_port: OuterViewPort<dyn IndexView<Point2<i16>, Item = TerminalAtom>>,
curpos_port: OuterViewPort<dyn SingletonView<Item = Option<Point2<i16>>>>,
offset_port: OuterViewPort<dyn SingletonView<Item = Option<Vector2<i16>>>>,
size_port: OuterViewPort<dyn SingletonView<Item = Option<Vector2<i16>>>>,
out_port: InnerViewPort<dyn TerminalView>
) -> Arc<RwLock<Self>> {
let mut proj_helper = ProjectionHelper::new(out_port.0.update_hooks.clone());
let proj = Arc::new(RwLock::new(
PtyView {
old_curpos: Point2::new(0, 0),
old_size: Vector2::new(0, 0),
old_offset: Vector2::new(0, 0),
max_pt: Point2::new(0, 0),
curpos: proj_helper.new_singleton_arg(
0,
curpos_port,
|s: &mut Self, _msg| {
s.cast.notify(&IndexArea::Set(vec![ s.old_curpos ]));
s.old_curpos = s.curpos.get().unwrap_or(Point2::new(0,0));
s.cast.notify(&IndexArea::Set(vec![ s.old_curpos ]));
}),
offset: proj_helper.new_singleton_arg(
1,
offset_port,
|s: &mut Self, _msg| {
// todo
let new_offset = s.offset.get().unwrap_or(Vector2::new(0, 0));
if s.old_offset != new_offset {
s.old_offset = new_offset;
s.cast.notify(&s.area());
}
}),
size: proj_helper.new_singleton_arg(
2,
size_port,
|s: &mut Self, _msg| {
let new_size = s.size.get().unwrap_or(Vector2::new(0, 0));
if s.old_size != new_size {
s.old_size = new_size;
s.cast.notify(&s.area());
}
}),
buf: proj_helper.new_index_arg(
3,
buf_port,
|s: &mut Self, area| {
let size = s.old_size;
let area = area.map(
|pt| {
*pt - s.old_offset
}
);
if s.max_pt.x < size.x || s.max_pt.y < size.y {
match &area {
IndexArea::Empty => {}
IndexArea::Full => {}
IndexArea::Range(_) => {}
IndexArea::Set(v) => {
let mx = v.iter().map(|pt| pt.x).max().unwrap_or(0);
if mx > s.max_pt.x && mx < size.x {
s.max_pt.x = mx;
}
let my = v.iter().map(|pt| pt.y).max().unwrap_or(0);
if my > s.max_pt.y && my < size.y {
s.max_pt.y = my;
}
}
}
}
s.cast.notify(&area);
}),
cast: out_port.get_broadcast(),
proj_helper
}
));
proj.write().unwrap().proj_helper.set_proj(&proj);
out_port.set_view(Some(proj.clone()));
proj
}
}
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
struct PerfAtom { struct PerfAtom {
colors: ColorPalett,
term_width: i16,
cursor: Point2<i16>,
style: TerminalStyle,
invert: bool,
cursor_save: Point2<i16>,
buf: IndexBuffer<Point2<i16>, TerminalAtom>, buf: IndexBuffer<Point2<i16>, TerminalAtom>,
size: SingletonBuffer<Vector2<i16>>,
offset: SingletonBuffer<Vector2<i16>>,
cursor: SingletonBuffer<Point2<i16>>,
cursty: TerminalStyle,
curinv: bool,
cursav: Point2<i16>,
colors: ColorPalett,
pty_proj: Arc<RwLock<PtyView>>
} }
impl PerfAtom { impl PerfAtom {
fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) { fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) {
if let Some(mut a) = atom { if let Some(mut a) = atom {
self.buf.insert(pos, a); self.buf.insert(pos + self.offset.get(), a);
} else { } else {
self.buf.remove(pos); self.buf.remove(pos);
} }
} }
fn get_style(&self) -> TerminalStyle { fn get_style(&self) -> TerminalStyle {
let mut style = self.style; let mut style = self.cursty;
if self.invert { if self.curinv {
style.fg_color = Some(self.style.bg_color.unwrap_or(self.colors.black)); style.fg_color = Some(self.cursty.bg_color.unwrap_or(self.colors.black));
style.bg_color = Some(self.style.fg_color.unwrap_or(self.colors.white)); style.bg_color = Some(self.cursty.fg_color.unwrap_or(self.colors.white));
} }
style style
} }
fn set_fg_color(&mut self, col: &TTYColor) {
self.cursty = self.cursty.add(TerminalStyle::fg_color(self.colors.get_rgb(col)));
}
fn set_bg_color(&mut self, col: &TTYColor) {
self.cursty = self.cursty.add(TerminalStyle::bg_color(self.colors.get_rgb(col)));
}
fn linefeed(&mut self) { fn linefeed(&mut self) {
self.cursor.x = 0; let size = self.size.get();
self.cursor.y += 1; let mut c = self.cursor.get_mut();
c.x = 0;
if c.y+1 >= size.y {
self.scroll_up(1);
} else {
c.y += 1;
}
} }
fn carriage_return(&mut self) { fn carriage_return(&mut self) {
self.cursor.x = 0; let mut c = self.cursor.get_mut();
c.x = 0;
} }
fn horizontal_tab(&mut self) { fn horizontal_tab(&mut self) {
self.cursor.x += 8 - (self.cursor.x % 8); let mut c = self.cursor.get_mut();
c.x += 8 - (c.x % 8);
} }
fn backspace(&mut self) { fn backspace(&mut self) {
self.write_atom(self.cursor, None); //self.write_atom(self.cursor.get(), None);
self.cursor.x -= 1; let mut c = self.cursor.get_mut();
if self.cursor.x < 0 { c.x -= 1;
self.cursor.y -= 0; if c.x < 0 {
self.cursor.x = self.term_width - 1; c.y -= 0;
c.x = self.size.get().x - 1;
} }
} }
fn cursor_up(&mut self, n: usize) { fn cursor_up(&mut self, n: usize) {
self.cursor.get_mut().y -= n as i16;
} }
fn cursor_down(&mut self, n: usize) { fn cursor_dn(&mut self, n: usize) {
self.cursor.get_mut().y += n as i16;
// todo: scroll ?
}
fn scroll_up(&mut self, n: usize) {
self.offset.get_mut().y += n as i16;
}
fn scroll_dn(&mut self, n: usize) {
self.offset.get_mut().y -= n as i16;
} }
fn save_cursor_position(&mut self) { fn save_cursor_position(&mut self) {
self.cursor_save = self.cursor; self.cursav = self.cursor.get();
} }
fn restore_cursor_position(&mut self) { fn restore_cursor_position(&mut self) {
self.cursor = self.cursor_save; self.cursor.set(self.cursav);
} }
} }
impl Perform for PerfAtom { impl Perform for PerfAtom {
fn print(&mut self, c: char) { fn print(&mut self, ch: char) {
self.write_atom(self.cursor, Some(TerminalAtom::new(c, self.get_style()))); let mut c = self.cursor.get_mut();
self.write_atom(*c, Some(TerminalAtom::new(ch, self.get_style())));
self.cursor.x += 1; c.x += 1;
if self.cursor.x >= self.term_width { if c.x >= self.size.get().x {
self.cursor.x = 0; self.linefeed();
self.cursor.y += 1;
} }
} }
@ -192,44 +427,61 @@ impl Perform for PerfAtom {
'm' => while let Some(n) = piter.next() { 'm' => while let Some(n) = piter.next() {
match n[0] { match n[0] {
0 => { 0 => {
self.style = TerminalStyle::default(); self.cursty = TerminalStyle::default();
self.invert = false; self.curinv = false;
} }
1 => self.style = self.style.add(TerminalStyle::bold(true)), 1 => self.cursty = self.cursty.add(TerminalStyle::bold(true)),
3 => self.style = self.style.add(TerminalStyle::italic(true)), 3 => self.cursty = self.cursty.add(TerminalStyle::italic(true)),
4 => self.style = self.style.add(TerminalStyle::underline(true)), 4 => self.cursty = self.cursty.add(TerminalStyle::underline(true)),
7 => self.invert = true, 7 => self.curinv = true,
27 => self.invert = false, 27 => self.curinv = false,
30 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.black)), 30 => self.set_fg_color(&TTYColor::Black),
40 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.black)), 40 => self.set_bg_color(&TTYColor::Black),
31 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.red)), 90 => self.set_fg_color(&TTYColor::LightBlack),
41 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.red)), 100 => self.set_bg_color(&TTYColor::LightBlack),
32 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.green)), 31 => self.set_fg_color(&TTYColor::Red),
42 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.green)), 41 => self.set_bg_color(&TTYColor::Red),
33 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.yellow)), 91 => self.set_fg_color(&TTYColor::LightRed),
43 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.yellow)), 101 => self.set_bg_color(&TTYColor::LightRed),
34 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.blue)), 32 => self.set_fg_color(&TTYColor::Green),
44 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.blue)), 42 => self.set_bg_color(&TTYColor::Green),
35 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.magenta)), 92 => self.set_fg_color(&TTYColor::LightGreen),
45 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.magenta)), 102 => self.set_bg_color(&TTYColor::LightGreen),
36 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.cyan)), 33 => self.set_fg_color(&TTYColor::Yellow),
46 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.cyan)), 43 => self.set_bg_color(&TTYColor::Yellow),
37 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.white)), 93 => self.set_fg_color(&TTYColor::LightYellow),
47 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.white)), 103 => self.set_bg_color(&TTYColor::LightYellow),
34 => self.set_fg_color(&TTYColor::Blue),
44 => self.set_bg_color(&TTYColor::Blue),
94 => self.set_fg_color(&TTYColor::LightBlue),
104 => self.set_bg_color(&TTYColor::LightBlue),
35 => self.set_fg_color(&TTYColor::Magenta),
45 => self.set_bg_color(&TTYColor::Magenta),
95 => self.set_fg_color(&TTYColor::LightMagenta),
105 => self.set_bg_color(&TTYColor::LightMagenta),
36 => self.set_fg_color(&TTYColor::Cyan),
46 => self.set_bg_color(&TTYColor::Cyan),
96 => self.set_fg_color(&TTYColor::LightCyan),
106 => self.set_bg_color(&TTYColor::LightCyan),
37 => self.set_fg_color(&TTYColor::White),
47 => self.set_bg_color(&TTYColor::White),
97 => self.set_fg_color(&TTYColor::LightWhite),
107 => self.set_bg_color(&TTYColor::LightWhite),
38 => { 38 => {
let x = piter.next().unwrap(); let x = piter.next().unwrap();
match x[0] { match x[0] {
2 => { 2 => {
let r = piter.next().unwrap(); let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap(); let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap(); let b = piter.next().unwrap()[0] as u8;
self.style = self.style.add(TerminalStyle::fg_color((r[0] as u8, g[0] as u8, b[0] as u8))) self.set_fg_color(&TTYColor::Rgb(r,g,b));
}, },
5 => { 5 => {
let v = piter.next().unwrap(); let v = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::fg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8);
self.set_fg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2));
}, },
_ => {} _ => {}
} }
@ -238,14 +490,15 @@ impl Perform for PerfAtom {
let x = piter.next().unwrap(); let x = piter.next().unwrap();
match x[0] { match x[0] {
2 => { 2 => {
let r = piter.next().unwrap(); let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap(); let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap(); let b = piter.next().unwrap()[0] as u8;
self.style = self.style.add(TerminalStyle::bg_color((r[0] as u8, g[0] as u8, b[0] as u8))) self.set_bg_color(&TTYColor::Rgb(r,g,b));
}, },
5 => { 5 => {
let v = piter.next().unwrap(); let v = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::bg_color(ansi_colours::rgb_from_ansi256(v[0] as u8))) let rgb = ansi_colours::rgb_from_ansi256(v[0] as u8);
self.set_bg_color(&TTYColor::Rgb(rgb.0, rgb.1, rgb.2));
}, },
_ => {} _ => {}
} }
@ -255,53 +508,52 @@ impl Perform for PerfAtom {
} }
} }
'@' => { '@' => {
for x in self.cursor.x .. self.term_width { let c = self.cursor.get();
self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.style))); for x in c.x .. self.size.get().x {
} self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.cursty)));
}
'A' => {
self.cursor.y -= piter.next().unwrap_or(&[1])[0] as i16;
}
'B' => {
self.cursor.y += piter.next().unwrap_or(&[1])[0] as i16;
if self.cursor.x >= self.term_width {
self.cursor.x = 0;
} }
} }
'A' => { self.cursor_up(piter.next().unwrap_or(&[1])[0] as usize); }
'B' => { self.cursor_dn(piter.next().unwrap_or(&[1])[0] as usize); }
'C' | 'a' => { 'C' | 'a' => {
self.cursor.x += piter.next().unwrap_or(&[1])[0] as i16; let mut c = self.cursor.get_mut();
if self.cursor.x >= self.term_width { c.x += piter.next().unwrap_or(&[1])[0] as i16;
self.cursor.y += self.cursor.x / self.term_width; if c.x >= self.size.get().x {
self.cursor.x %= self.term_width; c.y += c.x / self.size.get().x;
c.x %= self.size.get().x;
} }
} }
'D' => { 'D' => {
self.cursor.x -= piter.next().unwrap_or(&[1])[0] as i16; let mut c = self.cursor.get_mut();
if self.cursor.x < 0 { c.x -= piter.next().unwrap_or(&[1])[0] as i16;
self.cursor.x = self.term_width - 1; if c.x < 0 {
self.cursor.y -= 1; c.x = self.size.get().x - 1;
c.y -= 1;
} }
} }
'd' => { 'd' => {
self.cursor.y = piter.next().unwrap_or(&[1])[0] as i16 - 1; self.cursor.get_mut().y = piter.next().unwrap_or(&[1])[0] as i16 - 1;
} }
'E' => { 'E' => {
if self.cursor.x >= self.term_width { let mut c = self.cursor.get_mut();
self.cursor.y += 1; if c.x >= self.size.get().x {
c.y += 1;
} }
self.cursor.x = 0; c.x = 0;
self.cursor.y += piter.next().unwrap_or(&[1])[0] as i16; c.y += piter.next().unwrap_or(&[1])[0] as i16;
} }
'F' => { 'F' => {
self.cursor.x = 0; let mut c = self.cursor.get_mut();
self.cursor.y -= piter.next().unwrap_or(&[1])[0] as i16; c.x = 0;
c.y -= piter.next().unwrap_or(&[1])[0] as i16;
} }
'G' | '`' => { 'G' | '`' => {
self.cursor.x = piter.next().unwrap_or(&[1])[0] as i16 - 1; self.cursor.get_mut().x = piter.next().unwrap_or(&[1])[0] as i16 - 1;
} }
'H' | 'f' => { 'H' | 'f' => {
self.cursor.y = piter.next().unwrap_or(&[1])[0] as i16 - 1; let mut c = self.cursor.get_mut();
self.cursor.x = piter.next().unwrap_or(&[1])[0] as i16 - 1; c.y = piter.next().unwrap_or(&[1])[0] as i16 - 1;
c.x = piter.next().unwrap_or(&[1])[0] as i16 - 1;
} }
'J' => { 'J' => {
let x = piter.next().unwrap_or(&[0 as u16; 1]); let x = piter.next().unwrap_or(&[0 as u16; 1]);
@ -309,13 +561,13 @@ impl Perform for PerfAtom {
// clear from cursor until end of screen // clear from cursor until end of screen
0 => { 0 => {
let mut pos = self.cursor; let mut pos = self.cursor.get();
while pos.y < 100 { while pos.y < 100 {
self.write_atom(pos, None); self.write_atom(pos, None);
pos.x += 1; pos.x += 1;
if pos.x >= self.term_width { if pos.x >= self.size.get().x {
pos.x = 0; pos.x = 0;
pos.y += 1; pos.y += 1;
} }
@ -324,13 +576,13 @@ impl Perform for PerfAtom {
// clear from cursor to begin // clear from cursor to begin
1 => { 1 => {
let mut pos = self.cursor; let mut pos = self.cursor.get();
while pos.y >= 0 || pos.x >= 0 { while pos.y >= 0 || pos.x >= 0 {
self.write_atom(pos, None); self.write_atom(pos, None);
pos.x -= 1; pos.x -= 1;
if pos.x < 0 { if pos.x < 0 {
pos.x = self.term_width; pos.x = self.size.get().x;
pos.y -= 1; pos.y -= 1;
} }
} }
@ -341,12 +593,12 @@ impl Perform for PerfAtom {
// erase entire screen // erase entire screen
2 => { 2 => {
for y in 0 .. 100 { for y in 0 .. 100 {
for x in 0 .. self.term_width { for x in 0 .. self.size.get().x {
self.write_atom(Point2::new(x, y), None); self.write_atom(Point2::new(x, y), None);
} }
} }
self.cursor = Point2::new(0, 0); self.cursor.set(Point2::new(0, 0));
} }
// invalid // invalid
@ -359,22 +611,25 @@ impl Perform for PerfAtom {
// clear from cursor until end of line // clear from cursor until end of line
0 => { 0 => {
for x in self.cursor.x .. self.term_width { let c = self.cursor.get();
self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style()))); for x in c.x .. self.size.get().x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style())));
} }
}, },
// clear from start of line until cursor // clear from start of line until cursor
1 => { 1 => {
for x in 0 .. self.cursor.x { let c = self.cursor.get();
self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style()))); for x in 0 .. c.x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style())));
} }
}, },
// clear entire line // clear entire line
2 => { 2 => {
for x in 0 .. self.term_width { let c = self.cursor.get();
self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style()))); for x in 0 .. self.size.get().x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style())));
} }
}, },
@ -386,7 +641,7 @@ impl Perform for PerfAtom {
'M' => { 'M' => {
let n = piter.next().unwrap_or(&[1])[0] as i16; let n = piter.next().unwrap_or(&[1])[0] as i16;
for y in 0 .. n { for y in 0 .. n {
for x in 0 .. self.term_width { for x in 0 .. self.size.get().x {
self.write_atom(Point2::new(x, self.cursor.y+y), None); self.write_atom(Point2::new(x, self.cursor.y+y), None);
} }
} }
@ -401,14 +656,11 @@ impl Perform for PerfAtom {
self.write_atom(Point2::new(self.cursor.x + x as i16, self.cursor.y), None); self.write_atom(Point2::new(self.cursor.x + x as i16, self.cursor.y), None);
} }
} }
*/ */
's' => { 'S' => { self.scroll_up(piter.next().unwrap_or(&[1])[0] as usize); }
self.save_cursor_position(); 'T' => { self.scroll_dn(piter.next().unwrap_or(&[1])[0] as usize); }
} 's' => { self.save_cursor_position(); }
'u' => { 'u' => { self.restore_cursor_position(); }
self.restore_cursor_position();
}
_ => { _ => {
/* /*
eprintln!( eprintln!(
@ -421,7 +673,6 @@ impl Perform for PerfAtom {
} }
fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) { fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
match (byte, intermediates) { match (byte, intermediates) {
//(b'B', intermediates) => configure_charset!(StandardCharset::Ascii, intermediates), //(b'B', intermediates) => configure_charset!(StandardCharset::Ascii, intermediates),
(b'D', []) => self.linefeed(), (b'D', []) => self.linefeed(),