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

📄 v_ntext.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			/* Update the old line. */			if (sp->s_change(sp, ep, tp->lno, LINE_RESET))				goto err;			/* 			 * Historic practice was to delete <blank> characters			 * following the inserted newline.  This affected the			 * 'R', 'c', and 's' commands; 'c' and 's' retained			 * the insert characters only, 'R' moved overwrite and			 * insert characters into the next TEXT structure.			 * All other commands simply deleted the overwrite			 * characters.  We have to keep track of the number of			 * characters erased for the 'R' command so that we			 * can get the final resolution of the line correct.			 */			tp->R_erase = 0;			owrite = tp->owrite;			insert = tp->insert;			if (LF_ISSET(TXT_REPLACE) && owrite != 0) {				for (p = tp->lb + sp->cno;				    owrite > 0 && isblank(*p);				    ++p, --owrite, ++tp->R_erase);				if (owrite == 0)					for (; insert > 0 && isblank(*p);					    ++p, ++tp->R_erase, --insert);			} else {				for (p = tp->lb + sp->cno + owrite;				    insert > 0 && isblank(*p); ++p, --insert);				owrite = 0;			}			/* Set up bookkeeping for the new line. */			if ((ntp = text_init(sp, p,			    insert + owrite, insert + owrite + 32)) == NULL)				goto err;			ntp->insert = insert;			ntp->owrite = owrite;			ntp->lno = tp->lno + 1;			/*			 * Reset the autoindent line value.  0^D keeps the ai			 * line from changing, ^D changes the level, even if			 * there are no characters in the old line.  Note,			 * if using the current tp structure, use the cursor			 * as the length, the user may have erased autoindent			 * characters.			 */			if (LF_ISSET(TXT_AUTOINDENT)) {				if (carat_st == C_NOCHANGE) {					if (txt_auto(sp, ep,					    OOBLNO, &ait, ait.ai, ntp))						goto err;					FREE_SPACE(sp, ait.lb, ait.lb_len);				} else					if (txt_auto(sp, ep,					    OOBLNO, tp, sp->cno, ntp))						goto err;				carat_st = C_NOTSET;			}			/* New lines are TXT_APPENDEOL. */			if (ntp->owrite == 0 && ntp->insert == 0) {				BINC_GOTO(sp,				    ntp->lb, ntp->lb_len, ntp->len + 1);				LF_SET(TXT_APPENDEOL);				ntp->lb[ntp->ai] = CH_CURSOR;				++ntp->insert;				++ntp->len;			}			/*			 * Swap old and new TEXT's, and insert the new TEXT			 * into the queue.			 *			 * !!!			 * DON'T insert until the old line has been updated,			 * or the inserted line count in line.c:file_gline()			 * will be wrong.			 */			tp = ntp;			CIRCLEQ_INSERT_TAIL(tiqh, tp, q);			/* Reset the cursor. */			sp->lno = tp->lno;			sp->cno = tp->ai;			/* Update the new line. */			if (sp->s_change(sp, ep, tp->lno, LINE_INSERT))				goto err;			/* Set the renumber bit. */			F_SET(sp, S_RENUMBER);			/* Refresh if nothing waiting. */			if (margin || !KEYS_WAITING(sp))				if (sp->s_refresh(sp, ep))					goto err;			goto next_ch;		case K_ESCAPE:				/* Escape. */			if (!LF_ISSET(TXT_ESCAPE))				goto ins_ch;k_escape:		LINE_RESOLVE;			/*			 * Clean up for the 'R' command, restoring overwrite			 * characters, and making them into insert characters.			 */			if (LF_ISSET(TXT_REPLACE))				txt_Rcleanup(sp, tiqh, tp, lp, len);			/*			 * If there are any overwrite characters, copy down			 * any insert characters, and decrement the length.			 */			if (tp->owrite) {				if (tp->insert)					memmove(tp->lb + sp->cno,					    tp->lb + sp->cno + tp->owrite,					    tp->insert);				tp->len -= tp->owrite;			}			/*			 * Optionally resolve the lines into the file.  Clear			 * the input flag, the look-aside buffer is no longer			 * valid.  If not resolving the lines into the file,			 * end it with a nul.			 *			 * XXX			 * This is wrong, should pass back a length.			 */			if (LF_ISSET(TXT_RESOLVE)) {				if (txt_resolve(sp, ep, tiqh, flags))					goto err;				F_CLR(sp, S_INPUT);			} else {				BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);				tp->lb[tp->len] = '\0';			}			/*			 * Set the return cursor position to rest on the last			 * inserted character.			 */			if (rp != NULL) {				rp->lno = tp->lno;				rp->cno = sp->cno ? sp->cno - 1 : 0;				if (sp->s_change(sp, ep, rp->lno, LINE_RESET))					goto err;			}			goto ret;		case K_CARAT:			/* Delete autoindent chars. */			if (LF_ISSET(TXT_AUTOINDENT) && sp->cno <= tp->ai)				carat_st = C_CARATSET;			goto ins_ch;		case K_ZERO:			/* Delete autoindent chars. */			if (LF_ISSET(TXT_AUTOINDENT) && sp->cno <= tp->ai)				carat_st = C_ZEROSET;			goto ins_ch;		case K_CNTRLD:			/* Delete autoindent char. */			/*			 * If in the first column or no characters to erase,			 * ignore the ^D (this matches historic practice).  If			 * not doing autoindent or already inserted non-ai			 * characters, it's a literal.  The latter test is done			 * in the switch, as the CARAT forms are N + 1, not N.			 */			if (!LF_ISSET(TXT_AUTOINDENT))				goto ins_ch;			if (sp->cno == 0)				break;			switch (carat_st) {			case C_CARATSET:	/* ^^D */				if (sp->cno > tp->ai + tp->offset + 1)					goto ins_ch;				/* Save the ai string for later. */				ait.lb = NULL;				ait.lb_len = 0;				BINC_GOTO(sp, ait.lb, ait.lb_len, tp->ai);				memmove(ait.lb, tp->lb, tp->ai);				ait.ai = ait.len = tp->ai;				carat_st = C_NOCHANGE;				goto leftmargin;			case C_ZEROSET:		/* 0^D */				if (sp->cno > tp->ai + tp->offset + 1)					goto ins_ch;				carat_st = C_NOTSET;leftmargin:			tp->lb[sp->cno - 1] = ' ';				tp->owrite += sp->cno - tp->offset;				tp->ai = 0;				sp->cno = tp->offset;				break;			case C_NOTSET:		/* ^D */				if (sp->cno > tp->ai + tp->offset)					goto ins_ch;				(void)txt_outdent(sp, tp);				break;			default:				abort();			}			break;		case K_VERASE:			/* Erase the last character. */			/*			 * If can erase over the prompt, return.  Len is 0			 * if backspaced over the prompt, 1 if only CR entered.			 */			if (LF_ISSET(TXT_BS) && sp->cno <= tp->offset) {				tp->len = 0;				goto ret;			}			/*			 * If at the beginning of the line, try and drop back			 * to a previously inserted line.			 */			if (sp->cno == 0) {				if ((ntp = txt_backup(sp,				    ep, tiqh, tp, &flags)) == NULL)					goto err;				tp = ntp;				break;			}			/* If nothing to erase, bell the user. */			if (sp->cno <= tp->offset) {				msgq(sp, M_BERR,				    "No more characters to erase.");				break;			}			/* Drop back one character. */			--sp->cno;			/*			 * Increment overwrite, decrement ai if deleted.			 *			 * !!!			 * Historic vi did not permit users to use erase			 * characters to delete autoindent characters.			 */			++tp->owrite;			if (sp->cno < tp->ai)				--tp->ai;			break;		case K_VINTR:			if (F_ISSET(sp, S_INTERRUPTIBLE)) {				/*				 * !!!				 * Historically, <interrupt> exited the user				 * from editing, and returned to command mode.				 * It also beeped the terminal, but that seems				 * excessive.				 */				F_SET(sp, S_INTERRUPTED);				msgq(sp, M_INFO, "Interrupted.");				goto k_escape;			}			goto ins_ch;		case K_VWERASE:			/* Skip back one word. */			/*			 * If at the beginning of the line, try and drop back			 * to a previously inserted line.			 */			if (sp->cno == 0) {				if ((ntp = txt_backup(sp,				    ep, tiqh, tp, &flags)) == NULL)					goto err;				tp = ntp;			}			/*			 * If at offset, nothing to erase so bell the user.			 */			if (sp->cno <= tp->offset) {				msgq(sp, M_BERR,				    "No more characters to erase.");				break;			}			/*			 * First werase goes back to any autoindent			 * and second werase goes back to the offset.			 *			 * !!!			 * Historic vi did not permit users to use erase			 * characters to delete autoindent characters.			 */			if (tp->ai && sp->cno > tp->ai)				max = tp->ai;			else {				tp->ai = 0;				max = tp->offset;			}			/* Skip over trailing space characters. */			while (sp->cno > max && isblank(tp->lb[sp->cno - 1])) {				--sp->cno;				++tp->owrite;			}			if (sp->cno == max)				break;			/*			 * There are three types of word erase found on UNIX			 * systems.  They can be identified by how the string			 * /a/b/c is treated -- as 1, 3, or 6 words.  Historic			 * vi had two classes of characters, and strings were			 * delimited by them and <blank>'s, so, 6 words.  The			 * historic tty interface used <blank>'s to delimit			 * strings, so, 1 word.  The algorithm offered in the			 * 4.4BSD tty interface (as stty altwerase) treats it			 * as 3 words -- there are two classes of characters,			 * and strings are delimited by them and <blank>'s.			 * The difference is that the type of the first erased			 * character erased is ignored, which is exactly right			 * when erasing pathname components.  Here, the options			 * TXT_ALTWERASE and TXT_TTYWERASE specify the 4.4BSD			 * tty interface and the historic tty driver behavior,			 * respectively, and the default is the same as the			 * historic vi behavior.			 */			if (LF_ISSET(TXT_TTYWERASE))				while (sp->cno > max) {					--sp->cno;					++tp->owrite;					if (isblank(tp->lb[sp->cno - 1]))						break;				}			else {				if (LF_ISSET(TXT_ALTWERASE)) {					--sp->cno;					++tp->owrite;					if (isblank(tp->lb[sp->cno - 1]))						break;				}				if (sp->cno > max)					tmp = inword(tp->lb[sp->cno - 1]);				while (sp->cno > max) {					--sp->cno;					++tp->owrite;					if (tmp != inword(tp->lb[sp->cno - 1])					    || isblank(tp->lb[sp->cno - 1]))						break;				}			}			break;		case K_VKILL:			/* Restart this line. */			/*			 * If at the beginning of the line, try and drop back			 * to a previously inserted line.			 */			if (sp->cno == 0) {				if ((ntp = txt_backup(sp,				    ep, tiqh, tp, &flags)) == NULL)					goto err;				tp = ntp;			}			/* If at offset, nothing to erase so bell the user. */			if (sp->cno <= tp->offset) {				msgq(sp, M_BERR,				    "No more characters to erase.");				break;			}			/*			 * First kill goes back to any autoindent			 * and second kill goes back to the offset.			 *			 * !!!			 * Historic vi did not permit users to use erase			 * characters to delete autoindent characters.			 */			if (tp->ai && sp->cno > tp->ai)				max = tp->ai;			else {				tp->ai = 0;				max = tp->offset;			}			tp->owrite += sp->cno - max;			sp->cno = max;			break;		case K_CNTRLT:			/* Add autoindent char. */			if (!LF_ISSET(TXT_CNTRLT))				goto ins_ch;			if (txt_indent(sp, tp))				goto err;			goto ebuf_chk;		case K_CNTRLZ:			(void)sp->s_suspend(sp);			break;#ifdef	HISTORIC_PRACTICE_IS_TO_INSERT_NOT_REPAINT		case K_FORMFEED:			F_SET(sp, S_REFRESH);			break;#endif		case K_RIGHTBRACE:		case K_RIGHTPAREN:			showmatch = LF_ISSET(TXT_SHOWMATCH);			goto ins_ch;		case K_VLNEXT:			/* Quote the next character. */			ch = '^';			quoted = Q_NEXTCHAR;			goto insq_ch;		case K_HEXCHAR:			hex = H_NEXTCHAR;			goto insq_ch;		default:			/* Insert the character. */ins_ch:			/*	 		 * Historically, vi eliminated nul's out of hand.  If			 * the beautify option was set, it also deleted any			 * unknown ASCII value less than space (040) and the			 * del character (0177), except for tabs.  Unknown is			 * a key word here.  Most vi documentation claims that			 * it deleted everything but <tab>, <nl> and <ff>, as			 * that's what the original 4BSD documentation said.			 * This is obviously wrong, however, as <esc> would be			 * included in that list.  What we do is eliminate any			 * unquoted, iscntrl() character that wasn't a replay			 * and wasn't handled specially, except <tab> or <ff>.			 */			if (LF_ISSET(TXT_BEAUTIFY) && iscntrl(ch) &&			    ikey.value != K_FORMFEED && ikey.value != K_TAB) {				msgq(sp, M_BERR,				    "Illegal character; quote to enter.");				break;			}insq_ch:		/*			 * If entering a non-word character after a word, check			 * for abbreviations.  If there was one, discard the			 * replay characters.  If entering a blank character,			 * check for unmap commands, as well.			 */			if (!inword(ch)) {				if (abb == A_INWORD && !replay) {					if (txt_abbrev(sp, tp, &ch,					    LF_ISSET(TXT_INFOLINE),					    &tmp, &ab_turnoff))						goto err;					if (tmp) {						if (LF_ISSET(TXT_RECORD))							rcol -= tmp;						goto next_ch;					}				}				if (isblank(ch) && unmap_tst)					txt_unmap(sp, tp, &iflags);

⌨️ 快捷键说明

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