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

📄 search.c

📁 STEVIE文本文件编缉器的C 语言源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
 * The command character (as well as the trailing slash) is optional, and
 * is assumed to be 'p' if missing.
 */
void
doglob(lp, up, cmd)
LPTR	*lp, *up;
char	*cmd;
{
	LINE	*cp;
	char	*pat;
	regexp	*prog;
	int	ndone;
	char	cmdchar = NUL;	/* what to do with matching lines */

	/*
	 * If no range was given, do every line. If only one line
	 * was given, just do that one.
	 */
	if (lp->linep == NULL) {
		*lp = *Filemem;
		*up = *Fileend;
	} else {
		if (up->linep == NULL)
			*up = *lp;
	}

	pat = ++cmd;		/* skip the initial '/' */

	while (*cmd) {
		if (*cmd == '\\')	/* next char is quoted */
			cmd += 2;
		else if (*cmd == '/') {	/* delimiter */
			cmdchar = cmd[1];
			*cmd++ = NUL;
			break;
		} else
			cmd++;		/* regular character */
	}
	if (cmdchar == NUL)
		cmdchar = 'p';

	reg_ic = P(P_IC);	/* set "ignore case" flag appropriately */

	if (cmdchar != 'd' && cmdchar != 'p') {
		emsg("Invalid command character");
		return;
	}

	if ((prog = regcomp(pat)) == NULL) {
		emsg("Invalid search string");
		return;
	}

	msg("");
	ndone = 0;
	got_int = FALSE;

	for (cp = lp->linep; cp != NULL && !got_int ;cp = cp->next) {
		if (regexec(prog, cp->s, TRUE)) { /* a match on this line */
			switch (cmdchar) {

			case 'd':		/* delete the line */
				if (Curschar->linep != cp) {
					LPTR	savep;

					savep = *Curschar;
					Curschar->linep = cp;
					Curschar->index = 0;
					delline(1, FALSE);
					*Curschar = savep;
				} else
					delline(1, FALSE);
				break;

			case 'p':		/* print the line */
				prt_line(cp->s);
				outstr("\r\n");
				break;
			}
			ndone++;
		}
		if (cp == up->linep)
			break;
	}

	if (ndone) {
		switch (cmdchar) {

		case 'd':
			updatescreen();
			if (ndone >= P(P_RP) || got_int)
				smsg("%s%d fewer line%c",
					got_int ? "Interrupt: " : "",
					ndone,
					(ndone > 1) ? 's' : ' ');
			break;

		case 'p':
			wait_return();
			break;
		}
	} else {
		if (got_int)
			msg("Interrupt");
		else
			msg("No match");
	}

	got_int = FALSE;
	free((char *)prog);
}

/*
 * Character Searches
 */

static char lastc = NUL;	/* last character searched for */
static int  lastcdir;		/* last direction of character search */
static int  lastctype;		/* last type of search ("find" or "to") */

/*
 * searchc(c, dir, type)
 *
 * Search for character 'c', in direction 'dir'. If type is 0, move to
 * the position of the character, otherwise move to just before the char.
 */
bool_t
searchc(c, dir, type)
char	c;
int	dir;
int	type;
{
	LPTR	save;

	save = *Curschar;	/* save position in case we fail */
	lastc = c;
	lastcdir = dir;
	lastctype = type;

	/*
	 * On 'to' searches, skip one to start with so we can repeat
	 * searches in the same direction and have it work right.
	 */
	if (type)
		(dir == FORWARD) ? oneright() : oneleft();

	while ( (dir == FORWARD) ? oneright() : oneleft() ) {
		if (gchar(Curschar) == c) {
			if (type)
				(dir == FORWARD) ? oneleft() : oneright();
			return TRUE;
		}
	}
	*Curschar = save;
	return FALSE;
}

bool_t
crepsearch(flag)
int	flag;
{
	int	dir = lastcdir;
	int	rval;

	if (lastc == NUL)
		return FALSE;

	rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype);

	lastcdir = dir;		/* restore dir., since it may have changed */

	return rval;
}

/*
 * "Other" Searches
 */

/*
 * showmatch - move the cursor to the matching paren or brace
 */
LPTR *
showmatch()
{
	static	LPTR	pos;
	int	(*move)(), inc(), dec();
	char	initc = gchar(Curschar);	/* initial char */
	char	findc;				/* terminating char */
	char	c;
	int	count = 0;

	pos = *Curschar;		/* set starting point */

	switch (initc) {

	case '(':
		findc = ')';
		move = inc;
		break;
	case ')':
		findc = '(';
		move = dec;
		break;
	case '{':
		findc = '}';
		move = inc;
		break;
	case '}':
		findc = '{';
		move = dec;
		break;
	case '[':
		findc = ']';
		move = inc;
		break;
	case ']':
		findc = '[';
		move = dec;
		break;
	default:
		return (LPTR *) NULL;
	}

	while ((*move)(&pos) != -1) {		/* until end of file */
		c = gchar(&pos);
		if (c == initc)
			count++;
		else if (c == findc) {
			if (count == 0)
				return &pos;
			count--;
		}
	}
	return (LPTR *) NULL;			/* never found it */
}

/*
 * findfunc(dir) - Find the next function in direction 'dir'
 *
 * Return TRUE if a function was found.
 */
bool_t
findfunc(dir)
int	dir;
{
	LPTR	*curr;

	curr = Curschar;

	do {
		curr = (dir == FORWARD) ? nextline(curr) : prevline(curr);

		if (curr != NULL && curr->linep->s[0] == '{') {
			setpcmark();
			*Curschar = *curr;
			return TRUE;
		}
	} while (curr != NULL);

	return FALSE;
}

/*
 * The following routines do the word searches performed by the
 * 'w', 'W', 'b', 'B', 'e', and 'E' commands.
 */

