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