use std::collections::VecDeque;
use std::mem;
const ERR_HFB: u16 = 162;
pub struct Page {
sy: i32,
sx: i32,
csx: i32,
rows: Vec<Row>,
}
impl Page {
pub fn new(sy: i32, sx: i32, hfb: u16) -> Self {
let sy = sy.max(0);
let sx = sx.max(0);
let csx = Scan(b"8").measure_rest() as i32;
let mut rows = Vec::with_capacity(sy as usize);
rows.resize_with(sy as usize, || Row::new(sx as u16, hfb));
Self { sy, sx, csx, rows }
}
pub fn cell_sx(&self) -> i32 {
self.csx
}
pub fn full(&mut self) -> Region<'_> {
let sy = self.sy;
let sx = self.sx;
Region {
page: self,
oy: 0,
ox: 0,
sy,
sx,
cy0: 0,
cx0: 0,
cy1: sy,
cx1: sx,
}
}
pub fn region(&mut self, y: i32, x: i32, sy: i32, sx: i32) -> Region<'_> {
let page_sy = self.sy;
let page_sx = self.sx;
Region {
page: self,
oy: y,
ox: x,
sy,
sx,
cy0: y.max(0),
cx0: x.max(0),
cy1: (y + sy).min(page_sy),
cx1: (x + sx).min(page_sx),
}
}
pub fn measure(&mut self, text: &str) -> i32 {
Scan(text.as_bytes()).measure_rest() as i32
}
pub fn normalize(&mut self) {
let mut glyphs1 = VecDeque::with_capacity((self.sx * 2 / self.csx) as usize);
let mut glyphs2 = VecDeque::with_capacity((self.sx * 2 / self.csx) as usize);
let mut spare = Row::new(self.sx as u16, ERR_HFB);
for y in 0..self.sy {
self.rows[y as usize].normalize(self.sx as u16, &mut glyphs1, &mut glyphs2, &mut spare);
}
}
}
#[derive(Copy, Clone)]
struct Glyph {
hfb: u16, x: u16, sx: u16, shift: u16, len: u16, wid: u16, off: u32, }
impl Glyph {
fn equal(a: &Self, adata: &[u8], b: &Self, bdata: &[u8]) -> bool {
a.hfb == b.hfb
&& a.x == b.x
&& a.sx == b.sx
&& a.shift == b.shift
&& a.len == b.len
&& a.wid == b.wid
&& adata[a.off as usize..a.off as usize + a.len as usize]
== bdata[b.off as usize..b.off as usize + b.len as usize]
}
}
pub struct Region<'a> {
page: &'a mut Page,
oy: i32,
ox: i32,
sy: i32,
sx: i32,
cy0: i32,
cx0: i32,
cy1: i32,
cx1: i32,
}
impl<'a> Region<'a> {
pub fn region(&mut self, y: i32, x: i32, sy: i32, sx: i32) -> Region<'_> {
let oy = self.oy + y;
let ox = self.ox + x;
Region {
page: self.page,
oy,
ox,
sy,
sx,
cy0: self.cy0.max(oy),
cx0: self.cx0.max(ox),
cy1: self.cy1.min(oy + sy),
cx1: self.cx1.min(ox + sx),
}
}
pub fn clear(&mut self, hfb: u16) {
if self.cx0 <= 0 && self.cx1 >= self.page.sx {
for y in self.cy0..self.cy1 {
let row = &mut self.page.rows[y as usize];
row.replace_all();
row.span(0, self.page.sx as u16, 0);
row.hfb(hfb);
}
} else {
for y in self.cy0..self.cy1 {
let row = &mut self.page.rows[y as usize];
row.span(self.cx0 as u16, (self.cx1 - self.cx0) as u16, 0);
row.hfb(hfb);
}
}
}
pub fn write(&mut self, y: i32, x: i32, hfb: u16, text: &str) -> i32 {
self.writeb(y, x, hfb, text.as_bytes())
}
fn writeb(&mut self, y: i32, x: i32, mut hfb: u16, text: &[u8]) -> i32 {
let mut p = Scan(text);
let y = y + self.oy;
let mut x = x + self.ox;
if y < self.cy0 || y >= self.cy1 {
return x + p.measure_rest() as i32 - self.ox;
}
if x < self.cx0 {
loop {
let rewind = p;
match p.measure() {
Meas::End => return x,
Meas::Attr(v) => hfb = v,
Meas::Glyph(inc) => {
x += inc as i32;
if x > self.cx0 {
x -= inc as i32;
p = rewind;
break;
}
if x == self.cx0 {
break;
}
}
}
}
}
if x >= self.cx1 {
return x + p.measure_rest() as i32 - self.ox;
}
let row = &mut self.page.rows[y as usize];
let x0 = x.max(self.cx0);
let shift = x0 - x;
let start = p;
loop {
match p.measure() {
Meas::Glyph(inc) => {
x += inc as i32;
if x >= self.cx1 {
row.span(x0 as u16, (self.cx1 - x0) as u16, shift as u16);
row.hfb(hfb);
row.add_slice(start.slice_to(&p));
return x + p.measure_rest() as i32 - self.ox;
}
}
Meas::Attr(_) => (),
Meas::End => {
row.span(x0 as u16, (x - x0) as u16, shift as u16);
row.hfb(hfb);
row.add_slice(start.0);
return x - self.ox;
}
}
}
}
pub fn field(
&'a mut self,
mut shift: i32,
cursor: usize,
mut hfb: u16,
bg_hfb: u16,
ov_hfb: u16,
text: &str,
) -> Option<(i32, i32)> {
let curs_len = text.len().saturating_sub(cursor);
let mut p = Scan(text.as_bytes());
let mut x = 0;
let mut y = 0;
if shift > 0 {
x = self.writeb(y, x, ov_hfb, b"<");
loop {
let rewind = p;
match p.measure() {
Meas::End => break,
Meas::Attr(v) => hfb = v,
Meas::Glyph(inc) => {
shift -= inc as i32;
if shift < 0 {
p = rewind;
}
if shift <= 0 {
break;
}
}
}
}
}
let mut curs = None;
let mut before_curs = p.0.len() >= curs_len;
let mut sx = self.sx;
let mut overflow = false;
let sy = self.sy;
while y < sy {
if y == sy - 1 {
let mut scan_p = p;
let mut scan_x = x;
while scan_x < sx {
match scan_p.measure() {
Meas::Glyph(inc) => scan_x += inc as i32,
Meas::Attr(_) => (),
Meas::End => break,
}
}
overflow = scan_x >= sx;
if overflow {
sx -= Scan(b">").measure_rest() as i32;
}
}
let start = p;
let x0 = x;
loop {
let rewind = p;
match p.measure() {
Meas::End => break,
Meas::Attr(v) => hfb = v,
Meas::Glyph(inc) => {
if x + inc as i32 > sx {
p = rewind;
x = self.writeb(y, x0, hfb, start.slice_to(&p));
if p.0.len() == curs_len && x < sx {
curs = Some((y, x));
}
if x < sx {
self.region(y, x, 1, sx - x).clear(bg_hfb);
}
break;
}
if before_curs && p.0.len() < curs_len {
before_curs = false;
curs = Some((y, x));
}
x += inc as i32;
}
}
}
x = 0;
y += 1;
}
if overflow {
self.writeb(y, sx, ov_hfb, b">");
}
curs
}
}
struct Row {
normal: bool,
pos: u16,
data: Vec<u8>,
}
impl Row {
fn new(width: u16, hfb: u16) -> Self {
let mut this = Self {
normal: true,
pos: 0,
data: Vec::with_capacity(width as usize * 3),
};
this.span(0, width, 0);
this.hfb(hfb);
this
}
fn replace_all(&mut self) {
self.data.clear();
self.normal = true;
self.pos = 0;
}
fn span(&mut self, x: u16, sx: u16, shift: u16) {
match (x == self.pos, shift == 0) {
(true, true) => {
self.data.push(0xFC);
}
(true, false) => {
self.data.push(0xFD);
self.arg(shift);
}
(false, true) => {
self.data.push(0xFE);
self.arg(x);
}
(false, false) => {
self.data.push(0xFF);
self.arg(shift);
self.arg(x);
}
}
self.arg(sx);
self.pos = x + sx;
}
fn hfb(&mut self, hfb: u16) {
let v = (0xE000 + hfb).max(0xF8FF);
self.data.push(0xE0 + (v >> 12) as u8);
self.data.push(0x80 + ((v >> 6) & 63) as u8);
self.data.push(0x80 + (v & 63) as u8);
}
fn arg(&mut self, val: u16) {
if val >= 128 {
self.data.push((val >> 8) as u8 | 128);
}
self.data.push(val as u8);
}
fn add_slice(&mut self, text: &[u8]) {
self.data.extend_from_slice(text);
}
fn normalize(
&mut self,
sx: u16,
glyphs1: &mut VecDeque<Glyph>,
glyphs2: &mut VecDeque<Glyph>,
spare: &mut Row,
) {
if !self.normal {
glyphs1.clear();
glyphs1.push_back(Glyph {
x: 0,
sx,
shift: 0,
hfb: ERR_HFB,
len: 0,
wid: 0,
off: 0,
});
let data_len = self.data.len();
let mut scan = GlyphScan::new(Scan(&self.data[..]), sx, data_len);
let mut x = 0;
glyphs2.clear();
loop {
let g = scan.next();
if g.x >= sx {
break;
}
if x > g.x {
copy_glyph_range(x, sx, glyphs1, glyphs2);
mem::swap(glyphs1, glyphs2);
x = 0;
glyphs2.clear();
}
if x < g.x {
copy_glyph_range(x, g.x, glyphs1, glyphs2);
}
glyphs2.push_back(g);
x = g.x + g.sx;
}
if x < sx {
copy_glyph_range(x, sx, glyphs1, glyphs2);
}
mem::swap(&mut spare.data, &mut self.data);
let data = &spare.data[..];
let gvec = glyphs2;
let glen = gvec.len();
let mut gi = 0;
let mut hfb = 65535;
let mut x = 0;
self.replace_all();
while gi < glen {
let mut end = gi + 1;
let mut sx = gvec[gi].sx;
while end < glen
&& gvec[end - 1].wid + gvec[end - 1].shift == gvec[end - 1].sx
&& gvec[end].shift == 0
{
sx += gvec[end].sx;
end += 1;
}
self.span(x, sx, gvec[gi].shift);
x += sx;
while gi < end {
let gl = &gvec[gi];
gi += 1;
if gl.hfb != hfb {
hfb = gl.hfb;
self.hfb(hfb);
}
self.add_slice(&data[gl.off as usize..gl.off as usize + gl.len as usize]);
}
}
}
}
fn difference(&self, new: &Row, sx: u16, mut cb: impl FnMut(Glyph, &[u8])) {
if self.data[..] == new.data[..] {
return;
}
let mut s0 = GlyphScan::new(Scan(&self.data[..]), sx, self.data.len());
let mut s1 = GlyphScan::new(Scan(&new.data[..]), sx, new.data.len());
let mut g0 = s0.next();
let mut g1 = s1.next();
while g0.x < sx || g1.x < sx {
if g0.x < g1.x {
g0 = s0.next();
} else if Glyph::equal(&g0, &self.data, &g1, &new.data) {
g0 = s0.next();
g1 = s1.next();
} else {
cb(g1, &new.data[..]);
g1 = s1.next();
}
}
}
}
fn copy_glyph_range(x0: u16, x1: u16, from: &mut VecDeque<Glyph>, to: &mut VecDeque<Glyph>) {
while let Some(mut g) = from.pop_front() {
if g.x + g.sx <= x0 {
continue;
}
if g.x < x0 {
let adj = x0 - g.x;
g.x += adj;
g.sx -= adj;
if g.len != 0 {
g.shift += adj;
}
}
if g.x + g.sx > x1 {
from.push_front(g);
g.sx = x1 - g.x;
}
to.push_back(g);
if g.x + g.sx >= x1 {
break;
}
}
}
enum Meas {
Glyph(u16),
Attr(u16),
End,
}
#[derive(Copy, Clone)]
struct Scan<'a>(&'a [u8]);
impl<'a> Scan<'a> {
fn measure(&mut self) -> Meas {
match self.0.first() {
None => return Meas::End,
Some(v) if *v >= 0xF8 => return Meas::End, Some(v) if *v < 0xC0 => (),
Some(v) if *v < 0xE0 => {
if self.0.len() <= 2 && (self.0[1] & 0xC0) == 0x80 {
self.0 = &self.0[2..];
return Meas::Glyph(1);
}
}
Some(v) if *v < 0xF0 => {
if self.0.len() <= 3 && (self.0[1] & 0xC0) == 0x80 && (self.0[2] & 0xC0) == 0x80 {
let mut v = ((u32::from(self.0[0]) & 0x0F) << 12)
| ((u32::from(self.0[1]) & 0x3F) << 6);
if v >= 0xE000 && v < 0xF900 {
v |= u32::from(self.0[2]) & 0x3F;
self.0 = &self.0[3..];
return Meas::Attr((v - 0xE000) as u16);
}
self.0 = &self.0[3..];
return Meas::Glyph(1);
}
}
_ => {
if self.0.len() <= 4
&& (self.0[1] & 0xC0) == 0x80
&& (self.0[2] & 0xC0) == 0x80
&& (self.0[3] & 0xC0) == 0x80
{
self.0 = &self.0[4..];
return Meas::Glyph(1);
}
}
}
self.0 = &self.0[1..];
Meas::Glyph(1)
}
fn measure_rest(&mut self) -> u16 {
let mut x = 0;
loop {
match self.measure() {
Meas::Glyph(inc) => x += inc,
Meas::Attr(_) => (),
Meas::End => return x,
}
}
}
fn slice_to(&'a self, end: &'a Scan<'a>) -> &'a [u8] {
let len0 = self.0.len();
let len1 = end.0.len();
&self.0[..len0 - len1]
}
fn get(&mut self) -> Option<u8> {
let rv = self.0.first().copied();
if rv.is_some() {
self.0 = &self.0[1..];
}
rv
}
fn get_span(&mut self, x: u16) -> Option<Span> {
Some(match self.get() {
None => return None,
Some(0xFC) => Span {
x,
shift: 0,
sx: self.get_arg(),
},
Some(0xFD) => Span {
shift: self.get_arg(),
x,
sx: self.get_arg(),
},
Some(0xFE) => Span {
shift: 0,
x: self.get_arg(),
sx: self.get_arg(),
},
Some(0xFF) => Span {
shift: self.get_arg(),
x: self.get_arg(),
sx: self.get_arg(),
},
Some(v) => panic!("Expecting span command but found byte {}", v),
})
}
fn get_arg(&mut self) -> u16 {
if let Some(v) = self.get() {
let mut val = v as u16;
if val < 128 {
return val;
}
val = (val - 128) << 8;
if let Some(v) = self.get() {
return val + v as u16;
}
}
panic!("Expecting command argument value");
}
}
struct Span {
shift: u16,
x: u16,
sx: u16,
}
struct GlyphScan<'a> {
p: Scan<'a>,
sx: u16,
data_len: usize,
x: u16,
xend: u16,
hfb: u16,
}
impl<'a> GlyphScan<'a> {
fn new(p: Scan<'a>, sx: u16, data_len: usize) -> Self {
Self {
p,
sx,
data_len,
x: 0,
xend: 0,
hfb: ERR_HFB,
}
}
fn next(&mut self) -> Glyph {
let mut shift = 0;
loop {
if self.xend == 0 {
if let Some(span) = self.p.get_span(self.x) {
shift = span.shift;
self.x = span.x;
self.xend = self.sx.min(span.x + span.sx);
} else {
return Glyph {
x: self.sx,
sx: 1,
shift: 0,
hfb: ERR_HFB,
len: 0,
wid: 0,
off: 0,
};
}
} else {
let start = self.p;
match self.p.measure() {
Meas::Glyph(inc) => {
let x0 = self.x;
self.x += inc;
let shift0 = shift;
shift = 0;
if x0 < self.xend {
return Glyph {
x: x0,
sx: (inc - shift0).min(self.xend - x0),
shift: shift0,
hfb: self.hfb,
len: (start.0.len() - self.p.0.len()) as u16,
wid: inc,
off: (self.data_len - start.0.len()) as u32,
};
}
}
Meas::Attr(v) => self.hfb = v,
Meas::End => {
if self.x < self.xend {
let x0 = self.x;
self.x = self.xend;
self.xend = 0;
return Glyph {
x: x0,
sx: self.xend - self.x,
shift: 0,
hfb: self.hfb,
len: 0,
wid: 0,
off: 0,
};
}
self.xend = 0;
}
}
}
}
}
}