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

📄 v_ntext.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	for (lno = tiqh->cqh_first->lno;	    file_gline(sp, ep, lno, &len) == NULL && lno > 0; --lno);	sp->lno = lno == 0 ? 1 : lno;	sp->cno = 0;	/* Redraw the screen, just in case. */	F_SET(sp, S_REDRAW);}/* * txt_hex -- *	Let the user insert any character value they want. * * !!! * This is an extension.  The pattern "^Vx[0-9a-fA-F]*" is a way * for the user to specify a character value which their keyboard * may not be able to enter. */static inttxt_hex(sp, tp)	SCR *sp;	TEXT *tp;{	CHAR_T savec;	size_t len, off;	u_long value;	char *p, *wp;	/*	 * Null-terminate the string.  Since nul isn't a legal hex value,	 * this should be okay, and lets us use a local routine, which	 * presumably understands the character set, to convert the value.	 */	savec = tp->lb[sp->cno];	tp->lb[sp->cno] = 0;	/* Find the previous CH_HEX character. */	for (off = sp->cno - 1, p = tp->lb + off, len = 0;; --p, --off, ++len) {		if (*p == CH_HEX) {			wp = p + 1;			break;		}		/* Not on this line?  Shouldn't happen. */		if (off == tp->ai || off == tp->offset)			goto nothex;	}	/* If length of 0, then it wasn't a hex value. */	if (len == 0)		goto nothex;	/* Get the value. */	errno = 0;	value = strtol(wp, NULL, 16);	if (errno || value > MAX_CHAR_T) {nothex:		tp->lb[sp->cno] = savec;		return (0);	}	/* Restore the original character. */	tp->lb[sp->cno] = savec;	/* Adjust the bookkeeping. */	sp->cno -= len;	tp->len -= len;	tp->lb[sp->cno - 1] = value;	/* Copy down any overwrite characters. */	if (tp->owrite)		memmove(tp->lb + sp->cno,		    tp->lb + sp->cno + len, tp->owrite);	/* Copy down any insert characters. */	if (tp->insert)		memmove(tp->lb + sp->cno + tp->owrite,		    tp->lb + sp->cno + tp->owrite + len, tp->insert);	return (0);}/* * Txt_indent and txt_outdent are truly strange.  ^T and ^D do movements * to the next or previous shiftwidth value, i.e. for a 1-based numbering, * with shiftwidth=3, ^T moves a cursor on the 7th, 8th or 9th column to * the 10th column, and ^D moves it back. * * !!! * The ^T and ^D characters in historical vi only had special meaning when * they were the first characters typed after entering text input mode. * Since normal erase characters couldn't erase autoindent (in this case * ^T) characters, this meant that inserting text into previously existing * text was quite strange, ^T only worked if it was the first keystroke, * and then it could only be erased by using ^D.  This implementation treats * ^T specially anywhere it occurs in the input, and permits the standard * erase characters to erase characters inserted using it. * * XXX * Technically, txt_indent, txt_outdent should part of the screen interface, * as they require knowledge of the size of a space character on the screen. * (Not the size of tabs, because tabs are logically composed of spaces.) * They're left in the text code  because they're complicated, not to mention * the gruesome awareness that if spaces aren't a single column on the screen * for any language, we're into some serious, ah, for lack of a better word, * "issues". *//* * txt_indent -- *	Handle ^T indents. */static inttxt_indent(sp, tp)	SCR *sp;	TEXT *tp;{	u_long sw, ts;	size_t cno, off, scno, spaces, tabs;	ts = O_VAL(sp, O_TABSTOP);	sw = O_VAL(sp, O_SHIFTWIDTH);	/* Get the current screen column. */	for (off = scno = 0; off < sp->cno; ++off)		if (tp->lb[off] == '\t')			scno += STOP_OFF(scno, ts);		else			++scno;	/* Count up spaces/tabs needed to get to the target. */	for (cno = scno, scno += STOP_OFF(scno, sw), tabs = 0;	    cno + STOP_OFF(cno, ts) <= scno; ++tabs)		cno += STOP_OFF(cno, ts);	spaces = scno - cno;	/* Put space/tab characters in place of any overwrite characters. */	for (; tp->owrite && tabs; --tp->owrite, --tabs, ++tp->ai)		tp->lb[sp->cno++] = '\t';	for (; tp->owrite && spaces; --tp->owrite, --spaces, ++tp->ai)		tp->lb[sp->cno++] = ' ';	if (!tabs && !spaces)		return (0);	/* Make sure there's enough room. */	BINC_RET(sp, tp->lb, tp->lb_len, tp->len + spaces + tabs);	/* Move the insert characters out of the way. */	if (tp->insert)		memmove(tp->lb + sp->cno + spaces + tabs,		    tp->lb + sp->cno, tp->insert);	/* Add new space/tab characters. */	for (; tabs--; ++tp->len, ++tp->ai)		tp->lb[sp->cno++] = '\t';	for (; spaces--; ++tp->len, ++tp->ai)		tp->lb[sp->cno++] = ' ';	return (0);}/* * txt_outdent -- *	Handle ^D outdents. * */static inttxt_outdent(sp, tp)	SCR *sp;	TEXT *tp;{	u_long sw, ts;	size_t cno, off, scno, spaces;	ts = O_VAL(sp, O_TABSTOP);	sw = O_VAL(sp, O_SHIFTWIDTH);	/* Get the current screen column. */	for (off = scno = 0; off < sp->cno; ++off)		if (tp->lb[off] == '\t')			scno += STOP_OFF(scno, ts);		else			++scno;	/* Get the previous shiftwidth column. */	for (cno = scno; --scno % sw != 0;);	/* Decrement characters until less than or equal to that slot. */	for (; cno > scno; --sp->cno, --tp->ai, ++tp->owrite)		if (tp->lb[--off] == '\t')			cno -= STOP_OFF(cno, ts);		else			--cno;	/* Spaces needed to get to the target. */	spaces = scno - cno;	/* Maybe just a delete. */	if (spaces == 0)		return (0);	/* Make sure there's enough room. */	BINC_RET(sp, tp->lb, tp->lb_len, tp->len + spaces);	/* Use up any overwrite characters. */	for (; tp->owrite && spaces; --spaces, ++tp->ai, --tp->owrite)		tp->lb[sp->cno++] = ' ';	/* Maybe that was enough. */	if (spaces == 0)		return (0);	/* Move the insert characters out of the way. */	if (tp->insert)		memmove(tp->lb + sp->cno + spaces,		    tp->lb + sp->cno, tp->insert);	/* Add new space characters. */	for (; spaces--; ++tp->len, ++tp->ai)		tp->lb[sp->cno++] = ' ';	return (0);}/* * txt_resolve -- *	Resolve the input text chain into the file. */static inttxt_resolve(sp, ep, tiqh, flags)	SCR *sp;	EXF *ep;	TEXTH *tiqh;	u_int flags;{	TEXT *tp;	recno_t lno;	/*	 * The first line replaces a current line, and all subsequent lines	 * are appended into the file.  Resolve autoindented characters for	 * each line before committing it.	 */	tp = tiqh->cqh_first;	if (LF_ISSET(TXT_AUTOINDENT))		txt_ai_resolve(sp, tp);	if (file_sline(sp, ep, tp->lno, tp->lb, tp->len))		return (1);	for (lno = tp->lno; (tp = tp->q.cqe_next) != (void *)sp->tiqp; ++lno) {		if (LF_ISSET(TXT_AUTOINDENT))			txt_ai_resolve(sp, tp);		if (file_aline(sp, ep, 0, lno, tp->lb, tp->len))			return (1);	}	return (0);}/* * txt_showmatch -- *	Show a character match. * * !!! * Historic vi tried to display matches even in the :colon command line. * I think not. */static voidtxt_showmatch(sp, ep)	SCR *sp;	EXF *ep;{	struct timeval second;	VCS cs;	MARK m;	fd_set zero;	int cnt, endc, startc;	/*	 * Do a refresh first, in case the v_ntext() code hasn't done	 * one in awhile, so the user can see what we're complaining	 * about.	 */	if (sp->s_refresh(sp, ep))		return;	/*	 * We don't display the match if it's not on the screen.  Find	 * out what the first character on the screen is.	 */	if (sp->s_position(sp, ep, &m, 0, P_TOP))		return;	/* Initialize the getc() interface. */	cs.cs_lno = sp->lno;	cs.cs_cno = sp->cno - 1;	if (cs_init(sp, ep, &cs))		return;	startc = (endc = cs.cs_ch)  == ')' ? '(' : '{';	/* Search for the match. */	for (cnt = 1;;) {		if (cs_prev(sp, ep, &cs))			return;		if (cs.cs_lno < m.lno ||		    cs.cs_lno == m.lno && cs.cs_cno < m.cno)			return;		if (cs.cs_flags != 0) {			if (cs.cs_flags == CS_EOF || cs.cs_flags == CS_SOF) {				(void)sp->s_bell(sp);				return;			}			continue;		}		if (cs.cs_ch == endc)			++cnt;		else if (cs.cs_ch == startc && --cnt == 0)			break;	}	/* Move to the match. */	m.lno = sp->lno;	m.cno = sp->cno;	sp->lno = cs.cs_lno;	sp->cno = cs.cs_cno;	(void)sp->s_refresh(sp, ep);	/*	 * Sleep(3) is eight system calls.  Do it fast -- besides,	 * I don't want to wait an entire second.	 */	FD_ZERO(&zero);	second.tv_sec = O_VAL(sp, O_MATCHTIME) / 10;	second.tv_usec = (O_VAL(sp, O_MATCHTIME) % 10) * 100000L;	(void)select(0, &zero, &zero, &zero, &second);	/* Return to the current location. */	sp->lno = m.lno;	sp->cno = m.cno;	(void)sp->s_refresh(sp, ep);}/* * txt_margin -- *	Handle margin wrap. * * !!! * Historic vi belled the user each time a character was entered after * crossing the margin until a space was entered which could be used to * break the line.  I don't, it tends to wake the cats. */static inttxt_margin(sp, tp, didbreak, pushcp)	SCR *sp;	TEXT *tp;	int *didbreak;	CHAR_T *pushcp;{	CHAR_T ch;	size_t len, off, tlen;	char *p, *wp;	/* Find the closest previous blank. */	for (off = sp->cno - 1, p = tp->lb + off, len = 0;; --p, --off) {		if (isblank(*p)) {			wp = p + 1;			break;		}		++len;		/* If it's the beginning of the line, there's nothing to do. */		if (off == tp->ai || off == tp->offset) {			*didbreak = 0;			return (0);		}	}	/*	 * Historic practice is to delete any trailing whitespace	 * from the previous line.	 */	for (tlen = len;; --p, --off) {		if (!isblank(*p))			break;		++tlen;		if (off == tp->ai || off == tp->offset)			break;	}	ch = *pushcp;	if (term_push(sp, &ch, 1, 0, CH_NOMAP))		return (1);	if (len && term_push(sp, wp, len, 0, CH_NOMAP | CH_QUOTED))		return (1);	ch = '\n';	if (term_push(sp, &ch, 1, 0, CH_NOMAP))		return (1);	sp->cno -= tlen;	tp->owrite += tlen;	*didbreak = 1;	return (0);}/* * txt_Rcleanup -- *	Resolve the input line for the 'R' command. */static voidtxt_Rcleanup(sp, tiqh, tp, lp, olen)	SCR *sp;	TEXTH *tiqh;	TEXT *tp;	const char *lp;	const size_t olen;{	TEXT *ttp;	size_t ilen, tmp;	/*	 * Check to make sure that the cursor hasn't moved beyond	 * the end of the line.	 */	if (tp->owrite == 0)		return;	/*	 * Calculate how many characters the user has entered,	 * plus the blanks erased by <carriage-return>/<newline>s.	 */	for (ttp = tiqh->cqh_first, ilen = 0;;) {		ilen += ttp == tp ? sp->cno : ttp->len + ttp->R_erase;		if ((ttp = ttp->q.cqe_next) == (void *)sp->tiqp)			break;	}	/*	 * If the user has entered less characters than the original line	 * was long, restore any overwriteable characters to the original	 * characters, and make them insert characters.  We don't copy them	 * anywhere, because the 'R' command doesn't have insert characters.	 */	if (ilen < olen) {		tmp = MIN(tp->owrite, olen - ilen);		memmove(tp->lb + sp->cno, lp + ilen, tmp);		tp->owrite -= tmp;		tp->insert += tmp;	}}

⌨️ 快捷键说明

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