Skip to main content

Page

Struct Page 

Source
pub struct Page { /* private fields */ }
Expand description

A whole page of text

This is a local copy of the entire terminal screen where the required display can be built up before sending to the terminal with an update TermShare::update.

This allows drawing text locally with clipping via the Region struct. Coordinates are all i32 to allow for display objects to be partially off the page edges. Each row stores cells with a width in bytes according to the largest glyph in that row. So storage adapts to the data.

Cloning a Page is efficient as the cloned page shares the same row data as the original, and does copy-on-write.

Implementations§

Source§

impl Page

Source

pub fn new(sy: i32, sx: i32, hfb: u16, sizer: Sizer) -> Self

Create a new page with sy rows and width of sx cells, filled with spaces with the given attribute hfb, and with sizer to determine glyph boundaries and widths.

In general it’s easier to create a new page using TermShare::page.

Source

pub fn empty() -> Self

Create a dummy empty page, of zero size

Examples found in repository?
examples/test2.rs (line 62)
46    fn init(cx: CX![]) -> Option<Self> {
47        let _terminal = actor!(
48            cx,
49            Terminal::init(
50                SimpleSizer::new(),
51                fwd_to!([cx], resize() as (Option<TermShare>)),
52                fwd_to!([cx], input() as (Key))
53            ),
54            ret_some_to!([cx], |_, cx, cause: StopCause| {
55                println!("Terminal actor failed: {cause}");
56                stop!(cx);
57            })
58        );
59        Some(Self {
60            _terminal,
61            tshare: None,
62            page: Page::empty(),
63            spacing: 0,
64            spacing_on: false,
65        })
66    }
Source

pub fn sx(&self) -> i32

Width of page in cells

Examples found in repository?
examples/test2.rs (line 99)
97    fn redraw(&mut self, cx: CX![], full: bool) {
98        let pg = &mut self.page;
99        let sx = pg.sx();
100        let sy = pg.sy();
101
102        if sy < 24 || sx < 80 {
103            let mut r = pg.full();
104            r.clear_all_99();
105            r.at(sy >> 1, (sx - 30) >> 1).hfb(162);
106            write!(r, " Terminal too small: {sy} x {sx} ").unwrap();
107            return;
108        }
109
110        const TEXT: &str = "This is a test.  ";
111        const TEXTLEN: usize = TEXT.len();
112        let mid = sx >> 1;
113        for y in 0..sy {
114            let mut r = pg.region(y, 0, 1, sx + TEXTLEN as i32 * 2);
115            r.at(0, y % TEXTLEN as i32 - TEXTLEN as i32).hfb(99);
116            while r.get_x() < sx {
117                r.text(TEXT);
118            }
119            if self.spacing_on {
120                let mut x = (sx + sy) / 2 - y;
121                while x > 0 {
122                    x -= self.spacing
123                }
124                r.at(0, x);
125                while r.get_x() < sx {
126                    r.text("/");
127                    r.skip(self.spacing - 1);
128                }
129            }
130            let shift = y * 6 / sy;
131            for x in 0..sx {
132                r.set_hfb(0, x, (((x - mid) >> shift) & 3) as u16 + 70);
133            }
134        }
135        pg.full()
136            .at(sy - 2, (sx - 40) >> 1)
137            .hfb(6)
138            .text("  PRESS ANY KEY TO CONTINUE, Ctrl-C TO END  ");
139
140        self.update(cx, full);
141    }
Source

pub fn sy(&self) -> i32

Height of page in lines

Examples found in repository?
examples/test2.rs (line 100)
97    fn redraw(&mut self, cx: CX![], full: bool) {
98        let pg = &mut self.page;
99        let sx = pg.sx();
100        let sy = pg.sy();
101
102        if sy < 24 || sx < 80 {
103            let mut r = pg.full();
104            r.clear_all_99();
105            r.at(sy >> 1, (sx - 30) >> 1).hfb(162);
106            write!(r, " Terminal too small: {sy} x {sx} ").unwrap();
107            return;
108        }
109
110        const TEXT: &str = "This is a test.  ";
111        const TEXTLEN: usize = TEXT.len();
112        let mid = sx >> 1;
113        for y in 0..sy {
114            let mut r = pg.region(y, 0, 1, sx + TEXTLEN as i32 * 2);
115            r.at(0, y % TEXTLEN as i32 - TEXTLEN as i32).hfb(99);
116            while r.get_x() < sx {
117                r.text(TEXT);
118            }
119            if self.spacing_on {
120                let mut x = (sx + sy) / 2 - y;
121                while x > 0 {
122                    x -= self.spacing
123                }
124                r.at(0, x);
125                while r.get_x() < sx {
126                    r.text("/");
127                    r.skip(self.spacing - 1);
128                }
129            }
130            let shift = y * 6 / sy;
131            for x in 0..sx {
132                r.set_hfb(0, x, (((x - mid) >> shift) & 3) as u16 + 70);
133            }
134        }
135        pg.full()
136            .at(sy - 2, (sx - 40) >> 1)
137            .hfb(6)
138            .text("  PRESS ANY KEY TO CONTINUE, Ctrl-C TO END  ");
139
140        self.update(cx, full);
141    }
Source

pub fn full(&mut self) -> Region<'_>

Return a Region representing the full area of the page for drawing on.

