insdel.c 42.2 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Buffer insertion/deletion and gap motion for GNU Emacs.
2
   Copyright (C) 1985, 86, 93, 94, 95, 1997 Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
3 4 5 6 7

This file is part of GNU Emacs.

GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Karl Heuer's avatar
Karl Heuer committed
8
the Free Software Foundation; either version 2, or (at your option)
Jim Blandy's avatar
Jim Blandy committed
9 10 11 12 13 14 15 16 17
any later version.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
18 19
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */
Jim Blandy's avatar
Jim Blandy committed
20 21


22
#include <config.h>
Jim Blandy's avatar
Jim Blandy committed
23
#include "lisp.h"
24
#include "intervals.h"
Jim Blandy's avatar
Jim Blandy committed
25
#include "buffer.h"
Karl Heuer's avatar
Karl Heuer committed
26
#include "charset.h"
Jim Blandy's avatar
Jim Blandy committed
27
#include "window.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
28
#include "blockinput.h"
Jim Blandy's avatar
Jim Blandy committed
29

30 31 32 33
#ifndef NULL
#define NULL 0
#endif

34 35
#define min(x, y) ((x) < (y) ? (x) : (y))

36
static void insert_from_string_1 P_ ((Lisp_Object, int, int, int, int, int));
37
static void insert_from_buffer_1 ();
38 39 40 41 42 43
static void gap_left P_ ((int, int, int));
static void gap_right P_ ((int, int));
static void adjust_markers_gap_motion P_ ((int, int, int));
static void adjust_markers_for_insert P_ ((int, int, int, int, int));
static void adjust_markers_for_delete P_ ((int, int, int, int));
static void adjust_point P_ ((int, int));
44

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
Lisp_Object Fcombine_after_change_execute ();

/* Non-nil means don't call the after-change-functions right away,
   just record an element in Vcombine_after_change_calls_list.  */
Lisp_Object Vcombine_after_change_calls;

/* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
   describing changes which happened while combine_after_change_calls
   was nonzero.  We use this to decide how to call them
   once the deferral ends.

   In each element.
   BEG-UNCHANGED is the number of chars before the changed range.
   END-UNCHANGED is the number of chars after the changed range,
   and CHANGE-AMOUNT is the number of characters inserted by the change
   (negative for a deletion).  */
Lisp_Object combine_after_change_list;

/* Buffer which combine_after_change_list is about.  */
Lisp_Object combine_after_change_buffer;

66
/* Move gap to position CHARPOS.
Jim Blandy's avatar
Jim Blandy committed
67 68
   Note that this can quit!  */

69
void
70 71
move_gap (charpos)
     int charpos;
Jim Blandy's avatar
Jim Blandy committed
72
{
73
  move_gap_both (charpos, charpos_to_bytepos (charpos));
Jim Blandy's avatar
Jim Blandy committed
74 75
}

76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
/* Move gap to byte position BYTEPOS, which is also char position CHARPOS.
   Note that this can quit!  */

void
move_gap_both (charpos, bytepos)
     int charpos, bytepos;
{
  if (bytepos < GPT_BYTE)
    gap_left (charpos, bytepos, 0);
  else if (bytepos > GPT_BYTE)
    gap_right (charpos, bytepos);
}

/* Move the gap to a position less than the current GPT.
   BYTEPOS describes the new position as a byte position,
   and CHARPOS is the corresponding char position.
Jim Blandy's avatar
Jim Blandy committed
92 93
   If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged.  */

Karl Heuer's avatar
Karl Heuer committed
94
static void
95 96
gap_left (charpos, bytepos, newgap)
     register int charpos, bytepos;
