coded_chars/device.rs
1//! Control sequences that are devices-related.
2
3use std::fmt::{Display, Formatter};
4use crate::control::ControlSequence;
5use crate::escape::{escape, EscapeSequence};
6
7/// # Device control 1
8///
9/// DC1 is primarily intended for turning on or starting an ancillary device. If it is not required for this
10/// purpose, it may be used to restore a device to the basic mode of operation (see also DC2 and DC3), or
11/// any other device control function not provided by other DCs.
12///
13/// ### Note
14/// When used for data flow control, DC1 is sometimes called **X-ON**.
15pub const DC1: char = '\x11';
16
17/// # Device control 2
18///
19/// DC2 is primarily intended for turning on or starting an ancillary device. If it is not required for this
20/// purpose, it may be used to set a device to a special mode of operation (in which case DC1 is used to
21/// restore the device to the basic mode), or for any other device control function not provided by other DCs.
22pub const DC2: char = '\x12';
23
24/// # Device control 3
25///
26/// DC3 is primarily intended for turning off or stopping an ancillary device. This function may be a
27/// secondary level stop, for example wait, pause, stand-by or halt (in which case DC1 is used to restore
28/// normal operation). If it is not required for this purpose, it may be used for any other device control
29/// function not provided by other DCs.
30///
31/// ### Note
32///
33/// When used for data flow control, DC3 is sometimes called "X-OFF".
34pub const DC3: char = '\x13';
35
36/// # Device control 4
37///
38/// DC4 is primarily intended for turning off, stopping or interrupting an ancillary device. If it is not
39/// required for this purpose, it may be used for any other device control function not provided by other DCs.
40pub const DC4: char = '\x14';
41
42/// Disable manual input
43pub const DMI: EscapeSequence = escape('`');
44
45/// Enable manual input
46pub const EMI: EscapeSequence = escape('b');
47
48/// Interrupt
49pub const INT: EscapeSequence = escape('a');
50
51/// Reset to initial state
52pub const RIS: EscapeSequence = escape('c');
53
54/// # DA - Device attributes
55///
56/// With a parameter value not equal to 0, DA is used to identify the device which sends the DA. The
57/// parameter value is a device type identification code according to a register which is to be established. If
58/// the parameter value is 0, DA is used to request an identifying DA from a device.
59pub fn attributes(n: usize) -> ControlSequence {
60 ControlSequence::new(&[&n.to_string()], "c")
61}
62
63#[derive(Copy, Clone, Debug)]
64pub enum StatusReport {
65 /// Ready, no malfunction detected.
66 Ready,
67 /// Busy, another DSR must be requested later.
68 BusyRetry,
69 /// Busy, another DSR will be sent later.
70 BusyWaiting,
71 /// Some malfunction detected, another DSR must be requested later.
72 ErrorRetry,
73 /// Some malfunction detected, another DSR will be sent later.
74 ErrorWaiting,
75 /// A DSR is requested.
76 MessageWaiting,
77 /// A report of the active presentation position or of the active data position in the form of ACTIVE
78 /// POSITION REPORT (CPR) is requested.
79 PositionWaiting,
80}
81
82impl Display for StatusReport {
83 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84 write!(f, "{}", match self {
85 StatusReport::Ready => "0",
86 StatusReport::BusyRetry => "1",
87 StatusReport::BusyWaiting => "2",
88 StatusReport::ErrorRetry => "3",
89 StatusReport::ErrorWaiting => "4",
90 StatusReport::MessageWaiting => "5",
91 StatusReport::PositionWaiting => "6",
92 })
93 }
94}
95
96/// # DSR - Device status report
97///
98/// DSR is used either to report the status of the sending device or to request a status report from the
99/// receiving device.
100///
101/// DSR with parameter value 0 [StatusReport::Ready], 1 [StatusReport::BusyRetry], 2 [StatusReport::BusyWaiting], 3 [StatusReport::ErrorRetry]
102/// or 4 [StatusReport::ErrorWaiting] may be sent either unsolicited or as a response to a request such as a DSR with
103/// a parameter value 5 [StatusReport::MessageWaiting] or MESSAGE WAITING (MW).
104pub fn report_status(status_report: StatusReport) -> ControlSequence {
105 ControlSequence::new(&[&status_report.to_string()], "c")
106}
107
108/// # FNK - Function key
109///
110/// FNK is a control function in which the parameter value identifies the function key which has been
111/// operated.
112pub fn function_key(n: usize) -> ControlSequence {
113 ControlSequence::new(&[&n.to_string()], " W")
114}
115/// # IDCS - Identify device control string
116///
117/// IDCS is used to specify the purpose and format of the command string of subsequent DEVICE
118/// CONTROL STRINGs (DCS). The specified purpose and format remain in effect until the next
119/// occurrence of IDCS in the data stream.
120///
121/// The format and interpretation of the command string corresponding to these parameter values are to be
122/// defined in appropriate standards. If this control function is used to identify a private command string, a
123/// private parameter value shall be used.
124pub fn identify_control_string(control_string: ControlString) -> ControlSequence {
125 ControlSequence::new(&[&control_string.to_string()], " O")
126}
127
128#[derive(Copy, Clone, Debug)]
129pub enum ControlString {
130 SRTMDiagnose,
131 Ecma35DCRS,
132}
133
134impl Display for ControlString {
135 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
136 write!(f, "{}", match self {
137 ControlString::SRTMDiagnose => "1",
138 ControlString::Ecma35DCRS => "2"
139 })
140 }
141}
142
143/// # IGS - Identify graphic sub-repertoire
144///
145/// IGS is used to indicate that a repertoire of the graphic characters of ISO/IEC 10367 is used in the
146/// subsequent text.
147/// The parameter value of IGS identifies a graphic character repertoire registered in accordance with
148/// ISO/IEC 7350.
149pub fn identify_graphic_sub(n: usize) -> ControlSequence {
150 ControlSequence::new(&[&n.to_string()], " W")
151}
152
153#[derive(Copy, Clone, Debug)]
154pub enum CopyStatus {
155 /// Initiate transfer to a primary auxiliary device.
156 InitTo1,
157 /// Initiate transfer from a primary auxiliary device.
158 InitFrom1,
159 /// Initiate transfer to a secondary auxiliary device.
160 InitTo2,
161 /// Initiate transfer from a secondary auxiliary device.
162 InitFrom2,
163 /// Stop relay to a primary auxiliary device.
164 Stop1,
165 /// Start relay to a primary auxiliary device.
166 Start1,
167 /// Stop relay to a secondary auxiliary device.
168 Stop2,
169 /// Start relay to a secondary auxiliary device.
170 Start2,
171}
172
173impl Display for CopyStatus {
174 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
175 write!(f, "{}", match self {
176 CopyStatus::InitTo1 => "0",
177 CopyStatus::InitFrom1 => "1",
178 CopyStatus::InitTo2 => "2",
179 CopyStatus::InitFrom2 => "3",
180 CopyStatus::Stop1 => "4",
181 CopyStatus::Start1 => "5",
182 CopyStatus::Stop2 => "6",
183 CopyStatus::Start2 => "7",
184 })
185 }
186}
187
188/// # MC - Media copy
189///
190/// MC is used either to initiate a transfer of data from or to an auxiliary input/output device or to enable or
191/// disable the relay of the received data stream to an auxiliary input/output device.
192///
193/// This control function may not be used to switch on or off an auxiliary device.
194pub fn media_copy(copy_status: CopyStatus) -> ControlSequence {
195 ControlSequence::new(&[©_status.to_string()], "i")
196}
197
198/// # SEF - Sheet eject and feed
199///
200/// SEF causes a sheet of paper to be ejected from a printing device into a specified output stacker and
201/// another sheet to be loaded into the printing device from a specified paper bin.
202pub fn eject_and_feed(bin: usize, stacker: usize) -> ControlSequence {
203 ControlSequence::new(&[&bin.to_string(), &stacker.to_string()], " Y")
204}
205
206
207#[cfg(test)]
208mod tests {
209 use super::*; // Import everything from the current module
210 use crate::introducers::CSI;
211
212 #[test]
213 fn test_attributes() {
214 let sequence = attributes(42);
215 assert_eq!(sequence.to_string(), format!("{}42c", CSI));
216 }
217
218 #[test]
219 fn test_report_status() {
220 let sequence = report_status(StatusReport::Ready);
221 assert_eq!(sequence.to_string(), format!("{}0c", CSI));
222
223 let sequence = report_status(StatusReport::ErrorRetry);
224 assert_eq!(sequence.to_string(), format!("{}3c", CSI));
225
226 let sequence = report_status(StatusReport::MessageWaiting);
227 assert_eq!(sequence.to_string(), format!("{}5c", CSI));
228 }
229
230 #[test]
231 fn test_function_key() {
232 let sequence = function_key(7);
233 assert_eq!(sequence.to_string(), format!("{}7 W", CSI));
234 }
235
236 #[test]
237 fn test_identify_control_string() {
238 let sequence = identify_control_string(ControlString::SRTMDiagnose);
239 assert_eq!(sequence.to_string(), format!("{}1 O", CSI));
240
241 let sequence = identify_control_string(ControlString::Ecma35DCRS);
242 assert_eq!(sequence.to_string(), format!("{}2 O", CSI));
243 }
244
245 #[test]
246 fn test_identify_graphic_sub() {
247 let sequence = identify_graphic_sub(4);
248 assert_eq!(sequence.to_string(), format!("{}4 W", CSI));
249 }
250
251 #[test]
252 fn test_media_copy() {
253 let sequence = media_copy(CopyStatus::InitTo1);
254 assert_eq!(sequence.to_string(), format!("{}0i", CSI));
255
256 let sequence = media_copy(CopyStatus::Start2);
257 assert_eq!(sequence.to_string(), format!("{}7i", CSI));
258 }
259
260 #[test]
261 fn test_eject_and_feed() {
262 let sequence = eject_and_feed(2, 3);
263 assert_eq!(sequence.to_string(), format!("{}2;3 Y", CSI));
264 }
265
266 #[test]
267 fn test_status_report_display() {
268 assert_eq!(StatusReport::Ready.to_string(), "0");
269 assert_eq!(StatusReport::BusyRetry.to_string(), "1");
270 assert_eq!(StatusReport::ErrorRetry.to_string(), "3");
271 }
272
273 #[test]
274 fn test_control_string_display() {
275 assert_eq!(ControlString::SRTMDiagnose.to_string(), "1");
276 assert_eq!(ControlString::Ecma35DCRS.to_string(), "2");
277 }
278
279 #[test]
280 fn test_copy_status_display() {
281 assert_eq!(CopyStatus::InitTo1.to_string(), "0");
282 assert_eq!(CopyStatus::Start2.to_string(), "7");
283 }
284}