Basic functionality seems to work!
This commit is contained in:
181
Cargo.lock
generated
181
Cargo.lock
generated
@@ -83,6 +83,15 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.71"
|
version = "1.0.71"
|
||||||
@@ -312,6 +321,17 @@ version = "1.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
|
checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.1.19",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -463,6 +483,21 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "2.34.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term 0.12.1",
|
||||||
|
"atty",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"strsim",
|
||||||
|
"textwrap",
|
||||||
|
"unicode-width",
|
||||||
|
"vec_map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codespan-reporting"
|
name = "codespan-reporting"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@@ -541,6 +576,32 @@ dependencies = [
|
|||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm"
|
||||||
|
version = "0.26.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crossterm_winapi",
|
||||||
|
"futures-core",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
|
"signal-hook",
|
||||||
|
"signal-hook-mio",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm_winapi"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-mac"
|
name = "crypto-mac"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -632,6 +693,20 @@ dependencies = [
|
|||||||
"bitflags 2.2.1",
|
"bitflags 2.2.1",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "d3270console"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"crossterm",
|
||||||
|
"d3270-common",
|
||||||
|
"futures",
|
||||||
|
"serde_json",
|
||||||
|
"structopt",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -905,6 +980,24 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
@@ -1356,6 +1449,30 @@ version = "0.2.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-hack"
|
name = "proc-macro-hack"
|
||||||
version = "0.5.20+deprecated"
|
version = "0.5.20+deprecated"
|
||||||
@@ -1681,6 +1798,17 @@ dependencies = [
|
|||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-mio"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"signal-hook",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
@@ -1797,6 +1925,36 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt"
|
||||||
|
version = "0.3.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"lazy_static",
|
||||||
|
"structopt-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt-derive"
|
||||||
|
version = "0.4.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
@@ -1843,6 +2001,15 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.40"
|
version = "1.0.40"
|
||||||
@@ -2092,7 +2259,7 @@ version = "0.1.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "192ca16595cdd0661ce319e8eede9c975f227cdaabc4faaefdc256f43d852e45"
|
checksum = "192ca16595cdd0661ce319e8eede9c975f227cdaabc4faaefdc256f43d852e45"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term 0.11.0",
|
||||||
"chrono",
|
"chrono",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"matchers 0.0.1",
|
"matchers 0.0.1",
|
||||||
@@ -2168,6 +2335,12 @@ dependencies = [
|
|||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@@ -2222,6 +2395,12 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
members = [
|
members = [
|
||||||
"d3270-common",
|
"d3270-common",
|
||||||
"d3270d",
|
"d3270d",
|
||||||
"qt3270"
|
"qt3270",
|
||||||
|
"d3270console",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ serde_json = "1.0.96"
|
|||||||
#serde_cbor = "0.11.2"
|
#serde_cbor = "0.11.2"
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.71"
|
||||||
bitflags = "2.2.1"
|
bitflags = "2.2.1"
|
||||||
|
tracing = "0.1.37"
|
||||||
|
|
||||||
# deps for bins
|
# deps for bins
|
||||||
#structopt = "0.3.26"
|
#structopt = "0.3.26"
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use indication::{
|
use indication::{
|
||||||
CodePage, ConnectAttempt, Connection, Erase, FileTransfer, Hello, Model, Oia, Passthru, Popup,
|
CodePage, ConnectAttempt, Connection, Erase, FileTransfer, Hello, Model, Passthru, Popup,
|
||||||
Proxy, RunResult, Screen, ScreenMode, Scroll, Setting, Stats, TerminalName, Thumb, Tls,
|
Proxy, RunResult, Screen, ScreenMode, Scroll, Setting, Stats, TerminalName, Thumb, Tls,
|
||||||
TlsHello, TraceFile, UiError,
|
TlsHello, TraceFile, UiError,
|
||||||
};
|
};
|
||||||
use operation::{Fail, Register, Run, Succeed};
|
use operation::{Fail, Register, Run, Succeed};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::b3270::indication::OiaField;
|
||||||
|
|
||||||
pub mod indication;
|
pub mod indication;
|
||||||
pub mod operation;
|
pub mod operation;
|
||||||
@@ -44,7 +45,7 @@ pub enum Indication {
|
|||||||
/// The first message sent
|
/// The first message sent
|
||||||
Initialize(Vec<InitializeIndication>),
|
Initialize(Vec<InitializeIndication>),
|
||||||
/// Change in the state of the Operator Information Area
|
/// Change in the state of the Operator Information Area
|
||||||
Oia(Oia),
|
Oia(OiaField),
|
||||||
/// A passthru action has been invoked.
|
/// A passthru action has been invoked.
|
||||||
/// Clients must respond with a succeed or fail operation
|
/// Clients must respond with a succeed or fail operation
|
||||||
Passthru(Passthru),
|
Passthru(Passthru),
|
||||||
@@ -89,7 +90,7 @@ pub enum InitializeIndication {
|
|||||||
/// Indicates which 3270 models are supported
|
/// Indicates which 3270 models are supported
|
||||||
Models(Vec<Model>),
|
Models(Vec<Model>),
|
||||||
/// Change in the state of the Operator Information Area
|
/// Change in the state of the Operator Information Area
|
||||||
Oia(Oia),
|
Oia(OiaField),
|
||||||
/// Set of supported prefixes
|
/// Set of supported prefixes
|
||||||
Prefixes {
|
Prefixes {
|
||||||
value: String,
|
value: String,
|
||||||
|
|||||||
@@ -96,15 +96,6 @@ pub struct Model {
|
|||||||
pub columns: u8,
|
pub columns: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
|
||||||
// This could be more typesafe, probably ¯\_(ツ)_/¯
|
|
||||||
pub struct Oia {
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub field: OiaField,
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub lu: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case", tag = "field")]
|
#[serde(rename_all = "kebab-case", tag = "field")]
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@@ -137,25 +128,26 @@ pub enum OiaField {
|
|||||||
NotUndera {
|
NotUndera {
|
||||||
value: bool,
|
value: bool,
|
||||||
},
|
},
|
||||||
PrinterSession {
|
// PrinterSession {
|
||||||
value: bool,
|
// value: bool,
|
||||||
/// Printer session LU name
|
// /// Printer session LU name
|
||||||
// TODO: determine if this is sent with this message or with Lu
|
// // TODO: determine if this is sent with this message or with Lu
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
// #[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
lu: Option<String>,
|
// lu: Option<String>,
|
||||||
},
|
// },
|
||||||
/// Reverse input mode
|
/// Reverse input mode
|
||||||
ReverseInput {
|
ReverseInput {
|
||||||
value: bool,
|
value: bool,
|
||||||
},
|
},
|
||||||
/// Screen trace count
|
/// Screen trace count
|
||||||
ScreenTrace {
|
ScreenTrace {
|
||||||
value: String,
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
value: Option<usize>,
|
||||||
},
|
},
|
||||||
/// Host command timer (minutes:seconds)
|
|
||||||
Script {
|
Script {
|
||||||
value: bool,
|
value: bool,
|
||||||
},
|
},
|
||||||
|
/// Host command timer (minutes:seconds)
|
||||||
Timing {
|
Timing {
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
value: Option<String>,
|
value: Option<String>,
|
||||||
@@ -188,7 +180,7 @@ impl OiaField {
|
|||||||
OiaField::Lock { .. } => OiaFieldName::Lock,
|
OiaField::Lock { .. } => OiaFieldName::Lock,
|
||||||
OiaField::Lu { .. } => OiaFieldName::Lu,
|
OiaField::Lu { .. } => OiaFieldName::Lu,
|
||||||
OiaField::NotUndera { .. } => OiaFieldName::NotUndera,
|
OiaField::NotUndera { .. } => OiaFieldName::NotUndera,
|
||||||
OiaField::PrinterSession { .. } => OiaFieldName::PrinterSession,
|
// OiaField::PrinterSession { .. } => OiaFieldName::PrinterSession,
|
||||||
OiaField::ReverseInput { .. } => OiaFieldName::ReverseInput,
|
OiaField::ReverseInput { .. } => OiaFieldName::ReverseInput,
|
||||||
OiaField::ScreenTrace { .. } => OiaFieldName::ScreenTrace,
|
OiaField::ScreenTrace { .. } => OiaFieldName::ScreenTrace,
|
||||||
OiaField::Script { .. } => OiaFieldName::Script,
|
OiaField::Script { .. } => OiaFieldName::Script,
|
||||||
@@ -336,6 +328,15 @@ pub enum CountOrText {
|
|||||||
Text(String),
|
Text(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CountOrText {
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
CountOrText::Count(n) => *n,
|
||||||
|
CountOrText::Text(text) => text.chars().count(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||||
pub struct Change {
|
pub struct Change {
|
||||||
pub column: u8,
|
pub column: u8,
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ static FLAG_NAMES: &'static [(GraphicRendition, &'static str)] = &[
|
|||||||
|
|
||||||
impl Display for GraphicRendition {
|
impl Display for GraphicRendition {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
if *self == Self::empty() {
|
||||||
|
return f.write_str("default");
|
||||||
|
}
|
||||||
let flag_names = FLAG_NAMES
|
let flag_names = FLAG_NAMES
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(val, name)| self.contains(*val).then_some(*name));
|
.filter_map(|(val, name)| self.contains(*val).then_some(*name));
|
||||||
@@ -106,7 +109,7 @@ impl FromStr for GraphicRendition {
|
|||||||
.iter()
|
.iter()
|
||||||
.find(|(_, name)| *name == attr)
|
.find(|(_, name)| *name == attr)
|
||||||
.map(|x| x.0)
|
.map(|x| x.0)
|
||||||
.ok_or_else(|| format!("Invalid attr name {attr}"))
|
.ok_or_else(|| format!("Invalid GR attr name {attr}"))
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@@ -241,7 +244,7 @@ impl PackedAttr for u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn c_setbg(self, bg: Color) -> Self {
|
fn c_setbg(self, bg: Color) -> Self {
|
||||||
self & !0xF0000 | (u8::from(bg) as u32) << 20
|
self & !0xF00000 | (u8::from(bg) as u32) << 20
|
||||||
}
|
}
|
||||||
|
|
||||||
fn c_pack(fg: Color, bg: Color, gr: GraphicRendition) -> Self {
|
fn c_pack(fg: Color, bg: Color, gr: GraphicRendition) -> Self {
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
use crate::b3270::indication::{
|
use std::collections::HashMap;
|
||||||
Change, Connection, ConnectionState, CountOrText, Cursor, Erase, Oia, OiaFieldName, Row,
|
use tracing::warn;
|
||||||
RunResult, Screen, ScreenMode, Scroll, Setting, Thumb, Tls, TraceFile,
|
|
||||||
};
|
use crate::b3270::indication::{Change, ComposeType, Connection, ConnectionState, CountOrText, Cursor, Erase, OiaField, OiaFieldName, Row, RunResult, Screen, ScreenMode, Scroll, Setting, Thumb, Tls, TraceFile};
|
||||||
use crate::b3270::types::{Color, GraphicRendition, PackedAttr};
|
use crate::b3270::types::{Color, GraphicRendition, PackedAttr};
|
||||||
use crate::b3270::{Indication, InitializeIndication};
|
use crate::b3270::{Indication, InitializeIndication};
|
||||||
use std::collections::HashMap;
|
use crate::b3270::types::Color::{NeutralBlack, NeutralWhite};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
struct CharCell {
|
pub struct CharCell {
|
||||||
pub ch: char,
|
pub ch: char,
|
||||||
pub attr: u32,
|
pub attr: u32,
|
||||||
}
|
}
|
||||||
pub struct Tracker {
|
pub struct Tracker {
|
||||||
screen: Vec<Vec<CharCell>>,
|
screen: Vec<Vec<CharCell>>,
|
||||||
oia: HashMap<OiaFieldName, Oia>,
|
oia: HashMap<OiaFieldName, OiaField>,
|
||||||
screen_mode: ScreenMode,
|
screen_mode: ScreenMode,
|
||||||
erase: Erase,
|
erase: Erase,
|
||||||
thumb: Thumb,
|
thumb: Thumb,
|
||||||
@@ -26,6 +26,7 @@ pub struct Tracker {
|
|||||||
trace_file: Option<String>,
|
trace_file: Option<String>,
|
||||||
tls: Option<Tls>,
|
tls: Option<Tls>,
|
||||||
|
|
||||||
|
oia_tracker: OiaTracker,
|
||||||
// These never change, but need to be represented in an initialize message
|
// These never change, but need to be represented in an initialize message
|
||||||
static_init: Vec<InitializeIndication>,
|
static_init: Vec<InitializeIndication>,
|
||||||
}
|
}
|
||||||
@@ -55,13 +56,17 @@ impl Tracker {
|
|||||||
self.connection = conn.clone();
|
self.connection = conn.clone();
|
||||||
}
|
}
|
||||||
Indication::Erase(erase) => {
|
Indication::Erase(erase) => {
|
||||||
self.erase.logical_cols = erase.logical_cols.or(self.erase.logical_cols);
|
erase.fg = erase.fg.or(self.erase.fg).or(Some(NeutralWhite));
|
||||||
self.erase.logical_rows = erase.logical_rows.or(self.erase.logical_rows);
|
erase.bg = erase.bg.or(self.erase.bg).or(Some(NeutralBlack));
|
||||||
self.erase.fg = erase.fg.or(self.erase.fg);
|
erase.logical_rows = erase.logical_rows.or(self.erase.logical_rows).or(Some(self.screen_mode.rows));
|
||||||
self.erase.bg = erase.bg.or(self.erase.bg);
|
erase.logical_cols = erase.logical_cols.or(self.erase.logical_cols).or(Some(self.screen_mode.columns));
|
||||||
|
self.erase.logical_cols = erase.logical_cols;
|
||||||
|
self.erase.logical_rows = erase.logical_rows;
|
||||||
|
self.erase.fg = erase.fg;
|
||||||
|
self.erase.bg = erase.bg;
|
||||||
|
|
||||||
let rows = self.erase.logical_rows.unwrap_or(self.screen_mode.rows) as usize;
|
let rows = self.erase.logical_rows.unwrap() as usize;
|
||||||
let cols = self.erase.logical_cols.unwrap_or(self.screen_mode.columns) as usize;
|
let cols = self.erase.logical_cols.unwrap() as usize;
|
||||||
|
|
||||||
self.screen = vec![
|
self.screen = vec![
|
||||||
vec![
|
vec![
|
||||||
@@ -119,7 +124,8 @@ impl Tracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Indication::Oia(oia) => {
|
Indication::Oia(oia) => {
|
||||||
self.oia.insert(oia.field.field_name(), oia.clone());
|
self.oia.insert(oia.field_name(), oia.clone());
|
||||||
|
self.oia_tracker.notice(oia.clone());
|
||||||
}
|
}
|
||||||
Indication::Screen(screen) => {
|
Indication::Screen(screen) => {
|
||||||
if let Some(cursor) = screen.cursor {
|
if let Some(cursor) = screen.cursor {
|
||||||
@@ -132,19 +138,21 @@ impl Tracker {
|
|||||||
// update screen contents
|
// update screen contents
|
||||||
let cols = self.screen[row_idx].iter_mut().skip(col_idx);
|
let cols = self.screen[row_idx].iter_mut().skip(col_idx);
|
||||||
match change.change {
|
match change.change {
|
||||||
CountOrText::Count(n) => cols.take(n).for_each(|cell| {
|
CountOrText::Count(n) => {
|
||||||
let mut attr = cell.attr;
|
cols.take(n).for_each(|cell| {
|
||||||
if let Some(fg) = change.fg {
|
let mut attr = cell.attr;
|
||||||
attr = attr.c_setfg(fg);
|
if let Some(fg) = change.fg {
|
||||||
}
|
attr = attr.c_setfg(fg);
|
||||||
if let Some(bg) = change.bg {
|
}
|
||||||
attr = attr.c_setbg(bg);
|
if let Some(bg) = change.bg {
|
||||||
}
|
attr = attr.c_setbg(bg);
|
||||||
if let Some(gr) = change.gr {
|
}
|
||||||
attr = attr.c_setgr(gr);
|
if let Some(gr) = change.gr {
|
||||||
}
|
attr = attr.c_setgr(gr);
|
||||||
cell.attr = attr;
|
}
|
||||||
}),
|
cell.attr = attr;
|
||||||
|
});
|
||||||
|
},
|
||||||
CountOrText::Text(ref text) => {
|
CountOrText::Text(ref text) => {
|
||||||
cols.zip(text.chars()).for_each(|(cell, ch)| {
|
cols.zip(text.chars()).for_each(|(cell, ch)| {
|
||||||
let mut attr = cell.attr;
|
let mut attr = cell.attr;
|
||||||
@@ -283,6 +291,65 @@ impl Tracker {
|
|||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_screen(&self) -> &Vec<Vec<CharCell>> {
|
||||||
|
&self.screen
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_oia(&self) -> &HashMap<OiaFieldName, OiaField> {
|
||||||
|
&self.oia
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_cursor(&self) -> &Cursor {
|
||||||
|
&self.cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_oia_state(&self) -> &OiaTracker {
|
||||||
|
&self.oia_tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_connection(&self) -> &Connection { &self.connection }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct OiaTracker {
|
||||||
|
pub compose: Option<(ComposeType, String)>,
|
||||||
|
pub insert: bool,
|
||||||
|
pub lock: Option<String>,
|
||||||
|
/// terminal, printer
|
||||||
|
pub lu: Option<String>,
|
||||||
|
pub not_undera: bool,
|
||||||
|
pub printer_lu: Option<String>,
|
||||||
|
pub reverse_input: bool,
|
||||||
|
pub screen_trace: Option<usize>,
|
||||||
|
pub script: bool,
|
||||||
|
pub timing: Option<String>,
|
||||||
|
pub typeahead: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OiaTracker {
|
||||||
|
pub fn notice(&mut self, oia: OiaField) {
|
||||||
|
match oia {
|
||||||
|
OiaField::Compose { value: true, type_: Some(typ), char:Some(ch_str) } => {
|
||||||
|
self.compose = Some((typ, ch_str))
|
||||||
|
}
|
||||||
|
OiaField::Compose { value: false, ..} => self.compose = None,
|
||||||
|
OiaField::Compose { .. } => warn!(?oia, "Unexpected OIA compose setting"),
|
||||||
|
OiaField::Insert { value } => self.insert = value,
|
||||||
|
OiaField::Lock { value } => self.lock = value,
|
||||||
|
OiaField::Lu { value, lu } => {
|
||||||
|
self.lu = Some(value);
|
||||||
|
self.printer_lu = lu;
|
||||||
|
}
|
||||||
|
OiaField::NotUndera { value } => self.not_undera = value,
|
||||||
|
OiaField::ReverseInput { value } => self.reverse_input = value,
|
||||||
|
OiaField::ScreenTrace { value } => self.screen_trace = value,
|
||||||
|
OiaField::Script { value } => self.script = value,
|
||||||
|
OiaField::Timing { value } => self.timing = value,
|
||||||
|
OiaField::Typeahead { value } => self.typeahead = value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Tracker {
|
impl Default for Tracker {
|
||||||
@@ -326,6 +393,7 @@ impl Default for Tracker {
|
|||||||
trace_file: None,
|
trace_file: None,
|
||||||
tls: None,
|
tls: None,
|
||||||
static_init: vec![],
|
static_init: vec![],
|
||||||
|
oia_tracker: OiaTracker::default(),
|
||||||
};
|
};
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user