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}