xref: /netbsd-src/sys/dev/wscons/wsemul_dumb.c (revision d1579b2d70337e1b895f03478838f880e450f6da)
1*d1579b2dSriastradh /* $NetBSD: wsemul_dumb.c,v 1.18 2018/09/03 16:29:34 riastradh Exp $ */
2b31e6386Sdrochner 
3b31e6386Sdrochner /*
4b31e6386Sdrochner  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
5b31e6386Sdrochner  *
6b31e6386Sdrochner  * Redistribution and use in source and binary forms, with or without
7b31e6386Sdrochner  * modification, are permitted provided that the following conditions
8b31e6386Sdrochner  * are met:
9b31e6386Sdrochner  * 1. Redistributions of source code must retain the above copyright
10b31e6386Sdrochner  *    notice, this list of conditions and the following disclaimer.
11b31e6386Sdrochner  * 2. Redistributions in binary form must reproduce the above copyright
12b31e6386Sdrochner  *    notice, this list of conditions and the following disclaimer in the
13b31e6386Sdrochner  *    documentation and/or other materials provided with the distribution.
14b31e6386Sdrochner  * 3. All advertising materials mentioning features or use of this software
15b31e6386Sdrochner  *    must display the following acknowledgement:
16b31e6386Sdrochner  *      This product includes software developed by Christopher G. Demetriou
17b31e6386Sdrochner  *	for the NetBSD Project.
18b31e6386Sdrochner  * 4. The name of the author may not be used to endorse or promote products
19b31e6386Sdrochner  *    derived from this software without specific prior written permission
20b31e6386Sdrochner  *
21b31e6386Sdrochner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22b31e6386Sdrochner  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23b31e6386Sdrochner  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24b31e6386Sdrochner  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25b31e6386Sdrochner  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26b31e6386Sdrochner  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27b31e6386Sdrochner  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28b31e6386Sdrochner  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29b31e6386Sdrochner  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30b31e6386Sdrochner  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31b31e6386Sdrochner  */
32b31e6386Sdrochner 
33b32647d4Sdrochner #include <sys/cdefs.h>
34*d1579b2dSriastradh __KERNEL_RCSID(0, "$NetBSD: wsemul_dumb.c,v 1.18 2018/09/03 16:29:34 riastradh Exp $");
35b31e6386Sdrochner 
36b31e6386Sdrochner #include <sys/param.h>
37b31e6386Sdrochner #include <sys/systm.h>
38b31e6386Sdrochner #include <sys/time.h>
39b31e6386Sdrochner #include <sys/malloc.h>
40b31e6386Sdrochner #include <sys/fcntl.h>
41b31e6386Sdrochner 
42b31e6386Sdrochner #include <dev/wscons/wsconsio.h>
43b31e6386Sdrochner #include <dev/wscons/wsdisplayvar.h>
44b31e6386Sdrochner #include <dev/wscons/wsemulvar.h>
45b31e6386Sdrochner #include <dev/wscons/ascii.h>
4625fb8de0Sdrochner #include <dev/wscons/wsksymdef.h>
47b31e6386Sdrochner 
4882e5e6abSaugustss void	*wsemul_dumb_cnattach(const struct wsscreen_descr *, void *,
4982e5e6abSaugustss 				   int, int, long);
5082e5e6abSaugustss void	*wsemul_dumb_attach(int console, const struct wsscreen_descr *,
5182e5e6abSaugustss 				 void *, int, int, void *, long);
5282e5e6abSaugustss void	wsemul_dumb_output(void *cookie, const u_char *data, u_int count, int);
53f90bcf3aSchristos int	wsemul_dumb_translate(void *cookie, keysym_t, const char **);
5482e5e6abSaugustss void	wsemul_dumb_detach(void *cookie, u_int *crowp, u_int *ccolp);
5582e5e6abSaugustss void	wsemul_dumb_resetop(void *, enum wsemul_resetops);
56b31e6386Sdrochner 
57b31e6386Sdrochner const struct wsemul_ops wsemul_dumb_ops = {
58dba91e04Smaya 	.name = "dumb",
59dba91e04Smaya 	.cnattach = wsemul_dumb_cnattach,
60dba91e04Smaya 	.attach = wsemul_dumb_attach,
61dba91e04Smaya 	.output = wsemul_dumb_output,
62dba91e04Smaya 	.translate = wsemul_dumb_translate,
63dba91e04Smaya 	.detach = wsemul_dumb_detach,
64dba91e04Smaya 	.reset = wsemul_dumb_resetop,
65dba91e04Smaya 	.getmsgattrs = NULL,
66dba91e04Smaya 	.setmsgattrs = NULL,
67dba91e04Smaya 	.resize = NULL,
68b31e6386Sdrochner };
69b31e6386Sdrochner 
70b31e6386Sdrochner struct wsemul_dumb_emuldata {
71b31e6386Sdrochner 	const struct wsdisplay_emulops *emulops;
72b31e6386Sdrochner 	void *emulcookie;
73b31e6386Sdrochner 	void *cbcookie;
74b31e6386Sdrochner 	u_int nrows, ncols, crow, ccol;
7595bdb660Sdrochner 	long defattr;
76b31e6386Sdrochner };
77b31e6386Sdrochner 
78b31e6386Sdrochner struct wsemul_dumb_emuldata wsemul_dumb_console_emuldata;
79b31e6386Sdrochner 
80b31e6386Sdrochner void *
wsemul_dumb_cnattach(const struct wsscreen_descr * type,void * cookie,int ccol,int crow,long defattr)8182e5e6abSaugustss wsemul_dumb_cnattach(const struct wsscreen_descr *type, void *cookie,
8282e5e6abSaugustss 	int ccol, int crow, long defattr)
83b31e6386Sdrochner {
84b31e6386Sdrochner 	struct wsemul_dumb_emuldata *edp;
85b31e6386Sdrochner 
86b31e6386Sdrochner 	edp = &wsemul_dumb_console_emuldata;
87b31e6386Sdrochner 
88b31e6386Sdrochner 	edp->emulops = type->textops;
89b31e6386Sdrochner 	edp->emulcookie = cookie;
90b31e6386Sdrochner 	edp->nrows = type->nrows;
91b31e6386Sdrochner 	edp->ncols = type->ncols;
92b31e6386Sdrochner 	edp->crow = crow;
93b31e6386Sdrochner 	edp->ccol = ccol;
9495bdb660Sdrochner 	edp->defattr = defattr;
95b31e6386Sdrochner 	edp->cbcookie = NULL;
96b31e6386Sdrochner 
97b31e6386Sdrochner 	return (edp);
98b31e6386Sdrochner }
99b31e6386Sdrochner 
100b31e6386Sdrochner void *
wsemul_dumb_attach(int console,const struct wsscreen_descr * type,void * cookie,int ccol,int crow,void * cbcookie,long defattr)10182e5e6abSaugustss wsemul_dumb_attach(int console, const struct wsscreen_descr *type,
10282e5e6abSaugustss 	void *cookie, int ccol, int crow, void *cbcookie, long defattr)
103b31e6386Sdrochner {
104b31e6386Sdrochner 	struct wsemul_dumb_emuldata *edp;
105b31e6386Sdrochner 
106b31e6386Sdrochner 	if (console)
107b31e6386Sdrochner 		edp = &wsemul_dumb_console_emuldata;
108b31e6386Sdrochner 	else {
109b31e6386Sdrochner 		edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK);
110b31e6386Sdrochner 
111b31e6386Sdrochner 		edp->emulops = type->textops;
112b31e6386Sdrochner 		edp->emulcookie = cookie;
113b31e6386Sdrochner 		edp->nrows = type->nrows;
114b31e6386Sdrochner 		edp->ncols = type->ncols;
115b31e6386Sdrochner 		edp->crow = crow;
116b31e6386Sdrochner 		edp->ccol = ccol;
11795bdb660Sdrochner 		edp->defattr = defattr;
118b31e6386Sdrochner 	}
119b31e6386Sdrochner 
120b31e6386Sdrochner 	edp->cbcookie = cbcookie;
121b31e6386Sdrochner 
122b31e6386Sdrochner 	return (edp);
123b31e6386Sdrochner }
124b31e6386Sdrochner 
125b31e6386Sdrochner void
wsemul_dumb_output(void * cookie,const u_char * data,u_int count,int kernel)12682e5e6abSaugustss wsemul_dumb_output(void *cookie, const u_char *data, u_int count,
127168cd830Schristos     int kernel)
128b31e6386Sdrochner {
129b31e6386Sdrochner 	struct wsemul_dumb_emuldata *edp = cookie;
130b31e6386Sdrochner 	u_char c;
131b31e6386Sdrochner 	int n;
132b31e6386Sdrochner 
133b31e6386Sdrochner 	/* XXX */
134b31e6386Sdrochner 	(*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol);
135b31e6386Sdrochner 	while (count-- > 0) {
136b31e6386Sdrochner 		c = *data++;
137b31e6386Sdrochner 		switch (c) {
138b31e6386Sdrochner 		case ASCII_BEL:
139b31e6386Sdrochner 			wsdisplay_emulbell(edp->cbcookie);
140b31e6386Sdrochner 			break;
141b31e6386Sdrochner 
142b31e6386Sdrochner 		case ASCII_BS:
143b31e6386Sdrochner 			if (edp->ccol > 0)
144b31e6386Sdrochner 				edp->ccol--;
145b31e6386Sdrochner 			break;
146b31e6386Sdrochner 
147b31e6386Sdrochner 		case ASCII_CR:
148b31e6386Sdrochner 			edp->ccol = 0;
149b31e6386Sdrochner 			break;
150b31e6386Sdrochner 
151b31e6386Sdrochner 		case ASCII_HT:
152*d1579b2dSriastradh 			n = uimin(8 - (edp->ccol & 7),
153b31e6386Sdrochner 			    edp->ncols - edp->ccol - 1);
154b31e6386Sdrochner 			(*edp->emulops->erasecols)(edp->emulcookie,
15595bdb660Sdrochner 			    edp->crow, edp->ccol, n, edp->defattr);
156b31e6386Sdrochner 			edp->ccol += n;
157b31e6386Sdrochner 			break;
158b31e6386Sdrochner 
159c06d6aa6Sdrochner 		case ASCII_FF:
160b31e6386Sdrochner 			(*edp->emulops->eraserows)(edp->emulcookie, 0,
16195bdb660Sdrochner 			    edp->nrows, edp->defattr);
162b31e6386Sdrochner 			edp->ccol = 0;
163b31e6386Sdrochner 			edp->crow = 0;
164b31e6386Sdrochner 			break;
165b31e6386Sdrochner 
166b31e6386Sdrochner 		case ASCII_VT:
167b31e6386Sdrochner 			if (edp->crow > 0)
168b31e6386Sdrochner 				edp->crow--;
169b31e6386Sdrochner 			break;
170b31e6386Sdrochner 
171b31e6386Sdrochner 		default:
172d3e8687bSdrochner 			(*edp->emulops->putchar)(edp->emulcookie, edp->crow,
173d3e8687bSdrochner 			    edp->ccol, c, edp->defattr);
174b31e6386Sdrochner 			edp->ccol++;
175b31e6386Sdrochner 
176b31e6386Sdrochner 			/* if cur col is still on cur line, done. */
177b31e6386Sdrochner 			if (edp->ccol < edp->ncols)
178b31e6386Sdrochner 				break;
179b31e6386Sdrochner 
180b31e6386Sdrochner 			/* wrap the column around. */
181b31e6386Sdrochner 			edp->ccol = 0;
182b31e6386Sdrochner 
183b31e6386Sdrochner                 	/* FALLTHRU */
184b31e6386Sdrochner 
185b31e6386Sdrochner 		case ASCII_LF:
186b31e6386Sdrochner 	                /* if the cur line isn't the last, incr and leave. */
187b31e6386Sdrochner 			if (edp->crow < edp->nrows - 1) {
188b31e6386Sdrochner 				edp->crow++;
189b31e6386Sdrochner 				break;
190b31e6386Sdrochner 			}
191b31e6386Sdrochner 			n = 1;		/* number of lines to scroll */
192b31e6386Sdrochner 			(*edp->emulops->copyrows)(edp->emulcookie, n, 0,
193b31e6386Sdrochner 			    edp->nrows - n);
194b31e6386Sdrochner 			(*edp->emulops->eraserows)(edp->emulcookie,
19595bdb660Sdrochner 			    edp->nrows - n, n, edp->defattr);
196b31e6386Sdrochner 			edp->crow -= n - 1;
197b31e6386Sdrochner 			break;
198b31e6386Sdrochner 		}
199b31e6386Sdrochner 	}
200b31e6386Sdrochner 	/* XXX */
201b31e6386Sdrochner 	(*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol);
202b31e6386Sdrochner }
203b31e6386Sdrochner 
204bd3b88b6Sdrochner int
wsemul_dumb_translate(void * cookie,keysym_t in,const char ** out)205168cd830Schristos wsemul_dumb_translate(void *cookie, keysym_t in,
206168cd830Schristos     const char **out)
207bd3b88b6Sdrochner {
20825fb8de0Sdrochner 	static char c;
20925fb8de0Sdrochner 
21025fb8de0Sdrochner 	if (KS_GROUP(in) == KS_GROUP_Plain) {
21125fb8de0Sdrochner 		/* allow ISO-1 */
21225fb8de0Sdrochner 		c = KS_VALUE(in);
21325fb8de0Sdrochner 		*out = &c;
21425fb8de0Sdrochner 		return (1);
21525fb8de0Sdrochner 	}
216bd3b88b6Sdrochner 	return (0);
217bd3b88b6Sdrochner }
218bd3b88b6Sdrochner 
219b31e6386Sdrochner void
wsemul_dumb_detach(void * cookie,u_int * crowp,u_int * ccolp)22082e5e6abSaugustss wsemul_dumb_detach(void *cookie, u_int *crowp, u_int *ccolp)
221b31e6386Sdrochner {
222b31e6386Sdrochner 	struct wsemul_dumb_emuldata *edp = cookie;
223b31e6386Sdrochner 
224b31e6386Sdrochner 	*crowp = edp->crow;
225b31e6386Sdrochner 	*ccolp = edp->ccol;
226b31e6386Sdrochner 	if (edp != &wsemul_dumb_console_emuldata)
227b31e6386Sdrochner 		free(edp, M_DEVBUF);
228b31e6386Sdrochner }
229b69b2fd8Sdrochner 
230b69b2fd8Sdrochner void
wsemul_dumb_resetop(void * cookie,enum wsemul_resetops op)23182e5e6abSaugustss wsemul_dumb_resetop(void *cookie, enum wsemul_resetops op)
232b69b2fd8Sdrochner {
233b69b2fd8Sdrochner 	struct wsemul_dumb_emuldata *edp = cookie;
234b69b2fd8Sdrochner 
235b69b2fd8Sdrochner 	switch (op) {
236b69b2fd8Sdrochner 	case WSEMUL_CLEARSCREEN:
237b69b2fd8Sdrochner 		(*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows,
238b69b2fd8Sdrochner 					   edp->defattr);
239b69b2fd8Sdrochner 		edp->ccol = edp->crow = 0;
240b69b2fd8Sdrochner 		(*edp->emulops->cursor)(edp->emulcookie, 1, 0, 0);
241b69b2fd8Sdrochner 		break;
242b69b2fd8Sdrochner 	default:
243b69b2fd8Sdrochner 		break;
244b69b2fd8Sdrochner 	}
245b69b2fd8Sdrochner }
246