tx2_web/
lw.rs

1use tracing::{Level, event};
2use web_sys::Document;
3
4use base::Unsigned6Bit;
5use base::charset::{Colour, DescribedChar, LincolnChar, LincolnState, Script};
6
7/// Generate HTML corresponding to Lincoln Writer character (in the given state).
8///
9/// While currently we use sup/sub elements here, this does not quite
10/// correspond with the way the Lincoln Writer generated
11/// superscript/subscript letters.  For the LW, these corresponded to
12/// half-line movements of the platen (see pages 9-11) of "The Lincoln
13/// Writer" (Lincoln Lab Group Report 51-8).
14///
15/// Also, the "line feed up" and "line feed down" characters don't
16/// affect the script in effect.  Per page 10 of "The Lincoln Writer"
17/// (i.e. the same document mentioned above):
18///
19/// > The line feed selectors do not affect the last remembered script
20/// > position of the typewriter. Therefore after one or more line feed selections,
21/// > care must be taken to return the typewriter platen to its original
22/// > position by the selection of the opposite line feed. For example, if the
23/// > typewriter platen were in normal script position and a line feed-up were
24/// > selected - followed by printable characters, the printed result would be
25/// > the same as if a superscript had been selected. However, if this were to
26/// > be followed by a normal script selection there would be no change since
27/// > the typewriter would act as if it was already in normal script, (since
28/// > no other script had been selected). Consequently the line feed selections
29/// > should be used for situations like superscripting a superscript or
30/// > subscripting a subscript, etc. On these occasions the opposite line feed
31/// > should be used to return the typewriter to its original script position.
32fn generate_html_for_char(uch: char, attributes: &LincolnState, _advance: bool) -> String {
33    let colour_class = match attributes.colour {
34        // These styles are defined in index.html, not in CSS files
35        // (because those styles get renamed).
36        Colour::Black => "lwb",
37        Colour::Red => "lwr",
38    };
39    let (script_open, script_close) = match attributes.script {
40        Script::Normal => ("", ""),
41        Script::Super => ("<sup>", "</sup>"),
42        Script::Sub => ("<sub>", "</sub>"),
43    };
44    // TODO: By recalling existing colour and script information we
45    // could save on volume of output here.
46    format!("<span class=\"{colour_class}\">{script_open}{uch}{script_close}</span>")
47}
48
49pub(crate) fn display_lw_unit_output_event(unit: Unsigned6Bit, ch: DescribedChar, doc: Document) {
50    event!(
51        Level::INFO,
52        "display_lw_unit_output_event: handling output event for LW unit {unit:?}"
53    );
54    let current_line_element_id = format!("lw{unit:o}-current-line");
55    let current_line_el = doc
56        .get_element_by_id(&current_line_element_id)
57        .expect("LW current line element is missing from HTML document");
58    let mut current_line_text = current_line_el.inner_html();
59    match ch {
60        DescribedChar {
61            base_char: LincolnChar::UnicodeBaseChar('\r'),
62            ..
63        } => {
64            event!(Level::INFO, "LW: processing a carriage return");
65            let history_element_id = format!("lw{unit:o}-history");
66            let history_el = doc
67                .get_element_by_id(&history_element_id)
68                .expect("LW history element is missing from HTML document");
69            // Append the current line to the history.
70            let mut history_text = history_el.inner_html();
71            history_text.push_str(&current_line_text);
72            history_text.push_str("<br/>\r\n");
73            history_el.set_inner_html(&history_text);
74            // Clear the current line.
75            current_line_el.set_inner_html("");
76        }
77        DescribedChar {
78            base_char: LincolnChar::Unprintable(_),
79            ..
80        } => {
81            // We don't print unprintable characters.
82        }
83        DescribedChar {
84            base_char: LincolnChar::UnicodeBaseChar(uch),
85            attributes,
86            advance,
87            unicode_representation: _,
88            label_matches_unicode: _,
89        } => {
90            let s: String = generate_html_for_char(uch, &attributes, advance);
91            current_line_text.push_str(&s);
92            current_line_el.set_inner_html(&current_line_text);
93        }
94    }
95}