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