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; }
void wsemul_sun_output_normal(struct wsemul_sun_emuldata *edp, u_char c, int kernel) { (*edp->emulops->putchar)(edp->emulcookie, edp->crow, edp->ccol, c, kernel ? edp->kernattr : edp->curattr); if (++edp->ccol >= edp->ncols) { /* if the cur line isn't the last, incr and leave. */ if (ROWS_LEFT > 0) edp->crow++; else wsemul_sun_scrollup(edp, edp->scrolldist); edp->ccol = 0; } }
void wsemul_sun_jump_scroll(struct wsemul_sun_emuldata *edp, const u_char *data, u_int count, int kernel) { u_char curchar; u_int pos, lines; lines = 0; pos = edp->ccol; for (; count != 0; data++, count--) { curchar = *data; if (curchar == ASCII_FF || curchar == ASCII_VT || curchar == ASCII_ESC) break; switch (curchar) { case ASCII_BS: if (pos > 0) pos--; break; case ASCII_CR: pos = 0; break; case ASCII_HT: pos = (pos + 7) & ~7; if (pos >= edp->ncols) pos = edp->ncols - 1; break; default: if (++pos >= edp->ncols) { pos = 0; curchar = ASCII_LF; } break; } if (curchar == ASCII_LF) { if (++lines >= edp->nrows - 1) break; } } if (lines > 1) { wsemul_sun_scrollup(edp, lines); edp->crow--; } }
u_int wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel) { struct wsemul_sun_emuldata *edp = cookie; struct wsemul_inputstate *instate; u_int processed = 0; #ifdef HAVE_JUMP_SCROLL int lines; #endif int rc = 0; #ifdef DIAGNOSTIC if (kernel && !edp->console) panic("wsemul_sun_output: kernel output, not console"); #endif instate = kernel ? &edp->kstate : &edp->instate; 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; } for (;;) { #ifdef HAVE_JUMP_SCROLL switch (edp->abortstate.state) { case ABORT_FAILED_JUMP_SCROLL: /* * If we failed a previous jump scroll attempt, we * need to try to resume it with the same distance. * We can not recompute it since there might be more * bytes in the tty ring, causing a different result. */ lines = edp->abortstate.lines; break; case ABORT_OK: /* * If scrolling is not disabled and we are the bottom of * the screen, count newlines until an escape sequence * appears. */ if ((edp->state == SUN_EMUL_STATE_NORMAL || kernel) && ROWS_LEFT == 0 && edp->scrolldist != 0) lines = wsemul_sun_jump_scroll(edp, data, count, kernel); else lines = 0; break; default: /* * If we are recovering a non-scrolling failure, * do not try to scroll yet. */ lines = 0; break; } if (lines > 1) { wsemul_resume_abort(&edp->abortstate); rc = wsemul_sun_scrollup(edp, lines); if (rc != 0) { wsemul_abort_jump_scroll(&edp->abortstate, lines); return processed; } wsemul_reset_abortstate(&edp->abortstate); edp->crow--; } #endif wsemul_resume_abort(&edp->abortstate); if (wsemul_getchar(&data, &count, instate, #ifdef HAVE_UTF8_SUPPORT (edp->state == SUN_EMUL_STATE_NORMAL && !kernel) ? edp->flags & SUN_EMUL_FLAGS_UTF8 : 0 #else 0 #endif ) != 0) break; if (instate->inchar < ' ') { rc = wsemul_sun_output_lowchars(edp, instate, kernel); if (rc != 0) break; processed++; continue; } if (kernel) { rc = wsemul_sun_output_normal(edp, instate, 1); if (rc != 0) break; processed++; continue; } switch (edp->state) { case SUN_EMUL_STATE_NORMAL: rc = wsemul_sun_output_normal(edp, instate, 0); break; case SUN_EMUL_STATE_HAVEESC: rc = wsemul_sun_output_haveesc(edp, instate); break; case SUN_EMUL_STATE_CONTROL: rc = wsemul_sun_output_control(edp, instate); break; #ifdef HAVE_UTF8_SUPPORT case SUN_EMUL_STATE_PERCENT: rc = wsemul_sun_output_percent(edp, instate); break; #endif default: #ifdef DIAGNOSTIC panic("wsemul_sun: invalid state %d", edp->state); #else /* try to recover, if things get screwed up... */ edp->state = SUN_EMUL_STATE_NORMAL; rc = wsemul_sun_output_normal(edp, instate, 0); #endif 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; }
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; }