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