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,
//async_std::{io::{Read, ReadExt}},
crate::{
core::{InnerViewPort, OuterViewPort},
core::{View, InnerViewPort, OuterViewPort, ViewPort, Observer, ObserverBroadcast},
projection::ProjectionHelper,
terminal::{
TerminalAtom,
TerminalStyle,
TerminalView
},
index::buffer::IndexBuffer
singleton::{
SingletonBuffer,
SingletonView
},
cgmath::Point2,
index::{
buffer::IndexBuffer,
IndexView,
IndexArea
}
},
cgmath::{Vector2, Point2},
vte::{Params, Parser, Perform}
};
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
pub fn read_ansi_from<R: Read + Unpin>(ansi_reader: &mut R, port: InnerViewPort<dyn TerminalView>) {
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 {
cursor: Point2::new(0, 0),
style: TerminalStyle::default(),
invert: false,
term_width: 120,
cursor_save: Point2::new(0, 0),
buf: IndexBuffer::new(port),
buf: IndexBuffer::new(buf_port.inner()),
size: SingletonBuffer::new(Vector2::new(120, 40), size_port.inner()),
offset: SingletonBuffer::new(Vector2::new(0, 0), offset_port.inner()),
cursor: SingletonBuffer::new(Point2::new(0, 0), cursor_port.inner()),
cursty: TerminalStyle::default(),
curinv: false,
cursav: Point2::new(0, 0),
colors: ColorPalett {
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),
cyan: (44, 181, 233),
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];
@ -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 {
black: (u8, u8, u8),
red: (u8, u8, u8),
@ -71,84 +111,279 @@ struct ColorPalett {
blue: (u8, u8, u8),
magenta: (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 {
colors: ColorPalett,
term_width: i16,
cursor: Point2<i16>,
style: TerminalStyle,
invert: bool,
cursor_save: Point2<i16>,
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 {
fn write_atom(&mut self, pos: Point2<i16>, atom: Option<TerminalAtom>) {
if let Some(mut a) = atom {
self.buf.insert(pos, a);
self.buf.insert(pos + self.offset.get(), a);
} else {
self.buf.remove(pos);
}
}
fn get_style(&self) -> TerminalStyle {
let mut style = self.style;
if self.invert {
style.fg_color = Some(self.style.bg_color.unwrap_or(self.colors.black));
style.bg_color = Some(self.style.fg_color.unwrap_or(self.colors.white));
let mut style = self.cursty;
if self.curinv {
style.fg_color = Some(self.cursty.bg_color.unwrap_or(self.colors.black));
style.bg_color = Some(self.cursty.fg_color.unwrap_or(self.colors.white));
}
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) {
self.cursor.x = 0;
self.cursor.y += 1;
let size = self.size.get();
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) {
self.cursor.x = 0;
let mut c = self.cursor.get_mut();
c.x = 0;
}
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) {
self.write_atom(self.cursor, None);
self.cursor.x -= 1;
if self.cursor.x < 0 {
self.cursor.y -= 0;
self.cursor.x = self.term_width - 1;
//self.write_atom(self.cursor.get(), None);
let mut c = self.cursor.get_mut();
c.x -= 1;
if c.x < 0 {
c.y -= 0;
c.x = self.size.get().x - 1;
}
}
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) {
self.cursor_save = self.cursor;
self.cursav = self.cursor.get();
}
fn restore_cursor_position(&mut self) {
self.cursor = self.cursor_save;
self.cursor.set(self.cursav);
}
}
impl Perform for PerfAtom {
fn print(&mut self, c: char) {
self.write_atom(self.cursor, Some(TerminalAtom::new(c, self.get_style())));
fn print(&mut self, ch: char) {
let mut c = self.cursor.get_mut();
self.write_atom(*c, Some(TerminalAtom::new(ch, self.get_style())));
self.cursor.x += 1;
if self.cursor.x >= self.term_width {
self.cursor.x = 0;
self.cursor.y += 1;
c.x += 1;
if c.x >= self.size.get().x {
self.linefeed();
}
}
@ -192,44 +427,61 @@ impl Perform for PerfAtom {
'm' => while let Some(n) = piter.next() {
match n[0] {
0 => {
self.style = TerminalStyle::default();
self.invert = false;
self.cursty = TerminalStyle::default();
self.curinv = false;
}
1 => self.style = self.style.add(TerminalStyle::bold(true)),
3 => self.style = self.style.add(TerminalStyle::italic(true)),
4 => self.style = self.style.add(TerminalStyle::underline(true)),
7 => self.invert = true,
27 => self.invert = false,
1 => self.cursty = self.cursty.add(TerminalStyle::bold(true)),
3 => self.cursty = self.cursty.add(TerminalStyle::italic(true)),
4 => self.cursty = self.cursty.add(TerminalStyle::underline(true)),
7 => self.curinv = true,
27 => self.curinv = false,
30 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.black)),
40 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.black)),
31 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.red)),
41 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.red)),
32 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.green)),
42 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.green)),
33 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.yellow)),
43 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.yellow)),
34 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.blue)),
44 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.blue)),
35 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.magenta)),
45 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.magenta)),
36 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.cyan)),
46 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.cyan)),
37 => self.style = self.style.add(TerminalStyle::fg_color(self.colors.white)),
47 => self.style = self.style.add(TerminalStyle::bg_color(self.colors.white)),
30 => self.set_fg_color(&TTYColor::Black),
40 => self.set_bg_color(&TTYColor::Black),
90 => self.set_fg_color(&TTYColor::LightBlack),
100 => self.set_bg_color(&TTYColor::LightBlack),
31 => self.set_fg_color(&TTYColor::Red),
41 => self.set_bg_color(&TTYColor::Red),
91 => self.set_fg_color(&TTYColor::LightRed),
101 => self.set_bg_color(&TTYColor::LightRed),
32 => self.set_fg_color(&TTYColor::Green),
42 => self.set_bg_color(&TTYColor::Green),
92 => self.set_fg_color(&TTYColor::LightGreen),
102 => self.set_bg_color(&TTYColor::LightGreen),
33 => self.set_fg_color(&TTYColor::Yellow),
43 => self.set_bg_color(&TTYColor::Yellow),
93 => self.set_fg_color(&TTYColor::LightYellow),
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 => {
let x = piter.next().unwrap();
match x[0] {
2 => {
let r = piter.next().unwrap();
let g = piter.next().unwrap();
let b = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::fg_color((r[0] as u8, g[0] as u8, b[0] as u8)))
let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap()[0] as u8;
self.set_fg_color(&TTYColor::Rgb(r,g,b));
},
5 => {
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();
match x[0] {
2 => {
let r = piter.next().unwrap();
let g = piter.next().unwrap();
let b = piter.next().unwrap();
self.style = self.style.add(TerminalStyle::bg_color((r[0] as u8, g[0] as u8, b[0] as u8)))
let r = piter.next().unwrap()[0] as u8;
let g = piter.next().unwrap()[0] as u8;
let b = piter.next().unwrap()[0] as u8;
self.set_bg_color(&TTYColor::Rgb(r,g,b));
},
5 => {
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 {
self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.style)));
}
}
'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;
let c = self.cursor.get();
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_up(piter.next().unwrap_or(&[1])[0] as usize); }
'B' => { self.cursor_dn(piter.next().unwrap_or(&[1])[0] as usize); }
'C' | 'a' => {
self.cursor.x += piter.next().unwrap_or(&[1])[0] as i16;
if self.cursor.x >= self.term_width {
self.cursor.y += self.cursor.x / self.term_width;
self.cursor.x %= self.term_width;
let mut c = self.cursor.get_mut();
c.x += piter.next().unwrap_or(&[1])[0] as i16;
if c.x >= self.size.get().x {
c.y += c.x / self.size.get().x;
c.x %= self.size.get().x;
}
}
'D' => {
self.cursor.x -= piter.next().unwrap_or(&[1])[0] as i16;
if self.cursor.x < 0 {
self.cursor.x = self.term_width - 1;
self.cursor.y -= 1;
let mut c = self.cursor.get_mut();
c.x -= piter.next().unwrap_or(&[1])[0] as i16;
if c.x < 0 {
c.x = self.size.get().x - 1;
c.y -= 1;
}
}
'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' => {
if self.cursor.x >= self.term_width {
self.cursor.y += 1;
let mut c = self.cursor.get_mut();
if c.x >= self.size.get().x {
c.y += 1;
}
self.cursor.x = 0;
self.cursor.y += piter.next().unwrap_or(&[1])[0] as i16;
c.x = 0;
c.y += piter.next().unwrap_or(&[1])[0] as i16;
}
'F' => {
self.cursor.x = 0;
self.cursor.y -= piter.next().unwrap_or(&[1])[0] as i16;
let mut c = self.cursor.get_mut();
c.x = 0;
c.y -= piter.next().unwrap_or(&[1])[0] as i16;
}
'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' => {
self.cursor.y = piter.next().unwrap_or(&[1])[0] as i16 - 1;
self.cursor.x = piter.next().unwrap_or(&[1])[0] as i16 - 1;
let mut c = self.cursor.get_mut();
c.y = piter.next().unwrap_or(&[1])[0] as i16 - 1;
c.x = piter.next().unwrap_or(&[1])[0] as i16 - 1;
}
'J' => {
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
0 => {
let mut pos = self.cursor;
let mut pos = self.cursor.get();
while pos.y < 100 {
self.write_atom(pos, None);
pos.x += 1;
if pos.x >= self.term_width {
if pos.x >= self.size.get().x {
pos.x = 0;
pos.y += 1;
}
@ -324,13 +576,13 @@ impl Perform for PerfAtom {
// clear from cursor to begin
1 => {
let mut pos = self.cursor;
let mut pos = self.cursor.get();
while pos.y >= 0 || pos.x >= 0 {
self.write_atom(pos, None);
pos.x -= 1;
if pos.x < 0 {
pos.x = self.term_width;
pos.x = self.size.get().x;
pos.y -= 1;
}
}
@ -341,12 +593,12 @@ impl Perform for PerfAtom {
// erase entire screen
2 => {
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.cursor = Point2::new(0, 0);
self.cursor.set(Point2::new(0, 0));
}
// invalid
@ -359,22 +611,25 @@ impl Perform for PerfAtom {
// clear from cursor until end of line
0 => {
for x in self.cursor.x .. self.term_width {
self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style())));
let c = self.cursor.get();
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
1 => {
for x in 0 .. self.cursor.x {
self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style())));
let c = self.cursor.get();
for x in 0 .. c.x {
self.write_atom(Point2::new(x, c.y), Some(TerminalAtom::new(' ', self.get_style())));
}
},
// clear entire line
2 => {
for x in 0 .. self.term_width {
self.write_atom(Point2::new(x, self.cursor.y), Some(TerminalAtom::new(' ', self.get_style())));
let c = self.cursor.get();
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' => {
let n = piter.next().unwrap_or(&[1])[0] as i16;
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);
}
}
@ -401,14 +656,11 @@ impl Perform for PerfAtom {
self.write_atom(Point2::new(self.cursor.x + x as i16, self.cursor.y), None);
}
}
*/
's' => {
self.save_cursor_position();
}
'u' => {
self.restore_cursor_position();
}
*/
'S' => { self.scroll_up(piter.next().unwrap_or(&[1])[0] as usize); }
'T' => { self.scroll_dn(piter.next().unwrap_or(&[1])[0] as usize); }
's' => { self.save_cursor_position(); }
'u' => { self.restore_cursor_position(); }
_ => {
/*
eprintln!(
@ -421,7 +673,6 @@ impl Perform for PerfAtom {
}
fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
match (byte, intermediates) {
//(b'B', intermediates) => configure_charset!(StandardCharset::Ascii, intermediates),
(b'D', []) => self.linefeed(),