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;
}
Exemple #5
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;
}