Jim Blandy's avatar
Jim Blandy committed
97 98 99 100 101 102 103 104
     int newgap;
{
  register unsigned char *to, *from;
  register int i;
  int new_s1;

  if (!newgap)
    {
105 106
      if (unchanged_modified == MODIFF
	  && overlay_unchanged_modified == OVERLAY_MODIFF)
Jim Blandy's avatar
Jim Blandy committed
107
	{
108 109
	  beg_unchanged = charpos - BEG;
	  end_unchanged = Z - charpos;
Jim Blandy's avatar
Jim Blandy committed
110 111 112 113 114
	}
      else
	{
	  if (Z - GPT < end_unchanged)
	    end_unchanged = Z - GPT;
115 116
	  if (charpos < beg_unchanged)
	    beg_unchanged = charpos - BEG;
Jim Blandy's avatar
Jim Blandy committed
117 118 119
	}
    }

120
  i = GPT_BYTE;
Jim Blandy's avatar
Jim Blandy committed
121 122
  to = GAP_END_ADDR;
  from = GPT_ADDR;
123
  new_s1 = GPT_BYTE;
Jim Blandy's avatar
Jim Blandy committed
124 125 126 127 128 129 130

  /* Now copy the characters.  To move the gap down,
     copy characters up.  */

  while (1)
    {
      /* I gets number of characters left to copy.  */
131
      i = new_s1 - bytepos;
Jim Blandy's avatar
Jim Blandy committed
132 133 134
      if (i == 0)
	break;
      /* If a quit is requested, stop copying now.
135
	 Change BYTEPOS to be where we have actually moved the gap to.  */
Jim Blandy's avatar
Jim Blandy committed
136 137
      if (QUITP)
	{
138 139
	  bytepos = new_s1;
	  charpos = BYTE_TO_CHAR (bytepos);
Jim Blandy's avatar
Jim Blandy committed
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
	  break;
	}
      /* Move at most 32000 chars before checking again for a quit.  */
      if (i > 32000)
	i = 32000;
#ifdef GAP_USE_BCOPY
      if (i >= 128
	  /* bcopy is safe if the two areas of memory do not overlap
	     or on systems where bcopy is always safe for moving upward.  */
	  && (BCOPY_UPWARD_SAFE
	      || to - from >= 128))
	{
	  /* If overlap is not safe, avoid it by not moving too many
	     characters at once.  */
	  if (!BCOPY_UPWARD_SAFE && i > to - from)
	    i = to - from;
	  new_s1 -= i;
	  from -= i, to -= i;
	  bcopy (from, to, i);
	}
      else
#endif
	{
	  new_s1 -= i;
	  while (--i >= 0)
	    *--to = *--from;
	}
    }

169 170
  /* Adjust markers, and buffer data structure, to put the gap at BYTEPOS.
     BYTEPOS is where the loop above stopped, which may be what was specified
Jim Blandy's avatar
Jim Blandy committed
171
     or may be where a quit was detected.  */
172 173 174 175 176
  adjust_markers_gap_motion (bytepos, GPT_BYTE, GAP_SIZE);
  GPT_BYTE = bytepos;
  GPT = charpos;
  if (bytepos < charpos)
    abort ();
Karl Heuer's avatar
Karl Heuer committed
177
  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
Jim Blandy's avatar
Jim Blandy committed
178 179 180
  QUIT;
}

181 182 183 184
/* Move the gap to a position greater than than the current GPT.
   BYTEPOS describes the new position as a byte position,
   and CHARPOS is the corresponding char position.  */

Karl Heuer's avatar
Karl Heuer committed
185
static void
186 187
gap_right (charpos, bytepos)
     register int charpos, bytepos;
Jim Blandy's avatar
Jim Blandy committed
188 189 190 191 192
{
  register unsigned char *to, *from;
  register int i;
  int new_s1;

193 194
  if (unchanged_modified == MODIFF
      && overlay_unchanged_modified == OVERLAY_MODIFF)
Jim Blandy's avatar
Jim Blandy committed
195
    {
196 197
      beg_unchanged = charpos - BEG;
      end_unchanged = Z - charpos;
Jim Blandy's avatar
Jim Blandy committed
198 199 200
    }
  else
    {
201 202
      if (Z - charpos - 1 < end_unchanged)
	end_unchanged = Z - charpos;
Jim Blandy's avatar
Jim Blandy committed
203 204 205 206
      if (GPT - BEG < beg_unchanged)
	beg_unchanged = GPT - BEG;
    }

207
  i = GPT_BYTE;
Jim Blandy's avatar
Jim Blandy committed
208 209
  from = GAP_END_ADDR;
  to = GPT_ADDR;
210
  new_s1 = GPT_BYTE;
Jim Blandy's avatar
Jim Blandy committed
211 212 213 214 215 216 217

  /* Now copy the characters.  To move the gap up,
     copy characters down.  */

  while (1)
    {
      /* I gets number of characters left to copy.  */
218
      i = bytepos - new_s1;
Jim Blandy's avatar
Jim Blandy committed
219 220 221
      if (i == 0)
	break;
      /* If a quit is requested, stop copying now.
222
	 Change BYTEPOS to be where we have actually moved the gap to.  */
Jim Blandy's avatar
Jim Blandy committed
223 224
      if (QUITP)
	{
225 226
	  bytepos = new_s1;
	  charpos = BYTE_TO_CHAR (bytepos);
Jim Blandy's avatar
Jim Blandy committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
	  break;
	}
      /* Move at most 32000 chars before checking again for a quit.  */
      if (i > 32000)
	i = 32000;
#ifdef GAP_USE_BCOPY
      if (i >= 128
	  /* bcopy is safe if the two areas of memory do not overlap
	     or on systems where bcopy is always safe for moving downward.  */
	  && (BCOPY_DOWNWARD_SAFE
	      || from - to >= 128))
	{
	  /* If overlap is not safe, avoid it by not moving too many
	     characters at once.  */
	  if (!BCOPY_DOWNWARD_SAFE && i > from - to)
	    i = from - to;
	  new_s1 += i;
	  bcopy (from, to, i);
	  from += i, to += i;
	}
      else
#endif
	{
	  new_s1 += i;
	  while (--i >= 0)
	    *to++ = *from++;
	}
    }

256 257 258 259 260 261
  adjust_markers_gap_motion (GPT_BYTE + GAP_SIZE, bytepos + GAP_SIZE,
			     - GAP_SIZE);
  GPT = charpos;
  GPT_BYTE = bytepos;
  if (bytepos < charpos)
    abort ();
Karl Heuer's avatar
Karl Heuer committed
262
  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
Jim Blandy's avatar
Jim Blandy committed
263 264 265
  QUIT;
}

