coded_chars/format.rs
1//! These control functions change the format.
2
3use std::fmt::{Display, Formatter};
4use crate::control::ControlSequence;
5use crate::escape::{escape, EscapeSequence};
6
7/// # Backspace
8///
9/// BS causes the active data position to be moved one character position in the data component in the
10/// direction opposite to that of the implicit movement.
11///
12/// The direction of the implicit movement depends on the parameter value of SELECT IMPLICIT
13/// MOVEMENT DIRECTION (SIMD).
14pub const BS: char = '\x08';
15
16/// # Horizontal tabulation
17///
18/// HT causes the active presentation position to be moved to the following character tabulation stop in the
19/// presentation component.
20///
21/// In addition, if that following character tabulation stop has been set by TABULATION ALIGN CENTRE
22/// (TAC), TABULATION ALIGN LEADING EDGE (TALE), TABULATION ALIGN TRAILING EDGE
23/// (TATE) or TABULATION CENTRED ON CHARACTER (TCC), HT indicates the beginning of a string
24/// of text which is to be positioned within a line according to the properties of that tabulation stop. The end
25/// of the string is indicated by the next occurrence of HT or CARRIAGE RETURN (CR) or NEXT LINE
26/// (NEL) in the data stream.
27pub const HT: char = '\x09';
28
29/// # Line feed
30///
31/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, LF causes the
32/// active presentation position to be moved to the corresponding character position of the following line in
33/// the presentation component.
34///
35/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, LF causes the active data
36/// position to be moved to the corresponding character position of the following line in the data
37/// component
38pub const LF: char = '\x0A';
39
40/// # Vertical tabulation
41///
42/// VT causes the active presentation position to be moved in the presentation component to the
43/// corresponding character position on the line at which the following line tabulation stop is set.
44pub const VT: char = '\x0B';
45
46/// # Form feed
47///
48/// FF causes the active presentation position to be moved to the corresponding character position of the
49/// line at the page home position of the next form or page in the presentation component. The page home
50/// position is established by the parameter value of SET PAGE HOME (SPH).
51pub const FF: char = '\x0C';
52
53/// # Carriage return
54///
55/// The effect of CR depends on the setting of the DEVICE COMPONENT SELECT MODE (DCSM) and
56/// on the parameter value of SELECT IMPLICIT MOVEMENT DIRECTION (SIMD).
57///
58/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION and with the
59/// parameter value of SIMD equal to 0, CR causes the active presentation position to be moved to the line
60/// home position of the same line in the presentation component. The line home position is established by
61/// the parameter value of SET LINE HOME (SLH).
62///
63/// With a parameter value of SIMD equal to 1, CR causes the active presentation position to be moved to
64/// the line limit position of the same line in the presentation component. The line limit position is
65/// established by the parameter value of SET LINE LIMIT (SLL).
66///
67/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA and with a parameter value of
68/// SIMD equal to 0, CR causes the active data position to be moved to the line home position of the same
69/// line in the data component. The line home position is established by the parameter value of SET LINE
70/// HOME (SLH).
71///
72/// With a parameter value of SIMD equal to 1, CR causes the active data position to be moved to the line
73/// limit position of the same line in the data component. The line limit position is established by the
74/// parameter value of SET LINE LIMIT (SLL).
75pub const CR: char = '\x0D';
76
77/// # Character tabulation with justification
78///
79/// HTJ causes the contents of the active field (the field in the presentation component that contains the
80/// active presentation position) to be shifted forward so that it ends at the character position preceding the
81/// following character tabulation stop. The active presentation position is moved to that following character
82/// tabulation stop. The character positions which precede the beginning of the shifted string are put into the
83/// erased state.
84pub const HTJ: EscapeSequence = escape('I');
85
86/// # Character tabulation set
87///
88/// HTS causes a character tabulation stop to be set at the active presentation position in the presentation component.
89///
90/// The number of lines affected depends on the setting of the TABULATION STOP MODE (TSM).
91pub const HTS: EscapeSequence = escape('H');
92
93/// # Next line
94///
95/// The effect of NEL depends on the setting of the DEVICE COMPONENT SELECT MODE (DCSM) and
96/// on the parameter value of SELECT IMPLICIT MOVEMENT DIRECTION (SIMD).
97///
98/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION and with a
99/// parameter value of SIMD equal to 0, NEL causes the active presentation position to be moved to the line
100/// home position of the following line in the presentation component. The line home position is established
101/// by the parameter value of SET LINE HOME (SLH).
102///
103/// With a parameter value of SIMD equal to 1, NEL causes the active presentation position to be moved to
104/// the line limit position of the following line in the presentation component. The line limit position is
105/// established by the parameter value of SET LINE LIMIT (SLL).
106///
107/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA and with a parameter value of
108/// SIMD equal to 0, NEL causes the active data position to be moved to the line home position of the
109/// following line in the data component. The line home position is established by the parameter value of
110/// SET LINE HOME (SLH).
111///
112/// With a parameter value of SIMD equal to 1, NEL causes the active data position to be moved to the line
113/// limit position of the following line in the data component. The line limit position is established by the
114/// parameter value of SET LINE LIMIT (SLL).
115pub const NEL: EscapeSequence = escape('E');
116
117/// # Partial line forward
118///
119/// PLD causes the active presentation position to be moved in the presentation component to the
120/// corresponding position of an imaginary line with a partial offset in the direction of the line progression.
121/// This offset should be sufficient either to image following characters as subscripts until the first
122/// following occurrence of PARTIAL LINE BACKWARD (PLU) in the data stream, or, if preceding
123/// characters were imaged as superscripts, to restore imaging of following characters to the active line (the
124/// line that contains the active presentation position).
125///
126/// Any interactions between PLD and format effectors other than PLU are not defined by this Standard.
127pub const PLD: EscapeSequence = escape('K');
128
129/// # Partial line backward
130///
131/// PLU causes the active presentation position to be moved in the presentation component to the
132/// corresponding position of an imaginary line with a partial offset in the direction opposite to that of the
133/// line progression. This offset should be sufficient either to image following characters as superscripts
134/// until the first following occurrence of PARTIAL LINE FORWARD (PLD) in the data stream, or, if
135/// preceding characters were imaged as subscripts, to restore imaging of following characters to the active
136/// line (the line that contains the active presentation position).
137///
138/// Any interactions between PLU and format effectors other than PLD are not defined by this Standard.
139pub const PLU: EscapeSequence = escape('L');
140
141/// Reserve line feed
142pub const RI: EscapeSequence = escape('M');
143
144/// # Line tabulation set
145///
146/// VTS causes a line tabulation stop to be set at the active line (the line that contains the active presentation position).
147pub const VTS: EscapeSequence = escape('J');
148
149
150/// # HPA - Character position absolute
151///
152/// HPA causes the active data position to be moved to character position `n` in the active line (the line in the
153/// data component that contains the active data position).
154pub fn character_absolute(n: usize) -> ControlSequence {
155 ControlSequence::new(&[&n.to_string()], "`")
156}
157
158/// # HPB - Character position backward
159///
160/// HPB causes the active data position to be moved by `n` character positions in the data component in the
161/// direction opposite to that of the character progression.
162pub fn character_backward(n: usize) -> ControlSequence {
163 ControlSequence::new(&[&n.to_string()], "j")
164}
165
166/// # HPR - Character position forward
167///
168/// HPR causes the active data position to be moved by `n` character positions in the data component in the
169/// direction of the character progression.
170pub fn character_forward(n: usize) -> ControlSequence {
171 ControlSequence::new(&[&n.to_string()], "a")
172}
173
174/// # HVP - Character and line position
175///
176/// HVP causes the active data position to be moved in the data component to the `l`-th line position
177/// according to the line progression and to the `c`-th character position according to the character
178/// progression.
179pub fn character_and_line_position(l: usize, c: usize) -> ControlSequence {
180 ControlSequence::new(&[&l.to_string(), &c.to_string()], "f")
181}
182
183/// # PPA - Page position absolute
184///
185/// PPA causes the active data position to be moved in the data component to the corresponding character
186/// position on the `n`-th page.
187pub fn page_position(n: usize) -> ControlSequence {
188 ControlSequence::new(&[&n.to_string()], " P")
189}
190
191/// # PPB - Page position backward
192///
193/// PPB causes the active data position to be moved in the data component to the corresponding character
194/// position on the `n`-th preceding page.
195pub fn page_backward(n: usize) -> ControlSequence {
196 ControlSequence::new(&[&n.to_string()], " R")
197}
198
199/// # PPR - Page position forward
200///
201/// PPR causes the active data position to be moved in the data component to the corresponding character
202/// position on the `n`-th following page.
203pub fn page_forward(n: usize) -> ControlSequence {
204 ControlSequence::new(&[&n.to_string()], " Q")
205}
206
207/// # TBC - Tabulation clear
208///
209/// TBC causes one or more tabulation stops in the presentation component to be cleared.
210pub fn clear_tabulation(tabulation_control: TabulationControl) -> ControlSequence {
211 ControlSequence::new(&[&tabulation_control.to_string()], "g")
212}
213
214#[derive(Copy, Clone, Debug)]
215pub enum TabulationControl {
216 /// A character tabulation stop is set at the active presentation position.
217 Character,
218 /// A line tabulation stop is set at the active line (the line that contains the active presentation position).
219 Line,
220 /// The character tabulation stop at the active presentation position is cleared.
221 CharacterRemove,
222 /// The line tabulation stop at the active line is cleared.
223 LineRemove,
224 /// All character tabulation stops in the active line are cleared.
225 CharacterClearLine,
226 /// All character tabulation stops are cleared.
227 CharacterClearAll,
228 /// All line tabulation stops are cleared.
229 LineClearAll,
230}
231
232impl Display for TabulationControl {
233 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
234 write!(f, "{}", match self {
235 TabulationControl::Character => "0",
236 TabulationControl::Line => "1",
237 TabulationControl::CharacterRemove => "2",
238 TabulationControl::LineRemove => "3",
239 TabulationControl::CharacterClearLine => "4",
240 TabulationControl::CharacterClearAll => "5",
241 TabulationControl::LineClearAll => "6",
242 })
243 }
244}
245
246/// # TSR - Tabulation stop remove
247///
248/// TSR causes any character tabulation stop at character position n in the active line (the line that contains
249/// the active presentation position) and lines of subsequent text in the presentation component to be
250/// cleared, but does not affect other tabulation stops.
251pub fn remove_tabulation_stop(n: usize) -> ControlSequence {
252 ControlSequence::new(&[&n.to_string()], " d")
253}
254
255/// # VPA - Line position absolute
256///
257/// VPA causes the active data position to be moved to line position n in the data component in a direction
258/// parallel to the line progression.
259pub fn line_position(n: usize) -> ControlSequence { ControlSequence::new(&[&n.to_string()], "d") }
260
261/// # VPB - Line position backward
262///
263/// VPB causes the active data position to be moved by n line positions in the data component in a direction
264/// opposite to that of the line progression.
265pub fn line_backward(n: usize) -> ControlSequence { ControlSequence::new(&[&n.to_string()], "k") }
266
267/// # VPR - Line position forward
268///
269/// VPR causes the active data position to be moved by n line positions in the data component in a direction
270/// parallel to the line progression.
271pub fn line_forward(n: usize) -> ControlSequence { ControlSequence::new(&[&n.to_string()], "e") }
272
273
274#[cfg(test)]
275mod tests {
276 use super::*;
277
278 #[test]
279 fn test_escape_constants() {
280 assert_eq!(NEL.to_string(), "\x1bE");
281 assert_eq!(PLD.to_string(), "\x1bK");
282 assert_eq!(PLU.to_string(), "\x1bL");
283 assert_eq!(RI.to_string(), "\x1bM");
284 assert_eq!(VTS.to_string(), "\x1bJ");
285 }
286
287 #[test]
288 fn test_character_absolute() {
289 let result = character_absolute(5);
290 assert_eq!(result.to_string(), "\u{1B}[5`");
291 }
292
293 #[test]
294 fn test_character_backward() {
295 let result = character_backward(3);
296 assert_eq!(result.to_string(), "\u{1B}[3j");
297 }
298
299 #[test]
300 fn test_character_forward() {
301 let result = character_forward(7);
302 assert_eq!(result.to_string(), "\u{1B}[7a");
303 }
304
305 #[test]
306 fn test_character_and_line_position() {
307 let result = character_and_line_position(2, 4);
308 assert_eq!(result.to_string(), "\u{1B}[2;4f");
309 }
310
311 #[test]
312 fn test_page_position() {
313 let result = page_position(1);
314 assert_eq!(result.to_string(), "\u{1B}[1 P");
315 }
316
317 #[test]
318 fn test_page_backward() {
319 let result = page_backward(2);
320 assert_eq!(result.to_string(), "\u{1B}[2 R");
321 }
322
323 #[test]
324 fn test_page_forward() {
325 let result = page_forward(3);
326 assert_eq!(result.to_string(), "\u{1B}[3 Q");
327 }
328
329 #[test]
330 fn test_clear_tabulation() {
331 let result = clear_tabulation(TabulationControl::LineClearAll);
332 assert_eq!(result.to_string(), "\u{1B}[6g");
333 }
334
335 #[test]
336 fn test_remove_tabulation_stop() {
337 let result = remove_tabulation_stop(8);
338 assert_eq!(result.to_string(), "\u{1B}[8 d");
339 }
340
341 #[test]
342 fn test_line_position() {
343 let result = line_position(5);
344 assert_eq!(result.to_string(), "\u{1B}[5d");
345 }
346
347 #[test]
348 fn test_line_backward() {
349 let result = line_backward(2);
350 assert_eq!(result.to_string(), "\u{1B}[2k");
351 }
352
353 #[test]
354 fn test_line_forward() {
355 let result = line_forward(4);
356 assert_eq!(result.to_string(), "\u{1B}[4e");
357 }
358
359 #[test]
360 fn test_tabulation_control_display_trait() {
361 assert_eq!(TabulationControl::Character.to_string(), "0");
362 assert_eq!(TabulationControl::Line.to_string(), "1");
363 assert_eq!(TabulationControl::CharacterRemove.to_string(), "2");
364 assert_eq!(TabulationControl::LineRemove.to_string(), "3");
365 assert_eq!(TabulationControl::CharacterClearLine.to_string(), "4");
366 assert_eq!(TabulationControl::CharacterClearAll.to_string(), "5");
367 assert_eq!(TabulationControl::LineClearAll.to_string(), "6");
368 }
369}