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