Esempio n. 1
0
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;
}
Esempio n. 2
0
void
wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel)
{
    struct wsemul_sun_emuldata *edp = cookie;
    u_int newstate;

#ifdef DIAGNOSTIC
    if (kernel && !edp->console)
        panic("wsemul_sun_output: kernel output, not console");
#endif

    /* XXX */
    (*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol);

    for (; count > 0; data++, count--) {
#ifdef JUMP_SCROLL
        /*
         * 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)
            wsemul_sun_jump_scroll(edp, data, count, kernel);
#endif

        if (*data < ' ') {
            wsemul_sun_output_lowchars(edp, *data, kernel);
            continue;
        }

        if (kernel) {
            wsemul_sun_output_normal(edp, *data, 1);
            continue;
        }

        switch (newstate = edp->state) {
        case SUN_EMUL_STATE_NORMAL:
            wsemul_sun_output_normal(edp, *data, 0);
            break;
        case SUN_EMUL_STATE_HAVEESC:
            newstate = wsemul_sun_output_haveesc(edp, *data);
            break;
        case SUN_EMUL_STATE_CONTROL:
            newstate = wsemul_sun_output_control(edp, *data);
            break;
        default:
#ifdef DIAGNOSTIC
            panic("wsemul_sun: invalid state %d", edp->state);
#else
            /* try to recover, if things get screwed up... */
            newstate = SUN_EMUL_STATE_NORMAL;
            wsemul_sun_output_normal(edp, *data, 0);
#endif
            break;
        }
        edp->state = newstate;
    }
    /* XXX */
    (*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol);
}