xref: /openbsd-src/sys/dev/wscons/wsemul_dumb.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /* $OpenBSD: wsemul_dumb.c,v 1.7 2007/11/27 16:37:27 miod Exp $ */
2 /* $NetBSD: wsemul_dumb.c,v 1.7 2000/01/05 11:19:36 drochner Exp $ */
3 
4 /*
5  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Christopher G. Demetriou
18  *	for the NetBSD Project.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/time.h>
37 #include <sys/malloc.h>
38 #include <sys/fcntl.h>
39 
40 #include <dev/wscons/wsconsio.h>
41 #include <dev/wscons/wsdisplayvar.h>
42 #include <dev/wscons/wsemulvar.h>
43 #include <dev/wscons/ascii.h>
44 
45 void	*wsemul_dumb_cnattach(const struct wsscreen_descr *, void *,
46 				   int, int, long);
47 void	*wsemul_dumb_attach(int console, const struct wsscreen_descr *,
48 				 void *, int, int, void *, long);
49 void	wsemul_dumb_output(void *cookie, const u_char *data, u_int count,
50 				int);
51 int	wsemul_dumb_translate(void *cookie, keysym_t, const char **);
52 void	wsemul_dumb_detach(void *cookie, u_int *crowp, u_int *ccolp);
53 void	wsemul_dumb_resetop(void *, enum wsemul_resetops);
54 
55 const struct wsemul_ops wsemul_dumb_ops = {
56 	"dumb",
57 	wsemul_dumb_cnattach,
58 	wsemul_dumb_attach,
59 	wsemul_dumb_output,
60 	wsemul_dumb_translate,
61 	wsemul_dumb_detach,
62 	wsemul_dumb_resetop
63 };
64 
65 struct wsemul_dumb_emuldata {
66 	const struct wsdisplay_emulops *emulops;
67 	void *emulcookie;
68 	void *cbcookie;
69 	int crippled;
70 	u_int nrows, ncols, crow, ccol;
71 	long defattr;
72 };
73 
74 struct wsemul_dumb_emuldata wsemul_dumb_console_emuldata;
75 
76 void *
77 wsemul_dumb_cnattach(type, cookie, ccol, crow, defattr)
78 	const struct wsscreen_descr *type;
79 	void *cookie;
80 	int ccol, crow;
81 	long defattr;
82 {
83 	struct wsemul_dumb_emuldata *edp;
84 	const struct wsdisplay_emulops *emulops;
85 
86 	edp = &wsemul_dumb_console_emuldata;
87 
88 	edp->emulops = emulops = type->textops;
89 	edp->emulcookie = cookie;
90 	edp->nrows = type->nrows;
91 	edp->ncols = type->ncols;
92 	edp->crow = crow;
93 	edp->ccol = ccol;
94 	edp->defattr = defattr;
95 	edp->cbcookie = NULL;
96 	edp->crippled = emulops->cursor == NULL ||
97 	    emulops->copycols == NULL || emulops->copyrows == NULL ||
98 	    emulops->erasecols == NULL || emulops->eraserows == NULL;
99 
100 	return (edp);
101 }
102 
103 void *
104 wsemul_dumb_attach(console, type, cookie, ccol, crow, cbcookie, defattr)
105 	int console;
106 	const struct wsscreen_descr *type;
107 	void *cookie;
108 	int ccol, crow;
109 	void *cbcookie;
110 	long defattr;
111 {
112 	struct wsemul_dumb_emuldata *edp;
113 
114 	if (console)
115 		edp = &wsemul_dumb_console_emuldata;
116 	else {
117 		edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK);
118 
119 		edp->emulops = type->textops;
120 		edp->emulcookie = cookie;
121 		edp->nrows = type->nrows;
122 		edp->ncols = type->ncols;
123 		edp->crow = crow;
124 		edp->ccol = ccol;
125 		edp->defattr = defattr;
126 	}
127 
128 	edp->cbcookie = cbcookie;
129 
130 	return (edp);
131 }
132 
133 void
134 wsemul_dumb_output(cookie, data, count, kernel)
135 	void *cookie;
136 	const u_char *data;
137 	u_int count;
138 	int kernel; /* ignored */
139 {
140 	struct wsemul_dumb_emuldata *edp = cookie;
141 	u_char c;
142 	int n;
143 
144 	if (edp->crippled) {
145 		while (count-- > 0) {
146 			c = *data++;
147 
148 			if (c == ASCII_BEL)
149 				wsdisplay_emulbell(edp->cbcookie);
150 			else
151 				(*edp->emulops->putchar)(edp->emulcookie, 0,
152 				    0, c, 0);
153 		}
154 		return;
155 	}
156 
157 	/* XXX */
158 	(*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol);
159 	while (count-- > 0) {
160 		c = *data++;
161 
162 		switch (c) {
163 		case ASCII_BEL:
164 			wsdisplay_emulbell(edp->cbcookie);
165 			break;
166 
167 		case ASCII_BS:
168 			if (edp->ccol > 0)
169 				edp->ccol--;
170 			break;
171 
172 		case ASCII_CR:
173 			edp->ccol = 0;
174 			break;
175 
176 		case ASCII_HT:
177 			n = min(8 - (edp->ccol & 7),
178 			    edp->ncols - edp->ccol - 1);
179 			(*edp->emulops->erasecols)(edp->emulcookie,
180 			    edp->crow, edp->ccol, n, edp->defattr);
181 			edp->ccol += n;
182 			break;
183 
184 		case ASCII_FF:
185 			(*edp->emulops->eraserows)(edp->emulcookie, 0,
186 			    edp->nrows, edp->defattr);
187 			edp->ccol = 0;
188 			edp->crow = 0;
189 			break;
190 
191 		case ASCII_VT:
192 			if (edp->crow > 0)
193 				edp->crow--;
194 			break;
195 
196 		default:
197 			(*edp->emulops->putchar)(edp->emulcookie, edp->crow,
198 			    edp->ccol, c, edp->defattr);
199 			edp->ccol++;
200 
201 			/* if cur col is still on cur line, done. */
202 			if (edp->ccol < edp->ncols)
203 				break;
204 
205 			/* wrap the column around. */
206 			edp->ccol = 0;
207 
208                 	/* FALLTHROUGH */
209 
210 		case ASCII_LF:
211 	                /* if the cur line isn't the last, incr and leave. */
212 			if (edp->crow < edp->nrows - 1) {
213 				edp->crow++;
214 				break;
215 			}
216 			n = 1;		/* number of lines to scroll */
217 			(*edp->emulops->copyrows)(edp->emulcookie, n, 0,
218 			    edp->nrows - n);
219 			(*edp->emulops->eraserows)(edp->emulcookie,
220 			    edp->nrows - n, n, edp->defattr);
221 			edp->crow -= n - 1;
222 			break;
223 		}
224 	}
225 	/* XXX */
226 	(*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol);
227 }
228 
229 int
230 wsemul_dumb_translate(cookie, in, out)
231 	void *cookie;
232 	keysym_t in;
233 	const char **out;
234 {
235 	return (0);
236 }
237 
238 void
239 wsemul_dumb_detach(cookie, crowp, ccolp)
240 	void *cookie;
241 	u_int *crowp, *ccolp;
242 {
243 	struct wsemul_dumb_emuldata *edp = cookie;
244 
245 	*crowp = edp->crow;
246 	*ccolp = edp->ccol;
247 	if (edp != &wsemul_dumb_console_emuldata)
248 		free(edp, M_DEVBUF);
249 }
250 
251 void
252 wsemul_dumb_resetop(cookie, op)
253 	void *cookie;
254 	enum wsemul_resetops op;
255 {
256 	struct wsemul_dumb_emuldata *edp = cookie;
257 
258 	if (edp->crippled)
259 		return;
260 
261 	switch (op) {
262 	case WSEMUL_CLEARSCREEN:
263 		(*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows,
264 					   edp->defattr);
265 		edp->ccol = edp->crow = 0;
266 		(*edp->emulops->cursor)(edp->emulcookie, 1, 0, 0);
267 		break;
268 	case WSEMUL_CLEARCURSOR:
269 		(*edp->emulops->cursor)(edp->emulcookie, 0,
270 		    edp->crow, edp->ccol);
271 		break;
272 	default:
273 		break;
274 	}
275 }
276