pub struct TermShare(/* private fields */);Expand description
Shared access for terminal output
Clone to get more references to the same shared Output buffer.
Implementations§
Sourcepub fn output<'a>(&'a self, core: &'a mut Core) -> &'a mut Output ⓘ
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?
More examples
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 }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 }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 }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 }Sourcepub fn page(&self, core: &mut Core) -> Page
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.
Sourcepub fn update(&self, core: &mut Core, page: &mut Page, redraw: bool)
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.
Sourcepub fn tile(&self, core: &mut Core) -> Tile
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?
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
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 }