292 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			292 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /* move2.c */
 | |
| 
 | |
| /* Author:
 | |
|  *	Steve Kirkendall
 | |
|  *	14407 SW Teal Blvd. #C
 | |
|  *	Beaverton, OR 97005
 | |
|  *	kirkenda@cs.pdx.edu
 | |
|  */
 | |
| 
 | |
| 
 | |
| /* This function contains the movement functions that perform RE searching */
 | |
| 
 | |
| #include "config.h"
 | |
| #include "vi.h"
 | |
| #include "regexp.h"
 | |
| 
 | |
| extern long	atol();
 | |
| 
 | |
| static regexp	*re;	/* compiled version of the pattern to search for */
 | |
| static		prevsf;	/* boolean: previous search direction was forward? */
 | |
| 
 | |
| #ifndef NO_EXTENSIONS
 | |
| /*ARGSUSED*/
 | |
| MARK m_wsrch(word, m, cnt)
 | |
| 	char	*word;	/* the word to search for */
 | |
| 	MARK	m;	/* the starting point */
 | |
| 	int	cnt;	/* ignored */
 | |
| {
 | |
| 	char	buffer[30];
 | |
| 
 | |
| 	/* wrap \< and \> around the word */
 | |
| 	strcpy(buffer, "/\\<");
 | |
| 	strcat(buffer, word);
 | |
| 	strcat(buffer, "\\>");
 | |
| 
 | |
| 	/* show the searched-for word on the bottom line */
 | |
| 	move(LINES - 1, 0);
 | |
| 	qaddstr(buffer);
 | |
| 	clrtoeol();
 | |
| 	refresh();
 | |
| 
 | |
| 	/* search for the word */
 | |
| 	return m_fsrch(m, buffer);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| MARK	m_nsrch(m)
 | |
| 	MARK	m;	/* where to start searching */
 | |
| {
 | |
| 	if (prevsf)
 | |
| 	{
 | |
| 		m = m_fsrch(m, (char *)0);
 | |
| 		prevsf = TRUE;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		m = m_bsrch(m, (char *)0);
 | |
| 		prevsf = FALSE;
 | |
| 	}
 | |
| 	return m;
 | |
| }
 | |
| 
 | |
| MARK	m_Nsrch(m)
 | |
| 	MARK	m;	/* where to start searching */
 | |
| {
 | |
| 	if (prevsf)
 | |
| 	{
 | |
| 		m = m_bsrch(m, (char *)0);
 | |
| 		prevsf = TRUE;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		m = m_fsrch(m, (char *)0);
 | |
| 		prevsf = FALSE;
 | |
| 	}
 | |
| 	return m;
 | |
| }
 | |
| 
 | |
| MARK	m_fsrch(m, ptrn)
 | |
| 	MARK	m;	/* where to start searching */
 | |
| 	char	*ptrn;	/* pattern to search for */
 | |
| {
 | |
| 	long	l;	/* line# of line to be searched */
 | |
| 	char	*line;	/* text of line to be searched */
 | |
| 	int	wrapped;/* boolean: has our search wrapped yet? */
 | |
| 	int	pos;	/* where we are in the line */
 | |
| #ifndef CRUNCH
 | |
| 	long	delta = INFINITY;/* line offset, for things like "/foo/+1" */
 | |
| #endif
 | |
| 
 | |
| 	/* remember: "previous search was forward" */
 | |
| 	prevsf = TRUE;
 | |
| 
 | |
| 	if (ptrn && *ptrn)
 | |
| 	{
 | |
| 		/* locate the closing '/', if any */
 | |
| 		line = parseptrn(ptrn);
 | |
| #ifndef CRUNCH
 | |
| 		if (*line)
 | |
| 		{
 | |
| 			delta = atol(line);
 | |
| 		}
 | |
| #endif
 | |
| 		ptrn++;
 | |
| 
 | |
| 		/* free the previous pattern */
 | |
| 		if (re) free(re);
 | |
| 
 | |
| 		/* compile the pattern */
 | |
| 		re = regcomp(ptrn);
 | |
| 		if (!re)
 | |
| 		{
 | |
| 			return MARK_UNSET;
 | |
| 		}
 | |
| 	}
 | |
| 	else if (!re)
 | |
| 	{
 | |
| 		msg("No previous expression");
 | |
| 		return MARK_UNSET;
 | |
| 	}
 | |
| 
 | |
| 	/* search forward for the pattern */
 | |
| 	pos = markidx(m) + 1;
 | |
| 	pfetch(markline(m));
 | |
| 	if (pos >= plen)
 | |
| 	{
 | |
| 		pos = 0;
 | |
| 		m = (m | (BLKSIZE - 1)) + 1;
 | |
| 	}
 | |
| 	wrapped = FALSE;
 | |
| 	for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
 | |
| 	{
 | |
| 		/* wrap search */
 | |
| 		if (l > nlines)
 | |
| 		{
 | |
| 			/* if we wrapped once already, then the search failed */
 | |
| 			if (wrapped)
 | |
| 			{
 | |
| 				break;
 | |
| 			}
 | |
| 
 | |
| 			/* else maybe we should wrap now? */
 | |
| 			if (*o_wrapscan)
 | |
| 			{
 | |
| 				l = 0;
 | |
| 				wrapped = TRUE;
 | |
| 				continue;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/* get this line */
 | |
| 		line = fetchline(l);
 | |
| 
 | |
| 		/* check this line */
 | |
| 		if (regexec(re, &line[pos], (pos == 0)))
 | |
| 		{
 | |
| 			/* match! */
 | |
| 			if (wrapped && *o_warn)
 | |
| 				msg("(wrapped)");
 | |
| #ifndef CRUNCH
 | |
| 			if (delta != INFINITY)
 | |
| 			{
 | |
| 				l += delta;
 | |
| 				if (l < 1 || l > nlines)
 | |
| 				{
 | |
| 					msg("search offset too big");
 | |
| 					return MARK_UNSET;
 | |
| 				}
 | |
| 				force_flags = LNMD|INCL;
 | |
| 				return MARK_AT_LINE(l);
 | |
| 			}
 | |
| #endif
 | |
| 			return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
 | |
| 		}
 | |
| 		pos = 0;
 | |
| 	}
 | |
| 
 | |
| 	/* not found */
 | |
| 	msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
 | |
| 	return MARK_UNSET;
 | |
| }
 | |
| 
 | |
| MARK	m_bsrch(m, ptrn)
 | |
| 	MARK	m;	/* where to start searching */
 | |
| 	char	*ptrn;	/* pattern to search for */
 | |
| {
 | |
| 	long	l;	/* line# of line to be searched */
 | |
| 	char	*line;	/* text of line to be searched */
 | |
| 	int	wrapped;/* boolean: has our search wrapped yet? */
 | |
| 	int	pos;	/* last acceptable idx for a match on this line */
 | |
| 	int	last;	/* remembered idx of the last acceptable match on this line */
 | |
| 	int	try;	/* an idx at which we strat searching for another match */
 | |
| #ifndef CRUNCH
 | |
| 	long	delta = INFINITY;/* line offset, for things like "/foo/+1" */
 | |
| #endif
 | |
| 
 | |
| 	/* remember: "previous search was not forward" */
 | |
| 	prevsf = FALSE;
 | |
| 
 | |
| 	if (ptrn && *ptrn)
 | |
| 	{
 | |
| 		/* locate the closing '?', if any */
 | |
| 		line = parseptrn(ptrn);
 | |
| #ifndef CRUNCH
 | |
| 		if (*line)
 | |
| 		{
 | |
| 			delta = atol(line);
 | |
| 		}
 | |
| #endif
 | |
| 		ptrn++;
 | |
| 
 | |
| 		/* free the previous pattern, if any */
 | |
| 		if (re) free(re);
 | |
| 
 | |
| 		/* compile the pattern */
 | |
| 		re = regcomp(ptrn);
 | |
| 		if (!re)
 | |
| 		{
 | |
| 			return MARK_UNSET;
 | |
| 		}
 | |
| 	}
 | |
| 	else if (!re)
 | |
| 	{
 | |
| 		msg("No previous expression");
 | |
| 		return MARK_UNSET;
 | |
| 	}
 | |
| 
 | |
| 	/* search backward for the pattern */
 | |
| 	pos = markidx(m);
 | |
| 	wrapped = FALSE;
 | |
| 	for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
 | |
| 	{
 | |
| 		/* wrap search */
 | |
| 		if (l < 1)
 | |
| 		{
 | |
| 			if (*o_wrapscan)
 | |
| 			{
 | |
| 				l = nlines + 1;
 | |
| 				wrapped = TRUE;
 | |
| 				continue;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/* get this line */
 | |
| 		line = fetchline(l);
 | |
| 
 | |
| 		/* check this line */
 | |
| 		if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
 | |
| 		{
 | |
| 			/* match!  now find the last acceptable one in this line */
 | |
| 			do
 | |
| 			{
 | |
| 				last = (int)(re->startp[0] - line);
 | |
| 				try = (int)(re->endp[0] - line);
 | |
| 			} while (try > 0
 | |
| 				 && regexec(re, &line[try], FALSE)
 | |
| 				 && (int)(re->startp[0] - line) < pos);
 | |
| 
 | |
| 			if (wrapped && *o_warn)
 | |
| 				msg("(wrapped)");
 | |
| #ifndef CRUNCH
 | |
| 			if (delta != INFINITY)
 | |
| 			{
 | |
| 				l += delta;
 | |
| 				if (l < 1 || l > nlines)
 | |
| 				{
 | |
| 					msg("search offset too big");
 | |
| 					return MARK_UNSET;
 | |
| 				}
 | |
| 				force_flags = LNMD|INCL;
 | |
| 				return MARK_AT_LINE(l);
 | |
| 			}
 | |
| #endif
 | |
| 			return MARK_AT_LINE(l) + last;
 | |
| 		}
 | |
| 		pos = BLKSIZE;
 | |
| 	}
 | |
| 
 | |
| 	/* not found */
 | |
| 	msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
 | |
| 	return MARK_UNSET;
 | |
| }
 | |
| 
 | 
