Mercurial > hg > xemacs-beta
annotate src/insdel.c @ 5159:cb303ff63e76
merge
| author | Ben Wing <ben@xemacs.org> |
|---|---|
| date | Fri, 19 Mar 2010 17:02:11 -0500 |
| parents | 6f2158fa75ed |
| 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 } |
