comparison src/insdel.c @ 20555:80a546059cbd

(move_gap): Use move_gap_both. (move_gap_both): New function. (gap_left, gap_right): Take both charpos and bytepos args. (adjust_markers_gap_motion): Renamed from adjust_markers and simplified. (adjust_markers_for_delete): New function. (adjust_markers_for_insert): Take args in chars and bytes. Also new arg BEFORE_MARKERS. One call does all marker updating needed for any insert. (adjust_point): Take 2 args and update PT and PT_BYTE. (make_gap): Handle bytes vs chars. (insert, insert_and_inherit): Handle bytes vs chars. Pass new BEFORE_MARKERS arg to insert_1. (insert_before_markers, insert_before_markers_and_inherit): Likewise. (insert_from_string, insert_from_string_before_markers): Likewise. (insert_from_buffer): Likewise. (insert_1): Handle bytes vs chars. New arg BEFORE_MARKERS. (insert_from_string_1, insert_from_buffer_1): Likewise. (replace_range): Likewise. (del_range_2): New subroutine, taken from del_range_1. (del_range_1): Use del_range_2. (del_range_byte, del_range_both): New functions.
author Richard M. Stallman <rms@gnu.org>
date Thu, 01 Jan 1998 07:03:19 +0000
parents bc4c4e15a135
children f0bacfbd9d47
comparison
equal deleted inserted replaced
20554:2ea1c9492531 20555:80a546059cbd
1 /* Buffer insertion/deletion and gap motion for GNU Emacs. 1 /* Buffer insertion/deletion and gap motion for GNU Emacs.
2 Copyright (C) 1985, 1986, 1993, 1994, 1995 Free Software Foundation, Inc. 2 Copyright (C) 1985, 86, 93, 94, 95, 1997 Free Software Foundation, Inc.
3 3
4 This file is part of GNU Emacs. 4 This file is part of GNU Emacs.
5 5
6 GNU Emacs is free software; you can redistribute it and/or modify 6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 7 it under the terms of the GNU General Public License as published by
31 #define NULL 0 31 #define NULL 0
32 #endif 32 #endif
33 33
34 #define min(x, y) ((x) < (y) ? (x) : (y)) 34 #define min(x, y) ((x) < (y) ? (x) : (y))
35 35
36 static void insert_from_string_1 (); 36 static void insert_from_string_1 P_ ((Lisp_Object, int, int, int, int, int));
37 static void insert_from_buffer_1 (); 37 static void insert_from_buffer_1 ();
38 static void gap_left (); 38 static void gap_left P_ ((int, int, int));
39 static void gap_right (); 39 static void gap_right P_ ((int, int));
40 static void adjust_markers (); 40 static void adjust_markers_gap_motion P_ ((int, int, int));
41 static void adjust_point (); 41 static void adjust_markers_for_insert P_ ((int, int, int, int, int));
42 static void adjust_markers_for_delete P_ ((int, int, int, int));
43 static void adjust_point P_ ((int, int));
42 44
43 Lisp_Object Fcombine_after_change_execute (); 45 Lisp_Object Fcombine_after_change_execute ();
44 46
45 /* Non-nil means don't call the after-change-functions right away, 47 /* Non-nil means don't call the after-change-functions right away,
46 just record an element in Vcombine_after_change_calls_list. */ 48 just record an element in Vcombine_after_change_calls_list. */
59 Lisp_Object combine_after_change_list; 61 Lisp_Object combine_after_change_list;
60 62
61 /* Buffer which combine_after_change_list is about. */ 63 /* Buffer which combine_after_change_list is about. */
62 Lisp_Object combine_after_change_buffer; 64 Lisp_Object combine_after_change_buffer;
63 65
64 /* Move gap to position `pos'. 66 /* Move gap to position CHARPOS.
65 Note that this can quit! */ 67 Note that this can quit! */
66 68
67 void 69 void
68 move_gap (pos) 70 move_gap (charpos)
69 int pos; 71 int charpos;
70 { 72 {
71 if (pos < GPT) 73 move_gap_both (charpos, charpos_to_bytepos (charpos));
72 gap_left (pos, 0); 74 }
73 else if (pos > GPT) 75
74 gap_right (pos); 76 /* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
75 } 77 Note that this can quit! */
76 78
77 /* Move the gap to POS, which is less than the current GPT. 79 void
80 move_gap_both (charpos, bytepos)
81 int charpos, bytepos;
82 {
83 if (bytepos < GPT_BYTE)
84 gap_left (charpos, bytepos, 0);
85 else if (bytepos > GPT_BYTE)
86 gap_right (charpos, bytepos);
87 }
88
89 /* Move the gap to a position less than the current GPT.
90 BYTEPOS describes the new position as a byte position,
91 and CHARPOS is the corresponding char position.
78 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */ 92 If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged. */
79 93
80 static void 94 static void
81 gap_left (pos, newgap) 95 gap_left (charpos, bytepos, newgap)
82 register int pos; 96 register int charpos, bytepos;
83 int newgap; 97 int newgap;
84 { 98 {
85 register unsigned char *to, *from; 99 register unsigned char *to, *from;
86 register int i; 100 register int i;
87 int new_s1; 101 int new_s1;
88 102
89 pos--;
90
91 if (!newgap) 103 if (!newgap)
92 { 104 {
93 if (unchanged_modified == MODIFF 105 if (unchanged_modified == MODIFF
94 && overlay_unchanged_modified == OVERLAY_MODIFF) 106 && overlay_unchanged_modified == OVERLAY_MODIFF)
95 { 107 {
96 beg_unchanged = pos; 108 beg_unchanged = charpos - BEG;
97 end_unchanged = Z - pos - 1; 109 end_unchanged = Z - charpos;
98 } 110 }
99 else 111 else
100 { 112 {
101 if (Z - GPT < end_unchanged) 113 if (Z - GPT < end_unchanged)
102 end_unchanged = Z - GPT; 114 end_unchanged = Z - GPT;
103 if (pos < beg_unchanged) 115 if (charpos < beg_unchanged)
104 beg_unchanged = pos; 116 beg_unchanged = charpos - BEG;
105 } 117 }
106 } 118 }
107 119
108 i = GPT; 120 i = GPT_BYTE;
109 to = GAP_END_ADDR; 121 to = GAP_END_ADDR;
110 from = GPT_ADDR; 122 from = GPT_ADDR;
111 new_s1 = GPT - BEG; 123 new_s1 = GPT_BYTE;
112 124
113 /* Now copy the characters. To move the gap down, 125 /* Now copy the characters. To move the gap down,
114 copy characters up. */ 126 copy characters up. */
115 127
116 while (1) 128 while (1)
117 { 129 {
118 /* I gets number of characters left to copy. */ 130 /* I gets number of characters left to copy. */
119 i = new_s1 - pos; 131 i = new_s1 - bytepos;
120 if (i == 0) 132 if (i == 0)
121 break; 133 break;
122 /* If a quit is requested, stop copying now. 134 /* If a quit is requested, stop copying now.
123 Change POS to be where we have actually moved the gap to. */ 135 Change BYTEPOS to be where we have actually moved the gap to. */
124 if (QUITP) 136 if (QUITP)
125 { 137 {
126 pos = new_s1; 138 bytepos = new_s1;
139 charpos = BYTE_TO_CHAR (bytepos);
127 break; 140 break;
128 } 141 }
129 /* Move at most 32000 chars before checking again for a quit. */ 142 /* Move at most 32000 chars before checking again for a quit. */
130 if (i > 32000) 143 if (i > 32000)
131 i = 32000; 144 i = 32000;
151 while (--i >= 0) 164 while (--i >= 0)
152 *--to = *--from; 165 *--to = *--from;
153 } 166 }
154 } 167 }
155 168
156 /* Adjust markers, and buffer data structure, to put the gap at POS. 169 /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
157 POS is where the loop above stopped, which may be what was specified 170 BYTEPOS is where the loop above stopped, which may be what was specified
158 or may be where a quit was detected. */ 171 or may be where a quit was detected. */
159 adjust_markers (pos + 1, GPT, GAP_SIZE); 172 adjust_markers_gap_motion (bytepos, GPT_BYTE, GAP_SIZE);
160 GPT = pos + 1; 173 GPT_BYTE = bytepos;
174 GPT = charpos;
175 if (bytepos < charpos)
176 abort ();
161 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ 177 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
162 QUIT; 178 QUIT;
163 } 179 }
164 180
181 /* Move the gap to a position greater than than the current GPT.
182 BYTEPOS describes the new position as a byte position,
183 and CHARPOS is the corresponding char position. */
184
165 static void 185 static void
166 gap_right (pos) 186 gap_right (charpos, bytepos)
167 register int pos; 187 register int charpos, bytepos;
168 { 188 {
169 register unsigned char *to, *from; 189 register unsigned char *to, *from;
170 register int i; 190 register int i;
171 int new_s1; 191 int new_s1;
172 192
173 pos--;
174
175 if (unchanged_modified == MODIFF 193 if (unchanged_modified == MODIFF
176 && overlay_unchanged_modified == OVERLAY_MODIFF) 194 && overlay_unchanged_modified == OVERLAY_MODIFF)
177 195 {
178 { 196 beg_unchanged = charpos - BEG;
179 beg_unchanged = pos; 197 end_unchanged = Z - charpos;
180 end_unchanged = Z - pos - 1;
181 } 198 }
182 else 199 else
183 { 200 {
184 if (Z - pos - 1 < end_unchanged) 201 if (Z - charpos - 1 < end_unchanged)
185 end_unchanged = Z - pos - 1; 202 end_unchanged = Z - charpos;
186 if (GPT - BEG < beg_unchanged) 203 if (GPT - BEG < beg_unchanged)
187 beg_unchanged = GPT - BEG; 204 beg_unchanged = GPT - BEG;
188 } 205 }
189 206
190 i = GPT; 207 i = GPT_BYTE;
191 from = GAP_END_ADDR; 208 from = GAP_END_ADDR;
192 to = GPT_ADDR; 209 to = GPT_ADDR;
193 new_s1 = GPT - 1; 210 new_s1 = GPT_BYTE;
194 211
195 /* Now copy the characters. To move the gap up, 212 /* Now copy the characters. To move the gap up,
196 copy characters down. */ 213 copy characters down. */
197 214
198 while (1) 215 while (1)
199 { 216 {
200 /* I gets number of characters left to copy. */ 217 /* I gets number of characters left to copy. */
201 i = pos - new_s1; 218 i = bytepos - new_s1;
202 if (i == 0) 219 if (i == 0)
203 break; 220 break;
204 /* If a quit is requested, stop copying now. 221 /* If a quit is requested, stop copying now.
205 Change POS to be where we have actually moved the gap to. */ 222 Change BYTEPOS to be where we have actually moved the gap to. */
206 if (QUITP) 223 if (QUITP)
207 { 224 {
208 pos = new_s1; 225 bytepos = new_s1;
226 charpos = BYTE_TO_CHAR (bytepos);
209 break; 227 break;
210 } 228 }
211 /* Move at most 32000 chars before checking again for a quit. */ 229 /* Move at most 32000 chars before checking again for a quit. */
212 if (i > 32000) 230 if (i > 32000)
213 i = 32000; 231 i = 32000;
233 while (--i >= 0) 251 while (--i >= 0)
234 *to++ = *from++; 252 *to++ = *from++;
235 } 253 }
236 } 254 }
237 255
238 adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE); 256 adjust_markers_gap_motion (GPT_BYTE + GAP_SIZE, bytepos + GAP_SIZE,
239 GPT = pos + 1; 257 - GAP_SIZE);
258 GPT = charpos;
259 GPT_BYTE = bytepos;
260 if (bytepos < charpos)
261 abort ();
240 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ 262 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
241 QUIT; 263 QUIT;
242 } 264 }
243 265
244 /* Add AMOUNT to the position of every marker in the current buffer 266 /* Add AMOUNT to the byte position of every marker in the current buffer
245 whose current position is between FROM (exclusive) and TO (inclusive). 267 whose current byte position is between FROM (exclusive) and TO (inclusive).
246 268
247 Also, any markers past the outside of that interval, in the direction 269 Also, any markers past the outside of that interval, in the direction
248 of adjustment, are first moved back to the near end of the interval 270 of adjustment, are first moved back to the near end of the interval
249 and then adjusted by AMOUNT. 271 and then adjusted by AMOUNT.
250 272
251 When the latter adjustment is done, if AMOUNT is negative, 273 When the latter adjustment is done, if AMOUNT is negative,
252 we record the adjustment for undo. (This case happens only for 274 we record the adjustment for undo. (This case happens only for
253 deletion.) */ 275 deletion.)
276
277 The markers' character positions are not altered,
278 because gap motion does not affect character positions. */
279
280 int adjust_markers_test;
254 281
255 static void 282 static void
256 adjust_markers (from, to, amount) 283 adjust_markers_gap_motion (from, to, amount)
257 register int from, to, amount; 284 register int from, to, amount;
258 { 285 {
259 Lisp_Object marker; 286 Lisp_Object marker;
260 register struct Lisp_Marker *m; 287 register struct Lisp_Marker *m;
261 register int mpos; 288 register int mpos;
267 m = XMARKER (marker); 294 m = XMARKER (marker);
268 mpos = m->bufpos; 295 mpos = m->bufpos;
269 if (amount > 0) 296 if (amount > 0)
270 { 297 {
271 if (mpos > to && mpos < to + amount) 298 if (mpos > to && mpos < to + amount)
272 mpos = to + amount; 299 {
300 if (adjust_markers_test)
301 abort ();
302 mpos = to + amount;
303 }
273 } 304 }
274 else 305 else
275 { 306 {
276 /* Here's the case where a marker is inside text being deleted. 307 /* Here's the case where a marker is inside text being deleted.
277 AMOUNT can be negative for gap motion, too, 308 AMOUNT can be negative for gap motion, too,
278 but then this range contains no markers. */ 309 but then this range contains no markers. */
279 if (mpos > from + amount && mpos <= from) 310 if (mpos > from + amount && mpos <= from)
280 { 311 {
281 int before = mpos; 312 if (adjust_markers_test)
282 int after = from + amount; 313 abort ();
283 314 mpos = from + amount;
284 mpos = after;
285
286 /* Compute the before and after positions
287 as buffer positions. */
288 if (before > GPT + GAP_SIZE)
289 before -= GAP_SIZE;
290 else if (before > GPT)
291 before = GPT;
292
293 if (after > GPT + GAP_SIZE)
294 after -= GAP_SIZE;
295 else if (after > GPT)
296 after = GPT;
297
298 record_marker_adjustment (marker, after - before);
299 } 315 }
300 } 316 }
301 if (mpos > from && mpos <= to) 317 if (mpos > from && mpos <= to)
302 mpos += amount; 318 mpos += amount;
303 m->bufpos = mpos; 319 m->bufpos = mpos;
304 marker = m->chain; 320 marker = m->chain;
305 } 321 }
306 } 322 }
307 323
308 /* Adjust markers whose insertion-type is t 324 /* Adjust all markers for a deletion
309 for an insertion of AMOUNT characters at POS. */ 325 whose range in bytes is FROM_BYTE to TO_BYTE.
326 The range in charpos is FROM to TO.
327
328 This function assumes that the gap is adjacent to
329 or inside of the range being deleted. */
310 330
311 static void 331 static void
312 adjust_markers_for_insert (pos, amount) 332 adjust_markers_for_delete (from, from_byte, to, to_byte)
313 register int pos, amount; 333 register int from, from_byte, to, to_byte;
334 {
335 Lisp_Object marker;
336 register struct Lisp_Marker *m;
337 register int charpos;
338 /* This is what GAP_SIZE will be when this deletion is finished. */
339 int coming_gap_size = GAP_SIZE + to_byte - from_byte;
340
341 marker = BUF_MARKERS (current_buffer);
342
343 while (!NILP (marker))
344 {
345 m = XMARKER (marker);
346 charpos = m->charpos;
347
348 if (charpos > Z)
349 abort ();
350
351 /* If the marker is after the deletion,
352 its bufpos needs no change because the deleted text
353 becomes gap; but its charpos needs to be decreased. */
354 if (charpos > to)
355 m->charpos -= to - from;
356
357 /* Here's the case where a marker is inside text being deleted.
358 We take advantage of the fact that the deletion is at the gap. */
359 else if (charpos > from)
360 {
361 record_marker_adjustment (marker, from - charpos);
362 m->charpos = from;
363 /* The gap must be at or after FROM_BYTE when we do a deletion. */
364 m->bufpos = from_byte;
365 }
366
367 /* In a single-byte buffer, a marker's two positions must be equal. */
368 if (Z == Z_BYTE)
369 {
370 register int i = m->bufpos;
371
372 /* We use FROM_BYTE here instead of GPT_BYTE
373 because FROM_BYTE is where the gap will be after the deletion. */
374 if (i > from_byte + coming_gap_size)
375 i -= coming_gap_size;
376 else if (i > from_byte)
377 i = from_byte;
378
379 if (m->charpos != i)
380 abort ();
381 }
382
383 marker = m->chain;
384 }
385 }
386
387 /* Adjust markers for an insertion at CHARPOS / BYTEPOS
388 consisting of NCHARS chars, which are NBYTES bytes.
389
390 We have to relocate the charpos of every marker that points
391 after the insertion (but not their bufpos).
392
393 When a marker points at the insertion point,
394 we advance it if either its insertion-type is t
395 or BEFORE_MARKERS is true. */
396
397 static void
398 adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
399 register int from, from_byte, to, to_byte, before_markers;
314 { 400 {
315 Lisp_Object marker; 401 Lisp_Object marker;
316 int adjusted = 0; 402 int adjusted = 0;
403 int nchars = to - from;
404 int nbytes = to_byte - from_byte;
317 405
318 marker = BUF_MARKERS (current_buffer); 406 marker = BUF_MARKERS (current_buffer);
319 407
320 while (!NILP (marker)) 408 while (!NILP (marker))
321 { 409 {
322 register struct Lisp_Marker *m = XMARKER (marker); 410 register struct Lisp_Marker *m = XMARKER (marker);
323 if (m->insertion_type && m->bufpos == pos) 411 if (m->bufpos == from_byte
412 && (m->insertion_type || before_markers))
324 { 413 {
325 m->bufpos += amount; 414 m->bufpos += nbytes;
326 adjusted = 1; 415 m->charpos += nchars;
416 if (m->insertion_type)
417 adjusted = 1;
327 } 418 }
419 else if (m->bufpos > from_byte)
420 m->charpos += nchars;
421
422 /* In a single-byte buffer, a marker's two positions must be equal. */
423 if (Z == Z_BYTE)
424 {
425 register int i = m->bufpos;
426
427 if (i > GPT_BYTE + GAP_SIZE)
428 i -= GAP_SIZE;
429 else if (i > GPT_BYTE)
430 i = GPT_BYTE;
431
432 if (m->charpos != i)
433 abort ();
434 }
435
328 marker = m->chain; 436 marker = m->chain;
329 } 437 }
438
439 /* Adjusting only markers whose insertion-type is t may result in
440 disordered overlays in the slot `overlays_before'. */
330 if (adjusted) 441 if (adjusted)
331 /* Adjusting only markers whose insertion-type is t may result in 442 fix_overlays_before (current_buffer, from, to);
332 disordered overlays in the slot `overlays_before'. */ 443 }
333 fix_overlays_before (current_buffer, pos, pos + amount); 444
334 } 445 /* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
335 446
336 /* Add the specified amount to point. This is used only when the value 447 This is used only when the value of point changes due to an insert
337 of point changes due to an insert or delete; it does not represent 448 or delete; it does not represent a conceptual change in point as a
338 a conceptual change in point as a marker. In particular, point is 449 marker. In particular, point is not crossing any interval
339 not crossing any interval boundaries, so there's no need to use the 450 boundaries, so there's no need to use the usual SET_PT macro. In
340 usual SET_PT macro. In fact it would be incorrect to do so, because 451 fact it would be incorrect to do so, because either the old or the
341 either the old or the new value of point is out of sync with the 452 new value of point is out of sync with the current set of
342 current set of intervals. */ 453 intervals. */
454
343 static void 455 static void
344 adjust_point (amount) 456 adjust_point (nchars, nbytes)
345 int amount; 457 int nchars, nbytes;
346 { 458 {
347 BUF_PT (current_buffer) += amount; 459 BUF_PT (current_buffer) += nchars;
460 BUF_PT_BYTE (current_buffer) += nbytes;
461
462 /* In a single-byte buffer, the two positions must be equal. */
463 if (ZV == ZV_BYTE
464 && PT != PT_BYTE)
465 abort ();
348 } 466 }
349 467
350 /* Make the gap INCREMENT characters longer. */ 468 /* Make the gap NBYTES_ADDED bytes longer. */
351 469
352 void 470 void
353 make_gap (increment) 471 make_gap (nbytes_added)
354 int increment; 472 int nbytes_added;
355 { 473 {
356 unsigned char *result; 474 unsigned char *result;
357 Lisp_Object tem; 475 Lisp_Object tem;
358 int real_gap_loc; 476 int real_gap_loc;
477 int real_gap_loc_byte;
359 int old_gap_size; 478 int old_gap_size;
360 479
361 /* If we have to get more space, get enough to last a while. */ 480 /* If we have to get more space, get enough to last a while. */
362 increment += 2000; 481 nbytes_added += 2000;
363 482
364 /* Don't allow a buffer size that won't fit in an int 483 /* Don't allow a buffer size that won't fit in an int
365 even if it will fit in a Lisp integer. 484 even if it will fit in a Lisp integer.
366 That won't work because so many places use `int'. */ 485 That won't work because so many places use `int'. */
367 486
368 if (Z - BEG + GAP_SIZE + increment 487 if (Z_BYTE - BEG_BYTE + GAP_SIZE + nbytes_added
369 >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1))) 488 >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
370 error ("Buffer exceeds maximum size"); 489 error ("Buffer exceeds maximum size");
371 490
372 BLOCK_INPUT; 491 BLOCK_INPUT;
373 /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */ 492 /* We allocate extra 1-byte `\0' at the tail for anchoring a search. */
374 result = BUFFER_REALLOC (BEG_ADDR, (Z - BEG + GAP_SIZE + increment + 1)); 493 result = BUFFER_REALLOC (BEG_ADDR, (Z_BYTE - BEG_BYTE
494 + GAP_SIZE + nbytes_added + 1));
375 495
376 if (result == 0) 496 if (result == 0)
377 { 497 {
378 UNBLOCK_INPUT; 498 UNBLOCK_INPUT;
379 memory_full (); 499 memory_full ();
386 /* Prevent quitting in move_gap. */ 506 /* Prevent quitting in move_gap. */
387 tem = Vinhibit_quit; 507 tem = Vinhibit_quit;
388 Vinhibit_quit = Qt; 508 Vinhibit_quit = Qt;
389 509
390 real_gap_loc = GPT; 510 real_gap_loc = GPT;
511 real_gap_loc_byte = GPT_BYTE;
391 old_gap_size = GAP_SIZE; 512 old_gap_size = GAP_SIZE;
392 513
393 /* Call the newly allocated space a gap at the end of the whole space. */ 514 /* Call the newly allocated space a gap at the end of the whole space. */
394 GPT = Z + GAP_SIZE; 515 GPT = Z + GAP_SIZE;
395 GAP_SIZE = increment; 516 GAP_SIZE = nbytes_added;
396 517
397 /* Move the new gap down to be consecutive with the end of the old one. 518 /* Move the new gap down to be consecutive with the end of the old one.
398 This adjusts the markers properly too. */ 519 This adjusts the markers properly too. */
399 gap_left (real_gap_loc + old_gap_size, 1); 520 gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
400 521
401 /* Now combine the two into one large gap. */ 522 /* Now combine the two into one large gap. */
402 GAP_SIZE += old_gap_size; 523 GAP_SIZE += old_gap_size;
403 GPT = real_gap_loc; 524 GPT = real_gap_loc;
525 GPT_BYTE = real_gap_loc_byte;
404 526
405 /* Put an anchor. */ 527 /* Put an anchor. */
406 *(Z_ADDR) = 0; 528 *(Z_ADDR) = 0;
407 529
408 Vinhibit_quit = tem; 530 Vinhibit_quit = tem;
411 /* Insert a string of specified length before point. 533 /* Insert a string of specified length before point.
412 DO NOT use this for the contents of a Lisp string or a Lisp buffer! 534 DO NOT use this for the contents of a Lisp string or a Lisp buffer!
413 prepare_to_modify_buffer could relocate the text. */ 535 prepare_to_modify_buffer could relocate the text. */
414 536
415 void 537 void
416 insert (string, length) 538 insert (string, nbytes)
417 register unsigned char *string; 539 register unsigned char *string;
418 register length; 540 register nbytes;
419 { 541 {
420 if (length > 0) 542 if (nbytes > 0)
421 { 543 {
422 insert_1 (string, length, 0, 1); 544 int opoint = PT;
423 signal_after_change (PT-length, 0, length); 545 insert_1 (string, nbytes, 0, 1, 0);
424 } 546 signal_after_change (opoint, 0, PT - opoint);
425 } 547 }
426 548 }
427 void 549
428 insert_and_inherit (string, length) 550 void
551 insert_and_inherit (string, nbytes)
429 register unsigned char *string; 552 register unsigned char *string;
430 register length; 553 register nbytes;
431 { 554 {
432 if (length > 0) 555 if (nbytes > 0)
433 { 556 {
434 insert_1 (string, length, 1, 1); 557 int opoint = PT;
435 signal_after_change (PT-length, 0, length); 558 insert_1 (string, nbytes, 1, 1, 0);
436 } 559 signal_after_change (opoint, 0, PT - opoint);
437 } 560 }
438 561 }
439 void 562
440 insert_1 (string, length, inherit, prepare) 563 /* Insert the character C before point */
564
565 void
566 insert_char (c)
567 int c;
568 {
569 unsigned char workbuf[4], *str;
570 int len = CHAR_STRING (c, workbuf, str);
571
572 insert (str, len);
573 }
574
575 /* Insert the null-terminated string S before point */
576
577 void
578 insert_string (s)
579 char *s;
580 {
581 insert (s, strlen (s));
582 }
583
584 /* Like `insert' except that all markers pointing at the place where
585 the insertion happens are adjusted to point after it.
586 Don't use this function to insert part of a Lisp string,
587 since gc could happen and relocate it. */
588
589 void
590 insert_before_markers (string, nbytes)
591 unsigned char *string;
592 register int nbytes;
593 {
594 if (nbytes > 0)
595 {
596 int opoint = PT;
597
598 insert_1 (string, nbytes, 0, 1, 1);
599 signal_after_change (opoint, 0, PT - opoint);
600 }
601 }
602
603 void
604 insert_before_markers_and_inherit (string, nbytes)
605 unsigned char *string;
606 register int nbytes;
607 {
608 if (nbytes > 0)
609 {
610 int opoint = PT;
611
612 insert_1 (string, nbytes, 1, 1, 1);
613 signal_after_change (opoint, 0, PT - opoint);
614 }
615 }
616
617 /* Subroutine used by the insert functions above. */
618
619 void
620 insert_1 (string, nbytes, inherit, prepare, before_markers)
441 register unsigned char *string; 621 register unsigned char *string;
442 register int length; 622 register int nbytes;
443 int inherit, prepare; 623 int inherit, prepare, before_markers;
444 { 624 {
445 register Lisp_Object temp; 625 register Lisp_Object temp;
626 int nchars = chars_in_text (string, nbytes);
446 627
447 if (prepare) 628 if (prepare)
448 prepare_to_modify_buffer (PT, PT, NULL); 629 prepare_to_modify_buffer (PT, PT, NULL);
449 630
450 if (PT != GPT) 631 if (PT != GPT)
451 move_gap (PT); 632 move_gap_both (PT, PT_BYTE);
452 if (GAP_SIZE < length) 633 if (GAP_SIZE < nbytes)
453 make_gap (length - GAP_SIZE); 634 make_gap (nbytes - GAP_SIZE);
454 635
455 record_insert (PT, length); 636 record_insert (PT, nchars);
456 MODIFF++; 637 MODIFF++;
457 638
458 bcopy (string, GPT_ADDR, length); 639 bcopy (string, GPT_ADDR, nbytes);
459 640
460 #ifdef USE_TEXT_PROPERTIES 641 #ifdef USE_TEXT_PROPERTIES
461 if (BUF_INTERVALS (current_buffer) != 0) 642 if (BUF_INTERVALS (current_buffer) != 0)
462 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */ 643 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */
463 offset_intervals (current_buffer, PT, length); 644 offset_intervals (current_buffer, PT, nchars);
464 #endif 645 #endif
465 646
466 GAP_SIZE -= length; 647 GAP_SIZE -= nbytes;
467 GPT += length; 648 GPT += nchars;
468 ZV += length; 649 ZV += nchars;
469 Z += length; 650 Z += nchars;
651 GPT_BYTE += nbytes;
652 ZV_BYTE += nbytes;
653 Z_BYTE += nbytes;
470 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ 654 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
471 adjust_overlays_for_insert (PT, length); 655 adjust_overlays_for_insert (PT, nchars);
472 adjust_markers_for_insert (PT, length); 656 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + nbytes,
473 adjust_point (length); 657 before_markers);
658 adjust_point (nchars, nbytes);
659
660 if (GPT_BYTE < GPT)
661 abort ();
474 662
475 #ifdef USE_TEXT_PROPERTIES 663 #ifdef USE_TEXT_PROPERTIES
476 if (!inherit && BUF_INTERVALS (current_buffer) != 0) 664 if (!inherit && BUF_INTERVALS (current_buffer) != 0)
477 Fset_text_properties (make_number (PT - length), make_number (PT), 665 Fset_text_properties (make_number (PT - nchars), make_number (PT),
478 Qnil, Qnil); 666 Qnil, Qnil);
479 #endif 667 #endif
480 } 668 }
481 669
482 /* Insert the part of the text of STRING, a Lisp object assumed to be 670 /* Insert the part of the text of STRING, a Lisp object assumed to be
483 of type string, consisting of the LENGTH characters starting at 671 of type string, consisting of the LENGTH characters starting at
484 position POS. If the text of STRING has properties, they are absorbed 672 position POS. If the text of STRING has properties, they are absorbed
485 into the buffer. 673 into the buffer.
486 674
494 register int pos, length; 682 register int pos, length;
495 int inherit; 683 int inherit;
496 { 684 {
497 if (length > 0) 685 if (length > 0)
498 { 686 {
499 insert_from_string_1 (string, pos, length, inherit); 687 int opoint = PT;
500 signal_after_change (PT-length, 0, length); 688 int nchars = chars_in_text (XSTRING (string)->data + pos, length);
501 } 689 insert_from_string_1 (string, pos, length, nchars, inherit, 0);
502 } 690 signal_after_change (opoint, 0, PT - opoint);
503 691 }
504 static void
505 insert_from_string_1 (string, pos, length, inherit)
506 Lisp_Object string;
507 register int pos, length;
508 int inherit;
509 {
510 register Lisp_Object temp;
511 struct gcpro gcpro1;
512
513 /* Make sure point-max won't overflow after this insertion. */
514 XSETINT (temp, length + Z);
515 if (length + Z != XINT (temp))
516 error ("maximum buffer size exceeded");
517
518 GCPRO1 (string);
519 prepare_to_modify_buffer (PT, PT, NULL);
520
521 if (PT != GPT)
522 move_gap (PT);
523 if (GAP_SIZE < length)
524 make_gap (length - GAP_SIZE);
525
526 record_insert (PT, length);
527 MODIFF++;
528 UNGCPRO;
529
530 bcopy (XSTRING (string)->data, GPT_ADDR, length);
531
532 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
533 offset_intervals (current_buffer, PT, length);
534
535 GAP_SIZE -= length;
536 GPT += length;
537 ZV += length;
538 Z += length;
539 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
540 adjust_overlays_for_insert (PT, length);
541 adjust_markers_for_insert (PT, length);
542
543 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
544 graft_intervals_into_buffer (XSTRING (string)->intervals, PT, length,
545 current_buffer, inherit);
546
547 adjust_point (length);
548 }
549
550 /* Insert text from BUF, starting at POS and having length LENGTH, into the
551 current buffer. If the text in BUF has properties, they are absorbed
552 into the current buffer.
553
554 It does not work to use `insert' for this, because a malloc could happen
555 and relocate BUF's text before the bcopy happens. */
556
557 void
558 insert_from_buffer (buf, pos, length, inherit)
559 struct buffer *buf;
560 int pos, length;
561 int inherit;
562 {
563 if (length > 0)
564 {
565 insert_from_buffer_1 (buf, pos, length, inherit);
566 signal_after_change (PT-length, 0, length);
567 }
568 }
569
570 static void
571 insert_from_buffer_1 (buf, pos, length, inherit)
572 struct buffer *buf;
573 int pos, length;
574 int inherit;
575 {
576 register Lisp_Object temp;
577 int chunk;
578
579 /* Make sure point-max won't overflow after this insertion. */
580 XSETINT (temp, length + Z);
581 if (length + Z != XINT (temp))
582 error ("maximum buffer size exceeded");
583
584 prepare_to_modify_buffer (PT, PT, NULL);
585
586 if (PT != GPT)
587 move_gap (PT);
588 if (GAP_SIZE < length)
589 make_gap (length - GAP_SIZE);
590
591 record_insert (PT, length);
592 MODIFF++;
593
594 if (pos < BUF_GPT (buf))
595 {
596 chunk = BUF_GPT (buf) - pos;
597 if (chunk > length)
598 chunk = length;
599 bcopy (BUF_CHAR_ADDRESS (buf, pos), GPT_ADDR, chunk);
600 }
601 else
602 chunk = 0;
603 if (chunk < length)
604 bcopy (BUF_CHAR_ADDRESS (buf, pos + chunk),
605 GPT_ADDR + chunk, length - chunk);
606
607 #ifdef USE_TEXT_PROPERTIES
608 if (BUF_INTERVALS (current_buffer) != 0)
609 offset_intervals (current_buffer, PT, length);
610 #endif
611
612 GAP_SIZE -= length;
613 GPT += length;
614 ZV += length;
615 Z += length;
616 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
617 adjust_overlays_for_insert (PT, length);
618 adjust_markers_for_insert (PT, length);
619 adjust_point (length);
620
621 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
622 graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf),
623 pos, length),
624 PT - length, length, current_buffer, inherit);
625 }
626
627 /* Insert the character C before point */
628
629 void
630 insert_char (c)
631 int c;
632 {
633 unsigned char workbuf[4], *str;
634 int len = CHAR_STRING (c, workbuf, str);
635
636 insert (str, len);
637 }
638
639 /* Insert the null-terminated string S before point */
640
641 void
642 insert_string (s)
643 char *s;
644 {
645 insert (s, strlen (s));
646 } 692 }
647 693
648 /* Like `insert' except that all markers pointing at the place where 694 /* Like `insert' except that all markers pointing at the place where
649 the insertion happens are adjusted to point after it. 695 the insertion happens are adjusted to point after it.
650 Don't use this function to insert part of a Lisp string, 696 Don't use this function to insert part of a Lisp string,
651 since gc could happen and relocate it. */ 697 since gc could happen and relocate it. */
652 698
653 void
654 insert_before_markers (string, length)
655 unsigned char *string;
656 register int length;
657 {
658 if (length > 0)
659 {
660 register int opoint = PT;
661 insert_1 (string, length, 0, 1);
662 adjust_markers (opoint - 1, opoint, length);
663 signal_after_change (PT-length, 0, length);
664 }
665 }
666
667 void
668 insert_before_markers_and_inherit (string, length)
669 unsigned char *string;
670 register int length;
671 {
672 if (length > 0)
673 {
674 register int opoint = PT;
675 insert_1 (string, length, 1, 1);
676 adjust_markers (opoint - 1, opoint, length);
677 signal_after_change (PT-length, 0, length);
678 }
679 }
680
681 /* Insert part of a Lisp string, relocating markers after. */ 699 /* Insert part of a Lisp string, relocating markers after. */
682 700
683 void 701 void
684 insert_from_string_before_markers (string, pos, length, inherit) 702 insert_from_string_before_markers (string, pos, length, inherit)
685 Lisp_Object string; 703 Lisp_Object string;
686 register int pos, length; 704 register int pos, length;
687 int inherit; 705 int inherit;
688 { 706 {
689 if (length > 0) 707 if (length > 0)
690 { 708 {
691 register int opoint = PT; 709 int opoint = PT;
692 insert_from_string_1 (string, pos, length, inherit); 710 int nchars = chars_in_text (XSTRING (string)->data + pos, length);
693 adjust_markers (opoint - 1, opoint, length); 711 insert_from_string_1 (string, pos, length, nchars, inherit, 1);
694 signal_after_change (PT-length, 0, length); 712 signal_after_change (opoint, 0, PT - opoint);
695 } 713 }
714 }
715
716 /* Subroutine of the insertion functions above. */
717
718 static void
719 insert_from_string_1 (string, pos, nbytes, nchars, inherit, before_markers)
720 Lisp_Object string;
721 register int pos, nbytes, nchars;
722 int inherit, before_markers;
723 {
724 register Lisp_Object temp;
725 struct gcpro gcpro1;
726
727 /* Make sure point-max won't overflow after this insertion. */
728 XSETINT (temp, nbytes + Z_BYTE);
729 if (nbytes + Z_BYTE != XINT (temp))
730 error ("Maximum buffer size exceeded");
731
732 GCPRO1 (string);
733 prepare_to_modify_buffer (PT, PT, NULL);
734
735 if (PT != GPT)
736 move_gap_both (PT, PT_BYTE);
737 if (GAP_SIZE < nbytes)
738 make_gap (nbytes - GAP_SIZE);
739
740 record_insert (PT, nchars);
741 MODIFF++;
742 UNGCPRO;
743
744 bcopy (XSTRING (string)->data, GPT_ADDR, nbytes);
745
746 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
747 offset_intervals (current_buffer, PT, nchars);
748
749 GAP_SIZE -= nbytes;
750 GPT += nchars;
751 ZV += nchars;
752 Z += nchars;
753 GPT_BYTE += nbytes;
754 ZV_BYTE += nbytes;
755 Z_BYTE += nbytes;
756 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
757 adjust_overlays_for_insert (PT, nchars);
758 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + nbytes,
759 before_markers);
760
761 if (GPT_BYTE < GPT)
762 abort ();
763
764 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
765 graft_intervals_into_buffer (XSTRING (string)->intervals, PT, nchars,
766 current_buffer, inherit);
767
768 adjust_point (nchars, nbytes);
696 } 769 }
697 770
698 /* Replace the text from FROM to TO with NEW, 771 /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
772 current buffer. If the text in BUF has properties, they are absorbed
773 into the current buffer.
774
775 It does not work to use `insert' for this, because a malloc could happen
776 and relocate BUF's text before the bcopy happens. */
777
778 void
779 insert_from_buffer (buf, charpos, nchars, inherit)
780 struct buffer *buf;
781 int charpos, nchars;
782 int inherit;
783 {
784 if (nchars > 0)
785 {
786 int opoint = PT;
787
788 insert_from_buffer_1 (buf, charpos, nchars, inherit);
789 signal_after_change (opoint, 0, PT - opoint);
790 }
791 }
792
793 static void
794 insert_from_buffer_1 (buf, from, nchars, inherit)
795 struct buffer *buf;
796 int from, nchars;
797 int inherit;
798 {
799 register Lisp_Object temp;
800 int chunk;
801 int from_byte = buf_charpos_to_bytepos (buf, from);
802 int to_byte = buf_charpos_to_bytepos (buf, from + nchars);
803 int nbytes = to_byte - from_byte;
804
805 /* Make sure point-max won't overflow after this insertion. */
806 XSETINT (temp, nbytes + Z);
807 if (nbytes + Z != XINT (temp))
808 error ("Maximum buffer size exceeded");
809
810 prepare_to_modify_buffer (PT, PT, NULL);
811
812 if (PT != GPT)
813 move_gap_both (PT, PT_BYTE);
814 if (GAP_SIZE < nbytes)
815 make_gap (nbytes - GAP_SIZE);
816
817 record_insert (PT, nchars);
818 MODIFF++;
819
820 if (from < BUF_GPT (buf))
821 {
822 chunk = BUF_GPT_BYTE (buf) - from_byte;
823 if (chunk > nbytes)
824 chunk = nbytes;
825 bcopy (BUF_BYTE_ADDRESS (buf, from_byte), GPT_ADDR, chunk);
826 }
827 else
828 chunk = 0;
829 if (chunk < nbytes)
830 bcopy (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
831 GPT_ADDR + chunk, nbytes - chunk);
832
833 #ifdef USE_TEXT_PROPERTIES
834 if (BUF_INTERVALS (current_buffer) != 0)
835 offset_intervals (current_buffer, PT, nchars);
836 #endif
837
838 GAP_SIZE -= nbytes;
839 GPT += nchars;
840 ZV += nchars;
841 Z += nchars;
842 GPT_BYTE += nbytes;
843 ZV_BYTE += nbytes;
844 Z_BYTE += nbytes;
845 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
846 adjust_overlays_for_insert (PT, nchars);
847 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + nbytes, 0);
848 adjust_point (nchars, nbytes);
849
850 if (GPT_BYTE < GPT)
851 abort ();
852
853 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
854 graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf),
855 from, nchars),
856 PT - nchars, nchars,
857 current_buffer, inherit);
858 }
859
860 /* Replace the text from character positions FROM to TO with NEW,
699 If PREPARE is nonzero, call prepare_to_modify_buffer. 861 If PREPARE is nonzero, call prepare_to_modify_buffer.
700 If INHERIT, the newly inserted text should inherit text properties 862 If INHERIT, the newly inserted text should inherit text properties
701 from the surrounding non-deleted text. */ 863 from the surrounding non-deleted text. */
702 864
703 /* Note that this does not yet handle markers quite right. 865 /* Note that this does not yet handle markers quite right.
708 void 870 void
709 replace_range (from, to, new, prepare, inherit) 871 replace_range (from, to, new, prepare, inherit)
710 Lisp_Object new; 872 Lisp_Object new;
711 int from, to, prepare, inherit; 873 int from, to, prepare, inherit;
712 { 874 {
713 int numdel; 875 int insbytes = XSTRING (new)->size;
714 int inslen = XSTRING (new)->size; 876 int inschars;
877 int from_byte, to_byte;
878 int nbytes_del, nchars_del;
715 register Lisp_Object temp; 879 register Lisp_Object temp;
716 struct gcpro gcpro1; 880 struct gcpro gcpro1;
717 881
718 GCPRO1 (new); 882 GCPRO1 (new);
719 883
721 { 885 {
722 int range_length = to - from; 886 int range_length = to - from;
723 prepare_to_modify_buffer (from, to, &from); 887 prepare_to_modify_buffer (from, to, &from);
724 to = from + range_length; 888 to = from + range_length;
725 } 889 }
890
891 UNGCPRO;
726 892
727 /* Make args be valid */ 893 /* Make args be valid */
728 if (from < BEGV) 894 if (from < BEGV)
729 from = BEGV; 895 from = BEGV;
730 if (to > ZV) 896 if (to > ZV)
731 to = ZV; 897 to = ZV;
732 898
733 UNGCPRO; 899 from_byte = CHAR_TO_BYTE (from);
734 900 to_byte = CHAR_TO_BYTE (to);
735 numdel = to - from; 901
902 nchars_del = to - from;
903 nbytes_del = to_byte - from_byte;
904
905 if (nbytes_del <= 0 && insbytes == 0)
906 return;
736 907
737 /* Make sure point-max won't overflow after this insertion. */ 908 /* Make sure point-max won't overflow after this insertion. */
738 XSETINT (temp, Z - numdel + inslen); 909 XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
739 if (Z - numdel + inslen != XINT (temp)) 910 if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
740 error ("maximum buffer size exceeded"); 911 error ("Maximum buffer size exceeded");
741 912
742 if (numdel <= 0 && inslen == 0) 913 inschars = XINT (Fchars_in_string (new));
743 return;
744 914
745 GCPRO1 (new); 915 GCPRO1 (new);
746 916
747 /* Make sure the gap is somewhere in or next to what we are deleting. */ 917 /* Make sure the gap is somewhere in or next to what we are deleting. */
748 if (from > GPT) 918 if (from > GPT)
749 gap_right (from); 919 gap_right (from, from_byte);
750 if (to < GPT) 920 if (to < GPT)
751 gap_left (to, 0); 921 gap_left (to, to_byte, 0);
752 922
753 /* Relocate all markers pointing into the new, larger gap 923 /* Relocate all markers pointing into the new, larger gap
754 to point at the end of the text before the gap. 924 to point at the end of the text before the gap.
755 This has to be done before recording the deletion, 925 Do this before recording the deletion,
756 so undo handles this after reinserting the text. */ 926 so that undo handles this after reinserting the text. */
757 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE); 927 adjust_markers_for_delete (from, from_byte, to, to_byte);
758 928
759 record_delete (from, numdel); 929 record_delete (from, nchars_del);
760 930
761 GAP_SIZE += numdel; 931 GAP_SIZE += nbytes_del;
762 ZV -= numdel; 932 ZV -= nchars_del;
763 Z -= numdel; 933 Z -= nchars_del;
934 ZV_BYTE -= nbytes_del;
935 Z_BYTE -= nbytes_del;
764 GPT = from; 936 GPT = from;
937 GPT_BYTE = from_byte;
765 *(GPT_ADDR) = 0; /* Put an anchor. */ 938 *(GPT_ADDR) = 0; /* Put an anchor. */
939
940 if (GPT_BYTE < GPT)
941 abort ();
766 942
767 if (GPT - BEG < beg_unchanged) 943 if (GPT - BEG < beg_unchanged)
768 beg_unchanged = GPT - BEG; 944 beg_unchanged = GPT - BEG;
769 if (Z - GPT < end_unchanged) 945 if (Z - GPT < end_unchanged)
770 end_unchanged = Z - GPT; 946 end_unchanged = Z - GPT;
771 947
772 if (GAP_SIZE < inslen) 948 if (GAP_SIZE < insbytes)
773 make_gap (inslen - GAP_SIZE); 949 make_gap (insbytes - GAP_SIZE);
774 950
775 record_insert (from, inslen); 951 record_insert (from, inschars);
776 952
777 bcopy (XSTRING (new)->data, GPT_ADDR, inslen); 953 bcopy (XSTRING (new)->data, GPT_ADDR, insbytes);
778 954
779 /* Relocate point as if it were a marker. */ 955 /* Relocate point as if it were a marker. */
780 if (from < PT) 956 if (from < PT)
781 adjust_point (from + inslen - (PT < to ? PT : to)); 957 adjust_point (from + inschars - (PT < to ? PT : to),
958 (from_byte + insbytes
959 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
782 960
783 #ifdef USE_TEXT_PROPERTIES 961 #ifdef USE_TEXT_PROPERTIES
784 offset_intervals (current_buffer, PT, inslen - numdel); 962 offset_intervals (current_buffer, PT, inschars - nchars_del);
785 #endif 963 #endif
786 964
787 GAP_SIZE -= inslen; 965 GAP_SIZE -= insbytes;
788 GPT += inslen; 966 GPT += inschars;
789 ZV += inslen; 967 ZV += inschars;
790 Z += inslen; 968 Z += inschars;
969 GPT_BYTE += insbytes;
970 ZV_BYTE += insbytes;
971 ZV_BYTE += insbytes;
791 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ 972 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */
973
974 if (GPT_BYTE < GPT)
975 abort ();
792 976
793 /* Adjust the overlay center as needed. This must be done after 977 /* Adjust the overlay center as needed. This must be done after
794 adjusting the markers that bound the overlays. */ 978 adjusting the markers that bound the overlays. */
795 adjust_overlays_for_delete (from, numdel); 979 adjust_overlays_for_delete (from, nchars_del);
796 adjust_overlays_for_insert (from, inslen); 980 adjust_overlays_for_insert (from, inschars);
797 adjust_markers_for_insert (from, inslen); 981 adjust_markers_for_insert (from, from_byte, from + inschars,
982 from_byte + insbytes, 0);
798 983
799 #ifdef USE_TEXT_PROPERTIES 984 #ifdef USE_TEXT_PROPERTIES
800 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */ 985 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
801 graft_intervals_into_buffer (XSTRING (new)->intervals, from, inslen, 986 graft_intervals_into_buffer (XSTRING (new)->intervals, from,
802 current_buffer, inherit); 987 inschars, current_buffer, inherit);
803 #endif 988 #endif
804 989
805 if (inslen == 0) 990 if (insbytes == 0)
806 evaporate_overlays (from); 991 evaporate_overlays (from);
807 992
808 MODIFF++; 993 MODIFF++;
809 UNGCPRO; 994 UNGCPRO;
810 995
811 signal_after_change (from, numdel, inslen); 996 signal_after_change (from, nchars_del, inschars);
812 } 997 }
813 998
814 /* Delete characters in current buffer 999 /* Delete characters in current buffer
815 from FROM up to (but not including) TO. */ 1000 from FROM up to (but not including) TO.
1001 If TO comes before FROM, we delete nothing. */
816 1002
817 void 1003 void
818 del_range (from, to) 1004 del_range (from, to)
819 register int from, to; 1005 register int from, to;
820 { 1006 {
825 1011
826 void 1012 void
827 del_range_1 (from, to, prepare) 1013 del_range_1 (from, to, prepare)
828 int from, to, prepare; 1014 int from, to, prepare;
829 { 1015 {
830 register int numdel; 1016 int from_byte, to_byte;
831
832 if (prepare)
833 {
834 int range_length = to - from;
835 prepare_to_modify_buffer (from, to, &from);
836 to = from + range_length;
837 }
838 1017
839 /* Make args be valid */ 1018 /* Make args be valid */
840 if (from < BEGV) 1019 if (from < BEGV)
841 from = BEGV; 1020 from = BEGV;
842 if (to > ZV) 1021 if (to > ZV)
843 to = ZV; 1022 to = ZV;
844 1023
845 if ((numdel = to - from) <= 0) 1024 if (to <= from)
846 return; 1025 return;
1026
1027 if (prepare)
1028 {
1029 int range_length = to - from;
1030 prepare_to_modify_buffer (from, to, &from);
1031 to = from + range_length;
1032 }
1033
1034 from_byte = CHAR_TO_BYTE (from);
1035 to_byte = CHAR_TO_BYTE (to);
1036
1037 del_range_2 (from, to, from_byte, to_byte);
1038 }
1039
1040 /* Like del_range_1 but args are byte positions, not char positions. */
1041
1042 void
1043 del_range_byte (from_byte, to_byte, prepare)
1044 int from_byte, to_byte, prepare;
1045 {
1046 int from, to;
1047
1048 /* Make args be valid */
1049 if (from_byte < BEGV_BYTE)
1050 from_byte = BEGV_BYTE;
1051 if (to_byte > ZV_BYTE)
1052 to_byte = ZV_BYTE;
1053
1054 if (to_byte <= from_byte)
1055 return;
1056
1057 from = BYTE_TO_CHAR (from_byte);
1058 to = BYTE_TO_CHAR (to_byte);
1059
1060 if (prepare)
1061 {
1062 int old_from = from, old_to = Z - to;
1063 int range_length = to - from;
1064 prepare_to_modify_buffer (from, to, &from);
1065 to = from + range_length;
1066
1067 if (old_from != from)
1068 from_byte = CHAR_TO_BYTE (from);
1069 if (old_to == Z - to)
1070 to_byte = CHAR_TO_BYTE (to);
1071 }
1072
1073 del_range_2 (from, to, from_byte, to_byte);
1074 }
1075
1076 /* Like del_range_1, but positions are specified both as charpos
1077 and bytepos. */
1078
1079 void
1080 del_range_both (from, to, from_byte, to_byte, prepare)
1081 int from, to, from_byte, to_byte, prepare;
1082 {
1083 /* Make args be valid */
1084 if (from_byte < BEGV_BYTE)
1085 from_byte = BEGV_BYTE;
1086 if (to_byte > ZV_BYTE)
1087 to_byte = ZV_BYTE;
1088
1089 if (to_byte <= from_byte)
1090 return;
1091
1092 if (from < BEGV)
1093 from = BEGV;
1094 if (to > ZV)
1095 to = ZV;
1096
1097 if (prepare)
1098 {
1099 int old_from = from, old_to = Z - to;
1100 int range_length = to - from;
1101 prepare_to_modify_buffer (from, to, &from);
1102 to = from + range_length;
1103
1104 if (old_from != from)
1105 from_byte = CHAR_TO_BYTE (from);
1106 if (old_to == Z - to)
1107 to_byte = CHAR_TO_BYTE (to);
1108 }
1109
1110 del_range_2 (from, to, from_byte, to_byte);
1111 }
1112
1113 /* Delete a range of text, specified both as character positions
1114 and byte positions. FROM and TO are character positions,
1115 while FROM_BYTE and TO_BYTE are byte positions. */
1116
1117 void
1118 del_range_2 (from, to, from_byte, to_byte)
1119 int from, to, from_byte, to_byte;
1120 {
1121 register int nbytes_del, nchars_del;
1122
1123 nchars_del = to - from;
1124 nbytes_del = to_byte - from_byte;
847 1125
848 /* Make sure the gap is somewhere in or next to what we are deleting. */ 1126 /* Make sure the gap is somewhere in or next to what we are deleting. */
849 if (from > GPT) 1127 if (from > GPT)
850 gap_right (from); 1128 gap_right (from, from_byte);
851 if (to < GPT) 1129 if (to < GPT)
852 gap_left (to, 0); 1130 gap_left (to, to_byte, 0);
853 1131
854 /* Relocate all markers pointing into the new, larger gap 1132 /* Relocate all markers pointing into the new, larger gap
855 to point at the end of the text before the gap. 1133 to point at the end of the text before the gap.
856 This has to be done before recording the deletion, 1134 Do this before recording the deletion,
857 so undo handles this after reinserting the text. */ 1135 so that undo handles this after reinserting the text. */
858 adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE); 1136 adjust_markers_for_delete (from, from_byte, to, to_byte);
859 1137
860 record_delete (from, numdel); 1138 record_delete (from, nchars_del);
861 MODIFF++; 1139 MODIFF++;
862 1140
863 /* Relocate point as if it were a marker. */ 1141 /* Relocate point as if it were a marker. */
864 if (from < PT) 1142 if (from < PT)
865 adjust_point (from - (PT < to ? PT : to)); 1143 adjust_point (from - (PT < to ? PT : to),
1144 from_byte - (PT_BYTE < to_byte ? PT_BYTE : to_byte));
866 1145
867 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */ 1146 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
868 offset_intervals (current_buffer, from, - numdel); 1147 offset_intervals (current_buffer, from, - nchars_del);
869 1148
870 /* Adjust the overlay center as needed. This must be done after 1149 /* Adjust the overlay center as needed. This must be done after
871 adjusting the markers that bound the overlays. */ 1150 adjusting the markers that bound the overlays. */
872 adjust_overlays_for_delete (from, numdel); 1151 adjust_overlays_for_delete (from_byte, nchars_del);
873 1152
874 GAP_SIZE += numdel; 1153 GAP_SIZE += nbytes_del;
875 ZV -= numdel; 1154 ZV_BYTE -= nbytes_del;
876 Z -= numdel; 1155 Z_BYTE -= nbytes_del;
1156 ZV -= nchars_del;
1157 Z -= nchars_del;
877 GPT = from; 1158 GPT = from;
1159 GPT_BYTE = from_byte;
878 *(GPT_ADDR) = 0; /* Put an anchor. */ 1160 *(GPT_ADDR) = 0; /* Put an anchor. */
1161
1162 if (GPT_BYTE < GPT)
1163 abort ();
879 1164
880 if (GPT - BEG < beg_unchanged) 1165 if (GPT - BEG < beg_unchanged)
881 beg_unchanged = GPT - BEG; 1166 beg_unchanged = GPT - BEG;
882 if (Z - GPT < end_unchanged) 1167 if (Z - GPT < end_unchanged)
883 end_unchanged = Z - GPT; 1168 end_unchanged = Z - GPT;
884 1169
885 evaporate_overlays (from); 1170 evaporate_overlays (from);
886 signal_after_change (from, numdel, 0); 1171 signal_after_change (from, nchars_del, 0);
887 } 1172 }
888 1173
889 /* Call this if you're about to change the region of BUFFER from START 1174 /* Call this if you're about to change the region of BUFFER from
890 to END. This checks the read-only properties of the region, calls 1175 character positions START to END. This checks the read-only
891 the necessary modification hooks, and warns the next redisplay that 1176 properties of the region, calls the necessary modification hooks,
892 it should pay attention to that area. */ 1177 and warns the next redisplay that it should pay attention to that
1178 area. */
1179
893 void 1180 void
894 modify_region (buffer, start, end) 1181 modify_region (buffer, start, end)
895 struct buffer *buffer; 1182 struct buffer *buffer;
896 int start, end; 1183 int start, end;
897 { 1184 {
919 1206
920 if (buffer != old_buffer) 1207 if (buffer != old_buffer)
921 set_buffer_internal (old_buffer); 1208 set_buffer_internal (old_buffer);
922 } 1209 }
923 1210
924 /* Check that it is okay to modify the buffer between START and END. 1211 /* Check that it is okay to modify the buffer between START and END,
1212 which are char positions.
1213
925 Run the before-change-function, if any. If intervals are in use, 1214 Run the before-change-function, if any. If intervals are in use,
926 verify that the text to be modified is not read-only, and call 1215 verify that the text to be modified is not read-only, and call
927 any modification properties the text may have. 1216 any modification properties the text may have.
928 1217
929 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR 1218 If PRESERVE_PTR is nonzero, we relocate *PRESERVE_PTR
1101 RESTORE_VALUE; 1390 RESTORE_VALUE;
1102 UNGCPRO; 1391 UNGCPRO;
1103 } 1392 }
1104 1393
1105 /* Signal a change immediately after it happens. 1394 /* Signal a change immediately after it happens.
1106 POS is the address of the start of the changed text. 1395 CHARPOS is the character position of the start of the changed text.
1107 LENDEL is the number of characters of the text before the change. 1396 LENDEL is the number of characters of the text before the change.
1108 (Not the whole buffer; just the part that was changed.) 1397 (Not the whole buffer; just the part that was changed.)
1109 LENINS is the number of characters in that part of the text 1398 LENINS is the number of characters in that part of the text
1110 after the change. */ 1399 after the change. */
1111 1400
1112 void 1401 void
1113 signal_after_change (pos, lendel, lenins) 1402 signal_after_change (charpos, lendel, lenins)
1114 int pos, lendel, lenins; 1403 int charpos, lendel, lenins;
1115 { 1404 {
1116 /* If we are deferring calls to the after-change functions 1405 /* If we are deferring calls to the after-change functions
1117 and there are no before-change functions, 1406 and there are no before-change functions,
1118 just record the args that we were going to use. */ 1407 just record the args that we were going to use. */
1119 if (! NILP (Vcombine_after_change_calls) 1408 if (! NILP (Vcombine_after_change_calls)
1125 1414
1126 if (!NILP (combine_after_change_list) 1415 if (!NILP (combine_after_change_list)
1127 && current_buffer != XBUFFER (combine_after_change_buffer)) 1416 && current_buffer != XBUFFER (combine_after_change_buffer))
1128 Fcombine_after_change_execute (); 1417 Fcombine_after_change_execute ();
1129 1418
1130 elt = Fcons (make_number (pos - BEG), 1419 elt = Fcons (make_number (charpos - BEG),
1131 Fcons (make_number (Z - (pos - lendel + lenins)), 1420 Fcons (make_number (Z - (charpos - lendel + lenins)),
1132 Fcons (make_number (lenins - lendel), Qnil))); 1421 Fcons (make_number (lenins - lendel), Qnil)));
1133 combine_after_change_list 1422 combine_after_change_list
1134 = Fcons (elt, combine_after_change_list); 1423 = Fcons (elt, combine_after_change_list);
1135 combine_after_change_buffer = Fcurrent_buffer (); 1424 combine_after_change_buffer = Fcurrent_buffer ();
1136 1425
1143 /* Run the after-change-function if any. 1432 /* Run the after-change-function if any.
1144 We don't bother "binding" this variable to nil 1433 We don't bother "binding" this variable to nil
1145 because it is obsolete anyway and new code should not use it. */ 1434 because it is obsolete anyway and new code should not use it. */
1146 if (!NILP (Vafter_change_function)) 1435 if (!NILP (Vafter_change_function))
1147 call3 (Vafter_change_function, 1436 call3 (Vafter_change_function,
1148 make_number (pos), make_number (pos + lenins), 1437 make_number (charpos), make_number (charpos + lenins),
1149 make_number (lendel)); 1438 make_number (lendel));
1150 1439
1151 if (!NILP (Vafter_change_functions)) 1440 if (!NILP (Vafter_change_functions))
1152 { 1441 {
1153 Lisp_Object args[4]; 1442 Lisp_Object args[4];
1164 Vafter_change_functions = Qnil; 1453 Vafter_change_functions = Qnil;
1165 GCPRO2 (before_change_functions, after_change_functions); 1454 GCPRO2 (before_change_functions, after_change_functions);
1166 1455
1167 /* Actually run the hook functions. */ 1456 /* Actually run the hook functions. */
1168 args[0] = Qafter_change_functions; 1457 args[0] = Qafter_change_functions;
1169 XSETFASTINT (args[1], pos); 1458 XSETFASTINT (args[1], charpos);
1170 XSETFASTINT (args[2], pos + lenins); 1459 XSETFASTINT (args[2], charpos + lenins);
1171 XSETFASTINT (args[3], lendel); 1460 XSETFASTINT (args[3], lendel);
1172 run_hook_list_with_args (after_change_functions, 1461 run_hook_list_with_args (after_change_functions,
1173 4, args); 1462 4, args);
1174 1463
1175 /* "Unbind" the variables we "bound" to nil. */ 1464 /* "Unbind" the variables we "bound" to nil. */
1178 UNGCPRO; 1467 UNGCPRO;
1179 } 1468 }
1180 1469
1181 if (!NILP (current_buffer->overlays_before) 1470 if (!NILP (current_buffer->overlays_before)
1182 || !NILP (current_buffer->overlays_after)) 1471 || !NILP (current_buffer->overlays_after))
1183 report_overlay_modification (make_number (pos), 1472 report_overlay_modification (make_number (charpos),
1184 make_number (pos + lenins), 1473 make_number (charpos + lenins),
1185 1, 1474 1,
1186 make_number (pos), make_number (pos + lenins), 1475 make_number (charpos),
1476 make_number (charpos + lenins),
1187 make_number (lendel)); 1477 make_number (lendel));
1188 1478
1189 /* After an insertion, call the text properties 1479 /* After an insertion, call the text properties
1190 insert-behind-hooks or insert-in-front-hooks. */ 1480 insert-behind-hooks or insert-in-front-hooks. */
1191 if (lendel == 0) 1481 if (lendel == 0)
1192 report_interval_modification (pos, pos + lenins); 1482 report_interval_modification (charpos, charpos + lenins);
1193 } 1483 }
1194 1484
1195 Lisp_Object 1485 Lisp_Object
1196 Fcombine_after_change_execute_1 (val) 1486 Fcombine_after_change_execute_1 (val)
1197 Lisp_Object val; 1487 Lisp_Object val;