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

📄 vi.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		 * !!!		 * If a '.' is immediately entered after an undo command, we		 * replay the log instead of redoing the last command.  This		 * is necessary because 'u' can't set the dot command -- see		 * vi/v_undo.c:v_undo for details.		 */		if (VIP(sp)->u_ccnt == sp->ccnt) {			vp->kp = &vikeys['u'];			F_SET(vp, VC_ISDOT);			return (0);		}		/* Set new count/buffer, if any, and return. */		if (F_ISSET(vp, VC_C1SET)) {			F_SET(dp, VC_C1SET);			dp->count = vp->count;		}		if (F_ISSET(vp, VC_BUFFER))			dp->buffer = vp->buffer;		*vp = *dp;		return (0);	}	flags = kp->flags;	/* Check for illegal count. */	if (F_ISSET(vp, VC_C1SET) && !LF_ISSET(V_CNT))		goto usage;	/* Illegal motion command. */	if (ismotion == NULL) {		/* Illegal buffer. */		if (!LF_ISSET(V_OBUF) && F_ISSET(vp, VC_BUFFER))			goto usage;		/* Required buffer. */		if (LF_ISSET(V_RBUF))			KEY(vp->buffer, 0);	}	/*	 * Special case: '[', ']' and 'Z' commands.  Doesn't the fact that	 * the *single* characters don't mean anything but the *doubled*	 * characters do just frost your shorts?	 */	if (vp->key == '[' || vp->key == ']' || vp->key == 'Z') {		KEY(key, TXT_MAPCOMMAND);		if (vp->key != key) {usage:			msgq(sp, M_ERR, "Usage: %s", ismotion != NULL ?			    vikeys[ismotion->key].usage : kp->usage);			return (1);		}	}	/* Special case: 'z' command. */	if (vp->key == 'z') {		KEY(vp->character, 0);		if (isdigit(vp->character)) {			if (getcount(sp, vp->character, &vp->count2))				return (1);			F_SET(vp, VC_C2SET);			KEY(vp->character, 0);		}	}	/*	 * Commands that have motion components can be doubled to	 * imply the current line.	 */	if (ismotion != NULL && ismotion->key != key && !LF_ISSET(V_MOVE)) {		msgq(sp, M_ERR, "%s may not be used as a motion command.",		    KEY_NAME(sp, key));		return (1);	}	/* Required character. */	if (LF_ISSET(V_CHAR))		KEY(vp->character, 0);	return (0);}/* * getmotion -- * * Get resulting motion mark. */static intgetmotion(sp, ep, dm, vp)	SCR *sp;	EXF *ep;	VICMDARG *dm, *vp;{	MARK m;	VICMDARG motion;	size_t len;	u_long cnt;	int notused;	/* If '.' command, use the dot motion, else get the motion command. */	if (F_ISSET(vp, VC_ISDOT)) {		motion = *dm;		F_SET(&motion, VC_ISDOT);	} else if (getcmd(sp, ep, NULL, &motion, vp, &notused))		return (1);	/*	 * A count may be provided both to the command and to the motion, in	 * which case the count is multiplicative.  For example, "3y4y" is the	 * same as "12yy".  This count is provided to the motion command and	 * not to the regular function.	 */	cnt = motion.count = F_ISSET(&motion, VC_C1SET) ? motion.count : 1;	if (F_ISSET(vp, VC_C1SET)) {		motion.count *= vp->count;		F_SET(&motion, VC_C1SET);		/*		 * Set flags to restore the original values of the command		 * structure so dot commands can change the count values,		 * e.g. "2dw" "3." deletes a total of five words.		 */		F_CLR(vp, VC_C1SET);		F_SET(vp, VC_C1RESET);	}	/*	 * Some commands can be repeated to indicate the current line.  In	 * this case, or if the command is a "line command", set the flags	 * appropriately.  If not a doubled command, run the function to get	 * the resulting mark. 	 */	if (vp->key == motion.key) {		F_SET(vp, VM_LDOUBLE | VM_LMODE);		/* Set the origin of the command. */		vp->m_start.lno = sp->lno;		vp->m_start.cno = 0;		/*		 * Set the end of the command.		 *		 * If the current line is missing, i.e. the file is empty,		 * historic vi permitted a "cc" or "!!" command to insert		 * text.		 */		vp->m_stop.lno = sp->lno + motion.count - 1;		if (file_gline(sp, ep, vp->m_stop.lno, &len) == NULL) {			if (vp->m_stop.lno != 1 ||			   vp->key != 'c' && vp->key != '!') {				m.lno = sp->lno;				m.cno = sp->cno;				v_eof(sp, ep, &m);				return (1);			}			vp->m_stop.cno = 0;		} else			vp->m_stop.cno = len ? len - 1 : 0;	} else {		/*		 * Motion commands change the underlying movement (*snarl*).		 * For example, "l" is illegal at the end of a line, but "dl"		 * is not.  Set flags so the function knows the situation.		 */		F_SET(&motion, vp->kp->flags & VC_COMMASK);		/* Copy the key flags into the local structure. */		F_SET(&motion, motion.kp->flags);		/*		 * Set the three cursor locations to the current cursor.  This		 * permits commands like 'j' and 'k', that are line oriented		 * motions and have special cursor suck semantics when they are		 * used as standalone commands, to ignore column positioning.		 */		motion.m_final.lno =		    motion.m_stop.lno = motion.m_start.lno = sp->lno;		motion.m_final.cno =		    motion.m_stop.cno = motion.m_start.cno = sp->cno;		/* Run the function. */		if ((motion.kp->func)(sp, ep, &motion))			return (1);		/*		 * Copy line mode and cursor position information from the		 * motion command structure.  The commands can flag the		 * movement as a line motion (see v_sentence) as well as set		 * the VM_RCM_* flags explicitly.		 */		F_SET(vp,		    F_ISSET(&motion, VM_LMODE | VM_NOMOTION | VM_RCM_MASK));		/*		 * Motion commands can reset all of the cursor information.		 * If the motion is in the reverse direction, switch the		 * from and to MARK's so that it's in a forward direction.		 * Motions are from the from MARK to the to MARK (inclusive).		 */		if (motion.m_start.lno > motion.m_stop.lno ||		    motion.m_start.lno == motion.m_stop.lno &&		    motion.m_start.cno > motion.m_stop.cno) {			vp->m_start = motion.m_stop;			vp->m_stop = motion.m_start;		} else {			vp->m_start = motion.m_start;			vp->m_stop = motion.m_stop;		}		vp->m_final = motion.m_final;	}	/*	 * If the command sets dot, save the motion structure.  The motion	 * count was changed above and needs to be reset, that's why this	 * is done here, and not in the calling routine.	 */	if (F_ISSET(vp->kp, V_DOT)) {		*dm = motion;		dm->count = cnt;	}	return (0);}#define	innum(c)	(isdigit(c) || strchr("abcdefABCDEF", c))/* * getkeyword -- *	Get the "word" the cursor is on. */static intgetkeyword(sp, ep, kp, flags)	SCR *sp;	EXF *ep;	VICMDARG *kp;	u_int flags;{	recno_t lno;	size_t beg, end, len;	char *p;	if ((p = file_gline(sp, ep, sp->lno, &len)) == NULL) {		if (file_lline(sp, ep, &lno))			return (1);		if (lno == 0)			v_eof(sp, ep, NULL);		else			GETLINE_ERR(sp, sp->lno);		return (1);	}	beg = sp->cno;	/* May not be a keyword at all. */	if (p == NULL || len == 0 ||	    LF_ISSET(V_KEYW) && !inword(p[beg]) ||	    LF_ISSET(V_KEYNUM) && !innum(p[beg]) &&	    p[beg] != '-' && p[beg] != '+') {noword:		msgq(sp, M_BERR, "Cursor not in a %s",		    LF_ISSET(V_KEYW) ? "word" : "number");		return (1);	}	/*	 * !!!	 * Find the beginning/end of the keyword.  Keywords (V_KEYW) are	 * used for cursor-word searching and for tags.  Historical vi	 * only used the word in a tag search from the cursor to the end	 * of the word, i.e. if the cursor was on the 'b' in " abc ", the	 * tag was "bc".  For no particular reason, we make cursor word	 * searches follow the same rule.	 */	if (beg != 0)		if (LF_ISSET(V_KEYW)) {#ifdef	MOVE_TO_KEYWORD_BEGINNING			for (;;) {				--beg;				if (!inword(p[beg])) {					++beg;					break;				}				if (beg == 0)					break;			}#endif		} else {			for (;;) {				--beg;				if (!innum(p[beg])) {					if (beg > 0 && p[beg - 1] == '0' &&					    (p[beg] == 'X' || p[beg] == 'x'))						--beg;					else						++beg;					break;				}				if (beg == 0)					break;			}			/* Skip possible leading sign. */			if (beg != 0 && p[beg] != '0' &&			    (p[beg - 1] == '+' || p[beg - 1] == '-'))				--beg;		}	if (LF_ISSET(V_KEYW)) {		for (end = sp->cno; ++end < len && inword(p[end]););		--end;	} else {		for (end = sp->cno; ++end < len;) {			if (p[end] == 'X' || p[end] == 'x') {				if (end != beg + 1 || p[beg] != '0')					break;				continue;			}			if (!innum(p[end]))				break;		}		/* Just a sign isn't a number. */		if (end == beg && (p[beg] == '+' || p[beg] == '-'))			goto noword;		--end;	}	/*	 * Getting a keyword implies moving the cursor to its beginning.	 * Refresh now.	 */	if (beg != sp->cno) {		sp->cno = beg;		sp->s_refresh(sp, ep);	}	/*	 * XXX	 * 8-bit clean problem.  Numeric keywords are handled using strtol(3)	 * and friends.  This would have to be fixed in v_increment and here	 * to not depend on a trailing NULL.	 */	len = (end - beg) + 2;				/* XXX */	kp->klen = (end - beg) + 1;	BINC_RET(sp, kp->keyword, kp->kbuflen, len);	memmove(kp->keyword, p + beg, kp->klen);	kp->keyword[kp->klen] = '\0';			/* XXX */	return (0);}/* * getcount -- *	Return the next count. */static inline intgetcount(sp, fkey, countp)	SCR *sp;	ARG_CHAR_T fkey;	u_long *countp;{	u_long count, tc;	CH ikey;	ikey.ch = fkey;	count = tc = 0;	do {		/* Assume that overflow results in a smaller number. */		tc = count * 10 + ikey.ch - '0';		if (count > tc) {			/* Toss to the next non-digit. */			do {				if (getkey(sp, &ikey,				    TXT_MAPCOMMAND | TXT_MAPNODIGIT))					return (1);			} while (isdigit(ikey.ch));			msgq(sp, M_ERR, "Number larger than %lu", ULONG_MAX);			return (1);		}		count = tc;		if (getkey(sp, &ikey, TXT_MAPCOMMAND | TXT_MAPNODIGIT))			return (1);	} while (isdigit(ikey.ch));	*countp = count;	return (0);}/* * getkey -- *	Return the next key. */static inline intgetkey(sp, ikeyp, map)	SCR *sp;	CH *ikeyp;	u_int map;{	switch (term_key(sp, ikeyp, map)) {	case INP_OK:		break;	case INP_EOF:	case INP_ERR:		F_SET(sp, S_EXIT_FORCE);		return (1);	}	return (ikeyp->value == K_ESCAPE);}

⌨️ 快捷键说明

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