File:  [MW Coherent from dump] / coherent / g / usr / bin / me / word.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:35 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * The routines in this file
 * implement commands that work word at
 * a time. There are all sorts of word mode
 * commands. If I do any sentence and/or paragraph
 * mode commands, they are likely to be put in
 * this file.
 */
#include	<stdio.h>
#if NORMAL_CHARS
#include <ctype.h>
#endif
#include	"ed.h"

/*
 * Word wrap on input.
 * called when data is typed in checks that we are at an 
 * end of line. And then trys to wrap the line.
 */
void
wrapword()
{
	register LINE *clp;
	
	if (llength(clp = curwp->w_dotp) == curwp->w_doto)
		wrapblock(clp, 0, llength(clp), 0);
}

/*
 * Refill region between mark and cursor.
 */
fillregion(f, n)
{
	REGION		region;

	if (getregion(&region) != TRUE)
		return (FALSE);

	if (!bind.fillcol) {
		mlwrite("Use <ctl-x> f to set fill collumn first");
		return (FALSE);
	}
	return (wrapblock(region.r_linep, region.r_offset, region.r_size,
						  truecol(region.r_linep, region.r_offset)));
}

/*
 * wrap a block of data. Gets the start address, size and
 * true collum of the start. Triggers when printable chars
 * are over wrap length and there is white space before them.
 */
wrapblock(lineP, offset, size, trueCol)
register LINE *lineP;
short offset, size, trueCol;
{
	int blackCt, whiteCt;

	for (blackCt = whiteCt = 0; size-- > 0; offset++) {
		if (offset == llength(lineP)) {
			if (!size)
				break;
			whiteCt = blackCt = 0;
			while (!llength(lineP = lforw(lineP))) {
				size--;
				trueCol = 0;
				offset = -1;
			}
			if (-1 == offset)
				continue;
			curwp->w_doto = offset;
			curwp->w_dotp = lineP = lback(lineP);
			ldelete(1, FALSE);
			linsert(whiteCt = 1, ' ');
			trueCol++;
			offset = curwp->w_doto - 1;
			lineP = curwp->w_dotp;
			continue;
		}
		switch (lgetc(lineP, offset)) {
		case '\t':
			taber(trueCol);
		case ' ':
			if (!blackCt)
				whiteCt++;
			else {
				whiteCt = 1;
				blackCt = 0;
			}
			break;
		default:
			if (!blackCt)
				blackCt = 1;
			else
				blackCt++;
		}
		if ((trueCol++ > bind.fillcol) && whiteCt && blackCt) {
			curwp->w_dotp = lineP;
			curwp->w_doto = offset -= whiteCt + blackCt - 1;
			lnewline();
			ldelete(whiteCt, FALSE);
			whiteCt = 0;
			offset = (trueCol = blackCt) - 1;
			lineP = curwp->w_dotp;
		}
	}
	curwp->w_doto  = llength(curwp->w_dotp);
	return (TRUE);
}

/*
 * Return TRUE if the character at dot is a character that is considered
 * to be white space. Used in wordwrap.
 * The whitespace character list is hard coded. Should be setable.
 */
inwhite()
{
	register int	c;

	if (curwp->w_doto == llength(curwp->w_dotp))
		return (FALSE);
	c = lgetc(curwp->w_dotp, curwp->w_doto);
	if (c == ' ' || c == '\t' )
		return (TRUE);
	return (FALSE);
}

/*
 * Move the cursor backward to the last bit of whitespace...
 * All of the details of motion are performed by the "backchar" and "forwchar"
 * routines. Error if you try to move beyond the buffers.
 */
backwhite()
{
	if (backchar(FALSE, 1) == FALSE)
		return (FALSE);
	while (!inwhite()) {
		if (backchar(FALSE, 1) == FALSE)
			return (FALSE);
	}
	return (forwchar(FALSE, 1));
}

/*
 * Move the cursor backward by "n" words.  All of the details of motion
 * are performed by the "backchar" and "forwchar" routines.  Error if you
 * try to move beyond the buffers.
 */
