xref: /dragonfly/usr.bin/window/wwinit.c (revision a632cd2d33eae3cdf365948061576a303057c733)
1 /*        @(#)wwinit.c        8.2 (Berkeley) 4/28/95        */
2 /*        $NetBSD: wwinit.c,v 1.19 2009/04/14 08:50:06 lukem Exp $    */
3 
4 /*
5  * Copyright (c) 1983, 1993
6  *        The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Edward Wang at The University of California, Berkeley.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <fcntl.h>
37 #include <signal.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <termcap.h>
41 #include "ww.h"
42 #include "tt.h"
43 #include "xx.h"
44 #include "char.h"
45 
46 int
wwinit(void)47 wwinit(void)
48 {
49           int i, j;
50           char *kp;
51           sigset_t nsigset, osigset;
52 
53           wwdtablesize = 3;
54           wwhead.ww_forw = &wwhead;
55           wwhead.ww_back = &wwhead;
56 
57           sigemptyset(&nsigset);
58           sigaddset(&nsigset, SIGCHLD);
59           sigaddset(&nsigset, SIGALRM);
60           sigaddset(&nsigset, SIGHUP);
61           sigaddset(&nsigset, SIGTERM);
62           sigprocmask(SIG_BLOCK, &nsigset, &osigset);
63 
64           if (signal(SIGCHLD, wwchild) == SIG_ERR ||
65               signal(SIGHUP, wwquit) == SIG_ERR ||
66               signal(SIGTERM, wwquit) == SIG_ERR ||
67               signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
68                     wwerrno = WWE_SYS;
69                     return -1;
70           }
71 
72           if (wwgettty(0, &wwoldtty) < 0)
73                     return -1;
74           wwwintty = wwoldtty;
75 #ifdef OLD_TTY
76           wwwintty.ww_sgttyb.sg_flags &= ~XTABS;
77           wwnewtty.ww_sgttyb = wwoldtty.ww_sgttyb;
78           wwnewtty.ww_sgttyb.sg_erase = -1;
79           wwnewtty.ww_sgttyb.sg_kill = -1;
80           wwnewtty.ww_sgttyb.sg_flags |= CBREAK;
81           wwnewtty.ww_sgttyb.sg_flags &= ~(ECHO|CRMOD);
82           wwnewtty.ww_tchars.t_intrc = -1;
83           wwnewtty.ww_tchars.t_quitc = -1;
84           wwnewtty.ww_tchars.t_startc = -1;
85           wwnewtty.ww_tchars.t_stopc = -1;
86           wwnewtty.ww_tchars.t_eofc = -1;
87           wwnewtty.ww_tchars.t_brkc = -1;
88           wwnewtty.ww_ltchars.t_suspc = -1;
89           wwnewtty.ww_ltchars.t_dsuspc = -1;
90           wwnewtty.ww_ltchars.t_rprntc = -1;
91           wwnewtty.ww_ltchars.t_flushc = -1;
92           wwnewtty.ww_ltchars.t_werasc = -1;
93           wwnewtty.ww_ltchars.t_lnextc = -1;
94           wwnewtty.ww_lmode = wwoldtty.ww_lmode | LLITOUT;
95           wwnewtty.ww_ldisc = wwoldtty.ww_ldisc;
96 #else
97 #ifndef OXTABS
98 #define OXTABS XTABS
99 #endif
100 #ifndef _POSIX_VDISABLE
101 #define _POSIX_VDISABLE -1
102 #endif
103           wwwintty.ww_termios.c_oflag &= ~OXTABS;
104           wwwintty.ww_termios.c_cflag &= ~CLOCAL;
105           wwwintty.ww_termios.c_cflag |= HUPCL;
106           wwnewtty.ww_termios = wwoldtty.ww_termios;
107           wwnewtty.ww_termios.c_iflag &=
108                     ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IMAXBEL);
109           wwnewtty.ww_termios.c_oflag = 0;
110           wwnewtty.ww_termios.c_cflag &= ~(CSIZE | PARENB);
111           wwnewtty.ww_termios.c_cflag |= CS8;
112           wwnewtty.ww_termios.c_lflag = 0;
113           for (i = 0; i < NCCS; i++)
114                     wwnewtty.ww_termios.c_cc[i] = _POSIX_VDISABLE;
115           wwnewtty.ww_termios.c_cc[VMIN] = 1;
116           wwnewtty.ww_termios.c_cc[VTIME] = 0;
117 #endif
118           if (wwsettty(0, &wwnewtty) < 0)
119                     goto bad;
120 
121           if ((wwterm = getenv("TERM")) == 0) {
122                     wwerrno = WWE_BADTERM;
123                     goto bad;
124           }
125           if (tgetent(wwtermcap, wwterm) != 1) {
126                     wwerrno = WWE_BADTERM;
127                     goto bad;
128           }
129 #ifdef OLD_TTY
130           wwospeed = wwoldtty.ww_sgttyb.sg_ospeed;
131 #else
132           wwospeed = cfgetospeed(&wwoldtty.ww_termios);
133           wwbaud = wwospeed;
134 #endif
135           switch (wwospeed) {
136           default:
137           case B0:
138                     wwbaud = 9600;
139                     break;
140           case B50:
141                     wwbaud = 50;
142                     break;
143           case B75:
144                     wwbaud = 75;
145                     break;
146           case B110:
147                     wwbaud = 110;
148                     break;
149           case B134:
150                     wwbaud = 134;
151                     break;
152           case B150:
153                     wwbaud = 150;
154                     break;
155           case B200:
156                     wwbaud = 200;
157                     break;
158           case B300:
159                     wwbaud = 300;
160                     break;
161           case B600:
162                     wwbaud = 600;
163                     break;
164           case B1200:
165                     wwbaud = 1200;
166                     break;
167           case B1800:
168                     wwbaud = 1800;
169                     break;
170           case B2400:
171                     wwbaud = 2400;
172                     break;
173           case B4800:
174                     wwbaud = 4800;
175                     break;
176           case B9600:
177                     wwbaud = 9600;
178                     break;
179 #ifdef B19200
180           case B19200:
181 #else
182           case EXTA:
183 #endif
184                     wwbaud = 19200;
185                     break;
186 #ifdef B38400
187           case B38400:
188 #else
189           case EXTB:
190 #endif
191                     wwbaud = 38400;
192                     break;
193 #ifdef B57600
194           case B57600:
195                     wwbaud = 57600;
196                     break;
197 #endif
198 #ifdef B115200
199           case B115200:
200                     wwbaud = 115200;
201                     break;
202 #endif
203           }
204 
205           if (xxinit() < 0)
206                     goto bad;
207           wwnrow = tt.tt_nrow;
208           wwncol = tt.tt_ncol;
209           wwavailmodes = tt.tt_availmodes;
210           wwwrap = tt.tt_wrap;
211 
212           if (wwavailmodes & WWM_REV)
213                     wwcursormodes = WWM_REV | (wwavailmodes & WWM_BLK);
214           else if (wwavailmodes & WWM_UL)
215                     wwcursormodes = WWM_UL;
216 
217           if ((wwib = malloc((unsigned) 512)) == 0)
218                     goto bad;
219           wwibe = wwib + 512;
220           wwibq = wwibp = wwib;
221 
222           wwsmap = (unsigned char **)
223                     wwalloc(0, 0, wwnrow, wwncol, sizeof (unsigned char));
224           if (wwsmap == 0)
225                     goto bad;
226           for (i = 0; i < wwnrow; i++)
227                     for (j = 0; j < wwncol; j++)
228                               wwsmap[i][j] = WWX_NOBODY;
229 
230           wwos = (union ww_char **)
231                     wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char));
232           if (wwos == 0)
233                     goto bad;
234           /* wwos is cleared in wwstart1() */
235           wwns = (union ww_char **)
236                     wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char));
237           if (wwns == 0)
238                     goto bad;
239           for (i = 0; i < wwnrow; i++)
240                     for (j = 0; j < wwncol; j++)
241                               wwns[i][j].c_w = ' ';
242           if (tt.tt_checkpoint) {
243                     /* wwcs is also cleared in wwstart1() */
244                     wwcs = (union ww_char **)
245                               wwalloc(0, 0, wwnrow, wwncol, sizeof (union ww_char));
246                     if (wwcs == 0)
247                               goto bad;
248           }
249 
250           wwtouched = malloc((unsigned) wwnrow);
251           if (wwtouched == 0) {
252                     wwerrno = WWE_NOMEM;
253                     goto bad;
254           }
255           for (i = 0; i < wwnrow; i++)
256                     wwtouched[i] = 0;
257 
258           wwupd = (struct ww_update *) malloc((unsigned) wwnrow * sizeof *wwupd);
259           if (wwupd == 0) {
260                     wwerrno = WWE_NOMEM;
261                     goto bad;
262           }
263 
264           wwindex[WWX_NOBODY] = &wwnobody;
265           wwnobody.ww_order = NWW;
266 
267           kp = wwwintermcap;
268           if (wwavailmodes & WWM_REV)
269                     wwaddcap1(WWT_REV, &kp);
270           if (wwavailmodes & WWM_BLK)
271                     wwaddcap1(WWT_BLK, &kp);
272           if (wwavailmodes & WWM_UL)
273                     wwaddcap1(WWT_UL, &kp);
274           if (wwavailmodes & WWM_GRP)
275                     wwaddcap1(WWT_GRP, &kp);
276           if (wwavailmodes & WWM_DIM)
277                     wwaddcap1(WWT_DIM, &kp);
278           if (wwavailmodes & WWM_USR)
279                     wwaddcap1(WWT_USR, &kp);
280           if ((tt.tt_insline && tt.tt_delline) || tt.tt_setscroll)
281                     wwaddcap1(WWT_ALDL, &kp);
282           if (tt.tt_inschar)
283                     wwaddcap1(WWT_IMEI, &kp);
284           if (tt.tt_insspace)
285                     wwaddcap1(WWT_IC, &kp);
286           if (tt.tt_delchar)
287                     wwaddcap1(WWT_DC, &kp);
288           wwaddcap("kb", &kp);
289           wwaddcap("ku", &kp);
290           wwaddcap("kd", &kp);
291           wwaddcap("kl", &kp);
292           wwaddcap("kr", &kp);
293           wwaddcap("kh", &kp);
294           if ((j = tgetnum("kn")) >= 0) {
295                     char cap[32];
296 
297                     (void) sprintf(kp, "kn#%d:", j);
298                     for (; *kp; kp++)
299                               ;
300                     for (i = 1; i <= j; i++) {
301                               (void) sprintf(cap, "k%d", i);
302                               wwaddcap(cap, &kp);
303                               cap[0] = 'l';
304                               wwaddcap(cap, &kp);
305                     }
306           }
307           /*
308            * It's ok to do this here even if setenv() is destructive
309            * since tt_init() has already made its own copy of it and
310            * wwterm now points to the copy.
311            */
312           (void) setenv("TERM", WWT_TERM, 1);
313 #ifdef TERMINFO
314           if (wwterminfoinit() < 0)
315                     goto bad;
316 #endif
317 
318           if (tt.tt_checkpoint)
319                     if (signal(SIGALRM, wwalarm) == SIG_ERR) {
320                               wwerrno = WWE_SYS;
321                               goto bad;
322                     }
323           wwstart1();
324 
325           sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
326           return 0;
327 
328 bad:
329           /*
330            * Don't bother to free storage.  We're supposed
331            * to exit when wwinit fails anyway.
332            */
333           (void) wwsettty(0, &wwoldtty);
334 
335           sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
336           return -1;
337 }
338 
339 void
wwaddcap(const char * cap,char ** kp)340 wwaddcap(const char *cap, char **kp)
341 {
342           char tbuf[512];
343           char *tp = tbuf;
344           char *str;
345           const char *p;
346 
347           if ((str = tgetstr(cap, &tp)) != NULL) {
348                     while ((*(*kp)++ = *cap++))
349                               ;
350                     (*kp)[-1] = '=';
351                     while (*str) {
352                               for (p = unctrl(*str++); (*(*kp)++ = *p++);)
353                                         ;
354                               (*kp)--;
355                     }
356                     *(*kp)++ = ':';
357                     **kp = 0;
358           }
359 }
360 
361 void
wwaddcap1(const char * cap,char ** kp)362 wwaddcap1(const char *cap, char **kp)
363 {
364           while ((*(*kp)++ = *cap++))
365                     ;
366           (*kp)--;
367 }
368 
369 void
wwstart(void)370 wwstart(void)
371 {
372           int i;
373 
374           (void) wwsettty(0, &wwnewtty);
375           for (i = 0; i < wwnrow; i++)
376                     wwtouched[i] = WWU_TOUCHED;
377           wwstart1();
378 }
379 
380 void
wwstart1(void)381 wwstart1(void)
382 {
383           int i, j;
384 
385           for (i = 0; i < wwnrow; i++)
386                     for (j = 0; j < wwncol; j++) {
387                               wwos[i][j].c_w = ' ';
388                               if (tt.tt_checkpoint)
389                                         wwcs[i][j].c_w = ' ';
390                     }
391           xxstart();
392           if (tt.tt_checkpoint)
393                     wwdocheckpoint = 1;
394 }
395 
396 /*
397  * Reset data structures and terminal from an unknown state.
398  * Restoring wwos has been taken care of elsewhere.
399  */
400 void
wwreset(void)401 wwreset(void)
402 {
403           int i;
404 
405           xxreset();
406           for (i = 0; i < wwnrow; i++)
407                     wwtouched[i] = WWU_TOUCHED;
408 }
409