266 267
/* Add AMOUNT to the byte position of every marker in the current buffer
   whose current byte position is between FROM (exclusive) and TO (inclusive).
268

Jim Blandy's avatar
Jim Blandy committed
269 270
   Also, any markers past the outside of that interval, in the direction
   of adjustment, are first moved back to the near end of the interval
271 272 273 274
   and then adjusted by AMOUNT.

   When the latter adjustment is done, if AMOUNT is negative,
   we record the adjustment for undo.  (This case happens only for
275 276 277 278 279 280
   deletion.)

   The markers' character positions are not altered,
   because gap motion does not affect character positions.  */

int adjust_markers_test;
Jim Blandy's avatar
Jim Blandy committed
281

Karl Heuer's avatar
Karl Heuer committed
282
static void
283
adjust_markers_gap_motion (from, to, amount)
Jim Blandy's avatar
Jim Blandy committed
284 285 286 287 288 289
     register int from, to, amount;
{
  Lisp_Object marker;
  register struct Lisp_Marker *m;
  register int mpos;

290
  marker = BUF_MARKERS (current_buffer);
Jim Blandy's avatar
Jim Blandy committed
291

Jim Blandy's avatar
Jim Blandy committed
292
  while (!NILP (marker))
Jim Blandy's avatar
Jim Blandy committed
293 294 295 296 297 298
    {
      m = XMARKER (marker);
      mpos = m->bufpos;
      if (amount > 0)
	{
	  if (mpos > to && mpos < to + amount)
299 300 301 302 303
	    {
	      if (adjust_markers_test)
		abort ();
	      mpos = to + amount;
	    }
Jim Blandy's avatar
Jim Blandy committed
304 305 306
	}
      else
	{
307 308 309
	  /* Here's the case where a marker is inside text being deleted.
	     AMOUNT can be negative for gap motion, too,
	     but then this range contains no markers.  */
Jim Blandy's avatar
Jim Blandy committed
310
	  if (mpos > from + amount && mpos <= from)
311
	    {
312 313 314
	      if (adjust_markers_test)
		abort ();
	      mpos = from + amount;
315
	    }
Jim Blandy's avatar
Jim Blandy committed
316 317 318 319 320 321 322
	}
      if (mpos > from && mpos <= to)
	mpos += amount;
      m->bufpos = mpos;
      marker = m->chain;
    }
}
Karl Heuer's avatar
Karl Heuer committed
323

324 325 326 327 328 329
/* Adjust all markers for a deletion
   whose range in bytes is FROM_BYTE to TO_BYTE.
   The range in charpos is FROM to TO.

   This function assumes that the gap is adjacent to
   or inside of the range being deleted.  */
330 331

static void
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
adjust_markers_for_delete (from, from_byte, to, to_byte)
     register int from, from_byte, to, to_byte;
{
  Lisp_Object marker;
  register struct Lisp_Marker *m;
  register int charpos;
  /* This is what GAP_SIZE will be when this deletion is finished.  */
  int coming_gap_size = GAP_SIZE + to_byte - from_byte;

  marker = BUF_MARKERS (current_buffer);

  while (!NILP (marker))
    {
      m = XMARKER (marker);
      charpos = m->charpos;

      if (charpos > Z)
	abort ();

      /* If the marker is after the deletion,
	 its bufpos needs no change because the deleted text
	 becomes gap; but its charpos needs to be decreased.  */
      if (charpos > to)
	m->charpos -= to - from;

      /* Here's the case where a marker is inside text being deleted.
	 We take advantage of the fact that the deletion is at the gap.  */
      else if (charpos > from)
	{
	  record_marker_adjustment (marker, from - charpos);
	  m->charpos = from;
	  /* The gap must be at or after FROM_BYTE when we do a deletion.  */
	  m->bufpos = from_byte;
	}

      /* In a single-byte buffer, a marker's two positions must be equal.  */
      if (Z == Z_BYTE)
	{
	  register int i = m->bufpos;

	  /* We use FROM_BYTE here instead of GPT_BYTE
	     because FROM_BYTE is where the gap will be after the deletion.  */
	  if (i > from_byte + coming_gap_size)
	    i -= coming_gap_size;
	  else if (i > from_byte)
	    i = from_byte;

	  if (m->charpos != i)
	    abort ();
	}

      marker = m->chain;
    }
}

/* Adjust markers for an insertion at CHARPOS / BYTEPOS
   consisting of NCHARS chars, which are NBYTES bytes.

   We have to relocate the charpos of every marker that points
   after the insertion (but not their bufpos).

   When a marker points at the insertion point,
   we advance it if either its insertion-type is t
   or BEFORE_MARKERS is true.  */

