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(¤t_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(¤t_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(¤t_line_text);
93 }
94 }
95}