/*
 * v_left -- [count]^H, [count]h
 *	Move left by columns.
 *
 * PUBLIC: int v_left __P((SCR *, VICMD *));
 */
int
v_left(SCR *sp, VICMD *vp)
{
	db_recno_t cnt;

	/*
	 * !!!
	 * The ^H and h commands always failed in the first column.
	 */
	if (vp->m_start.cno == 0) {
		v_sol(sp);
		return (1);
	}

	/* Find the end of the range. */
	cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
	if (vp->m_start.cno > cnt)
		vp->m_stop.cno = vp->m_start.cno - cnt;
	else
		vp->m_stop.cno = 0;

	/*
	 * All commands move to the end of the range.  Motion commands
	 * adjust the starting point to the character before the current
	 * one.
	 */
	if (ISMOTION(vp))
		--vp->m_start.cno;
	vp->m_final = vp->m_stop;
	return (0);
}
/*
 * v_cfirst -- [count]_
 *	Move to the first non-blank character in a line.
 *
 * PUBLIC: int v_cfirst __P((SCR *, VICMD *));
 */
int
v_cfirst(SCR *sp, VICMD *vp)
{
	db_recno_t cnt, lno;

	/*
	 * !!!
	 * If the _ is a motion component, it makes the command a line motion
	 * e.g. "d_" deletes the line.  It also means that the cursor doesn't
	 * move.
	 *
	 * The _ command never failed in the first column.
	 */
	if (ISMOTION(vp))
		F_SET(vp, VM_LMODE);
	/*
	 * !!!
	 * Historically a specified count makes _ move down count - 1
	 * rows, so, "3_" is the same as "2j_".
	 */
	cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1;
	if (cnt != 1) {
		--vp->count;
		return (v_down(sp, vp));
	}

	/*
	 * Move to the first non-blank.
	 *
	 * Can't just use RCM_SET_FNB, in case _ is used as the motion
	 * component of another command.
	 */
	vp->m_stop.cno = 0;
	if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
		return (1);

	/*
	 * !!!
	 * The _ command has to fail if the file is empty and we're doing
	 * a delete.  If deleting line 1, and 0 is the first nonblank,
	 * make the check.
	 */
	if (vp->m_stop.lno == 1 &&
	    vp->m_stop.cno == 0 && ISCMD(vp->rkp, 'd')) {
		if (db_last(sp, &lno))
			return (1);
		if (lno == 0) {
			v_sol(sp);
			return (1);
		}
	}

	/*
	 * Delete and non-motion commands move to the end of the range,
	 * yank stays at the start.  Ignore others.
	 */
	vp->m_final =
	    ISMOTION(vp) && ISCMD(vp->rkp, 'y') ? vp->m_start : vp->m_stop;
	return (0);
}
/*
 * v_ncol -- [count]|
 *	Move to column count or the first column on this line.  If the
 *	requested column is past EOL, move to EOL.  The nasty part is
 *	that we have to know character column widths to make this work.
 *
 * PUBLIC: int v_ncol __P((SCR *, VICMD *));
 */
int
v_ncol(SCR *sp, VICMD *vp)
{
	if (F_ISSET(vp, VC_C1SET) && vp->count > 1) {
		--vp->count;
		vp->m_stop.cno =
		    vs_colpos(sp, vp->m_start.lno, (size_t)vp->count);
		/*
		 * !!!
		 * The | command succeeded if used as a command and the cursor
		 * didn't move, but failed if used as a motion component in the
		 * same situation.
		 */
		if (ISMOTION(vp) && vp->m_stop.cno == vp->m_start.cno) {
			v_nomove(sp);
			return (1);
		}
	} else {
		/*
		 * !!!
		 * The | command succeeded if used as a command in column 0
		 * without a count, but failed if used as a motion component
		 * in the same situation.
		 */
		if (ISMOTION(vp) && vp->m_start.cno == 0) {
			v_sol(sp);
			return (1);
		}
		vp->m_stop.cno = 0;
	}

	/*
	 * If moving right, non-motion commands move to the end of the range.
	 * Delete and yank stay at the start.  Motion commands adjust the
	 * ending point to the character before the current ending charcter.
	 *
	 * If moving left, all commands move to the end of the range.  Motion
	 * commands adjust the starting point to the character before the
	 * current starting character.
	 */
	if (vp->m_start.cno < vp->m_stop.cno)
		if (ISMOTION(vp)) {
			--vp->m_stop.cno;
			vp->m_final = vp->m_start;
		} else
			vp->m_final = vp->m_stop;
	else {
		if (ISMOTION(vp))
			--vp->m_start.cno;
		vp->m_final = vp->m_stop;
	}
	return (0);
}
/*
 * v_first -- ^
 *	Move to the first non-blank character in this line.
 *
 * PUBLIC: int v_first __P((SCR *, VICMD *));
 */