static void
adjust_markers_for_insert (from, from_byte, to, to_byte, before_markers)
     register int from, from_byte, to, to_byte, before_markers;
400 401
{
  Lisp_Object marker;
Karl Heuer's avatar
Karl Heuer committed
402
  int adjusted = 0;
403 404
  int nchars = to - from;
  int nbytes = to_byte - from_byte;
405 406 407 408 409 410

  marker = BUF_MARKERS (current_buffer);

  while (!NILP (marker))
    {
      register struct Lisp_Marker *m = XMARKER (marker);
411 412
      if (m->bufpos == from_byte
	  && (m->insertion_type || before_markers))
Karl Heuer's avatar
Karl Heuer committed
413
	{
414 415 416 417
	  m->bufpos += nbytes;
	  m->charpos += nchars;
	  if (m->insertion_type)
	    adjusted = 1;
Karl Heuer's avatar
Karl Heuer committed
418
	}
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
      else if (m->bufpos > from_byte)
	m->charpos += nchars;

      /* In a single-byte buffer, a marker's two positions must be equal.  */
      if (Z == Z_BYTE)
	{
	  register int i = m->bufpos;

	  if (i > GPT_BYTE + GAP_SIZE)
	    i -= GAP_SIZE;
	  else if (i > GPT_BYTE)
	    i = GPT_BYTE;

	  if (m->charpos != i)
	    abort ();
	}

436 437
      marker = m->chain;
    }
438 439 440

  /* Adjusting only markers whose insertion-type is t may result in
     disordered overlays in the slot `overlays_before'.  */
Karl Heuer's avatar
Karl Heuer committed
441
  if (adjusted)
442
    fix_overlays_before (current_buffer, from, to);
443 444
}

445 446 447 448 449 450 451 452 453 454
/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.

   This is used only when the value of point changes due to an insert
   or delete; it does not represent a conceptual change in point as a
   marker.  In particular, point is not crossing any interval
   boundaries, so there's no need to use the usual SET_PT macro.  In
   fact it would be incorrect to do so, because either the old or the
   new value of point is out of sync with the current set of
   intervals.  */

Karl Heuer's avatar
Karl Heuer committed
455
static void
456 457
adjust_point (nchars, nbytes)
     int nchars, nbytes;
Karl Heuer's avatar
Karl Heuer committed
458
{
459 460 461 462 463 464 465
  BUF_PT (current_buffer) += nchars;
  BUF_PT_BYTE (current_buffer) += nbytes;

  /* In a single-byte buffer, the two positions must be equal.  */
  if (ZV == ZV_BYTE
      && PT != PT_BYTE)
    abort ();
Karl Heuer's avatar
Karl Heuer committed
466
}
Jim Blandy's avatar
Jim Blandy committed
467

468
/* Make the gap NBYTES_ADDED bytes longer.  */
Jim Blandy's avatar
Jim Blandy committed
469

470
void
471 472
make_gap (nbytes_added)
     int nbytes_added;
Jim Blandy's avatar
Jim Blandy committed
473 474 475 476
{
  unsigned char *result;
  Lisp_Object tem;
  int real_gap_loc;
477
  int real_gap_loc_byte;
Jim Blandy's avatar
Jim Blandy committed
478 479 480
  int old_gap_size;

  /* If we have to get more space, get enough to last a while.  */
481
  nbytes_added += 2000;
Jim Blandy's avatar
Jim Blandy committed
482

483 484 485 486
  /* Don't allow a buffer size that won't fit in an int
     even if it will fit in a Lisp integer.
     That won't work because so many places use `int'.  */
     
487
  if (Z_BYTE - BEG_BYTE + GAP_SIZE + nbytes_added
488
      >= ((unsigned) 1 << (min (BITS_PER_INT, VALBITS) - 1)))
489
    error ("Buffer exceeds maximum size");
490

491
  BLOCK_INPUT;
Karl Heuer's avatar
Karl Heuer committed
492
  /* We allocate extra 1-byte `\0' at the tail for anchoring a search.  */
493 494
  result = BUFFER_REALLOC (BEG_ADDR, (Z_BYTE - BEG_BYTE
				      + GAP_SIZE + nbytes_added + 1));
495

Jim Blandy's avatar
Jim Blandy committed
496
  if (result == 0)
497 498 499 500 501 502
    {
      UNBLOCK_INPUT;
      memory_full ();
    }

  /* We can't unblock until the new address is properly stored.  */
Jim Blandy's avatar
Jim Blandy committed
503
  BEG_ADDR = result;
504
  UNBLOCK_INPUT;
Jim Blandy's avatar
Jim Blandy committed
505 506 507 508 509 510

  /* Prevent quitting in move_gap.  */
  tem = Vinhibit_quit;
  Vinhibit_quit = Qt;

  real_gap_loc = GPT;
511
  real_gap_loc_byte = GPT_BYTE;
Jim Blandy's avatar
Jim Blandy committed
512 513 514 515
  old_gap_size = GAP_SIZE;

  /* Call the newly allocated space a gap at the end of the whole space.  */
  GPT = Z + GAP_SIZE;
516
  GAP_SIZE = nbytes_added;
Jim Blandy's avatar
Jim Blandy committed
517 518 519

  /* Move the new gap down to be consecutive with the end of the old one.
     This adjusts the markers properly too.  */
520
  gap_left (real_gap_loc + old_gap_size, real_gap_loc_byte + old_gap_size, 1);
Jim Blandy's avatar
Jim Blandy committed
521 522 523 524

  /* Now combine the two into one large gap.  */
  GAP_SIZE += old_gap_size;
  GPT = real_gap_loc;
525
  GPT_BYTE = real_gap_loc_byte;
Jim Blandy's avatar
Jim Blandy committed
526

Karl Heuer's avatar
Karl Heuer committed
527 528 529
  /* Put an anchor.  */
  *(Z_ADDR) = 0;

Jim Blandy's avatar
Jim Blandy committed
530 531 532 533
  Vinhibit_quit = tem;
}

