/* Lisp functions pertaining to editing.
- Copyright (C) 1985,86,87,89,93,94,95,96,97,98, 1999, 2000, 2001
+ Copyright (C) 1985,86,87,89,93,94,95,96,97,98, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <config.h>
-#include <ctype.h>
#include <sys/types.h>
#ifdef VMS
#include <unistd.h>
#endif
+/* Without this, sprintf on Mac OS Classic will produce wrong
+ result. */
+#ifdef MAC_OS8
+#include <stdio.h>
+#endif
+
+#include <ctype.h>
+
#include "lisp.h"
#include "intervals.h"
#include "buffer.h"
extern size_t emacs_strftimeu P_ ((char *, size_t, const char *,
const struct tm *, int));
static int tm_diff P_ ((struct tm *, struct tm *));
-static void find_field P_ ((Lisp_Object, Lisp_Object, int *, int *));
+static void find_field P_ ((Lisp_Object, Lisp_Object, Lisp_Object, int *, Lisp_Object, int *));
static void update_buffer_properties P_ ((int, int));
static Lisp_Object region_limit P_ ((int));
static int lisp_time_argument P_ ((Lisp_Object, time_t *, int *));
static size_t emacs_memftimeu P_ ((char *, size_t, const char *,
size_t, const struct tm *, int));
-static void general_insert_function P_ ((void (*) (unsigned char *, int),
+static void general_insert_function P_ ((void (*) (const unsigned char *, int),
void (*) (Lisp_Object, int, int, int,
int, int),
int, int, Lisp_Object *));
int len;
unsigned char str[MAX_MULTIBYTE_LENGTH];
- CHECK_NUMBER (character, 0);
+ CHECK_NUMBER (character);
len = (SINGLE_BYTE_CHAR_P (XFASTINT (character))
? (*str = (unsigned char)(XFASTINT (character)), 1)
register Lisp_Object string;
{
register Lisp_Object val;
- register struct Lisp_String *p;
- CHECK_STRING (string, 0);
- p = XSTRING (string);
- if (p->size)
+ CHECK_STRING (string);
+ if (SCHARS (string))
{
if (STRING_MULTIBYTE (string))
- XSETFASTINT (val, STRING_CHAR (p->data, STRING_BYTES (p)));
+ XSETFASTINT (val, STRING_CHAR (SDATA (string), SBYTES (string)));
else
- XSETFASTINT (val, p->data[0]);
+ XSETFASTINT (val, SREF (string, 0));
}
else
XSETFASTINT (val, 0);
return position;
}
- CHECK_NUMBER_COERCE_MARKER (position, 0);
+ CHECK_NUMBER_COERCE_MARKER (position);
pos = clip_to_bounds (BEGV, XINT (position), ZV);
SET_PT (pos);
m = Fmarker_position (current_buffer->mark);
if (NILP (m))
- error ("There is no region now");
+ error ("The mark is not set now, so there is no region");
if ((PT < XFASTINT (m)) == beginningp)
m = make_number (PT);
}
\f
-#if 0 /* Not used. */
-
-/* Return nonzero if POS1 and POS2 have the same value
- for the text property PROP. */
+/* Find all the overlays in the current buffer that touch position POS.
+ Return the number found, and store them in a vector in VEC
+ of length LEN. */
static int
-char_property_eq (prop, pos1, pos2)
- Lisp_Object prop;
- Lisp_Object pos1, pos2;
+overlays_around (pos, vec, len)
+ int pos;
+ Lisp_Object *vec;
+ int len;
{
- Lisp_Object pval1, pval2;
+ Lisp_Object tail, overlay, start, end;
+ int startpos, endpos;
+ int idx = 0;
- pval1 = Fget_char_property (pos1, prop, Qnil);
- pval2 = Fget_char_property (pos2, prop, Qnil);
+ for (tail = current_buffer->overlays_before;
+ GC_CONSP (tail);
+ tail = XCDR (tail))
+ {
+ overlay = XCAR (tail);
+
+ end = OVERLAY_END (overlay);
+ endpos = OVERLAY_POSITION (end);
+ if (endpos < pos)
+ break;
+ start = OVERLAY_START (overlay);
+ startpos = OVERLAY_POSITION (start);
+ if (startpos <= pos)
+ {
+ if (idx < len)
+ vec[idx] = overlay;
+ /* Keep counting overlays even if we can't return them all. */
+ idx++;
+ }
+ }
- return EQ (pval1, pval2);
+ for (tail = current_buffer->overlays_after;
+ GC_CONSP (tail);
+ tail = XCDR (tail))
+ {
+ overlay = XCAR (tail);
+
+ start = OVERLAY_START (overlay);
+ startpos = OVERLAY_POSITION (start);
+ if (pos < startpos)
+ break;
+ end = OVERLAY_END (overlay);
+ endpos = OVERLAY_POSITION (end);
+ if (pos <= endpos)
+ {
+ if (idx < len)
+ vec[idx] = overlay;
+ idx++;
+ }
+ }
+
+ return idx;
}
-#endif /* 0 */
+/* Return the value of property PROP, in OBJECT at POSITION.
+ It's the value of PROP that a char inserted at POSITION would get.
+ OBJECT is optional and defaults to the current buffer.
+ If OBJECT is a buffer, then overlay properties are considered as well as
+ text properties.
+ If OBJECT is a window, then that window's buffer is used, but
+ window-specific overlays are considered only if they are associated
+ with OBJECT. */
+Lisp_Object
+get_pos_property (position, prop, object)
+ Lisp_Object position, object;
+ register Lisp_Object prop;
+{
+ struct window *w = 0;
-/* Return the direction from which the text-property PROP would be
- inherited by any new text inserted at POS: 1 if it would be
- inherited from the char after POS, -1 if it would be inherited from
- the char before POS, and 0 if from neither. */
+ CHECK_NUMBER_COERCE_MARKER (position);
-static int
-text_property_stickiness (prop, pos)
- Lisp_Object prop;
- Lisp_Object pos;
-{
- Lisp_Object prev_pos, front_sticky;
- int is_rear_sticky = 1, is_front_sticky = 0; /* defaults */
+ if (NILP (object))
+ XSETBUFFER (object, current_buffer);
- if (XINT (pos) > BEGV)
- /* Consider previous character. */
+ if (WINDOWP (object))
{
- Lisp_Object rear_non_sticky;
+ w = XWINDOW (object);
+ object = w->buffer;
+ }
+ if (BUFFERP (object))
+ {
+ int posn = XINT (position);
+ int noverlays;
+ Lisp_Object *overlay_vec, tem;
+ struct buffer *obuf = current_buffer;
+
+ set_buffer_temp (XBUFFER (object));
- prev_pos = make_number (XINT (pos) - 1);
- rear_non_sticky = Fget_text_property (prev_pos, Qrear_nonsticky, Qnil);
+ /* First try with room for 40 overlays. */
+ noverlays = 40;
+ overlay_vec = (Lisp_Object *) alloca (noverlays * sizeof (Lisp_Object));
+ noverlays = overlays_around (posn, overlay_vec, noverlays);
+
+ /* If there are more than 40,
+ make enough space for all, and try again. */
+ if (noverlays > 40)
+ {
+ overlay_vec = (Lisp_Object *) alloca (noverlays * sizeof (Lisp_Object));
+ noverlays = overlays_around (posn, overlay_vec, noverlays);
+ }
+ noverlays = sort_overlays (overlay_vec, noverlays, NULL);
- if (!NILP (CONSP (rear_non_sticky)
- ? Fmemq (prop, rear_non_sticky)
- : rear_non_sticky))
- /* PROP is rear-non-sticky. */
- is_rear_sticky = 0;
+ set_buffer_temp (obuf);
+
+ /* Now check the overlays in order of decreasing priority. */
+ while (--noverlays >= 0)
+ {
+ Lisp_Object ol = overlay_vec[noverlays];
+ tem = Foverlay_get (ol, prop);
+ if (!NILP (tem))
+ {
+ /* Check the overlay is indeed active at point. */
+ Lisp_Object start = OVERLAY_START (ol), finish = OVERLAY_END (ol);
+ if ((OVERLAY_POSITION (start) == posn
+ && XMARKER (start)->insertion_type == 1)
+ || (OVERLAY_POSITION (finish) == posn
+ && XMARKER (finish)->insertion_type == 0))
+ ; /* The overlay will not cover a char inserted at point. */
+ else
+ {
+ return tem;
+ }
+ }
+ }
+
}
- /* Consider following character. */
- front_sticky = Fget_text_property (pos, Qfront_sticky, Qnil);
-
- if (EQ (front_sticky, Qt)
- || (CONSP (front_sticky)
- && !NILP (Fmemq (prop, front_sticky))))
- /* PROP is inherited from after. */
- is_front_sticky = 1;
-
- /* Simple cases, where the properties are consistent. */
- if (is_rear_sticky && !is_front_sticky)
- return -1;
- else if (!is_rear_sticky && is_front_sticky)
- return 1;
- else if (!is_rear_sticky && !is_front_sticky)
- return 0;
-
- /* The stickiness properties are inconsistent, so we have to
- disambiguate. Basically, rear-sticky wins, _except_ if the
- property that would be inherited has a value of nil, in which case
- front-sticky wins. */
- if (XINT (pos) == BEGV || NILP (Fget_text_property (prev_pos, prop, Qnil)))
- return 1;
- else
- return -1;
+ { /* Now check the text-properties. */
+ int stickiness = text_property_stickiness (prop, position);
+ if (stickiness > 0)
+ return Fget_text_property (position, prop, Qnil);
+ else if (stickiness < 0 && XINT (position) > BEGV)
+ return Fget_text_property (make_number (XINT (position) - 1),
+ prop, Qnil);
+ else
+ return Qnil;
+ }
}
-\f
/* Find the field surrounding POS in *BEG and *END. If POS is nil,
the value of point is used instead. If BEG or END null,
means don't store the beginning or end of the field.
+ BEG_LIMIT and END_LIMIT serve to limit the ranged of the returned
+ results; they do not effect boundary behavior.
+
If MERGE_AT_BOUNDARY is nonzero, then if POS is at the very first
position of a field, then the beginning of the previous field is
returned instead of the beginning of POS's field (since the end of a
is not stored. */
static void
-find_field (pos, merge_at_boundary, beg, end)
+find_field (pos, merge_at_boundary, beg_limit, beg, end_limit, end)
Lisp_Object pos;
Lisp_Object merge_at_boundary;
+ Lisp_Object beg_limit, end_limit;
int *beg, *end;
{
/* Fields right before and after the point. */
Lisp_Object before_field, after_field;
- /* If the fields came from overlays, the associated overlays.
- Qnil means they came from text-properties. */
- Lisp_Object before_overlay = Qnil, after_overlay = Qnil;
/* 1 if POS counts as the start of a field. */
int at_field_start = 0;
/* 1 if POS counts as the end of a field. */
if (NILP (pos))
XSETFASTINT (pos, PT);
else
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
+ CHECK_NUMBER_COERCE_MARKER (pos);
after_field
- = get_char_property_and_overlay (pos, Qfield, Qnil, &after_overlay);
+ = get_char_property_and_overlay (pos, Qfield, Qnil, NULL);
before_field
= (XFASTINT (pos) > BEGV
? get_char_property_and_overlay (make_number (XINT (pos) - 1),
- Qfield, Qnil,
- &before_overlay)
+ Qfield, Qnil, NULL)
: Qnil);
/* See if we need to handle the case where MERGE_AT_BOUNDARY is nil
MERGE_AT_BOUNDARY is non-nil (see function comment) is actually the
more natural one; then we avoid treating the beginning of a field
specially. */
- if (NILP (merge_at_boundary) && !EQ (after_field, before_field))
- /* We are at a boundary, see which direction is inclusive. We
- decide by seeing which field the `field' property sticks to. */
+ if (NILP (merge_at_boundary))
{
- /* -1 means insertions go into before_field, 1 means they go
- into after_field, 0 means neither. */
- int stickiness;
- /* Whether the before/after_field come from overlays. */
- int bop = !NILP (before_overlay);
- int aop = !NILP (after_overlay);
-
- if (bop && XMARKER (OVERLAY_END (before_overlay))->insertion_type == 1)
- /* before_field is from an overlay, which expands upon
- end-insertions. Note that it's possible for after_overlay to
- also eat insertions here, but then they will overlap, and
- there's not much we can do. */
- stickiness = -1;
- else if (aop
- && XMARKER (OVERLAY_START (after_overlay))->insertion_type == 0)
- /* after_field is from an overlay, which expand to contain
- start-insertions. */
- stickiness = 1;
- else if (bop && aop)
- /* Both fields come from overlays, but neither will contain any
- insertion here. */
- stickiness = 0;
- else if (bop)
- /* before_field is an overlay that won't eat any insertion, but
- after_field is from a text-property. Assume that the
- text-property continues underneath the overlay, and so will
- be inherited by any insertion, regardless of any stickiness
- settings. */
- stickiness = 1;
- else if (aop)
- /* Similarly, when after_field is the overlay. */
- stickiness = -1;
- else
- /* Both fields come from text-properties. Look for explicit
- stickiness properties. */
- stickiness = text_property_stickiness (Qfield, pos);
-
- if (stickiness > 0)
- at_field_start = 1;
- else if (stickiness < 0)
+ Lisp_Object field = get_pos_property (pos, Qfield, Qnil);
+ if (!EQ (field, after_field))
at_field_end = 1;
- else
- /* STICKINESS == 0 means that any inserted text will get a
- `field' char-property of nil, so check to see if that
- matches either of the adjacent characters (this being a
- kind of "stickiness by default"). */
- {
- if (NILP (before_field))
- at_field_end = 1; /* Sticks to the left. */
- else if (NILP (after_field))
- at_field_start = 1; /* Sticks to the right. */
- }
+ if (!EQ (field, before_field))
+ at_field_start = 1;
+ if (NILP (field) && at_field_start && at_field_end)
+ /* If an inserted char would have a nil field while the surrounding
+ text is non-nil, we're probably not looking at a
+ zero-length field, but instead at a non-nil field that's
+ not intended for editing (such as comint's prompts). */
+ at_field_end = at_field_start = 0;
}
/* Note about special `boundary' fields:
else
/* Find the previous field boundary. */
{
+ Lisp_Object p = pos;
if (!NILP (merge_at_boundary) && EQ (before_field, Qboundary))
/* Skip a `boundary' field. */
- pos = Fprevious_single_char_property_change (pos, Qfield, Qnil,Qnil);
+ p = Fprevious_single_char_property_change (p, Qfield, Qnil,
+ beg_limit);
- pos = Fprevious_single_char_property_change (pos, Qfield, Qnil, Qnil);
- *beg = NILP (pos) ? BEGV : XFASTINT (pos);
+ p = Fprevious_single_char_property_change (p, Qfield, Qnil,
+ beg_limit);
+ *beg = NILP (p) ? BEGV : XFASTINT (p);
}
}
{
if (!NILP (merge_at_boundary) && EQ (after_field, Qboundary))
/* Skip a `boundary' field. */
- pos = Fnext_single_char_property_change (pos, Qfield, Qnil, Qnil);
+ pos = Fnext_single_char_property_change (pos, Qfield, Qnil,
+ end_limit);
- pos = Fnext_single_char_property_change (pos, Qfield, Qnil, Qnil);
+ pos = Fnext_single_char_property_change (pos, Qfield, Qnil,
+ end_limit);
*end = NILP (pos) ? ZV : XFASTINT (pos);
}
}
Lisp_Object pos;
{
int beg, end;
- find_field (pos, Qnil, &beg, &end);
+ find_field (pos, Qnil, Qnil, &beg, Qnil, &end);
if (beg != end)
del_range (beg, end);
return Qnil;
Lisp_Object pos;
{
int beg, end;
- find_field (pos, Qnil, &beg, &end);
+ find_field (pos, Qnil, Qnil, &beg, Qnil, &end);
return make_buffer_string (beg, end, 1);
}
Lisp_Object pos;
{
int beg, end;
- find_field (pos, Qnil, &beg, &end);
+ find_field (pos, Qnil, Qnil, &beg, Qnil, &end);
return make_buffer_string (beg, end, 0);
}
-DEFUN ("field-beginning", Ffield_beginning, Sfield_beginning, 0, 2, 0,
+DEFUN ("field-beginning", Ffield_beginning, Sfield_beginning, 0, 3, 0,
doc: /* Return the beginning of the field surrounding POS.
A field is a region of text with the same `field' property.
If POS is nil, the value of point is used for POS.
If ESCAPE-FROM-EDGE is non-nil and POS is at the beginning of its
-field, then the beginning of the *previous* field is returned. */)
- (pos, escape_from_edge)
- Lisp_Object pos, escape_from_edge;
+field, then the beginning of the *previous* field is returned.
+If LIMIT is non-nil, it is a buffer position; if the beginning of the field
+is before LIMIT, then LIMIT will be returned instead. */)
+ (pos, escape_from_edge, limit)
+ Lisp_Object pos, escape_from_edge, limit;
{
int beg;
- find_field (pos, escape_from_edge, &beg, 0);
+ find_field (pos, escape_from_edge, limit, &beg, Qnil, 0);
return make_number (beg);
}
-DEFUN ("field-end", Ffield_end, Sfield_end, 0, 2, 0,
+DEFUN ("field-end", Ffield_end, Sfield_end, 0, 3, 0,
doc: /* Return the end of the field surrounding POS.
A field is a region of text with the same `field' property.
If POS is nil, the value of point is used for POS.
If ESCAPE-FROM-EDGE is non-nil and POS is at the end of its field,
-then the end of the *following* field is returned. */)
- (pos, escape_from_edge)
- Lisp_Object pos, escape_from_edge;
+then the end of the *following* field is returned.
+If LIMIT is non-nil, it is a buffer position; if the end of the field
+is after LIMIT, then LIMIT will be returned instead. */)
+ (pos, escape_from_edge, limit)
+ Lisp_Object pos, escape_from_edge, limit;
{
int end;
- find_field (pos, escape_from_edge, 0, &end);
+ find_field (pos, escape_from_edge, Qnil, 0, limit, &end);
return make_number (end);
}
int fwd, shortage;
Lisp_Object field_bound;
- CHECK_NUMBER_COERCE_MARKER (new_pos, 0);
- CHECK_NUMBER_COERCE_MARKER (old_pos, 0);
+ CHECK_NUMBER_COERCE_MARKER (new_pos);
+ CHECK_NUMBER_COERCE_MARKER (old_pos);
fwd = (XFASTINT (new_pos) > XFASTINT (old_pos));
if (fwd)
- field_bound = Ffield_end (old_pos, escape_from_edge);
+ field_bound = Ffield_end (old_pos, escape_from_edge, new_pos);
else
- field_bound = Ffield_beginning (old_pos, escape_from_edge);
+ field_bound = Ffield_beginning (old_pos, escape_from_edge, new_pos);
if (/* See if ESCAPE_FROM_EDGE caused FIELD_BOUND to jump to the
other side of NEW_POS, which would mean that NEW_POS is
if (NILP (n))
XSETFASTINT (n, 1);
else
- CHECK_NUMBER (n, 0);
+ CHECK_NUMBER (n);
orig = PT;
orig_byte = PT_BYTE;
if (NILP (n))
XSETFASTINT (n, 1);
else
- CHECK_NUMBER (n, 0);
+ CHECK_NUMBER (n);
end_pos = find_before_next_newline (orig, 0, XINT (n) - (XINT (n) <= 0));
Lisp_Object args;
{
register Lisp_Object val;
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
record_unwind_protect (save_excursion_restore, save_excursion_save ());
Lisp_Object args;
{
Lisp_Object val;
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
return make_number (Z - BEG);
else
{
- CHECK_BUFFER (buffer, 1);
+ CHECK_BUFFER (buffer);
return make_number (BUF_Z (XBUFFER (buffer))
- BUF_BEG (XBUFFER (buffer)));
}
(position)
Lisp_Object position;
{
- CHECK_NUMBER_COERCE_MARKER (position, 1);
+ CHECK_NUMBER_COERCE_MARKER (position);
if (XINT (position) < BEG || XINT (position) > Z)
return Qnil;
return make_number (CHAR_TO_BYTE (XINT (position)));
(bytepos)
Lisp_Object bytepos;
{
- CHECK_NUMBER (bytepos, 1);
+ CHECK_NUMBER (bytepos);
if (XINT (bytepos) < BEG_BYTE || XINT (bytepos) > Z_BYTE)
return Qnil;
return make_number (BYTE_TO_CHAR (XINT (bytepos)));
}
else
{
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
+ CHECK_NUMBER_COERCE_MARKER (pos);
if (XINT (pos) < BEGV || XINT (pos) >= ZV)
return Qnil;
}
else
{
- CHECK_NUMBER_COERCE_MARKER (pos, 0);
+ CHECK_NUMBER_COERCE_MARKER (pos);
if (XINT (pos) <= BEGV || XINT (pos) > ZV)
return Qnil;
if (NILP (uid))
return Vuser_login_name;
- CHECK_NUMBER (uid, 0);
+ CHECK_NUMBER (uid);
pw = (struct passwd *) getpwuid (XINT (uid));
return (pw ? build_string (pw->pw_name) : Qnil);
}
DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
- 0, 0, 0,
+ 0, 0, 0,
doc: /* Return the name of the user's real uid, as a string.
This ignores the environment variables LOGNAME and USER, so it differs from
`user-login-name' when running under `su'. */)
else if (NUMBERP (uid))
pw = (struct passwd *) getpwuid ((uid_t) XFLOATINT (uid));
else if (STRINGP (uid))
- pw = (struct passwd *) getpwnam (XSTRING (uid)->data);
+ pw = (struct passwd *) getpwnam (SDATA (uid));
else
error ("Invalid UID specification");
full = make_string (p, q ? q - p : strlen (p));
#ifdef AMPERSAND_FULL_NAME
- p = XSTRING (full)->data;
+ p = SDATA (full);
q = (unsigned char *) index (p, '&');
/* Substitute the login name for the &, upcasing the first character. */
if (q)
Lisp_Object login;
login = Fuser_login_name (make_number (pw->pw_uid));
- r = (unsigned char *) alloca (strlen (p) + XSTRING (login)->size + 1);
+ r = (unsigned char *) alloca (strlen (p) + SCHARS (login) + 1);
bcopy (p, r, q - p);
r[q - p] = 0;
- strcat (r, XSTRING (login)->data);
+ strcat (r, SDATA (login));
r[q - p] = UPCASE (r[q - p]);
strcat (r, q + 1);
full = build_string (r);
get_system_name ()
{
if (STRINGP (Vsystem_name))
- return (char *) XSTRING (Vsystem_name)->data;
+ return (char *) SDATA (Vsystem_name);
else
return "";
}
{
Lisp_Object high, low;
high = Fcar (specified_time);
- CHECK_NUMBER (high, 0);
+ CHECK_NUMBER (high);
low = Fcdr (specified_time);
if (CONSP (low))
{
*usec = 0;
else
{
- CHECK_NUMBER (usec_l, 0);
+ CHECK_NUMBER (usec_l);
*usec = XINT (usec_l);
}
}
}
else if (usec)
*usec = 0;
- CHECK_NUMBER (low, 0);
+ CHECK_NUMBER (low);
*result = (XINT (high) << 16) + (XINT (low) & 0xffff);
return *result >> 16 == XINT (high);
}
Certain flags and modifiers are available with some format controls.
The flags are `_', `-', `^' and `#'. For certain characters X,
%_X is like %X, but padded with blanks; %-X is like %X,
-ut without padding. %^X is like %X but with all textual
-characters up-cased; %#X is like %X but with letter-case of
+but without padding. %^X is like %X, but with all textual
+characters up-cased; %#X is like %X, but with letter-case of
all textual characters reversed.
%NX (where N stands for an integer) is like %X,
but takes up at least N (a number) positions.
struct tm *tm;
int ut = ! NILP (universal);
- CHECK_STRING (format_string, 1);
+ CHECK_STRING (format_string);
if (! lisp_time_argument (time, &value, NULL))
error ("Invalid time specification");
Vlocale_coding_system, 1);
/* This is probably enough. */
- size = STRING_BYTES (XSTRING (format_string)) * 6 + 50;
+ size = SBYTES (format_string) * 6 + 50;
tm = ut ? gmtime (&value) : localtime (&value);
if (! tm)
int result;
buf[0] = '\1';
- result = emacs_memftimeu (buf, size, XSTRING (format_string)->data,
- STRING_BYTES (XSTRING (format_string)),
+ result = emacs_memftimeu (buf, size, SDATA (format_string),
+ SBYTES (format_string),
tm, ut);
if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
return code_convert_string_norecord (make_string (buf, result),
/* If buffer was too small, make it bigger and try again. */
result = emacs_memftimeu (NULL, (size_t) -1,
- XSTRING (format_string)->data,
- STRING_BYTES (XSTRING (format_string)),
+ SDATA (format_string),
+ SBYTES (format_string),
tm, ut);
size = result + 1;
}
struct tm tm;
Lisp_Object zone = (nargs > 6 ? args[nargs - 1] : Qnil);
- CHECK_NUMBER (args[0], 0); /* second */
- CHECK_NUMBER (args[1], 1); /* minute */
- CHECK_NUMBER (args[2], 2); /* hour */
- CHECK_NUMBER (args[3], 3); /* day */
- CHECK_NUMBER (args[4], 4); /* month */
- CHECK_NUMBER (args[5], 5); /* year */
+ CHECK_NUMBER (args[0]); /* second */
+ CHECK_NUMBER (args[1]); /* minute */
+ CHECK_NUMBER (args[2]); /* hour */
+ CHECK_NUMBER (args[3]); /* day */
+ CHECK_NUMBER (args[4]); /* month */
+ CHECK_NUMBER (args[5]); /* year */
tm.tm_sec = XINT (args[0]);
tm.tm_min = XINT (args[1]);
if (EQ (zone, Qt))
tzstring = "UTC0";
else if (STRINGP (zone))
- tzstring = (char *) XSTRING (zone)->data;
+ tzstring = (char *) SDATA (zone);
else if (INTEGERP (zone))
{
int abszone = abs (XINT (zone));
tzstring = "UTC0";
else
{
- CHECK_STRING (tz, 0);
- tzstring = (char *) XSTRING (tz)->data;
+ CHECK_STRING (tz);
+ tzstring = (char *) SDATA (tz);
}
set_time_zone_rule (tzstring);
static void
general_insert_function (insert_func, insert_from_string_func,
inherit, nargs, args)
- void (*insert_func) P_ ((unsigned char *, int));
+ void (*insert_func) P_ ((const unsigned char *, int));
void (*insert_from_string_func) P_ ((Lisp_Object, int, int, int, int, int));
int inherit, nargs;
register Lisp_Object *args;
else if (STRINGP (val))
{
(*insert_from_string_func) (val, 0, 0,
- XSTRING (val)->size,
- STRING_BYTES (XSTRING (val)),
+ SCHARS (val),
+ SBYTES (val),
inherit);
}
else
int len;
unsigned char str[MAX_MULTIBYTE_LENGTH];
- CHECK_NUMBER (character, 0);
- CHECK_NUMBER (count, 1);
+ CHECK_NUMBER (character);
+ CHECK_NUMBER (count);
if (!NILP (current_buffer->enable_multibyte_characters))
len = CHAR_STRING (XFASTINT (character), str);
result = make_uninit_multibyte_string (end - start, end_byte - start_byte);
else
result = make_uninit_string (end - start);
- bcopy (BYTE_POS_ADDR (start_byte), XSTRING (result)->data,
+ bcopy (BYTE_POS_ADDR (start_byte), SDATA (result),
end_byte - start_byte);
/* If desired, update and copy the text properties. */
}
DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
- 1, 3, 0,
+ 1, 3, 0,
doc: /* Insert before point a substring of the contents of buffer BUFFER.
BUFFER may be a buffer or a buffer name.
Arguments START and END are character numbers specifying the substring.
b = BUF_BEGV (bp);
else
{
- CHECK_NUMBER_COERCE_MARKER (start, 0);
+ CHECK_NUMBER_COERCE_MARKER (start);
b = XINT (start);
}
if (NILP (end))
e = BUF_ZV (bp);
else
{
- CHECK_NUMBER_COERCE_MARKER (end, 1);
+ CHECK_NUMBER_COERCE_MARKER (end);
e = XINT (end);
}
}
DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings,
- 6, 6, 0,
+ 6, 6, 0,
doc: /* Compare two substrings of two buffers; return result as number.
the value is -N if first string is less after N-1 chars,
+N if first string is greater after N-1 chars, or 0 if strings match.
begp1 = BUF_BEGV (bp1);
else
{
- CHECK_NUMBER_COERCE_MARKER (start1, 1);
+ CHECK_NUMBER_COERCE_MARKER (start1);
begp1 = XINT (start1);
}
if (NILP (end1))
endp1 = BUF_ZV (bp1);
else
{
- CHECK_NUMBER_COERCE_MARKER (end1, 2);
+ CHECK_NUMBER_COERCE_MARKER (end1);
endp1 = XINT (end1);
}
begp2 = BUF_BEGV (bp2);
else
{
- CHECK_NUMBER_COERCE_MARKER (start2, 4);
+ CHECK_NUMBER_COERCE_MARKER (start2);
begp2 = XINT (start2);
}
if (NILP (end2))
endp2 = BUF_ZV (bp2);
else
{
- CHECK_NUMBER_COERCE_MARKER (end2, 5);
+ CHECK_NUMBER_COERCE_MARKER (end2);
endp2 = XINT (end2);
}
characters, not just the bytes. */
int c1, c2;
+ QUIT;
+
if (! NILP (bp1->enable_multibyte_characters))
{
c1 = BUF_FETCH_MULTIBYTE_CHAR (bp1, i1_byte);
}
DEFUN ("subst-char-in-region", Fsubst_char_in_region,
- Ssubst_char_in_region, 4, 5, 0,
+ Ssubst_char_in_region, 4, 5, 0,
doc: /* From START to END, replace FROMCHAR with TOCHAR each time it occurs.
If optional arg NOUNDO is non-nil, don't record this change for undo
and don't mark the buffer as really changed.
int changed = 0;
unsigned char fromstr[MAX_MULTIBYTE_LENGTH], tostr[MAX_MULTIBYTE_LENGTH];
unsigned char *p;
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
#define COMBINING_NO 0
#define COMBINING_BEFORE 1
#define COMBINING_AFTER 2
int multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
validate_region (&start, &end);
- CHECK_NUMBER (fromchar, 2);
- CHECK_NUMBER (tochar, 3);
+ CHECK_NUMBER (fromchar);
+ CHECK_NUMBER (tochar);
if (multibyte_p)
{
int multibyte = !NILP (current_buffer->enable_multibyte_characters);
validate_region (&start, &end);
- CHECK_STRING (table, 2);
+ CHECK_STRING (table);
- size = STRING_BYTES (XSTRING (table));
- tt = XSTRING (table)->data;
+ size = SBYTES (table);
+ tt = SDATA (table);
pos_byte = CHAR_TO_BYTE (XINT (start));
stop = CHAR_TO_BYTE (XINT (end));
(start, end)
register Lisp_Object start, end;
{
- CHECK_NUMBER_COERCE_MARKER (start, 0);
- CHECK_NUMBER_COERCE_MARKER (end, 1);
+ CHECK_NUMBER_COERCE_MARKER (start);
+ CHECK_NUMBER_COERCE_MARKER (end);
if (XINT (start) > XINT (end))
{
struct Lisp_Marker *end = XMARKER (XCDR (data));
struct buffer *buf = beg->buffer; /* END should have the same buffer. */
- if (beg->charpos != BUF_BEGV(buf) || end->charpos != BUF_ZV(buf))
+ if (buf /* Verify marker still points to a buffer. */
+ && (beg->charpos != BUF_BEGV (buf) || end->charpos != BUF_ZV (buf)))
/* The restriction has changed from the saved one, so restore
the saved restriction. */
{
/* The point is outside the new visible range, move it inside. */
SET_BUF_PT_BOTH (buf,
clip_to_bounds (beg->charpos, pt, end->charpos),
- clip_to_bounds (beg->bytepos, BUF_PT_BYTE(buf),
+ clip_to_bounds (beg->bytepos, BUF_PT_BYTE (buf),
end->bytepos));
buf->clip_changed = 1; /* Remember that the narrowing changed. */
{
struct buffer *buf = XBUFFER (data);
- if (BUF_BEGV(buf) != BUF_BEG(buf) || BUF_ZV(buf) != BUF_Z(buf))
+ if (buf /* Verify marker still points to a buffer. */
+ && (BUF_BEGV (buf) != BUF_BEG (buf) || BUF_ZV (buf) != BUF_Z (buf)))
/* The buffer has been narrowed, get rid of the narrowing. */
{
- SET_BUF_BEGV_BOTH (buf, BUF_BEG(buf), BUF_BEG_BYTE(buf));
- SET_BUF_ZV_BOTH (buf, BUF_Z(buf), BUF_Z_BYTE(buf));
+ SET_BUF_BEGV_BOTH (buf, BUF_BEG (buf), BUF_BEG_BYTE (buf));
+ SET_BUF_ZV_BOTH (buf, BUF_Z (buf), BUF_Z_BYTE (buf));
buf->clip_changed = 1; /* Remember that the narrowing changed. */
}
Lisp_Object body;
{
register Lisp_Object val;
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
record_unwind_protect (save_restriction_restore, save_restriction_save ());
val = Fprogn (body);
int nargs;
Lisp_Object *args;
{
- if (NILP (args[0]))
+ if (NILP (args[0])
+ || (STRINGP (args[0])
+ && SBYTES (args[0]) == 0))
{
message (0);
return Qnil;
{
register Lisp_Object val;
val = Fformat (nargs, args);
- message3 (val, STRING_BYTES (XSTRING (val)), STRING_MULTIBYTE (val));
+ message3 (val, SBYTES (val), STRING_MULTIBYTE (val));
return val;
}
}
message_text = (char *)xmalloc (80);
message_length = 80;
}
- if (STRING_BYTES (XSTRING (val)) > message_length)
+ if (SBYTES (val) > message_length)
{
- message_length = STRING_BYTES (XSTRING (val));
+ message_length = SBYTES (val);
message_text = (char *)xrealloc (message_text, message_length);
}
- bcopy (XSTRING (val)->data, message_text, STRING_BYTES (XSTRING (val)));
- message2 (message_text, STRING_BYTES (XSTRING (val)),
+ bcopy (SDATA (val), message_text, SBYTES (val));
+ message2 (message_text, SBYTES (val),
STRING_MULTIBYTE (val));
return val;
}
}
-DEFUN ("propertize", Fpropertize, Spropertize, 3, MANY, 0,
+DEFUN ("propertize", Fpropertize, Spropertize, 1, MANY, 0,
doc: /* Return a copy of STRING with text properties added.
First argument is the string to copy.
Remaining arguments form a sequence of PROPERTY VALUE pairs for text
int i;
/* Number of args must be odd. */
- if ((nargs & 1) == 0 || nargs < 3)
+ if ((nargs & 1) == 0 || nargs < 1)
error ("Wrong number of arguments");
properties = string = Qnil;
GCPRO2 (properties, string);
/* First argument must be a string. */
- CHECK_STRING (args[0], 0);
+ CHECK_STRING (args[0]);
string = Fcopy_sequence (args[0]);
for (i = 1; i < nargs; i += 2)
{
- CHECK_SYMBOL (args[i], i);
+ CHECK_SYMBOL (args[i]);
properties = Fcons (args[i], Fcons (args[i + 1], properties));
}
Fadd_text_properties (make_number (0),
- make_number (XSTRING (string)->size),
+ make_number (SCHARS (string)),
properties, string);
RETURN_UNGCPRO (string);
}
#define CONVERTED_BYTE_SIZE(MULTIBYTE, STRING) \
(((MULTIBYTE) && ! STRING_MULTIBYTE (STRING)) \
- ? count_size_as_multibyte (XSTRING (STRING)->data, \
- STRING_BYTES (XSTRING (STRING))) \
- : STRING_BYTES (XSTRING (STRING)))
+ ? count_size_as_multibyte (SDATA (STRING), SBYTES (STRING)) \
+ : SBYTES (STRING))
DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
doc: /* Format a string out of a control-string and arguments.
if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
multibyte = 1;
- CHECK_STRING (args[0], 0);
+ CHECK_STRING (args[0]);
/* If we start out planning a unibyte result,
and later find it has to be multibyte, we jump back to retry. */
retry:
- format = XSTRING (args[0])->data;
- end = format + STRING_BYTES (XSTRING (args[0]));
+ format = SDATA (args[0]);
+ end = format + SBYTES (args[0]);
longest_format = 0;
/* Make room in result for all the non-%-codes in the control string. */
if (*format++ == '%')
{
int thissize = 0;
+ int actual_width = 0;
unsigned char *this_format_start = format - 1;
int field_width, precision;
}
else if (SYMBOLP (args[n]))
{
- /* Use a temp var to avoid problems when ENABLE_CHECKING
- is turned on. */
- struct Lisp_String *t = XSYMBOL (args[n])->name;
- XSETSTRING (args[n], t);
+ args[n] = SYMBOL_NAME (args[n]);
if (STRING_MULTIBYTE (args[n]) && ! multibyte)
{
multibyte = 1;
if (*format != 's' && *format != 'S')
error ("Format specifier doesn't match argument type");
thissize = CONVERTED_BYTE_SIZE (multibyte, args[n]);
+ actual_width = lisp_string_width (args[n], -1, NULL, NULL);
}
/* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */
else if (INTEGERP (args[n]) && *format != 's')
goto retry;
}
args[n] = Fchar_to_string (args[n]);
- thissize = STRING_BYTES (XSTRING (args[n]));
+ thissize = SBYTES (args[n]);
}
}
else if (FLOATP (args[n]) && *format != 's')
{
if (! (*format == 'e' || *format == 'f' || *format == 'g'))
- args[n] = Ftruncate (args[n], Qnil);
+ {
+ if (*format != 'd' && *format != 'o' && *format != 'x'
+ && *format != 'i' && *format != 'X' && *format != 'c')
+ error ("Invalid format operation %%%c", *format);
+ args[n] = Ftruncate (args[n], Qnil);
+ }
/* Note that we're using sprintf to print floats,
so we have to take into account what that function
goto string;
}
- thissize = max (field_width, thissize);
+ thissize += max (0, field_width - actual_width);
total += thissize + 4;
}
n = 0;
/* Scan the format and store result in BUF. */
- format = XSTRING (args[0])->data;
+ format = SDATA (args[0]);
maybe_combine_byte = 0;
while (format != end)
{
&& multibyte
&& !ASCII_BYTE_P (*((unsigned char *) p - 1))
&& STRING_MULTIBYTE (args[n])
- && !CHAR_HEAD_P (XSTRING (args[n])->data[0]))
+ && !CHAR_HEAD_P (SREF (args[n], 0)))
maybe_combine_byte = 1;
- nbytes = copy_text (XSTRING (args[n])->data, p,
- STRING_BYTES (XSTRING (args[n])),
+ nbytes = copy_text (SDATA (args[n]), p,
+ SBYTES (args[n]),
STRING_MULTIBYTE (args[n]), multibyte);
p += nbytes;
- nchars += XSTRING (args[n])->size;
+ nchars += SCHARS (args[n]);
end = nchars;
if (negative)
/* If this argument has text properties, record where
in the result string it appears. */
- if (XSTRING (args[n])->intervals)
+ if (STRING_INTERVALS (args[n]))
{
if (!info)
{
arguments has text properties, set up text properties of the
result string. */
- if (XSTRING (args[0])->intervals || info)
+ if (STRING_INTERVALS (args[0]) || info)
{
Lisp_Object len, new_len, props;
struct gcpro gcpro1;
/* Add text properties from the format string. */
- len = make_number (XSTRING (args[0])->size);
+ len = make_number (SCHARS (args[0]));
props = text_property_list (args[0], make_number (0), len, Qnil);
GCPRO1 (props);
if (CONSP (props))
{
- new_len = make_number (XSTRING (val)->size);
+ new_len = make_number (SCHARS (val));
extend_property_ranges (props, len, new_len);
add_text_properties_from_list (val, props, make_number (0));
}
for (n = 1; n < nargs; ++n)
if (info[n].end)
{
- len = make_number (XSTRING (args[n])->size);
+ len = make_number (SCHARS (args[n]));
new_len = make_number (info[n].end - info[n].start);
props = text_property_list (args[n], make_number (0), len, Qnil);
extend_property_ranges (props, len, new_len);
register Lisp_Object c1, c2;
{
int i1, i2;
- CHECK_NUMBER (c1, 0);
- CHECK_NUMBER (c2, 1);
+ CHECK_NUMBER (c1);
+ CHECK_NUMBER (c2);
if (XINT (c1) == XINT (c2))
return Qt;
staticpro (&Qbuffer_access_fontify_functions);
DEFVAR_LISP ("inhibit-field-text-motion", &Vinhibit_field_text_motion,
- doc: /* Non-nil means.text motion commands don't notice fields. */);
+ doc: /* Non-nil means text motion commands don't notice fields. */);
Vinhibit_field_text_motion = Qnil;
DEFVAR_LISP ("buffer-access-fontify-functions",