4.3BSD/usr/contrib/jove/marks.c

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

/*************************************************************************
 * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
 * provided to you without charge for use only on a licensed Unix        *
 * system.  You may copy JOVE provided that this notice is included with *
 * the copy.  You may not sell copies of this program or versions        *
 * modified for use on microcomputer systems, unless the copies are      *
 * included with a Unix system distribution and the source is provided.  *
 *************************************************************************/

int	MarksShouldFloat = 1;

#include "jove.h"

Mark *
MakeMark(line, column, type)
register Line	*line;
{
	register Mark	*newmark = (Mark *) emalloc(sizeof *newmark);

	MarkSet(newmark, line, column);
	newmark->m_next = curbuf->b_marks;
	newmark->m_floater = type;
	curbuf->b_marks = newmark;
	return newmark;
}

DelMark(m)
register Mark	*m;
{
	register Mark	*mp = curbuf->b_marks;

	if (m == mp)
		curbuf->b_marks = m->m_next;
	else {
		while (mp != 0 && mp->m_next != m)
			mp = mp->m_next;
		if (mp == 0)
			complain("Unknown mark!");
		mp->m_next = m->m_next;
	}
	free((char *) m);
}

AllMarkSet(b, line, col)
Buffer	*b;
register Line	*line;
{
	register Mark	*mp;

	for (mp = b->b_marks; mp != 0; mp = mp->m_next)
		MarkSet(mp, line, col);
}

MarkSet(m, line, column)
Mark	*m;
Line	*line;
{
	m->m_line = line;
	m->m_char = column;
}

PopMark()
{
	int	pmark;

	if (curmark == 0)
		return;
	if (curbuf->b_markring[(curbuf->b_themark + 1) % NMARKS] == 0) {
		pmark = curbuf->b_themark;
		do {
			if (--pmark < 0)
				pmark = NMARKS - 1;
		} while (curbuf->b_markring[pmark] != 0);

		curbuf->b_markring[pmark] = MakeMark(curline, curchar, MarksShouldFloat);
		ToMark(curmark);
		DelMark(curmark);
		curmark = 0;
	} else
		PtToMark();

	pmark = curbuf->b_themark - 1;
	if (pmark < 0)
		pmark = NMARKS - 1;
	curbuf->b_themark = pmark;
}

SetMark()
{
	if (exp_p)
		PopMark();
	else
		DoSetMark(curline, curchar);
}

DoSetMark(l, c)
Line	*l;
{
	curbuf->b_themark = (curbuf->b_themark + 1) % NMARKS;
	if (curmark == 0)
		curmark = MakeMark(l, c, MarksShouldFloat);
	else
		MarkSet(curmark, l, c);
	s_mess("[Point pushed]");
}

/* Move point to Mark */

ToMark(m)
Mark	*m;
{
	int	len;

	if (m == 0)
		return;
	DotTo(m->m_line, m->m_char);
	if (curchar > (len = length(curline)))
		curchar = len;
}

Mark *
CurMark()
{
	if (curmark == 0)
		complain("No mark.");
	return curmark;
}

PtToMark()
{
	Line	*mline;
	int	mchar;
	Mark	*m = CurMark();

	mline = curline;
	mchar = curchar;

	ToMark(m);
	MarkSet(m, mline, mchar);
}

/* Fix marks for after a deletion.  For now, even marks that don't
   float will actually float, because we can't allow marks to point
   to non-existant lines. */

DFixMarks(line1, char1, line2, char2)
register Line	*line1,
		*line2;
{
	register Mark	*m;
	Line	*lp = line1;

	if (curbuf->b_marks == 0)
		return;
	while (lp != line2->l_next) {
		for (m = curbuf->b_marks; m != 0; m = m->m_next) {
/*			if (!m->m_floater)
				continue; */
			if (m->m_line == lp)
				m->m_char |= (1 << 15);
		}
		lp = lp->l_next;
	}
	for (m = curbuf->b_marks; m; m = m->m_next) {
/*		if (!m->m_floater)
			continue; */
		if ((m->m_char & (1 << 15)) == 0)
			continue;	/* Not effected */
		m->m_char &= ~(1 << 15);
		if (m->m_line == line1 && m->m_char < char1)
			continue;	/* This mark is not affected */
		if (line1 == line2) {
			if (m->m_char >= char1 && m->m_char <= char2)
				m->m_char = char1;
			else if (m->m_char > char2)
				m->m_char -= (char2 - char1);
			/* Same line move the mark backward */
		} else if (m->m_line == line2) {
			if (m->m_char > char2)
				m->m_char = char1 + (m->m_char - char2);
			else
				m->m_char = char1;
			m->m_line = line1;
		} else {
			m->m_char = char1;
			m->m_line = line1;
		}
	}
}

/* Fix marks after an insertion.  Marks that don't float are ignored
   on insertion, which means PtToMark has to be careful ... */

IFixMarks(line1, char1, line2, char2)
register Line	*line1,
		*line2;
{
	register Mark	*m;

	for (m = curbuf->b_marks; m != 0; m = m->m_next) {
		if (!m->m_floater)
			continue;
		if (m->m_line == line1) {
			if (m->m_char > char1) {
				m->m_line = line2;
				if (line1 == line2)
					m->m_char += (char2 - char1);
				else
					m->m_char = char2 + (m->m_char - char1);
			}
		} 
	}
}