/* Insert a string of specified length before point.
534 535
   DO NOT use this for the contents of a Lisp string or a Lisp buffer!
   prepare_to_modify_buffer could relocate the text.  */
Jim Blandy's avatar
Jim Blandy committed
536

537
void
538
insert (string, nbytes)
Jim Blandy's avatar
Jim Blandy committed
539
     register unsigned char *string;
540
     register nbytes;
Jim Blandy's avatar
Jim Blandy committed
541
{
542
  if (nbytes > 0)
543
    {
544 545 546
      int opoint = PT;
      insert_1 (string, nbytes, 0, 1, 0);
      signal_after_change (opoint, 0, PT - opoint);
547 548 549
    }
}

550
void
551
insert_and_inherit (string, nbytes)
552
     register unsigned char *string;
553
     register nbytes;
554
{
555
  if (nbytes > 0)
556
    {
557 558 559
      int opoint = PT;
      insert_1 (string, nbytes, 1, 1, 0);
      signal_after_change (opoint, 0, PT - opoint);
560 561
    }
}
Jim Blandy's avatar
Jim Blandy committed
562

563 564
/* Insert the character C before point */

565
void
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
insert_char (c)
     int c;
{
  unsigned char workbuf[4], *str;
  int len = CHAR_STRING (c, workbuf, str);

  insert (str, len);
}

/* Insert the null-terminated string S before point */

void
insert_string (s)
     char *s;
{
  insert (s, strlen (s));
}

/* Like `insert' except that all markers pointing at the place where
   the insertion happens are adjusted to point after it.
   Don't use this function to insert part of a Lisp string,
   since gc could happen and relocate it.  */

void
insert_before_markers (string, nbytes)
     unsigned char *string;
     register int nbytes;
{
  if (nbytes > 0)
    {
      int opoint = PT;

      insert_1 (string, nbytes, 0, 1, 1);
      signal_after_change (opoint, 0, PT - opoint);
    }
}

void
insert_before_markers_and_inherit (string, nbytes)
     unsigned char *string;
     register int nbytes;
{
  if (nbytes > 0)
    {
      int opoint = PT;

      insert_1 (string, nbytes, 1, 1, 1);
      signal_after_change (opoint, 0, PT - opoint);
    }
}

/* Subroutine used by the insert functions above.  */

void
insert_1 (string, nbytes, inherit, prepare, before_markers)
621
     register unsigned char *string;
622 623
     register int nbytes;
     int inherit, prepare, before_markers;
624 625
{
  register Lisp_Object temp;
626
  int nchars = chars_in_text (string, nbytes);
Jim Blandy's avatar
Jim Blandy committed
627

628
  if (prepare)
629
    prepare_to_modify_buffer (PT, PT, NULL);
Jim Blandy's avatar
Jim Blandy committed
630

Karl Heuer's avatar
Karl Heuer committed
631
  if (PT != GPT)
632 633 634
    move_gap_both (PT, PT_BYTE);
  if (GAP_SIZE < nbytes)
    make_gap (nbytes - GAP_SIZE);
Jim Blandy's avatar
Jim Blandy committed
635

636
  record_insert (PT, nchars);
Jim Blandy's avatar
Jim Blandy committed
637 638
  MODIFF++;

639
  bcopy (string, GPT_ADDR, nbytes);
Jim Blandy's avatar
Jim Blandy committed
640

641
#ifdef USE_TEXT_PROPERTIES
642
  if (BUF_INTERVALS (current_buffer) != 0)
643
    /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES.  */
644
    offset_intervals (current_buffer, PT, nchars);
645
#endif
646

647 648 649 650 651 652 653
  GAP_SIZE -= nbytes;
  GPT += nchars;
  ZV += nchars;
  Z += nchars;
  GPT_BYTE += nbytes;
  ZV_BYTE += nbytes;
  Z_BYTE += nbytes;
Karl Heuer's avatar
Karl Heuer committed
654
  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
655 656 657 658 659 660 661
  adjust_overlays_for_insert (PT, nchars);
  adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + nbytes,
			     before_markers);
  adjust_point (nchars, nbytes);

  if (GPT_BYTE < GPT)
    abort ();
