Mercurial > hg > xemacs-beta
annotate src/insdel.c @ 4964:1f509f82c8c9
fix compile error
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-01 Ben Wing <ben@xemacs.org>
* alloc.c (common_init_alloc_early):
Fix compiler breakage.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Mon, 01 Feb 2010 13:35:15 -0600 |
parents | 304aebb79cd3 |
children | 16112448d484 |
rev | line source |
---|---|
428 | 1 /* Buffer insertion/deletion and gap motion for XEmacs. |
2 Copyright (C) 1985, 1986, 1991, 1992, 1993, 1994, 1995 | |
3 Free Software Foundation, Inc. | |
4 Copyright (C) 1995 Sun Microsystems, Inc. | |
2367 | 5 Copyright (C) 2001, 2002, 2003, 2004 Ben Wing. |
428 | 6 |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Mule 2.0, FSF 19.30. Diverges significantly. */ | |
25 | |
26 /* This file has been Mule-ized. */ | |
27 | |
853 | 28 /* Original file from FSF, 1991. |
29 Some changes for extents, c. 1991 by unknown Lucid author. | |
30 Completely rewritten December 1994, for Mule implementation by Ben Wing; | |
31 all buffer modification code ripped out of other files and consolidated | |
32 here. | |
33 Indirect buffers written c. 1997? by Hrvoje Niksic. | |
34 */ | |
428 | 35 |
36 #include <config.h> | |
37 #include "lisp.h" | |
38 | |
39 #include "buffer.h" | |
40 #include "device.h" | |
41 #include "frame.h" | |
42 #include "extents.h" | |
43 #include "insdel.h" | |
44 #include "lstream.h" | |
45 #include "redisplay.h" | |
46 #include "line-number.h" | |
47 | |
48 /* Various macros modelled along the lines of those in buffer.h. | |
49 Purposefully omitted from buffer.h because files other than this | |
50 one should not be using them. */ | |
51 | |
52 /* Address of beginning of buffer. This is an lvalue because | |
53 BUFFER_ALLOC needs it to be. */ | |
54 #define BUF_BEG_ADDR(buf) ((buf)->text->beg) | |
55 | |
56 /* Set the address of beginning of buffer. */ | |
57 #define SET_BUF_BEG_ADDR(buf, addr) do { (buf)->text->beg = (addr); } while (0) | |
58 | |
59 /* Gap size. */ | |
60 #define BUF_GAP_SIZE(buf) ((buf)->text->gap_size + 0) | |
61 #define BUF_END_GAP_SIZE(buf) ((buf)->text->end_gap_size + 0) | |
62 /* Set gap size. */ | |
63 #define SET_BUF_GAP_SIZE(buf, value) \ | |
64 do { (buf)->text->gap_size = (value); } while (0) | |
65 #define SET_BUF_END_GAP_SIZE(buf, value) \ | |
66 do { (buf)->text->end_gap_size = (value); } while (0) | |
67 | |
826 | 68 #define BUF_GPT_ADDR(buf) (BUF_BEG_ADDR (buf) + BYTE_BUF_GPT (buf) - 1) |
428 | 69 |
70 /* Set gap location. */ | |
2367 | 71 #define SET_BOTH_BUF_GPT(buf, cval, bval) \ |
72 do \ | |
73 { \ | |
74 (buf)->text->gpt = (bval); \ | |
75 (buf)->text->bufgpt = (cval); \ | |
76 } while (0) | |
428 | 77 |
78 /* Set end of buffer. */ | |
2367 | 79 #define SET_BOTH_BUF_Z(buf, cval, bval) \ |
428 | 80 do \ |
81 { \ | |
2367 | 82 (buf)->text->z = (bval); \ |
83 (buf)->text->bufz = (cval); \ | |
428 | 84 } while (0) |
85 | |
86 /* Under Mule, we maintain two sentinels in the buffer: one at the | |
87 beginning of the gap, and one at the end of the buffer. This | |
88 allows us to move forward, examining bytes looking for the | |
89 end of a character, and not worry about running off the end. | |
90 We do not need corresponding sentinels when moving backwards | |
91 because we do not have to look past the beginning of a character | |
92 to find the beginning of the character. | |
93 | |
94 Every time we change the beginning of the gap, we have to | |
95 call SET_GAP_SENTINEL(). | |
96 | |
97 Every time we change the total size (characters plus gap) | |
98 of the buffer, we have to call SET_END_SENTINEL(). | |
99 */ | |
100 | |
101 | |
102 #ifdef MULE | |
103 # define GAP_CAN_HOLD_SIZE_P(buf, len) (BUF_GAP_SIZE (buf) >= (len) + 1) | |
104 # define SET_GAP_SENTINEL(buf) (*BUF_GPT_ADDR (buf) = 0) | |
105 # define BUF_END_SENTINEL_SIZE 1 | |
106 # define SET_END_SENTINEL(buf) \ | |
826 | 107 (*(BUF_BEG_ADDR (buf) + BUF_GAP_SIZE (buf) + BYTE_BUF_Z (buf) - 1) = 0) |
428 | 108 #else |
109 # define GAP_CAN_HOLD_SIZE_P(buf, len) (BUF_GAP_SIZE (buf) >= (len)) | |
110 # define SET_GAP_SENTINEL(buf) | |
111 # define BUF_END_SENTINEL_SIZE 0 | |
112 # define SET_END_SENTINEL(buf) | |
113 #endif | |
114 | |
115 | |
116 /************************************************************************/ | |
117 /* point and marker adjustment */ | |
118 /************************************************************************/ | |
119 | |
120 /* just_set_point() is the only place `PT' is an lvalue in all of emacs. | |
121 This function is called from set_buffer_point(), which is the function | |
122 that the SET_PT and BUF_SET_PT macros expand into, and from the | |
123 routines below that insert and delete text. (This is in cases where | |
124 the point marker logically doesn't move but PT (being a byte index) | |
125 needs to get adjusted.) */ | |
126 | |
127 /* Set point to a specified value. This is used only when the value | |
128 of point changes due to an insert or delete; it does not represent | |
129 a conceptual change in point as a marker. In particular, point is | |
130 not crossing any interval boundaries, so there's no need to use the | |
131 usual SET_PT macro. In fact it would be incorrect to do so, because | |
132 either the old or the new value of point is out of synch with the | |
133 current set of intervals. */ | |
134 | |
135 /* This gets called more than enough to make the function call | |
136 overhead a significant factor so we've turned it into a macro. */ | |
665 | 137 #define JUST_SET_POINT(buf, charbpos, ind) \ |
428 | 138 do \ |
139 { \ | |
665 | 140 buf->bufpt = (charbpos); \ |
428 | 141 buf->pt = (ind); \ |
142 } while (0) | |
143 | |
144 /* Set a buffer's point. */ | |
145 | |
146 void | |
665 | 147 set_buffer_point (struct buffer *buf, Charbpos charbpos, Bytebpos bytpos) |
428 | 148 { |
826 | 149 assert (bytpos >= BYTE_BUF_BEGV (buf) && bytpos <= BYTE_BUF_ZV (buf)); |
150 if (bytpos == BYTE_BUF_PT (buf)) | |
428 | 151 return; |
665 | 152 JUST_SET_POINT (buf, charbpos, bytpos); |
428 | 153 MARK_POINT_CHANGED; |
154 assert (MARKERP (buf->point_marker)); | |
665 | 155 XMARKER (buf->point_marker)->membpos = |
156 bytebpos_to_membpos (buf, bytpos); | |
428 | 157 |
158 /* FSF makes sure that PT is not being set within invisible text. | |
159 However, this is the wrong place for that check. The check | |
160 should happen only at the next redisplay. */ | |
161 | |
162 /* Some old coder said: | |
163 | |
164 "If there were to be hooks which were run when point entered/left an | |
165 extent, this would be the place to put them. | |
166 | |
167 However, it's probably the case that such hooks should be implemented | |
168 using a post-command-hook instead, to avoid running the hooks as a | |
169 result of intermediate motion inside of save-excursions, for example." | |
170 | |
171 I definitely agree with this. PT gets moved all over the place | |
172 and it would be a Bad Thing for any hooks to get called, both for | |
173 the reason above and because many callers are not prepared for | |
174 a GC within this function. --ben | |
175 */ | |
176 } | |
177 | |
178 /* Do the correct marker-like adjustment on MPOS (see below). FROM, TO, | |
179 and AMOUNT are as in adjust_markers(). If MPOS doesn't need to be | |
180 adjusted, nothing will happen. */ | |
665 | 181 Membpos |
182 do_marker_adjustment (Membpos mpos, Membpos from, | |
183 Membpos to, Bytecount amount) | |
428 | 184 { |
185 if (amount > 0) | |
186 { | |
187 if (mpos > to && mpos < to + amount) | |
188 mpos = to + amount; | |
189 } | |
190 else | |
191 { | |
192 if (mpos > from + amount && mpos <= from) | |
193 mpos = from + amount; | |
194 } | |
195 if (mpos > from && mpos <= to) | |
196 mpos += amount; | |
197 return mpos; | |
198 } | |
199 | |
200 /* Do the following: | |
201 | |
202 (1) Add `amount' to the position of every marker in the current buffer | |
203 whose current position is between `from' (exclusive) and `to' (inclusive). | |
204 | |
205 (2) Also, any markers past the outside of that interval, in the direction | |
206 of adjustment, are first moved back to the near end of the interval | |
207 and then adjusted by `amount'. | |
208 | |
209 This function is called in two different cases: when a region of | |
210 characters adjacent to the gap is moved, causing the gap to shift | |
211 to the other side of the region (in this case, `from' and `to' | |
212 point to the old position of the region and there should be no | |
213 markers affected by (2) because they would be inside the gap), | |
214 or when a region of characters adjacent to the gap is wiped out, | |
215 causing the gap to increase to include the region (in this case, | |
216 `from' and `to' are the same, both pointing to the boundary | |
217 between the gap and the deleted region, and there are no markers | |
218 affected by (1)). | |
219 | |
220 The reason for the use of exclusive and inclusive is that markers at | |
221 the gap always sit at the beginning, not at the end. | |
222 */ | |
223 | |
224 static void | |
665 | 225 adjust_markers (struct buffer *buf, Membpos from, Membpos to, |
428 | 226 Bytecount amount) |
227 { | |
440 | 228 Lisp_Marker *m; |
428 | 229 |
230 for (m = BUF_MARKERS (buf); m; m = marker_next (m)) | |
665 | 231 m->membpos = do_marker_adjustment (m->membpos, from, to, amount); |
428 | 232 } |
233 | |
234 /* Adjust markers whose insertion-type is t | |
235 for an insertion of AMOUNT characters at POS. */ | |
236 | |
237 static void | |
665 | 238 adjust_markers_for_insert (struct buffer *buf, Membpos ind, Bytecount amount) |
428 | 239 { |
440 | 240 Lisp_Marker *m; |
428 | 241 |
242 for (m = BUF_MARKERS (buf); m; m = marker_next (m)) | |
243 { | |
665 | 244 if (m->insertion_type && m->membpos == ind) |
245 m->membpos += amount; | |
428 | 246 } |
247 } | |
248 | |
249 | |
250 /************************************************************************/ | |
251 /* Routines for dealing with the gap */ | |
252 /************************************************************************/ | |
253 | |
254 /* maximum amount of memory moved in a single chunk. Increasing this | |
255 value improves gap-motion efficiency but decreases QUIT responsiveness | |
256 time. Was 32000 but today's processors are faster and files are | |
257 bigger. --ben */ | |
258 #define GAP_MOVE_CHUNK 300000 | |
259 | |
2367 | 260 /* Move the gap to CPOS/BPOS, which is less than the current GPT. */ |
428 | 261 |
262 static void | |
2367 | 263 gap_left (struct buffer *buf, Charbpos cpos, Bytebpos bpos) |
428 | 264 { |
867 | 265 Ibyte *to, *from; |
428 | 266 Bytecount i; |
665 | 267 Bytebpos new_s1; |
428 | 268 struct buffer *mbuf; |
269 Lisp_Object bufcons; | |
270 | |
271 from = BUF_GPT_ADDR (buf); | |
272 to = from + BUF_GAP_SIZE (buf); | |
826 | 273 new_s1 = BYTE_BUF_GPT (buf); |
428 | 274 |
275 /* Now copy the characters. To move the gap down, | |
276 copy characters up. */ | |
277 | |
278 while (1) | |
279 { | |
280 /* I gets number of characters left to copy. */ | |
2367 | 281 i = new_s1 - bpos; |
428 | 282 if (i == 0) |
283 break; | |
284 /* If a quit is requested, stop copying now. | |
2367 | 285 Change BPOS to be where we have actually moved the gap to. */ |
428 | 286 if (QUITP) |
287 { | |
2367 | 288 bpos = new_s1; |
289 cpos = bytebpos_to_charbpos (buf, bpos); | |
428 | 290 break; |
291 } | |
292 /* Move at most GAP_MOVE_CHUNK chars before checking again for a quit. */ | |
293 if (i > GAP_MOVE_CHUNK) | |
294 i = GAP_MOVE_CHUNK; | |
440 | 295 |
2367 | 296 if (i >= 10) /* was 128 but memmove() should be extremely efficient |
297 nowadays */ | |
428 | 298 { |
299 new_s1 -= i; | |
440 | 300 from -= i; |
301 to -= i; | |
428 | 302 memmove (to, from, i); |
303 } | |
304 else | |
305 { | |
306 new_s1 -= i; | |
307 while (--i >= 0) | |
308 *--to = *--from; | |
309 } | |
310 } | |
311 | |
2367 | 312 /* Adjust markers, and buffer data structure, to put the gap at BPOS. |
313 BPOS is where the loop above stopped, which may be what was specified | |
428 | 314 or may be where a quit was detected. */ |
315 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
316 { | |
2367 | 317 adjust_markers (mbuf, bpos, BYTE_BUF_GPT (mbuf), BUF_GAP_SIZE (mbuf)); |
428 | 318 } |
319 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
320 { | |
2367 | 321 adjust_extents (wrap_buffer (mbuf), bpos, BYTE_BUF_GPT (mbuf), |
428 | 322 BUF_GAP_SIZE (mbuf)); |
323 } | |
2367 | 324 SET_BOTH_BUF_GPT (buf, cpos, bpos); |
428 | 325 SET_GAP_SENTINEL (buf); |
326 #ifdef ERROR_CHECK_EXTENTS | |
327 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
328 { | |
771 | 329 sledgehammer_extent_check (wrap_buffer (mbuf)); |
428 | 330 } |
331 #endif | |
332 QUIT; | |
333 } | |
334 | |
335 static void | |
2367 | 336 gap_right (struct buffer *buf, Charbpos cpos, Bytebpos bpos) |
428 | 337 { |
867 | 338 Ibyte *to, *from; |
428 | 339 Bytecount i; |
665 | 340 Bytebpos new_s1; |
428 | 341 struct buffer *mbuf; |
342 Lisp_Object bufcons; | |
343 | |
344 to = BUF_GPT_ADDR (buf); | |
345 from = to + BUF_GAP_SIZE (buf); | |
826 | 346 new_s1 = BYTE_BUF_GPT (buf); |
428 | 347 |
348 /* Now copy the characters. To move the gap up, | |
349 copy characters down. */ | |
350 | |
351 while (1) | |
352 { | |
353 /* I gets number of characters left to copy. */ | |
2367 | 354 i = bpos - new_s1; |
428 | 355 if (i == 0) |
356 break; | |
357 /* If a quit is requested, stop copying now. | |
2367 | 358 Change BPOS to be where we have actually moved the gap to. */ |
428 | 359 if (QUITP) |
360 { | |
2367 | 361 bpos = new_s1; |
362 cpos = bytebpos_to_charbpos (buf, bpos); | |
428 | 363 break; |
364 } | |
365 /* Move at most GAP_MOVE_CHUNK chars before checking again for a quit. */ | |
366 if (i > GAP_MOVE_CHUNK) | |
367 i = GAP_MOVE_CHUNK; | |
440 | 368 |
2367 | 369 if (i >= 10) /* was 128 but memmove() should be extremely efficient |
370 nowadays */ | |
428 | 371 { |
372 new_s1 += i; | |
373 memmove (to, from, i); | |
440 | 374 from += i; |
375 to += i; | |
428 | 376 } |
377 else | |
378 { | |
379 new_s1 += i; | |
380 while (--i >= 0) | |
381 *to++ = *from++; | |
382 } | |
383 } | |
384 | |
385 { | |
386 int gsize = BUF_GAP_SIZE (buf); | |
387 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
388 { | |
2367 | 389 adjust_markers (mbuf, BYTE_BUF_GPT (mbuf) + gsize, bpos + gsize, - gsize); |
428 | 390 } |
391 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
392 { | |
826 | 393 adjust_extents (wrap_buffer (mbuf), BYTE_BUF_GPT (mbuf) + gsize, |
2367 | 394 bpos + gsize, - gsize); |
428 | 395 } |
2367 | 396 SET_BOTH_BUF_GPT (buf, cpos, bpos); |
428 | 397 SET_GAP_SENTINEL (buf); |
398 #ifdef ERROR_CHECK_EXTENTS | |
399 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
400 { | |
771 | 401 sledgehammer_extent_check (wrap_buffer (mbuf)); |
428 | 402 } |
403 #endif | |
404 } | |
2367 | 405 if (bpos == BYTE_BUF_Z (buf)) |
428 | 406 { |
407 /* merge gap with end gap */ | |
408 | |
409 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + BUF_END_GAP_SIZE (buf)); | |
410 SET_BUF_END_GAP_SIZE (buf, 0); | |
411 SET_END_SENTINEL (buf); | |
412 } | |
413 | |
414 QUIT; | |
415 } | |
416 | |
2367 | 417 /* Move gap to position `bpos'. |
428 | 418 Note that this can quit! */ |
419 | |
420 static void | |
2367 | 421 move_gap (struct buffer *buf, Charbpos cpos, Bytebpos bpos) |
428 | 422 { |
423 if (! BUF_BEG_ADDR (buf)) | |
2500 | 424 ABORT (); |
2367 | 425 if (bpos < BYTE_BUF_GPT (buf)) |
426 gap_left (buf, cpos, bpos); | |
427 else if (bpos > BYTE_BUF_GPT (buf)) | |
428 gap_right (buf, cpos, bpos); | |
428 | 429 } |
430 | |
431 /* Merge the end gap into the gap */ | |
432 | |
433 static void | |
434 merge_gap_with_end_gap (struct buffer *buf) | |
435 { | |
436 Lisp_Object tem; | |
2367 | 437 Charbpos real_gap_loc_char; |
438 Bytebpos real_gap_loc_byte; | |
428 | 439 Bytecount old_gap_size; |
440 Bytecount increment; | |
441 | |
442 increment = BUF_END_GAP_SIZE (buf); | |
443 SET_BUF_END_GAP_SIZE (buf, 0); | |
444 | |
445 if (increment > 0) | |
446 { | |
447 /* Prevent quitting in move_gap. */ | |
448 tem = Vinhibit_quit; | |
449 Vinhibit_quit = Qt; | |
450 | |
2367 | 451 real_gap_loc_char = BUF_GPT (buf); |
452 real_gap_loc_byte = BYTE_BUF_GPT (buf); | |
428 | 453 old_gap_size = BUF_GAP_SIZE (buf); |
454 | |
455 /* Pretend the end gap is the gap */ | |
2367 | 456 SET_BOTH_BUF_GPT (buf, BUF_Z (buf) + BUF_GAP_SIZE (buf), |
457 BYTE_BUF_Z (buf) + BUF_GAP_SIZE (buf)); | |
428 | 458 SET_BUF_GAP_SIZE (buf, increment); |
459 | |
460 /* Move the new gap down to be consecutive with the end of the old one. | |
461 This adjusts the markers properly too. */ | |
2367 | 462 gap_left (buf, real_gap_loc_char + old_gap_size, |
463 real_gap_loc_byte + old_gap_size); | |
428 | 464 |
465 /* Now combine the two into one large gap. */ | |
466 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + old_gap_size); | |
2367 | 467 SET_BOTH_BUF_GPT (buf, real_gap_loc_char, real_gap_loc_byte); |
428 | 468 SET_GAP_SENTINEL (buf); |
469 | |
470 /* We changed the total size of the buffer (including gap), | |
471 so we need to fix up the end sentinel. */ | |
472 SET_END_SENTINEL (buf); | |
473 | |
474 Vinhibit_quit = tem; | |
475 } | |
476 } | |
477 | |
478 /* Make the gap INCREMENT bytes longer. */ | |
479 | |
480 static void | |
481 make_gap (struct buffer *buf, Bytecount increment) | |
482 { | |
867 | 483 Ibyte *result; |
428 | 484 Lisp_Object tem; |
2367 | 485 Charbpos real_gap_loc_char; |
486 Bytebpos real_gap_loc_byte; | |
428 | 487 Bytecount old_gap_size; |
488 | |
489 /* If we have to get more space, get enough to last a while. We use | |
490 a geometric progression that saves on realloc space. */ | |
826 | 491 increment += 2000 + ((BYTE_BUF_Z (buf) - BYTE_BUF_BEG (buf)) / 8); |
492 /* Make sure the gap is always aligned properly in case we're using a | |
493 16-bit or 32-bit fixed-width format. (Other sizes should already be | |
494 aligned in such a case.) */ | |
495 increment = MAX_ALIGN_SIZE (increment); | |
428 | 496 |
497 if (increment > BUF_END_GAP_SIZE (buf)) | |
498 { | |
499 /* Don't allow a buffer size that won't fit in an int | |
500 even if it will fit in a Lisp integer. | |
501 That won't work because so many places use `int'. */ | |
502 | |
503 if (BUF_Z (buf) - BUF_BEG (buf) + BUF_GAP_SIZE (buf) + increment | |
504 > EMACS_INT_MAX) | |
563 | 505 out_of_memory ("Maximum buffer size exceeded", Qunbound); |
428 | 506 |
507 result = BUFFER_REALLOC (buf->text->beg, | |
826 | 508 BYTE_BUF_Z (buf) - BYTE_BUF_BEG (buf) + |
428 | 509 BUF_GAP_SIZE (buf) + increment + |
510 BUF_END_SENTINEL_SIZE); | |
511 if (result == 0) | |
512 memory_full (); | |
513 | |
514 SET_BUF_BEG_ADDR (buf, result); | |
515 } | |
516 else | |
517 increment = BUF_END_GAP_SIZE (buf); | |
518 | |
519 /* Prevent quitting in move_gap. */ | |
520 tem = Vinhibit_quit; | |
521 Vinhibit_quit = Qt; | |
522 | |
2367 | 523 real_gap_loc_char = BUF_GPT (buf); |
524 real_gap_loc_byte = BYTE_BUF_GPT (buf); | |
428 | 525 old_gap_size = BUF_GAP_SIZE (buf); |
526 | |
527 /* Call the newly allocated space a gap at the end of the whole space. */ | |
2367 | 528 SET_BOTH_BUF_GPT (buf, BUF_Z (buf) + BUF_GAP_SIZE (buf), |
529 BYTE_BUF_Z (buf) + BUF_GAP_SIZE (buf)); | |
428 | 530 SET_BUF_GAP_SIZE (buf, increment); |
531 | |
532 SET_BUF_END_GAP_SIZE (buf, 0); | |
533 | |
534 /* Move the new gap down to be consecutive with the end of the old one. | |
535 This adjusts the markers properly too. */ | |
2367 | 536 gap_left (buf, real_gap_loc_char + old_gap_size, |
537 real_gap_loc_byte + old_gap_size); | |
428 | 538 |
539 /* Now combine the two into one large gap. */ | |
540 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + old_gap_size); | |
2367 | 541 SET_BOTH_BUF_GPT (buf, real_gap_loc_char, real_gap_loc_byte); |
428 | 542 SET_GAP_SENTINEL (buf); |
543 | |
544 /* We changed the total size of the buffer (including gap), | |
545 so we need to fix up the end sentinel. */ | |
546 SET_END_SENTINEL (buf); | |
547 | |
548 Vinhibit_quit = tem; | |
549 } | |
550 | |
551 | |
552 /************************************************************************/ | |
553 /* Before/after-change processing */ | |
554 /************************************************************************/ | |
555 | |
556 /* Those magic changes ... */ | |
557 | |
558 static void | |
665 | 559 buffer_signal_changed_region (struct buffer *buf, Charbpos start, |
560 Charbpos end) | |
428 | 561 { |
562 /* The changed region is recorded as the number of unchanged | |
563 characters from the beginning and from the end of the | |
564 buffer. This obviates much of the need of shifting the | |
565 region around to compensate for insertions and deletions. | |
566 */ | |
567 if (buf->changes->begin_unchanged < 0 || | |
568 buf->changes->begin_unchanged > start - BUF_BEG (buf)) | |
569 buf->changes->begin_unchanged = start - BUF_BEG (buf); | |
570 if (buf->changes->end_unchanged < 0 || | |
571 buf->changes->end_unchanged > BUF_Z (buf) - end) | |
572 buf->changes->end_unchanged = BUF_Z (buf) - end; | |
573 } | |
574 | |
575 void | |
665 | 576 buffer_extent_signal_changed_region (struct buffer *buf, Charbpos start, |
577 Charbpos end) | |
428 | 578 { |
579 if (buf->changes->begin_extent_unchanged < 0 || | |
580 buf->changes->begin_extent_unchanged > start - BUF_BEG (buf)) | |
581 buf->changes->begin_extent_unchanged = start - BUF_BEG (buf); | |
582 if (buf->changes->end_extent_unchanged < 0 || | |
583 buf->changes->end_extent_unchanged > BUF_Z (buf) - end) | |
584 buf->changes->end_extent_unchanged = BUF_Z (buf) - end; | |
585 } | |
586 | |
587 void | |
588 buffer_reset_changes (struct buffer *buf) | |
589 { | |
590 buf->changes->begin_unchanged = -1; | |
591 buf->changes->end_unchanged = -1; | |
592 buf->changes->begin_extent_unchanged = -1; | |
593 buf->changes->end_extent_unchanged = -1; | |
594 buf->changes->newline_was_deleted = 0; | |
595 } | |
596 | |
597 static void | |
665 | 598 signal_after_change (struct buffer *buf, Charbpos start, Charbpos orig_end, |
599 Charbpos new_end); | |
428 | 600 |
601 | |
602 /* Call the after-change-functions according to the changes made so far | |
603 and treat all further changes as single until the outermost | |
604 multiple change exits. This is called when the outermost multiple | |
605 change exits and when someone is trying to make a change that violates | |
606 the constraints specified in begin_multiple_change(), typically | |
607 when nested multiple-change sessions occur. (There are smarter ways of | |
608 dealing with nested multiple changes, but these rarely occur so there's | |
609 probably no point in it.) */ | |
610 | |
611 /* #### This needs to keep track of what actually changed and only | |
612 call the after-change functions on that region. */ | |
613 | |
614 static void | |
615 cancel_multiple_change (struct buffer *buf) | |
616 { | |
617 /* This function can GC */ | |
618 /* Call the after-change-functions except when they've already been | |
619 called or when there were no changes made to the buffer at all. */ | |
620 if (buf->text->changes->mc_begin != 0 && | |
621 buf->text->changes->mc_begin_signaled) | |
622 { | |
665 | 623 Charbpos real_mc_begin = buf->text->changes->mc_begin; |
428 | 624 buf->text->changes->mc_begin = 0; |
625 | |
626 signal_after_change (buf, real_mc_begin, buf->text->changes->mc_orig_end, | |
627 buf->text->changes->mc_new_end); | |
628 } | |
629 else | |
630 { | |
631 buf->text->changes->mc_begin = 0; | |
632 } | |
633 } | |
634 | |
635 /* this is an unwind_protect, to ensure that the after-change-functions | |
636 get called even in a non-local exit. */ | |
637 | |
638 static Lisp_Object | |
639 multiple_change_finish_up (Lisp_Object buffer) | |
640 { | |
641 struct buffer *buf = XBUFFER (buffer); | |
642 | |
643 /* #### I don't know whether or not it should even be possible to | |
644 get here with a dead buffer (though given how it is called I can | |
645 see how it might be). In any case, there isn't time before 19.14 | |
646 to find out. */ | |
647 if (!BUFFER_LIVE_P (buf)) | |
648 return Qnil; | |
649 | |
650 /* This function can GC */ | |
651 buf->text->changes->in_multiple_change = 0; /* do this first so that | |
652 errors in the after-change | |
653 functions don't mess things | |
654 up. */ | |
655 cancel_multiple_change (buf); | |
656 return Qnil; | |
657 } | |
658 | |
659 /* Call this function when you're about to make a number of buffer changes | |
660 that should be considered a single change. (e.g. `replace-match' calls | |
661 this.) You need to specify the START and END of the region that is | |
662 going to be changed so that the before-change-functions are called | |
663 with the correct arguments. The after-change region is calculated | |
664 automatically, however, and if changes somehow or other happen outside | |
665 of the specified region, that will also be handled correctly. | |
666 | |
667 begin_multiple_change() returns a number (actually a specpdl depth) | |
438 | 668 that you must pass to end_multiple_change() when you are done. |
669 | |
670 FSF Emacs 20 implements a similar feature, accessible from Lisp | |
671 through a `combine-after-change-calls' special form, which is | |
672 essentially equivalent to this function. We should consider | |
673 whether we want to introduce a similar Lisp form. */ | |
428 | 674 |
675 int | |
665 | 676 begin_multiple_change (struct buffer *buf, Charbpos start, Charbpos end) |
428 | 677 { |
678 /* This function can GC */ | |
679 int count = -1; | |
680 if (buf->text->changes->in_multiple_change) | |
681 { | |
682 if (buf->text->changes->mc_begin != 0 && | |
683 (start < buf->text->changes->mc_begin || | |
684 end > buf->text->changes->mc_new_end)) | |
685 cancel_multiple_change (buf); | |
686 } | |
687 else | |
688 { | |
689 Lisp_Object buffer; | |
690 | |
691 buf->text->changes->mc_begin = start; | |
692 buf->text->changes->mc_orig_end = buf->text->changes->mc_new_end = end; | |
693 buf->text->changes->mc_begin_signaled = 0; | |
694 count = specpdl_depth (); | |
793 | 695 buffer = wrap_buffer (buf); |
428 | 696 record_unwind_protect (multiple_change_finish_up, buffer); |
697 } | |
698 buf->text->changes->in_multiple_change++; | |
699 /* We don't call before-change-functions until signal_before_change() | |
700 is called, in case there is a read-only or other error. */ | |
701 return count; | |
702 } | |
703 | |
704 void | |
705 end_multiple_change (struct buffer *buf, int count) | |
706 { | |
707 assert (buf->text->changes->in_multiple_change > 0); | |
708 buf->text->changes->in_multiple_change--; | |
709 if (!buf->text->changes->in_multiple_change) | |
771 | 710 unbind_to (count); |
428 | 711 } |
712 | |
713 static int inside_change_hook; | |
714 | |
715 static Lisp_Object | |
716 change_function_restore (Lisp_Object buffer) | |
717 { | |
718 /* We should first reset the variable and then change the buffer, | |
719 because Fset_buffer() can throw. */ | |
720 inside_change_hook = 0; | |
438 | 721 if (XBUFFER (buffer) != current_buffer) |
722 Fset_buffer (buffer); | |
428 | 723 return Qnil; |
724 } | |
725 | |
726 static int in_first_change; | |
727 | |
728 static Lisp_Object | |
729 first_change_hook_restore (Lisp_Object buffer) | |
730 { | |
731 in_first_change = 0; | |
732 Fset_buffer (buffer); | |
733 return Qnil; | |
734 } | |
735 | |
736 /* Signal an initial modification to the buffer. */ | |
737 | |
738 static void | |
739 signal_first_change (struct buffer *buf) | |
740 { | |
741 /* This function can GC */ | |
793 | 742 Lisp_Object buffer = wrap_buffer (current_buffer); |
743 | |
428 | 744 |
745 if (!in_first_change) | |
746 { | |
747 if (!NILP (symbol_value_in_buffer (Qfirst_change_hook, buffer))) | |
748 { | |
749 int speccount = specpdl_depth (); | |
750 record_unwind_protect (first_change_hook_restore, buffer); | |
751 set_buffer_internal (buf); | |
752 in_first_change = 1; | |
853 | 753 run_hook_trapping_problems |
1333 | 754 (Qchange, Qfirst_change_hook, |
853 | 755 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); |
771 | 756 unbind_to (speccount); |
428 | 757 } |
758 } | |
759 } | |
760 | |
761 /* Signal a change to the buffer immediately before it happens. | |
762 START and END are the bounds of the text to be changed. */ | |
763 | |
764 static void | |
665 | 765 signal_before_change (struct buffer *buf, Charbpos start, Charbpos end) |
428 | 766 { |
767 /* This function can GC */ | |
768 struct buffer *mbuf; | |
769 Lisp_Object bufcons; | |
770 | |
771 if (!inside_change_hook) | |
772 { | |
773 Lisp_Object buffer; | |
438 | 774 int speccount; |
428 | 775 |
776 /* Are we in a multiple-change session? */ | |
777 if (buf->text->changes->in_multiple_change && | |
778 buf->text->changes->mc_begin != 0) | |
779 { | |
780 /* If we're violating the constraints of the session, | |
781 call the after-change-functions as necessary for the | |
782 changes already made and treat further changes as | |
783 single. */ | |
784 if (start < buf->text->changes->mc_begin || | |
785 end > buf->text->changes->mc_new_end) | |
786 cancel_multiple_change (buf); | |
787 /* Do nothing if this is not the first change in the session. */ | |
788 else if (buf->text->changes->mc_begin_signaled) | |
789 return; | |
790 else | |
791 { | |
792 /* First time through; call the before-change-functions | |
793 specifying the entire region to be changed. (Note that | |
794 we didn't call before-change-functions in | |
795 begin_multiple_change() because the buffer might be | |
796 read-only, etc.) */ | |
797 start = buf->text->changes->mc_begin; | |
798 end = buf->text->changes->mc_new_end; | |
799 } | |
800 } | |
801 | |
802 /* If buffer is unmodified, run a special hook for that case. */ | |
803 if (BUF_SAVE_MODIFF (buf) >= BUF_MODIFF (buf)) | |
804 { | |
805 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
806 { | |
807 signal_first_change (mbuf); | |
808 } | |
809 } | |
810 | |
811 /* Now in any case run the before-change-functions if any. */ | |
438 | 812 speccount = specpdl_depth (); |
813 record_unwind_protect (change_function_restore, Fcurrent_buffer ()); | |
814 inside_change_hook = 1; | |
428 | 815 |
816 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
817 { | |
793 | 818 buffer = wrap_buffer (mbuf); |
428 | 819 if (!NILP (symbol_value_in_buffer (Qbefore_change_functions, buffer)) |
820 /* Obsolete, for compatibility */ | |
821 || !NILP (symbol_value_in_buffer (Qbefore_change_function, buffer))) | |
822 { | |
823 set_buffer_internal (buf); | |
853 | 824 va_run_hook_with_args_trapping_problems |
1333 | 825 (Qchange, Qbefore_change_functions, 2, |
853 | 826 make_int (start), make_int (end), |
827 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 828 /* Obsolete, for compatibility */ |
853 | 829 va_run_hook_with_args_trapping_problems |
1333 | 830 (Qchange, Qbefore_change_function, 2, |
853 | 831 make_int (start), make_int (end), |
832 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 833 } |
834 } | |
835 | |
438 | 836 /* Make sure endpoints remain valid. before-change-functions |
837 might have modified the buffer. */ | |
838 if (start < BUF_BEGV (buf)) start = BUF_BEGV (buf); | |
839 if (start > BUF_ZV (buf)) start = BUF_ZV (buf); | |
840 if (end < BUF_BEGV (buf)) end = BUF_BEGV (buf); | |
841 if (end > BUF_ZV (buf)) end = BUF_ZV (buf); | |
842 | |
428 | 843 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
844 { | |
826 | 845 report_extent_modification (wrap_buffer (mbuf), start, end, 0); |
428 | 846 } |
771 | 847 unbind_to (speccount); |
428 | 848 |
849 /* Only now do we indicate that the before-change-functions have | |
850 been called, in case some function throws out. */ | |
851 buf->text->changes->mc_begin_signaled = 1; | |
852 } | |
853 } | |
854 | |
855 /* Signal a change immediately after it happens. | |
665 | 856 START is the charbpos of the start of the changed text. |
857 ORIG_END is the charbpos of the end of the before-changed text. | |
858 NEW_END is the charbpos of the end of the after-changed text. | |
428 | 859 */ |
860 | |
861 static void | |
665 | 862 signal_after_change (struct buffer *buf, Charbpos start, Charbpos orig_end, |
863 Charbpos new_end) | |
428 | 864 { |
865 /* This function can GC */ | |
866 struct buffer *mbuf; | |
867 Lisp_Object bufcons; | |
868 | |
869 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
870 { | |
871 /* always do this. */ | |
872 buffer_signal_changed_region (mbuf, start, new_end); | |
873 } | |
826 | 874 #ifdef USE_C_FONT_LOCK |
428 | 875 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
876 { | |
877 /* #### This seems inefficient. Wouldn't it be better to just | |
878 keep one cache per base buffer? */ | |
879 font_lock_maybe_update_syntactic_caches (mbuf, start, orig_end, new_end); | |
880 } | |
826 | 881 #endif /* USE_C_FONT_LOCK */ |
428 | 882 |
883 if (!inside_change_hook) | |
884 { | |
885 Lisp_Object buffer; | |
438 | 886 int speccount; |
428 | 887 |
888 if (buf->text->changes->in_multiple_change && | |
889 buf->text->changes->mc_begin != 0) | |
890 { | |
891 assert (start >= buf->text->changes->mc_begin && | |
892 start <= buf->text->changes->mc_new_end); | |
893 assert (orig_end >= buf->text->changes->mc_begin && | |
894 orig_end <= buf->text->changes->mc_new_end); | |
895 buf->text->changes->mc_new_end += new_end - orig_end; | |
896 return; /* after-change-functions signalled when all changes done */ | |
897 } | |
898 | |
438 | 899 speccount = specpdl_depth (); |
900 record_unwind_protect (change_function_restore, Fcurrent_buffer ()); | |
901 inside_change_hook = 1; | |
428 | 902 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
903 { | |
793 | 904 buffer = wrap_buffer (mbuf); |
428 | 905 |
906 if (!NILP (symbol_value_in_buffer (Qafter_change_functions, buffer)) | |
907 /* Obsolete, for compatibility */ | |
908 || !NILP (symbol_value_in_buffer (Qafter_change_function, buffer))) | |
909 { | |
910 set_buffer_internal (buf); | |
911 /* The actual after-change functions take slightly | |
912 different arguments than what we were passed. */ | |
853 | 913 va_run_hook_with_args_trapping_problems |
1333 | 914 (Qchange, Qafter_change_functions, 3, |
853 | 915 make_int (start), make_int (new_end), |
916 make_int (orig_end - start), | |
917 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 918 /* Obsolete, for compatibility */ |
853 | 919 va_run_hook_with_args_trapping_problems |
1333 | 920 (Qchange, Qafter_change_function, 3, |
853 | 921 make_int (start), make_int (new_end), |
922 make_int (orig_end - start), | |
923 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 924 } |
925 } | |
926 | |
438 | 927 /* Make sure endpoints remain valid. after-change-functions |
928 might have modified the buffer. */ | |
929 if (start < BUF_BEGV (buf)) start = BUF_BEGV (buf); | |
930 if (start > BUF_ZV (buf)) start = BUF_ZV (buf); | |
931 if (new_end < BUF_BEGV (buf)) new_end = BUF_BEGV (buf); | |
932 if (new_end > BUF_ZV (buf)) new_end = BUF_ZV (buf); | |
933 if (orig_end < BUF_BEGV (buf)) orig_end = BUF_BEGV (buf); | |
934 if (orig_end > BUF_ZV (buf)) orig_end = BUF_ZV (buf); | |
935 | |
428 | 936 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
937 { | |
793 | 938 buffer = wrap_buffer (mbuf); |
438 | 939 report_extent_modification (buffer, start, new_end, 1); |
428 | 940 } |
771 | 941 unbind_to (speccount); /* sets inside_change_hook back to 0 */ |
428 | 942 } |
943 } | |
944 | |
945 /* Call this if you're about to change the region of BUFFER from START | |
946 to END. This checks the read-only properties of the region, calls | |
947 the necessary modification hooks, and warns the next redisplay that | |
948 it should pay attention to that area. */ | |
949 | |
950 static void | |
665 | 951 prepare_to_modify_buffer (struct buffer *buf, Charbpos start, Charbpos end, |
428 | 952 int lockit) |
953 { | |
954 /* This function can GC */ | |
955 /* dmoore - This function can also kill the buffer buf, the current | |
956 buffer, and do anything it pleases. So if you call it, be | |
957 careful. */ | |
958 struct buffer *mbuf; | |
959 Lisp_Object buffer, bufcons; | |
960 struct gcpro gcpro1; | |
961 | |
962 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
963 { | |
853 | 964 check_allowed_operation (OPERATION_MODIFY_BUFFER_TEXT, |
965 wrap_buffer (mbuf), Qnil); | |
428 | 966 barf_if_buffer_read_only (mbuf, start, end); |
967 } | |
968 | |
969 /* if this is the first modification, see about locking the buffer's | |
970 file */ | |
793 | 971 buffer = wrap_buffer (buf); |
428 | 972 GCPRO1 (buffer); |
973 if (!NILP (buf->filename) && lockit && | |
974 BUF_SAVE_MODIFF (buf) >= BUF_MODIFF (buf)) | |
975 { | |
758 | 976 #ifdef CLASH_DETECTION |
977 if (!NILP (buf->file_truename)) | |
978 /* Make binding buffer-file-name to nil effective. */ | |
979 lock_file (buf->file_truename); | |
980 #else | |
428 | 981 /* At least warn if this file has changed on disk since it was visited.*/ |
982 if (NILP (Fverify_visited_file_modtime (buffer)) | |
983 && !NILP (Ffile_exists_p (buf->filename))) | |
984 call1_in_buffer (buf, intern ("ask-user-about-supersession-threat"), | |
985 buf->filename); | |
986 #endif /* not CLASH_DETECTION */ | |
987 } | |
988 UNGCPRO; | |
989 | |
990 /* #### dmoore - is this reasonable in case of buf being killed above? */ | |
991 if (!BUFFER_LIVE_P (buf)) | |
992 return; | |
993 | |
994 signal_before_change (buf, start, end); | |
995 | |
996 #ifdef REGION_CACHE_NEEDS_WORK | |
997 if (buf->newline_cache) | |
998 invalidate_region_cache (buf, | |
999 buf->newline_cache, | |
1000 start - BUF_BEG (buf), BUF_Z (buf) - end); | |
1001 if (buf->width_run_cache) | |
1002 invalidate_region_cache (buf, | |
1003 buf->width_run_cache, | |
1004 start - BUF_BEG (buf), BUF_Z (buf) - end); | |
1005 #endif | |
1006 | |
1007 #if 0 /* FSFmacs */ | |
1008 Vdeactivate_mark = Qt; | |
1009 #endif | |
1010 | |
1011 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1012 { | |
1013 mbuf->point_before_scroll = Qnil; | |
1014 } | |
1015 } | |
1016 | |
1017 | |
1018 /************************************************************************/ | |
1019 /* Insertion of strings */ | |
1020 /************************************************************************/ | |
1021 | |
1022 void | |
867 | 1023 fixup_internal_substring (const Ibyte *nonreloc, Lisp_Object reloc, |
428 | 1024 Bytecount offset, Bytecount *len) |
1025 { | |
1026 assert ((nonreloc && NILP (reloc)) || (!nonreloc && STRINGP (reloc))); | |
1027 | |
1028 if (*len < 0) | |
1029 { | |
1030 if (nonreloc) | |
442 | 1031 *len = strlen ((const char *) nonreloc) - offset; |
428 | 1032 else |
1033 *len = XSTRING_LENGTH (reloc) - offset; | |
1034 } | |
800 | 1035 #ifdef ERROR_CHECK_TEXT |
428 | 1036 assert (*len >= 0); |
1037 if (STRINGP (reloc)) | |
1038 { | |
1039 assert (offset >= 0 && offset <= XSTRING_LENGTH (reloc)); | |
1040 assert (offset + *len <= XSTRING_LENGTH (reloc)); | |
1041 } | |
1042 #endif | |
1043 } | |
1044 | |
665 | 1045 /* Insert a string into BUF at Charbpos POS. The string data comes |
428 | 1046 from one of two sources: constant, non-relocatable data (specified |
1047 in NONRELOC), or a Lisp string object (specified in RELOC), which | |
1048 is relocatable and may have extent data that needs to be copied | |
1049 into the buffer. OFFSET and LENGTH specify the substring of the | |
1050 data that is actually to be inserted. As a special case, if POS | |
1051 is -1, insert the string at point and move point to the end of the | |
1052 string. | |
1053 | |
1054 Normally, markers at the insertion point end up before the | |
1055 inserted string. If INSDEL_BEFORE_MARKERS is set in flags, however, | |
1056 they end up after the string. | |
1057 | |
1058 INSDEL_NO_LOCKING is kludgy and is used when insert-file-contents is | |
1059 visiting a new file; it inhibits the locking checks normally done | |
1060 before modifying a buffer. Similar checks were already done | |
1061 in the higher-level Lisp functions calling insert-file-contents. */ | |
1062 | |
1063 Charcount | |
665 | 1064 buffer_insert_string_1 (struct buffer *buf, Charbpos pos, |
867 | 1065 const Ibyte *nonreloc, Lisp_Object reloc, |
428 | 1066 Bytecount offset, Bytecount length, |
1067 int flags) | |
1068 { | |
1069 /* This function can GC */ | |
1070 struct gcpro gcpro1; | |
826 | 1071 Bytebpos bytepos; |
1072 Bytecount length_in_buffer; | |
428 | 1073 Charcount cclen; |
1074 int move_point = 0; | |
1075 struct buffer *mbuf; | |
1076 Lisp_Object bufcons; | |
1077 | |
1078 /* Defensive steps just in case a buffer gets deleted and a calling | |
1079 function doesn't notice it. */ | |
1080 if (!BUFFER_LIVE_P (buf)) | |
1081 return 0; | |
1082 | |
1083 fixup_internal_substring (nonreloc, reloc, offset, &length); | |
1084 | |
1085 if (pos == -1) | |
1086 { | |
1087 pos = BUF_PT (buf); | |
1088 move_point = 1; | |
1089 } | |
1090 | |
1091 #ifdef I18N3 | |
1092 /* #### See the comment in print_internal(). If this buffer is marked | |
1093 as translatable, then Fgettext() should be called on obj if it | |
1094 is a string. */ | |
1095 #endif | |
1096 | |
1097 /* Make sure that point-max won't exceed the size of an emacs int. */ | |
1098 if ((length + BUF_Z (buf)) > EMACS_INT_MAX) | |
563 | 1099 out_of_memory ("Maximum buffer size exceeded", Qunbound); |
428 | 1100 |
1101 /* theoretically not necessary -- caller should GCPRO. | |
1102 #### buffer_insert_from_buffer_1() doesn't! */ | |
1103 GCPRO1 (reloc); | |
1104 | |
1105 prepare_to_modify_buffer (buf, pos, pos, !(flags & INSDEL_NO_LOCKING)); | |
1106 | |
1107 /* Defensive steps in case the before-change-functions fuck around */ | |
1108 if (!BUFFER_LIVE_P (buf)) | |
1109 { | |
1110 UNGCPRO; | |
1111 /* Bad bad pre-change function. */ | |
1112 return 0; | |
1113 } | |
1114 | |
1115 /* Make args be valid again. prepare_to_modify_buffer() might have | |
1116 modified the buffer. */ | |
1117 if (pos < BUF_BEGV (buf)) | |
1118 pos = BUF_BEGV (buf); | |
1119 if (pos > BUF_ZV (buf)) | |
1120 pos = BUF_ZV (buf); | |
1121 | |
826 | 1122 bytepos = charbpos_to_bytebpos (buf, pos); |
771 | 1123 |
428 | 1124 /* string may have been relocated up to this point */ |
1125 if (STRINGP (reloc)) | |
771 | 1126 { |
793 | 1127 cclen = string_offset_byte_to_char_len (reloc, offset, length); |
771 | 1128 nonreloc = XSTRING_DATA (reloc); |
1129 } | |
1130 else | |
1131 cclen = bytecount_to_charcount (nonreloc + offset, length); | |
826 | 1132 /* &&#### Here we check if the text can't fit into the format of the buffer, |
1133 and if so convert it to another format (either default or 32-bit-fixed, | |
1134 according to some flag; if no flag, use default). */ | |
1135 | |
1136 length_in_buffer = copy_text_between_formats (nonreloc + offset, length, | |
1137 FORMAT_DEFAULT, | |
1138 STRINGP (reloc) ? reloc : Qnil, | |
1139 NULL, 0, | |
1140 BUF_FORMAT (buf), | |
1141 wrap_buffer (buf), | |
1142 NULL); | |
428 | 1143 |
826 | 1144 if (bytepos != BYTE_BUF_GPT (buf)) |
428 | 1145 /* #### if debug-on-quit is invoked and the user changes the |
1146 buffer, bad things can happen. This is a rampant problem | |
1147 in Emacs. */ | |
2367 | 1148 move_gap (buf, pos, bytepos); /* may QUIT */ |
826 | 1149 if (! GAP_CAN_HOLD_SIZE_P (buf, length_in_buffer)) |
428 | 1150 { |
826 | 1151 if (BUF_END_GAP_SIZE (buf) >= length_in_buffer) |
428 | 1152 merge_gap_with_end_gap (buf); |
1153 else | |
826 | 1154 make_gap (buf, length_in_buffer - BUF_GAP_SIZE (buf)); |
428 | 1155 } |
1156 | |
826 | 1157 /* At this point, no more QUITting or processing of Lisp code. Buffer is |
1158 in a consistent state. Following code puts buffer in an inconsistent | |
1159 state and can be considered a "critical section". */ | |
1160 | |
428 | 1161 insert_invalidate_line_number_cache (buf, pos, nonreloc + offset, length); |
1162 | |
1163 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1164 { | |
1165 record_insert (mbuf, pos, cclen); | |
1166 } | |
1167 | |
1168 BUF_MODIFF (buf)++; | |
1169 MARK_BUFFERS_CHANGED; | |
1170 | |
826 | 1171 /* string may have been relocated up to this point #### if string is |
1172 modified during quit processing, bad things can happen. */ | |
428 | 1173 if (STRINGP (reloc)) |
1174 nonreloc = XSTRING_DATA (reloc); | |
1175 | |
853 | 1176 memcpy (BUF_GPT_ADDR (buf), nonreloc + offset, length); |
1177 | |
826 | 1178 copy_text_between_formats (nonreloc + offset, length, FORMAT_DEFAULT, |
1179 STRINGP (reloc) ? reloc : Qnil, | |
1180 BUF_GPT_ADDR (buf), length_in_buffer, | |
1181 BUF_FORMAT (buf), wrap_buffer (buf), NULL); | |
1182 | |
1183 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) - length_in_buffer); | |
2367 | 1184 SET_BOTH_BUF_GPT (buf, BUF_GPT (buf) + cclen, |
1185 BYTE_BUF_GPT (buf) + length_in_buffer); | |
428 | 1186 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
1187 { | |
826 | 1188 SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) + cclen, |
1189 BYTE_BUF_ZV (mbuf) + length_in_buffer); | |
428 | 1190 } |
826 | 1191 SET_BOTH_BUF_Z (buf, BUF_Z (buf) + cclen, BYTE_BUF_Z (buf) + length_in_buffer); |
428 | 1192 SET_GAP_SENTINEL (buf); |
771 | 1193 |
1194 | |
428 | 1195 #ifdef MULE |
826 | 1196 buffer_mule_signal_inserted_region (buf, pos, length_in_buffer, cclen); |
1197 /* Update our count of ASCII, 8-bit and 16-bit chars and the | |
1198 entirely-one-byte flag */ | |
1199 { | |
867 | 1200 const Ibyte *ptr = nonreloc + offset; |
1201 const Ibyte *ptrend = ptr + length; | |
826 | 1202 |
1203 while (ptr < ptrend) | |
1204 { | |
867 | 1205 Ichar ch = itext_ichar (ptr); |
1206 if (ichar_ascii_p (ch)) | |
826 | 1207 buf->text->num_ascii_chars++; |
867 | 1208 if (ichar_8_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1209 buf->text->num_8_bit_fixed_chars++; |
867 | 1210 if (ichar_16_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1211 buf->text->num_16_bit_fixed_chars++; |
867 | 1212 INC_IBYTEPTR (ptr); |
826 | 1213 } |
1214 | |
1215 buf->text->entirely_one_byte_p = | |
1216 (BUF_FORMAT (buf) == FORMAT_8_BIT_FIXED || | |
1217 (BUF_FORMAT (buf) == FORMAT_DEFAULT && BUF_Z (buf) == BYTE_BUF_Z (buf))); | |
1218 } | |
428 | 1219 #endif |
1220 | |
1221 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1222 { | |
826 | 1223 process_extents_for_insertion (wrap_buffer (mbuf), bytepos, |
1224 length_in_buffer); | |
428 | 1225 } |
1226 | |
1227 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1228 { | |
826 | 1229 /* We know the gap is at BYTEPOS so the cast is OK. */ |
1230 adjust_markers_for_insert (mbuf, (Membpos) bytepos, length_in_buffer); | |
428 | 1231 } |
1232 | |
1233 /* Point logically doesn't move, but may need to be adjusted because | |
1234 it's a byte index. point-marker doesn't change because it's a | |
1235 memory index. */ | |
1236 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1237 { | |
826 | 1238 if (BYTE_BUF_PT (mbuf) > bytepos) |
428 | 1239 JUST_SET_POINT (mbuf, BUF_PT (mbuf) + cclen, |
826 | 1240 BYTE_BUF_PT (mbuf) + length_in_buffer); |
428 | 1241 } |
1242 | |
1243 /* Well, point might move. */ | |
1244 if (move_point) | |
826 | 1245 BYTE_BUF_SET_PT (buf, bytepos + length_in_buffer); |
428 | 1246 |
1247 if (STRINGP (reloc)) | |
1248 { | |
1249 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1250 { | |
826 | 1251 splice_in_string_extents (reloc, mbuf, bytepos, length, offset); |
428 | 1252 } |
1253 } | |
1254 | |
1255 if (flags & INSDEL_BEFORE_MARKERS) | |
1256 { | |
1257 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1258 { | |
826 | 1259 /* bytepos - 1 is correct because the FROM argument is exclusive. |
665 | 1260 I formerly used DEC_BYTEBPOS() but that caused problems at the |
428 | 1261 beginning of the buffer. */ |
826 | 1262 adjust_markers (mbuf, bytepos - 1, bytepos, length_in_buffer); |
428 | 1263 } |
1264 } | |
1265 | |
826 | 1266 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
1267 { | |
3250 | 1268 signal_syntax_cache_extent_adjust (mbuf); |
826 | 1269 } |
1270 | |
428 | 1271 signal_after_change (buf, pos, pos, pos + cclen); |
1272 | |
1273 UNGCPRO; | |
1274 | |
1275 return cclen; | |
1276 } | |
1277 | |
1278 | |
1279 /* The following functions are interfaces onto the above function, | |
1280 for inserting particular sorts of data. In all the functions, | |
1281 BUF and POS specify the buffer and location where the insertion is | |
1282 to take place. (If POS is -1, text is inserted at point and point | |
1283 moves forward past the text.) FLAGS is as above. */ | |
1284 | |
1285 Charcount | |
665 | 1286 buffer_insert_raw_string_1 (struct buffer *buf, Charbpos pos, |
867 | 1287 const Ibyte *nonreloc, Bytecount length, |
428 | 1288 int flags) |
1289 { | |
1290 /* This function can GC */ | |
1291 return buffer_insert_string_1 (buf, pos, nonreloc, Qnil, 0, length, | |
1292 flags); | |
1293 } | |
1294 | |
1295 Charcount | |
665 | 1296 buffer_insert_lisp_string_1 (struct buffer *buf, Charbpos pos, Lisp_Object str, |
428 | 1297 int flags) |
1298 { | |
1299 /* This function can GC */ | |
1300 return buffer_insert_string_1 (buf, pos, 0, str, 0, | |
1301 XSTRING_LENGTH (str), | |
1302 flags); | |
1303 } | |
1304 | |
1305 /* Insert the null-terminated string S (in external format). */ | |
1306 | |
1307 Charcount | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
3250
diff
changeset
|
1308 buffer_insert_ascstring_1 (struct buffer *buf, Charbpos pos, const Ascbyte *s, |
428 | 1309 int flags) |
1310 { | |
1311 /* This function can GC */ | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
3250
diff
changeset
|
1312 const CIbyte *translated = GETTEXT (s); |
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
3250
diff
changeset
|
1313 ASSERT_ASCTEXT_ASCII (s); |
867 | 1314 return buffer_insert_string_1 (buf, pos, (const Ibyte *) translated, Qnil, |
428 | 1315 0, strlen (translated), flags); |
1316 } | |
1317 | |
1318 Charcount | |
867 | 1319 buffer_insert_emacs_char_1 (struct buffer *buf, Charbpos pos, Ichar ch, |
428 | 1320 int flags) |
1321 { | |
1322 /* This function can GC */ | |
867 | 1323 Ibyte str[MAX_ICHAR_LEN]; |
1324 Bytecount len = set_itext_ichar (str, ch); | |
428 | 1325 return buffer_insert_string_1 (buf, pos, str, Qnil, 0, len, flags); |
1326 } | |
1327 | |
1328 Charcount | |
665 | 1329 buffer_insert_c_char_1 (struct buffer *buf, Charbpos pos, char c, |
428 | 1330 int flags) |
1331 { | |
1332 /* This function can GC */ | |
867 | 1333 return buffer_insert_emacs_char_1 (buf, pos, (Ichar) (unsigned char) c, |
428 | 1334 flags); |
1335 } | |
1336 | |
1337 Charcount | |
665 | 1338 buffer_insert_from_buffer_1 (struct buffer *buf, Charbpos pos, |
1339 struct buffer *buf2, Charbpos pos2, | |
428 | 1340 Charcount length, int flags) |
1341 { | |
1342 /* This function can GC */ | |
1343 Lisp_Object str = make_string_from_buffer (buf2, pos2, length); | |
1344 return buffer_insert_string_1 (buf, pos, 0, str, 0, | |
1345 XSTRING_LENGTH (str), flags); | |
1346 } | |
1347 | |
1348 | |
1349 /************************************************************************/ | |
1350 /* Deletion of ranges */ | |
1351 /************************************************************************/ | |
1352 | |
1353 /* Delete characters in buffer from FROM up to (but not including) TO. */ | |
1354 | |
1355 void | |
665 | 1356 buffer_delete_range (struct buffer *buf, Charbpos from, Charbpos to, int flags) |
428 | 1357 { |
1358 /* This function can GC */ | |
1359 Charcount numdel; | |
826 | 1360 Bytebpos byte_from, byte_to; |
1361 Bytecount byte_numdel; | |
428 | 1362 EMACS_INT shortage; |
1363 struct buffer *mbuf; | |
1364 Lisp_Object bufcons; | |
826 | 1365 int do_move_gap = 0; |
428 | 1366 |
1367 /* Defensive steps just in case a buffer gets deleted and a calling | |
1368 function doesn't notice it. */ | |
1369 if (!BUFFER_LIVE_P (buf)) | |
1370 return; | |
1371 | |
1372 /* Make args be valid */ | |
1373 if (from < BUF_BEGV (buf)) | |
1374 from = BUF_BEGV (buf); | |
1375 if (to > BUF_ZV (buf)) | |
1376 to = BUF_ZV (buf); | |
1377 if ((numdel = to - from) <= 0) | |
1378 return; | |
1379 | |
1380 prepare_to_modify_buffer (buf, from, to, !(flags & INSDEL_NO_LOCKING)); | |
1381 | |
1382 /* Defensive steps in case the before-change-functions fuck around */ | |
1383 if (!BUFFER_LIVE_P (buf)) | |
1384 /* Bad bad pre-change function. */ | |
1385 return; | |
1386 | |
1387 /* Make args be valid again. prepare_to_modify_buffer() might have | |
1388 modified the buffer. */ | |
1389 if (from < BUF_BEGV (buf)) | |
1390 from = BUF_BEGV (buf); | |
1391 if (to > BUF_ZV (buf)) | |
1392 to = BUF_ZV (buf); | |
1393 if ((numdel = to - from) <= 0) | |
1394 return; | |
1395 | |
826 | 1396 byte_from = charbpos_to_bytebpos (buf, from); |
1397 byte_to = charbpos_to_bytebpos (buf, to); | |
1398 byte_numdel = byte_to - byte_from; | |
1399 | |
1400 if (to == BUF_Z (buf) && | |
1401 byte_from > BYTE_BUF_GPT (buf)) | |
1402 /* avoid moving the gap just to delete from the bottom. */ | |
1403 do_move_gap = 0; | |
1404 else | |
1405 { | |
1406 /* Make sure the gap is somewhere in or next to what we are deleting. */ | |
1407 /* NOTE: Can QUIT! */ | |
1408 if (byte_to < BYTE_BUF_GPT (buf)) | |
2367 | 1409 gap_left (buf, to, byte_to); |
826 | 1410 if (byte_from > BYTE_BUF_GPT (buf)) |
2367 | 1411 gap_right (buf, from, byte_from); |
826 | 1412 do_move_gap = 1; |
1413 } | |
1414 | |
1415 /* At this point, no more QUITting or processing of Lisp code. Buffer is | |
1416 in a consistent state. Following code puts buffer in an inconsistent | |
1417 state and can be considered a "critical section". */ | |
1418 | |
1419 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1420 { | |
1421 record_delete (mbuf, from, numdel); | |
1422 } | |
1423 BUF_MODIFF (buf)++; | |
1424 MARK_BUFFERS_CHANGED; | |
1425 | |
1426 /* We used to do the following before the gap move. But that might QUIT, | |
1427 and (as a result of this) the gap code always leaves the buffer in | |
1428 a consistent state. Therefore, it's totally safe to do these operations | |
1429 now, and just as well not before, as we're making state changes | |
1430 related to the deletion. */ | |
1431 | |
428 | 1432 /* Redisplay needs to know if a newline was in the deleted region. |
1433 If we've already marked the changed region as having a deleted | |
1434 newline there is no use in performing the check. */ | |
1435 if (!buf->changes->newline_was_deleted) | |
1436 { | |
1437 scan_buffer (buf, '\n', from, to, 1, &shortage, 1); | |
1438 if (!shortage) | |
1439 { | |
1440 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1441 { | |
1442 mbuf->changes->newline_was_deleted = 1; | |
1443 } | |
1444 } | |
1445 } | |
1446 | |
1447 delete_invalidate_line_number_cache (buf, from, to); | |
1448 | |
826 | 1449 #ifdef MULE |
1450 /* Update our count of ASCII, 8-bit and 16-bit chars and the | |
1451 entirely-one-byte flag */ | |
1452 { | |
1453 Bytebpos i; | |
428 | 1454 |
826 | 1455 for (i = byte_from; i < byte_to; i = next_bytebpos (buf, i)) |
1456 { | |
867 | 1457 Ichar ch = BYTE_BUF_FETCH_CHAR (buf, i); |
1458 if (ichar_ascii_p (ch)) | |
826 | 1459 buf->text->num_ascii_chars--; |
867 | 1460 if (ichar_8_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1461 buf->text->num_8_bit_fixed_chars--; |
867 | 1462 if (ichar_16_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1463 buf->text->num_16_bit_fixed_chars--; |
1464 } | |
1465 } | |
1466 #endif /* MULE */ | |
428 | 1467 |
826 | 1468 /* #### Point used to be modified here, but this causes problems |
1469 with MULE, as point is used to calculate bytebpos's, and if the | |
1470 offset in byte_numdel causes point to move to a non first-byte | |
1471 location, causing some other function to throw an assertion | |
1472 in ASSERT_VALID_BYTEBPOS. I've moved the code to right after | |
1473 the other movements and adjustments, but before the gap is | |
1474 moved. -- jh 970813 */ | |
428 | 1475 |
826 | 1476 /* Detach any extents that are completely within the range [FROM, TO], |
1477 if the extents are detachable. | |
1478 | |
1479 This must come AFTER record_delete(), so that the appropriate extents | |
1480 will be present to be recorded, and BEFORE the gap size is increased, | |
1481 as otherwise we will be confused about where the extents end. */ | |
1482 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1483 { | |
1484 process_extents_for_deletion (wrap_buffer (mbuf), byte_from, byte_to, 0); | |
428 | 1485 } |
1486 | |
826 | 1487 /* Relocate all markers pointing into the new, larger gap to |
1488 point at the end of the text before the gap. */ | |
1489 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1490 { | |
1491 adjust_markers (mbuf, | |
1492 (byte_to + BUF_GAP_SIZE (mbuf)), | |
1493 (byte_to + BUF_GAP_SIZE (mbuf)), | |
1494 (- byte_numdel - | |
1495 (do_move_gap ? BUF_GAP_SIZE (mbuf) : 0))); | |
1496 } | |
1497 | |
1498 /* Relocate any extent endpoints just like markers. */ | |
1499 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1500 { | |
1501 adjust_extents_for_deletion (wrap_buffer (mbuf), byte_from, byte_to, | |
1502 BUF_GAP_SIZE (mbuf), | |
1503 byte_numdel, | |
1504 do_move_gap ? BUF_GAP_SIZE (mbuf) : 0); | |
1505 } | |
1506 | |
1507 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1508 { | |
1509 /* Relocate point as if it were a marker. */ | |
1510 if (byte_from < BYTE_BUF_PT (mbuf)) | |
1511 { | |
1512 if (BYTE_BUF_PT (mbuf) < byte_to) | |
1513 JUST_SET_POINT (mbuf, from, byte_from); | |
1514 else | |
1515 JUST_SET_POINT (mbuf, BUF_PT (mbuf) - numdel, | |
1516 BYTE_BUF_PT (mbuf) - byte_numdel); | |
1517 } | |
1518 } | |
1519 | |
1520 if (do_move_gap) | |
1521 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + byte_numdel); | |
1522 else | |
1523 SET_BUF_END_GAP_SIZE (buf, BUF_END_GAP_SIZE (buf) + byte_numdel); | |
1524 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1525 { | |
1526 SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) - numdel, | |
1527 BYTE_BUF_ZV (mbuf) - byte_numdel); | |
1528 } | |
1529 SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BYTE_BUF_Z (buf) - byte_numdel); | |
1530 if (do_move_gap) | |
2367 | 1531 SET_BOTH_BUF_GPT (buf, from, byte_from); |
826 | 1532 SET_GAP_SENTINEL (buf); |
1533 | |
428 | 1534 #ifdef MULE |
826 | 1535 buffer_mule_signal_deleted_region (buf, from, to, byte_from, byte_to); |
1536 buf->text->entirely_one_byte_p = | |
1537 (BUF_FORMAT (buf) == FORMAT_8_BIT_FIXED || | |
1538 (BUF_FORMAT (buf) == FORMAT_DEFAULT && BUF_Z (buf) == BYTE_BUF_Z (buf))); | |
428 | 1539 #endif |
1540 | |
1541 #ifdef ERROR_CHECK_EXTENTS | |
1542 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1543 { | |
771 | 1544 sledgehammer_extent_check (wrap_buffer (mbuf)); |
428 | 1545 } |
1546 #endif | |
1547 | |
826 | 1548 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
1549 { | |
3250 | 1550 signal_syntax_cache_extent_adjust (mbuf); |
826 | 1551 } |
1552 | |
1553 /* &&#### Here we consider converting the buffer from default to | |
1554 8-bit-fixed if is entirely 8-bit-fixed chars and has been that way for | |
1555 a long time, e.g. 20 minutes. And if the buffer just switched to all | |
1556 8-bit-fixed chars, start the timer. */ | |
428 | 1557 signal_after_change (buf, from, to, from); |
1558 } | |
1559 | |
1560 | |
1561 /************************************************************************/ | |
1562 /* Replacement of characters */ | |
1563 /************************************************************************/ | |
1564 | |
1565 /* Replace the character at POS in buffer B with CH. */ | |
1566 | |
1567 void | |
867 | 1568 buffer_replace_char (struct buffer *buf, Charbpos pos, Ichar ch, |
428 | 1569 int not_real_change, int force_lock_check) |
1570 { | |
1571 /* This function can GC */ | |
867 | 1572 Ibyte newstr[MAX_ICHAR_LEN]; |
826 | 1573 Bytecount newlen; |
867 | 1574 Ichar oldch; |
428 | 1575 |
1576 /* Defensive steps just in case a buffer gets deleted and a calling | |
1577 function doesn't notice it. */ | |
1578 if (!BUFFER_LIVE_P (buf)) | |
1579 return; | |
1580 | |
867 | 1581 newlen = set_itext_ichar_fmt (newstr, ch, BUF_FORMAT (buf), |
826 | 1582 wrap_buffer (buf)); |
1583 oldch = BUF_FETCH_CHAR (buf, pos); | |
867 | 1584 if (ichar_fits_in_format (ch, BUF_FORMAT (buf), wrap_buffer (buf)) && |
1585 newlen == ichar_len_fmt (oldch, BUF_FORMAT (buf))) | |
428 | 1586 { |
1587 struct buffer *mbuf; | |
1588 Lisp_Object bufcons; | |
1589 | |
1590 /* then we can just replace the text. */ | |
1591 prepare_to_modify_buffer (buf, pos, pos + 1, | |
1592 !not_real_change || force_lock_check); | |
1593 /* Defensive steps in case the before-change-functions fuck around */ | |
1594 if (!BUFFER_LIVE_P (buf)) | |
1595 /* Bad bad pre-change function. */ | |
1596 return; | |
1597 | |
1598 /* Make args be valid again. prepare_to_modify_buffer() might have | |
1599 modified the buffer. */ | |
1600 if (pos < BUF_BEGV (buf)) | |
1601 pos = BUF_BEGV (buf); | |
1602 if (pos >= BUF_ZV (buf)) | |
1603 pos = BUF_ZV (buf) - 1; | |
1604 if (pos < BUF_BEGV (buf)) | |
1605 /* no more characters in buffer! */ | |
1606 return; | |
1607 | |
1608 if (BUF_FETCH_CHAR (buf, pos) == '\n') | |
1609 { | |
1610 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1611 { | |
1612 mbuf->changes->newline_was_deleted = 1; | |
1613 } | |
1614 } | |
1615 MARK_BUFFERS_CHANGED; | |
1616 if (!not_real_change) | |
1617 { | |
1618 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1619 { | |
1620 record_change (mbuf, pos, 1); | |
1621 } | |
1622 BUF_MODIFF (buf)++; | |
1623 } | |
826 | 1624 |
1625 #ifdef MULE | |
867 | 1626 if (ichar_ascii_p (oldch)) |
826 | 1627 buf->text->num_ascii_chars--; |
867 | 1628 if (ichar_8_bit_fixed_p (oldch, wrap_buffer (buf))) |
826 | 1629 buf->text->num_8_bit_fixed_chars--; |
867 | 1630 if (ichar_16_bit_fixed_p (oldch, wrap_buffer (buf))) |
826 | 1631 buf->text->num_16_bit_fixed_chars--; |
867 | 1632 if (ichar_ascii_p (ch)) |
826 | 1633 buf->text->num_ascii_chars++; |
867 | 1634 if (ichar_8_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1635 buf->text->num_8_bit_fixed_chars++; |
867 | 1636 if (ichar_16_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1637 buf->text->num_16_bit_fixed_chars++; |
1638 #endif /* MULE */ | |
1639 | |
428 | 1640 memcpy (BUF_BYTE_ADDRESS (buf, pos), newstr, newlen); |
1641 | |
1642 signal_after_change (buf, pos, pos + 1, pos + 1); | |
1643 | |
1644 /* We do not have to adjust the Mule data; we just replaced a | |
1645 character with another of the same number of bytes. */ | |
1646 } | |
1647 else | |
1648 { | |
1649 /* | |
1650 * Must implement as deletion followed by insertion. | |
1651 * | |
1652 * Make a note to move point forward later in the one situation | |
1653 * where it is needed, a delete/insert one position behind | |
1654 * point. Point will drift backward by one position and stay | |
1655 * there otherwise. | |
1656 */ | |
1657 int movepoint = (pos == BUF_PT (buf) - 1); | |
1658 | |
1659 buffer_delete_range (buf, pos, pos + 1, 0); | |
1660 /* Defensive steps in case the before-change-functions fuck around */ | |
1661 if (!BUFFER_LIVE_P (buf)) | |
1662 /* Bad bad pre-change function. */ | |
1663 return; | |
1664 | |
1665 /* Make args be valid again. prepare_to_modify_buffer() might have | |
1666 modified the buffer. */ | |
1667 if (pos < BUF_BEGV (buf)) | |
1668 pos = BUF_BEGV (buf); | |
1669 if (pos >= BUF_ZV (buf)) | |
1670 pos = BUF_ZV (buf) - 1; | |
1671 if (pos < BUF_BEGV (buf)) | |
1672 /* no more characters in buffer! */ | |
1673 return; | |
1674 /* | |
1675 * -1 as the pos argument means to move point forward with the | |
1676 * insertion, which we must do if the deletion moved point | |
1677 * backward so that it now equals the insertion point. | |
1678 */ | |
1679 buffer_insert_string_1 (buf, (movepoint ? -1 : pos), | |
1680 newstr, Qnil, 0, newlen, 0); | |
1681 } | |
1682 } | |
1683 | |
1684 | |
1685 /************************************************************************/ | |
1686 /* Other functions */ | |
1687 /************************************************************************/ | |
1688 | |
1689 /* Make a string from a buffer. This needs to take into account the gap, | |
1690 and add any necessary extents from the buffer. */ | |
1691 | |
1692 static Lisp_Object | |
665 | 1693 make_string_from_buffer_1 (struct buffer *buf, Charbpos pos, Charcount length, |
428 | 1694 int no_extents) |
1695 { | |
1696 /* This function can GC */ | |
826 | 1697 Bytebpos bytepos = charbpos_to_bytebpos (buf, pos); |
1698 Bytecount bytelen = charbpos_to_bytebpos (buf, pos + length) - bytepos; | |
1699 Bytecount needed = copy_buffer_text_out (buf, bytepos, bytelen, NULL, 0, | |
1700 FORMAT_DEFAULT, Qnil, NULL); | |
1701 Lisp_Object val = make_uninit_string (needed); | |
428 | 1702 |
1703 struct gcpro gcpro1; | |
1704 GCPRO1 (val); | |
1705 | |
1706 if (!no_extents) | |
826 | 1707 add_string_extents (val, buf, bytepos, bytelen); |
1708 copy_buffer_text_out (buf, bytepos, bytelen, XSTRING_DATA (val), needed, | |
1709 FORMAT_DEFAULT, Qnil, NULL); | |
771 | 1710 init_string_ascii_begin (val); |
1711 sledgehammer_check_ascii_begin (val); | |
1712 | |
428 | 1713 UNGCPRO; |
1714 return val; | |
1715 } | |
1716 | |
1717 Lisp_Object | |
665 | 1718 make_string_from_buffer (struct buffer *buf, Charbpos pos, Charcount length) |
428 | 1719 { |
1720 return make_string_from_buffer_1 (buf, pos, length, 0); | |
1721 } | |
1722 | |
1723 Lisp_Object | |
665 | 1724 make_string_from_buffer_no_extents (struct buffer *buf, Charbpos pos, |
428 | 1725 Charcount length) |
1726 { | |
1727 return make_string_from_buffer_1 (buf, pos, length, 1); | |
1728 } | |
1729 | |
1730 void | |
665 | 1731 barf_if_buffer_read_only (struct buffer *buf, Charbpos from, Charbpos to) |
428 | 1732 { |
1733 Lisp_Object buffer; | |
1734 Lisp_Object iro; | |
1735 | |
793 | 1736 buffer = wrap_buffer (buf); |
428 | 1737 back: |
1738 iro = (buf == current_buffer ? Vinhibit_read_only : | |
1739 symbol_value_in_buffer (Qinhibit_read_only, buffer)); | |
1740 if (!LISTP (iro)) | |
1741 return; | |
1742 if (NILP (iro) && !NILP (buf->read_only)) | |
1743 { | |
1744 Fsignal (Qbuffer_read_only, (list1 (buffer))); | |
1745 goto back; | |
1746 } | |
1747 if (from > 0) | |
1748 { | |
1749 if (to < 0) | |
1750 to = from; | |
1751 verify_extent_modification (buffer, | |
665 | 1752 charbpos_to_bytebpos (buf, from), |
1753 charbpos_to_bytebpos (buf, to), | |
428 | 1754 iro); |
1755 } | |
1756 } | |
1757 | |
1758 | |
1759 /************************************************************************/ | |
1760 /* initialization */ | |
1761 /************************************************************************/ | |
1762 | |
1763 void | |
1764 reinit_vars_of_insdel (void) | |
1765 { | |
1766 inside_change_hook = 0; | |
1767 in_first_change = 0; | |
1768 } | |
1769 | |
1770 void | |
1771 vars_of_insdel (void) | |
1772 { | |
1773 } | |
1774 | |
1775 void | |
1776 init_buffer_text (struct buffer *b) | |
1777 { | |
1778 if (!b->base_buffer) | |
1779 { | |
1780 SET_BUF_GAP_SIZE (b, 20); | |
1781 BUFFER_ALLOC (b->text->beg, BUF_GAP_SIZE (b) + BUF_END_SENTINEL_SIZE); | |
1782 if (! BUF_BEG_ADDR (b)) | |
1783 memory_full (); | |
1784 | |
1785 SET_BUF_END_GAP_SIZE (b, 0); | |
2367 | 1786 SET_BOTH_BUF_GPT (b, 1, 1); |
428 | 1787 SET_BOTH_BUF_Z (b, 1, 1); |
1788 SET_GAP_SENTINEL (b); | |
1789 SET_END_SENTINEL (b); | |
2367 | 1790 |
428 | 1791 #ifdef MULE |
2367 | 1792 b->text->entirely_one_byte_p = 1; |
428 | 1793 |
2367 | 1794 #ifdef OLD_BYTE_CHAR |
1795 b->text->mule_bufmin = b->text->mule_bufmax = 1; | |
1796 b->text->mule_bytmin = b->text->mule_bytmax = 1; | |
1797 #endif | |
428 | 1798 |
2367 | 1799 b->text->cached_charpos = 1; |
1800 b->text->cached_bytepos = 1; | |
1801 | |
826 | 1802 /* &&#### Set to FORMAT_8_BIT_FIXED when that code is working */ |
1803 BUF_FORMAT (b) = FORMAT_DEFAULT; | |
428 | 1804 #endif /* MULE */ |
1805 b->text->line_number_cache = Qnil; | |
1806 | |
1807 BUF_MODIFF (b) = 1; | |
1808 BUF_SAVE_MODIFF (b) = 1; | |
1809 | |
1810 JUST_SET_POINT (b, 1, 1); | |
1811 SET_BOTH_BUF_BEGV (b, 1, 1); | |
1812 SET_BOTH_BUF_ZV (b, 1, 1); | |
1813 | |
1814 b->text->changes = xnew_and_zero (struct buffer_text_change_data); | |
1815 } | |
1816 else | |
1817 { | |
826 | 1818 JUST_SET_POINT (b, BUF_PT (b->base_buffer), BYTE_BUF_PT (b->base_buffer)); |
428 | 1819 SET_BOTH_BUF_BEGV (b, BUF_BEGV (b->base_buffer), |
826 | 1820 BYTE_BUF_BEGV (b->base_buffer)); |
428 | 1821 SET_BOTH_BUF_ZV (b, BUF_ZV (b->base_buffer), |
826 | 1822 BYTE_BUF_ZV (b->base_buffer)); |
428 | 1823 } |
1824 | |
1825 b->changes = xnew_and_zero (struct each_buffer_change_data); | |
1826 BUF_FACECHANGE (b) = 1; | |
1827 | |
1828 #ifdef REGION_CACHE_NEEDS_WORK | |
1829 b->newline_cache = 0; | |
1830 b->width_run_cache = 0; | |
1831 b->width_table = Qnil; | |
1832 #endif | |
1833 } | |
1834 | |
1835 void | |
1836 uninit_buffer_text (struct buffer *b) | |
1837 { | |
1838 if (!b->base_buffer) | |
1839 { | |
1840 BUFFER_FREE (b->text->beg); | |
1726 | 1841 xfree (b->text->changes, struct buffer_text_change_data *); |
428 | 1842 } |
1726 | 1843 xfree (b->changes, struct each_buffer_change_data *); |
428 | 1844 |
1845 #ifdef REGION_CACHE_NEEDS_WORK | |
1846 if (b->newline_cache) | |
1847 { | |
1848 free_region_cache (b->newline_cache); | |
1849 b->newline_cache = 0; | |
1850 } | |
1851 if (b->width_run_cache) | |
1852 { | |
1853 free_region_cache (b->width_run_cache); | |
1854 b->width_run_cache = 0; | |
1855 } | |
1856 b->width_table = Qnil; | |
1857 #endif | |
1858 } |