2.9BSD/usr/contrib/jove/jove_delete.c

Compare this file to the similar file:
Show the results in this format:

/*
   Jonathan Payne at Lincoln-Sudbury Regional High School 5-25-83

   jove_delete.c
  
   Routines to perform deletion.  The word delete and line delete 
   use the same routine as "delete-to-killbuffer".  Character delete
   uses some of the same stuff, but doesn't save the text in the
   kill-buffer.  */

#include "jove.h"

int diffnum = 0;

/* Returns whether line1 char1 is before line2 char2 in the buffer.
   Also sets `diffnum' to the number of lines between the two for
   redisplay purposes. */

inorder(line1, char1, line2, char2)
LINE	*line1,
	*line2;
{
	register int	i = 1;
	register LINE	*lp = curbuf->b_zero;
	int	f1,
		f2;

	diffnum = f1 = f2 = 0;

	if (line1 == line2)
		return char1 < char2;

	while (lp && (!f1 || !f2)) {
		if (lp == line1)
			f1 = i;
		else if (lp == line2)
			f2 = i;
		lp = lp->l_next;
		++i;
	}
	diffnum = abs(f1 - f2);
	if (f1 == 0 || f2 == 0)
		return -1;
	return f1 < f2;
}

/* Use this when you just want to look at a line without
   changing anything.  It'll return linebuf if it is the
   current line of the current buffer (no copying). */

char *
getcptr(line, buf)
LINE	*line;
char	*buf;
{
	if (line == curline)
		return linebuf;
	else {
		ignore(getline(line->l_dline, buf));
		return buf;
	}
}

/* Use this when ggetcptr is not appropiate */

char *
getright(line, buf)
LINE	*line;
char	*buf;
{
	if (line == curline) {
		if (buf != linebuf)
			strcpy(buf, linebuf);
	} else
		ignore(getline(line->l_dline, buf));
	return buf;
}

/* Assumes that either line1 or line2 is actual the current line, so it can
   put its result into linebuf. */

patchup(line1, char1, line2, char2)
register LINE	*line1,
		*line2;
{
	char	line2buf[LBSIZE];
	register char	*twoptr;

	if (line1 != line2)
		KludgeWindows(line1, line2);
	SetModified(curbuf);
	if (line2 == curline) {		/* So we don't need to getline it */
		if (line1 == curline)
			twoptr = linebuf;
		else {
			strcpy(line2buf, linebuf);
			twoptr = line2buf;
		}
		SetLine(line1);		/* Line1 now in linebuf */
	} else
		twoptr = getright(line2, line2buf);

	curchar = char1;
	linecopy(linebuf, curchar, twoptr + char2);

	DFixMarks(line1, char1, line2, char2);
	makedirty(curline);
}

/* Deletes the region by unlinking the lines in the middle,
   and patching things up.  The unlinked lines are still in
   order.  */

LINE *
reg_delete(line1, char1, line2, char2)
LINE	*line1, *line2;
{
	LINE	*retline;

	if ((line1 == line2 && char1 == char2) || line2 == 0)
		complain((char *) 0);
	fixorder(&line1, &char1, &line2, &char2);

	retline = nbufline();	/* New buffer line */

	ignore(getright(line1, genbuf));
	if (line1 == line2)
		genbuf[char2] = '\0';

	retline->l_prev = 0;
	retline->l_dline = putline(&genbuf[char1]);
	patchup(line1, char1, line2, char2);

	if (line1 == line2)
		retline->l_next = 0;
	else {
		retline->l_next = line1->l_next;
		ignore(getright(line2, genbuf));
		genbuf[char2] = '\0';
		line2->l_dline = putline(genbuf);	/* Shorten this line */
	}

	if (line1 != line2) {
		line1->l_next = line2->l_next;
		if (line1->l_next)
			line1->l_next->l_prev = line1;
		else
			curbuf->b_dol = line1;
		line2->l_next = 0;
	}

	return retline;
}

lremove(line1, line2)
register LINE	*line1,
		*line2;
{
	LINE	*next = line1->l_next;

	if (line1 == line2)
		return;
	line1->l_next = line2->l_next;
	if (line1->l_next)
		line1->l_next->l_prev = line1;
	else
		curbuf->b_dol = line1;
	lfreereg(next, line2);	/* Put region at end of free line list */
}

/* Delete character forward */

DelNChar()
{
	del_char(1);
}

/* Delete character backward */

DelPChar()
{
	del_char(0);
}

/* Delete some characters.  If deleting `forward' then call for_char
 * to the final position otherwise call back_char.  Then delete the
 * region between the two with patchup().
 */

del_char(forward)
{
	BUFLOC	newdot,
		pt;

	if (forward) {
		DOTsave(&newdot);
		ForChar();
		DOTsave(&pt);
	} else {
		DOTsave(&pt);
		BackChar();
		DOTsave(&newdot);	/* New dot will be back here */
	}

	/* Patchup puts the result in linebuf, which is fine with us */
	patchup(newdot.p_line, newdot.p_char, pt.p_line, pt.p_char);
	lremove(newdot.p_line, pt.p_line);
}

/* This kills a region and puts it on the kill-ring.  If the last command
   was one of the kill commands, the region is appended (prepended if
   backwards) to the last entry. */
   

reg_kill(line1, char1, line2, char2, backwards)
LINE	*line1, *line2;
{
	LINE *nl, *ol;
	char buf[LBSIZE];

	fixorder(&line1, &char1, &line2, &char2);
	DotTo(line1, char1);

	nl = reg_delete(line1, char1, line2, char2);

	if (last_cmd != KILLCMD) {
		killptr = ((killptr + 1) % NUMKILLS);
		lfreelist(killbuf[killptr]);
		killbuf[killptr] = nl;
	} else {
		/* Last cmd was a KILLCMD so merge the kills */
		if (backwards) {
			LINE *fl, *lastln;

			fl = killbuf[killptr];
			lastln = lastline(nl);
			ignore(getright(lastln, buf));
			ignore(getright(fl, genbuf));
			linecopy(buf, strlen(buf), genbuf);
			lastln->l_dline = putline(buf);
			killbuf[killptr] = nl;
			lastln->l_next = fl->l_next;
		} else {
			ol = lastline(killbuf[killptr]);
			ignore(getright(ol, buf));
			ignore(getright(nl, genbuf));
			linecopy(buf, strlen(buf), genbuf);
			ol->l_dline = putline(buf);
			makedirty(ol);
			ol->l_next = nl->l_next;
		}
	}
	this_cmd = KILLCMD;
}

fixorder(line1, char1, line2, char2)
register LINE	**line1,
		**line2;
register int	*char1,
		*char2;
{
	LINE	*tline;
	int	tchar;

	if (inorder(*line1, *char1, *line2, *char2))
		return;

	tline = *line1;
	tchar = *char1;
	*line1 = *line2;
	*char1 = *char2;
	*line2 = tline;
	*char2 = tchar;
}

DelReg()
{
	register MARK	*mp = CurMark();

	reg_kill(mp->m_line, mp->m_char, curline, curchar, 0);
}

DelWtSpace()
{
	register char	c;

	while (!eolp() && ((c = linebuf[curchar]) == ' ' || c == '\t'))
		DelNChar();
	while (curchar > 0 && ((c = linebuf[curchar - 1]) == ' ' || c == '\t'))
		DelPChar();
}