157
|
1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
|
64770
|
2 Copyright (C) 1985, 1986, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
|
|
3 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
157
|
4
|
|
5 This file is part of GNU Emacs.
|
|
6
|
|
7 GNU Emacs is free software; you can redistribute it and/or modify
|
|
8 it under the terms of the GNU General Public License as published by
|
12244
|
9 the Free Software Foundation; either version 2, or (at your option)
|
157
|
10 any later version.
|
|
11
|
|
12 GNU Emacs is distributed in the hope that it will be useful,
|
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 GNU General Public License for more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License
|
|
18 along with GNU Emacs; see the file COPYING. If not, write to
|
64084
|
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
20 Boston, MA 02110-1301, USA. */
|
157
|
21
|
|
22
|
4696
|
23 #include <config.h>
|
157
|
24 #include "lisp.h"
|
1289
|
25 #include "intervals.h"
|
157
|
26 #include "buffer.h"
|
17034
|
27 #include "charset.h"
|
157
|
28 #include "window.h"
|
2480
|
29 #include "blockinput.h"
|
21514
|
30 #include "region-cache.h"
|
157
|
31
|
18446
|
32 #ifndef NULL
|
|
33 #define NULL 0
|
|
34 #endif
|
|
35
|
20608
|
36 static void insert_from_string_1 P_ ((Lisp_Object, int, int, int, int, int, int));
|
9656
|
37 static void insert_from_buffer_1 ();
|
20555
|
38 static void gap_left P_ ((int, int, int));
|
|
39 static void gap_right P_ ((int, int));
|
|
40 static void adjust_markers_gap_motion P_ ((int, int, int));
|
29012
|
41 static void adjust_markers_for_insert P_ ((int, int, int, int, int));
|
26731
|
42 void adjust_markers_for_delete P_ ((int, int, int, int));
|
29012
|
43 static void adjust_markers_for_replace P_ ((int, int, int, int, int, int));
|
20555
|
44 static void adjust_point P_ ((int, int));
|
6739
|
45
|
16547
|
46 Lisp_Object Fcombine_after_change_execute ();
|
|
47
|
|
48 /* Non-nil means don't call the after-change-functions right away,
|
|
49 just record an element in Vcombine_after_change_calls_list. */
|
|
50 Lisp_Object Vcombine_after_change_calls;
|
|
51
|
|
52 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
|
|
53 describing changes which happened while combine_after_change_calls
|
|
54 was nonzero. We use this to decide how to call them
|
|
55 once the deferral ends.
|
|
56
|
|
57 In each element.
|
|
58 BEG-UNCHANGED is the number of chars before the changed range.
|
|
59 END-UNCHANGED is the number of chars after the changed range,
|
|
60 and CHANGE-AMOUNT is the number of characters inserted by the change
|
|
61 (negative for a deletion). */
|
|
62 Lisp_Object combine_after_change_list;
|
|
63
|
|
64 /* Buffer which combine_after_change_list is about. */
|
|
65 Lisp_Object combine_after_change_buffer;
|
39244
|
66
|
|
67 Lisp_Object Qinhibit_modification_hooks;
|
|
68
|
20608
|
69
|
21307
|
70 /* Check all markers in the current buffer, looking for something invalid. */
|
|
71
|
|
72 static int check_markers_debug_flag;
|
|
73
|
|
74 #define CHECK_MARKERS() \
|
|
75 if (check_markers_debug_flag) \
|
|
76 check_markers (); \
|
|
77 else
|
|
78
|
|
79 void
|
|
80 check_markers ()
|
|
81 {
|
51671
|
82 register struct Lisp_Marker *tail;
|
23566
|
83 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
|
21307
|
84
|
51671
|
85 for (tail = BUF_MARKERS (current_buffer); tail; tail = tail->next)
|
21307
|
86 {
|
51671
|
87 if (tail->buffer->text != current_buffer->text)
|
21307
|
88 abort ();
|
51671
|
89 if (tail->charpos > Z)
|
21307
|
90 abort ();
|
51671
|
91 if (tail->bytepos > Z_BYTE)
|
23566
|
92 abort ();
|
51671
|
93 if (multibyte && ! CHAR_HEAD_P (FETCH_BYTE (tail->bytepos)))
|
|
94 abort ();
|
21307
|
95 }
|
|
96 }
|
|
97
|
20555
|
98 /* Move gap to position CHARPOS.
|
|
99 Note that this can quit! */
|
|
100
|
|
101 void
|
|
102 move_gap (charpos)
|
|
103 int charpos;
|
|
104 {
|
|
105 move_gap_both (charpos, charpos_to_bytepos (charpos));
|
|
106 }
|
|
107
|
|
108 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
|
157
|
109 Note that this can quit! */
|
|
110
|
10391
|
111 void
|
20555
|
112 move_gap_both (charpos, bytepos)
|
|
113 int charpos, bytepos;
|
157
|
114 {
|
20555
|
115 if (bytepos < GPT_BYTE)
|
|
116 gap_left (charpos, bytepos, 0);
|
|
117 else if (bytepos > GPT_BYTE)
|
|
118 gap_right (charpos, bytepos);
|
157
|
119 }
|
|
120
|
20555
|
121 /* Move the gap to a position less than the current GPT.
|
|
122 BYTEPOS describes the new position as a byte position,
|
|
123 and CHARPOS is the corresponding char position.
|
157
|
124 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
|
|
125
|
7108
|
126 static void
|
20555
|
127 gap_left (charpos, bytepos, newgap)
|
|
128 register int charpos, bytepos;
|
157
|
129 int newgap;
|
|
130 {
|
|
131 register unsigned char *to, *from;
|
|
132 register int i;
|
|
133 int new_s1;
|
|
134
|
|
135 if (!newgap)
|
25373
|
136 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
|
157
|
137
|
20555
|
138 i = GPT_BYTE;
|
157
|
139 to = GAP_END_ADDR;
|
|
140 from = GPT_ADDR;
|
20555
|
141 new_s1 = GPT_BYTE;
|
157
|
142
|
|
143 /* Now copy the characters. To move the gap down,
|
|
144 copy characters up. */
|
|
145
|
|
146 while (1)
|
|
147 {
|
|
148 /* I gets number of characters left to copy. */
|
20555
|
149 i = new_s1 - bytepos;
|
157
|
150 if (i == 0)
|
|
151 break;
|
|
152 /* If a quit is requested, stop copying now.
|
20555
|
153 Change BYTEPOS to be where we have actually moved the gap to. */
|
157
|
154 if (QUITP)
|
|
155 {
|
20555
|
156 bytepos = new_s1;
|
|
157 charpos = BYTE_TO_CHAR (bytepos);
|
157
|
158 break;
|
|
159 }
|
|
160 /* Move at most 32000 chars before checking again for a quit. */
|
|
161 if (i > 32000)
|
|
162 i = 32000;
|
|
163 #ifdef GAP_USE_BCOPY
|
|
164 if (i >= 128
|
|
165 /* bcopy is safe if the two areas of memory do not overlap
|
|
166 or on systems where bcopy is always safe for moving upward. */
|
|
167 && (BCOPY_UPWARD_SAFE
|
|
168 || to - from >= 128))
|
|
169 {
|
|
170 /* If overlap is not safe, avoid it by not moving too many
|
|
171 characters at once. */
|
|
172 if (!BCOPY_UPWARD_SAFE && i > to - from)
|
|
173 i = to - from;
|
|
174 new_s1 -= i;
|
|
175 from -= i, to -= i;
|
|
176 bcopy (from, to, i);
|
|
177 }
|
|
178 else
|
|
179 #endif
|
|
180 {
|
|
181 new_s1 -= i;
|
|
182 while (--i >= 0)
|
|
183 *--to = *--from;
|
|
184 }
|
|
185 }
|
|
186
|
20555
|
187 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
|
|
188 BYTEPOS is where the loop above stopped, which may be what was specified
|
157
|
189 or may be where a quit was detected. */
|
20555
|
190 adjust_markers_gap_motion (bytepos, GPT_BYTE, GAP_SIZE);
|
|
191 GPT_BYTE = bytepos;
|
|
192 GPT = charpos;
|
|
193 if (bytepos < charpos)
|
|
194 abort ();
|
17034
|
195 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
157
|
196 QUIT;
|
|
197 }
|
|
198
|
20555
|
199 /* Move the gap to a position greater than than the current GPT.
|
|
200 BYTEPOS describes the new position as a byte position,
|
|
201 and CHARPOS is the corresponding char position. */
|
|
202
|
7108
|
203 static void
|
20555
|
204 gap_right (charpos, bytepos)
|
|
205 register int charpos, bytepos;
|
157
|
206 {
|
|
207 register unsigned char *to, *from;
|
|
208 register int i;
|
|
209 int new_s1;
|
|
210
|
25373
|
211 BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
|
157
|
212
|
20555
|
213 i = GPT_BYTE;
|
157
|
214 from = GAP_END_ADDR;
|
|
215 to = GPT_ADDR;
|
20555
|
216 new_s1 = GPT_BYTE;
|
157
|
217
|
|
218 /* Now copy the characters. To move the gap up,
|
|
219 copy characters down. */
|
|
220
|
|
221 while (1)
|
|
222 {
|
|
223 /* I gets number of characters left to copy. */
|
20555
|
224 i = bytepos - new_s1;
|
157
|
225 if (i == 0)
|
|
226 break;
|
|
227 /* If a quit is requested, stop copying now.
|
20555
|
228 Change BYTEPOS to be where we have actually moved the gap to. */
|
157
|
229 if (QUITP)
|
|
230 {
|
20555
|
231 bytepos = new_s1;
|
|
232 charpos = BYTE_TO_CHAR (bytepos);
|
157
|
233 break;
|
|
234 }
|
|
235 /* Move at most 32000 chars before checking again for a quit. */
|
|
236 if (i > 32000)
|
|
237 i = 32000;
|
|
238 #ifdef GAP_USE_BCOPY
|
|
239 if (i >= 128
|
|
240 /* bcopy is safe if the two areas of memory do not overlap
|
|
241 or on systems where bcopy is always safe for moving downward. */
|
|
242 && (BCOPY_DOWNWARD_SAFE
|
|
243 || from - to >= 128))
|
|
244 {
|
|
245 /* If overlap is not safe, avoid it by not moving too many
|
|
246 characters at once. */
|
|
247 if (!BCOPY_DOWNWARD_SAFE && i > from - to)
|
|
248 i = from - to;
|
|
249 new_s1 += i;
|
|
250 bcopy (from, to, i);
|
|
251 from += i, to += i;
|
|
252 }
|
|
253 else
|
|
254 #endif
|
|
255 {
|
|
256 new_s1 += i;
|
|
257 while (--i >= 0)
|
|
258 *to++ = *from++;
|
|
259 }
|
|
260 }
|
|
261
|
20555
|
262 adjust_markers_gap_motion (GPT_BYTE + GAP_SIZE, bytepos + GAP_SIZE,
|
|
263 - GAP_SIZE);
|
|
264 GPT = charpos;
|
|
265 GPT_BYTE = bytepos;
|
|
266 if (bytepos < charpos)
|
|
267 abort ();
|
17034
|
268 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
157
|
269 QUIT;
|
|
270 }
|
20608
|
271
|
20555
|
272 /* Add AMOUNT to the byte position of every marker in the current buffer
|
|
273 whose current byte position is between FROM (exclusive) and TO (inclusive).
|
14479
|
274
|
157
|
275 Also, any markers past the outside of that interval, in the direction
|
|
276 of adjustment, are first moved back to the near end of the interval
|
14479
|
277 and then adjusted by AMOUNT.
|
|
278
|
|
279 When the latter adjustment is done, if AMOUNT is negative,
|
|
280 we record the adjustment for undo. (This case happens only for
|
20555
|
281 deletion.)
|
|
282
|
|
283 The markers' character positions are not altered,
|
|
284 because gap motion does not affect character positions. */
|
|
285
|
|
286 int adjust_markers_test;
|
157
|
287
|
7108
|
288 static void
|
20555
|
289 adjust_markers_gap_motion (from, to, amount)
|
157
|
290 register int from, to, amount;
|
|
291 {
|
20568
|
292 /* Now that a marker has a bytepos, not counting the gap,
|
|
293 nothing needs to be done here. */
|
|
294 #if 0
|
157
|
295 Lisp_Object marker;
|
|
296 register struct Lisp_Marker *m;
|
|
297 register int mpos;
|
|
298
|
10311
|
299 marker = BUF_MARKERS (current_buffer);
|
157
|
300
|
484
|
301 while (!NILP (marker))
|
157
|
302 {
|
|
303 m = XMARKER (marker);
|
20568
|
304 mpos = m->bytepos;
|
157
|
305 if (amount > 0)
|
|
306 {
|
|
307 if (mpos > to && mpos < to + amount)
|
20555
|
308 {
|
|
309 if (adjust_markers_test)
|
|
310 abort ();
|
|
311 mpos = to + amount;
|
|
312 }
|
157
|
313 }
|
|
314 else
|
|
315 {
|
14479
|
316 /* Here's the case where a marker is inside text being deleted.
|
|
317 AMOUNT can be negative for gap motion, too,
|
|
318 but then this range contains no markers. */
|
157
|
319 if (mpos > from + amount && mpos <= from)
|
14479
|
320 {
|
20555
|
321 if (adjust_markers_test)
|
|
322 abort ();
|
|
323 mpos = from + amount;
|
14479
|
324 }
|
157
|
325 }
|
|
326 if (mpos > from && mpos <= to)
|
|
327 mpos += amount;
|
|
328 m->bufpos = mpos;
|
|
329 marker = m->chain;
|
|
330 }
|
20568
|
331 #endif
|
157
|
332 }
|
20608
|
333
|
20555
|
334 /* Adjust all markers for a deletion
|
|
335 whose range in bytes is FROM_BYTE to TO_BYTE.
|
|
336 The range in charpos is FROM to TO.
|
|
337
|
|
338 This function assumes that the gap is adjacent to
|
|
339 or inside of the range being deleted. */
|
12997
|
340
|
26731
|
341 void
|
20555
|
342 adjust_markers_for_delete (from, from_byte, to, to_byte)
|
|
343 register int from, from_byte, to, to_byte;
|
|
344 {
|
|
345 Lisp_Object marker;
|
|
346 register struct Lisp_Marker *m;
|
|
347 register int charpos;
|
|
348
|
51671
|
349 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
|
20555
|
350 {
|
|
351 charpos = m->charpos;
|
|
352
|
|
353 if (charpos > Z)
|
|
354 abort ();
|
|
355
|
|
356 /* If the marker is after the deletion,
|
20568
|
357 relocate by number of chars / bytes deleted. */
|
20555
|
358 if (charpos > to)
|
20568
|
359 {
|
|
360 m->charpos -= to - from;
|
|
361 m->bytepos -= to_byte - from_byte;
|
|
362 }
|
|
363 /* Here's the case where a marker is inside text being deleted. */
|
20555
|
364 else if (charpos > from)
|
|
365 {
|
32601
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
366 if (! m->insertion_type)
|
51671
|
367 { /* Normal markers will end up at the beginning of the
|
32601
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
368 re-inserted text after undoing a deletion, and must be
|
49600
|
369 adjusted to move them to the correct place. */
|
51671
|
370 XSETMISC (marker, m);
|
32601
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
371 record_marker_adjustment (marker, from - charpos);
|
51671
|
372 }
|
32601
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
373 else if (charpos < to)
|
51671
|
374 { /* Before-insertion markers will automatically move forward
|
32601
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
375 upon re-inserting the deleted text, so we have to arrange
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
376 for them to move backward to the correct position. */
|
51671
|
377 XSETMISC (marker, m);
|
32601
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
378 record_marker_adjustment (marker, charpos - to);
|
51671
|
379 }
|
20555
|
380 m->charpos = from;
|
20568
|
381 m->bytepos = from_byte;
|
20555
|
382 }
|
32601
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
383 /* Here's the case where a before-insertion marker is immediately
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
384 before the deleted region. */
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
385 else if (charpos == from && m->insertion_type)
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
386 {
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
387 /* Undoing the change uses normal insertion, which will
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
388 incorrectly make MARKER move forward, so we arrange for it
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
389 to then move backward to the correct place at the beginning
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
390 of the deleted region. */
|
51671
|
391 XSETMISC (marker, m);
|
32601
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
392 record_marker_adjustment (marker, to - from);
|
f9b498650e20
(adjust_markers_for_delete): Handle before-insertion markers correctly.
Miles Bader <miles@gnu.org>
diff
changeset
|
393 }
|
20555
|
394 }
|
|
395 }
|
23259
|
396
|
20608
|
397
|
21126
|
398 /* Adjust markers for an insertion that stretches from FROM / FROM_BYTE
|
|
399 to TO / TO_BYTE. We have to relocate the charpos of every marker
|
|
400 that points after the insertion (but not their bytepos).
|
20555
|
401
|
|
402 When a marker points at the insertion point,
|
|
403 we advance it if either its insertion-type is t
|
|
404 or BEFORE_MARKERS is true. */
|
|
405
|
|
406 static void
|
29012
|
407 adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
|
21126
|
408 register int from, from_byte, to, to_byte;
|
29012
|
409 int before_markers;
|
12997
|
410 {
|
51671
|
411 struct Lisp_Marker *m;
|
17034
|
412 int adjusted = 0;
|
20555
|
413 int nchars = to - from;
|
|
414 int nbytes = to_byte - from_byte;
|
12997
|
415
|
51671
|
416 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
|
12997
|
417 {
|
29012
|
418 /* In a single-byte buffer, a marker's two positions must be
|
|
419 equal. */
|
21137
|
420 if (Z == Z_BYTE)
|
|
421 {
|
|
422 if (m->charpos != m->bytepos)
|
|
423 abort ();
|
|
424 }
|
|
425
|
21126
|
426 if (m->bytepos == from_byte)
|
17034
|
427 {
|
21126
|
428 if (m->insertion_type || before_markers)
|
|
429 {
|
29012
|
430 m->bytepos = to_byte;
|
|
431 m->charpos = to;
|
21126
|
432 if (m->insertion_type)
|
|
433 adjusted = 1;
|
|
434 }
|
21136
|
435 }
|
20568
|
436 else if (m->bytepos > from_byte)
|
|
437 {
|
|
438 m->bytepos += nbytes;
|
29012
|
439 m->charpos += nchars;
|
20568
|
440 }
|
12997
|
441 }
|
20555
|
442
|
|
443 /* Adjusting only markers whose insertion-type is t may result in
|
54555
b136a4512609
* insdel.c (adjust_markers_for_insert): Call fix_start_end_in_overlays.
Masatake YAMATO <jet@gyve.org>
diff
changeset
|
444 - disordered start and end in overlays, and
|
b136a4512609
* insdel.c (adjust_markers_for_insert): Call fix_start_end_in_overlays.
Masatake YAMATO <jet@gyve.org>
diff
changeset
|
445 - disordered overlays in the slot `overlays_before' of current_buffer. */
|
17034
|
446 if (adjusted)
|
54555
b136a4512609
* insdel.c (adjust_markers_for_insert): Call fix_start_end_in_overlays.
Masatake YAMATO <jet@gyve.org>
diff
changeset
|
447 {
|
b136a4512609
* insdel.c (adjust_markers_for_insert): Call fix_start_end_in_overlays.
Masatake YAMATO <jet@gyve.org>
diff
changeset
|
448 fix_start_end_in_overlays(from, to);
|
b136a4512609
* insdel.c (adjust_markers_for_insert): Call fix_start_end_in_overlays.
Masatake YAMATO <jet@gyve.org>
diff
changeset
|
449 fix_overlays_before (current_buffer, from, to);
|
b136a4512609
* insdel.c (adjust_markers_for_insert): Call fix_start_end_in_overlays.
Masatake YAMATO <jet@gyve.org>
diff
changeset
|
450 }
|
12997
|
451 }
|
|
452
|
20555
|
453 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
|
|
454
|
|
455 This is used only when the value of point changes due to an insert
|
|
456 or delete; it does not represent a conceptual change in point as a
|
|
457 marker. In particular, point is not crossing any interval
|
|
458 boundaries, so there's no need to use the usual SET_PT macro. In
|
|
459 fact it would be incorrect to do so, because either the old or the
|
|
460 new value of point is out of sync with the current set of
|
|
461 intervals. */
|
|
462
|
7109
|
463 static void
|
20555
|
464 adjust_point (nchars, nbytes)
|
|
465 int nchars, nbytes;
|
7109
|
466 {
|
20555
|
467 BUF_PT (current_buffer) += nchars;
|
|
468 BUF_PT_BYTE (current_buffer) += nbytes;
|
|
469
|
|
470 /* In a single-byte buffer, the two positions must be equal. */
|
|
471 if (ZV == ZV_BYTE
|
|
472 && PT != PT_BYTE)
|
|
473 abort ();
|
7109
|
474 }
|
157
|
475
|
21323
|
476 /* Adjust markers for a replacement of a text at FROM (FROM_BYTE) of
|
|
477 length OLD_CHARS (OLD_BYTES) to a new text of length NEW_CHARS
|
29065
|
478 (NEW_BYTES). It is assumed that OLD_CHARS > 0, i.e., this is not
|
|
479 an insertion. */
|
21323
|
480
|
|
481 static void
|
|
482 adjust_markers_for_replace (from, from_byte, old_chars, old_bytes,
|
29012
|
483 new_chars, new_bytes)
|
21323
|
484 int from, from_byte, old_chars, old_bytes, new_chars, new_bytes;
|
|
485 {
|
51671
|
486 register struct Lisp_Marker *m;
|
21323
|
487 int prev_to_byte = from_byte + old_bytes;
|
29012
|
488 int diff_chars = new_chars - old_chars;
|
21323
|
489 int diff_bytes = new_bytes - old_bytes;
|
|
490
|
51671
|
491 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
|
21323
|
492 {
|
29065
|
493 if (m->bytepos >= prev_to_byte)
|
21323
|
494 {
|
29065
|
495 m->charpos += diff_chars;
|
|
496 m->bytepos += diff_bytes;
|
21323
|
497 }
|
29065
|
498 else if (m->bytepos > from_byte)
|
21323
|
499 {
|
|
500 m->charpos = from;
|
29012
|
501 m->bytepos = from_byte;
|
21323
|
502 }
|
|
503 }
|
23455
|
504
|
|
505 CHECK_MARKERS ();
|
21323
|
506 }
|
|
507
|
|
508
|
20555
|
509 /* Make the gap NBYTES_ADDED bytes longer. */
|
157
|
510
|
10391
|
511 void
|
41830
|
512 make_gap_larger (nbytes_added)
|
20555
|
513 int nbytes_added;
|
157
|
514 {
|
|
515 Lisp_Object tem;
|
|
516 int real_gap_loc;
|
20555
|
517 int real_gap_loc_byte;
|
157
|
518 int old_gap_size;
|
|
519
|
|
520 /* If we have to get more space, get enough to last a while. */
|
20555
|
521 nbytes_added += 2000;
|
157
|
522
|
11691
|
523 /* Don't allow a buffer size that won't fit in an int
|
|
524 even if it will fit in a Lisp integer.
|
42581
5f4c5a17743f
(make_gap_larger): Make sure buffer size does not overflow range of int.
Andreas Schwab <schwab@suse.de>
diff
changeset
|
525 That won't work because so many places use `int'.
|
5f4c5a17743f
(make_gap_larger): Make sure buffer size does not overflow range of int.
Andreas Schwab <schwab@suse.de>
diff
changeset
|
526
|
5f4c5a17743f
(make_gap_larger): Make sure buffer size does not overflow range of int.
Andreas Schwab <schwab@suse.de>
diff
changeset
|
527 Make sure we don't introduce overflows in the calculation. */
|
49600
|
528
|
42581
5f4c5a17743f
(make_gap_larger): Make sure buffer size does not overflow range of int.
Andreas Schwab <schwab@suse.de>
diff
changeset
|
529 if (Z_BYTE - BEG_BYTE + GAP_SIZE
|
5f4c5a17743f
(make_gap_larger): Make sure buffer size does not overflow range of int.
Andreas Schwab <schwab@suse.de>
diff
changeset
|
530 >= (((EMACS_INT) 1 << (min (VALBITS, BITS_PER_INT) - 1)) - 1
|
5f4c5a17743f
(make_gap_larger): Make sure buffer size does not overflow range of int.
Andreas Schwab <schwab@suse.de>
diff
changeset
|
531 - nbytes_added))
|
11703
3c5b974e1c10
(make_gap): Make this new error check also check exceeding VALBITS.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
532 error ("Buffer exceeds maximum size");
|
11691
|
533
|
31603
|
534 enlarge_buffer_text (current_buffer, nbytes_added);
|
157
|
535
|
|
536 /* Prevent quitting in move_gap. */
|
|
537 tem = Vinhibit_quit;
|
|
538 Vinhibit_quit = Qt;
|
|
539
|
|
540 real_gap_loc = GPT;
|
20555
|
541 real_gap_loc_byte = GPT_BYTE;
|
157
|
542 old_gap_size = GAP_SIZE;
|
|
543
|
|
544 /* Call the newly allocated space a gap at the end of the whole space. */
|
|
545 GPT = Z + GAP_SIZE;
|
20574
|
546 GPT_BYTE = Z_BYTE + GAP_SIZE;
|
20555
|
547 GAP_SIZE = nbytes_added;
|
157
|
548
|
|
549 /* Move the new gap down to be consecutive with the end of the old one.
|
|
550 This adjusts the markers properly too. */
|
20555
|
551 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
|
157
|
552
|
|
553 /* Now combine the two into one large gap. */
|
|
554 GAP_SIZE += old_gap_size;
|
|
555 GPT = real_gap_loc;
|
20555
|
556 GPT_BYTE = real_gap_loc_byte;
|
157
|
557
|
17034
|
558 /* Put an anchor. */
|
|
559 *(Z_ADDR) = 0;
|
|
560
|
157
|
561 Vinhibit_quit = tem;
|
|
562 }
|
41830
|
563
|
|
564
|
48090
|
565 /* Make the gap NBYTES_REMOVED bytes shorter. */
|
41830
|
566
|
|
567 void
|
|
568 make_gap_smaller (nbytes_removed)
|
|
569 int nbytes_removed;
|
|
570 {
|
|
571 Lisp_Object tem;
|
|
572 int real_gap_loc;
|
|
573 int real_gap_loc_byte;
|
|
574 int real_Z;
|
|
575 int real_Z_byte;
|
43218
|
576 int real_beg_unchanged;
|
|
577 int new_gap_size;
|
41830
|
578
|
|
579 /* Make sure the gap is at least 20 bytes. */
|
|
580 if (GAP_SIZE - nbytes_removed < 20)
|
|
581 nbytes_removed = GAP_SIZE - 20;
|
|
582
|
|
583 /* Prevent quitting in move_gap. */
|
|
584 tem = Vinhibit_quit;
|
|
585 Vinhibit_quit = Qt;
|
|
586
|
|
587 real_gap_loc = GPT;
|
|
588 real_gap_loc_byte = GPT_BYTE;
|
43218
|
589 new_gap_size = GAP_SIZE - nbytes_removed;
|
41830
|
590 real_Z = Z;
|
|
591 real_Z_byte = Z_BYTE;
|
43218
|
592 real_beg_unchanged = BEG_UNCHANGED;
|
41830
|
593
|
|
594 /* Pretend that the last unwanted part of the gap is the entire gap,
|
|
595 and that the first desired part of the gap is part of the buffer
|
|
596 text. */
|
43218
|
597 bzero (GPT_ADDR, new_gap_size);
|
|
598 GPT += new_gap_size;
|
|
599 GPT_BYTE += new_gap_size;
|
|
600 Z += new_gap_size;
|
|
601 Z_BYTE += new_gap_size;
|
41830
|
602 GAP_SIZE = nbytes_removed;
|
|
603
|
|
604 /* Move the unwanted pretend gap to the end of the buffer. This
|
|
605 adjusts the markers properly too. */
|
|
606 gap_right (Z, Z_BYTE);
|
|
607
|
|
608 enlarge_buffer_text (current_buffer, -nbytes_removed);
|
|
609
|
|
610 /* Now restore the desired gap. */
|
43218
|
611 GAP_SIZE = new_gap_size;
|
41830
|
612 GPT = real_gap_loc;
|
|
613 GPT_BYTE = real_gap_loc_byte;
|
|
614 Z = real_Z;
|
|
615 Z_BYTE = real_Z_byte;
|
43218
|
616 BEG_UNCHANGED = real_beg_unchanged;
|
41830
|
617
|
|
618 /* Put an anchor. */
|
|
619 *(Z_ADDR) = 0;
|
|
620
|
|
621 Vinhibit_quit = tem;
|
|
622 }
|
|
623
|
|
624 void
|
|
625 make_gap (nbytes_added)
|
|
626 int nbytes_added;
|
|
627 {
|
|
628 if (nbytes_added >= 0)
|
|
629 make_gap_larger (nbytes_added);
|
41964
|
630 #if defined USE_MMAP_FOR_BUFFERS || defined REL_ALLOC || defined DOUG_LEA_MALLOC
|
41830
|
631 else
|
|
632 make_gap_smaller (-nbytes_added);
|
|
633 #endif
|
|
634 }
|
157
|
635
|
20608
|
636 /* Copy NBYTES bytes of text from FROM_ADDR to TO_ADDR.
|
|
637 FROM_MULTIBYTE says whether the incoming text is multibyte.
|
|
638 TO_MULTIBYTE says whether to store the text as multibyte.
|
|
639 If FROM_MULTIBYTE != TO_MULTIBYTE, we convert.
|
|
640
|
|
641 Return the number of bytes stored at TO_ADDR. */
|
|
642
|
|
643 int
|
|
644 copy_text (from_addr, to_addr, nbytes,
|
|
645 from_multibyte, to_multibyte)
|
46468
|
646 const unsigned char *from_addr;
|
20608
|
647 unsigned char *to_addr;
|
|
648 int nbytes;
|
|
649 int from_multibyte, to_multibyte;
|
|
650 {
|
|
651 if (from_multibyte == to_multibyte)
|
|
652 {
|
|
653 bcopy (from_addr, to_addr, nbytes);
|
|
654 return nbytes;
|
|
655 }
|
|
656 else if (from_multibyte)
|
|
657 {
|
|
658 int nchars = 0;
|
|
659 int bytes_left = nbytes;
|
25764
|
660 Lisp_Object tbl = Qnil;
|
22876
|
661
|
|
662 /* We set the variable tbl to the reverse table of
|
|
663 Vnonascii_translation_table in advance. */
|
|
664 if (CHAR_TABLE_P (Vnonascii_translation_table))
|
|
665 {
|
|
666 tbl = Fchar_table_extra_slot (Vnonascii_translation_table,
|
|
667 make_number (0));
|
|
668 if (!CHAR_TABLE_P (tbl))
|
|
669 tbl = Qnil;
|
|
670 }
|
20608
|
671
|
|
672 /* Convert multibyte to single byte. */
|
|
673 while (bytes_left > 0)
|
|
674 {
|
29012
|
675 int thislen, c;
|
|
676 c = STRING_CHAR_AND_LENGTH (from_addr, bytes_left, thislen);
|
22876
|
677 if (!SINGLE_BYTE_CHAR_P (c))
|
23028
|
678 c = multibyte_char_to_unibyte (c, tbl);
|
22876
|
679 *to_addr++ = c;
|
20608
|
680 from_addr += thislen;
|
21676
|
681 bytes_left -= thislen;
|
20608
|
682 nchars++;
|
|
683 }
|
|
684 return nchars;
|
|
685 }
|
|
686 else
|
|
687 {
|
|
688 unsigned char *initial_to_addr = to_addr;
|
|
689
|
|
690 /* Convert single-byte to multibyte. */
|
|
691 while (nbytes > 0)
|
|
692 {
|
|
693 int c = *from_addr++;
|
|
694
|
29012
|
695 if (c >= 0200)
|
20608
|
696 {
|
21037
|
697 c = unibyte_char_to_multibyte (c);
|
26860
|
698 to_addr += CHAR_STRING (c, to_addr);
|
20608
|
699 nbytes--;
|
|
700 }
|
|
701 else
|
|
702 /* Special case for speed. */
|
|
703 *to_addr++ = c, nbytes--;
|
|
704 }
|
|
705 return to_addr - initial_to_addr;
|
|
706 }
|
|
707 }
|
|
708
|
|
709 /* Return the number of bytes it would take
|
|
710 to convert some single-byte text to multibyte.
|
|
711 The single-byte text consists of NBYTES bytes at PTR. */
|
|
712
|
|
713 int
|
|
714 count_size_as_multibyte (ptr, nbytes)
|
46468
|
715 const unsigned char *ptr;
|
20608
|
716 int nbytes;
|
|
717 {
|
|
718 int i;
|
|
719 int outgoing_nbytes = 0;
|
|
720
|
|
721 for (i = 0; i < nbytes; i++)
|
|
722 {
|
|
723 unsigned int c = *ptr++;
|
21037
|
724
|
29012
|
725 if (c < 0200)
|
21037
|
726 outgoing_nbytes++;
|
|
727 else
|
20608
|
728 {
|
21037
|
729 c = unibyte_char_to_multibyte (c);
|
23133
48fb93ba8b10
(count_size_as_multibyte): Use macro CHAR_BYTES instead of Fchar_bytes.
Kenichi Handa <handa@m17n.org>
diff
changeset
|
730 outgoing_nbytes += CHAR_BYTES (c);
|
20608
|
731 }
|
|
732 }
|
|
733
|
|
734 return outgoing_nbytes;
|
|
735 }
|
|
736
|
157
|
737 /* Insert a string of specified length before point.
|
20608
|
738 This function judges multibyteness based on
|
|
739 enable_multibyte_characters in the current buffer;
|
|
740 it never converts between single-byte and multibyte.
|
|
741
|
9656
|
742 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
|
|
743 prepare_to_modify_buffer could relocate the text. */
|
157
|
744
|
10391
|
745 void
|
20555
|
746 insert (string, nbytes)
|
46468
|
747 register const unsigned char *string;
|
21514
|
748 register int nbytes;
|
157
|
749 {
|
20555
|
750 if (nbytes > 0)
|
6739
|
751 {
|
20555
|
752 int opoint = PT;
|
|
753 insert_1 (string, nbytes, 0, 1, 0);
|
|
754 signal_after_change (opoint, 0, PT - opoint);
|
26860
|
755 update_compositions (opoint, PT, CHECK_BORDER);
|
6739
|
756 }
|
|
757 }
|
157
|
758
|
20608
|
759 /* Likewise, but inherit text properties from neighboring characters. */
|
|
760
|
10391
|
761 void
|
20555
|
762 insert_and_inherit (string, nbytes)
|
46468
|
763 register const unsigned char *string;
|
21514
|
764 register int nbytes;
|
6739
|
765 {
|
20555
|
766 if (nbytes > 0)
|
9656
|
767 {
|
20555
|
768 int opoint = PT;
|
|
769 insert_1 (string, nbytes, 1, 1, 0);
|
|
770 signal_after_change (opoint, 0, PT - opoint);
|
26860
|
771 update_compositions (opoint, PT, CHECK_BORDER);
|
9656
|
772 }
|
|
773 }
|
|
774
|
20608
|
775 /* Insert the character C before point. Do not inherit text properties. */
|
157
|
776
|
|
777 void
|
|
778 insert_char (c)
|
17034
|
779 int c;
|
157
|
780 {
|
26860
|
781 unsigned char str[MAX_MULTIBYTE_LENGTH];
|
20608
|
782 int len;
|
|
783
|
|
784 if (! NILP (current_buffer->enable_multibyte_characters))
|
26860
|
785 len = CHAR_STRING (c, str);
|
20608
|
786 else
|
|
787 {
|
|
788 len = 1;
|
26860
|
789 str[0] = c;
|
20608
|
790 }
|
17034
|
791
|
|
792 insert (str, len);
|
157
|
793 }
|
|
794
|
20608
|
795 /* Insert the null-terminated string S before point. */
|
157
|
796
|
|
797 void
|
|
798 insert_string (s)
|
46468
|
799 const char *s;
|
157
|
800 {
|
|
801 insert (s, strlen (s));
|
|
802 }
|
|
803
|
|
804 /* Like `insert' except that all markers pointing at the place where
|
|
805 the insertion happens are adjusted to point after it.
|
|
806 Don't use this function to insert part of a Lisp string,
|
|
807 since gc could happen and relocate it. */
|
|
808
|
10391
|
809 void
|
20555
|
810 insert_before_markers (string, nbytes)
|
46468
|
811 const unsigned char *string;
|
20555
|
812 register int nbytes;
|
157
|
813 {
|
20555
|
814 if (nbytes > 0)
|
6739
|
815 {
|
20555
|
816 int opoint = PT;
|
|
817
|
|
818 insert_1 (string, nbytes, 0, 1, 1);
|
|
819 signal_after_change (opoint, 0, PT - opoint);
|
26860
|
820 update_compositions (opoint, PT, CHECK_BORDER);
|
6739
|
821 }
|
157
|
822 }
|
|
823
|
20608
|
824 /* Likewise, but inherit text properties from neighboring characters. */
|
|
825
|
10391
|
826 void
|
20555
|
827 insert_before_markers_and_inherit (string, nbytes)
|
46468
|
828 const unsigned char *string;
|
20555
|
829 register int nbytes;
|
|
830 {
|
|
831 if (nbytes > 0)
|
|
832 {
|
|
833 int opoint = PT;
|
|
834
|
|
835 insert_1 (string, nbytes, 1, 1, 1);
|
|
836 signal_after_change (opoint, 0, PT - opoint);
|
26860
|
837 update_compositions (opoint, PT, CHECK_BORDER);
|
20555
|
838 }
|
|
839 }
|
21137
|
840
|
20555
|
841 /* Subroutine used by the insert functions above. */
|
|
842
|
|
843 void
|
|
844 insert_1 (string, nbytes, inherit, prepare, before_markers)
|
46468
|
845 register const unsigned char *string;
|
20555
|
846 register int nbytes;
|
|
847 int inherit, prepare, before_markers;
|
|
848 {
|
21126
|
849 insert_1_both (string, chars_in_text (string, nbytes), nbytes,
|
|
850 inherit, prepare, before_markers);
|
|
851 }
|
29012
|
852
|
21137
|
853
|
29012
|
854 #ifdef BYTE_COMBINING_DEBUG
|
|
855
|
21126
|
856 /* See if the bytes before POS/POS_BYTE combine with bytes
|
|
857 at the start of STRING to form a single character.
|
21136
|
858 If so, return the number of bytes at the start of STRING
|
21126
|
859 which combine in this way. Otherwise, return 0. */
|
20555
|
860
|
21126
|
861 int
|
|
862 count_combining_before (string, length, pos, pos_byte)
|
46468
|
863 const unsigned char *string;
|
21126
|
864 int length;
|
|
865 int pos, pos_byte;
|
|
866 {
|
25509
|
867 int len, combining_bytes;
|
46468
|
868 const unsigned char *p;
|
20555
|
869
|
21126
|
870 if (NILP (current_buffer->enable_multibyte_characters))
|
|
871 return 0;
|
25509
|
872
|
|
873 /* At first, we can exclude the following cases:
|
|
874 (1) STRING[0] can't be a following byte of multibyte sequence.
|
|
875 (2) POS is the start of the current buffer.
|
|
876 (3) A character before POS is not a multibyte character. */
|
|
877 if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
|
21126
|
878 return 0;
|
25509
|
879 if (pos_byte == BEG_BYTE) /* case (2) */
|
21126
|
880 return 0;
|
25509
|
881 len = 1;
|
|
882 p = BYTE_POS_ADDR (pos_byte - 1);
|
|
883 while (! CHAR_HEAD_P (*p)) p--, len++;
|
|
884 if (! BASE_LEADING_CODE_P (*p)) /* case (3) */
|
21126
|
885 return 0;
|
25509
|
886
|
|
887 combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
|
|
888 if (combining_bytes <= 0)
|
|
889 /* The character preceding POS is, complete and no room for
|
|
890 combining bytes (combining_bytes == 0), or an independent 8-bit
|
|
891 character (combining_bytes < 0). */
|
21126
|
892 return 0;
|
21136
|
893
|
25509
|
894 /* We have a combination situation. Count the bytes at STRING that
|
|
895 may combine. */
|
|
896 p = string + 1;
|
21136
|
897 while (!CHAR_HEAD_P (*p) && p < string + length)
|
|
898 p++;
|
|
899
|
25509
|
900 return (combining_bytes < p - string ? combining_bytes : p - string);
|
21126
|
901 }
|
20555
|
902
|
21126
|
903 /* See if the bytes after POS/POS_BYTE combine with bytes
|
|
904 at the end of STRING to form a single character.
|
|
905 If so, return the number of bytes after POS/POS_BYTE
|
|
906 which combine in this way. Otherwise, return 0. */
|
|
907
|
|
908 int
|
|
909 count_combining_after (string, length, pos, pos_byte)
|
46468
|
910 const unsigned char *string;
|
21126
|
911 int length;
|
|
912 int pos, pos_byte;
|
|
913 {
|
25764
|
914 int opos_byte = pos_byte;
|
21126
|
915 int i;
|
25764
|
916 int bytes;
|
25509
|
917 unsigned char *bufp;
|
20555
|
918
|
21126
|
919 if (NILP (current_buffer->enable_multibyte_characters))
|
|
920 return 0;
|
25509
|
921
|
|
922 /* At first, we can exclude the following cases:
|
|
923 (1) The last byte of STRING is an ASCII.
|
|
924 (2) POS is the last of the current buffer.
|
|
925 (3) A character at POS can't be a following byte of multibyte
|
|
926 character. */
|
|
927 if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
|
21126
|
928 return 0;
|
25509
|
929 if (pos_byte == Z_BYTE) /* case (2) */
|
|
930 return 0;
|
|
931 bufp = BYTE_POS_ADDR (pos_byte);
|
|
932 if (CHAR_HEAD_P (*bufp)) /* case (3) */
|
|
933 return 0;
|
|
934
|
21126
|
935 i = length - 1;
|
23203
|
936 while (i >= 0 && ! CHAR_HEAD_P (string[i]))
|
21126
|
937 {
|
|
938 i--;
|
|
939 }
|
23203
|
940 if (i < 0)
|
|
941 {
|
25509
|
942 /* All characters in STRING are not character head. We must
|
|
943 check also preceding bytes at POS. We are sure that the gap
|
|
944 is at POS. */
|
|
945 unsigned char *p = BEG_ADDR;
|
23203
|
946 i = pos_byte - 2;
|
25509
|
947 while (i >= 0 && ! CHAR_HEAD_P (p[i]))
|
23203
|
948 i--;
|
25509
|
949 if (i < 0 || !BASE_LEADING_CODE_P (p[i]))
|
23203
|
950 return 0;
|
26860
|
951
|
25509
|
952 bytes = BYTES_BY_CHAR_HEAD (p[i]);
|
|
953 return (bytes <= pos_byte - 1 - i + length
|
|
954 ? 0
|
|
955 : bytes - (pos_byte - 1 - i + length));
|
23203
|
956 }
|
25509
|
957 if (!BASE_LEADING_CODE_P (string[i]))
|
21126
|
958 return 0;
|
25509
|
959
|
|
960 bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
|
|
961 bufp++, pos_byte++;
|
|
962 while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
|
|
963
|
|
964 return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
|
20555
|
965 }
|
|
966
|
29012
|
967 #endif
|
23566
|
968
|
21137
|
969
|
20608
|
970 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
|
|
971 starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS
|
|
972 are the same as in insert_1. */
|
157
|
973
|
10391
|
974 void
|
20608
|
975 insert_1_both (string, nchars, nbytes, inherit, prepare, before_markers)
|
46468
|
976 register const unsigned char *string;
|
20608
|
977 register int nchars, nbytes;
|
|
978 int inherit, prepare, before_markers;
|
20555
|
979 {
|
40331
|
980 if (nchars == 0)
|
|
981 return;
|
49600
|
982
|
21054
|
983 if (NILP (current_buffer->enable_multibyte_characters))
|
|
984 nchars = nbytes;
|
|
985
|
21817
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
986 if (prepare)
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
987 /* Do this before moving and increasing the gap,
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
988 because the before-change hooks might move the gap
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
989 or make it smaller. */
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
990 prepare_to_modify_buffer (PT, PT, NULL);
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
991
|
20555
|
992 if (PT != GPT)
|
|
993 move_gap_both (PT, PT_BYTE);
|
|
994 if (GAP_SIZE < nbytes)
|
|
995 make_gap (nbytes - GAP_SIZE);
|
|
996
|
29012
|
997 #ifdef BYTE_COMBINING_DEBUG
|
|
998 if (count_combining_before (string, nbytes, PT, PT_BYTE)
|
|
999 || count_combining_after (string, nbytes, PT, PT_BYTE))
|
|
1000 abort ();
|
|
1001 #endif
|
21126
|
1002
|
|
1003 /* Record deletion of the surrounding text that combines with
|
|
1004 the insertion. This, together with recording the insertion,
|
29012
|
1005 will add up to the right stuff in the undo list. */
|
|
1006 record_insert (PT, nchars);
|
20555
|
1007 MODIFF++;
|
20608
|
1008
|
|
1009 bcopy (string, GPT_ADDR, nbytes);
|
20555
|
1010
|
|
1011 GAP_SIZE -= nbytes;
|
21137
|
1012 GPT += nchars;
|
|
1013 ZV += nchars;
|
|
1014 Z += nchars;
|
20555
|
1015 GPT_BYTE += nbytes;
|
|
1016 ZV_BYTE += nbytes;
|
|
1017 Z_BYTE += nbytes;
|
|
1018 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
21137
|
1019
|
|
1020 if (GPT_BYTE < GPT)
|
|
1021 abort ();
|
|
1022
|
45818
|
1023 /* The insert may have been in the unchanged region, so check again. */
|
|
1024 if (Z - GPT < END_UNCHANGED)
|
|
1025 END_UNCHANGED = Z - GPT;
|
|
1026
|
21137
|
1027 adjust_overlays_for_insert (PT, nchars);
|
21126
|
1028 adjust_markers_for_insert (PT, PT_BYTE,
|
21137
|
1029 PT + nchars, PT_BYTE + nbytes,
|
20555
|
1030 before_markers);
|
21136
|
1031
|
21137
|
1032 if (BUF_INTERVALS (current_buffer) != 0)
|
|
1033 offset_intervals (current_buffer, PT, nchars);
|
21136
|
1034
|
|
1035 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
|
26604
|
1036 set_text_properties (make_number (PT), make_number (PT + nchars),
|
|
1037 Qnil, Qnil, Qnil);
|
21136
|
1038
|
29012
|
1039 adjust_point (nchars, nbytes);
|
23538
|
1040
|
|
1041 CHECK_MARKERS ();
|
20608
|
1042 }
|
|
1043
|
|
1044 /* Insert the part of the text of STRING, a Lisp object assumed to be
|
|
1045 of type string, consisting of the LENGTH characters (LENGTH_BYTE bytes)
|
|
1046 starting at position POS / POS_BYTE. If the text of STRING has properties,
|
|
1047 copy them into the buffer.
|
|
1048
|
|
1049 It does not work to use `insert' for this, because a GC could happen
|
|
1050 before we bcopy the stuff into the buffer, and relocate the string
|
|
1051 without insert noticing. */
|
|
1052
|
|
1053 void
|
|
1054 insert_from_string (string, pos, pos_byte, length, length_byte, inherit)
|
|
1055 Lisp_Object string;
|
|
1056 register int pos, pos_byte, length, length_byte;
|
|
1057 int inherit;
|
|
1058 {
|
21765
|
1059 int opoint = PT;
|
58735
|
1060
|
|
1061 if (SCHARS (string) == 0)
|
|
1062 return;
|
|
1063
|
21765
|
1064 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
|
|
1065 inherit, 0);
|
|
1066 signal_after_change (opoint, 0, PT - opoint);
|
26860
|
1067 update_compositions (opoint, PT, CHECK_BORDER);
|
20608
|
1068 }
|
|
1069
|
|
1070 /* Like `insert_from_string' except that all markers pointing
|
|
1071 at the place where the insertion happens are adjusted to point after it. */
|
|
1072
|
|
1073 void
|
|
1074 insert_from_string_before_markers (string, pos, pos_byte,
|
|
1075 length, length_byte, inherit)
|
|
1076 Lisp_Object string;
|
|
1077 register int pos, pos_byte, length, length_byte;
|
|
1078 int inherit;
|
|
1079 {
|
21765
|
1080 int opoint = PT;
|
58735
|
1081
|
|
1082 if (SCHARS (string) == 0)
|
|
1083 return;
|
|
1084
|
21765
|
1085 insert_from_string_1 (string, pos, pos_byte, length, length_byte,
|
|
1086 inherit, 1);
|
|
1087 signal_after_change (opoint, 0, PT - opoint);
|
26860
|
1088 update_compositions (opoint, PT, CHECK_BORDER);
|
20608
|
1089 }
|
|
1090
|
|
1091 /* Subroutine of the insertion functions above. */
|
|
1092
|
|
1093 static void
|
|
1094 insert_from_string_1 (string, pos, pos_byte, nchars, nbytes,
|
|
1095 inherit, before_markers)
|
|
1096 Lisp_Object string;
|
|
1097 register int pos, pos_byte, nchars, nbytes;
|
|
1098 int inherit, before_markers;
|
|
1099 {
|
|
1100 struct gcpro gcpro1;
|
|
1101 int outgoing_nbytes = nbytes;
|
21136
|
1102 INTERVAL intervals;
|
20608
|
1103
|
|
1104 /* Make OUTGOING_NBYTES describe the text
|
|
1105 as it will be inserted in this buffer. */
|
|
1106
|
|
1107 if (NILP (current_buffer->enable_multibyte_characters))
|
|
1108 outgoing_nbytes = nchars;
|
21246
|
1109 else if (! STRING_MULTIBYTE (string))
|
20608
|
1110 outgoing_nbytes
|
46426
|
1111 = count_size_as_multibyte (SDATA (string) + pos_byte,
|
20608
|
1112 nbytes);
|
|
1113
|
|
1114 GCPRO1 (string);
|
21817
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
1115 /* Do this before moving and increasing the gap,
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
1116 because the before-change hooks might move the gap
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
1117 or make it smaller. */
|
20608
|
1118 prepare_to_modify_buffer (PT, PT, NULL);
|
|
1119
|
|
1120 if (PT != GPT)
|
|
1121 move_gap_both (PT, PT_BYTE);
|
25170
|
1122 if (GAP_SIZE < outgoing_nbytes)
|
20608
|
1123 make_gap (outgoing_nbytes - GAP_SIZE);
|
|
1124 UNGCPRO;
|
|
1125
|
|
1126 /* Copy the string text into the buffer, perhaps converting
|
|
1127 between single-byte and multibyte. */
|
46370
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1128 copy_text (SDATA (string) + pos_byte, GPT_ADDR, nbytes,
|
21246
|
1129 STRING_MULTIBYTE (string),
|
20608
|
1130 ! NILP (current_buffer->enable_multibyte_characters));
|
|
1131
|
29012
|
1132 #ifdef BYTE_COMBINING_DEBUG
|
21126
|
1133 /* We have copied text into the gap, but we have not altered
|
|
1134 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
|
|
1135 to these functions and get the same results as we would
|
|
1136 have got earlier on. Meanwhile, PT_ADDR does point to
|
|
1137 the text that has been stored by copy_text. */
|
29012
|
1138 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
|
|
1139 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
|
|
1140 abort ();
|
|
1141 #endif
|
22107
|
1142
|
29012
|
1143 record_insert (PT, nchars);
|
21126
|
1144 MODIFF++;
|
|
1145
|
20642
|
1146 GAP_SIZE -= outgoing_nbytes;
|
21137
|
1147 GPT += nchars;
|
|
1148 ZV += nchars;
|
|
1149 Z += nchars;
|
20608
|
1150 GPT_BYTE += outgoing_nbytes;
|
|
1151 ZV_BYTE += outgoing_nbytes;
|
|
1152 Z_BYTE += outgoing_nbytes;
|
|
1153 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
21137
|
1154
|
|
1155 if (GPT_BYTE < GPT)
|
|
1156 abort ();
|
|
1157
|
45818
|
1158 /* The insert may have been in the unchanged region, so check again. */
|
|
1159 if (Z - GPT < END_UNCHANGED)
|
|
1160 END_UNCHANGED = Z - GPT;
|
|
1161
|
21137
|
1162 adjust_overlays_for_insert (PT, nchars);
|
|
1163 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
|
20608
|
1164 PT_BYTE + outgoing_nbytes,
|
|
1165 before_markers);
|
|
1166
|
21137
|
1167 offset_intervals (current_buffer, PT, nchars);
|
20608
|
1168
|
46370
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1169 intervals = STRING_INTERVALS (string);
|
29012
|
1170 /* Get the intervals for the part of the string we are inserting. */
|
46370
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1171 if (nbytes < SBYTES (string))
|
21137
|
1172 intervals = copy_intervals (intervals, pos, nchars);
|
49600
|
1173
|
21136
|
1174 /* Insert those intervals. */
|
21137
|
1175 graft_intervals_into_buffer (intervals, PT, nchars,
|
20555
|
1176 current_buffer, inherit);
|
21136
|
1177
|
29012
|
1178 adjust_point (nchars, outgoing_nbytes);
|
20555
|
1179 }
|
157
|
1180
|
20555
|
1181 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
|
|
1182 current buffer. If the text in BUF has properties, they are absorbed
|
|
1183 into the current buffer.
|
|
1184
|
|
1185 It does not work to use `insert' for this, because a malloc could happen
|
|
1186 and relocate BUF's text before the bcopy happens. */
|
|
1187
|
|
1188 void
|
|
1189 insert_from_buffer (buf, charpos, nchars, inherit)
|
|
1190 struct buffer *buf;
|
|
1191 int charpos, nchars;
|
|
1192 int inherit;
|
|
1193 {
|
21765
|
1194 int opoint = PT;
|
20555
|
1195
|
21765
|
1196 insert_from_buffer_1 (buf, charpos, nchars, inherit);
|
|
1197 signal_after_change (opoint, 0, PT - opoint);
|
26860
|
1198 update_compositions (opoint, PT, CHECK_BORDER);
|
20555
|
1199 }
|
|
1200
|
|
1201 static void
|
|
1202 insert_from_buffer_1 (buf, from, nchars, inherit)
|
|
1203 struct buffer *buf;
|
|
1204 int from, nchars;
|
|
1205 int inherit;
|
|
1206 {
|
22107
|
1207 register Lisp_Object temp;
|
23850
|
1208 int chunk, chunk_expanded;
|
20555
|
1209 int from_byte = buf_charpos_to_bytepos (buf, from);
|
|
1210 int to_byte = buf_charpos_to_bytepos (buf, from + nchars);
|
20608
|
1211 int incoming_nbytes = to_byte - from_byte;
|
|
1212 int outgoing_nbytes = incoming_nbytes;
|
21136
|
1213 INTERVAL intervals;
|
20608
|
1214
|
|
1215 /* Make OUTGOING_NBYTES describe the text
|
|
1216 as it will be inserted in this buffer. */
|
|
1217
|
|
1218 if (NILP (current_buffer->enable_multibyte_characters))
|
|
1219 outgoing_nbytes = nchars;
|
|
1220 else if (NILP (buf->enable_multibyte_characters))
|
23850
|
1221 {
|
|
1222 int outgoing_before_gap = 0;
|
|
1223 int outgoing_after_gap = 0;
|
|
1224
|
|
1225 if (from < BUF_GPT (buf))
|
|
1226 {
|
|
1227 chunk = BUF_GPT_BYTE (buf) - from_byte;
|
|
1228 if (chunk > incoming_nbytes)
|
|
1229 chunk = incoming_nbytes;
|
|
1230 outgoing_before_gap
|
|
1231 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf, from_byte),
|
|
1232 chunk);
|
|
1233 }
|
|
1234 else
|
|
1235 chunk = 0;
|
|
1236
|
|
1237 if (chunk < incoming_nbytes)
|
|
1238 outgoing_after_gap
|
49600
|
1239 = count_size_as_multibyte (BUF_BYTE_ADDRESS (buf,
|
23850
|
1240 from_byte + chunk),
|
|
1241 incoming_nbytes - chunk);
|
|
1242
|
|
1243 outgoing_nbytes = outgoing_before_gap + outgoing_after_gap;
|
|
1244 }
|
49600
|
1245
|
20555
|
1246 /* Make sure point-max won't overflow after this insertion. */
|
20608
|
1247 XSETINT (temp, outgoing_nbytes + Z);
|
|
1248 if (outgoing_nbytes + Z != XINT (temp))
|
20555
|
1249 error ("Maximum buffer size exceeded");
|
|
1250
|
21817
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
1251 /* Do this before moving and increasing the gap,
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
1252 because the before-change hooks might move the gap
|
4dbf2af94988
(insert_1_both): Call prepare_to_modify_buffer before moving or making gap.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
1253 or make it smaller. */
|
20555
|
1254 prepare_to_modify_buffer (PT, PT, NULL);
|
|
1255
|
|
1256 if (PT != GPT)
|
|
1257 move_gap_both (PT, PT_BYTE);
|
20608
|
1258 if (GAP_SIZE < outgoing_nbytes)
|
|
1259 make_gap (outgoing_nbytes - GAP_SIZE);
|
20555
|
1260
|
|
1261 if (from < BUF_GPT (buf))
|
|
1262 {
|
|
1263 chunk = BUF_GPT_BYTE (buf) - from_byte;
|
20608
|
1264 if (chunk > incoming_nbytes)
|
|
1265 chunk = incoming_nbytes;
|
23850
|
1266 /* Record number of output bytes, so we know where
|
|
1267 to put the output from the second copy_text. */
|
|
1268 chunk_expanded
|
|
1269 = copy_text (BUF_BYTE_ADDRESS (buf, from_byte),
|
|
1270 GPT_ADDR, chunk,
|
|
1271 ! NILP (buf->enable_multibyte_characters),
|
|
1272 ! NILP (current_buffer->enable_multibyte_characters));
|
20555
|
1273 }
|
|
1274 else
|
23850
|
1275 chunk_expanded = chunk = 0;
|
|
1276
|
20608
|
1277 if (chunk < incoming_nbytes)
|
|
1278 copy_text (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
|
23850
|
1279 GPT_ADDR + chunk_expanded, incoming_nbytes - chunk,
|
20608
|
1280 ! NILP (buf->enable_multibyte_characters),
|
|
1281 ! NILP (current_buffer->enable_multibyte_characters));
|
20555
|
1282
|
29012
|
1283 #ifdef BYTE_COMBINING_DEBUG
|
21126
|
1284 /* We have copied text into the gap, but we have not altered
|
|
1285 PT or PT_BYTE yet. So we can pass PT and PT_BYTE
|
|
1286 to these functions and get the same results as we would
|
21137
|
1287 have got earlier on. Meanwhile, GPT_ADDR does point to
|
21126
|
1288 the text that has been stored by copy_text. */
|
29012
|
1289 if (count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE)
|
|
1290 || count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE))
|
|
1291 abort ();
|
|
1292 #endif
|
22107
|
1293
|
29012
|
1294 record_insert (PT, nchars);
|
21126
|
1295 MODIFF++;
|
|
1296
|
20608
|
1297 GAP_SIZE -= outgoing_nbytes;
|
21137
|
1298 GPT += nchars;
|
|
1299 ZV += nchars;
|
|
1300 Z += nchars;
|
20608
|
1301 GPT_BYTE += outgoing_nbytes;
|
|
1302 ZV_BYTE += outgoing_nbytes;
|
|
1303 Z_BYTE += outgoing_nbytes;
|
20555
|
1304 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
21137
|
1305
|
|
1306 if (GPT_BYTE < GPT)
|
|
1307 abort ();
|
|
1308
|
45818
|
1309 /* The insert may have been in the unchanged region, so check again. */
|
|
1310 if (Z - GPT < END_UNCHANGED)
|
|
1311 END_UNCHANGED = Z - GPT;
|
|
1312
|
21137
|
1313 adjust_overlays_for_insert (PT, nchars);
|
|
1314 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
|
21126
|
1315 PT_BYTE + outgoing_nbytes,
|
29012
|
1316 0);
|
21136
|
1317
|
21137
|
1318 if (BUF_INTERVALS (current_buffer) != 0)
|
|
1319 offset_intervals (current_buffer, PT, nchars);
|
21136
|
1320
|
29012
|
1321 /* Get the intervals for the part of the string we are inserting. */
|
21136
|
1322 intervals = BUF_INTERVALS (buf);
|
21137
|
1323 if (outgoing_nbytes < BUF_Z_BYTE (buf) - BUF_BEG_BYTE (buf))
|
28813
|
1324 {
|
|
1325 if (buf == current_buffer && PT <= from)
|
|
1326 from += nchars;
|
|
1327 intervals = copy_intervals (intervals, from, nchars);
|
|
1328 }
|
49600
|
1329
|
21136
|
1330 /* Insert those intervals. */
|
21137
|
1331 graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit);
|
21136
|
1332
|
29012
|
1333 adjust_point (nchars, outgoing_nbytes);
|
20555
|
1334 }
|
|
1335
|
21323
|
1336 /* Record undo information and adjust markers and position keepers for
|
|
1337 a replacement of a text PREV_TEXT at FROM to a new text of LEN
|
|
1338 chars (LEN_BYTE bytes) which resides in the gap just after
|
|
1339 GPT_ADDR.
|
|
1340
|
|
1341 PREV_TEXT nil means the new text was just inserted. */
|
20937
|
1342
|
20725
|
1343 void
|
21323
|
1344 adjust_after_replace (from, from_byte, prev_text, len, len_byte)
|
|
1345 int from, from_byte, len, len_byte;
|
|
1346 Lisp_Object prev_text;
|
20725
|
1347 {
|
29012
|
1348 int nchars_del = 0, nbytes_del = 0;
|
23597
|
1349
|
29012
|
1350 #ifdef BYTE_COMBINING_DEBUG
|
|
1351 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
|
|
1352 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
|
|
1353 abort ();
|
|
1354 #endif
|
21139
|
1355
|
23538
|
1356 if (STRINGP (prev_text))
|
|
1357 {
|
46370
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1358 nchars_del = SCHARS (prev_text);
|
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1359 nbytes_del = SBYTES (prev_text);
|
23538
|
1360 }
|
|
1361
|
21139
|
1362 /* Update various buffer positions for the new text. */
|
|
1363 GAP_SIZE -= len_byte;
|
|
1364 ZV += len; Z+= len;
|
|
1365 ZV_BYTE += len_byte; Z_BYTE += len_byte;
|
|
1366 GPT += len; GPT_BYTE += len_byte;
|
|
1367 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
|
1368
|
29065
|
1369 if (nchars_del > 0)
|
|
1370 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
|
|
1371 len, len_byte);
|
|
1372 else
|
|
1373 adjust_markers_for_insert (from, from_byte,
|
|
1374 from + len, from_byte + len_byte, 0);
|
21139
|
1375
|
23538
|
1376 if (! EQ (current_buffer->undo_list, Qt))
|
|
1377 {
|
|
1378 if (nchars_del > 0)
|
29012
|
1379 record_delete (from, prev_text);
|
|
1380 record_insert (from, len);
|
23538
|
1381 }
|
21323
|
1382
|
|
1383 if (len > nchars_del)
|
|
1384 adjust_overlays_for_insert (from, len - nchars_del);
|
|
1385 else if (len < nchars_del)
|
|
1386 adjust_overlays_for_delete (from, nchars_del - len);
|
21139
|
1387 if (BUF_INTERVALS (current_buffer) != 0)
|
23137
|
1388 {
|
|
1389 offset_intervals (current_buffer, from, len - nchars_del);
|
|
1390 }
|
21139
|
1391
|
29012
|
1392 if (from < PT)
|
|
1393 adjust_point (len - nchars_del, len_byte - nbytes_del);
|
21139
|
1394
|
23566
|
1395 /* As byte combining will decrease Z, we must check this again. */
|
25373
|
1396 if (Z - GPT < END_UNCHANGED)
|
|
1397 END_UNCHANGED = Z - GPT;
|
23566
|
1398
|
21307
|
1399 CHECK_MARKERS ();
|
|
1400
|
20725
|
1401 if (len == 0)
|
|
1402 evaporate_overlays (from);
|
|
1403 MODIFF++;
|
|
1404 }
|
|
1405
|
42662
|
1406 /* Like adjust_after_replace, but doesn't require PREV_TEXT.
|
|
1407 This is for use when undo is not enabled in the current buffer. */
|
|
1408
|
|
1409 void
|
|
1410 adjust_after_replace_noundo (from, from_byte, nchars_del, nbytes_del, len, len_byte)
|
|
1411 int from, from_byte, nchars_del, nbytes_del, len, len_byte;
|
|
1412 {
|
|
1413 #ifdef BYTE_COMBINING_DEBUG
|
|
1414 if (count_combining_before (GPT_ADDR, len_byte, from, from_byte)
|
|
1415 || count_combining_after (GPT_ADDR, len_byte, from, from_byte))
|
|
1416 abort ();
|
|
1417 #endif
|
|
1418
|
|
1419 /* Update various buffer positions for the new text. */
|
|
1420 GAP_SIZE -= len_byte;
|
|
1421 ZV += len; Z+= len;
|
|
1422 ZV_BYTE += len_byte; Z_BYTE += len_byte;
|
|
1423 GPT += len; GPT_BYTE += len_byte;
|
|
1424 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
|
1425
|
|
1426 if (nchars_del > 0)
|
|
1427 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
|
|
1428 len, len_byte);
|
|
1429 else
|
|
1430 adjust_markers_for_insert (from, from_byte,
|
|
1431 from + len, from_byte + len_byte, 0);
|
|
1432
|
|
1433 if (len > nchars_del)
|
|
1434 adjust_overlays_for_insert (from, len - nchars_del);
|
|
1435 else if (len < nchars_del)
|
|
1436 adjust_overlays_for_delete (from, nchars_del - len);
|
|
1437 if (BUF_INTERVALS (current_buffer) != 0)
|
|
1438 {
|
|
1439 offset_intervals (current_buffer, from, len - nchars_del);
|
|
1440 }
|
|
1441
|
|
1442 if (from < PT)
|
|
1443 adjust_point (len - nchars_del, len_byte - nbytes_del);
|
|
1444
|
|
1445 /* As byte combining will decrease Z, we must check this again. */
|
|
1446 if (Z - GPT < END_UNCHANGED)
|
|
1447 END_UNCHANGED = Z - GPT;
|
|
1448
|
|
1449 CHECK_MARKERS ();
|
|
1450
|
|
1451 if (len == 0)
|
|
1452 evaporate_overlays (from);
|
|
1453 MODIFF++;
|
|
1454 }
|
|
1455
|
21323
|
1456 /* Record undo information, adjust markers and position keepers for an
|
|
1457 insertion of a text from FROM (FROM_BYTE) to TO (TO_BYTE). The
|
|
1458 text already exists in the current buffer but character length (TO
|
|
1459 - FROM) may be incorrect, the correct length is NEWLEN. */
|
|
1460
|
|
1461 void
|
|
1462 adjust_after_insert (from, from_byte, to, to_byte, newlen)
|
|
1463 int from, from_byte, to, to_byte, newlen;
|
|
1464 {
|
|
1465 int len = to - from, len_byte = to_byte - from_byte;
|
|
1466
|
|
1467 if (GPT != to)
|
|
1468 move_gap_both (to, to_byte);
|
|
1469 GAP_SIZE += len_byte;
|
|
1470 GPT -= len; GPT_BYTE -= len_byte;
|
|
1471 ZV -= len; ZV_BYTE -= len_byte;
|
|
1472 Z -= len; Z_BYTE -= len_byte;
|
|
1473 adjust_after_replace (from, from_byte, Qnil, newlen, len_byte);
|
|
1474 }
|
57878
|
1475
|
20555
|
1476 /* Replace the text from character positions FROM to TO with NEW,
|
18830
|
1477 If PREPARE is nonzero, call prepare_to_modify_buffer.
|
|
1478 If INHERIT, the newly inserted text should inherit text properties
|
|
1479 from the surrounding non-deleted text. */
|
|
1480
|
|
1481 /* Note that this does not yet handle markers quite right.
|
|
1482 Also it needs to record a single undo-entry that does a replacement
|
|
1483 rather than a separate delete and insert.
|
23053
|
1484 That way, undo will also handle markers properly.
|
|
1485
|
|
1486 But if MARKERS is 0, don't relocate markers. */
|
18830
|
1487
|
|
1488 void
|
23053
|
1489 replace_range (from, to, new, prepare, inherit, markers)
|
18830
|
1490 Lisp_Object new;
|
23053
|
1491 int from, to, prepare, inherit, markers;
|
18830
|
1492 {
|
46370
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1493 int inschars = SCHARS (new);
|
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1494 int insbytes = SBYTES (new);
|
20555
|
1495 int from_byte, to_byte;
|
|
1496 int nbytes_del, nchars_del;
|
18830
|
1497 register Lisp_Object temp;
|
|
1498 struct gcpro gcpro1;
|
21136
|
1499 INTERVAL intervals;
|
21137
|
1500 int outgoing_insbytes = insbytes;
|
23259
|
1501 Lisp_Object deletion;
|
18830
|
1502
|
21307
|
1503 CHECK_MARKERS ();
|
|
1504
|
18830
|
1505 GCPRO1 (new);
|
31829
|
1506 deletion = Qnil;
|
18830
|
1507
|
|
1508 if (prepare)
|
|
1509 {
|
|
1510 int range_length = to - from;
|
|
1511 prepare_to_modify_buffer (from, to, &from);
|
|
1512 to = from + range_length;
|
|
1513 }
|
|
1514
|
20555
|
1515 UNGCPRO;
|
|
1516
|
18830
|
1517 /* Make args be valid */
|
|
1518 if (from < BEGV)
|
|
1519 from = BEGV;
|
|
1520 if (to > ZV)
|
|
1521 to = ZV;
|
|
1522
|
20555
|
1523 from_byte = CHAR_TO_BYTE (from);
|
|
1524 to_byte = CHAR_TO_BYTE (to);
|
18830
|
1525
|
20555
|
1526 nchars_del = to - from;
|
|
1527 nbytes_del = to_byte - from_byte;
|
|
1528
|
|
1529 if (nbytes_del <= 0 && insbytes == 0)
|
|
1530 return;
|
18830
|
1531
|
21137
|
1532 /* Make OUTGOING_INSBYTES describe the text
|
|
1533 as it will be inserted in this buffer. */
|
|
1534
|
|
1535 if (NILP (current_buffer->enable_multibyte_characters))
|
|
1536 outgoing_insbytes = inschars;
|
21246
|
1537 else if (! STRING_MULTIBYTE (new))
|
21137
|
1538 outgoing_insbytes
|
46370
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1539 = count_size_as_multibyte (SDATA (new), insbytes);
|
21137
|
1540
|
18830
|
1541 /* Make sure point-max won't overflow after this insertion. */
|
20555
|
1542 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
|
|
1543 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
|
|
1544 error ("Maximum buffer size exceeded");
|
18830
|
1545
|
|
1546 GCPRO1 (new);
|
|
1547
|
|
1548 /* Make sure the gap is somewhere in or next to what we are deleting. */
|
|
1549 if (from > GPT)
|
20555
|
1550 gap_right (from, from_byte);
|
18830
|
1551 if (to < GPT)
|
20555
|
1552 gap_left (to, to_byte, 0);
|
18830
|
1553
|
23597
|
1554 /* Even if we don't record for undo, we must keep the original text
|
|
1555 because we may have to recover it because of inappropriate byte
|
|
1556 combining. */
|
29012
|
1557 if (! EQ (current_buffer->undo_list, Qt))
|
|
1558 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
|
23259
|
1559
|
20555
|
1560 GAP_SIZE += nbytes_del;
|
|
1561 ZV -= nchars_del;
|
|
1562 Z -= nchars_del;
|
|
1563 ZV_BYTE -= nbytes_del;
|
|
1564 Z_BYTE -= nbytes_del;
|
18830
|
1565 GPT = from;
|
20555
|
1566 GPT_BYTE = from_byte;
|
55740
eba675d00657
(del_range_2, replace_range): Don't write an anchor if the gap is empty.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
1567 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
18830
|
1568
|
20555
|
1569 if (GPT_BYTE < GPT)
|
|
1570 abort ();
|
|
1571
|
25373
|
1572 if (GPT - BEG < BEG_UNCHANGED)
|
|
1573 BEG_UNCHANGED = GPT - BEG;
|
|
1574 if (Z - GPT < END_UNCHANGED)
|
|
1575 END_UNCHANGED = Z - GPT;
|
18830
|
1576
|
20555
|
1577 if (GAP_SIZE < insbytes)
|
|
1578 make_gap (insbytes - GAP_SIZE);
|
18830
|
1579
|
21137
|
1580 /* Copy the string text into the buffer, perhaps converting
|
|
1581 between single-byte and multibyte. */
|
46370
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1582 copy_text (SDATA (new), GPT_ADDR, insbytes,
|
21246
|
1583 STRING_MULTIBYTE (new),
|
21137
|
1584 ! NILP (current_buffer->enable_multibyte_characters));
|
|
1585
|
29012
|
1586 #ifdef BYTE_COMBINING_DEBUG
|
22896
|
1587 /* We have copied text into the gap, but we have not marked
|
|
1588 it as part of the buffer. So we can use the old FROM and FROM_BYTE
|
|
1589 here, for both the previous text and the following text.
|
|
1590 Meanwhile, GPT_ADDR does point to
|
21126
|
1591 the text that has been stored by copy_text. */
|
29012
|
1592 if (count_combining_before (GPT_ADDR, outgoing_insbytes, from, from_byte)
|
|
1593 || count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte))
|
|
1594 abort ();
|
|
1595 #endif
|
21126
|
1596
|
23259
|
1597 if (! EQ (current_buffer->undo_list, Qt))
|
|
1598 {
|
29012
|
1599 record_delete (from, deletion);
|
|
1600 record_insert (from, inschars);
|
23259
|
1601 }
|
18830
|
1602
|
21137
|
1603 GAP_SIZE -= outgoing_insbytes;
|
|
1604 GPT += inschars;
|
|
1605 ZV += inschars;
|
|
1606 Z += inschars;
|
|
1607 GPT_BYTE += outgoing_insbytes;
|
|
1608 ZV_BYTE += outgoing_insbytes;
|
|
1609 Z_BYTE += outgoing_insbytes;
|
|
1610 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
18830
|
1611
|
20555
|
1612 if (GPT_BYTE < GPT)
|
|
1613 abort ();
|
|
1614
|
18830
|
1615 /* Adjust the overlay center as needed. This must be done after
|
|
1616 adjusting the markers that bound the overlays. */
|
20555
|
1617 adjust_overlays_for_delete (from, nchars_del);
|
21137
|
1618 adjust_overlays_for_insert (from, inschars);
|
40923
|
1619
|
|
1620 /* Adjust markers for the deletion and the insertion. */
|
23053
|
1621 if (markers)
|
40923
|
1622 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
|
|
1623 inschars, outgoing_insbytes);
|
18830
|
1624
|
22896
|
1625 offset_intervals (current_buffer, from, inschars - nchars_del);
|
21136
|
1626
|
|
1627 /* Get the intervals for the part of the string we are inserting--
|
|
1628 not including the combined-before bytes. */
|
46370
40db0673e6f0
Most uses of XSTRING combined with STRING_BYTES or indirection changed to
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
1629 intervals = STRING_INTERVALS (new);
|
21136
|
1630 /* Insert those intervals. */
|
21137
|
1631 graft_intervals_into_buffer (intervals, from, inschars,
|
21136
|
1632 current_buffer, inherit);
|
18830
|
1633
|
21137
|
1634 /* Relocate point as if it were a marker. */
|
|
1635 if (from < PT)
|
23212
|
1636 adjust_point ((from + inschars - (PT < to ? PT : to)),
|
21137
|
1637 (from_byte + outgoing_insbytes
|
23212
|
1638 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
|
18830
|
1639
|
21137
|
1640 if (outgoing_insbytes == 0)
|
|
1641 evaporate_overlays (from);
|
21135
|
1642
|
21307
|
1643 CHECK_MARKERS ();
|
|
1644
|
18830
|
1645 MODIFF++;
|
|
1646 UNGCPRO;
|
|
1647
|
22896
|
1648 signal_after_change (from, nchars_del, GPT - from);
|
26860
|
1649 update_compositions (from, GPT, CHECK_BORDER);
|
18830
|
1650 }
|
|
1651
|
57878
|
1652 /* Replace the text from character positions FROM to TO with
|
|
1653 the text in INS of length INSCHARS.
|
|
1654 Keep the text properties that applied to the old characters
|
|
1655 (extending them to all the new chars if there are more new chars).
|
|
1656
|
|
1657 Note that this does not yet handle markers quite right.
|
|
1658
|
|
1659 If MARKERS is nonzero, relocate markers.
|
|
1660
|
|
1661 Unlike most functions at this level, never call
|
|
1662 prepare_to_modify_buffer and never call signal_after_change. */
|
|
1663
|
|
1664 void
|
|
1665 replace_range_2 (from, from_byte, to, to_byte, ins, inschars, insbytes, markers)
|
|
1666 int from, from_byte, to, to_byte;
|
|
1667 char *ins;
|
|
1668 int inschars, insbytes, markers;
|
|
1669 {
|
|
1670 int nbytes_del, nchars_del;
|
|
1671 Lisp_Object temp;
|
|
1672
|
|
1673 CHECK_MARKERS ();
|
|
1674
|
|
1675 nchars_del = to - from;
|
|
1676 nbytes_del = to_byte - from_byte;
|
|
1677
|
|
1678 if (nbytes_del <= 0 && insbytes == 0)
|
|
1679 return;
|
|
1680
|
|
1681 /* Make sure point-max won't overflow after this insertion. */
|
|
1682 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
|
|
1683 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
|
|
1684 error ("Maximum buffer size exceeded");
|
|
1685
|
|
1686 /* Make sure the gap is somewhere in or next to what we are deleting. */
|
|
1687 if (from > GPT)
|
|
1688 gap_right (from, from_byte);
|
|
1689 if (to < GPT)
|
|
1690 gap_left (to, to_byte, 0);
|
|
1691
|
|
1692 GAP_SIZE += nbytes_del;
|
|
1693 ZV -= nchars_del;
|
|
1694 Z -= nchars_del;
|
|
1695 ZV_BYTE -= nbytes_del;
|
|
1696 Z_BYTE -= nbytes_del;
|
|
1697 GPT = from;
|
|
1698 GPT_BYTE = from_byte;
|
|
1699 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
|
1700
|
|
1701 if (GPT_BYTE < GPT)
|
|
1702 abort ();
|
|
1703
|
|
1704 if (GPT - BEG < BEG_UNCHANGED)
|
|
1705 BEG_UNCHANGED = GPT - BEG;
|
|
1706 if (Z - GPT < END_UNCHANGED)
|
|
1707 END_UNCHANGED = Z - GPT;
|
|
1708
|
|
1709 if (GAP_SIZE < insbytes)
|
|
1710 make_gap (insbytes - GAP_SIZE);
|
|
1711
|
|
1712 /* Copy the replacement text into the buffer. */
|
|
1713 bcopy (ins, GPT_ADDR, insbytes);
|
|
1714
|
|
1715 #ifdef BYTE_COMBINING_DEBUG
|
|
1716 /* We have copied text into the gap, but we have not marked
|
|
1717 it as part of the buffer. So we can use the old FROM and FROM_BYTE
|
|
1718 here, for both the previous text and the following text.
|
|
1719 Meanwhile, GPT_ADDR does point to
|
|
1720 the text that has been stored by copy_text. */
|
|
1721 if (count_combining_before (GPT_ADDR, insbytes, from, from_byte)
|
|
1722 || count_combining_after (GPT_ADDR, insbytes, from, from_byte))
|
|
1723 abort ();
|
|
1724 #endif
|
|
1725
|
|
1726 GAP_SIZE -= insbytes;
|
|
1727 GPT += inschars;
|
|
1728 ZV += inschars;
|
|
1729 Z += inschars;
|
|
1730 GPT_BYTE += insbytes;
|
|
1731 ZV_BYTE += insbytes;
|
|
1732 Z_BYTE += insbytes;
|
|
1733 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
|
1734
|
|
1735 if (GPT_BYTE < GPT)
|
|
1736 abort ();
|
|
1737
|
|
1738 /* Adjust the overlay center as needed. This must be done after
|
|
1739 adjusting the markers that bound the overlays. */
|
|
1740 if (nchars_del != inschars)
|
|
1741 {
|
|
1742 adjust_overlays_for_insert (from, inschars);
|
|
1743 adjust_overlays_for_delete (from + inschars, nchars_del);
|
|
1744 }
|
|
1745
|
|
1746 /* Adjust markers for the deletion and the insertion. */
|
|
1747 if (markers
|
59853
|
1748 && ! (nchars_del == 1 && inschars == 1 && nbytes_del == insbytes))
|
57878
|
1749 adjust_markers_for_replace (from, from_byte, nchars_del, nbytes_del,
|
|
1750 inschars, insbytes);
|
|
1751
|
|
1752 offset_intervals (current_buffer, from, inschars - nchars_del);
|
|
1753
|
|
1754 /* Relocate point as if it were a marker. */
|
59853
|
1755 if (from < PT && (nchars_del != inschars || nbytes_del != insbytes))
|
|
1756 {
|
|
1757 if (PT < to)
|
|
1758 /* PT was within the deleted text. Move it to FROM. */
|
|
1759 adjust_point (from - PT, from_byte - PT_BYTE);
|
|
1760 else
|
|
1761 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
|
|
1762 }
|
57878
|
1763
|
|
1764 if (insbytes == 0)
|
|
1765 evaporate_overlays (from);
|
|
1766
|
|
1767 CHECK_MARKERS ();
|
|
1768
|
|
1769 MODIFF++;
|
|
1770 }
|
|
1771
|
157
|
1772 /* Delete characters in current buffer
|
20555
|
1773 from FROM up to (but not including) TO.
|
|
1774 If TO comes before FROM, we delete nothing. */
|
157
|
1775
|
10391
|
1776 void
|
157
|
1777 del_range (from, to)
|
|
1778 register int from, to;
|
|
1779 {
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1780 del_range_1 (from, to, 1, 0);
|
6126
|
1781 }
|
|
1782
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1783 /* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1784 RET_STRING says to return the deleted text. */
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1785
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1786 Lisp_Object
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1787 del_range_1 (from, to, prepare, ret_string)
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1788 int from, to, prepare, ret_string;
|
6126
|
1789 {
|
20555
|
1790 int from_byte, to_byte;
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1791 Lisp_Object deletion;
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1792 struct gcpro gcpro1;
|
20555
|
1793
|
|
1794 /* Make args be valid */
|
|
1795 if (from < BEGV)
|
|
1796 from = BEGV;
|
|
1797 if (to > ZV)
|
|
1798 to = ZV;
|
|
1799
|
|
1800 if (to <= from)
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1801 return Qnil;
|
157
|
1802
|
18446
|
1803 if (prepare)
|
|
1804 {
|
|
1805 int range_length = to - from;
|
|
1806 prepare_to_modify_buffer (from, to, &from);
|
36070
|
1807 to = min (ZV, from + range_length);
|
18446
|
1808 }
|
|
1809
|
20555
|
1810 from_byte = CHAR_TO_BYTE (from);
|
|
1811 to_byte = CHAR_TO_BYTE (to);
|
|
1812
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1813 deletion = del_range_2 (from, from_byte, to, to_byte, ret_string);
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1814 GCPRO1(deletion);
|
24041
|
1815 signal_after_change (from, to - from, 0);
|
27664
|
1816 update_compositions (from, from, CHECK_HEAD);
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1817 UNGCPRO;
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1818 return deletion;
|
20555
|
1819 }
|
|
1820
|
|
1821 /* Like del_range_1 but args are byte positions, not char positions. */
|
|
1822
|
|
1823 void
|
|
1824 del_range_byte (from_byte, to_byte, prepare)
|
|
1825 int from_byte, to_byte, prepare;
|
|
1826 {
|
|
1827 int from, to;
|
|
1828
|
157
|
1829 /* Make args be valid */
|
20555
|
1830 if (from_byte < BEGV_BYTE)
|
|
1831 from_byte = BEGV_BYTE;
|
|
1832 if (to_byte > ZV_BYTE)
|
|
1833 to_byte = ZV_BYTE;
|
|
1834
|
|
1835 if (to_byte <= from_byte)
|
|
1836 return;
|
|
1837
|
|
1838 from = BYTE_TO_CHAR (from_byte);
|
|
1839 to = BYTE_TO_CHAR (to_byte);
|
|
1840
|
|
1841 if (prepare)
|
|
1842 {
|
|
1843 int old_from = from, old_to = Z - to;
|
|
1844 int range_length = to - from;
|
|
1845 prepare_to_modify_buffer (from, to, &from);
|
|
1846 to = from + range_length;
|
|
1847
|
|
1848 if (old_from != from)
|
|
1849 from_byte = CHAR_TO_BYTE (from);
|
36070
|
1850 if (to > ZV)
|
|
1851 {
|
|
1852 to = ZV;
|
|
1853 to_byte = ZV_BYTE;
|
|
1854 }
|
|
1855 else if (old_to == Z - to)
|
20555
|
1856 to_byte = CHAR_TO_BYTE (to);
|
|
1857 }
|
|
1858
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1859 del_range_2 (from, from_byte, to, to_byte, 0);
|
24041
|
1860 signal_after_change (from, to - from, 0);
|
26860
|
1861 update_compositions (from, from, CHECK_HEAD);
|
20555
|
1862 }
|
|
1863
|
|
1864 /* Like del_range_1, but positions are specified both as charpos
|
|
1865 and bytepos. */
|
|
1866
|
|
1867 void
|
20983
|
1868 del_range_both (from, from_byte, to, to_byte, prepare)
|
|
1869 int from, from_byte, to, to_byte, prepare;
|
20555
|
1870 {
|
|
1871 /* Make args be valid */
|
|
1872 if (from_byte < BEGV_BYTE)
|
|
1873 from_byte = BEGV_BYTE;
|
|
1874 if (to_byte > ZV_BYTE)
|
|
1875 to_byte = ZV_BYTE;
|
|
1876
|
|
1877 if (to_byte <= from_byte)
|
|
1878 return;
|
|
1879
|
157
|
1880 if (from < BEGV)
|
|
1881 from = BEGV;
|
|
1882 if (to > ZV)
|
|
1883 to = ZV;
|
|
1884
|
20555
|
1885 if (prepare)
|
|
1886 {
|
|
1887 int old_from = from, old_to = Z - to;
|
|
1888 int range_length = to - from;
|
|
1889 prepare_to_modify_buffer (from, to, &from);
|
|
1890 to = from + range_length;
|
|
1891
|
|
1892 if (old_from != from)
|
|
1893 from_byte = CHAR_TO_BYTE (from);
|
36070
|
1894 if (to > ZV)
|
|
1895 {
|
|
1896 to = ZV;
|
|
1897 to_byte = ZV_BYTE;
|
|
1898 }
|
|
1899 else if (old_to == Z - to)
|
20555
|
1900 to_byte = CHAR_TO_BYTE (to);
|
|
1901 }
|
|
1902
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1903 del_range_2 (from, from_byte, to, to_byte, 0);
|
24041
|
1904 signal_after_change (from, to - from, 0);
|
26860
|
1905 update_compositions (from, from, CHECK_HEAD);
|
20555
|
1906 }
|
|
1907
|
|
1908 /* Delete a range of text, specified both as character positions
|
|
1909 and byte positions. FROM and TO are character positions,
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1910 while FROM_BYTE and TO_BYTE are byte positions.
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1911 If RET_STRING is true, the deleted area is returned as a string. */
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1912
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1913 Lisp_Object
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1914 del_range_2 (from, from_byte, to, to_byte, ret_string)
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1915 int from, from_byte, to, to_byte, ret_string;
|
20555
|
1916 {
|
|
1917 register int nbytes_del, nchars_del;
|
21236
|
1918 Lisp_Object deletion;
|
20555
|
1919
|
21307
|
1920 CHECK_MARKERS ();
|
|
1921
|
20555
|
1922 nchars_del = to - from;
|
|
1923 nbytes_del = to_byte - from_byte;
|
157
|
1924
|
|
1925 /* Make sure the gap is somewhere in or next to what we are deleting. */
|
|
1926 if (from > GPT)
|
20555
|
1927 gap_right (from, from_byte);
|
157
|
1928 if (to < GPT)
|
20555
|
1929 gap_left (to, to_byte, 0);
|
157
|
1930
|
29012
|
1931 #ifdef BYTE_COMBINING_DEBUG
|
|
1932 if (count_combining_before (BUF_BYTE_ADDRESS (current_buffer, to_byte),
|
|
1933 Z_BYTE - to_byte, from, from_byte))
|
|
1934 abort ();
|
|
1935 #endif
|
21236
|
1936
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1937 if (ret_string || ! EQ (current_buffer->undo_list, Qt))
|
29012
|
1938 deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1939 else
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1940 deletion = Qnil;
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1941
|
14479
|
1942 /* Relocate all markers pointing into the new, larger gap
|
|
1943 to point at the end of the text before the gap.
|
20555
|
1944 Do this before recording the deletion,
|
|
1945 so that undo handles this after reinserting the text. */
|
|
1946 adjust_markers_for_delete (from, from_byte, to, to_byte);
|
21228
|
1947
|
22107
|
1948 if (! EQ (current_buffer->undo_list, Qt))
|
29012
|
1949 record_delete (from, deletion);
|
1247
|
1950 MODIFF++;
|
|
1951
|
157
|
1952 /* Relocate point as if it were a marker. */
|
7108
|
1953 if (from < PT)
|
20555
|
1954 adjust_point (from - (PT < to ? PT : to),
|
|
1955 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
|
157
|
1956
|
20555
|
1957 offset_intervals (current_buffer, from, - nchars_del);
|
1963
|
1958
|
11474
|
1959 /* Adjust the overlay center as needed. This must be done after
|
12617
|
1960 adjusting the markers that bound the overlays. */
|
21191
|
1961 adjust_overlays_for_delete (from, nchars_del);
|
11474
|
1962
|
20555
|
1963 GAP_SIZE += nbytes_del;
|
|
1964 ZV_BYTE -= nbytes_del;
|
|
1965 Z_BYTE -= nbytes_del;
|
|
1966 ZV -= nchars_del;
|
|
1967 Z -= nchars_del;
|
157
|
1968 GPT = from;
|
20555
|
1969 GPT_BYTE = from_byte;
|
55740
eba675d00657
(del_range_2, replace_range): Don't write an anchor if the gap is empty.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
1970 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
|
21191
|
1971
|
20555
|
1972 if (GPT_BYTE < GPT)
|
|
1973 abort ();
|
|
1974
|
25373
|
1975 if (GPT - BEG < BEG_UNCHANGED)
|
|
1976 BEG_UNCHANGED = GPT - BEG;
|
|
1977 if (Z - GPT < END_UNCHANGED)
|
|
1978 END_UNCHANGED = Z - GPT;
|
157
|
1979
|
21307
|
1980 CHECK_MARKERS ();
|
|
1981
|
8840
|
1982 evaporate_overlays (from);
|
26742
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1983
|
936b39bd05b4
* editfns.c (Fdelete_and_extract_region): New function.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
1984 return deletion;
|
157
|
1985 }
|
|
1986
|
20555
|
1987 /* Call this if you're about to change the region of BUFFER from
|
|
1988 character positions START to END. This checks the read-only
|
|
1989 properties of the region, calls the necessary modification hooks,
|
|
1990 and warns the next redisplay that it should pay attention to that
|
|
1991 area. */
|
|
1992
|
10391
|
1993 void
|
2783
|
1994 modify_region (buffer, start, end)
|
|
1995 struct buffer *buffer;
|
157
|
1996 int start, end;
|
|
1997 {
|
2783
|
1998 struct buffer *old_buffer = current_buffer;
|
|
1999
|
|
2000 if (buffer != old_buffer)
|
|
2001 set_buffer_internal (buffer);
|
|
2002
|
18446
|
2003 prepare_to_modify_buffer (start, end, NULL);
|
157
|
2004
|
25373
|
2005 BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
|
5237
|
2006
|
10311
|
2007 if (MODIFF <= SAVE_MODIFF)
|
5237
|
2008 record_first_change ();
|
157
|
2009 MODIFF++;
|
2783
|
2010
|
10564
|
2011 buffer->point_before_scroll = Qnil;
|
|
2012
|
2783
|
2013 if (buffer != old_buffer)
|
|
2014 set_buffer_internal (old_buffer);
|
157
|
2015 }
|
18446
|
2016
|
20555
|
2017 /* Check that it is okay to modify the buffer between START and END,
|
|
2018 which are char positions.
|
|
2019
|
1289
|
2020 Run the before-change-function, if any. If intervals are in use,
|
|
2021 verify that the text to be modified is not read-only, and call
|
18446
|
2022 any modification properties the text may have.
|
|
2023
|
|
2024 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
|
|
2025 by holding its value temporarily in a marker. */
|
157
|
2026
|
10391
|
2027 void
|
18446
|
2028 prepare_to_modify_buffer (start, end, preserve_ptr)
|
16102
|
2029 int start, end;
|
18446
|
2030 int *preserve_ptr;
|
157
|
2031 {
|
484
|
2032 if (!NILP (current_buffer->read_only))
|
157
|
2033 Fbarf_if_buffer_read_only ();
|
|
2034
|
25025
|
2035 /* Let redisplay consider other windows than selected_window
|
|
2036 if modifying another buffer. */
|
|
2037 if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
|
|
2038 ++windows_or_buffers_changed;
|
|
2039
|
10311
|
2040 if (BUF_INTERVALS (current_buffer) != 0)
|
18446
|
2041 {
|
|
2042 if (preserve_ptr)
|
|
2043 {
|
|
2044 Lisp_Object preserve_marker;
|
|
2045 struct gcpro gcpro1;
|
|
2046 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil);
|
|
2047 GCPRO1 (preserve_marker);
|
|
2048 verify_interval_modification (current_buffer, start, end);
|
|
2049 *preserve_ptr = marker_position (preserve_marker);
|
51671
|
2050 unchain_marker (XMARKER (preserve_marker));
|
18446
|
2051 UNGCPRO;
|
|
2052 }
|
|
2053 else
|
|
2054 verify_interval_modification (current_buffer, start, end);
|
|
2055 }
|
157
|
2056
|
|
2057 #ifdef CLASH_DETECTION
|
11657
|
2058 if (!NILP (current_buffer->file_truename)
|
12621
|
2059 /* Make binding buffer-file-name to nil effective. */
|
|
2060 && !NILP (current_buffer->filename)
|
10311
|
2061 && SAVE_MODIFF >= MODIFF)
|
11657
|
2062 lock_file (current_buffer->file_truename);
|
157
|
2063 #else
|
|
2064 /* At least warn if this file has changed on disk since it was visited. */
|
484
|
2065 if (!NILP (current_buffer->filename)
|
10311
|
2066 && SAVE_MODIFF >= MODIFF
|
484
|
2067 && NILP (Fverify_visited_file_modtime (Fcurrent_buffer ()))
|
|
2068 && !NILP (Ffile_exists_p (current_buffer->filename)))
|
157
|
2069 call1 (intern ("ask-user-about-supersession-threat"),
|
|
2070 current_buffer->filename);
|
|
2071 #endif /* not CLASH_DETECTION */
|
|
2072
|
18446
|
2073 signal_before_change (start, end, preserve_ptr);
|
2050
|
2074
|
9409
|
2075 if (current_buffer->newline_cache)
|
|
2076 invalidate_region_cache (current_buffer,
|
|
2077 current_buffer->newline_cache,
|
|
2078 start - BEG, Z - end);
|
|
2079 if (current_buffer->width_run_cache)
|
|
2080 invalidate_region_cache (current_buffer,
|
|
2081 current_buffer->width_run_cache,
|
|
2082 start - BEG, Z - end);
|
|
2083
|
2050
|
2084 Vdeactivate_mark = Qt;
|
157
|
2085 }
|
|
2086
|
18446
|
2087 /* These macros work with an argument named `preserve_ptr'
|
|
2088 and a local variable named `preserve_marker'. */
|
|
2089
|
|
2090 #define PRESERVE_VALUE \
|
|
2091 if (preserve_ptr && NILP (preserve_marker)) \
|
|
2092 preserve_marker = Fcopy_marker (make_number (*preserve_ptr), Qnil)
|
|
2093
|
|
2094 #define RESTORE_VALUE \
|
|
2095 if (! NILP (preserve_marker)) \
|
|
2096 { \
|
|
2097 *preserve_ptr = marker_position (preserve_marker); \
|
51671
|
2098 unchain_marker (XMARKER (preserve_marker)); \
|
18446
|
2099 }
|
|
2100
|
19331
|
2101 #define PRESERVE_START_END \
|
|
2102 if (NILP (start_marker)) \
|
|
2103 start_marker = Fcopy_marker (start, Qnil); \
|
|
2104 if (NILP (end_marker)) \
|
|
2105 end_marker = Fcopy_marker (end, Qnil);
|
|
2106
|
|
2107 #define FETCH_START \
|
|
2108 (! NILP (start_marker) ? Fmarker_position (start_marker) : start)
|
|
2109
|
|
2110 #define FETCH_END \
|
|
2111 (! NILP (end_marker) ? Fmarker_position (end_marker) : end)
|
|
2112
|
3591
|
2113 /* Signal a change to the buffer immediately before it happens.
|
18446
|
2114 START_INT and END_INT are the bounds of the text to be changed.
|
|
2115
|
|
2116 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
|
|
2117 by holding its value temporarily in a marker. */
|
157
|
2118
|
10391
|
2119 void
|
18446
|
2120 signal_before_change (start_int, end_int, preserve_ptr)
|
16153
|
2121 int start_int, end_int;
|
18446
|
2122 int *preserve_ptr;
|
157
|
2123 {
|
16102
|
2124 Lisp_Object start, end;
|
19331
|
2125 Lisp_Object start_marker, end_marker;
|
18446
|
2126 Lisp_Object preserve_marker;
|
19331
|
2127 struct gcpro gcpro1, gcpro2, gcpro3;
|
16102
|
2128
|
23400
|
2129 if (inhibit_modification_hooks)
|
|
2130 return;
|
|
2131
|
16102
|
2132 start = make_number (start_int);
|
|
2133 end = make_number (end_int);
|
18446
|
2134 preserve_marker = Qnil;
|
19331
|
2135 start_marker = Qnil;
|
|
2136 end_marker = Qnil;
|
|
2137 GCPRO3 (preserve_marker, start_marker, end_marker);
|
16102
|
2138
|
157
|
2139 /* If buffer is unmodified, run a special hook for that case. */
|
10311
|
2140 if (SAVE_MODIFF >= MODIFF
|
1821
|
2141 && !NILP (Vfirst_change_hook)
|
|
2142 && !NILP (Vrun_hooks))
|
18446
|
2143 {
|
|
2144 PRESERVE_VALUE;
|
19331
|
2145 PRESERVE_START_END;
|
18446
|
2146 call1 (Vrun_hooks, Qfirst_change_hook);
|
|
2147 }
|
1821
|
2148
|
12784
|
2149 /* Now run the before-change-functions if any. */
|
6787
|
2150 if (!NILP (Vbefore_change_functions))
|
|
2151 {
|
12784
|
2152 Lisp_Object args[3];
|
|
2153 Lisp_Object before_change_functions;
|
|
2154 Lisp_Object after_change_functions;
|
|
2155 struct gcpro gcpro1, gcpro2;
|
37760
|
2156 struct buffer *old = current_buffer;
|
|
2157 struct buffer *new;
|
6787
|
2158
|
18446
|
2159 PRESERVE_VALUE;
|
19331
|
2160 PRESERVE_START_END;
|
18446
|
2161
|
12784
|
2162 /* "Bind" before-change-functions and after-change-functions
|
|
2163 to nil--but in a way that errors don't know about.
|
|
2164 That way, if there's an error in them, they will stay nil. */
|
|
2165 before_change_functions = Vbefore_change_functions;
|
|
2166 after_change_functions = Vafter_change_functions;
|
12798
|
2167 Vbefore_change_functions = Qnil;
|
|
2168 Vafter_change_functions = Qnil;
|
12784
|
2169 GCPRO2 (before_change_functions, after_change_functions);
|
6787
|
2170
|
12784
|
2171 /* Actually run the hook functions. */
|
|
2172 args[0] = Qbefore_change_functions;
|
19331
|
2173 args[1] = FETCH_START;
|
|
2174 args[2] = FETCH_END;
|
12784
|
2175 run_hook_list_with_args (before_change_functions, 3, args);
|
|
2176
|
37760
|
2177 /* "Unbind" the variables we "bound" to nil. Beware a
|
|
2178 buffer-local hook which changes the buffer when run (e.g. W3). */
|
|
2179 if (old != current_buffer)
|
|
2180 {
|
|
2181 new = current_buffer;
|
|
2182 set_buffer_internal (old);
|
|
2183 Vbefore_change_functions = before_change_functions;
|
|
2184 Vafter_change_functions = after_change_functions;
|
|
2185 set_buffer_internal (new);
|
|
2186 }
|
|
2187 else
|
|
2188 {
|
|
2189 Vbefore_change_functions = before_change_functions;
|
|
2190 Vafter_change_functions = after_change_functions;
|
|
2191 }
|
12784
|
2192 UNGCPRO;
|
6787
|
2193 }
|
10144
|
2194
|
51837
87ec975874ab
(signal_before_change, signal_after_change): Use new type for
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
2195 if (current_buffer->overlays_before || current_buffer->overlays_after)
|
18446
|
2196 {
|
|
2197 PRESERVE_VALUE;
|
19331
|
2198 report_overlay_modification (FETCH_START, FETCH_END, 0,
|
|
2199 FETCH_START, FETCH_END, Qnil);
|
18446
|
2200 }
|
|
2201
|
19331
|
2202 if (! NILP (start_marker))
|
|
2203 free_marker (start_marker);
|
|
2204 if (! NILP (end_marker))
|
|
2205 free_marker (end_marker);
|
18446
|
2206 RESTORE_VALUE;
|
|
2207 UNGCPRO;
|
157
|
2208 }
|
|
2209
|
3591
|
2210 /* Signal a change immediately after it happens.
|
20555
|
2211 CHARPOS is the character position of the start of the changed text.
|
157
|
2212 LENDEL is the number of characters of the text before the change.
|
|
2213 (Not the whole buffer; just the part that was changed.)
|
15123
d6106d651a71
(signal_after_change): Correct the arg to report_overlay_modification.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
2214 LENINS is the number of characters in that part of the text
|
d6106d651a71
(signal_after_change): Correct the arg to report_overlay_modification.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
2215 after the change. */
|
157
|
2216
|
10391
|
2217 void
|
20555
|
2218 signal_after_change (charpos, lendel, lenins)
|
|
2219 int charpos, lendel, lenins;
|
157
|
2220 {
|
23400
|
2221 if (inhibit_modification_hooks)
|
|
2222 return;
|
|
2223
|
16547
|
2224 /* If we are deferring calls to the after-change functions
|
|
2225 and there are no before-change functions,
|
|
2226 just record the args that we were going to use. */
|
|
2227 if (! NILP (Vcombine_after_change_calls)
|
29379
|
2228 && NILP (Vbefore_change_functions)
|
51837
87ec975874ab
(signal_before_change, signal_after_change): Use new type for
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
2229 && !current_buffer->overlays_before
|
87ec975874ab
(signal_before_change, signal_after_change): Use new type for
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
2230 && !current_buffer->overlays_after)
|
16547
|
2231 {
|
|
2232 Lisp_Object elt;
|
|
2233
|
|
2234 if (!NILP (combine_after_change_list)
|
|
2235 && current_buffer != XBUFFER (combine_after_change_buffer))
|
|
2236 Fcombine_after_change_execute ();
|
|
2237
|
20555
|
2238 elt = Fcons (make_number (charpos - BEG),
|
|
2239 Fcons (make_number (Z - (charpos - lendel + lenins)),
|
16547
|
2240 Fcons (make_number (lenins - lendel), Qnil)));
|
|
2241 combine_after_change_list
|
|
2242 = Fcons (elt, combine_after_change_list);
|
|
2243 combine_after_change_buffer = Fcurrent_buffer ();
|
|
2244
|
|
2245 return;
|
|
2246 }
|
|
2247
|
49600
|
2248 if (!NILP (combine_after_change_list))
|
16547
|
2249 Fcombine_after_change_execute ();
|
|
2250
|
6787
|
2251 if (!NILP (Vafter_change_functions))
|
|
2252 {
|
12784
|
2253 Lisp_Object args[4];
|
|
2254 Lisp_Object before_change_functions;
|
|
2255 Lisp_Object after_change_functions;
|
37760
|
2256 struct buffer *old = current_buffer;
|
|
2257 struct buffer *new;
|
12784
|
2258 struct gcpro gcpro1, gcpro2;
|
6787
|
2259
|
12784
|
2260 /* "Bind" before-change-functions and after-change-functions
|
|
2261 to nil--but in a way that errors don't know about.
|
|
2262 That way, if there's an error in them, they will stay nil. */
|
|
2263 before_change_functions = Vbefore_change_functions;
|
|
2264 after_change_functions = Vafter_change_functions;
|
12798
|
2265 Vbefore_change_functions = Qnil;
|
|
2266 Vafter_change_functions = Qnil;
|
12784
|
2267 GCPRO2 (before_change_functions, after_change_functions);
|
6787
|
2268
|
12784
|
2269 /* Actually run the hook functions. */
|
|
2270 args[0] = Qafter_change_functions;
|
20555
|
2271 XSETFASTINT (args[1], charpos);
|
|
2272 XSETFASTINT (args[2], charpos + lenins);
|
12784
|
2273 XSETFASTINT (args[3], lendel);
|
|
2274 run_hook_list_with_args (after_change_functions,
|
|
2275 4, args);
|
|
2276
|
37760
|
2277 /* "Unbind" the variables we "bound" to nil. Beware a
|
|
2278 buffer-local hook which changes the buffer when run (e.g. W3). */
|
|
2279 if (old != current_buffer)
|
|
2280 {
|
|
2281 new = current_buffer;
|
|
2282 set_buffer_internal (old);
|
|
2283 Vbefore_change_functions = before_change_functions;
|
|
2284 Vafter_change_functions = after_change_functions;
|
|
2285 set_buffer_internal (new);
|
|
2286 }
|
|
2287 else
|
|
2288 {
|
|
2289 Vbefore_change_functions = before_change_functions;
|
|
2290 Vafter_change_functions = after_change_functions;
|
|
2291 }
|
12784
|
2292 UNGCPRO;
|
6787
|
2293 }
|
10144
|
2294
|
51837
87ec975874ab
(signal_before_change, signal_after_change): Use new type for
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
2295 if (current_buffer->overlays_before || current_buffer->overlays_after)
|
20555
|
2296 report_overlay_modification (make_number (charpos),
|
|
2297 make_number (charpos + lenins),
|
10144
|
2298 1,
|
20555
|
2299 make_number (charpos),
|
|
2300 make_number (charpos + lenins),
|
10144
|
2301 make_number (lendel));
|
13026
|
2302
|
|
2303 /* After an insertion, call the text properties
|
|
2304 insert-behind-hooks or insert-in-front-hooks. */
|
|
2305 if (lendel == 0)
|
21526
|
2306 report_interval_modification (make_number (charpos),
|
|
2307 make_number (charpos + lenins));
|
157
|
2308 }
|
16547
|
2309
|
|
2310 Lisp_Object
|
|
2311 Fcombine_after_change_execute_1 (val)
|
|
2312 Lisp_Object val;
|
|
2313 {
|
|
2314 Vcombine_after_change_calls = val;
|
|
2315 return val;
|
|
2316 }
|
|
2317
|
|
2318 DEFUN ("combine-after-change-execute", Fcombine_after_change_execute,
|
41001
|
2319 Scombine_after_change_execute, 0, 0, 0,
|
|
2320 doc: /* This function is for use internally in `combine-after-change-calls'. */)
|
|
2321 ()
|
16547
|
2322 {
|
46293
|
2323 int count = SPECPDL_INDEX ();
|
16547
|
2324 int beg, end, change;
|
|
2325 int begpos, endpos;
|
|
2326 Lisp_Object tail;
|
|
2327
|
23646
|
2328 if (NILP (combine_after_change_list))
|
|
2329 return Qnil;
|
|
2330
|
16547
|
2331 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
|
|
2332
|
|
2333 Fset_buffer (combine_after_change_buffer);
|
|
2334
|
|
2335 /* # chars unchanged at beginning of buffer. */
|
|
2336 beg = Z - BEG;
|
|
2337 /* # chars unchanged at end of buffer. */
|
|
2338 end = beg;
|
|
2339 /* Total amount of insertion (negative for deletion). */
|
|
2340 change = 0;
|
|
2341
|
|
2342 /* Scan the various individual changes,
|
|
2343 accumulating the range info in BEG, END and CHANGE. */
|
|
2344 for (tail = combine_after_change_list; CONSP (tail);
|
25662
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2345 tail = XCDR (tail))
|
16547
|
2346 {
|
17373
|
2347 Lisp_Object elt;
|
|
2348 int thisbeg, thisend, thischange;
|
16547
|
2349
|
|
2350 /* Extract the info from the next element. */
|
25662
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2351 elt = XCAR (tail);
|
16547
|
2352 if (! CONSP (elt))
|
|
2353 continue;
|
25662
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2354 thisbeg = XINT (XCAR (elt));
|
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2355
|
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2356 elt = XCDR (elt);
|
16547
|
2357 if (! CONSP (elt))
|
|
2358 continue;
|
25662
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2359 thisend = XINT (XCAR (elt));
|
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2360
|
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2361 elt = XCDR (elt);
|
16547
|
2362 if (! CONSP (elt))
|
|
2363 continue;
|
25662
0a7261c1d487
Use XCAR, XCDR, and XFLOAT_DATA instead of explicit member access.
Ken Raeburn <raeburn@raeburn.org>
diff
changeset
|
2364 thischange = XINT (XCAR (elt));
|
16547
|
2365
|
|
2366 /* Merge this range into the accumulated range. */
|
|
2367 change += thischange;
|
|
2368 if (thisbeg < beg)
|
|
2369 beg = thisbeg;
|
|
2370 if (thisend < end)
|
|
2371 end = thisend;
|
|
2372 }
|
|
2373
|
|
2374 /* Get the current start and end positions of the range
|
|
2375 that was changed. */
|
|
2376 begpos = BEG + beg;
|
|
2377 endpos = Z - end;
|
49600
|
2378
|
16547
|
2379 /* We are about to handle these, so discard them. */
|
|
2380 combine_after_change_list = Qnil;
|
|
2381
|
|
2382 /* Now run the after-change functions for real.
|
|
2383 Turn off the flag that defers them. */
|
|
2384 record_unwind_protect (Fcombine_after_change_execute_1,
|
|
2385 Vcombine_after_change_calls);
|
|
2386 signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
|
26860
|
2387 update_compositions (begpos, endpos, CHECK_ALL);
|
16547
|
2388
|
23646
|
2389 return unbind_to (count, Qnil);
|
16547
|
2390 }
|
|
2391
|
21514
|
2392 void
|
16547
|
2393 syms_of_insdel ()
|
|
2394 {
|
|
2395 staticpro (&combine_after_change_list);
|
64616
|
2396 staticpro (&combine_after_change_buffer);
|
16547
|
2397 combine_after_change_list = Qnil;
|
23646
|
2398 combine_after_change_buffer = Qnil;
|
16547
|
2399
|
21307
|
2400 DEFVAR_BOOL ("check-markers-debug-flag", &check_markers_debug_flag,
|
41001
|
2401 doc: /* Non-nil means enable debugging checks for invalid marker positions. */);
|
21307
|
2402 check_markers_debug_flag = 0;
|
16547
|
2403 DEFVAR_LISP ("combine-after-change-calls", &Vcombine_after_change_calls,
|
41001
|
2404 doc: /* Used internally by the `combine-after-change-calls' macro. */);
|
16547
|
2405 Vcombine_after_change_calls = Qnil;
|
|
2406
|
25579
5662c18836ae
(syms_of_insdel): Define Lisp variable inhibit-modification-hooks.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
2407 DEFVAR_BOOL ("inhibit-modification-hooks", &inhibit_modification_hooks,
|
41001
|
2408 doc: /* Non-nil means don't run any of the hooks that respond to buffer changes.
|
|
2409 This affects `before-change-functions' and `after-change-functions',
|
|
2410 as well as hooks attached to text properties and overlays. */);
|
25579
5662c18836ae
(syms_of_insdel): Define Lisp variable inhibit-modification-hooks.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
2411 inhibit_modification_hooks = 0;
|
39244
|
2412 Qinhibit_modification_hooks = intern ("inhibit-modification-hooks");
|
|
2413 staticpro (&Qinhibit_modification_hooks);
|
25579
5662c18836ae
(syms_of_insdel): Define Lisp variable inhibit-modification-hooks.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
2414
|
16547
|
2415 defsubr (&Scombine_after_change_execute);
|
|
2416 }
|
52401
|
2417
|
|
2418 /* arch-tag: 9b34b886-47d7-465e-a234-299af411b23d
|
|
2419 (do not change this comment) */
|