int
v_first(SCR *sp, VICMD *vp)
{
	/*
	 * !!!
	 * Yielding to none in our quest for compatibility with every
	 * historical blemish of vi, no matter how strange it might be,
	 * we permit the user to enter a count and then ignore it.
	 */

	/*
	 * Move to the first non-blank.
	 *
	 * Can't just use RCM_SET_FNB, in case ^ is used as the motion
	 * component of another command.
	 */
	vp->m_stop.cno = 0;
	if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
		return (1);

	/*
	 * !!!
	 * The ^ command succeeded if used as a command when the cursor was
	 * on the first non-blank in the line, but failed if used as a motion
	 * component in the same situation.
	 */
	if (ISMOTION(vp) && vp->m_start.cno == vp->m_stop.cno) {
		v_sol(sp);
		return (1);
	}

	/*
	 * If moving right, non-motion commands move to the end of the range.
	 * Delete and yank stay at the start.  Motion commands adjust the
	 * ending point to the character before the current ending charcter.
	 *
	 * If moving left, all commands move to the end of the range.  Motion
	 * commands adjust the starting point to the character before the
	 * current starting character.
	 */
	if (vp->m_start.cno < vp->m_stop.cno)
		if (ISMOTION(vp)) {
			--vp->m_stop.cno;
			vp->m_final = vp->m_start;
		} else
			vp->m_final = vp->m_stop;
	else {
		if (ISMOTION(vp))
			--vp->m_start.cno;
		vp->m_final = vp->m_stop;
	}
	return (0);
}
Ejemplo n.º 5
0
/*
 * Compute the  earliest time  and position of  the intersection  of a
 * sphere and a vertex.
 *
 * The sphere has radius R and moves along vector V from point P.  The
 * vertex moves  along vector  W from point  Q in a  coordinate system
 * based at O.
 */
static float v_vert(float Q[3],
                    const float o[3],
                    const float q[3],
                    const float w[3],
                    const float p[3],
                    const float v[3], float r)
{
    float O[3], P[3], V[3];
    float t = LARGE;

    v_add(O, o, q);
    v_sub(P, p, O);
    v_sub(V, v, w);

    if (v_dot(P, V) < 0.0f)
    {
        t = v_sol(P, V, r);

        if (t < LARGE)
            v_mad(Q, O, w, t);
    }
    return t;
}
/*
 * v_zero -- 0
 *	Move to the first column on this line.
 *
 * PUBLIC: int v_zero __P((SCR *, VICMD *));
 */
int
v_zero(SCR *sp, VICMD *vp)
{
	/*
	 * !!!
	 * The 0 command succeeded if used as a command in the first column
	 * but failed if used as a motion component in the same situation.
	 */
	if (ISMOTION(vp) && vp->m_start.cno == 0) {
		v_sol(sp);
		return (1);
	}

	/*
	 * All commands move to the end of the range.  Motion commands
	 * adjust the starting point to the character before the current
	 * one.
	 */
	vp->m_stop.cno = 0;
	if (ISMOTION(vp))
		--vp->m_start.cno;
	vp->m_final = vp->m_stop;
	return (0);
}
Ejemplo n.º 7
0
/*
 * Compute the  earliest time  and position of  the intersection  of a
 * sphere and an edge.
 *
 * The sphere has radius R and moves along vector V from point P.  The
 * edge moves along vector W from point Q in a coordinate system based
 * at O.  The edge extends along the length of vector U.
 */
static float v_edge(float Q[3],
                    const float o[3],
                    const float q[3],
                    const float u[3],
                    const float w[3],
                    const float p[3],
                    const float v[3], float r)
{
    float d[3], e[3];
    float P[3], V[3];
    float du, eu, uu, s, t;

    v_sub(d, p, o);
    v_sub(d, d, q);
    v_sub(e, v, w);

    /*
     * Think projections.  Vectors D, extending from the edge vertex Q
     * to the sphere,  and E, the relative velocity  of sphere wrt the
     * edge, are  made orthogonal to  the edge vector U.   Division of
     * the  dot products  is required  to obtain  the  true projection
     * ratios since U does not have unit length.
     */

    du = v_dot(d, u);
    eu = v_dot(e, u);
    uu = v_dot(u, u);

    v_mad(P, d, u, -du / uu);

    /* First, test for intersection. */

    if (v_dot(P, P) < r * r)
    {
        /* The sphere already intersects the line of the edge. */

        if (du < 0 || du > uu)
        {
            /*
             * The sphere is behind the endpoints of the edge, and
             * can't hit the edge without hitting the vertices first.
             */
            return LARGE;
        }

        /* The sphere already intersects the edge. */

        if (v_dot(P, e) >= 0)
        {
            /* Moving apart. */
            return LARGE;
        }

        v_nrm(P, P);
        v_mad(Q, p, P, -r);

        return 0;
    }

    v_mad(V, e, u, -eu / uu);

    t = v_sol(P, V, r);
    s = (du + eu * t) / uu; /* Projection of D + E * t on U. */

    if (0.0f <= t && t < LARGE && 0.0f < s && s < 1.0f)
    {
        v_mad(d, o, w, t);
        v_mad(e, q, u, s);
        v_add(Q, e, d);
    }
    else
        t = LARGE;

    return t;
}