Sync with r21-4-9-utf-2000-0_19-jc3lisp.
[chise/xemacs-chise.git-] / 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 #ifdef CLASH_DETECTION
2356       if (!NILP (buf->file_truename))
2357         /* Make binding buffer-file-name to nil effective.  */
2358         lock_file (buf->file_truename);
2359 #else
2360       /* At least warn if this file has changed on disk since it was visited.*/
2361       if (NILP (Fverify_visited_file_modtime (buffer))
2362           && !NILP (Ffile_exists_p (buf->filename)))
2363         call1_in_buffer (buf, intern ("ask-user-about-supersession-threat"),
2364                          buf->filename);
2365 #endif /* not CLASH_DETECTION */
2366     }
2367   UNGCPRO;
2368
2369   /* #### dmoore - is this reasonable in case of buf being killed above? */
2370   if (!BUFFER_LIVE_P (buf))
2371     return;
2372
2373   signal_before_change (buf, start, end);
2374
2375 #ifdef REGION_CACHE_NEEDS_WORK
2376   if (buf->newline_cache)
2377     invalidate_region_cache (buf,
2378                              buf->newline_cache,
2379                              start - BUF_BEG (buf), BUF_Z (buf) - end);
2380   if (buf->width_run_cache)
2381     invalidate_region_cache (buf,
2382                              buf->width_run_cache,
2383                              start - BUF_BEG (buf), BUF_Z (buf) - end);
2384 #endif
2385
2386 #if 0 /* FSFmacs */
2387   Vdeactivate_mark = Qt;
2388 #endif
2389
2390   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2391     {
2392       mbuf->point_before_scroll = Qnil;
2393     }
2394 }
2395
2396 \f
2397 /************************************************************************/
2398 /*                        Insertion of strings                          */
2399 /************************************************************************/
2400
2401 void
2402 fixup_internal_substring (const Bufbyte *nonreloc, Lisp_Object reloc,
2403                           Bytecount offset, Bytecount *len)
2404 {
2405   assert ((nonreloc && NILP (reloc)) || (!nonreloc && STRINGP (reloc)));
2406
2407   if (*len < 0)
2408     {
2409       if (nonreloc)
2410         *len = strlen ((const char *) nonreloc) - offset;
2411       else
2412         *len = XSTRING_LENGTH (reloc) - offset;
2413     }
2414 #ifdef ERROR_CHECK_BUFPOS
2415   assert (*len >= 0);
2416   if (STRINGP (reloc))
2417     {
2418       assert (offset >= 0 && offset <= XSTRING_LENGTH (reloc));
2419       assert (offset + *len <= XSTRING_LENGTH (reloc));
2420     }
2421 #endif
2422 }
2423
2424 /* Insert a string into BUF at Bufpos POS.  The string data comes
2425    from one of two sources: constant, non-relocatable data (specified
2426    in NONRELOC), or a Lisp string object (specified in RELOC), which
2427    is relocatable and may have extent data that needs to be copied
2428    into the buffer.  OFFSET and LENGTH specify the substring of the
2429    data that is actually to be inserted.  As a special case, if POS
2430    is -1, insert the string at point and move point to the end of the
2431    string.
2432
2433    Normally, markers at the insertion point end up before the
2434    inserted string.  If INSDEL_BEFORE_MARKERS is set in flags, however,
2435    they end up after the string.
2436
2437    INSDEL_NO_LOCKING is kludgy and is used when insert-file-contents is
2438    visiting a new file; it inhibits the locking checks normally done
2439    before modifying a buffer.  Similar checks were already done
2440    in the higher-level Lisp functions calling insert-file-contents. */
2441
2442 Charcount
2443 buffer_insert_string_1 (struct buffer *buf, Bufpos pos,
2444                         const Bufbyte *nonreloc, Lisp_Object reloc,
2445                         Bytecount offset, Bytecount length,
2446                         int flags)
2447 {
2448   /* This function can GC */
2449   struct gcpro gcpro1;
2450   Bytind ind;
2451   Charcount cclen;
2452   int move_point = 0;
2453   struct buffer *mbuf;
2454   Lisp_Object bufcons;
2455
2456   /* Defensive steps just in case a buffer gets deleted and a calling
2457      function doesn't notice it. */
2458   if (!BUFFER_LIVE_P (buf))
2459     return 0;
2460
2461   fixup_internal_substring (nonreloc, reloc, offset, &length);
2462
2463   if (pos == -1)
2464     {
2465       pos = BUF_PT (buf);
2466       move_point = 1;
2467     }
2468
2469 #ifdef I18N3
2470   /* #### See the comment in print_internal().  If this buffer is marked
2471      as translatable, then Fgettext() should be called on obj if it
2472      is a string. */
2473 #endif
2474
2475   /* Make sure that point-max won't exceed the size of an emacs int. */
2476   if ((length + BUF_Z (buf)) > EMACS_INT_MAX)
2477     error ("Maximum buffer size exceeded");
2478
2479   /* theoretically not necessary -- caller should GCPRO.
2480      #### buffer_insert_from_buffer_1() doesn't!  */
2481   GCPRO1 (reloc);
2482
2483   prepare_to_modify_buffer (buf, pos, pos, !(flags & INSDEL_NO_LOCKING));
2484
2485   /* Defensive steps in case the before-change-functions fuck around */
2486   if (!BUFFER_LIVE_P (buf))
2487     {
2488       UNGCPRO;
2489       /* Bad bad pre-change function. */
2490       return 0;
2491     }
2492
2493   /* Make args be valid again.  prepare_to_modify_buffer() might have
2494      modified the buffer. */
2495   if (pos < BUF_BEGV (buf))
2496     pos = BUF_BEGV (buf);
2497   if (pos > BUF_ZV (buf))
2498     pos = BUF_ZV (buf);
2499
2500   /* string may have been relocated up to this point */
2501   if (STRINGP (reloc))
2502     nonreloc = XSTRING_DATA (reloc);
2503
2504   ind = bufpos_to_bytind (buf, pos);
2505   cclen = bytecount_to_charcount (nonreloc + offset, length);
2506
2507   if (ind != BI_BUF_GPT (buf))
2508     /* #### if debug-on-quit is invoked and the user changes the
2509        buffer, bad things can happen.  This is a rampant problem
2510        in Emacs. */
2511     move_gap (buf, ind); /* may QUIT */
2512   if (! GAP_CAN_HOLD_SIZE_P (buf, length))
2513     {
2514       if (BUF_END_GAP_SIZE (buf) >= length)
2515         merge_gap_with_end_gap (buf);
2516       else
2517         make_gap (buf, length - BUF_GAP_SIZE (buf));
2518     }
2519
2520   insert_invalidate_line_number_cache (buf, pos, nonreloc + offset, length);
2521
2522   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2523     {
2524       record_insert (mbuf, pos, cclen);
2525     }
2526
2527   BUF_MODIFF (buf)++;
2528   MARK_BUFFERS_CHANGED;
2529
2530   /* string may have been relocated up to this point */
2531   if (STRINGP (reloc))
2532     nonreloc = XSTRING_DATA (reloc);
2533
2534   memcpy (BUF_GPT_ADDR (buf), nonreloc + offset, length);
2535
2536   SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) - length);
2537   SET_BI_BUF_GPT (buf, BI_BUF_GPT (buf) + length);
2538   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2539     {
2540       SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) + cclen, BI_BUF_ZV (mbuf) + length);
2541     }
2542   SET_BOTH_BUF_Z (buf, BUF_Z (buf) + cclen, BI_BUF_Z (buf) + length);
2543   SET_GAP_SENTINEL (buf);
2544
2545 #ifdef MULE
2546   buffer_mule_signal_inserted_region (buf, pos, length, cclen);
2547 #endif
2548
2549   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2550     {
2551       process_extents_for_insertion (make_buffer (mbuf), ind, length);
2552     }
2553
2554   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2555     {
2556       /* We know the gap is at IND so the cast is OK. */
2557       adjust_markers_for_insert (mbuf, (Memind) ind, length);
2558     }
2559
2560   /* Point logically doesn't move, but may need to be adjusted because
2561      it's a byte index.  point-marker doesn't change because it's a
2562      memory index. */
2563   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2564     {
2565       if (BI_BUF_PT (mbuf) > ind)
2566         JUST_SET_POINT (mbuf, BUF_PT (mbuf) + cclen,
2567                         BI_BUF_PT (mbuf) + length);
2568     }
2569
2570   /* Well, point might move. */
2571   if (move_point)
2572     BI_BUF_SET_PT (buf, ind + length);
2573
2574   if (STRINGP (reloc))
2575     {
2576       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2577         {
2578           splice_in_string_extents (reloc, mbuf, ind, length, offset);
2579         }
2580     }
2581
2582   if (flags & INSDEL_BEFORE_MARKERS)
2583     {
2584       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2585         {
2586           /* ind - 1 is correct because the FROM argument is exclusive.
2587              I formerly used DEC_BYTIND() but that caused problems at the
2588              beginning of the buffer. */
2589           adjust_markers (mbuf, ind - 1, ind, length);
2590         }
2591     }
2592
2593   signal_after_change (buf, pos, pos, pos + cclen);
2594
2595   UNGCPRO;
2596
2597   return cclen;
2598 }
2599
2600
2601 /* The following functions are interfaces onto the above function,
2602    for inserting particular sorts of data.  In all the functions,
2603    BUF and POS specify the buffer and location where the insertion is
2604    to take place. (If POS is -1, text is inserted at point and point
2605    moves forward past the text.) FLAGS is as above. */
2606
2607 Charcount
2608 buffer_insert_raw_string_1 (struct buffer *buf, Bufpos pos,
2609                             const Bufbyte *nonreloc, Bytecount length,
2610                             int flags)
2611 {
2612   /* This function can GC */
2613   return buffer_insert_string_1 (buf, pos, nonreloc, Qnil, 0, length,
2614                                  flags);
2615 }
2616
2617 Charcount
2618 buffer_insert_lisp_string_1 (struct buffer *buf, Bufpos pos, Lisp_Object str,
2619                              int flags)
2620 {
2621   /* This function can GC */
2622 #ifdef ERROR_CHECK_TYPECHECK
2623   assert (STRINGP (str));
2624 #endif
2625   return buffer_insert_string_1 (buf, pos, 0, str, 0,
2626                                  XSTRING_LENGTH (str),
2627                                  flags);
2628 }
2629
2630 /* Insert the null-terminated string S (in external format). */
2631
2632 Charcount
2633 buffer_insert_c_string_1 (struct buffer *buf, Bufpos pos, const char *s,
2634                           int flags)
2635 {
2636   /* This function can GC */
2637   const char *translated = GETTEXT (s);
2638   return buffer_insert_string_1 (buf, pos, (const Bufbyte *) translated, Qnil,
2639                                  0, strlen (translated), flags);
2640 }
2641
2642 Charcount
2643 buffer_insert_emacs_char_1 (struct buffer *buf, Bufpos pos, Emchar ch,
2644                             int flags)
2645 {
2646   /* This function can GC */
2647   Bufbyte str[MAX_EMCHAR_LEN];
2648   Bytecount len = set_charptr_emchar (str, ch);
2649   return buffer_insert_string_1 (buf, pos, str, Qnil, 0, len, flags);
2650 }
2651
2652 Charcount
2653 buffer_insert_c_char_1 (struct buffer *buf, Bufpos pos, char c,
2654                         int flags)
2655 {
2656   /* This function can GC */
2657   return buffer_insert_emacs_char_1 (buf, pos, (Emchar) (unsigned char) c,
2658                                      flags);
2659 }
2660
2661 Charcount
2662 buffer_insert_from_buffer_1 (struct buffer *buf, Bufpos pos,
2663                              struct buffer *buf2, Bufpos pos2,
2664                              Charcount length, int flags)
2665 {
2666   /* This function can GC */
2667   Lisp_Object str = make_string_from_buffer (buf2, pos2, length);
2668   return buffer_insert_string_1 (buf, pos, 0, str, 0,
2669                                  XSTRING_LENGTH (str), flags);
2670 }
2671
2672 \f
2673 /************************************************************************/
2674 /*                        Deletion of ranges                            */
2675 /************************************************************************/
2676
2677 /* Delete characters in buffer from FROM up to (but not including) TO.  */
2678
2679 void
2680 buffer_delete_range (struct buffer *buf, Bufpos from, Bufpos to, int flags)
2681 {
2682   /* This function can GC */
2683   Charcount numdel;
2684   Bytind bi_from, bi_to;
2685   Bytecount bc_numdel;
2686   EMACS_INT shortage;
2687   struct buffer *mbuf;
2688   Lisp_Object bufcons;
2689
2690   /* Defensive steps just in case a buffer gets deleted and a calling
2691      function doesn't notice it. */
2692   if (!BUFFER_LIVE_P (buf))
2693     return;
2694
2695   /* Make args be valid */
2696   if (from < BUF_BEGV (buf))
2697     from = BUF_BEGV (buf);
2698   if (to > BUF_ZV (buf))
2699     to = BUF_ZV (buf);
2700   if ((numdel = to - from) <= 0)
2701     return;
2702
2703   prepare_to_modify_buffer (buf, from, to, !(flags & INSDEL_NO_LOCKING));
2704
2705   /* Defensive steps in case the before-change-functions fuck around */
2706   if (!BUFFER_LIVE_P (buf))
2707     /* Bad bad pre-change function. */
2708     return;
2709
2710   /* Make args be valid again.  prepare_to_modify_buffer() might have
2711      modified the buffer. */
2712   if (from < BUF_BEGV (buf))
2713     from = BUF_BEGV (buf);
2714   if (to > BUF_ZV (buf))
2715     to = BUF_ZV (buf);
2716   if ((numdel = to - from) <= 0)
2717     return;
2718
2719   /* Redisplay needs to know if a newline was in the deleted region.
2720      If we've already marked the changed region as having a deleted
2721      newline there is no use in performing the check. */
2722   if (!buf->changes->newline_was_deleted)
2723     {
2724       scan_buffer (buf, '\n', from, to, 1, &shortage, 1);
2725       if (!shortage)
2726         {
2727           MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2728             {
2729               mbuf->changes->newline_was_deleted = 1;
2730             }
2731         }
2732     }
2733
2734   bi_from = bufpos_to_bytind (buf, from);
2735   bi_to = bufpos_to_bytind (buf, to);
2736   bc_numdel = bi_to - bi_from;
2737
2738   delete_invalidate_line_number_cache (buf, from, to);
2739
2740   if (to == BUF_Z (buf) &&
2741       bi_from > BI_BUF_GPT (buf))
2742     {
2743       /* avoid moving the gap just to delete from the bottom. */
2744
2745       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2746         {
2747           record_delete (mbuf, from, numdel);
2748         }
2749       BUF_MODIFF (buf)++;
2750       MARK_BUFFERS_CHANGED;
2751
2752       /* #### Point used to be modified here, but this causes problems
2753          with MULE, as point is used to calculate bytinds, and if the
2754          offset in bc_numdel causes point to move to a non first-byte
2755          location, causing some other function to throw an assertion
2756          in ASSERT_VALID_BYTIND. I've moved the code to right after
2757          the other movements and adjustments, but before the gap is
2758          moved.  -- jh 970813 */
2759
2760       /* Detach any extents that are completely within the range [FROM, TO],
2761          if the extents are detachable.
2762
2763          This must come AFTER record_delete(), so that the appropriate
2764          extents will be present to be recorded, and BEFORE the gap
2765          size is increased, as otherwise we will be confused about
2766          where the extents end. */
2767       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2768         {
2769           process_extents_for_deletion (make_buffer (mbuf), bi_from, bi_to, 0);
2770         }
2771
2772       /* Relocate all markers pointing into the new, larger gap to
2773          point at the end of the text before the gap.  */
2774       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2775         {
2776           adjust_markers (mbuf,
2777                           (bi_to + BUF_GAP_SIZE (mbuf)),
2778                           (bi_to + BUF_GAP_SIZE (mbuf)),
2779                           (- bc_numdel));
2780         }
2781
2782       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2783         {
2784           /* Relocate any extent endpoints just like markers. */
2785           adjust_extents_for_deletion (make_buffer (mbuf), bi_from, bi_to,
2786                                        BUF_GAP_SIZE (mbuf), bc_numdel, 0);
2787         }
2788
2789       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2790         {
2791           /* Relocate point as if it were a marker.  */
2792           if (bi_from < BI_BUF_PT (mbuf))
2793             {
2794               if (BI_BUF_PT (mbuf) < bi_to)
2795                 JUST_SET_POINT (mbuf, from, bi_from);
2796               else
2797                 JUST_SET_POINT (mbuf, BUF_PT (mbuf) - numdel,
2798                                 BI_BUF_PT (mbuf) - bc_numdel);
2799             }
2800         }
2801
2802       SET_BUF_END_GAP_SIZE (buf, BUF_END_GAP_SIZE (buf) + bc_numdel);
2803
2804       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2805         {
2806           SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) - numdel,
2807                            BI_BUF_ZV (mbuf) - bc_numdel);
2808         }
2809       SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel);
2810       SET_GAP_SENTINEL (buf);
2811     }
2812   else
2813     {
2814       /* Make sure the gap is somewhere in or next to what we are deleting.  */
2815       if (bi_to < BI_BUF_GPT (buf))
2816         gap_left (buf, bi_to);
2817       if (bi_from > BI_BUF_GPT (buf))
2818         gap_right (buf, bi_from);
2819
2820       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2821         {
2822           record_delete (mbuf, from, numdel);
2823         }
2824       BUF_MODIFF (buf)++;
2825       MARK_BUFFERS_CHANGED;
2826
2827       /* #### Point used to be modified here, but this causes problems
2828          with MULE, as point is used to calculate bytinds, and if the
2829          offset in bc_numdel causes point to move to a non first-byte
2830          location, causing some other function to throw an assertion
2831          in ASSERT_VALID_BYTIND. I've moved the code to right after
2832          the other movements and adjustments, but before the gap is
2833          moved.  -- jh 970813 */
2834
2835       /* Detach any extents that are completely within the range [FROM, TO],
2836          if the extents are detachable.
2837
2838          This must come AFTER record_delete(), so that the appropriate extents
2839          will be present to be recorded, and BEFORE the gap size is increased,
2840          as otherwise we will be confused about where the extents end. */
2841       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2842         {
2843           process_extents_for_deletion (make_buffer (mbuf), bi_from, bi_to, 0);
2844         }
2845
2846       /* Relocate all markers pointing into the new, larger gap to
2847          point at the end of the text before the gap.  */
2848       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2849         {
2850           adjust_markers (mbuf,
2851                           (bi_to + BUF_GAP_SIZE (mbuf)),
2852                           (bi_to + BUF_GAP_SIZE (mbuf)),
2853                           (- bc_numdel - BUF_GAP_SIZE (mbuf)));
2854         }
2855
2856       /* Relocate any extent endpoints just like markers. */
2857       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2858         {
2859           adjust_extents_for_deletion (make_buffer (mbuf), bi_from, bi_to,
2860                                        BUF_GAP_SIZE (mbuf),
2861                                        bc_numdel, BUF_GAP_SIZE (mbuf));
2862         }
2863
2864       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2865         {
2866           /* Relocate point as if it were a marker.  */
2867           if (bi_from < BI_BUF_PT (mbuf))
2868             {
2869               if (BI_BUF_PT (mbuf) < bi_to)
2870                 JUST_SET_POINT (mbuf, from, bi_from);
2871               else
2872                 JUST_SET_POINT (mbuf, BUF_PT (mbuf) - numdel,
2873                                 BI_BUF_PT (mbuf) - bc_numdel);
2874             }
2875         }
2876
2877       SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + bc_numdel);
2878       MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2879         {
2880           SET_BOTH_BUF_ZV (mbuf, BUF_ZV (mbuf) - numdel,
2881                            BI_BUF_ZV (mbuf) - bc_numdel);
2882         }
2883       SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel);
2884       SET_BI_BUF_GPT (buf, bi_from);
2885       SET_GAP_SENTINEL (buf);
2886     }
2887
2888 #ifdef MULE
2889   buffer_mule_signal_deleted_region (buf, from, to, bi_from, bi_to);
2890 #endif
2891
2892 #ifdef ERROR_CHECK_EXTENTS
2893   MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2894     {
2895       sledgehammer_extent_check (make_buffer (mbuf));
2896     }
2897 #endif
2898
2899   signal_after_change (buf, from, to, from);
2900 }
2901
2902 \f
2903 /************************************************************************/
2904 /*                    Replacement of characters                         */
2905 /************************************************************************/
2906
2907 /* Replace the character at POS in buffer B with CH. */
2908
2909 void
2910 buffer_replace_char (struct buffer *buf, Bufpos pos, Emchar ch,
2911                      int not_real_change, int force_lock_check)
2912 {
2913   /* This function can GC */
2914   Bufbyte curstr[MAX_EMCHAR_LEN];
2915   Bufbyte newstr[MAX_EMCHAR_LEN];
2916   Bytecount curlen, newlen;
2917
2918   /* Defensive steps just in case a buffer gets deleted and a calling
2919      function doesn't notice it. */
2920   if (!BUFFER_LIVE_P (buf))
2921     return;
2922
2923   curlen = BUF_CHARPTR_COPY_CHAR (buf, pos, curstr);
2924   newlen = set_charptr_emchar (newstr, ch);
2925
2926   if (curlen == newlen)
2927     {
2928       struct buffer *mbuf;
2929       Lisp_Object bufcons;
2930
2931       /* then we can just replace the text. */
2932       prepare_to_modify_buffer (buf, pos, pos + 1,
2933                                 !not_real_change || force_lock_check);
2934       /* Defensive steps in case the before-change-functions fuck around */
2935       if (!BUFFER_LIVE_P (buf))
2936         /* Bad bad pre-change function. */
2937         return;
2938
2939       /* Make args be valid again.  prepare_to_modify_buffer() might have
2940          modified the buffer. */
2941       if (pos < BUF_BEGV (buf))
2942         pos = BUF_BEGV (buf);
2943       if (pos >= BUF_ZV (buf))
2944         pos = BUF_ZV (buf) - 1;
2945       if (pos < BUF_BEGV (buf))
2946         /* no more characters in buffer! */
2947         return;
2948
2949       if (BUF_FETCH_CHAR (buf, pos) == '\n')
2950         {
2951           MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2952             {
2953               mbuf->changes->newline_was_deleted = 1;
2954             }
2955         }
2956       MARK_BUFFERS_CHANGED;
2957       if (!not_real_change)
2958         {
2959           MAP_INDIRECT_BUFFERS (buf, mbuf, bufcons)
2960             {
2961               record_change (mbuf, pos, 1);
2962             }
2963           BUF_MODIFF (buf)++;
2964         }
2965       memcpy (BUF_BYTE_ADDRESS (buf, pos), newstr, newlen);
2966
2967       signal_after_change (buf, pos, pos + 1, pos + 1);
2968
2969       /* We do not have to adjust the Mule data; we just replaced a
2970          character with another of the same number of bytes. */
2971     }
2972   else
2973     {
2974       /*
2975        * Must implement as deletion followed by insertion.
2976        *
2977        * Make a note to move point forward later in the one situation
2978        * where it is needed, a delete/insert one position behind
2979        * point.  Point will drift backward by one position and stay
2980        * there otherwise.
2981        */
2982       int movepoint = (pos == BUF_PT (buf) - 1);
2983
2984       buffer_delete_range (buf, pos, pos + 1, 0);
2985       /* Defensive steps in case the before-change-functions fuck around */
2986       if (!BUFFER_LIVE_P (buf))
2987         /* Bad bad pre-change function. */
2988         return;
2989
2990       /* Make args be valid again.  prepare_to_modify_buffer() might have
2991          modified the buffer. */
2992       if (pos < BUF_BEGV (buf))
2993         pos = BUF_BEGV (buf);
2994       if (pos >= BUF_ZV (buf))
2995         pos = BUF_ZV (buf) - 1;
2996       if (pos < BUF_BEGV (buf))
2997         /* no more characters in buffer! */
2998         return;
2999       /*
3000        * -1 as the pos argument means to move point forward with the
3001        * insertion, which we must do if the deletion moved point
3002        * backward so that it now equals the insertion point.
3003        */
3004       buffer_insert_string_1 (buf, (movepoint ? -1 : pos),
3005                               newstr, Qnil, 0, newlen, 0);
3006     }
3007 }
3008
3009 \f
3010 /************************************************************************/
3011 /*                            Other functions                           */
3012 /************************************************************************/
3013
3014 /* Make a string from a buffer.  This needs to take into account the gap,
3015    and add any necessary extents from the buffer. */
3016
3017 static Lisp_Object
3018 make_string_from_buffer_1 (struct buffer *buf, Bufpos pos, Charcount length,
3019                            int no_extents)
3020 {
3021   /* This function can GC */
3022   Bytind    bi_ind = bufpos_to_bytind (buf, pos);
3023   Bytecount bi_len = bufpos_to_bytind (buf, pos + length) - bi_ind;
3024   Lisp_Object  val = make_uninit_string (bi_len);
3025
3026   struct gcpro gcpro1;
3027   GCPRO1 (val);
3028
3029   if (!no_extents)
3030     add_string_extents (val, buf, bi_ind, bi_len);
3031
3032   {
3033     Bytecount len1 = BI_BUF_GPT (buf) - bi_ind;
3034     Bufbyte *start1 = BI_BUF_BYTE_ADDRESS (buf, bi_ind);
3035     Bufbyte *dest = XSTRING_DATA (val);
3036
3037     if (len1 < 0)
3038       {
3039         /* Completely after gap */
3040         memcpy (dest, start1, bi_len);
3041       }
3042     else if (bi_len <= len1)
3043       {
3044         /* Completely before gap */
3045         memcpy (dest, start1, bi_len);
3046       }
3047     else
3048       {
3049         /* Spans gap */
3050         Bytind pos2 = bi_ind + len1;
3051         Bufbyte *start2 = BI_BUF_BYTE_ADDRESS (buf, pos2);
3052
3053         memcpy (dest, start1, len1);
3054         memcpy (dest + len1, start2, bi_len - len1);
3055       }
3056   }
3057
3058   UNGCPRO;
3059   return val;
3060 }
3061
3062 Lisp_Object
3063 make_string_from_buffer (struct buffer *buf, Bufpos pos, Charcount length)
3064 {
3065   return make_string_from_buffer_1 (buf, pos, length, 0);
3066 }
3067
3068 Lisp_Object
3069 make_string_from_buffer_no_extents (struct buffer *buf, Bufpos pos,
3070                                     Charcount length)
3071 {
3072   return make_string_from_buffer_1 (buf, pos, length, 1);
3073 }
3074
3075 void
3076 barf_if_buffer_read_only (struct buffer *buf, Bufpos from, Bufpos to)
3077 {
3078   Lisp_Object buffer;
3079   Lisp_Object iro;
3080
3081   XSETBUFFER (buffer, buf);
3082  back:
3083   iro = (buf == current_buffer ? Vinhibit_read_only :
3084          symbol_value_in_buffer (Qinhibit_read_only, buffer));
3085   if (!LISTP (iro))
3086     return;
3087   if (NILP (iro) && !NILP (buf->read_only))
3088     {
3089       Fsignal (Qbuffer_read_only, (list1 (buffer)));
3090       goto back;
3091     }
3092   if (from > 0)
3093     {
3094       if (to < 0)
3095         to = from;
3096       verify_extent_modification (buffer,
3097                                   bufpos_to_bytind (buf, from),
3098                                   bufpos_to_bytind (buf, to),
3099                                   iro);
3100     }
3101 }
3102
3103 void
3104 find_charsets_in_bufbyte_string (Charset_ID *charsets, const Bufbyte *str,
3105                                  Bytecount len)
3106 {
3107 #ifndef MULE
3108   /* Telescope this. */
3109   charsets[0] = 1;
3110 #else
3111   const Bufbyte *strend = str + len;
3112   memset (charsets, 0, NUM_LEADING_BYTES * sizeof(Charset_ID));
3113
3114   /* #### SJT doesn't like this. */
3115   if (len == 0)
3116     {
3117       charsets[XCHARSET_LEADING_BYTE (Vcharset_ascii) - MIN_LEADING_BYTE] = 1;
3118       return;
3119     }
3120
3121   while (str < strend)
3122     {
3123 #ifdef UTF2000
3124       charsets[CHAR_CHARSET_ID (charptr_emchar (str))
3125               - MIN_LEADING_BYTE] = 1;
3126 #else /* I'm not sure the definition for UTF2000 works with leading-byte
3127          representation. */
3128       charsets[CHAR_LEADING_BYTE (charptr_emchar (str))
3129               - MIN_LEADING_BYTE] = 1;
3130 #endif
3131       INC_CHARPTR (str);
3132     }
3133 #endif
3134 }
3135
3136 void
3137 find_charsets_in_charc_string (Charset_ID *charsets, const Charc *str,
3138                                Charcount len)
3139 {
3140 #ifndef MULE
3141   /* Telescope this. */
3142   charsets[0] = 1;
3143 #else
3144   int i;
3145
3146   memset (charsets, 0, NUM_LEADING_BYTES * sizeof(Charset_ID));
3147
3148   /* #### SJT doesn't like this. */
3149   if (len == 0)
3150     {
3151       charsets[XCHARSET_ID (Vcharset_ascii) - MIN_LEADING_BYTE] = 1;
3152       return;
3153     }
3154
3155   for (i = 0; i < len; i++)
3156     {
3157       charsets[CHARC_CHARSET_ID (str[i]) - MIN_LEADING_BYTE] = 1;
3158     }
3159 #endif
3160 }
3161
3162 int
3163 bufbyte_string_displayed_columns (const Bufbyte *str, Bytecount len)
3164 {
3165   int cols = 0;
3166   const Bufbyte *end = str + len;
3167
3168   while (str < end)
3169     {
3170 #ifdef MULE
3171       Emchar ch = charptr_emchar (str);
3172       cols += CHAR_COLUMNS (ch);
3173 #else
3174       cols++;
3175 #endif
3176       INC_CHARPTR (str);
3177     }
3178
3179   return cols;
3180 }
3181
3182 int
3183 charc_string_displayed_columns (const Charc *str, Charcount len)
3184 {
3185 #ifdef MULE
3186   int cols = 0;
3187   int i;
3188
3189   for (i = 0; i < len; i++)
3190     cols += CHARC_COLUMNS (str[i]);
3191
3192   return cols;
3193 #else  /* not MULE */
3194   return len;
3195 #endif
3196 }
3197
3198 /* NOTE: Does not reset the Dynarr. */
3199
3200 void
3201 convert_bufbyte_string_into_charc_dynarr (const Bufbyte *str, Bytecount len,
3202                                           Charc_dynarr *dyn)
3203 {
3204   const Bufbyte *strend = str + len;
3205
3206   while (str < strend)
3207     {
3208       Dynarr_add (dyn, CHAR_TO_CHARC (charptr_emchar (str)));
3209       INC_CHARPTR (str);
3210     }
3211 }
3212
3213 Charcount
3214 convert_bufbyte_string_into_emchar_string (const Bufbyte *str, Bytecount len,
3215                                            Emchar *arr)
3216 {
3217   const Bufbyte *strend = str + len;
3218   Charcount newlen = 0;
3219   while (str < strend)
3220     {
3221       Emchar ch = charptr_emchar (str);
3222       arr[newlen++] = ch;
3223       INC_CHARPTR (str);
3224     }
3225   return newlen;
3226 }
3227
3228 /* Convert an array of Emchars into the equivalent string representation.
3229    Store into the given Bufbyte dynarr.  Does not reset the dynarr.
3230    Does not add a terminating zero. */
3231
3232 void
3233 convert_charc_string_into_bufbyte_dynarr (Charc *arr, int nels,
3234                                             Bufbyte_dynarr *dyn)
3235 {
3236   Bufbyte str[MAX_EMCHAR_LEN];
3237   int i;
3238
3239   for (i = 0; i < nels; i++)
3240     {
3241       Bytecount len = set_charptr_emchar (str, CHARC_TO_CHAR (arr[i]));
3242       Dynarr_add_many (dyn, str, len);
3243     }
3244 }
3245
3246 /* Convert an array of Emchars into the equivalent string representation.
3247    Malloc the space needed for this and return it.  If LEN_OUT is not a
3248    NULL pointer, store into LEN_OUT the number of Bufbytes in the
3249    malloc()ed string.  Note that the actual number of Bufbytes allocated
3250    is one more than this: the returned string is zero-terminated. */
3251
3252 Bufbyte *
3253 convert_charc_string_into_malloced_string (Charc *arr, int nels,
3254                                            Bytecount *len_out)
3255 {
3256   /* Damn zero-termination. */
3257   Bufbyte *str = (Bufbyte *) alloca (nels * MAX_EMCHAR_LEN + 1);
3258   Bufbyte *strorig = str;
3259   Bytecount len;
3260
3261   int i;
3262
3263   for (i = 0; i < nels; i++)
3264     {
3265       str += set_charptr_emchar (str, CHARC_TO_CHAR (arr[i]));
3266     }
3267   *str = '\0';
3268   len = str - strorig;
3269   str = (Bufbyte *) xmalloc (1 + len);
3270   memcpy (str, strorig, 1 + len);
3271   if (len_out)
3272     *len_out = len;
3273   return str;
3274 }
3275
3276 \f
3277 /************************************************************************/
3278 /*                            initialization                            */
3279 /************************************************************************/
3280
3281 void
3282 reinit_vars_of_insdel (void)
3283 {
3284 #ifndef UTF2000
3285   int i;
3286 #endif
3287
3288   inside_change_hook = 0;
3289   in_first_change = 0;
3290
3291 #ifndef UTF2000
3292   for (i = 0; i <= MAX_BYTIND_GAP_SIZE_3; i++)
3293     three_to_one_table[i] = i / 3;
3294 #endif
3295 }
3296
3297 void
3298 vars_of_insdel (void)
3299 {
3300   reinit_vars_of_insdel ();
3301 }
3302
3303 void
3304 init_buffer_text (struct buffer *b)
3305 {
3306   if (!b->base_buffer)
3307     {
3308       SET_BUF_GAP_SIZE (b, 20);
3309       BUFFER_ALLOC (b->text->beg, BUF_GAP_SIZE (b) + BUF_END_SENTINEL_SIZE);
3310       if (! BUF_BEG_ADDR (b))
3311         memory_full ();
3312
3313       SET_BUF_END_GAP_SIZE (b, 0);
3314       SET_BI_BUF_GPT (b, 1);
3315       SET_BOTH_BUF_Z (b, 1, 1);
3316       SET_GAP_SENTINEL (b);
3317       SET_END_SENTINEL (b);
3318 #ifdef MULE
3319       {
3320         int i;
3321
3322         b->text->mule_bufmin = b->text->mule_bufmax = 1;
3323         b->text->mule_bytmin = b->text->mule_bytmax = 1;
3324 #ifdef UTF2000
3325         b->text->mule_size = 0;
3326 #else
3327         b->text->mule_shifter = 0;
3328         b->text->mule_three_p = 0;
3329 #endif
3330
3331         for (i = 0; i < 16; i++)
3332           {
3333             b->text->mule_bufpos_cache[i] = 1;
3334             b->text->mule_bytind_cache[i] = 1;
3335           }
3336       }
3337 #endif /* MULE */
3338       b->text->line_number_cache = Qnil;
3339
3340       BUF_MODIFF (b) = 1;
3341       BUF_SAVE_MODIFF (b) = 1;
3342
3343       JUST_SET_POINT (b, 1, 1);
3344       SET_BOTH_BUF_BEGV (b, 1, 1);
3345       SET_BOTH_BUF_ZV (b, 1, 1);
3346
3347       b->text->changes = xnew_and_zero (struct buffer_text_change_data);
3348     }
3349   else
3350     {
3351       JUST_SET_POINT (b, BUF_PT (b->base_buffer), BI_BUF_PT (b->base_buffer));
3352       SET_BOTH_BUF_BEGV (b, BUF_BEGV (b->base_buffer),
3353                          BI_BUF_BEGV (b->base_buffer));
3354       SET_BOTH_BUF_ZV (b, BUF_ZV (b->base_buffer),
3355                          BI_BUF_ZV (b->base_buffer));
3356     }
3357
3358   b->changes = xnew_and_zero (struct each_buffer_change_data);
3359   BUF_FACECHANGE (b) = 1;
3360
3361 #ifdef REGION_CACHE_NEEDS_WORK
3362   b->newline_cache = 0;
3363   b->width_run_cache = 0;
3364   b->width_table = Qnil;
3365 #endif
3366 }
3367
3368 void
3369 uninit_buffer_text (struct buffer *b)
3370 {
3371   if (!b->base_buffer)
3372     {
3373       BUFFER_FREE (b->text->beg);
3374       xfree (b->text->changes);
3375     }
3376   xfree (b->changes);
3377
3378 #ifdef REGION_CACHE_NEEDS_WORK
3379   if (b->newline_cache)
3380     {
3381       free_region_cache (b->newline_cache);
3382       b->newline_cache = 0;
3383     }
3384   if (b->width_run_cache)
3385     {
3386       free_region_cache (b->width_run_cache);
3387       b->width_run_cache = 0;
3388     }
3389   b->width_table = Qnil;
3390 #endif
3391 }