window.1: unbreak macros, hyphens are `-' not minus `\-'
[dragonfly.git] / usr.bin / window / wwinit.c
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
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
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
362 wwaddcap1(const char *cap, char **kp)
363 {
364         while ((*(*kp)++ = *cap++))
365                 ;
366         (*kp)--;
367 }
368
369 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
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
401 wwreset(void)
402 {
403         int i;
404
405         xxreset();
406         for (i = 0; i < wwnrow; i++)
407                 wwtouched[i] = WWU_TOUCHED;
408 }