Sync up with XEmacs 21.4.17.
[chise/xemacs-chise.git.1] / src / insdel.c
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.
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Mule 2.0, FSF 19.30.  Diverges significantly. */
24
25 /* This file has been Mule-ized. */
26
27 /* Overhauled by Ben Wing, December 1994, for Mule implementation. */
28
29 /*
30    There are three possible ways to specify positions in a buffer.  All
31    of these are one-based: the beginning of the buffer is position or
32    index 1, and 0 is not a valid position.
33
34    As a "buffer position" (typedef Bufpos):
35
36       This is an index specifying an offset in characters from the
37       beginning of the buffer.  Note that buffer positions are
38       logically *between* characters, not on a character.  The
39       difference between two buffer positions specifies the number of
40       characters between those positions.  Buffer positions are the
41       only kind of position externally visible to the user.
42
43    As a "byte index" (typedef Bytind):
44
45       This is an index over the bytes used to represent the characters
46       in the buffer.  If there is no Mule support, this is identical
47       to a buffer position, because each character is represented
48       using one byte.  However, with Mule support, many characters
49       require two or more bytes for their representation, and so a
50       byte index may be greater than the corresponding buffer
51       position.
52
53    As a "memory index" (typedef Memind):
54
55       This is the byte index adjusted for the gap.  For positions
56       before the gap, this is identical to the byte index.  For
57       positions after the gap, this is the byte index plus the gap
58       size.  There are two possible memory indices for the gap
59       position; the memory index at the beginning of the gap should
60       always be used, except in code that deals with manipulating the
61       gap, where both indices may be seen.  The address of the
62       character "at" (i.e. following) a particular position can be
63       obtained from the formula
64
65         buffer_start_address + memory_index(position) - 1
66
67       except in the case of characters at the gap position.
68
69    Other typedefs:
70    ===============
71
72       Emchar:
73       -------
74         This typedef represents a single Emacs character, which can be
75         ASCII, ISO-8859, or some extended character, as would typically
76         be used for Kanji.  Note that the representation of a character
77         as an Emchar is *not* the same as the representation of that
78         same character in a string; thus, you cannot do the standard
79         C trick of passing a pointer to a character to a function that
80         expects a string.
81
82         An Emchar takes up 19 bits of representation and (for code
83         compatibility and such) is compatible with an int.  This
84         representation is visible on the Lisp level.  The important
85         characteristics of the Emchar representation are
86
87           -- values 0x00 - 0x7f represent ASCII.
88           -- values 0x80 - 0xff represent the right half of ISO-8859-1.
89           -- values 0x100 and up represent all other characters.
90
91         This means that Emchar values are upwardly compatible with
92         the standard 8-bit representation of ASCII/ISO-8859-1.
93
94       Bufbyte:
95       --------
96         The data in a buffer or string is logically made up of Bufbyte
97         objects, where a Bufbyte takes up the same amount of space as a
98         char. (It is declared differently, though, to catch invalid
99         usages.) Strings stored using Bufbytes are said to be in
100         "internal format".  The important characteristics of internal
101         format are
102
103           -- ASCII characters are represented as a single Bufbyte,
104              in the range 0 - 0x7f.
105           -- All other characters are represented as a Bufbyte in
106              the range 0x80 - 0x9f followed by one or more Bufbytes
107              in the range 0xa0 to 0xff.
108
109         This leads to a number of desirable properties:
110
111           -- Given the position of the beginning of a character,
112              you can find the beginning of the next or previous
113              character in constant time.
114           -- When searching for a substring or an ASCII character
115              within the string, you need merely use standard
116              searching routines.
117
118       array of char:
119       --------------
120         Strings that go in or out of Emacs are in "external format",
121         typedef'ed as an array of char or a char *.  There is more
122         than one external format (JIS, EUC, etc.) but they all
123         have similar properties.  They are modal encodings,
124         which is to say that the meaning of particular bytes is
125         not fixed but depends on what "mode" the string is currently
126         in (e.g. bytes in the range 0 - 0x7f might be
127         interpreted as ASCII, or as Hiragana, or as 2-byte Kanji,
128         depending on the current mode).  The mode starts out in
129         ASCII/ISO-8859-1 and is switched using escape sequences --
130         for example, in the JIS encoding, 'ESC $ B' switches to a
131         mode where pairs of bytes in the range 0 - 0x7f
132         are interpreted as Kanji characters.
133
134         External-formatted data is generally desirable for passing
135         data between programs because it is upwardly compatible
136         with standard ASCII/ISO-8859-1 strings and may require
137         less space than internal encodings such as the one
138         described above.  In addition, some encodings (e.g. JIS)
139         keep all characters (except the ESC used to switch modes)
140         in the printing ASCII range 0x20 - 0x7e, which results in
141         a much higher probability that the data will avoid being
142         garbled in transmission.  Externally-formatted data is
143         generally not very convenient to work with, however, and
144         for this reason is usually converted to internal format
145         before any work is done on the string.
146
147         NOTE: filenames need to be in external format so that
148         ISO-8859-1 characters come out correctly.
149
150       Charcount:
151       ----------
152         This typedef represents a count of characters, such as
153         a character offset into a string or the number of
154         characters between two positions in a buffer.  The
155         difference between two Bufpos's is a Charcount, and
156         character positions in a string are represented using
157         a Charcount.
158
159       Bytecount:
160       ----------
161         Similar to a Charcount but represents a count of bytes.
162         The difference between two Bytind's is a Bytecount.
163
164
165    Usage of the various representations:
166    =====================================
167
168    Memory indices are used in low-level functions in insdel.c and for
169    extent endpoints and marker positions.  The reason for this is that
170    this way, the extents and markers don't need to be updated for most
171    insertions, which merely shrink the gap and don't move any
172    characters around in memory.
173
174    (The beginning-of-gap memory index simplifies insertions w.r.t.
175    markers, because text usually gets inserted after markers.  For
176    extents, it is merely for consistency, because text can get
177    inserted either before or after an extent's endpoint depending on
178    the open/closedness of the endpoint.)
179
180    Byte indices are used in other code that needs to be fast,
181    such as the searching, redisplay, and extent-manipulation code.
182
183    Buffer positions are used in all other code.  This is because this
184    representation is easiest to work with (especially since Lisp
185    code always uses buffer positions), necessitates the fewest
186    changes to existing code, and is the safest (e.g. if the text gets
187    shifted underneath a buffer position, it will still point to a
188    character; if text is shifted under a byte index, it might point
189    to the middle of a character, which would be bad).
190
191    Similarly, Charcounts are used in all code that deals with strings
192    except for code that needs to be fast, which used Bytecounts.
193
194    Strings are always passed around internally using internal format.
195    Conversions between external format are performed at the time
196    that the data goes in or out of Emacs.
197
198    Working with the various representations:
199    ========================================= */
200
201 #include <config.h>
202 #include "lisp.h"
203
204 #include "buffer.h"
205 #include "device.h"
206 #include "frame.h"
207 #include "extents.h"
208 #include "insdel.h"
209 #include "lstream.h"
210 #include "redisplay.h"
211 #include "line-number.h"
212
213 /* We write things this way because it's very important the
214    MAX_BYTIND_GAP_SIZE_3 is a multiple of 3. (As it happens,
215    65535 is a multiple of 3, but this may not always be the
216    case.) */
217
218 #define MAX_BUFPOS_GAP_SIZE_3 (65535/3)
219 #define MAX_BYTIND_GAP_SIZE_3 (3 * MAX_BUFPOS_GAP_SIZE_3)
220
221 #ifndef UTF2000
222 short three_to_one_table[1 + MAX_BYTIND_GAP_SIZE_3];
223 #endif
224
225 /* Various macros modelled along the lines of those in buffer.h.
226    Purposefully omitted from buffer.h because files other than this
227    one should not be using them. */
228
229 /* Address of beginning of buffer.  This is an lvalue because
230    BUFFER_ALLOC needs it to be. */
231 #define BUF_BEG_ADDR(buf) ((buf)->text->beg)
232
233 /* Set the address of beginning of buffer. */
234 #define SET_BUF_BEG_ADDR(buf, addr) do { (buf)->text->beg = (addr); } while (0)
235
236 /* Gap size.  */
237 #define BUF_GAP_SIZE(buf) ((buf)->text->gap_size + 0)
238 #define BUF_END_GAP_SIZE(buf) ((buf)->text->end_gap_size + 0)
239 /* Set gap size.  */
240 #define SET_BUF_GAP_SIZE(buf, value) \
241   do { (buf)->text->gap_size = (value); } while (0)
242 #define SET_BUF_END_GAP_SIZE(buf, value) \
243   do { (buf)->text->end_gap_size = (value); } while (0)
244
245 /* Gap location.  */
246 #define BI_BUF_GPT(buf) ((buf)->text->gpt + 0)
247 #define BUF_GPT_ADDR(buf) (BUF_BEG_ADDR (buf) + BI_BUF_GPT (buf) - 1)
248
249 /* Set gap location.  */
250 #define SET_BI_BUF_GPT(buf, value) do { (buf)->text->gpt = (value); } while (0)
251
252 /* Set end of buffer.  */
253 #define SET_BOTH_BUF_Z(buf, val, bival)         \
254 do                                              \
255 {                                               \
256   (buf)->text->z = (bival);                     \
257   (buf)->text->bufz = (val);                    \
258 } while (0)
259
260 /* Under Mule, we maintain two sentinels in the buffer: one at the
261    beginning of the gap, and one at the end of the buffer.  This
262    allows us to move forward, examining bytes looking for the
263    end of a character, and not worry about running off the end.
264    We do not need corresponding sentinels when moving backwards
265    because we do not have to look past the beginning of a character
266    to find the beginning of the character.
267
268    Every time we change the beginning of the gap, we have to
269    call SET_GAP_SENTINEL().
270
271    Every time we change the total size (characters plus gap)
272    of the buffer, we have to call SET_END_SENTINEL().
273  */
274
275
276 #ifdef MULE
277 # define GAP_CAN_HOLD_SIZE_P(buf, len) (BUF_GAP_SIZE (buf) >= (len) + 1)
278 # define SET_GAP_SENTINEL(buf) (*BUF_GPT_ADDR (buf) = 0)
279 # define BUF_END_SENTINEL_SIZE 1
280 # define SET_END_SENTINEL(buf) \
281   (*(BUF_BEG_ADDR (buf) + BUF_GAP_SIZE (buf) + BI_BUF_Z (buf) - 1) = 0)
282 #else
283 # define GAP_CAN_HOLD_SIZE_P(buf, len) (BUF_GAP_SIZE (buf) >= (len))
284 # define SET_GAP_SENTINEL(buf)
285 # define BUF_END_SENTINEL_SIZE 0
286 # define SET_END_SENTINEL(buf)
287 #endif
288
289 \f
290 /************************************************************************/
291 /*                    Charcount/Bytecount conversion                    */
292 /************************************************************************/
293
294 /* Optimization.  Do it.  Live it.  Love it.  */
295
296 #ifdef MULE
297
298 /* We include the basic functions here that require no specific
299    knowledge of how data is Mule-encoded into a buffer other
300    than the basic (00 - 7F), (80 - 9F), (A0 - FF) scheme.
301    Anything that requires more specific knowledge goes into
302    mule-charset.c. */
303
304 /* Given a pointer to a text string and a length in bytes, return
305    the equivalent length in characters. */
306
307 Charcount
308 bytecount_to_charcount (const Bufbyte *ptr, Bytecount len)
309 {
310   Charcount count = 0;
311   const Bufbyte *end = ptr + len;
312
313 #if SIZEOF_LONG == 8
314 # define STRIDE_TYPE long
315 # define HIGH_BIT_MASK 0x8080808080808080UL
316 #elif SIZEOF_LONG_LONG == 8 && !(defined (i386) || defined (__i386__))
317 # define STRIDE_TYPE long long
318 # define HIGH_BIT_MASK 0x8080808080808080ULL
319 #elif SIZEOF_LONG == 4
320 # define STRIDE_TYPE long
321 # define HIGH_BIT_MASK 0x80808080UL
322 #else
323 # error Add support for 128-bit systems here
324 #endif
325
326 #define ALIGN_BITS ((EMACS_UINT) (ALIGNOF (STRIDE_TYPE) - 1))
327 #define ALIGN_MASK (~ ALIGN_BITS)
328 #define ALIGNED(ptr) ((((EMACS_UINT) ptr) & ALIGN_BITS) == 0)
329 #define STRIDE sizeof (STRIDE_TYPE)
330
331   while (ptr < end)
332     {
333       if (BYTE_ASCII_P (*ptr))
334         {
335           /* optimize for long stretches of ASCII */
336           if (! ALIGNED (ptr))
337             ptr++, count++;
338           else
339             {
340               const unsigned STRIDE_TYPE *ascii_end =
341                 (const unsigned STRIDE_TYPE *) ptr;
342               /* This loop screams, because we can typically
343                  detect ASCII characters 8 at a time. */
344               while ((const Bufbyte *) ascii_end + STRIDE <= end
345                      && !(*ascii_end & HIGH_BIT_MASK))
346                 ascii_end++;
347               if ((Bufbyte *) ascii_end == ptr)
348                 ptr++, count++;
349               else
350                 {
351                   count += (Bufbyte *) ascii_end - ptr;
352                   ptr = (Bufbyte *) ascii_end;
353                 }
354             }
355         }
356       else
357         {
358           /* optimize for successive characters from the same charset */
359           Bufbyte leading_byte = *ptr;
360           size_t bytes = REP_BYTES_BY_FIRST_BYTE (leading_byte);
361           while ((ptr < end) && (*ptr == leading_byte))
362             ptr += bytes, count++;
363         }
364     }
365
366 #ifdef ERROR_CHECK_BUFPOS
367   /* Bomb out if the specified substring ends in the middle
368      of a character.  Note that we might have already gotten
369      a core dump above from an invalid reference, but at least
370      we will get no farther than here. */
371   assert (ptr == end);
372 #endif
373
374   return count;
375 }
376
377 /* Given a pointer to a text string and a length in characters, return
378    the equivalent length in bytes. */
379
380 Bytecount
381 charcount_to_bytecount (const Bufbyte *ptr, Charcount len)
382 {
383   const Bufbyte *newptr = ptr;
384
385   while (len > 0)
386     {
387       INC_CHARPTR (newptr);
388       len--;
389     }
390   return newptr - ptr;
391 }
392
393 /* The next two functions are the actual meat behind the
394    bufpos-to-bytind and bytind-to-bufpos conversions.  Currently
395    the method they use is fairly unsophisticated; see buffer.h.
396
397    Note that bufpos_to_bytind_func() is probably the most-called
398    function in all of XEmacs.  Therefore, it must be FAST FAST FAST.
399    This is the reason why so much of the code is duplicated.
400
401    Similar considerations apply to bytind_to_bufpos_func(), although
402    less so because the function is not called so often.
403
404    #### At some point this should use a more sophisticated method;
405    see buffer.h. */
406
407 static int not_very_random_number;
408
409 Bytind
410 bufpos_to_bytind_func (struct buffer *buf, Bufpos x)
411 {
412   Bufpos bufmin;
413   Bufpos bufmax;
414   Bytind bytmin;
415   Bytind bytmax;
416   int size;
417   int forward_p;
418   Bytind retval;
419   int diff_so_far;
420   int add_to_cache = 0;
421
422   /* Check for some cached positions, for speed. */
423   if (x == BUF_PT (buf))
424     return BI_BUF_PT (buf);
425   if (x == BUF_ZV (buf))
426     return BI_BUF_ZV (buf);
427   if (x == BUF_BEGV (buf))
428     return BI_BUF_BEGV (buf);
429
430   bufmin = buf->text->mule_bufmin;
431   bufmax = buf->text->mule_bufmax;
432   bytmin = buf->text->mule_bytmin;
433   bytmax = buf->text->mule_bytmax;
434 #ifdef UTF2000
435   size = buf->text->mule_size;
436 #else
437   size = (1 << buf->text->mule_shifter) + !!buf->text->mule_three_p;
438 #endif
439
440   /* The basic idea here is that we shift the "known region" up or down
441      until it overlaps the specified position.  We do this by moving
442      the upper bound of the known region up one character at a time,
443      and moving the lower bound of the known region up as necessary
444      when the size of the character just seen changes.
445
446      We optimize this, however, by first shifting the known region to
447      one of the cached points if it's close by. (We don't check BEG or
448      Z, even though they're cached; most of the time these will be the
449      same as BEGV and ZV, and when they're not, they're not likely
450      to be used.) */
451
452   if (x > bufmax)
453     {
454       Bufpos diffmax = x - bufmax;
455       Bufpos diffpt = x - BUF_PT (buf);
456       Bufpos diffzv = BUF_ZV (buf) - x;
457       /* #### This value could stand some more exploration. */
458       Charcount heuristic_hack = (bufmax - bufmin) >> 2;
459
460       /* Check if the position is closer to PT or ZV than to the
461          end of the known region. */
462
463       if (diffpt < 0)
464         diffpt = -diffpt;
465       if (diffzv < 0)
466         diffzv = -diffzv;
467
468       /* But also implement a heuristic that favors the known region
469          over PT or ZV.  The reason for this is that switching to
470          PT or ZV will wipe out the knowledge in the known region,
471          which might be annoying if the known region is large and
472          PT or ZV is not that much closer than the end of the known
473          region. */
474
475       diffzv += heuristic_hack;
476       diffpt += heuristic_hack;
477       if (diffpt < diffmax && diffpt <= diffzv)
478         {
479           bufmax = bufmin = BUF_PT (buf);
480           bytmax = bytmin = BI_BUF_PT (buf);
481           /* We set the size to 1 even though it doesn't really
482              matter because the new known region contains no
483              characters.  We do this because this is the most
484              likely size of the characters around the new known
485              region, and we avoid potential yuckiness that is
486              done when size == 3. */
487           size = 1;
488         }
489       if (diffzv < diffmax)
490         {
491           bufmax = bufmin = BUF_ZV (buf);
492           bytmax = bytmin = BI_BUF_ZV (buf);
493           size = 1;
494         }
495     }
496 #ifdef ERROR_CHECK_BUFPOS
497   else if (x >= bufmin)
498     ABORT ();
499 #endif
500   else
501     {
502       Bufpos diffmin = bufmin - x;
503       Bufpos diffpt = BUF_PT (buf) - x;
504       Bufpos diffbegv = x - BUF_BEGV (buf);
505       /* #### This value could stand some more exploration. */
506       Charcount heuristic_hack = (bufmax - bufmin) >> 2;
507
508       if (diffpt < 0)
509         diffpt = -diffpt;
510       if (diffbegv < 0)
511         diffbegv = -diffbegv;
512
513       /* But also implement a heuristic that favors the known region --
514          see above. */
515
516       diffbegv += heuristic_hack;
517       diffpt += heuristic_hack;
518
519       if (diffpt < diffmin && diffpt <= diffbegv)
520         {
521           bufmax = bufmin = BUF_PT (buf);
522           bytmax = bytmin = BI_BUF_PT (buf);
523           /* We set the size to 1 even though it doesn't really
524              matter because the new known region contains no
525              characters.  We do this because this is the most
526              likely size of the characters around the new known
527              region, and we avoid potential yuckiness that is
528              done when size == 3. */
529           size = 1;
530         }
531       if (diffbegv < diffmin)
532         {
533           bufmax = bufmin = BUF_BEGV (buf);
534           bytmax = bytmin = BI_BUF_BEGV (buf);
535           size = 1;
536         }
537     }
538
539   diff_so_far = x > bufmax ? x - bufmax : bufmin - x;
540   if (diff_so_far > 50)
541     {
542       /* If we have to move more than a certain amount, then look
543          into our cache. */
544       int minval = INT_MAX;
545       int found = 0;
546       int i;
547
548       add_to_cache = 1;
549       /* I considered keeping the positions ordered.  This would speed
550          up this loop, but updating the cache would take longer, so
551          it doesn't seem like it would really matter. */
552       for (i = 0; i < 16; i++)
553         {
554           int diff = buf->text->mule_bufpos_cache[i] - x;
555
556           if (diff < 0)
557             diff = -diff;
558           if (diff < minval)
559             {
560               minval = diff;
561               found = i;
562             }
563         }
564
565       if (minval < diff_so_far)
566         {
567           bufmax = bufmin = buf->text->mule_bufpos_cache[found];
568           bytmax = bytmin = buf->text->mule_bytind_cache[found];
569           size = 1;
570         }
571     }
572
573   /* It's conceivable that the caching above could lead to X being
574      the same as one of the range edges. */
575   if (x >= bufmax)
576     {
577       Bytind newmax;
578       Bytecount newsize;
579
580       forward_p = 1;
581       while (x > bufmax)
582         {
583           newmax = bytmax;
584
585           INC_BYTIND (buf, newmax);
586           newsize = newmax - bytmax;
587           if (newsize != size)
588             {
589               bufmin = bufmax;
590               bytmin = bytmax;
591               size = newsize;
592             }
593           bytmax = newmax;
594           bufmax++;
595         }
596       retval = bytmax;
597
598       /* #### Should go past the found location to reduce the number
599          of times that this function is called */
600     }
601   else /* x < bufmin */
602     {
603       Bytind newmin;
604       Bytecount newsize;
605
606       forward_p = 0;
607       while (x < bufmin)
608         {
609           newmin = bytmin;
610
611           DEC_BYTIND (buf, newmin);
612           newsize = bytmin - newmin;
613           if (newsize != size)
614             {
615               bufmax = bufmin;
616               bytmax = bytmin;
617               size = newsize;
618             }
619           bytmin = newmin;
620           bufmin--;
621         }
622       retval = bytmin;
623
624       /* #### Should go past the found location to reduce the number
625          of times that this function is called
626          */
627     }
628
629   /* If size is three, than we have to max sure that the range we
630      discovered isn't too large, because we use a fixed-length
631      table to divide by 3. */
632
633 #ifdef UTF2000
634   buf->text->mule_size = size;
635 #endif
636   if (size == 3)
637     {
638       int gap = bytmax - bytmin;
639 #ifndef UTF2000
640       buf->text->mule_three_p = 1;
641       buf->text->mule_shifter = 1;
642 #endif
643
644       if (gap > MAX_BYTIND_GAP_SIZE_3)
645         {
646           if (forward_p)
647             {
648               bytmin = bytmax - MAX_BYTIND_GAP_SIZE_3;
649               bufmin = bufmax - MAX_BUFPOS_GAP_SIZE_3;
650             }
651           else
652             {
653               bytmax = bytmin + MAX_BYTIND_GAP_SIZE_3;
654               bufmax = bufmin + MAX_BUFPOS_GAP_SIZE_3;
655             }
656         }
657     }
658   else
659     {
660 #ifndef UTF2000
661       buf->text->mule_three_p = 0;
662       if (size == 4)
663         buf->text->mule_shifter = 2;
664       else
665         buf->text->mule_shifter = size - 1;
666 #endif
667     }
668
669   buf->text->mule_bufmin = bufmin;
670   buf->text->mule_bufmax = bufmax;
671   buf->text->mule_bytmin = bytmin;
672   buf->text->mule_bytmax = bytmax;
673
674   if (add_to_cache)
675     {
676       int replace_loc;
677
678       /* We throw away a "random" cached value and replace it with
679          the new value.  It doesn't actually have to be very random
680          at all, just evenly distributed.
681
682          #### It would be better to use a least-recently-used algorithm
683          or something that tries to space things out, but I'm not sure
684          it's worth it to go to the trouble of maintaining that. */
685       not_very_random_number += 621;
686       replace_loc = not_very_random_number & 15;
687       buf->text->mule_bufpos_cache[replace_loc] = x;
688       buf->text->mule_bytind_cache[replace_loc] = retval;
689     }
690
691   return retval;
692 }
693
694 /* The logic in this function is almost identical to the logic in
695    the previous function. */
696
697 Bufpos
698 bytind_to_bufpos_func (struct buffer *buf, Bytind x)
699 {
700   Bufpos bufmin;
701   Bufpos bufmax;
702   Bytind bytmin;
703   Bytind bytmax;
704   int size;
705   int forward_p;
706   Bufpos retval;
707   int diff_so_far;
708   int add_to_cache = 0;
709
710   /* Check for some cached positions, for speed. */
711   if (x == BI_BUF_PT (buf))
712     return BUF_PT (buf);
713   if (x == BI_BUF_ZV (buf))
714     return BUF_ZV (buf);
715   if (x == BI_BUF_BEGV (buf))
716     return BUF_BEGV (buf);
717
718   bufmin = buf->text->mule_bufmin;
719   bufmax = buf->text->mule_bufmax;
720   bytmin = buf->text->mule_bytmin;
721   bytmax = buf->text->mule_bytmax;
722 #ifdef UTF2000
723   size = buf->text->mule_size;
724 #else
725   size = (1 << buf->text->mule_shifter) + !!buf->text->mule_three_p;
726 #endif
727
728   /* The basic idea here is that we shift the "known region" up or down
729      until it overlaps the specified position.  We do this by moving
730      the upper bound of the known region up one character at a time,
731      and moving the lower bound of the known region up as necessary
732      when the size of the character just seen changes.
733
734      We optimize this, however, by first shifting the known region to
735      one of the cached points if it's close by. (We don't check BI_BEG or
736      BI_Z, even though they're cached; most of the time these will be the
737      same as BI_BEGV and BI_ZV, and when they're not, they're not likely
738      to be used.) */
739
740   if (x > bytmax)
741     {
742       Bytind diffmax = x - bytmax;
743       Bytind diffpt = x - BI_BUF_PT (buf);
744       Bytind diffzv = BI_BUF_ZV (buf) - x;
745       /* #### This value could stand some more exploration. */
746       Bytecount heuristic_hack = (bytmax - bytmin) >> 2;
747
748       /* Check if the position is closer to PT or ZV than to the
749          end of the known region. */
750
751       if (diffpt < 0)
752         diffpt = -diffpt;
753       if (diffzv < 0)
754         diffzv = -diffzv;
755
756       /* But also implement a heuristic that favors the known region
757          over BI_PT or BI_ZV.  The reason for this is that switching to
758          BI_PT or BI_ZV will wipe out the knowledge in the known region,
759          which might be annoying if the known region is large and
760          BI_PT or BI_ZV is not that much closer than the end of the known
761          region. */
762
763       diffzv += heuristic_hack;
764       diffpt += heuristic_hack;
765       if (diffpt < diffmax && diffpt <= diffzv)
766         {
767           bufmax = bufmin = BUF_PT (buf);
768           bytmax = bytmin = BI_BUF_PT (buf);
769           /* We set the size to 1 even though it doesn't really
770              matter because the new known region contains no
771              characters.  We do this because this is the most
772              likely size of the characters around the new known
773              region, and we avoid potential yuckiness that is
774              done when size == 3. */
775           size = 1;
776         }
777       if (diffzv < diffmax)
778         {
779           bufmax = bufmin = BUF_ZV (buf);
780           bytmax = bytmin = BI_BUF_ZV (buf);
781           size = 1;
782         }
783     }
784 #ifdef ERROR_CHECK_BUFPOS
785   else if (x >= bytmin)
786     ABORT ();
787 #endif
788   else
789     {
790       Bytind diffmin = bytmin - x;
791       Bytind diffpt = BI_BUF_PT (buf) - x;
792       Bytind diffbegv = x - BI_BUF_BEGV (buf);
793       /* #### This value could stand some more exploration. */
794       Bytecount heuristic_hack = (bytmax - bytmin) >> 2;
795
796       if (diffpt < 0)
797         diffpt = -diffpt;
798       if (diffbegv < 0)
799         diffbegv = -diffbegv;
800
801       /* But also implement a heuristic that favors the known region --
802          see above. */
803
804       diffbegv += heuristic_hack;
805       diffpt += heuristic_hack;
806
807       if (diffpt < diffmin && diffpt <= diffbegv)
808         {
809           bufmax = bufmin = BUF_PT (buf);
810           bytmax = bytmin = BI_BUF_PT (buf);
811           /* We set the size to 1 even though it doesn't really
812              matter because the new known region contains no
813              characters.  We do this because this is the most
814              likely size of the characters around the new known
815              region, and we avoid potential yuckiness that is
816              done when size == 3. */
817           size = 1;
818         }
819       if (diffbegv < diffmin)
820         {
821           bufmax = bufmin = BUF_BEGV (buf);
822           bytmax = bytmin = BI_BUF_BEGV (buf);
823           size = 1;
824         }
825     }
826
827   diff_so_far = x > bytmax ? x - bytmax : bytmin - x;
828   if (diff_so_far > 50)
829     {
830       /* If we have to move more than a certain amount, then look
831          into our cache. */
832       int minval = INT_MAX;
833       int found = 0;
834       int i;
835
836       add_to_cache = 1;
837       /* I considered keeping the positions ordered.  This would speed
838          up this loop, but updating the cache would take longer, so
839          it doesn't seem like it would really matter. */
840       for (i = 0; i < 16; i++)
841         {
842           int diff = buf->text->mule_bytind_cache[i] - x;
843
844           if (diff < 0)
845             diff = -diff;
846           if (diff < minval)
847             {
848               minval = diff;
849               found = i;
850             }
851         }
852
853       if (minval < diff_so_far)
854         {
855           bufmax = bufmin = buf->text->mule_bufpos_cache[found];
856           bytmax = bytmin = buf->text->mule_bytind_cache[found];
857           size = 1;
858         }
859     }
860
861   /* It's conceivable that the caching above could lead to X being
862      the same as one of the range edges. */
863   if (x >= bytmax)
864     {
865       Bytind newmax;
866       Bytecount newsize;
867
868       forward_p = 1;
869       while (x > bytmax)
870         {
871           newmax = bytmax;
872
873           INC_BYTIND (buf, newmax);
874           newsize = newmax - bytmax;
875           if (newsize != size)
876             {
877               bufmin = bufmax;
878               bytmin = bytmax;
879               size = newsize;
880             }
881           bytmax = newmax;
882           bufmax++;
883         }
884       retval = bufmax;
885
886       /* #### Should go past the found location to reduce the number
887          of times that this function is called */
888     }
889   else /* x <= bytmin */
890     {
891       Bytind newmin;
892       Bytecount newsize;
893
894       forward_p = 0;
895       while (x < bytmin)
896         {
897           newmin = bytmin;
898
899           DEC_BYTIND (buf, newmin);
900           newsize = bytmin - newmin;
901           if (newsize != size)
902             {
903               bufmax = bufmin;
904               bytmax = bytmin;
905               size = newsize;
906             }
907           bytmin = newmin;
908           bufmin--;
909         }
910       retval = bufmin;
911
912       /* #### Should go past the found location to reduce the number
913          of times that this function is called
914          */
915     }
916
917   /* If size is three, than we have to max sure that the range we
918      discovered isn't too large, because we use a fixed-length
919      table to divide by 3. */
920
921 #ifdef UTF2000
922   buf->text->mule_size = size;
923   #endif
924   if (size == 3)
925     {
926       int gap = bytmax - bytmin;
927 #ifndef UTF2000
928       buf->text->mule_three_p = 1;
929       buf->text->mule_shifter = 1;
930 #endif
931
932       if (gap > MAX_BYTIND_GAP_SIZE_3)
933         {
934           if (forward_p)
935             {
936               bytmin = bytmax - MAX_BYTIND_GAP_SIZE_3;
937               bufmin = bufmax - MAX_BUFPOS_GAP_SIZE_3;
938             }
939           else
940             {
941               bytmax = bytmin + MAX_BYTIND_GAP_SIZE_3;
942               bufmax = bufmin + MAX_BUFPOS_GAP_SIZE_3;
943             }
944         }
945     }
946   else
947     {
948 #ifndef UTF2000
949       buf->text->mule_three_p = 0;
950       if (size == 4)
951         buf->text->mule_shifter = 2;
952       else
953         buf->text->mule_shifter = size - 1;
954 #endif
955     }
956
957   buf->text->mule_bufmin = bufmin;
958   buf->text->mule_bufmax = bufmax;
959   buf->text->mule_bytmin = bytmin;
960   buf->text->mule_bytmax = bytmax;
961
962   if (add_to_cache)
963     {
964       int replace_loc;
965
966       /* We throw away a "random" cached value and replace it with
967          the new value.  It doesn't actually have to be very random
968          at all, just evenly distributed.
969
970          #### It would be better to use a least-recently-used algorithm
971          or something that tries to space things out, but I'm not sure
972          it's worth it to go to the trouble of maintaining that. */
973       not_very_random_number += 621;
974       replace_loc = not_very_random_number & 15;
975       buf->text->mule_bufpos_cache[replace_loc] = retval;
976       buf->text->mule_bytind_cache[replace_loc] = x;
977     }
978
979   return retval;
980 }
981
982 /* Text of length BYTELENGTH and CHARLENGTH (in different units)
983    was inserted at bufpos START. */
984
985 static void
986 buffer_mule_signal_inserted_region (struct buffer *buf, Bufpos start,
987                                     Bytecount bytelength,
988                                     Charcount charlength)
989 {
990 #ifdef UTF2000
991   int size = buf->text->mule_size;
992 #else
993   int size = (1 << buf->text->mule_shifter) + !!buf->text->mule_three_p;
994 #endif
995   int i;
996
997   /* Adjust the cache of known positions. */
998   for (i = 0; i < 16; i++)
999     {
1000
1001       if (buf->text->mule_bufpos_cache[i] > start)
1002         {
1003           buf->text->mule_bufpos_cache[i] += charlength;
1004           buf->text->mule_bytind_cache[i] += bytelength;
1005         }
1006     }
1007
1008   if (start >= buf->text->mule_bufmax)
1009     return;
1010
1011   /* The insertion is either before the known region, in which case
1012      it shoves it forward; or within the known region, in which case
1013      it shoves the end forward. (But it may make the known region
1014      inconsistent, so we may have to shorten it.) */
1015
1016   if (start <= buf->text->mule_bufmin)
1017     {
1018       buf->text->mule_bufmin += charlength;
1019       buf->text->mule_bufmax += charlength;
1020       buf->text->mule_bytmin += bytelength;
1021       buf->text->mule_bytmax += bytelength;
1022     }
1023   else
1024     {
1025       Bufpos end = start + charlength;
1026       /* the insertion point divides the known region in two.
1027          Keep the longer half, at least, and expand into the
1028          inserted chunk as much as possible. */
1029
1030       if (start - buf->text->mule_bufmin > buf->text->mule_bufmax - start)
1031         {
1032           Bytind bytestart = (buf->text->mule_bytmin
1033                               + size * (start - buf->text->mule_bufmin));
1034           Bytind bytenew;
1035
1036           while (start < end)
1037             {
1038               bytenew = bytestart;
1039               INC_BYTIND (buf, bytenew);
1040               if (bytenew - bytestart != size)
1041                 break;
1042               start++;
1043               bytestart = bytenew;
1044             }
1045           if (start != end)
1046             {
1047               buf->text->mule_bufmax = start;
1048               buf->text->mule_bytmax = bytestart;
1049             }
1050           else
1051             {
1052               buf->text->mule_bufmax += charlength;
1053               buf->text->mule_bytmax += bytelength;
1054             }
1055         }
1056       else
1057         {
1058           Bytind byteend = (buf->text->mule_bytmin
1059                             + size * (start - buf->text->mule_bufmin)
1060                             + bytelength);
1061           Bytind bytenew;
1062
1063           buf->text->mule_bufmax += charlength;
1064           buf->text->mule_bytmax += bytelength;
1065
1066           while (end > start)
1067             {
1068               bytenew = byteend;
1069               DEC_BYTIND (buf, bytenew);
1070               if (byteend - bytenew != size)
1071                 break;
1072               end--;
1073               byteend = bytenew;
1074             }
1075           if (start != end)
1076             {
1077               buf->text->mule_bufmin = end;
1078               buf->text->mule_bytmin = byteend;
1079             }
1080         }
1081     }
1082 }
1083
1084 /* Text from START to END (equivalent in Bytinds: from BI_START to
1085    BI_END) was deleted. */
1086
1087 static void
1088 buffer_mule_signal_deleted_region (struct buffer *buf, Bufpos start,
1089                                    Bufpos end, Bytind bi_start,
1090                                    Bytind bi_end)
1091 {
1092   int i;
1093
1094   /* Adjust the cache of known positions. */
1095   for (i = 0; i < 16; i++)
1096     {
1097       /* After the end; gets shoved backward */
1098       if (buf->text->mule_bufpos_cache[i] > end)
1099         {
1100           buf->text->mule_bufpos_cache[i] -= end - start;
1101           buf->text->mule_bytind_cache[i] -= bi_end - bi_start;
1102         }
1103       /* In the range; moves to start of range */
1104       else if (buf->text->mule_bufpos_cache[i] > start)
1105         {
1106           buf->text->mule_bufpos_cache[i] = start;
1107           buf->text->mule_bytind_cache[i] = bi_start;
1108         }
1109     }
1110
1111   /* We don't care about any text after the end of the known region. */
1112
1113   end = min (end, buf->text->mule_bufmax);
1114   bi_end = min (bi_end, buf->text->mule_bytmax);
1115   if (start >= end)
1116     return;
1117
1118   /* The end of the known region offsets by the total amount of deletion,
1119      since it's all before it. */
1120
1121   buf->text->mule_bufmax -= end - start;
1122   buf->text->mule_bytmax -= bi_end - bi_start;
1123
1124   /* Now we don't care about any text after the start of the known region. */
1125
1126   end = min (end, buf->text->mule_bufmin);
1127   bi_end = min (bi_end, buf->text->mule_bytmin);
1128   if (start >= end)
1129     return;
1130
1131   buf->text->mule_bufmin -= end - start;
1132   buf->text->mule_bytmin -= bi_end - bi_start;
1133 }
1134
1135 #endif /* MULE */
1136
1137 #ifdef ERROR_CHECK_BUFPOS
1138
1139 Bytind
1140 bufpos_to_bytind (struct buffer *buf, Bufpos x)
1141 {
1142   Bytind retval = real_bufpos_to_bytind (buf, x);
1143   ASSERT_VALID_BYTIND_UNSAFE (buf, retval);
1144   return retval;
1145 }
1146
1147 Bufpos
1148 bytind_to_bufpos (struct buffer *buf, Bytind x)
1149 {
1150   ASSERT_VALID_BYTIND_UNSAFE (buf, x);
1151   return real_bytind_to_bufpos (buf, x);
1152 }
1153
1154 #endif /* ERROR_CHECK_BUFPOS */
1155
1156 \f
1157 /************************************************************************/
1158 /*                verifying buffer and string positions                 */
1159 /************************************************************************/
1160
1161 /* Functions below are tagged with either _byte or _char indicating
1162    whether they return byte or character positions.  For a buffer,
1163    a character position is a "Bufpos" and a byte position is a "Bytind".
1164    For strings, these are sometimes typed using "Charcount" and
1165    "Bytecount". */
1166
1167 /* Flags for the functions below are:
1168
1169    GB_ALLOW_PAST_ACCESSIBLE
1170
1171      Allow positions to range over the entire buffer (BUF_BEG to BUF_Z),
1172      rather than just the accessible portion (BUF_BEGV to BUF_ZV).
1173      For strings, this flag has no effect.
1174
1175    GB_COERCE_RANGE
1176
1177      If the position is outside the allowable range, return the lower
1178      or upper bound of the range, whichever is closer to the specified
1179      position.
1180
1181    GB_NO_ERROR_IF_BAD
1182
1183      If the position is outside the allowable range, return -1.
1184
1185    GB_NEGATIVE_FROM_END
1186
1187      If a value is negative, treat it as an offset from the end.
1188      Only applies to strings.
1189
1190    The following additional flags apply only to the functions
1191    that return ranges:
1192
1193    GB_ALLOW_NIL
1194
1195      Either or both positions can be nil.  If FROM is nil,
1196      FROM_OUT will contain the lower bound of the allowed range.
1197      If TO is nil, TO_OUT will contain the upper bound of the
1198      allowed range.
1199
1200    GB_CHECK_ORDER
1201
1202      FROM must contain the lower bound and TO the upper bound
1203      of the range.  If the positions are reversed, an error is
1204      signalled.
1205
1206    The following is a combination flag:
1207
1208    GB_HISTORICAL_STRING_BEHAVIOR
1209
1210      Equivalent to (GB_NEGATIVE_FROM_END | GB_ALLOW_NIL).
1211  */
1212
1213 /* Return a buffer position stored in a Lisp_Object.  Full
1214    error-checking is done on the position.  Flags can be specified to
1215    control the behavior of out-of-range values.  The default behavior
1216    is to require that the position is within the accessible part of
1217    the buffer (BEGV and ZV), and to signal an error if the position is
1218    out of range.
1219
1220 */
1221
1222 Bufpos
1223 get_buffer_pos_char (struct buffer *b, Lisp_Object pos, unsigned int flags)
1224 {
1225   /* Does not GC */
1226   Bufpos ind;
1227   Bufpos min_allowed, max_allowed;
1228
1229   CHECK_INT_COERCE_MARKER (pos);
1230   ind = XINT (pos);
1231   min_allowed = flags & GB_ALLOW_PAST_ACCESSIBLE ? BUF_BEG (b) : BUF_BEGV (b);
1232   max_allowed = flags & GB_ALLOW_PAST_ACCESSIBLE ? BUF_Z   (b) : BUF_ZV   (b);
1233
1234   if (ind < min_allowed || ind > max_allowed)
1235     {
1236       if (flags & GB_COERCE_RANGE)
1237         ind = ind < min_allowed ? min_allowed : max_allowed;
1238       else if (flags & GB_NO_ERROR_IF_BAD)
1239         ind = -1;
1240       else
1241         {
1242           Lisp_Object buffer;
1243           XSETBUFFER (buffer, b);
1244           args_out_of_range (buffer, pos);
1245         }
1246     }
1247
1248   return ind;
1249 }
1250
1251 Bytind
1252 get_buffer_pos_byte (struct buffer *b, Lisp_Object pos, unsigned int flags)
1253 {
1254   Bufpos bpos = get_buffer_pos_char (b, pos, flags);
1255   if (bpos < 0) /* could happen with GB_NO_ERROR_IF_BAD */
1256     return -1;
1257   return bufpos_to_bytind (b, bpos);
1258 }
1259
1260 /* Return a pair of buffer positions representing a range of text,
1261    taken from a pair of Lisp_Objects.  Full error-checking is
1262    done on the positions.  Flags can be specified to control the
1263    behavior of out-of-range values.  The default behavior is to
1264    allow the range bounds to be specified in either order
1265    (however, FROM_OUT will always be the lower bound of the range
1266    and TO_OUT the upper bound),to require that the positions
1267    are within the accessible part of the buffer (BEGV and ZV),
1268    and to signal an error if the positions are out of range.
1269 */
1270
1271 void
1272 get_buffer_range_char (struct buffer *b, Lisp_Object from, Lisp_Object to,
1273                        Bufpos *from_out, Bufpos *to_out, unsigned int flags)
1274 {
1275   /* Does not GC */
1276   Bufpos min_allowed, max_allowed;
1277
1278   min_allowed = (flags & GB_ALLOW_PAST_ACCESSIBLE) ?
1279     BUF_BEG (b) : BUF_BEGV (b);
1280   max_allowed = (flags & GB_ALLOW_PAST_ACCESSIBLE) ?
1281     BUF_Z (b) : BUF_ZV (b);
1282
1283   if (NILP (from) && (flags & GB_ALLOW_NIL))
1284     *from_out = min_allowed;
1285   else
1286     *from_out = get_buffer_pos_char (b, from, flags | GB_NO_ERROR_IF_BAD);
1287
1288   if (NILP (to) && (flags & GB_ALLOW_NIL))
1289     *to_out = max_allowed;
1290   else
1291     *to_out = get_buffer_pos_char (b, to, flags | GB_NO_ERROR_IF_BAD);
1292
1293   if ((*from_out < 0 || *to_out < 0) && !(flags & GB_NO_ERROR_IF_BAD))
1294     {
1295       Lisp_Object buffer;
1296       XSETBUFFER (buffer, b);
1297       args_out_of_range_3 (buffer, from, to);
1298     }
1299
1300   if (*from_out >= 0 && *to_out >= 0 && *from_out > *to_out)
1301     {
1302       if (flags & GB_CHECK_ORDER)
1303         signal_simple_error_2 ("start greater than end", from, to);
1304       else
1305         {
1306           Bufpos temp = *from_out;
1307           *from_out = *to_out;
1308           *to_out = temp;
1309         }
1310     }
1311 }
1312
1313 void
1314 get_buffer_range_byte (struct buffer *b, Lisp_Object from, Lisp_Object to,
1315                        Bytind *from_out, Bytind *to_out, unsigned int flags)
1316 {
1317   Bufpos s, e;
1318
1319   get_buffer_range_char (b, from, to, &s, &e, flags);
1320   if (s >= 0)
1321     *from_out = bufpos_to_bytind (b, s);
1322   else /* could happen with GB_NO_ERROR_IF_BAD */
1323     *from_out = -1;
1324   if (e >= 0)
1325     *to_out = bufpos_to_bytind (b, e);
1326   else
1327     *to_out = -1;
1328 }
1329
1330 static Charcount
1331 get_string_pos_char_1 (Lisp_Object string, Lisp_Object pos, unsigned int flags,
1332                        Charcount known_length)
1333 {
1334   Charcount ccpos;
1335   Charcount min_allowed = 0;
1336   Charcount max_allowed = known_length;
1337
1338   /* Computation of KNOWN_LENGTH is potentially expensive so we pass
1339      it in. */
1340   CHECK_INT (pos);
1341   ccpos = XINT (pos);
1342   if (ccpos < 0 && flags & GB_NEGATIVE_FROM_END)
1343     ccpos += max_allowed;
1344
1345   if (ccpos < min_allowed || ccpos > max_allowed)
1346     {
1347       if (flags & GB_COERCE_RANGE)
1348         ccpos = ccpos < min_allowed ? min_allowed : max_allowed;
1349       else if (flags & GB_NO_ERROR_IF_BAD)
1350         ccpos = -1;
1351       else
1352         args_out_of_range (string, pos);
1353     }
1354
1355   return ccpos;
1356 }
1357
1358 Charcount
1359 get_string_pos_char (Lisp_Object string, Lisp_Object pos, unsigned int flags)
1360 {
1361   return get_string_pos_char_1 (string, pos, flags,
1362                                 XSTRING_CHAR_LENGTH (string));
1363 }
1364
1365 Bytecount
1366 get_string_pos_byte (Lisp_Object string, Lisp_Object pos, unsigned int flags)
1367 {
1368   Charcount ccpos = get_string_pos_char (string, pos, flags);
1369   if (ccpos < 0) /* could happen with GB_NO_ERROR_IF_BAD */
1370     return -1;
1371   return charcount_to_bytecount (XSTRING_DATA (string), ccpos);
1372 }
1373
1374 void
1375 get_string_range_char (Lisp_Object string, Lisp_Object from, Lisp_Object to,
1376                        Charcount *from_out, Charcount *to_out,
1377                        unsigned int flags)
1378 {
1379   Charcount min_allowed = 0;
1380   Charcount max_allowed = XSTRING_CHAR_LENGTH (string);
1381
1382   if (NILP (from) && (flags & GB_ALLOW_NIL))
1383     *from_out = min_allowed;
1384   else
1385     *from_out = get_string_pos_char_1 (string, from,
1386                                        flags | GB_NO_ERROR_IF_BAD,
1387                                        max_allowed);
1388
1389   if (NILP (to) && (flags & GB_ALLOW_NIL))
1390     *to_out = max_allowed;
1391   else
1392     *to_out = get_string_pos_char_1 (string, to,
1393                                      flags | GB_NO_ERROR_IF_BAD,
1394                                      max_allowed);
1395
1396   if ((*from_out < 0 || *to_out < 0) && !(flags & GB_NO_ERROR_IF_BAD))
1397     args_out_of_range_3 (string, from, to);
1398
1399   if (*from_out >= 0 && *to_out >= 0 && *from_out > *to_out)
1400     {
1401       if (flags & GB_CHECK_ORDER)
1402         signal_simple_error_2 ("start greater than end", from, to);
1403       else
1404         {
1405           Bufpos temp = *from_out;
1406           *from_out = *to_out;
1407           *to_out = temp;
1408         }
1409     }
1410 }
1411
1412 void
1413 get_string_range_byte (Lisp_Object string, Lisp_Object from, Lisp_Object to,
1414                        Bytecount *from_out, Bytecount *to_out,
1415                        unsigned int flags)
1416 {
1417   Charcount s, e;
1418
1419   get_string_range_char (string, from, to, &s, &e, flags);
1420   if (s >= 0)
1421     *from_out = charcount_to_bytecount (XSTRING_DATA (string), s);
1422   else /* could happen with GB_NO_ERROR_IF_BAD */
1423     *from_out = -1;
1424   if (e >= 0)
1425     *to_out = charcount_to_bytecount (XSTRING_DATA (string), e);
1426   else
1427     *to_out = -1;
1428
1429 }
1430
1431 Bufpos
1432 get_buffer_or_string_pos_char (Lisp_Object object, Lisp_Object pos,
1433                                unsigned int flags)
1434 {
1435   return STRINGP (object) ?
1436     get_string_pos_char (object, pos, flags) :
1437     get_buffer_pos_char (XBUFFER (object), pos, flags);
1438 }
1439
1440 Bytind
1441 get_buffer_or_string_pos_byte (Lisp_Object object, Lisp_Object pos,
1442                                unsigned int flags)
1443 {
1444   return STRINGP (object) ?
1445     get_string_pos_byte (object, pos, flags) :
1446     get_buffer_pos_byte (XBUFFER (object), pos, flags);
1447 }
1448
1449 void
1450 get_buffer_or_string_range_char (Lisp_Object object, Lisp_Object from,
1451                                  Lisp_Object to, Bufpos *from_out,
1452                                  Bufpos *to_out, unsigned int flags)
1453 {
1454   if (STRINGP (object))
1455     get_string_range_char (object, from, to, from_out, to_out, flags);
1456   else
1457     get_buffer_range_char (XBUFFER (object), from, to, from_out, to_out, flags);
1458 }
1459
1460 void
1461 get_buffer_or_string_range_byte (Lisp_Object object, Lisp_Object from,
1462                                  Lisp_Object to, Bytind *from_out,
1463                                  Bytind *to_out, unsigned int flags)
1464 {
1465   if (STRINGP (object))
1466     get_string_range_byte (object, from, to, from_out, to_out, flags);
1467   else
1468     get_buffer_range_byte (XBUFFER (object), from, to, from_out, to_out, flags);
1469 }
1470
1471 Bufpos
1472 buffer_or_string_accessible_begin_char (Lisp_Object object)
1473 {
1474   return STRINGP (object) ? 0 : BUF_BEGV (XBUFFER (object));
1475 }
1476
1477 Bufpos
1478 buffer_or_string_accessible_end_char (Lisp_Object object)
1479 {
1480   return STRINGP (object) ?
1481     XSTRING_CHAR_LENGTH (object) : BUF_ZV (XBUFFER (object));
1482 }
1483
1484 Bytind
1485 buffer_or_string_accessible_begin_byte (Lisp_Object object)
1486 {
1487   return STRINGP (object) ? 0 : BI_BUF_BEGV (XBUFFER (object));
1488 }
1489
1490 Bytind
1491 buffer_or_string_accessible_end_byte (Lisp_Object object)
1492 {
1493   return STRINGP (object) ?
1494     XSTRING_LENGTH (object) : BI_BUF_ZV (XBUFFER (object));
1495 }
1496
1497 Bufpos
1498 buffer_or_string_absolute_begin_char (Lisp_Object object)
1499 {
1500   return STRINGP (object) ? 0 : BUF_BEG (XBUFFER (object));
1501 }
1502
1503 Bufpos
1504 buffer_or_string_absolute_end_char (Lisp_Object object)
1505 {
1506   return STRINGP (object) ?
1507     XSTRING_CHAR_LENGTH (object) : BUF_Z (XBUFFER (object));
1508 }
1509
1510 Bytind
1511 buffer_or_string_absolute_begin_byte (Lisp_Object object)
1512 {
1513   return STRINGP (object) ? 0 : BI_BUF_BEG (XBUFFER (object));
1514 }
1515
1516 Bytind
1517 buffer_or_string_absolute_end_byte (Lisp_Object object)
1518 {
1519   return STRINGP (object) ?
1520     XSTRING_LENGTH (object) : BI_BUF_Z (XBUFFER (object));
1521 }
1522
1523 \f
1524 /************************************************************************/
1525 /*                     point and marker adjustment                      */
1526 /************************************************************************/
1527
1528 /* just_set_point() is the only place `PT' is an lvalue in all of emacs.
1529    This function is called from set_buffer_point(), which is the function
1530    that the SET_PT and BUF_SET_PT macros expand into, and from the
1531    routines below that insert and delete text. (This is in cases where
1532    the point marker logically doesn't move but PT (being a byte index)
1533    needs to get adjusted.) */
1534
1535 /* Set point to a specified value.  This is used only when the value
1536    of point changes due to an insert or delete; it does not represent
1537    a conceptual change in point as a marker.  In particular, point is
1538    not crossing any interval boundaries, so there's no need to use the
1539    usual SET_PT macro.  In fact it would be incorrect to do so, because
1540    either the old or the new value of point is out of synch with the
1541    current set of intervals.  */
1542
1543 /* This gets called more than enough to make the function call
1544    overhead a significant factor so we've turned it into a macro. */
1545 #define JUST_SET_POINT(buf, bufpos, ind)        \
1546 do                                              \
1547 {                                               \
1548   buf->bufpt = (bufpos);                        \
1549   buf->pt = (ind);                              \
1550 } while (0)
1551
1552 /* Set a buffer's point. */
1553
1554 void
1555 set_buffer_point (struct buffer *buf, Bufpos bufpos, Bytind bytpos)
1556 {
1557   assert (bytpos >= BI_BUF_BEGV (buf) && bytpos <= BI_BUF_ZV (buf));
1558   if (bytpos == BI_BUF_PT (buf))
1559     return;
1560   JUST_SET_POINT (buf, bufpos, bytpos);
1561   MARK_POINT_CHANGED;
1562   assert (MARKERP (buf->point_marker));
1563   XMARKER (buf->point_marker)->memind =
1564     bytind_to_memind (buf, bytpos);
1565
1566   /* FSF makes sure that PT is not being set within invisible text.
1567      However, this is the wrong place for that check.  The check
1568      should happen only at the next redisplay. */
1569
1570   /* Some old coder said:
1571
1572      "If there were to be hooks which were run when point entered/left an
1573      extent, this would be the place to put them.
1574
1575      However, it's probably the case that such hooks should be implemented
1576      using a post-command-hook instead, to avoid running the hooks as a
1577      result of intermediate motion inside of save-excursions, for example."
1578
1579      I definitely agree with this.  PT gets moved all over the place
1580      and it would be a Bad Thing for any hooks to get called, both for
1581      the reason above and because many callers are not prepared for
1582      a GC within this function. --ben
1583    */
1584 }
1585
1586 /* Do the correct marker-like adjustment on MPOS (see below).  FROM, TO,
1587    and AMOUNT are as in adjust_markers().  If MPOS doesn't need to be
1588    adjusted, nothing will happen. */
1589 Memind
1590 do_marker_adjustment (Memind mpos, Memind from,
1591                       Memind to, Bytecount amount)
1592 {
1593   if (amount > 0)
1594     {
1595       if (mpos > to && mpos < to + amount)
1596         mpos = to + amount;
1597     }
1598   else
1599     {
1600       if (mpos > from + amount && mpos <= from)
1601         mpos = from + amount;
1602     }
1603   if (mpos > from && mpos <= to)
1604     mpos += amount;
1605   return mpos;
1606 }
1607
1608 /* Do the following:
1609
1610    (1) Add `amount' to the position of every marker in the current buffer
1611    whose current position is between `from' (exclusive) and `to' (inclusive).
1612
1613    (2) Also, any markers past the outside of that interval, in the direction
1614    of adjustment, are first moved back to the near end of the interval
1615    and then adjusted by `amount'.
1616
1617    This function is called in two different cases: when a region of
1618    characters adjacent to the gap is moved, causing the gap to shift
1619    to the other side of the region (in this case, `from' and `to'
1620    point to the old position of the region and there should be no
1621    markers affected by (2) because they would be inside the gap),
1622    or when a region of characters adjacent to the gap is wiped out,
1623    causing the gap to increase to include the region (in this case,
1624    `from' and `to' are the same, both pointing to the boundary
1625    between the gap and the deleted region, and there are no markers
1626    affected by (1)).
1627
1628    The reason for the use of exclusive and inclusive is that markers at
1629    the gap always sit at the beginning, not at the end.
1630 */
1631
1632 static void
1633 adjust_markers (struct buffer *buf, Memind from, Memind to,
1634                 Bytecount amount)
1635 {
1636   Lisp_Marker *m;
1637
1638   for (m = BUF_MARKERS (buf); m; m = marker_next (m))
1639     m->memind = do_marker_adjustment (m->memind, from, to, amount);
1640 }
1641
1642 /* Adjust markers whose insertion-type is t
1643    for an insertion of AMOUNT characters at POS.  */
1644
1645 static void
1646 adjust_markers_for_insert (struct buffer *buf, Memind ind, Bytecount amount)
1647 {
1648   Lisp_Marker *m;
1649
1650   for (m = BUF_MARKERS (buf); m; m = marker_next (m))
1651     {
1652       if (m->insertion_type && m->memind == ind)
1653         m->memind += amount;
1654     }
1655 }
1656
1657 \f
1658 /************************************************************************/
1659 /*                  Routines for dealing with the gap                   */
1660 /************************************************************************/
1661
1662 /* maximum amount of memory moved in a single chunk.  Increasing this
1663    value improves gap-motion efficiency but decreases QUIT responsiveness
1664    time.  Was 32000 but today's processors are faster and files are
1665    bigger.  --ben */
1666 #define GAP_MOVE_CHUNK 300000
1667
1668 /* Move the gap to POS, which is less than the current GPT. */
1669
1670 static void
1671 gap_left (struct buffer *buf, Bytind pos)
1672 {
1673   Bufbyte *to, *from;
1674   Bytecount i;
1675   Bytind new_s1;
1676   struct buffer *mbuf;
1677   Lisp_Object bufcons;
1678
1679   from = BUF_GPT_ADDR (buf);
1680   to = from + BUF_GAP_SIZE (buf);
1681   new_s1 = BI_BUF_GPT (buf);
1682
1683   /* Now copy the characters.  To move the gap down,
1684      copy characters up.  */
1685
1686   while (1)
1687     {
1688       /* I gets number of characters left to copy.  */
1689       i = new_s1 - pos;
1690       if (i == 0)
1691         break;
1692       /* If a quit is requested, stop copying now.
1693          Change POS to be where we have actually moved the gap to.  */
1694       if (QUITP)
1695         {
1696           pos = new_s1;
1697           break;
1698         }
1699       /* Move at most GAP_MOVE_CHUNK chars before checking again for a quit. */
1700       if (i > GAP_MOVE_CHUNK)
1701         i = GAP_MOVE_CHUNK;
1702
1703       if (i >= 128)
1704         {
1705           new_s1 -= i;
1706           from   -= i;
1707           to     -= i;
1708           memmove (to, from, i);
1709         }
1710       else
1711         {
1712           new_s1 -= i;
1713           while (--i >= 0)
1714             *--to = *--from;
1715         }
1716     }
1717
1718   /* Adjust markers, and buffer data structure, to put the gap at POS.
1719      POS is where the loop above stopped, which may be what was specified
1720      or may be where a quit was detected.  */
1721   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
1722     {
1723       adjust_markers (mbuf, pos, BI_BUF_GPT (mbuf), BUF_GAP_SIZE (mbuf));
1724     }
1725   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
1726     {
1727       adjust_extents (make_buffer (mbuf), pos, BI_BUF_GPT (mbuf),
1728                       BUF_GAP_SIZE (mbuf));
1729     }
1730   SET_BI_BUF_GPT (buf, pos);
1731   SET_GAP_SENTINEL (buf);
1732 #ifdef ERROR_CHECK_EXTENTS
1733   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
1734     {
1735       sledgehammer_extent_check (make_buffer (mbuf));
1736     }
1737 #endif
1738   QUIT;
1739 }
1740
1741 static void
1742 gap_right (struct buffer *buf, Bytind pos)
1743 {
1744   Bufbyte *to, *from;
1745   Bytecount i;
1746   Bytind new_s1;
1747   struct buffer *mbuf;
1748   Lisp_Object bufcons;
1749
1750   to = BUF_GPT_ADDR (buf);
1751   from = to + BUF_GAP_SIZE (buf);
1752   new_s1 = BI_BUF_GPT (buf);
1753
1754   /* Now copy the characters.  To move the gap up,
1755      copy characters down.  */
1756
1757   while (1)
1758     {
1759       /* I gets number of characters left to copy.  */
1760       i = pos - new_s1;
1761       if (i == 0)
1762         break;
1763       /* If a quit is requested, stop copying now.
1764          Change POS to be where we have actually moved the gap to.  */
1765       if (QUITP)
1766         {
1767           pos = new_s1;
1768           break;
1769         }
1770       /* Move at most GAP_MOVE_CHUNK chars before checking again for a quit. */
1771       if (i > GAP_MOVE_CHUNK)
1772         i = GAP_MOVE_CHUNK;
1773
1774       if (i >= 128)
1775         {
1776           new_s1 += i;
1777           memmove (to, from, i);
1778           from += i;
1779           to   += i;
1780         }
1781       else
1782         {
1783           new_s1 += i;
1784           while (--i >= 0)
1785             *to++ = *from++;
1786         }
1787     }
1788
1789   {
1790     int gsize = BUF_GAP_SIZE (buf);
1791     MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
1792       {
1793         adjust_markers (mbuf, BI_BUF_GPT (mbuf) + gsize, pos + gsize, - gsize);
1794       }
1795     MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
1796       {
1797         adjust_extents (make_buffer (mbuf), BI_BUF_GPT (mbuf) + gsize,
1798                         pos + gsize, - gsize);
1799       }
1800     SET_BI_BUF_GPT (buf, pos);
1801     SET_GAP_SENTINEL (buf);
1802 #ifdef ERROR_CHECK_EXTENTS
1803     MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
1804       {
1805         sledgehammer_extent_check (make_buffer (mbuf));
1806       }
1807 #endif
1808   }
1809   if (pos == BI_BUF_Z (buf))
1810     {
1811       /* merge gap with end gap */
1812
1813       SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + BUF_END_GAP_SIZE (buf));
1814       SET_BUF_END_GAP_SIZE (buf, 0);
1815       SET_END_SENTINEL (buf);
1816     }
1817
1818   QUIT;
1819 }
1820
1821 /* Move gap to position `pos'.
1822    Note that this can quit!  */
1823
1824 static void
1825 move_gap (struct buffer *buf, Bytind pos)
1826 {
1827   if (! BUF_BEG_ADDR (buf))
1828     ABORT ();
1829   if (pos < BI_BUF_GPT (buf))
1830     gap_left (buf, pos);
1831   else if (pos > BI_BUF_GPT (buf))
1832     gap_right (buf, pos);
1833 }
1834
1835 /* Merge the end gap into the gap */
1836
1837 static void
1838 merge_gap_with_end_gap (struct buffer *buf)
1839 {
1840   Lisp_Object tem;
1841   Bytind real_gap_loc;
1842   Bytecount old_gap_size;
1843   Bytecount increment;
1844
1845   increment = BUF_END_GAP_SIZE (buf);
1846   SET_BUF_END_GAP_SIZE (buf, 0);
1847
1848   if (increment > 0)
1849     {
1850       /* Prevent quitting in move_gap.  */
1851       tem = Vinhibit_quit;
1852       Vinhibit_quit = Qt;
1853
1854       real_gap_loc = BI_BUF_GPT (buf);
1855       old_gap_size = BUF_GAP_SIZE (buf);
1856
1857       /* Pretend the end gap is the gap */
1858       SET_BI_BUF_GPT (buf, BI_BUF_Z (buf) + BUF_GAP_SIZE (buf));
1859       SET_BUF_GAP_SIZE (buf, increment);
1860
1861       /* Move the new gap down to be consecutive with the end of the old one.
1862          This adjusts the markers properly too.  */
1863       gap_left (buf, real_gap_loc + old_gap_size);
1864
1865       /* Now combine the two into one large gap.  */
1866       SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + old_gap_size);
1867       SET_BI_BUF_GPT (buf, real_gap_loc);
1868       SET_GAP_SENTINEL (buf);
1869
1870       /* We changed the total size of the buffer (including gap),
1871          so we need to fix up the end sentinel. */
1872       SET_END_SENTINEL (buf);
1873
1874       Vinhibit_quit = tem;
1875     }
1876 }
1877
1878 /* Make the gap INCREMENT bytes longer.  */
1879
1880 static void
1881 make_gap (struct buffer *buf, Bytecount increment)
1882 {
1883   Bufbyte *result;
1884   Lisp_Object tem;
1885   Bytind real_gap_loc;
1886   Bytecount old_gap_size;
1887
1888   /* If we have to get more space, get enough to last a while.  We use
1889      a geometric progression that saves on realloc space. */
1890   increment += 2000 + ((BI_BUF_Z (buf) - BI_BUF_BEG (buf)) / 8);
1891
1892   if (increment > BUF_END_GAP_SIZE (buf))
1893     {
1894       /* Don't allow a buffer size that won't fit in an int
1895          even if it will fit in a Lisp integer.
1896          That won't work because so many places use `int'.  */
1897
1898       if (BUF_Z (buf) - BUF_BEG (buf) + BUF_GAP_SIZE (buf) + increment
1899           > EMACS_INT_MAX)
1900         error ("Maximum buffer size exceeded");
1901
1902       result = BUFFER_REALLOC (buf->text->beg,
1903                                BI_BUF_Z (buf) - BI_BUF_BEG (buf) +
1904                                BUF_GAP_SIZE (buf) + increment +
1905                                BUF_END_SENTINEL_SIZE);
1906       if (result == 0)
1907         memory_full ();
1908
1909       SET_BUF_BEG_ADDR (buf, result);
1910     }
1911   else
1912     increment = BUF_END_GAP_SIZE (buf);
1913
1914   /* Prevent quitting in move_gap.  */
1915   tem = Vinhibit_quit;
1916   Vinhibit_quit = Qt;
1917
1918   real_gap_loc = BI_BUF_GPT (buf);
1919   old_gap_size = BUF_GAP_SIZE (buf);
1920
1921   /* Call the newly allocated space a gap at the end of the whole space.  */
1922   SET_BI_BUF_GPT (buf, BI_BUF_Z (buf) + BUF_GAP_SIZE (buf));
1923   SET_BUF_GAP_SIZE (buf, increment);
1924
1925   SET_BUF_END_GAP_SIZE (buf, 0);
1926
1927   /* Move the new gap down to be consecutive with the end of the old one.
1928      This adjusts the markers properly too.  */
1929   gap_left (buf, real_gap_loc + old_gap_size);
1930
1931   /* Now combine the two into one large gap.  */
1932   SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + old_gap_size);
1933   SET_BI_BUF_GPT (buf, real_gap_loc);
1934   SET_GAP_SENTINEL (buf);
1935
1936   /* We changed the total size of the buffer (including gap),
1937      so we need to fix up the end sentinel. */
1938   SET_END_SENTINEL (buf);
1939
1940   Vinhibit_quit = tem;
1941 }
1942
1943 \f
1944 /************************************************************************/
1945 /*                     Before/after-change processing                   */
1946 /************************************************************************/
1947
1948 /* Those magic changes ... */
1949
1950 static void
1951 buffer_signal_changed_region (struct buffer *buf, Bufpos start,
1952                               Bufpos end)
1953 {
1954   /* The changed region is recorded as the number of unchanged
1955      characters from the beginning and from the end of the
1956      buffer.  This obviates much of the need of shifting the
1957      region around to compensate for insertions and deletions.
1958      */
1959   if (buf->changes->begin_unchanged < 0 ||
1960       buf->changes->begin_unchanged > start - BUF_BEG (buf))
1961     buf->changes->begin_unchanged = start - BUF_BEG (buf);
1962   if (buf->changes->end_unchanged < 0 ||
1963       buf->changes->end_unchanged > BUF_Z (buf) - end)
1964     buf->changes->end_unchanged = BUF_Z (buf) - end;
1965 }
1966
1967 void
1968 buffer_extent_signal_changed_region (struct buffer *buf, Bufpos start,
1969                                      Bufpos end)
1970 {
1971   if (buf->changes->begin_extent_unchanged < 0 ||
1972       buf->changes->begin_extent_unchanged > start - BUF_BEG (buf))
1973     buf->changes->begin_extent_unchanged = start - BUF_BEG (buf);
1974   if (buf->changes->end_extent_unchanged < 0 ||
1975       buf->changes->end_extent_unchanged > BUF_Z (buf) - end)
1976     buf->changes->end_extent_unchanged = BUF_Z (buf) - end;
1977 }
1978
1979 void
1980 buffer_reset_changes (struct buffer *buf)
1981 {
1982   buf->changes->begin_unchanged = -1;
1983   buf->changes->end_unchanged = -1;
1984   buf->changes->begin_extent_unchanged = -1;
1985   buf->changes->end_extent_unchanged = -1;
1986   buf->changes->newline_was_deleted = 0;
1987 }
1988
1989 static void
1990 signal_after_change (struct buffer *buf, Bufpos start, Bufpos orig_end,
1991                      Bufpos new_end);
1992
1993
1994 /* Call the after-change-functions according to the changes made so far
1995    and treat all further changes as single until the outermost
1996    multiple change exits.  This is called when the outermost multiple
1997    change exits and when someone is trying to make a change that violates
1998    the constraints specified in begin_multiple_change(), typically
1999    when nested multiple-change sessions occur. (There are smarter ways of
2000    dealing with nested multiple changes, but these rarely occur so there's
2001    probably no point in it.) */
2002
2003 /* #### This needs to keep track of what actually changed and only
2004    call the after-change functions on that region. */
2005
2006 static void
2007 cancel_multiple_change (struct buffer *buf)
2008 {
2009   /* This function can GC */
2010   /* Call the after-change-functions except when they've already been
2011      called or when there were no changes made to the buffer at all. */
2012   if (buf->text->changes->mc_begin != 0 &&
2013       buf->text->changes->mc_begin_signaled)
2014     {
2015       Bufpos real_mc_begin = buf->text->changes->mc_begin;
2016       buf->text->changes->mc_begin = 0;
2017
2018       signal_after_change (buf, real_mc_begin, buf->text->changes->mc_orig_end,
2019                            buf->text->changes->mc_new_end);
2020     }
2021   else
2022     {
2023       buf->text->changes->mc_begin = 0;
2024     }
2025 }
2026
2027 /* this is an unwind_protect, to ensure that the after-change-functions
2028    get called even in a non-local exit. */
2029
2030 static Lisp_Object
2031 multiple_change_finish_up (Lisp_Object buffer)
2032 {
2033   struct buffer *buf = XBUFFER (buffer);
2034
2035   /* #### I don't know whether or not it should even be possible to
2036      get here with a dead buffer (though given how it is called I can
2037      see how it might be).  In any case, there isn't time before 19.14
2038      to find out. */
2039   if (!BUFFER_LIVE_P (buf))
2040     return Qnil;
2041
2042   /* This function can GC */
2043   buf->text->changes->in_multiple_change = 0; /* do this first so that
2044                                                  errors in the after-change
2045                                                  functions don't mess things
2046                                                  up. */
2047   cancel_multiple_change (buf);
2048   return Qnil;
2049 }
2050
2051 /* Call this function when you're about to make a number of buffer changes
2052    that should be considered a single change. (e.g. `replace-match' calls
2053    this.) You need to specify the START and END of the region that is
2054    going to be changed so that the before-change-functions are called
2055    with the correct arguments.  The after-change region is calculated
2056    automatically, however, and if changes somehow or other happen outside
2057    of the specified region, that will also be handled correctly.
2058
2059    begin_multiple_change() returns a number (actually a specpdl depth)
2060    that you must pass to end_multiple_change() when you are done.
2061
2062    FSF Emacs 20 implements a similar feature, accessible from Lisp
2063    through a `combine-after-change-calls' special form, which is
2064    essentially equivalent to this function.  We should consider
2065    whether we want to introduce a similar Lisp form.  */
2066
2067 int
2068 begin_multiple_change (struct buffer *buf, Bufpos start, Bufpos end)
2069 {
2070   /* This function can GC */
2071   int count = -1;
2072   if (buf->text->changes->in_multiple_change)
2073     {
2074       if (buf->text->changes->mc_begin != 0 &&
2075           (start < buf->text->changes->mc_begin ||
2076            end > buf->text->changes->mc_new_end))
2077         cancel_multiple_change (buf);
2078     }
2079   else
2080     {
2081       Lisp_Object buffer;
2082
2083       buf->text->changes->mc_begin = start;
2084       buf->text->changes->mc_orig_end = buf->text->changes->mc_new_end = end;
2085       buf->text->changes->mc_begin_signaled = 0;
2086       count = specpdl_depth ();
2087       XSETBUFFER (buffer, buf);
2088       record_unwind_protect (multiple_change_finish_up, buffer);
2089     }
2090   buf->text->changes->in_multiple_change++;
2091   /* We don't call before-change-functions until signal_before_change()
2092      is called, in case there is a read-only or other error. */
2093   return count;
2094 }
2095
2096 void
2097 end_multiple_change (struct buffer *buf, int count)
2098 {
2099   assert (buf->text->changes->in_multiple_change > 0);
2100   buf->text->changes->in_multiple_change--;
2101   if (!buf->text->changes->in_multiple_change)
2102     unbind_to (count, Qnil);
2103 }
2104
2105 static int inside_change_hook;
2106
2107 static Lisp_Object
2108 change_function_restore (Lisp_Object buffer)
2109 {
2110   /* We should first reset the variable and then change the buffer,
2111      because Fset_buffer() can throw.  */
2112   inside_change_hook = 0;
2113   if (XBUFFER (buffer) != current_buffer)
2114     Fset_buffer (buffer);
2115   return Qnil;
2116 }
2117
2118 static int in_first_change;
2119
2120 static Lisp_Object
2121 first_change_hook_restore (Lisp_Object buffer)
2122 {
2123   in_first_change = 0;
2124   Fset_buffer (buffer);
2125   return Qnil;
2126 }
2127
2128 /* Signal an initial modification to the buffer.  */
2129
2130 static void
2131 signal_first_change (struct buffer *buf)
2132 {
2133   /* This function can GC */
2134   Lisp_Object buffer;
2135   XSETBUFFER (buffer, current_buffer);
2136
2137   if (!in_first_change)
2138     {
2139       if (!NILP (symbol_value_in_buffer (Qfirst_change_hook, buffer)))
2140         {
2141           int speccount = specpdl_depth ();
2142           record_unwind_protect (first_change_hook_restore, buffer);
2143           set_buffer_internal (buf);
2144           in_first_change = 1;
2145           run_hook (Qfirst_change_hook);
2146           unbind_to (speccount, Qnil);
2147         }
2148     }
2149 }
2150
2151 /* Signal a change to the buffer immediately before it happens.
2152    START and END are the bounds of the text to be changed. */
2153
2154 static void
2155 signal_before_change (struct buffer *buf, Bufpos start, Bufpos end)
2156 {
2157   /* This function can GC */
2158   struct buffer *mbuf;
2159   Lisp_Object bufcons;
2160
2161   if (!inside_change_hook)
2162     {
2163       Lisp_Object buffer;
2164       int speccount;
2165
2166       /* Are we in a multiple-change session? */
2167       if (buf->text->changes->in_multiple_change &&
2168           buf->text->changes->mc_begin != 0)
2169         {
2170           /* If we're violating the constraints of the session,
2171              call the after-change-functions as necessary for the
2172              changes already made and treat further changes as
2173              single. */
2174           if (start < buf->text->changes->mc_begin ||
2175               end > buf->text->changes->mc_new_end)
2176             cancel_multiple_change (buf);
2177           /* Do nothing if this is not the first change in the session. */
2178           else if (buf->text->changes->mc_begin_signaled)
2179             return;
2180           else
2181             {
2182               /* First time through; call the before-change-functions
2183                  specifying the entire region to be changed. (Note that
2184                  we didn't call before-change-functions in
2185                  begin_multiple_change() because the buffer might be
2186                  read-only, etc.) */
2187               start = buf->text->changes->mc_begin;
2188               end = buf->text->changes->mc_new_end;
2189             }
2190         }
2191
2192       /* If buffer is unmodified, run a special hook for that case.  */
2193       if (BUF_SAVE_MODIFF (buf) >= BUF_MODIFF (buf))
2194         {
2195           MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2196             {
2197               signal_first_change (mbuf);
2198             }
2199         }
2200
2201       /* Now in any case run the before-change-functions if any.  */
2202       speccount = specpdl_depth ();
2203       record_unwind_protect (change_function_restore, Fcurrent_buffer ());
2204       inside_change_hook = 1;
2205
2206       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2207         {
2208           XSETBUFFER (buffer, mbuf);
2209           if (!NILP (symbol_value_in_buffer (Qbefore_change_functions, buffer))
2210               /* Obsolete, for compatibility */
2211               || !NILP (symbol_value_in_buffer (Qbefore_change_function, buffer)))
2212             {
2213               set_buffer_internal (buf);
2214               va_run_hook_with_args (Qbefore_change_functions, 2,
2215                                      make_int (start), make_int (end));
2216               /* Obsolete, for compatibility */
2217               va_run_hook_with_args (Qbefore_change_function, 2,
2218                                      make_int (start), make_int (end));
2219             }
2220         }
2221
2222       /* Make sure endpoints remain valid.  before-change-functions
2223          might have modified the buffer. */
2224       if (start < BUF_BEGV (buf)) start = BUF_BEGV (buf);
2225       if (start > BUF_ZV (buf))   start = BUF_ZV (buf);
2226       if (end < BUF_BEGV (buf)) end = BUF_BEGV (buf);
2227       if (end > BUF_ZV (buf))   end = BUF_ZV (buf);
2228
2229       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2230         {
2231           XSETBUFFER (buffer, mbuf);
2232           report_extent_modification (buffer, start, end, 0);
2233         }
2234       unbind_to (speccount, Qnil);
2235
2236       /* Only now do we indicate that the before-change-functions have
2237          been called, in case some function throws out. */
2238       buf->text->changes->mc_begin_signaled = 1;
2239     }
2240 }
2241
2242 /* Signal a change immediately after it happens.
2243    START is the bufpos of the start of the changed text.
2244    ORIG_END is the bufpos of the end of the before-changed text.
2245    NEW_END is the bufpos of the end of the after-changed text.
2246  */
2247
2248 static void
2249 signal_after_change (struct buffer *buf, Bufpos start, Bufpos orig_end,
2250                      Bufpos new_end)
2251 {
2252   /* This function can GC */
2253   struct buffer *mbuf;
2254   Lisp_Object bufcons;
2255
2256   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2257     {
2258       /* always do this. */
2259       buffer_signal_changed_region (mbuf, start, new_end);
2260     }
2261   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2262     {
2263       /* #### This seems inefficient.  Wouldn't it be better to just
2264          keep one cache per base buffer?  */
2265       font_lock_maybe_update_syntactic_caches (mbuf, start, orig_end, new_end);
2266     }
2267
2268   if (!inside_change_hook)
2269     {
2270       Lisp_Object buffer;
2271       int speccount;
2272
2273       if (buf->text->changes->in_multiple_change &&
2274           buf->text->changes->mc_begin != 0)
2275         {
2276           assert (start >= buf->text->changes->mc_begin &&
2277                   start <= buf->text->changes->mc_new_end);
2278           assert (orig_end >= buf->text->changes->mc_begin &&
2279                   orig_end <= buf->text->changes->mc_new_end);
2280           buf->text->changes->mc_new_end += new_end - orig_end;
2281           return; /* after-change-functions signalled when all changes done */
2282         }
2283
2284       speccount = specpdl_depth ();
2285       record_unwind_protect (change_function_restore, Fcurrent_buffer ());
2286       inside_change_hook = 1;
2287       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2288         {
2289           XSETBUFFER (buffer, mbuf);
2290
2291           if (!NILP (symbol_value_in_buffer (Qafter_change_functions, buffer))
2292               /* Obsolete, for compatibility */
2293               || !NILP (symbol_value_in_buffer (Qafter_change_function, buffer)))
2294             {
2295               set_buffer_internal (buf);
2296               /* The actual after-change functions take slightly
2297                  different arguments than what we were passed. */
2298               va_run_hook_with_args (Qafter_change_functions, 3,
2299                                      make_int (start), make_int (new_end),
2300                                      make_int (orig_end - start));
2301               /* Obsolete, for compatibility */
2302               va_run_hook_with_args (Qafter_change_function, 3,
2303                                      make_int (start), make_int (new_end),
2304                                      make_int (orig_end - start));
2305             }
2306         }
2307
2308       /* Make sure endpoints remain valid.  after-change-functions
2309          might have modified the buffer. */
2310       if (start < BUF_BEGV (buf)) start = BUF_BEGV (buf);
2311       if (start > BUF_ZV (buf))   start = BUF_ZV (buf);
2312       if (new_end < BUF_BEGV (buf)) new_end = BUF_BEGV (buf);
2313       if (new_end > BUF_ZV (buf))   new_end = BUF_ZV (buf);
2314       if (orig_end < BUF_BEGV (buf)) orig_end = BUF_BEGV (buf);
2315       if (orig_end > BUF_ZV (buf))   orig_end = BUF_ZV (buf);
2316
2317       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2318         {
2319           XSETBUFFER (buffer, mbuf);
2320           report_extent_modification (buffer, start, new_end, 1);
2321         }
2322       unbind_to (speccount, Qnil); /* sets inside_change_hook back to 0 */
2323     }
2324 }
2325
2326 /* Call this if you're about to change the region of BUFFER from START
2327    to END.  This checks the read-only properties of the region, calls
2328    the necessary modification hooks, and warns the next redisplay that
2329    it should pay attention to that area.  */
2330
2331 static void
2332 prepare_to_modify_buffer (struct buffer *buf, Bufpos start, Bufpos end,
2333                           int lockit)
2334 {
2335   /* This function can GC */
2336   /* dmoore - This function can also kill the buffer buf, the current
2337      buffer, and do anything it pleases.  So if you call it, be
2338      careful. */
2339   struct buffer *mbuf;
2340   Lisp_Object buffer, bufcons;
2341   struct gcpro gcpro1;
2342
2343   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2344     {
2345       barf_if_buffer_read_only (mbuf, start, end);
2346     }
2347
2348   /* if this is the first modification, see about locking the buffer's
2349      file */
2350   XSETBUFFER (buffer, buf);
2351   GCPRO1 (buffer);
2352   if (!NILP (buf->filename) && lockit &&
2353       BUF_SAVE_MODIFF (buf) >= BUF_MODIFF (buf))
2354     {
2355       /* At least warn if this file has changed on disk since it was visited.*/
2356       if (NILP (Fverify_visited_file_modtime (buffer))
2357           && !NILP (Ffile_exists_p (buf->filename)))
2358         call1_in_buffer (buf, intern ("ask-user-about-supersession-threat"),
2359                          buf->filename);
2360 #ifdef CLASH_DETECTION
2361       if (!NILP (buf->file_truename))
2362         /* Make binding buffer-file-name to nil effective.  */
2363         lock_file (buf->file_truename);
2364 #endif /* not CLASH_DETECTION */
2365     }
2366   UNGCPRO;
2367
2368   /* #### dmoore - is this reasonable in case of buf being killed above? */
2369   if (!BUFFER_LIVE_P (buf))
2370     return;
2371
2372   signal_before_change (buf, start, end);
2373
2374 #ifdef REGION_CACHE_NEEDS_WORK
2375   if (buf->newline_cache)
2376     invalidate_region_cache (buf,
2377                              buf->newline_cache,
2378                              start - BUF_BEG (buf), BUF_Z (buf) - end);
2379   if (buf->width_run_cache)
2380     invalidate_region_cache (buf,
2381                              buf->width_run_cache,
2382                              start - BUF_BEG (buf), BUF_Z (buf) - end);
2383 #endif
2384
2385 #if 0 /* FSFmacs */
2386   Vdeactivate_mark = Qt;
2387 #endif
2388
2389   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2390     {
2391       mbuf->point_before_scroll = Qnil;
2392     }
2393 }
2394
2395 \f
2396 /************************************************************************/
2397 /*                        Insertion of strings                          */
2398 /************************************************************************/
2399
2400 void
2401 fixup_internal_substring (const Bufbyte *nonreloc, Lisp_Object reloc,
2402                           Bytecount offset, Bytecount *len)
2403 {
2404   assert ((nonreloc && NILP (reloc)) || (!nonreloc && STRINGP (reloc)));
2405
2406   if (*len < 0)
2407     {
2408       if (nonreloc)
2409         *len = strlen ((const char *) nonreloc) - offset;
2410       else
2411         *len = XSTRING_LENGTH (reloc) - offset;
2412     }
2413 #ifdef ERROR_CHECK_BUFPOS
2414   assert (*len >= 0);
2415   if (STRINGP (reloc))
2416     {
2417       assert (offset >= 0 && offset <= XSTRING_LENGTH (reloc));
2418       assert (offset + *len <= XSTRING_LENGTH (reloc));
2419     }
2420 #endif
2421 }
2422
2423 /* Insert a string into BUF at Bufpos POS.  The string data comes
2424    from one of two sources: constant, non-relocatable data (specified
2425    in NONRELOC), or a Lisp string object (specified in RELOC), which
2426    is relocatable and may have extent data that needs to be copied
2427    into the buffer.  OFFSET and LENGTH specify the substring of the
2428    data that is actually to be inserted.  As a special case, if POS
2429    is -1, insert the string at point and move point to the end of the
2430    string.
2431
2432    Normally, markers at the insertion point end up before the
2433    inserted string.  If INSDEL_BEFORE_MARKERS is set in flags, however,
2434    they end up after the string.
2435
2436    INSDEL_NO_LOCKING is kludgy and is used when insert-file-contents is
2437    visiting a new file; it inhibits the locking checks normally done
2438    before modifying a buffer.  Similar checks were already done
2439    in the higher-level Lisp functions calling insert-file-contents. */
2440
2441 Charcount
2442 buffer_insert_string_1 (struct buffer *buf, Bufpos pos,
2443                         const Bufbyte *nonreloc, Lisp_Object reloc,
2444                         Bytecount offset, Bytecount length,
2445                         int flags)
2446 {
2447   /* This function can GC */
2448   struct gcpro gcpro1;
2449   Bytind ind;
2450   Charcount cclen;
2451   int move_point = 0;
2452   struct buffer *mbuf;
2453   Lisp_Object bufcons;
2454
2455   /* Defensive steps just in case a buffer gets deleted and a calling
2456      function doesn't notice it. */
2457   if (!BUFFER_LIVE_P (buf))
2458     return 0;
2459
2460   fixup_internal_substring (nonreloc, reloc, offset, &length);
2461
2462   if (pos == -1)
2463     {
2464       pos = BUF_PT (buf);
2465       move_point = 1;
2466     }
2467
2468 #ifdef I18N3
2469   /* #### See the comment in print_internal().  If this buffer is marked
2470      as translatable, then Fgettext() should be called on obj if it
2471      is a string. */
2472 #endif
2473
2474   /* Make sure that point-max won't exceed the size of an emacs int. */
2475   if ((length + BUF_Z (buf)) > EMACS_INT_MAX)
2476     error ("Maximum buffer size exceeded");
2477
2478   /* theoretically not necessary -- caller should GCPRO.
2479      #### buffer_insert_from_buffer_1() doesn't!  */
2480   GCPRO1 (reloc);
2481
2482   prepare_to_modify_buffer (buf, pos, pos, !(flags & INSDEL_NO_LOCKING));
2483
2484   /* Defensive steps in case the before-change-functions fuck around */
2485   if (!BUFFER_LIVE_P (buf))
2486     {
2487       UNGCPRO;
2488       /* Bad bad pre-change function. */
2489       return 0;
2490     }
2491
2492   /* Make args be valid again.  prepare_to_modify_buffer() might have
2493      modified the buffer. */
2494   if (pos < BUF_BEGV (buf))
2495     pos = BUF_BEGV (buf);
2496   if (pos > BUF_ZV (buf))
2497     pos = BUF_ZV (buf);
2498
2499   /* string may have been relocated up to this point */
2500   if (STRINGP (reloc))
2501     nonreloc = XSTRING_DATA (reloc);
2502
2503   ind = bufpos_to_bytind (buf, pos);
2504   cclen = bytecount_to_charcount (nonreloc + offset, length);
2505
2506   if (ind != BI_BUF_GPT (buf))
2507     /* #### if debug-on-quit is invoked and the user changes the
2508        buffer, bad things can happen.  This is a rampant problem
2509        in Emacs. */
2510     move_gap (buf, ind); /* may QUIT */
2511   if (! GAP_CAN_HOLD_SIZE_P (buf, length))
2512     {
2513       if (BUF_END_GAP_SIZE (buf) >= length)
2514         merge_gap_with_end_gap (buf);
2515       else
2516         make_gap (buf, length - BUF_GAP_SIZE (buf));
2517     }
2518
2519   insert_invalidate_line_number_cache (buf, pos, nonreloc + offset, length);
2520
2521   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2522     {
2523       record_insert (mbuf, pos, cclen);
2524     }
2525
2526   BUF_MODIFF (buf)++;
2527   MARK_BUFFERS_CHANGED;
2528
2529   /* string may have been relocated up to this point */
2530   if (STRINGP (reloc))
2531     nonreloc = XSTRING_DATA (reloc);
2532
2533   memcpy (BUF_GPT_ADDR (buf), nonreloc + offset, length);
2534
2535   SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) - length);
2536   SET_BI_BUF_GPT (buf, BI_BUF_GPT (buf) + length);
2537   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2538     {
2539       SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) + cclen, BI_BUF_ZV (mbuf) + length);
2540     }
2541   SET_BOTH_BUF_Z (buf, BUF_Z (buf) + cclen, BI_BUF_Z (buf) + length);
2542   SET_GAP_SENTINEL (buf);
2543
2544 #ifdef MULE
2545   buffer_mule_signal_inserted_region (buf, pos, length, cclen);
2546 #endif
2547
2548   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2549     {
2550       process_extents_for_insertion (make_buffer (mbuf), ind, length);
2551     }
2552
2553   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2554     {
2555       /* We know the gap is at IND so the cast is OK. */
2556       adjust_markers_for_insert (mbuf, (Memind) ind, length);
2557     }
2558
2559   /* Point logically doesn't move, but may need to be adjusted because
2560      it's a byte index.  point-marker doesn't change because it's a
2561      memory index. */
2562   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2563     {
2564       if (BI_BUF_PT (mbuf) > ind)
2565         JUST_SET_POINT (mbuf, BUF_PT (mbuf) + cclen,
2566                         BI_BUF_PT (mbuf) + length);
2567     }
2568
2569   /* Well, point might move. */
2570   if (move_point)
2571     BI_BUF_SET_PT (buf, ind + length);
2572
2573   if (STRINGP (reloc))
2574     {
2575       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2576         {
2577           splice_in_string_extents (reloc, mbuf, ind, length, offset);
2578         }
2579     }
2580
2581   if (flags & INSDEL_BEFORE_MARKERS)
2582     {
2583       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2584         {
2585           /* ind - 1 is correct because the FROM argument is exclusive.
2586              I formerly used DEC_BYTIND() but that caused problems at the
2587              beginning of the buffer. */
2588           adjust_markers (mbuf, ind - 1, ind, length);
2589         }
2590     }
2591
2592   signal_after_change (buf, pos, pos, pos + cclen);
2593
2594   UNGCPRO;
2595
2596   return cclen;
2597 }
2598
2599
2600 /* The following functions are interfaces onto the above function,
2601    for inserting particular sorts of data.  In all the functions,
2602    BUF and POS specify the buffer and location where the insertion is
2603    to take place. (If POS is -1, text is inserted at point and point
2604    moves forward past the text.) FLAGS is as above. */
2605
2606 Charcount
2607 buffer_insert_raw_string_1 (struct buffer *buf, Bufpos pos,
2608                             const Bufbyte *nonreloc, Bytecount length,
2609                             int flags)
2610 {
2611   /* This function can GC */
2612   return buffer_insert_string_1 (buf, pos, nonreloc, Qnil, 0, length,
2613                                  flags);
2614 }
2615
2616 Charcount
2617 buffer_insert_lisp_string_1 (struct buffer *buf, Bufpos pos, Lisp_Object str,
2618                              int flags)
2619 {
2620   /* This function can GC */
2621 #ifdef ERROR_CHECK_TYPECHECK
2622   assert (STRINGP (str));
2623 #endif
2624   return buffer_insert_string_1 (buf, pos, 0, str, 0,
2625                                  XSTRING_LENGTH (str),
2626                                  flags);
2627 }
2628
2629 /* Insert the null-terminated string S (in external format). */
2630
2631 Charcount
2632 buffer_insert_c_string_1 (struct buffer *buf, Bufpos pos, const char *s,
2633                           int flags)
2634 {
2635   /* This function can GC */
2636   const char *translated = GETTEXT (s);
2637   return buffer_insert_string_1 (buf, pos, (const Bufbyte *) translated, Qnil,
2638                                  0, strlen (translated), flags);
2639 }
2640
2641 Charcount
2642 buffer_insert_emacs_char_1 (struct buffer *buf, Bufpos pos, Emchar ch,
2643                             int flags)
2644 {
2645   /* This function can GC */
2646   Bufbyte str[MAX_EMCHAR_LEN];
2647   Bytecount len = set_charptr_emchar (str, ch);
2648   return buffer_insert_string_1 (buf, pos, str, Qnil, 0, len, flags);
2649 }
2650
2651 Charcount
2652 buffer_insert_c_char_1 (struct buffer *buf, Bufpos pos, char c,
2653                         int flags)
2654 {
2655   /* This function can GC */
2656   return buffer_insert_emacs_char_1 (buf, pos, (Emchar) (unsigned char) c,
2657                                      flags);
2658 }
2659
2660 Charcount
2661 buffer_insert_from_buffer_1 (struct buffer *buf, Bufpos pos,
2662                              struct buffer *buf2, Bufpos pos2,
2663                              Charcount length, int flags)
2664 {
2665   /* This function can GC */
2666   Lisp_Object str = make_string_from_buffer (buf2, pos2, length);
2667   return buffer_insert_string_1 (buf, pos, 0, str, 0,
2668                                  XSTRING_LENGTH (str), flags);
2669 }
2670
2671 \f
2672 /************************************************************************/
2673 /*                        Deletion of ranges                            */
2674 /************************************************************************/
2675
2676 /* Delete characters in buffer from FROM up to (but not including) TO.  */
2677
2678 void
2679 buffer_delete_range (struct buffer *buf, Bufpos from, Bufpos to, int flags)
2680 {
2681   /* This function can GC */
2682   Charcount numdel;
2683   Bytind bi_from, bi_to;
2684   Bytecount bc_numdel;
2685   EMACS_INT shortage;
2686   struct buffer *mbuf;
2687   Lisp_Object bufcons;
2688
2689   /* Defensive steps just in case a buffer gets deleted and a calling
2690      function doesn't notice it. */
2691   if (!BUFFER_LIVE_P (buf))
2692     return;
2693
2694   /* Make args be valid */
2695   if (from < BUF_BEGV (buf))
2696     from = BUF_BEGV (buf);
2697   if (to > BUF_ZV (buf))
2698     to = BUF_ZV (buf);
2699   if ((numdel = to - from) <= 0)
2700     return;
2701
2702   prepare_to_modify_buffer (buf, from, to, !(flags & INSDEL_NO_LOCKING));
2703
2704   /* Defensive steps in case the before-change-functions fuck around */
2705   if (!BUFFER_LIVE_P (buf))
2706     /* Bad bad pre-change function. */
2707     return;
2708
2709   /* Make args be valid again.  prepare_to_modify_buffer() might have
2710      modified the buffer. */
2711   if (from < BUF_BEGV (buf))
2712     from = BUF_BEGV (buf);
2713   if (to > BUF_ZV (buf))
2714     to = BUF_ZV (buf);
2715   if ((numdel = to - from) <= 0)
2716     return;
2717
2718   /* Redisplay needs to know if a newline was in the deleted region.
2719      If we've already marked the changed region as having a deleted
2720      newline there is no use in performing the check. */
2721   if (!buf->changes->newline_was_deleted)
2722     {
2723       scan_buffer (buf, '\n', from, to, 1, &shortage, 1);
2724       if (!shortage)
2725         {
2726           MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2727             {
2728               mbuf->changes->newline_was_deleted = 1;
2729             }
2730         }
2731     }
2732
2733   bi_from = bufpos_to_bytind (buf, from);
2734   bi_to = bufpos_to_bytind (buf, to);
2735   bc_numdel = bi_to - bi_from;
2736
2737   delete_invalidate_line_number_cache (buf, from, to);
2738
2739   if (to == BUF_Z (buf) &&
2740       bi_from > BI_BUF_GPT (buf))
2741     {
2742       /* avoid moving the gap just to delete from the bottom. */
2743
2744       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2745         {
2746           record_delete (mbuf, from, numdel);
2747         }
2748       BUF_MODIFF (buf)++;
2749       MARK_BUFFERS_CHANGED;
2750
2751       /* #### Point used to be modified here, but this causes problems
2752          with MULE, as point is used to calculate bytinds, and if the
2753          offset in bc_numdel causes point to move to a non first-byte
2754          location, causing some other function to throw an assertion
2755          in ASSERT_VALID_BYTIND. I've moved the code to right after
2756          the other movements and adjustments, but before the gap is
2757          moved.  -- jh 970813 */
2758
2759       /* Detach any extents that are completely within the range [FROM, TO],
2760          if the extents are detachable.
2761
2762          This must come AFTER record_delete(), so that the appropriate
2763          extents will be present to be recorded, and BEFORE the gap
2764          size is increased, as otherwise we will be confused about
2765          where the extents end. */
2766       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2767         {
2768           process_extents_for_deletion (make_buffer (mbuf), bi_from, bi_to, 0);
2769         }
2770
2771       /* Relocate all markers pointing into the new, larger gap to
2772          point at the end of the text before the gap.  */
2773       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2774         {
2775           adjust_markers (mbuf,
2776                           (bi_to + BUF_GAP_SIZE (mbuf)),
2777                           (bi_to + BUF_GAP_SIZE (mbuf)),
2778                           (- bc_numdel));
2779         }
2780
2781       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2782         {
2783           /* Relocate any extent endpoints just like markers. */
2784           adjust_extents_for_deletion (make_buffer (mbuf), bi_from, bi_to,
2785                                        BUF_GAP_SIZE (mbuf), bc_numdel, 0);
2786         }
2787
2788       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2789         {
2790           /* Relocate point as if it were a marker.  */
2791           if (bi_from < BI_BUF_PT (mbuf))
2792             {
2793               if (BI_BUF_PT (mbuf) < bi_to)
2794                 JUST_SET_POINT (mbuf, from, bi_from);
2795               else
2796                 JUST_SET_POINT (mbuf, BUF_PT (mbuf) - numdel,
2797                                 BI_BUF_PT (mbuf) - bc_numdel);
2798             }
2799         }
2800
2801       SET_BUF_END_GAP_SIZE (buf, BUF_END_GAP_SIZE (buf) + bc_numdel);
2802
2803       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2804         {
2805           SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) - numdel,
2806                            BI_BUF_ZV (mbuf) - bc_numdel);
2807         }
2808       SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel);
2809       SET_GAP_SENTINEL (buf);
2810     }
2811   else
2812     {
2813       /* Make sure the gap is somewhere in or next to what we are deleting.  */
2814       if (bi_to < BI_BUF_GPT (buf))
2815         gap_left (buf, bi_to);
2816       if (bi_from > BI_BUF_GPT (buf))
2817         gap_right (buf, bi_from);
2818
2819       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2820         {
2821           record_delete (mbuf, from, numdel);
2822         }
2823       BUF_MODIFF (buf)++;
2824       MARK_BUFFERS_CHANGED;
2825
2826       /* #### Point used to be modified here, but this causes problems
2827          with MULE, as point is used to calculate bytinds, and if the
2828          offset in bc_numdel causes point to move to a non first-byte
2829          location, causing some other function to throw an assertion
2830          in ASSERT_VALID_BYTIND. I've moved the code to right after
2831          the other movements and adjustments, but before the gap is
2832          moved.  -- jh 970813 */
2833
2834       /* Detach any extents that are completely within the range [FROM, TO],
2835          if the extents are detachable.
2836
2837          This must come AFTER record_delete(), so that the appropriate extents
2838          will be present to be recorded, and BEFORE the gap size is increased,
2839          as otherwise we will be confused about where the extents end. */
2840       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2841         {
2842           process_extents_for_deletion (make_buffer (mbuf), bi_from, bi_to, 0);
2843         }
2844
2845       /* Relocate all markers pointing into the new, larger gap to
2846          point at the end of the text before the gap.  */
2847       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2848         {
2849           adjust_markers (mbuf,
2850                           (bi_to + BUF_GAP_SIZE (mbuf)),
2851                           (bi_to + BUF_GAP_SIZE (mbuf)),
2852                           (- bc_numdel - BUF_GAP_SIZE (mbuf)));
2853         }
2854
2855       /* Relocate any extent endpoints just like markers. */
2856       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2857         {
2858           adjust_extents_for_deletion (make_buffer (mbuf), bi_from, bi_to,
2859                                        BUF_GAP_SIZE (mbuf),
2860                                        bc_numdel, BUF_GAP_SIZE (mbuf));
2861         }
2862
2863       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2864         {
2865           /* Relocate point as if it were a marker.  */
2866           if (bi_from < BI_BUF_PT (mbuf))
2867             {
2868               if (BI_BUF_PT (mbuf) < bi_to)
2869                 JUST_SET_POINT (mbuf, from, bi_from);
2870               else
2871                 JUST_SET_POINT (mbuf, BUF_PT (mbuf) - numdel,
2872                                 BI_BUF_PT (mbuf) - bc_numdel);
2873             }
2874         }
2875
2876       SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + bc_numdel);
2877       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2878         {
2879           SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) - numdel,
2880                            BI_BUF_ZV (mbuf) - bc_numdel);
2881         }
2882       SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel);
2883       SET_BI_BUF_GPT (buf, bi_from);
2884       SET_GAP_SENTINEL (buf);
2885     }
2886
2887 #ifdef MULE
2888   buffer_mule_signal_deleted_region (buf, from, to, bi_from, bi_to);
2889 #endif
2890
2891 #ifdef ERROR_CHECK_EXTENTS
2892   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2893     {
2894       sledgehammer_extent_check (make_buffer (mbuf));
2895     }
2896 #endif
2897
2898   signal_after_change (buf, from, to, from);
2899 }
2900
2901 \f
2902 /************************************************************************/
2903 /*                    Replacement of characters                         */
2904 /************************************************************************/
2905
2906 /* Replace the character at POS in buffer B with CH. */
2907
2908 void
2909 buffer_replace_char (struct buffer *buf, Bufpos pos, Emchar ch,
2910                      int not_real_change, int force_lock_check)
2911 {
2912   /* This function can GC */
2913   Bufbyte curstr[MAX_EMCHAR_LEN];
2914   Bufbyte newstr[MAX_EMCHAR_LEN];
2915   Bytecount curlen, newlen;
2916
2917   /* Defensive steps just in case a buffer gets deleted and a calling
2918      function doesn't notice it. */
2919   if (!BUFFER_LIVE_P (buf))
2920     return;
2921
2922   curlen = BUF_CHARPTR_COPY_CHAR (buf, pos, curstr);
2923   newlen = set_charptr_emchar (newstr, ch);
2924
2925   if (curlen == newlen)
2926     {
2927       struct buffer *mbuf;
2928       Lisp_Object bufcons;
2929
2930       /* then we can just replace the text. */
2931       prepare_to_modify_buffer (buf, pos, pos + 1,
2932                                 !not_real_change || force_lock_check);
2933       /* Defensive steps in case the before-change-functions fuck around */
2934       if (!BUFFER_LIVE_P (buf))
2935         /* Bad bad pre-change function. */
2936         return;
2937
2938       /* Make args be valid again.  prepare_to_modify_buffer() might have
2939          modified the buffer. */
2940       if (pos < BUF_BEGV (buf))
2941         pos = BUF_BEGV (buf);
2942       if (pos >= BUF_ZV (buf))
2943         pos = BUF_ZV (buf) - 1;
2944       if (pos < BUF_BEGV (buf))
2945         /* no more characters in buffer! */
2946         return;
2947
2948       if (BUF_FETCH_CHAR (buf, pos) == '\n')
2949         {
2950           MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2951             {
2952               mbuf->changes->newline_was_deleted = 1;
2953             }
2954         }
2955       MARK_BUFFERS_CHANGED;
2956       if (!not_real_change)
2957         {
2958           MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2959             {
2960               record_change (mbuf, pos, 1);
2961             }
2962           BUF_MODIFF (buf)++;
2963         }
2964       memcpy (BUF_BYTE_ADDRESS (buf, pos), newstr, newlen);
2965
2966       signal_after_change (buf, pos, pos + 1, pos + 1);
2967
2968       /* We do not have to adjust the Mule data; we just replaced a
2969          character with another of the same number of bytes. */
2970     }
2971   else
2972     {
2973       /*
2974        * Must implement as deletion followed by insertion.
2975        *
2976        * Make a note to move point forward later in the one situation
2977        * where it is needed, a delete/insert one position behind
2978        * point.  Point will drift backward by one position and stay
2979        * there otherwise.
2980        */
2981       int movepoint = (pos == BUF_PT (buf) - 1);
2982
2983       buffer_delete_range (buf, pos, pos + 1, 0);
2984       /* Defensive steps in case the before-change-functions fuck around */
2985       if (!BUFFER_LIVE_P (buf))
2986         /* Bad bad pre-change function. */
2987         return;
2988
2989       /* Make args be valid again.  prepare_to_modify_buffer() might have
2990          modified the buffer. */
2991       if (pos < BUF_BEGV (buf))
2992         pos = BUF_BEGV (buf);
2993       if (pos >= BUF_ZV (buf))
2994         pos = BUF_ZV (buf) - 1;
2995       if (pos < BUF_BEGV (buf))
2996         /* no more characters in buffer! */
2997         return;
2998       /*
2999        * -1 as the pos argument means to move point forward with the
3000        * insertion, which we must do if the deletion moved point
3001        * backward so that it now equals the insertion point.
3002        */
3003       buffer_insert_string_1 (buf, (movepoint ? -1 : pos),
3004                               newstr, Qnil, 0, newlen, 0);
3005     }
3006 }
3007
3008 \f
3009 /************************************************************************/
3010 /*                            Other functions                           */
3011 /************************************************************************/
3012
3013 /* Make a string from a buffer.  This needs to take into account the gap,
3014    and add any necessary extents from the buffer. */
3015
3016 static Lisp_Object
3017 make_string_from_buffer_1 (struct buffer *buf, Bufpos pos, Charcount length,
3018                            int no_extents)
3019 {
3020   /* This function can GC */
3021   Bytind    bi_ind = bufpos_to_bytind (buf, pos);
3022   Bytecount bi_len = bufpos_to_bytind (buf, pos + length) - bi_ind;
3023   Lisp_Object  val = make_uninit_string (bi_len);
3024
3025   struct gcpro gcpro1;
3026   GCPRO1 (val);
3027
3028   if (!no_extents)
3029     add_string_extents (val, buf, bi_ind, bi_len);
3030
3031   {
3032     Bytecount len1 = BI_BUF_GPT (buf) - bi_ind;
3033     Bufbyte *start1 = BI_BUF_BYTE_ADDRESS (buf, bi_ind);
3034     Bufbyte *dest = XSTRING_DATA (val);
3035
3036     if (len1 < 0)
3037       {
3038         /* Completely after gap */
3039         memcpy (dest, start1, bi_len);
3040       }
3041     else if (bi_len <= len1)
3042       {
3043         /* Completely before gap */
3044         memcpy (dest, start1, bi_len);
3045       }
3046     else
3047       {
3048         /* Spans gap */
3049         Bytind pos2 = bi_ind + len1;
3050         Bufbyte *start2 = BI_BUF_BYTE_ADDRESS (buf, pos2);
3051
3052         memcpy (dest, start1, len1);
3053         memcpy (dest + len1, start2, bi_len - len1);
3054       }
3055   }
3056
3057   UNGCPRO;
3058   return val;
3059 }
3060
3061 Lisp_Object
3062 make_string_from_buffer (struct buffer *buf, Bufpos pos, Charcount length)
3063 {
3064   return make_string_from_buffer_1 (buf, pos, length, 0);
3065 }
3066
3067 Lisp_Object
3068 make_string_from_buffer_no_extents (struct buffer *buf, Bufpos pos,
3069                                     Charcount length)
3070 {
3071   return make_string_from_buffer_1 (buf, pos, length, 1);
3072 }
3073
3074 void
3075 barf_if_buffer_read_only (struct buffer *buf, Bufpos from, Bufpos to)
3076 {
3077   Lisp_Object buffer;
3078   Lisp_Object iro;
3079
3080   XSETBUFFER (buffer, buf);
3081  back:
3082   iro = (buf == current_buffer ? Vinhibit_read_only :
3083          symbol_value_in_buffer (Qinhibit_read_only, buffer));
3084   if (!LISTP (iro))
3085     return;
3086   if (NILP (iro) && !NILP (buf->read_only))
3087     {
3088       Fsignal (Qbuffer_read_only, (list1 (buffer)));
3089       goto back;
3090     }
3091   if (from > 0)
3092     {
3093       if (to < 0)
3094         to = from;
3095       verify_extent_modification (buffer,
3096                                   bufpos_to_bytind (buf, from),
3097                                   bufpos_to_bytind (buf, to),
3098                                   iro);
3099     }
3100 }
3101
3102 void
3103 find_charsets_in_bufbyte_string (Charset_ID *charsets, const Bufbyte *str,
3104                                  Bytecount len)
3105 {
3106 #ifndef MULE
3107   /* Telescope this. */
3108   charsets[0] = 1;
3109 #else
3110   const Bufbyte *strend = str + len;
3111   memset (charsets, 0, NUM_LEADING_BYTES * sizeof(Charset_ID));
3112
3113   /* #### SJT doesn't like this. */
3114   if (len == 0)
3115     {
3116       charsets[XCHARSET_LEADING_BYTE (Vcharset_ascii) - MIN_LEADING_BYTE] = 1;
3117       return;
3118     }
3119
3120   while (str < strend)
3121     {
3122 #ifdef UTF2000
3123       charsets[CHAR_CHARSET_ID (charptr_emchar (str))
3124               - MIN_LEADING_BYTE] = 1;
3125 #else /* I'm not sure the definition for UTF2000 works with leading-byte
3126          representation. */
3127       charsets[CHAR_LEADING_BYTE (charptr_emchar (str))
3128               - MIN_LEADING_BYTE] = 1;
3129 #endif
3130       INC_CHARPTR (str);
3131     }
3132 #endif
3133 }
3134
3135 void
3136 find_charsets_in_charc_string (Charset_ID *charsets, const Charc *str,
3137                                Charcount len)
3138 {
3139 #ifndef MULE
3140   /* Telescope this. */
3141   charsets[0] = 1;
3142 #else
3143   int i;
3144
3145   memset (charsets, 0, NUM_LEADING_BYTES * sizeof(Charset_ID));
3146
3147   /* #### SJT doesn't like this. */
3148   if (len == 0)
3149     {
3150       charsets[XCHARSET_ID (Vcharset_ascii) - MIN_LEADING_BYTE] = 1;
3151       return;
3152     }
3153
3154   for (i = 0; i < len; i++)
3155     {
3156       charsets[CHARC_CHARSET_ID (str[i]) - MIN_LEADING_BYTE] = 1;
3157     }
3158 #endif
3159 }
3160
3161 int
3162 bufbyte_string_displayed_columns (const Bufbyte *str, Bytecount len)
3163 {
3164   int cols = 0;
3165   const Bufbyte *end = str + len;
3166
3167   while (str < end)
3168     {
3169 #ifdef MULE
3170       Emchar ch = charptr_emchar (str);
3171       cols += CHAR_COLUMNS (ch);
3172 #else
3173       cols++;
3174 #endif
3175       INC_CHARPTR (str);
3176     }
3177
3178   return cols;
3179 }
3180
3181 int
3182 charc_string_displayed_columns (const Charc *str, Charcount len)
3183 {
3184 #ifdef MULE
3185   int cols = 0;
3186   int i;
3187
3188   for (i = 0; i < len; i++)
3189     cols += CHARC_COLUMNS (str[i]);
3190
3191   return cols;
3192 #else  /* not MULE */
3193   return len;
3194 #endif
3195 }
3196
3197 /* NOTE: Does not reset the Dynarr. */
3198
3199 void
3200 convert_bufbyte_string_into_charc_dynarr (const Bufbyte *str, Bytecount len,
3201                                           Charc_dynarr *dyn)
3202 {
3203   const Bufbyte *strend = str + len;
3204
3205   while (str < strend)
3206     {
3207       Dynarr_add (dyn, CHAR_TO_CHARC (charptr_emchar (str)));
3208       INC_CHARPTR (str);
3209     }
3210 }
3211
3212 Charcount
3213 convert_bufbyte_string_into_emchar_string (const Bufbyte *str, Bytecount len,
3214                                            Emchar *arr)
3215 {
3216   const Bufbyte *strend = str + len;
3217   Charcount newlen = 0;
3218   while (str < strend)
3219     {
3220       Emchar ch = charptr_emchar (str);
3221       arr[newlen++] = ch;
3222       INC_CHARPTR (str);
3223     }
3224   return newlen;
3225 }
3226
3227 /* Convert an array of Emchars into the equivalent string representation.
3228    Store into the given Bufbyte dynarr.  Does not reset the dynarr.
3229    Does not add a terminating zero. */
3230
3231 void
3232 convert_charc_string_into_bufbyte_dynarr (Charc *arr, int nels,
3233                                             Bufbyte_dynarr *dyn)
3234 {
3235   Bufbyte str[MAX_EMCHAR_LEN];
3236   int i;
3237
3238   for (i = 0; i < nels; i++)
3239     {
3240       Bytecount len = set_charptr_emchar (str, CHARC_TO_CHAR (arr[i]));
3241       Dynarr_add_many (dyn, str, len);
3242     }
3243 }
3244
3245 /* Convert an array of Emchars into the equivalent string representation.
3246    Malloc the space needed for this and return it.  If LEN_OUT is not a
3247    NULL pointer, store into LEN_OUT the number of Bufbytes in the
3248    malloc()ed string.  Note that the actual number of Bufbytes allocated
3249    is one more than this: the returned string is zero-terminated. */
3250
3251 Bufbyte *
3252 convert_charc_string_into_malloced_string (Charc *arr, int nels,
3253                                            Bytecount *len_out)
3254 {
3255   /* Damn zero-termination. */
3256   Bufbyte *str = (Bufbyte *) alloca (nels * MAX_EMCHAR_LEN + 1);
3257   Bufbyte *strorig = str;
3258   Bytecount len;
3259
3260   int i;
3261
3262   for (i = 0; i < nels; i++)
3263     {
3264       str += set_charptr_emchar (str, CHARC_TO_CHAR (arr[i]));
3265     }
3266   *str = '\0';
3267   len = str - strorig;
3268   str = (Bufbyte *) xmalloc (1 + len);
3269   memcpy (str, strorig, 1 + len);
3270   if (len_out)
3271     *len_out = len;
3272   return str;
3273 }
3274
3275 \f
3276 /************************************************************************/
3277 /*                            initialization                            */
3278 /************************************************************************/
3279
3280 void
3281 reinit_vars_of_insdel (void)
3282 {
3283 #ifndef UTF2000
3284   int i;
3285 #endif
3286
3287   inside_change_hook = 0;
3288   in_first_change = 0;
3289
3290 #ifndef UTF2000
3291   for (i = 0; i <= MAX_BYTIND_GAP_SIZE_3; i++)
3292     three_to_one_table[i] = i / 3;
3293 #endif
3294 }
3295
3296 void
3297 vars_of_insdel (void)
3298 {
3299   reinit_vars_of_insdel ();
3300 }
3301
3302 void
3303 init_buffer_text (struct buffer *b)
3304 {
3305   if (!b->base_buffer)
3306     {
3307       SET_BUF_GAP_SIZE (b, 20);
3308       BUFFER_ALLOC (b->text->beg, BUF_GAP_SIZE (b) + BUF_END_SENTINEL_SIZE);
3309       if (! BUF_BEG_ADDR (b))
3310         memory_full ();
3311
3312       SET_BUF_END_GAP_SIZE (b, 0);
3313       SET_BI_BUF_GPT (b, 1);
3314       SET_BOTH_BUF_Z (b, 1, 1);
3315       SET_GAP_SENTINEL (b);
3316       SET_END_SENTINEL (b);
3317 #ifdef MULE
3318       {
3319         int i;
3320
3321         b->text->mule_bufmin = b->text->mule_bufmax = 1;
3322         b->text->mule_bytmin = b->text->mule_bytmax = 1;
3323 #ifdef UTF2000
3324         b->text->mule_size = 0;
3325 #else
3326         b->text->mule_shifter = 0;
3327         b->text->mule_three_p = 0;
3328 #endif
3329
3330         for (i = 0; i < 16; i++)
3331           {
3332             b->text->mule_bufpos_cache[i] = 1;
3333             b->text->mule_bytind_cache[i] = 1;
3334           }
3335       }
3336 #endif /* MULE */
3337       b->text->line_number_cache = Qnil;
3338
3339       BUF_MODIFF (b) = 1;
3340       BUF_SAVE_MODIFF (b) = 1;
3341
3342       JUST_SET_POINT (b, 1, 1);
3343       SET_BOTH_BUF_BEGV (b, 1, 1);
3344       SET_BOTH_BUF_ZV (b, 1, 1);
3345
3346       b->text->changes = xnew_and_zero (struct buffer_text_change_data);
3347     }
3348   else
3349     {
3350       JUST_SET_POINT (b, BUF_PT (b->base_buffer), BI_BUF_PT (b->base_buffer));
3351       SET_BOTH_BUF_BEGV (b, BUF_BEGV (b->base_buffer),
3352                          BI_BUF_BEGV (b->base_buffer));
3353       SET_BOTH_BUF_ZV (b, BUF_ZV (b->base_buffer),
3354                          BI_BUF_ZV (b->base_buffer));
3355     }
3356
3357   b->changes = xnew_and_zero (struct each_buffer_change_data);
3358   BUF_FACECHANGE (b) = 1;
3359
3360 #ifdef REGION_CACHE_NEEDS_WORK
3361   b->newline_cache = 0;
3362   b->width_run_cache = 0;
3363   b->width_table = Qnil;
3364 #endif
3365 }
3366
3367 void
3368 uninit_buffer_text (struct buffer *b)
3369 {
3370   if (!b->base_buffer)
3371     {
3372       BUFFER_FREE (b->text->beg);
3373       xfree (b->text->changes);
3374     }
3375   xfree (b->changes);
3376
3377 #ifdef REGION_CACHE_NEEDS_WORK
3378   if (b->newline_cache)
3379     {
3380       free_region_cache (b->newline_cache);
3381       b->newline_cache = 0;
3382     }
3383   if (b->width_run_cache)
3384     {
3385       free_region_cache (b->width_run_cache);
3386       b->width_run_cache = 0;
3387     }
3388   b->width_table = Qnil;
3389 #endif
3390 }