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

📄 svi_refresh.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	 *	 * XXX	 * With some work, it should be possible to handle tabs quickly, at	 * least in obvious situations, like moving right and encountering	 * a tab, without reparsing the whole line.	 */	/* If the line we're working with has changed, reparse. */	if (F_ISSET(SVP(sp), SVI_CUR_INVALID) || LNO != OLNO) {		F_CLR(SVP(sp), SVI_CUR_INVALID);		goto slow;	}	/* Otherwise, if nothing's changed, go fast. */	if (CNO == OCNO)		goto fast;	/*	 * Get the current line.  If this fails, we either have an empty	 * file and can just repaint, or there's a real problem.  This	 * isn't a performance issue because there aren't any ways to get	 * here repeatedly.	 */	if ((p = file_gline(sp, ep, LNO, &len)) == NULL) {		if (file_lline(sp, ep, &lastline))			return (1);		if (lastline == 0)			goto slow;		GETLINE_ERR(sp, LNO);		return (1);	}#ifdef DEBUG	/* This is just a test. */	if (CNO >= len && len != 0) {		msgq(sp, M_ERR, "Error: %s/%d: cno (%u) >= len (%u)",		     tail(__FILE__), __LINE__, CNO, len);		return (1);	}#endif	/*	 * The basic scheme here is to look at the characters in between	 * the old and new positions and decide how big they are on the	 * screen, and therefore, how many screen positions to move.	 */	if (CNO < OCNO) {		/*		 * 4a: Cursor moved left.		 *		 * Point to the old character.  The old cursor position can		 * be past EOL if, for example, we just deleted the rest of		 * the line.  In this case, since we don't know the width of		 * the characters we traversed, we have to do it slowly.		 */		p += OCNO;		cnt = (OCNO - CNO) + 1;		if (OCNO >= len)			goto slow;		/*		 * Quick sanity check -- it's hard to figure out exactly when		 * we cross a screen boundary as we do in the cursor right		 * movement.  If cnt is so large that we're going to cross the		 * boundary no matter what, stop now.		 */		if (SCNO + 1 + MAX_CHARACTER_COLUMNS < cnt)			goto lscreen;		/*		 * Count up the widths of the characters.  If it's a tab		 * character, go do it the the slow way.		 */		for (cwtotal = 0; cnt--; cwtotal += KEY_LEN(sp, ch))			if ((ch = *(u_char *)p--) == '\t')				goto slow;		/*		 * Decrement the screen cursor by the total width of the		 * characters minus 1.		 */		cwtotal -= 1;		/*		 * If we're moving left, and there's a wide character in the		 * current position, go to the end of the character.		 */		if (KEY_LEN(sp, ch) > 1)			cwtotal -= KEY_LEN(sp, ch) - 1;		/*		 * If the new column moved us off of the current logical line,		 * calculate a new one.  If doing leftright scrolling, we've		 * moved off of the current screen, as well.  Since most files		 * don't have more than two screens, we optimize moving from		 * screen 2 to screen 1.		 */		if (SCNO < cwtotal) {lscreen:		if (O_ISSET(sp, O_LEFTRIGHT)) {				cnt = HMAP->off == 2 ? 1 :				    svi_opt_screens(sp, ep, LNO, &CNO);				for (smp = HMAP; smp <= TMAP; ++smp)					smp->off = cnt;				leftright_warp = 1;				goto paint;			}			goto slow;		}		SCNO -= cwtotal;	} else {		/*		 * 4b: Cursor moved right.		 *		 * Point to the first character to the right.		 */		p += OCNO + 1;		cnt = CNO - OCNO;		/*		 * Count up the widths of the characters.  If it's a tab		 * character, go do it the the slow way.  If we cross a		 * screen boundary, we can quit.		 */		for (cwtotal = SCNO; cnt--;) {			if ((ch = *(u_char *)p++) == '\t')				goto slow;			if ((cwtotal += KEY_LEN(sp, ch)) >= SCREEN_COLS(sp))				break;		}		/*		 * Increment the screen cursor by the total width of the		 * characters.		 */		SCNO = cwtotal;		/* See screen change comment in section 4a. */		if (SCNO >= SCREEN_COLS(sp)) {			if (O_ISSET(sp, O_LEFTRIGHT)) {				cnt = svi_opt_screens(sp, ep, LNO, &CNO);				for (smp = HMAP; smp <= TMAP; ++smp)					smp->off = cnt;				leftright_warp = 1;				goto paint;			}			goto slow;		}	}	/*	 * 4c: Fast cursor update.	 *	 * Retrieve the current cursor position, and correct it	 * for split screens.	 */fast:	getyx(stdscr, y, x);	y -= sp->woff;	goto number;	/*	 * 4d: Slow cursor update.	 *	 * Walk through the map and find the current line.  If doing left-right	 * scrolling and the cursor movement has changed the screen displayed,	 * scroll the screen left or right, unless we're updating the info line	 * in which case we just scroll that one line.  Then update the screen	 * lines for this file line until we have a new screen cursor position.	 */slow:	for (smp = HMAP; smp->lno != LNO; ++smp);	if (O_ISSET(sp, O_LEFTRIGHT)) {		cnt = svi_opt_screens(sp, ep, LNO, &CNO) % SCREEN_COLS(sp);		if (cnt != HMAP->off) {			if (ISINFOLINE(sp, smp))				smp->off = cnt;			else {				for (smp = HMAP; smp <= TMAP; ++smp)					smp->off = cnt;				leftright_warp = 1;			}			goto paint;		}	}	for (y = -1; smp <= TMAP && smp->lno == LNO; ++smp) {		if (svi_line(sp, ep, smp, &y, &SCNO))			return (1);		if (y != -1)			break;	}	goto number;	/*	 * 5: Repaint the entire screen.	 *	 * Lost big, do what you have to do.  We flush the cache as S_REDRAW	 * gets set when the screen isn't worth fixing, and it's simpler to	 * repaint.  So, don't trust anything that we think we know about it.	 */paint:	for (smp = HMAP; smp <= TMAP; ++smp)		SMAP_FLUSH(smp);	for (smp = HMAP; smp <= TMAP; ++smp)		if (svi_line(sp, ep, smp, &y, &SCNO))			return (1);	/*	 * If it's a small screen and we're redrawing, clear the unused lines,	 * ex may have overwritten them.	 */	if (F_ISSET(sp, S_REDRAW)) {		if (ISSMALLSCREEN(sp))			for (cnt = sp->t_rows; cnt <= sp->t_maxrows; ++cnt) {				MOVE(sp, cnt, 0);				clrtoeol();			}		F_CLR(sp, S_REDRAW);	}	didpaint = 1;	/*	 * 6: Repaint the line numbers.	 *	 * If O_NUMBER is set and the S_RENUMBER bit is set, and we didn't	 * repaint the screen, repaint all of the line numbers, they've	 * changed.	 */number:	if (O_ISSET(sp, O_NUMBER) && F_ISSET(sp, S_RENUMBER) && !didpaint) {		if (svi_number(sp, ep))			return (1);		F_CLR(sp, S_RENUMBER);	}	/*	 * 7: Refresh the screen.	 *	 * If the screen was corrupted, refresh it.	 */	if (F_ISSET(sp, S_REFRESH)) {		wrefresh(curscr);		F_CLR(sp, S_REFRESH);	}	if (F_ISSET(sp, S_BELLSCHED))		svi_bell(sp);	/*	 * If the bottom line isn't in use by the colon command:	 *	 *	Display any messages.  Don't test S_UPDATE_MODE.  The	 *	message printing routine set it to avoid anyone else	 *	destroying the message we're about to display.	 *	 *	If the bottom line isn't in use by anyone, put out the	 *	standard status line.	 */	if (!F_ISSET(SVP(sp), SVI_INFOLINE))		if (sp->msgq.lh_first != NULL &&		    !F_ISSET(sp->msgq.lh_first, M_EMPTY))			svi_msgflush(sp);		else if (!F_ISSET(sp, S_UPDATE_MODE))			svi_modeline(sp, ep);	/* Update saved information. */	OCNO = CNO;	OLNO = LNO;	/* Place the cursor. */	MOVE(sp, y, SCNO);	/* Flush it all out. */	refresh();	/*	 * XXX	 * Recalculate the "most favorite" cursor position.  Vi doesn't know	 * that we've warped the screen and it's going to have a completely	 * wrong idea about where the cursor should be.  This is vi's problem,	 * and fixing it here is a gross violation of layering.	 */	if (leftright_warp)		(void)svi_column(sp, ep, &sp->rcm);	return (0);}/* * svi_msgflush -- *	Flush any accumulated messages. */static intsvi_msgflush(sp)	SCR *sp;{	CH ikey;	CHAR_T ch;	MSG *mp;	size_t chlen, len;	char *p;#define	MCONTMSG	" [More ...]"	/* Display the messages. */	for (mp = sp->msgq.lh_first, p = NULL;	    mp != NULL && !F_ISSET(mp, M_EMPTY); mp = mp->q.le_next) {		p = mp->mbuf;lcont:		/* Move to the message line and clear it. */		MOVE(sp, INFOLINE(sp), 0);		clrtoeol();		/*		 * Turn on standout mode if requested, or, if we've split		 * the screen and need a divider.		 */		if (F_ISSET(mp, M_INV_VIDEO) ||		    sp->q.cqe_next != (void *)&sp->gp->dq)			standout();		/*		 * Print up to the "more" message.  Avoid the last character		 * in the last line, some hardware doesn't like it.		 */		if (svi_screens(sp, sp->ep, p, mp->len, 0, NULL) < sp->cols - 1)			len = sp->cols - 1;		else			len = (sp->cols - sizeof(MCONTMSG)) - 1;		for (;; ++p) {			if (!mp->len)				break;			ch = *(u_char *)p;			chlen = KEY_LEN(sp, ch);			if (chlen >= len)				break;			len -= chlen;			--mp->len;			ADDNSTR(KEY_NAME(sp, ch), chlen);		}		/*		 * If more, print continue message.  If user key fails,		 * keep showing the messages anyway.		 */		if (mp->len || (mp->q.le_next != NULL &&		    !F_ISSET(mp->q.le_next, M_EMPTY))) {			ADDNSTR(MCONTMSG, sizeof(MCONTMSG) - 1);			refresh();			for (;;) {				if (term_user_key(sp, &ikey) != INP_OK)					break;				if (ikey.value == K_CR ||				    ikey.value == K_NL || ikey.ch == ' ')					break;				svi_bell(sp);			}		}		/* Turn off standout mode. */		if (F_ISSET(mp, M_INV_VIDEO) ||		    sp->q.cqe_next != (void *)&sp->gp->dq)			standend();		if (mp->len)			goto lcont;		refresh();		F_SET(mp, M_EMPTY);	}	return (0);}#define	RULERSIZE	15#define	MODESIZE	(RULERSIZE + 15)/* * svi_modeline -- *	Update the mode line. */static intsvi_modeline(sp, ep)	SCR *sp;	EXF *ep;{	char *s, buf[RULERSIZE];	MOVE(sp, INFOLINE(sp), 0);	clrtoeol();	/* Display a dividing line if not the bottom screen. */	if (sp->q.cqe_next != (void *)&sp->gp->dq)		svi_divider(sp);	/* Display the ruler. */	if (O_ISSET(sp, O_RULER) && sp->cols > RULERSIZE + 2) {		MOVE(sp, INFOLINE(sp), sp->cols / 2 - RULERSIZE / 2);		clrtoeol();		(void)snprintf(buf,		    sizeof(buf), "%lu,%lu", sp->lno, sp->cno + 1);		ADDSTR(buf);	}	/* Show the modified bit. */	if (O_ISSET(sp, O_SHOWDIRTY) &&	    F_ISSET(ep, F_MODIFIED) && sp->cols > MODESIZE) {		MOVE(sp, INFOLINE(sp), sp->cols - 9);		ADDSTR("*");	}	/*	 * Show the mode.  Leave the last character blank, in case it's a	 * really dumb terminal with hardware scroll.  Second, don't try	 * to *paint* the last character, SunOS 4.1.1 and Ultrix 4.2 curses	 * won't let you paint the last character in the screen.	 */	if (O_ISSET(sp, O_SHOWMODE) && sp->cols > MODESIZE) {		MOVE(sp, INFOLINE(sp), sp->cols - 8);		s = F_ISSET(sp, S_INPUT) ? "  Input" : "Command";		ADDSTR(s);	}	return (0);}/* * svi_divider -- *	Draw a dividing line between the screens. */intsvi_divider(sp)	SCR *sp;{	size_t len;#define	DIVIDESTR	"+=+=+=+=+=+=+=+"	len = sizeof(DIVIDESTR) - 1 > sp->cols ?	    sp->cols : sizeof(DIVIDESTR) - 1;	ADDNSTR(DIVIDESTR, len);	return (0);}

⌨️ 快捷键说明

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