Skip to main content

TermShare

Struct TermShare 

Source
pub struct TermShare(/* private fields */);
Expand description

Shared access for terminal output

Clone to get more references to the same shared Output buffer.

Implementations§

Source§

impl TermShare

Source

pub fn output<'a>(&'a self, core: &'a mut Core) -> &'a mut Output

Get access to the output buffer for direct ANSI output

Examples found in repository?
examples/test0.rs (line 71)
69    fn redraw(&mut self, cx: CX![]) {
70        if let Some(ref tshare) = self.tshare {
71            let o = tshare.output(cx);
72            o.attr_99().cursor_show().scroll_up().save_cleanup();
73            o.cursor_hide();
74            Self::draw(o);
75        }
76    }
More examples
Hide additional examples
examples/test1.rs (line 71)
69    fn redraw(&mut self, cx: CX![]) {
70        if let Some(ref tshare) = self.tshare {
71            let o = tshare.output(cx);
72            o.attr_99().cursor_show().scroll_up().save_cleanup();
73            o.cursor_hide();
74            Self::draw(o);
75        }
76    }
77
78    fn input(&mut self, cx: CX![], key: Key) {
79        match key {
80            Key::Ctrl('L') => self.redraw(cx),
81            Key::Ctrl('C') => stop!(cx),
82            _ => {
83                use std::str::FromStr;
84                let s = format!("{key}");
85                let k = Key::from_str(&s);
86                assert!(k.is_ok(), "Round-trip failed for {s}");
87                let k = k.unwrap();
88                assert_eq!(k, key, "Mismatch for {key} -> {s} -> {k}");
89                let hfb = if s.starts_with("M-") {
90                    172
91                } else if s.starts_with("C-") {
92                    141
93                } else if matches!(key, Key::Pr(_)) {
94                    151
95                } else {
96                    162
97                };
98                if let Some(ref tshare) = self.tshare {
99                    let o = tshare.output(cx);
100                    o.hfb(hfb).text(&s);
101                    o.hfb(71).text(" ");
102                    o.flush();
103                }
104            }
105        }
106    }
examples/test2.rs (line 72)
68    fn resize(&mut self, cx: CX![], tshare: Option<TermShare>) {
69        self.tshare = tshare;
70
71        if let Some(ref tshare) = self.tshare {
72            let o = tshare.output(cx);
73            o.attr_99().cursor_show().scroll_up().save_cleanup();
74            o.cursor_hide();
75            self.page = o.new_page();
76        }
77
78        self.redraw(cx, true);
79    }
80
81    fn input(&mut self, cx: CX![], key: Key) {
82        match key {
83            Key::Ctrl('L') => self.redraw(cx, true),
84            Key::Ctrl('C') => stop!(cx),
85            _ => {
86                if self.spacing_on {
87                    self.spacing_on = false;
88                } else {
89                    self.spacing_on = true;
90                    self.spacing = ((self.spacing + 1) % 20).max(3);
91                }
92                self.redraw(cx, false);
93            }
94        }
95    }
96
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    }
142
143    fn update(&mut self, cx: CX![], full: bool) {
144        if let Some(ref tshare) = self.tshare {
145            let o = tshare.output(cx);
146            o.update_to(&mut self.page, full);
147        }
148    }
examples/teeclub/main.rs (line 93)
89    fn resize(&mut self, cx: CX![], tsh: Option<TermShare>) {
90        self.tsh = tsh;
91
92        if let Some(ref tsh) = self.tsh {
93            let out = tsh.output(cx);
94            out.attr_99().cursor_show().scroll_up().save_cleanup();
95            out.cursor_hide().clear_all_99();
96
97            if self.logo_hfb.is_none() && out.features().colour_256 {
98                const LOGO_RGB: [(f64, u32); 7] = [
99                    (0.0, 0xFFFF00),
100                    (1.0, 0x00FF00),
101                    (2.0, 0x22FFFF),
102                    (3.0, 0x4444FF),
103                    (4.0, 0xFF22FF),
104                    (5.0, 0xFF0000),
105                    (6.0, 0xFFFF00),
106                ];
107                self.logo_hfb = Some(
108                    (0..30)
109                        .map(|i| {
110                            let rgb = out.rgb_interpolate(&LOGO_RGB, i as f64 * 0.2);
111                            out.hfb_alloc(false, false, rgb, 0x000000)
112                        })
113                        .collect(),
114                );
115            }
116
117            self.layout(cx);
118        }
119    }
examples/fontedit/app.rs (line 87)
85    fn redraw(&mut self, cx: CX![]) {
86        if let Some(ref tsh) = self.tsh {
87            let out = tsh.output(cx);
88            out.attr_99().cursor_show().scroll_up().save_cleanup();
89            out.cursor_hide().clear_all_99_and_remote();
90
91            // Draw fixed stuff here, then break out and store
92            // sub-tiles for areas that need to be updated later
93            let tile = tsh.tile(cx);
94            let sx = tile.sx();
95            let sy = tile.sy();
96            let split_y1 = sy - self.font.sy as i32;
97            let split_y0 = split_y1.min(10);
98            let (top, _, cells_tile) = tile.split_yy(split_y0, split_y1);
99            let spare = sx.saturating_sub(80);
100            let (ox, mini_sx) = if (spare as usize) < self.font.sx / 2 {
101                (spare / 2, 0)
102            } else {
103                (0, spare)
104            };
105            let (_, rest) = top.split_x(ox);
106            let (param_tile, mini_tile, mut keys_tile) = rest.split_xx(40, 40 + mini_sx);
107
108            if let Some(mut r) = keys_tile.region(cx, 0, 0, split_y0, 40) {
109                r.hfb(172).clear_all();
110                let text = "\
111Keys: Arrows move, [Space] change pixel
112Mode on/off: [d] draw, [r] roll
113Fill: [f] flood, [v] vert, [h] horiz
114[n] new glyph, [u] undo, [l] ruler line
115Clip: [c] copy, [P] paste.
116Index: [PgUp] [PgDn] [Home] [End].
117[S] save, [Q] save+quit, [^C] hard quit
118Edit the font file directly to change
119font size or codepoint numbers.";
120                r.text(&text.replace('[', "\0171 ").replace(']', " \0172"));
121            }
122            self.cells_tile = cells_tile;
123            self.param_tile = param_tile;
124            self.mini_tile = mini_tile;
125
126            self.draw_cells(cx);
127            self.draw_mini(cx);
128            self.draw_param(cx);
129        }
130    }
Source

