coded_chars/presentation.rs
1//! This module provides control function to change the presentation.
2
3use std::fmt::{Display, Formatter};
4use crate::control::ControlSequence;
5use crate::escape::{escape, EscapeSequence};
6
7/// # Break permitted here
8///
9/// BPH is used to indicate a point where a line break may occur when text is formatted. BPH may occur
10/// between two graphic characters, either or both of which may be SPACE.
11pub const BPH: EscapeSequence = escape('B');
12
13/// # No break here
14///
15/// NBH is used to indicate a point where a line break shall not occur when text is formatted. NBH may
16/// occur between two graphic characters either or both of which may be SPACE.
17pub const NBH: EscapeSequence = escape('C');
18
19/// # DTA - Dimension text area
20///
21/// DTA is used to establish the dimensions of the text area for subsequent pages.
22/// The established dimensions remain in effect until the next occurrence of DTA in the data stream.
23/// - `l` specifies the dimension in the direction perpendicular to the line orientation.
24/// - `c` specifies the dimension in the direction parallel to the line orientation.
25///
26/// The unit in which the parameter value is expressed is that established by the parameter value of SELECT
27/// SIZE UNIT (SSU).
28pub fn dimension_text(l: usize, c: usize) -> ControlSequence {
29 ControlSequence::new(&[&l.to_string(), &c.to_string()], " T")
30}
31
32/// # FNT - Font selection
33///
34/// FNT is used to identify the character font to be selected as primary or alternative font by subsequent
35/// occurrences of SELECT GRAPHIC RENDITION (SGR) in the data stream.
36pub fn select_font(font: Font) -> ControlSequence {
37 ControlSequence::new(&[&font.to_string(), "0"], " D")
38}
39
40#[derive(Copy, Clone, Debug)]
41pub enum Font {
42 Primary,
43 Alternative1,
44 Alternative2,
45 Alternative3,
46 Alternative4,
47 Alternative5,
48 Alternative6,
49 Alternative7,
50 Alternative8,
51 Alternative9,
52}
53
54impl Display for Font {
55 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
56 write!(f, "{}", match self {
57 Font::Primary => "0",
58 Font::Alternative1 => "1",
59 Font::Alternative2 => "2",
60 Font::Alternative3 => "3",
61 Font::Alternative4 => "4",
62 Font::Alternative5 => "5",
63 Font::Alternative6 => "6",
64 Font::Alternative7 => "7",
65 Font::Alternative8 => "8",
66 Font::Alternative9 => "9"
67 })
68 }
69}
70
71/// # GCC - Graphic character combination
72///
73/// GCC is used to indicate that two or more graphic characters are to be imaged as one single graphic
74/// symbol. GCC with a parameter value of 0 indicates that the following two graphic characters are to be
75/// imaged as one single graphic symbol; GCC with a parameter value of 1 and GCC with a parameter value
76/// of 2 indicate respectively the beginning and the end of a string of graphic characters which are to be
77/// imaged as one single graphic symbol.
78///
79/// ### Note
80/// GCC does not explicitly specify the relative sizes or placements of the component parts of a composite
81/// graphic symbol. In the simplest case, two components may be "half-width" and side-by-side. For
82/// example, in Japanese text a pair of characters may be presented side-by-side, and occupy the space of a
83/// normal-size Kanji character.
84pub fn character_combination(combination: Combination) -> ControlSequence {
85 ControlSequence::new(&[&combination.to_string()], " _")
86}
87
88#[derive(Copy, Clone, Debug)]
89pub enum Combination {
90 Two,
91 Start,
92 End,
93}
94
95impl Display for Combination {
96 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
97 write!(f, "{}", match self {
98 Self::Two => "0",
99 Self::Start => "1",
100 Self::End => "2"
101 })
102 }
103}
104
105/// # GSM - Graphic size modification
106///
107/// GSM is used to modify for subsequent text the height and/or the width of all primary and alternative
108/// fonts identified by FONT SELECTION (FNT) and established by GRAPHIC SIZE SELECTION (GSS).
109///
110/// The established values remain in effect until the next occurrence of GSM or GSS in the data steam.
111///
112/// `height` and `width` are percentage of values established by GSS ([select_size]).
113pub fn modify_size(height: usize, width: usize) -> ControlSequence {
114 ControlSequence::new(&[&height.to_string(), &width.to_string()], " B")
115}
116
117/// # GSS - Graphic size selection
118///
119/// GSS is used to establish for subsequent text the height and the width of all primary and alternative fonts
120/// identified by FONT SELECTION (FNT). The established values remain in effect until the next
121/// occurrence of GSS in the data stream.
122///
123/// `n` specifies the height, the width is implicitly defined by the height.
124///
125/// The unit in which the parameter value is expressed is that established by the parameter value of SELECT
126/// SIZE UNIT (SSU).
127pub fn select_size(n: usize) -> ControlSequence {
128 ControlSequence::new(&[&n.to_string()], " C")
129}
130
131/// # JFY - Justify
132///
133/// JFY is used to indicate the beginning of a string of graphic characters in the presentation component that
134/// are to be justified according to the layout specified by the parameter values.
135///
136/// The end of the string to be justified is indicated by the next occurrence of JFY in the data stream.
137pub fn justify(modes: &[JustifyMode]) -> ControlSequence {
138 let str_modes: Vec<String> = modes.iter()
139 .map(|mode| mode.to_string())
140 .collect();
141
142 let str_ref_modes: Vec<&str> = str_modes.iter()
143 .map(AsRef::as_ref)
144 .collect();
145
146 ControlSequence::new(&str_ref_modes, " F")
147}
148
149#[derive(Copy, Clone, Debug)]
150pub enum JustifyMode {
151 /// No justification, end of justification of preceding text.
152 None,
153 WordFill,
154 WordSpace,
155 LetterSpace,
156 Hyphen,
157 /// Flush to line home position margin.
158 FlushHome,
159 /// Centre between line home position and line limit position margins.
160 Center,
161 /// Flush to line limit position margin.
162 FlushLimit,
163 ItalianHyphen,
164}
165
166impl Display for JustifyMode {
167 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
168 write!(f, "{}", match self {
169 JustifyMode::None => "0",
170 JustifyMode::WordFill => "1",
171 JustifyMode::WordSpace => "2",
172 JustifyMode::LetterSpace => "3",
173 JustifyMode::Hyphen => "4",
174 JustifyMode::FlushHome => "5",
175 JustifyMode::Center => "6",
176 JustifyMode::FlushLimit => "7",
177 JustifyMode::ItalianHyphen => "8",
178 })
179 }
180}
181
182/// # PEC - Presentation expand or contract
183///
184/// PEC is used to establish the spacing and the extent of the graphic characters for subsequent text. The
185/// spacing is specified in the line as multiples of the spacing established by the most recent occurrence of
186/// SET CHARACTER SPACING (SCS) or of SELECT CHARACTER SPACING (SHS) or of SPACING
187/// INCREMENT (SPI) in the data stream. The extent of the characters is implicitly established by these
188/// control functions. The established spacing and the extent remain in effect until the next occurrence of
189/// PEC, of SCS, of SHS or of SPI in the data stream.
190pub fn expand_or_condense(expansion: Expansion) -> ControlSequence {
191 ControlSequence::new(&[&expansion.to_string()], " Z")
192}
193
194#[derive(Copy, Clone, Debug)]
195pub enum Expansion {
196 Normal,
197 Expanded,
198 Condensed,
199}
200
201impl Display for Expansion {
202 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
203 write!(f, "{}", match self {
204 Self::Normal => "0",
205 Self::Expanded => "1",
206 Self::Condensed => "2"
207 })
208 }
209}
210
211/// # PFS - Page format selection
212///
213/// PFS is used to establish the available area for the imaging of pages of text based on paper size. The
214/// pages are introduced by the subsequent occurrence of FORM FEED (FF) in the data stream.
215///
216/// The established image area remains in effect until the next occurrence of PFS in the data stream.
217///
218/// The page home position is established by the parameter value of SET PAGE HOME (SPH), the page
219/// limit position is established by the parameter value of SET PAGE LIMIT (SPL).
220pub fn select_page_format(page_format: PageFormat) -> ControlSequence {
221 ControlSequence::new(&[&page_format.to_string()], " J")
222}
223
224#[derive(Copy, Clone, Debug)]
225pub enum PageFormat {
226 TallText,
227 WideText,
228 TallA4,
229 WideA4,
230 TallLetter,
231 WideLetter,
232 TallExtA4,
233 WideExtA4,
234 TallLegal,
235 WideLegal,
236 A4ShortLines,
237 A4LongLines,
238 B5ShortLines,
239 B5LongLines,
240 B4ShortLines,
241 B4LongLines,
242}
243
244impl Display for PageFormat {
245 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
246 write!(f, "{}", match self {
247 PageFormat::TallText => "0",
248 PageFormat::WideText => "1",
249 PageFormat::TallA4 => "2",
250 PageFormat::WideA4 => "3",
251 PageFormat::TallLetter => "4",
252 PageFormat::WideLetter => "5",
253 PageFormat::TallExtA4 => "6",
254 PageFormat::WideExtA4 => "7",
255 PageFormat::TallLegal => "8",
256 PageFormat::WideLegal => "9",
257 PageFormat::A4ShortLines => "10",
258 PageFormat::A4LongLines => "11",
259 PageFormat::B5ShortLines => "12",
260 PageFormat::B5LongLines => "13",
261 PageFormat::B4ShortLines => "14",
262 PageFormat::B4LongLines => "15",
263 })
264 }
265}
266
267
268/// # PTX - Parallel texts
269///
270/// PTX is used to delimit strings of graphic characters that are communicated one after another in the data
271/// stream but that are intended to be presented in parallel with one another, usually in adjacent lines.
272///
273/// PTX with a parameter value of 1 indicates the beginning of the string of principal text intended to be
274/// presented in parallel with one or more strings of supplementary text.
275///
276/// PTX with a parameter value of 2, 3 or 4 indicates the beginning of a string of supplementary text that is
277/// intended to be presented in parallel with either a string of principal text or the immediately preceding
278/// string of supplementary text, if any; at the same time it indicates the end of the preceding string of
279/// principal text or of the immediately preceding string of supplementary text, if any. The end of a string of
280/// supplementary text is indicated by a subsequent occurrence of PTX with a parameter value other than 1.
281/// PTX with a parameter value of 0 indicates the end of the strings of text intended to be presented in
282/// parallel with one another.
283///
284///### Note
285/// PTX does not explicitly specify the relative placement of the strings of principal and supplementary
286/// parallel texts, or the relative sizes of graphic characters in the strings of parallel text. A string of
287/// supplementary text is normally presented in a line adjacent to the line containing the string of principal
288/// text, or adjacent to the line containing the immediately preceding string of supplementary text, if any.
289/// The first graphic character of the string of principal text and the first graphic character of a string of
290/// supplementary text are normally presented in the same position of their respective lines. However, a
291/// string of supplementary text longer (when presented) than the associated string of principal text may be
292/// centred on that string. In the case of long strings of text, such as paragraphs in different languages, the
293/// strings may be presented in successive lines in parallel columns, with their beginnings aligned with one
294/// another and the shorter of the paragraphs followed by an appropriate amount of "white space".
295///
296/// Japanese phonetic annotation typically consists of a few half-size or smaller Kana characters which
297/// indicate the pronunciation or interpretation of one or more Kanji characters and are presented above
298/// those Kanji characters if the character path is horizontal, or to the right of them if the character path is
299/// vertical.
300///
301/// Chinese phonetic annotation typically consists of a few Pinyin characters which indicate the
302/// pronunciation of one or more Hanzi characters and are presented above those Hanzi characters.
303/// Alternatively, the Pinyin characters may be presented in the same line as the Hanzi characters and
304/// following the respective Hanzi characters. The Pinyin characters will then be presented within enclosing
305/// pairs of parentheses
306pub fn parallel_texts(text_delimiter: TextDelimiter) -> ControlSequence {
307 ControlSequence::new(&[&text_delimiter.to_string()], "\\")
308}
309
310#[derive(Copy, Clone, Debug)]
311pub enum TextDelimiter {
312 End,
313 BeginPrincipal,
314 BeginSupplementary,
315 BeginSupplementaryPhoneticJapanese,
316 BeginSupplementaryPhoneticChinese,
317 EndPhonetic,
318}
319
320impl Display for TextDelimiter {
321 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
322 write!(f, "{}", match self {
323 TextDelimiter::End => "0",
324 TextDelimiter::BeginPrincipal => "1",
325 TextDelimiter::BeginSupplementary => "2",
326 TextDelimiter::BeginSupplementaryPhoneticJapanese => "3",
327 TextDelimiter::BeginSupplementaryPhoneticChinese => "4",
328 TextDelimiter::EndPhonetic => "5",
329 })
330 }
331}
332
333/// # QUAD
334///
335/// QUAD is used to indicate the end of a string of graphic characters that are to be positioned on a single
336/// line according to the layout specified.
337///
338/// The beginning of the string to be positioned is indicated by the preceding occurrence in the data stream
339/// of either QUAD or one of the following formator functions: FORM FEED (FF), CHARACTER AND
340/// LINE POSITION (HVP), LINE FEED (LF), NEXT LINE (NEL), PAGE POSITION ABSOLUTE (PPA),
341/// PAGE POSITION BACKWARD (PPB), PAGE POSITION FORWARD (PPR), REVERSE LINE FEED
342/// (RI), LINE POSITION ABSOLUTE (VPA), LINE POSITION BACKWARD (VPB), LINE POSITION
343/// FORWARD (VPR), or LINE TABULATION (VT).
344///
345/// The line home position is established by the parameter value of SET LINE HOME (SLH). The line limit
346/// position is established by the parameter value of SET LINE LIMIT (SLL).
347pub fn quad(layouts: &[Layout]) -> ControlSequence {
348 let str_layouts: Vec<String> = layouts.iter()
349 .map(|mode| mode.to_string())
350 .collect();
351
352 let str_ref_modes: Vec<&str> = str_layouts.iter()
353 .map(AsRef::as_ref)
354 .collect();
355
356 ControlSequence::new(&str_ref_modes, " H")
357}
358
359#[derive(Copy, Clone, Debug)]
360pub enum Layout {
361 FlushHome,
362 FlushHomeAndFill,
363 Center,
364 CenterAndFill,
365 FlushLimit,
366 FlushLimitAndFill,
367 FlushBoth,
368}
369
370impl Display for Layout {
371 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
372 write!(f, "{}", match self {
373 Layout::FlushHome => "0",
374 Layout::FlushHomeAndFill => "1",
375 Layout::Center => "2",
376 Layout::CenterAndFill => "3",
377 Layout::FlushLimit => "4",
378 Layout::FlushLimitAndFill => "5",
379 Layout::FlushBoth => "6",
380 })
381 }
382}
383
384/// # REP - Repeat
385///
386/// REP is used to indicate that the preceding character in the data stream, if it is a graphic character
387/// (represented by one or more bit combinations) including SPACE, is to be repeated `n` times.
388///
389/// If the character preceding REP is a control function or part of a control function,
390/// the effect of REP is not defined by this Standard.
391pub fn repeat(n: usize) -> ControlSequence {
392 ControlSequence::new(&[&n.to_string()], "b")
393}
394
395/// # SACS - Set additional character separation
396///
397/// SACS is used to establish extra inter-character escapement for subsequent text. The established extra
398/// escapement remains in effect until the next occurrence of SACS or of SET REDUCED CHARACTER
399/// SEPARATION (SRCS) in the data stream or until it is reset to the default value by a subsequent
400/// occurrence of CARRIAGE RETURN/LINE FEED (CR LF) or of NEXT LINE (NEL) in the data stream.
401///
402/// `n` specifies the number of units by which the inter-character escapement is enlarged.
403///
404/// The unit in which the parameter value is expressed is that established by the parameter value of SELECT
405/// SIZE UNIT (SSU).
406pub fn add_separation(n: usize) -> ControlSequence {
407 ControlSequence::new(&[&n.to_string()], " \\")
408}
409
410/// # SAPV - Select alternative presentation variants
411///
412/// SAPV is used to specify one or more variants for the presentation of subsequent text.
413pub fn select_alternative() -> PresentationVariant {
414 PresentationVariant::new()
415}
416
417#[derive(Clone)]
418pub struct PresentationVariant {
419 modes: Vec<String>,
420}
421impl PresentationVariant {
422 pub fn new() -> Self { Self { modes: vec![] } }
423
424 /// Default presentation (implementation-defined); cancels the effect of any preceding occurrence of
425 /// SAPV in the data stream.
426 pub fn default(&mut self) -> &mut Self { self.add("0") }
427
428 /// The decimal digits are presented by means of the graphic symbols used in the Latin script.
429 pub fn latin_decimal(&mut self) -> &mut Self { self.add("1") }
430
431 /// The decimal digits are presented by means of the graphic symbols used in the Arabic script, i.e. the Hindi symbols.
432 pub fn arabic_decimal(&mut self) -> &mut Self { self.add("2") }
433
434 /// When the direction of the character path is right-to-left, each of the graphic characters in the graphic
435 /// character set(s) in use which is one of a left/right-handed pair (parentheses, square brackets, curly
436 /// brackets, greater-than/less-than signs, etc.) is presented as "mirrored", i.e. as the other member of the
437 /// pair. For example, the coded graphic character given the name LEFT PARENTHESIS is presented as
438 /// RIGHT PARENTHESIS, and vice versa.
439 pub fn mirror_horizontal(&mut self) -> &mut Self { self.add("3") }
440
441 /// When the direction of the character path is right-to-left, all graphic characters which represent
442 /// operators and delimiters in mathematical formulae and which are not symmetrical about a vertical
443 /// axis are presented as mirrored about that vertical axis.
444 pub fn mirror_vertical(&mut self) -> &mut Self { self.add("4") }
445
446 /// The following graphic character is presented in its isolated form.
447 pub fn character_isolate(&mut self) -> &mut Self { self.add("5") }
448
449 /// The following graphic character is presented in its initial form.
450 pub fn character_initial(&mut self) -> &mut Self { self.add("6") }
451
452 /// The following graphic character is presented in its medial form.
453 pub fn character_medial(&mut self) -> &mut Self { self.add("7") }
454
455 /// The following graphic character is presented in its final form.
456 pub fn character_final(&mut self) -> &mut Self { self.add("8") }
457
458 /// Where the bit combination 0x2E is intended to represent a decimal mark in a decimal number it shall
459 /// be presented by means of the graphic symbol FULL STOP.
460 pub fn decimal_stop(&mut self) -> &mut Self { self.add("9") }
461
462 /// Where the bit combination 0x2E is intended to represent a decimal mark in a decimal number it shall
463 /// be presented by means of the graphic symbol COMMA.
464 pub fn decimal_comma(&mut self) -> &mut Self { self.add("10") }
465
466 /// Vowels are presented above or below the preceding character.
467 pub fn vowel_above_or_below(&mut self) -> &mut Self { self.add("11") }
468
469 /// Vowels are presented after the preceding character.
470 pub fn vowel_after(&mut self) -> &mut Self { self.add("12") }
471
472 /// Contextual shape determination of Arabic scripts, including the LAM-ALEPH ligature but excluding
473 /// all other Arabic ligatures.
474 pub fn arabic_ligature_aleph(&mut self) -> &mut Self { self.add("13") }
475
476 /// Contextual shape determination of Arabic scripts, excluding all Arabic ligatures.
477 pub fn arabic_ligature_none(&mut self) -> &mut Self { self.add("14") }
478
479 /// Cancels the effect of parameter values [Self::mirror_horizontal] and [Self::mirror_vertical].
480 pub fn no_mirror(&mut self) -> &mut Self { self.add("15") }
481
482 /// Vowels are not presented.
483 pub fn no_vowel(&mut self) -> &mut Self { self.add("16") }
484
485 /// When the string direction is right-to-left, the italicized characters are slanted to the left; when the
486 /// string direction is left-to-right, the italicized characters are slanted to the right.
487 pub fn italic_direction(&mut self) -> &mut Self { self.add("17") }
488
489 /// Contextual shape determination of Arabic scripts is not used, the graphic characters - including the
490 /// digits - are presented in the form they are stored (Pass-through).
491 pub fn arabic_no_context_with_digit(&mut self) -> &mut Self { self.add("18") }
492
493 /// Contextual shape determination of Arabic scripts is not used, the graphic characters - excluding the
494 /// digits - are presented in the form they are stored (Pass-through).
495 pub fn arabic_no_context(&mut self) -> &mut Self { self.add("19") }
496
497 /// The graphic symbols used to present the decimal digits are device dependent.
498 pub fn device_digit(&mut self) -> &mut Self { self.add("20") }
499
500 /// Establishes the effect of parameter values [Self::character_isolate], [Self::character_initial],
501 /// [Self::character_medial], and [Self::character_final] for the following graphic characters until
502 /// cancelled.
503 pub fn character_establish(&mut self) -> &mut Self { self.add("21") }
504
505 /// Cancels the effect of parameter value [Self::character_establish], i.e. re-establishes the effect
506 /// of parameter values [Self::character_isolate], [Self::character_initial],
507 /// [Self::character_medial], and [Self::character_final] for the next single graphic character only.
508 pub fn character_cancel(&mut self) -> &mut Self { self.add("22") }
509
510 pub fn get(&self) -> ControlSequence {
511 ControlSequence::new(&self.modes.iter().map(|s| s.as_str()).collect::<Vec<_>>(), " ]")
512 }
513 fn add(&mut self, s: &str) -> &mut Self {
514 self.modes.push(s.to_string());
515 self
516 }
517}
518impl Display for PresentationVariant {
519 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
520 write!(f, "{}", self.get())
521 }
522}
523
524/// # SCO - Select character orientation
525///
526/// SCO is used to establish the amount of rotation of the graphic characters following in the data stream.
527/// The established value remains in effect until the next occurrence of SCO in the data stream.
528///
529///
530pub fn character_orientation(orientation: Orientation) -> ControlSequence {
531 ControlSequence::new(&[&orientation.to_string()], " e")
532}
533
534#[derive(Copy, Clone, Debug)]
535pub enum Orientation {
536 /// 0°
537 North,
538 /// 45°
539 NorthWest,
540 /// 90°
541 West,
542 /// 135°
543 SouthWest,
544 /// 180°
545 South,
546 /// 225°
547 SouthEast,
548 /// 270°
549 East,
550 /// 315°
551 NorthEast,
552}
553
554impl Display for Orientation {
555 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
556 write!(f, "{}", match self {
557 Orientation::North => "0",
558 Orientation::NorthWest => "1",
559 Orientation::West => "2",
560 Orientation::SouthWest => "3",
561 Orientation::South => "4",
562 Orientation::SouthEast => "5",
563 Orientation::East => "6",
564 Orientation::NorthEast => "7",
565 })
566 }
567}
568
569/// # SCP - Select character path
570///
571/// SCP is used to select the character path, relative to the line orientation, for the active line (the line that
572/// contains the active presentation position) and subsequent lines in the presentation component. It is also
573/// used to update the content of the active line in the presentation component and the content of the active
574/// line (the line that contains the active data position) in the data component. This takes effect immediately.
575pub fn character_path(character_path: CharacterPath, path_effect: PathEffect) -> ControlSequence {
576 ControlSequence::new(&[&character_path.to_string(), &path_effect.to_string()], " k")
577}
578
579#[derive(Copy, Clone, Debug)]
580pub enum CharacterPath {
581 /// left-to-right (in the case of horizontal line orientation), or top-to-bottom (in the case of vertical line
582 /// orientation).
583 LeftToRight,
584
585 /// right-to-left (in the case of horizontal line orientation), or bottom-to-top (in the case of vertical line
586 /// orientation).
587 RightToLeft,
588}
589
590impl Display for CharacterPath {
591 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
592 write!(f, "{}", match self {
593 CharacterPath::LeftToRight => "1",
594 CharacterPath::RightToLeft => "2",
595 })
596 }
597}
598
599#[derive(Copy, Clone, Debug)]
600pub enum PathEffect {
601 /// Implementation dependant.
602 Undefined,
603
604 /// The content of the active line in the presentation component (the line that contains the active
605 /// presentation position) is updated to correspond to the content of the active line in the data component
606 /// (the line that contains the active data position) according to the newly established character path
607 /// characteristics in the presentation component; the active data position is moved to the first character
608 /// position in the active line in the data component, the active presentation position in the presentation
609 /// component is updated accordingly.
610 UpdatePresentation,
611
612 /// The content of the active line in the data component (the line that contains the active data position) is
613 /// updated to correspond to the content of the active line in the presentation component (the line that
614 /// contains the active presentation position) according to the newly established character path
615 /// characteristics of the presentation component; the active presentation position is moved to the first
616 /// character position in the active line in the presentation component, the active data position in the data
617 /// component is updated accordingly.
618 UpdateData,
619}
620
621impl Display for PathEffect {
622 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
623 write!(f, "{}", match self {
624 PathEffect::Undefined => "0",
625 PathEffect::UpdatePresentation => "1",
626 PathEffect::UpdateData => "2",
627 })
628 }
629}
630
631/// # SDS - Start directed string
632///
633/// SDS is used to establish in the data component the beginning and the end of a string of characters as
634/// well as the direction of the string. This direction may be different from that currently established. The
635/// indicated string follows the preceding text. The established character progression is not affected.
636///
637/// The beginning of a directed string is indicated by SDS with a parameter value not equal to 0. A directed
638/// string may contain one or more nested strings. These nested strings may be directed strings the
639/// beginnings of which are indicated by SDS with a parameter value not equal to 0, or reversed strings the
640/// beginnings of which are indicated by START REVERSED STRING (SRS) with a parameter value of 1.
641///
642/// Every beginning of such a string invokes the next deeper level of nesting.
643///
644/// This Standard does not define the location of the active data position within any such nested string.
645///
646/// The end of a directed string is indicated by SDS with a parameter value of 0. Every end of such a string
647/// re-establishes the next higher level of nesting (the one in effect prior to the string just ended). The
648/// direction is re-established to that in effect prior to the string just ended. The active data position is
649/// moved to the character position following the characters of the string just ended.
650///
651/// ### Note 1
652/// The effect of receiving a CVT, HT, SCP, SPD or VT control function within an SDS string is not defined
653/// by this Standard.
654///
655/// ### Note 2
656/// The control functions for area definition (DAQ, EPA, ESA, SPA, SSA) should not be used within an SDS
657/// string.
658pub fn directed(string_direction: StringDirection) -> ControlSequence {
659 ControlSequence::new(&[&string_direction.to_string()], "]")
660}
661
662#[derive(Copy, Clone, Debug)]
663pub enum StringDirection {
664 End,
665 StartLeftToRight,
666 StartRightToLeft,
667}
668
669impl Display for StringDirection {
670 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
671 write!(f, "{}", match self {
672 StringDirection::End => "0",
673 StringDirection::StartLeftToRight => "1",
674 StringDirection::StartRightToLeft => "2",
675 })
676 }
677}
678
679/// # SIMD - Select implicit movement direction
680///
681/// SIMD is used to select the direction of implicit movement of the data position relative to the character
682/// progression. The direction selected remains in effect until the next occurrence of SIMD.
683pub fn select_implicit(movement_direction: MovementDirection) -> ControlSequence {
684 ControlSequence::new(&[&movement_direction.to_string()], "^")
685}
686
687#[derive(Copy, Clone, Debug)]
688pub enum MovementDirection {
689 Same,
690 Opposite,
691}
692
693impl Display for MovementDirection {
694 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
695 write!(f, "{}", match self {
696 MovementDirection::Same => "0",
697 MovementDirection::Opposite => "1",
698 })
699 }
700}
701
702/// # SGR - Select graphic rendition
703///
704/// SGR is used to establish one or more graphic rendition aspects for subsequent text. The established
705/// aspects remain in effect until the next occurrence of SGR in the data stream, depending on the setting of
706/// the GRAPHIC RENDITION COMBINATION MODE (GRCM).
707///
708/// ### Example
709/// ```
710///
711/// // Direct format
712/// use coded_chars::presentation::select_graphic;
713/// println!("Hello {}{}{} !", select_graphic().fg_red().bold().underline(), "World", select_graphic().default());
714/// ```
715pub fn select_graphic() -> GraphicSelection {
716 GraphicSelection::new()
717}
718
719#[derive(Clone)]
720pub struct GraphicSelection {
721 modes: Vec<String>,
722}
723impl GraphicSelection {
724 pub fn new() -> Self { Self { modes: vec![] } }
725
726 /// Default rendition (implementation-defined), cancels the effect of any preceding occurrence of SGR in
727 /// the data stream regardless of the setting of the GRAPHIC RENDITION COMBINATION MODE (GRCM).
728 pub fn default(&mut self) -> &mut Self { self.add("0") }
729
730 /// Bold or increased intensity
731 pub fn bold(&mut self) -> &mut Self { self.add("1") }
732
733 /// Faint, decreased intensity or second color
734 pub fn faint(&mut self) -> &mut Self { self.add("2") }
735 pub fn italic(&mut self) -> &mut Self { self.add("3") }
736 pub fn underline(&mut self) -> &mut Self { self.add("4") }
737
738 /// Slowly blinking (less than 150/minute)
739 pub fn slow_blink(&mut self) -> &mut Self { self.add("5") }
740
741 /// Rapidly blinking (150/minute or more)
742 pub fn fast_blink(&mut self) -> &mut Self { self.add("6") }
743 pub fn negative(&mut self) -> &mut Self { self.add("7") }
744 pub fn conceal(&mut self) -> &mut Self { self.add("8") }
745
746 /// Crossed-out (characters still legible but marked as to be deleted)
747 pub fn cross(&mut self) -> &mut Self { self.add("9") }
748 pub fn primary_font(&mut self) -> &mut Self { self.add("10") }
749 pub fn alter1_font(&mut self) -> &mut Self { self.add("11") }
750 pub fn alter2_font(&mut self) -> &mut Self { self.add("12") }
751 pub fn alter3_font(&mut self) -> &mut Self { self.add("13") }
752 pub fn alter4_font(&mut self) -> &mut Self { self.add("14") }
753 pub fn alter5_font(&mut self) -> &mut Self { self.add("15") }
754 pub fn alter6_font(&mut self) -> &mut Self { self.add("16") }
755 pub fn alter7_font(&mut self) -> &mut Self { self.add("17") }
756 pub fn alter8_font(&mut self) -> &mut Self { self.add("18") }
757 pub fn alter9_font(&mut self) -> &mut Self { self.add("19") }
758 pub fn gothic_font(&mut self) -> &mut Self { self.add("20") }
759 pub fn double_underline(&mut self) -> &mut Self { self.add("21") }
760
761 /// Normal color or normal intensity
762 pub fn not_bold_or_faint(&mut self) -> &mut Self { self.add("22") }
763
764 /// Not italicized, not gothic font
765 pub fn not_italic(&mut self) -> &mut Self { self.add("23") }
766
767 /// Not underline (neither singly or doubly)
768 pub fn not_underline(&mut self) -> &mut Self { self.add("24") }
769
770 /// Steady (not blinking)
771 pub fn not_blink(&mut self) -> &mut Self { self.add("25") }
772
773 /// Positive image
774 pub fn not_negative(&mut self) -> &mut Self { self.add("27") }
775
776 /// Revealed characters
777 pub fn not_conceal(&mut self) -> &mut Self { self.add("28") }
778 pub fn not_cross(&mut self) -> &mut Self { self.add("29") }
779 pub fn fg_black(&mut self) -> &mut Self { self.add("30") }
780 pub fn fg_red(&mut self) -> &mut Self { self.add("31") }
781 pub fn fg_green(&mut self) -> &mut Self { self.add("32") }
782 pub fn fg_yellow(&mut self) -> &mut Self { self.add("33") }
783 pub fn fg_blue(&mut self) -> &mut Self { self.add("34") }
784 pub fn fg_magenta(&mut self) -> &mut Self { self.add("35") }
785 pub fn fg_cyan(&mut self) -> &mut Self { self.add("36") }
786 pub fn fg_gray(&mut self) -> &mut Self { self.add("37") }
787 pub fn fg_color(&mut self) -> &mut Self { self.add("38") }
788 pub fn fg_default(&mut self) -> &mut Self { self.add("39") }
789 pub fn bg_black(&mut self) -> &mut Self { self.add("40") }
790 pub fn bg_red(&mut self) -> &mut Self { self.add("41") }
791 pub fn bg_green(&mut self) -> &mut Self { self.add("42") }
792 pub fn bg_yellow(&mut self) -> &mut Self { self.add("43") }
793 pub fn bg_blue(&mut self) -> &mut Self { self.add("44") }
794 pub fn bg_magenta(&mut self) -> &mut Self { self.add("45") }
795 pub fn bg_cyan(&mut self) -> &mut Self { self.add("46") }
796 pub fn bg_gray(&mut self) -> &mut Self { self.add("47") }
797 pub fn bg_color(&mut self) -> &mut Self { self.add("48") }
798 pub fn bg_default(&mut self) -> &mut Self { self.add("49") }
799 pub fn frame(&mut self) -> &mut Self { self.add("51") }
800 pub fn encircle(&mut self) -> &mut Self { self.add("52") }
801 pub fn overline(&mut self) -> &mut Self { self.add("53") }
802 pub fn not_frame_not_encircle(&mut self) -> &mut Self { self.add("54") }
803 pub fn not_overline(&mut self) -> &mut Self { self.add("55") }
804 pub fn ideogram_underline(&mut self) -> &mut Self { self.add("60") }
805 pub fn ideogram_double_underline(&mut self) -> &mut Self { self.add("61") }
806 pub fn ideogram_overline(&mut self) -> &mut Self { self.add("62") }
807 pub fn ideogram_double_overline(&mut self) -> &mut Self { self.add("63") }
808 pub fn ideogram_stress_marking(&mut self) -> &mut Self { self.add("64") }
809 pub fn ideogram_cancel(&mut self) -> &mut Self { self.add("65") }
810 pub fn get(&self) -> ControlSequence {
811 ControlSequence::new(&self.modes.iter().map(|s| s.as_str()).collect::<Vec<_>>(), "m")
812 }
813 fn add(&mut self, s: &str) -> &mut Self {
814 self.modes.push(s.to_string());
815 self
816 }
817}
818
819impl Display for GraphicSelection {
820 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
821 write!(f, "{}", self.get())
822 }
823}
824
825/// Format a string with the specified `SGR` sequence.
826///
827/// The string is terminated with the sequence `\x1b[0m` to reset the style.
828///
829/// ### Example
830/// ```
831/// use coded_chars::presentation::{format_str, select_graphic};
832/// let formatted = format_str(
833/// "World",
834/// select_graphic().fg_red().bold().underline()
835/// );
836/// println!("Hello {} !", formatted);
837/// ```
838pub fn format_str(str: &str, format: &GraphicSelection) -> String {
839 format!("{}{}{}", format, str, select_graphic().default())
840}
841
842/// # SHS - Select character spacing
843///
844/// SHS is used to establish the character spacing for subsequent text. The established spacing remains in
845/// effect until the next occurrence of SHS or of SET CHARACTER SPACING (SCS) or of SPACING
846/// INCREMENT (SPI) in the data stream.
847pub fn select_spacing(character_spacing: CharacterSpacing) -> ControlSequence {
848 ControlSequence::new(&[&character_spacing.to_string()], " K")
849}
850
851#[derive(Copy, Clone, Debug)]
852pub enum CharacterSpacing {
853 Per25mm10Chars,
854 Per25mm12Chars,
855 Per25mm15Chars,
856 Per25mm16Chars,
857 Per25mm3Chars,
858 Per50mm9Chars,
859 Per25mm4Chars,
860}
861
862impl Display for CharacterSpacing {
863 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
864 write!(f, "{}", match self {
865 CharacterSpacing::Per25mm10Chars => "0",
866 CharacterSpacing::Per25mm12Chars => "1",
867 CharacterSpacing::Per25mm15Chars => "2",
868 CharacterSpacing::Per25mm16Chars => "3",
869 CharacterSpacing::Per25mm3Chars => "4",
870 CharacterSpacing::Per50mm9Chars => "5",
871 CharacterSpacing::Per25mm4Chars => "6",
872 })
873 }
874}
875
876/// # SLH - Set line home
877///
878/// If the DEVICE COMPONENT SELECT MODE is set to PRESENTATION, SLH is used to establish at
879/// character position n in the active line (the line that contains the active presentation position) and lines of
880/// subsequent text in the presentation component the position to which the active presentation position will
881/// be moved by subsequent occurrences of CARRIAGE RETURN (CR), DELETE LINE (DL), INSERT
882/// LINE (IL) or NEXT LINE (NEL) in the data stream. In the case of a
883/// device without data component, it is also the position ahead of which no implicit movement of the active
884/// presentation position shall occur.
885///
886/// If the DEVICE COMPONENT SELECT MODE is set to DATA, SLH is used to establish at character
887/// position n in the active line (the line that contains the active data position) and lines of subsequent text
888/// in the data component the position to which the active data position will be moved by subsequent
889/// occurrences of CARRIAGE RETURN (CR), DELETE LINE (DL), INSERT LINE (IL) or NEXT LINE
890/// (NEL) in the data stream. It is also the position ahead of which no
891/// implicit movement of the active data position shall occur.
892///
893/// The established position is called the line home position and remains in effect until the next occurrence
894/// of SLH in the data stream.
895pub fn line_home(c: usize) -> ControlSequence {
896 ControlSequence::new(&[&c.to_string()], " U")
897}
898
899/// # SLL - Set line limit
900///
901/// If the DEVICE COMPONENT SELECT MODE is set to PRESENTATION, SLL is used to establish at
902/// character position n in the active line (the line that contains the active presentation position) and lines of
903/// subsequent text in the presentation component the position to which the active presentation position will
904/// be moved by subsequent occurrences of CARRIAGE RETURN (CR), or NEXT LINE (NEL) in the data
905/// stream if the parameter value of SELECT IMPLICIT MOVEMENT DIRECTION (SIMD) is equal to 1;
906/// where n equals the value of Pn. In the case of a device without data component, it is also the position
907/// beyond which no implicit movement of the active presentation position shall occur.
908///
909/// If the DEVICE COMPONENT SELECT MODE is set to DATA, SLL is used to establish at character
910/// position n in the active line (the line that contains the active data position) and lines of subsequent text
911/// in the data component the position beyond which no implicit movement of the active data position shall
912/// occur. It is also the position in the data component to which the active data position will be moved by
913/// subsequent occurrences of CR or NEL in the data stream, if the parameter value of SELECT IMPLICIT
914/// MOVEMENT DIRECTION (SIMD) is equal to 1.
915///
916/// The established position is called the line limit position and remains in effect until the next occurrence
917/// of SLL in the data stream.
918pub fn line_limit(n: usize) -> ControlSequence {
919 ControlSequence::new(&[&n.to_string()], " V")
920}
921
922/// # SLS - Set line spacing
923///
924/// SLS is used to establish the line spacing for subsequent text. The established spacing remains in effect
925/// until the next occurrence of SLS or of SELECT LINE SPACING (SVS) or of SPACING INCREMENT
926/// (SPI) in the data stream.
927///
928/// The unit in which the parameter value is expressed is that established by the parameter value of SELECT
929/// SIZE UNIT (SSU).
930pub fn line_spacing(n: usize) -> ControlSequence {
931 ControlSequence::new(&[&n.to_string()], " h")
932}
933
934/// # SPD - Select presentation directions
935///
936/// SPD is used to select the line orientation, the line progression, and the character path in the presentation
937/// component. It is also used to update the content of the presentation component and the content of the
938/// data component. This takes effect immediately.
939pub fn select_directions(
940 line_orientation: LineOrientation,
941 line_progression: CharacterPath,
942 character_path: CharacterPath,
943 path_effect: PathEffect,
944) -> ControlSequence {
945 ControlSequence::new(&[&spd_ps1(line_orientation, line_progression, character_path).to_string(), &path_effect.to_string()], " S")
946}
947
948#[derive(Copy, Clone, Debug)]
949pub enum LineOrientation {
950 Horizontal,
951 Vertical,
952}
953
954fn spd_ps1(line_orientation: LineOrientation, line_progression: CharacterPath, character_path: CharacterPath) -> usize {
955 match line_orientation {
956 LineOrientation::Horizontal => {
957 match line_progression {
958 CharacterPath::LeftToRight => {
959 match character_path {
960 CharacterPath::LeftToRight => 0,
961 CharacterPath::RightToLeft => 3,
962 }
963 }
964 CharacterPath::RightToLeft => {
965 match character_path {
966 CharacterPath::LeftToRight => 6,
967 CharacterPath::RightToLeft => 5,
968 }
969 }
970 }
971 }
972 LineOrientation::Vertical => {
973 match line_progression {
974 CharacterPath::LeftToRight => {
975 match character_path {
976 CharacterPath::LeftToRight => 2,
977 CharacterPath::RightToLeft => 4,
978 }
979 }
980 CharacterPath::RightToLeft => {
981 match character_path {
982 CharacterPath::LeftToRight => 1,
983 CharacterPath::RightToLeft => 7,
984 }
985 }
986 }
987 }
988 }
989}
990
991/// # SPH - Set page home
992///
993/// If the DEVICE COMPONENT SELECT MODE is set to PRESENTATION, SPH is used to establish at
994/// line position n in the active page (the page that contains the active presentation position) and subsequent
995/// pages in the presentation component the position to which the active presentation position will be moved
996/// by subsequent occurrences of FORM FEED (FF) in the data stream In
997/// the case of a device without data component, it is also the position ahead of which no implicit movement
998/// of the active presentation position shall occur.
999///
1000/// If the DEVICE COMPONENT SELECT MODE is set to DATA, SPH is used to establish at line position
1001/// `n` in the active page (the page that contains the active data position) and subsequent pages in the data
1002/// component the position to which the active data position will be moved by subsequent occurrences of
1003/// FORM FEED (FF) in the data stream. It is also the position ahead of
1004/// which no implicit movement of the active presentation position shall occur.
1005///
1006/// The established position is called the page home position and remains in effect until the next occurrence
1007/// of SPH in the data stream.
1008pub fn page_home(n: usize) -> ControlSequence {
1009 ControlSequence::new(&[&n.to_string()], " i")
1010}
1011
1012/// # SPI - Spacing increment
1013///
1014/// SPI is used to establish the line spacing and the character spacing for subsequent text. The established
1015/// line spacing remains in effect until the next occurrence of SPI or of SET LINE SPACING (SLS) or of
1016/// SELECT LINE SPACING (SVS) in the data stream. The established character spacing remains in effect
1017/// until the next occurrence of SET CHARACTER SPACING (SCS) or of SELECT CHARACTER
1018/// SPACING (SHS) in the data stream.
1019///
1020/// The unit in which the parameter values are expressed is that established by the parameter value of
1021/// SELECT SIZE UNIT (SSU).
1022pub fn spacing_increment(line_spacing: usize, character_spacing: usize) -> ControlSequence {
1023 ControlSequence::new(&[&line_spacing.to_string(), &character_spacing.to_string()], " G")
1024}
1025
1026/// # SPL - Set page limit
1027///
1028/// If the DEVICE COMPONENT SELECT MODE is set to PRESENTATION, SPL is used to establish at
1029/// line position n in the active page (the page that contains the active presentation position) and pages of
1030/// subsequent text in the presentation component the position beyond which the active presentation position
1031/// can normally not be moved In the case of a device without data
1032/// component, it is also the position beyond which no implicit movement of the active presentation position
1033/// shall occur.
1034///
1035/// If the DEVICE COMPONENT SELECT MODE is set to DATA, SPL is used to establish at line position
1036/// n in the active page (the page that contains the active data position) and pages of subsequent text in the
1037/// data component the position beyond which no implicit movement of the active data position shall occur.
1038///
1039/// The established position is called the page limit position and remains in effect until the next occurrence
1040/// of SPL in the data stream.
1041pub fn page_limit(n: usize) -> ControlSequence {
1042 ControlSequence::new(&[&n.to_string()], " j")
1043}
1044
1045
1046/// # SPQR - Select print quality and rapidity
1047///
1048/// SPQR is used to select the relative print quality and the print speed for devices the output quality and
1049/// speed of which are inversely related. The selected values remain in effect until the next occurrence of
1050/// SPQR in the data stream.
1051pub fn print_quality(print_quality: PrintQuality) -> ControlSequence {
1052 ControlSequence::new(&[&print_quality.to_string()], " X")
1053}
1054
1055#[derive(Copy, Clone, Debug)]
1056pub enum PrintQuality {
1057 /// Highest available print quality, low print speed.
1058 Highest,
1059 /// Medium print quality, medium print speed.
1060 Medium,
1061 /// Draft print quality, highest available print speed.
1062 Draft,
1063}
1064
1065impl Display for PrintQuality {
1066 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1067 write!(f, "{}", match self {
1068 PrintQuality::Highest => "0",
1069 PrintQuality::Medium => "1",
1070 PrintQuality::Draft => "2",
1071 })
1072 }
1073}
1074
1075/// # SRCS - Set reduced character separation
1076///
1077/// SRCS is used to establish reduced inter-character escapement for subsequent text. The established
1078/// reduced escapement remains in effect until the next occurrence of SRCS or of SET ADDITIONAL
1079/// CHARACTER SEPARATION (SACS) in the data stream or until it is reset to the default value by a
1080/// subsequent occurrence of CARRIAGE RETURN/LINE FEED (CR/LF) or of NEXT LINE (NEL) in the
1081/// data stream.
1082///
1083/// `n` specifies the number of units by which the inter-character escapement is reduced.
1084///
1085/// The unit in which the parameter value is expressed is that established by the parameter value of SELECT
1086/// SIZE UNIT (SSU).
1087pub fn reduce_separation(n: usize) -> ControlSequence {
1088 ControlSequence::new(&[&n.to_string()], " f")
1089}
1090
1091/// # SRS - Start reversed string
1092///
1093/// SRS is used to establish in the data component the beginning and the end of a string of characters as well
1094/// as the direction of the string. This direction is opposite to that currently established. The indicated string
1095/// follows the preceding text. The established character progression is not affected.
1096///
1097/// The beginning of a reversed string is indicated by SRS with a parameter value of 1. A reversed string
1098/// may contain one or more nested strings. These nested strings may be reversed strings the beginnings of
1099/// which are indicated by SRS with a parameter value of 1, or directed strings the beginnings of which are
1100/// indicated by START DIRECTED STRING (SDS) with a parameter value not equal to 0. Every
1101/// beginning of such a string invokes the next deeper level of nesting.
1102///
1103/// This Standard does not define the location of the active data position within any such nested string.
1104///
1105/// The end of a reversed string is indicated by SRS with a parameter value of 0. Every end of such a string
1106/// re-establishes the next higher level of nesting (the one in effect prior to the string just ended). The
1107/// direction is re-established to that in effect prior to the string just ended. The active data position is
1108/// moved to the character position following the characters of the string just ended.
1109///
1110/// ### Note 1
1111/// The effect of receiving a CVT, HT, SCP, SPD or VT control function within an SRS string is not defined
1112/// by this Standard.
1113///
1114/// ### Note 2
1115/// The control functions for area definition (DAQ, EPA, ESA, SPA, SSA) should not be used within an SRS
1116/// string.
1117pub fn reversed(string_reversion: StringReversion) -> ControlSequence {
1118 ControlSequence::new(&[&string_reversion.to_string()], "[")
1119}
1120
1121#[derive(Copy, Clone, Debug)]
1122pub enum StringReversion {
1123 End,
1124 BeginReverse,
1125}
1126
1127impl Display for StringReversion {
1128 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1129 write!(f, "{}", match self {
1130 Self::End => "0",
1131 Self::BeginReverse => "1",
1132 })
1133 }
1134}
1135
1136/// # SSU - Select size unit
1137///
1138/// SSU is used to establish the unit in which the numeric parameters of certain control functions are
1139/// expressed. The established unit remains in effect until the next occurrence of SSU in the data stream.
1140pub fn select_size_unit(size_unit: SizeUnit) -> ControlSequence {
1141 ControlSequence::new(&[&size_unit.to_string()], " I")
1142}
1143
1144#[derive(Copy, Clone, Debug)]
1145pub enum SizeUnit {
1146 Character,
1147 Millimeter,
1148 ComputerDeciPoint,
1149 DeciDidot,
1150 Mil,
1151 BasicMeasuringUnit,
1152 Micrometer,
1153 Pixel,
1154 DeciPoint,
1155}
1156
1157impl Display for SizeUnit {
1158 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1159 write!(f, "{}", match self {
1160 SizeUnit::Character => "0",
1161 SizeUnit::Millimeter => "1",
1162 SizeUnit::ComputerDeciPoint => "2",
1163 SizeUnit::DeciDidot => "3",
1164 SizeUnit::Mil => "4",
1165 SizeUnit::BasicMeasuringUnit => "5",
1166 SizeUnit::Micrometer => "6",
1167 SizeUnit::Pixel => "7",
1168 SizeUnit::DeciPoint => "8",
1169 })
1170 }
1171}
1172
1173/// # SSW - Set space width
1174///
1175/// SSW is used to establish for subsequent text the character escapement associated with the character
1176/// SPACE. The established escapement remains in effect until the next occurrence of SSW in the data
1177/// stream or until it is reset to the default value by a subsequent occurrence of CARRIAGE RETURN/LINE
1178/// FEED (CR/LF), CARRIAGE RETURN/FORM FEED (CR/FF), or of NEXT LINE (NEL) in the data stream.
1179///
1180/// `n` specifies the escapement.
1181///
1182/// The unit in which the parameter value is expressed is that established by the parameter value of SELECT
1183/// SIZE UNIT (SSU).
1184///
1185/// The default character escapement of SPACE is specified by the most recent occurrence of SET
1186/// CHARACTER SPACING (SCS) or of SELECT CHARACTER SPACING (SHS) or of SELECT
1187/// SPACING INCREMENT (SPI) in the data stream if the current font has constant spacing, or is specified
1188/// by the nominal width of the character SPACE in the current font if that font has proportional spacing.
1189pub fn space_width(n: usize) -> ControlSequence {
1190 ControlSequence::new(&[&n.to_string()], " [")
1191}
1192
1193/// # STAB - Selective tabulation
1194///
1195/// STAB causes subsequent text in the presentation component to be aligned according to the position and
1196/// the properties of a tabulation stop which is selected from a list according to the value of the parameter.
1197///
1198/// The use of this control function and means of specifying a list of tabulation stops to be referenced by the
1199/// control function are specified in other standards, for example ISO 8613-6.
1200pub fn select_tabulation(n: usize) -> ControlSequence {
1201 ControlSequence::new(&[&n.to_string()], " ^")
1202}
1203
1204/// # SVS - Select line spacing
1205///
1206/// SVS is used to establish the line spacing for subsequent text. The established spacing remains in effect
1207/// until the next occurrence of SVS or of SET LINE SPACING (SLS) or of SPACING INCREMENT (SPI)
1208/// in the data stream.
1209pub fn select_line_spacing(line_spacing: LineSpacing) -> ControlSequence {
1210 ControlSequence::new(&[&line_spacing.to_string()], " L")
1211}
1212
1213#[derive(Copy, Clone, Debug)]
1214pub enum LineSpacing {
1215 Per25mm6Lines,
1216 Per25mm4Lines,
1217 Per25mm3Lines,
1218 Per25mm12Lines,
1219 Per25mm8Lines,
1220 Per30mm6Lines,
1221 Per30mm4Lines,
1222 Per30mm3Lines,
1223 Per30mm12Lines,
1224 Per25mm2Lines,
1225}
1226
1227impl Display for LineSpacing {
1228 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1229 write!(f, "{}", match self {
1230 LineSpacing::Per25mm6Lines => "0",
1231 LineSpacing::Per25mm4Lines => "1",
1232 LineSpacing::Per25mm3Lines => "2",
1233 LineSpacing::Per25mm12Lines => "3",
1234 LineSpacing::Per25mm8Lines => "4",
1235 LineSpacing::Per30mm6Lines => "5",
1236 LineSpacing::Per30mm4Lines => "6",
1237 LineSpacing::Per30mm3Lines => "7",
1238 LineSpacing::Per30mm12Lines => "8",
1239 LineSpacing::Per25mm2Lines => "9",
1240 })
1241 }
1242}
1243
1244
1245/// # TAC - Tabulation aligned centred
1246///
1247/// TAC causes a character tabulation stop calling for centring to be set at character position n in the active
1248/// line (the line that contains the active presentation position) and lines of subsequent text in the
1249/// presentation component, where n equals the value of Pn. TAC causes the replacement of any tabulation
1250/// stop previously set at that character position, but does not affect other tabulation stops.
1251///
1252/// A text string centred upon a tabulation stop set by TAC will be positioned so that the (trailing edge of
1253/// the) first graphic character and the (leading edge of the) last graphic character are at approximately equal
1254/// distances from the tabulation stop.
1255pub fn align_center(n: usize) -> ControlSequence {
1256 ControlSequence::new(&[&n.to_string()], " b")
1257}
1258
1259/// # TALE - Tabulation aligned leading edge
1260///
1261/// TALE causes a character tabulation stop calling for leading edge alignment to be set at character
1262/// position n in the active line (the line that contains the active presentation position) and lines of
1263/// subsequent text in the presentation component, where n equals the value of Pn. TALE causes the
1264/// replacement of any tabulation stop previously set at that character position, but does not affect other
1265/// tabulation stops.
1266///
1267/// A text string aligned with a tabulation stop set by TALE will be positioned so that the (leading edge of
1268/// the) last graphic character of the string is placed at the tabulation stop.
1269pub fn align_leading(n: usize) -> ControlSequence {
1270 ControlSequence::new(&[&n.to_string()], " a")
1271}
1272
1273/// # TATE - Tabulation aligned trailing edge
1274///
1275/// TATE causes a character tabulation stop calling for trailing edge alignment to be set at character
1276/// position n in the active line (the line that contains the active presentation position) and lines of
1277/// subsequent text in the presentation component, where n equals the value of Pn. TATE causes the
1278/// replacement of any tabulation stop previously set at that character position, but does not affect other
1279/// tabulation stops.
1280///
1281/// A text string aligned with a tabulation stop set by TATE will be positioned so that the (trailing edge of
1282/// the) first graphic character of the string is placed at the tabulation stop.
1283pub fn align_trailing(n: usize) -> ControlSequence {
1284 ControlSequence::new(&[&n.to_string()], " `")
1285}
1286
1287/// # TCC - Tabulation centred on character
1288///
1289/// TCC causes a character tabulation stop calling for alignment of a target graphic character to be set at
1290/// character position `l` in the active line (the line that contains the active presentation position) and lines of
1291/// subsequent text in the presentation component, and the target character
1292/// about which centring is to be performed is specified by `ascii`. TCC causes the replacement of any
1293/// tabulation stop previously set at that character position, but does not affect other tabulation stops.
1294///
1295/// The positioning of a text string aligned with a tabulation stop set by TCC will be determined by the first
1296/// occurrence in the string of the target graphic character; that character will be centred upon the tabulation
1297/// stop. If the target character does not occur within the string, then the trailing edge of the first character
1298/// of the string will be positioned at the tabulation stop.
1299///
1300/// The value of `ascii` indicates the code table position (binary value) of the target character in the currently
1301/// invoked code. For a 7-bit code, the permissible range of values is 32 to 127; for an 8-bit code, the
1302/// permissible range of values is 32 to 127 and 160 to 255.
1303pub fn tabulation_center_on_char(l: usize, ascii: usize) -> ControlSequence {
1304 ControlSequence::new(&[&l.to_string(), &ascii.to_string()], " c")
1305}
1306
1307/// # TSS - Thin space specification
1308///
1309/// TSS is used to establish the width of a thin space for subsequent text. The established width remains in
1310/// effect until the next occurrence of TSS in the data stream, see annex C.
1311///
1312/// `width` specifies the width of the thin space.
1313///
1314/// The unit in which the parameter value is expressed is that established by the parameter value of SELECT
1315/// SIZE UNIT (SSU).
1316pub fn specify_thin_space(width: usize) -> ControlSequence {
1317 ControlSequence::new(&[&width.to_string()], " E")
1318}
1319
1320
1321#[cfg(test)]
1322mod tests {
1323 use super::*;
1324
1325 #[test]
1326 fn test_space_width() {
1327 let cs = space_width(5);
1328 assert_eq!(cs.to_string(), "\x1b[5 [");
1329 }
1330
1331 #[test]
1332 fn test_select_tabulation() {
1333 let cs = select_tabulation(3);
1334 assert_eq!(cs.to_string(), "\x1b[3 ^");
1335 }
1336
1337 #[test]
1338 fn test_select_line_spacing() {
1339 let cs = select_line_spacing(LineSpacing::Per25mm6Lines);
1340 assert_eq!(cs.to_string(), "\x1b[0 L");
1341 let cs = select_line_spacing(LineSpacing::Per30mm12Lines);
1342 assert_eq!(cs.to_string(), "\x1b[8 L");
1343 }
1344
1345 #[test]
1346 fn test_line_spacing_display() {
1347 let ls = LineSpacing::Per25mm4Lines;
1348 assert_eq!(ls.to_string(), "1");
1349 let ls = LineSpacing::Per30mm3Lines;
1350 assert_eq!(ls.to_string(), "7");
1351 }
1352
1353 #[test]
1354 fn test_align_center() {
1355 let cs = align_center(10);
1356 assert_eq!(cs.to_string(), "\x1b[10 b");
1357 }
1358
1359 #[test]
1360 fn test_align_leading() {
1361 let cs = align_leading(15);
1362 assert_eq!(cs.to_string(), "\x1b[15 a");
1363 }
1364
1365 #[test]
1366 fn test_align_trailing() {
1367 let cs = align_trailing(20);
1368 assert_eq!(cs.to_string(), "\x1b[20 `");
1369 }
1370
1371 #[test]
1372 fn test_tabulation_center_on_char() {
1373 let cs = tabulation_center_on_char(25, 65);
1374 assert_eq!(cs.to_string(), "\x1b[25;65 c");
1375 }
1376
1377 #[test]
1378 fn test_specify_thin_space() {
1379 let cs = specify_thin_space(2);
1380 assert_eq!(cs.to_string(), "\x1b[2 E");
1381 }
1382}