root/dev/wscons/wsemul_sun.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wsemul_sun_init
  2. wsemul_sun_reset
  3. wsemul_sun_cnattach
  4. wsemul_sun_attach
  5. wsemul_sun_output_lowchars
  6. wsemul_sun_output_normal
  7. wsemul_sun_output_haveesc
  8. wsemul_sun_control
  9. wsemul_sun_output_control
  10. wsemul_sun_output
  11. wsemul_sun_selectattribute
  12. wsemul_sun_translate
  13. wsemul_sun_detach
  14. wsemul_sun_resetop
  15. wsemul_sun_scrollup

    1 /* $OpenBSD: wsemul_sun.c,v 1.20 2007/02/14 01:12:16 jsg Exp $ */
    2 /* $NetBSD: wsemul_sun.c,v 1.11 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 /*
   35  * This file implements a sun terminal personality for wscons.
   36  *
   37  * Derived from old rcons code.
   38  * Color support from NetBSD's rcons color code, and wsemul_vt100.
   39  */
   40 
   41 #ifndef SMALL_KERNEL
   42 #define JUMP_SCROLL
   43 #endif
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/time.h>
   48 #include <sys/malloc.h>
   49 #include <sys/fcntl.h>
   50 
   51 #include <dev/wscons/wsconsio.h>
   52 #include <dev/wscons/wsdisplayvar.h>
   53 #include <dev/wscons/wsemulvar.h>
   54 #include <dev/wscons/wsksymdef.h>
   55 #include <dev/wscons/ascii.h>
   56 
   57 void    *wsemul_sun_cnattach(const struct wsscreen_descr *, void *,
   58     int, int, long);
   59 void    *wsemul_sun_attach(int, const struct wsscreen_descr *,
   60     void *, int, int, void *, long);
   61 void    wsemul_sun_output(void *, const u_char *, u_int, int);
   62 int     wsemul_sun_translate(void *, keysym_t, char **);
   63 void    wsemul_sun_detach(void *, u_int *, u_int *);
   64 void    wsemul_sun_resetop(void *, enum wsemul_resetops);
   65 
   66 const struct wsemul_ops wsemul_sun_ops = {
   67         "sun",
   68         wsemul_sun_cnattach,
   69         wsemul_sun_attach,
   70         wsemul_sun_output,
   71         wsemul_sun_translate,
   72         wsemul_sun_detach,
   73         wsemul_sun_resetop
   74 };
   75 
   76 #define SUN_EMUL_STATE_NORMAL   0       /* normal processing */
   77 #define SUN_EMUL_STATE_HAVEESC  1       /* seen start of ctl seq */
   78 #define SUN_EMUL_STATE_CONTROL  2       /* processing ctl seq */
   79 
   80 #define SUN_EMUL_NARGS  2               /* max # of args to a command */
   81 
   82 struct wsemul_sun_emuldata {
   83         const struct wsdisplay_emulops *emulops;
   84         void *emulcookie;
   85         void *cbcookie;
   86         int scrcapabilities;
   87         u_int nrows, ncols, crow, ccol;
   88         long defattr;                   /* default attribute (rendition) */
   89 
   90         u_int state;                    /* processing state */
   91         u_int args[SUN_EMUL_NARGS];     /* command args, if CONTROL */
   92         int nargs;                      /* number of args */
   93 
   94         u_int scrolldist;               /* distance to scroll */
   95         long curattr, bkgdattr;         /* currently used attribute */
   96         long kernattr;                  /* attribute for kernel output */
   97         int attrflags, fgcol, bgcol;    /* properties of curattr */
   98 
   99 #ifdef DIAGNOSTIC
  100         int console;
  101 #endif
  102 };
  103 
  104 void wsemul_sun_init(struct wsemul_sun_emuldata *,
  105     const struct wsscreen_descr *, void *, int, int, long);
  106 void wsemul_sun_reset(struct wsemul_sun_emuldata *);
  107 void wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *, u_char, int);
  108 void wsemul_sun_output_normal(struct wsemul_sun_emuldata *, u_char, int);
  109 u_int wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *, u_char);
  110 u_int wsemul_sun_output_control(struct wsemul_sun_emuldata *, u_char);
  111 void wsemul_sun_control(struct wsemul_sun_emuldata *, u_char);
  112 int wsemul_sun_selectattribute(struct wsemul_sun_emuldata *, int, int, int,
  113     long *, long *);
  114 void wsemul_sun_scrollup(struct wsemul_sun_emuldata *, u_int);
  115 
  116 struct wsemul_sun_emuldata wsemul_sun_console_emuldata;
  117 
  118 /* some useful utility macros */
  119 #define ARG(n,c) \
  120         ((n) >= edp->nargs ? 0 : edp->args[(n) + MAX(0, edp->nargs - (c))])
  121 #define NORMALIZE(arg)          ((arg) != 0 ? (arg) : 1)
  122 #define COLS_LEFT               (edp->ncols - 1 - edp->ccol)
  123 #define ROWS_LEFT               (edp->nrows - 1 - edp->crow)
  124 
  125 void
  126 wsemul_sun_init(edp, type, cookie, ccol, crow, defattr)
  127         struct wsemul_sun_emuldata *edp;
  128         const struct wsscreen_descr *type;
  129         void *cookie;
  130         int ccol, crow;
  131         long defattr;
  132 {
  133         edp->emulops = type->textops;
  134         edp->emulcookie = cookie;
  135         edp->scrcapabilities = type->capabilities;
  136         edp->nrows = type->nrows;
  137         edp->ncols = type->ncols;
  138         edp->crow = crow;
  139         edp->ccol = ccol;
  140         edp->defattr = defattr;
  141 }
  142 
  143 void
  144 wsemul_sun_reset(edp)
  145         struct wsemul_sun_emuldata *edp;
  146 {
  147         edp->state = SUN_EMUL_STATE_NORMAL;
  148         edp->bkgdattr = edp->curattr = edp->defattr;
  149         edp->attrflags = 0;
  150         edp->fgcol = WSCOL_BLACK;
  151         edp->bgcol = WSCOL_WHITE;
  152         edp->scrolldist = 1;
  153 }
  154 
  155 void *
  156 wsemul_sun_cnattach(type, cookie, ccol, crow, defattr)
  157         const struct wsscreen_descr *type;
  158         void *cookie;
  159         int ccol, crow;
  160         long defattr;
  161 {
  162         struct wsemul_sun_emuldata *edp;
  163         int res;
  164 
  165         edp = &wsemul_sun_console_emuldata;
  166         wsemul_sun_init(edp, type, cookie, ccol, crow, defattr);
  167 
  168 #ifndef WS_KERNEL_FG
  169 #define WS_KERNEL_FG WSCOL_BLACK
  170 #endif
  171 #ifndef WS_KERNEL_BG
  172 #define WS_KERNEL_BG WSCOL_WHITE
  173 #endif
  174 #ifndef WS_KERNEL_COLATTR
  175 #define WS_KERNEL_COLATTR 0
  176 #endif
  177 #ifndef WS_KERNEL_MONOATTR
  178 #define WS_KERNEL_MONOATTR 0
  179 #endif
  180         if (type->capabilities & WSSCREEN_WSCOLORS)
  181                 res = (*edp->emulops->alloc_attr)(cookie,
  182                                             WS_KERNEL_FG, WS_KERNEL_BG,
  183                                             WS_KERNEL_COLATTR | WSATTR_WSCOLORS,
  184                                             &edp->kernattr);
  185         else
  186                 res = (*edp->emulops->alloc_attr)(cookie, 0, 0,
  187                                             WS_KERNEL_MONOATTR,
  188                                             &edp->kernattr);
  189         if (res)
  190                 edp->kernattr = defattr;
  191 
  192         edp->cbcookie = NULL;
  193 
  194 #ifdef DIAGNOSTIC
  195         edp->console = 1;
  196 #endif
  197 
  198         wsemul_sun_reset(edp);
  199         return (edp);
  200 }
  201 
  202 void *
  203 wsemul_sun_attach(console, type, cookie, ccol, crow, cbcookie, defattr)
  204         int console;
  205         const struct wsscreen_descr *type;
  206         void *cookie;
  207         int ccol, crow;
  208         void *cbcookie;
  209         long defattr;
  210 {
  211         struct wsemul_sun_emuldata *edp;
  212 
  213         if (console) {
  214                 edp = &wsemul_sun_console_emuldata;
  215 #ifdef DIAGNOSTIC
  216                 KASSERT(edp->console == 1);
  217 #endif
  218         } else {
  219                 edp = malloc(sizeof *edp, M_DEVBUF, M_NOWAIT);
  220                 if (edp == NULL)
  221                         return (NULL);
  222                 wsemul_sun_init(edp, type, cookie, ccol, crow, defattr);
  223 
  224 #ifdef DIAGNOSTIC
  225                 edp->console = 0;
  226 #endif
  227         }
  228 
  229         edp->cbcookie = cbcookie;
  230 
  231         wsemul_sun_reset(edp);
  232         return (edp);
  233 }
  234 
  235 void
  236 wsemul_sun_output_lowchars(edp, c, kernel)
  237         struct wsemul_sun_emuldata *edp;
  238         u_char c;
  239         int kernel;
  240 {
  241         u_int n;
  242 
  243         switch (c) {
  244         case ASCII_NUL:
  245         default:
  246                 /* ignore */
  247                 break;
  248 
  249         case ASCII_BEL:         /* "Bell (BEL)" */
  250                 wsdisplay_emulbell(edp->cbcookie);
  251                 break;
  252 
  253         case ASCII_BS:          /* "Backspace (BS)" */
  254                 if (edp->ccol > 0)
  255                         edp->ccol--;
  256                 break;
  257 
  258         case ASCII_CR:          /* "Return (CR)" */
  259                 edp->ccol = 0;
  260                 break;
  261 
  262         case ASCII_HT:          /* "Tab (TAB)" */
  263                 n = min(8 - (edp->ccol & 7), COLS_LEFT);
  264                 if (n != 0) {
  265                         (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
  266                             edp->ccol, n,
  267                             kernel ? edp->kernattr : edp->bkgdattr);
  268                         edp->ccol += n;
  269                 }
  270                 break;
  271 
  272         case ASCII_FF:          /* "Form Feed (FF)" */
  273                 (*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows,
  274                     edp->bkgdattr);
  275                 edp->ccol = edp->crow = 0;
  276                 break;
  277 
  278         case ASCII_VT:          /* "Reverse Line Feed" */
  279                 if (edp->crow > 0)
  280                         edp->crow--;
  281                 break;
  282 
  283         case ASCII_ESC:         /* "Escape (ESC)" */
  284                 if (kernel) {
  285                         printf("wsemul_sun_output_lowchars: ESC in kernel "
  286                             "output ignored\n");
  287                         break;  /* ignore the ESC */
  288                 }
  289 
  290                 edp->state = SUN_EMUL_STATE_HAVEESC;
  291                 break;
  292 
  293         case ASCII_LF:          /* "Line Feed (LF)" */
  294                 /* if the cur line isn't the last, incr and leave. */
  295                 if (ROWS_LEFT > 0)
  296                         edp->crow++;
  297                 else
  298                         wsemul_sun_scrollup(edp, edp->scrolldist);
  299                 break;
  300         }
  301 }
  302 
  303 void
  304 wsemul_sun_output_normal(edp, c, kernel)
  305         struct wsemul_sun_emuldata *edp;
  306         u_char c;
  307         int kernel;
  308 {
  309 
  310         (*edp->emulops->putchar)(edp->emulcookie, edp->crow, edp->ccol,
  311             c, kernel ? edp->kernattr : edp->curattr);
  312 
  313         if (++edp->ccol >= edp->ncols) {
  314                 /* if the cur line isn't the last, incr and leave. */
  315                 if (ROWS_LEFT > 0)
  316                         edp->crow++;
  317                 else
  318                         wsemul_sun_scrollup(edp, edp->scrolldist);
  319                 edp->ccol = 0;
  320         }
  321 }
  322 
  323 u_int
  324 wsemul_sun_output_haveesc(edp, c)
  325         struct wsemul_sun_emuldata *edp;
  326         u_char c;
  327 {
  328         u_int newstate;
  329 
  330         switch (c) {
  331         case '[':               /* continuation of multi-char sequence */
  332                 edp->nargs = 0;
  333                 bzero(edp->args, sizeof (edp->args));
  334                 newstate = SUN_EMUL_STATE_CONTROL;
  335                 break;
  336 
  337         default:
  338 #ifdef DEBUG
  339                 printf("ESC%c unknown\n", c);
  340 #endif
  341                 newstate = SUN_EMUL_STATE_NORMAL;       /* XXX is this wise? */
  342                 break;
  343         }
  344 
  345         return (newstate);
  346 }
  347 
  348 void
  349 wsemul_sun_control(edp, c)
  350         struct wsemul_sun_emuldata *edp;
  351         u_char c;
  352 {
  353         u_int n, src, dst;
  354         int flags, fgcol, bgcol;
  355         long attr, bkgdattr;
  356 
  357         switch (c) {
  358         case '@':               /* "Insert Character (ICH)" */
  359                 n = min(NORMALIZE(ARG(0,1)), COLS_LEFT + 1);
  360                 src = edp->ccol;
  361                 dst = edp->ccol + n;
  362                 if (dst < edp->ncols) {
  363                         (*edp->emulops->copycols)(edp->emulcookie, edp->crow,
  364                             src, dst, edp->ncols - dst);
  365                 }
  366                 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
  367                     src, n, edp->bkgdattr);
  368                 break;
  369 
  370         case 'A':               /* "Cursor Up (CUU)" */
  371                 edp->crow -= min(NORMALIZE(ARG(0,1)), edp->crow);
  372                 break;
  373 
  374         case 'E':               /* "Cursor Next Line (CNL)" */
  375                 edp->ccol = 0;
  376                 /* FALLTHROUGH */
  377         case 'B':               /* "Cursor Down (CUD)" */
  378                 edp->crow += min(NORMALIZE(ARG(0,1)), ROWS_LEFT);
  379                 break;
  380 
  381         case 'C':               /* "Cursor Forward (CUF)" */
  382                 edp->ccol += min(NORMALIZE(ARG(0,1)), COLS_LEFT);
  383                 break;
  384 
  385         case 'D':               /* "Cursor Backward (CUB)" */
  386                 edp->ccol -= min(NORMALIZE(ARG(0,1)), edp->ccol);
  387                 break;
  388 
  389         case 'f':               /* "Horizontal And Vertical Position (HVP)" */
  390         case 'H':               /* "Cursor Position (CUP)" */
  391                 edp->crow = min(NORMALIZE(ARG(0,2)), edp->nrows) - 1;
  392                 edp->ccol = min(NORMALIZE(ARG(1,2)), edp->ncols) - 1;
  393                 break;
  394 
  395         case 'J':               /* "Erase in Display (ED)" */
  396                 if (ROWS_LEFT > 0) {
  397                         (*edp->emulops->eraserows)(edp->emulcookie,
  398                              edp->crow + 1, ROWS_LEFT, edp->bkgdattr);
  399                 }
  400                 /* FALLTHROUGH */
  401         case 'K':               /* "Erase in Line (EL)" */
  402                 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
  403                     edp->ccol, COLS_LEFT + 1, edp->bkgdattr);
  404                 break;
  405 
  406         case 'L':               /* "Insert Line (IL)" */
  407                 n = min(NORMALIZE(ARG(0,1)), ROWS_LEFT + 1);
  408                 src = edp->crow;
  409                 dst = edp->crow + n;
  410                 if (dst < edp->nrows) {
  411                         (*edp->emulops->copyrows)(edp->emulcookie,
  412                             src, dst, edp->nrows - dst);
  413                 }
  414                 (*edp->emulops->eraserows)(edp->emulcookie,
  415                     src, n, edp->bkgdattr);
  416                 break;
  417 
  418         case 'M':               /* "Delete Line (DL)" */
  419                 n = min(NORMALIZE(ARG(0,1)), ROWS_LEFT + 1);
  420                 src = edp->crow + n;
  421                 dst = edp->crow;
  422                 if (src < edp->nrows) {
  423                         (*edp->emulops->copyrows)(edp->emulcookie,
  424                             src, dst, edp->nrows - src);
  425                 }
  426                 (*edp->emulops->eraserows)(edp->emulcookie,
  427                     dst + edp->nrows - src, n, edp->bkgdattr);
  428                 break;
  429 
  430         case 'P':               /* "Delete Character (DCH)" */
  431                 n = min(NORMALIZE(ARG(0,1)), COLS_LEFT + 1);
  432                 src = edp->ccol + n;
  433                 dst = edp->ccol;
  434                 if (src < edp->ncols) {
  435                         (*edp->emulops->copycols)(edp->emulcookie, edp->crow,
  436                             src, dst, edp->ncols - src);
  437                 }
  438                 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
  439                     edp->ncols - n, n, edp->bkgdattr);
  440                 break;
  441 
  442         case 'm':               /* "Select Graphic Rendition (SGR)" */
  443                 flags = edp->attrflags;
  444                 fgcol = edp->fgcol;
  445                 bgcol = edp->bgcol;
  446 
  447                 for (n = 0; n < edp->nargs; n++) {
  448                         switch (ARG(n,edp->nargs)) {
  449                         /* Clear all attributes || End underline */
  450                         case 0:
  451                                 if (n == edp->nargs - 1) {
  452                                         edp->bkgdattr =
  453                                             edp->curattr = edp->defattr;
  454                                         edp->attrflags = 0;
  455                                         edp->fgcol = WSCOL_BLACK;
  456                                         edp->bgcol = WSCOL_WHITE;
  457                                         return;
  458                                 }
  459                                 flags = 0;
  460                                 fgcol = WSCOL_BLACK;
  461                                 bgcol = WSCOL_WHITE;
  462                                 break;
  463                         /* Begin bold */
  464                         case 1:
  465                                 flags |= WSATTR_HILIT;
  466                                 break;
  467                         /* Begin underline */
  468                         case 4:
  469                                 flags |= WSATTR_UNDERLINE;
  470                                 break;
  471                         /* Begin reverse */
  472                         case 7:
  473                                 flags |= WSATTR_REVERSE;
  474                                 break;
  475                         /* ANSI foreground color */
  476                         case 30: case 31: case 32: case 33:
  477                         case 34: case 35: case 36: case 37:
  478                                 fgcol = ARG(n,edp->nargs) - 30;
  479                                 break;
  480                         /* ANSI background color */
  481                         case 40: case 41: case 42: case 43:
  482                         case 44: case 45: case 46: case 47:
  483                                 bgcol = ARG(n,edp->nargs) - 40;
  484                                 break;
  485                         }
  486                 }
  487 setattr:
  488                 if (wsemul_sun_selectattribute(edp, flags, fgcol, bgcol, &attr,
  489                     &bkgdattr)) {
  490 #ifdef DEBUG
  491                         printf("error allocating attr %d/%d/%x\n",
  492                             fgcol, bgcol, flags);
  493 #endif
  494                 } else {
  495                         edp->curattr = attr;
  496                         edp->bkgdattr = bkgdattr;
  497                         edp->attrflags = flags;
  498                         edp->fgcol = fgcol;
  499                         edp->bgcol = bgcol;
  500                 }
  501                 break;
  502 
  503         case 'p':               /* "Black On White (SUNBOW)" */
  504                 flags = 0;
  505                 fgcol = WSCOL_BLACK;
  506                 bgcol = WSCOL_WHITE;
  507                 goto setattr;
  508 
  509         case 'q':               /* "White On Black (SUNWOB)" */
  510                 flags = 0;
  511                 fgcol = WSCOL_WHITE;
  512                 bgcol = WSCOL_BLACK;
  513                 goto setattr;
  514 
  515         case 'r':               /* "Set Scrolling (SUNSCRL)" */
  516                 edp->scrolldist = min(ARG(0,1), edp->nrows);
  517                 break;
  518 
  519         case 's':               /* "Reset Terminal Emulator (SUNRESET)" */
  520                 wsemul_sun_reset(edp);
  521                 break;
  522         }
  523 }
  524 
  525 u_int
  526 wsemul_sun_output_control(edp, c)
  527         struct wsemul_sun_emuldata *edp;
  528         u_char c;
  529 {
  530         u_int newstate = SUN_EMUL_STATE_CONTROL;
  531 
  532         switch (c) {
  533         case '0': case '1': case '2': case '3': case '4': /* argument digit */
  534         case '5': case '6': case '7': case '8': case '9':
  535                 /*
  536                  * If we receive more arguments than we are expecting,
  537                  * discard the earliest arguments.
  538                  */
  539                 if (edp->nargs > SUN_EMUL_NARGS - 1) {
  540                         bcopy(edp->args + 1, edp->args,
  541                             (SUN_EMUL_NARGS - 1) * sizeof(edp->args[0]));
  542                         edp->args[edp->nargs = SUN_EMUL_NARGS - 1] = 0;
  543                 }
  544                 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
  545                     (c - '0');
  546                 break;
  547 
  548         case ';':               /* argument terminator */
  549                 edp->nargs++;
  550                 break;
  551 
  552         default:                /* end of escape sequence */
  553                 edp->nargs++;
  554                 if (edp->nargs > SUN_EMUL_NARGS)
  555                         edp->nargs = SUN_EMUL_NARGS;
  556                 wsemul_sun_control(edp, c);
  557                 newstate = SUN_EMUL_STATE_NORMAL;
  558                 break;
  559         }
  560         return (newstate);
  561 }
  562 
  563 void
  564 wsemul_sun_output(cookie, data, count, kernel)
  565         void *cookie;
  566         const u_char *data;
  567         u_int count;
  568         int kernel;
  569 {
  570         struct wsemul_sun_emuldata *edp = cookie;
  571         u_int newstate;
  572 #ifdef JUMP_SCROLL
  573         const u_char *eot;
  574         u_char curchar;
  575         u_int cnt, pos, lines;
  576 #endif
  577 
  578 #ifdef DIAGNOSTIC
  579         if (kernel && !edp->console)
  580                 panic("wsemul_sun_output: kernel output, not console");
  581 #endif
  582 
  583         /* XXX */
  584         (*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol);
  585 
  586         for (; count > 0; data++, count--) {
  587 #ifdef JUMP_SCROLL
  588                 /*
  589                  * If scrolling is not disabled and we are the bottom of
  590                  * the screen, count newlines until an escape sequence
  591                  * appears.
  592                  */
  593                 if ((edp->state == SUN_EMUL_STATE_NORMAL || kernel) &&
  594                     ROWS_LEFT == 0 && edp->scrolldist != 0) {
  595                         lines = 0;
  596                         pos = edp->ccol;
  597                         for (eot = data, cnt = count; cnt != 0; eot++, cnt--) {
  598                                 curchar = *eot;
  599                                 if (curchar == ASCII_FF ||
  600                                     curchar == ASCII_VT || curchar == ASCII_ESC)
  601                                         break;
  602 
  603                                 switch (curchar) {
  604                                 case ASCII_BS:
  605                                         if (pos > 0)
  606                                                 pos--;
  607                                         break;
  608                                 case ASCII_CR:
  609                                         pos = 0;
  610                                         break;
  611                                 case ASCII_HT:
  612                                         pos = (pos + 7) & ~7;
  613                                         if (pos >= edp->ncols)
  614                                                 pos = edp->ncols - 1;
  615                                         break;
  616                                 default:
  617                                         if (++pos >= edp->ncols) {
  618                                                 pos = 0;
  619                                                 curchar = ASCII_LF;
  620                                         }
  621                                         break;
  622                                 }
  623                                 if (curchar == ASCII_LF) {
  624                                         if (++lines >= edp->nrows - 1)
  625                                                 break;
  626                                 }
  627                         }
  628 
  629                         if (lines > 1) {
  630                                 wsemul_sun_scrollup(edp, lines);
  631                                 edp->crow--;
  632                         }
  633                 }
  634 #endif
  635 
  636                 if (*data < ' ') {
  637                         wsemul_sun_output_lowchars(edp, *data, kernel);
  638                         continue;
  639                 }
  640 
  641                 if (kernel) {
  642                         wsemul_sun_output_normal(edp, *data, 1);
  643                         continue;
  644                 }
  645 
  646                 switch (newstate = edp->state) {
  647                 case SUN_EMUL_STATE_NORMAL:
  648                         wsemul_sun_output_normal(edp, *data, 0);
  649                         break;
  650                 case SUN_EMUL_STATE_HAVEESC:
  651                         newstate = wsemul_sun_output_haveesc(edp, *data);
  652                         break;
  653                 case SUN_EMUL_STATE_CONTROL:
  654                         newstate = wsemul_sun_output_control(edp, *data);
  655                         break;
  656                 default:
  657 #ifdef DIAGNOSTIC
  658                         panic("wsemul_sun: invalid state %d", edp->state);
  659 #else
  660                         /* try to recover, if things get screwed up... */
  661                         newstate = SUN_EMUL_STATE_NORMAL;
  662                         wsemul_sun_output_normal(edp, *data, 0);
  663 #endif
  664                         break;
  665                 }
  666                 edp->state = newstate;
  667         }
  668         /* XXX */
  669         (*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol);
  670 }
  671 
  672 
  673 /*
  674  * Get an attribute from the graphics driver.
  675  * Try to find replacements if the desired appearance is not supported.
  676  */
  677 int
  678 wsemul_sun_selectattribute(edp, flags, fgcol, bgcol, attr, bkgdattr)
  679         struct wsemul_sun_emuldata *edp;
  680         int flags, fgcol, bgcol;
  681         long *attr, *bkgdattr;
  682 {
  683         int error;
  684 
  685         /*
  686          * Rasops will force white on black as normal output colors, unless
  687          * WSATTR_WSCOLORS is specified. Since Sun console is black on white,
  688          * always use WSATTR_WSCOLORS and our colors, as we know better.
  689          */
  690         if (!(edp->scrcapabilities & WSSCREEN_WSCOLORS)) {
  691                 flags &= ~WSATTR_WSCOLORS;
  692         } else {
  693                 flags |= WSATTR_WSCOLORS;
  694         }
  695 
  696         error = (*edp->emulops->alloc_attr)(edp->emulcookie, fgcol, bgcol,
  697                                             flags & WSATTR_WSCOLORS, bkgdattr);
  698         if (error)
  699                 return (error);
  700 
  701         if ((flags & WSATTR_HILIT) &&
  702             !(edp->scrcapabilities & WSSCREEN_HILIT)) {
  703                 flags &= ~WSATTR_HILIT;
  704                 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) {
  705                         fgcol = WSCOL_RED;
  706                         flags |= WSATTR_WSCOLORS;
  707                 }
  708         }
  709         if ((flags & WSATTR_UNDERLINE) &&
  710             !(edp->scrcapabilities & WSSCREEN_UNDERLINE)) {
  711                 flags &= ~WSATTR_UNDERLINE;
  712                 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) {
  713                         fgcol = WSCOL_CYAN;
  714                         flags &= ~WSATTR_UNDERLINE;
  715                         flags |= WSATTR_WSCOLORS;
  716                 }
  717         }
  718         if ((flags & WSATTR_BLINK) &&
  719             !(edp->scrcapabilities & WSSCREEN_BLINK)) {
  720                 flags &= ~WSATTR_BLINK;
  721         }
  722         if ((flags & WSATTR_REVERSE) &&
  723             !(edp->scrcapabilities & WSSCREEN_REVERSE)) {
  724                 flags &= ~WSATTR_REVERSE;
  725                 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) {
  726                         int help;
  727                         help = bgcol;
  728                         bgcol = fgcol;
  729                         fgcol = help;
  730                         flags |= WSATTR_WSCOLORS;
  731                 }
  732         }
  733         error = (*edp->emulops->alloc_attr)(edp->emulcookie, fgcol, bgcol,
  734                                             flags, attr);
  735         if (error)
  736                 return (error);
  737 
  738         return (0);
  739 }
  740 
  741 static char *sun_fkeys[] = {
  742         "\033[224z",    /* F1 */
  743         "\033[225z",
  744         "\033[226z",
  745         "\033[227z",
  746         "\033[228z",
  747         "\033[229z",
  748         "\033[230z",
  749         "\033[231z",
  750         "\033[232z",
  751         "\033[233z",
  752         "\033[234z",
  753         "\033[235z",    /* F12 */
  754 };
  755 
  756 static char *sun_lkeys[] = {
  757         "\033[207z",    /* KS_Help */
  758         NULL,           /* KS_Execute */
  759         "\033[200z",    /* KS_Find */
  760         NULL,           /* KS_Select */
  761         "\033[193z",    /* KS_Again */
  762         "\033[194z",    /* KS_Props */
  763         "\033[195z",    /* KS_Undo */
  764         "\033[196z",    /* KS_Front */
  765         "\033[197z",    /* KS_Copy */
  766         "\033[198z",    /* KS_Open */
  767         "\033[199z",    /* KS_Paste */
  768         "\033[201z",    /* KS_Cut */
  769 };
  770 
  771 int
  772 wsemul_sun_translate(cookie, in, out)
  773         void *cookie;
  774         keysym_t in;
  775         char **out;
  776 {
  777         static char c;
  778 
  779         if (KS_GROUP(in) == KS_GROUP_Keypad && (in & 0x80) == 0) {
  780                 c = in & 0xff; /* turn into ASCII */
  781                 *out = &c;
  782                 return (1);
  783         }
  784 
  785         if (in >= KS_f1 && in <= KS_f12) {
  786                 *out = sun_fkeys[in - KS_f1];
  787                 return (6);
  788         }
  789         if (in >= KS_F1 && in <= KS_F12) {
  790                 *out = sun_fkeys[in - KS_F1];
  791                 return (6);
  792         }
  793         if (in >= KS_KP_F1 && in <= KS_KP_F4) {
  794                 *out = sun_fkeys[in - KS_KP_F1];
  795                 return (6);
  796         }
  797         if (in >= KS_Help && in <= KS_Cut && sun_lkeys[in - KS_Help] != NULL) {
  798                 *out = sun_lkeys[in - KS_Help];
  799                 return (6);
  800         }
  801 
  802         switch (in) {
  803         case KS_Home:
  804         case KS_KP_Home:
  805         case KS_KP_Begin:
  806                 *out = "\033[214z";
  807                 return (6);
  808         case KS_End:
  809         case KS_KP_End:
  810                 *out = "\033[220z";
  811                 return (6);
  812         case KS_Insert:
  813         case KS_KP_Insert:
  814                 *out = "\033[247z";
  815                 return (6);
  816         case KS_Prior:
  817         case KS_KP_Prior:
  818                 *out = "\033[216z";
  819                 return (6);
  820         case KS_Next:
  821         case KS_KP_Next:
  822                 *out = "\033[222z";
  823                 return (6);
  824         case KS_Up:
  825         case KS_KP_Up:
  826                 *out = "\033[A";
  827                 return (3);
  828         case KS_Down:
  829         case KS_KP_Down:
  830                 *out = "\033[B";
  831                 return (3);
  832         case KS_Left:
  833         case KS_KP_Left:
  834                 *out = "\033[D";
  835                 return (3);
  836         case KS_Right:
  837         case KS_KP_Right:
  838                 *out = "\033[C";
  839                 return (3);
  840         case KS_KP_Delete:
  841                 *out = "\177";
  842                 return (1);
  843         }
  844         return (0);
  845 }
  846 
  847 void
  848 wsemul_sun_detach(cookie, crowp, ccolp)
  849         void *cookie;
  850         u_int *crowp, *ccolp;
  851 {
  852         struct wsemul_sun_emuldata *edp = cookie;
  853 
  854         *crowp = edp->crow;
  855         *ccolp = edp->ccol;
  856         if (edp != &wsemul_sun_console_emuldata)
  857                 free(edp, M_DEVBUF);
  858 }
  859 
  860 void
  861 wsemul_sun_resetop(cookie, op)
  862         void *cookie;
  863         enum wsemul_resetops op;
  864 {
  865         struct wsemul_sun_emuldata *edp = cookie;
  866 
  867         switch (op) {
  868         case WSEMUL_RESET:
  869                 wsemul_sun_reset(edp);
  870                 break;
  871         case WSEMUL_CLEARSCREEN:
  872                 (*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows,
  873                     edp->bkgdattr);
  874                 edp->ccol = edp->crow = 0;
  875                 (*edp->emulops->cursor)(edp->emulcookie, 1, 0, 0);
  876                 break;
  877         default:
  878                 break;
  879         }
  880 }
  881 
  882 void
  883 wsemul_sun_scrollup(edp, lines)
  884         struct wsemul_sun_emuldata *edp;
  885         u_int lines;
  886 {
  887         /*
  888          * if we're in wrap-around mode, go to the first
  889          * line and clear it.
  890          */
  891         if (lines == 0) {
  892                 edp->crow = 0;
  893                 (*edp->emulops->eraserows)(edp->emulcookie, 0, 1,
  894                     edp->bkgdattr);
  895                 return;
  896         }
  897 
  898         /*
  899          * If the scrolling distance is equal to the screen height
  900          * (usually 34), clear the screen; otherwise, scroll by the
  901          * scrolling distance.
  902          */
  903         if (lines < edp->nrows)
  904                 (*edp->emulops->copyrows)(edp->emulcookie, lines, 0,
  905                     edp->nrows - lines);
  906         (*edp->emulops->eraserows)(edp->emulcookie,
  907             edp->nrows - lines, lines, edp->bkgdattr);
  908         edp->crow -= lines - 1;
  909 }

/* [<][>][^][v][top][bottom][index][help] */