662

663
#ifdef USE_TEXT_PROPERTIES
664
  if (!inherit && BUF_INTERVALS (current_buffer) != 0)
665
    Fset_text_properties (make_number (PT - nchars), make_number (PT),
666
			  Qnil, Qnil);
667
#endif
Jim Blandy's avatar
Jim Blandy committed
668
}
669

670 671 672 673 674 675
/* Insert the part of the text of STRING, a Lisp object assumed to be
   of type string, consisting of the LENGTH characters starting at
   position POS.  If the text of STRING has properties, they are absorbed
   into the buffer.

   It does not work to use `insert' for this, because a GC could happen
Jim Blandy's avatar
Jim Blandy committed
676 677
   before we bcopy the stuff into the buffer, and relocate the string
   without insert noticing.  */
678

679
void
680
insert_from_string (string, pos, length, inherit)
Jim Blandy's avatar
Jim Blandy committed
681 682
     Lisp_Object string;
     register int pos, length;
683
     int inherit;
684 685 686
{
  if (length > 0)
    {
687 688 689 690
      int opoint = PT;
      int nchars = chars_in_text (XSTRING (string)->data + pos, length);
      insert_from_string_1 (string, pos, length, nchars, inherit, 0);
      signal_after_change (opoint, 0, PT - opoint);
691 692 693
    }
}

694 695 696 697 698 699 700 701 702
/* Like `insert' except that all markers pointing at the place where
   the insertion happens are adjusted to point after it.
   Don't use this function to insert part of a Lisp string,
   since gc could happen and relocate it.  */

/* Insert part of a Lisp string, relocating markers after.  */

void
insert_from_string_before_markers (string, pos, length, inherit)
703 704 705
     Lisp_Object string;
     register int pos, length;
     int inherit;
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
{
  if (length > 0)
    {
      int opoint = PT;
      int nchars = chars_in_text (XSTRING (string)->data + pos, length);
      insert_from_string_1 (string, pos, length, nchars, inherit, 1);
      signal_after_change (opoint, 0, PT - opoint);
    }
}

/* Subroutine of the insertion functions above.  */

static void
insert_from_string_1 (string, pos, nbytes, nchars, inherit, before_markers)
     Lisp_Object string;
     register int pos, nbytes, nchars;
     int inherit, before_markers;
Jim Blandy's avatar
Jim Blandy committed
723 724 725 726 727
{
  register Lisp_Object temp;
  struct gcpro gcpro1;

  /* Make sure point-max won't overflow after this insertion.  */
728 729 730
  XSETINT (temp, nbytes + Z_BYTE);
  if (nbytes + Z_BYTE != XINT (temp))
    error ("Maximum buffer size exceeded");
Jim Blandy's avatar
Jim Blandy committed
731 732

  GCPRO1 (string);
733
  prepare_to_modify_buffer (PT, PT, NULL);
Jim Blandy's avatar
Jim Blandy committed
734

Karl Heuer's avatar
Karl Heuer committed
735
  if (PT != GPT)
736 737 738
    move_gap_both (PT, PT_BYTE);
  if (GAP_SIZE < nbytes)
    make_gap (nbytes - GAP_SIZE);
Jim Blandy's avatar
Jim Blandy committed
739

740
  record_insert (PT, nchars);
Jim Blandy's avatar
Jim Blandy committed
741 742 743
  MODIFF++;
  UNGCPRO;

744
  bcopy (XSTRING (string)->data, GPT_ADDR, nbytes);
Jim Blandy's avatar
Jim Blandy committed
745

746
  /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
747 748 749 750 751 752 753 754 755
  offset_intervals (current_buffer, PT, nchars);

  GAP_SIZE -= nbytes;
  GPT += nchars;
  ZV += nchars;
  Z += nchars;
  GPT_BYTE += nbytes;
  ZV_BYTE += nbytes;
  Z_BYTE += nbytes;
Karl Heuer's avatar
Karl Heuer committed
756
  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
757 758 759 760 761 762
  adjust_overlays_for_insert (PT, nchars);
  adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + nbytes,
			     before_markers);

  if (GPT_BYTE < GPT)
    abort ();
763 764

  /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
765
  graft_intervals_into_buffer (XSTRING (string)->intervals, PT, nchars,
766
			       current_buffer, inherit);
767

768
  adjust_point (nchars, nbytes);
Jim Blandy's avatar
Jim Blandy committed
769
}
770 771

/* Insert text from BUF, NCHARS characters starting at CHARPOS, into the
772 773 774 775 776 777 778
   current buffer.  If the text in BUF has properties, they are absorbed
   into the current buffer.

   It does not work to use `insert' for this, because a malloc could happen
   and relocate BUF's text before the bcopy happens.  */

void
779
insert_from_buffer (buf, charpos, nchars, inherit)
780
     struct buffer *buf;
781
     int charpos, nchars;
