}
DEFUN ("position-bytes", Fposition_bytes, Sposition_bytes, 1, 1, 0,
- "Return the byte position for character position POSITION.")
+ "Return the byte position for character position POSITION.\n\
+If POSITION is out of range, the value is nil.")
(position)
Lisp_Object position;
{
CHECK_NUMBER_COERCE_MARKER (position, 1);
+ if (XINT (position) < BEG || XINT (position) > Z)
+ return Qnil;
return make_number (CHAR_TO_BYTE (XINT (position)));
}
DEFUN ("byte-to-position", Fbyte_to_position, Sbyte_to_position, 1, 1, 0,
- "Return the character position for byte position BYTEPOS.")
+ "Return the character position for byte position BYTEPOS.\n\
+If BYTEPOS is out of range, the value is nil.")
(bytepos)
Lisp_Object bytepos;
{
CHECK_NUMBER (bytepos, 1);
+ if (XINT (bytepos) < BEG_BYTE || XINT (bytepos) > Z_BYTE)
+ return Qnil;
return make_number (BYTE_TO_CHAR (XINT (bytepos)));
}
\f
if (!NILP (current_buffer->enable_multibyte_characters))
len = CHAR_STRING (XFASTINT (val), workbuf, str);
else
- workbuf[0] = XINT (val), str = workbuf, len = 1;
+ {
+ workbuf[0] = (SINGLE_BYTE_CHAR_P (XINT (val))
+ ? XINT (val)
+ : multibyte_char_to_unibyte (XINT (val), Qnil));
+ str = workbuf;
+ len = 1;
+ }
(*insert_func) (str, len);
}
else if (STRINGP (val))
changed = 1;
}
- if (NILP (noundo))
- record_change (pos, 1);
- for (i = 0; i < len; i++) *p++ = tostr[i];
+ /* Take care of the case where the new character
+ combines with neighboring bytes. */
+ if (len == 1
+ && ((! CHAR_HEAD_P (tostr[0])
+ && pos_byte > BEGV_BYTE
+ && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1)))
+ ||
+ (! ASCII_BYTE_P (tostr[0])
+ && pos_byte + 1 < ZV_BYTE
+ && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1)))))
+ {
+ Lisp_Object tem, string;
+
+ struct gcpro gcpro1;
+
+ tem = current_buffer->undo_list;
+ GCPRO1 (tem);
+
+ /* Make a multibyte string containing this
+ single-byte character. */
+ string = Fmake_string (make_number (1),
+ make_number (tochar));
+ SET_STRING_BYTES (XSTRING (string), 1);
+ /* replace_range is less efficient, because it moves the gap,
+ but it handles combining correctly. */
+ replace_range (pos, pos + 1, string,
+ 0, 0, 0);
+ if (! NILP (noundo))
+ current_buffer->undo_list = tem;
+
+ UNGCPRO;
+ }
+ else
+ {
+ if (NILP (noundo))
+ record_change (pos, 1);
+ for (i = 0; i < len; i++) *p++ = tostr[i];
+ }
}
INC_BOTH (pos, pos_byte);
}
nc = tt[oc];
if (nc != oc)
{
- record_change (pos, 1);
- *p = nc;
- signal_after_change (pos, 1, 1);
+ /* Take care of the case where the new character
+ combines with neighboring bytes. */
+ if ((! CHAR_HEAD_P (nc)
+ && pos_byte > BEGV_BYTE
+ && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1)))
+ ||
+ (! ASCII_BYTE_P (nc)
+ && pos_byte + 1 < ZV_BYTE
+ && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1))))
+ {
+ Lisp_Object string;
+
+ string = Fmake_string (make_number (1),
+ make_number (nc));
+ SET_STRING_BYTES (XSTRING (string), 1);
+
+ /* This is less efficient, because it moves the gap,
+ but it handles combining correctly. */
+ replace_range (pos, pos + 1, string,
+ 1, 0, 0);
+ }
+ else
+ {
+ record_change (pos, 1);
+ *p = nc;
+ signal_after_change (pos, 1, 1);
+ }
++cnt;
}
}
start1_byte, start1_byte + len1_byte,
start2_byte, start2_byte + len2_byte);
- replace_range (start2, end2, text1, 1, 0, 1);
- replace_range (start1, end1, text2, 1, 0, 1);
+ replace_range (start2, end2, text1, 1, 0, 0);
+ replace_range (start1, end1, text2, 1, 0, 0);
UNGCPRO;
return Qnil;
/* Don't precompute these addresses. We have to compute them
at the last minute, because the relocating allocator might
have moved the buffer around during the xmalloc. */
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1_byte);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2_byte);
+ start1_addr = BYTE_POS_ADDR (start1_byte);
+ start2_addr = BYTE_POS_ADDR (start2_byte);
bcopy (start2_addr, temp, len2_byte);
bcopy (start1_addr, start1_addr + len2_byte, len1_byte);
temp = (unsigned char *) xmalloc (len1_byte);
else
temp = (unsigned char *) alloca (len1_byte);
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1_byte);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2_byte);
+ start1_addr = BYTE_POS_ADDR (start1_byte);
+ start2_addr = BYTE_POS_ADDR (start2_byte);
bcopy (start1_addr, temp, len1_byte);
bcopy (start2_addr, start1_addr, len2_byte);
bcopy (temp, start1_addr + len2_byte, len1_byte);
temp = (unsigned char *) xmalloc (len1_byte);
else
temp = (unsigned char *) alloca (len1_byte);
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1_byte);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2_byte);
+ start1_addr = BYTE_POS_ADDR (start1_byte);
+ start2_addr = BYTE_POS_ADDR (start2_byte);
bcopy (start1_addr, temp, len1_byte);
bcopy (start2_addr, start1_addr, len2_byte);
bcopy (temp, start2_addr, len1_byte);
temp = (unsigned char *) xmalloc (len2_byte);
else
temp = (unsigned char *) alloca (len2_byte);
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1_byte);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2_byte);
+ start1_addr = BYTE_POS_ADDR (start1_byte);
+ start2_addr = BYTE_POS_ADDR (start2_byte);
bcopy (start2_addr, temp, len2_byte);
bcopy (start1_addr, start1_addr + len_mid + len2_byte, len1_byte);
safe_bcopy (start1_addr + len1_byte, start1_addr + len2_byte, len_mid);
temp = (unsigned char *) xmalloc (len1_byte);
else
temp = (unsigned char *) alloca (len1_byte);
- start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1_byte);
- start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2_byte);
+ start1_addr = BYTE_POS_ADDR (start1_byte);
+ start2_addr = BYTE_POS_ADDR (start2_byte);
bcopy (start1_addr, temp, len1_byte);
bcopy (start2_addr, start1_addr, len2_byte);
bcopy (start1_addr + len1_byte, start1_addr + len2_byte, len_mid);