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);
}
|