782 783
     int inherit;
{
784
  if (nchars > 0)
785
    {
786 787 788 789
      int opoint = PT;

      insert_from_buffer_1 (buf, charpos, nchars, inherit);
      signal_after_change (opoint, 0, PT - opoint);
790 791 792 793
    }
}

static void
794
insert_from_buffer_1 (buf, from, nchars, inherit)
795
     struct buffer *buf;
796
     int from, nchars;
797 798 799 800
     int inherit;
{
  register Lisp_Object temp;
  int chunk;
801 802 803
  int from_byte = buf_charpos_to_bytepos (buf, from);
  int to_byte = buf_charpos_to_bytepos (buf, from + nchars);
  int nbytes = to_byte - from_byte;
804 805

  /* Make sure point-max won't overflow after this insertion.  */
806 807 808
  XSETINT (temp, nbytes + Z);
  if (nbytes + Z != XINT (temp))
    error ("Maximum buffer size exceeded");
809

810
  prepare_to_modify_buffer (PT, PT, NULL);
811 812

  if (PT != GPT)
813 814 815
    move_gap_both (PT, PT_BYTE);
  if (GAP_SIZE < nbytes)
    make_gap (nbytes - GAP_SIZE);
816

817
  record_insert (PT, nchars);
818 819
  MODIFF++;

820
  if (from < BUF_GPT (buf))
821
    {
822 823 824 825
      chunk = BUF_GPT_BYTE (buf) - from_byte;
      if (chunk > nbytes)
	chunk = nbytes;
      bcopy (BUF_BYTE_ADDRESS (buf, from_byte), GPT_ADDR, chunk);
826 827 828
    }
  else
    chunk = 0;
829 830 831
  if (chunk < nbytes)
    bcopy (BUF_BYTE_ADDRESS (buf, from_byte + chunk),
	   GPT_ADDR + chunk, nbytes - chunk);
832 833

#ifdef USE_TEXT_PROPERTIES
834
  if (BUF_INTERVALS (current_buffer) != 0)
835
    offset_intervals (current_buffer, PT, nchars);
836 837
#endif

838 839 840 841 842 843 844
  GAP_SIZE -= nbytes;
  GPT += nchars;
  ZV += nchars;
  Z += nchars;
  GPT_BYTE += nbytes;
  ZV_BYTE += nbytes;
  Z_BYTE += nbytes;
Karl Heuer's avatar
Karl Heuer committed
845
  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */
846 847 848 849 850 851
  adjust_overlays_for_insert (PT, nchars);
  adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + nbytes, 0);
  adjust_point (nchars, nbytes);

  if (GPT_BYTE < GPT)
    abort ();
852 853

  /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
854
  graft_intervals_into_buffer (copy_intervals (BUF_INTERVALS (buf),
855 856 857
					       from, nchars),
			       PT - nchars, nchars,
			       current_buffer, inherit);
Jim Blandy's avatar
Jim Blandy committed
858 859
}

860
/* Replace the text from character positions FROM to TO with NEW,
861 862 863 864 865 866 867 868 869 870 871 872 873 874
   If PREPARE is nonzero, call prepare_to_modify_buffer.
   If INHERIT, the newly inserted text should inherit text properties
   from the surrounding non-deleted text.  */

/* Note that this does not yet handle markers quite right.
   Also it needs to record a single undo-entry that does a replacement
   rather than a separate delete and insert.
   That way, undo will also handle markers properly.  */

