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