Examples found in repository?
examples/test2.rs (line 103)
97    fn redraw(&mut self, cx: CX![], full: bool) {
98        let pg = &mut self.page;
99        let sx = pg.sx();
100        let sy = pg.sy();
101
102        if sy < 24 || sx < 80 {
103            let mut r = pg.full();
104            r.clear_all_99();
105            r.at(sy >> 1, (sx - 30) >> 1).hfb(162);
106            write!(r, " Terminal too small: {sy} x {sx} ").unwrap();
107            return;
108        }
109
110        const TEXT: &str = "This is a test.  ";
111        const TEXTLEN: usize = TEXT.len();
112        let mid = sx >> 1;
113        for y in 0..sy {
114            let mut r = pg.region(y, 0, 1, sx + TEXTLEN as i32 * 2);
115            r.at(0, y % TEXTLEN as i32 - TEXTLEN as i32).hfb(99);
116            while r.get_x() < sx {
117                r.text(TEXT);
118            }
119            if self.spacing_on {
120                let mut x = (sx + sy) / 2 - y;
121                while x > 0 {
122                    x -= self.spacing
123                }
124                r.at(0, x);
125                while r.get_x() < sx {
126                    r.text("/");
127                    r.skip(self.spacing - 1);
128                }
129            }
130            let shift = y * 6 / sy;
131            for x in 0..sx {
132                r.set_hfb(0, x, (((x - mid) >> shift) & 3) as u16 + 70);
133            }
134        }
135        pg.full()
136            .at(sy - 2, (sx - 40) >> 1)
137            .hfb(6)
138            .text("  PRESS ANY KEY TO CONTINUE, Ctrl-C TO END  ");
139
140        self.update(cx, full);
141    }
Source

pub fn region(&mut self, y: i32, x: i32, sy: i32, sx: i32) -> Region<'_>

Generate a Region that may be any size, inside or outside the actual page. When drawn to, only the part of the region that overlaps the actual page will be affected.

Examples found in repository?
examples/test2.rs (line 114)
97    fn redraw(&mut self, cx: CX![], full: bool) {
98        let pg = &mut self.page;
99        let sx = pg.sx();
100        let sy = pg.sy();
101
102        if sy < 24 || sx < 80 {
103            let mut r = pg.full();
104            r.clear_all_99();
105            r.at(sy >> 1, (sx - 30) >> 1).hfb(162);
106            write!(r, " Terminal too small: {sy} x {sx} ").unwrap();
107            return;
108        }
109
110        const TEXT: &str = "This is a test.  ";
111        const TEXTLEN: usize = TEXT.len();
112        let mid = sx >> 1;
113        for y in 0..sy {
114            let mut r = pg.region(y, 0, 1, sx + TEXTLEN as i32 * 2);
115            r.at(0, y % TEXTLEN as i32 - TEXTLEN as i32).hfb(99);
116            while r.get_x() < sx {
117                r.text(TEXT);
118            }
119            if self.spacing_on {
120                let mut x = (sx + sy) / 2 - y;
121                while x > 0 {
122                    x -= self.spacing
123                }
124                r.at(0, x);
125                while r.get_x() < sx {
126                    r.text("/");
127                    r.skip(self.spacing - 1);
128                }
129            }
130            let shift = y * 6 / sy;
131            for x in 0..sx {
132                r.set_hfb(0, x, (((x - mid) >> shift) & 3) as u16 + 70);
133            }
134        }
135        pg.full()
136            .at(sy - 2, (sx - 40) >> 1)
137            .hfb(6)
138            .text("  PRESS ANY KEY TO CONTINUE, Ctrl-C TO END  ");
139
140        self.update(cx, full);
141    }
Source

pub fn measure(&mut self, text: &str) -> i32

Measures some text to see how many cells it will take up horizontally. Skips HFB sequences of the form \0ZZZ

Source

pub fn set_cursor(&mut self, cursor: Option<(i32, i32)>)

Set the cursor position, or hide the cursor if None is passed. If the cursor position is provided but is off the page, then the cursor is hidden instead.

Source

pub fn cursor(&self) -> Option<(i32, i32)>

Get the cursor position, or None if hidden

Source

pub fn scroll_up(&mut self, y0: i32, y1: i32, count: i32, hfb: u16)

Scroll the given region y0..y1 up the given number of lines. Empty lines are filled with spaces of the given hfb colour. This is very efficient as it manipulates whole rows.

Source

pub fn scroll_down(&mut self, y0: i32, y1: i32, count: i32, hfb: u16)

Scroll the given region y0..y1 down by the given number of lines. Empty lines are filled with spaces of the given hfb colour. This is very efficient as it manipulates whole rows.

Source

pub fn copy_lines(&mut self, ya: i32, yb: i32, sy: i32)

Copy lines from one part of a page to another, from line ya..ya+sy to yb..yb+sy. Handles overlapping copies correctly. Clips to page size before copying. Since this copies whole rows using CoW it is very efficient.

Source

pub fn copy_region( &mut self, ya: i32, xa: i32, yb: i32, xb: i32, sy: i32, sx: i32, )

Copy one region with size (sy,sx) at (ya,xa) to another at (yb,xb), cell by cell. Handles overlapping regions correctly. Clips to page size before copying.

Trait Implementations§

Source§

impl Clone for Page

Source§

fn clone(&self) -> Page

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Page

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Page

Source§

fn default() -> Self

Defaults to an empty 0x0-sized page

Auto Trait Implementations§

§

impl Freeze for Page

§

impl !RefUnwindSafe for Page

§

impl !Send for Page

§

impl !Sync for Page

§

impl Unpin for Page

§

impl UnsafeUnpin for Page

§

impl !UnwindSafe for Page

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.