Skip to content

Commit ac125d3

Browse files
committed
Fix console copy/paste issue
Fixes #936
1 parent 956e68b commit ac125d3

File tree

4 files changed

+49
-60
lines changed

4 files changed

+49
-60
lines changed

libc/calls/read-nt.c

Lines changed: 46 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
1717
│ PERFORMANCE OF THIS SOFTWARE. │
1818
╚─────────────────────────────────────────────────────────────────────────────*/
19-
#include "libc/assert.h"
20-
#include "libc/atomic.h"
2119
#include "libc/calls/createfileflags.internal.h"
2220
#include "libc/calls/internal.h"
2321
#include "libc/calls/sig.internal.h"
@@ -29,14 +27,11 @@
2927
#include "libc/cosmo.h"
3028
#include "libc/errno.h"
3129
#include "libc/fmt/itoa.h"
32-
#include "libc/intrin/atomic.h"
3330
#include "libc/intrin/describeflags.internal.h"
3431
#include "libc/intrin/dll.h"
3532
#include "libc/intrin/nomultics.internal.h"
3633
#include "libc/intrin/strace.internal.h"
37-
#include "libc/intrin/weaken.h"
3834
#include "libc/macros.internal.h"
39-
#include "libc/mem/mem.h"
4035
#include "libc/nt/console.h"
4136
#include "libc/nt/createfile.h"
4237
#include "libc/nt/enum/accessmask.h"
@@ -51,6 +46,7 @@
5146
#include "libc/nt/synchronization.h"
5247
#include "libc/str/str.h"
5348
#include "libc/str/utf16.h"
49+
#include "libc/sysv/consts/limits.h"
5450
#include "libc/sysv/consts/o.h"
5551
#include "libc/sysv/consts/sicode.h"
5652
#include "libc/sysv/consts/sig.h"
@@ -134,7 +130,7 @@ struct Keystrokes {
134130
bool end_of_file;
135131
bool ohno_decckm;
136132
uint16_t utf16hs;
137-
atomic_int_fast16_t used;
133+
int16_t freekeys;
138134
int64_t cin, cot;
139135
struct Dll *list;
140136
struct Dll *line;
@@ -150,12 +146,42 @@ textwindows void __keystroke_wipe(void) {
150146
bzero(&__keystroke, sizeof(__keystroke));
151147
}
152148

149+
static textwindows void FreeKeystrokeImpl(struct Dll *key) {
150+
dll_make_first(&__keystroke.free, key);
151+
++__keystroke.freekeys;
152+
}
153+
154+
static textwindows struct Keystroke *NewKeystroke(void) {
155+
struct Dll *e = dll_first(__keystroke.free);
156+
struct Keystroke *k = KEYSTROKE_CONTAINER(e);
157+
dll_remove(&__keystroke.free, &k->elem);
158+
--__keystroke.freekeys;
159+
k->buflen = 0;
160+
return k;
161+
}
162+
163+
static textwindows void FreeKeystroke(struct Dll **list, struct Dll *key) {
164+
dll_remove(list, key);
165+
FreeKeystrokeImpl(key);
166+
}
167+
168+
static textwindows void FreeKeystrokes(struct Dll **list) {
169+
struct Dll *key;
170+
while ((key = dll_first(*list))) {
171+
FreeKeystroke(list, key);
172+
}
173+
}
174+
153175
static textwindows void OpenConsole(void) {
154176
__keystroke.vkt = kVirtualKey;
155177
__keystroke.cin = CreateFile(u"CONIN$", kNtGenericRead | kNtGenericWrite,
156178
kNtFileShareRead, 0, kNtOpenExisting, 0, 0);
157179
__keystroke.cot = CreateFile(u"CONOUT$", kNtGenericRead | kNtGenericWrite,
158180
kNtFileShareWrite, 0, kNtOpenExisting, 0, 0);
181+
for (int i = 0; i < ARRAYLEN(__keystroke.pool); ++i) {
182+
dll_init(&__keystroke.pool[i].elem);
183+
FreeKeystrokeImpl(&__keystroke.pool[i].elem);
184+
}
159185
}
160186

161187
static textwindows int AddSignal(int sig) {
@@ -413,34 +439,6 @@ static textwindows int ConvertConsoleInputToAnsi(const struct NtInputRecord *r,
413439
}
414440
}
415441

416-
static textwindows struct Keystroke *NewKeystroke(void) {
417-
struct Dll *e;
418-
struct Keystroke *k = 0;
419-
int i, n = ARRAYLEN(__keystroke.pool);
420-
if (atomic_load_explicit(&__keystroke.used, memory_order_acquire) < n &&
421-
(i = atomic_fetch_add(&__keystroke.used, 1)) < n) {
422-
k = __keystroke.pool + i;
423-
} else {
424-
if ((e = dll_first(__keystroke.free))) {
425-
k = KEYSTROKE_CONTAINER(e);
426-
dll_remove(&__keystroke.free, &k->elem);
427-
}
428-
if (!k) {
429-
if (_weaken(malloc)) {
430-
k = _weaken(malloc)(sizeof(struct Keystroke));
431-
} else {
432-
enomem();
433-
return 0;
434-
}
435-
}
436-
}
437-
if (k) {
438-
bzero(k, sizeof(*k));
439-
dll_init(&k->elem);
440-
}
441-
return k;
442-
}
443-
444442
static textwindows void WriteTty(const char *p, size_t n) {
445443
WriteFile(__keystroke.cot, p, n, 0, 0);
446444
}
@@ -479,8 +477,7 @@ static textwindows bool EraseKeystroke(void) {
479477
struct Dll *e;
480478
if ((e = dll_last(__keystroke.line))) {
481479
struct Keystroke *k = KEYSTROKE_CONTAINER(e);
482-
dll_remove(&__keystroke.line, e);
483-
dll_make_first(&__keystroke.free, e);
480+
FreeKeystroke(&__keystroke.line, e);
484481
for (int i = k->buflen; i--;) {
485482
if ((k->buf[i] & 0300) == 0200) continue; // utf-8 cont
486483
EraseCharacter();
@@ -521,11 +518,7 @@ static textwindows void IngestConsoleInputRecord(struct NtInputRecord *r) {
521518
}
522519

523520
// allocate object to hold keystroke
524-
struct Keystroke *k;
525-
if (!(k = NewKeystroke())) {
526-
STRACE("out of keystroke memory");
527-
return;
528-
}
521+
struct Keystroke *k = NewKeystroke();
529522
memcpy(k->buf, buf, sizeof(k->buf));
530523
k->buflen = len;
531524

@@ -541,11 +534,11 @@ static textwindows void IngestConsoleInputRecord(struct NtInputRecord *r) {
541534
} else {
542535
dll_make_last(&__keystroke.line, &k->elem);
543536

544-
// handle enter in canonical mode
545-
if (len == 1 && buf[0] &&
546-
((buf[0] & 255) == '\n' || //
547-
(buf[0] & 255) == __ttyconf.veol || //
548-
(buf[0] & 255) == __ttyconf.veol2)) {
537+
// flush canonical mode line if oom or enter
538+
if (!__keystroke.freekeys || (len == 1 && buf[0] &&
539+
((buf[0] & 255) == '\n' || //
540+
(buf[0] & 255) == __ttyconf.veol || //
541+
(buf[0] & 255) == __ttyconf.veol2))) {
549542
dll_make_last(&__keystroke.list, __keystroke.line);
550543
__keystroke.line = 0;
551544
}
@@ -556,12 +549,13 @@ static textwindows void IngestConsoleInput(void) {
556549
uint32_t i, n;
557550
struct NtInputRecord records[16];
558551
for (;;) {
552+
if (!__keystroke.freekeys) return;
559553
if (__keystroke.end_of_file) return;
560554
if (!GetNumberOfConsoleInputEvents(__keystroke.cin, &n)) {
561555
goto UnexpectedEof;
562556
}
563557
if (!n) return;
564-
n = MIN(ARRAYLEN(records), n);
558+
n = MIN(__keystroke.freekeys, MIN(ARRAYLEN(records), n));
565559
if (!ReadConsoleInput(__keystroke.cin, records, n, &n)) {
566560
goto UnexpectedEof;
567561
}
@@ -576,19 +570,15 @@ static textwindows void IngestConsoleInput(void) {
576570

577571
// Discards all unread stdin bytes.
578572
textwindows int FlushConsoleInputBytes(void) {
579-
int rc;
580573
BLOCK_SIGNALS;
581574
InitConsole();
582575
LockKeystrokes();
583576
FlushConsoleInputBuffer(__keystroke.cin);
584-
dll_make_first(&__keystroke.free, __keystroke.list);
585-
__keystroke.list = 0;
586-
dll_make_first(&__keystroke.free, __keystroke.line);
587-
__keystroke.line = 0;
588-
rc = 0;
577+
FreeKeystrokes(&__keystroke.list);
578+
FreeKeystrokes(&__keystroke.line);
589579
UnlockKeystrokes();
590580
ALLOW_SIGNALS;
591-
return rc;
581+
return 0;
592582
}
593583

594584
// Returns number of stdin bytes that may be read without blocking.
@@ -700,11 +690,10 @@ static textwindows bool DigestConsoleInput(char *data, size_t size, int *rc) {
700690
}
701691
if (remain) {
702692
memmove(k->buf, k->buf + got, remain);
693+
k->buflen = remain;
703694
} else {
704-
dll_remove(&__keystroke.list, e);
705-
dll_make_first(&__keystroke.free, e);
695+
FreeKeystroke(&__keystroke.list, e);
706696
}
707-
k->buflen = remain;
708697
if ((__ttyconf.magic & kTtyUncanon) && toto >= __ttyconf.vmin) {
709698
break;
710699
}

libc/calls/write-nt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static textwindows ssize_t sys_write_nt_impl(int fd, void *data, size_t size,
5959
}
6060

6161
// intercept ansi tty configuration sequences
62-
if (isconsole && _weaken(InterceptTerminalCommands)) {
62+
if (isconsole && _weaken(GetConsoleOutputHandle)) {
6363
_weaken(InterceptTerminalCommands)(data, size);
6464
}
6565

libc/sysv/consts.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,7 @@ syscon mount MNT_SNAPSHOT 0 0 0x40000000 0x40000000 0x01000000 0 0
10441044
# limits
10451045
#
10461046
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
1047-
syscon limits PIPE_BUF 4096 4096 512 512 512 512 512 512 # bsd consensus
1047+
syscon limits PIPE_BUF 4096 4096 512 512 512 512 512 4096 # bsd consensus
10481048
syscon limits NGROUPS_MAX 65536 65536 16 16 1023 16 16 0 #
10491049
syscon limits LINK_MAX 127 127 32767 32767 32767 32767 32767 64 # freebsd/windows are educated guesses
10501050
syscon limits MAX_CANON 255 255 1024 1024 255 255 255 255 # windows is guessed

libc/sysv/consts/PIPE_BUF.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#include "libc/sysv/consts/syscon.internal.h"
2-
.syscon limits,PIPE_BUF,4096,4096,512,512,512,512,512,512
2+
.syscon limits,PIPE_BUF,4096,4096,512,512,512,512,512,4096

0 commit comments

Comments
 (0)