⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svi_smap.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		    !O_ISSET(sp, O_LEFTRIGHT) &&		    tmp.off > svi_opt_screens(sp, ep, tmp.lno, NULL)) {			v_eof(sp, ep, NULL);			return (1);		}	}	/*	 * Small screens: see svi/svi_refresh.c:svi_refresh, section 3b.	 *	 * If it's a small screen, and the movement is small, open up the	 * screen.  Otherwise, compress and repaint.  If we compress, we	 * ignore the cursor, the movement is too large to care.	 */	if (ISSMALLSCREEN(sp))		if (count <= HALFTEXT(sp)) {			for (; count && sp->t_rows != sp->t_maxrows;			     --count, ++sp->t_rows) {				if (svi_sm_next(sp, ep, TMAP, &tmp))					return (1);				if (TMAP->lno != tmp.lno &&				    !file_gline(sp, ep, tmp.lno, NULL))					break;				*++TMAP = tmp;				/* svi_sm_next() flushed the cache. */				if (svi_line(sp, ep, TMAP, NULL, NULL))					return (1);			}			if (count == 0)				return (0);		} else {			MOVE(sp, INFOLINE(sp), 0);			clrtoeol();			for (;			    sp->t_rows > sp->t_minrows; --sp->t_rows, --TMAP) {				MOVE(sp, TMAP - HMAP, 0);				clrtoeol();			}			ignore_cursor = 1;		}	for (; count; --count) {		/* Decide what would show up on the screen. */		if (svi_sm_next(sp, ep, TMAP, &tmp))			return (1);		/* If the line doesn't exist, we're done. */		if (TMAP->lno != tmp.lno && !file_gline(sp, ep, tmp.lno, NULL))			break;		/* Scroll the screen cursor up one logical line. */		if (svi_sm_1up(sp, ep))			return (1);		if (!cursor_move && !ignore_cursor && p > HMAP)			--p;	}	/* If ignoring the cursor, we're done. */	if (ignore_cursor)		return (0);	if (cursor_move) {		/*		 * If we didn't move enough, head toward EOF.  Check to make		 * sure the lines actually, if the file is smaller than the		 * screen they may not.		 */		for (; count; --count, ++p)			if (p == TMAP || !file_gline(sp, ep, p[1].lno, NULL))				break;	} else {		/*		 * If the line itself moved, invalidate the cursor, because		 * the comparison with the old line/new line won't be right		 */		F_SET(SVP(sp), SVI_CUR_INVALID);		/* If didn't move enough, it's an error. */		if (count) {			v_eof(sp, ep, NULL);			return (1);		}		/* If the cursor moved off the screen, move it to the top. */		if (sp->lno < HMAP->lno)			p = HMAP;	}	/*	 * On a logical movement, we try and keep the cursor as close as	 * possible to the last position, but also set it up so that the	 * next "real" movement will return the cursor to the closest position	 * to the last real movement.	 */	if (p->lno != svmap.lno || p->off != svmap.off) {		rp->lno = p->lno;		rp->cno = svi_cm_private(sp, ep, p->lno, p->off, sp->rcm);	}	return (0);}/* * svi_sm_1up -- *	Scroll the SMAP up one. */intsvi_sm_1up(sp, ep)	SCR *sp;	EXF *ep;{	/*	 * Delete the top line of the screen.  Shift the screen map up.	 * Display a new line at the bottom of the screen.	 */	MOVE(sp, 0, 0);	if (svi_deleteln(sp, 1))		return (1);	/* One-line screens can fail. */	if (HMAP == TMAP) {		if (svi_sm_next(sp, ep, TMAP, TMAP))			return (1);	} else {		memmove(HMAP, HMAP + 1, (sp->rows - 1) * sizeof(SMAP));		if (svi_sm_next(sp, ep, TMAP - 1, TMAP))			return (1);	}	/* svi_sm_next() flushed the cache. */	if (svi_line(sp, ep, TMAP, NULL, NULL))		return (1);	return (0);}/* * svi_deleteln -- *	Delete a line a la curses, make sure to put the information *	line and other screens back. */static intsvi_deleteln(sp, cnt)	SCR *sp;	int cnt;{	size_t oldy, oldx;	getyx(stdscr, oldy, oldx);	while (cnt--) {		deleteln();		MOVE(sp, INFOLINE(sp) - 1, 0);		insertln();		MOVEA(sp, oldy, oldx);	}	return (0);}/* * svi_sm_down -- *	Scroll the SMAP down count logical lines. */intsvi_sm_down(sp, ep, rp, count, cursor_move)	SCR *sp;	EXF *ep;	MARK *rp;	recno_t count;	int cursor_move;{	SMAP *p, svmap;	int ignore_cursor;	/* Set the default return position. */	rp->lno = sp->lno;	rp->cno = sp->cno;	/*	 * Invalidate the cursor.  The line is probably going to change,	 * but if cursor_move isn't set it may not.  In any case, this	 * routine moves the cursor to draw things.	 */	F_SET(SVP(sp), SVI_CUR_INVALID);	/*	 * There are two forms of this command, one where the cursor tries to	 * follow the line, and one where it doesn't.  In the latter, we try	 * and keep the cursor at the same position on the screen, but, if the	 * screen is small enough and the line length large enough, the cursor	 * can end up in very strange places.  Probably not worth fixing.	 *	 * Find the line in the SMAP -- ignore the cursor if it wasn't on the	 * screen.	 */	if (svi_sm_cursor(sp, ep, &p))		return (1);	if (p == NULL)		ignore_cursor = 1;	else {		svmap = *p;		ignore_cursor = 0;	}	/* Check to see if movement is possible. */	if (HMAP->lno == 1 && HMAP->off == 1 &&	    (!cursor_move || ignore_cursor || p == HMAP)) {		v_sof(sp, NULL);		return (1);	}	/*	 * Small screens: see svi/svi_refresh.c:svi_refresh, section 3b.	 *	 * If it's a small screen, and the movement is small, open up the	 * screen.  Otherwise, compress and repaint.  If we compress, we	 * ignore the cursor, the movement is too large to care.	 */	if (ISSMALLSCREEN(sp))		if (count <= HALFTEXT(sp)) {			for (; count && sp->t_rows != sp->t_maxrows &&			    (HMAP->lno > 1 || HMAP->off > 1);			    --count, ++sp->t_rows) {				++TMAP;				if (svi_sm_1down(sp, ep))					return (1);				if (!cursor_move)					++p;			}			if (count == 0)				return (0);		} else {			MOVE(sp, INFOLINE(sp), 0);			clrtoeol();			for (;			    sp->t_rows > sp->t_minrows; --sp->t_rows, --TMAP) {				MOVE(sp, TMAP - HMAP, 0);				clrtoeol();			}			ignore_cursor = 1;		}	for (; count; --count) {		/* If the line doesn't exist, we're done. */		if (HMAP->lno == 1 && HMAP->off == 1)			break;		/* Scroll the screen and cursor down one logical line. */		if (svi_sm_1down(sp, ep))			return (1);		if (!cursor_move && !ignore_cursor && p < TMAP)			++p;	}	/* If ignoring the cursor, we're done. */	if (ignore_cursor)		return (0);	if (cursor_move) {		/* If we didn't move enough, move to SOF. */		if (count)			p = HMAP;	} else {		/*		 * If the line itself moved, invalidate the cursor, because		 * the comparison with the old line/new line won't be right.		 */		F_SET(SVP(sp), SVI_CUR_INVALID);		/* If didn't move enough, it's an error. */		if (count) {			v_sof(sp, NULL);			return (1);		}		/* If the cursor moved off the screen, move it to the bottom. */		if (sp->lno > TMAP->lno)			p = TMAP;	}	/*	 * On a logical movement, we try and keep the cursor as close as	 * possible to the last position, but also set it up so that the	 * next "real" movement will return the cursor to the closest position	 * to the last real movement.	 */	if (p->lno != svmap.lno || p->off != svmap.off) {		rp->lno = p->lno;		rp->cno = svi_cm_private(sp, ep, p->lno, p->off, sp->rcm);	}	return (0);}/* * svi_sm_1down -- *	Scroll the SMAP down one. */intsvi_sm_1down(sp, ep)	SCR *sp;	EXF *ep;{	/*	 * Clear the bottom line of the screen, insert a line at the top	 * of the screen.  Shift the screen map down, display a new line	 * at the top of the screen.	 */	MOVE(sp, sp->t_rows, 0);	clrtoeol();	MOVE(sp, 0, 0);	if (svi_insertln(sp, 1))		return (1);	memmove(HMAP + 1, HMAP, (sp->rows - 1) * sizeof(SMAP));	if (svi_sm_prev(sp, ep, HMAP + 1, HMAP))		return (1);	/* svi_sm_prev() flushed the cache. */	if (svi_line(sp, ep, HMAP, NULL, NULL))		return (1);	return (0);}/* * svi_insertln -- *	Insert a line a la curses, make sure to put the information *	line and other screens back. */static intsvi_insertln(sp, cnt)	SCR *sp;	int cnt;{	size_t oldy, oldx;	getyx(stdscr, oldy, oldx);	while (cnt--) {		MOVE(sp, INFOLINE(sp) - 1, 0);		deleteln();		MOVEA(sp, oldy, oldx);		insertln();	}	return (0);}/* * svi_sm_next -- *	Fill in the next entry in the SMAP. */intsvi_sm_next(sp, ep, p, t)	SCR *sp;	EXF *ep;	SMAP *p, *t;{	size_t lcnt;	SMAP_FLUSH(t);	if (O_ISSET(sp, O_LEFTRIGHT)) {		t->lno = p->lno + 1;		t->off = p->off;	} else {		lcnt = svi_opt_screens(sp, ep, p->lno, NULL);		if (lcnt == p->off) {			t->lno = p->lno + 1;			t->off = 1;		} else {			t->lno = p->lno;			t->off = p->off + 1;		}	}	return (0);}/* * svi_sm_prev -- *	Fill in the previous entry in the SMAP. */intsvi_sm_prev(sp, ep, p, t)	SCR *sp;	EXF *ep;	SMAP *p, *t;{	SMAP_FLUSH(t);	if (O_ISSET(sp, O_LEFTRIGHT)) {		t->lno = p->lno - 1;		t->off = p->off;	} else if (p->off != 1) {		t->lno = p->lno;		t->off = p->off - 1;	} else {		t->lno = p->lno - 1;		t->off = svi_opt_screens(sp, ep, t->lno, NULL);	}	return (t->lno == 0);}/* * svi_sm_cursor -- *	Return the SMAP entry referenced by the cursor. */intsvi_sm_cursor(sp, ep, smp)	SCR *sp;	EXF *ep;	SMAP **smp;{	SMAP *p;	/* See if the cursor is not in the map. */	if (sp->lno < HMAP->lno || sp->lno > TMAP->lno) {		*smp = NULL;		return (0);	}	/* Find the first occurence of the line. */	for (p = HMAP; p->lno != sp->lno; ++p);	/* Fill in the map information until we find the right line. */	for (; p <= TMAP; ++p) {		/* Short lines are common and easy to detect. */		if (p != TMAP && (p + 1)->lno != p->lno) {			*smp = p;			return (0);		}		if (!SMAP_CACHE(p) && svi_line(sp, ep, p, NULL, NULL))			return (1);		if (p->c_eboff >= sp->cno) {			*smp = p;			return (0);		}	}	/* It was past the end of the map after all. */	*smp = NULL;	return (0);}/* * svi_sm_position -- *	Return the line/column of the top, middle or last line on the screen. *	(The vi H, M and L commands.)  Here because only the screen routines *	know what's really out there. */intsvi_sm_position(sp, ep, rp, cnt, pos)	SCR *sp;	EXF *ep;	MARK *rp;	u_long cnt;	enum position pos;{	SMAP *smp;	recno_t last;	switch (pos) {	case P_TOP:		/*		 * !!!		 * Historically, an invalid count to the H command failed.		 * We do nothing special here, just making sure that H in		 * an empty screen works.		 */		if (cnt > TMAP - HMAP)			goto sof;		smp = HMAP + cnt;		if (cnt && file_gline(sp, ep, smp->lno, NULL) == NULL) {sof:			msgq(sp, M_BERR, "Movement past the end-of-screen.");			return (1);		}		break;	case P_MIDDLE:		/*		 * !!!		 * Historically, a count to the M command was ignored.		 * If the screen isn't filled, find the middle of what's		 * real and move there.		 */		if (file_gline(sp, ep, TMAP->lno, NULL) == NULL) {			if (file_lline(sp, ep, &last))				return (1);			for (smp = TMAP; smp->lno > last && smp > HMAP; --smp);			if (smp > HMAP)				smp -= (smp - HMAP) / 2;		} else			smp = (HMAP + (TMAP - HMAP) / 2) + cnt;		break;	case P_BOTTOM:		/*		 * !!!		 * Historically, an invalid count to the L command failed.		 * If the screen isn't filled, find the bottom of what's		 * real and try to offset from there.		 */		if (cnt > TMAP - HMAP)			goto eof;		smp = TMAP - cnt;		if (file_gline(sp, ep, smp->lno, NULL) == NULL) {			if (file_lline(sp, ep, &last))				return (1);			for (; smp->lno > last && smp > HMAP; --smp);			if (cnt > smp - HMAP) {eof:				msgq(sp, M_BERR,				    "Movement past the beginning-of-screen.");				return (1);			}			smp -= cnt;		}		break;	default:		abort();	}	/* Make sure that the cached information is valid. */	if (!SMAP_CACHE(smp) && svi_line(sp, ep, smp, NULL, NULL))		return (1);	rp->lno = smp->lno;	rp->cno = smp->c_sboff;	return (0);}/* * svi_sm_nlines -- *	Return the number of screen lines from an SMAP entry to the *	start of some file line, less than a maximum value. */recno_tsvi_sm_nlines(sp, ep, from_sp, to_lno, max)	SCR *sp;	EXF *ep;	SMAP *from_sp;	recno_t to_lno;	size_t max;{	recno_t lno, lcnt;	if (O_ISSET(sp, O_LEFTRIGHT))		return (from_sp->lno > to_lno ?		    from_sp->lno - to_lno : to_lno - from_sp->lno);	if (from_sp->lno == to_lno)		return (from_sp->off - 1);	if (from_sp->lno > to_lno) {		lcnt = from_sp->off - 1;	/* Correct for off-by-one. */		for (lno = from_sp->lno; --lno >= to_lno && lcnt <= max;)			lcnt += svi_opt_screens(sp, ep, lno, NULL);	} else {		lno = from_sp->lno;		lcnt = (svi_opt_screens(sp, ep, lno, NULL) - from_sp->off) + 1;		for (; ++lno < to_lno && lcnt <= max;)			lcnt += svi_opt_screens(sp, ep, lno, NULL);	}	return (lcnt);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -