coded_chars/
mode.rs

1//! This module helps create the CSI sequences for `SM` and `RM`.
2
3use crate::control::ControlSequence;
4
5/// A struct representing an `SM` or an `RM` CSI function.
6///
7/// ### Examples
8/// ```
9/// use coded_chars::mode::mode;
10///
11/// // Set a mode (EXPLICIT-BDSM mode)
12/// println!("{}", mode().bi_directional_support().set());
13///
14/// // Reset a mode (IMPLICIT-BDSM mode)
15/// println!("{}", mode().bi_directional_support().reset());
16/// ```
17pub struct Mode {
18    modes: Vec<String>,
19}
20
21impl Mode {
22    pub fn new() -> Self { Self { modes: vec![] } }
23
24    /// # GATM - Guarded area transfer mode
25    ///
26    /// - GUARD (set) : Only the contents of unguarded areas in an eligible area are transmitted or transferred.
27    /// - ALL (reset) : The contents of guarded as well as of unguarded areas in an eligible area are transmitted or transferred.
28    ///
29    /// ### Note
30    /// No control functions are affected.
31    pub fn guarded_area_transfer(&mut self) -> &mut Self { self.add("1") }
32
33    /// # KAM - Keyboard action mode
34    ///
35    /// - ENABLED (set) : All or part of the manual input facilities are enabled to be used.
36    /// - DISABLED (reset) : All or part of the manual input facilities are disabled.
37    ///
38    /// ### Note
39    /// No control functions are affected.
40    pub fn keyboard_action(&mut self) -> &mut Self { self.add("2") }
41
42    /// # CRM - Control representation mode
43    ///
44    /// - CONTROL (set) : All control functions are performed as defined; the way formator functions are processed depends on the
45    /// setting of the FORMAT EFFECTOR ACTION MODE (FEAM). A device may choose to image the
46    /// graphical representations of control functions in addition to performing them.
47    /// - GRAPHIC (reset) : All control functions, except RESET MODE (RM), are treated as graphic characters. A device may
48    /// choose to perform some control functions in addition to storing them and imaging their graphical
49    /// representations.
50    ///
51    /// ### Note
52    /// All control functions, except RM, are affected.
53    pub fn control_representation(&mut self) -> &mut Self { self.add("3") }
54
55    /// # IRM - Insertion replacement mode
56    ///
57    /// - REPLACE (set) : The graphic symbol of a graphic character or of a control function, for which a graphical representation
58    /// is required, replaces (or, depending upon the implementation, is combined with) the graphic symbol
59    /// imaged at the active presentation position.
60    /// - INSERT (reset) : The graphic symbol of a graphic character or of a control function, for which a graphical representation
61    /// is required, is inserted at the active presentation position.
62    ///
63    /// ### Note
64    /// Only control functions for which a graphical representation is required are affected.
65    pub fn insertion_replacement(&mut self) -> &mut Self { self.add("4") }
66
67    /// # SRTM - Status report transfer mode
68    ///
69    /// - NORMAL (set) :  Status reports in the form of DEVICE CONTROL STRINGs (DCS) are not generated automatically.
70    /// - DIAGNOSTIC (reset) : Status reports in the form of DEVICE CONTROL STRINGs (DCS) are included in every data stream transmitted or transferred.
71    ///
72    /// ### Note
73    /// No control functions are affected.
74    pub fn status_report_transfer(&mut self) -> &mut Self { self.add("5") }
75
76    /// # ERM - Erasure mode
77    ///
78    /// - PROTECT (set) : Only the contents of unprotected areas are affected by an erasure control function.
79    /// - ALL (reset) : The contents of protected as well as of unprotected areas are affected by an erasure control function.
80    ///
81    /// ### Note
82    /// Control functions affected are: EA, ECH, ED, EF, EL.
83    ///
84    /// - [crate::editor::erase]
85    /// - [crate::editor::erase_char]
86    /// - [crate::editor::erase_in_page]
87    /// - [crate::editor::erase_in_field]
88    /// - [crate::editor::erase_in_line]
89    pub fn erasure(&mut self) -> &mut Self { self.add("6") }
90
91    /// # VEM - Line editing mode
92    ///
93    /// - FOLLOWING (set) :
94    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, a line insertion
95    ///     causes the contents of the active line (the line that contains the active presentation position) and of the
96    ///     following lines in the presentation component to be shifted in the direction of the line progression; a line
97    ///     deletion causes the contents of the lines following the active line to be shifted in the direction opposite
98    ///     to that of the line progression.
99    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, a line insertion causes the
100    ///     contents of the active line (the line that contains the active data position) and of the following lines in
101    ///     the data component to be shifted in the direction of the line progression; a line deletion causes the
102    ///     contents of the lines following the active line to be shifted in the direction opposite to that of the line
103    ///     progression.
104    /// - PRECEDING (reset) :
105    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, a line insertion
106    ///     causes the contents of the active line (the line that contains the active presentation position) and of the
107    ///     preceding lines to be shifted in the direction opposite to that of the line progression; a line deletion
108    ///     causes the contents of the lines preceding the active line to be shifted in the direction of the line
109    ///     progression.
110    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, a line insertion causes the
111    ///     contents of the active line (the line that contains the active data position) and of the preceding lines to be
112    ///     shifted in the direction opposite to that of the line progression; a line deletion causes the contents of the
113    ///     lines preceding the active line to be shifted in the direction of the line progression.
114    ///
115    /// ### Note
116    /// Control functions affected are: DL, IL.
117    ///
118    /// - [crate::editor::delete_line]
119    /// - [crate::editor::insert_line]
120    pub fn line_editing(&mut self) -> &mut Self { self.add("7") }
121
122    /// # BDSM - Bidirectional support mode
123    ///
124    /// - EXPLICIT (set) : Control functions are performed in the data component or in the presentation component, depending on
125    /// the setting of the DEVICE COMPONENT SELECT MODE (DCSM).
126    /// - IMPLICIT (reset) :  Control functions are performed in the data component. All bi-directional aspects of data are handled by
127    /// the device itself.
128    pub fn bi_directional_support(&mut self) -> &mut Self { self.add("8") }
129
130    /// # DCSM -- Device component select mode
131    ///
132    /// - PRESENTATION (set) : Certain control functions are performed in the presentation component. The active presentation position
133    /// (or the active line, where applicable) in the presentation component is the reference position against
134    /// which the relevant control functions are performed.
135    /// - DATA (reset) : Certain control functions are performed in the data component. The active data position (or the active
136    /// line, where applicable) in the data component is the reference position against which the relevant control
137    /// functions are performed
138    ///
139    /// ### Note
140    /// Control functions affected are: CPR, CR, DCH, DL, EA, ECH, ED, EF, EL, ICH, IL, LF, NEL, RI, SLH,
141    /// SLL, SPH, SPL.
142    ///
143    /// - [crate::cursor::position_report]
144    /// - [crate::format::CR],
145    /// - [crate::editor::delete_char],
146    /// - [crate::editor::delete_line],
147    /// - [crate::editor::erase],
148    /// - [crate::editor::erase_char]
149    /// - [crate::editor::erase_in_page]
150    /// - [crate::editor::erase_in_field]
151    /// - [crate::editor::erase_in_line]
152    /// - [crate::editor::insert_char]
153    /// - [crate::editor::insert_line]
154    /// - [crate::format::LF],
155    /// - [crate::format::NEL],
156    /// - [crate::format::RI],
157    /// - [crate::presentation::line_home],
158    /// - [crate::presentation::line_limit],
159    /// - [crate::presentation::page_home],
160    /// - [crate::presentation::page_limit].
161    ///
162    pub fn device_component_select(&mut self) -> &mut Self { self.add("9") }
163
164    /// # HEM - Character editing mode
165    ///
166    /// - FOLLOWING (set) :
167    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, a character
168    ///     insertion causes the contents of the active presentation position and of the following character positions
169    ///     in the presentation component to be shifted in the direction of the character path; a character deletion
170    ///     causes the contents of the character positions following the active presentation position to be shifted in
171    ///     the direction opposite to that of the character path.
172    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, a character insertion causes
173    ///     the contents of the active data position and of the following character positions in the data component to
174    ///     be shifted in the direction of the character progression; a character deletion causes the contents of the
175    ///     character positions following the active data position to be shifted in the direction opposite to that of the
176    ///     character progression.
177    /// - PRECEDING (reset) :
178    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to PRESENTATION, a character
179    ///     insertion causes the contents of the active presentation position and of the following character positions
180    ///     in the presentation component to be shifted in the direction opposite to that of the character path; a
181    ///     character deletion causes the contents of the character positions following the active presentation
182    ///     position to be shifted in the direction of the character path.
183    ///     - If the DEVICE COMPONENT SELECT MODE (DCSM) is set to DATA, a character insertion causes
184    ///     the contents of the active data position and of preceding character positions in the data component to be
185    ///     shifted in the direction opposite to that of the character progression; a character deletion causes the
186    ///     contents of the character positions preceding the active data position to be shifted in the direction of the
187    ///     character progression.
188    ///
189    /// ### Note
190    /// Control functions affected are: DCH, ICH.
191    ///
192    /// - [crate::editor::delete_char],
193    /// - [crate::editor::insert_char].
194    pub fn character_editing(&mut self) -> &mut Self { self.add("10") }
195
196    /// # SRM - Send/receive mode
197    ///
198    /// - MONITOR (set) : Data which are locally entered are immediately imaged.
199    /// - SIMULTANEOUS (reset) : Local input facilities are logically disconnected from the output mechanism; only data which are sent to
200    /// the device are imaged.
201    ///
202    /// ### Note
203    /// No control functions are affected.
204    pub fn send_receive(&mut self) -> &mut Self { self.add("12") }
205
206    /// # FEAM - Format effector action mode
207    ///
208    /// - EXECUTE (set) : Formator functions are performed immediately and may be stored in addition to being performed.
209    /// - STORE (reset) :Formator functions are stored but not performed. In this case, the specified action is intended to be
210    /// performed by another device when the associated data are transmitted or transferred.
211    ///
212    /// ### Note
213    /// Control functions affected are: BPH, BS, CR, DTA, FF, FNT, GCC, GSM, GSS, HPA, HPB, HPR, HT,
214    /// HTJ, HTS, HVP, JFY, NEL, PEC, PFS, PLD, PLU, PPA, PPB, PPR, PTX, QUAD, RI, SACS, SAPV,
215    /// SCO, SCS, SGR, SHS, SLH, SLL, SLS, SPD, SPI, SPQR, SRCS, SRS, SSU, SSW, STAB, SVS, TAC, TALE,
216    /// TATE, TBC, TCC, TSS, VPA, VPB, VPR, VTS.
217    pub fn format_effector_action(&mut self) -> &mut Self { self.add("13") }
218
219    /// # FETM - Format effector transfer mode
220    ///
221    /// - INSERT (set) : Formator functions may be inserted in a data stream to be transmitted or in data to be transferred to an
222    /// auxiliary input/output device.
223    /// - EXCLUDE (reset) : No formator functions other than those received while the FORMAT EFFECTOR ACTION MODE
224    /// (FEAM) is set to STORE are included in a transmitted data stream or in data transferred to an auxiliary
225    /// input/output device.
226    ///
227    /// ### Note
228    /// No control functions are affected.
229    pub fn format_effector_transfer(&mut self) -> &mut Self { self.add("14") }
230
231    /// # MATM - Multiple area transfer mode
232    ///
233    /// - SINGLE (set) : Only the contents of the selected area which contains the active presentation position are eligible to be
234    /// transmitted or transferred.
235    /// - MULTIPLE (reset) : The contents of all selected areas are eligible to be transmitted or transferred.
236    ///
237    /// ### Note
238    /// No control functions are affected.
239    pub fn multiple_area_transfer(&mut self) -> &mut Self { self.add("15") }
240
241    /// # TTM - Transfer termination mode
242    ///
243    /// - CURSOR (set) : Only the contents of the character positions preceding the active presentation position in the presentation
244    /// component are eligible to be transmitted or transferred.
245    /// - ALL (reset) : The contents of character positions preceding, following, and at the active presentation position are
246    /// eligible to be transmitted or transferred.
247    ///
248    /// ### Note
249    /// No control functions are affected.
250    pub fn transfert_termination(&mut self) -> &mut Self { self.add("16") }
251
252    /// # SATM - Selected area transfer mode
253    ///
254    /// - SELECT (set) : Only the contents of selected areas are eligible to be transmitted or transferred.
255    /// - ALL (reset) : The contents of all character positions, irrespective of any explicitly defined selected areas, are eligible
256    /// to be transmitted or transferred.
257    ///
258    /// ### Note
259    /// No control functions are affected.
260    pub fn selected_area_transfer(&mut self) -> &mut Self { self.add("17") }
261
262    /// # TSM - Tabulation stop mode
263    ///
264    /// - MULTIPLE (set) : Character tabulation stops in the presentation component are set or cleared in the active line (the line
265    /// that contains the active presentation position) and in the corresponding character positions of the
266    /// preceding lines and of the following lines.
267    /// - SINGLE (reset) : Character tabulation stops in the presentation component are set or cleared in the active line only.
268    ///
269    /// ### Note
270    /// Control functions affected are: CTC, DL, HTS, IL, TBC.
271    ///
272    /// - [crate::cursor::tabulation_control],
273    /// - [crate::editor::delete_line],
274    /// - [crate::format::HTS],
275    /// - [crate::editor::insert_line].
276    /// - [crate::format::clear_tabulation].
277    pub fn tabulation_stop(&mut self) -> &mut Self { self.add("18") }
278    
279    /// # GRCM - Graphic rendition combination mode
280    /// 
281    /// - REPLACING (set) : Each occurrence of the control function SELECT GRAPHIC RENDITION (SGR) cancels the effect of
282    /// any preceding occurrence. Any graphic rendition aspects that are to remain unchanged after an
283    /// occurrence of SGR have to be re-specified by that SGR.
284    /// - CUMULATIVE (reset) : Each occurrence of the control function SELECT GRAPHIC RENDITION (SGR) causes only those
285    /// graphic rendition aspects to be changed that are specified by that SGR. All other graphic rendition
286    /// aspects remain unchanged.
287    /// 
288    /// ### Note
289    /// Control function affected is SGR : [crate::presentation::select_graphic].
290    pub fn graphic_rendition_combination(&mut self) -> &mut Self { self.add("21") }
291
292    /// # SM - Set Mode
293    /// SM causes the modes of the receiving device to be set as specified.
294    pub fn set(&self) -> ControlSequence {
295        ControlSequence::new(&self.modes.iter().map(|s| s.as_str()).collect::<Vec<_>>(), "h")
296    }
297
298    /// # RM - Reset Mode
299    /// RM causes the modes of the receiving device to be reset as specified.
300    pub fn reset(&self) -> ControlSequence {
301        ControlSequence::new(&self.modes.iter().map(|s| s.as_str()).collect::<Vec<_>>(), "l")
302    }
303    fn add(&mut self, s: &str) -> &mut Self {
304        self.modes.push(s.to_string());
305        self
306    }
307}
308
309/// Creates a new [Mode] sequence to set or reset devices modes.
310///
311/// ### Example
312/// ```
313/// use coded_chars::mode::mode;
314///
315/// // Sets the DCSM mode to PRESENTATION and the HEM mode to FOLLOWING.
316/// mode().device_component_select().character_editing().set().exec();
317/// ```
318pub fn mode() -> Mode { Mode::new() }
319
320
321#[cfg(test)]
322mod tests {
323    use super::*;
324
325    #[test]
326    fn test_character_editing() {
327        let generated_sequence = mode().character_editing().set();
328        assert_eq!(format!("{}", generated_sequence), "\x1b[10h");
329    }
330
331    #[test]
332    fn test_send_receive() {
333        let generated_sequence = mode().send_receive().set();
334        assert_eq!(format!("{}", generated_sequence), "\x1b[12h");
335    }
336
337    #[test]
338    fn test_format_effector_action() {
339        let generated_sequence = mode().format_effector_action().set();
340        assert_eq!(format!("{}", generated_sequence), "\x1b[13h");
341    }
342
343    #[test]
344    fn test_format_effector_transfer() {
345        let generated_sequence = mode().format_effector_transfer().set();
346        assert_eq!(format!("{}", generated_sequence), "\x1b[14h");
347    }
348
349    #[test]
350    fn test_multiple_area_transfer() {
351        let generated_sequence = mode().multiple_area_transfer().set();
352        assert_eq!(format!("{}", generated_sequence), "\x1b[15h");
353    }
354
355    #[test]
356    fn test_transfer_termination() {
357        let generated_sequence = mode().transfert_termination().set();
358        assert_eq!(format!("{}", generated_sequence), "\x1b[16h");
359    }
360
361    #[test]
362    fn test_selected_area_transfer() {
363        let generated_sequence = mode().selected_area_transfer().set();
364        assert_eq!(format!("{}", generated_sequence), "\x1b[17h");
365    }
366
367    #[test]
368    fn test_tabulation_stop() {
369        let generated_sequence = mode().tabulation_stop().set();
370        assert_eq!(format!("{}", generated_sequence), "\x1b[18h");
371    }
372
373    #[test]
374    fn test_graphic_rendition_combination() {
375        let generated_sequence = mode().graphic_rendition_combination().set();
376        assert_eq!(format!("{}", generated_sequence), "\x1b[21h");
377    }
378
379    #[test]
380    fn test_reset_mode() {
381        let generated_sequence = mode().character_editing().reset();
382        assert_eq!(format!("{}", generated_sequence), "\x1b[10l");
383    }
384
385    #[test]
386    fn test_combined_modes() {
387        let generated_sequence = mode().character_editing().send_receive().format_effector_transfer().set();
388        assert_eq!(format!("{}", generated_sequence), "\x1b[10;12;14h");
389    }
390}