backword(f, n)
{
	if (n < 0)
		return (forwword(f, -n));
	if (backchar(FALSE, 1) == FALSE)
		return (FALSE);
	while (n--) {
		while (inword() == FALSE) {
			if (backchar(FALSE, 1) == FALSE)
				return (FALSE);
		}
		while (inword() != FALSE) {
			if (backchar(FALSE, 1) == FALSE)
				return (FALSE);
		}
	}
	return (forwchar(FALSE, 1));
}

/*
 * Move the cursor forward by the specified number of words.  All of the
 * motion is done by "forwchar".  Error if you try and move beyond the
 * buffer's end.
 */
forwword(f, n)
{
	if (n < 0)
		return (backword(f, -n));
	while (n--) {
		while (inword() == FALSE) {
			if (forwchar(FALSE, 1) == FALSE)
				return (FALSE);
		}
		while (inword() != FALSE) {
			if (forwchar(FALSE, 1) == FALSE)
				return (FALSE);
		}
	}
	return (TRUE);
}

/*
 * There is no pattern I can discover to the upper and lower case
 * of the wierd umlauts etc tacked on to ascii. These tables are the
 * convertable wierd characters upFor has the upper case and loFor
 * the corresponding lower case.
 */
static uchar upFor[8] = { 0x80, 0x9A, 0x90, 0x8E, 0x8F, 0x92, 0x99, 0 };
static uchar loFor[8] = { 0x87, 0x81, 0x82, 0x84, 0x86, 0x91, 0x94, 0 };

/*
 * Turn a char to upper case.
 */
capChar()
{
	register int c;

	if (c = islow(lgetc(curwp->w_dotp, curwp->w_doto))) {
		lputc(curwp->w_dotp, curwp->w_doto, c);
		lchange(WFHARD);
	}
	return (forwchar(FALSE, 1));
}

/*
 * If character is lower case return upper case version.
 * else return 0
 */
islow(c)
register int c;
{
#if NORMAL_CHARS
	return (islower(c) ? toupper(c) : 0);
#else
	int i, d;

	if (c>='a' && c<='z')
		return (c - ('a'-'A'));

	if (c & 0x80)
		for (i = 0; d = loFor[i]; i++)
			if (d == c)
				return (upFor[i]);
	return (0);
#endif
}

/*
 * Turn a char to lower case.
 */
lowChar()
{
	register int c;

	if (c = ishi(lgetc(curwp->w_dotp, curwp->w_doto))) {
		lputc(curwp->w_dotp, curwp->w_doto, c);
		lchange(WFHARD);
	}
	return (forwchar(FALSE, 1));
}

/*
 * If character is upper case return lower case version.
 * else return 0
 */
ishi(c)
register int c;
{
#if NORMAL_CHARS
	return (isupper(c) ? tolower(c) : 0);
#else
	int i, d;

	if (c>='A' && c<='Z')
		return (c - ('A'-'a'));

	if (c & 0x80)
		for (i = 0; d = upFor[i]; i++)
			if (d == c)
				return (loFor[i]);
	return (0);
#endif
}

/*
 * Move the cursor forward by the specified number of words.  As you move,
 * convert any characters to upper case.  Error if you try and move beyond
 * the end of the buffer.
 * Bound to "M-U".
 */
upperword(f, n)
{
	if (n < 0)
		return (FALSE);
	while (n--) {
		while (inword() == FALSE)
			if (forwchar(FALSE, 1) == FALSE)
				return (FALSE);

		while (inword() != FALSE)
			if (capChar() == FALSE)
				return (FALSE);
	}
	return (TRUE);
}

/*
 * Move the cursor forward by the specified number of words.  As you move
 * convert characters to lower case.  Error if you try and move over the
 * end of the buffer.
 * Bound to "M-L".
 */
lowerword(f, n)
{
	register int	c;

	if (n < 0)
		return (FALSE);
	while (n--) {
		while (inword() == FALSE)
			if (forwchar(FALSE, 1) == FALSE)
				return (FALSE);

		while (inword() != FALSE)
			if (lowChar() == FALSE)
				return (FALSE);
	}
	return (TRUE);
}

/*
 * Move the cursor forward by
 * the specified number of words. As you move
 * convert the first character of the word to upper
 * case, and subsequent characters to lower case. Error
 * if you try and move past the end of the buffer.
 * Bound to "M-C".
 */
