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}