int wsemul_sun_output_normal(struct wsemul_sun_emuldata *edp, struct wsemul_inputstate *instate, int kernel) { int rc; u_int outchar; (*edp->emulops->mapchar)(edp->emulcookie, instate->inchar, &outchar); WSEMULOP(rc, edp, &edp->abortstate, putchar, (edp->emulcookie, edp->crow, edp->ccol, outchar, kernel ? edp->kernattr : edp->curattr)); if (rc != 0) return rc; if (++edp->ccol >= edp->ncols) { /* if the cur line isn't the last, incr and leave. */ if (ROWS_LEFT > 0) edp->crow++; else { rc = wsemul_sun_scrollup(edp, edp->scrolldist); if (rc != 0) { /* undo line wrap */ edp->ccol--; return rc; } } edp->ccol = 0; } return 0; }
int wsemul_sun_scrollup(struct wsemul_sun_emuldata *edp, u_int lines) { int rc; /* * if we're in wrap-around mode, go to the first * line and clear it. */ if (lines == 0) { WSEMULOP(rc, edp, &edp->abortstate, eraserows, (edp->emulcookie, 0, 1, edp->bkgdattr)); if (rc != 0) return rc; edp->crow = 0; return 0; } /* * If the scrolling distance is equal to the screen height * (usually 34), clear the screen; otherwise, scroll by the * scrolling distance. */ if (lines < edp->nrows) { WSEMULOP(rc, edp, &edp->abortstate, copyrows, (edp->emulcookie, lines, 0, edp->nrows - lines)); if (rc != 0) return rc; } WSEMULOP(rc, edp, &edp->abortstate, eraserows, (edp->emulcookie, edp->nrows - lines, lines, edp->bkgdattr)); if (rc != 0) return rc; edp->crow -= lines - 1; return 0; }
int wsemul_sun_control(struct wsemul_sun_emuldata *edp, struct wsemul_inputstate *instate) { u_int n, src, dst; int flags, fgcol, bgcol; long attr, bkgdattr; int rc = 0; switch (instate->inchar) { case '@': /* "Insert Character (ICH)" */ n = min(NORMALIZE(ARG(0,1)), COLS_LEFT + 1); src = edp->ccol; dst = edp->ccol + n; if (dst < edp->ncols) { WSEMULOP(rc, edp, &edp->abortstate, copycols, (edp->emulcookie, edp->crow, src, dst, edp->ncols - dst)); if (rc != 0) break; } WSEMULOP(rc, edp, &edp->abortstate, erasecols, (edp->emulcookie, edp->crow, src, n, edp->bkgdattr)); break; case 'A': /* "Cursor Up (CUU)" */ edp->crow -= min(NORMALIZE(ARG(0,1)), edp->crow); break; case 'E': /* "Cursor Next Line (CNL)" */ edp->ccol = 0; /* FALLTHROUGH */ case 'B': /* "Cursor Down (CUD)" */ edp->crow += min(NORMALIZE(ARG(0,1)), ROWS_LEFT); break; case 'C': /* "Cursor Forward (CUF)" */ edp->ccol += min(NORMALIZE(ARG(0,1)), COLS_LEFT); break; case 'D': /* "Cursor Backward (CUB)" */ edp->ccol -= min(NORMALIZE(ARG(0,1)), edp->ccol); break; case 'f': /* "Horizontal And Vertical Position (HVP)" */ case 'H': /* "Cursor Position (CUP)" */ edp->crow = min(NORMALIZE(ARG(0,2)), edp->nrows) - 1; edp->ccol = min(NORMALIZE(ARG(1,2)), edp->ncols) - 1; break; case 'J': /* "Erase in Display (ED)" */ if (ROWS_LEFT > 0) { WSEMULOP(rc, edp, &edp->abortstate, eraserows, (edp->emulcookie, edp->crow + 1, ROWS_LEFT, edp->bkgdattr)); if (rc != 0) break; } /* FALLTHROUGH */ case 'K': /* "Erase in Line (EL)" */ WSEMULOP(rc, edp, &edp->abortstate, erasecols, (edp->emulcookie, edp->crow, edp->ccol, COLS_LEFT + 1, edp->bkgdattr)); break; case 'L': /* "Insert Line (IL)" */ n = min(NORMALIZE(ARG(0,1)), ROWS_LEFT + 1); src = edp->crow; dst = edp->crow + n; if (dst < edp->nrows) { WSEMULOP(rc, edp, &edp->abortstate, copyrows, (edp->emulcookie, src, dst, edp->nrows - dst)); if (rc != 0) break; } WSEMULOP(rc, edp, &edp->abortstate, eraserows, (edp->emulcookie, src, n, edp->bkgdattr)); break; case 'M': /* "Delete Line (DL)" */ n = min(NORMALIZE(ARG(0,1)), ROWS_LEFT + 1); src = edp->crow + n; dst = edp->crow; if (src < edp->nrows) { WSEMULOP(rc, edp, &edp->abortstate, copyrows, (edp->emulcookie, src, dst, edp->nrows - src)); if (rc != 0) break; } WSEMULOP(rc, edp, &edp->abortstate, eraserows, (edp->emulcookie, dst + edp->nrows - src, n, edp->bkgdattr)); break; case 'P': /* "Delete Character (DCH)" */ n = min(NORMALIZE(ARG(0,1)), COLS_LEFT + 1); src = edp->ccol + n; dst = edp->ccol; if (src < edp->ncols) { WSEMULOP(rc, edp, &edp->abortstate, copycols, (edp->emulcookie, edp->crow, src, dst, edp->ncols - src)); if (rc != 0) break; } WSEMULOP(rc, edp, &edp->abortstate, erasecols, (edp->emulcookie, edp->crow, edp->ncols - n, n, edp->bkgdattr)); break; case 'm': /* "Select Graphic Rendition (SGR)" */ flags = edp->attrflags; fgcol = edp->fgcol; bgcol = edp->bgcol; for (n = 0; n < edp->nargs; n++) { switch (ARG(n,edp->nargs)) { /* Clear all attributes || End underline */ case 0: if (n == edp->nargs - 1) { edp->bkgdattr = edp->curattr = edp->defattr; edp->attrflags = 0; edp->fgcol = WSCOL_BLACK; edp->bgcol = WSCOL_WHITE; return 0; } flags = 0; fgcol = WSCOL_BLACK; bgcol = WSCOL_WHITE; break; /* Begin bold */ case 1: flags |= WSATTR_HILIT; break; /* Begin underline */ case 4: flags |= WSATTR_UNDERLINE; break; /* Begin reverse */ case 7: flags |= WSATTR_REVERSE; break; /* ANSI foreground color */ case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: fgcol = ARG(n,edp->nargs) - 30; break; /* ANSI background color */ case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: bgcol = ARG(n,edp->nargs) - 40; break; } } setattr: if (wsemul_sun_selectattribute(edp, flags, fgcol, bgcol, &attr, &bkgdattr)) { #ifdef DEBUG printf("error allocating attr %d/%d/%x\n", fgcol, bgcol, flags); #endif } else { edp->curattr = attr; edp->bkgdattr = bkgdattr; edp->attrflags = flags; edp->fgcol = fgcol; edp->bgcol = bgcol; } break; case 'p': /* "Black On White (SUNBOW)" */ flags = 0; fgcol = WSCOL_BLACK; bgcol = WSCOL_WHITE; goto setattr; case 'q': /* "White On Black (SUNWOB)" */ flags = 0; fgcol = WSCOL_WHITE; bgcol = WSCOL_BLACK; goto setattr; case 'r': /* "Set Scrolling (SUNSCRL)" */ edp->scrolldist = min(ARG(0,1), edp->nrows); break; case 's': /* "Reset Terminal Emulator (SUNRESET)" */ wsemul_sun_reset(edp); break; } return rc; }
int wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *edp, struct wsemul_inputstate *instate, int kernel) { u_int n; int rc = 0; switch (instate->inchar) { case ASCII_NUL: default: /* ignore */ break; case ASCII_BEL: /* "Bell (BEL)" */ wsdisplay_emulbell(edp->cbcookie); break; case ASCII_BS: /* "Backspace (BS)" */ if (edp->ccol > 0) edp->ccol--; break; case ASCII_CR: /* "Return (CR)" */ edp->ccol = 0; break; case ASCII_HT: /* "Tab (TAB)" */ n = min(8 - (edp->ccol & 7), COLS_LEFT); if (n != 0) { WSEMULOP(rc, edp, &edp->abortstate, erasecols, (edp->emulcookie, edp->crow, edp->ccol, n, kernel ? edp->kernattr : edp->bkgdattr)); if (rc != 0) break; edp->ccol += n; } break; case ASCII_FF: /* "Form Feed (FF)" */ WSEMULOP(rc, edp, &edp->abortstate, eraserows, (edp->emulcookie, 0, edp->nrows, edp->bkgdattr)); if (rc != 0) break; edp->ccol = edp->crow = 0; break; case ASCII_VT: /* "Reverse Line Feed" */ if (edp->crow > 0) edp->crow--; break; case ASCII_ESC: /* "Escape (ESC)" */ if (kernel) { printf("wsemul_sun_output_lowchars: ESC in kernel " "output ignored\n"); break; /* ignore the ESC */ } edp->state = SUN_EMUL_STATE_HAVEESC; break; case ASCII_LF: /* "Line Feed (LF)" */ /* if the cur line isn't the last, incr and leave. */ if (ROWS_LEFT > 0) edp->crow++; else { rc = wsemul_sun_scrollup(edp, edp->scrolldist); if (rc != 0) break; } break; } return rc; }
u_int wsemul_dumb_output(void *cookie, const u_char *data, u_int count, int kernel) { struct wsemul_dumb_emuldata *edp = cookie; u_int processed = 0; u_char c; int n; int rc = 0; if (edp->crippled) { while (count-- > 0) { wsemul_resume_abort(&edp->abortstate); c = *data++; if (c == ASCII_BEL) wsdisplay_emulbell(edp->cbcookie); else { WSEMULOP(rc, edp, &edp->abortstate, putchar, (edp->emulcookie, 0, 0, c, 0)); if (rc != 0) break; } processed++; } if (rc != 0) wsemul_abort_other(&edp->abortstate); return processed; } switch (edp->abortstate.state) { case ABORT_FAILED_CURSOR: /* * If we could not display the cursor back, we pretended not * having been able to display the last character. But this * is a lie, so compensate here. */ data++, count--; processed++; wsemul_reset_abortstate(&edp->abortstate); break; case ABORT_OK: /* remove cursor image */ rc = (*edp->emulops->cursor) (edp->emulcookie, 0, edp->crow, edp->ccol); if (rc != 0) return 0; break; default: break; } while (count-- > 0) { wsemul_resume_abort(&edp->abortstate); c = *data++; switch (c) { case ASCII_BEL: wsdisplay_emulbell(edp->cbcookie); break; case ASCII_BS: if (edp->ccol > 0) edp->ccol--; break; case ASCII_CR: edp->ccol = 0; break; case ASCII_HT: n = min(8 - (edp->ccol & 7), edp->ncols - edp->ccol - 1); WSEMULOP(rc, edp, &edp->abortstate, erasecols, (edp->emulcookie, edp->crow, edp->ccol, n, edp->defattr)); if (rc != 0) break; edp->ccol += n; break; case ASCII_FF: WSEMULOP(rc, edp, &edp->abortstate, eraserows, (edp->emulcookie, 0, edp->nrows, edp->defattr)); if (rc != 0) break; edp->ccol = 0; edp->crow = 0; break; case ASCII_VT: if (edp->crow > 0) edp->crow--; break; default: WSEMULOP(rc, edp, &edp->abortstate, putchar, (edp->emulcookie, edp->crow, edp->ccol, c, edp->defattr)); if (rc != 0) break; edp->ccol++; /* if cur col is still on cur line, done. */ if (edp->ccol < edp->ncols) break; /* wrap the column around. */ edp->ccol = 0; /* FALLTHROUGH */ case ASCII_LF: /* if the cur line isn't the last, incr and leave. */ if (edp->crow < edp->nrows - 1) { edp->crow++; break; } n = 1; /* number of lines to scroll */ WSEMULOP(rc, edp, &edp->abortstate, copyrows, (edp->emulcookie, n, 0, edp->nrows - n)); if (rc == 0) WSEMULOP(rc, edp, &edp->abortstate, eraserows, (edp->emulcookie, edp->nrows - n, n, edp->defattr)); if (rc != 0) { /* undo wrap-at-eol processing if necessary */ if (c != ASCII_LF) edp->ccol = edp->ncols - 1; break; } edp->crow -= n - 1; break; } if (rc != 0) break; processed++; } if (rc != 0) wsemul_abort_other(&edp->abortstate); else { /* put cursor image back */ rc = (*edp->emulops->cursor) (edp->emulcookie, 1, edp->crow, edp->ccol); if (rc != 0) { /* * Fail the last character output, remembering that * only the cursor operation really needs to be done. */ wsemul_abort_cursor(&edp->abortstate); processed--; } } if (rc == 0) wsemul_reset_abortstate(&edp->abortstate); return processed; }