257 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* move5.c */
 | 
						|
 | 
						|
/* Author:
 | 
						|
 *	Steve Kirkendall
 | 
						|
 *	14407 SW Teal Blvd. #C
 | 
						|
 *	Beaverton, OR 97005
 | 
						|
 *	kirkenda@cs.pdx.edu
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
/* This file contains the word-oriented movement functions */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
#include "ctype.h"
 | 
						|
#include "vi.h"
 | 
						|
 | 
						|
MARK	m_fword(m, cnt, cmd, prevkey)
 | 
						|
	MARK	m;	/* movement is relative to this mark */
 | 
						|
	long	cnt;	/* a numeric argument */
 | 
						|
	int	cmd;	/* either 'w' or 'W' */
 | 
						|
	int	prevkey;/* previous command... if 'c' then exclude whitespace */
 | 
						|
{
 | 
						|
	REG long	l;
 | 
						|
	REG char	*text;
 | 
						|
	REG int		i;
 | 
						|
 | 
						|
	DEFAULT(1);
 | 
						|
 | 
						|
	l = markline(m);
 | 
						|
	pfetch(l);
 | 
						|
	text = ptext + markidx(m);
 | 
						|
 | 
						|
#ifndef CRUNCH
 | 
						|
	/* As a special case, "cw" or "cW" on whitespace without a count
 | 
						|
	 * treats the single whitespace character under the cursor as a word.
 | 
						|
	 */
 | 
						|
	if (cnt == 1L && prevkey == 'c' && isspace(*text))
 | 
						|
	{
 | 
						|
		return m + 1L;
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	while (cnt-- > 0) /* yes, ASSIGNMENT! */
 | 
						|
	{
 | 
						|
		i = *text++;
 | 
						|
 | 
						|
		if (cmd == 'W')
 | 
						|
		{
 | 
						|
			/* include any non-whitespace */
 | 
						|
			while (i && !isspace(i))
 | 
						|
			{
 | 
						|
				i = *text++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (isalnum(i) || i == '_')
 | 
						|
		{
 | 
						|
			/* include an alphanumeric word */
 | 
						|
			while (i && isalnum(i))
 | 
						|
			{
 | 
						|
				i = *text++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			/* include contiguous punctuation */
 | 
						|
			while (i && !isalnum(i) && !isspace(i))
 | 
						|
			{
 | 
						|
				i = *text++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		/* if not part of "cw" or "cW" command... */
 | 
						|
		if (prevkey != 'c' || cnt > 0)
 | 
						|
		{
 | 
						|
			/* include trailing whitespace */
 | 
						|
			while (!i || isspace(i))
 | 
						|
			{
 | 
						|
				/* did we hit the end of this line? */
 | 
						|
				if (!i)
 | 
						|
				{
 | 
						|
					/* "dw" shouldn't delete newline after word */
 | 
						|
					if (prevkey && cnt == 0)
 | 
						|
					{
 | 
						|
						break;
 | 
						|
					}
 | 
						|
 | 
						|
					/* move to next line, if there is one */
 | 
						|
					l++;
 | 
						|
					if (l > nlines)
 | 
						|
					{
 | 
						|
						return MARK_UNSET;
 | 
						|
					}
 | 
						|
					pfetch(l);
 | 
						|
					text = ptext;
 | 
						|
				}
 | 
						|
 | 
						|
				i = *text++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		text--;
 | 
						|
	}
 | 
						|
 | 
						|
	/* if argument to operator, then back off 1 char since "w" and "W"
 | 
						|
	 * include the last char in the affected text.
 | 
						|
	 */
 | 
						|
	if (prevkey)
 | 
						|
	{
 | 
						|
		text--;
 | 
						|
	}
 | 
						|
 | 
						|
	/* construct a MARK for this place */
 | 
						|
	m = buildmark(text);
 | 
						|
	return m;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
MARK	m_bword(m, cnt, cmd)
 | 
						|
	MARK	m;	/* movement is relative to this mark */
 | 
						|
	long	cnt;	/* a numeric argument */
 | 
						|
	int	cmd;	/* either 'b' or 'B' */
 | 
						|
{
 | 
						|
	REG long	l;
 | 
						|
	REG char	*text;
 | 
						|
 | 
						|
	DEFAULT(1);
 | 
						|
 | 
						|
	l = markline(m);
 | 
						|
	pfetch(l);
 | 
						|
	text = ptext + markidx(m);
 | 
						|
	while (cnt-- > 0) /* yes, ASSIGNMENT! */
 | 
						|
	{
 | 
						|
		text--;
 | 
						|
 | 
						|
		/* include preceding whitespace */
 | 
						|
		while (text < ptext || isspace(*text))
 | 
						|
		{
 | 
						|
			/* did we hit the end of this line? */
 | 
						|
			if (text < ptext)
 | 
						|
			{
 | 
						|
				/* move to preceding line, if there is one */
 | 
						|
				l--;
 | 
						|
				if (l <= 0)
 | 
						|
				{
 | 
						|
					return MARK_UNSET;
 | 
						|
				}
 | 
						|
				pfetch(l);
 | 
						|
				text = ptext + plen - 1;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				text--;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if (cmd == 'B')
 | 
						|
		{
 | 
						|
			/* include any non-whitespace */
 | 
						|
			while (text >= ptext && !isspace(*text))
 | 
						|
			{
 | 
						|
				text--;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (isalnum(*text) || *text == '_')
 | 
						|
		{
 | 
						|
			/* include an alphanumeric word */
 | 
						|
			while (text >= ptext && isalnum(*text))
 | 
						|
			{
 | 
						|
				text--;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			/* include contiguous punctuation */
 | 
						|
			while (text >= ptext && !isalnum(*text) && !isspace(*text))
 | 
						|
			{
 | 
						|
				text--;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		text++;
 | 
						|
	}
 | 
						|
 | 
						|
	/* construct a MARK for this place */
 | 
						|
	m = buildmark(text);
 | 
						|
	return m;
 | 
						|
}
 | 
						|
 | 
						|
MARK	m_eword(m, cnt, cmd)
 | 
						|
	MARK	m;	/* movement is relative to this mark */
 | 
						|
	long	cnt;	/* a numeric argument */
 | 
						|
	int	cmd;	/* either 'e' or 'E' */
 | 
						|
{
 | 
						|
	REG long	l;
 | 
						|
	REG char	*text;
 | 
						|
	REG int		i;
 | 
						|
 | 
						|
	DEFAULT(1);
 | 
						|
 | 
						|
	l = markline(m);
 | 
						|
	pfetch(l);
 | 
						|
	text = ptext + markidx(m);
 | 
						|
	while (cnt-- > 0) /* yes, ASSIGNMENT! */
 | 
						|
	{
 | 
						|
		if (*text)
 | 
						|
			text++;
 | 
						|
		i = *text++;
 | 
						|
 | 
						|
		/* include preceding whitespace */
 | 
						|
		while (!i || isspace(i))
 | 
						|
		{
 | 
						|
			/* did we hit the end of this line? */
 | 
						|
			if (!i)
 | 
						|
			{
 | 
						|
				/* move to next line, if there is one */
 | 
						|
				l++;
 | 
						|
				if (l > nlines)
 | 
						|
				{
 | 
						|
					return MARK_UNSET;
 | 
						|
				}
 | 
						|
				pfetch(l);
 | 
						|
				text = ptext;
 | 
						|
			}
 | 
						|
 | 
						|
			i = *text++;
 | 
						|
		}
 | 
						|
 | 
						|
		if (cmd == 'E')
 | 
						|
		{
 | 
						|
			/* include any non-whitespace */
 | 
						|
			while (i && !isspace(i))
 | 
						|
			{
 | 
						|
				i = *text++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (isalnum(i) || i == '_')
 | 
						|
		{
 | 
						|
			/* include an alphanumeric word */
 | 
						|
			while (i && isalnum(i))
 | 
						|
			{
 | 
						|
				i = *text++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			/* include contiguous punctuation */
 | 
						|
			while (i && !isalnum(i) && !isspace(i))
 | 
						|
			{
 | 
						|
				i = *text++;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		text -= 2;
 | 
						|
	}
 | 
						|
 | 
						|
	/* construct a MARK for this place */
 | 
						|
	m = buildmark(text);
 | 
						|
	return m;
 | 
						|
}
 |