void
replace_range (from, to, new, prepare, inherit)
     Lisp_Object new;
     int from, to, prepare, inherit;
{
875 876 877 878
  int insbytes = XSTRING (new)->size;
  int inschars;
  int from_byte, to_byte;
  int nbytes_del, nchars_del;
879 880 881 882 883 884 885 886 887 888 889 890
  register Lisp_Object temp;
  struct gcpro gcpro1;

  GCPRO1 (new);

  if (prepare)
    {
      int range_length = to - from;
      prepare_to_modify_buffer (from, to, &from);
      to = from + range_length;
    }

891 892
  UNGCPRO;

893 894 895 896 897 898
  /* Make args be valid */
  if (from < BEGV)
    from = BEGV;
  if (to > ZV)
    to = ZV;

899 900
  from_byte = CHAR_TO_BYTE (from);
  to_byte = CHAR_TO_BYTE (to);
901

902 903 904 905 906
  nchars_del = to - from;
  nbytes_del = to_byte - from_byte;

  if (nbytes_del <= 0 && insbytes == 0)
    return;
907 908

  /* Make sure point-max won't overflow after this insertion.  */
909 910 911
  XSETINT (temp, Z_BYTE - nbytes_del + insbytes);
  if (Z_BYTE - nbytes_del + insbytes != XINT (temp))
    error ("Maximum buffer size exceeded");
912

913
  inschars = XINT (Fchars_in_string (new));
914 915 916 917 918

  GCPRO1 (new);

  /* Make sure the gap is somewhere in or next to what we are deleting.  */
  if (from > GPT)
919
    gap_right (from, from_byte);
920
  if (to < GPT)
921
    gap_left (to, to_byte, 0);
922 923 924

  /* Relocate all markers pointing into the new, larger gap
     to point at the end of the text before the gap.
925 926 927
     Do this before recording the deletion,
     so that undo handles this after reinserting the text.  */
  adjust_markers_for_delete (from, from_byte, to, to_byte);
928

929
  record_delete (from, nchars_del);
930

931 932 933 934 935
  GAP_SIZE += nbytes_del;
  ZV -= nchars_del;
  Z -= nchars_del;
  ZV_BYTE -= nbytes_del;
  Z_BYTE -= nbytes_del;
936
  GPT = from;
937
  GPT_BYTE = from_byte;
938 939
  *(GPT_ADDR) = 0;		/* Put an anchor.  */

940 941 942
  if (GPT_BYTE < GPT)
    abort ();

943 944 945 946 947
  if (GPT - BEG < beg_unchanged)
    beg_unchanged = GPT - BEG;
  if (Z - GPT < end_unchanged)
    end_unchanged = Z - GPT;

948 949
  if (GAP_SIZE < insbytes)
    make_gap (insbytes - GAP_SIZE);
950

951
  record_insert (from, inschars);
952

953
  bcopy (XSTRING (new)->data, GPT_ADDR, insbytes);
954 955 956

  /* Relocate point as if it were a marker.  */
  if (from < PT)
957 958 959
    adjust_point (from + inschars - (PT < to ? PT : to),
		  (from_byte + insbytes
		   - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
960 961

#ifdef USE_TEXT_PROPERTIES
962
  offset_intervals (current_buffer, PT, inschars - nchars_del);
963 964
#endif

965 966 967 968 969 970 971
  GAP_SIZE -= insbytes;
  GPT += inschars;
  ZV += inschars;
  Z += inschars;
  GPT_BYTE += insbytes;
  ZV_BYTE += insbytes;
  ZV_BYTE += insbytes;
972 973
  if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor.  */

974 975 976
  if (GPT_BYTE < GPT)
    abort ();

977 978
  /* Adjust the overlay center as needed.  This must be done after
     adjusting the markers that bound the overlays.  */
979 980 981 982
  adjust_overlays_for_delete (from, nchars_del);
  adjust_overlays_for_insert (from, inschars);
  adjust_markers_for_insert (from, from_byte, from + inschars,
			     from_byte + insbytes, 0);
983 984 985

#ifdef USE_TEXT_PROPERTIES
  /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
986 987
  graft_intervals_into_buffer (XSTRING (new)->intervals, from,
			       inschars, current_buffer, inherit);
988 989
#endif

990
  if (insbytes == 0)
991 992 993 994 995
    evaporate_overlays (from);

  MODIFF++;
  UNGCPRO;

996
  signal_after_change (from, nchars_del, inschars);
997 998
}

Jim Blandy's avatar
Jim Blandy committed
999
/* Delete characters in current buffer
1000 1001
   from FROM up to (but not including) TO.
   If TO comes before FROM, we delete nothing.  */
Jim Blandy's avatar
Jim Blandy committed
1002

1003
void
Jim Blandy's avatar
Jim Blandy committed
1004 1005
del_range (from, to)
     register int from, to;
1006
{
1007
  del_range_1 (from, to, 1);
1008 1009 1010 1011
}

/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.  */

1012
void
1013
del_range_1 (from, to, prepare)
1014
     int from, to, prepare;
Jim Blandy's avatar
Jim Blandy committed
1015
{
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
  int from_byte, to_byte;

  /* Make args be valid */
  if (from < BEGV)
    from = BEGV;
  if (to > ZV)
    to = ZV;

  if (to <= from)
    return;

  if (prepare)
    {
      int range_length = to - from;
      prepare_to_modify_buffer (from, to, &from);
      to = from + range_length;
    }

  from_byte = CHAR_TO_BYTE (from);
  to_byte = CHAR_TO_BYTE (to);

  del_range_2 (from, to, from_byte, to_byte);
}

/* Like del_range_1 but args are byte positions, not char positions.  */

void
del_range_byte (from_byte, to_byte, prepare)
     int from_byte, to_byte, prepare;
{
  int from, to;

  /* Make args be valid */
  if (from_byte < BEGV_BYTE)
    from_byte = BEGV_BYTE;
  if (to_byte > ZV_BYTE)
    to_byte = ZV_BYTE;

  if (to_byte <= from_byte)
    return;

  from = BYTE_TO_CHAR (from_byte);
  to = BYTE_TO_CHAR (to_byte);
Jim Blandy's avatar
Jim Blandy committed
1059

1060 1061
  if (prepare)
    {
1062
      int old_from = from, old_to = Z - to;
1063 1064 1065
      int range_length = to - from;
      prepare_to_modify_buffer (from, to, &from);
      to = from + range_length;
1066 1067 1068 1069 1070

      if (old_from != from)
	from_byte = CHAR_TO_BYTE (from);
      if (old_to == Z - to)
	to_byte = CHAR_TO_BYTE (to);