A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/text/mapper.rs')
| -rw-r--r-- | src/text/mapper.rs | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/text/mapper.rs b/src/text/mapper.rs new file mode 100644 index 0000000..2d29286 --- /dev/null +++ b/src/text/mapper.rs @@ -0,0 +1,224 @@ +use std::ops::Deref; + +use dsb::Cell; + +#[derive(Copy, Clone)] +/// this struct is made to mimic a simple 2d vec +/// over the entire text area +/// without requiring that entire allocation, and the subsequent copy into the output area. +/// ```text +/// text above view offset (global text area)² +/// ╶╶╶╶╶├╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶ view offset +/// ┏━━━━┿━━━━━━━━━━━━┓← into_ and into_s³ +/// ┃ ╏← offset y ┃ +/// ┃ ┏╺╺┿╺╺╺╺╺╺╺╺╺╺╺╺┃ +/// ┃ ╏ v╎iewable area┃ +/// ┃ ╏ g╎oes here¹ ┃ +/// ┃ ╏ ╎ ┃ +/// ┃ ╏ ╎ ┃ +/// ┃ ╏ ╎ ┃ +/// ┗━━━━━━━━━━━━━━━━━┛ +/// ═ ══╎ +/// ↑ ↑ ╎ +/// │ ╰ horiz scroll +/// ╰ horizontal offset +/// ``` +#[allow(dead_code)] // ? +pub struct Mapper { + /// c, r + pub into_s: (usize, usize), + pub ox: usize, + pub oy: usize, + + pub from_c: usize, + pub from_r: usize, + pub vo: usize, + pub ho: usize, +} +pub struct Output<'a> { + pub into: &'a mut [Cell], + pub output: Mapper, +} +impl Deref for Output<'_> { + type Target = Mapper; + + fn deref(&self) -> &Self::Target { + &self.output + } +} + +impl Mapper { + /// translate an index into the global text buffer² into an (x, y), of the global text buffer + // fn to_point(&self, rope: &Rope, index: usize) -> (usize, usize) { + // ((index % self.from_c), (index / self.from_c)) + // } + + // fn from_point(&self, (x, y): (usize, usize)) -> usize { + // y * self.from_c + x + // } + + /// translate an (x, y) into the global text buffer² + /// to a point over the viewable area¹ (offset by the given offsets) of the global text buffer, + /// returning none if the given point is outside of the viewable area + fn translate(&self, (x, y): (usize, usize)) -> Option<(usize, usize)> { + let (x, y) = ( + x.checked_sub(self.ho)? + self.ox, + y.checked_sub(self.vo)? + self.oy, + ); + ((x < self.into_s.0) & (y < self.into_s.1) + & (x >= self.ox) // this is kind of forced already but its ok + & (y >= self.oy)) // " + .then_some((x, y)) + } + /// converts an (x, y) of the viewable area¹ to an index into [`Output::into`] + fn from_point_global(&self, (x, y): (usize, usize)) -> usize { + y * self.into_s.0 + x + } + // /// translate an index into a (x, y), of the output³ + // fn to_point_global(&self, index: usize) -> (usize, usize) { + // (index % self.into_s.0, index / self.into_s.0) + // } + // fn etalsnart_( + // &self, + // (x, y): (usize, usize), + // ) -> Option<(usize, usize)> { + // Some(( + // x.checked_sub(self.ox)? + self.ho, // + // y.checked_sub(self.oy)? + self.vo, + // )) + // } +} +impl<'a> Output<'a> { + // /// get an index thats relative over the viewable area¹ of the global text area + // fn get_at_compensated( + // &mut self, + // (x, y): (usize, usize), + // ) -> Option<&mut Cell> { + // Some(&mut self.into[(y + self.oy) * self.into_s.0 + (x + self.ox)]) + // } + pub fn get_range( + &mut self, + a: (usize, usize), + b: (usize, usize), + ) -> impl Iterator<Item = &mut Cell> { + self.get_range_enumerated(a, b).map(|x| x.0) + } + // needs rope to work properly (see [xy]) + // pub fn get_char_range( + // &mut self, + // a: usize, + // b: usize, + // ) -> impl Iterator<Item = &mut Cell> { + // self.get_range_enumerated(self.to_point(a), self.to_point(b)) + // .map(|x| x.0) + // } + //// coords reference global text buffer² + pub gen fn get_range_enumerated( + &mut self, + (x1, y1): (usize, usize), + (x2, y2): (usize, usize), + // impl Iterator<Item = (&mut Cell, (usize, usize))> { + ) -> (&mut Cell, (usize, usize)) { + let m = self.output; + let c = self.into.as_mut_ptr(); + // x1 = x1.checked_sub(m.ho).unwrap_or(m.ho); + // x2 = x2.checked_sub(m.ho).unwrap_or(m.ho); + // y1 = y1.checked_sub(m.vo).unwrap_or(m.vo); + // y2 = y2.checked_sub(m.vo).unwrap_or(m.vo); + // let a = m.from_point((x1, y1)); + // let b = m.from_point((x2, y2)); + // let a = m.from_point_global(m.translate(m.to_point(a)).unwrap()); + // let b = m.from_point_global(m.translate(m.to_point(b)).unwrap()); + // dbg!(a, b); + let mut p = (x1, y1); + while p != (x2, y2) { + if let Some(x) = m.translate(p) { + // SAFETY: trust me very disjoint + yield (unsafe { &mut *c.add(m.from_point_global(x)) }, p) + } + p.0 += 1; + if p.0.checked_sub(m.ho) == Some(m.from_c) { + p.0 = 0; + p.1 += 1; + if p.1 > y2 { + break; + } + } + if let Some(x) = p.0.checked_sub(m.ho) + && x > m.from_c + { + break; + } + } + + // (a..=b) + // .filter_map(move |x| { + // // println!("{:?} {x}", m.translate(m.to_point(x))); + // let (x, y) = m.to_point(x); + // m.translate((x, y)) + // // m.to_point_global(x) + // }) + // .inspect(move |x| { + // assert!(x.0 < self.into_s.0 && x.1 < self.into_s.1); + // assert!(m.from_point_global(*x) < self.into.len()); + // }) + // .map(move |x| { + // // SAFETY: :) + // (unsafe { &mut *p.add(m.from_point_global(x)) }, x) + // }) + // self.get_char_range_enumerated( + // self.output.from_point(a), + // self.output.from_point(b), + // ) + } + + // oughtnt really be multiline + pub fn get_simple( + &mut self, + s: (usize, usize), + e: (usize, usize), + ) -> Option<&mut [Cell]> { + let s = self.from_point_global(self.translate(s)?); + let e = self.from_point_global(self.translate(e)?); + self.into.get_mut(s..e) + } + // impl<'a> IndexMut<(usize, usize)> for Output<'a> { + // fn index_mut(&mut self, p: (usize, usize)) -> &mut Self::Output { + // let x = self.from_point_global(self.translate(p).unwrap()); + // &mut self.into[x] + // } + // } + pub fn get(&mut self, p: (usize, usize)) -> Option<&mut Cell> { + let n = self.from_point_global(self.translate(p)?); + self.into.get_mut(n) + } +} + +// impl<'a> Index<usize> for Output<'a> { +// type Output = Cell; + +// fn index(&self, index: usize) -> &Self::Output { +// &self[self.translate(index).unwrap()] +// } +// } + +// impl<'a> IndexMut<usize> for Output<'a> { +// fn index_mut(&mut self, index: usize) -> &mut Self::Output { +// let x = self.translate(index).unwrap(); +// &mut self[x] +// } +// } + +// impl<'a> Index<(usize, usize)> for Output<'a> { +// type Output = Cell; + +// fn index(&self, p: (usize, usize)) -> &Self::Output { +// &self.into[self.from_point_global(self.translate(p).unwrap())] +// } +// } +// impl<'a> IndexMut<(usize, usize)> for Output<'a> { +// fn index_mut(&mut self, p: (usize, usize)) -> &mut Self::Output { +// let x = self.from_point_global(self.translate(p).unwrap()); +// &mut self.into[x] +// } +// } |