Get Fat Emacs working in Windows Console

This commit is contained in:
Justine Tunney 2023-08-18 04:55:57 -07:00
parent bf835de612
commit 7100b1cf91
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
34 changed files with 479 additions and 168 deletions

View file

@ -26,6 +26,7 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/calls/wincrash.internal.h"
#include "libc/errno.h"
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/filetype.h"
@ -40,23 +41,63 @@
#include "libc/nt/thread.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
#ifdef __x86_64__
enum Action {
DO_NOTHING,
DO_RESTART,
DO_EINTR,
};
static textwindows void sys_read_nt_abort(int64_t handle,
struct NtOverlapped *overlapped) {
unassert(CancelIoEx(handle, overlapped) ||
GetLastError() == kNtErrorNotFound);
}
static textwindows void MungeTerminalInput(struct Fd *fd, char *p, size_t n) {
if (!(fd->ttymagic & kFdTtyNoCr2Nl)) {
size_t i;
for (i = 0; i < n; ++i) {
static textwindows int MungeTerminalInput(char *p, uint32_t *n) {
size_t i, j;
if (!(__ttymagic & kFdTtyNoCr2Nl)) {
for (i = 0; i < *n; ++i) {
if (p[i] == '\r') {
p[i] = '\n';
}
}
}
if (!(__ttymagic & kFdTtyNoIsigs)) {
bool delivered = false;
bool got_vintr = false;
bool got_vquit = false;
for (j = i = 0; i < *n; ++i) {
if (__vintr != _POSIX_VDISABLE && p[i] == __vintr) {
got_vintr = true;
} else if (__vquit != _POSIX_VDISABLE && p[i] == __vquit) {
got_vquit = true;
} else {
p[j++] = p[i];
}
}
if (got_vintr) {
delivered |= __sig_handle(0, SIGINT, SI_KERNEL, 0);
}
if (got_vquit) {
delivered |= __sig_handle(0, SIGQUIT, SI_KERNEL, 0);
}
if (*n && !j) {
if (delivered) {
return DO_EINTR;
} else {
return DO_RESTART;
}
}
*n = j;
}
return DO_NOTHING;
}
// Manual CMD.EXE echoing for when !ICANON && ECHO is the case.
@ -67,7 +108,7 @@ static textwindows void EchoTerminalInput(struct Fd *fd, char *p, size_t n) {
} else {
hOutput = g_fds.p[1].handle;
}
if (fd->ttymagic & kFdTtyEchoRaw) {
if (__ttymagic & kFdTtyEchoRaw) {
WriteFile(hOutput, p, n, 0, 0);
} else {
size_t i;
@ -93,6 +134,7 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
int filetype;
int64_t handle;
int abort_errno = EAGAIN;
StartOver:
size = MIN(size, 0x7ffff000);
handle = __resolve_stdin_handle(fd->handle);
filetype = GetFileType(handle);
@ -107,9 +149,9 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
// since for overlapped i/o, we always use GetOverlappedResult
ok = ReadFile(handle, data, size, 0, &overlap);
if (!ok && GetLastError() == kNtErrorIoPending) {
// i/o operation is in flight; blocking is unavoidable
// if we're in non-blocking mode, then immediately abort
// if an interrupt is pending, then abort before waiting
// the i/o operation is in flight; blocking is unavoidable
// if we're in a non-blocking mode, then immediately abort
// if an interrupt is pending then we abort before waiting
// otherwise wait for i/o periodically checking interrupts
if (fd->flags & O_NONBLOCK) {
sys_read_nt_abort(handle, &overlap);
@ -161,11 +203,23 @@ static textwindows ssize_t sys_read_nt_impl(struct Fd *fd, void *data,
unassert(SetFilePointerEx(handle, position, 0, SEEK_SET));
}
if (ok) {
if (fd->ttymagic & kFdTtyMunging) {
MungeTerminalInput(fd, data, got);
}
if (fd->ttymagic & kFdTtyEchoing) {
EchoTerminalInput(fd, data, got);
if (g_fds.stdin.handle ? fd->handle == g_fds.stdin.handle
: fd->handle == g_fds.p[0].handle) {
if (__ttymagic & kFdTtyMunging) {
switch (MungeTerminalInput(data, &got)) {
case DO_NOTHING:
break;
case DO_RESTART:
goto StartOver;
case DO_EINTR:
return eintr();
default:
__builtin_unreachable();
}
}
if (__ttymagic & kFdTtyEchoing) {
EchoTerminalInput(fd, data, got);
}
}
return got;
}
@ -207,3 +261,5 @@ textwindows ssize_t sys_read_nt(struct Fd *fd, const struct iovec *iov,
return sys_read_nt_impl(fd, NULL, 0, opt_offset);
}
}
#endif /* __x86_64__ */