/* $NetBSD: vt220.c,v 1.2 2002/10/05 17:16:37 chs Exp $ */ /* * Copyright (c) 1994-1995 Melvyn Tang-Richardson * Copyright (c) 1994-1995 RiscBSD kernel team * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the RiscBSD kernel team * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * RiscBSD kernel project * * vt220.c * * VT220 emulation functions * * Created : 17/09/94 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DIAGNOSTIC #include "qms.h" #endif static char vt220_name[] = "vt100"; /* These defines are for the developer only !!!! */ #define SELFTEST #define dprintf(x) ; /*************************************************/ #define FGCOL 0x0700 #define BGCOL 0x3800 /* Options */ #define HARD_RESET_AT_INIT #undef SIMPLE_CURSOR /* Define if any render engine is cursorless */ /*************************************************/ #define DA_VT220 "\033[?62;1;2;6;7;8;9c" char console_proc[41]; /* Is this debugging ? */ #ifdef SIMPLE_CURSOR #define SIMPLE_CURSOR_CHAR ('_') #endif #define TERMTYPE_PUTSTRING vt220_putstring #define TERMTYPE_INIT vt220_init extern struct vconsole *vconsole_master; extern void sysbeep(int, int); /* XXX elsewhere ? */ static int default_beepstate = 0; #define CDATA struct vt220_info *cdata = (struct vt220_info *)vc->data struct vt220_info master_termdata_store; struct vt220_info *master_termdata = &master_termdata_store; int do_render(char, struct vconsole *); void do_render_noscroll(char, struct vconsole *); void do_scrollcheck(struct vconsole *); int mapped_cls(struct vconsole *); void do_scrollup(struct vconsole *); void do_scrolldown(struct vconsole *); void vt_ris(struct vconsole *); #if defined(DIAGNOSTIC) && NQMS > 0 void qms_console_freeze(void); /* XXX */ #endif /* DIAGNOSTIC && NQMS */ void clr_params(struct vt220_info *); void respond(struct vconsole *); int vt220_init(struct vconsole *); int vt220_putstring(char *, int, struct vconsole *); int vt220_swapin(struct vconsole *); int vt220_swapout(struct vconsole *); int vt220_sleep(struct vconsole *); int vt220_wake(struct vconsole *); int vt220_scrollback(struct vconsole *); int vt220_scrollforward(struct vconsole *); int vt220_scrollbackend(struct vconsole *); int vt220_debugprint(struct vconsole *); int vt220_modechange(struct vconsole *); int vt220_attach(struct vconsole *, struct device *, struct device *, void *); void vt_curadr(struct vconsole *); void vt_reset_dec_priv_qm(struct vconsole *); void vt_sc(struct vconsole *); void vt_rc(struct vconsole *); void vt_clreol(struct vconsole *); void vt_ind(struct vconsole *); void vt_nel(struct vconsole *); void vt_ri(struct vconsole *); int vt_sel(struct vconsole *); void vt_cuu(struct vconsole *); void vt_cub(struct vconsole *); void vt_da(struct vconsole *); void vt_str(struct vconsole *); void vt_ris(struct vconsole *); void vt_cud(struct vconsole *); void vt_tst(struct vconsole *); void vt_il(struct vconsole *); void vt_ic(struct vconsole *); void vt_dch(struct vconsole *); void vt_dl(struct vconsole *); void vt_stbm(struct vconsole *); void vt_dsr(struct vconsole *); void vt_su(struct vconsole *); void vt_set_dec_priv_qm(struct vconsole *); void vt_keyappl(struct vconsole *); void vt_clrtab(struct vconsole *); void vt_cuf(struct vconsole *); void vt_sgr(struct vconsole *); void vt_clreos(struct vconsole *); void vt_set_ansi(struct vconsole *); void vt_reset_ansi(struct vconsole *); void clr_params(cdata) struct vt220_info *cdata; { int i; for (i=0; iparam[i] = 0; cdata->parami = 0; } int TERMTYPE_INIT(vc) struct vconsole *vc; { struct vt220_info *cdata; if (vc->data==NULL) { if (vc==vconsole_master) { vc->data = (char *) master_termdata; } else { MALLOC(vc->data, char *, sizeof(struct vt220_info), M_DEVBUF, M_NOWAIT); /* printf("vc=%08x data=%08x\n", vc, vc->data);*/ } } cdata = (struct vt220_info *)vc->data; memset((char *)cdata, 0, sizeof (cdata)); #ifdef HARD_RESET_AT_INIT vt_ris(vc); #else cdata->state = STATE_INIT; cdata->disable_function = 1; cdata->m_om = 0; vc->xcur = vc->ycur = 0; cdata->beepoff=default_beepstate; cdata->simple_cursor_store = ' '; cdata->scrr_beg = 0; cdata->scrr_len = vc->ychars; cdata->scrr_end = vc->ychars-1; cdata->simple_cursor_on = 0; for ( counter=0; countertab_stops[counter] = 1; else cdata->tab_stops[counter] = 0; } #endif return 0; } int mapped_cls(vc) struct vconsole *vc; { int ptr; if (vc->charmap == NULL) return -1; for (ptr=0; ptr<(vc->xchars*vc->ychars); ptr++) vc->charmap[ptr]=0x20; return 0; } void do_scrolldown(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; /* if ( ( cdata->scrr_beg<0 ) || ( cdata->scrr_end>=vc->ychars) ) dprintf ( "INVALID SCROLLDOWN" ); */ /* Clean up */ /* if ( cdata->scrr_beg < 0 ) cdata->scrr_beg = 0; */ if ( cdata->scrr_end >= vc->ychars ) cdata->scrr_end=vc->ychars-1; if (vc==vconsole_current) vc->SCROLLDOWN ( vc, cdata->scrr_beg, cdata->scrr_end ); else vconsole_pending=vc->number; if (((vc->flags)&(LOSSY)) == 0) { int counter; for (counter=((cdata->scrr_end+1)*(vc->xchars)) - 1; counter >= (cdata->scrr_beg+1)*(vc->xchars) ; counter-- ) { vc->charmap[counter] = vc->charmap[counter-vc->xchars]; } for (counter=(cdata->scrr_beg)*(vc->xchars); counter < (cdata->scrr_beg+1)*(vc->xchars); counter++ ) { vc->charmap[counter]=0x20; } } } void do_scrollup(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; if (vc==vconsole_current) vc->SCROLLUP ( vc, cdata->scrr_beg, cdata->scrr_end ); else vconsole_pending = vc->number; if ( cdata->scrr_end == 0 ) vc->ycur=vc->ychars-1; else vc->ycur=cdata->scrr_end; /* Do a cyclic buffer for this !!!!!!!!!!!!!! */ if ( ((vc->flags)&(LOSSY)) == 0 ) { /* bcopy was weird, do this for now */ int counter; for ( counter=(cdata->scrr_beg+1)*vc->xchars; counter < ((cdata->scrr_end+1)*(vc->xchars)); counter++ ) { vc->charmap[counter-vc->xchars] = vc->charmap[counter]; } for ( counter=vc->xchars*(cdata->scrr_end); counter < (vc->xchars*(cdata->scrr_end+1)); counter++ ) { vc->charmap[counter]=0x20; } } } void respond(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; while (*cdata->report_chars && cdata->report_count > 0) { (*vc->tp->t_linesw->l_rint) (*cdata->report_chars++ & 0xff, vc->tp); cdata->report_count--; } } void vt_curadr(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; #ifdef SELFTEST strcpy ( console_proc, "vt_curadr" ); #endif if (cdata->m_om) { /* relative to scrolling region */ cdata->param[0]+=cdata->scrr_beg; if ( (cdata->param[0]==0) && (cdata->param[1]==0) ) { vc->xcur = 0; vc->ycur = 0; return; } /* Limit checking */ cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; cdata->param[0] = (cdata->param[0] > vc->ychars) ? vc->ychars : cdata->param[0]; cdata->param[1] = (cdata->param[1] <= 0) ? 1 : cdata->param[1]; cdata->param[1] = (cdata->param[1] >= vc->xchars) ? (vc->xchars-1) : cdata->param[1]; (cdata->param[0])--; (cdata->param[1])--; vc->ycur = cdata->param[0]; vc->xcur = cdata->param[1]; } else { if ( (cdata->param[0]==0) && (cdata->param[1]==0) ) { vc->xcur = 0; vc->ycur = 0; return; } /* Limit checking */ cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; cdata->param[0] = (cdata->param[0] > vc->ychars) ? vc->ychars : cdata->param[0]; cdata->param[1] = (cdata->param[1] <= 0) ? 1 : cdata->param[1]; cdata->param[1] = (cdata->param[1] >= vc->xchars) ? (vc->xchars-1) : cdata->param[1]; (cdata->param[0])--; (cdata->param[1])--; vc->ycur = cdata->param[0]; vc->xcur = cdata->param[1]; { char buf[80]; sprintf ( buf, "vc->xcur %d vc->ycur %d", vc->xcur, vc->ycur ); dprintf ( buf ); } } } void vt_reset_dec_priv_qm(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; #ifdef SELFTEST strcpy(console_proc, "vt_reset_dec_priv_qm"); #endif switch(cdata->param[0]) { case 7: /* AWM - auto wrap mode */ sysbeep(1000, 100); cdata->flags &= ~F_AWM; break; case 0: /* error, ignored */ case 1: /* CKM - cursor key mode */ case 2: /* ANM - ansi/vt52 mode */ case 3: /* COLM - column mode */ case 4: /* SCLM - scrolling mode */ case 5: /* SCNM - screen mode */ case 8: /* ARM - auto repeat mode */ case 9: /* INLM - interlace mode */ case 10: /* EDM - edit mode */ case 11: /* LTM - line transmit mode */ case 12: /* */ case 13: /* SCFDM - space compression / field delimiting */ case 14: /* TEM - transmit execution mode */ case 15: /* */ case 16: /* EKEM - edit key execution mode */ case 25: /* TCEM - text cursor enable mode */ case 42: /* NRCM - 7bit NRC characters */ break; case 6: /* OM - origin mode */ cdata->m_om = 0; break; } } void vt_sc(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; #ifdef SELFTEST strcpy(console_proc, "vt_sc"); #endif cdata->sc_G0 = cdata->G0; cdata->sc_G1 = cdata->G1; cdata->sc_G2 = cdata->G2; cdata->sc_G3 = cdata->G3; cdata->sc_GL = cdata->GL; cdata->sc_GR = cdata->GR; cdata->sc_xcur = vc->xcur; cdata->sc_ycur = vc->ycur; cdata->sc_om = cdata->m_om; cdata->sflags = cdata->flags; /* cdata->sc_attr = cdata->c_attr; cdata->sc_awm = cdata->m_awm; cdata->sc_sel = cdata->selchar; cdata->sc_vtsgr = cdata->vtsgr; cdata->sc_flag = 1; */ } void vt_rc(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; cdata->G0 = cdata->sc_G0; cdata->G1 = cdata->sc_G1; cdata->G2 = cdata->sc_G2; cdata->G3 = cdata->sc_G3; cdata->GL = cdata->sc_GL; cdata->GR = cdata->sc_GR; vc->xcur = cdata->sc_xcur; vc->ycur = cdata->sc_ycur; cdata->m_om = cdata->sc_om; cdata->flags = cdata->sflags; /* cdata->c_attr = cdata->sc_attr; cdata->awm = cdata->sc_awm; cdata->sel = cdata->sc_selchar; cdata->vtsgr = cdata->sc_vtsgr; cdata->flag = 0; */ } void vt_clreol(vc) struct vconsole *vc; { int counter; int x = vc->xcur; int y = vc->ycur; #ifdef SELFTEST strcpy(console_proc, "vt_clreol"); #endif for (counter = vc->xcur; counter < vc->xchars; counter++) do_render_noscroll(' ', vc); vc->xcur = x; vc->ycur = y; } /* index, move cursor down */ void vt_ind(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; char buf[80]; #ifdef SELFTEST strcpy(console_proc, "vt_ind"); #endif vc->ycur++; sprintf ( buf, "{vt_ind [%d,%d] [%d,%d] }", vc->xcur, vc->ycur, cdata->scrr_beg, cdata->scrr_end); dprintf ( buf ); do_scrollcheck ( vc ); } void vt_nel(vc) struct vconsole *vc; { vc->ycur++; do_scrollcheck(vc); vc->xcur=0; } void vt_ri(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; vc->ycur--; if (vc->ycur <= cdata->scrr_beg) vc->ycur = cdata->scrr_beg; if (vc->ycur <= cdata->scrr_beg) { do_scrolldown ( vc ); vc->ycur = cdata->scrr_beg; } } /* selective in line erase */ int vt_sel(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; int counter; int x = vc->xcur; int y = vc->ycur; switch (cdata->param[0]) { case 0: /* Delete to the end of the line */ for (counter = x; counter < vc->xchars; counter++) do_render_noscroll(' ', vc); break; case 1: /* Delete to the beginning of the line */ vc->xcur = 0; for (counter = 0; counter < x; counter++) do_render_noscroll(' ', vc); break; case 2: /* Delete the whole line */ default: vc->xcur = 0; for (counter = 0; counter < vc->xchars; counter++) do_render_noscroll(' ', vc); break; } vc->xcur = x; vc->ycur = y; return 0; } void vt_cuu(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; vc->ycur -= cdata->param[0]; vc->ycur = vc->ycur < 0 ? 0 : vc->ycur; } void vt_cub(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; vc->xcur -= cdata->param[0]; cdata->param[0] = (cdata->param[0] < 0 ) ? 0 : cdata->param[0]; } void vt_da(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; static u_char *response = (u_char *)DA_VT220; cdata->report_chars = response; cdata->report_count = 18; respond(vc); } void vt_str(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; int counter; if (cdata == NULL) return; clr_params ( cdata ); cdata->state = STATE_INIT; cdata->disable_function = 1; cdata->m_om = 0; /* origin mode */ vc->xcur = vc->ycur = 0; cdata->beepoff=default_beepstate; cdata->simple_cursor_store = ' '; cdata->scrr_beg = 0; cdata->scrr_len = vc->ychars; cdata->scrr_end = vc->ychars-1; cdata->simple_cursor_on = 0; cdata->nfgcol = 7; cdata->nbgcol = 0; cdata->fgcol = cdata->nfgcol; cdata->bgcol = cdata->nbgcol; cdata->attribs=cdata->fgcol<<8 | cdata->bgcol<<11; cdata->sc_flag = 0; /* save cursor position */ cdata->flags = F_AWM; cdata->irm = 0; for (counter = 0; counter < MAXTABSTOPS; counter++) { if (!(counter % 8)) cdata->tab_stops[counter] = 1; else cdata->tab_stops[counter] = 0; } } void vt_ris(vc) struct vconsole *vc; { vc->xcur = vc->ycur = 0; vt_str(vc); /* and soft terminal reset */ } void vt_cud(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; cdata->param[0] = (cdata->param[0] > (cdata->scrr_end-vc->ycur)) ? (cdata->scrr_end-vc->ycur) : cdata->param[0]; vc->ycur += cdata->param[0]; do_scrollcheck ( vc ); } /* What is this for ? --mark */ void vt_tst(vc) struct vconsole *vc; { int counter, times; for (times=0; times<100; times++); for (counter=32; counter<127; counter++) do_render(counter, vc); } void vt_il(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; register int beg, end; if (vc->ycur >= (vc->ychars-2)) return; cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0]; beg = cdata->scrr_beg; end = cdata->scrr_end; cdata->scrr_beg = vc->ycur; cdata->scrr_end = vc->ychars-1; for (; cdata->param[0]>0; cdata->param[0]--) do_scrolldown( vc ); cdata->scrr_beg = beg; cdata->scrr_end = end; } void vt_ic(vc) struct vconsole *vc; { int counter; int ox, oy; int *ptr = vc->charmap + (vc->xcur + vc->ycur*vc->xchars); for (counter=vc->xchars-vc->xcur; counter>=0; counter--) ptr[counter+1] = ptr[counter]; ptr[0] = ' '; ox = vc->xcur; oy = vc->ycur; for (; vc->xcur < vc->xchars;) do_render_noscroll(vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc); vc->xcur = ox; vc->ycur = oy; } void vt_dch(vc) struct vconsole *vc; { int counter; int ox, oy; int *ptr = vc->charmap + (vc->ycur*vc->xchars); for (counter=vc->xcur; counter<(vc->xchars-1); counter++) ptr[counter] = ptr[counter+1]; ptr[vc->xchars] = ' '; ox = vc->xcur; oy = vc->ycur; for (; vc->xcur < vc->xchars;) do_render_noscroll(vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc); vc->xcur = ox; vc->ycur = oy; } void vt_dl(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; register int beg, end; cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0]; cdata->param[0] = cdata->param[0]>vc->xchars ? vc->xchars : cdata->param[0]; /* vc->xcur=0; */ beg = cdata->scrr_beg; end = cdata->scrr_end; cdata->scrr_beg = vc->ycur; cdata->scrr_end = vc->ychars-1; for (; cdata->param[0]>0; cdata->param[0]--) do_scrollup( vc ); cdata->scrr_beg = beg; cdata->scrr_end = end; } /* Set scrolling region */ void vt_stbm(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; if((cdata->param[0] == 0) && (cdata->param[1] == 0)) { cdata->xcur = 0; cdata->ycur = 0; cdata->scrr_beg = 0; cdata->scrr_len = vc->ychars; cdata->scrr_end = cdata->scrr_len - 1; return; } if(cdata->param[1] <= cdata->param[0]) return; /* range parm 1 */ cdata->scrr_beg = cdata->param[0]-1; cdata->scrr_len = cdata->param[1] - cdata->param[0] + 1; cdata->scrr_end = cdata->param[1]-1; /* if (cdata->scrr_beg<0) cdata->scrr_beg = 0; */ if (cdata->scrr_end>(vc->ychars-1)) cdata->scrr_end = vc->ychars-1; cdata->scrr_len = cdata->scrr_end - cdata->scrr_beg - 1; { char buf[80]; sprintf ( buf, "scrr_beg %d, scrr_end %d", cdata->scrr_beg, cdata->scrr_end ); dprintf ( buf ); } cdata->flags &= ~F_LASTCHAR; } void vt_dsr(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; static u_char *answr = (u_char *)"\033[0n"; static u_char *panswr = (u_char *)"\033[?13n"; /* Printer Unattached */ static u_char *udkanswr = (u_char *)"\033[?21n"; /* UDK Locked */ static u_char *langanswr = (u_char *)"\033[?27;1n"; /* North American*/ static u_char buffer[16]; int i = 0; switch(cdata->param[0]) { case 5: /* return status */ cdata->report_chars = answr; cdata->report_count = 4; respond(vc); break; case 6: /* return cursor position */ buffer[i++] = 0x1b; buffer[i++] = '['; if((vc->ycur+1) > 10) buffer[i++] = ((vc->ycur+1) / 10) + '0'; buffer[i++] = ((vc->ycur+1) % 10) + '0'; buffer[i++] = ';'; if((vc->xcur+1) > 10) buffer[i++] = ((cdata->xcur+1) / 10) + '0'; buffer[i++] = ((vc->xcur+1) % 10) + '0'; buffer[i++] = 'R'; buffer[i++] = '\0'; cdata->report_chars = buffer; cdata->report_count = i; respond(vc); break; case 15: /* return printer status */ cdata->report_chars = panswr; cdata->report_count = 6; respond(vc); break; case 25: /* return udk status */ cdata->report_chars = udkanswr; cdata->report_count = 6; respond(vc); break; case 26: /* return language status */ cdata->report_chars = langanswr; cdata->report_count = 8; respond(vc); break; default: /* nothing else valid */ break; } } void vt_su(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0]; cdata->param[0] = cdata->param[0]>(vc->xchars-1) ? vc->xchars-1 : cdata->param[0]; do_scrollup(vc); } void vt_set_dec_priv_qm(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; switch(cdata->param[0]) { case 7: /* AWM - auto wrap mode */ cdata->flags |= F_AWM; break; /* Implement these */ case 1: /* CKM - cursor key mode */ case 3: /* COLM - column mode */ case 6: /* OM - origin mode */ case 8: /* ARM - auto repeat mode */ case 25: /* TCEM - text cursor enable mode */ break; case 0: /* error, ignored */ case 2: /* ANM - ansi/vt52 mode */ case 4: /* SCLM - scrolling mode */ case 5: /* SCNM - screen mode */ case 9: /* INLM - interlace mode */ case 10: /* EDM - edit mode */ case 11: /* LTM - line transmit mode */ case 12: /* */ case 13: /* SCFDM - space compression / field delimiting */ case 14: /* TEM - transmit execution mode */ case 15: /* */ case 16: /* EKEM - edit key execution mode */ case 42: /* NRCM - 7bit NRC characters */ break; } } void vt_keyappl(vc) struct vconsole *vc; { dprintf ( "VT_KEYAPPL" ); } void vt_clrtab(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; int i; if(cdata->param[0] == 0) cdata->tab_stops[vc->xcur] = 0; else if (cdata->param[0] == 3) { for(i=0; itab_stops[i] = 0; } } void vt_cuf(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; register int p = cdata->param[0]; if(vc->xcur == ((vc->xchars)-1)) /* already at right margin */ return; if(p <= 0) /* parameter min = 1 */ p = 1; else if(p > ((vc->xchars)-1)) /* parameter max = 79 */ p = ((vc->xchars)-1); if((vc->xcur + p) > ((vc->xchars)-1)) /* not more than */ p = ((vc->xchars)-1) - vc->xcur; vc->xcur += p; } void vt_sgr(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; int i=0; do { vc->SGR ( vc, cdata->param[i] ); switch ( cdata->param[i++] ) { case 0: /* reset to normal attributes */ cdata->fgcol = cdata->nfgcol; cdata->bgcol = cdata->nbgcol; cdata->attribs=cdata->fgcol<<8 | cdata->bgcol<<11; break; case 1: /* bold */ cdata->attribs |= BOLD; break; case 4: /* underline */ cdata->attribs |= UNDERLINE; break; case 5: /* blinking */ cdata->attribs |= BLINKING; break; case 7: /* reverse */ cdata->fgcol = cdata->nbgcol; cdata->bgcol = cdata->nfgcol; cdata->attribs |= REVERSE; cdata->attribs&=~0x3F00; cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11; break; case 22: /* not bold */ cdata->attribs &= ~BOLD; break; case 24: /* not underlined */ cdata->attribs &= ~UNDERLINE; break; case 25: /* not blinking */ cdata->attribs &= ~BLINKING; break; case 27: /* not reverse */ cdata->attribs &= ~REVERSE; cdata->fgcol = cdata->nfgcol; cdata->bgcol = cdata->nbgcol; cdata->attribs&=~0x3F00; cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11; break; default: if ((cdata->param[i-1] > 29) && (cdata->param[i-1] < 38)) { vc->SETFGCOL ( vc, cdata->param[i-1] - 30 ); cdata->fgcol = cdata->param[i-1] - 30; cdata->attribs&=~0x3F00; cdata->attribs |= cdata->fgcol<<8 | cdata->bgcol<<11; } if ((cdata->param[i-1] > 39) && (cdata->param[i-1] < 48)) { vc->SETBGCOL ( vc, cdata->param[i-1] - 40 ); cdata->bgcol = cdata->param[i-1] - 40; cdata->attribs&=~0x3F00; cdata->attribs |= cdata->fgcol<<8 | cdata->bgcol<<11; } } } while ( i<=cdata->parami ); } void vt_clreos(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; int ptr; if ( vc == vconsole_current ) vc->R_CLREOS ( vc, cdata->param[0] ); else vconsole_pending = vc->number; switch ( cdata->param[0] ) { case 0: /* Erase from cursor to end of screen */ for (ptr = vc->xcur + vc->ycur * vc->xchars ; ptr<(vc->xchars*vc->ychars); ptr++) vc->charmap[ptr]=0x20; break; case 1: /* Erase from start to cursor */ for (ptr=0; ptr < vc->ycur*vc->xchars + vc->xcur; ptr++) vc->charmap[ptr]=0x20; break; case 2: /* Blitz the whole bloody thing */ if ((vc->flags&LOSSY)==0) mapped_cls(vc); if (vc==vconsole_current) vc->CLS(vc); else vconsole_pending = vc->number; break; } } void vt_set_ansi(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; switch(cdata->param[0]) { case 0: /* error, ignored */ case 1: /* GATM - guarded area transfer mode */ case 2: /* KAM - keyboard action mode */ case 3: /* CRM - Control Representation mode */ break; case 4: /* IRM - insert replacement mode */ cdata->irm = 1; break; case 5: /* SRTM - status report transfer mode */ case 6: /* ERM - erasue mode */ case 7: /* VEM - vertical editing mode */ case 10: /* HEM - horizontal editing mode */ case 11: /* PUM - position unit mode */ case 12: /* SRM - send-receive mode */ case 13: /* FEAM - format effector action mode */ case 14: /* FETM - format effector transfer mode */ case 15: /* MATM - multiple area transfer mode */ case 16: /* TTM - transfer termination */ case 17: /* SATM - selected area transfer mode */ case 18: /* TSM - tabulation stop mode */ case 19: /* EBM - editing boundary mode */ case 20: /* LNM - line feed / newline mode */ break; } } void vt_reset_ansi(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; switch(cdata->param[0]) { /* Implement these */ case 0: /* error, ignored */ case 1: /* GATM - guarded area transfer mode */ case 2: /* KAM - keyboard action mode */ case 3: /* CRM - Control Representation mode */ break; case 4: /* IRM - insert replacement mode */ cdata->irm = 0; break; case 5: /* SRTM - status report transfer mode */ case 6: /* ERM - erasue mode */ case 7: /* VEM - vertical editing mode */ case 10: /* HEM - horizontal editing mode */ case 11: /* PUM - position unit mode */ case 12: /* SRM - send-receive mode */ case 13: /* FEAM - format effector action mode */ case 14: /* FETM - format effector transfer mode */ case 15: /* MATM - multiple area transfer mode */ case 16: /* TTM - transfer termination */ case 17: /* SATM - selected area transfer mode */ case 18: /* TSM - tabulation stop mode */ case 19: /* EBM - editing boundary mode */ case 20: /* LNM - line feed / newline mode */ break; } } /* DRN */ void do_render_noscroll(c, vc) char c; struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; /* THE RENDER STAGE **********************************/ if ((c >= 0x20) && (c <= 0x7f)) { if (((vc->flags) & (LOSSY)) == 0) { if ((vc->charmap[vc->xcur+vc->ycur*vc->xchars] != c) | cdata->attribs) { if ( vc==vconsole_current ) vc->RENDER ( vc, c ); else vconsole_pending = vc->number; } vc->charmap[ vc->xcur + vc->ycur*vc->xchars ] = c | cdata->attribs; } else { if (vc == vconsole_current) vc->RENDER (vc, c); else vconsole_pending = vc->number; } } vc->xcur++; /*do_scrollcheck ( vc );*/ } #ifdef SIMPLE_CURSOR void simple_cursor_on(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; if (cdata->simple_cursor_on) return 0; if (vc!=vconsole_current) return 0; if (((vc->flags)&(LOSSY))==0) { cdata->simple_cursor_store = vc->charmap[ vc->xcur + vc->ycur*vc->xchars ]; vc->RENDER ( vc, SIMPLE_CURSOR_CHAR ); } cdata->simple_cursor_on = 1; } void simple_cursor_off(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; if (!cdata->simple_cursor_on) return 0; if (vc!=vconsole_current) return 0; if (((vc->flags)&(LOSSY))==0) vc->RENDER ( vc, cdata->simple_cursor_store ); cdata->simple_cursor_on = 0; } #endif /* DSC */ void do_scrollcheck(vc) struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; /* BOUNDARY CHECK ************************************/ if ((vc->xcur >= (vc->xchars))&&((cdata->flags&F_AWM)!=0)) { cdata->flags|=F_LASTCHAR; cdata->lastpos = vc->ycur*vc->xchars+vc->xcur; } /* SCROLL CHECK *************************************/ if (vc->ycur >= cdata->scrr_end+1) do_scrollup ( vc ); } /* DR */ int do_render(c, vc) char c; struct vconsole *vc; { struct vt220_info *cdata = (struct vt220_info *)vc->data; /* THE RENDER STAGE **********************************/ if (((cdata->flags&F_AWM)==0)&&(vc->xcur >= 20)) return 0; if ( cdata->flags & F_LASTCHAR ) { if ( cdata->lastpos==vc->ycur*vc->xchars+vc->xchars) { vc->ycur++; vc->xcur = 0; cdata->flags &= ~F_LASTCHAR; do_scrollcheck(vc); } else { cdata->flags &= ~F_LASTCHAR; } } if ((c>=0x20)&&(c<=0x7f)) { if (((vc->flags)&(LOSSY))==0) { if ( cdata->irm == 0 ) { if((vc->charmap[vc->xcur+vc->ycur*vc->xchars]!= c) | cdata->attribs ) { if ( vc==vconsole_current ) vc->RENDER ( vc, c ); else vconsole_pending = vc->number; } vc->charmap[vc->xcur+vc->ycur*vc->xchars ] = c|cdata->attribs; } else { int counter; int ox, oy; int *ptr = vc->charmap + (vc->xcur + vc->ycur*vc->xchars); for ( counter=vc->xchars-vc->xcur; counter>=0; counter-- ) ptr[counter+1] = ptr[counter]; ptr[0] = c; ox = vc->xcur; oy = vc->ycur; for ( ; vc->xcur < vc->xchars; ) do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc ); vc->xcur = ox; vc->ycur = oy; } } else { if ( vc==vconsole_current ) vc->RENDER ( vc, c ); else vconsole_pending = vc->number; } } vc->xcur++; do_scrollcheck ( vc ); if ( cdata->flags & F_LASTCHAR ) vc->xcur--; return 0; } int TERMTYPE_PUTSTRING(string, length, vc) char *string; int length; struct vconsole *vc; { struct vt220_info *cdata; register char c; #ifdef DEBUGTERM char dc[] = "x\0"; #endif cdata = (struct vt220_info *)vc->data; /* A piece of saftey code */ if ( vc->vtty == 0 ) return 0; #ifdef SIMPLE_CURSOR if ( vc==vconsole_current ) if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_off ( vc ); #else if ( vc==vconsole_current ) vc->CURSORUPDATE (vc); #endif while ( ((c=*(string++))!=0) && ((length--)>0) ) { if ( cdata->state != STATE_INIT ) cdata->flags &= ~F_LASTCHAR; if ( ( c == 0x0a ) || ( c== 0x0d ) ) cdata->flags &= ~F_LASTCHAR; #if defined(DIAGNOSTIC) && NQMS > 0 qms_console_freeze(); #endif /* DIAGNOSTIC && NQMS */ /* Always process characters in the range of 0x00 to 0x1f */ #ifdef DEBUGTERM *dc = c; switch (c) { case 0x0a: dprintf ( "[0a]" ); break; case 0x0d: dprintf ( "[0d]" ); break; case 0x0c: dprintf ( "[0c]" ); break; case 0x1b: dprintf ( "[1b]" ); break; } #endif if (c <= 0x1f) { if ( cdata->disable_function ) { if ( cdata->flags & F_LASTCHAR ) { if ( cdata->lastpos==vc->ycur*vc->xchars+vc->xchars) { vc->ycur++; vc->xcur = 0; cdata->flags &= ~F_LASTCHAR; do_scrollcheck(vc); } else { cdata->flags &= ~F_LASTCHAR; } } switch (c) { case 0x00: /* NUL */ case 0x01: /* SOH */ case 0x02: /* STX */ case 0x03: /* ETX */ case 0x04: /* EOT */ case 0x05: /* ENQ */ case 0x06: /* ACK */ break; case 0x07: /* BEL */ sysbeep(1000, 100); if ( !cdata->beepoff ) c = 'G'; break; case 0x08: /* BS */ cdata->flags &= ~F_LASTCHAR; if ( vc->xcur>0 ) vc->xcur--; break; case 0x09: /* TAB */ while ( vc->xcur < vc->xchars-1 ) { vc->xcur++; if (cdata->tab_stops[vc->xcur]) break; } break; case 0x0a: cdata->flags &= ~F_LASTCHAR; vc->ycur++; do_scrollcheck ( vc ); break; case 0x0c: cdata->flags &= ~F_LASTCHAR; if ((vc->flags&LOSSY)==0) mapped_cls(vc); if (vc==vconsole_current) vc->CLS(vc); vc->xcur=0; vc->ycur=0; break; case 0x0d: cdata->flags &= ~F_LASTCHAR; vc->xcur=0; break; case 0x10: /* DLE */ case 0x11: /* DC1/XON */ case 0x12: /* DC2 */ case 0x13: /* DC3/XOFF */ case 0x14: /* DC4 */ case 0x15: /* NAK */ case 0x16: /* SYN */ case 0x17: /* ETB */ break; case 0x18: /* CAN */ cdata->state = STATE_INIT; clr_params(cdata); break; case 0x19: /* EM */ break; case 0x1a: /* SUB */ cdata->state = STATE_INIT; clr_params(cdata); break; case 0x1b: /* ESC */ cdata->state = STATE_ESC; clr_params(cdata); break; case 0x1c: /* FS */ case 0x1d: /* GS */ case 0x1e: /* RS */ case 0x1f: /* US */ break; } } } else { /* 0x20 to 0xff depends on current state */ switch ( cdata->state ) { case STATE_INIT: do_render ( c, vc ); break; case STATE_ESC: #ifdef DEBUGTERM { char buf[]="x"; buf[0] = c; dprintf(buf); } #endif switch (c) { case '7': /* SAVE CUSOR */ vt_sc ( vc ); cdata->state = STATE_INIT; break; case '8': /* RESTORE CUSOR */ vt_rc ( vc ); cdata->state = STATE_INIT; break; case '=': vt_keyappl ( vc ); cdata->state = STATE_INIT; break; case '>': /* Keypad numeric mode */ #ifdef DEBUGTERM dprintf ( "\r\nKEYPAD NUMERIC MODE\r\n "); #endif cdata->state = STATE_INIT; break; case 'D': vt_ind ( vc ); cdata->state = STATE_INIT; break; case 'E': vt_nel ( vc ); cdata->state = STATE_INIT; break; case 'H': cdata->tab_stops[vc->xcur] = 1; cdata->state = STATE_INIT; break; case 'M': vt_ri ( vc ); cdata->state = STATE_INIT; break; case 'N': cdata->Gs = cdata->G2; cdata->ss = 1; cdata->state = STATE_INIT; break; case 'O': cdata->Gs = cdata->G3; cdata->ss = 1; cdata->state = STATE_INIT; break; case 'P': cdata->dcs_state = DCS_INIT; cdata->state = STATE_DCS; break; case 'Z': vt_da ( vc ); cdata->state = STATE_INIT; break; case '~': cdata->GR = cdata->G1; cdata->state = STATE_INIT; break; case '[': clr_params ( cdata ); cdata->state = STATE_CSI; break; case '\\': cdata->state = STATE_INIT; break; case 'c': vt_ris ( vc ); cdata->state = STATE_CSI; break; case 'n': cdata->GL = cdata->G2; cdata->state = STATE_INIT; break; case 'o': cdata->GL = cdata->G3; cdata->state = STATE_INIT; break; case '}': cdata->GR = cdata->G2; cdata->state = STATE_INIT; break; case '|': cdata->GR = cdata->G3; cdata->state = STATE_INIT; break; default: do_render ( c, vc ); cdata->state = STATE_INIT; break; } break; case STATE_CSIQM: #ifdef DEBUGTERM { char buf[]="x"; buf[0] = c; dprintf(buf); } #endif switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* parameters */ cdata->param[cdata->parami] *= 10; cdata->param[cdata->parami] += (c-'0'); break; case ';': /* next parameter */ cdata->parami = (cdata->parami+1 < MAXPARMS) ? cdata->parami+1 : cdata->parami; break; case 'h': vt_set_dec_priv_qm ( vc ); cdata->state = STATE_INIT; break; case 'l': vt_reset_dec_priv_qm ( vc ); cdata->state = STATE_INIT; break; case 'n': vt_dsr ( vc ); cdata->state = STATE_INIT; break; case 'K': vt_sel ( vc ); cdata->state = STATE_INIT; break; default: do_render ( '[', vc ); do_render ( c, vc ); cdata->state = STATE_INIT; /* What is this ? --mark */ { register int counter; for ( counter=0; counter<=cdata->parami; counter++ ) { do_render ( '@', vc ); } } do_render ( c, vc ); break; } case STATE_CSI: #ifdef DEBUGTERM { char buf[]="x"; buf[0] = c; dprintf(buf); } #endif switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* parameters */ cdata->param[cdata->parami] *= 10; cdata->param[cdata->parami] += (c-'0'); break; case ';': /* next parameter */ cdata->parami = (cdata->parami+1 < MAXPARMS) ? cdata->parami+1 : cdata->parami; break; case '?': /* ESC [ ? family */ cdata->state = STATE_CSIQM; break; case '@': /* insert char */ vt_ic ( vc ); cdata->state = STATE_INIT; break; /* case '!': cdata->state = STATE_STR; break; */ case 'A': /* cursor up */ vt_cuu ( vc ); cdata->state = STATE_INIT; break; case 'B': /* cursor down */ vt_cud ( vc ); cdata->state = STATE_INIT; break; case 'C': vt_cuf ( vc ); cdata->state = STATE_INIT; break; case 'D': /* cursor back */ vt_cub ( vc ); cdata->state = STATE_INIT; break; case 'H': /* direct cursor addressing */ vt_curadr ( vc ); cdata->state = STATE_INIT; break; case 'J': /* erase screen */ vt_clreos ( vc ); cdata->state = STATE_INIT; break; cdata->state = STATE_INIT; break; case 'K': /* erase line */ vt_clreol ( vc ); cdata->state = STATE_INIT; break; case 'L': /* insert line */ vt_il ( vc ); cdata->state = STATE_INIT; break; case 'M': /* delete line */ vt_dl ( vc ); cdata->state = STATE_INIT; break; case 'P': /* Delete chars */ vt_dch ( vc ); cdata->state = STATE_INIT; break; case 'S': /* scroll up */ vt_su ( vc ); cdata->state = STATE_INIT; break; case 'c': vt_da ( vc ); cdata->state = STATE_INIT; break; case 'f': vt_curadr ( vc ); cdata->state = STATE_INIT; break; case 'g': vt_clrtab ( vc ); cdata->state = STATE_INIT; break; case 'h': vt_set_ansi ( vc ); cdata->state = STATE_INIT; break; case 'l': vt_reset_ansi ( vc ); cdata->state = STATE_INIT; break; case 'm': /* select graphic rendition */ vt_sgr( vc ); cdata->state = STATE_INIT; break; case 'n': vt_dsr ( vc ); cdata->state = STATE_INIT; break; case 'r': /* set scrolling region */ vt_stbm ( vc ); cdata->state = STATE_INIT; break; case 'y': vt_tst ( vc ); cdata->state = STATE_INIT; break; default: do_render ( '[', vc ); do_render ( c, vc ); cdata->state = STATE_INIT; /* What is this ??? - mark */ { register int counter; for ( counter=0; counter<=cdata->parami; counter++ ) { do_render('@', vc); } } do_render(c, vc); cdata->state = STATE_INIT; break; } break; default: cdata->state = STATE_INIT; break; } } } #ifdef SIMPLE_CURSOR if (vc==vconsole_current) if (vc->CURSORUPDATE(vc)==-1) simple_cursor_on(vc); #else if (vc==vconsole_current) vc->CURSORUPDATE(vc); #endif return 0; } int vt220_swapin(vc) struct vconsole *vc; { #ifdef SIMPLE_CURSOR if (vc==vconsole_current) if (vc->CURSORUPDATE(vc)==-1) simple_cursor_on(vc); #else if (vc==vconsole_current) vc->CURSORUPDATE(vc); #endif return 0; } int vt220_swapout(vc) struct vconsole *vc; { return 0; } int vt220_sleep(vc) struct vconsole *vc; { #ifdef SIMPLE_CURSOR if (vc==vconsole_current) if (vc->CURSORUPDATE(vc)==-1) simple_cursor_off(vc); #else if (vc==vconsole_current) vc->CURSORUPDATE(vc); #endif vc->FLASH (vc, 0); vc->CURSOR_FLASH (vc, 0); return 0; } int vt220_wake(vc) struct vconsole *vc; { vc->FLASH (vc, 1); vc->CURSOR_FLASH (vc, 1); #ifdef SIMPLE_CURSOR if (vc==vconsole_current) if (vc->CURSORUPDATE(vc)==-1) simple_cursor_on(vc); #else if (vc==vconsole_current) vc->CURSORUPDATE(vc); #endif return 0; } int vt220_scrollback(vc) struct vconsole *vc; { return -1; } int vt220_scrollforward(vc) struct vconsole *vc; { return -1; } int vt220_scrollbackend(vc) struct vconsole *vc; { return -1; } int vt220_debugprint(vc) struct vconsole *vc; { printf("VT220 TERMINAL EMULATOR\n\n"); printf("no information\n"); printf("\n"); return 0; } int vt220_modechange(vc) struct vconsole *vc; { if (vc->number >= 64) return(0); if (vc == NULL) return(EINVAL); vt_str(vc); if (vc->charmap) { free(vc->charmap, M_DEVBUF); MALLOC(vc->charmap, int *, sizeof(int)*((vc->xchars)*(vc->ychars)), M_DEVBUF, M_NOWAIT); /* printf("vc=%08x charmap=%08x\n", vc, vc->charmap);*/ if ((vc->flags&LOSSY)==0) mapped_cls(vc); if (vc==vconsole_current) vc->CLS(vc); vc->xcur=0; vc->ycur=0; } return 0; } int vt220_attach(vc, a, b, aux) struct vconsole *vc; struct device *a; struct device *b; void *aux; { return 0; } struct terminal_emulator vt220 = { vt220_name, vt220_init, vt220_putstring, vt220_swapin, vt220_swapout, vt220_sleep, vt220_wake, vt220_scrollback, vt220_scrollforward, vt220_scrollbackend, vt220_debugprint, vt220_modechange, vt220_attach };