root/dev/wscons/wsemul_vt100.c

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

DEFINITIONS

This source file includes following definitions.
  1. wsemul_vt100_init
  2. wsemul_vt100_cnattach
  3. wsemul_vt100_attach
  4. wsemul_vt100_detach
  5. wsemul_vt100_resetop
  6. wsemul_vt100_reset
  7. wsemul_vt100_nextline
  8. wsemul_vt100_output_normal
  9. wsemul_vt100_output_c0c1
  10. wsemul_vt100_output_esc
  11. wsemul_vt100_output_scs94
  12. wsemul_vt100_output_scs94_percent
  13. wsemul_vt100_output_scs96
  14. wsemul_vt100_output_scs96_percent
  15. wsemul_vt100_output_esc_spc
  16. wsemul_vt100_output_string
  17. wsemul_vt100_output_string_esc
  18. wsemul_vt100_output_dcs
  19. wsemul_vt100_output_dcs_dollar
  20. wsemul_vt100_output_esc_hash
  21. wsemul_vt100_output_csi
  22. wsemul_vt100_output

    1 /* $OpenBSD: wsemul_vt100.c,v 1.18 2007/02/14 01:12:16 jsg Exp $ */
    2 /* $NetBSD: wsemul_vt100.c,v 1.13 2000/04/28 21:56:16 mycroft Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1998
    6  *      Matthias Drochner.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  */
   29 
   30 #ifndef SMALL_KERNEL
   31 #define JUMP_SCROLL
   32 #endif
   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/wsemul_vt100var.h>
   44 #include <dev/wscons/ascii.h>
   45 
   46 void    *wsemul_vt100_cnattach(const struct wsscreen_descr *, void *,
   47                                   int, int, long);
   48 void    *wsemul_vt100_attach(int console, const struct wsscreen_descr *,
   49                                   void *, int, int, void *, long);
   50 void    wsemul_vt100_output(void *cookie, const u_char *data, u_int count,
   51                                  int);
   52 void    wsemul_vt100_detach(void *cookie, u_int *crowp, u_int *ccolp);
   53 void    wsemul_vt100_resetop(void *, enum wsemul_resetops);
   54 
   55 const struct wsemul_ops wsemul_vt100_ops = {
   56         "vt100",
   57         wsemul_vt100_cnattach,
   58         wsemul_vt100_attach,
   59         wsemul_vt100_output,
   60         wsemul_vt100_translate,
   61         wsemul_vt100_detach,
   62         wsemul_vt100_resetop
   63 };
   64 
   65 struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata;
   66 
   67 void wsemul_vt100_init(struct wsemul_vt100_emuldata *,
   68                             const struct wsscreen_descr *, void *, int, int,
   69                             long);
   70 
   71 void wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *, u_char,
   72                                      int);
   73 void wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *, u_char,
   74                                    int);
   75 void wsemul_vt100_nextline(struct wsemul_vt100_emuldata *);
   76 typedef u_int vt100_handler(struct wsemul_vt100_emuldata *, u_char);
   77 vt100_handler
   78 wsemul_vt100_output_esc,
   79 wsemul_vt100_output_csi,
   80 wsemul_vt100_output_scs94,
   81 wsemul_vt100_output_scs94_percent,
   82 wsemul_vt100_output_scs96,
   83 wsemul_vt100_output_scs96_percent,
   84 wsemul_vt100_output_esc_hash,
   85 wsemul_vt100_output_esc_spc,
   86 wsemul_vt100_output_string,
   87 wsemul_vt100_output_string_esc,
   88 wsemul_vt100_output_dcs,
   89 wsemul_vt100_output_dcs_dollar;
   90 
   91 #define VT100_EMUL_STATE_NORMAL         0       /* normal processing */
   92 #define VT100_EMUL_STATE_ESC            1       /* got ESC */
   93 #define VT100_EMUL_STATE_CSI            2       /* got CSI (ESC[) */
   94 #define VT100_EMUL_STATE_SCS94          3       /* got ESC{()*+} */
   95 #define VT100_EMUL_STATE_SCS94_PERCENT  4       /* got ESC{()*+}% */
   96 #define VT100_EMUL_STATE_SCS96          5       /* got ESC{-./} */
   97 #define VT100_EMUL_STATE_SCS96_PERCENT  6       /* got ESC{-./}% */
   98 #define VT100_EMUL_STATE_ESC_HASH       7       /* got ESC# */
   99 #define VT100_EMUL_STATE_ESC_SPC        8       /* got ESC<SPC> */
  100 #define VT100_EMUL_STATE_STRING         9       /* waiting for ST (ESC\) */
  101 #define VT100_EMUL_STATE_STRING_ESC     10      /* waiting for ST, got ESC */
  102 #define VT100_EMUL_STATE_DCS            11      /* got DCS (ESC P) */
  103 #define VT100_EMUL_STATE_DCS_DOLLAR     12      /* got DCS<p>$ */
  104 
  105 vt100_handler *vt100_output[] = {
  106         wsemul_vt100_output_esc,
  107         wsemul_vt100_output_csi,
  108         wsemul_vt100_output_scs94,
  109         wsemul_vt100_output_scs94_percent,
  110         wsemul_vt100_output_scs96,
  111         wsemul_vt100_output_scs96_percent,
  112         wsemul_vt100_output_esc_hash,
  113         wsemul_vt100_output_esc_spc,
  114         wsemul_vt100_output_string,
  115         wsemul_vt100_output_string_esc,
  116         wsemul_vt100_output_dcs,
  117         wsemul_vt100_output_dcs_dollar,
  118 };
  119 
  120 void
  121 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr)
  122         struct wsemul_vt100_emuldata *edp;
  123         const struct wsscreen_descr *type;
  124         void *cookie;
  125         int ccol, crow;
  126         long defattr;
  127 {
  128         edp->emulops = type->textops;
  129         edp->emulcookie = cookie;
  130         edp->scrcapabilities = type->capabilities;
  131         edp->nrows = type->nrows;
  132         edp->ncols = type->ncols;
  133         edp->crow = crow;
  134         edp->ccol = ccol;
  135         edp->defattr = defattr;
  136 }
  137 
  138 void *
  139 wsemul_vt100_cnattach(type, cookie, ccol, crow, defattr)
  140         const struct wsscreen_descr *type;
  141         void *cookie;
  142         int ccol, crow;
  143         long defattr;
  144 {
  145         struct wsemul_vt100_emuldata *edp;
  146         int res;
  147 
  148         edp = &wsemul_vt100_console_emuldata;
  149         wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
  150 #ifdef DIAGNOSTIC
  151         edp->console = 1;
  152 #endif
  153         edp->cbcookie = NULL;
  154 
  155 #ifndef WS_KERNEL_FG
  156 #define WS_KERNEL_FG WSCOL_WHITE
  157 #endif
  158 #ifndef WS_KERNEL_BG
  159 #define WS_KERNEL_BG WSCOL_BLUE
  160 #endif
  161 #ifndef WS_KERNEL_COLATTR
  162 #define WS_KERNEL_COLATTR 0
  163 #endif
  164 #ifndef WS_KERNEL_MONOATTR
  165 #define WS_KERNEL_MONOATTR 0
  166 #endif
  167         if (type->capabilities & WSSCREEN_WSCOLORS)
  168                 res = (*edp->emulops->alloc_attr)(cookie,
  169                                             WS_KERNEL_FG, WS_KERNEL_BG,
  170                                             WS_KERNEL_COLATTR | WSATTR_WSCOLORS,
  171                                             &edp->kernattr);
  172         else
  173                 res = (*edp->emulops->alloc_attr)(cookie, 0, 0,
  174                                             WS_KERNEL_MONOATTR,
  175                                             &edp->kernattr);
  176         if (res)
  177                 edp->kernattr = defattr;
  178 
  179         edp->tabs = NULL;
  180         edp->dblwid = NULL;
  181         edp->dw = 0;
  182         edp->dcsarg = 0;
  183         edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = NULL;
  184         edp->nrctab = NULL;
  185         wsemul_vt100_reset(edp);
  186         return (edp);
  187 }
  188 
  189 void *
  190 wsemul_vt100_attach(console, type, cookie, ccol, crow, cbcookie, defattr)
  191         int console;
  192         const struct wsscreen_descr *type;
  193         void *cookie;
  194         int ccol, crow;
  195         void *cbcookie;
  196         long defattr;
  197 {
  198         struct wsemul_vt100_emuldata *edp;
  199 
  200         if (console) {
  201                 edp = &wsemul_vt100_console_emuldata;
  202 #ifdef DIAGNOSTIC
  203                 KASSERT(edp->console == 1);
  204 #endif
  205         } else {
  206                 edp = malloc(sizeof *edp, M_DEVBUF, M_NOWAIT);
  207                 if (edp == NULL)
  208                         return (NULL);
  209                 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
  210 #ifdef DIAGNOSTIC
  211                 edp->console = 0;
  212 #endif
  213         }
  214         edp->cbcookie = cbcookie;
  215 
  216         edp->tabs = malloc(edp->ncols, M_DEVBUF, M_NOWAIT);
  217         edp->dblwid = malloc(edp->nrows, M_DEVBUF, M_NOWAIT);
  218         if (edp->dblwid != NULL)
  219                 memset(edp->dblwid, 0, edp->nrows);
  220         edp->dw = 0;
  221         edp->dcsarg = malloc(DCS_MAXLEN, M_DEVBUF, M_NOWAIT);
  222         edp->isolatin1tab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
  223         edp->decgraphtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
  224         edp->dectechtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
  225         edp->nrctab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
  226         vt100_initchartables(edp);
  227         wsemul_vt100_reset(edp);
  228         return (edp);
  229 }
  230 
  231 void
  232 wsemul_vt100_detach(cookie, crowp, ccolp)
  233         void *cookie;
  234         u_int *crowp, *ccolp;
  235 {
  236         struct wsemul_vt100_emuldata *edp = cookie;
  237 
  238         *crowp = edp->crow;
  239         *ccolp = edp->ccol;
  240 #define f(ptr) if (ptr) {free(ptr, M_DEVBUF); ptr = NULL;}
  241         f(edp->tabs)
  242         f(edp->dblwid)
  243         f(edp->dcsarg)
  244         f(edp->isolatin1tab)
  245         f(edp->decgraphtab)
  246         f(edp->dectechtab)
  247         f(edp->nrctab)
  248 #undef f
  249         if (edp != &wsemul_vt100_console_emuldata)
  250                 free(edp, M_DEVBUF);
  251 }
  252 
  253 void
  254 wsemul_vt100_resetop(cookie, op)
  255         void *cookie;
  256         enum wsemul_resetops op;
  257 {
  258         struct wsemul_vt100_emuldata *edp = cookie;
  259 
  260         switch (op) {
  261         case WSEMUL_RESET:
  262                 wsemul_vt100_reset(edp);
  263                 break;
  264         case WSEMUL_SYNCFONT:
  265                 vt100_initchartables(edp);
  266                 break;
  267         case WSEMUL_CLEARSCREEN:
  268                 wsemul_vt100_ed(edp, 2);
  269                 edp->ccol = edp->crow = 0;
  270                 (*edp->emulops->cursor)(edp->emulcookie,
  271                                         edp->flags & VTFL_CURSORON, 0, 0);
  272                 break;
  273         default:
  274                 break;
  275         }
  276 }
  277 
  278 void
  279 wsemul_vt100_reset(edp)
  280         struct wsemul_vt100_emuldata *edp;
  281 {
  282         int i;
  283 
  284         edp->state = VT100_EMUL_STATE_NORMAL;
  285         edp->flags = VTFL_DECAWM | VTFL_CURSORON;
  286         edp->bkgdattr = edp->curattr = edp->defattr;
  287         edp->attrflags = 0;
  288         edp->fgcol = WSCOL_WHITE;
  289         edp->bgcol = WSCOL_BLACK;
  290         edp->scrreg_startrow = 0;
  291         edp->scrreg_nrows = edp->nrows;
  292         if (edp->tabs) {
  293                 memset(edp->tabs, 0, edp->ncols);
  294                 for (i = 8; i < edp->ncols; i += 8)
  295                         edp->tabs[i] = 1;
  296         }
  297         edp->dcspos = 0;
  298         edp->dcstype = 0;
  299         edp->chartab_G[0] = NULL;
  300         edp->chartab_G[1] = edp->nrctab; /* ??? */
  301         edp->chartab_G[2] = edp->isolatin1tab;
  302         edp->chartab_G[3] = edp->isolatin1tab;
  303         edp->chartab0 = 0;
  304         edp->chartab1 = 2;
  305         edp->sschartab = 0;
  306 }
  307 
  308 /*
  309  * Move the cursor to the next line if possible. If the cursor is at
  310  * the bottom of the scroll area, then scroll it up. If the cursor is
  311  * at the bottom of the screen then don't move it down.
  312  */
  313 void
  314 wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
  315 {
  316         if (ROWS_BELOW == 0) {
  317                 /* Bottom of the scroll region. */
  318                 wsemul_vt100_scrollup(edp, 1);
  319         } else {
  320                 if ((edp->crow+1) < edp->nrows)
  321                         /* Cursor not at the bottom of the screen. */
  322                         edp->crow++;
  323                 CHECK_DW;
  324         }
  325 }       
  326 
  327 /*
  328  * now all the state machine bits
  329  */
  330 
  331 void
  332 wsemul_vt100_output_normal(edp, c, kernel)
  333         struct wsemul_vt100_emuldata *edp;
  334         u_char c;
  335         int kernel;
  336 {
  337         u_int *ct, dc;
  338 
  339         if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
  340             (VTFL_LASTCHAR | VTFL_DECAWM)) {
  341                 wsemul_vt100_nextline(edp);
  342                 edp->ccol = 0;
  343                 edp->flags &= ~VTFL_LASTCHAR;
  344         }
  345 
  346         if (c & 0x80) {
  347                 c &= 0x7f;
  348                 ct = edp->chartab_G[edp->chartab1];
  349         } else {
  350                 if (edp->sschartab) {
  351                         ct = edp->chartab_G[edp->sschartab];
  352                         edp->sschartab = 0;
  353                 } else
  354                         ct = edp->chartab_G[edp->chartab0];
  355         }
  356         dc = (ct ? ct[c] : c);
  357 
  358         if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT)
  359                 COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT);
  360 
  361         (*edp->emulops->putchar)(edp->emulcookie, edp->crow,
  362                                  edp->ccol << edp->dw, dc,
  363                                  kernel ? edp->kernattr : edp->curattr);
  364 
  365         if (COLS_LEFT)
  366                 edp->ccol++;
  367         else
  368                 edp->flags |= VTFL_LASTCHAR;
  369 }
  370 
  371 void
  372 wsemul_vt100_output_c0c1(edp, c, kernel)
  373         struct wsemul_vt100_emuldata *edp;
  374         u_char c;
  375         int kernel;
  376 {
  377         u_int n;
  378 
  379         switch (c) {
  380         case ASCII_NUL:
  381         default:
  382                 /* ignore */
  383                 break;
  384         case ASCII_BEL:
  385                 wsdisplay_emulbell(edp->cbcookie);
  386                 break;
  387         case ASCII_BS:
  388                 if (edp->ccol > 0) {
  389                         edp->ccol--;
  390                         edp->flags &= ~VTFL_LASTCHAR;
  391                 }
  392                 break;
  393         case ASCII_CR:
  394                 edp->ccol = 0;
  395                 edp->flags &= ~VTFL_LASTCHAR;
  396                 break;
  397         case ASCII_HT:
  398                 if (edp->tabs) {
  399                         if (!COLS_LEFT)
  400                                 break;
  401                         for (n = edp->ccol + 1; n < NCOLS - 1; n++)
  402                                 if (edp->tabs[n])
  403                                         break;
  404                 } else {
  405                         n = edp->ccol + min(8 - (edp->ccol & 7), COLS_LEFT);
  406                 }
  407                 edp->ccol = n;
  408                 break;
  409         case ASCII_SO: /* LS1 */
  410                 edp->chartab0 = 1;
  411                 break;
  412         case ASCII_SI: /* LS0 */
  413                 edp->chartab0 = 0;
  414                 break;
  415         case ASCII_ESC:
  416                 if (kernel) {
  417                         printf("wsemul_vt100_output_c0c1: ESC in kernel "
  418                             "output ignored\n");
  419                         break;  /* ignore the ESC */
  420                 }
  421 
  422                 if (edp->state == VT100_EMUL_STATE_STRING) {
  423                         /* might be a string end */
  424                         edp->state = VT100_EMUL_STATE_STRING_ESC;
  425                 } else {
  426                         /* XXX cancel current escape sequence */
  427                         edp->state = VT100_EMUL_STATE_ESC;
  428                 }
  429                 break;
  430 #if 0
  431         case CSI: /* 8-bit */
  432                 /* XXX cancel current escape sequence */
  433                 edp->nargs = 0;
  434                 memset(edp->args, 0, sizeof (edp->args));
  435                 edp->modif1 = edp->modif2 = '\0';
  436                 edp->state = VT100_EMUL_STATE_CSI;
  437                 break;
  438         case DCS: /* 8-bit */
  439                 /* XXX cancel current escape sequence */
  440                 edp->nargs = 0;
  441                 memset(edp->args, 0, sizeof (edp->args));
  442                 edp->state = VT100_EMUL_STATE_DCS;
  443                 break;
  444         case ST: /* string end 8-bit */
  445                 /* XXX only in VT100_EMUL_STATE_STRING */
  446                 wsemul_vt100_handle_dcs(edp);
  447                 return (VT100_EMUL_STATE_NORMAL);
  448 #endif
  449         case ASCII_LF:
  450         case ASCII_VT:
  451         case ASCII_FF:
  452                 wsemul_vt100_nextline(edp);
  453                 break;
  454         }
  455 }
  456 
  457 u_int
  458 wsemul_vt100_output_esc(edp, c)
  459         struct wsemul_vt100_emuldata *edp;
  460         u_char c;
  461 {
  462         u_int newstate = VT100_EMUL_STATE_NORMAL;
  463         int i;
  464 
  465         switch (c) {
  466         case '[': /* CSI */
  467                 edp->nargs = 0;
  468                 memset(edp->args, 0, sizeof (edp->args));
  469                 edp->modif1 = edp->modif2 = '\0';
  470                 newstate = VT100_EMUL_STATE_CSI;
  471                 break;
  472         case '7': /* DECSC */
  473                 edp->flags |= VTFL_SAVEDCURS;
  474                 edp->savedcursor_row = edp->crow;
  475                 edp->savedcursor_col = edp->ccol;
  476                 edp->savedattr = edp->curattr;
  477                 edp->savedbkgdattr = edp->bkgdattr;
  478                 edp->savedattrflags = edp->attrflags;
  479                 edp->savedfgcol = edp->fgcol;
  480                 edp->savedbgcol = edp->bgcol;
  481                 for (i = 0; i < 4; i++)
  482                         edp->savedchartab_G[i] = edp->chartab_G[i];
  483                 edp->savedchartab0 = edp->chartab0;
  484                 edp->savedchartab1 = edp->chartab1;
  485                 break;
  486         case '8': /* DECRC */
  487                 if ((edp->flags & VTFL_SAVEDCURS) == 0)
  488                         break;
  489                 edp->crow = edp->savedcursor_row;
  490                 edp->ccol = edp->savedcursor_col;
  491                 edp->curattr = edp->savedattr;
  492                 edp->bkgdattr = edp->savedbkgdattr;
  493                 edp->attrflags = edp->savedattrflags;
  494                 edp->fgcol = edp->savedfgcol;
  495                 edp->bgcol = edp->savedbgcol;
  496                 for (i = 0; i < 4; i++)
  497                         edp->chartab_G[i] = edp->savedchartab_G[i];
  498                 edp->chartab0 = edp->savedchartab0;
  499                 edp->chartab1 = edp->savedchartab1;
  500                 break;
  501         case '=': /* DECKPAM application mode */
  502                 edp->flags |= VTFL_APPLKEYPAD;
  503                 break;
  504         case '>': /* DECKPNM numeric mode */
  505                 edp->flags &= ~VTFL_APPLKEYPAD;
  506                 break;
  507         case 'E': /* NEL */
  508                 edp->ccol = 0;
  509                 /* FALLTHROUGH */
  510         case 'D': /* IND */
  511                 wsemul_vt100_nextline(edp);
  512                 break;
  513         case 'H': /* HTS */
  514                 if (edp->tabs != NULL)
  515                         edp->tabs[edp->ccol] = 1;
  516                 break;
  517         case '~': /* LS1R */
  518                 edp->chartab1 = 1;
  519                 break;
  520         case 'n': /* LS2 */
  521                 edp->chartab0 = 2;
  522                 break;
  523         case '}': /* LS2R */
  524                 edp->chartab1 = 2;
  525                 break;
  526         case 'o': /* LS3 */
  527                 edp->chartab0 = 3;
  528                 break;
  529         case '|': /* LS3R */
  530                 edp->chartab1 = 3;
  531                 break;
  532         case 'N': /* SS2 */
  533                 edp->sschartab = 2;
  534                 break;
  535         case 'O': /* SS3 */
  536                 edp->sschartab = 3;
  537                 break;
  538         case 'M': /* RI */
  539                 if (ROWS_ABOVE > 0) {
  540                         edp->crow--;
  541                         CHECK_DW;
  542                         break;
  543                 }
  544                 wsemul_vt100_scrolldown(edp, 1);
  545                 break;
  546         case 'P': /* DCS */
  547                 edp->nargs = 0;
  548                 memset(edp->args, 0, sizeof (edp->args));
  549                 newstate = VT100_EMUL_STATE_DCS;
  550                 break;
  551         case 'c': /* RIS */
  552                 wsemul_vt100_reset(edp);
  553                 wsemul_vt100_ed(edp, 2);
  554                 edp->ccol = edp->crow = 0;
  555                 break;
  556         case '(': case ')': case '*': case '+': /* SCS */
  557                 edp->designating = c - '(';
  558                 newstate = VT100_EMUL_STATE_SCS94;
  559                 break;
  560         case '-': case '.': case '/': /* SCS */
  561                 edp->designating = c - '-' + 1;
  562                 newstate = VT100_EMUL_STATE_SCS96;
  563                 break;
  564         case '#':
  565                 newstate = VT100_EMUL_STATE_ESC_HASH;
  566                 break;
  567         case ' ': /* 7/8 bit */
  568                 newstate = VT100_EMUL_STATE_ESC_SPC;
  569                 break;
  570         case ']': /* OSC operating system command */
  571         case '^': /* PM privacy message */
  572         case '_': /* APC application program command */
  573                 /* ignored */
  574                 newstate = VT100_EMUL_STATE_STRING;
  575                 break;
  576         case '<': /* exit VT52 mode - ignored */
  577                 break;
  578             default:
  579 #ifdef VT100_PRINTUNKNOWN
  580                 printf("ESC%c unknown\n", c);
  581 #endif
  582                 break;
  583         }
  584 
  585         return (newstate);
  586 }
  587 
  588 u_int
  589 wsemul_vt100_output_scs94(edp, c)
  590         struct wsemul_vt100_emuldata *edp;
  591         u_char c;
  592 {
  593         u_int newstate = VT100_EMUL_STATE_NORMAL;
  594 
  595         switch (c) {
  596         case '%': /* probably DEC supplemental graphic */
  597                 newstate = VT100_EMUL_STATE_SCS94_PERCENT;
  598                 break;
  599         case 'A': /* british / national */
  600                 edp->chartab_G[edp->designating] = edp->nrctab;
  601                 break;
  602         case 'B': /* ASCII */
  603                 edp->chartab_G[edp->designating] = 0;
  604                 break;
  605         case '<': /* user preferred supplemental */
  606                 /* XXX not really "user" preferred */
  607                 edp->chartab_G[edp->designating] = edp->isolatin1tab;
  608                 break;
  609         case '0': /* DEC special graphic */
  610                 edp->chartab_G[edp->designating] = edp->decgraphtab;
  611                 break;
  612         case '>': /* DEC tech */
  613                 edp->chartab_G[edp->designating] = edp->dectechtab;
  614                 break;
  615             default:
  616 #ifdef VT100_PRINTUNKNOWN
  617                 printf("ESC%c%c unknown\n", edp->designating + '(', c);
  618 #endif
  619                 break;
  620         }
  621         return (newstate);
  622 }
  623 
  624 u_int
  625 wsemul_vt100_output_scs94_percent(edp, c)
  626         struct wsemul_vt100_emuldata *edp;
  627         u_char c;
  628 {
  629         switch (c) {
  630         case '5': /* DEC supplemental graphic */
  631                 /* XXX there are differences */
  632                 edp->chartab_G[edp->designating] = edp->isolatin1tab;
  633                 break;
  634             default:
  635 #ifdef VT100_PRINTUNKNOWN
  636                 printf("ESC%c%%%c unknown\n", edp->designating + '(', c);
  637 #endif
  638                 break;
  639         }
  640         return (VT100_EMUL_STATE_NORMAL);
  641 }
  642 
  643 u_int
  644 wsemul_vt100_output_scs96(edp, c)
  645         struct wsemul_vt100_emuldata *edp;
  646         u_char c;
  647 {
  648         u_int newstate = VT100_EMUL_STATE_NORMAL;
  649         int nrc;
  650 
  651         switch (c) {
  652         case '%': /* probably portugese */
  653                 newstate = VT100_EMUL_STATE_SCS96_PERCENT;
  654                 break;
  655         case 'A': /* ISO-latin-1 supplemental */
  656                 edp->chartab_G[edp->designating] = edp->isolatin1tab;
  657                 break;
  658         case '4': /* dutch */
  659                 nrc = 1;
  660                 goto setnrc;
  661         case '5': case 'C': /* finnish */
  662                 nrc = 2;
  663                 goto setnrc;
  664         case 'R': /* french */
  665                 nrc = 3;
  666                 goto setnrc;
  667         case 'Q': /* french canadian */
  668                 nrc = 4;
  669                 goto setnrc;
  670         case 'K': /* german */
  671                 nrc = 5;
  672                 goto setnrc;
  673         case 'Y': /* italian */
  674                 nrc = 6;
  675                 goto setnrc;
  676         case 'E': case '6': /* norwegian / danish */
  677                 nrc = 7;
  678                 goto setnrc;
  679         case 'Z': /* spanish */
  680                 nrc = 9;
  681                 goto setnrc;
  682         case '7': case 'H': /* swedish */
  683                 nrc = 10;
  684                 goto setnrc;
  685         case '=': /* swiss */
  686                 nrc = 11;
  687 setnrc:
  688                 if (vt100_setnrc(edp, nrc) == 0) /* what table ??? */
  689                         break;
  690                 /* else FALLTHROUGH */
  691             default:
  692 #ifdef VT100_PRINTUNKNOWN
  693                 printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c);
  694 #endif
  695                 break;
  696         }
  697         return (newstate);
  698 }
  699 
  700 u_int
  701 wsemul_vt100_output_scs96_percent(edp, c)
  702         struct wsemul_vt100_emuldata *edp;
  703         u_char c;
  704 {
  705         switch (c) {
  706         case '6': /* portugese */
  707                 if (vt100_setnrc(edp, 8) == 0)
  708                         break;
  709                 /* else FALLTHROUGH */
  710             default:
  711 #ifdef VT100_PRINTUNKNOWN
  712                 printf("ESC%c%%%c unknown\n", edp->designating + '-' - 1, c);
  713 #endif
  714                 break;
  715         }
  716         return (VT100_EMUL_STATE_NORMAL);
  717 }
  718 
  719 u_int
  720 wsemul_vt100_output_esc_spc(edp, c)
  721         struct wsemul_vt100_emuldata *edp;
  722         u_char c;
  723 {
  724         switch (c) {
  725         case 'F': /* 7-bit controls */
  726         case 'G': /* 8-bit controls */
  727 #ifdef VT100_PRINTNOTIMPL
  728                 printf("ESC<SPC>%c ignored\n", c);
  729 #endif
  730                 break;
  731             default:
  732 #ifdef VT100_PRINTUNKNOWN
  733                 printf("ESC<SPC>%c unknown\n", c);
  734 #endif
  735                 break;
  736         }
  737         return (VT100_EMUL_STATE_NORMAL);
  738 }
  739 
  740 u_int
  741 wsemul_vt100_output_string(edp, c)
  742         struct wsemul_vt100_emuldata *edp;
  743         u_char c;
  744 {
  745         if (edp->dcstype && edp->dcspos < DCS_MAXLEN)
  746                 edp->dcsarg[edp->dcspos++] = c;
  747         return (VT100_EMUL_STATE_STRING);
  748 }
  749 
  750 u_int
  751 wsemul_vt100_output_string_esc(edp, c)
  752         struct wsemul_vt100_emuldata *edp;
  753         u_char c;
  754 {
  755         if (c == '\\') { /* ST complete */
  756                 wsemul_vt100_handle_dcs(edp);
  757                 return (VT100_EMUL_STATE_NORMAL);
  758         } else
  759                 return (VT100_EMUL_STATE_STRING);
  760 }
  761 
  762 u_int
  763 wsemul_vt100_output_dcs(edp, c)
  764         struct wsemul_vt100_emuldata *edp;
  765         u_char c;
  766 {
  767         u_int newstate = VT100_EMUL_STATE_DCS;
  768 
  769         switch (c) {
  770         case '0': case '1': case '2': case '3': case '4':
  771         case '5': case '6': case '7': case '8': case '9':
  772                 /* argument digit */
  773                 if (edp->nargs > VT100_EMUL_NARGS - 1)
  774                         break;
  775                 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
  776                     (c - '0');
  777                 break;
  778         case ';': /* argument terminator */
  779                 edp->nargs++;
  780                 break;
  781             default:
  782                 edp->nargs++;
  783                 if (edp->nargs > VT100_EMUL_NARGS) {
  784 #ifdef VT100_DEBUG
  785                         printf("vt100: too many arguments\n");
  786 #endif
  787                         edp->nargs = VT100_EMUL_NARGS;
  788                 }
  789                 newstate = VT100_EMUL_STATE_STRING;
  790                 switch (c) {
  791                 case '$':
  792                         newstate = VT100_EMUL_STATE_DCS_DOLLAR;
  793                         break;
  794                 case '{': /* DECDLD soft charset */
  795                 case '!': /* DECRQUPSS user preferred supplemental set */
  796                         /* 'u' must follow - need another state */
  797                 case '|': /* DECUDK program F6..F20 */
  798 #ifdef VT100_PRINTNOTIMPL
  799                         printf("DCS%c ignored\n", c);
  800 #endif
  801                         break;
  802                     default:
  803 #ifdef VT100_PRINTUNKNOWN
  804                         printf("DCS%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
  805 #endif
  806                         break;
  807                 }
  808         }
  809 
  810         return (newstate);
  811 }
  812 
  813 u_int
  814 wsemul_vt100_output_dcs_dollar(edp, c)
  815         struct wsemul_vt100_emuldata *edp;
  816         u_char c;
  817 {
  818         switch (c) {
  819         case 'p': /* DECRSTS terminal state restore */
  820         case 'q': /* DECRQSS control function request */
  821 #ifdef VT100_PRINTNOTIMPL
  822                 printf("DCS$%c ignored\n", c);
  823 #endif
  824                 break;
  825         case 't': /* DECRSPS restore presentation state */
  826                 switch (ARG(0)) {
  827                 case 0: /* error */
  828                         break;
  829                 case 1: /* cursor information restore */
  830 #ifdef VT100_PRINTNOTIMPL
  831                         printf("DCS1$t ignored\n");
  832 #endif
  833                         break;
  834                 case 2: /* tab stop restore */
  835                         edp->dcspos = 0;
  836                         edp->dcstype = DCSTYPE_TABRESTORE;
  837                         break;
  838                     default:
  839 #ifdef VT100_PRINTUNKNOWN
  840                         printf("DCS%d$t unknown\n", ARG(0));
  841 #endif
  842                         break;
  843                 }
  844                 break;
  845             default:
  846 #ifdef VT100_PRINTUNKNOWN
  847                 printf("DCS$%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
  848 #endif
  849                 break;
  850         }
  851         return (VT100_EMUL_STATE_STRING);
  852 }
  853 
  854 u_int
  855 wsemul_vt100_output_esc_hash(edp, c)
  856         struct wsemul_vt100_emuldata *edp;
  857         u_char c;
  858 {
  859         int i;
  860 
  861         switch (c) {
  862         case '5': /*  DECSWL single width, single height */
  863                 if (edp->dblwid != NULL && edp->dw != 0) {
  864                         for (i = 0; i < edp->ncols / 2; i++)
  865                                 (*edp->emulops->copycols)(edp->emulcookie,
  866                                                           edp->crow,
  867                                                           2 * i, i, 1);
  868                         (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
  869                                                    i, edp->ncols - i,
  870                                                    edp->bkgdattr);
  871                         edp->dblwid[edp->crow] = 0;
  872                         edp->dw = 0;
  873                 }
  874                 break;
  875         case '6': /*  DECDWL double width, single height */
  876         case '3': /*  DECDHL double width, double height, top half */
  877         case '4': /*  DECDHL double width, double height, bottom half */
  878                 if (edp->dblwid != NULL && edp->dw == 0) {
  879                         for (i = edp->ncols / 2 - 1; i >= 0; i--)
  880                                 (*edp->emulops->copycols)(edp->emulcookie,
  881                                                           edp->crow,
  882                                                           i, 2 * i, 1);
  883                         for (i = 0; i < edp->ncols / 2; i++)
  884                                 (*edp->emulops->erasecols)(edp->emulcookie,
  885                                                            edp->crow,
  886                                                            2 * i + 1, 1,
  887                                                            edp->bkgdattr);
  888                         edp->dblwid[edp->crow] = 1;
  889                         edp->dw = 1;
  890                         if (edp->ccol > (edp->ncols >> 1) - 1)
  891                                 edp->ccol = (edp->ncols >> 1) - 1;
  892                 }
  893                 break;
  894         case '8': { /* DECALN */
  895                 int i, j;
  896                 for (i = 0; i < edp->nrows; i++)
  897                         for (j = 0; j < edp->ncols; j++)
  898                                 (*edp->emulops->putchar)(edp->emulcookie, i, j,
  899                                                          'E', edp->curattr);
  900                 }
  901                 edp->ccol = 0;
  902                 edp->crow = 0;
  903                 break;
  904             default:
  905 #ifdef VT100_PRINTUNKNOWN
  906                 printf("ESC#%c unknown\n", c);
  907 #endif
  908                 break;
  909         }
  910         return (VT100_EMUL_STATE_NORMAL);
  911 }
  912 
  913 u_int
  914 wsemul_vt100_output_csi(edp, c)
  915         struct wsemul_vt100_emuldata *edp;
  916         u_char c;
  917 {
  918         u_int newstate = VT100_EMUL_STATE_CSI;
  919 
  920         switch (c) {
  921         case '0': case '1': case '2': case '3': case '4':
  922         case '5': case '6': case '7': case '8': case '9':
  923                 /* argument digit */
  924                 if (edp->nargs > VT100_EMUL_NARGS - 1)
  925                         break;
  926                 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
  927                     (c - '0');
  928                 break;
  929         case ';': /* argument terminator */
  930                 edp->nargs++;
  931                 break;
  932         case '?': /* DEC specific */
  933         case '>': /* DA query */
  934                 edp->modif1 = c;
  935                 break;
  936         case '!':
  937         case '"':
  938         case '$':
  939         case '&':
  940                 edp->modif2 = c;
  941                 break;
  942             default: /* end of escape sequence */
  943                 edp->nargs++;
  944                 if (edp->nargs > VT100_EMUL_NARGS) {
  945 #ifdef VT100_DEBUG
  946                         printf("vt100: too many arguments\n");
  947 #endif
  948                         edp->nargs = VT100_EMUL_NARGS;
  949                 }
  950                 wsemul_vt100_handle_csi(edp, c);
  951                 newstate = VT100_EMUL_STATE_NORMAL;
  952                 break;
  953         }
  954         return (newstate);
  955 }
  956 
  957 void
  958 wsemul_vt100_output(cookie, data, count, kernel)
  959         void *cookie;
  960         const u_char *data;
  961         u_int count;
  962         int kernel;
  963 {
  964         struct wsemul_vt100_emuldata *edp = cookie;
  965 #ifdef JUMP_SCROLL
  966         const u_char *eot;
  967         u_char curchar;
  968         u_int cnt, pos, lines;
  969 #endif
  970 
  971 #ifdef DIAGNOSTIC
  972         if (kernel && !edp->console)
  973                 panic("wsemul_vt100_output: kernel output, not console");
  974 #endif
  975 
  976         if (edp->flags & VTFL_CURSORON)
  977                 (*edp->emulops->cursor)(edp->emulcookie, 0,
  978                                 edp->crow, edp->ccol << edp->dw);
  979 
  980         for (; count > 0; data++, count--) {
  981 #ifdef JUMP_SCROLL
  982                 /*
  983                  * If we are at the bottom of the scrolling area, count
  984                  * newlines until an escape sequence appears.
  985                  */
  986                 if ((edp->state == VT100_EMUL_STATE_NORMAL || kernel) &&
  987                     ROWS_BELOW == 0) {
  988                         lines = 0;
  989                         pos = edp->ccol;
  990                         for (eot = data, cnt = count; cnt != 0; eot++, cnt--) {
  991                                 curchar = *eot;
  992                                 /*
  993                                  * Only char for which
  994                                  * wsemul_vt100_output_c0c1() will switch
  995                                  * to escape mode, for now.
  996                                  * Revisit this when this changes...
  997                                  */
  998                                 if (curchar == ASCII_ESC)
  999                                         break;
 1000 
 1001                                 if (ISSET(edp->flags, VTFL_DECAWM))
 1002                                     switch (curchar) {
 1003                                     case ASCII_BS:
 1004                                         if (pos > 0)
 1005                                                 pos--;
 1006                                         break;
 1007                                     case ASCII_CR:
 1008                                         pos = 0;
 1009                                         break;
 1010                                     case ASCII_HT:
 1011                                         if (edp->tabs) {
 1012                                                 pos++;
 1013                                                 while (pos < NCOLS - 1 &&
 1014                                                     edp->tabs[pos] == 0)
 1015                                                         pos++;
 1016                                         } else {
 1017                                                 pos = (pos + 7) & ~7;
 1018                                                 if (pos >= NCOLS)
 1019                                                         pos = NCOLS - 1;
 1020                                         }
 1021                                         break;
 1022                                     default:
 1023                                         if ((curchar & 0x7f) < 0x20)
 1024                                                 break;
 1025                                         if (pos++ >= NCOLS) {
 1026                                                 pos = 0;
 1027                                                 curchar = ASCII_LF;
 1028                                         }
 1029                                         break;
 1030                                     }
 1031 
 1032                                 if (curchar == ASCII_LF ||
 1033                                     curchar == ASCII_VT ||
 1034                                     curchar == ASCII_FF) {
 1035                                         if (++lines >= edp->scrreg_nrows - 1)
 1036                                                 break;
 1037                                 }
 1038                         }
 1039 
 1040                         if (lines > 1) {
 1041                                 wsemul_vt100_scrollup(edp, lines);
 1042                                 edp->crow -= lines;
 1043                         }
 1044                 }
 1045 #endif
 1046 
 1047                 if ((*data & 0x7f) < 0x20) {
 1048                         wsemul_vt100_output_c0c1(edp, *data, kernel);
 1049                         continue;
 1050                 }
 1051 
 1052                 if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
 1053                         wsemul_vt100_output_normal(edp, *data, kernel);
 1054                         continue;
 1055                 }
 1056 #ifdef DIAGNOSTIC
 1057                 if (edp->state > sizeof(vt100_output) / sizeof(vt100_output[0]))
 1058                         panic("wsemul_vt100: invalid state %d", edp->state);
 1059 #endif
 1060                 edp->state = vt100_output[edp->state - 1](edp, *data);
 1061         }
 1062 
 1063         if (edp->flags & VTFL_CURSORON)
 1064                 (*edp->emulops->cursor)(edp->emulcookie, 1,
 1065                                 edp->crow, edp->ccol << edp->dw);
 1066 }

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