Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ written on the kernel's own calls.

```toml
[dependencies]
openkal = "0.13.0"
openkal = "0.14.0"

[target.'cfg(os = "macos")'.dependencies]
openkal-macos = "0.10.0"
openkal-macos = "0.11.0"
```

Its purpose is as much to test the specification as to be used. A specification
Expand Down
4 changes: 2 additions & 2 deletions mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
namespace = "mcpplibs"
name = "openkal-macos"
version = "0.10.0"
version = "0.11.0"
description = "An implementation of openkal for macOS, written on the kernel's own calls. Its purpose is as much to test the specification as to be used."
license = "Apache-2.0"

Expand All @@ -18,7 +18,7 @@ authors = ["mcpplibs"]
repo = "https://github.com/mcpplibs/openkal-macos"

[dependencies]
openkal = "0.13.0"
openkal = "0.14.0"

[build]
# The flags are attached to this package's own sources rather than to the whole
Expand Down
46 changes: 44 additions & 2 deletions src/terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,29 @@ constexpr okm_long tiocgeta = 0x40000000L | (72L << 16) | ('t' << 8) | 19;
constexpr okm_long tiocseta = 0x80000000L | (72L << 16) | ('t' << 8) | 20;
constexpr okm_long tiocgwinsz = 0x40000000L | (8L << 16) | ('t' << 8) | 104;

// Positions within lflag. This kernel's values, which are not the other's.
// Positions within lflag and iflag, and the two entries of cc that decide how
// long a read waits. This kernel's values, which are not the other's.
constexpr okm_ulong t_echo = 0x00000008u;
constexpr okm_ulong t_isig = 0x00000080u;
constexpr okm_ulong t_icanon = 0x00000100u;

constexpr okm_ulong t_iexten = 0x00000400u;
constexpr okm_ulong t_ixon = 0x00000200u; // iflag
constexpr unsigned v_min = 16, v_time = 17;

// KAL_TERM_PASS_CONTROL IS READ FROM THREE FLAGS AND NOT FROM ISIG. The
// position states that the environment reserves NO keystroke, so it is set only
// where every mechanism by which this kernel reserves one is off: ISIG for the
// interrupt and its neighbours, IXON for the pair that stops and starts output,
// IEXTEN for the one that takes the next keystroke literally. A terminal upon
// which some of them had been released reads as clear and is restored to the
// set this kernel ordinarily reserves, which is the cost the specification
// records beside the position.
kal_uintptr mode_of(const oktermios& t) {
kal_uintptr m = 0;
if ((t.lflag & t_icanon) != 0) m |= KAL_TERM_LINE_EDIT;
if ((t.lflag & t_echo) != 0) m |= KAL_TERM_ECHO;
if ((t.lflag & (t_isig | t_iexten)) == 0 &&
(t.iflag & t_ixon) == 0) m |= KAL_TERM_PASS_CONTROL;
return m;
}

Expand Down Expand Up @@ -81,12 +96,39 @@ int kal_terminal_set_mode(kal_stream s, kal_uintptr mode) {
oktermios t{};
const int rc = get_termios(s, t);
if (rc != kal_ok) return rc;
const kal_uintptr in_effect = mode_of(t);

if ((mode & KAL_TERM_LINE_EDIT) != 0) t.lflag |= t_icanon;
else t.lflag &= ~t_icanon;
if ((mode & KAL_TERM_ECHO) != 0) t.lflag |= t_echo;
else t.lflag &= ~t_echo;

// A POSITION WHOSE REQUESTED VALUE IS THE ONE IN EFFECT IS NOT WRITTEN.
// This position stands for three of the kernel's flags, so establishing it
// again would settle two mechanisms the caller never asked about: a user
// who had released the keystroke that stops output keeps it released while
// a program turns the echo off and back on.
if (((mode ^ in_effect) & KAL_TERM_PASS_CONTROL) != 0) {
if ((mode & KAL_TERM_PASS_CONTROL) != 0) {
t.lflag &= ~(t_isig | t_iexten);
t.iflag &= ~t_ixon;
} else {
t.lflag |= (t_isig | t_iexten);
t.iflag |= t_ixon;
}
}

// AND A MODE IS NOT A WAY TO END THE INPUT. With line assembly off, how
// long a read waits is decided by VMIN and VTIME rather than by a newline,
// and a terminal left at VMIN=0 by whatever ran before makes
// `kal_stream_read' report zero --- which clause 7.4 says denotes the end
// of the input. A caller that wants a read which gives up asks
// `kal_timeout_read' for one.
if ((mode & KAL_TERM_LINE_EDIT) == 0) {
t.cc[v_min] = 1;
t.cc[v_time] = 0;
}

// A position this implementation does not distinguish is ignored rather than
// refused, which clause 6.2 requires: a program compiled against a later
// revision sets a position this build has never heard of.
Expand Down
Loading