File: mark.c

package info (click to toggle)
elvis 2.1i-3
  • links: PTS
  • area: non-free
  • in suites: hamm
  • size: 4,120 kB
  • ctags: 5,838
  • sloc: ansic: 53,854; sh: 811; makefile: 263
file content (207 lines) | stat: -rw-r--r-- 5,302 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/* mark.c */
/* Copyright 1995 by Steve Kirkendall */

char id_mark[] = "$Id: mark.c,v 2.11 1997/01/04 17:55:47 steve Exp $";

#include "elvis.h"


MARK namedmark[26];

/* Allocate a mark, pointing to a specific location in a specific buffer.  As changes are
 * make to the buffer, the mark's offset into that buffer will automatically be updated.
 */
#ifndef DEBUG_ALLOC
MARK markalloc(buffer, offset)
	BUFFER	buffer;	/* the buffer that the new mark will refer to */
	long	offset;	/* position of the mark within buffer */
{
	MARK	newp;

	newp = (MARK)safealloc(1, sizeof(MARKBUF));
#else
MARK _markalloc(file, line, buffer, offset)
	char	*file;	/* source file where allocating */
	int	line;	/* source line where allocating */
	BUFFER	buffer;	/* the buffer that the new mark will refer to */
	long	offset;	/* position of the mark within buffer */
{
	MARK	newp;

	assert(buffer != NULL && offset >= 0 && offset <= o_bufchars(buffer));

	newp = (MARK)_safealloc(file, line, False, 1, sizeof(MARKBUF));
#endif
	newp->buffer = buffer;
	newp->offset = offset;
	newp->next = bufmarks(buffer);
	bufsetmarks(buffer, newp);
	return newp;
}

/* Free a mark which was created by markalloc().  This also adjusts the
 * namedmarks[] array, if necessary.
 */
#ifndef DEBUG_ALLOC
void markfree(mark)
	MARK	mark;	/* the mark to destroy */
{
#else
void _markfree(file, line, mark)
	char	*file;
	int	line;
	MARK	mark;
{
#endif
	MARK	lag;
	int	i;

	/* remove from buffer's list of marks */
	if (mark == bufmarks(mark->buffer))
	{
		bufsetmarks(mark->buffer, mark->next);
	}
	else
	{
		for (lag = bufmarks(mark->buffer); lag->next != mark; lag = lag->next)
		{
			assert(lag->next);
		}
		lag->next = mark->next;
	}

	/* if in namedmarks, then unset the namedmarks variable */
	for (i = 0; i < QTY(namedmark); i++)
	{
		if (namedmark[i] == mark)
		{
			namedmark[i] = NULL;
			break;
		}
	}

	/* free the mark's resources */
#ifndef DEBUG_ALLOC
	safefree(mark);
#else
	_safefree(file, line, mark);
#endif
}

/* Adjust the offset of every who's offset is greater than "from".  If at "to"
 * or later, add "delta" to it.  Between "from" and "to", add some fraction
 * of "delta" to it.
 *
 * This function is meant to be called only from bufreplace().
 */
void markadjust(from, to, delta)
	MARK	from;	/* old start of text */
	MARK	to;	/* old end of text */
	long	delta;	/* difference between old "to" and new "to" offsets */
{
	MARK	mark;	/* used for scanning the buffer's mark list */
	long	dist;	/* original distance between "from" and "to" */
	long	tooff;	/* original offset of "to" */
	long	fromoff;/* original offset of "from" */

	/* trivial case */
	if (delta == 0)
	{
		return;
	}

	/* Compute some stuff that depends on the "to" mark.  Note that we
	 * must do this before the loop, because during the loop we may adjust
	 * the value of the "to" mark itself!
	 */
	tooff = to->offset;
	fromoff = from->offset;
	dist = tooff - fromoff;
	assert(from->buffer == to->buffer && -delta <= dist && dist >= 0);

	/* for every mark... */
	for (mark = bufmarks(from->buffer); mark; mark = mark->next)
	{
		/* adjust, if affected by mod */
		if (mark->offset > tooff)
		{
			mark->offset += delta;
		}
		else if (mark->offset > fromoff)
		{
			/* NOTE: At this point we know that dist!=0 because
			 * that could only happen if fromoff==tooff, and we
			 * can only get here if this mark's offset <= tooff
			 * but >fromoff.  When tooff==fromoff, that is
			 * impossible!
			 */
			mark->offset += delta * (mark->offset - from->offset) / dist;
		}
	}
}

/* Find the line number of a mark.  This is defined as being the number of
 * newlines preceding the mark, plus 1.  Note that this is not necessarily
 * how the edit mode defines lines.
 */
long markline(mark)
	MARK	mark;	/* mark to be converted */
{
	long	lnum;

	(void)lowoffset(bufbufinfo(markbuffer(mark)), markoffset(mark), NULL, NULL, NULL, &lnum);
	return lnum;
}

/* Adjust a mark so that it points to a specific line, and then return mark.
 * If the requested line doesn't exist, return NULL.
 */
MARK marksetline(mark, linenum)
	MARK	mark;	/* the mark to be adjusted */
	long	linenum;/* the desired line number */
{
	/* if bogus line number, return NULL */
	if (linenum < 1 || linenum > o_buflines(markbuffer(mark)))
	{
		return NULL;
	}

	/* else change the mark's offset & return it */
	mark->offset = lowline(bufbufinfo(markbuffer(mark)), linenum);
	assert(mark->offset < o_bufchars(markbuffer(mark)));
	return mark;
}

/* Change the buffer of a mark.  This involves deleting the mark from the mark
 * list of the old buffer, and then adding it to the list of the new buffer.
 */
void marksetbuffer(mark, buffer)
	MARK	mark;	/* the mark to be moved */
	BUFFER	buffer;	/* the new buffer that the mark should refer to */
{
	MARK	lag;

	/* if no change, then do nothing */
	if (markbuffer(mark) == buffer)
		return;

	/* remove from old buffer's list of marks */
	if (mark == bufmarks(mark->buffer))
	{
		bufsetmarks(mark->buffer, mark->next);
	}
	else
	{
		assert(bufmarks(mark->buffer));
		for (lag = bufmarks(mark->buffer); lag->next != mark; lag = lag->next)
		{
			assert(lag->next->next);
		}
		lag->next = mark->next;
	}

	/* insert it into the new buffer's list */
	mark->buffer = buffer;
	mark->next = bufmarks(buffer);
	bufsetmarks(buffer, mark);
}