Example #1
0
File: words.c Project: jnbek/TekNap
/* 
 * Move a relative number of words from the present mark 
 */
static const char *	move_word_rel (const char *start, const char **mark, int word, int extended)
{
	int 		counter = word;
	const char *	pointer = *mark;
	const char *	end = start + strlen(start);

	if (end == start) 	/* null string, return it */
		return start;

	CHECK_EXTENDED_SUPPORT
	if (counter > 0)
	{
	    for (;counter > 0 && pointer;counter--)
	    {
		if (extended && *pointer == '"')
		{
			const char *	after;

			if (!(after = find_forward_quote(pointer, start)))
				nappanic("find_forward returned NULL [2]");
			if (*after)
				after++;
			pointer = after;
		}
		else
			while (*pointer && !my_isspace(*pointer))
				pointer++;

		while (*pointer && my_isspace(*pointer)) 
			pointer++;
	    }
	}
	else if (counter == 0)
		pointer = *mark;
	else /* counter < 0 */
	{
	    for (; counter < 0 && pointer > start; counter++)
	    {
		if (extended && *pointer == '"')
		{
			const char *	before;

			if (!(before = find_backward_quote(pointer, start)))
				nappanic("find_backward returned NULL [2]");
			if (before > start)
				before--;
			pointer = before;
		}
		else
		    while (pointer >= start && !my_isspace(*pointer))
			pointer--;

		while (pointer > start && my_isspace(*pointer)) 
		    pointer--;
	    }

	    pointer++; /* bump up to the word we just passed */
	}

	if (mark)
		*mark = pointer;
	return pointer;
}
Example #2
0
/*
 * 'move_to_prev_word': Move a "mark" from its current position to the
 *	beginning of the "previous" word.
 *
 * Arguments:
 *  'str' - a pointer to a character pointer -- The initial value is the
 *	    "mark", and it will be changed upon return to the beginning
 *	    of the previous word.
 *  'start' - The start of the string that (*str) points to.
 *  'extended' - Whether double quoted words shall be supported
 *  'delims' - The types of double quoets to honor (if applicable)
 *
 * Return value:
 *  If (*str) points to 'start' or is NULL (there is no previous word)
 *	the return value is 0.
 *  Otherwise, the return value is 1.
 *
 * Notes:
 *  Regardless of whether 'start' is actually the start of the string that
 *    '*str' points to, this function will treat it as such and will never go
 *    backwards further than 'start'.
 *  If (*str) points to the nul that terminates 'start', then (*str) shall
 *    be set to the first character in the last word in 'start'.
 *  If (*str) points to the first character in any word, then (*str) shall
 *    be set to the first character in the full word BEFORE (*str).
 *  If (*str) points to the middle of a string, then (*str) shall be set to
 *    the first character IN THAT WORD (*str) points to.
 *  If (*str) points to a space, then (*str) shall be set to the first
 *    character in the word before the space.
 *  A "word" always begins on the second character after the end of a word
 *    because the first character after a word is a space (which is reserved
 *    because we might want to change it to a nul).  That means if there is
 *    more than one space between words, the first space belongs to the "left"
 *    word and all the rest of the spaces belong to the "right" word!
 *
 * XXX - The debugging printfs are ugly.
 */
static int	move_to_prev_word (const char **str, const char *start, int extended, const char *delims)
{
	char	what;
	int	simple;
	const char	*pos;

	if (!str || *str <= start)
		return 0;

	/* Overhead -- work out if "" support will be cheap or expensive */
	if (delims && delims[0] && delims[1] == 0) {
		if (x_debug & DEBUG_EXTRACTW_DEBUG)
			yell(".... move_to_prev_word: Simple processing");
		simple = 1;
		what = delims[0];
	} else {
		if (x_debug & DEBUG_EXTRACTW_DEBUG)
			yell(".... move_to_prev_word: Expensive processing");
		simple = 0;
		what = 255;
	}

	/* Overhead -- work out if we're doing "" support or not. */
	CHECK_EXTENDED_SUPPORT

	/* Start at the mark the user provided us */
	pos = *str;

	if (x_debug & DEBUG_EXTRACTW_DEBUG)
		yell(".... move_to_prev_word: Starting at [%s] (in [%s])", pos, start);

	/*
	 * XXX This is a hack, but what do i care?
	 * If we are pointing at the start of a string, then
	 * we want to go to the PREVIOUS word, so cheat by 
	 * stepping off the word.  This means if you want the
	 * last word, you need to point to the nul, not the last
	 * character before the nul!
	 */
	if (pos > start && isspace(pos[-1]))
		pos--;

	/*
	 * Skip over whitespace
	 */
	while (pos >= start && ((*pos == 0) || my_isspace(*pos)))
		pos--;

	/*
	 * In the above 'mark1' case (the normal case), we would be pointing
	 * at the last character in 'two'.  If this were a double quoted word
	 * then this would be a double quote of some sort, and this code
	 * checks for that.  If it finds a double quote, then it moves to the
	 * "matching" double quote.
	 */
	if (pos > start && extended == DWORD_YES && 
	     ( (simple == 1 && *pos == what) ||
	       (simple == 0 && strchr(delims, *pos)) ) )
	{
		const char *	before;

		if (x_debug & DEBUG_EXTRACTW_DEBUG)
			yell(".... move_to_prev_word: Handling extended word.");

		if (!(before = find_backward_quote(pos, start, delims)))
			panic("find_backward returned NULL [2]");

		if (x_debug & DEBUG_EXTRACTW_DEBUG)
			yell(".... move_to_prev_word: Extended word begins at [%s] (of [%s])", before, start);

		/*
		 * "Before" either points at a double quote or it points
		 * at the start of the string.  If it points at a double
		 * quote, move back one position so it points at a space.
		 */
		if (before > start)
			before--;

		/* So our new mark is the space before the double quoted word */
		pos = before;

		if (x_debug & DEBUG_EXTRACTW_DEBUG)
			yell(".... move_to_prev_word: So the position before the extended word is [%s] (of [%s])", pos, start);
	}

	/* 
	 * If this is not a double quoted word, keep moving backwards until
	 * we find a space -- so our new mark is the space before the start
	 * of the word.
	 */
	else
	{
	    if (x_debug & DEBUG_EXTRACTW_DEBUG)
		yell(".... move_to_prev_word: Handling simple word.");

	    while (pos >= start && !my_isspace(*pos))
		pos--;

	    if (x_debug & DEBUG_EXTRACTW_DEBUG)
		yell(".... move_to_prev_word: So the position before the simple word is [%s] (of [%s])", pos, start);
	}

	/*
	 * If we hit the front of the string (*gulp*), set the return value
	 * (*str) to the start of the string and just punt right here.
	 */
	if (pos <= start)
	{
		if (x_debug & DEBUG_EXTRACTW_DEBUG)
			yell(".... move_to_prev_word: Ooops. we hit the start "
				"of the string.  Stopping here.");

		*str = start;
		return 1;
	}

	/*
	 * Slurp up spaces.
	 */
	else
	{
		while (*pos && isspace(*pos))
			pos++;

		while (pos > start && isspace(pos[0]) && isspace(pos[-1]))
			pos--;
	}
	
	if (x_debug & DEBUG_EXTRACTW_DEBUG)
		yell(".... move_to_prev_word: And after we're done, [%s] is "
			"the start of the previous word!", pos);

	*str = pos;
	return 1;
}