Skip to content

Commit

Permalink
Turn ESC+'[' into a CSI character
Browse files Browse the repository at this point in the history
This avoids the annoying behavior where we're on the command line,
waiting for an ESC, and any control character sequence ends up finishing
the command line and eating the first ESC.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
torvalds committed Jun 7, 2008
1 parent 686a9e7 commit c2a7e41
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 34 deletions.
3 changes: 3 additions & 0 deletions input.c
Expand Up @@ -338,11 +338,14 @@ int getcmd(void)
#if VT220
proc_metac:
#endif
if (c == 128+27) /* CSI */
goto handle_CSI;
/* process META prefix */
if (c == (CONTROL | '[')) {
c = get1key();
#if VT220
if (c == '[' || c == 'O') { /* CSI P.K. */
handle_CSI:

This comment has been minimized.

Copy link
@alexalkis

alexalkis Jul 27, 2016

Yeah, cool and all, except the goto is outside the #if VT220 and the label in inside the #if VT220 and that looks like a bug to me! :P

(breaks compilation on my puny attempt to cross-compile this for Amiga)

c = get1key();
if (c >= 'A' && c <= 'D')
return (SPEC | c | cmask);
Expand Down
89 changes: 55 additions & 34 deletions posix.c
Expand Up @@ -168,34 +168,64 @@ void ttflush(void)
*/
int ttgetc(void)
{
static unsigned char pending;
static unsigned char buffer[32];
static int pending;
unsigned char c, second;
int n;
int count;

count = pending;
if (!count) {
count = read(0, buffer, sizeof(buffer));
if (count <= 0)
return 0;
pending = count;
}

c = buffer[0];
if (c >= 32 && c < 128)
goto done;

/* Special character - try to fill buffer */
if (count == 1) {
int n;
ntermios.c_cc[VMIN] = 0;
ntermios.c_cc[VTIME] = 1; /* A .1 second lag */
tcsetattr(0, TCSANOW, &ntermios);

n = read(0, buffer + count, sizeof(buffer) - count);

/* Undo timeout */
ntermios.c_cc[VMIN] = 1;
ntermios.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &ntermios);

if (pending) {
c = pending;
pending = 0;
return c;
if (n <= 0)
goto done;
pending += n;
}
second = buffer[1];

n = read(0, &c, 1);
if (n != 1)
return 0;
/* Turn ESC+'[' into CSI */
if (c == 27 && second == '[') {
pending -= 2;
memmove(buffer, buffer+2, pending);
return 128+27;
}

if (!utf8_mode())
return c;
goto done;

/* Normal 7-bit? */
if (!(c & 0x80))
return c;
goto done;

/*
* Unexpected UTF-8 continuation character? Maybe
* we're in non-UTF mode, or maybe it's a control
* character.. Regardless, just pass it on.
*/
if (!(c & 0x40))
return c;
goto done;

/*
* Multi-byte sequences.. Right now we only
Expand All @@ -204,33 +234,24 @@ int ttgetc(void)
* anything else..
*/
if (c & 0x3c)
return c;
goto done;

if ((second & 0xc0) != 0x80)
goto done;

/*
* Two-byte sequence representing 0x80-0xff.. We want
* to do this read with a timeout.
* Ok, it's a two-byte UTF-8 character that can be represented
* as a single-byte Latin1 character!
*/
ntermios.c_cc[VMIN] = 1;
ntermios.c_cc[VTIME] = 10; /* 1 second */
tcsetattr(0, TCSANOW, &ntermios);

n = read(0, &second, 1);

/* Undo timeout */
ntermios.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &ntermios);

if (n != 1)
return c;

if ((second & 0xc0) != 0x80) {
pending = second;
return c;
}

c = (c << 6) | (second & 0x3f);
pending -= 2;
memmove(buffer, buffer+2, pending);

return c;

/* Ok, real UTF-8 character */
done:
pending--;
memmove(buffer, buffer+1, pending);
return c;
}

Expand Down

0 comments on commit c2a7e41

Please sign in to comment.