1296465Sdelphij/*	$NetBSD: wwopen.c,v 1.11 2002/08/12 02:44:18 itojun Exp $	*/
2110010Smarkm
3110010Smarkm/*
4142429Snectar * Copyright (c) 1983, 1993
5110010Smarkm *	The Regents of the University of California.  All rights reserved.
6110010Smarkm *
7110010Smarkm * This code is derived from software contributed to Berkeley by
8110010Smarkm * Edward Wang at The University of California, Berkeley.
9110010Smarkm *
10110010Smarkm * Redistribution and use in source and binary forms, with or without
11110010Smarkm * modification, are permitted provided that the following conditions
12110010Smarkm * are met:
13110010Smarkm * 1. Redistributions of source code must retain the above copyright
14110010Smarkm *    notice, this list of conditions and the following disclaimer.
15110010Smarkm * 2. Redistributions in binary form must reproduce the above copyright
16110010Smarkm *    notice, this list of conditions and the following disclaimer in the
17110010Smarkm *    documentation and/or other materials provided with the distribution.
18110010Smarkm * 3. Neither the name of the University nor the names of its contributors
19110010Smarkm *    may be used to endorse or promote products derived from this software
20215698Ssimon *    without specific prior written permission.
21215698Ssimon *
22215698Ssimon * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23215698Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24215698Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25110010Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26110010Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27110010Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28110010Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29110010Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30110010Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31110010Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32110010Smarkm * SUCH DAMAGE.
33110010Smarkm */
34110010Smarkm
35110010Smarkm#include <sys/cdefs.h>
36110010Smarkm#ifndef lint
37110010Smarkm#if 0
38110010Smarkmstatic char sccsid[] = "@(#)wwopen.c	8.2 (Berkeley) 4/28/95";
39110010Smarkm#else
40110010Smarkm__RCSID("$NetBSD: wwopen.c,v 1.11 2002/08/12 02:44:18 itojun Exp $");
41279265Sdelphij#endif
42279265Sdelphij#endif /* not lint */
43110010Smarkm
44110010Smarkm#include <sys/types.h>
45215698Ssimon#include <sys/socket.h>
46215698Ssimon#include <fcntl.h>
47215698Ssimon#include <stdlib.h>
48215698Ssimon#include <unistd.h>
49142429Snectar#include "ww.h"
50215698Ssimon
51142429Snectarstruct ww *
52142429Snectarwwopen(int type, int oflags, int nrow, int ncol, int row, int col, int nline)
53279265Sdelphij{
54279265Sdelphij	struct ww *w;
55279265Sdelphij	int i, j;
56110010Smarkm	char m;
57279265Sdelphij	short nvis;
58279265Sdelphij
59279265Sdelphij	w = (struct ww *)calloc(1, sizeof (struct ww));
60279265Sdelphij	if (w == 0) {
61279265Sdelphij		wwerrno = WWE_NOMEM;
62279265Sdelphij		goto bad;
63215698Ssimon	}
64279265Sdelphij	w->ww_pty = -1;
65279265Sdelphij	w->ww_socket = -1;
66279265Sdelphij
67279265Sdelphij	for (i = 0; i < NWW && wwindex[i] != 0; i++)
68279265Sdelphij		;
69215698Ssimon	if (i >= NWW) {
70279265Sdelphij		wwerrno = WWE_TOOMANY;
71110010Smarkm		goto bad;
72110010Smarkm	}
73110010Smarkm	w->ww_index = i;
74110010Smarkm
75110010Smarkm	if (nline < nrow)
76110010Smarkm		nline = nrow;
77110010Smarkm
78110010Smarkm	w->ww_w.t = row;
79110010Smarkm	w->ww_w.b = row + nrow;
80110010Smarkm	w->ww_w.l = col;
81110010Smarkm	w->ww_w.r = col + ncol;
82110010Smarkm	w->ww_w.nr = nrow;
83110010Smarkm	w->ww_w.nc = ncol;
84110010Smarkm
85110010Smarkm	w->ww_b.t = row;
86110010Smarkm	w->ww_b.b = row + nline;
87110010Smarkm	w->ww_b.l = col;
88110010Smarkm	w->ww_b.r = col + ncol;
89110010Smarkm	w->ww_b.nr = nline;
90110010Smarkm	w->ww_b.nc = ncol;
91110010Smarkm
92110010Smarkm	w->ww_i.t = MAX(w->ww_w.t, 0);
93110010Smarkm	w->ww_i.b = MIN(w->ww_w.b, wwnrow);
94110010Smarkm	w->ww_i.l = MAX(w->ww_w.l, 0);
95110010Smarkm	w->ww_i.r = MIN(w->ww_w.r, wwncol);
96110010Smarkm	w->ww_i.nr = w->ww_i.b - w->ww_i.t;
97110010Smarkm	w->ww_i.nc = w->ww_i.r - w->ww_i.l;
98110010Smarkm
99110010Smarkm	w->ww_cur.r = w->ww_w.t;
100110010Smarkm	w->ww_cur.c = w->ww_w.l;
101110010Smarkm
102110010Smarkm	w->ww_type = type;
103110010Smarkm	switch (type) {
104110010Smarkm	case WWT_PTY:
105110010Smarkm		if (wwgetpty(w) < 0)
106110010Smarkm			goto bad;
107110010Smarkm		break;
108110010Smarkm	case WWT_SOCKET:
109110010Smarkm	    {
110110010Smarkm		int d[2];
111110010Smarkm		if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, d) < 0) {
112110010Smarkm			wwerrno = WWE_SYS;
113110010Smarkm			goto bad;
114110010Smarkm		}
115110010Smarkm		(void) fcntl(d[0], F_SETFD, 1);
116110010Smarkm		(void) fcntl(d[1], F_SETFD, 1);
117110010Smarkm		w->ww_pty = d[0];
118110010Smarkm		w->ww_socket = d[1];
119110010Smarkm		break;
120110010Smarkm	    }
121110010Smarkm	}
122110010Smarkm	if (type != WWT_INTERNAL) {
123110010Smarkm		if ((w->ww_ob = malloc(512)) == 0) {
124110010Smarkm			wwerrno = WWE_NOMEM;
125110010Smarkm			goto bad;
126110010Smarkm		}
127110010Smarkm		w->ww_obe = w->ww_ob + 512;
128110010Smarkm		w->ww_obp = w->ww_obq = w->ww_ob;
129110010Smarkm		if (w->ww_pty >= wwdtablesize)
130110010Smarkm			wwdtablesize = w->ww_pty + 1;
131110010Smarkm	}
132110010Smarkm
133142429Snectar	w->ww_win = wwalloc(w->ww_w.t, w->ww_w.l,
134110010Smarkm		w->ww_w.nr, w->ww_w.nc, sizeof (char));
135110655Snectar	if (w->ww_win == 0)
136296465Sdelphij		goto bad;
137215698Ssimon	m = 0;
138215698Ssimon	if (oflags & WWO_GLASS)
139215698Ssimon		m |= WWM_GLS;
140215698Ssimon	if (oflags & WWO_REVERSE) {
141110010Smarkm		if (wwavailmodes & WWM_REV)
142110010Smarkm			m |= WWM_REV;
143110010Smarkm		else	oflags &= ~WWO_REVERSE;
144110010Smarkm	}
145110010Smarkm	for (i = w->ww_w.t; i < w->ww_w.b; i++)
146110010Smarkm		for (j = w->ww_w.l; j < w->ww_w.r; j++)
147110010Smarkm			w->ww_win[i][j] = m;
148110010Smarkm
149110010Smarkm	if (oflags & WWO_FRAME) {
150110010Smarkm		w->ww_fmap = wwalloc(w->ww_w.t, w->ww_w.l,
151110010Smarkm			w->ww_w.nr, w->ww_w.nc, sizeof (char));
152110010Smarkm		if (w->ww_fmap == 0)
153160819Ssimon			goto bad;
154110010Smarkm		for (i = w->ww_w.t; i < w->ww_w.b; i++)
155110010Smarkm			for (j = w->ww_w.l; j < w->ww_w.r; j++)
156110010Smarkm				w->ww_fmap[i][j] = 0;
157194208Ssimon	}
158110010Smarkm
159110010Smarkm	w->ww_buf = (union ww_char **)
160110010Smarkm		wwalloc(w->ww_b.t, w->ww_b.l,
161110010Smarkm			w->ww_b.nr, w->ww_b.nc, sizeof (union ww_char));
162110010Smarkm	if (w->ww_buf == 0)
163110010Smarkm		goto bad;
164110010Smarkm	for (i = w->ww_b.t; i < w->ww_b.b; i++)
165110010Smarkm		for (j = w->ww_b.l; j < w->ww_b.r; j++)
166110010Smarkm			w->ww_buf[i][j].c_w = ' ';
167110010Smarkm
168110010Smarkm	w->ww_nvis = (short *)malloc((unsigned) w->ww_w.nr * sizeof (short));
169110010Smarkm	if (w->ww_nvis == 0) {
170142429Snectar		wwerrno = WWE_NOMEM;
171110010Smarkm		goto bad;
172110010Smarkm	}
173110010Smarkm	w->ww_nvis -= w->ww_w.t;
174142429Snectar	nvis = m ? 0 : w->ww_w.nc;
175110010Smarkm	for (i = w->ww_w.t; i < w->ww_w.b; i++)
176110010Smarkm		w->ww_nvis[i] = nvis;
177142429Snectar
178110010Smarkm	w->ww_state = WWS_INITIAL;
179110010Smarkm	CLR(w->ww_oflags, WWO_ALLFLAGS);
180110010Smarkm	SET(w->ww_oflags, oflags);
181142429Snectar	return wwindex[w->ww_index] = w;
182110010Smarkmbad:
183110010Smarkm	if (w != 0) {
184142429Snectar		if (w->ww_win != 0)
185110010Smarkm			wwfree(w->ww_win, w->ww_w.t);
186110010Smarkm		if (w->ww_fmap != 0)
187142429Snectar			wwfree(w->ww_fmap, w->ww_w.t);
188110010Smarkm		if (w->ww_buf != 0)
189110010Smarkm			wwfree((char **)w->ww_buf, w->ww_b.t);
190160819Ssimon		if (w->ww_nvis != 0)
191160819Ssimon			free((char *)(w->ww_nvis + w->ww_w.t));
192160819Ssimon		if (w->ww_ob != 0)
193279265Sdelphij			free(w->ww_ob);
194142429Snectar		if (w->ww_pty >= 0)
195110010Smarkm			(void) close(w->ww_pty);
196237998Sjkim		if (w->ww_socket >= 0)
197279265Sdelphij			(void) close(w->ww_socket);
198142429Snectar		free((char *)w);
199110010Smarkm	}
200110010Smarkm	return 0;
201142429Snectar}
202110010Smarkm