mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 07:18:30 +00:00
Get Fat Emacs working in Windows Console
This commit is contained in:
parent
bf835de612
commit
7100b1cf91
34 changed files with 479 additions and 168 deletions
|
@ -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__ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue