The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/wscons/wsemul_vt100.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 05f2baf737883c57f68e8100434ad797


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.