Mercurial > hg > xemacs-beta
annotate src/insdel.c @ 5518:3cc7470ea71c
gnuclient: if TMPDIR was set and connect failed, try again with /tmp
2011-06-03 Aidan Kehoe <kehoea@parhasard.net>
* gnuslib.c (connect_to_unix_server):
Retry with /tmp as a directory in which to search for Unix sockets
if an attempt to connect with some other directory failed (which
may be because gnuclient and gnuserv don't share an environment
value for TMPDIR, or because gnuserv was compiled with USE_TMPDIR
turned off).
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Fri, 03 Jun 2011 18:40:57 +0100 |
parents | 308d34e9f07d |
children | 56144c8593a8 |
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 | |
501 > EMACS_INT_MAX) | |
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, |
853 | 823 make_int (start), make_int (end), |
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, |
853 | 828 make_int (start), make_int (end), |
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, |
853 | 912 make_int (start), make_int (new_end), |
913 make_int (orig_end - start), | |
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, |
853 | 918 make_int (start), make_int (new_end), |
919 make_int (orig_end - start), | |
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 | |
665 | 1042 /* Insert a string into BUF at Charbpos POS. The string data comes |
428 | 1043 from one of two sources: constant, non-relocatable data (specified |
1044 in NONRELOC), or a Lisp string object (specified in RELOC), which | |
1045 is relocatable and may have extent data that needs to be copied | |
1046 into the buffer. OFFSET and LENGTH specify the substring of the | |
1047 data that is actually to be inserted. As a special case, if POS | |
1048 is -1, insert the string at point and move point to the end of the | |
1049 string. | |
1050 | |
1051 Normally, markers at the insertion point end up before the | |
1052 inserted string. If INSDEL_BEFORE_MARKERS is set in flags, however, | |
1053 they end up after the string. | |
1054 | |
1055 INSDEL_NO_LOCKING is kludgy and is used when insert-file-contents is | |
1056 visiting a new file; it inhibits the locking checks normally done | |
1057 before modifying a buffer. Similar checks were already done | |
1058 in the higher-level Lisp functions calling insert-file-contents. */ | |
1059 | |
1060 Charcount | |
665 | 1061 buffer_insert_string_1 (struct buffer *buf, Charbpos pos, |
867 | 1062 const Ibyte *nonreloc, Lisp_Object reloc, |
428 | 1063 Bytecount offset, Bytecount length, |
1064 int flags) | |
1065 { | |
1066 /* This function can GC */ | |
1067 struct gcpro gcpro1; | |
826 | 1068 Bytebpos bytepos; |
1069 Bytecount length_in_buffer; | |
428 | 1070 Charcount cclen; |
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. */ | |
1095 if ((length + BUF_Z (buf)) > EMACS_INT_MAX) | |
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 |
428 | 1121 /* string may have been relocated up to this point */ |
1122 if (STRINGP (reloc)) | |
771 | 1123 { |
793 | 1124 cclen = string_offset_byte_to_char_len (reloc, offset, length); |
771 | 1125 nonreloc = XSTRING_DATA (reloc); |
1126 } | |
1127 else | |
1128 cclen = bytecount_to_charcount (nonreloc + offset, length); | |
826 | 1129 /* &&#### Here we check if the text can't fit into the format of the buffer, |
1130 and if so convert it to another format (either default or 32-bit-fixed, | |
1131 according to some flag; if no flag, use default). */ | |
1132 | |
1133 length_in_buffer = copy_text_between_formats (nonreloc + offset, length, | |
1134 FORMAT_DEFAULT, | |
1135 STRINGP (reloc) ? reloc : Qnil, | |
1136 NULL, 0, | |
1137 BUF_FORMAT (buf), | |
1138 wrap_buffer (buf), | |
1139 NULL); | |
428 | 1140 |
826 | 1141 if (bytepos != BYTE_BUF_GPT (buf)) |
428 | 1142 /* #### if debug-on-quit is invoked and the user changes the |
1143 buffer, bad things can happen. This is a rampant problem | |
1144 in Emacs. */ | |
2367 | 1145 move_gap (buf, pos, bytepos); /* may QUIT */ |
826 | 1146 if (! GAP_CAN_HOLD_SIZE_P (buf, length_in_buffer)) |
428 | 1147 { |
826 | 1148 if (BUF_END_GAP_SIZE (buf) >= length_in_buffer) |
428 | 1149 merge_gap_with_end_gap (buf); |
1150 else | |
826 | 1151 make_gap (buf, length_in_buffer - BUF_GAP_SIZE (buf)); |
428 | 1152 } |
1153 | |
826 | 1154 /* At this point, no more QUITting or processing of Lisp code. Buffer is |
1155 in a consistent state. Following code puts buffer in an inconsistent | |
1156 state and can be considered a "critical section". */ | |
1157 | |
428 | 1158 insert_invalidate_line_number_cache (buf, pos, nonreloc + offset, length); |
1159 | |
1160 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1161 { | |
1162 record_insert (mbuf, pos, cclen); | |
1163 } | |
1164 | |
1165 BUF_MODIFF (buf)++; | |
1166 MARK_BUFFERS_CHANGED; | |
1167 | |
826 | 1168 /* string may have been relocated up to this point #### if string is |
1169 modified during quit processing, bad things can happen. */ | |
428 | 1170 if (STRINGP (reloc)) |
1171 nonreloc = XSTRING_DATA (reloc); | |
1172 | |
853 | 1173 memcpy (BUF_GPT_ADDR (buf), nonreloc + offset, length); |
1174 | |
826 | 1175 copy_text_between_formats (nonreloc + offset, length, FORMAT_DEFAULT, |
1176 STRINGP (reloc) ? reloc : Qnil, | |
1177 BUF_GPT_ADDR (buf), length_in_buffer, | |
1178 BUF_FORMAT (buf), wrap_buffer (buf), NULL); | |
1179 | |
1180 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) - length_in_buffer); | |
2367 | 1181 SET_BOTH_BUF_GPT (buf, BUF_GPT (buf) + cclen, |
1182 BYTE_BUF_GPT (buf) + length_in_buffer); | |
428 | 1183 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
1184 { | |
826 | 1185 SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) + cclen, |
1186 BYTE_BUF_ZV (mbuf) + length_in_buffer); | |
428 | 1187 } |
826 | 1188 SET_BOTH_BUF_Z (buf, BUF_Z (buf) + cclen, BYTE_BUF_Z (buf) + length_in_buffer); |
428 | 1189 SET_GAP_SENTINEL (buf); |
771 | 1190 |
1191 | |
428 | 1192 #ifdef MULE |
826 | 1193 buffer_mule_signal_inserted_region (buf, pos, length_in_buffer, cclen); |
1194 /* Update our count of ASCII, 8-bit and 16-bit chars and the | |
1195 entirely-one-byte flag */ | |
1196 { | |
867 | 1197 const Ibyte *ptr = nonreloc + offset; |
1198 const Ibyte *ptrend = ptr + length; | |
826 | 1199 |
1200 while (ptr < ptrend) | |
1201 { | |
867 | 1202 Ichar ch = itext_ichar (ptr); |
1203 if (ichar_ascii_p (ch)) | |
826 | 1204 buf->text->num_ascii_chars++; |
867 | 1205 if (ichar_8_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1206 buf->text->num_8_bit_fixed_chars++; |
867 | 1207 if (ichar_16_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1208 buf->text->num_16_bit_fixed_chars++; |
867 | 1209 INC_IBYTEPTR (ptr); |
826 | 1210 } |
1211 | |
1212 buf->text->entirely_one_byte_p = | |
1213 (BUF_FORMAT (buf) == FORMAT_8_BIT_FIXED || | |
1214 (BUF_FORMAT (buf) == FORMAT_DEFAULT && BUF_Z (buf) == BYTE_BUF_Z (buf))); | |
1215 } | |
428 | 1216 #endif |
1217 | |
1218 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1219 { | |
826 | 1220 process_extents_for_insertion (wrap_buffer (mbuf), bytepos, |
1221 length_in_buffer); | |
428 | 1222 } |
1223 | |
1224 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1225 { | |
826 | 1226 /* We know the gap is at BYTEPOS so the cast is OK. */ |
1227 adjust_markers_for_insert (mbuf, (Membpos) bytepos, length_in_buffer); | |
428 | 1228 } |
1229 | |
1230 /* Point logically doesn't move, but may need to be adjusted because | |
1231 it's a byte index. point-marker doesn't change because it's a | |
1232 memory index. */ | |
1233 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1234 { | |
826 | 1235 if (BYTE_BUF_PT (mbuf) > bytepos) |
428 | 1236 JUST_SET_POINT (mbuf, BUF_PT (mbuf) + cclen, |
826 | 1237 BYTE_BUF_PT (mbuf) + length_in_buffer); |
428 | 1238 } |
1239 | |
1240 /* Well, point might move. */ | |
1241 if (move_point) | |
826 | 1242 BYTE_BUF_SET_PT (buf, bytepos + length_in_buffer); |
428 | 1243 |
1244 if (STRINGP (reloc)) | |
1245 { | |
1246 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1247 { | |
826 | 1248 splice_in_string_extents (reloc, mbuf, bytepos, length, offset); |
428 | 1249 } |
1250 } | |
1251 | |
1252 if (flags & INSDEL_BEFORE_MARKERS) | |
1253 { | |
1254 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1255 { | |
826 | 1256 /* bytepos - 1 is correct because the FROM argument is exclusive. |
665 | 1257 I formerly used DEC_BYTEBPOS() but that caused problems at the |
428 | 1258 beginning of the buffer. */ |
826 | 1259 adjust_markers (mbuf, bytepos - 1, bytepos, length_in_buffer); |
428 | 1260 } |
1261 } | |
1262 | |
826 | 1263 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
1264 { | |
3250 | 1265 signal_syntax_cache_extent_adjust (mbuf); |
826 | 1266 } |
1267 | |
428 | 1268 signal_after_change (buf, pos, pos, pos + cclen); |
1269 | |
1270 UNGCPRO; | |
1271 | |
1272 return cclen; | |
1273 } | |
1274 | |
1275 | |
1276 /* The following functions are interfaces onto the above function, | |
1277 for inserting particular sorts of data. In all the functions, | |
1278 BUF and POS specify the buffer and location where the insertion is | |
1279 to take place. (If POS is -1, text is inserted at point and point | |
1280 moves forward past the text.) FLAGS is as above. */ | |
1281 | |
1282 Charcount | |
665 | 1283 buffer_insert_raw_string_1 (struct buffer *buf, Charbpos pos, |
867 | 1284 const Ibyte *nonreloc, Bytecount length, |
428 | 1285 int flags) |
1286 { | |
1287 /* This function can GC */ | |
1288 return buffer_insert_string_1 (buf, pos, nonreloc, Qnil, 0, length, | |
1289 flags); | |
1290 } | |
1291 | |
1292 Charcount | |
665 | 1293 buffer_insert_lisp_string_1 (struct buffer *buf, Charbpos pos, Lisp_Object str, |
428 | 1294 int flags) |
1295 { | |
1296 /* This function can GC */ | |
1297 return buffer_insert_string_1 (buf, pos, 0, str, 0, | |
1298 XSTRING_LENGTH (str), | |
1299 flags); | |
1300 } | |
1301 | |
1302 /* Insert the null-terminated string S (in external format). */ | |
1303 | |
1304 Charcount | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
3250
diff
changeset
|
1305 buffer_insert_ascstring_1 (struct buffer *buf, Charbpos pos, const Ascbyte *s, |
428 | 1306 int flags) |
1307 { | |
1308 /* This function can GC */ | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
3250
diff
changeset
|
1309 const CIbyte *translated = GETTEXT (s); |
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
3250
diff
changeset
|
1310 ASSERT_ASCTEXT_ASCII (s); |
867 | 1311 return buffer_insert_string_1 (buf, pos, (const Ibyte *) translated, Qnil, |
428 | 1312 0, strlen (translated), flags); |
1313 } | |
1314 | |
1315 Charcount | |
867 | 1316 buffer_insert_emacs_char_1 (struct buffer *buf, Charbpos pos, Ichar ch, |
428 | 1317 int flags) |
1318 { | |
1319 /* This function can GC */ | |
867 | 1320 Ibyte str[MAX_ICHAR_LEN]; |
1321 Bytecount len = set_itext_ichar (str, ch); | |
428 | 1322 return buffer_insert_string_1 (buf, pos, str, Qnil, 0, len, flags); |
1323 } | |
1324 | |
1325 Charcount | |
665 | 1326 buffer_insert_c_char_1 (struct buffer *buf, Charbpos pos, char c, |
428 | 1327 int flags) |
1328 { | |
1329 /* This function can GC */ | |
867 | 1330 return buffer_insert_emacs_char_1 (buf, pos, (Ichar) (unsigned char) c, |
428 | 1331 flags); |
1332 } | |
1333 | |
1334 Charcount | |
665 | 1335 buffer_insert_from_buffer_1 (struct buffer *buf, Charbpos pos, |
1336 struct buffer *buf2, Charbpos pos2, | |
428 | 1337 Charcount length, int flags) |
1338 { | |
1339 /* This function can GC */ | |
1340 Lisp_Object str = make_string_from_buffer (buf2, pos2, length); | |
1341 return buffer_insert_string_1 (buf, pos, 0, str, 0, | |
1342 XSTRING_LENGTH (str), flags); | |
1343 } | |
1344 | |
1345 | |
1346 /************************************************************************/ | |
1347 /* Deletion of ranges */ | |
1348 /************************************************************************/ | |
1349 | |
1350 /* Delete characters in buffer from FROM up to (but not including) TO. */ | |
1351 | |
1352 void | |
665 | 1353 buffer_delete_range (struct buffer *buf, Charbpos from, Charbpos to, int flags) |
428 | 1354 { |
1355 /* This function can GC */ | |
1356 Charcount numdel; | |
826 | 1357 Bytebpos byte_from, byte_to; |
1358 Bytecount byte_numdel; | |
428 | 1359 EMACS_INT shortage; |
1360 struct buffer *mbuf; | |
1361 Lisp_Object bufcons; | |
826 | 1362 int do_move_gap = 0; |
428 | 1363 |
1364 /* Defensive steps just in case a buffer gets deleted and a calling | |
1365 function doesn't notice it. */ | |
1366 if (!BUFFER_LIVE_P (buf)) | |
1367 return; | |
1368 | |
1369 /* Make args be valid */ | |
1370 if (from < BUF_BEGV (buf)) | |
1371 from = BUF_BEGV (buf); | |
1372 if (to > BUF_ZV (buf)) | |
1373 to = BUF_ZV (buf); | |
1374 if ((numdel = to - from) <= 0) | |
1375 return; | |
1376 | |
1377 prepare_to_modify_buffer (buf, from, to, !(flags & INSDEL_NO_LOCKING)); | |
1378 | |
1379 /* Defensive steps in case the before-change-functions fuck around */ | |
1380 if (!BUFFER_LIVE_P (buf)) | |
1381 /* Bad bad pre-change function. */ | |
1382 return; | |
1383 | |
1384 /* Make args be valid again. prepare_to_modify_buffer() might have | |
1385 modified the buffer. */ | |
1386 if (from < BUF_BEGV (buf)) | |
1387 from = BUF_BEGV (buf); | |
1388 if (to > BUF_ZV (buf)) | |
1389 to = BUF_ZV (buf); | |
1390 if ((numdel = to - from) <= 0) | |
1391 return; | |
1392 | |
826 | 1393 byte_from = charbpos_to_bytebpos (buf, from); |
1394 byte_to = charbpos_to_bytebpos (buf, to); | |
1395 byte_numdel = byte_to - byte_from; | |
1396 | |
1397 if (to == BUF_Z (buf) && | |
1398 byte_from > BYTE_BUF_GPT (buf)) | |
1399 /* avoid moving the gap just to delete from the bottom. */ | |
1400 do_move_gap = 0; | |
1401 else | |
1402 { | |
1403 /* Make sure the gap is somewhere in or next to what we are deleting. */ | |
1404 /* NOTE: Can QUIT! */ | |
1405 if (byte_to < BYTE_BUF_GPT (buf)) | |
2367 | 1406 gap_left (buf, to, byte_to); |
826 | 1407 if (byte_from > BYTE_BUF_GPT (buf)) |
2367 | 1408 gap_right (buf, from, byte_from); |
826 | 1409 do_move_gap = 1; |
1410 } | |
1411 | |
1412 /* At this point, no more QUITting or processing of Lisp code. Buffer is | |
1413 in a consistent state. Following code puts buffer in an inconsistent | |
1414 state and can be considered a "critical section". */ | |
1415 | |
1416 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1417 { | |
1418 record_delete (mbuf, from, numdel); | |
1419 } | |
1420 BUF_MODIFF (buf)++; | |
1421 MARK_BUFFERS_CHANGED; | |
1422 | |
1423 /* We used to do the following before the gap move. But that might QUIT, | |
1424 and (as a result of this) the gap code always leaves the buffer in | |
1425 a consistent state. Therefore, it's totally safe to do these operations | |
1426 now, and just as well not before, as we're making state changes | |
1427 related to the deletion. */ | |
1428 | |
428 | 1429 /* Redisplay needs to know if a newline was in the deleted region. |
1430 If we've already marked the changed region as having a deleted | |
1431 newline there is no use in performing the check. */ | |
1432 if (!buf->changes->newline_was_deleted) | |
1433 { | |
1434 scan_buffer (buf, '\n', from, to, 1, &shortage, 1); | |
1435 if (!shortage) | |
1436 { | |
1437 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1438 { | |
1439 mbuf->changes->newline_was_deleted = 1; | |
1440 } | |
1441 } | |
1442 } | |
1443 | |
1444 delete_invalidate_line_number_cache (buf, from, to); | |
1445 | |
826 | 1446 #ifdef MULE |
1447 /* Update our count of ASCII, 8-bit and 16-bit chars and the | |
1448 entirely-one-byte flag */ | |
1449 { | |
1450 Bytebpos i; | |
428 | 1451 |
826 | 1452 for (i = byte_from; i < byte_to; i = next_bytebpos (buf, i)) |
1453 { | |
867 | 1454 Ichar ch = BYTE_BUF_FETCH_CHAR (buf, i); |
1455 if (ichar_ascii_p (ch)) | |
826 | 1456 buf->text->num_ascii_chars--; |
867 | 1457 if (ichar_8_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1458 buf->text->num_8_bit_fixed_chars--; |
867 | 1459 if (ichar_16_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1460 buf->text->num_16_bit_fixed_chars--; |
1461 } | |
1462 } | |
1463 #endif /* MULE */ | |
428 | 1464 |
826 | 1465 /* #### Point used to be modified here, but this causes problems |
1466 with MULE, as point is used to calculate bytebpos's, and if the | |
1467 offset in byte_numdel causes point to move to a non first-byte | |
1468 location, causing some other function to throw an assertion | |
1469 in ASSERT_VALID_BYTEBPOS. I've moved the code to right after | |
1470 the other movements and adjustments, but before the gap is | |
1471 moved. -- jh 970813 */ | |
428 | 1472 |
826 | 1473 /* Detach any extents that are completely within the range [FROM, TO], |
1474 if the extents are detachable. | |
1475 | |
1476 This must come AFTER record_delete(), so that the appropriate extents | |
1477 will be present to be recorded, and BEFORE the gap size is increased, | |
1478 as otherwise we will be confused about where the extents end. */ | |
1479 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1480 { | |
1481 process_extents_for_deletion (wrap_buffer (mbuf), byte_from, byte_to, 0); | |
428 | 1482 } |
1483 | |
826 | 1484 /* Relocate all markers pointing into the new, larger gap to |
1485 point at the end of the text before the gap. */ | |
1486 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1487 { | |
1488 adjust_markers (mbuf, | |
1489 (byte_to + BUF_GAP_SIZE (mbuf)), | |
1490 (byte_to + BUF_GAP_SIZE (mbuf)), | |
1491 (- byte_numdel - | |
1492 (do_move_gap ? BUF_GAP_SIZE (mbuf) : 0))); | |
1493 } | |
1494 | |
1495 /* Relocate any extent endpoints just like markers. */ | |
1496 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1497 { | |
1498 adjust_extents_for_deletion (wrap_buffer (mbuf), byte_from, byte_to, | |
1499 BUF_GAP_SIZE (mbuf), | |
1500 byte_numdel, | |
1501 do_move_gap ? BUF_GAP_SIZE (mbuf) : 0); | |
1502 } | |
1503 | |
1504 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1505 { | |
1506 /* Relocate point as if it were a marker. */ | |
1507 if (byte_from < BYTE_BUF_PT (mbuf)) | |
1508 { | |
1509 if (BYTE_BUF_PT (mbuf) < byte_to) | |
1510 JUST_SET_POINT (mbuf, from, byte_from); | |
1511 else | |
1512 JUST_SET_POINT (mbuf, BUF_PT (mbuf) - numdel, | |
1513 BYTE_BUF_PT (mbuf) - byte_numdel); | |
1514 } | |
1515 } | |
1516 | |
1517 if (do_move_gap) | |
1518 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + byte_numdel); | |
1519 else | |
1520 SET_BUF_END_GAP_SIZE (buf, BUF_END_GAP_SIZE (buf) + byte_numdel); | |
1521 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1522 { | |
1523 SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) - numdel, | |
1524 BYTE_BUF_ZV (mbuf) - byte_numdel); | |
1525 } | |
1526 SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BYTE_BUF_Z (buf) - byte_numdel); | |
1527 if (do_move_gap) | |
2367 | 1528 SET_BOTH_BUF_GPT (buf, from, byte_from); |
826 | 1529 SET_GAP_SENTINEL (buf); |
1530 | |
428 | 1531 #ifdef MULE |
826 | 1532 buffer_mule_signal_deleted_region (buf, from, to, byte_from, byte_to); |
1533 buf->text->entirely_one_byte_p = | |
1534 (BUF_FORMAT (buf) == FORMAT_8_BIT_FIXED || | |
1535 (BUF_FORMAT (buf) == FORMAT_DEFAULT && BUF_Z (buf) == BYTE_BUF_Z (buf))); | |
428 | 1536 #endif |
1537 | |
1538 #ifdef ERROR_CHECK_EXTENTS | |
1539 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1540 { | |
771 | 1541 sledgehammer_extent_check (wrap_buffer (mbuf)); |
428 | 1542 } |
1543 #endif | |
1544 | |
826 | 1545 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) |
1546 { | |
3250 | 1547 signal_syntax_cache_extent_adjust (mbuf); |
826 | 1548 } |
1549 | |
1550 /* &&#### Here we consider converting the buffer from default to | |
1551 8-bit-fixed if is entirely 8-bit-fixed chars and has been that way for | |
1552 a long time, e.g. 20 minutes. And if the buffer just switched to all | |
1553 8-bit-fixed chars, start the timer. */ | |
428 | 1554 signal_after_change (buf, from, to, from); |
1555 } | |
1556 | |
1557 | |
1558 /************************************************************************/ | |
1559 /* Replacement of characters */ | |
1560 /************************************************************************/ | |
1561 | |
1562 /* Replace the character at POS in buffer B with CH. */ | |
1563 | |
1564 void | |
867 | 1565 buffer_replace_char (struct buffer *buf, Charbpos pos, Ichar ch, |
428 | 1566 int not_real_change, int force_lock_check) |
1567 { | |
1568 /* This function can GC */ | |
867 | 1569 Ibyte newstr[MAX_ICHAR_LEN]; |
826 | 1570 Bytecount newlen; |
867 | 1571 Ichar oldch; |
428 | 1572 |
1573 /* Defensive steps just in case a buffer gets deleted and a calling | |
1574 function doesn't notice it. */ | |
1575 if (!BUFFER_LIVE_P (buf)) | |
1576 return; | |
1577 | |
867 | 1578 newlen = set_itext_ichar_fmt (newstr, ch, BUF_FORMAT (buf), |
826 | 1579 wrap_buffer (buf)); |
1580 oldch = BUF_FETCH_CHAR (buf, pos); | |
867 | 1581 if (ichar_fits_in_format (ch, BUF_FORMAT (buf), wrap_buffer (buf)) && |
1582 newlen == ichar_len_fmt (oldch, BUF_FORMAT (buf))) | |
428 | 1583 { |
1584 struct buffer *mbuf; | |
1585 Lisp_Object bufcons; | |
1586 | |
1587 /* then we can just replace the text. */ | |
1588 prepare_to_modify_buffer (buf, pos, pos + 1, | |
1589 !not_real_change || force_lock_check); | |
1590 /* Defensive steps in case the before-change-functions fuck around */ | |
1591 if (!BUFFER_LIVE_P (buf)) | |
1592 /* Bad bad pre-change function. */ | |
1593 return; | |
1594 | |
1595 /* Make args be valid again. prepare_to_modify_buffer() might have | |
1596 modified the buffer. */ | |
1597 if (pos < BUF_BEGV (buf)) | |
1598 pos = BUF_BEGV (buf); | |
1599 if (pos >= BUF_ZV (buf)) | |
1600 pos = BUF_ZV (buf) - 1; | |
1601 if (pos < BUF_BEGV (buf)) | |
1602 /* no more characters in buffer! */ | |
1603 return; | |
1604 | |
1605 if (BUF_FETCH_CHAR (buf, pos) == '\n') | |
1606 { | |
1607 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1608 { | |
1609 mbuf->changes->newline_was_deleted = 1; | |
1610 } | |
1611 } | |
1612 MARK_BUFFERS_CHANGED; | |
1613 if (!not_real_change) | |
1614 { | |
1615 MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons) | |
1616 { | |
1617 record_change (mbuf, pos, 1); | |
1618 } | |
1619 BUF_MODIFF (buf)++; | |
1620 } | |
826 | 1621 |
1622 #ifdef MULE | |
867 | 1623 if (ichar_ascii_p (oldch)) |
826 | 1624 buf->text->num_ascii_chars--; |
867 | 1625 if (ichar_8_bit_fixed_p (oldch, wrap_buffer (buf))) |
826 | 1626 buf->text->num_8_bit_fixed_chars--; |
867 | 1627 if (ichar_16_bit_fixed_p (oldch, wrap_buffer (buf))) |
826 | 1628 buf->text->num_16_bit_fixed_chars--; |
867 | 1629 if (ichar_ascii_p (ch)) |
826 | 1630 buf->text->num_ascii_chars++; |
867 | 1631 if (ichar_8_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1632 buf->text->num_8_bit_fixed_chars++; |
867 | 1633 if (ichar_16_bit_fixed_p (ch, wrap_buffer (buf))) |
826 | 1634 buf->text->num_16_bit_fixed_chars++; |
1635 #endif /* MULE */ | |
1636 | |
428 | 1637 memcpy (BUF_BYTE_ADDRESS (buf, pos), newstr, newlen); |
1638 | |
1639 signal_after_change (buf, pos, pos + 1, pos + 1); | |
1640 | |
1641 /* We do not have to adjust the Mule data; we just replaced a | |
1642 character with another of the same number of bytes. */ | |
1643 } | |
1644 else | |
1645 { | |
1646 /* | |
1647 * Must implement as deletion followed by insertion. | |
1648 * | |
1649 * Make a note to move point forward later in the one situation | |
1650 * where it is needed, a delete/insert one position behind | |
1651 * point. Point will drift backward by one position and stay | |
1652 * there otherwise. | |
1653 */ | |
1654 int movepoint = (pos == BUF_PT (buf) - 1); | |
1655 | |
1656 buffer_delete_range (buf, pos, pos + 1, 0); | |
1657 /* Defensive steps in case the before-change-functions fuck around */ | |
1658 if (!BUFFER_LIVE_P (buf)) | |
1659 /* Bad bad pre-change function. */ | |
1660 return; | |
1661 | |
1662 /* Make args be valid again. prepare_to_modify_buffer() might have | |
1663 modified the buffer. */ | |
1664 if (pos < BUF_BEGV (buf)) | |
1665 pos = BUF_BEGV (buf); | |
1666 if (pos >= BUF_ZV (buf)) | |
1667 pos = BUF_ZV (buf) - 1; | |
1668 if (pos < BUF_BEGV (buf)) | |
1669 /* no more characters in buffer! */ | |
1670 return; | |
1671 /* | |
1672 * -1 as the pos argument means to move point forward with the | |
1673 * insertion, which we must do if the deletion moved point | |
1674 * backward so that it now equals the insertion point. | |
1675 */ | |
1676 buffer_insert_string_1 (buf, (movepoint ? -1 : pos), | |
1677 newstr, Qnil, 0, newlen, 0); | |
1678 } | |
1679 } | |
1680 | |
1681 | |
1682 /************************************************************************/ | |
1683 /* Other functions */ | |
1684 /************************************************************************/ | |
1685 | |
1686 /* Make a string from a buffer. This needs to take into account the gap, | |
1687 and add any necessary extents from the buffer. */ | |
1688 | |
1689 static Lisp_Object | |
665 | 1690 make_string_from_buffer_1 (struct buffer *buf, Charbpos pos, Charcount length, |
428 | 1691 int no_extents) |
1692 { | |
1693 /* This function can GC */ | |
826 | 1694 Bytebpos bytepos = charbpos_to_bytebpos (buf, pos); |
1695 Bytecount bytelen = charbpos_to_bytebpos (buf, pos + length) - bytepos; | |
1696 Bytecount needed = copy_buffer_text_out (buf, bytepos, bytelen, NULL, 0, | |
1697 FORMAT_DEFAULT, Qnil, NULL); | |
1698 Lisp_Object val = make_uninit_string (needed); | |
428 | 1699 |
1700 struct gcpro gcpro1; | |
1701 GCPRO1 (val); | |
1702 | |
1703 if (!no_extents) | |
826 | 1704 add_string_extents (val, buf, bytepos, bytelen); |
1705 copy_buffer_text_out (buf, bytepos, bytelen, XSTRING_DATA (val), needed, | |
1706 FORMAT_DEFAULT, Qnil, NULL); | |
771 | 1707 init_string_ascii_begin (val); |
1708 sledgehammer_check_ascii_begin (val); | |
1709 | |
428 | 1710 UNGCPRO; |
1711 return val; | |
1712 } | |
1713 | |
1714 Lisp_Object | |
665 | 1715 make_string_from_buffer (struct buffer *buf, Charbpos pos, Charcount length) |
428 | 1716 { |
1717 return make_string_from_buffer_1 (buf, pos, length, 0); | |
1718 } | |
1719 | |
1720 Lisp_Object | |
665 | 1721 make_string_from_buffer_no_extents (struct buffer *buf, Charbpos pos, |
428 | 1722 Charcount length) |
1723 { | |
1724 return make_string_from_buffer_1 (buf, pos, length, 1); | |
1725 } | |
1726 | |
1727 void | |
665 | 1728 barf_if_buffer_read_only (struct buffer *buf, Charbpos from, Charbpos to) |
428 | 1729 { |
1730 Lisp_Object buffer; | |
1731 Lisp_Object iro; | |
1732 | |
793 | 1733 buffer = wrap_buffer (buf); |
428 | 1734 back: |
1735 iro = (buf == current_buffer ? Vinhibit_read_only : | |
1736 symbol_value_in_buffer (Qinhibit_read_only, buffer)); | |
1737 if (!LISTP (iro)) | |
1738 return; | |
1739 if (NILP (iro) && !NILP (buf->read_only)) | |
1740 { | |
1741 Fsignal (Qbuffer_read_only, (list1 (buffer))); | |
1742 goto back; | |
1743 } | |
1744 if (from > 0) | |
1745 { | |
1746 if (to < 0) | |
1747 to = from; | |
1748 verify_extent_modification (buffer, | |
665 | 1749 charbpos_to_bytebpos (buf, from), |
1750 charbpos_to_bytebpos (buf, to), | |
428 | 1751 iro); |
1752 } | |
1753 } | |
1754 | |
1755 | |
1756 /************************************************************************/ | |
1757 /* initialization */ | |
1758 /************************************************************************/ | |
1759 | |
1760 void | |
1761 reinit_vars_of_insdel (void) | |
1762 { | |
1763 inside_change_hook = 0; | |
1764 in_first_change = 0; | |
1765 } | |
1766 | |
1767 void | |
1768 vars_of_insdel (void) | |
1769 { | |
1770 } | |
1771 | |
1772 void | |
1773 init_buffer_text (struct buffer *b) | |
1774 { | |
1775 if (!b->base_buffer) | |
1776 { | |
1777 SET_BUF_GAP_SIZE (b, 20); | |
1778 BUFFER_ALLOC (b->text->beg, BUF_GAP_SIZE (b) + BUF_END_SENTINEL_SIZE); | |
1779 if (! BUF_BEG_ADDR (b)) | |
1780 memory_full (); | |
1781 | |
1782 SET_BUF_END_GAP_SIZE (b, 0); | |
2367 | 1783 SET_BOTH_BUF_GPT (b, 1, 1); |
428 | 1784 SET_BOTH_BUF_Z (b, 1, 1); |
1785 SET_GAP_SENTINEL (b); | |
1786 SET_END_SENTINEL (b); | |
2367 | 1787 |
428 | 1788 #ifdef MULE |
2367 | 1789 b->text->entirely_one_byte_p = 1; |
428 | 1790 |
2367 | 1791 #ifdef OLD_BYTE_CHAR |
1792 b->text->mule_bufmin = b->text->mule_bufmax = 1; | |
1793 b->text->mule_bytmin = b->text->mule_bytmax = 1; | |
1794 #endif | |
428 | 1795 |
2367 | 1796 b->text->cached_charpos = 1; |
1797 b->text->cached_bytepos = 1; | |
1798 | |
826 | 1799 /* &&#### Set to FORMAT_8_BIT_FIXED when that code is working */ |
1800 BUF_FORMAT (b) = FORMAT_DEFAULT; | |
428 | 1801 #endif /* MULE */ |
1802 b->text->line_number_cache = Qnil; | |
1803 | |
1804 BUF_MODIFF (b) = 1; | |
1805 BUF_SAVE_MODIFF (b) = 1; | |
1806 | |
1807 JUST_SET_POINT (b, 1, 1); | |
1808 SET_BOTH_BUF_BEGV (b, 1, 1); | |
1809 SET_BOTH_BUF_ZV (b, 1, 1); | |
1810 | |
1811 b->text->changes = xnew_and_zero (struct buffer_text_change_data); | |
1812 } | |
1813 else | |
1814 { | |
826 | 1815 JUST_SET_POINT (b, BUF_PT (b->base_buffer), BYTE_BUF_PT (b->base_buffer)); |
428 | 1816 SET_BOTH_BUF_BEGV (b, BUF_BEGV (b->base_buffer), |
826 | 1817 BYTE_BUF_BEGV (b->base_buffer)); |
428 | 1818 SET_BOTH_BUF_ZV (b, BUF_ZV (b->base_buffer), |
826 | 1819 BYTE_BUF_ZV (b->base_buffer)); |
428 | 1820 } |
1821 | |
1822 b->changes = xnew_and_zero (struct each_buffer_change_data); | |
1823 BUF_FACECHANGE (b) = 1; | |
1824 | |
1825 #ifdef REGION_CACHE_NEEDS_WORK | |
1826 b->newline_cache = 0; | |
1827 b->width_run_cache = 0; | |
1828 b->width_table = Qnil; | |
1829 #endif | |
1830 } | |
1831 | |
1832 void | |
1833 uninit_buffer_text (struct buffer *b) | |
1834 { | |
1835 if (!b->base_buffer) | |
1836 { | |
1837 BUFFER_FREE (b->text->beg); | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1838 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
|
1839 b->text->changes = 0; |
428 | 1840 } |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1841 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
|
1842 b->changes = 0; |
428 | 1843 |
1844 #ifdef REGION_CACHE_NEEDS_WORK | |
1845 if (b->newline_cache) | |
1846 { | |
1847 free_region_cache (b->newline_cache); | |
1848 b->newline_cache = 0; | |
1849 } | |
1850 if (b->width_run_cache) | |
1851 { | |
1852 free_region_cache (b->width_run_cache); | |
1853 b->width_run_cache = 0; | |
1854 } | |
1855 b->width_table = Qnil; | |
1856 #endif | |
1857 } |