Mercurial > emacs
annotate src/insdel.c @ 1255:ff06503c93b4
* gud.el (gud-def): Doc fix.
(gud-gdb-marker-filter, gud-sdb-marker-filter,
gud-dbx-marker-filter): Rename the argument `s' or `str' to
`string', and change all uses; these definitions were referring to
`string', which is unbound in the lexical context, but which
happens to end up being bound to the right thing by the caller,
gud-filter.
(sdb): Set comint-prompt-regexp, not comint-prompt-pattern; the
latter doesn't exist.
(gud-dbx-debugger-setup): Use the argument `f', not the variable
`file', which happens to be bound in the caller.
(gud-filter-insert): The variable `start' is never used. The
variable `moving' is unnecessary. The variable `old-buffer' and
the unwind-protect form are unneeded, since save-excursion can do
their work. The binding of output-after-point should be done after
switching to the process's buffer, not in whatever random buffer
happens to be current when the process filter is called. There's
no need to set the process mark if we've just inserted at its
location using insert-before-markers.
(gud-read-address): Don't bother setting the variable `result'; it
is never used.
* gud.el (gud-mode-map): Bind gud-refresh to C-c C-l, not C-c l;
the latter is reserved for the user's purposes.
* gud.el (gdb, sdb, dbx): Use C-c C-r ("resume") for continuing,
instead of C-c C-c. C-c C-c should be comint-interrupt-subjob;
it's important to have that available, and the C-c C-c binding is
consistent with all the other comint-derived modes.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Tue, 29 Sep 1992 07:45:05 +0000 |
parents | 8dce1588f37f |
children | 74b26ab86df4 |
rev | line source |
---|---|
157 | 1 /* Buffer insertion/deletion and gap motion for GNU Emacs. |
2 Copyright (C) 1985, 1986 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GNU Emacs. | |
5 | |
6 GNU Emacs is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 1, or (at your option) | |
9 any later version. | |
10 | |
11 GNU Emacs is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GNU Emacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | |
20 | |
21 #include "config.h" | |
22 #include "lisp.h" | |
23 #include "buffer.h" | |
24 #include "window.h" | |
25 | |
26 /* Nonzero means don't allow protected fields to be modified. */ | |
27 | |
28 extern int check_protected_fields; | |
29 | |
30 /* Move gap to position `pos'. | |
31 Note that this can quit! */ | |
32 | |
33 move_gap (pos) | |
34 int pos; | |
35 { | |
36 if (pos < GPT) | |
37 gap_left (pos, 0); | |
38 else if (pos > GPT) | |
39 gap_right (pos); | |
40 } | |
41 | |
42 /* Move the gap to POS, which is less than the current GPT. | |
43 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */ | |
44 | |
45 gap_left (pos, newgap) | |
46 register int pos; | |
47 int newgap; | |
48 { | |
49 register unsigned char *to, *from; | |
50 register int i; | |
51 int new_s1; | |
52 | |
53 pos--; | |
54 | |
55 if (!newgap) | |
56 { | |
57 if (unchanged_modified == MODIFF) | |
58 { | |
59 beg_unchanged = pos; | |
60 end_unchanged = Z - pos - 1; | |
61 } | |
62 else | |
63 { | |
64 if (Z - GPT < end_unchanged) | |
65 end_unchanged = Z - GPT; | |
66 if (pos < beg_unchanged) | |
67 beg_unchanged = pos; | |
68 } | |
69 } | |
70 | |
71 i = GPT; | |
72 to = GAP_END_ADDR; | |
73 from = GPT_ADDR; | |
74 new_s1 = GPT - BEG; | |
75 | |
76 /* Now copy the characters. To move the gap down, | |
77 copy characters up. */ | |
78 | |
79 while (1) | |
80 { | |
81 /* I gets number of characters left to copy. */ | |
82 i = new_s1 - pos; | |
83 if (i == 0) | |
84 break; | |
85 /* If a quit is requested, stop copying now. | |
86 Change POS to be where we have actually moved the gap to. */ | |
87 if (QUITP) | |
88 { | |
89 pos = new_s1; | |
90 break; | |
91 } | |
92 /* Move at most 32000 chars before checking again for a quit. */ | |
93 if (i > 32000) | |
94 i = 32000; | |
95 #ifdef GAP_USE_BCOPY | |
96 if (i >= 128 | |
97 /* bcopy is safe if the two areas of memory do not overlap | |
98 or on systems where bcopy is always safe for moving upward. */ | |
99 && (BCOPY_UPWARD_SAFE | |
100 || to - from >= 128)) | |
101 { | |
102 /* If overlap is not safe, avoid it by not moving too many | |
103 characters at once. */ | |
104 if (!BCOPY_UPWARD_SAFE && i > to - from) | |
105 i = to - from; | |
106 new_s1 -= i; | |
107 from -= i, to -= i; | |
108 bcopy (from, to, i); | |
109 } | |
110 else | |
111 #endif | |
112 { | |
113 new_s1 -= i; | |
114 while (--i >= 0) | |
115 *--to = *--from; | |
116 } | |
117 } | |
118 | |
119 /* Adjust markers, and buffer data structure, to put the gap at POS. | |
120 POS is where the loop above stopped, which may be what was specified | |
121 or may be where a quit was detected. */ | |
122 adjust_markers (pos + 1, GPT, GAP_SIZE); | |
123 GPT = pos + 1; | |
124 QUIT; | |
125 } | |
126 | |
127 gap_right (pos) | |
128 register int pos; | |
129 { | |
130 register unsigned char *to, *from; | |
131 register int i; | |
132 int new_s1; | |
133 | |
134 pos--; | |
135 | |
136 if (unchanged_modified == MODIFF) | |
137 { | |
138 beg_unchanged = pos; | |
139 end_unchanged = Z - pos - 1; | |
140 } | |
141 else | |
142 { | |
143 if (Z - pos - 1 < end_unchanged) | |
144 end_unchanged = Z - pos - 1; | |
145 if (GPT - BEG < beg_unchanged) | |
146 beg_unchanged = GPT - BEG; | |
147 } | |
148 | |
149 i = GPT; | |
150 from = GAP_END_ADDR; | |
151 to = GPT_ADDR; | |
152 new_s1 = GPT - 1; | |
153 | |
154 /* Now copy the characters. To move the gap up, | |
155 copy characters down. */ | |
156 | |
157 while (1) | |
158 { | |
159 /* I gets number of characters left to copy. */ | |
160 i = pos - new_s1; | |
161 if (i == 0) | |
162 break; | |
163 /* If a quit is requested, stop copying now. | |
164 Change POS to be where we have actually moved the gap to. */ | |
165 if (QUITP) | |
166 { | |
167 pos = new_s1; | |
168 break; | |
169 } | |
170 /* Move at most 32000 chars before checking again for a quit. */ | |
171 if (i > 32000) | |
172 i = 32000; | |
173 #ifdef GAP_USE_BCOPY | |
174 if (i >= 128 | |
175 /* bcopy is safe if the two areas of memory do not overlap | |
176 or on systems where bcopy is always safe for moving downward. */ | |
177 && (BCOPY_DOWNWARD_SAFE | |
178 || from - to >= 128)) | |
179 { | |
180 /* If overlap is not safe, avoid it by not moving too many | |
181 characters at once. */ | |
182 if (!BCOPY_DOWNWARD_SAFE && i > from - to) | |
183 i = from - to; | |
184 new_s1 += i; | |
185 bcopy (from, to, i); | |
186 from += i, to += i; | |
187 } | |
188 else | |
189 #endif | |
190 { | |
191 new_s1 += i; | |
192 while (--i >= 0) | |
193 *to++ = *from++; | |
194 } | |
195 } | |
196 | |
197 adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE); | |
198 GPT = pos + 1; | |
199 QUIT; | |
200 } | |
201 | |
202 /* Add `amount' to the position of every marker in the current buffer | |
203 whose current position is between `from' (exclusive) and `to' (inclusive). | |
204 Also, any markers past the outside of that interval, in the direction | |
205 of adjustment, are first moved back to the near end of the interval | |
206 and then adjusted by `amount'. */ | |
207 | |
208 adjust_markers (from, to, amount) | |
209 register int from, to, amount; | |
210 { | |
211 Lisp_Object marker; | |
212 register struct Lisp_Marker *m; | |
213 register int mpos; | |
214 | |
215 marker = current_buffer->markers; | |
216 | |
484 | 217 while (!NILP (marker)) |
157 | 218 { |
219 m = XMARKER (marker); | |
220 mpos = m->bufpos; | |
221 if (amount > 0) | |
222 { | |
223 if (mpos > to && mpos < to + amount) | |
224 mpos = to + amount; | |
225 } | |
226 else | |
227 { | |
228 if (mpos > from + amount && mpos <= from) | |
229 mpos = from + amount; | |
230 } | |
231 if (mpos > from && mpos <= to) | |
232 mpos += amount; | |
233 m->bufpos = mpos; | |
234 marker = m->chain; | |
235 } | |
236 } | |
237 | |
238 /* Make the gap INCREMENT characters longer. */ | |
239 | |
240 make_gap (increment) | |
241 int increment; | |
242 { | |
243 unsigned char *result; | |
244 Lisp_Object tem; | |
245 int real_gap_loc; | |
246 int old_gap_size; | |
247 | |
248 /* If we have to get more space, get enough to last a while. */ | |
249 increment += 2000; | |
250 | |
251 result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment)); | |
252 if (result == 0) | |
253 memory_full (); | |
254 BEG_ADDR = result; | |
255 | |
256 /* Prevent quitting in move_gap. */ | |
257 tem = Vinhibit_quit; | |
258 Vinhibit_quit = Qt; | |
259 | |
260 real_gap_loc = GPT; | |
261 old_gap_size = GAP_SIZE; | |
262 | |
263 /* Call the newly allocated space a gap at the end of the whole space. */ | |
264 GPT = Z + GAP_SIZE; | |
265 GAP_SIZE = increment; | |
266 | |
267 /* Move the new gap down to be consecutive with the end of the old one. | |
268 This adjusts the markers properly too. */ | |
269 gap_left (real_gap_loc + old_gap_size, 1); | |
270 | |
271 /* Now combine the two into one large gap. */ | |
272 GAP_SIZE += old_gap_size; | |
273 GPT = real_gap_loc; | |
274 | |
275 Vinhibit_quit = tem; | |
276 } | |
277 | |
278 /* Insert a string of specified length before point. | |
279 DO NOT use this for the contents of a Lisp string! | |
280 prepare_to_modify_buffer could relocate the string. */ | |
281 | |
282 insert (string, length) | |
283 register unsigned char *string; | |
284 register length; | |
285 { | |
286 register Lisp_Object temp; | |
287 | |
288 if (length < 1) | |
289 return; | |
290 | |
291 /* Make sure point-max won't overflow after this insertion. */ | |
292 XSET (temp, Lisp_Int, length + Z); | |
293 if (length + Z != XINT (temp)) | |
294 error ("maximum buffer size exceeded"); | |
295 | |
296 prepare_to_modify_buffer (point, point); | |
297 | |
298 if (point != GPT) | |
299 move_gap (point); | |
300 if (GAP_SIZE < length) | |
301 make_gap (length - GAP_SIZE); | |
302 | |
303 record_insert (point, length); | |
304 MODIFF++; | |
305 | |
306 bcopy (string, GPT_ADDR, length); | |
307 | |
308 GAP_SIZE -= length; | |
309 GPT += length; | |
310 ZV += length; | |
311 Z += length; | |
312 SET_PT (point + length); | |
313 | |
314 signal_after_change (point-length, 0, length); | |
315 } | |
316 | |
251 | 317 /* Function to insert part of the text of a string (STRING) consisting |
318 of LENGTH characters at position POS. | |
319 It does not work to use `insert' for this, becase a GC could happen | |
320 before we bcopy the stuff into the buffer, and relocate the string | |
321 without insert noticing. */ | |
157 | 322 insert_from_string (string, pos, length) |
323 Lisp_Object string; | |
324 register int pos, length; | |
325 { | |
326 register Lisp_Object temp; | |
327 struct gcpro gcpro1; | |
328 | |
329 if (length < 1) | |
330 return; | |
331 | |
332 /* Make sure point-max won't overflow after this insertion. */ | |
333 XSET (temp, Lisp_Int, length + Z); | |
334 if (length + Z != XINT (temp)) | |
335 error ("maximum buffer size exceeded"); | |
336 | |
337 GCPRO1 (string); | |
338 prepare_to_modify_buffer (point, point); | |
339 | |
340 if (point != GPT) | |
341 move_gap (point); | |
342 if (GAP_SIZE < length) | |
343 make_gap (length - GAP_SIZE); | |
344 | |
345 record_insert (point, length); | |
346 MODIFF++; | |
347 UNGCPRO; | |
348 | |
349 bcopy (XSTRING (string)->data, GPT_ADDR, length); | |
350 | |
351 GAP_SIZE -= length; | |
352 GPT += length; | |
353 ZV += length; | |
354 Z += length; | |
484 | 355 SET_PT (point + length); |
157 | 356 |
357 signal_after_change (point-length, 0, length); | |
358 } | |
359 | |
360 /* Insert the character C before point */ | |
361 | |
362 void | |
363 insert_char (c) | |
364 unsigned char c; | |
365 { | |
366 insert (&c, 1); | |
367 } | |
368 | |
369 /* Insert the null-terminated string S before point */ | |
370 | |
371 void | |
372 insert_string (s) | |
373 char *s; | |
374 { | |
375 insert (s, strlen (s)); | |
376 } | |
377 | |
378 /* Like `insert' except that all markers pointing at the place where | |
379 the insertion happens are adjusted to point after it. | |
380 Don't use this function to insert part of a Lisp string, | |
381 since gc could happen and relocate it. */ | |
382 | |
383 insert_before_markers (string, length) | |
384 unsigned char *string; | |
385 register int length; | |
386 { | |
387 register int opoint = point; | |
388 insert (string, length); | |
389 adjust_markers (opoint - 1, opoint, length); | |
390 } | |
391 | |
392 /* Insert part of a Lisp string, relocating markers after. */ | |
393 | |
394 insert_from_string_before_markers (string, pos, length) | |
395 Lisp_Object string; | |
396 register int pos, length; | |
397 { | |
398 register int opoint = point; | |
399 insert_from_string (string, pos, length); | |
400 adjust_markers (opoint - 1, opoint, length); | |
401 } | |
402 | |
403 /* Delete characters in current buffer | |
404 from FROM up to (but not including) TO. */ | |
405 | |
406 del_range (from, to) | |
407 register int from, to; | |
408 { | |
409 register int numdel; | |
410 | |
411 /* Make args be valid */ | |
412 if (from < BEGV) | |
413 from = BEGV; | |
414 if (to > ZV) | |
415 to = ZV; | |
416 | |
417 if ((numdel = to - from) <= 0) | |
418 return; | |
419 | |
420 /* Make sure the gap is somewhere in or next to what we are deleting. */ | |
421 if (from > GPT) | |
422 gap_right (from); | |
423 if (to < GPT) | |
424 gap_left (to, 0); | |
425 | |
426 prepare_to_modify_buffer (from, to); | |
427 | |
1247
8dce1588f37f
(del_range): Call record_delete before updating point.
Richard M. Stallman <rms@gnu.org>
parents:
484
diff
changeset
|
428 record_delete (from, numdel); |
8dce1588f37f
(del_range): Call record_delete before updating point.
Richard M. Stallman <rms@gnu.org>
parents:
484
diff
changeset
|
429 MODIFF++; |
8dce1588f37f
(del_range): Call record_delete before updating point.
Richard M. Stallman <rms@gnu.org>
parents:
484
diff
changeset
|
430 |
157 | 431 /* Relocate point as if it were a marker. */ |
432 if (from < point) | |
433 { | |
434 if (point < to) | |
435 SET_PT (from); | |
436 else | |
437 SET_PT (point - numdel); | |
438 } | |
439 | |
440 /* Relocate all markers pointing into the new, larger gap | |
441 to point at the end of the text before the gap. */ | |
442 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE); | |
443 | |
444 GAP_SIZE += numdel; | |
445 ZV -= numdel; | |
446 Z -= numdel; | |
447 GPT = from; | |
448 | |
449 if (GPT - BEG < beg_unchanged) | |
450 beg_unchanged = GPT - BEG; | |
451 if (Z - GPT < end_unchanged) | |
452 end_unchanged = Z - GPT; | |
453 | |
454 signal_after_change (from, numdel, 0); | |
455 } | |
456 | |
457 modify_region (start, end) | |
458 int start, end; | |
459 { | |
460 prepare_to_modify_buffer (start, end); | |
461 | |
462 if (start - 1 < beg_unchanged || unchanged_modified == MODIFF) | |
463 beg_unchanged = start - 1; | |
464 if (Z - end < end_unchanged | |
465 || unchanged_modified == MODIFF) | |
466 end_unchanged = Z - end; | |
467 MODIFF++; | |
468 } | |
469 | |
470 /* Check that it is okay to modify the buffer between START and END. | |
471 Run the before-change-function, if any. */ | |
472 | |
473 prepare_to_modify_buffer (start, end) | |
474 Lisp_Object start, end; | |
475 { | |
484 | 476 if (!NILP (current_buffer->read_only)) |
157 | 477 Fbarf_if_buffer_read_only (); |
478 | |
479 if (check_protected_fields) | |
480 Fregion_fields (start, end, Qnil, Qt); | |
481 | |
482 #ifdef CLASH_DETECTION | |
484 | 483 if (!NILP (current_buffer->filename) |
157 | 484 && current_buffer->save_modified >= MODIFF) |
485 lock_file (current_buffer->filename); | |
486 #else | |
487 /* At least warn if this file has changed on disk since it was visited. */ | |
484 | 488 if (!NILP (current_buffer->filename) |
157 | 489 && current_buffer->save_modified >= MODIFF |
484 | 490 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ())) |
491 && !NILP (Ffile_exists_p (current_buffer->filename))) | |
157 | 492 call1 (intern ("ask-user-about-supersession-threat"), |
493 current_buffer->filename); | |
494 #endif /* not CLASH_DETECTION */ | |
495 | |
496 signal_before_change (start, end); | |
497 } | |
498 | |
499 static Lisp_Object | |
500 before_change_function_restore (value) | |
501 Lisp_Object value; | |
502 { | |
503 Vbefore_change_function = value; | |
504 } | |
505 | |
506 static Lisp_Object | |
507 after_change_function_restore (value) | |
508 Lisp_Object value; | |
509 { | |
510 Vafter_change_function = value; | |
511 } | |
512 | |
513 /* Signal a change to the buffer immediatly before it happens. | |
514 START and END are the bounds of the text to be changed, | |
515 as Lisp objects. */ | |
516 | |
517 signal_before_change (start, end) | |
518 Lisp_Object start, end; | |
519 { | |
520 /* If buffer is unmodified, run a special hook for that case. */ | |
521 if (current_buffer->save_modified >= MODIFF | |
484 | 522 && !NILP (Vfirst_change_function)) |
157 | 523 { |
524 call0 (Vfirst_change_function); | |
525 } | |
526 /* Now in any case run the before-change-function if any. */ | |
484 | 527 if (!NILP (Vbefore_change_function)) |
157 | 528 { |
529 int count = specpdl_ptr - specpdl; | |
530 Lisp_Object function; | |
531 | |
532 function = Vbefore_change_function; | |
533 record_unwind_protect (after_change_function_restore, | |
534 Vafter_change_function); | |
535 record_unwind_protect (before_change_function_restore, | |
536 Vbefore_change_function); | |
537 Vafter_change_function = Qnil; | |
538 Vbefore_change_function = Qnil; | |
539 | |
540 call2 (function, start, end); | |
541 unbind_to (count, Qnil); | |
542 } | |
543 } | |
544 | |
545 /* Signal a change immediatly after it happens. | |
546 POS is the address of the start of the changed text. | |
547 LENDEL is the number of characters of the text before the change. | |
548 (Not the whole buffer; just the part that was changed.) | |
549 LENINS is the number of characters in the changed text. */ | |
550 | |
551 signal_after_change (pos, lendel, lenins) | |
552 int pos, lendel, lenins; | |
553 { | |
484 | 554 if (!NILP (Vafter_change_function)) |
157 | 555 { |
556 int count = specpdl_ptr - specpdl; | |
557 Lisp_Object function; | |
558 function = Vafter_change_function; | |
559 | |
560 record_unwind_protect (after_change_function_restore, | |
561 Vafter_change_function); | |
562 record_unwind_protect (before_change_function_restore, | |
563 Vbefore_change_function); | |
564 Vafter_change_function = Qnil; | |
565 Vbefore_change_function = Qnil; | |
566 | |
567 call3 (function, make_number (pos), make_number (pos + lenins), | |
568 make_number (lendel)); | |
569 unbind_to (count, Qnil); | |
570 } | |
571 } |