source separated to alot of files (don't know if it's better this way, but...)
[k8sterm.git] / src / ttyrw.c
blob17972c5cf35e36bbc5221f8c920352f456671c82
1 ////////////////////////////////////////////////////////////////////////////////
2 // tty r/w
3 static int ttycanread (void) {
4 for (;;) {
5 fd_set rfd;
6 struct timeval timeout = {0};
7 //
8 if (term->dead || term->cmdfd < 0) return 0;
9 FD_ZERO(&rfd);
10 FD_SET(term->cmdfd, &rfd);
11 if (select(term->cmdfd+1, &rfd, NULL, NULL, &timeout) < 0) {
12 if (errno == EINTR) continue;
13 die("select failed: %s", SERRNO);
15 if (FD_ISSET(term->cmdfd, &rfd)) return 1;
16 break;
18 return 0;
22 static int ttycanwrite (void) {
23 for (;;) {
24 fd_set wfd;
25 struct timeval timeout = {0};
27 if (term->dead || term->cmdfd < 0) return 0;
28 FD_ZERO(&wfd);
29 FD_SET(term->cmdfd, &wfd);
30 if (select(term->cmdfd+1, NULL, &wfd, NULL, &timeout) < 0) {
31 if (errno == EINTR) continue;
32 die("select failed: %s", SERRNO);
34 if (FD_ISSET(term->cmdfd, &wfd)) return 1;
35 break;
37 return 0;
41 #ifdef DUMP_IO
42 static void wrstr (const char *s, int len) {
43 if (s == NULL) return;
44 while (len-- > 0) {
45 unsigned char c = (unsigned char)(*s++);
47 if (c < 32) fprintf(stderr, "{%u}", c); else fwrite(&c, 1, 1, stderr);
50 #endif
53 static void ttyread (void) {
54 char *ptr;
55 int left;
57 /* append read bytes to unprocessed bytes */
58 if (term == NULL || term->dead || term->cmdfd < 0) return;
59 #ifdef DUMP_PROG_OUTPUT
60 term->xobuflen = term->obuflen;
61 #endif
62 left = OBUFSIZ-term->obuflen;
63 //dlogf("0: ttyread before: free=%d, used=%d", left, term->obuflen);
64 while (left > 0 && ttycanread()) {
65 int ret;
67 //if ((ret = read(term->cmdfd, term->obuf+term->obuflen, 1)) < 0) die("Couldn't read from shell: %s", SERRNO);
68 if ((ret = read(term->cmdfd, term->obuf+term->obuflen, left)) < 0) {
69 //fprintf(stderr, "Warning: couldn't read from tty #%d: %s\n", termidx, SERRNO);
70 break;
72 term->obuflen += ret;
73 left -= ret;
75 //dlogf("1: ttyread after: free=%d, used=%d", left, term->obuflen);
76 /* process every complete utf8 char */
77 #ifdef DUMP_PROG_OUTPUT
79 FILE *fo = fopen("zlogo.log", "ab");
80 if (fo) {
81 fwrite(term->obuf+term->xobuflen, term->obuflen-term->xobuflen, 1, fo);
82 fclose(fo);
85 #endif
86 ptr = term->obuf;
87 if (term->needConv) {
88 // need conversion from locale to utf-8
89 //fprintf(stderr, "buf: %d bytes\n", term->obuflen);
90 while (term->obuflen > 0) {
91 char obuf[UTF_SIZ+1];
92 int len;
94 len = loc2utf(obuf, ptr, 1);
95 #ifdef DUMP_IO_READ
97 fprintf(stderr, "rdc: [");
98 wrstr(ptr, 1);
99 fprintf(stderr, "] --> [");
100 wrstr(obuf, len);
101 fprintf(stderr, "]\n");
102 fflush(stderr);
104 #endif
105 if (len > 0) {
106 obuf[len] = 0;
107 tputc(obuf);
109 ++ptr;
110 --term->obuflen;
112 term->obuflen = 0;
113 } else {
114 // don't do any conversion
115 while (term->obuflen >= UTF_SIZ || isfullutf8(ptr, term->obuflen)) {
116 uint32 utf8c;
117 char s[UTF_SIZ+1];
118 int charsize = utf8decode(&utf8c, ptr);
119 int len;
121 len = utf8encode(s, utf8c);
122 #ifdef DUMP_IO_READ
124 fprintf(stderr, "rdx: [");
125 wrstr(s, len);
126 fprintf(stderr, "]\n");
127 fflush(stderr);
129 #endif
130 if (len > 0) {
131 s[len] = 0;
132 tputc(s);
134 ptr += charsize;
135 term->obuflen -= charsize;
137 //dlogf("2: ttyread afterproc: used=%d", term->obuflen);
139 /* keep any uncomplete utf8 char for the next call */
140 if (term->obuflen > 0) memmove(term->obuf, ptr, term->obuflen);
144 static void ttyflushwrbuf (void) {
145 if (term == NULL || term->dead || term->cmdfd < 0) return;
146 if (term->wrbufpos >= term->wrbufused) {
147 term->wrbufpos = term->wrbufused = 0;
148 return;
150 //dlogf("0: ttyflushwrbuf before: towrite=%d", term->wrbufused-term->wrbufpos);
151 while (term->wrbufpos < term->wrbufused && ttycanwrite()) {
152 int ret;
154 if ((ret = write(term->cmdfd, term->wrbuf+term->wrbufpos, term->wrbufused-term->wrbufpos)) == -1) {
155 //fprintf(stderr, "Warning: write error on tty #%d: %s\n", termidx, SERRNO);
157 term->wrbufpos += ret;
159 if (term->wrbufpos > 0) {
160 int left = term->wrbufused-term->wrbufpos;
162 if (left < 1) {
163 // write buffer is empty
164 term->wrbufpos = term->wrbufused = 0;
165 } else {
166 memmove(term->wrbuf, term->wrbuf+term->wrbufpos, left);
167 term->wrbufpos = 0;
168 term->wrbufused = left;
171 //dlogf("1: ttyflushwrbuf after: towrite=%d", term->wrbufused-term->wrbufpos);
175 // convert char to locale and write it
176 static void ttywriterawchar (const char *s, int len, int noenc) {
177 char loc[16];
178 int clen;
180 if (s == NULL || len < 1) return;
181 if (!noenc) {
182 if (term->needConv) {
183 if ((clen = utf2loc(loc, s, len)) < 1) return;
184 } else {
185 if ((clen = utf8size(s)) < 1) return;
186 memmove(loc, s, clen);
188 } else {
189 memmove(loc, s, (clen = len));
191 #ifdef DUMP_IO_WRITE
193 fprintf(stderr, "wrc: [");
194 wrstr(s, len);
195 fprintf(stderr, "] --> [");
196 wrstr(loc, clen);
197 fprintf(stderr, "]\n");
198 fflush(stderr);
200 #endif
202 while (term->wrbufused+clen >= term->wrbufsize) {
203 //FIXME: make write buffer dynamic?
204 // force write at least one char
205 //dlogf("ttywrite: forced write");
206 if (write(term->cmdfd, term->wrbuf+term->wrbufpos, 1) == -1) {
207 //fprintf(stderr, "Warning: write error on tty #%d: %s\n", termidx, SERRNO);
208 } else {
209 ++term->wrbufpos;
211 ttyflushwrbuf(); // make room for char
213 memcpy(term->wrbuf+term->wrbufused, loc, clen);
214 term->wrbufused += clen;
218 static void ttywritenoenc (const char *s, size_t n) {
219 if (n > 0) {
220 term->ubufpos = 0; // discard possible utf-8 char
221 while (n-- > 0) ttywriterawchar(s++, 1, 1);
223 ttyflushwrbuf();
227 static void ttywrite (const char *s, size_t n) {
228 if (term == NULL || term->dead || term->cmdfd < 0) return;
229 #ifdef DUMP_PROG_INPUT
230 if (s != NULL && n > 0) {
231 FILE *fo = fopen("zlogw.log", "ab");
232 if (fo) {
233 fwrite(s, n, 1, fo);
234 fclose(fo);
237 #endif
238 //ttyflushwrbuf();
239 if (s != NULL && n > 0) {
240 while (n > 0) {
241 unsigned char c = (unsigned char)(s[0]);
243 if (term->ubufpos > 0 && isfullutf8(term->ubuf, term->ubufpos)) {
244 // have complete char
245 ttywriterawchar(term->ubuf, term->ubufpos, 0);
246 term->ubufpos = 0;
247 continue;
250 if (term->ubufpos == 0) {
251 // new char
252 if (c < 128) {
253 ttywriterawchar(s, 1, 0);
254 } else if ((c&0xc0) == 0xc0) {
255 // new utf-8 char
256 term->ubuf[term->ubufpos++] = *s;
257 } else {
258 // ignore unsynced utf-8
260 ++s;
261 --n;
262 continue;
264 // char continues
265 if (c < 128 || term->ubufpos >= UTF_SIZ || (c&0xc0) == 0xc0) {
266 // discard previous utf-8, it's bad
267 term->ubufpos = 0;
268 continue;
270 // collect
271 term->ubuf[term->ubufpos++] = *s;
272 ++s;
273 --n;
274 if (isfullutf8(term->ubuf, term->ubufpos)) {
275 // have complete char
276 ttywriterawchar(term->ubuf, term->ubufpos, 0);
277 term->ubufpos = 0;
281 ttyflushwrbuf();