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}