pub struct Output { /* private fields */ }Expand description
Output buffer for the terminal
This just buffers byte data on the way to the terminal. It allows
batching up a whole screen update into a single write, to try to
avoid tearing. This is shared between the Terminal actor and
the actor(s) that will be writing data to the terminal whilst
output is enabled via TermShare shared references.
Note that coordinates and sizes are passed as i32 here, because
that is more convenient when relative offsets might be negative.
Calls that add to the buffer return the same self value,
allowing the calls to be chained. This implements Write so
macro calls in the form of write!(termout, ...) may be used to
do formatted output. Nothing will be send to the output until the
flush() call is made.
Not all ANSI sequences are covered here, just the basic ones
required to implement a full-screen application and that are
commonly supported everywhere, i.e. the lowest common denominator.
If you need another ANSI sequence, it is easy to create, for
example termout.csi().num(5).asc(';').num(10).asc('r') to set
the scroll region to lines 5-10.
Implementations§
Source§impl Output
impl Output
Sourcepub const BOX: &'static [char; 256]
pub const BOX: &'static [char; 256]
Unicode box-drawing characters. There are four options for
each direction: 0 nothing, 1 normal line, 2 thick line, 3
double line. The array index combines the four directions
using (up << 6) + (down << 4) + (left << 2) + right, giving
256 combinations. Where a combination doesn’t exist in
unicode (e.g. combined thick and double lines, or some
double-line combinations) a replacement is made by converting
double lines to thick lines.
See also Output::box_from_ascii_art
Sourcepub fn features(&self) -> &Features
pub fn features(&self) -> &Features
Get the features supported by the terminal
Examples found in repository?
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 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn sy(&self) -> i32
pub fn sy(&self) -> i32
Get current terminal size-Y, i.e. rows
Examples found in repository?
108 fn draw(o: &mut Output) {
109 o.clear_all_99();
110 let sx = o.sx();
111 let sy = o.sy();
112 if sy < 24 || sx < 80 {
113 o.hfb(162);
114 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
115 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
116 o.hfb(99);
117 o.flush();
118 return;
119 }
120
121 const TEXT: [char; 17] = [
122 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', '.', ' ', ' ',
123 ];
124 let mut last_hfb = 99;
125 for y in 0..sy {
126 o.at(y, 0);
127 for x in 0..sx {
128 let hfb = ((x * 8) / sx + (y & 7) * 10 + ((y >> 3) & 1) * 100) as u16;
129 if hfb != last_hfb {
130 o.hfb(hfb);
131 last_hfb = hfb;
132 }
133 o.char(TEXT[(1000 + x - y) as usize % TEXT.len()]);
134 }
135 }
136 o.at(sy - 2, (sx - 60) / 2)
137 .hfb(162)
138 .text("[ Type to show decoding, Ctrl-C to exit, Ctrl-L to redraw ]")
139 .hfb(99);
140 o.at(0, 0);
141 o.flush();
142 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn sx(&self) -> i32
pub fn sx(&self) -> i32
Get current terminal size-X, i.e. columns
Examples found in repository?
108 fn draw(o: &mut Output) {
109 o.clear_all_99();
110 let sx = o.sx();
111 let sy = o.sy();
112 if sy < 24 || sx < 80 {
113 o.hfb(162);
114 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
115 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
116 o.hfb(99);
117 o.flush();
118 return;
119 }
120
121 const TEXT: [char; 17] = [
122 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', '.', ' ', ' ',
123 ];
124 let mut last_hfb = 99;
125 for y in 0..sy {
126 o.at(y, 0);
127 for x in 0..sx {
128 let hfb = ((x * 8) / sx + (y & 7) * 10 + ((y >> 3) & 1) * 100) as u16;
129 if hfb != last_hfb {
130 o.hfb(hfb);
131 last_hfb = hfb;
132 }
133 o.char(TEXT[(1000 + x - y) as usize % TEXT.len()]);
134 }
135 }
136 o.at(sy - 2, (sx - 60) / 2)
137 .hfb(162)
138 .text("[ Type to show decoding, Ctrl-C to exit, Ctrl-L to redraw ]")
139 .hfb(99);
140 o.at(0, 0);
141 o.flush();
142 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn flush(&mut self)
pub fn flush(&mut self)
Mark all the data from the start of the buffer to the current
end of the buffer as ready for flushing and send a message to
the Terminal to do the flush. Any data added after this
call won’t be flushed unless another call to this method is
made. This gives precise control of how much data is flushed
despite flushing being an asynchronous operation.
Examples found in repository?
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 }
107
108 fn draw(o: &mut Output) {
109 o.clear_all_99();
110 let sx = o.sx();
111 let sy = o.sy();
112 if sy < 24 || sx < 80 {
113 o.hfb(162);
114 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
115 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
116 o.hfb(99);
117 o.flush();
118 return;
119 }
120
121 const TEXT: [char; 17] = [
122 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', '.', ' ', ' ',
123 ];
124 let mut last_hfb = 99;
125 for y in 0..sy {
126 o.at(y, 0);
127 for x in 0..sx {
128 let hfb = ((x * 8) / sx + (y & 7) * 10 + ((y >> 3) & 1) * 100) as u16;
129 if hfb != last_hfb {
130 o.hfb(hfb);
131 last_hfb = hfb;
132 }
133 o.char(TEXT[(1000 + x - y) as usize % TEXT.len()]);
134 }
135 }
136 o.at(sy - 2, (sx - 60) / 2)
137 .hfb(162)
138 .text("[ Type to show decoding, Ctrl-C to exit, Ctrl-L to redraw ]")
139 .hfb(99);
140 o.at(0, 0);
141 o.flush();
142 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn text(&mut self, data: &str) -> &mut Self
pub fn text(&mut self, data: &str) -> &mut Self
Add a chunk of UTF-8 string data to the output buffer.
See also the Write implementation, which allows use of
write! and writeln! to add data to the buffer.
Examples found in repository?
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 }
107
108 fn draw(o: &mut Output) {
109 o.clear_all_99();
110 let sx = o.sx();
111 let sy = o.sy();
112 if sy < 24 || sx < 80 {
113 o.hfb(162);
114 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
115 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
116 o.hfb(99);
117 o.flush();
118 return;
119 }
120
121 const TEXT: [char; 17] = [
122 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', '.', ' ', ' ',
123 ];
124 let mut last_hfb = 99;
125 for y in 0..sy {
126 o.at(y, 0);
127 for x in 0..sx {
128 let hfb = ((x * 8) / sx + (y & 7) * 10 + ((y >> 3) & 1) * 100) as u16;
129 if hfb != last_hfb {
130 o.hfb(hfb);
131 last_hfb = hfb;
132 }
133 o.char(TEXT[(1000 + x - y) as usize % TEXT.len()]);
134 }
135 }
136 o.at(sy - 2, (sx - 60) / 2)
137 .hfb(162)
138 .text("[ Type to show decoding, Ctrl-C to exit, Ctrl-L to redraw ]")
139 .hfb(99);
140 o.at(0, 0);
141 o.flush();
142 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn bytes(&mut self, data: &[u8]) -> &mut Self
pub fn bytes(&mut self, data: &[u8]) -> &mut Self
Add a chunk of byte data to the output buffer.
See also the Write implementation, which allows use of
write! and writeln! to add data to the buffer.
Sourcepub fn char(&mut self, ch: char) -> &mut Self
pub fn char(&mut self, ch: char) -> &mut Self
Add a char to the output buffer as 1-4 bytes of UTF-8
Examples found in repository?
108 fn draw(o: &mut Output) {
109 o.clear_all_99();
110 let sx = o.sx();
111 let sy = o.sy();
112 if sy < 24 || sx < 80 {
113 o.hfb(162);
114 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
115 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
116 o.hfb(99);
117 o.flush();
118 return;
119 }
120
121 const TEXT: [char; 17] = [
122 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', '.', ' ', ' ',
123 ];
124 let mut last_hfb = 99;
125 for y in 0..sy {
126 o.at(y, 0);
127 for x in 0..sx {
128 let hfb = ((x * 8) / sx + (y & 7) * 10 + ((y >> 3) & 1) * 100) as u16;
129 if hfb != last_hfb {
130 o.hfb(hfb);
131 last_hfb = hfb;
132 }
133 o.char(TEXT[(1000 + x - y) as usize % TEXT.len()]);
134 }
135 }
136 o.at(sy - 2, (sx - 60) / 2)
137 .hfb(162)
138 .text("[ Type to show decoding, Ctrl-C to exit, Ctrl-L to redraw ]")
139 .hfb(99);
140 o.at(0, 0);
141 o.flush();
142 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn spaces(&mut self, n: i32) -> &mut Self
pub fn spaces(&mut self, n: i32) -> &mut Self
Add N spaces. The spaces are written with the current colour-pair. This is the only portable way to write areas of coloured empty cells.
Examples found in repository?
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn esc(&mut self, c: char) -> &mut Self
pub fn esc(&mut self, c: char) -> &mut Self
Add an ESC byte (27) + ASCII byte to the output buffer.
Sourcepub fn num(&mut self, v: i32) -> &mut Self
pub fn num(&mut self, v: i32) -> &mut Self
Add a 1-3 digit decimal number (0..=999) to the output buffer, as used in control sequences. If number is out of range, then nearest valid number is used.
Sourcepub fn at(&mut self, y: i32, x: i32) -> &mut Self
pub fn at(&mut self, y: i32, x: i32) -> &mut Self
Add ANSI sequence to move cursor to the given coordinates. Note that coordinates are row-first, with (0,0) as top-left. Coordinates are taken modulo the screen dimensions, so for example -1,-1 is bottom-right, and (0, -10) is 10 from the right on the top line.
Examples found in repository?
108 fn draw(o: &mut Output) {
109 o.clear_all_99();
110 let sx = o.sx();
111 let sy = o.sy();
112 if sy < 24 || sx < 80 {
113 o.hfb(162);
114 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
115 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
116 o.hfb(99);
117 o.flush();
118 return;
119 }
120
121 const TEXT: [char; 17] = [
122 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', '.', ' ', ' ',
123 ];
124 let mut last_hfb = 99;
125 for y in 0..sy {
126 o.at(y, 0);
127 for x in 0..sx {
128 let hfb = ((x * 8) / sx + (y & 7) * 10 + ((y >> 3) & 1) * 100) as u16;
129 if hfb != last_hfb {
130 o.hfb(hfb);
131 last_hfb = hfb;
132 }
133 o.char(TEXT[(1000 + x - y) as usize % TEXT.len()]);
134 }
135 }
136 o.at(sy - 2, (sx - 60) / 2)
137 .hfb(162)
138 .text("[ Type to show decoding, Ctrl-C to exit, Ctrl-L to redraw ]")
139 .hfb(99);
140 o.at(0, 0);
141 o.flush();
142 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn skip(&mut self, n: i32) -> &mut Self
pub fn skip(&mut self, n: i32) -> &mut Self
Add ANSI sequence to skip the cursor forwards (rightwards) N cells, without overwriting them.
Sourcepub fn newline(&mut self) -> &mut Self
pub fn newline(&mut self) -> &mut Self
Move cursor to the start of the next row. Note that writing a full line leaves the write position just past the end of the line, but not on the next line, so calling this method correctly moves to the next line in that case.
Sourcepub fn attr(&mut self, codes: &str) -> &mut Self
pub fn attr(&mut self, codes: &str) -> &mut Self
Add an attribute string. The codes passed should be the semicolon-separated list of numeric codes, for example “1;31;46”.
Sourcepub fn hfb(&mut self, hfb: u16) -> &mut Self
pub fn hfb(&mut self, hfb: u16) -> &mut Self
Add an attribute string to provide the given HFB attribute-set
expressed as 3 decimal digits HFB, or 2 decimal digits FB,
or for 256-colours as a value returned by
Output::hfb_alloc. This is intended for compact
representation of combinations of the basic 8 colours and bold
and/or underline.
H is highlight, used to control bold/underline: 0 normal, 1
bold, 2 underline, 3 bold+underline. F and B are
foreground and background in colour-intensity order, 0-9: 0
black, 1 blue, 2 red, 3 magenta, 4 green, 5 cyan, 6 yellow, 7
white, 9 default. Note that this means that 99 gives the
default colour combination, i.e. white on black on a black
terminal, or black on white on a white terminal.
Examples found in repository?
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 }
107
108 fn draw(o: &mut Output) {
109 o.clear_all_99();
110 let sx = o.sx();
111 let sy = o.sy();
112 if sy < 24 || sx < 80 {
113 o.hfb(162);
114 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
115 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
116 o.hfb(99);
117 o.flush();
118 return;
119 }
120
121 const TEXT: [char; 17] = [
122 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', '.', ' ', ' ',
123 ];
124 let mut last_hfb = 99;
125 for y in 0..sy {
126 o.at(y, 0);
127 for x in 0..sx {
128 let hfb = ((x * 8) / sx + (y & 7) * 10 + ((y >> 3) & 1) * 100) as u16;
129 if hfb != last_hfb {
130 o.hfb(hfb);
131 last_hfb = hfb;
132 }
133 o.char(TEXT[(1000 + x - y) as usize % TEXT.len()]);
134 }
135 }
136 o.at(sy - 2, (sx - 60) / 2)
137 .hfb(162)
138 .text("[ Type to show decoding, Ctrl-C to exit, Ctrl-L to redraw ]")
139 .hfb(99);
140 o.at(0, 0);
141 o.flush();
142 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn clear_all_99(&mut self) -> &mut Self
pub fn clear_all_99(&mut self) -> &mut Self
Add ANSI sequence to clear the whole display. This clears with the terminal’s default colour-pair (99), and leaves the current colours set to the default, and cursor at top-left.
Examples found in repository?
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 }More examples
108 fn draw(o: &mut Output) {
109 o.clear_all_99();
110 let sx = o.sx();
111 let sy = o.sy();
112 if sy < 24 || sx < 80 {
113 o.hfb(162);
114 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
115 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
116 o.hfb(99);
117 o.flush();
118 return;
119 }
120
121 const TEXT: [char; 17] = [
122 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', '.', ' ', ' ',
123 ];
124 let mut last_hfb = 99;
125 for y in 0..sy {
126 o.at(y, 0);
127 for x in 0..sx {
128 let hfb = ((x * 8) / sx + (y & 7) * 10 + ((y >> 3) & 1) * 100) as u16;
129 if hfb != last_hfb {
130 o.hfb(hfb);
131 last_hfb = hfb;
132 }
133 o.char(TEXT[(1000 + x - y) as usize % TEXT.len()]);
134 }
135 }
136 o.at(sy - 2, (sx - 60) / 2)
137 .hfb(162)
138 .text("[ Type to show decoding, Ctrl-C to exit, Ctrl-L to redraw ]")
139 .hfb(99);
140 o.at(0, 0);
141 o.flush();
142 }86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn clear_all_99_and_remote(&mut self) -> &mut Self
pub fn clear_all_99_and_remote(&mut self) -> &mut Self
Add ANSI sequence to clear the whole display. This clears with the terminal’s default colour-pair (99), and leaves the current colours set to the default, and cursor at top-left.
This also clears the internal idea of what the remote page looks like for the update and tile mechanism, so that updates operate correctly. This would typically be called on a resize.
Examples found in repository?
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 clear_all(&mut self) -> &mut Self
pub fn clear_all(&mut self) -> &mut Self
Clear the whole display to the current colour-pair. This is done by writing spaces to all the cells on the display, since it cannot be done portably using ANSI sequences. Leaves cursor at top-left.
Sourcepub fn clear_eol_99(&mut self) -> &mut Self
pub fn clear_eol_99(&mut self) -> &mut Self
Add ANSI sequence to erase to end-of-line. This erases with the terminal’s default colour-pair (99), and leaves the current colours set to the default. Some terminals can erase with any colour-pair, but this is not univerally supported, so is not provided here.
Sourcepub fn attr_99(&mut self) -> &mut Self
pub fn attr_99(&mut self) -> &mut Self
Add ANSI sequence to reset attributes to the default colour-pair (99). The default colour-pair is white on black on a black terminal, or black on white on a white terminal.
Examples found in repository?
More examples
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 }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 reset(&mut self) -> &mut Self
pub fn reset(&mut self) -> &mut Self
Add ANSI sequence to do a full reset of the terminal. This is
ESC c. The screen is erased, and all settings are reset to
defaults. This includes tab stops, scroll region, character
set, etc.
Sourcepub fn cursor_underline(&mut self) -> &mut Self
pub fn cursor_underline(&mut self) -> &mut Self
Add ANSI sequence to switch to underline cursor
Sourcepub fn cursor_block(&mut self) -> &mut Self
pub fn cursor_block(&mut self) -> &mut Self
Add ANSI sequence to switch to block cursor
Sourcepub fn cursor_show(&mut self) -> &mut Self
pub fn cursor_show(&mut self) -> &mut Self
Add ANSI sequences to show cursor
Examples found in repository?
More examples
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 }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 cursor_hide(&mut self) -> &mut Self
pub fn cursor_hide(&mut self) -> &mut Self
Add ANSI sequences to hide cursor
Examples found in repository?
More examples
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 }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 scroll_up(&mut self) -> &mut Self
pub fn scroll_up(&mut self) -> &mut Self
Move cursor to bottom line and do a linefeed. This results in the screen scrolling one line, and the cursor being left at the bottom-left corner, with default colours active.
Examples found in repository?
More examples
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 }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 save_cleanup(&mut self)
pub fn save_cleanup(&mut self)
Save the current contents of the output buffer as the cleanup string, then clear the output buffer. The cleanup string will be output to the terminal on error or when the terminal is paused or shutdown.
This string should reset any settings that have been modified,
and put the cursor somewhere sensible. The default is Esc c
which completely resets the terminal, but usually it’s better
to do something less drastic, resetting just the terminal
state that was changed by the app, for example
termout.attr_99().show_cursor().scroll_up().save_cleanup().
The new cleanup string will be installed on the next flush.
Note that when the Terminal actor is dropped, the cleanup
string will be emitted if required. However if the event loop
has stopped running, then this will not happen. So in the app
shutdown, it’s important that the Terminal actor is
dropped before the main loop stops running. See the examples
for configurations that work.
Examples found in repository?
More examples
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 }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 hfb_alloc(
&mut self,
bold: bool,
underline: bool,
fg: u32,
bg: u32,
) -> u16
pub fn hfb_alloc( &mut self, bold: bool, underline: bool, fg: u32, bg: u32, ) -> u16
Allocate an HFB value to represent the given attribute-set
(bold, underline, foreground, background), where colours are
expressed using 0xRRGGBB values. Chooses nearest colours
out of standard 256-colour palette if available, or else
reverts to 8-colour approximations. If the colour has been
allocated previously, returns that HFB value. Colour
allocations last as long as the Terminal actor remains
alive.
Examples found in repository?
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 }More examples
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Sourcepub fn rgb_interpolate(&self, list: &[(f64, u32)], value: f64) -> u32
pub fn rgb_interpolate(&self, list: &[(f64, u32)], value: f64) -> u32
Generate an interpolated 24-bit RGB value based on the given
value within the given ordered list of value-to-RGB mappings
(f64, u32) which should be in order of value. If the
provided value is before the first or after the last, the
first/last RGB value is returned instead of an interpolated
value.
Examples found in repository?
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 }Sourcepub fn update_to(&mut self, page: &mut Page, redraw: bool)
pub fn update_to(&mut self, page: &mut Page, redraw: bool)
Update the terminal screen to match the given Page. A
minimised update is sent to the terminal (by comparing to the
previous Page sent) unless redraw is true in which case
the terminal is cleared and a full update is sent.
Sourcepub fn new_page(&self) -> Page
pub fn new_page(&self) -> Page
Create a new blank Page with the same size as the
terminal, cleared to default foreground/background colours
(HFB 99).
Examples found in repository?
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 }Sourcepub fn box_from_ascii_art(inp: &str) -> String
pub fn box_from_ascii_art(inp: &str) -> String
Generate a multi-line diagram in Unicode box characters from simple ASCII-art. The input is a multi-line diagram using the following characters:
|and-for single-line vertical and horizontalHand=for double-lined vertical and horizontal$and*for thick single-line vertical and horizontal+for a cautious joiner, which won’t join to itself#for an enthusiastic joiner, which will join to any joiner
The joiner uses thick, thin or double parts depending on the adjacent characters.
Examples found in repository?
86 fn draw(o: &mut Output) {
87 o.clear_all_99();
88 if o.sy() < 24 || o.sx() < 80 {
89 o.hfb(162);
90 o.at(o.sy() >> 1, (o.sx() - 30) >> 1);
91 write!(o, " Terminal too small: {} x {} ", o.sy(), o.sx()).unwrap();
92 o.hfb(99);
93 o.flush();
94 return;
95 }
96
97 let x0 = (o.sx() - 80) >> 1;
98 let y0 = (o.sy() - 24) >> 1;
99 let mut yy = y0;
100 let c256 = o.features().colour_256;
101 o.at(yy, x0).hfb(99).text("Colour mode:");
102 o.at(yy, x0 + 15)
103 .hfb(199)
104 .text(if c256 { "256-colour" } else { "8-colour" });
105 yy += 2;
106
107 o.at(yy, x0).hfb(99).text("Attributes:");
108 yy += 1;
109 const TEXT: [&str; 4] = ["White:", "Brown:", "Blue:", "Black:"];
110 const BASE_HFB: [u16; 4] = [70, 60, 10, 3];
111 for i in 0..4 {
112 let hfb = BASE_HFB[i];
113 o.at(yy, x0 + 2).hfb(99).text(TEXT[i]);
114 o.at(yy, x0 + 16).hfb(hfb).text(" norm ");
115 o.at(yy, x0 + 22).hfb(100 + hfb).text("bold ");
116 o.at(yy, x0 + 27).hfb(200 + hfb).text("undl ");
117 o.at(yy, x0 + 32).hfb(300 + hfb).text("both ");
118 yy += 1;
119 }
120 o.at(yy + 1, x0)
121 .hfb(60)
122 .text(" (On 8-colour expect bold/ul to");
123 o.at(yy + 2, x0)
124 .hfb(60)
125 .text(" be emulated as colour changes.)");
126 let y1a = yy + 3;
127
128 yy = y0;
129 o.at(yy, x0 + 40)
130 .hfb(99)
131 .text("Base, bold and background colours:");
132 o.at(yy + 1, x0 + 42).hfb(7).text(" black ");
133 o.at(yy + 2, x0 + 42).hfb(10).text(" blue ");
134 o.at(yy + 3, x0 + 42).hfb(20).text(" red ");
135 o.at(yy + 4, x0 + 42).hfb(30).text(" magenta ");
136 o.at(yy + 5, x0 + 42).hfb(40).text(" green ");
137 o.at(yy + 6, x0 + 42).hfb(50).text(" cyan ");
138 o.at(yy + 7, x0 + 42).hfb(60).text(" yellow ");
139 o.at(yy + 8, x0 + 42).hfb(70).text(" white ");
140 o.at(yy + 1, x0 + 54).hfb(100).text(" black ");
141 o.at(yy + 2, x0 + 54).hfb(110).text(" blue ");
142 o.at(yy + 3, x0 + 54).hfb(120).text(" red ");
143 o.at(yy + 4, x0 + 54).hfb(130).text(" magenta ");
144 o.at(yy + 5, x0 + 54).hfb(140).text(" green ");
145 o.at(yy + 6, x0 + 54).hfb(150).text(" cyan ");
146 o.at(yy + 7, x0 + 54).hfb(160).text(" yellow ");
147 o.at(yy + 8, x0 + 54).hfb(170).text(" white ");
148 o.at(yy + 1, x0 + 66).hfb(70).text(" black ");
149 o.at(yy + 2, x0 + 66).hfb(71).text(" blue ");
150 o.at(yy + 3, x0 + 66).hfb(72).text(" red ");
151 o.at(yy + 4, x0 + 66).hfb(73).text(" magenta ");
152 o.at(yy + 5, x0 + 66).hfb(4).text(" green ");
153 o.at(yy + 6, x0 + 66).hfb(5).text(" cyan ");
154 o.at(yy + 7, x0 + 66).hfb(6).text(" yellow ");
155 o.at(yy + 8, x0 + 66).hfb(7).text(" white ");
156 o.at(yy + 10, x0 + 40)
157 .hfb(60)
158 .text(" (Expect all 16 colours to be");
159 o.at(yy + 11, x0 + 40)
160 .hfb(60)
161 .text(" visible in all cases.)");
162 let y1b = yy + 12;
163 let end = y1a.max(y1b);
164
165 yy = end + 10;
166 o.at(yy - 1, x0).hfb(99).text("Hue wheel");
167 o.at(yy, x0);
168 if o.features().colour_256 {
169 const RED: [i32; 7] = [255, 255, 0, 0, 0, 255, 255];
170 const GREEN: [i32; 7] = [0, 255, 255, 255, 0, 0, 0];
171 const BLUE: [i32; 7] = [0, 0, 0, 255, 255, 255, 0];
172 for x in 0..78 {
173 let i = x / 13;
174 let off = (x - i * 13) as i32;
175 let r = RED[i] + (RED[i + 1] - RED[i]) * off / 13;
176 let g = GREEN[i] + (GREEN[i + 1] - GREEN[i]) * off / 13;
177 let b = BLUE[i] + (BLUE[i + 1] - BLUE[i]) * off / 13;
178 let rgb = (r << 16) + (g << 8) + b;
179 let hfb = o.hfb_alloc(false, false, 0xFFFFFF, rgb as u32);
180 o.hfb(hfb).spaces(1);
181 }
182 } else {
183 o.hfb(2).spaces(13);
184 o.hfb(6).spaces(13);
185 o.hfb(4).spaces(13);
186 o.hfb(5).spaces(13);
187 o.hfb(1).spaces(13);
188 o.hfb(3).spaces(13);
189 }
190
191 yy = end + 1;
192 let mut xx = x0 + 40;
193
194 o.at(yy, xx).hfb(99).text("ASCII");
195 for a in 0..96 {
196 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
197 .char(char::from_u32((a + 32) as u32).unwrap());
198 }
199
200 xx += 20;
201 o.at(yy, xx).hfb(99).text("Latin-1");
202 for a in 0..96 {
203 o.at(yy + 1 + (a >> 4), xx + 1 + (a & 15))
204 .char(char::from_u32((a + 160) as u32).unwrap());
205 }
206
207 const BOXTITLE1: &str = "\
208Single Single Double Thick";
209 const BOXTITLE2: &str = "\
210+Double +Thick +Single +Single";
211
212 const BOXTEST: &str = "\
213+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
214| | H | | | $ | H H | H $ $ | $
215+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+
216| | H | | | $ | H H | H $ $ | $
217+=+=+=+ +*+*+*+ +-+-+-+ +-+-+-+
218| | H | | | $ | H H | H $ $ | $
219+-+-+-+ +-+-+-+ +=+=+=+ +*+*+*+";
220
221 let boxtest = Output::box_from_ascii_art(BOXTEST);
222 yy = end + 1;
223 xx = x0 + 2;
224 o.at(yy - 2, xx).text(BOXTITLE1);
225 o.at(yy - 1, xx).text(BOXTITLE2);
226 for line in boxtest.split('\n') {
227 o.at(yy, xx).text(line);
228 yy += 1;
229 }
230
231 o.flush();
232 }Trait Implementations§
Source§impl Write for Output
impl Write for Output
Source§fn flush(&mut self) -> Result<()>
fn flush(&mut self) -> Result<()>
Logically we consider the final destination of the Write trait
to be the buffer. So this flush call does nothing. In
general we’ll want to gather all the updates into one big
flush to avoid tearing on the terminal.
Source§fn write(&mut self, buf: &[u8]) -> Result<usize>
fn write(&mut self, buf: &[u8]) -> Result<usize>
Source§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
can_vector)1.0.0 · Source§fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
Source§fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>
write_all_vectored)