/*
 * To perform these searches, characters are placed into one of three
 * classes, and transitions between classes determine word boundaries.
 *
 * The classes are:
 *
 * 0 - white space
 * 1 - letters, digits, and underscore
 * 2 - everything else
 */

static	int	stype;		/* type of the word motion being performed */

#define	C0(c)	(((c) == ' ') || ((c) == '\t') || ((c) == NUL))
#define	C1(c)	(isalpha(c) || isdigit(c) || ((c) == '_'))

/*
 * cls(c) - returns the class of character 'c'
 *
 * The 'type' of the current search modifies the classes of characters
 * if a 'W', 'B', or 'E' motion is being done. In this case, chars. from
 * class 2 are reported as class 1 since only white space boundaries are
 * of interest.
 */
static	int
cls(c)
char	c;
{
	if (C0(c))
		return 0;

	if (C1(c))
		return 1;

	/*
	 * If stype is non-zero, report these as class 1.
	 */
	return (stype == 0) ? 2 : 1;
}


/*
 * fwd_word(pos, type) - move forward one word
 *
 * Returns the resulting position, or NULL if EOF was reached.
 */
LPTR *
fwd_word(p, type)
LPTR	*p;
int	type;
{
	static	LPTR	pos;
	int	sclass = cls(gchar(p));		/* starting class */

	pos = *p;

	stype = type;

	/*
	 * We always move at least one character.
	 */
	if (inc(&pos) == -1)
		return NULL;

	if (sclass != 0) {
		while (cls(gchar(&pos)) == sclass) {
			if (inc(&pos) == -1)
				return NULL;
		}
		/*
		 * If we went from 1 -> 2 or 2 -> 1, return here.
		 */
		if (cls(gchar(&pos)) != 0)
			return &pos;
	}

	/* We're in white space; go to next non-white */

	while (cls(gchar(&pos)) == 0) {
		/*
		 * We'll stop if we land on a blank line
		 */
		if (pos.index == 0 && pos.linep->s[0] == NUL)
			break;

		if (inc(&pos) == -1)
			return NULL;
	}

	return &pos;
}

/*
 * bck_word(pos, type) - move backward one word
 *
 * Returns the resulting position, or NULL if EOF was reached.
 */
LPTR *
bck_word(p, type)
LPTR	*p;
int	type;
{
	static	LPTR	pos;
	int	sclass = cls(gchar(p));		/* starting class */

	pos = *p;

	stype = type;

	if (dec(&pos) == -1)
		return NULL;

	/*
	 * If we're in the middle of a word, we just have to
	 * back up to the start of it.
	 */
	if (cls(gchar(&pos)) == sclass && sclass != 0) {
		/*
		 * Move backward to start of the current word
		 */
		while (cls(gchar(&pos)) == sclass) {
			if (dec(&pos) == -1)
				return NULL;
		}
		inc(&pos);			/* overshot - forward one */
		return &pos;
	}

	/*
	 * We were at the start of a word. Go back to the start
	 * of the prior word.
	 */

	while (cls(gchar(&pos)) == 0) {		/* skip any white space */
		/*
		 * We'll stop if we land on a blank line
		 */
		if (pos.index == 0 && pos.linep->s[0] == NUL)
			return &pos;

		if (dec(&pos) == -1)
			return NULL;
	}

	sclass = cls(gchar(&pos));

	/*
	 * Move backward to start of this word.
	 */
	while (cls(gchar(&pos)) == sclass) {
		if (dec(&pos) == -1)
			return NULL;
	}
	inc(&pos);			/* overshot - forward one */

	return &pos;
}

/*
 * end_word(pos, type, in_change) - move to the end of the word
 *
 * There is an apparent bug in the 'e' motion of the real vi. At least
 * on the System V Release 3 version for the 80386. Unlike 'b' and 'w',
 * the 'e' motion crosses blank lines. When the real vi crosses a blank
 * line in an 'e' motion, the cursor is placed on the FIRST character
 * of the next non-blank line. The 'E' command, however, works correctly.
 * Since this appears to be a bug, I have not duplicated it here.
 *
 * There's a strange special case here that the 'in_change' parameter
 * helps us deal with. Vi effectively turns 'cw' into 'ce'. If we're on
 * a word with only one character, we need to stick at the current
 * position so we don't change two words.
 *
 * Returns the resulting position, or NULL if EOF was reached.
 */
LPTR *
end_word(p, type, in_change)
LPTR	*p;
int	type;
bool_t	in_change;
{
	static	LPTR	pos;
	int	sclass = cls(gchar(p));		/* starting class */

	pos = *p;

	stype = type;

	if (inc(&pos) == -1)
		return NULL;

	/*
	 * If we're in the middle of a word, we just have to
	 * move to the end of it.
	 */
	if (cls(gchar(&pos)) == sclass && sclass != 0) {
		/*
		 * Move forward to end of the current word
		 */
		while (cls(gchar(&pos)) == sclass) {
			if (inc(&pos) == -1)
				return NULL;
		}
		dec(&pos);			/* overshot - forward one */
		return &pos;
	}

	/*
	 * We were at the end of a word. Go to the end of the next
	 * word, unless we're doing a change. In that case we stick
	 * at the end of the current word.
	 */
	if (in_change)
		return p;

	while (cls(gchar(&pos)) == 0) {		/* skip any white space */
		if (inc(&pos) == -1)
			return NULL;
	}

	sclass = cls(gchar(&pos));

	/*
	 * Move forward to end of this word.
	 */
	while (cls(gchar(&pos)) == sclass) {
		if (inc(&pos) == -1)
			return NULL;
	}
	dec(&pos);			/* overshot - forward one */

	return &pos;
}

⌨️ 快捷键说明

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