Ejemplo n.º 1
0
/*
 * v_c_settop --
 *	Scrollbar position.
 */
static int
v_c_settop(SCR *sp, VICMD *vp)
{
	SMAP *smp;
	size_t x = 0, y = LASTLINE(sp); /* Future: change to -1 to not
					 * display the cursor
					 */
	size_t tx, ty = -1;

	/*
	 * We want to scroll the screen, without changing the cursor position.
	 * So, we fill the screen map and then flush it to the screen.  Then,
	 * set the VIP_S_REFRESH flag so the main vi loop doesn't update the
	 * screen.  When the next real command happens, the refresh code will
	 * notice that the screen map is way wrong and fix it.
	 *
	 * XXX
	 * There may be a serious performance problem here -- we're doing no
	 * optimization whatsoever, which means that we're copying the entire
	 * screen out to the X11 screen code on each change.
	 */
	if (vs_sm_fill(sp, vp->ev.e_lno, P_TOP))
		return (1);
	for (smp = HMAP; smp <= TMAP; ++smp) {
                SMAP_FLUSH(smp);
		if (vs_line(sp, smp, &ty, &tx))
			return (1);
		if (ty != (size_t)-1) {
			y = ty;
			x = tx;
		}
        }
	(void)sp->gp->scr_move(sp, y, x);

	F_SET(VIP(sp), VIP_S_REFRESH);

	return (sp->gp->scr_refresh(sp, 0));
}
Ejemplo n.º 2
0
Archivo: v_z.c Proyecto: 2asoft/freebsd
/*
 * v_z -- [count]z[count][-.+^<CR>]
 *	Move the screen.
 *
 * PUBLIC: int v_z(SCR *, VICMD *);
 */
int
v_z(SCR *sp, VICMD *vp)
{
	recno_t lno;
	e_key_t value;

	/*
	 * The first count is the line to use.  If the value doesn't
	 * exist, use the last line.
	 */
	if (F_ISSET(vp, VC_C1SET)) {
		lno = vp->count;
		if (!db_exist(sp, lno) && db_last(sp, &lno))
			return (1);
	} else
		lno = vp->m_start.lno;

	/* Set default return cursor line. */
	vp->m_final.lno = lno;
	vp->m_final.cno = vp->m_start.cno;

	/*
	 * The second count is the displayed window size, i.e. the 'z' command
	 * is another way to get artificially small windows.  Note, you can't
	 * grow beyond the size of the window.
	 *
	 * !!!
	 * A window size of 0 was historically allowed, and simply ignored.
	 * This could be much more simply done by modifying the value of the
	 * O_WINDOW option, but that's not how it worked historically.
	 */
	if (F_ISSET(vp, VC_C2SET) && vp->count2 != 0) {
		if (vp->count2 > O_VAL(sp, O_WINDOW))
			vp->count2 = O_VAL(sp, O_WINDOW);
		if (vs_crel(sp, vp->count2))
			return (1);
	}

	switch (vp->character) {
	case '-':		/* Put the line at the bottom. */
		if (vs_sm_fill(sp, lno, P_BOTTOM))
			return (1);
		break;
	case '.':		/* Put the line in the middle. */
		if (vs_sm_fill(sp, lno, P_MIDDLE))
			return (1);
		break;
	case '+':
		/*
		 * If the user specified a line number, put that line at the
		 * top and move the cursor to it.  Otherwise, scroll forward
		 * a screen from the current screen.
		 */
		if (F_ISSET(vp, VC_C1SET)) {
			if (vs_sm_fill(sp, lno, P_TOP))
				return (1);
			if (vs_sm_position(sp, &vp->m_final, 0, P_TOP))
				return (1);
		} else
			if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_PLUS))
				return (1);
		break;
	case '^':
		/*
		 * If the user specified a line number, put that line at the
		 * bottom, move the cursor to it, and then display the screen
		 * before that one.  Otherwise, scroll backward a screen from
		 * the current screen.
		 *
		 * !!!
		 * Note, we match the off-by-one characteristics of historic
		 * vi, here.
		 */
		if (F_ISSET(vp, VC_C1SET)) {
			if (vs_sm_fill(sp, lno, P_BOTTOM))
				return (1);
			if (vs_sm_position(sp, &vp->m_final, 0, P_TOP))
				return (1);
			if (vs_sm_fill(sp, vp->m_final.lno, P_BOTTOM))
				return (1);
		} else
			if (vs_sm_scroll(sp, &vp->m_final, sp->t_rows, Z_CARAT))
				return (1);
		break;
	default:		/* Put the line at the top for <cr>. */
		value = KEY_VAL(sp, vp->character);
		if (value != K_CR && value != K_NL) {
			v_emsg(sp, vp->kp->usage, VIM_USAGE);
			return (1);
		}
		if (vs_sm_fill(sp, lno, P_TOP))
			return (1);
		break;
	}
	return (0);
}