-
Notifications
You must be signed in to change notification settings - Fork 7
/
posix.c
253 lines (208 loc) · 5.64 KB
/
posix.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/* posix.c -- posix implementation of termio.h */
#include "termio.h"
#include "defines.h" /* POSIX */
#ifdef POSIX
/* 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
*/
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include "retcode.h"
#include "utf8.h"
int ttrow = -1 ; /* Row location of HW cursor */
int ttcol = -1 ; /* Column location of HW cursor */
/* Define missing macroes for BSD and CYGWIN environment */
#if BSD
# ifndef OLCUC
# define OLCUC 0000002
# endif
# ifndef XCASE
# define XCASE 0000004
# endif
#endif
#ifdef __CYGWIN__ /* gcc predefined (see cpp -dM) */
#define XCASE 0
#define ECHOPRT 0
#define PENDIN 0
#endif
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 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
| IXON | IXOFF | IXANY
| 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 = ttcol = -1 ;
}
/*
* This function gets called just before we go back home to the command
* interpreter.
* Another no-operation on CPM.
*/
void ttclose(void)
{
tcsetattr(0, TCSADRAIN, &otermios); /* restore terminal settings */
}
/*
* Write a character to the display.
* 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( unicode_t c) {
char utf8[6];
int bytes;
bytes = unicode_to_utf8(c, utf8);
fwrite(utf8, 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.
*/
int ttgetc( void) {
static char buffer[ 32] ;
static int pending ;
unicode_t c ;
int count = pending ;
if( !count) {
count = read( 0, buffer, sizeof( buffer)) ;
if( count <= 0)
return 0 ;
pending = count ;
}
int bytes = 1 ;
c = (unsigned char) buffer[ 0] ;
#if 0 // temporary fix for wsl
if (c >= 32 && c < 128)
goto done;
/*
* Lazy. We don't bother calculating the exact
* expected length. We want at least two characters
* for the special character case (ESC+[) and for
* the normal short UTF8 sequence that starts with
* the 110xxxxx pattern.
*
* But if we have any of the other patterns, just
* try to get more characters. At worst, that will
* just result in a barely perceptible 0.1 second
* delay for some *very* unusual utf8 character
* input.
*/
int expected = 2;
if ((c & 0xe0) == 0xe0)
expected = 6;
/* Special character - try to fill buffer */
if (count < expected) {
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)
pending += n;
}
if (pending > 1) {
unsigned char second = buffer[1];
/* Turn ESC+'[' into CSI */
if (c == 27 && second == '[') {
bytes = 2;
c = 128+27;
goto done;
}
}
bytes = utf8_to_unicode(buffer, 0, pending, &c);
done:
#endif
pending -= bytes ;
memmove( buffer, buffer + bytes, 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
/* end of posix.c */