pub fn page(&self, core: &mut Core) -> Page

Create a new page with the same size as the terminal. This can be sent to the screen using TermShare::update.

Source

pub fn update(&self, core: &mut Core, page: &mut Page, redraw: bool)

Update the terminal to match the given Page. If redraw is false then sends the minimum updates to change the current terminal contents to match the page. Otherwise does a full redraw.

Source

pub fn tile(&self, core: &mut Core) -> Tile

Create a new top-level tile and clear the local page to default colours (99). (The local page is the page that backs all Tile operations.) All previous tiles are automatically invalidated, meaning that it’s no longer possible to write to the terminal through them. After calling this, the caller should redraw static text and break up the tile into subtiles as necessary and pass the new tiles to the code that needs them in order to redraw them and to allow them to continue to be updated. See Tile.

Examples found in repository?
examples/teeclub/main.rs (line 126)
122    fn redraw(&mut self, cx: CX![]) {
123        let Some(ref tsh) = self.tsh else {
124            return;
125        };
126        let mut tile = tsh.tile(cx);
127        if let Some(mut r) = tile.full(cx) {
128            r.clear_all_99();
129        }
130        after!(Duration::from_millis(10), [cx], layout());
131    }
132
133    fn layout(&mut self, cx: CX![]) {
134        let Some(ref tsh) = self.tsh else {
135            return;
136        };
137
138        let mut tile = tsh.tile(cx);
139        if let Some(mut r) = tile.full(cx) {
140            r.clear_all_99();
141        }
142        let left_gap = 0.max(tile.sx() - 80) / 2;
143        let right_off = (left_gap + 80).min(tile.sx());
144        let right_gap = tile.sx() - right_off;
145        self.adjust = self.adjust.max(-left_gap).min(right_gap);
146        let left_gap = left_gap + self.adjust;
147        let right_off = (left_gap + 80).min(tile.sx());
148
149        let (_, mid, _) = tile.split_xx(left_gap, right_off);
150        let (main, scores) = mid.split_x(74);
151        self.scores_tile = scores;
152        let sy = main.sy();
153        if let Some(game) = &mut self.game {
154            game.layout(cx, main);
155        } else {
156            let logo_sy = 9;
157            let instr_sy = 16;
158            let gap = (sy - logo_sy - instr_sy) / 3;
159            let (_, mut logo, rest) = main.split_yy(gap, gap + logo_sy);
160            let (_, mut text, _) = rest.split_yy(gap, gap + instr_sy);
161            if let Some(r) = logo.full(cx) {
162                self.draw_logo(r);
163            }
164            if let Some(r) = text.full(cx) {
165                Self::draw_instructions(r);
166            }
167        }
168
169        self.draw_scores(cx);
170    }
More examples
Hide additional examples
examples/fontedit/app.rs (line 93)
85    fn redraw(&mut self, cx: CX![]) {
86        if let Some(ref tsh) = self.tsh {
87            let out = tsh.output(cx);
88            out.attr_99().cursor_show().scroll_up().save_cleanup();
89            out.cursor_hide().clear_all_99_and_remote();
90
91            // Draw fixed stuff here, then break out and store
92            // sub-tiles for areas that need to be updated later
93            let tile = tsh.tile(cx);
94            let sx = tile.sx();
95            let sy = tile.sy();
96            let split_y1 = sy - self.font.sy as i32;
97            let split_y0 = split_y1.min(10);
98            let (top, _, cells_tile) = tile.split_yy(split_y0, split_y1);
99            let spare = sx.saturating_sub(80);
100            let (ox, mini_sx) = if (spare as usize) < self.font.sx / 2 {
101                (spare / 2, 0)
102            } else {
103                (0, spare)
104            };
105            let (_, rest) = top.split_x(ox);
106            let (param_tile, mini_tile, mut keys_tile) = rest.split_xx(40, 40 + mini_sx);
107
108            if let Some(mut r) = keys_tile.region(cx, 0, 0, split_y0, 40) {
109                r.hfb(172).clear_all();
110                let text = "\
111Keys: Arrows move, [Space] change pixel
112Mode on/off: [d] draw, [r] roll
113Fill: [f] flood, [v] vert, [h] horiz
114[n] new glyph, [u] undo, [l] ruler line
115Clip: [c] copy, [P] paste.
116Index: [PgUp] [PgDn] [Home] [End].
117[S] save, [Q] save+quit, [^C] hard quit
118Edit the font file directly to change
119font size or codepoint numbers.";
120                r.text(&text.replace('[', "\0171 ").replace(']', " \0172"));
121            }
122            self.cells_tile = cells_tile;
123            self.param_tile = param_tile;
124            self.mini_tile = mini_tile;
125
126            self.draw_cells(cx);
127            self.draw_mini(cx);
128            self.draw_param(cx);
129        }
130    }

Trait Implementations§

Source§

impl Clone for TermShare

Source§

fn clone(&self) -> TermShare

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

Auto Trait Implementations§

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.