LCOV - code coverage report
Current view: top level - dev/wscons - wsemul_vt100.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 543 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: wsemul_vt100.c,v 1.36 2017/08/10 09:12:32 fcambus Exp $ */
       2             : /* $NetBSD: wsemul_vt100.c,v 1.13 2000/04/28 21:56:16 mycroft Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 2007, 2013 Miodrag Vallat.
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice, this permission notice, and the disclaimer below
      10             :  * appear in all copies.
      11             :  *
      12             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      13             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      14             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      15             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      16             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      17             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      18             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      19             :  */
      20             : /*
      21             :  * Copyright (c) 1998
      22             :  *      Matthias Drochner.  All rights reserved.
      23             :  *
      24             :  * Redistribution and use in source and binary forms, with or without
      25             :  * modification, are permitted provided that the following conditions
      26             :  * are met:
      27             :  * 1. Redistributions of source code must retain the above copyright
      28             :  *    notice, this list of conditions and the following disclaimer.
      29             :  * 2. Redistributions in binary form must reproduce the above copyright
      30             :  *    notice, this list of conditions and the following disclaimer in the
      31             :  *    documentation and/or other materials provided with the distribution.
      32             :  *
      33             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      34             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      35             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      36             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      37             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      38             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      39             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      40             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      41             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      42             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      43             :  *
      44             :  */
      45             : 
      46             : #include <sys/param.h>
      47             : #include <sys/systm.h>
      48             : #include <sys/time.h>
      49             : #include <sys/malloc.h>
      50             : #include <sys/fcntl.h>
      51             : 
      52             : #include <dev/wscons/wscons_features.h>
      53             : #include <dev/wscons/wsconsio.h>
      54             : #include <dev/wscons/wsdisplayvar.h>
      55             : #include <dev/wscons/wsemulvar.h>
      56             : #include <dev/wscons/wsemul_vt100var.h>
      57             : #include <dev/wscons/ascii.h>
      58             : 
      59             : void    *wsemul_vt100_cnattach(const struct wsscreen_descr *, void *,
      60             :                                   int, int, long);
      61             : void    *wsemul_vt100_attach(int, const struct wsscreen_descr *,
      62             :                                   void *, int, int, void *, long);
      63             : u_int   wsemul_vt100_output(void *, const u_char *, u_int, int);
      64             : void    wsemul_vt100_detach(void *, u_int *, u_int *);
      65             : void    wsemul_vt100_resetop(void *, enum wsemul_resetops);
      66             : 
      67             : const struct wsemul_ops wsemul_vt100_ops = {
      68             :         "vt100",
      69             :         wsemul_vt100_cnattach,
      70             :         wsemul_vt100_attach,
      71             :         wsemul_vt100_output,
      72             :         wsemul_vt100_translate,
      73             :         wsemul_vt100_detach,
      74             :         wsemul_vt100_resetop
      75             : };
      76             : 
      77             : struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata;
      78             : 
      79             : void    wsemul_vt100_init(struct wsemul_vt100_emuldata *,
      80             :             const struct wsscreen_descr *, void *, int, int, long);
      81             : int     wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *,
      82             :             const u_char *, u_int, int);
      83             : int     wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
      84             :             struct wsemul_inputstate *, int);
      85             : int     wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *,
      86             :             struct wsemul_inputstate *, int);
      87             : int     wsemul_vt100_nextline(struct wsemul_vt100_emuldata *);
      88             : 
      89             : typedef int vt100_handler(struct wsemul_vt100_emuldata *, struct
      90             :             wsemul_inputstate *);
      91             : vt100_handler
      92             :         wsemul_vt100_output_esc,
      93             :         wsemul_vt100_output_csi,
      94             :         wsemul_vt100_output_scs94,
      95             :         wsemul_vt100_output_scs94_percent,
      96             :         wsemul_vt100_output_scs96,
      97             :         wsemul_vt100_output_scs96_percent,
      98             :         wsemul_vt100_output_esc_hash,
      99             :         wsemul_vt100_output_esc_spc,
     100             :         wsemul_vt100_output_string,
     101             :         wsemul_vt100_output_string_esc,
     102             :         wsemul_vt100_output_dcs,
     103             :         wsemul_vt100_output_dcs_dollar,
     104             :         wsemul_vt100_output_esc_percent;
     105             : 
     106             : #define VT100_EMUL_STATE_NORMAL         0       /* normal processing */
     107             : #define VT100_EMUL_STATE_ESC            1       /* got ESC */
     108             : #define VT100_EMUL_STATE_CSI            2       /* got CSI (ESC[) */
     109             : #define VT100_EMUL_STATE_SCS94          3       /* got ESC{()*+} */
     110             : #define VT100_EMUL_STATE_SCS94_PERCENT  4       /* got ESC{()*+}% */
     111             : #define VT100_EMUL_STATE_SCS96          5       /* got ESC{-./} */
     112             : #define VT100_EMUL_STATE_SCS96_PERCENT  6       /* got ESC{-./}% */
     113             : #define VT100_EMUL_STATE_ESC_HASH       7       /* got ESC# */
     114             : #define VT100_EMUL_STATE_ESC_SPC        8       /* got ESC<SPC> */
     115             : #define VT100_EMUL_STATE_STRING         9       /* waiting for ST (ESC\) */
     116             : #define VT100_EMUL_STATE_STRING_ESC     10      /* waiting for ST, got ESC */
     117             : #define VT100_EMUL_STATE_DCS            11      /* got DCS (ESC P) */
     118             : #define VT100_EMUL_STATE_DCS_DOLLAR     12      /* got DCS<p>$ */
     119             : #define VT100_EMUL_STATE_ESC_PERCENT    13      /* got ESC% */
     120             : 
     121             : vt100_handler *vt100_output[] = {
     122             :         wsemul_vt100_output_esc,
     123             :         wsemul_vt100_output_csi,
     124             :         wsemul_vt100_output_scs94,
     125             :         wsemul_vt100_output_scs94_percent,
     126             :         wsemul_vt100_output_scs96,
     127             :         wsemul_vt100_output_scs96_percent,
     128             :         wsemul_vt100_output_esc_hash,
     129             :         wsemul_vt100_output_esc_spc,
     130             :         wsemul_vt100_output_string,
     131             :         wsemul_vt100_output_string_esc,
     132             :         wsemul_vt100_output_dcs,
     133             :         wsemul_vt100_output_dcs_dollar,
     134             :         wsemul_vt100_output_esc_percent,
     135             : };
     136             : 
     137             : void
     138           0 : wsemul_vt100_init(struct wsemul_vt100_emuldata *edp,
     139             :     const struct wsscreen_descr *type, void *cookie, int ccol, int crow,
     140             :     long defattr)
     141             : {
     142           0 :         edp->emulops = type->textops;
     143           0 :         edp->emulcookie = cookie;
     144           0 :         edp->scrcapabilities = type->capabilities;
     145           0 :         edp->nrows = type->nrows;
     146           0 :         edp->ncols = type->ncols;
     147           0 :         edp->crow = crow;
     148           0 :         edp->ccol = ccol;
     149           0 :         edp->defattr = defattr;
     150           0 :         wsemul_reset_abortstate(&edp->abortstate);
     151           0 : }
     152             : 
     153             : void *
     154           0 : wsemul_vt100_cnattach(const struct wsscreen_descr *type, void *cookie, int ccol,
     155             :     int crow, long defattr)
     156             : {
     157             :         struct wsemul_vt100_emuldata *edp;
     158             :         int res;
     159             : 
     160             :         edp = &wsemul_vt100_console_emuldata;
     161           0 :         wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
     162             : #ifdef DIAGNOSTIC
     163           0 :         edp->console = 1;
     164             : #endif
     165           0 :         edp->cbcookie = NULL;
     166             : 
     167             : #ifndef WS_KERNEL_FG
     168             : #define WS_KERNEL_FG WSCOL_WHITE
     169             : #endif
     170             : #ifndef WS_KERNEL_BG
     171             : #define WS_KERNEL_BG WSCOL_BLUE
     172             : #endif
     173             : #ifndef WS_KERNEL_COLATTR
     174             : #define WS_KERNEL_COLATTR 0
     175             : #endif
     176             : #ifndef WS_KERNEL_MONOATTR
     177             : #define WS_KERNEL_MONOATTR 0
     178             : #endif
     179           0 :         if (type->capabilities & WSSCREEN_WSCOLORS)
     180           0 :                 res = (*edp->emulops->alloc_attr)(cookie,
     181             :                     WS_KERNEL_FG, WS_KERNEL_BG,
     182             :                     WS_KERNEL_COLATTR | WSATTR_WSCOLORS, &edp->kernattr);
     183             :         else
     184           0 :                 res = (*edp->emulops->alloc_attr)(cookie, 0, 0,
     185             :                     WS_KERNEL_MONOATTR, &edp->kernattr);
     186           0 :         if (res)
     187           0 :                 edp->kernattr = defattr;
     188             : 
     189           0 :         edp->tabs = NULL;
     190           0 :         edp->dblwid = NULL;
     191           0 :         edp->dw = 0;
     192           0 :         edp->dcsarg = 0;
     193           0 :         edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = NULL;
     194           0 :         edp->nrctab = NULL;
     195           0 :         wsemul_vt100_reset(edp);
     196           0 :         return (edp);
     197             : }
     198             : 
     199             : void *
     200           0 : wsemul_vt100_attach(int console, const struct wsscreen_descr *type,
     201             :     void *cookie, int ccol, int crow, void *cbcookie, long defattr)
     202             : {
     203             :         struct wsemul_vt100_emuldata *edp;
     204             : 
     205           0 :         if (console) {
     206             :                 edp = &wsemul_vt100_console_emuldata;
     207             : #ifdef DIAGNOSTIC
     208           0 :                 KASSERT(edp->console == 1);
     209             : #endif
     210             :         } else {
     211           0 :                 edp = malloc(sizeof *edp, M_DEVBUF, M_NOWAIT);
     212           0 :                 if (edp == NULL)
     213           0 :                         return (NULL);
     214           0 :                 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
     215             : #ifdef DIAGNOSTIC
     216           0 :                 edp->console = 0;
     217             : #endif
     218             :         }
     219           0 :         edp->cbcookie = cbcookie;
     220             : 
     221           0 :         edp->tabs = malloc(edp->ncols, M_DEVBUF, M_NOWAIT);
     222           0 :         edp->dblwid = malloc(edp->nrows, M_DEVBUF, M_NOWAIT | M_ZERO);
     223           0 :         edp->dw = 0;
     224           0 :         edp->dcsarg = malloc(DCS_MAXLEN, M_DEVBUF, M_NOWAIT);
     225           0 :         edp->isolatin1tab = malloc(128 * sizeof(u_int), M_DEVBUF, M_NOWAIT);
     226           0 :         edp->decgraphtab = malloc(128 * sizeof(u_int), M_DEVBUF, M_NOWAIT);
     227           0 :         edp->dectechtab = malloc(128 * sizeof(u_int), M_DEVBUF, M_NOWAIT);
     228           0 :         edp->nrctab = malloc(128 * sizeof(u_int), M_DEVBUF, M_NOWAIT);
     229           0 :         vt100_initchartables(edp);
     230           0 :         wsemul_vt100_reset(edp);
     231           0 :         return (edp);
     232           0 : }
     233             : 
     234             : void
     235           0 : wsemul_vt100_detach(void *cookie, u_int *crowp, u_int *ccolp)
     236             : {
     237           0 :         struct wsemul_vt100_emuldata *edp = cookie;
     238             : 
     239           0 :         *crowp = edp->crow;
     240           0 :         *ccolp = edp->ccol;
     241             : #define f(ptr) if (ptr) {free(ptr, M_DEVBUF, 0); ptr = NULL;}
     242           0 :         f(edp->tabs)
     243           0 :         f(edp->dblwid)
     244           0 :         f(edp->dcsarg)
     245           0 :         f(edp->isolatin1tab)
     246           0 :         f(edp->decgraphtab)
     247           0 :         f(edp->dectechtab)
     248           0 :         f(edp->nrctab)
     249             : #undef f
     250           0 :         if (edp != &wsemul_vt100_console_emuldata)
     251           0 :                 free(edp, M_DEVBUF, sizeof *edp);
     252           0 : }
     253             : 
     254             : void
     255           0 : wsemul_vt100_resetop(void *cookie, enum wsemul_resetops op)
     256             : {
     257           0 :         struct wsemul_vt100_emuldata *edp = cookie;
     258             : 
     259           0 :         switch (op) {
     260             :         case WSEMUL_RESET:
     261           0 :                 wsemul_vt100_reset(edp);
     262           0 :                 break;
     263             :         case WSEMUL_SYNCFONT:
     264           0 :                 vt100_initchartables(edp);
     265           0 :                 break;
     266             :         case WSEMUL_CLEARSCREEN:
     267           0 :                 (void)wsemul_vt100_ed(edp, 2);
     268           0 :                 edp->ccol = edp->crow = 0;
     269           0 :                 (*edp->emulops->cursor)(edp->emulcookie,
     270           0 :                     edp->flags & VTFL_CURSORON, 0, 0);
     271           0 :                 break;
     272             :         case WSEMUL_CLEARCURSOR:
     273           0 :                 (*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow,
     274           0 :                     edp->ccol);
     275           0 :                 break;
     276             :         default:
     277             :                 break;
     278             :         }
     279           0 : }
     280             : 
     281             : void
     282           0 : wsemul_vt100_reset(struct wsemul_vt100_emuldata *edp)
     283             : {
     284             :         int i;
     285             : 
     286           0 :         edp->state = VT100_EMUL_STATE_NORMAL;
     287           0 :         edp->flags = VTFL_DECAWM | VTFL_CURSORON;
     288           0 :         edp->bkgdattr = edp->curattr = edp->defattr;
     289           0 :         edp->attrflags = 0;
     290           0 :         edp->fgcol = WSCOL_WHITE;
     291           0 :         edp->bgcol = WSCOL_BLACK;
     292           0 :         edp->scrreg_startrow = 0;
     293           0 :         edp->scrreg_nrows = edp->nrows;
     294           0 :         if (edp->tabs) {
     295           0 :                 memset(edp->tabs, 0, edp->ncols);
     296           0 :                 for (i = 8; i < edp->ncols; i += 8)
     297           0 :                         edp->tabs[i] = 1;
     298             :         }
     299           0 :         edp->dcspos = 0;
     300           0 :         edp->dcstype = 0;
     301           0 :         edp->chartab_G[0] = NULL;
     302           0 :         edp->chartab_G[1] = edp->nrctab; /* ??? */
     303           0 :         edp->chartab_G[2] = edp->isolatin1tab;
     304           0 :         edp->chartab_G[3] = edp->isolatin1tab;
     305           0 :         edp->chartab0 = 0;
     306           0 :         edp->chartab1 = 2;
     307           0 :         edp->sschartab = 0;
     308           0 : }
     309             : 
     310             : /*
     311             :  * Move the cursor to the next line if possible. If the cursor is at
     312             :  * the bottom of the scroll area, then scroll it up. If the cursor is
     313             :  * at the bottom of the screen then don't move it down.
     314             :  */
     315             : int
     316           0 : wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
     317             : {
     318             :         int rc;
     319             : 
     320           0 :         if (ROWS_BELOW == 0) {
     321             :                 /* Bottom of the scroll region. */
     322           0 :                 rc = wsemul_vt100_scrollup(edp, 1);
     323           0 :         } else {
     324           0 :                 if ((edp->crow+1) < edp->nrows)
     325             :                         /* Cursor not at the bottom of the screen. */
     326           0 :                         edp->crow++;
     327           0 :                 CHECK_DW;
     328             :                 rc = 0;
     329             :         }
     330             : 
     331           0 :         return rc;
     332             : }
     333             : 
     334             : /*
     335             :  * now all the state machine bits
     336             :  */
     337             : 
     338             : int
     339           0 : wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp,
     340             :     struct wsemul_inputstate *instate, int kernel)
     341             : {
     342           0 :         u_int *ct, dc;
     343             :         u_char c;
     344           0 :         int oldsschartab = edp->sschartab;
     345             :         int rc = 0;
     346             : 
     347           0 :         if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
     348             :             (VTFL_LASTCHAR | VTFL_DECAWM)) {
     349           0 :                 rc = wsemul_vt100_nextline(edp);
     350           0 :                 if (rc != 0)
     351           0 :                         return rc;
     352           0 :                 edp->ccol = 0;
     353           0 :                 edp->flags &= ~VTFL_LASTCHAR;
     354           0 :         }
     355             : 
     356             : #ifdef HAVE_UTF8_SUPPORT
     357           0 :         if (edp->flags & VTFL_UTF8) {
     358           0 :                 (*edp->emulops->mapchar)(edp->emulcookie, instate->inchar, &dc);
     359           0 :         } else
     360             : #endif
     361             :         {
     362           0 :                 c = instate->inchar & 0xff;
     363           0 :                 if (c & 0x80) {
     364           0 :                         c &= 0x7f;
     365           0 :                         ct = edp->chartab_G[edp->chartab1];
     366           0 :                 } else {
     367           0 :                         if (edp->sschartab) {
     368           0 :                                 ct = edp->chartab_G[edp->sschartab];
     369           0 :                                 edp->sschartab = 0;
     370           0 :                         } else
     371           0 :                                 ct = edp->chartab_G[edp->chartab0];
     372             :                 }
     373           0 :                 dc = ct ? ct[c] : c;
     374             :         }
     375             : 
     376           0 :         if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT) {
     377           0 :                 WSEMULOP(rc, edp, &edp->abortstate, copycols,
     378             :                     COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT));
     379           0 :                 if (rc != 0) {
     380             :                         /* undo potential sschartab update */
     381           0 :                         edp->sschartab = oldsschartab;
     382             : 
     383           0 :                         return rc;
     384             :                 }
     385             :         }
     386             : 
     387           0 :         WSEMULOP(rc, edp, &edp->abortstate, putchar,
     388             :             (edp->emulcookie, edp->crow, edp->ccol << edp->dw, dc,
     389             :              kernel ? edp->kernattr : edp->curattr));
     390           0 :         if (rc != 0) {
     391             :                 /* undo potential sschartab update */
     392           0 :                 edp->sschartab = oldsschartab;
     393             : 
     394           0 :                 return rc;
     395             :         }
     396             : 
     397           0 :         if (COLS_LEFT)
     398           0 :                 edp->ccol++;
     399             :         else
     400           0 :                 edp->flags |= VTFL_LASTCHAR;
     401             : 
     402           0 :         return 0;
     403           0 : }
     404             : 
     405             : int
     406           0 : wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp,
     407             :     struct wsemul_inputstate *instate, int kernel)
     408             : {
     409             :         u_int n;
     410             :         int rc = 0;
     411             : 
     412           0 :         switch (instate->inchar) {
     413             :         case ASCII_NUL:
     414             :         default:
     415             :                 /* ignore */
     416             :                 break;
     417             :         case ASCII_BEL:
     418           0 :                 if (edp->state == VT100_EMUL_STATE_STRING) {
     419             :                         /* acts as an equivalent to the ``ESC \'' string end */
     420           0 :                         wsemul_vt100_handle_dcs(edp);
     421           0 :                         edp->state = VT100_EMUL_STATE_NORMAL;
     422           0 :                 } else {
     423           0 :                         wsdisplay_emulbell(edp->cbcookie);
     424             :                 }
     425             :                 break;
     426             :         case ASCII_BS:
     427           0 :                 if (edp->ccol > 0) {
     428           0 :                         edp->ccol--;
     429           0 :                         edp->flags &= ~VTFL_LASTCHAR;
     430           0 :                 }
     431             :                 break;
     432             :         case ASCII_CR:
     433           0 :                 edp->ccol = 0;
     434           0 :                 break;
     435             :         case ASCII_HT:
     436           0 :                 if (edp->tabs) {
     437           0 :                         if (!COLS_LEFT)
     438             :                                 break;
     439           0 :                         for (n = edp->ccol + 1; n < NCOLS - 1; n++)
     440           0 :                                 if (edp->tabs[n])
     441             :                                         break;
     442             :                 } else {
     443           0 :                         n = edp->ccol + min(8 - (edp->ccol & 7), COLS_LEFT);
     444             :                 }
     445           0 :                 edp->ccol = n;
     446           0 :                 break;
     447             :         case ASCII_SO: /* LS1 */
     448           0 :                 edp->flags &= ~VTFL_UTF8;
     449           0 :                 edp->chartab0 = 1;
     450           0 :                 break;
     451             :         case ASCII_SI: /* LS0 */
     452           0 :                 edp->flags &= ~VTFL_UTF8;
     453           0 :                 edp->chartab0 = 0;
     454           0 :                 break;
     455             :         case ASCII_ESC:
     456           0 :                 if (kernel) {
     457           0 :                         printf("wsemul_vt100_output_c0c1: ESC in kernel "
     458             :                             "output ignored\n");
     459           0 :                         break;  /* ignore the ESC */
     460             :                 }
     461             : 
     462           0 :                 if (edp->state == VT100_EMUL_STATE_STRING) {
     463             :                         /* might be a string end */
     464           0 :                         edp->state = VT100_EMUL_STATE_STRING_ESC;
     465           0 :                 } else {
     466             :                         /* XXX cancel current escape sequence */
     467           0 :                         edp->state = VT100_EMUL_STATE_ESC;
     468             :                 }
     469             :                 break;
     470             :         case ASCII_CAN:
     471             :         case ASCII_SUB:
     472             :                 /* cancel current escape sequence */
     473           0 :                 edp->state = VT100_EMUL_STATE_NORMAL;
     474           0 :                 break;
     475             :         case ASCII_LF:
     476             :         case ASCII_VT:
     477             :         case ASCII_FF:
     478           0 :                 rc = wsemul_vt100_nextline(edp);
     479           0 :                 break;
     480             :         }
     481             : 
     482           0 :         if (COLS_LEFT != 0)
     483           0 :                 edp->flags &= ~VTFL_LASTCHAR;
     484             : 
     485           0 :         return rc;
     486             : }
     487             : 
     488             : int
     489           0 : wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp,
     490             :     struct wsemul_inputstate *instate)
     491             : {
     492             :         u_int newstate = VT100_EMUL_STATE_NORMAL;
     493             :         int rc = 0;
     494             :         int i;
     495             : 
     496           0 :         switch (instate->inchar) {
     497             :         case '[': /* CSI */
     498           0 :                 edp->nargs = 0;
     499           0 :                 memset(edp->args, 0, sizeof (edp->args));
     500           0 :                 edp->modif1 = edp->modif2 = '\0';
     501             :                 newstate = VT100_EMUL_STATE_CSI;
     502           0 :                 break;
     503             :         case '7': /* DECSC */
     504           0 :                 edp->flags |= VTFL_SAVEDCURS;
     505           0 :                 edp->savedcursor_row = edp->crow;
     506           0 :                 edp->savedcursor_col = edp->ccol;
     507           0 :                 edp->savedattr = edp->curattr;
     508           0 :                 edp->savedbkgdattr = edp->bkgdattr;
     509           0 :                 edp->savedattrflags = edp->attrflags;
     510           0 :                 edp->savedfgcol = edp->fgcol;
     511           0 :                 edp->savedbgcol = edp->bgcol;
     512           0 :                 for (i = 0; i < 4; i++)
     513           0 :                         edp->savedchartab_G[i] = edp->chartab_G[i];
     514           0 :                 edp->savedchartab0 = edp->chartab0;
     515           0 :                 edp->savedchartab1 = edp->chartab1;
     516           0 :                 break;
     517             :         case '8': /* DECRC */
     518           0 :                 if ((edp->flags & VTFL_SAVEDCURS) == 0)
     519             :                         break;
     520           0 :                 edp->crow = edp->savedcursor_row;
     521           0 :                 edp->ccol = edp->savedcursor_col;
     522           0 :                 edp->curattr = edp->savedattr;
     523           0 :                 edp->bkgdattr = edp->savedbkgdattr;
     524           0 :                 edp->attrflags = edp->savedattrflags;
     525           0 :                 edp->fgcol = edp->savedfgcol;
     526           0 :                 edp->bgcol = edp->savedbgcol;
     527           0 :                 for (i = 0; i < 4; i++)
     528           0 :                         edp->chartab_G[i] = edp->savedchartab_G[i];
     529           0 :                 edp->chartab0 = edp->savedchartab0;
     530           0 :                 edp->chartab1 = edp->savedchartab1;
     531           0 :                 break;
     532             :         case '=': /* DECKPAM application mode */
     533           0 :                 edp->flags |= VTFL_APPLKEYPAD;
     534           0 :                 break;
     535             :         case '>': /* DECKPNM numeric mode */
     536           0 :                 edp->flags &= ~VTFL_APPLKEYPAD;
     537           0 :                 break;
     538             :         case 'E': /* NEL */
     539           0 :                 edp->ccol = 0;
     540             :                 /* FALLTHROUGH */
     541             :         case 'D': /* IND */
     542           0 :                 rc = wsemul_vt100_nextline(edp);
     543           0 :                 break;
     544             :         case 'H': /* HTS */
     545           0 :                 if (edp->tabs != NULL)
     546           0 :                         edp->tabs[edp->ccol] = 1;
     547             :                 break;
     548             :         case '~': /* LS1R */
     549           0 :                 edp->flags &= ~VTFL_UTF8;
     550           0 :                 edp->chartab1 = 1;
     551           0 :                 break;
     552             :         case 'n': /* LS2 */
     553           0 :                 edp->flags &= ~VTFL_UTF8;
     554           0 :                 edp->chartab0 = 2;
     555           0 :                 break;
     556             :         case '}': /* LS2R */
     557           0 :                 edp->flags &= ~VTFL_UTF8;
     558           0 :                 edp->chartab1 = 2;
     559           0 :                 break;
     560             :         case 'o': /* LS3 */
     561           0 :                 edp->flags &= ~VTFL_UTF8;
     562           0 :                 edp->chartab0 = 3;
     563           0 :                 break;
     564             :         case '|': /* LS3R */
     565           0 :                 edp->flags &= ~VTFL_UTF8;
     566           0 :                 edp->chartab1 = 3;
     567           0 :                 break;
     568             :         case 'N': /* SS2 */
     569           0 :                 edp->flags &= ~VTFL_UTF8;
     570           0 :                 edp->sschartab = 2;
     571           0 :                 break;
     572             :         case 'O': /* SS3 */
     573           0 :                 edp->flags &= ~VTFL_UTF8;
     574           0 :                 edp->sschartab = 3;
     575           0 :                 break;
     576             :         case 'M': /* RI */
     577           0 :                 if (ROWS_ABOVE > 0) {
     578           0 :                         edp->crow--;
     579           0 :                         CHECK_DW;
     580             :                         break;
     581             :                 }
     582           0 :                 rc = wsemul_vt100_scrolldown(edp, 1);
     583           0 :                 break;
     584             :         case 'P': /* DCS */
     585           0 :                 edp->nargs = 0;
     586           0 :                 memset(edp->args, 0, sizeof (edp->args));
     587             :                 newstate = VT100_EMUL_STATE_DCS;
     588           0 :                 break;
     589             :         case 'c': /* RIS */
     590           0 :                 wsemul_vt100_reset(edp);
     591           0 :                 rc = wsemul_vt100_ed(edp, 2);
     592           0 :                 if (rc != 0)
     593             :                         break;
     594           0 :                 edp->ccol = edp->crow = 0;
     595           0 :                 break;
     596             :         case '(': case ')': case '*': case '+': /* SCS */
     597           0 :                 edp->designating = instate->inchar - '(';
     598             :                 newstate = VT100_EMUL_STATE_SCS94;
     599           0 :                 break;
     600             :         case '-': case '.': case '/': /* SCS */
     601           0 :                 edp->designating = instate->inchar - '-' + 1;
     602             :                 newstate = VT100_EMUL_STATE_SCS96;
     603           0 :                 break;
     604             :         case '#':
     605             :                 newstate = VT100_EMUL_STATE_ESC_HASH;
     606           0 :                 break;
     607             :         case ' ': /* 7/8 bit */
     608             :                 newstate = VT100_EMUL_STATE_ESC_SPC;
     609           0 :                 break;
     610             :         case ']': /* OSC operating system command */
     611             :         case '^': /* PM privacy message */
     612             :         case '_': /* APC application program command */
     613             :                 /* ignored */
     614             :                 newstate = VT100_EMUL_STATE_STRING;
     615           0 :                 break;
     616             :         case '<': /* exit VT52 mode - ignored */
     617             :                 break;
     618             :         case '%': /* UTF-8 encoding sequences */
     619             :                 newstate = VT100_EMUL_STATE_ESC_PERCENT;
     620           0 :                 break;
     621             :         default:
     622             : #ifdef VT100_PRINTUNKNOWN
     623             :                 printf("ESC %x unknown\n", instate->inchar);
     624             : #endif
     625             :                 break;
     626             :         }
     627             : 
     628           0 :         if (COLS_LEFT != 0)
     629           0 :                 edp->flags &= ~VTFL_LASTCHAR;
     630             : 
     631           0 :         if (rc != 0)
     632           0 :                 return rc;
     633             : 
     634           0 :         edp->state = newstate;
     635           0 :         return 0;
     636           0 : }
     637             : 
     638             : int
     639           0 : wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp,
     640             :     struct wsemul_inputstate *instate)
     641             : {
     642             :         u_int newstate = VT100_EMUL_STATE_NORMAL;
     643             : 
     644           0 :         switch (instate->inchar) {
     645             :         case '%': /* probably DEC supplemental graphic */
     646             :                 newstate = VT100_EMUL_STATE_SCS94_PERCENT;
     647           0 :                 break;
     648             :         case 'A': /* british / national */
     649           0 :                 edp->flags &= ~VTFL_UTF8;
     650           0 :                 edp->chartab_G[edp->designating] = edp->nrctab;
     651           0 :                 break;
     652             :         case 'B': /* ASCII */
     653           0 :                 edp->flags &= ~VTFL_UTF8;
     654           0 :                 edp->chartab_G[edp->designating] = 0;
     655           0 :                 break;
     656             :         case '<': /* user preferred supplemental */
     657             :                 /* XXX not really "user" preferred */
     658           0 :                 edp->flags &= ~VTFL_UTF8;
     659           0 :                 edp->chartab_G[edp->designating] = edp->isolatin1tab;
     660           0 :                 break;
     661             :         case '0': /* DEC special graphic */
     662           0 :                 edp->flags &= ~VTFL_UTF8;
     663           0 :                 edp->chartab_G[edp->designating] = edp->decgraphtab;
     664           0 :                 break;
     665             :         case '>': /* DEC tech */
     666           0 :                 edp->flags &= ~VTFL_UTF8;
     667           0 :                 edp->chartab_G[edp->designating] = edp->dectechtab;
     668           0 :                 break;
     669             :         default:
     670             : #ifdef VT100_PRINTUNKNOWN
     671             :                 printf("ESC%c %x unknown\n", edp->designating + '(',
     672             :                     instate->inchar);
     673             : #endif
     674             :                 break;
     675             :         }
     676             : 
     677           0 :         edp->state = newstate;
     678           0 :         return 0;
     679             : }
     680             : 
     681             : int
     682           0 : wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp,
     683             :     struct wsemul_inputstate *instate)
     684             : {
     685           0 :         switch (instate->inchar) {
     686             :         case '5': /* DEC supplemental graphic */
     687             :                 /* XXX there are differences */
     688           0 :                 edp->flags &= ~VTFL_UTF8;
     689           0 :                 edp->chartab_G[edp->designating] = edp->isolatin1tab;
     690           0 :                 break;
     691             :         default:
     692             : #ifdef VT100_PRINTUNKNOWN
     693             :                 printf("ESC%c%% %x unknown\n", edp->designating + '(',
     694             :                     instate->inchar);
     695             : #endif
     696             :                 break;
     697             :         }
     698             : 
     699           0 :         edp->state = VT100_EMUL_STATE_NORMAL;
     700           0 :         return 0;
     701             : }
     702             : 
     703             : int
     704           0 : wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata *edp,
     705             :     struct wsemul_inputstate *instate)
     706             : {
     707             :         u_int newstate = VT100_EMUL_STATE_NORMAL;
     708             :         int nrc;
     709             : 
     710           0 :         switch (instate->inchar) {
     711             :         case '%': /* probably portuguese */
     712             :                 newstate = VT100_EMUL_STATE_SCS96_PERCENT;
     713           0 :                 break;
     714             :         case 'A': /* ISO-latin-1 supplemental */
     715           0 :                 edp->flags &= ~VTFL_UTF8;
     716           0 :                 edp->chartab_G[edp->designating] = edp->isolatin1tab;
     717           0 :                 break;
     718             :         case '4': /* dutch */
     719             :                 nrc = 1;
     720           0 :                 goto setnrc;
     721             :         case '5': case 'C': /* finnish */
     722             :                 nrc = 2;
     723           0 :                 goto setnrc;
     724             :         case 'R': /* french */
     725             :                 nrc = 3;
     726           0 :                 goto setnrc;
     727             :         case 'Q': /* french canadian */
     728             :                 nrc = 4;
     729           0 :                 goto setnrc;
     730             :         case 'K': /* german */
     731             :                 nrc = 5;
     732           0 :                 goto setnrc;
     733             :         case 'Y': /* italian */
     734             :                 nrc = 6;
     735           0 :                 goto setnrc;
     736             :         case 'E': case '6': /* norwegian / danish */
     737             :                 nrc = 7;
     738           0 :                 goto setnrc;
     739             :         case 'Z': /* spanish */
     740             :                 nrc = 9;
     741           0 :                 goto setnrc;
     742             :         case '7': case 'H': /* swedish */
     743             :                 nrc = 10;
     744           0 :                 goto setnrc;
     745             :         case '=': /* swiss */
     746           0 :                 nrc = 11;
     747             : setnrc:
     748           0 :                 if (vt100_setnrc(edp, nrc) == 0) /* what table ??? */
     749             :                         break;
     750             :                 /* else FALLTHROUGH */
     751             :         default:
     752             : #ifdef VT100_PRINTUNKNOWN
     753             :                 printf("ESC%c %x unknown\n", edp->designating + '-' - 1,
     754             :                     instate->inchar);
     755             : #endif
     756             :                 break;
     757             :         }
     758             : 
     759           0 :         edp->state = newstate;
     760           0 :         return 0;
     761             : }
     762             : 
     763             : int
     764           0 : wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp,
     765             :     struct wsemul_inputstate *instate)
     766             : {
     767           0 :         switch (instate->inchar) {
     768             :         case '6': /* portuguese */
     769           0 :                 if (vt100_setnrc(edp, 8) == 0)
     770             :                         break;
     771             :                 /* else FALLTHROUGH */
     772             :         default:
     773             : #ifdef VT100_PRINTUNKNOWN
     774             :                 printf("ESC%c%% %x unknown\n", edp->designating + '-' - 1,
     775             :                     instate->inchar);
     776             : #endif
     777             :                 break;
     778             :         }
     779             : 
     780           0 :         edp->state = VT100_EMUL_STATE_NORMAL;
     781           0 :         return 0;
     782             : }
     783             : 
     784             : int
     785           0 : wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp,
     786             :     struct wsemul_inputstate *instate)
     787             : {
     788             :         switch (instate->inchar) {
     789             :         case 'F': /* 7-bit controls */
     790             :         case 'G': /* 8-bit controls */
     791             : #ifdef VT100_PRINTNOTIMPL
     792             :                 printf("ESC<SPC> %x ignored\n", instate->inchar);
     793             : #endif
     794             :                 break;
     795             :         default:
     796             : #ifdef VT100_PRINTUNKNOWN
     797             :                 printf("ESC<SPC> %x unknown\n", instate->inchar);
     798             : #endif
     799             :                 break;
     800             :         }
     801             : 
     802           0 :         edp->state = VT100_EMUL_STATE_NORMAL;
     803           0 :         return 0;
     804             : }
     805             : 
     806             : int
     807           0 : wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp,
     808             :     struct wsemul_inputstate *instate)
     809             : {
     810           0 :         if (edp->dcstype && edp->dcspos < DCS_MAXLEN) {
     811           0 :                 if (instate->inchar & ~0xff) {
     812             : #ifdef VT100_PRINTUNKNOWN
     813             :                         printf("unknown char %x in DCS\n", instate->inchar);
     814             : #endif
     815             :                 } else
     816           0 :                         edp->dcsarg[edp->dcspos++] = (char)instate->inchar;
     817             :         }
     818             : 
     819           0 :         edp->state = VT100_EMUL_STATE_STRING;
     820           0 :         return 0;
     821             : }
     822             : 
     823             : int
     824           0 : wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp,
     825             :     struct wsemul_inputstate *instate)
     826             : {
     827           0 :         if (instate->inchar == '\\') { /* ST complete */
     828           0 :                 wsemul_vt100_handle_dcs(edp);
     829           0 :                 edp->state = VT100_EMUL_STATE_NORMAL;
     830           0 :         } else
     831           0 :                 edp->state = VT100_EMUL_STATE_STRING;
     832             : 
     833           0 :         return 0;
     834             : }
     835             : 
     836             : int
     837           0 : wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp,
     838             :     struct wsemul_inputstate *instate)
     839             : {
     840             :         u_int newstate = VT100_EMUL_STATE_DCS;
     841             : 
     842           0 :         switch (instate->inchar) {
     843             :         case '0': case '1': case '2': case '3': case '4':
     844             :         case '5': case '6': case '7': case '8': case '9':
     845             :                 /* argument digit */
     846           0 :                 if (edp->nargs > VT100_EMUL_NARGS - 1)
     847             :                         break;
     848           0 :                 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
     849           0 :                     (instate->inchar - '0');
     850           0 :                 break;
     851             :         case ';': /* argument terminator */
     852           0 :                 edp->nargs++;
     853           0 :                 break;
     854             :         default:
     855           0 :                 edp->nargs++;
     856           0 :                 if (edp->nargs > VT100_EMUL_NARGS) {
     857             : #ifdef VT100_DEBUG
     858             :                         printf("vt100: too many arguments\n");
     859             : #endif
     860           0 :                         edp->nargs = VT100_EMUL_NARGS;
     861           0 :                 }
     862             :                 newstate = VT100_EMUL_STATE_STRING;
     863           0 :                 switch (instate->inchar) {
     864             :                 case '$':
     865             :                         newstate = VT100_EMUL_STATE_DCS_DOLLAR;
     866             :                         break;
     867             :                 case '{': /* DECDLD soft charset */     /* } */
     868             :                 case '!': /* DECRQUPSS user preferred supplemental set */
     869             :                         /* 'u' must follow - need another state */
     870             :                 case '|': /* DECUDK program F6..F20 */
     871             : #ifdef VT100_PRINTNOTIMPL
     872             :                         printf("DCS%c ignored\n", (char)instate->inchar);
     873             : #endif
     874             :                         break;
     875             :                 default:
     876             : #ifdef VT100_PRINTUNKNOWN
     877             :                         printf("DCS %x (%d, %d) unknown\n", instate->inchar,
     878             :                             ARG(0), ARG(1));
     879             : #endif
     880             :                         break;
     881             :                 }
     882             :         }
     883             : 
     884           0 :         edp->state = newstate;
     885           0 :         return 0;
     886             : }
     887             : 
     888             : int
     889           0 : wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp,
     890             :     struct wsemul_inputstate *instate)
     891             : {
     892           0 :         switch (instate->inchar) {
     893             :         case 'p': /* DECRSTS terminal state restore */
     894             :         case 'q': /* DECRQSS control function request */
     895             : #ifdef VT100_PRINTNOTIMPL
     896             :                 printf("DCS$%c ignored\n", (char)instate->inchar);
     897             : #endif
     898             :                 break;
     899             :         case 't': /* DECRSPS restore presentation state */
     900           0 :                 switch (ARG(0)) {
     901             :                 case 0: /* error */
     902             :                         break;
     903             :                 case 1: /* cursor information restore */
     904             : #ifdef VT100_PRINTNOTIMPL
     905             :                         printf("DCS1$t ignored\n");
     906             : #endif
     907             :                         break;
     908             :                 case 2: /* tab stop restore */
     909           0 :                         edp->dcspos = 0;
     910           0 :                         edp->dcstype = DCSTYPE_TABRESTORE;
     911           0 :                         break;
     912             :                 default:
     913             : #ifdef VT100_PRINTUNKNOWN
     914             :                         printf("DCS%d$t unknown\n", ARG(0));
     915             : #endif
     916             :                         break;
     917             :                 }
     918             :                 break;
     919             :         default:
     920             : #ifdef VT100_PRINTUNKNOWN
     921             :                 printf("DCS$ %x (%d, %d) unknown\n",
     922             :                     instate->inchar, ARG(0), ARG(1));
     923             : #endif
     924             :                 break;
     925             :         }
     926             : 
     927           0 :         edp->state = VT100_EMUL_STATE_STRING;
     928           0 :         return 0;
     929             : }
     930             : 
     931             : int
     932           0 : wsemul_vt100_output_esc_percent(struct wsemul_vt100_emuldata *edp,
     933             :     struct wsemul_inputstate *instate)
     934             : {
     935           0 :         switch (instate->inchar) {
     936             : #ifdef HAVE_UTF8_SUPPORT
     937             :         case 'G':
     938           0 :                 edp->flags |= VTFL_UTF8;
     939           0 :                 edp->kstate.mbleft = edp->instate.mbleft = 0;
     940           0 :                 break;
     941             :         case '@':
     942           0 :                 edp->flags &= ~VTFL_UTF8;
     943           0 :                 break;
     944             : #endif
     945             :         default:
     946             : #ifdef VT100_PRINTUNKNOWN
     947             :                 printf("ESC% %x unknown\n", instate->inchar);
     948             : #endif
     949             :                 break;
     950             :         }
     951           0 :         edp->state = VT100_EMUL_STATE_NORMAL;
     952           0 :         return 0;
     953             : }
     954             : 
     955             : int
     956           0 : wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp,
     957             :     struct wsemul_inputstate *instate)
     958             : {
     959             :         int i;
     960             :         int rc = 0;
     961             : 
     962           0 :         switch (instate->inchar) {
     963             :         case '5': /*  DECSWL single width, single height */
     964           0 :                 if (edp->dblwid != NULL && edp->dw != 0) {
     965           0 :                         for (i = 0; i < edp->ncols / 2; i++) {
     966           0 :                                 WSEMULOP(rc, edp, &edp->abortstate, copycols,
     967             :                                     (edp->emulcookie, edp->crow, 2 * i, i, 1));
     968           0 :                                 if (rc != 0)
     969           0 :                                         return rc;
     970             :                         }
     971           0 :                         WSEMULOP(rc, edp, &edp->abortstate, erasecols,
     972             :                             (edp->emulcookie, edp->crow, i, edp->ncols - i,
     973             :                              edp->bkgdattr));
     974           0 :                         if (rc != 0)
     975           0 :                                 return rc;
     976           0 :                         edp->dblwid[edp->crow] = 0;
     977           0 :                         edp->dw = 0;
     978           0 :                 }
     979             :                 break;
     980             :         case '6': /*  DECDWL double width, single height */
     981             :         case '3': /*  DECDHL double width, double height, top half */
     982             :         case '4': /*  DECDHL double width, double height, bottom half */
     983           0 :                 if (edp->dblwid != NULL && edp->dw == 0) {
     984           0 :                         for (i = edp->ncols / 2 - 1; i >= 0; i--) {
     985           0 :                                 WSEMULOP(rc, edp, &edp->abortstate, copycols,
     986             :                                     (edp->emulcookie, edp->crow, i, 2 * i, 1));
     987           0 :                                 if (rc != 0)
     988           0 :                                         return rc;
     989             :                         }
     990           0 :                         for (i = 0; i < edp->ncols / 2; i++) {
     991           0 :                                 WSEMULOP(rc, edp, &edp->abortstate, erasecols,
     992             :                                     (edp->emulcookie, edp->crow, 2 * i + 1, 1,
     993             :                                      edp->bkgdattr));
     994           0 :                                 if (rc != 0)
     995           0 :                                         return rc;
     996             :                         }
     997           0 :                         edp->dblwid[edp->crow] = 1;
     998           0 :                         edp->dw = 1;
     999           0 :                         if (edp->ccol > (edp->ncols >> 1) - 1)
    1000           0 :                                 edp->ccol = (edp->ncols >> 1) - 1;
    1001             :                 }
    1002             :                 break;
    1003             :         case '8': { /* DECALN */
    1004             :                 int i, j;
    1005           0 :                 for (i = 0; i < edp->nrows; i++)
    1006           0 :                         for (j = 0; j < edp->ncols; j++) {
    1007           0 :                                 WSEMULOP(rc, edp, &edp->abortstate, putchar,
    1008             :                                     (edp->emulcookie, i, j, 'E', edp->curattr));
    1009           0 :                                 if (rc != 0)
    1010           0 :                                         return rc;
    1011             :                         }
    1012           0 :                 }
    1013           0 :                 edp->ccol = 0;
    1014           0 :                 edp->crow = 0;
    1015           0 :                 break;
    1016             :         default:
    1017             : #ifdef VT100_PRINTUNKNOWN
    1018             :                 printf("ESC# %x unknown\n", instate->inchar);
    1019             : #endif
    1020             :                 break;
    1021             :         }
    1022             : 
    1023           0 :         if (COLS_LEFT != 0)
    1024           0 :                 edp->flags &= ~VTFL_LASTCHAR;
    1025             : 
    1026           0 :         edp->state = VT100_EMUL_STATE_NORMAL;
    1027           0 :         return 0;
    1028           0 : }
    1029             : 
    1030             : int
    1031           0 : wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp,
    1032             :     struct wsemul_inputstate *instate)
    1033             : {
    1034             :         u_int newstate = VT100_EMUL_STATE_CSI;
    1035             :         int oargs;
    1036             :         int rc = 0;
    1037             : 
    1038           0 :         switch (instate->inchar) {
    1039             :         case '0': case '1': case '2': case '3': case '4':
    1040             :         case '5': case '6': case '7': case '8': case '9':
    1041             :                 /* argument digit */
    1042           0 :                 if (edp->nargs > VT100_EMUL_NARGS - 1)
    1043             :                         break;
    1044           0 :                 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
    1045           0 :                     (instate->inchar - '0');
    1046           0 :                 break;
    1047             :         case ';': /* argument terminator */
    1048           0 :                 edp->nargs++;
    1049           0 :                 break;
    1050             :         case '?': /* DEC specific */
    1051             :         case '>': /* DA query */
    1052           0 :                 edp->modif1 = (char)instate->inchar;
    1053           0 :                 break;
    1054             :         case '!':
    1055             :         case '"':
    1056             :         case '$':
    1057             :         case '&':
    1058           0 :                 edp->modif2 = (char)instate->inchar;
    1059           0 :                 break;
    1060             :         default: /* end of escape sequence */
    1061           0 :                 oargs = edp->nargs++;
    1062           0 :                 if (edp->nargs > VT100_EMUL_NARGS) {
    1063             : #ifdef VT100_DEBUG
    1064             :                         printf("vt100: too many arguments\n");
    1065             : #endif
    1066           0 :                         edp->nargs = VT100_EMUL_NARGS;
    1067           0 :                 }
    1068           0 :                 rc = wsemul_vt100_handle_csi(edp, instate);
    1069           0 :                 if (rc != 0) {
    1070           0 :                         edp->nargs = oargs;
    1071           0 :                         return rc;
    1072             :                 }
    1073             :                 newstate = VT100_EMUL_STATE_NORMAL;
    1074           0 :                 break;
    1075             :         }
    1076             : 
    1077           0 :         if (COLS_LEFT != 0)
    1078           0 :                 edp->flags &= ~VTFL_LASTCHAR;
    1079             : 
    1080           0 :         edp->state = newstate;
    1081           0 :         return 0;
    1082           0 : }
    1083             : 
    1084             : u_int
    1085           0 : wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
    1086             : {
    1087           0 :         struct wsemul_vt100_emuldata *edp = cookie;
    1088             :         struct wsemul_inputstate *instate;
    1089             :         u_int processed = 0;
    1090             : #ifdef HAVE_JUMP_SCROLL
    1091             :         int lines;
    1092             : #endif
    1093             :         int rc = 0;
    1094             : 
    1095             : #ifdef DIAGNOSTIC
    1096           0 :         if (kernel && !edp->console)
    1097           0 :                 panic("wsemul_vt100_output: kernel output, not console");
    1098             : #endif
    1099             : 
    1100           0 :         instate = kernel ? &edp->kstate : &edp->instate;
    1101             : 
    1102           0 :         switch (edp->abortstate.state) {
    1103             :         case ABORT_FAILED_CURSOR:
    1104             :                 /*
    1105             :                  * If we could not display the cursor back, we pretended not
    1106             :                  * having been able to display the last character. But this
    1107             :                  * is a lie, so compensate here.
    1108             :                  */
    1109           0 :                 data++, count--;
    1110             :                 processed++;
    1111           0 :                 wsemul_reset_abortstate(&edp->abortstate);
    1112           0 :                 break;
    1113             :         case ABORT_OK:
    1114             :                 /* remove cursor image if visible */
    1115           0 :                 if (edp->flags & VTFL_CURSORON) {
    1116           0 :                         rc = (*edp->emulops->cursor)
    1117           0 :                             (edp->emulcookie, 0, edp->crow,
    1118           0 :                              edp->ccol << edp->dw);
    1119           0 :                         if (rc != 0)
    1120           0 :                                 return 0;
    1121             :                 }
    1122             :                 break;
    1123             :         default:
    1124             :                 break;
    1125             :         }
    1126             : 
    1127           0 :         for (;;) {
    1128             : #ifdef HAVE_JUMP_SCROLL
    1129           0 :                 switch (edp->abortstate.state) {
    1130             :                 case ABORT_FAILED_JUMP_SCROLL:
    1131             :                         /*
    1132             :                          * If we failed a previous jump scroll attempt, we
    1133             :                          * need to try to resume it with the same distance.
    1134             :                          * We can not recompute it since there might be more
    1135             :                          * bytes in the tty ring, causing a different result.
    1136             :                          */
    1137           0 :                         lines = edp->abortstate.lines;
    1138           0 :                         break;
    1139             :                 case ABORT_OK:
    1140             :                         /*
    1141             :                          * If we are at the bottom of the scrolling area, count
    1142             :                          * newlines until an escape sequence appears.
    1143             :                          */
    1144           0 :                         if ((edp->state == VT100_EMUL_STATE_NORMAL || kernel) &&
    1145           0 :                             ROWS_BELOW == 0)
    1146           0 :                                 lines = wsemul_vt100_jump_scroll(edp, data,
    1147           0 :                                     count, kernel);
    1148             :                         else
    1149             :                                 lines = 0;
    1150             :                         break;
    1151             :                 default:
    1152             :                         /*
    1153             :                          * If we are recovering a non-scrolling failure,
    1154             :                          * do not try to scroll yet.
    1155             :                          */
    1156             :                         lines = 0;
    1157           0 :                         break;
    1158             :                 }
    1159             : 
    1160           0 :                 if (lines > 1) {
    1161           0 :                         wsemul_resume_abort(&edp->abortstate);
    1162           0 :                         rc = wsemul_vt100_scrollup(edp, lines);
    1163           0 :                         if (rc != 0) {
    1164           0 :                                 wsemul_abort_jump_scroll(&edp->abortstate,
    1165             :                                     lines);
    1166           0 :                                 return processed;
    1167             :                         }
    1168           0 :                         wsemul_reset_abortstate(&edp->abortstate);
    1169           0 :                         edp->crow -= lines;
    1170           0 :                 }
    1171             : #endif
    1172             : 
    1173           0 :                 wsemul_resume_abort(&edp->abortstate);
    1174             : 
    1175           0 :                 if (wsemul_getchar(&data, &count, instate,
    1176             : #ifdef HAVE_UTF8_SUPPORT
    1177           0 :                     (edp->state == VT100_EMUL_STATE_NORMAL && !kernel) ?
    1178           0 :                       edp->flags & VTFL_UTF8 : 0
    1179             : #else
    1180             :                     0
    1181             : #endif
    1182           0 :                     ) != 0)
    1183             :                         break;
    1184             : 
    1185           0 :                 if (!(instate->inchar & ~0xff) &&
    1186           0 :                     (instate->inchar & 0x7f) < 0x20) {
    1187           0 :                         rc = wsemul_vt100_output_c0c1(edp, instate, kernel);
    1188           0 :                         if (rc != 0)
    1189             :                                 break;
    1190           0 :                         processed++;
    1191           0 :                         continue;
    1192             :                 }
    1193             :  
    1194           0 :                 if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
    1195           0 :                         rc = wsemul_vt100_output_normal(edp, instate, kernel);
    1196           0 :                         if (rc != 0)
    1197             :                                 break;
    1198           0 :                         processed++;
    1199           0 :                         continue;
    1200             :                 }
    1201             : #ifdef DIAGNOSTIC
    1202           0 :                 if (edp->state > nitems(vt100_output))
    1203           0 :                         panic("wsemul_vt100: invalid state %d", edp->state);
    1204             : #endif
    1205           0 :                 rc = vt100_output[edp->state - 1](edp, instate);
    1206           0 :                 if (rc != 0)
    1207             :                         break;
    1208           0 :                 processed++;
    1209             :         }
    1210             : 
    1211           0 :         if (rc != 0)
    1212           0 :                 wsemul_abort_other(&edp->abortstate);
    1213             :         else {
    1214             :                 /* put cursor image back if visible */
    1215           0 :                 if (edp->flags & VTFL_CURSORON) {
    1216           0 :                         rc = (*edp->emulops->cursor)
    1217           0 :                             (edp->emulcookie, 1, edp->crow,
    1218           0 :                              edp->ccol << edp->dw);
    1219           0 :                         if (rc != 0) {
    1220             :                                 /*
    1221             :                                  * Fail the last character output, remembering
    1222             :                                  * that only the cursor operation really needs
    1223             :                                  * to be done.
    1224             :                                  */
    1225           0 :                                 wsemul_abort_cursor(&edp->abortstate);
    1226           0 :                                 processed--;
    1227           0 :                         }
    1228             :                 }
    1229             :         }
    1230             : 
    1231           0 :         if (rc == 0)
    1232           0 :                 wsemul_reset_abortstate(&edp->abortstate);
    1233             : 
    1234           0 :         return processed;
    1235           0 : }
    1236             : 
    1237             : #ifdef HAVE_JUMP_SCROLL
    1238             : int
    1239           0 : wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *edp, const u_char *data,
    1240             :     u_int count, int kernel)
    1241             : {
    1242           0 :         struct wsemul_inputstate tmpstate;
    1243             :         u_int pos, lines;
    1244             : 
    1245             :         lines = 0;
    1246           0 :         pos = edp->ccol;
    1247           0 :         tmpstate = kernel ? edp->kstate : edp->instate;   /* structure copy */
    1248             : 
    1249           0 :         while (wsemul_getchar(&data, &count, &tmpstate,
    1250             : #ifdef HAVE_UTF8_SUPPORT
    1251           0 :             kernel ? 0 : edp->flags & VTFL_UTF8
    1252             : #else
    1253             :             0
    1254             : #endif
    1255           0 :             ) == 0) {
    1256             :                 /*
    1257             :                  * Only char causing a transition from
    1258             :                  * VT100_EMUL_STATE_NORMAL to another state, for now.
    1259             :                  * Revisit this if this changes...
    1260             :                  */
    1261           0 :                 if (tmpstate.inchar == ASCII_ESC)
    1262             :                         break;
    1263             : 
    1264           0 :                 if (ISSET(edp->flags, VTFL_DECAWM))
    1265           0 :                         switch (tmpstate.inchar) {
    1266             :                         case ASCII_BS:
    1267           0 :                                 if (pos > 0)
    1268           0 :                                         pos--;
    1269             :                                 break;
    1270             :                         case ASCII_CR:
    1271             :                                 pos = 0;
    1272           0 :                                 break;
    1273             :                         case ASCII_HT:
    1274           0 :                                 if (edp->tabs) {
    1275           0 :                                         pos++;
    1276           0 :                                         while (pos < NCOLS - 1 &&
    1277           0 :                                             edp->tabs[pos] == 0)
    1278           0 :                                                 pos++;
    1279             :                                 } else {
    1280           0 :                                         pos = (pos + 7) & ~7;
    1281           0 :                                         if (pos >= NCOLS)
    1282           0 :                                                 pos = NCOLS - 1;
    1283             :                                 }
    1284             :                                 break;
    1285             :                         default:
    1286           0 :                                 if (!(tmpstate.inchar & ~0xff) &&
    1287           0 :                                     (tmpstate.inchar & 0x7f) < 0x20)
    1288             :                                         break;
    1289           0 :                                 if (pos++ >= NCOLS) {
    1290             :                                         pos = 0;
    1291           0 :                                         tmpstate.inchar = ASCII_LF;
    1292           0 :                                 }
    1293             :                                 break;
    1294             :                         }
    1295             : 
    1296           0 :                 if (tmpstate.inchar == ASCII_LF ||
    1297           0 :                     tmpstate.inchar == ASCII_VT ||
    1298           0 :                     tmpstate.inchar == ASCII_FF) {
    1299           0 :                         if (++lines >= edp->scrreg_nrows - 1)
    1300             :                                 break;
    1301             :                 }
    1302             :         }
    1303             : 
    1304           0 :         return lines;
    1305           0 : }
    1306             : #endif

Generated by: LCOV version 1.13