coded_chars/
editor.rs

1//! Helps edit text.
2
3use std::fmt::{Display, Formatter};
4use crate::control::ControlSequence;
5
6/// # ICH - Insert character
7///
8/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, ICH is used to
9/// prepare the insertion of n characters, by putting into the erased state the active presentation position and,
10/// depending on the setting of the CHARACTER EDITING MODE (HEM), the n-1 preceding or following
11/// character positions in the presentation component, where n equals the value of `n`. The previous contents
12/// of the active presentation position and an adjacent string of character positions are shifted away from the
13/// active presentation position. The contents of n character positions at the other end of the shifted part are
14/// removed. The active presentation position is moved to the line home position in the active line. The line
15/// home position is established by the parameter value of SET LINE HOME (SLH).
16///
17/// The extent of the shifted part is established by SELECT EDITING EXTENT (SEE).
18///
19/// The effect of ICH on the start or end of a selected area, the start or end of a qualified area, or a
20/// tabulation stop in the shifted part, is not defined by this Standard.
21///
22/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, ICH is used to prepare the
23/// insertion of n characters, by putting into the erased state the active data position and, depending on the
24/// setting of the CHARACTER EDITING MODE (HEM), the n-1 preceding or following character
25/// positions in the data component, where n equals the value of `n`. The previous contents of the active data
26/// position and an adjacent string of character positions are shifted away from the active data position. The
27/// contents of n character positions at the other end of the shifted part are removed. The active data
28/// position is moved to the line home position in the active line. The line home position is established by
29/// the parameter value of SET LINE HOME (SLH).
30pub fn insert_char(n: usize) -> ControlSequence {
31    ControlSequence::new(&[&n.to_string()], "@")
32}
33
34/// # IL - Insert line
35///
36/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, IL is used to
37/// prepare the insertion of n lines, by putting into the erased state in the presentation component the active
38/// line (the line that contains the active presentation position) and, depending on the setting of the LINE
39/// EDITING MODE (VEM), the n-1 preceding or following lines, where n equals the value of `n`. The
40/// previous contents of the active line and of adjacent lines are shifted away from the active line. The
41/// contents of n lines at the other end of the shifted part are removed. The active presentation position is
42/// moved to the line home position in the active line. The line home position is established by the
43/// parameter value of SET LINE HOME (SLH).
44///
45/// The extent of the shifted part is established by SELECT EDITING EXTENT (SEE).
46///
47/// Any occurrences of the start or end of a selected area, the start or end of a qualified area, or a tabulation
48/// stop in the shifted part, are also shifted.
49///
50/// If the TABULATION STOP MODE (TSM) is set to SINGLE, character tabulation stops are cleared in
51/// the lines that are put into the erased state.
52///
53/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, IL is used to prepare the
54/// insertion of n lines, by putting into the erased state in the data component the active line (the line that
55/// contains the active data position) and, depending on the setting of the LINE EDITING MODE (VEM),
56/// the n-1 preceding or following lines, where n equals the value of `n`. The previous contents of the active
57/// line and of adjacent lines are shifted away from the active line. The contents of n lines at the other end
58/// of the shifted part are removed. The active data position is moved to the line home position in the active
59/// line. The line home position is established by the parameter value of SET LINE HOME (SLH).
60pub fn insert_line(n: usize) -> ControlSequence {
61    ControlSequence::new(&[&n.to_string()], "K")
62}
63
64/// # DCH - Delete character
65///
66/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, DCH causes the
67/// contents of the active presentation position and, depending on the setting of the CHARACTER
68/// EDITING MODE (HEM), the contents of the n-1 preceding or following character positions to be
69/// removed from the presentation component, where n equals the value of `n`. The resulting gap is closed
70/// by shifting the contents of the adjacent character positions towards the active presentation position. At
71/// the other end of the shifted part, n character positions are put into the erased state.
72///
73/// The extent of the shifted part is established by SELECT EDITING EXTENT (SEE).
74///
75/// The effect of DCH on the start or end of a selected area, the start or end of a qualified area, or a
76/// tabulation stop in the shifted part is not defined by this Standard.
77///
78/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, DCH causes the contents of
79/// the active data position and, depending on the setting of the CHARACTER EDITING MODE (HEM),
80/// the contents of the n-1 preceding or following character positions to be removed from the data
81/// component, where n equals the value of `n`. The resulting gap is closed by shifting the contents of the
82/// adjacent character positions towards the active data position. At the other end of the shifted part, n
83/// character positions are put into the erased state.
84pub fn delete_char(n: usize) -> ControlSequence {
85    ControlSequence::new(&[&n.to_string()], "P")
86}
87
88
89/// # DL - Delete line
90///
91/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, DL causes the
92/// contents of the active line (the line that contains the active presentation position) and, depending on the
93/// setting of the LINE EDITING MODE (VEM), the contents of the n-1 preceding or following lines to be
94/// removed from the presentation component, where n equals the value of `n`. The resulting gap is closed
95/// by shifting the contents of a number of adjacent lines towards the active line. At the other end of the
96/// shifted part, n lines are put into the erased state.
97///
98/// The active presentation position is moved to the line home position in the active line. The line home
99/// position is established by the parameter value of SET LINE HOME (SLH). If the TABULATION STOP
100/// MODE (TSM) is set to SINGLE, character tabulation stops are cleared in the lines that are put into the
101/// erased state.
102///
103/// The extent of the shifted part is established by SELECT EDITING EXTENT (SEE).
104///
105/// Any occurrences of the start or end of a selected area, the start or end of a qualified area, or a tabulation
106/// stop in the shifted part, are also shifted.
107///
108/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, DL causes the contents of the
109/// active line (the line that contains the active data position) and, depending on the setting of the LINE
110/// EDITING MODE (VEM), the contents of the n-1 preceding or following lines to be removed from the
111/// data component, where n equals the value of `n`. The resulting gap is closed by shifting the contents of a
112/// number of adjacent lines towards the active line. At the other end of the shifted part, n lines are put into
113/// the erased state. The active data position is moved to the line home position in the active line. The line
114/// home position is established by the parameter value of SET LINE HOME (SLH).
115pub fn delete_line(n: usize) -> ControlSequence {
116    ControlSequence::new(&[&n.to_string()], "M")
117}
118
119/// # ECH - Erase character
120///
121/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, ECH causes the
122/// active presentation position and the n-1 following character positions in the presentation component to
123/// be put into the erased state, where n equals the value of `n`.
124///
125/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, ECH causes the active data
126/// position and the n-1 following character positions in the data component to be put into the erased state,
127/// where n equals the value of `n`.
128///
129/// Whether the character positions of protected areas are put into the erased state, or the character positions
130/// of unprotected areas only, depends on the setting of the ERASURE MODE (ERM).
131pub fn erase_char(n: usize) -> ControlSequence {
132    ControlSequence::new(&[&n.to_string()], "X")
133}
134
135/// # EA - Erase in area
136///
137/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, EA causes some or
138/// all character positions in the active qualified area (the qualified area in the presentation component
139/// which contains the active presentation position) to be put into the erased state, depending on the
140/// parameter values:
141/// - 0 the active presentation position and the character positions up to the end of the qualified area are put
142/// into the erased state
143/// - 1 the character positions from the beginning of the qualified area up to and including the active
144/// presentation position are put into the erased state
145/// - 2 all character positions of the qualified area are put into the erased state
146///
147/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, EA causes some or all
148/// character positions in the active qualified area (the qualified area in the data component which contains
149/// the active data position) to be put into the erased state, depending on the parameter values:
150/// - 0 the active data position and the character positions up to the end of the qualified area are put into the
151/// erased state
152/// - 1 the character positions from the beginning of the qualified area up to and including the active data
153/// position are put into the erased state
154/// - 2 all character positions of the qualified area are put into the erased state
155///
156/// Whether the character positions of protected areas are put into the erased state, or the character positions
157/// of unprotected areas only, depends on the setting of the ERASURE MODE (ERM).
158pub fn erase(area_position: AreaPosition) -> ControlSequence {
159    ControlSequence::new(&[&area_position.to_string()], "O")
160}
161
162#[derive(Copy, Clone, Debug)]
163pub enum AreaPosition {
164    AfterCursor,
165    BeforeCursor,
166    Whole,
167}
168
169impl Display for AreaPosition {
170    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
171        write!(f, "{}", match self {
172            Self::AfterCursor => "0",
173            Self::BeforeCursor => "1",
174            Self::Whole => "2"
175        })
176    }
177}
178
179
180/// # ED - Erase in page
181///
182/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, ED causes some or
183/// all character positions of the active page (the page which contains the active presentation position in the
184/// presentation component) to be put into the erased state, depending on the parameter values:
185/// - 0 the active presentation position and the character positions up to the end of the page are put into the
186/// erased state
187/// - 1 the character positions from the beginning of the page up to and including the active presentation
188/// position are put into the erased state
189/// - 2 all character positions of the page are put into the erased state
190///
191/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, ED causes some or all
192/// character positions of the active page (the page which contains the active data position in the data
193/// component) to be put into the erased state, depending on the parameter values:
194/// - 0 the active data position and the character positions up to the end of the page are put into the erased
195/// state
196/// - 1 the character positions from the beginning of the page up to and including the active data position are
197/// put into the erased state
198/// - 2 all character positions of the page are put into the erased state
199///
200/// Whether the character positions of protected areas are put into the erased state, or the character positions
201/// of unprotected areas only, depends on the setting of the ERASURE MODE (ERM).
202pub fn erase_in_page(area_position: AreaPosition) -> ControlSequence {
203    ControlSequence::new(&[&area_position.to_string()], "J")
204}
205
206/// # EF - Erase in field
207///
208/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, EF causes some or
209/// all character positions of the active field (the field which contains the active presentation position in the
210/// presentation component) to be put into the erased state, depending on the parameter values:
211/// - 0 the active presentation position and the character positions up to the end of the field are put into the
212/// erased state
213/// - 1 the character positions from the beginning of the field up to and including the active presentation
214/// position are put into the erased state
215/// - 2 all character positions of the field are put into the erased state
216///
217/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, EF causes some or all
218/// character positions of the active field (the field which contains the active data position in the data
219/// component) to be put into the erased state, depending on the parameter values:
220/// - 0 the active data position and the character positions up to the end of the field are put into the erased
221/// state
222/// - 1 the character positions from the beginning of the field up to and including the active data position are
223/// put into the erased state
224/// - 2 all character positions of the field are put into the erased state
225///
226/// Whether the character positions of protected areas are put into the erased state, or the character positions
227/// of unprotected areas only, depends on the setting of the ERASURE MODE (ERM)
228pub fn erase_in_field(area_position: AreaPosition) -> ControlSequence {
229    ControlSequence::new(&[&area_position.to_string()], "N")
230}
231
232/// # EL - Erase in line
233///
234/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, EL causes some or
235/// all character positions of the active line (the line which contains the active presentation position in the
236/// presentation component) to be put into the erased state, depending on the parameter values:
237/// - 0 the active presentation position and the character positions up to the end of the line are put into the
238/// erased state
239/// - 1 the character positions from the beginning of the line up to and including the active presentation
240/// position are put into the erased state
241/// - 2 all character positions of the line are put into the erased state
242///
243/// If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, EL causes some or all
244/// character positions of the active line (the line which contains the active data position in the data
245/// component) to be put into the erased state, depending on the parameter values:
246/// - 0 the active data position and the character positions up to the end of the line are put into the erased
247/// state
248/// - 1 the character positions from the beginning of the line up to and including the active data position are
249/// put into the erased state
250/// - 2 all character positions of the line are put into the erased state
251///
252/// Whether the character positions of protected areas are put into the erased state, or the character positions
253/// of unprotected areas only, depends on the setting of the ERASURE MODE (ERM).
254pub fn erase_in_line(area_position: AreaPosition) -> ControlSequence {
255    ControlSequence::new(&[&area_position.to_string()], "K")
256}
257
258/// # SEE - Select editing extent
259///
260/// SEE is used to establish the editing extent for subsequent character or line insertion or deletion. The
261/// established extent remains in effect until the next occurrence of SEE in the data stream.
262pub fn select_extent(editing_extent: EditingExtent) -> ControlSequence {
263    ControlSequence::new(&[&editing_extent.to_string()], "Q")
264}
265
266#[derive(Copy, Clone, Debug)]
267pub enum EditingExtent {
268    Page,
269    Line,
270    Field,
271    QualifiedArea,
272    Relevant,
273}
274
275impl Display for EditingExtent {
276    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
277        write!(f, "{}", match self {
278            EditingExtent::Page => "0",
279            EditingExtent::Line => "1",
280            EditingExtent::Field => "2",
281            EditingExtent::QualifiedArea => "3",
282            EditingExtent::Relevant => "4",
283        })
284    }
285}
286
287
288#[cfg(test)]
289mod tests {
290    use super::*;
291
292    #[test]
293    fn test_erase_area_position() {
294        assert_eq!(erase(AreaPosition::AfterCursor).to_string(), ControlSequence::new(&["0"], "O").to_string());
295        assert_eq!(erase(AreaPosition::BeforeCursor).to_string(), ControlSequence::new(&["1"], "O").to_string());
296        assert_eq!(erase(AreaPosition::Whole).to_string(), ControlSequence::new(&["2"], "O").to_string());
297    }
298
299    #[test]
300    fn test_erase_in_page() {
301        assert_eq!(erase_in_page(AreaPosition::AfterCursor).to_string(), ControlSequence::new(&["0"], "J").to_string());
302        assert_eq!(erase_in_page(AreaPosition::BeforeCursor).to_string(), ControlSequence::new(&["1"], "J").to_string());
303        assert_eq!(erase_in_page(AreaPosition::Whole).to_string(), ControlSequence::new(&["2"], "J").to_string());
304    }
305
306    #[test]
307    fn test_erase_in_field() {
308        assert_eq!(erase_in_field(AreaPosition::AfterCursor).to_string(), ControlSequence::new(&["0"], "N").to_string());
309        assert_eq!(erase_in_field(AreaPosition::BeforeCursor).to_string(), ControlSequence::new(&["1"], "N").to_string());
310        assert_eq!(erase_in_field(AreaPosition::Whole).to_string(), ControlSequence::new(&["2"], "N").to_string());
311    }
312
313    #[test]
314    fn test_erase_in_line() {
315        assert_eq!(erase_in_line(AreaPosition::AfterCursor).to_string(), ControlSequence::new(&["0"], "K").to_string());
316        assert_eq!(erase_in_line(AreaPosition::BeforeCursor).to_string(), ControlSequence::new(&["1"], "K").to_string());
317        assert_eq!(erase_in_line(AreaPosition::Whole).to_string(), ControlSequence::new(&["2"], "K").to_string());
318    }
319
320    #[test]
321    fn test_select_extent() {
322        assert_eq!(select_extent(EditingExtent::Page).to_string(), ControlSequence::new(&["0"], "Q").to_string());
323        assert_eq!(select_extent(EditingExtent::Line).to_string(), ControlSequence::new(&["1"], "Q").to_string());
324        assert_eq!(select_extent(EditingExtent::Field).to_string(), ControlSequence::new(&["2"], "Q").to_string());
325        assert_eq!(select_extent(EditingExtent::QualifiedArea).to_string(), ControlSequence::new(&["3"], "Q").to_string());
326        assert_eq!(select_extent(EditingExtent::Relevant).to_string(), ControlSequence::new(&["4"], "Q").to_string());
327    }
328
329    #[test]
330    fn test_area_position_display() {
331        assert_eq!(AreaPosition::AfterCursor.to_string(), "0");
332        assert_eq!(AreaPosition::BeforeCursor.to_string(), "1");
333        assert_eq!(AreaPosition::Whole.to_string(), "2");
334    }
335
336    #[test]
337    fn test_editing_extent_display() {
338        assert_eq!(EditingExtent::Page.to_string(), "0");
339        assert_eq!(EditingExtent::Line.to_string(), "1");
340        assert_eq!(EditingExtent::Field.to_string(), "2");
341        assert_eq!(EditingExtent::QualifiedArea.to_string(), "3");
342        assert_eq!(EditingExtent::Relevant.to_string(), "4");
343    }
344}