capword(f, n)
{
	register int	c;

	if (n < 0)
		return (FALSE);
	while (n--) {
		while (inword() == FALSE)
			if (forwchar(FALSE, 1) == FALSE)
				return (FALSE);

		if (inword() != FALSE) {
			if (capChar() == FALSE)
				return (FALSE);
			while (inword() != FALSE)
				if (lowChar() == FALSE)
					return (FALSE);
		}
	}
	return (TRUE);
}

/*
 * Kill forward by "n" words.
 * Remember the location of dot. Move forward
 * by the right number of words. Put dot back where
 * it was and issue the kill command for the
 * right number of characters. Bound to "M-D".
 */
delfword(f, n)
{
	register int	size;
	register LINE	*dotp;
	register int	doto;

	if (n < 0)
		return (FALSE);
	dotp = curwp->w_dotp;
	doto = curwp->w_doto;
	size = 0;
	if ((lastflag&CFKILL) == 0)		/* Clear kill buffer if	*/
		kdelete();			/* last wasn't a kill.	*/
	thisflag |= CFKILL;
	while (n--) {
		while (inword() == FALSE) {
			if (forwchar(FALSE, 1) == FALSE)
				return (FALSE);
			++size;
		}
		while (inword() != FALSE) {
			if (forwchar(FALSE, 1) == FALSE)
				return (FALSE);
			++size;
		}
	}
	curwp->w_dotp = dotp;
	curwp->w_doto = doto;
	return (ldelete(size, TRUE));
}

/*
 * Kill backwards by "n" words.
 * Move backwards by the desired number of
 * words, counting the characters. When dot is
 * finally moved to its resting place, fire off
 * the kill command. Bound to "M-Rubout" and
 * to "M-Backspace".
 */
delbword(f, n)
{
	register int	size;

	if (n < 0)
		return (FALSE);
	if (backchar(FALSE, 1) == FALSE)
		return (FALSE);
	size = 0;
	if ((lastflag&CFKILL) == 0)		/* Clear kill buffer if	*/
		kdelete();			/* last wasn't a kill.	*/
	thisflag |= CFKILL;
	while (n--) {
		while (inword() == FALSE) {
			if (backchar(FALSE, 1) == FALSE)
				return (FALSE);
			++size;
		}
		while (inword() != FALSE) {
			if (backchar(FALSE, 1) == FALSE)
				return (FALSE);
			++size;
		}
	}
	if (forwchar(FALSE, 1) == FALSE)
		return (FALSE);
	return (ldelete(size, TRUE));
}

/*
 * Return TRUE if the character at dot
 * is a character that is considered to be
 * part of a word. The word character list is hard
 * coded. Should be setable.
 */
inword()
{
	register int	c;

	if (curwp->w_doto == llength(curwp->w_dotp))
		return (FALSE);
	c = lgetc(curwp->w_dotp, curwp->w_doto);
	if (c>='a' && c<='z')
		return (TRUE);
	if (c>='A' && c<='Z')
		return (TRUE);
	if (c>='0' && c<='9')
		return (TRUE);
	if (c=='$' || c=='_' || c=='\\')	/* For identifiers */
		return (TRUE);
	if (c & 0x80)
		return (TRUE);
	return (FALSE);
}

#if	LIBHELP
/*
 * Lookup the current word.
 * Error if you try and move past the end of the buffer.
 * Bound to "M-M-".  Count is passed to lookup routine.
 */
lookupword(f, n)
{
	static uchar wordplace[128];
	register uchar *cp;

	while (inword() != FALSE)		/* Get to beginning of word */
		if (backchar(FALSE, 1) == FALSE)
			break;

	while (inword() == FALSE) {		/* Advance to next word	*/
		if (forwchar(FALSE, 1) == FALSE)
			return (FALSE);
	}

	cp = wordplace;
	while (inword() != FALSE) {
		*cp++ = lgetc(curwp->w_dotp, curwp->w_doto);
		if (forwchar(FALSE, 1) == FALSE)
			break;
	}
	*cp = '\0';
	return do_lookup(wordplace, f, n);
}
#endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.