|
|
1.1 root 1: /* Buffer insertion/deletion and gap motion for GNU Emacs.
2: Copyright (C) 1985 Richard M. Stallman.
3:
4: This file is part of GNU Emacs.
5:
6: GNU Emacs is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU Emacs General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU Emacs, but only under the conditions described in the
15: GNU Emacs General Public License. A copy of this license is
16: supposed to have been given to you along with GNU Emacs so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: #include "config.h"
23: #include "lisp.h"
24: #include "buffer.h"
25: #include "window.h"
26:
27: /* Move gap to position `pos'. */
28:
29: GapTo (pos)
30: int pos;
31: {
32: if (bf_p2 != bf_gap + bf_p1)
33: abort ();
34:
35: if (pos <= bf_s1)
36: gap_left (pos);
37: else if (pos > bf_s1 + 1)
38: gap_right (pos);
39: }
40:
41: gap_left (pos)
42: register int pos;
43: {
44: register unsigned char *to, *from;
45: register int i;
46:
47: pos--;
48:
49: if (unchanged_modified == bf_modified)
50: {
51: beg_unchanged = pos;
52: end_unchanged = bf_s1 + bf_s2 - pos;
53: }
54: else
55: {
56: if (bf_s2 < end_unchanged)
57: end_unchanged = bf_s2;
58: if (pos < beg_unchanged)
59: beg_unchanged = pos;
60: }
61:
62: adjust_markers (pos + 1, bf_s1 + 1, bf_gap);
63:
64: to = bf_p2;
65: from = bf_p1;
66:
67: i = bf_s1 + 1;
68: while (--i > pos)
69: to[i] = from[i];
70:
71: bf_s2 += bf_s1 - pos;
72: bf_s1 = pos;
73: }
74:
75: gap_right (pos)
76: register int pos;
77: {
78: register unsigned char *to, *from;
79: register int i;
80:
81: pos--;
82:
83: if (unchanged_modified == bf_modified)
84: {
85: beg_unchanged = pos;
86: end_unchanged = bf_s1 + bf_s2 - pos;
87: }
88: else
89: {
90: if (bf_s1 + bf_s2 - pos < end_unchanged)
91: end_unchanged = bf_s1 + bf_s2 - pos;
92: if (bf_s1 < beg_unchanged)
93: beg_unchanged = bf_s1;
94: }
95:
96: adjust_markers (bf_s1 + bf_gap + 1, pos + bf_gap + 1, - bf_gap);
97:
98: from = bf_p2;
99: to = bf_p1;
100:
101: i = bf_s1;
102: while (++i <= pos)
103: to[i] = from[i];
104:
105: bf_s2 += bf_s1 - pos;
106: bf_s1 = pos;
107: }
108:
109: /* Add `amount' to the position of every marker in the current buffer
110: whose current position is between `from' (exclusive) and `to' (inclusive).
111: Also, any markers past the outside of that interval, in the direction
112: of adjustment, are first moved back to the near end of the interval
113: and then adjusted by `amount'. */
114:
115: adjust_markers (from, to, amount)
116: register int from, to, amount;
117: {
118: Lisp_Object marker;
119: register struct Lisp_Marker *m;
120: register int mpos;
121:
122: marker = bf_cur->markers;
123:
124: while (!NULL (marker))
125: {
126: m = XMARKER (marker);
127: mpos = m->bufpos;
128: if (amount > 0)
129: {
130: if (mpos > to && mpos < to + amount)
131: mpos = to + amount;
132: }
133: else
134: {
135: if (mpos > from + amount && mpos <= from)
136: mpos = from + amount;
137: }
138: if (mpos > from && mpos <= to)
139: mpos += amount;
140: if (m->bufpos != mpos)
141: m->bufpos = mpos, m->modified++;
142: marker = m->chain;
143: }
144: }
145:
146: /* make sure that the gap in the current buffer is at least k
147: characters wide */
148:
149: make_gap (k)
150: int k;
151: {
152: register unsigned char *p1, *p2, *lim;
153:
154: if (bf_gap >= k)
155: return;
156:
157: k += 2000; /* Get more than just enough */
158:
159: p1 = (unsigned char *) realloc (bf_p1 + 1, bf_s1 + bf_s2 + k);
160: if (p1 == 0)
161: memory_full ();
162:
163: k -= bf_gap; /* Amount of increase. */
164:
165: /* Record new location of text */
166: bf_p1 = p1 - 1;
167:
168: /* Transfer the new free space from the end to the gap
169: by shifting the second segment upward */
170: p2 = bf_p1 + 1 + bf_s1 + bf_s2 + bf_gap;
171: p1 = p2 + k;
172: lim = p2 - bf_s2;
173: while (lim < p2)
174: *--p1 = *--p2;
175:
176: /* Finish updating text location data */
177: bf_gap += k;
178: bf_p2 = bf_p1 + bf_gap;
179:
180: /* Don't wait for next SetBfp; make it permanent now. */
181: bf_cur->text = bf_text;
182:
183: /* adjust markers */
184: adjust_markers (bf_s1 + 1, bf_s1 + bf_s2 + bf_gap + 1, k);
185: }
186:
187: /* Insert the character c before point */
188:
189: insert_char (c)
190: unsigned char c;
191: {
192: InsCStr (&c, 1);
193: }
194:
195: /* Insert the null-terminated string s before point */
196:
197: InsStr (s)
198: char *s;
199: {
200: InsCStr (s, strlen (s));
201: }
202:
203: /* Insert a string of specified length before point */
204:
205: InsCStr (string, length)
206: register unsigned char *string;
207: register length;
208: {
209: if (length<1)
210: return;
211:
212: prepare_to_modify_buffer ();
213: RecordInsert (point, length);
214: bf_modified++;
215:
216: if (point != bf_s1 + 1)
217: GapTo (point);
218: if (bf_gap < length)
219: make_gap (length);
220:
221: bcopy (string, bf_p1 + point, length);
222:
223: bf_gap -= length;
224: bf_p2 -= length;
225: bf_s1 += length;
226: point += length;
227: }
228:
229: /* like InsCStr except that all markers pointing at the place where
230: the insertion happens are adjusted to point after it. */
231:
232: insert_before_markers (string, length)
233: unsigned char *string;
234: register int length;
235: {
236: register int opoint = point;
237: InsCStr (string, length);
238: adjust_markers (opoint - 1, opoint, length);
239: }
240:
241: /* Delete characters in current buffer
242: from `from' up to (but not incl) `to' */
243:
244: del_range (from, to)
245: register int from, to;
246: {
247: register int numdel;
248:
249: /* Make args be valid */
250: if (from < FirstCharacter)
251: from = FirstCharacter;
252: if (to > NumCharacters)
253: to = NumCharacters + 1;
254:
255: if ((numdel = to - from) <= 0)
256: return;
257:
258: if (from < point)
259: {
260: if (point < to)
261: point = from;
262: else
263: point -= numdel;
264: }
265:
266: /* Make sure the gap is somewhere in or next to what we are deleting */
267: if (from - 1 > bf_s1)
268: gap_right (from);
269: if (to - 1 < bf_s1)
270: gap_left (to);
271:
272: prepare_to_modify_buffer ();
273: RecordDelete (from, numdel);
274: bf_modified++;
275:
276: /* All markers pointing between from and to, inclusive,
277: should now point at from. */
278: adjust_markers (to, to, -numdel);
279:
280: bf_gap += numdel;
281: bf_p2 += numdel;
282: bf_s2 -= to - 1 - bf_s1;
283: bf_s1 = from - 1;
284:
285: if (bf_s1 < beg_unchanged)
286: beg_unchanged = bf_s1;
287: if (bf_s2 < end_unchanged)
288: end_unchanged = bf_s2;
289: }
290:
291: modify_region (start, end)
292: int start, end;
293: {
294: prepare_to_modify_buffer ();
295: if (start - 1 < beg_unchanged || unchanged_modified == bf_modified)
296: beg_unchanged = start - 1;
297: if (bf_s1 + bf_s2 + 1 - end < end_unchanged
298: || unchanged_modified == bf_modified)
299: end_unchanged = bf_s1 + bf_s2 + 1 - end;
300: bf_modified++;
301: }
302:
303: prepare_to_modify_buffer ()
304: {
305: if (!NULL (bf_cur->read_only))
306: Fbarf_if_buffer_read_only();
307:
308: #ifdef CLASH_DETECTION
309: if (!NULL (bf_cur->filename)
310: && bf_cur->save_modified >= bf_modified)
311: lock_file (bf_cur->filename);
312: #endif /* CLASH_DETECTION */
313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.