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;
}
Beispiel #2
0
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;
}