#include <config.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
#include "lisp.h"
#include "intervals.h"
#include "buffer.h"
#endif
#define min(x, y) ((x) < (y) ? (x) : (y))
+#define max(x, y) ((x) > (y) ? (x) : (y))
static void insert_from_string_1 P_ ((Lisp_Object, int, int, int, int, int, int));
static void insert_from_buffer_1 ();
void
check_markers ()
{
- register Lisp_Object tail, prev, next;
+ register Lisp_Object tail;
int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
tail = BUF_MARKERS (current_buffer);
int new_s1;
if (!newgap)
- {
- if (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF)
- {
- beg_unchanged = charpos - BEG;
- end_unchanged = Z - charpos;
- }
- else
- {
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
- if (charpos < beg_unchanged)
- beg_unchanged = charpos - BEG;
- }
- }
+ BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
i = GPT_BYTE;
to = GAP_END_ADDR;
register int i;
int new_s1;
- if (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF)
- {
- beg_unchanged = charpos - BEG;
- end_unchanged = Z - charpos;
- }
- else
- {
- if (Z - charpos - 1 < end_unchanged)
- end_unchanged = Z - charpos;
- if (GPT - BEG < beg_unchanged)
- beg_unchanged = GPT - BEG;
- }
+ BUF_COMPUTE_UNCHANGED (current_buffer, charpos, GPT);
i = GPT_BYTE;
from = GAP_END_ADDR;
{
int nchars = 0;
int bytes_left = nbytes;
- Lisp_Object tbl = Qnil, temp;
+ Lisp_Object tbl = Qnil;
/* We set the variable tbl to the reverse table of
Vnonascii_translation_table in advance. */
inherit, prepare, before_markers);
}
\f
+/* See if the byte sequence at STR1 of length LEN1 combine with the
+ byte sequence at STR2 of length LEN2 to form a single composite
+ character. If so, return the number of bytes at the start of STR2
+ which combine in this way. Otherwise, return 0. If STR3 is not
+ NULL, it is a byte sequence of length LEN3 to be appended to STR1
+ before checking the combining. */
+int
+count_combining_composition (str1, len1, str2, len2, str3, len3)
+ unsigned char *str1, *str2, *str3;
+ int len1, len2, len3;
+{
+ int len = len1 + len2 + len3;
+ unsigned char *buf = (unsigned char *) alloca (len + 1);
+ int bytes;
+
+ bcopy (str1, buf, len1);
+ if (str3)
+ {
+ bcopy (str3, buf + len1, len3);
+ len1 += len3;
+ }
+ bcopy (str2, buf + len1 , len2);
+ buf[len] = 0;
+ PARSE_MULTIBYTE_SEQ (buf, len, bytes);
+ return (bytes <= len1 ? 0 : bytes - len1);
+}
+
/* See if the bytes before POS/POS_BYTE combine with bytes
at the start of STRING to form a single character.
If so, return the number of bytes at the start of STRING
int length;
int pos, pos_byte;
{
- int opos = pos, opos_byte = pos_byte;
- int c;
- unsigned char *p = string;
+ int len, combining_bytes;
+ unsigned char *p;
if (NILP (current_buffer->enable_multibyte_characters))
return 0;
- if (length == 0 || CHAR_HEAD_P (*string))
+
+ /* At first, we can exclude the following cases:
+ (1) STRING[0] can't be a following byte of multibyte sequence.
+ (2) POS is the start of the current buffer.
+ (3) A character before POS is not a multibyte character. */
+ if (length == 0 || CHAR_HEAD_P (*string)) /* case (1) */
return 0;
- if (pos == BEG)
+ if (pos_byte == BEG_BYTE) /* case (2) */
return 0;
- c = FETCH_BYTE (pos_byte - 1);
- if (ASCII_BYTE_P (c))
+ len = 1;
+ p = BYTE_POS_ADDR (pos_byte - 1);
+ while (! CHAR_HEAD_P (*p)) p--, len++;
+ if (! BASE_LEADING_CODE_P (*p)) /* case (3) */
return 0;
- DEC_BOTH (pos, pos_byte);
- c = FETCH_BYTE (pos_byte);
- if (! BASE_LEADING_CODE_P (c))
+
+ /* A sequence of a composite character requires a special handling. */
+ if (*p == LEADING_CODE_COMPOSITION)
+ return count_combining_composition (p, len, string, length, NULL, 0);
+
+ combining_bytes = BYTES_BY_CHAR_HEAD (*p) - len;
+ if (combining_bytes <= 0)
+ /* The character preceding POS is, complete and no room for
+ combining bytes (combining_bytes == 0), or an independent 8-bit
+ character (combining_bytes < 0). */
return 0;
- /* We have a combination situation.
- Count the bytes at STRING that will combine. */
+ /* We have a combination situation. Count the bytes at STRING that
+ may combine. */
+ p = string + 1;
while (!CHAR_HEAD_P (*p) && p < string + length)
p++;
- return p - string;
+ return (combining_bytes < p - string ? combining_bytes : p - string);
}
/* See if the bytes after POS/POS_BYTE combine with bytes
int length;
int pos, pos_byte;
{
- int opos = pos, opos_byte = pos_byte;
+ int opos_byte = pos_byte;
int i;
- int c;
+ int bytes;
+ unsigned char *bufp;
if (NILP (current_buffer->enable_multibyte_characters))
return 0;
- if (length > 0 && ASCII_BYTE_P (string[length - 1]))
+
+ /* At first, we can exclude the following cases:
+ (1) The last byte of STRING is an ASCII.
+ (2) POS is the last of the current buffer.
+ (3) A character at POS can't be a following byte of multibyte
+ character. */
+ if (length > 0 && ASCII_BYTE_P (string[length - 1])) /* case (1) */
+ return 0;
+ if (pos_byte == Z_BYTE) /* case (2) */
return 0;
+ bufp = BYTE_POS_ADDR (pos_byte);
+ if (CHAR_HEAD_P (*bufp)) /* case (3) */
+ return 0;
+
i = length - 1;
while (i >= 0 && ! CHAR_HEAD_P (string[i]))
{
}
if (i < 0)
{
- /* All characters in `string' are not character head.
- We must check also preceding bytes at POS.
- We are sure that the gap is at POS. */
- string = BEG_ADDR;
+ /* All characters in STRING are not character head. We must
+ check also preceding bytes at POS. We are sure that the gap
+ is at POS. */
+ unsigned char *p = BEG_ADDR;
i = pos_byte - 2;
- while (i >= 0 && ! CHAR_HEAD_P (string[i]))
+ while (i >= 0 && ! CHAR_HEAD_P (p[i]))
i--;
- if (i < 0 || !BASE_LEADING_CODE_P (string[i]))
+ if (i < 0 || !BASE_LEADING_CODE_P (p[i]))
return 0;
+ /* A sequence of a composite character requires a special handling. */
+ if (p[i] == LEADING_CODE_COMPOSITION)
+ return count_combining_composition (p + i, pos_byte - 1 - i,
+ bufp, Z_BYTE - pos_byte,
+ string, length);
+ bytes = BYTES_BY_CHAR_HEAD (p[i]);
+ return (bytes <= pos_byte - 1 - i + length
+ ? 0
+ : bytes - (pos_byte - 1 - i + length));
}
- else if (!BASE_LEADING_CODE_P (string[i]))
+ if (!BASE_LEADING_CODE_P (string[i]))
return 0;
+ /* A sequence of a composite character requires a special handling. */
+ if (string[i] == LEADING_CODE_COMPOSITION)
+ return count_combining_composition (string + i, length - i,
+ bufp, Z_BYTE - pos_byte, NULL, 0);
- if (pos == Z)
- return 0;
- c = FETCH_BYTE (pos_byte);
- if (CHAR_HEAD_P (c))
- return 0;
- while (pos_byte < Z_BYTE)
- {
- c = FETCH_BYTE (pos_byte);
- if (CHAR_HEAD_P (c))
- break;
- pos_byte++;
- }
+ bytes = BYTES_BY_CHAR_HEAD (string[i]) - (length - i);
+ bufp++, pos_byte++;
+ while (!CHAR_HEAD_P (*bufp)) bufp++, pos_byte++;
- return pos_byte - opos_byte;
+ return (bytes <= pos_byte - opos_byte ? bytes : pos_byte - opos_byte);
}
/* Adjust the position TARGET/TARGET_BYTE for the combining of NBYTES
region boundary, signal an error. */
#define CHECK_BYTE_COMBINING_FOR_INSERT(pos) \
do { \
- if (combined_before_bytes && pos == BEGV \
- || combined_after_bytes && pos == ZV) \
+ if ((combined_before_bytes && pos == BEGV) \
+ || (combined_after_bytes && pos == ZV)) \
byte_combining_error (); \
} while (0)
register int nchars, nbytes;
int inherit, prepare, before_markers;
{
- register Lisp_Object temp;
int combined_before_bytes, combined_after_bytes;
if (NILP (current_buffer->enable_multibyte_characters))
register int pos, pos_byte, nchars, nbytes;
int inherit, before_markers;
{
- register Lisp_Object temp;
struct gcpro gcpro1;
int outgoing_nbytes = nbytes;
int combined_before_bytes, combined_after_bytes;
- int adjusted_nchars;
INTERVAL intervals;
/* Make OUTGOING_NBYTES describe the text
if (PT != GPT)
move_gap_both (PT, PT_BYTE);
- if (GAP_SIZE < nbytes)
+ if (GAP_SIZE < outgoing_nbytes)
make_gap (outgoing_nbytes - GAP_SIZE);
UNGCPRO;
int incoming_nbytes = to_byte - from_byte;
int outgoing_nbytes = incoming_nbytes;
int combined_before_bytes, combined_after_bytes;
- int adjusted_nchars;
INTERVAL intervals;
/* Make OUTGOING_NBYTES describe the text
nbytes_del = STRING_BYTES (XSTRING (prev_text));
}
- if (combine_before && from == BEGV
- || combined_after_bytes && from == ZV)
+ if ((combine_before && from == BEGV)
+ || (combined_after_bytes && from == ZV))
{
/* We can't combine bytes nor signal an error here. So, let's
pretend that the new text is just a single space. */
}
if (combined_before_bytes
- || len_byte == 0 && combined_after_bytes > 0)
+ || (len_byte == 0 && combined_after_bytes > 0))
{
Lisp_Object deletion;
deletion = Qnil;
#endif
{
- int pos = PT, pos_byte = PT_BYTE;
-
if (from < PT)
adjust_point (len - nchars_del, len_byte - nbytes_del);
}
/* As byte combining will decrease Z, we must check this again. */
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
+ if (Z - GPT < END_UNCHANGED)
+ END_UNCHANGED = Z - GPT;
CHECK_MARKERS ();
register Lisp_Object temp;
struct gcpro gcpro1;
int combined_before_bytes, combined_after_bytes;
- int adjusted_inschars;
INTERVAL intervals;
int outgoing_insbytes = insbytes;
Lisp_Object deletion;
if (GPT_BYTE < GPT)
abort ();
- if (GPT - BEG < beg_unchanged)
- beg_unchanged = GPT - BEG;
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
+ if (GPT - BEG < BEG_UNCHANGED)
+ BEG_UNCHANGED = GPT - BEG;
+ if (Z - GPT < END_UNCHANGED)
+ END_UNCHANGED = Z - GPT;
if (GAP_SIZE < insbytes)
make_gap (insbytes - GAP_SIZE);
combined_after_bytes
= count_combining_after (GPT_ADDR, outgoing_insbytes, from, from_byte);
- if (combined_before_bytes && from == BEGV
- || combined_after_bytes && from == ZV)
+ if ((combined_before_bytes && from == BEGV)
+ || (combined_after_bytes && from == ZV))
{
/* Bytes are being combined across the region boundary. We
should avoid it. We recover the original contents before
combine_bytes (from, from_byte, combined_before_bytes);
/* As byte combining will decrease Z, we must check this again. */
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
+ if (Z - GPT < END_UNCHANGED)
+ END_UNCHANGED = Z - GPT;
if (outgoing_insbytes == 0)
evaporate_overlays (from);
if (GPT_BYTE < GPT)
abort ();
- if (GPT - BEG < beg_unchanged)
- beg_unchanged = GPT - BEG;
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
+ if (GPT - BEG < BEG_UNCHANGED)
+ BEG_UNCHANGED = GPT - BEG;
+ if (Z - GPT < END_UNCHANGED)
+ END_UNCHANGED = Z - GPT;
if (combined_after_bytes)
{
record_insert (GPT - 1, 1);
- if (Z - GPT < end_unchanged)
- end_unchanged = Z - GPT;
+ if (Z - GPT < END_UNCHANGED)
+ END_UNCHANGED = Z - GPT;
}
CHECK_MARKERS ();
prepare_to_modify_buffer (start, end, NULL);
- if (start - 1 < beg_unchanged
- || (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF))
- beg_unchanged = start - 1;
- if (Z - end < end_unchanged
- || (unchanged_modified == MODIFF
- && overlay_unchanged_modified == OVERLAY_MODIFF))
- end_unchanged = Z - end;
+ BUF_COMPUTE_UNCHANGED (buffer, start - 1, end);
if (MODIFF <= SAVE_MODIFF)
record_first_change ();
if (!NILP (current_buffer->read_only))
Fbarf_if_buffer_read_only ();
+ /* Let redisplay consider other windows than selected_window
+ if modifying another buffer. */
+ if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
+ ++windows_or_buffers_changed;
+
/* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
if (BUF_INTERVALS (current_buffer) != 0)
{
/* Scan the various individual changes,
accumulating the range info in BEG, END and CHANGE. */
for (tail = combine_after_change_list; CONSP (tail);
- tail = XCONS (tail)->cdr)
+ tail = XCDR (tail))
{
Lisp_Object elt;
int thisbeg, thisend, thischange;
/* Extract the info from the next element. */
- elt = XCONS (tail)->car;
+ elt = XCAR (tail);
if (! CONSP (elt))
continue;
- thisbeg = XINT (XCONS (elt)->car);
+ thisbeg = XINT (XCAR (elt));
- elt = XCONS (elt)->cdr;
+ elt = XCDR (elt);
if (! CONSP (elt))
continue;
- thisend = XINT (XCONS (elt)->car);
+ thisend = XINT (XCAR (elt));
- elt = XCONS (elt)->cdr;
+ elt = XCDR (elt);
if (! CONSP (elt))
continue;
- thischange = XINT (XCONS (elt)->car);
+ thischange = XINT (XCAR (elt));
/* Merge this range into the accumulated range. */
change += thischange;
"Used internally by the `combine-after-change-calls' macro.");
Vcombine_after_change_calls = Qnil;
+ DEFVAR_BOOL ("inhibit-modification-hooks", &inhibit_modification_hooks,
+ "Non-nil means don't run any of the hooks that respond to buffer changes.\n\
+This affects `before-change-functions' and `after-change-functions',\n\
+as well as hooks attached to text properties and overlays.");
+ inhibit_modification_hooks = 0;
+
defsubr (&Scombine_after_change_execute);
}