/* * This file is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify this file without charge, but are not authorized to * license or distribute it to anyone else except as part of a product * or program developed by the user. * * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * This file is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even * if Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #ifndef lint static char sccsid[] = "@(#)charproc.c 1.11 88/02/10 Copyright 1987 Sun Micro"; #endif /* * Copyright (c) 1987 by Sun Microsystems, Inc. * Steve Isaac 12/18/87 * */ /* Copyright (c) 1985 Massachusetts Institute of Technology */ /* Copyright (c) 1985 Digital Equipment Corporation */ /* charproc.c */ #include #include #include #include #include #include #include #include "ptyx.h" #include "NeWS.h" #include "VTparse.h" #include "data.h" #include "error.h" #define LDEBUG FALSE #define DEFAULT -1 #define MIN(a,b) ab ? a : b #ifndef lint #endif lint static long arg, arg1; static int ch; static int nparam; static ANSI reply; static int param[NPARAM]; static unsigned long ctotal; static unsigned long ntotal; static jmp_buf vtjmpbuf; char printbuffer[MAXSCREENWIDTH]; char *printptr; int printlargest = 0; /* largest print buffer col used */ int printsmallest = MAXSCREENWIDTH; /* smallest print buffer col used */ int firstlargest = 0; /* largest col used in current write */ int firstsmallest = MAXSCREENWIDTH; /* smallest col used in current write */ int firstY; int do_startwrite = TRUE; /* need to do a startwrite */ int firstline = TRUE; /* if first line of a multi-line write */ int lineswritten = 0; /* # of lines written without a flush */ struct timeval select_timeout = {0, 0}; extern int groundtable[]; extern int csitable[]; extern int dectable[]; extern int eigtable[]; extern int esctable[]; extern int iestable[]; extern int igntable[]; extern int scrtable[]; extern int scstable[]; #ifdef KANJI #define input() ((unsigned char)(--bcnt >= 0 ? *bptr++ : in_put())) #else #define input() (--bcnt >= 0 ? *bptr++ : in_put()) #endif VTparse() { register Screen *screen = &term.screen; register int *parsestate = groundtable; register int c; register unsigned char *cp; register char *cpp; register int i, row, col, top, bot, scstype; int x,y,width,height; int *p; extern int bitset(), bitclr(), finput(); if (setjmp(vtjmpbuf)) parsestate = groundtable; for (;;) { c = input(); if (c > 0177) goto printable_character; switch (parsestate[c]) { case CASE_GROUND_STATE: /* exit ignore mode */ parsestate = groundtable; break; case CASE_IGNORE_STATE: /* Ies: ignore anything else */ parsestate = igntable; break; case CASE_IGNORE_ESC: /* Ign: escape */ parsestate = iestable; break; case CASE_IGNORE: /* Ignore character */ break; case CASE_BELL: /* bell */ if (!do_startwrite) { flushwrite(); clearbuffer(); } Bell(); break; case CASE_BS: /* backspace */ caretX = (caretX-1 < 1) ? 1 : caretX-1; checkunderflow(); break; case CASE_CR: /* carriage return */ caretX = 1; checkunderflow(); break; case CASE_ESC: /* escape */ parsestate = esctable; break; case CASE_VMOT: /* * form feed, line feed, vertical tab, but not in status line */ if (term.flags & LINEFEED) { caretX = 1; checkunderflow(); } doVMOT(); break; case CASE_TAB: /* tab */ i = TabNext(term.tabs, caretX-1) + 1; if (LDEBUG) fprintf(stderr,"TAB Linelength %d: %d\n",caretY,linelength[caretY]); /* * Either move the caret or print out blank spaces, depending on * whether we are on top of existing stuff or writing new stuff. */ if (linelength[caretY] >= caretX) { caretX = i; checkoverflow(); } else { cpp = blankline; dotext(screen, term.flags, screen->gsets[screen->curgl], cpp, cpp+i-caretX); } break; case CASE_SI: screen->curgl = 0; break; case CASE_SO: screen->curgl = 1; break; case CASE_SCR_STATE: /* enter scr state */ parsestate = scrtable; break; case CASE_SCS0_STATE: /* enter scs state 0 */ scstype = 0; parsestate = scstable; break; case CASE_SCS1_STATE: /* enter scs state 1 */ scstype = 1; parsestate = scstable; break; case CASE_SCS2_STATE: /* enter scs state 2 */ scstype = 2; parsestate = scstable; break; case CASE_SCS3_STATE: /* enter scs state 3 */ scstype = 3; parsestate = scstable; break; case CASE_ESC_IGNORE: /* unknown escape sequence */ parsestate = eigtable; break; case CASE_ESC_DIGIT: /* digit in csi or dec mode */ if ((row = param[nparam - 1]) == DEFAULT) row = 0; param[nparam - 1] = 10 * row + (c - '0'); break; case CASE_ESC_SEMI: /* semicolon in csi or dec mode */ param[nparam++] = DEFAULT; break; case CASE_DEC_STATE: /* enter dec mode */ parsestate = dectable; break; case CASE_ICH: /* ICH */ if ((c = param[0]) < 1) c = 1; if (!do_startwrite) { flushwrite(); clearbuffer(); } ps_insertstring(blankline,c,caretX,caretY); if (caretX > linelength[caretY]) linelength[caretY] = caretX + c - 1; else linelength[caretY] = linelength[caretY] + c; if (LDEBUG) { fprintf(stderr,"ICH Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } parsestate = groundtable; break; case CASE_CUU: /* CUU */ /* only if not in status line */ if (!screen->instatus) { if ((c = param[0]) < 1) c = 1; if (!do_startwrite) { flushwrite(); clearbuffer(); } caretY = (caretY-c < screen->top_marg) ? screen->top_marg : caretY-c; ps_movecaret(caretX,caretY); } if (psio_availinputbytes(PostScriptInput) > 0 || (ioctl(psio_fileno(PostScriptInput), FIONREAD, &arg), arg) > 0) xevents(); parsestate = groundtable; break; case CASE_CUD: /* CUD */ /* only if not in status line */ if (!screen->instatus) { if ((c = param[0]) < 1) c = 1; if (!do_startwrite) { flushwrite(); clearbuffer(); } caretY = (caretY+c > screen->bot_marg) ? screen->bot_marg : caretY+c; ps_movecaret(caretX,caretY); } if (psio_availinputbytes(PostScriptInput) > 0 || (ioctl(psio_fileno(PostScriptInput), FIONREAD, &arg), arg) > 0) xevents(); parsestate = groundtable; break; case CASE_CUF: /* CUF */ if ((c = param[0]) < 1) c = 1; caretX = (caretX+c > screen_cols) ? screen_cols : caretX+c; checkoverflow(); parsestate = groundtable; break; case CASE_CUB: /* CUB */ if ((c = param[0]) < 1) c = 1; caretX = (caretX-c < 1) ? 1 : caretX-c; checkunderflow(); parsestate = groundtable; break; case CASE_CUP: /* CUP | HVP */ /* only if not in status line */ if (!screen->instatus) { if ((row = param[0]) < 1) row = 1; if (nparam < 2 || (col = param[1]) < 1) col = 1; if (row == caretY) { if (col > caretX) { caretX = MIN(col,screen_cols); checkoverflow(); } else { caretX = MIN(col,screen_cols); checkunderflow(); } } else { if (!do_startwrite) { flushwrite(); clearbuffer(); } CaretSet(screen, col, row, term.flags); if (psio_availinputbytes(PostScriptInput) > 0 || (ioctl(psio_fileno(PostScriptInput), FIONREAD, &arg), arg) > 0) xevents(); } } parsestate = groundtable; break; case CASE_ED: /* ED */ switch (param[0]) { case DEFAULT: case 0: if (screen->instatus) {} else if (!do_startwrite) { flushwrite(); clearbuffer(); } ps_deletestring(MAX(linelength[caretY]-caretX+1,0),caretX,caretY); linelength[caretY] = caretX - 1; for (i=caretY+1; i <= screen_rows; i++) { ps_deletestring(linelength[i],1,i); linelength[i] = 0; } break; case 1: if (screen->instatus) {} else if (!do_startwrite) { flushwrite(); clearbuffer(); } if (caretX >= linelength[caretY]) { ps_deletestring(linelength[caretY],1,caretY); linelength[caretY] = 0; } else { ps_startwrite(); ps_write(blankline,caretX); ps_finishwrite(FALSE,1,caretY); } for (i=1; i <= caretY-1; i++) { ps_deletestring(linelength[i],1,i); linelength[i] = 0; } break; case 2: if (screen->instatus) {} else if (!do_startwrite) { flushwrite(); clearbuffer(); } ps_clearscreen(); for (i=1; i <= screen_rows; i++) linelength[i] = 0; break; } if (LDEBUG) { fprintf(stderr,"ED Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } parsestate = groundtable; break; case CASE_EL: /* EL */ if (!do_startwrite) { flushwrite(); clearbuffer(); } switch (param[0]) { case DEFAULT: case 0: ps_deletestring(MAX(linelength[caretY]-caretX+1,0),caretX,caretY); linelength[caretY] = caretX - 1; break; case 1: if (caretX >= linelength[caretY]) { ps_deletestring(linelength[caretY],1,caretY); linelength[caretY] = 0; } else { ps_startwrite(); ps_write(blankline,caretX); ps_finishwrite(FALSE,1,caretY); } break; case 2: ps_deletestring(linelength[caretY],1,caretY); linelength[caretY] = 0; break; } if (LDEBUG) { fprintf(stderr,"EL Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } parsestate = groundtable; break; case CASE_IL: /* IL */ /* only if not in status line */ if (!screen->instatus) { if (!do_startwrite) { flushwrite(); clearbuffer(); } if ((c = param[0]) < 1) c = 1; if (caretY+c > screen_rows+1) c = screen_rows - caretY + 1; ps_insertline(c,caretY); for (i=screen_rows; i>=caretY+c; i--) linelength[i] = linelength[i-c]; for (i=caretY; iinstatus) { if (!do_startwrite) { flushwrite(); clearbuffer(); } if ((c = param[0]) < 1) c = 1; if (caretY+c > screen_rows+1) c = screen_rows - caretY + 1; ps_deleteline(c,caretY); for (i=caretY; i<=screen_rows-c; i++) linelength[i] = linelength[i+c]; for (i=screen_rows-c+1; i<=screen_rows; i++) linelength[i] = 0; } if (LDEBUG) { fprintf(stderr,"DL Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } parsestate = groundtable; break; case CASE_DCH: /* DCH */ if ((c = param[0]) < 1) c = 1; if (!do_startwrite) { flushwrite(); clearbuffer(); } ps_deletestring(c,caretX,caretY); if (caretX <= linelength[caretY]) linelength[caretY] = MAX(linelength[caretY] - c,caretX); if (LDEBUG) { fprintf(stderr,"DCH Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } parsestate = groundtable; break; case CASE_DA1: /* DA1 */ if (param[0] <= 0) {/* less than means DEFAULT */ reply.a_type = CSI; reply.a_pintro = '?'; reply.a_nparam = 2; reply.a_param[0] = 1; /* VT102 */ reply.a_param[1] = 2; /* VT102 */ reply.a_inters = 0; reply.a_final = 'c'; unparseseq(&reply, screen->respond); } parsestate = groundtable; break; case CASE_TBC: /* TBC */ if ((c = param[0]) <= 0) /* less than means default */ TabClear(term.tabs, caretX); else if (c == 3) TabZonk(term.tabs); parsestate = groundtable; break; case CASE_SET: /* SET */ modes(&term, bitset); parsestate = groundtable; break; case CASE_RST: /* RST */ modes(&term, bitclr); parsestate = groundtable; break; case CASE_SGR: /* SGR */ for (c = 0; c < nparam; ++c) { switch (param[c]) { case DEFAULT: case 0: term.flags &= ~(INVERSE | BOLD | UNDERLINE); break; case 1: case 5: /* Blink, really. */ term.flags |= BOLD; break; case 4: /* Underscore */ term.flags |= UNDERLINE; break; case 7: term.flags |= INVERSE; } } parsestate = groundtable; break; case CASE_CPR: /* CPR */ if ((c = param[0]) == 5) { reply.a_type = CSI; reply.a_pintro = 0; reply.a_nparam = 1; reply.a_param[0] = 0; reply.a_inters = 0; reply.a_final = 'n'; unparseseq(&reply, screen->respond); } else if (c == 6) { reply.a_type = CSI; reply.a_pintro = 0; reply.a_nparam = 2; reply.a_param[0] = caretY; reply.a_param[1] = caretX; reply.a_inters = 0; reply.a_final = 'R'; unparseseq(&reply, screen->respond); } parsestate = groundtable; break; case CASE_DECSTBM: /* DECSTBM */ /* only if not in status line */ if (!screen->instatus) { if ((top = param[0]) < 1) top = 1; if (nparam < 2 || (bot = param[1]) == DEFAULT || bot > screen_rows || bot == 0) bot = screen_rows; if (bot > top) { if (top ==1 && bot == screen_rows) { scrollingregion_enabled = FALSE; if (!scrolling_disabled) ps_removescrollinglimits(); } else ps_setscrollinglimits(top,bot); screen->top_marg = top; screen->bot_marg = bot; CaretSet(screen, 1, 1, term.flags); } } parsestate = groundtable; break; case CASE_SUN_EMU: /* sub-set of sun tty emulation */ switch (param[0]) { case 2: /* iconify */ break; case 3: /* move window */ if (nparam == 3) { } break; case 4: /* resize window (pixels) */ if (nparam == 3) { } break; case 5: /* raise window */ break; case 6: /* lower window */ break; case 7: /* redisplay window */ break; case 8: /* resize window (rows and columns) */ if (nparam == 3) { } break; case 13: /* send window position */ break; case 14: /* send window size (pixels) */ break; case 18: /* send window size (rows and cols) */ reply.a_type = CSI; reply.a_pintro = 0; reply.a_nparam = 3; reply.a_param[0] = 8; reply.a_param[1] = screen_rows; reply.a_param[2] = screen_cols; reply.a_inters = 0; reply.a_final = 't'; unparseseq(&reply, screen->respond); break; } parsestate = groundtable; break; case CASE_DECREQTPARM: /* DECREQTPARM */ if ((c = param[0]) == DEFAULT) c = 0; if (c == 0 || c == 1) { reply.a_type = CSI; reply.a_pintro = 0; reply.a_nparam = 7; reply.a_param[0] = c + 2; reply.a_param[1] = 1; /* no parity */ reply.a_param[2] = 1; /* eight bits */ reply.a_param[3] = 112; /* transmit 9600 baud */ reply.a_param[4] = 112; /* receive 9600 baud */ reply.a_param[5] = 1; /* clock multiplier ? */ reply.a_param[6] = 0; /* STP flags ? */ reply.a_inters = 0; reply.a_final = 'x'; unparseseq(&reply, screen->respond); } parsestate = groundtable; break; case CASE_DECSET: /* DECSET */ dpmodes(&term, bitset); parsestate = groundtable; break; case CASE_DECRST: /* DECRST */ dpmodes(&term, bitclr); parsestate = groundtable; break; case CASE_HIDDEN: /* special "hidden" sequence */ fprintf(stderr, "avg call = %ld char\n", ctotal / ntotal); parsestate = groundtable; break; case CASE_DECALN: /* DECALN */ if (!do_startwrite) { flushwrite(); clearbuffer(); } ps_startwrite(); printptr = printbuffer; for (i=1; i<=screen_cols; i++) *(printptr)++ = 'E'; for (i=1; i<=screen_rows; i++) { ps_write(printbuffer,screen_cols); linelength[i] = screen_cols; } ps_finishwrite(FALSE,1,1); clearbuffer(); parsestate = groundtable; break; case CASE_GSETS: screen->gsets[scstype] = c; parsestate = groundtable; break; case CASE_DECSC: /* DECSC */ CaretSave(&term, &screen->sc); parsestate = groundtable; break; case CASE_DECRC: /* DECRC */ CaretRestore(&term, &screen->sc); parsestate = groundtable; break; case CASE_DECKPAM: /* DECKPAM */ term.keyboard.flags |= KYPD_APL; parsestate = groundtable; break; case CASE_DECKPNM: /* DECKPNM */ term.keyboard.flags &= ~KYPD_APL; parsestate = groundtable; break; case CASE_IND: /* IND */ /* only if not in status line */ if (!screen->instatus) { if (!do_startwrite) { flushwrite(); clearbuffer(); } ps_movecaretdelta(0,1); caretY++; if (caretY>screen->bot_marg) { caretY = screen->bot_marg; /* Scroll the line length array up */ for (i=screen->top_marg; ibot_marg; i++) linelength[i] = linelength[i+1]; linelength[screen->bot_marg] = 0; } } if (LDEBUG) { fprintf(stderr,"IND Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } parsestate = groundtable; break; case CASE_NEL: /* NEL */ /* only if not in status line */ if (!screen->instatus) { if (!do_startwrite) { flushwrite(); clearbuffer(); } caretX = 1; ps_movecaret(caretX,caretY); ps_movecaretdelta(0,1); caretY++; if (caretY>screen->bot_marg) { caretY = screen->bot_marg; /* Scroll the line length array up */ for (i=screen->top_marg; ibot_marg; i++) linelength[i] = linelength[i+1]; linelength[screen->bot_marg] = 0; } } if (LDEBUG) { fprintf(stderr,"NEL Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } parsestate = groundtable; break; case CASE_HTS: /* HTS */ TabSet(term.tabs, caretX); parsestate = groundtable; break; case CASE_RI: /* RI */ /* only if not in status line */ if (!screen->instatus) { if (!do_startwrite) { flushwrite(); clearbuffer(); } ps_movecaretdelta(0,-1); caretY--; if (caretY < screen->top_marg) { caretY = 1; /* Scroll the line length array down */ for (i=screen->bot_marg; i>screen->top_marg; i--) linelength[i] = linelength[i-1]; linelength[screen->top_marg] = 0; } } if (LDEBUG) { fprintf(stderr,"RI Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } parsestate = groundtable; break; case CASE_SS2: /* SS2 */ screen->curss = 2; parsestate = groundtable; break; case CASE_SS3: /* SS3 */ screen->curss = 3; parsestate = groundtable; break; case CASE_CSI_STATE: /* enter csi state */ nparam = 1; param[0] = DEFAULT; parsestate = csitable; break; case CASE_OSC: /* do osc escapes */ do_osc(finput); parsestate = groundtable; break; case CASE_RIS: /* RIS */ VTReset(TRUE); parsestate = groundtable; break; case CASE_LS2: /* LS2 */ screen->curgl = 2; parsestate = groundtable; break; case CASE_LS3: /* LS3 */ screen->curgl = 3; parsestate = groundtable; break; case CASE_LS3R: /* LS3R */ screen->curgr = 3; parsestate = groundtable; break; case CASE_LS2R: /* LS2R */ screen->curgr = 2; parsestate = groundtable; break; case CASE_LS1R: /* LS1R */ screen->curgr = 1; parsestate = groundtable; break; case CASE_TO_STATUS: if ((c = param[0]) < 1) c = 1; parsestate = groundtable; break; case CASE_FROM_STATUS: parsestate = groundtable; break; case CASE_SHOW_STATUS: parsestate = groundtable; break; case CASE_HIDE_STATUS: parsestate = groundtable; break; case CASE_ERASE_STATUS: parsestate = groundtable; break; case CASE_XTERM_SAVE: parsestate = groundtable; break; case CASE_XTERM_RESTORE: parsestate = groundtable; break; case CASE_PRINT: printable_character: /* printable characters */ top = bcnt; cp = (unsigned char *) bptr; *--bptr = c; while (top > 0 && *cp >= ' ' && *cp != 0177) { top--; bcnt--; cp++; } if (screen->curss) { dotext(screen, term.flags, screen->gsets[screen->curss], bptr, bptr + 1); screen->curss = 0; bptr++; } if ((unsigned char *) bptr < cp) dotext(screen, term.flags, screen->gsets[screen->curgl], bptr, cp); bptr = (char *) cp; break; } } } finput() { return (input()); } checkunderflow() { if (!do_startwrite && caretX < printsmallest) flushwrite(); } checkoverflow() { if (!do_startwrite && caretX > printlargest) flushwrite(); } clearbuffer() { bcopy(blankline,printbuffer,printlargest); printsmallest = MAXSCREENWIDTH; printlargest = 0; } flushwrite() { writebuffer(); endwrite(); } writebuffer() { int i; if (!do_startwrite) { if (firstline) { printptr = printbuffer + firstsmallest-1; ps_write(printptr,firstlargest-firstsmallest+1); } else { printptr = printbuffer; ps_write(printptr,printlargest); lineswritten++; } } } endwrite() { if (!do_startwrite) { ps_finishwrite(term.flags & INSERT,firstsmallest,firstY); firstsmallest = MAXSCREENWIDTH; firstlargest = 0; do_startwrite = TRUE; firstline = TRUE; lineswritten = 0; } } static int select_mask; in_put() { register Screen *screen = &term.screen; register char *cp; register int i; long arg; int select_mask = 0; int first_time = TRUE; psio_clearerr(PostScriptInput); for (;;) { ioctl(screen->respond, FIONREAD, &arg); if (arg > 0 || select_mask & pty_mask) { if (!screen->multiscroll && lineswritten > screen_rows) { flushwrite(); clearbuffer(); } if ((bcnt = read(screen->respond, bptr = buffer, BUF_SIZE)) < 0) { if (errno == EIO && am_slave) exit(0); else if (errno != EWOULDBLOCK) Panic( "input: read returned unexpected error (%d)\n", errno); } else if (bcnt == 0) Panic("input: read returned zero\n"); else { #ifndef KANJI /* strip parity bit */ for (i = bcnt, cp = bptr; i > 0; i--) *cp++ &= CHAR; #endif break; } } ioctl(psio_fileno(PostScriptInput), FIONREAD, &arg); if (select_mask & X_mask || arg > 0) { if (bcnt <= 0) { bcnt = 0; bptr = buffer; } xevents(); if (psio_error(PostScriptInput) || psio_eof(PostScriptInput)) Exit(ERROR_XERROR); if (bcnt > 0) break; } select_mask = Select_mask; select_timeout.tv_usec = select_delay; if (first_time) i = select(max_plus1, &select_mask, NULL, NULL, &select_timeout); else i = select(max_plus1, &select_mask, NULL, NULL, NULL); if (i < 0) { if (errno != EINTR) SysError(ERROR_SELECT); continue; } else { if (i == 0) { flushwrite(); ps_movecaret(caretX,caretY); if (psio_needsflush(PostScript)) ps_flush_PostScript(); first_time = FALSE; continue; } } } bcnt--; return (*bptr++); } /* * process a string of characters according to the character set indicated by * charset. worry about end of line conditions (wraparound if selected). */ dotext(screen, flags, charset, buf, ptr) register Screen *screen; unsigned flags; char charset; char *buf; char *ptr; { register char *s; register int len; register int n; register int next_col; switch (charset) { case 'A': /* United Kingdom set */ for (s = buf; s < ptr; ++s) if (*s == '#') *s = '\036'; /* UK pound sign */ break; case 'B': /* ASCII set */ break; case '0': /* special graphics (line drawing) */ for (s = buf; s < ptr; ++s) if (*s >= 0x5f && *s <= 0x7e) *s = *s == 0x5f ? 0x7f : *s - 0x5f; break; default: /* any character sets we don't recognize */ return; } len = ptr - buf; ptr = buf; while (len > 0) { if (caretX > MAXSCREENWIDTH) { doVMOT(); caretX = 1; } if (caretX > screen_cols && flags & WRAPAROUND) { doVMOT(); caretX = 1; } if (flags & WRAPAROUND) n = MIN(screen_cols-caretX+1,len); else n = MIN(MAXSCREENWIDTH-caretX+1,len); WriteText(screen, ptr, n, flags); len -= n; ptr += n; } } /* * write a string str of length len to the screen, starting at the * current caret position. Update caretX. */ WriteText(screen, str, len, flags) register Screen *screen; register char *str; register int len; unsigned flags; { register char *cp; int end; if (len > 0) { if (do_startwrite) { ps_startwrite(); firstY = caretY; do_startwrite = FALSE; printsmallest = caretX; printlargest = caretX; } end = caretX+len-1; bcopy(str,printbuffer+caretX-1,len); if (firstline) firstsmallest = MIN(firstsmallest,caretX); printsmallest = MIN(printsmallest,caretX); if (firstline) firstlargest = MAX(firstlargest,end); printlargest = MAX(printlargest,end); if (term.flags & INSERT) if (caretX <= linelength[caretY]) linelength[caretY] = linelength[caretY]+len; else linelength[caretY] = end; else linelength[caretY] = MAX(linelength[caretY],end); caretX += len; ctotal += len; ++ntotal; if (LDEBUG) fprintf(stderr,"WriteText Linelength %d: %d\n",caretY,linelength[caretY]); } } /* * process ANSI modes set, reset */ modes(term, func) Terminal *term; int (*func) (); { register Screen *screen = &term->screen; register int i; for (i = 0; i < nparam; ++i) { switch (param[i]) { case 4: /* IRM */ flushwrite(); clearbuffer(); (*func) (&term->flags, INSERT); break; case 20: /* LNM */ (*func) (&term->flags, LINEFEED); break; } } } /* * process DEC private modes set, reset */ dpmodes(term, func) Terminal *term; int (*func) (); { register Screen *screen = &term->screen; register int i, j; extern int bitset(); for (i = 0; i < nparam; ++i) { switch (param[i]) { case 1: /* DECCKM */ (*func) (&term->keyboard.flags, CURSOR_APL); break; case 3: /* DECCOLM */ if (screen->c132) { ps_clearscreen(); } break; case 4: /* DECSCLM (slow scroll) */ break; case 5: /* DECSCNM */ j = term->flags; (*func) (&term->flags, REVERSE_VIDEO); if ((term->flags ^ j) & REVERSE_VIDEO) ps_reversevideo(); break; case 6: /* DECOM */ (*func) (&term->flags, ORIGIN); CaretSet(screen, 1, 1, term->flags); break; case 7: /* DECAWM */ (*func) (&term->flags, WRAPAROUND); break; case 8: /* DECARM */ break; case 9: /* MIT bogus sequence */ (*func) (&screen->send_mouse_pos, 1); break; case 38: /* DECTEK */ break; case 40: /* 132 column mode */ (*func) (&screen->c132, 1); break; case 41: /* curses hack */ (*func) (&screen->curses, 1); break; case 42: /* scrollbar */ break; case 43: /* lines off top */ break; case 44: /* margin bell */ (*func) (&screen->marginbell, 1); if (!screen->marginbell) screen->bellarmed = -1; break; case 45: /* reverse wraparound */ (*func) (&term->flags, REVERSEWRAP); break; case 46: /* logging */ if (func == bitset) StartLog(screen); else CloseLog(screen); break; case 47: /* disable scrolling */ if (func == bitset) { scrolling_disabled = TRUE; if (!scrollingregion_enabled) ps_setscrollinglimits(1,screen_rows); } else { scrolling_disabled = FALSE; if (!scrollingregion_enabled) ps_removescrollinglimits(); } break; case 48: /* reverse status line */ j = screen->reversestatus; (*func) (&screen->reversestatus, 1); break; case 49: /* page mode */ j = screen->pagemode; (*func) (&screen->pagemode, 1); if (!j && screen->pagemode) screen->pagecnt = 0; break; } } } /* * process nterm private modes save */ savemodes(term) Terminal *term; { register Screen *screen = &term->screen; register int i; for (i = 0; i < nparam; i++) { switch (param[i]) { case 1: /* DECCKM */ screen->save_modes[0] = term->keyboard.flags & CURSOR_APL; break; case 3: /* DECCOLM */ if (screen->c132) screen->save_modes[1] = term->flags & IN132COLUMNS; break; case 4: /* DECSCLM (slow scroll) */ screen->save_modes[2] = term->flags & SMOOTHSCROLL; break; case 5: /* DECSCNM */ screen->save_modes[3] = term->flags & REVERSE_VIDEO; break; case 6: /* DECOM */ screen->save_modes[4] = term->flags & ORIGIN; break; case 7: /* DECAWM */ screen->save_modes[5] = term->flags & WRAPAROUND; break; case 8: /* DECARM */ screen->save_modes[6] = term->flags & AUTOREPEAT; break; case 9: /* MIT bogus sequence */ screen->save_modes[7] = screen->send_mouse_pos; break; case 40: /* 132 column mode */ screen->save_modes[8] = screen->c132; break; case 41: /* curses hack */ screen->save_modes[9] = screen->curses; break; case 42: /* scrollbar */ break; case 43: /* lines off top */ break; case 44: /* margin bell */ screen->save_modes[12] = screen->marginbell; break; case 45: /* reverse wraparound */ screen->save_modes[13] = term->flags & REVERSEWRAP; break; case 46: /* logging */ screen->save_modes[14] = screen->logging; break; case 47: /* disable scrolling */ screen->save_modes[15] = scrolling_disabled; break; case 48: /* reverse status line */ screen->save_modes[16] = screen->reversestatus; break; case 49: /* page mode */ screen->save_modes[17] = screen->pagemode; screen->save_modes[18] = screen->pagecnt; break; } } } /* * process nterm private modes restore */ restoremodes(term) Terminal *term; { register Screen *screen = &term->screen; register int i, j; for (i = 0; i < nparam; i++) { switch (param[i]) { case 1: /* DECCKM */ term->keyboard.flags &= ~CURSOR_APL; term->keyboard.flags |= screen->save_modes[0] & CURSOR_APL; break; case 3: /* DECCOLM */ break; case 4: /* DECSCLM (slow scroll) */ break; case 5: /* DECSCNM */ if ((screen->save_modes[3] ^ term->flags) & REVERSE_VIDEO) { term->flags &= ~REVERSE_VIDEO; term->flags |= screen->save_modes[3] & REVERSE_VIDEO; ps_reversevideo(); } break; case 6: /* DECOM */ term->flags &= ~ORIGIN; term->flags |= screen->save_modes[4] & ORIGIN; CaretSet(screen, 1, 1, term->flags); break; case 7: /* DECAWM */ term->flags &= ~WRAPAROUND; term->flags |= screen->save_modes[5] & WRAPAROUND; break; case 8: /* DECARM */ if ((screen->save_modes[6] ^ term->flags) & AUTOREPEAT) { term->flags &= ~REVERSE_VIDEO; term->flags |= screen->save_modes[6] & REVERSE_VIDEO; } break; case 9: /* MIT bogus sequence */ screen->send_mouse_pos = screen->save_modes[7]; break; case 40: /* 132 column mode */ screen->c132 = screen->save_modes[8]; break; case 41: /* curses hack */ screen->curses = screen->save_modes[9]; break; case 42: /* scrollbar */ break; case 43: /* lines off top */ /* if (screen->sb) SetSaveState(screen->sb, screen->save_modes[11]); */ break; case 44: /* margin bell */ if (!(screen->marginbell = screen->save_modes[12])) screen->bellarmed = -1; break; case 45: /* reverse wraparound */ term->flags &= ~REVERSEWRAP; term->flags |= screen->save_modes[13] & REVERSEWRAP; break; case 46: /* logging */ if (screen->save_modes[14]) StartLog(screen); else CloseLog(screen); break; case 47: /* disable scrolling */ if (!scrolling_disabled && screen->save_modes[15]) { scrolling_disabled = TRUE; if (!scrollingregion_enabled) ps_setscrollinglimits(1,screen_rows); } if (scrolling_disabled && !screen->save_modes[15]) { scrolling_disabled = FALSE; if (!scrollingregion_enabled) ps_removescrollinglimits(); } break; case 48: /* reverse status line */ break; case 49: /* page mode */ screen->pagemode = screen->save_modes[17]; screen->pagecnt = screen->save_modes[18]; break; } } } /* * set a bit in a word given a pointer to the word and a mask. */ bitset(p, mask) int *p; { *p |= mask; } /* * clear a bit in a word given a pointer to the word and a mask. */ bitclr(p, mask) int *p; { *p &= ~mask; } unparseseq(ap, fd) register ANSI *ap; { register int c; register int i; register int inters; c = ap->a_type; if (c >= 0x80 && c <= 0x9F) { unparseputc(ESC, fd); c -= 0x40; } unparseputc(c, fd); c = ap->a_type; if (c == ESC || c == DCS || c == CSI || c == OSC || c == PM || c == APC) { if (ap->a_pintro != 0) unparseputc(ap->a_pintro, fd); for (i = 0; i < ap->a_nparam; ++i) { if (i != 0) unparseputc(';', fd); unparseputn(ap->a_param[i], fd); } inters = ap->a_inters; for (i = 3; i >= 0; --i) c = (inters >> (8 * i)) & 0xff; if (c != 0) unparseputc(c, fd); unparseputc(ap->a_final, fd); } } unparseputn(n, fd) unsigned int n; { unsigned int q; q = n / 10; if (q != 0) unparseputn(q, fd); unparseputc((n % 10) + '0', fd); } unparseputc(c, fd) { char buf[2]; register i = 1; extern Terminal term; if ((buf[0] = c) == '\r' && (term.flags & LINEFEED)) { buf[1] = '\n'; i++; } if (write(fd, buf, i) != i) Panic("unparseputc: error writing character\n", 0); } static int alt_pagecnt; static int alt_pagemode; static int alt_saving; ToAlternate(screen) register Screen *screen; { } FromAlternate(screen) register Screen *screen; { } SwitchBufs(screen) register Screen *screen; { } VTRun() { register Screen *screen = &term.screen; register int i; VTInit(); ps_oncaret(); bcnt = 0; bptr = buffer; printptr = printbuffer; if (!setjmp(VTend)) VTparse(); } VTInit() { register Screen *screen = &term.screen; bcopy(blankline,printbuffer,MAXSCREENWIDTH); TabReset(term.tabs); /* Reset variables used by ANSI emulation. */ screen->gsets[0] = 'B'; /* ASCII_G */ screen->gsets[1] = 'B'; screen->gsets[2] = 'B'; /* DEC supplemental. */ screen->gsets[3] = 'B'; screen->curgl = 0; /* G0 => GL. */ screen->curgr = 2; /* G2 => GR. */ screen->curss = 0; /* No single shift. */ } VTReset(full) int full; { register Screen *screen = &term.screen; scrollingregion_enabled = FALSE; scrolling_disabled = FALSE; ps_removescrollinglimits(); if (full) { TabReset(term.tabs); term.keyboard.flags = NULL; screen->gsets[0] = 'B'; screen->gsets[1] = 'B'; screen->gsets[2] = 'B'; screen->gsets[3] = 'B'; screen->curgl = 0; screen->curgr = 2; screen->curss = 0; ps_clearscreen(); if (term.flags & REVERSE_VIDEO) ps_reversevideo(); term.flags = term.initflags; if (screen->c132 && (term.flags & IN132COLUMNS)) { } ps_movecaret(1,1); } longjmp(vtjmpbuf, 1); /* force ground state in parser */ } /* * Do what needs to be done for LF, VT, FF */ doVMOT () { register Screen *screen = &term.screen; register int i; if (!do_startwrite) { writebuffer(); if (caretX != 1) { endwrite(); } } clearbuffer(); printlargest = 0; firstlargest = 0; caretY++; if (caretY > screen->bot_marg) { caretY = screen->bot_marg; /* Send out two 0 length lines to force a scroll */ if (do_startwrite) { ps_startwrite(); ps_write(printbuffer,0); firstY = caretY; firstsmallest = 1; do_startwrite = FALSE; flushwrite(); } /* Scroll the line length array */ for (i=screen->top_marg; ibot_marg; i++) linelength[i] = linelength[i+1]; linelength[screen->bot_marg] = 0; if (LDEBUG) { fprintf(stderr,"VMOT Linelength\n"); for (i=1; i<=screen_rows; i++) fprintf(stderr,"%d: %d\n",i,linelength[i]); } } if (!do_startwrite) firstline = FALSE; if (psio_availinputbytes(PostScriptInput) > 0 || (ioctl(psio_fileno(PostScriptInput), FIONREAD, &arg), arg) > 0) xevents(); } /* * Move caret, taking origin mode into account */ CaretSet(screen, col, row, flags) register Screen *screen; register int row, col; unsigned flags; { register int maxr; col = (col < 1 ? 1 : col); caretX = col; if (!screen->instatus) { maxr = screen_rows; if (flags & ORIGIN) { row += screen->top_marg; maxr = screen->bot_marg; } row = (row < 0 ? 0 : row); caretY = (row <= maxr ? row : maxr); } ps_movecaret(caretX,caretY); } /* * Save Caret and Attributes */ CaretSave(term, sc) register Terminal *term; register SavedCaret *sc; { register Screen *screen = &term->screen; sc->row = caretY; sc->col = caretX; sc->flags = term->flags; sc->curgl = screen->curgl; sc->curgr = screen->curgr; bcopy(screen->gsets, sc->gsets, sizeof(screen->gsets)); } /* * Restore Caret and Attributes */ CaretRestore(term, sc) register Terminal *term; register SavedCaret *sc; { register Screen *screen = &term->screen; bcopy(sc->gsets, screen->gsets, sizeof(screen->gsets)); screen->curgl = sc->curgl; screen->curgr = sc->curgr; term->flags &= ~(BOLD | INVERSE | UNDERLINE); term->flags |= sc->flags & (BOLD | INVERSE | UNDERLINE); caretY = sc->row; caretX = sc->col; ps_movecaret(caretX,caretY); }