1 1.34 hannken /* $NetBSD: wsemul_sun.c,v 1.34 2022/01/01 11:57:44 hannken Exp $ */ 2 1.1 drochner 3 1.1 drochner /* 4 1.1 drochner * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. 5 1.1 drochner * 6 1.1 drochner * Redistribution and use in source and binary forms, with or without 7 1.1 drochner * modification, are permitted provided that the following conditions 8 1.1 drochner * are met: 9 1.1 drochner * 1. Redistributions of source code must retain the above copyright 10 1.1 drochner * notice, this list of conditions and the following disclaimer. 11 1.1 drochner * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 drochner * notice, this list of conditions and the following disclaimer in the 13 1.1 drochner * documentation and/or other materials provided with the distribution. 14 1.1 drochner * 3. All advertising materials mentioning features or use of this software 15 1.1 drochner * must display the following acknowledgement: 16 1.1 drochner * This product includes software developed by Christopher G. Demetriou 17 1.1 drochner * for the NetBSD Project. 18 1.1 drochner * 4. The name of the author may not be used to endorse or promote products 19 1.1 drochner * derived from this software without specific prior written permission 20 1.1 drochner * 21 1.1 drochner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 1.1 drochner * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 1.1 drochner * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 1.1 drochner * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 1.1 drochner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 1.1 drochner * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 1.1 drochner * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 1.1 drochner * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 1.1 drochner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 1.1 drochner * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 1.1 drochner */ 32 1.1 drochner 33 1.11 drochner /* XXX DESCRIPTION/SOURCE OF INFORMATION */ 34 1.1 drochner 35 1.11 drochner #include <sys/cdefs.h> 36 1.34 hannken __KERNEL_RCSID(0, "$NetBSD: wsemul_sun.c,v 1.34 2022/01/01 11:57:44 hannken Exp $"); 37 1.1 drochner 38 1.1 drochner #include <sys/param.h> 39 1.1 drochner #include <sys/systm.h> 40 1.1 drochner #include <sys/time.h> 41 1.1 drochner #include <sys/malloc.h> 42 1.1 drochner #include <sys/fcntl.h> 43 1.1 drochner 44 1.1 drochner #include <dev/wscons/wsconsio.h> 45 1.1 drochner #include <dev/wscons/wsdisplayvar.h> 46 1.1 drochner #include <dev/wscons/wsemulvar.h> 47 1.6 drochner #include <dev/wscons/wsksymdef.h> 48 1.1 drochner #include <dev/wscons/ascii.h> 49 1.1 drochner 50 1.13 augustss void *wsemul_sun_cnattach(const struct wsscreen_descr *, void *, 51 1.13 augustss int, int, long); 52 1.13 augustss void *wsemul_sun_attach(int console, const struct wsscreen_descr *, 53 1.13 augustss void *, int, int, void *, long); 54 1.13 augustss void wsemul_sun_output(void *cookie, const u_char *data, u_int count, 55 1.13 augustss int); 56 1.21 martin int wsemul_sun_translate(void *cookie, keysym_t, const char **); 57 1.13 augustss void wsemul_sun_detach(void *cookie, u_int *crowp, u_int *ccolp); 58 1.13 augustss void wsemul_sun_resetop(void *, enum wsemul_resetops); 59 1.1 drochner 60 1.1 drochner const struct wsemul_ops wsemul_sun_ops = { 61 1.32 maya .name = "sun", 62 1.32 maya .cnattach = wsemul_sun_cnattach, 63 1.32 maya .attach = wsemul_sun_attach, 64 1.32 maya .output = wsemul_sun_output, 65 1.32 maya .translate = wsemul_sun_translate, 66 1.32 maya .detach = wsemul_sun_detach, 67 1.32 maya .reset = wsemul_sun_resetop, 68 1.32 maya .getmsgattrs = NULL, 69 1.32 maya .setmsgattrs = NULL, 70 1.32 maya .resize = NULL, 71 1.1 drochner }; 72 1.1 drochner 73 1.1 drochner #define SUN_EMUL_STATE_NORMAL 0 /* normal processing */ 74 1.1 drochner #define SUN_EMUL_STATE_HAVEESC 1 /* seen start of ctl seq */ 75 1.1 drochner #define SUN_EMUL_STATE_CONTROL 2 /* processing ctl seq */ 76 1.1 drochner 77 1.1 drochner #define SUN_EMUL_NARGS 2 /* max # of args to a command */ 78 1.1 drochner 79 1.1 drochner struct wsemul_sun_emuldata { 80 1.1 drochner const struct wsdisplay_emulops *emulops; 81 1.1 drochner void *emulcookie; 82 1.1 drochner void *cbcookie; 83 1.3 drochner int scrcapabilities; 84 1.1 drochner u_int nrows, ncols, crow, ccol; 85 1.1 drochner 86 1.3 drochner u_int state; /* processing state */ 87 1.3 drochner u_int args[SUN_EMUL_NARGS]; /* command args, if CONTROL */ 88 1.3 drochner u_int scrolldist; /* distance to scroll */ 89 1.3 drochner long defattr; /* default attribute (rendition) */ 90 1.3 drochner long bowattr; /* attribute for reversed mode */ 91 1.3 drochner int rendflags; 92 1.3 drochner #define REND_BOW 1 93 1.3 drochner #define REND_SO 2 94 1.3 drochner long curattr; /* currently used attribute */ 95 1.3 drochner long kernattr; /* attribute for kernel output */ 96 1.3 drochner #ifdef DIAGNOSTIC 97 1.3 drochner int console; 98 1.3 drochner #endif 99 1.1 drochner }; 100 1.1 drochner 101 1.13 augustss static u_int wsemul_sun_output_normal(struct wsemul_sun_emuldata *, 102 1.13 augustss u_char, int); 103 1.13 augustss static u_int wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *, u_char); 104 1.13 augustss static u_int wsemul_sun_output_control(struct wsemul_sun_emuldata *, u_char); 105 1.13 augustss static void wsemul_sun_control(struct wsemul_sun_emuldata *, u_char); 106 1.1 drochner 107 1.1 drochner struct wsemul_sun_emuldata wsemul_sun_console_emuldata; 108 1.1 drochner 109 1.1 drochner /* some useful utility macros */ 110 1.1 drochner #define ARG(n) (edp->args[(n)]) 111 1.1 drochner #define NORMALIZE_ARG(n) (ARG(n) ? ARG(n) : 1) 112 1.1 drochner #define COLS_LEFT (edp->ncols - edp->ccol - 1) 113 1.1 drochner #define ROWS_LEFT (edp->nrows - edp->crow - 1) 114 1.1 drochner 115 1.1 drochner void * 116 1.13 augustss wsemul_sun_cnattach(const struct wsscreen_descr *type, void *cookie, 117 1.13 augustss int ccol, int crow, long defattr) 118 1.1 drochner { 119 1.1 drochner struct wsemul_sun_emuldata *edp; 120 1.3 drochner int res; 121 1.1 drochner 122 1.1 drochner edp = &wsemul_sun_console_emuldata; 123 1.1 drochner 124 1.1 drochner edp->emulops = type->textops; 125 1.1 drochner edp->emulcookie = cookie; 126 1.3 drochner edp->scrcapabilities = type->capabilities; 127 1.1 drochner edp->nrows = type->nrows; 128 1.1 drochner edp->ncols = type->ncols; 129 1.1 drochner edp->crow = crow; 130 1.1 drochner edp->ccol = ccol; 131 1.4 drochner edp->curattr = edp->defattr = defattr; 132 1.3 drochner #if defined(WS_KERNEL_FG) || defined(WS_KERNEL_BG) || \ 133 1.3 drochner defined(WS_KERNEL_COLATTR) || defined(WS_KERNEL_MONOATTR) 134 1.3 drochner #ifndef WS_KERNEL_FG 135 1.3 drochner #define WS_KERNEL_FG WSCOL_WHITE 136 1.3 drochner #endif 137 1.3 drochner #ifndef WS_KERNEL_BG 138 1.3 drochner #define WS_KERNEL_BG WSCOL_BLACK 139 1.3 drochner #endif 140 1.3 drochner #ifndef WS_KERNEL_COLATTR 141 1.3 drochner #define WS_KERNEL_COLATTR 0 142 1.3 drochner #endif 143 1.3 drochner #ifndef WS_KERNEL_MONOATTR 144 1.3 drochner #define WS_KERNEL_MONOATTR 0 145 1.3 drochner #endif 146 1.3 drochner if (type->capabilities & WSSCREEN_WSCOLORS) 147 1.15 junyoung res = (*edp->emulops->allocattr)(cookie, 148 1.3 drochner WS_KERNEL_FG, WS_KERNEL_BG, 149 1.3 drochner WS_KERNEL_COLATTR | WSATTR_WSCOLORS, 150 1.3 drochner &edp->kernattr); 151 1.3 drochner else 152 1.15 junyoung res = (*edp->emulops->allocattr)(cookie, 0, 0, 153 1.3 drochner WS_KERNEL_MONOATTR, 154 1.3 drochner &edp->kernattr); 155 1.3 drochner #else 156 1.29 christos res = EINVAL; 157 1.3 drochner #endif 158 1.29 christos if (res) 159 1.29 christos edp->kernattr = defattr; 160 1.3 drochner 161 1.1 drochner edp->cbcookie = NULL; 162 1.1 drochner 163 1.1 drochner edp->state = SUN_EMUL_STATE_NORMAL; 164 1.1 drochner edp->scrolldist = 1; 165 1.3 drochner #ifdef DIAGNOSTIC 166 1.3 drochner edp->console = 1; 167 1.3 drochner #endif 168 1.1 drochner return (edp); 169 1.1 drochner } 170 1.1 drochner 171 1.1 drochner void * 172 1.13 augustss wsemul_sun_attach(int console, const struct wsscreen_descr *type, 173 1.13 augustss void *cookie, int ccol, int crow, void *cbcookie, long defattr) 174 1.1 drochner { 175 1.1 drochner struct wsemul_sun_emuldata *edp; 176 1.1 drochner 177 1.3 drochner if (console) { 178 1.1 drochner edp = &wsemul_sun_console_emuldata; 179 1.34 hannken #ifdef DIAGNOSTIC 180 1.3 drochner KASSERT(edp->console == 1); 181 1.34 hannken #endif 182 1.3 drochner } else { 183 1.1 drochner edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK); 184 1.1 drochner 185 1.1 drochner edp->emulops = type->textops; 186 1.1 drochner edp->emulcookie = cookie; 187 1.3 drochner edp->scrcapabilities = type->capabilities; 188 1.1 drochner edp->nrows = type->nrows; 189 1.1 drochner edp->ncols = type->ncols; 190 1.1 drochner edp->crow = crow; 191 1.1 drochner edp->ccol = ccol; 192 1.3 drochner edp->defattr = defattr; 193 1.1 drochner 194 1.1 drochner edp->state = SUN_EMUL_STATE_NORMAL; 195 1.1 drochner edp->scrolldist = 1; 196 1.3 drochner #ifdef DIAGNOSTIC 197 1.3 drochner edp->console = 0; 198 1.3 drochner #endif 199 1.1 drochner } 200 1.1 drochner 201 1.1 drochner edp->cbcookie = cbcookie; 202 1.1 drochner 203 1.20 martin if ((!(edp->scrcapabilities & WSSCREEN_REVERSE) || 204 1.20 martin (*edp->emulops->allocattr)(edp->emulcookie, 0, 0, 205 1.20 martin WSATTR_REVERSE, 206 1.20 martin &edp->bowattr)) && 207 1.20 martin (!(edp->scrcapabilities & WSSCREEN_WSCOLORS) || 208 1.15 junyoung (*edp->emulops->allocattr)(edp->emulcookie, 209 1.15 junyoung WSCOL_BLACK, WSCOL_WHITE, 210 1.15 junyoung WSATTR_WSCOLORS, 211 1.15 junyoung &edp->bowattr))) 212 1.3 drochner edp->bowattr = edp->defattr; 213 1.3 drochner 214 1.3 drochner edp->curattr = edp->defattr; 215 1.3 drochner edp->rendflags = 0; 216 1.3 drochner 217 1.1 drochner return (edp); 218 1.1 drochner } 219 1.1 drochner 220 1.1 drochner static inline u_int 221 1.13 augustss wsemul_sun_output_normal(struct wsemul_sun_emuldata *edp, u_char c, int kernel) 222 1.1 drochner { 223 1.1 drochner u_int newstate = SUN_EMUL_STATE_NORMAL; 224 1.1 drochner u_int n; 225 1.1 drochner 226 1.1 drochner switch (c) { 227 1.1 drochner case ASCII_BEL: /* "Bell (BEL)" */ 228 1.1 drochner wsdisplay_emulbell(edp->cbcookie); 229 1.1 drochner break; 230 1.1 drochner 231 1.1 drochner case ASCII_BS: /* "Backspace (BS)" */ 232 1.1 drochner if (edp->ccol > 0) 233 1.1 drochner edp->ccol--; 234 1.1 drochner break; 235 1.1 drochner 236 1.1 drochner case ASCII_CR: /* "Return (CR)" */ 237 1.1 drochner edp->ccol = 0; 238 1.1 drochner break; 239 1.1 drochner 240 1.1 drochner case ASCII_HT: /* "Tab (TAB)" */ 241 1.33 riastrad n = uimin(8 - (edp->ccol & 7), COLS_LEFT); 242 1.1 drochner (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 243 1.3 drochner edp->ccol, n, 244 1.3 drochner kernel ? edp->kernattr : edp->curattr); 245 1.1 drochner edp->ccol += n; 246 1.1 drochner break; 247 1.1 drochner 248 1.7 drochner case ASCII_FF: /* "Form Feed (FF)" */ 249 1.3 drochner (*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows, 250 1.3 drochner kernel ? edp->kernattr : edp->curattr); 251 1.3 drochner /* XXX possible in kernel output? */ 252 1.1 drochner edp->ccol = 0; 253 1.1 drochner edp->crow = 0; 254 1.1 drochner break; 255 1.1 drochner 256 1.1 drochner case ASCII_VT: /* "Reverse Line Feed" */ 257 1.1 drochner if (edp->crow > 0) 258 1.1 drochner edp->crow--; 259 1.1 drochner break; 260 1.1 drochner 261 1.1 drochner case ASCII_ESC: /* "Escape (ESC)" */ 262 1.12 jdolecek if (kernel) { 263 1.12 jdolecek printf("wsemul_sun_output_normal: ESC in kernel output ignored\n"); 264 1.12 jdolecek break; /* ignore the ESC */ 265 1.12 jdolecek } 266 1.12 jdolecek 267 1.1 drochner if (edp->state == SUN_EMUL_STATE_NORMAL) { 268 1.1 drochner newstate = SUN_EMUL_STATE_HAVEESC; 269 1.1 drochner break; 270 1.1 drochner } 271 1.1 drochner /* special case: fall through, we're printing one out */ 272 1.1 drochner /* FALLTHRU */ 273 1.1 drochner 274 1.1 drochner default: /* normal character */ 275 1.8 drochner (*edp->emulops->putchar)(edp->emulcookie, edp->crow, edp->ccol, 276 1.8 drochner c, kernel ? edp->kernattr : edp->curattr); 277 1.1 drochner edp->ccol++; 278 1.1 drochner 279 1.1 drochner /* if cur col is still on cur line, done. */ 280 1.1 drochner if (edp->ccol < edp->ncols) 281 1.1 drochner break; 282 1.1 drochner 283 1.1 drochner /* wrap the column around. */ 284 1.1 drochner edp->ccol = 0; 285 1.1 drochner 286 1.1 drochner /* FALLTHRU */ 287 1.1 drochner 288 1.1 drochner case ASCII_LF: /* "Line Feed (LF)" */ 289 1.1 drochner /* if the cur line isn't the last, incr and leave. */ 290 1.1 drochner if (edp->crow < edp->nrows - 1) { 291 1.1 drochner edp->crow++; 292 1.1 drochner break; 293 1.1 drochner } 294 1.1 drochner 295 1.1 drochner /* 296 1.1 drochner * if we're in wrap-around mode, go to the first 297 1.1 drochner * line and clear it. 298 1.1 drochner */ 299 1.1 drochner if (edp->scrolldist == 0) { 300 1.1 drochner edp->crow = 0; 301 1.3 drochner (*edp->emulops->eraserows)(edp->emulcookie, 0, 1, 302 1.3 drochner edp->curattr); 303 1.1 drochner break; 304 1.1 drochner } 305 1.1 drochner 306 1.1 drochner /* scroll by the scrolling distance. */ 307 1.1 drochner (*edp->emulops->copyrows)(edp->emulcookie, edp->scrolldist, 0, 308 1.1 drochner edp->nrows - edp->scrolldist); 309 1.1 drochner (*edp->emulops->eraserows)(edp->emulcookie, 310 1.3 drochner edp->nrows - edp->scrolldist, edp->scrolldist, 311 1.3 drochner edp->curattr); 312 1.1 drochner edp->crow -= edp->scrolldist - 1; 313 1.1 drochner break; 314 1.1 drochner } 315 1.1 drochner 316 1.1 drochner return (newstate); 317 1.1 drochner } 318 1.1 drochner 319 1.1 drochner static inline u_int 320 1.13 augustss wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *edp, u_char c) 321 1.1 drochner { 322 1.1 drochner u_int newstate; 323 1.1 drochner 324 1.1 drochner switch (c) { 325 1.1 drochner case '[': /* continuation of multi-char sequence */ 326 1.9 augustss memset(edp->args, 0, sizeof (edp->args)); 327 1.1 drochner newstate = SUN_EMUL_STATE_CONTROL; 328 1.1 drochner break; 329 1.1 drochner 330 1.1 drochner default: 331 1.1 drochner /* spit out the escape char (???), then the new character */ 332 1.3 drochner wsemul_sun_output_normal(edp, ASCII_ESC, 0); /* ??? */ 333 1.3 drochner newstate = wsemul_sun_output_normal(edp, c, 0); 334 1.1 drochner break; 335 1.1 drochner } 336 1.1 drochner 337 1.1 drochner return (newstate); 338 1.1 drochner } 339 1.1 drochner 340 1.1 drochner static inline void 341 1.13 augustss wsemul_sun_control(struct wsemul_sun_emuldata *edp, u_char c) 342 1.1 drochner { 343 1.1 drochner u_int n, src, dst; 344 1.1 drochner 345 1.1 drochner switch (c) { 346 1.1 drochner case '@': /* "Insert Character (ICH)" */ 347 1.33 riastrad n = uimin(NORMALIZE_ARG(0), COLS_LEFT + 1); 348 1.1 drochner src = edp->ccol; 349 1.1 drochner dst = edp->ccol + n; 350 1.1 drochner if (dst < edp->ncols) { 351 1.1 drochner (*edp->emulops->copycols)(edp->emulcookie, edp->crow, 352 1.1 drochner src, dst, edp->ncols - dst); 353 1.1 drochner } 354 1.1 drochner (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 355 1.3 drochner src, dst - src, edp->curattr); 356 1.1 drochner break; 357 1.1 drochner 358 1.1 drochner case 'A': /* "Cursor Up (CUU)" */ 359 1.33 riastrad edp->crow -= uimin(NORMALIZE_ARG(0), edp->crow); 360 1.1 drochner break; 361 1.1 drochner 362 1.5 drochner case 'E': /* "Cursor Next Line (CNL)" */ 363 1.5 drochner edp->ccol = 0; 364 1.5 drochner /* FALLTHRU */ 365 1.1 drochner case 'B': /* "Cursor Down (CUD)" */ 366 1.33 riastrad edp->crow += uimin(NORMALIZE_ARG(0), ROWS_LEFT); 367 1.1 drochner break; 368 1.1 drochner 369 1.1 drochner case 'C': /* "Cursor Forward (CUF)" */ 370 1.33 riastrad edp->ccol += uimin(NORMALIZE_ARG(0), COLS_LEFT); 371 1.1 drochner break; 372 1.1 drochner 373 1.1 drochner case 'D': /* "Cursor Backward (CUB)" */ 374 1.33 riastrad edp->ccol -= uimin(NORMALIZE_ARG(0), edp->ccol); 375 1.1 drochner break; 376 1.1 drochner 377 1.1 drochner case 'f': /* "Horizontal And Vertical Position (HVP)" */ 378 1.1 drochner case 'H': /* "Cursor Position (CUP)" */ 379 1.33 riastrad edp->crow = uimin(NORMALIZE_ARG(1), edp->nrows) - 1; 380 1.33 riastrad edp->ccol = uimin(NORMALIZE_ARG(0), edp->ncols) - 1; 381 1.1 drochner break; 382 1.1 drochner 383 1.1 drochner case 'J': /* "Erase in Display (ED)" */ 384 1.1 drochner if (ROWS_LEFT > 0) { 385 1.1 drochner (*edp->emulops->eraserows)(edp->emulcookie, 386 1.3 drochner edp->crow + 1, ROWS_LEFT, edp->curattr); 387 1.1 drochner } 388 1.1 drochner /* FALLTHRU */ 389 1.1 drochner case 'K': /* "Erase in Line (EL)" */ 390 1.1 drochner (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 391 1.3 drochner edp->ccol, COLS_LEFT + 1, edp->curattr); 392 1.1 drochner break; 393 1.1 drochner 394 1.1 drochner case 'L': /* "Insert Line (IL)" */ 395 1.33 riastrad n = uimin(NORMALIZE_ARG(0), ROWS_LEFT + 1); 396 1.1 drochner src = edp->crow; 397 1.1 drochner dst = edp->crow + n; 398 1.1 drochner if (dst < edp->nrows) { 399 1.1 drochner (*edp->emulops->copyrows)(edp->emulcookie, 400 1.1 drochner src, dst, edp->nrows - dst); 401 1.1 drochner } 402 1.1 drochner (*edp->emulops->eraserows)(edp->emulcookie, 403 1.3 drochner src, dst - src, edp->curattr); 404 1.1 drochner break; 405 1.1 drochner 406 1.1 drochner case 'M': /* "Delete Line (DL)" */ 407 1.33 riastrad n = uimin(NORMALIZE_ARG(0), ROWS_LEFT + 1); 408 1.1 drochner src = edp->crow + n; 409 1.1 drochner dst = edp->crow; 410 1.1 drochner if (src < edp->nrows) { 411 1.1 drochner (*edp->emulops->copyrows)(edp->emulcookie, 412 1.1 drochner src, dst, edp->nrows - src); 413 1.1 drochner } 414 1.1 drochner (*edp->emulops->eraserows)(edp->emulcookie, 415 1.3 drochner dst + edp->nrows - src, src - dst, edp->curattr); 416 1.1 drochner break; 417 1.1 drochner 418 1.1 drochner case 'P': /* "Delete Character (DCH)" */ 419 1.33 riastrad n = uimin(NORMALIZE_ARG(0), COLS_LEFT + 1); 420 1.1 drochner src = edp->ccol + n; 421 1.1 drochner dst = edp->ccol; 422 1.1 drochner if (src < edp->ncols) { 423 1.1 drochner (*edp->emulops->copycols)(edp->emulcookie, edp->crow, 424 1.1 drochner src, dst, edp->ncols - src); 425 1.1 drochner } 426 1.1 drochner (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 427 1.3 drochner dst + edp->ncols - src, src - dst, edp->curattr); 428 1.1 drochner break; 429 1.1 drochner 430 1.1 drochner case 'm': /* "Select Graphic Rendition (SGR)" */ 431 1.3 drochner if (ARG(0)) 432 1.3 drochner edp->rendflags |= REND_SO; 433 1.3 drochner else 434 1.3 drochner edp->rendflags &= ~REND_SO; 435 1.3 drochner goto setattr; 436 1.1 drochner 437 1.1 drochner case 'p': /* "Black On White (SUNBOW)" */ 438 1.3 drochner edp->rendflags |= REND_BOW; 439 1.3 drochner goto setattr; 440 1.1 drochner 441 1.1 drochner case 'q': /* "White On Black (SUNWOB)" */ 442 1.3 drochner edp->rendflags &= ~REND_BOW; 443 1.3 drochner goto setattr; 444 1.1 drochner 445 1.1 drochner case 'r': /* "Set Scrolling (SUNSCRL)" */ 446 1.33 riastrad edp->scrolldist = uimin(ARG(0), edp->nrows); 447 1.1 drochner break; 448 1.1 drochner 449 1.1 drochner case 's': /* "Reset Terminal Emulator (SUNRESET)" */ 450 1.1 drochner edp->scrolldist = 1; 451 1.3 drochner edp->rendflags = 0; 452 1.3 drochner setattr: 453 1.3 drochner if (((edp->rendflags & REND_BOW) != 0) ^ 454 1.3 drochner ((edp->rendflags & REND_SO) != 0)) 455 1.3 drochner edp->curattr = edp->bowattr; 456 1.3 drochner else 457 1.3 drochner edp->curattr = edp->defattr; 458 1.1 drochner break; 459 1.1 drochner } 460 1.1 drochner } 461 1.1 drochner 462 1.1 drochner static inline u_int 463 1.13 augustss wsemul_sun_output_control(struct wsemul_sun_emuldata *edp, u_char c) 464 1.1 drochner { 465 1.1 drochner u_int newstate = SUN_EMUL_STATE_CONTROL; 466 1.1 drochner u_int i; 467 1.1 drochner 468 1.1 drochner switch (c) { 469 1.1 drochner case '0': case '1': case '2': case '3': case '4': /* argument digit */ 470 1.1 drochner case '5': case '6': case '7': case '8': case '9': 471 1.1 drochner edp->args[0] = (edp->args[0] * 10) + (c - '0'); 472 1.1 drochner break; 473 1.1 drochner 474 1.1 drochner case ';': /* argument terminator */ 475 1.1 drochner for (i = 1; i < SUN_EMUL_NARGS; i++) 476 1.1 drochner edp->args[i] = edp->args[i - 1]; 477 1.1 drochner edp->args[0] = 0; 478 1.1 drochner break; 479 1.1 drochner 480 1.1 drochner default: /* end of escape sequence */ 481 1.1 drochner wsemul_sun_control(edp, c); 482 1.1 drochner newstate = SUN_EMUL_STATE_NORMAL; 483 1.1 drochner break; 484 1.1 drochner } 485 1.1 drochner return (newstate); 486 1.1 drochner } 487 1.1 drochner 488 1.1 drochner void 489 1.13 augustss wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel) 490 1.1 drochner { 491 1.1 drochner struct wsemul_sun_emuldata *edp = cookie; 492 1.1 drochner u_int newstate; 493 1.1 drochner 494 1.3 drochner #ifdef DIAGNOSTIC 495 1.3 drochner if (kernel && !edp->console) 496 1.3 drochner panic("wsemul_sun_output: kernel output, not console"); 497 1.3 drochner #endif 498 1.3 drochner 499 1.1 drochner /* XXX */ 500 1.1 drochner (*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol); 501 1.1 drochner for (; count > 0; data++, count--) { 502 1.3 drochner if (kernel) { 503 1.3 drochner wsemul_sun_output_normal(edp, *data, 1); 504 1.3 drochner continue; 505 1.3 drochner } 506 1.1 drochner switch (edp->state) { 507 1.1 drochner case SUN_EMUL_STATE_NORMAL: 508 1.1 drochner /* XXX SCAN INPUT FOR NEWLINES, DO PRESCROLLING */ 509 1.3 drochner newstate = wsemul_sun_output_normal(edp, *data, 0); 510 1.1 drochner break; 511 1.1 drochner case SUN_EMUL_STATE_HAVEESC: 512 1.1 drochner newstate = wsemul_sun_output_haveesc(edp, *data); 513 1.1 drochner break; 514 1.1 drochner case SUN_EMUL_STATE_CONTROL: 515 1.1 drochner newstate = wsemul_sun_output_control(edp, *data); 516 1.1 drochner break; 517 1.1 drochner default: 518 1.1 drochner #ifdef DIAGNOSTIC 519 1.17 provos panic("wsemul_sun: invalid state %d", edp->state); 520 1.1 drochner #endif 521 1.1 drochner /* try to recover, if things get screwed up... */ 522 1.3 drochner newstate = wsemul_sun_output_normal(edp, *data, 0); 523 1.1 drochner break; 524 1.1 drochner } 525 1.1 drochner edp->state = newstate; 526 1.1 drochner } 527 1.1 drochner /* XXX */ 528 1.1 drochner (*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol); 529 1.6 drochner } 530 1.6 drochner 531 1.22 christos static const char *sun_fkeys[] = { 532 1.6 drochner "\033[224z", /* F1 */ 533 1.6 drochner "\033[225z", 534 1.6 drochner "\033[226z", 535 1.6 drochner "\033[227z", 536 1.6 drochner "\033[228z", 537 1.6 drochner "\033[229z", 538 1.6 drochner "\033[230z", 539 1.6 drochner "\033[231z", 540 1.6 drochner "\033[232z", 541 1.6 drochner "\033[233z", /* F10 */ 542 1.6 drochner }; 543 1.6 drochner 544 1.6 drochner int 545 1.26 christos wsemul_sun_translate(void *cookie, keysym_t in, const char **out) 546 1.6 drochner { 547 1.6 drochner static char c; 548 1.6 drochner 549 1.27 drochner if (KS_GROUP(in) == KS_GROUP_Plain) { 550 1.27 drochner /* allow ISO-1 */ 551 1.27 drochner c = KS_VALUE(in); 552 1.27 drochner *out = &c; 553 1.27 drochner return (1); 554 1.27 drochner } 555 1.27 drochner 556 1.6 drochner if (KS_GROUP(in) == KS_GROUP_Keypad && (in & 0x80) == 0) { 557 1.6 drochner c = in & 0xff; /* turn into ASCII */ 558 1.6 drochner *out = &c; 559 1.6 drochner return (1); 560 1.6 drochner } 561 1.6 drochner 562 1.6 drochner if (in >= KS_f1 && in <= KS_f10) { 563 1.6 drochner *out = sun_fkeys[in - KS_f1]; 564 1.6 drochner return (6); 565 1.6 drochner } 566 1.6 drochner if (in >= KS_F1 && in <= KS_F10) { 567 1.6 drochner *out = sun_fkeys[in - KS_F1]; 568 1.6 drochner return (6); 569 1.6 drochner } 570 1.6 drochner if (in >= KS_KP_F1 && in <= KS_KP_F4) { 571 1.6 drochner *out = sun_fkeys[in - KS_KP_F1]; 572 1.6 drochner return (6); 573 1.6 drochner } 574 1.6 drochner 575 1.6 drochner switch (in) { 576 1.16 junyoung case KS_Home: 577 1.16 junyoung case KS_KP_Home: 578 1.16 junyoung case KS_KP_Begin: 579 1.6 drochner *out = "\033[214z"; 580 1.6 drochner return (6); 581 1.28 jdc case KS_End: 582 1.28 jdc case KS_KP_End: 583 1.28 jdc *out = "\033[220z"; 584 1.28 jdc return (6); 585 1.16 junyoung case KS_Prior: 586 1.16 junyoung case KS_KP_Prior: 587 1.6 drochner *out = "\033[216z"; 588 1.6 drochner return (6); 589 1.16 junyoung case KS_Next: 590 1.16 junyoung case KS_KP_Next: 591 1.6 drochner *out = "\033[222z"; 592 1.6 drochner return (6); 593 1.16 junyoung case KS_Up: 594 1.16 junyoung case KS_KP_Up: 595 1.6 drochner *out = "\033[A"; 596 1.6 drochner return (3); 597 1.16 junyoung case KS_Down: 598 1.16 junyoung case KS_KP_Down: 599 1.6 drochner *out = "\033[B"; 600 1.6 drochner return (3); 601 1.16 junyoung case KS_Left: 602 1.16 junyoung case KS_KP_Left: 603 1.6 drochner *out = "\033[D"; 604 1.6 drochner return (3); 605 1.16 junyoung case KS_Right: 606 1.16 junyoung case KS_KP_Right: 607 1.6 drochner *out = "\033[C"; 608 1.6 drochner return (3); 609 1.16 junyoung case KS_KP_Delete: 610 1.6 drochner *out = "\177"; 611 1.6 drochner return (1); 612 1.6 drochner } 613 1.6 drochner return (0); 614 1.1 drochner } 615 1.1 drochner 616 1.1 drochner void 617 1.14 veego wsemul_sun_detach(void *cookie, u_int *crowp, u_int *ccolp) 618 1.1 drochner { 619 1.1 drochner struct wsemul_sun_emuldata *edp = cookie; 620 1.1 drochner 621 1.1 drochner *crowp = edp->crow; 622 1.1 drochner *ccolp = edp->ccol; 623 1.1 drochner if (edp != &wsemul_sun_console_emuldata) 624 1.1 drochner free(edp, M_DEVBUF); 625 1.10 drochner } 626 1.10 drochner 627 1.10 drochner void 628 1.13 augustss wsemul_sun_resetop(void *cookie, enum wsemul_resetops op) 629 1.10 drochner { 630 1.10 drochner struct wsemul_sun_emuldata *edp = cookie; 631 1.10 drochner 632 1.10 drochner switch (op) { 633 1.10 drochner case WSEMUL_RESET: 634 1.10 drochner edp->state = SUN_EMUL_STATE_NORMAL; 635 1.10 drochner edp->scrolldist = 1; 636 1.10 drochner edp->rendflags = 0; 637 1.10 drochner edp->curattr = edp->defattr; 638 1.10 drochner break; 639 1.10 drochner case WSEMUL_CLEARSCREEN: 640 1.10 drochner (*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows, 641 1.10 drochner edp->defattr); 642 1.10 drochner edp->ccol = edp->crow = 0; 643 1.10 drochner (*edp->emulops->cursor)(edp->emulcookie, 1, 0, 0); 644 1.10 drochner break; 645 1.10 drochner default: 646 1.10 drochner break; 647 1.10 drochner } 648 1.1 drochner } 649