mirror of
https://github.com/rfivet/uemacs.git
synced 2024-11-19 19:15:55 -05:00
e8f984a1b0
This is disgusting. And quite frankly, it's debatable whether this will ever work. The "line" structure is still just an array of characters, so that has to work with utf-8. But the 'struct video' thing is what represents the actual screen rectangle, and is fixed-size by the size of the screen. So making it contain actual 32-bit unicode characters *may* make sense. Right now we translate things the same way we always used to, though, so utf-8 in 'struct line' will not be translated to the proper unicode array, but to the bytes of the utf-8 representation. So this really doesn't improve anything per se yet, just expands the memory use of the video array. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
284 lines
6.6 KiB
C
284 lines
6.6 KiB
C
/* posix.c
|
|
*
|
|
* The functions in this file negotiate with the operating system for
|
|
* characters, and write characters in a barely buffered fashion on the
|
|
* display. All operating systems.
|
|
*
|
|
* modified by Petri Kutvonen
|
|
*
|
|
* based on termio.c, with all the old cruft removed, and
|
|
* fixed for termios rather than the old termio.. Linus Torvalds
|
|
*/
|
|
|
|
#ifdef POSIX
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
|
|
#include "estruct.h"
|
|
#include "edef.h"
|
|
#include "efunc.h"
|
|
|
|
/* Since Mac OS X's termios.h doesn't have the following 2 macros, define them.
|
|
*/
|
|
#if defined(SYSV) && (defined(_DARWIN_C_SOURCE) || defined(_FREEBSD_C_SOURCE))
|
|
#define OLCUC 0000002
|
|
#define XCASE 0000004
|
|
#endif
|
|
|
|
/*
|
|
* NOTE NOTE NOTE!
|
|
*
|
|
* Uemacs is currently very much byte-oriented, and not at all UTF8-aware
|
|
* interally. However, this allows it to understand a _terminal_ that is
|
|
* in utf-8 mode, and will turn input into the 8-bit subset, and will turn
|
|
* things back into UTF8 on output.
|
|
*
|
|
* Do _not_ confuse this with the notion of actually being able to edit
|
|
* UTF-8 file _contents_. That's a totally different thing.
|
|
*/
|
|
#define utf8_mode() \
|
|
(curwp && curwp->w_bufp && (curwp->w_bufp->b_mode & MDUTF8))
|
|
|
|
static int kbdflgs; /* saved keyboard fd flags */
|
|
static int kbdpoll; /* in O_NDELAY mode */
|
|
|
|
static struct termios otermios; /* original terminal characteristics */
|
|
static struct termios ntermios; /* charactoristics to use inside */
|
|
|
|
#define TBUFSIZ 128
|
|
static char tobuf[TBUFSIZ]; /* terminal output buffer */
|
|
|
|
|
|
/*
|
|
* This function is called once to set up the terminal device streams.
|
|
* On VMS, it translates TT until it finds the terminal, then assigns
|
|
* a channel to it and sets it raw. On CPM it is a no-op.
|
|
*/
|
|
void ttopen(void)
|
|
{
|
|
tcgetattr(0, &otermios); /* save old settings */
|
|
|
|
/*
|
|
* base new settings on old ones - don't change things
|
|
* we don't know about
|
|
*/
|
|
ntermios = otermios;
|
|
|
|
/* raw CR/NL etc input handling, but keep ISTRIP if we're on a 7-bit line */
|
|
ntermios.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK
|
|
| INPCK | INLCR | IGNCR | ICRNL);
|
|
|
|
/* raw CR/NR etc output handling */
|
|
ntermios.c_oflag &=
|
|
~(OPOST | ONLCR | OLCUC | OCRNL | ONOCR | ONLRET);
|
|
|
|
/* No signal handling, no echo etc */
|
|
ntermios.c_lflag &= ~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK
|
|
| ECHONL | NOFLSH | TOSTOP | ECHOCTL |
|
|
ECHOPRT | ECHOKE | FLUSHO | PENDIN | IEXTEN);
|
|
|
|
/* one character, no timeout */
|
|
ntermios.c_cc[VMIN] = 1;
|
|
ntermios.c_cc[VTIME] = 0;
|
|
tcsetattr(0, TCSADRAIN, &ntermios); /* and activate them */
|
|
|
|
/*
|
|
* provide a smaller terminal output buffer so that
|
|
* the type ahead detection works better (more often)
|
|
*/
|
|
setbuffer(stdout, &tobuf[0], TBUFSIZ);
|
|
|
|
kbdflgs = fcntl(0, F_GETFL, 0);
|
|
kbdpoll = FALSE;
|
|
|
|
/* on all screens we are not sure of the initial position
|
|
of the cursor */
|
|
ttrow = 999;
|
|
ttcol = 999;
|
|
}
|
|
|
|
/*
|
|
* This function gets called just before we go back home to the command
|
|
* interpreter. On VMS it puts the terminal back in a reasonable state.
|
|
* Another no-operation on CPM.
|
|
*/
|
|
void ttclose(void)
|
|
{
|
|
tcsetattr(0, TCSADRAIN, &otermios); /* restore terminal settings */
|
|
}
|
|
|
|
/*
|
|
* Write a character to the display. On VMS, terminal output is buffered, and
|
|
* we just put the characters in the big array, after checking for overflow.
|
|
* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
|
|
* MS-DOS (use the very very raw console output routine).
|
|
*/
|
|
int ttputc(int c)
|
|
{
|
|
unsigned char utf8[6], *p = utf8+5;
|
|
int bytes = 1;
|
|
|
|
if (c < 0)
|
|
return 0;
|
|
*p = c;
|
|
if (c > 0x7f) {
|
|
int prefix = 0x40;
|
|
do {
|
|
*p = 0x80 + (c & 0x3f);
|
|
--p;
|
|
bytes++;
|
|
prefix >>= 1;
|
|
c >>= 6;
|
|
} while (c > prefix);
|
|
*p = c - 2*prefix;
|
|
}
|
|
fwrite(p, 1, bytes, stdout);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Flush terminal buffer. Does real work where the terminal output is buffered
|
|
* up. A no-operation on systems where byte at a time terminal I/O is done.
|
|
*/
|
|
void ttflush(void)
|
|
{
|
|
/*
|
|
* Add some terminal output success checking, sometimes an orphaned
|
|
* process may be left looping on SunOS 4.1.
|
|
*
|
|
* How to recover here, or is it best just to exit and lose
|
|
* everything?
|
|
*
|
|
* jph, 8-Oct-1993
|
|
* Jani Jaakkola suggested using select after EAGAIN but let's just wait a bit
|
|
*
|
|
*/
|
|
int status;
|
|
|
|
status = fflush(stdout);
|
|
while (status < 0 && errno == EAGAIN) {
|
|
sleep(1);
|
|
status = fflush(stdout);
|
|
}
|
|
if (status < 0)
|
|
exit(15);
|
|
}
|
|
|
|
/*
|
|
* Read a character from the terminal, performing no editing and doing no echo
|
|
* at all. More complex in VMS that almost anyplace else, which figures. Very
|
|
* simple on CPM, because the system can do exactly what you want.
|
|
*/
|
|
int ttgetc(void)
|
|
{
|
|
static unsigned char buffer[32];
|
|
static int pending;
|
|
unsigned char c, second;
|
|
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 (n <= 0)
|
|
goto done;
|
|
pending += n;
|
|
}
|
|
second = buffer[1];
|
|
|
|
/* Turn ESC+'[' into CSI */
|
|
if (c == 27 && second == '[') {
|
|
pending -= 2;
|
|
memmove(buffer, buffer+2, pending);
|
|
return 128+27;
|
|
}
|
|
|
|
if (!utf8_mode())
|
|
goto done;
|
|
|
|
/* Normal 7-bit? */
|
|
if (!(c & 0x80))
|
|
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))
|
|
goto done;
|
|
|
|
/*
|
|
* Multi-byte sequences.. Right now we only
|
|
* want to get characters that can be represented
|
|
* in a single byte, so we're not interested in
|
|
* anything else..
|
|
*/
|
|
if (c & 0x3c)
|
|
goto done;
|
|
|
|
if ((second & 0xc0) != 0x80)
|
|
goto done;
|
|
|
|
/*
|
|
* Ok, it's a two-byte UTF-8 character that can be represented
|
|
* as a single-byte Latin1 character!
|
|
*/
|
|
c = (c << 6) | (second & 0x3f);
|
|
pending -= 2;
|
|
memmove(buffer, buffer+2, pending);
|
|
|
|
return c;
|
|
|
|
done:
|
|
pending--;
|
|
memmove(buffer, buffer+1, pending);
|
|
return c;
|
|
}
|
|
|
|
/* typahead: Check to see if any characters are already in the
|
|
keyboard buffer
|
|
*/
|
|
|
|
int typahead(void)
|
|
{
|
|
int x; /* holds # of pending chars */
|
|
|
|
#ifdef FIONREAD
|
|
if (ioctl(0, FIONREAD, &x) < 0)
|
|
x = 0;
|
|
#else
|
|
x = 0;
|
|
#endif
|
|
return x;
|
|
}
|
|
|
|
#endif /* POSIX */
|