1 /*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Edward Wang at The University of California, Berkeley.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #ifndef lint
38 static char sccsid[] = "@(#)wwinit.c 8.1 (Berkeley) 6/6/93";
39 static char rcsid[] =
40 "$FreeBSD: head/usr.bin/window/wwinit.c 188828 2009-02-19 20:07:59Z imp $";
41 #endif /* not lint */
42
43 #include "ww.h"
44 #include "tt.h"
45 #include <signal.h>
46 #include <stdio.h>
47 #include <fcntl.h>
48 #include <termcap.h>
49 #include "char.h"
50
51 struct ww wwhead;
52 struct ww *wwindex[NWW + 1]; /* last location is for wwnobody */
53 struct ww wwnobody;
54
55 extern char *wwterm; /* the terminal name */
56 extern char wwtermcap[1024]; /* place for the termcap */
57
58 int wwnrow, wwncol; /* the screen size */
59 char wwavailmodes; /* actually supported modes */
60 char wwcursormodes; /* the modes for the fake cursor */
61 char wwwrap; /* terminal has auto wrap around */
62 int wwdtablesize; /* result of getdtablesize() call */
63 char **wwsmap; /* the screen map */
64 union ww_char **wwos; /* the old (current) screen */
65 union ww_char **wwns; /* the new (desired) screen */
66 union ww_char **wwcs; /* the checkpointed screen */
67 char *wwtouched; /* wwns changed flags */
68 struct ww_update *wwupd; /* for display update */
69 int wwospeed; /* output baud rate, copied from wwoldtty */
70 int wwbaud; /* wwospeed converted into actual number */
71 int wwcursorrow, wwcursorcol; /* where we want the cursor to be */
72 int wwerrno; /* error number */
73
74 int wwnflush, wwnwr, wwnwre, wwnwrz, wwnwrc;
75 int wwnwwr, wwnwwra, wwnwwrc;
76 int wwntokdef, wwntokuse, wwntokbad, wwntoksave, wwntokc;
77 int wwnupdate, wwnupdline, wwnupdmiss;
78 int wwnupdscan, wwnupdclreol, wwnupdclreos, wwnupdclreosmiss, wwnupdclreosline;
79 int wwnread, wwnreade, wwnreadz;
80 int wwnreadc, wwnreadack, wwnreadnack, wwnreadstat, wwnreadec;
81 int wwnwread, wwnwreade, wwnwreadz, wwnwreadd, wwnwreadc, wwnwreadp;
82 int wwnselect, wwnselecte, wwnselectz;
83
84 struct ww_tty wwoldtty; /* the old (saved) terminal settings */
85 struct ww_tty wwnewtty; /* the new (current) terminal settings */
86 struct ww_tty wwwintty; /* the terminal settings for windows */
87 char *wwterm;
88 char wwtermcap[1024];
89 char wwwintermcap[1024];
90
91 struct ww *wwcurwin; /* window to copy input into */
92 char *wwib; /* input (keyboard) buffer */
93 char *wwibe; /* wwib + sizeof buffer */
94 char *wwibp; /* current read position in buffer */
95 char *wwibq; /* current write position in buffer */
96
97 char wwintr;
98 char wwsetjmp;
99 jmp_buf wwjmpbuf;
100
101 int wwdocheckpoint;
102
wwinit()103 wwinit()
104 {
105 register i, j;
106 char *kp;
107 int s;
108
109 wwdtablesize = getdtablesize();
110 wwhead.ww_forw = &wwhead;
111 wwhead.ww_back = &wwhead;
112
113 s = sigblock(sigmask(SIGIO) | sigmask(SIGCHLD) | sigmask(SIGALRM) |
114 sigmask(SIGHUP) | sigmask(SIGTERM));
115 if (signal(SIGIO, wwrint) == BADSIG ||
116 signal(SIGCHLD, wwchild) == BADSIG ||
117 signal(SIGHUP, wwquit) == BADSIG ||
118 signal(SIGTERM, wwquit) == BADSIG ||
119 signal(SIGPIPE, SIG_IGN) == BADSIG) {
120 wwerrno = WWE_SYS;
121 return -1;
122 }
123
124 if (wwgettty(0, &wwoldtty) < 0)
125 return -1;
126 wwwintty = wwoldtty;
127 #ifdef OLD_TTY
128 wwwintty.ww_sgttyb.sg_flags &= ~XTABS;
129 wwnewtty.ww_sgttyb = wwoldtty.ww_sgttyb;
130 wwnewtty.ww_sgttyb.sg_erase = -1;
131 wwnewtty.ww_sgttyb.sg_kill = -1;
132 wwnewtty.ww_sgttyb.sg_flags |= CBREAK;
133 wwnewtty.ww_sgttyb.sg_flags &= ~(ECHO|CRMOD);
134 wwnewtty.ww_tchars.t_intrc = -1;
135 wwnewtty.ww_tchars.t_quitc = -1;
136 wwnewtty.ww_tchars.t_startc = -1;
137 wwnewtty.ww_tchars.t_stopc = -1;
138 wwnewtty.ww_tchars.t_eofc = -1;
139 wwnewtty.ww_tchars.t_brkc = -1;
140 wwnewtty.ww_ltchars.t_suspc = -1;
141 wwnewtty.ww_ltchars.t_dsuspc = -1;
142 wwnewtty.ww_ltchars.t_rprntc = -1;
143 wwnewtty.ww_ltchars.t_flushc = -1;
144 wwnewtty.ww_ltchars.t_werasc = -1;
145 wwnewtty.ww_ltchars.t_lnextc = -1;
146 wwnewtty.ww_lmode = wwoldtty.ww_lmode | LLITOUT;
147 wwnewtty.ww_ldisc = wwoldtty.ww_ldisc;
148 #else
149 #ifndef OXTABS
150 #define OXTABS XTABS
151 #endif
152 #ifndef _POSIX_VDISABLE
153 #define _POSIX_VDISABLE -1
154 #endif
155 wwwintty.ww_termios.c_oflag &= ~OXTABS;
156 wwnewtty.ww_termios = wwoldtty.ww_termios;
157 wwnewtty.ww_termios.c_iflag &=
158 ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IMAXBEL);
159 wwnewtty.ww_termios.c_oflag = 0;
160 wwnewtty.ww_termios.c_cflag &= ~(CSIZE | PARENB);
161 wwnewtty.ww_termios.c_cflag |= CS8;
162 wwnewtty.ww_termios.c_lflag = 0;
163 for (i = 0; i < NCCS; i++)
164 wwnewtty.ww_termios.c_cc[i] = _POSIX_VDISABLE;
165 wwnewtty.ww_termios.c_cc[VMIN] = 0;
166 wwnewtty.ww_termios.c_cc[VTIME] = 0;
167 #endif
168 wwnewtty.ww_fflags = wwoldtty.ww_fflags | FASYNC;
169 if (wwsettty(0, &wwnewtty) < 0)
170 goto bad;
171
172 if ((wwterm = getenv("TERM")) == 0) {
173 wwerrno = WWE_BADTERM;
174 goto bad;
175 }
176 if (tgetent(wwtermcap, wwterm) != 1) {
177 wwerrno = WWE_BADTERM;
178 goto bad;
179 }
180 #ifdef OLD_TTY
181 ospeed = wwoldtty.ww_sgttyb.sg_ospeed;
182 switch (ospeed) {
183 default:
184 case B0:
185 goto bad;
186 case B50:
187 wwbaud = 50;
188 break;
189 case B75:
190 wwbaud = 75;
191 break;
192 case B110:
193 wwbaud = 110;
194 break;
195 case B134:
196 wwbaud = 134;
197 break;
198 case B150:
199 wwbaud = 150;
200 break;
201 case B200:
202 wwbaud = 200;
203 break;
204 case B300:
205 wwbaud = 300;
206 break;
207 case B600:
208 wwbaud = 600;
209 break;
210 case B1200:
211 wwbaud = 1200;
212 break;
213 case B1800:
214 wwbaud = 1800;
215 break;
216 case B2400:
217 wwbaud = 2400;
218 break;
219 case B4800:
220 wwbaud = 4800;
221 break;
222 case B9600:
223 wwbaud = 9600;
224 break;
225 #ifdef B19200
226 case B19200:
227 #else
228 case EXTA:
229 #endif
230 wwbaud = 19200;
231 break;
232 #ifdef B38400
233 case B38400:
234 #else
235 case EXTB:
236 #endif
237 wwbaud = 38400;
238 break;
239 #ifdef B57600
240 case B57600:
241 wwbaud = 57600;
242 break;
243 #endif
244 #ifdef B115200
245 case B115200:
246 wwbaud = 115200;
247 break;
248 #endif
249 }
250 #else
251 if ((wwbaud = cfgetospeed(&wwoldtty.ww_termios)) == B0)
252 goto bad;
253 #endif
254 wwospeed = ospeed;
255
256 if (xxinit() < 0)
257 goto bad;
258 wwnrow = tt.tt_nrow;
259 wwncol = tt.tt_ncol;
260 wwavailmodes = tt.tt_availmodes;
261 wwwrap = tt.tt_wrap;
262
263 if (wwavailmodes & WWM_REV)
264 wwcursormodes = WWM_REV | wwavailmodes & WWM_BLK;
265 else if (wwavailmodes & WWM_UL)
266 wwcursormodes = WWM_UL;
267
268 if ((wwib = malloc((unsigned) 512)) == 0)
269 goto bad;
270 wwibe = wwib + 512;
271 wwibq = wwibp = wwib;
272
273 if ((wwsmap = wwalloc(0, 0, wwnrow, wwncol, sizeof (char))) == 0)
274 goto bad;
275 for (i = 0; i < wwnrow; i++)
276 for (j = 0; j < wwncol; j++)
277 wwsmap[i][j] = WWX_NOBODY;
278
279 wwos = (union ww_char **)
280 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char));
281 if (wwos == 0)
282 goto bad;
283 /* wwos is cleared in wwstart1() */
284 wwns = (union ww_char **)
285 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char));
286 if (wwns == 0)
287 goto bad;
288 for (i = 0; i < wwnrow; i++)
289 for (j = 0; j < wwncol; j++)
290 wwns[i][j].c_w = ' ';
291 if (tt.tt_checkpoint) {
292 /* wwcs is also cleared in wwstart1() */
293 wwcs = (union ww_char **)
294 wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char));
295 if (wwcs == 0)
296 goto bad;
297 }
298
299 wwtouched = malloc((unsigned) wwnrow);
300 if (wwtouched == 0) {
301 wwerrno = WWE_NOMEM;
302 goto bad;
303 }
304 for (i = 0; i < wwnrow; i++)
305 wwtouched[i] = 0;
306
307 wwupd = (struct ww_update *) malloc((unsigned) wwnrow * sizeof *wwupd);
308 if (wwupd == 0) {
309 wwerrno = WWE_NOMEM;
310 goto bad;
311 }
312
313 wwindex[WWX_NOBODY] = &wwnobody;
314 wwnobody.ww_order = NWW;
315
316 kp = wwwintermcap;
317 if (wwavailmodes & WWM_REV)
318 wwaddcap1(WWT_REV, &kp);
319 if (wwavailmodes & WWM_BLK)
320 wwaddcap1(WWT_BLK, &kp);
321 if (wwavailmodes & WWM_UL)
322 wwaddcap1(WWT_UL, &kp);
323 if (wwavailmodes & WWM_GRP)
324 wwaddcap1(WWT_GRP, &kp);
325 if (wwavailmodes & WWM_DIM)
326 wwaddcap1(WWT_DIM, &kp);
327 if (wwavailmodes & WWM_USR)
328 wwaddcap1(WWT_USR, &kp);
329 if (tt.tt_insline && tt.tt_delline || tt.tt_setscroll)
330 wwaddcap1(WWT_ALDL, &kp);
331 if (tt.tt_inschar)
332 wwaddcap1(WWT_IMEI, &kp);
333 if (tt.tt_insspace)
334 wwaddcap1(WWT_IC, &kp);
335 if (tt.tt_delchar)
336 wwaddcap1(WWT_DC, &kp);
337 wwaddcap("kb", &kp);
338 wwaddcap2("ku", &kp);
339 wwaddcap2("kd", &kp);
340 wwaddcap2("kl", &kp);
341 wwaddcap2("kr", &kp);
342 wwaddcap("kh", &kp);
343 if ((j = tgetnum("kn")) >= 0) {
344 char cap[32];
345
346 (void) sprintf(kp, "kn#%d:", j);
347 for (; *kp; kp++)
348 ;
349 for (i = 1; i <= j; i++) {
350 (void) sprintf(cap, "k%d", i);
351 wwaddcap(cap, &kp);
352 cap[0] = 'l';
353 wwaddcap(cap, &kp);
354 }
355 }
356 /*
357 * It's ok to do this here even if setenv() is destructive
358 * since tt_init() has already made its own copy of it and
359 * wwterm now points to the copy.
360 */
361 (void) setenv("TERM", WWT_TERM, 1);
362 #ifdef TERMINFO
363 if (wwterminfoinit() < 0)
364 goto bad;
365 #endif
366
367 if (tt.tt_checkpoint)
368 if (signal(SIGALRM, wwalarm) == BADSIG) {
369 wwerrno = WWE_SYS;
370 goto bad;
371 }
372 fcntl(0, F_SETOWN, getpid());
373 /* catch typeahead before ASYNC was set */
374 (void) kill(getpid(), SIGIO);
375 wwstart1();
376 (void) sigsetmask(s);
377 return 0;
378 bad:
379 /*
380 * Don't bother to free storage. We're supposed
381 * to exit when wwinit fails anyway.
382 */
383 (void) signal(SIGIO, SIG_DFL);
384 (void) wwsettty(0, &wwoldtty);
385 (void) sigsetmask(s);
386 return -1;
387 }
388
wwaddcap(cap,kp)389 wwaddcap(cap, kp)
390 register char *cap;
391 register char **kp;
392 {
393 char tbuf[512];
394 char *tp = tbuf;
395 register char *str, *p;
396
397 if ((str = tgetstr(cap, &tp)) != 0) {
398 while (*(*kp)++ = *cap++)
399 ;
400 (*kp)[-1] = '=';
401 while (*str) {
402 for (p = unctrl(*str++); *(*kp)++ = *p++;)
403 ;
404 (*kp)--;
405 }
406 *(*kp)++ = ':';
407 **kp = 0;
408 }
409 }
410
wwaddcap1(cap,kp)411 wwaddcap1(cap, kp)
412 register char *cap;
413 register char **kp;
414 {
415 while (*(*kp)++ = *cap++)
416 ;
417 (*kp)--;
418 }
419
wwaddcap2(cap,kp)420 wwaddcap2(cap, kp)
421 register char *cap;
422 register char **kp;
423 {
424 char tbuf[512];
425 char *tp = tbuf;
426 register char *str, *p;
427
428 if ((str = tgetstr(cap, &tp)) != 0) {
429 /* we don't support vt100's application key mode, remap */
430 if (str[0] == ctrl('[') && str[1] == 'O')
431 str[1] = '[';
432 while (*(*kp)++ = *cap++)
433 ;
434 (*kp)[-1] = '=';
435 while (*str) {
436 for (p = unctrl(*str++); *(*kp)++ = *p++;)
437 ;
438 (*kp)--;
439 }
440 *(*kp)++ = ':';
441 **kp = 0;
442 }
443 }
444
wwstart()445 wwstart()
446 {
447 register i;
448
449 (void) wwsettty(0, &wwnewtty);
450 signal(SIGIO, wwrint);
451 for (i = 0; i < wwnrow; i++)
452 wwtouched[i] = WWU_TOUCHED;
453 wwstart1();
454 }
455
wwstart1()456 wwstart1()
457 {
458 register i, j;
459
460 for (i = 0; i < wwnrow; i++)
461 for (j = 0; j < wwncol; j++) {
462 wwos[i][j].c_w = ' ';
463 if (tt.tt_checkpoint)
464 wwcs[i][j].c_w = ' ';
465 }
466 xxstart();
467 if (tt.tt_checkpoint)
468 wwdocheckpoint = 1;
469 }
470
471 /*
472 * Reset data structures and terminal from an unknown state.
473 * Restoring wwos has been taken care of elsewhere.
474 */
wwreset()475 wwreset()
476 {
477 register i;
478
479 xxreset();
480 for (i = 0; i < wwnrow; i++)
481 wwtouched[i] = WWU_TOUCHED;
482 }
483