Check for buffer and string overflow more precisely.
[bpt/emacs.git] / src / editfns.c
CommitLineData
35692fe0 1/* Lisp functions pertaining to editing.
64c60c2f 2
73b0cd50 3Copyright (C) 1985-1987, 1989, 1993-2011 Free Software Foundation, Inc.
35692fe0
JB
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
35692fe0 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
35692fe0
JB
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
35692fe0
JB
19
20
18160b98 21#include <config.h>
68c45bf0 22#include <sys/types.h>
3c14598c 23#include <stdio.h>
d7306fe6 24#include <setjmp.h>
bfb61299 25
5b9c0a1d 26#ifdef HAVE_PWD_H
35692fe0 27#include <pwd.h>
bfb61299
JB
28#endif
29
dfcf069d 30#include <unistd.h>
dfcf069d 31
3bb9abc8
ST
32#ifdef HAVE_SYS_UTSNAME_H
33#include <sys/utsname.h>
34#endif
35
b17f9379
DN
36#include "lisp.h"
37
3c14598c
EZ
38/* systime.h includes <sys/time.h> which, on some systems, is required
39 for <sys/resource.h>; thus systime.h must be included before
40 <sys/resource.h> */
41#include "systime.h"
21acf124
ST
42
43#if defined HAVE_SYS_RESOURCE_H
4211ee7d 44#include <sys/resource.h>
e0f712ba
AC
45#endif
46
409847a1 47#include <ctype.h>
37910ab2 48#include <float.h>
b8d9bd41
PE
49#include <limits.h>
50#include <intprops.h>
16c3e636 51#include <strftime.h>
37910ab2 52#include <verify.h>
409847a1 53
74d6d8c5 54#include "intervals.h"
35692fe0 55#include "buffer.h"
40fbd254 56#include "character.h"
68c45bf0 57#include "coding.h"
0ae83348 58#include "frame.h"
35692fe0 59#include "window.h"
b91834c3 60#include "blockinput.h"
35692fe0 61
a03eaf1c
RS
62#ifndef NULL
63#define NULL 0
64#endif
65
d823c26b
EZ
66#ifndef USER_FULL_NAME
67#define USER_FULL_NAME pw->pw_gecos
68#endif
69
f12ef5eb 70#ifndef USE_CRT_DLL
c59b5089 71extern char **environ;
f12ef5eb
AI
72#endif
73
aac18aa4
PE
74#define TM_YEAR_BASE 1900
75
d65b4235
PE
76/* Nonzero if TM_YEAR is a struct tm's tm_year value that causes
77 asctime to have well-defined behavior. */
78#ifndef TM_YEAR_IN_ASCTIME_RANGE
79# define TM_YEAR_IN_ASCTIME_RANGE(tm_year) \
80 (1000 - TM_YEAR_BASE <= (tm_year) && (tm_year) <= 9999 - TM_YEAR_BASE)
81#endif
82
c433c134 83#ifdef WINDOWSNT
361358ea 84extern Lisp_Object w32_get_internal_run_time (void);
c433c134
JR
85#endif
86
fe31d94c 87static void time_overflow (void) NO_RETURN;
f57e2426 88static int tm_diff (struct tm *, struct tm *);
413d18e7
EZ
89static void find_field (Lisp_Object, Lisp_Object, Lisp_Object,
90 EMACS_INT *, Lisp_Object, EMACS_INT *);
29cdc13e 91static void update_buffer_properties (EMACS_INT, EMACS_INT);
f57e2426 92static Lisp_Object region_limit (int);
a4180391
PE
93static size_t emacs_nmemftime (char *, size_t, const char *,
94 size_t, const struct tm *, int, int);
b68864e5 95static void general_insert_function (void (*) (const char *, EMACS_INT),
9628fed7
SM
96 void (*) (Lisp_Object, EMACS_INT,
97 EMACS_INT, EMACS_INT,
98 EMACS_INT, int),
c5101a77 99 int, size_t, Lisp_Object *);
f57e2426
J
100static Lisp_Object subst_char_in_region_unwind (Lisp_Object);
101static Lisp_Object subst_char_in_region_unwind_1 (Lisp_Object);
29cdc13e
EZ
102static void transpose_markers (EMACS_INT, EMACS_INT, EMACS_INT, EMACS_INT,
103 EMACS_INT, EMACS_INT, EMACS_INT, EMACS_INT);
260e2e2a 104
955cbe7b 105static Lisp_Object Qbuffer_access_fontify_functions;
cd64ea1d 106static Lisp_Object Fuser_full_name (Lisp_Object);
e3ed8469 107
acb7cc89
GM
108/* Symbol for the text property used to mark fields. */
109
110Lisp_Object Qfield;
111
112/* A special value for Qfield properties. */
113
955cbe7b 114static Lisp_Object Qboundary;
acb7cc89
GM
115
116
35692fe0 117void
971de7fb 118init_editfns (void)
35692fe0 119{
63c5d10b 120 const char *user_name;
e7f8264d 121 register char *p;
35692fe0 122 struct passwd *pw; /* password entry for the current user */
35692fe0
JB
123 Lisp_Object tem;
124
125 /* Set up system_name even when dumping. */
ac988277 126 init_system_name ();
35692fe0
JB
127
128#ifndef CANNOT_DUMP
129 /* Don't bother with this on initial start when just dumping out */
130 if (!initialized)
131 return;
132#endif /* not CANNOT_DUMP */
133
63c5d10b 134 pw = getpwuid (getuid ());
87485d6f
MW
135#ifdef MSDOS
136 /* We let the real user name default to "root" because that's quite
137 accurate on MSDOG and because it lets Emacs find the init file.
138 (The DVX libraries override the Djgpp libraries here.) */
35b34f72 139 Vuser_real_login_name = build_string (pw ? pw->pw_name : "root");
87485d6f 140#else
35b34f72 141 Vuser_real_login_name = build_string (pw ? pw->pw_name : "unknown");
87485d6f 142#endif
35692fe0 143
52b14ac0
JB
144 /* Get the effective user name, by consulting environment variables,
145 or the effective uid if those are unset. */
63c5d10b 146 user_name = getenv ("LOGNAME");
35692fe0 147 if (!user_name)
4691c06d 148#ifdef WINDOWSNT
63c5d10b 149 user_name = getenv ("USERNAME"); /* it's USERNAME on NT */
4691c06d 150#else /* WINDOWSNT */
63c5d10b 151 user_name = getenv ("USER");
4691c06d 152#endif /* WINDOWSNT */
52b14ac0
JB
153 if (!user_name)
154 {
63c5d10b
PE
155 pw = getpwuid (geteuid ());
156 user_name = pw ? pw->pw_name : "unknown";
52b14ac0 157 }
35b34f72 158 Vuser_login_name = build_string (user_name);
35692fe0 159
52b14ac0
JB
160 /* If the user name claimed in the environment vars differs from
161 the real uid, use the claimed name to find the full name. */
35b34f72 162 tem = Fstring_equal (Vuser_login_name, Vuser_real_login_name);
3415b0e9
RS
163 Vuser_full_name = Fuser_full_name (NILP (tem)? make_number (geteuid())
164 : Vuser_login_name);
34a7a267 165
e7f8264d 166 p = getenv ("NAME");
9d36d071
RS
167 if (p)
168 Vuser_full_name = build_string (p);
3347526c
RS
169 else if (NILP (Vuser_full_name))
170 Vuser_full_name = build_string ("unknown");
3bb9abc8
ST
171
172#ifdef HAVE_SYS_UTSNAME_H
173 {
174 struct utsname uts;
175 uname (&uts);
176 Voperating_system_release = build_string (uts.release);
177 }
178#else
179 Voperating_system_release = Qnil;
180#endif
35692fe0
JB
181}
182\f
a7ca3326 183DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
06283081
PJ
184 doc: /* Convert arg CHAR to a string containing that character.
185usage: (char-to-string CHAR) */)
5842a27b 186 (Lisp_Object character)
35692fe0 187{
fb8106e8 188 int len;
d5c2c403 189 unsigned char str[MAX_MULTIBYTE_LENGTH];
fb8106e8 190
1b9c91ed 191 CHECK_CHARACTER (character);
35692fe0 192
40fbd254 193 len = CHAR_STRING (XFASTINT (character), str);
e7f8264d 194 return make_string_from_bytes ((char *) str, 1, len);
35692fe0
JB
195}
196
c3bb441d 197DEFUN ("byte-to-string", Fbyte_to_string, Sbyte_to_string, 1, 1, 0,
35f1de62 198 doc: /* Convert arg BYTE to a unibyte string containing that byte. */)
5842a27b 199 (Lisp_Object byte)
c3bb441d 200{
64c60c2f 201 unsigned char b;
c3bb441d 202 CHECK_NUMBER (byte);
35f1de62
CY
203 if (XINT (byte) < 0 || XINT (byte) > 255)
204 error ("Invalid byte");
64c60c2f 205 b = XINT (byte);
e7f8264d 206 return make_string_from_bytes ((char *) &b, 1, 1);
c3bb441d
SM
207}
208
35692fe0 209DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
7ee72033
MB
210 doc: /* Convert arg STRING to a character, the first character of that string.
211A multibyte character is handled correctly. */)
5842a27b 212 (register Lisp_Object string)
35692fe0
JB
213{
214 register Lisp_Object val;
b7826503 215 CHECK_STRING (string);
4e491f8d 216 if (SCHARS (string))
d9d851ea
KH
217 {
218 if (STRING_MULTIBYTE (string))
62a6e103 219 XSETFASTINT (val, STRING_CHAR (SDATA (string)));
d9d851ea 220 else
4e491f8d 221 XSETFASTINT (val, SREF (string, 0));
d9d851ea 222 }
35692fe0 223 else
55561c63 224 XSETFASTINT (val, 0);
35692fe0
JB
225 return val;
226}
227\f
228static Lisp_Object
29cdc13e 229buildmark (EMACS_INT charpos, EMACS_INT bytepos)
35692fe0
JB
230{
231 register Lisp_Object mark;
232 mark = Fmake_marker ();
ec1c14f6 233 set_marker_both (mark, Qnil, charpos, bytepos);
35692fe0
JB
234 return mark;
235}
236
a7ca3326 237DEFUN ("point", Fpoint, Spoint, 0, 0, 0,
7ee72033
MB
238 doc: /* Return value of point, as an integer.
239Beginning of buffer is position (point-min). */)
5842a27b 240 (void)
35692fe0
JB
241{
242 Lisp_Object temp;
6ec8bbd2 243 XSETFASTINT (temp, PT);
35692fe0
JB
244 return temp;
245}
246
a7ca3326 247DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
7ee72033 248 doc: /* Return value of point, as a marker object. */)
5842a27b 249 (void)
35692fe0 250{
ec1c14f6 251 return buildmark (PT, PT_BYTE);
35692fe0
JB
252}
253
fe3537c3 254EMACS_INT
29cdc13e 255clip_to_bounds (EMACS_INT lower, EMACS_INT num, EMACS_INT upper)
35692fe0
JB
256{
257 if (num < lower)
258 return lower;
259 else if (num > upper)
260 return upper;
261 else
262 return num;
263}
264
a7ca3326 265DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
7ee72033 266 doc: /* Set point to POSITION, a number or marker.
8696b557
EZ
267Beginning of buffer is position (point-min), end is (point-max).
268
269The return value is POSITION. */)
5842a27b 270 (register Lisp_Object position)
35692fe0 271{
29cdc13e 272 EMACS_INT pos;
fb8106e8 273
72ef82ec
RS
274 if (MARKERP (position)
275 && current_buffer == XMARKER (position)->buffer)
ec1c14f6
RS
276 {
277 pos = marker_position (position);
278 if (pos < BEGV)
279 SET_PT_BOTH (BEGV, BEGV_BYTE);
280 else if (pos > ZV)
281 SET_PT_BOTH (ZV, ZV_BYTE);
282 else
283 SET_PT_BOTH (pos, marker_byte_position (position));
284
285 return position;
286 }
287
b7826503 288 CHECK_NUMBER_COERCE_MARKER (position);
35692fe0 289
fb8106e8 290 pos = clip_to_bounds (BEGV, XINT (position), ZV);
fb8106e8 291 SET_PT (pos);
2591ec64 292 return position;
35692fe0
JB
293}
294
acb7cc89
GM
295
296/* Return the start or end position of the region.
297 BEGINNINGP non-zero means return the start.
298 If there is no region active, signal an error. */
299
35692fe0 300static Lisp_Object
971de7fb 301region_limit (int beginningp)
35692fe0 302{
acb7cc89 303 Lisp_Object m;
177c0ea7 304
acb7cc89
GM
305 if (!NILP (Vtransient_mark_mode)
306 && NILP (Vmark_even_if_inactive)
4b4deea2 307 && NILP (BVAR (current_buffer, mark_active)))
8a0ff744 308 xsignal0 (Qmark_inactive);
177c0ea7 309
4b4deea2 310 m = Fmarker_position (BVAR (current_buffer, mark));
acb7cc89 311 if (NILP (m))
7b5ad687 312 error ("The mark is not set now, so there is no region");
177c0ea7 313
f555f8cf 314 if ((PT < XFASTINT (m)) == (beginningp != 0))
acb7cc89
GM
315 m = make_number (PT);
316 return m;
35692fe0
JB
317}
318
319DEFUN ("region-beginning", Fregion_beginning, Sregion_beginning, 0, 0, 0,
7b0815ba 320 doc: /* Return the integer value of point or mark, whichever is smaller. */)
5842a27b 321 (void)
35692fe0 322{
acb7cc89 323 return region_limit (1);
35692fe0
JB
324}
325
326DEFUN ("region-end", Fregion_end, Sregion_end, 0, 0, 0,
7b0815ba 327 doc: /* Return the integer value of point or mark, whichever is larger. */)
5842a27b 328 (void)
35692fe0 329{
acb7cc89 330 return region_limit (0);
35692fe0
JB
331}
332
35692fe0 333DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
7ee72033 334 doc: /* Return this buffer's mark, as a marker object.
a1f17501 335Watch out! Moving this marker changes the mark position.
7ee72033 336If you set the marker not to point anywhere, the buffer will have no mark. */)
5842a27b 337 (void)
35692fe0 338{
4b4deea2 339 return BVAR (current_buffer, mark);
35692fe0 340}
acb7cc89 341
c9ed721d 342\f
58401a34
SM
343/* Find all the overlays in the current buffer that touch position POS.
344 Return the number found, and store them in a vector in VEC
345 of length LEN. */
346
347static int
29cdc13e 348overlays_around (EMACS_INT pos, Lisp_Object *vec, int len)
58401a34 349{
88006f77
SM
350 Lisp_Object overlay, start, end;
351 struct Lisp_Overlay *tail;
29cdc13e 352 EMACS_INT startpos, endpos;
58401a34
SM
353 int idx = 0;
354
88006f77 355 for (tail = current_buffer->overlays_before; tail; tail = tail->next)
58401a34 356 {
88006f77 357 XSETMISC (overlay, tail);
58401a34
SM
358
359 end = OVERLAY_END (overlay);
360 endpos = OVERLAY_POSITION (end);
361 if (endpos < pos)
362 break;
363 start = OVERLAY_START (overlay);
364 startpos = OVERLAY_POSITION (start);
365 if (startpos <= pos)
366 {
367 if (idx < len)
368 vec[idx] = overlay;
369 /* Keep counting overlays even if we can't return them all. */
370 idx++;
371 }
372 }
373
88006f77 374 for (tail = current_buffer->overlays_after; tail; tail = tail->next)
58401a34 375 {
88006f77 376 XSETMISC (overlay, tail);
58401a34
SM
377
378 start = OVERLAY_START (overlay);
379 startpos = OVERLAY_POSITION (start);
380 if (pos < startpos)
381 break;
382 end = OVERLAY_END (overlay);
383 endpos = OVERLAY_POSITION (end);
384 if (pos <= endpos)
385 {
386 if (idx < len)
387 vec[idx] = overlay;
388 idx++;
389 }
390 }
391
392 return idx;
393}
394
395/* Return the value of property PROP, in OBJECT at POSITION.
396 It's the value of PROP that a char inserted at POSITION would get.
397 OBJECT is optional and defaults to the current buffer.
398 If OBJECT is a buffer, then overlay properties are considered as well as
399 text properties.
400 If OBJECT is a window, then that window's buffer is used, but
401 window-specific overlays are considered only if they are associated
402 with OBJECT. */
538f9462 403Lisp_Object
971de7fb 404get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object object)
58401a34 405{
58401a34
SM
406 CHECK_NUMBER_COERCE_MARKER (position);
407
408 if (NILP (object))
409 XSETBUFFER (object, current_buffer);
dfe6cbf8
SM
410 else if (WINDOWP (object))
411 object = XWINDOW (object)->buffer;
412
413 if (!BUFFERP (object))
414 /* pos-property only makes sense in buffers right now, since strings
415 have no overlays and no notion of insertion for which stickiness
416 could be obeyed. */
417 return Fget_text_property (position, prop, object);
418 else
58401a34 419 {
29cdc13e 420 EMACS_INT posn = XINT (position);
58401a34
SM
421 int noverlays;
422 Lisp_Object *overlay_vec, tem;
423 struct buffer *obuf = current_buffer;
424
425 set_buffer_temp (XBUFFER (object));
426
427 /* First try with room for 40 overlays. */
428 noverlays = 40;
429 overlay_vec = (Lisp_Object *) alloca (noverlays * sizeof (Lisp_Object));
430 noverlays = overlays_around (posn, overlay_vec, noverlays);
431
432 /* If there are more than 40,
433 make enough space for all, and try again. */
434 if (noverlays > 40)
435 {
436 overlay_vec = (Lisp_Object *) alloca (noverlays * sizeof (Lisp_Object));
437 noverlays = overlays_around (posn, overlay_vec, noverlays);
438 }
439 noverlays = sort_overlays (overlay_vec, noverlays, NULL);
440
441 set_buffer_temp (obuf);
442
443 /* Now check the overlays in order of decreasing priority. */
444 while (--noverlays >= 0)
445 {
446 Lisp_Object ol = overlay_vec[noverlays];
447 tem = Foverlay_get (ol, prop);
448 if (!NILP (tem))
449 {
450 /* Check the overlay is indeed active at point. */
451 Lisp_Object start = OVERLAY_START (ol), finish = OVERLAY_END (ol);
452 if ((OVERLAY_POSITION (start) == posn
453 && XMARKER (start)->insertion_type == 1)
454 || (OVERLAY_POSITION (finish) == posn
455 && XMARKER (finish)->insertion_type == 0))
456 ; /* The overlay will not cover a char inserted at point. */
457 else
458 {
459 return tem;
460 }
461 }
462 }
177c0ea7 463
7a6a86ad 464 { /* Now check the text properties. */
dfe6cbf8
SM
465 int stickiness = text_property_stickiness (prop, position, object);
466 if (stickiness > 0)
467 return Fget_text_property (position, prop, object);
468 else if (stickiness < 0
469 && XINT (position) > BUF_BEGV (XBUFFER (object)))
470 return Fget_text_property (make_number (XINT (position) - 1),
471 prop, object);
472 else
473 return Qnil;
474 }
58401a34 475 }
58401a34
SM
476}
477
a3caef99 478/* Find the field surrounding POS in *BEG and *END. If POS is nil,
59062dce 479 the value of point is used instead. If BEG or END is null,
acb7cc89 480 means don't store the beginning or end of the field.
a3caef99 481
9ac741c5
MB
482 BEG_LIMIT and END_LIMIT serve to limit the ranged of the returned
483 results; they do not effect boundary behavior.
484
a3caef99 485 If MERGE_AT_BOUNDARY is nonzero, then if POS is at the very first
ee547125
MB
486 position of a field, then the beginning of the previous field is
487 returned instead of the beginning of POS's field (since the end of a
488 field is actually also the beginning of the next input field, this
489 behavior is sometimes useful). Additionally in the MERGE_AT_BOUNDARY
490 true case, if two fields are separated by a field with the special
491 value `boundary', and POS lies within it, then the two separated
492 fields are considered to be adjacent, and POS between them, when
493 finding the beginning and ending of the "merged" field.
a3caef99
RS
494
495 Either BEG or END may be 0, in which case the corresponding value
496 is not stored. */
497
acb7cc89 498static void
413d18e7
EZ
499find_field (Lisp_Object pos, Lisp_Object merge_at_boundary,
500 Lisp_Object beg_limit,
501 EMACS_INT *beg, Lisp_Object end_limit, EMACS_INT *end)
0daf6e8d 502{
ee547125
MB
503 /* Fields right before and after the point. */
504 Lisp_Object before_field, after_field;
a3caef99
RS
505 /* 1 if POS counts as the start of a field. */
506 int at_field_start = 0;
507 /* 1 if POS counts as the end of a field. */
508 int at_field_end = 0;
ee547125 509
0daf6e8d
GM
510 if (NILP (pos))
511 XSETFASTINT (pos, PT);
512 else
b7826503 513 CHECK_NUMBER_COERCE_MARKER (pos);
0daf6e8d 514
acb7cc89 515 after_field
58401a34 516 = get_char_property_and_overlay (pos, Qfield, Qnil, NULL);
acb7cc89
GM
517 before_field
518 = (XFASTINT (pos) > BEGV
7ae1c032 519 ? get_char_property_and_overlay (make_number (XINT (pos) - 1),
58401a34 520 Qfield, Qnil, NULL)
e477bb04
KL
521 /* Using nil here would be a more obvious choice, but it would
522 fail when the buffer starts with a non-sticky field. */
523 : after_field);
ee547125
MB
524
525 /* See if we need to handle the case where MERGE_AT_BOUNDARY is nil
526 and POS is at beginning of a field, which can also be interpreted
527 as the end of the previous field. Note that the case where if
528 MERGE_AT_BOUNDARY is non-nil (see function comment) is actually the
529 more natural one; then we avoid treating the beginning of a field
530 specially. */
58401a34 531 if (NILP (merge_at_boundary))
ee547125 532 {
58401a34
SM
533 Lisp_Object field = get_pos_property (pos, Qfield, Qnil);
534 if (!EQ (field, after_field))
ee547125 535 at_field_end = 1;
58401a34
SM
536 if (!EQ (field, before_field))
537 at_field_start = 1;
2db1186a
SM
538 if (NILP (field) && at_field_start && at_field_end)
539 /* If an inserted char would have a nil field while the surrounding
540 text is non-nil, we're probably not looking at a
541 zero-length field, but instead at a non-nil field that's
542 not intended for editing (such as comint's prompts). */
543 at_field_end = at_field_start = 0;
0daf6e8d
GM
544 }
545
ee547125
MB
546 /* Note about special `boundary' fields:
547
548 Consider the case where the point (`.') is between the fields `x' and `y':
549
550 xxxx.yyyy
551
552 In this situation, if merge_at_boundary is true, we consider the
553 `x' and `y' fields as forming one big merged field, and so the end
554 of the field is the end of `y'.
555
556 However, if `x' and `y' are separated by a special `boundary' field
557 (a field with a `field' char-property of 'boundary), then we ignore
558 this special field when merging adjacent fields. Here's the same
559 situation, but with a `boundary' field between the `x' and `y' fields:
560
561 xxx.BBBByyyy
562
563 Here, if point is at the end of `x', the beginning of `y', or
564 anywhere in-between (within the `boundary' field), we merge all
565 three fields and consider the beginning as being the beginning of
566 the `x' field, and the end as being the end of the `y' field. */
567
0daf6e8d 568 if (beg)
acb7cc89
GM
569 {
570 if (at_field_start)
571 /* POS is at the edge of a field, and we should consider it as
572 the beginning of the following field. */
573 *beg = XFASTINT (pos);
574 else
575 /* Find the previous field boundary. */
576 {
58401a34 577 Lisp_Object p = pos;
acb7cc89
GM
578 if (!NILP (merge_at_boundary) && EQ (before_field, Qboundary))
579 /* Skip a `boundary' field. */
58401a34 580 p = Fprevious_single_char_property_change (p, Qfield, Qnil,
9ac741c5 581 beg_limit);
58401a34
SM
582
583 p = Fprevious_single_char_property_change (p, Qfield, Qnil,
584 beg_limit);
585 *beg = NILP (p) ? BEGV : XFASTINT (p);
acb7cc89
GM
586 }
587 }
0daf6e8d
GM
588
589 if (end)
acb7cc89
GM
590 {
591 if (at_field_end)
592 /* POS is at the edge of a field, and we should consider it as
593 the end of the previous field. */
594 *end = XFASTINT (pos);
595 else
596 /* Find the next field boundary. */
597 {
598 if (!NILP (merge_at_boundary) && EQ (after_field, Qboundary))
599 /* Skip a `boundary' field. */
9ac741c5
MB
600 pos = Fnext_single_char_property_change (pos, Qfield, Qnil,
601 end_limit);
ee547125 602
9ac741c5
MB
603 pos = Fnext_single_char_property_change (pos, Qfield, Qnil,
604 end_limit);
acb7cc89
GM
605 *end = NILP (pos) ? ZV : XFASTINT (pos);
606 }
607 }
0daf6e8d 608}
acb7cc89 609
0daf6e8d 610\f
d01f3570 611DEFUN ("delete-field", Fdelete_field, Sdelete_field, 0, 1, 0,
7ee72033 612 doc: /* Delete the field surrounding POS.
a1f17501 613A field is a region of text with the same `field' property.
f554db0f 614If POS is nil, the value of point is used for POS. */)
5842a27b 615 (Lisp_Object pos)
0daf6e8d 616{
413d18e7 617 EMACS_INT beg, end;
9ac741c5 618 find_field (pos, Qnil, Qnil, &beg, Qnil, &end);
0daf6e8d
GM
619 if (beg != end)
620 del_range (beg, end);
d01f3570 621 return Qnil;
0daf6e8d
GM
622}
623
624DEFUN ("field-string", Ffield_string, Sfield_string, 0, 1, 0,
7ee72033 625 doc: /* Return the contents of the field surrounding POS as a string.
a1f17501 626A field is a region of text with the same `field' property.
f554db0f 627If POS is nil, the value of point is used for POS. */)
5842a27b 628 (Lisp_Object pos)
0daf6e8d 629{
413d18e7 630 EMACS_INT beg, end;
9ac741c5 631 find_field (pos, Qnil, Qnil, &beg, Qnil, &end);
0daf6e8d
GM
632 return make_buffer_string (beg, end, 1);
633}
634
635DEFUN ("field-string-no-properties", Ffield_string_no_properties, Sfield_string_no_properties, 0, 1, 0,
7a6a86ad 636 doc: /* Return the contents of the field around POS, without text properties.
a1f17501 637A field is a region of text with the same `field' property.
f554db0f 638If POS is nil, the value of point is used for POS. */)
5842a27b 639 (Lisp_Object pos)
0daf6e8d 640{
413d18e7 641 EMACS_INT beg, end;
9ac741c5 642 find_field (pos, Qnil, Qnil, &beg, Qnil, &end);
0daf6e8d
GM
643 return make_buffer_string (beg, end, 0);
644}
645
9ac741c5 646DEFUN ("field-beginning", Ffield_beginning, Sfield_beginning, 0, 3, 0,
7ee72033 647 doc: /* Return the beginning of the field surrounding POS.
a1f17501
PJ
648A field is a region of text with the same `field' property.
649If POS is nil, the value of point is used for POS.
650If ESCAPE-FROM-EDGE is non-nil and POS is at the beginning of its
9ac741c5
MB
651field, then the beginning of the *previous* field is returned.
652If LIMIT is non-nil, it is a buffer position; if the beginning of the field
f554db0f 653is before LIMIT, then LIMIT will be returned instead. */)
5842a27b 654 (Lisp_Object pos, Lisp_Object escape_from_edge, Lisp_Object limit)
0daf6e8d 655{
413d18e7 656 EMACS_INT beg;
9ac741c5 657 find_field (pos, escape_from_edge, limit, &beg, Qnil, 0);
0daf6e8d
GM
658 return make_number (beg);
659}
660
a7ca3326 661DEFUN ("field-end", Ffield_end, Sfield_end, 0, 3, 0,
7ee72033 662 doc: /* Return the end of the field surrounding POS.
a1f17501
PJ
663A field is a region of text with the same `field' property.
664If POS is nil, the value of point is used for POS.
665If ESCAPE-FROM-EDGE is non-nil and POS is at the end of its field,
9ac741c5
MB
666then the end of the *following* field is returned.
667If LIMIT is non-nil, it is a buffer position; if the end of the field
f554db0f 668is after LIMIT, then LIMIT will be returned instead. */)
5842a27b 669 (Lisp_Object pos, Lisp_Object escape_from_edge, Lisp_Object limit)
0daf6e8d 670{
413d18e7 671 EMACS_INT end;
9ac741c5 672 find_field (pos, escape_from_edge, Qnil, 0, limit, &end);
0daf6e8d
GM
673 return make_number (end);
674}
675
a7ca3326 676DEFUN ("constrain-to-field", Fconstrain_to_field, Sconstrain_to_field, 2, 5, 0,
7ee72033 677 doc: /* Return the position closest to NEW-POS that is in the same field as OLD-POS.
a1f17501
PJ
678
679A field is a region of text with the same `field' property.
680If NEW-POS is nil, then the current point is used instead, and set to the
681constrained position if that is different.
682
683If OLD-POS is at the boundary of two fields, then the allowable
684positions for NEW-POS depends on the value of the optional argument
685ESCAPE-FROM-EDGE: If ESCAPE-FROM-EDGE is nil, then NEW-POS is
686constrained to the field that has the same `field' char-property
687as any new characters inserted at OLD-POS, whereas if ESCAPE-FROM-EDGE
688is non-nil, NEW-POS is constrained to the union of the two adjacent
689fields. Additionally, if two fields are separated by another field with
690the special value `boundary', then any point within this special field is
691also considered to be `on the boundary'.
692
693If the optional argument ONLY-IN-LINE is non-nil and constraining
694NEW-POS would move it to a different line, NEW-POS is returned
695unconstrained. This useful for commands that move by line, like
696\\[next-line] or \\[beginning-of-line], which should generally respect field boundaries
697only in the case where they can still move to the right line.
698
699If the optional argument INHIBIT-CAPTURE-PROPERTY is non-nil, and OLD-POS has
700a non-nil property of that name, then any field boundaries are ignored.
701
7ee72033 702Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */)
5842a27b 703 (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge, Lisp_Object only_in_line, Lisp_Object inhibit_capture_property)
0daf6e8d
GM
704{
705 /* If non-zero, then the original point, before re-positioning. */
29cdc13e 706 EMACS_INT orig_point = 0;
d63b4018
KR
707 int fwd;
708 Lisp_Object prev_old, prev_new;
aac18aa4 709
0daf6e8d
GM
710 if (NILP (new_pos))
711 /* Use the current point, and afterwards, set it. */
712 {
713 orig_point = PT;
714 XSETFASTINT (new_pos, PT);
715 }
716
e477bb04
KL
717 CHECK_NUMBER_COERCE_MARKER (new_pos);
718 CHECK_NUMBER_COERCE_MARKER (old_pos);
719
720 fwd = (XFASTINT (new_pos) > XFASTINT (old_pos));
721
722 prev_old = make_number (XFASTINT (old_pos) - 1);
723 prev_new = make_number (XFASTINT (new_pos) - 1);
aac18aa4 724
ee5cd4db
GM
725 if (NILP (Vinhibit_field_text_motion)
726 && !EQ (new_pos, old_pos)
42ab8e36
MB
727 && (!NILP (Fget_char_property (new_pos, Qfield, Qnil))
728 || !NILP (Fget_char_property (old_pos, Qfield, Qnil))
e477bb04
KL
729 /* To recognize field boundaries, we must also look at the
730 previous positions; we could use `get_pos_property'
731 instead, but in itself that would fail inside non-sticky
732 fields (like comint prompts). */
733 || (XFASTINT (new_pos) > BEGV
42ab8e36 734 && !NILP (Fget_char_property (prev_new, Qfield, Qnil)))
e477bb04 735 || (XFASTINT (old_pos) > BEGV
42ab8e36 736 && !NILP (Fget_char_property (prev_old, Qfield, Qnil))))
ee547125 737 && (NILP (inhibit_capture_property)
e477bb04
KL
738 /* Field boundaries are again a problem; but now we must
739 decide the case exactly, so we need to call
740 `get_pos_property' as well. */
741 || (NILP (get_pos_property (old_pos, inhibit_capture_property, Qnil))
742 && (XFASTINT (old_pos) <= BEGV
42ab8e36
MB
743 || NILP (Fget_char_property (old_pos, inhibit_capture_property, Qnil))
744 || NILP (Fget_char_property (prev_old, inhibit_capture_property, Qnil))))))
2cb3aec4
KL
745 /* It is possible that NEW_POS is not within the same field as
746 OLD_POS; try to move NEW_POS so that it is. */
0daf6e8d 747 {
a53e2e89 748 EMACS_INT shortage;
0daf6e8d
GM
749 Lisp_Object field_bound;
750
0daf6e8d 751 if (fwd)
9ac741c5 752 field_bound = Ffield_end (old_pos, escape_from_edge, new_pos);
0daf6e8d 753 else
9ac741c5 754 field_bound = Ffield_beginning (old_pos, escape_from_edge, new_pos);
0daf6e8d 755
10b0f752
MB
756 if (/* See if ESCAPE_FROM_EDGE caused FIELD_BOUND to jump to the
757 other side of NEW_POS, which would mean that NEW_POS is
758 already acceptable, and it's not necessary to constrain it
759 to FIELD_BOUND. */
760 ((XFASTINT (field_bound) < XFASTINT (new_pos)) ? fwd : !fwd)
761 /* NEW_POS should be constrained, but only if either
762 ONLY_IN_LINE is nil (in which case any constraint is OK),
763 or NEW_POS and FIELD_BOUND are on the same line (in which
764 case the constraint is OK even if ONLY_IN_LINE is non-nil). */
765 && (NILP (only_in_line)
766 /* This is the ONLY_IN_LINE case, check that NEW_POS and
767 FIELD_BOUND are on the same line by seeing whether
768 there's an intervening newline or not. */
769 || (scan_buffer ('\n',
770 XFASTINT (new_pos), XFASTINT (field_bound),
771 fwd ? -1 : 1, &shortage, 1),
772 shortage != 0)))
0daf6e8d
GM
773 /* Constrain NEW_POS to FIELD_BOUND. */
774 new_pos = field_bound;
775
776 if (orig_point && XFASTINT (new_pos) != orig_point)
777 /* The NEW_POS argument was originally nil, so automatically set PT. */
778 SET_PT (XFASTINT (new_pos));
779 }
780
781 return new_pos;
782}
acb7cc89 783
0daf6e8d 784\f
a7ca3326 785DEFUN ("line-beginning-position",
6d57c318 786 Fline_beginning_position, Sline_beginning_position, 0, 1, 0,
7ee72033 787 doc: /* Return the character position of the first character on the current line.
a1f17501
PJ
788With argument N not nil or 1, move forward N - 1 lines first.
789If scan reaches end of buffer, return that position.
6d57c318 790
cd21226d
EZ
791The returned position is of the first character in the logical order,
792i.e. the one that has the smallest character position.
793
2cb3aec4
KL
794This function constrains the returned position to the current field
795unless that would be on a different line than the original,
796unconstrained result. If N is nil or 1, and a front-sticky field
797starts at point, the scan stops as soon as it starts. To ignore field
6d57c318 798boundaries bind `inhibit-field-text-motion' to t.
a1f17501 799
7ee72033 800This function does not move point. */)
5842a27b 801 (Lisp_Object n)
c9ed721d 802{
29cdc13e 803 EMACS_INT orig, orig_byte, end;
4e8f005c
CY
804 int count = SPECPDL_INDEX ();
805 specbind (Qinhibit_point_motion_hooks, Qt);
c9ed721d
RS
806
807 if (NILP (n))
808 XSETFASTINT (n, 1);
809 else
b7826503 810 CHECK_NUMBER (n);
c9ed721d
RS
811
812 orig = PT;
ec1c14f6 813 orig_byte = PT_BYTE;
c9ed721d
RS
814 Fforward_line (make_number (XINT (n) - 1));
815 end = PT;
e2dae3f2 816
ec1c14f6 817 SET_PT_BOTH (orig, orig_byte);
35692fe0 818
4e8f005c
CY
819 unbind_to (count, Qnil);
820
0daf6e8d 821 /* Return END constrained to the current input field. */
ee5cd4db
GM
822 return Fconstrain_to_field (make_number (end), make_number (orig),
823 XINT (n) != 1 ? Qt : Qnil,
ee547125 824 Qt, Qnil);
c9ed721d
RS
825}
826
a7ca3326 827DEFUN ("line-end-position", Fline_end_position, Sline_end_position, 0, 1, 0,
7ee72033 828 doc: /* Return the character position of the last character on the current line.
a1f17501
PJ
829With argument N not nil or 1, move forward N - 1 lines first.
830If scan reaches end of buffer, return that position.
6d57c318 831
cd21226d
EZ
832The returned position is of the last character in the logical order,
833i.e. the character whose buffer position is the largest one.
834
2cb3aec4
KL
835This function constrains the returned position to the current field
836unless that would be on a different line than the original,
837unconstrained result. If N is nil or 1, and a rear-sticky field ends
838at point, the scan stops as soon as it starts. To ignore field
6d57c318
MB
839boundaries bind `inhibit-field-text-motion' to t.
840
7ee72033 841This function does not move point. */)
5842a27b 842 (Lisp_Object n)
c9ed721d 843{
29cdc13e
EZ
844 EMACS_INT end_pos;
845 EMACS_INT orig = PT;
0daf6e8d 846
c9ed721d
RS
847 if (NILP (n))
848 XSETFASTINT (n, 1);
849 else
b7826503 850 CHECK_NUMBER (n);
c9ed721d 851
0daf6e8d
GM
852 end_pos = find_before_next_newline (orig, 0, XINT (n) - (XINT (n) <= 0));
853
854 /* Return END_POS constrained to the current input field. */
ee5cd4db 855 return Fconstrain_to_field (make_number (end_pos), make_number (orig),
ee547125 856 Qnil, Qt, Qnil);
c9ed721d 857}
6d57c318 858
c9ed721d 859\f
35692fe0 860Lisp_Object
971de7fb 861save_excursion_save (void)
35692fe0 862{
acb7cc89
GM
863 int visible = (XBUFFER (XWINDOW (selected_window)->buffer)
864 == current_buffer);
35692fe0
JB
865
866 return Fcons (Fpoint_marker (),
4b4deea2 867 Fcons (Fcopy_marker (BVAR (current_buffer, mark), Qnil),
9772455e 868 Fcons (visible ? Qt : Qnil,
4b4deea2 869 Fcons (BVAR (current_buffer, mark_active),
2483cf58 870 selected_window))));
35692fe0
JB
871}
872
873Lisp_Object
971de7fb 874save_excursion_restore (Lisp_Object info)
35692fe0 875{
4ad8681a
RS
876 Lisp_Object tem, tem1, omark, nmark;
877 struct gcpro gcpro1, gcpro2, gcpro3;
2483cf58 878 int visible_p;
35692fe0 879
2483cf58 880 tem = Fmarker_buffer (XCAR (info));
35692fe0
JB
881 /* If buffer being returned to is now deleted, avoid error */
882 /* Otherwise could get error here while unwinding to top level
883 and crash */
884 /* In that case, Fmarker_buffer returns nil now. */
56a98455 885 if (NILP (tem))
35692fe0 886 return Qnil;
4ad8681a
RS
887
888 omark = nmark = Qnil;
889 GCPRO3 (info, omark, nmark);
890
35692fe0 891 Fset_buffer (tem);
2483cf58
GM
892
893 /* Point marker. */
894 tem = XCAR (info);
35692fe0 895 Fgoto_char (tem);
12038f9f 896 unchain_marker (XMARKER (tem));
2483cf58
GM
897
898 /* Mark marker. */
899 info = XCDR (info);
900 tem = XCAR (info);
4b4deea2
TT
901 omark = Fmarker_position (BVAR (current_buffer, mark));
902 Fset_marker (BVAR (current_buffer, mark), tem, Fcurrent_buffer ());
03d18690 903 nmark = Fmarker_position (tem);
12038f9f 904 unchain_marker (XMARKER (tem));
2483cf58
GM
905
906 /* visible */
907 info = XCDR (info);
908 visible_p = !NILP (XCAR (info));
177c0ea7 909
ef580991
RS
910#if 0 /* We used to make the current buffer visible in the selected window
911 if that was true previously. That avoids some anomalies.
912 But it creates others, and it wasn't documented, and it is simpler
913 and cleaner never to alter the window/buffer connections. */
9772455e
RS
914 tem1 = Fcar (tem);
915 if (!NILP (tem1)
0e2c9c70 916 && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
35692fe0 917 Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
ef580991 918#endif /* 0 */
9772455e 919
2483cf58
GM
920 /* Mark active */
921 info = XCDR (info);
922 tem = XCAR (info);
4b4deea2
TT
923 tem1 = BVAR (current_buffer, mark_active);
924 BVAR (current_buffer, mark_active) = tem;
2483cf58 925
dee091a3
JD
926 /* If mark is active now, and either was not active
927 or was at a different place, run the activate hook. */
928 if (! NILP (tem))
9fed2b18 929 {
dee091a3
JD
930 if (! EQ (omark, nmark))
931 {
932 tem = intern ("activate-mark-hook");
933 Frun_hooks (1, &tem);
934 }
935 }
936 /* If mark has ceased to be active, run deactivate hook. */
937 else if (! NILP (tem1))
938 {
939 tem = intern ("deactivate-mark-hook");
940 Frun_hooks (1, &tem);
9fed2b18 941 }
2483cf58
GM
942
943 /* If buffer was visible in a window, and a different window was
793cd2c8
GM
944 selected, and the old selected window is still showing this
945 buffer, restore point in that window. */
2483cf58
GM
946 tem = XCDR (info);
947 if (visible_p
948 && !EQ (tem, selected_window)
ba973f7a
GM
949 && (tem1 = XWINDOW (tem)->buffer,
950 (/* Window is live... */
951 BUFFERP (tem1)
952 /* ...and it shows the current buffer. */
953 && XBUFFER (tem1) == current_buffer)))
2483cf58
GM
954 Fset_window_point (tem, make_number (PT));
955
4ad8681a 956 UNGCPRO;
35692fe0
JB
957 return Qnil;
958}
959
960DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
7ee72033 961 doc: /* Save point, mark, and current buffer; execute BODY; restore those things.
a1f17501
PJ
962Executes BODY just like `progn'.
963The values of point, mark and the current buffer are restored
964even in case of abnormal exit (throw or error).
965The state of activation of the mark is also restored.
966
967This construct does not save `deactivate-mark', and therefore
968functions that change the buffer will still cause deactivation
969of the mark at the end of the command. To prevent that, bind
33c2d29f
MB
970`deactivate-mark' with `let'.
971
7450fd36
SM
972If you only want to save the current buffer but not point nor mark,
973then just use `save-current-buffer', or even `with-current-buffer'.
974
33c2d29f 975usage: (save-excursion &rest BODY) */)
5842a27b 976 (Lisp_Object args)
35692fe0
JB
977{
978 register Lisp_Object val;
aed13378 979 int count = SPECPDL_INDEX ();
35692fe0
JB
980
981 record_unwind_protect (save_excursion_restore, save_excursion_save ());
4bc8c7d2
RS
982
983 val = Fprogn (args);
984 return unbind_to (count, val);
985}
986
987DEFUN ("save-current-buffer", Fsave_current_buffer, Ssave_current_buffer, 0, UNEVALLED, 0,
7ee72033 988 doc: /* Save the current buffer; execute BODY; restore the current buffer.
33c2d29f
MB
989Executes BODY just like `progn'.
990usage: (save-current-buffer &rest BODY) */)
5842a27b 991 (Lisp_Object args)
4bc8c7d2 992{
acb7cc89 993 Lisp_Object val;
aed13378 994 int count = SPECPDL_INDEX ();
4bc8c7d2 995
cb5e5f74 996 record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
4bc8c7d2 997
35692fe0
JB
998 val = Fprogn (args);
999 return unbind_to (count, val);
1000}
1001\f
95dccf75 1002DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 1, 0,
7ee72033
MB
1003 doc: /* Return the number of characters in the current buffer.
1004If BUFFER, return the number of characters in that buffer instead. */)
5842a27b 1005 (Lisp_Object buffer)
35692fe0 1006{
95dccf75
RS
1007 if (NILP (buffer))
1008 return make_number (Z - BEG);
02050596
RS
1009 else
1010 {
b7826503 1011 CHECK_BUFFER (buffer);
02050596
RS
1012 return make_number (BUF_Z (XBUFFER (buffer))
1013 - BUF_BEG (XBUFFER (buffer)));
1014 }
35692fe0
JB
1015}
1016
1017DEFUN ("point-min", Fpoint_min, Spoint_min, 0, 0, 0,
7ee72033
MB
1018 doc: /* Return the minimum permissible value of point in the current buffer.
1019This is 1, unless narrowing (a buffer restriction) is in effect. */)
5842a27b 1020 (void)
35692fe0
JB
1021{
1022 Lisp_Object temp;
55561c63 1023 XSETFASTINT (temp, BEGV);
35692fe0
JB
1024 return temp;
1025}
1026
1027DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 0, 0,
7ee72033
MB
1028 doc: /* Return a marker to the minimum permissible value of point in this buffer.
1029This is the beginning, unless narrowing (a buffer restriction) is in effect. */)
5842a27b 1030 (void)
35692fe0 1031{
ec1c14f6 1032 return buildmark (BEGV, BEGV_BYTE);
35692fe0
JB
1033}
1034
1035DEFUN ("point-max", Fpoint_max, Spoint_max, 0, 0, 0,
7ee72033 1036 doc: /* Return the maximum permissible value of point in the current buffer.
a1f17501 1037This is (1+ (buffer-size)), unless narrowing (a buffer restriction)
7ee72033 1038is in effect, in which case it is less. */)
5842a27b 1039 (void)
35692fe0
JB
1040{
1041 Lisp_Object temp;
55561c63 1042 XSETFASTINT (temp, ZV);
35692fe0
JB
1043 return temp;
1044}
1045
a7ca3326 1046DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 0, 0,
7ee72033 1047 doc: /* Return a marker to the maximum permissible value of point in this buffer.
a1f17501 1048This is (1+ (buffer-size)), unless narrowing (a buffer restriction)
7ee72033 1049is in effect, in which case it is less. */)
5842a27b 1050 (void)
35692fe0 1051{
ec1c14f6 1052 return buildmark (ZV, ZV_BYTE);
35692fe0
JB
1053}
1054
c86212b9 1055DEFUN ("gap-position", Fgap_position, Sgap_position, 0, 0, 0,
7ee72033
MB
1056 doc: /* Return the position of the gap, in the current buffer.
1057See also `gap-size'. */)
5842a27b 1058 (void)
c86212b9
RS
1059{
1060 Lisp_Object temp;
1061 XSETFASTINT (temp, GPT);
1062 return temp;
1063}
1064
1065DEFUN ("gap-size", Fgap_size, Sgap_size, 0, 0, 0,
7ee72033
MB
1066 doc: /* Return the size of the current buffer's gap.
1067See also `gap-position'. */)
5842a27b 1068 (void)
c86212b9
RS
1069{
1070 Lisp_Object temp;
1071 XSETFASTINT (temp, GAP_SIZE);
1072 return temp;
1073}
1074
7df74da6 1075DEFUN ("position-bytes", Fposition_bytes, Sposition_bytes, 1, 1, 0,
7ee72033
MB
1076 doc: /* Return the byte position for character position POSITION.
1077If POSITION is out of range, the value is nil. */)
5842a27b 1078 (Lisp_Object position)
7df74da6 1079{
b7826503 1080 CHECK_NUMBER_COERCE_MARKER (position);
fcf9683e
KH
1081 if (XINT (position) < BEG || XINT (position) > Z)
1082 return Qnil;
fa8a5a15 1083 return make_number (CHAR_TO_BYTE (XINT (position)));
7df74da6 1084}
3ab0732d
RS
1085
1086DEFUN ("byte-to-position", Fbyte_to_position, Sbyte_to_position, 1, 1, 0,
7ee72033
MB
1087 doc: /* Return the character position for byte position BYTEPOS.
1088If BYTEPOS is out of range, the value is nil. */)
5842a27b 1089 (Lisp_Object bytepos)
3ab0732d 1090{
b7826503 1091 CHECK_NUMBER (bytepos);
fcf9683e
KH
1092 if (XINT (bytepos) < BEG_BYTE || XINT (bytepos) > Z_BYTE)
1093 return Qnil;
3ab0732d
RS
1094 return make_number (BYTE_TO_CHAR (XINT (bytepos)));
1095}
7df74da6 1096\f
a7ca3326 1097DEFUN ("following-char", Ffollowing_char, Sfollowing_char, 0, 0, 0,
7ee72033
MB
1098 doc: /* Return the character following point, as a number.
1099At the end of the buffer or accessible region, return 0. */)
5842a27b 1100 (void)
35692fe0
JB
1101{
1102 Lisp_Object temp;
6ec8bbd2 1103 if (PT >= ZV)
55561c63 1104 XSETFASTINT (temp, 0);
850a8179 1105 else
ec1c14f6 1106 XSETFASTINT (temp, FETCH_CHAR (PT_BYTE));
35692fe0
JB
1107 return temp;
1108}
1109
a7ca3326 1110DEFUN ("preceding-char", Fprevious_char, Sprevious_char, 0, 0, 0,
7ee72033
MB
1111 doc: /* Return the character preceding point, as a number.
1112At the beginning of the buffer or accessible region, return 0. */)
5842a27b 1113 (void)
35692fe0
JB
1114{
1115 Lisp_Object temp;
6ec8bbd2 1116 if (PT <= BEGV)
55561c63 1117 XSETFASTINT (temp, 0);
4b4deea2 1118 else if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
fb8106e8 1119 {
29cdc13e 1120 EMACS_INT pos = PT_BYTE;
fb8106e8
KH
1121 DEC_POS (pos);
1122 XSETFASTINT (temp, FETCH_CHAR (pos));
1123 }
35692fe0 1124 else
ec1c14f6 1125 XSETFASTINT (temp, FETCH_BYTE (PT_BYTE - 1));
35692fe0
JB
1126 return temp;
1127}
1128
a7ca3326 1129DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0,
7ee72033
MB
1130 doc: /* Return t if point is at the beginning of the buffer.
1131If the buffer is narrowed, this means the beginning of the narrowed part. */)
5842a27b 1132 (void)
35692fe0 1133{
6ec8bbd2 1134 if (PT == BEGV)
35692fe0
JB
1135 return Qt;
1136 return Qnil;
1137}
1138
a7ca3326 1139DEFUN ("eobp", Feobp, Seobp, 0, 0, 0,
7ee72033
MB
1140 doc: /* Return t if point is at the end of the buffer.
1141If the buffer is narrowed, this means the end of the narrowed part. */)
5842a27b 1142 (void)
35692fe0 1143{
6ec8bbd2 1144 if (PT == ZV)
35692fe0
JB
1145 return Qt;
1146 return Qnil;
1147}
1148
a7ca3326 1149DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0,
7ee72033 1150 doc: /* Return t if point is at the beginning of a line. */)
5842a27b 1151 (void)
35692fe0 1152{
ec1c14f6 1153 if (PT == BEGV || FETCH_BYTE (PT_BYTE - 1) == '\n')
35692fe0
JB
1154 return Qt;
1155 return Qnil;
1156}
1157
a7ca3326 1158DEFUN ("eolp", Feolp, Seolp, 0, 0, 0,
7ee72033
MB
1159 doc: /* Return t if point is at the end of a line.
1160`End of a line' includes point being at the end of the buffer. */)
5842a27b 1161 (void)
35692fe0 1162{
ec1c14f6 1163 if (PT == ZV || FETCH_BYTE (PT_BYTE) == '\n')
35692fe0
JB
1164 return Qt;
1165 return Qnil;
1166}
1167
a7ca3326 1168DEFUN ("char-after", Fchar_after, Schar_after, 0, 1, 0,
7ee72033 1169 doc: /* Return character in current buffer at position POS.
f555f8cf 1170POS is an integer or a marker and defaults to point.
7ee72033 1171If POS is out of range, the value is nil. */)
5842a27b 1172 (Lisp_Object pos)
35692fe0 1173{
29cdc13e 1174 register EMACS_INT pos_byte;
35692fe0 1175
fa1d3816 1176 if (NILP (pos))
39a4c932
RS
1177 {
1178 pos_byte = PT_BYTE;
3c52e568 1179 XSETFASTINT (pos, PT);
39a4c932
RS
1180 }
1181
1182 if (MARKERP (pos))
85cac557
RS
1183 {
1184 pos_byte = marker_byte_position (pos);
1185 if (pos_byte < BEGV_BYTE || pos_byte >= ZV_BYTE)
1186 return Qnil;
1187 }
fa1d3816
RS
1188 else
1189 {
b7826503 1190 CHECK_NUMBER_COERCE_MARKER (pos);
b98ef0dc 1191 if (XINT (pos) < BEGV || XINT (pos) >= ZV)
85cac557 1192 return Qnil;
34a7a267 1193
ec1c14f6 1194 pos_byte = CHAR_TO_BYTE (XINT (pos));
fa1d3816 1195 }
35692fe0 1196
ec1c14f6 1197 return make_number (FETCH_CHAR (pos_byte));
35692fe0 1198}
fb8106e8 1199
fa1d3816 1200DEFUN ("char-before", Fchar_before, Schar_before, 0, 1, 0,
7ee72033 1201 doc: /* Return character in current buffer preceding position POS.
f555f8cf 1202POS is an integer or a marker and defaults to point.
7ee72033 1203If POS is out of range, the value is nil. */)
5842a27b 1204 (Lisp_Object pos)
fb8106e8
KH
1205{
1206 register Lisp_Object val;
29cdc13e 1207 register EMACS_INT pos_byte;
fb8106e8 1208
fa1d3816 1209 if (NILP (pos))
39a4c932
RS
1210 {
1211 pos_byte = PT_BYTE;
3c52e568 1212 XSETFASTINT (pos, PT);
39a4c932
RS
1213 }
1214
1215 if (MARKERP (pos))
85cac557
RS
1216 {
1217 pos_byte = marker_byte_position (pos);
1218
1219 if (pos_byte <= BEGV_BYTE || pos_byte > ZV_BYTE)
1220 return Qnil;
1221 }
fa1d3816
RS
1222 else
1223 {
b7826503 1224 CHECK_NUMBER_COERCE_MARKER (pos);
fb8106e8 1225
b98ef0dc 1226 if (XINT (pos) <= BEGV || XINT (pos) > ZV)
85cac557
RS
1227 return Qnil;
1228
ec1c14f6 1229 pos_byte = CHAR_TO_BYTE (XINT (pos));
fa1d3816 1230 }
fb8106e8 1231
4b4deea2 1232 if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
fb8106e8 1233 {
ec1c14f6
RS
1234 DEC_POS (pos_byte);
1235 XSETFASTINT (val, FETCH_CHAR (pos_byte));
fb8106e8
KH
1236 }
1237 else
1238 {
ec1c14f6
RS
1239 pos_byte--;
1240 XSETFASTINT (val, FETCH_BYTE (pos_byte));
fb8106e8
KH
1241 }
1242 return val;
1243}
35692fe0 1244\f
a7ca3326 1245DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 1, 0,
7ee72033 1246 doc: /* Return the name under which the user logged in, as a string.
a1f17501 1247This is based on the effective uid, not the real uid.
412f1fab 1248Also, if the environment variables LOGNAME or USER are set,
a1f17501
PJ
1249that determines the value of this function.
1250
7b1c38a4
EZ
1251If optional argument UID is an integer or a float, return the login name
1252of the user with that uid, or nil if there is no such user. */)
5842a27b 1253 (Lisp_Object uid)
35692fe0 1254{
87485d6f 1255 struct passwd *pw;
7b1c38a4 1256 uid_t id;
87485d6f 1257
f8a0e364
RS
1258 /* Set up the user name info if we didn't do it before.
1259 (That can happen if Emacs is dumpable
1260 but you decide to run `temacs -l loadup' and not dump. */
35b34f72 1261 if (INTEGERP (Vuser_login_name))
f8a0e364 1262 init_editfns ();
87485d6f
MW
1263
1264 if (NILP (uid))
35b34f72 1265 return Vuser_login_name;
87485d6f 1266
63c5d10b 1267 id = XFLOATINT (uid);
b91834c3 1268 BLOCK_INPUT;
63c5d10b 1269 pw = getpwuid (id);
b91834c3 1270 UNBLOCK_INPUT;
87485d6f 1271 return (pw ? build_string (pw->pw_name) : Qnil);
35692fe0
JB
1272}
1273
1274DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
deb8e082 1275 0, 0, 0,
7ee72033 1276 doc: /* Return the name of the user's real uid, as a string.
a1f17501 1277This ignores the environment variables LOGNAME and USER, so it differs from
7ee72033 1278`user-login-name' when running under `su'. */)
5842a27b 1279 (void)
35692fe0 1280{
f8a0e364
RS
1281 /* Set up the user name info if we didn't do it before.
1282 (That can happen if Emacs is dumpable
1283 but you decide to run `temacs -l loadup' and not dump. */
35b34f72 1284 if (INTEGERP (Vuser_login_name))
f8a0e364 1285 init_editfns ();
35b34f72 1286 return Vuser_real_login_name;
35692fe0
JB
1287}
1288
1289DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
7ee72033 1290 doc: /* Return the effective uid of Emacs.
e00553bf 1291Value is an integer or a float, depending on the value. */)
5842a27b 1292 (void)
35692fe0 1293{
3aef3c0a
EZ
1294 /* Assignment to EMACS_INT stops GCC whining about limited range of
1295 data type. */
1296 EMACS_INT euid = geteuid ();
e00553bf
EZ
1297
1298 /* Make sure we don't produce a negative UID due to signed integer
1299 overflow. */
1300 if (euid < 0)
63c5d10b 1301 return make_float (geteuid ());
3aef3c0a 1302 return make_fixnum_or_float (euid);
35692fe0
JB
1303}
1304
1305DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
7ee72033 1306 doc: /* Return the real uid of Emacs.
e00553bf 1307Value is an integer or a float, depending on the value. */)
5842a27b 1308 (void)
35692fe0 1309{
3aef3c0a
EZ
1310 /* Assignment to EMACS_INT stops GCC whining about limited range of
1311 data type. */
1312 EMACS_INT uid = getuid ();
e00553bf
EZ
1313
1314 /* Make sure we don't produce a negative UID due to signed integer
1315 overflow. */
1316 if (uid < 0)
63c5d10b 1317 return make_float (getuid ());
3aef3c0a 1318 return make_fixnum_or_float (uid);
35692fe0
JB
1319}
1320
c9ed721d 1321DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 1, 0,
7ee72033 1322 doc: /* Return the full name of the user logged in, as a string.
a1f17501
PJ
1323If the full name corresponding to Emacs's userid is not known,
1324return "unknown".
1325
1326If optional argument UID is an integer or float, return the full name
1327of the user with that uid, or nil if there is no such user.
1328If UID is a string, return the full name of the user with that login
7ee72033 1329name, or nil if there is no such user. */)
5842a27b 1330 (Lisp_Object uid)
35692fe0 1331{
c9ed721d 1332 struct passwd *pw;
e7f8264d 1333 register char *p, *q;
3415b0e9 1334 Lisp_Object full;
c9ed721d
RS
1335
1336 if (NILP (uid))
34a7a267 1337 return Vuser_full_name;
3415b0e9 1338 else if (NUMBERP (uid))
b91834c3 1339 {
63c5d10b 1340 uid_t u = XFLOATINT (uid);
b91834c3 1341 BLOCK_INPUT;
63c5d10b 1342 pw = getpwuid (u);
b91834c3
YM
1343 UNBLOCK_INPUT;
1344 }
34a7a267 1345 else if (STRINGP (uid))
b91834c3
YM
1346 {
1347 BLOCK_INPUT;
63c5d10b 1348 pw = getpwnam (SSDATA (uid));
b91834c3
YM
1349 UNBLOCK_INPUT;
1350 }
3415b0e9
RS
1351 else
1352 error ("Invalid UID specification");
c9ed721d 1353
3415b0e9 1354 if (!pw)
3347526c 1355 return Qnil;
34a7a267 1356
e7f8264d 1357 p = USER_FULL_NAME;
3415b0e9 1358 /* Chop off everything after the first comma. */
e7f8264d 1359 q = strchr (p, ',');
3415b0e9 1360 full = make_string (p, q ? q - p : strlen (p));
34a7a267 1361
3415b0e9 1362#ifdef AMPERSAND_FULL_NAME
e7f8264d
PE
1363 p = SSDATA (full);
1364 q = strchr (p, '&');
3415b0e9
RS
1365 /* Substitute the login name for the &, upcasing the first character. */
1366 if (q)
1367 {
e7f8264d 1368 register char *r;
3415b0e9
RS
1369 Lisp_Object login;
1370
1371 login = Fuser_login_name (make_number (pw->pw_uid));
e7f8264d 1372 r = (char *) alloca (strlen (p) + SCHARS (login) + 1);
72af86bd 1373 memcpy (r, p, q - p);
3415b0e9 1374 r[q - p] = 0;
42a5b22f 1375 strcat (r, SSDATA (login));
5da9919f 1376 r[q - p] = upcase ((unsigned char) r[q - p]);
3415b0e9
RS
1377 strcat (r, q + 1);
1378 full = build_string (r);
1379 }
1380#endif /* AMPERSAND_FULL_NAME */
1381
1382 return full;
35692fe0
JB
1383}
1384
a7ca3326 1385DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
1a7e0117 1386 doc: /* Return the host name of the machine you are running on, as a string. */)
5842a27b 1387 (void)
35692fe0
JB
1388{
1389 return Vsystem_name;
1390}
1391
8ea90aa3 1392const char *
971de7fb 1393get_system_name (void)
ac988277 1394{
3d976a9a 1395 if (STRINGP (Vsystem_name))
51b59d79 1396 return SSDATA (Vsystem_name);
3d976a9a
RS
1397 else
1398 return "";
ac988277
KH
1399}
1400
7fd233b3 1401DEFUN ("emacs-pid", Femacs_pid, Semacs_pid, 0, 0, 0,
7ee72033 1402 doc: /* Return the process ID of Emacs, as an integer. */)
5842a27b 1403 (void)
7fd233b3
RS
1404{
1405 return make_number (getpid ());
1406}
1407
b8d9bd41
PE
1408\f
1409
1410#ifndef TIME_T_MIN
1411# define TIME_T_MIN TYPE_MINIMUM (time_t)
1412#endif
1413#ifndef TIME_T_MAX
1414# define TIME_T_MAX TYPE_MAXIMUM (time_t)
1415#endif
1416
1417/* Report that a time value is out of range for Emacs. */
1418static void
1419time_overflow (void)
1420{
1421 error ("Specified time is not representable");
1422}
1423
1424/* Return the upper part of the time T (everything but the bottom 16 bits),
1425 making sure that it is representable. */
1426static EMACS_INT
1427hi_time (time_t t)
1428{
1429 time_t hi = t >> 16;
313c1e54
PE
1430
1431 /* Check for overflow, helping the compiler for common cases where
1432 no runtime check is needed, and taking care not to convert
1433 negative numbers to unsigned before comparing them. */
1434 if (! ((! TYPE_SIGNED (time_t)
1435 || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> 16
1436 || MOST_NEGATIVE_FIXNUM <= hi)
1437 && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM
1438 || hi <= MOST_POSITIVE_FIXNUM)))
b8d9bd41 1439 time_overflow ();
313c1e54 1440
b8d9bd41
PE
1441 return hi;
1442}
1443
1444/* Return the bottom 16 bits of the time T. */
1445static EMACS_INT
1446lo_time (time_t t)
1447{
1448 return t & ((1 << 16) - 1);
1449}
1450
a7ca3326 1451DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
7ee72033 1452 doc: /* Return the current time, as the number of seconds since 1970-01-01 00:00:00.
a1f17501
PJ
1453The time is returned as a list of three integers. The first has the
1454most significant 16 bits of the seconds, while the second has the
1455least significant 16 bits. The third integer gives the microsecond
1456count.
1457
1458The microsecond count is zero on systems that do not provide
7ee72033 1459resolution finer than a second. */)
5842a27b 1460 (void)
d940e0e4 1461{
956ace37 1462 EMACS_TIME t;
956ace37
JB
1463
1464 EMACS_GET_TIME (t);
b8d9bd41
PE
1465 return list3 (make_number (hi_time (EMACS_SECS (t))),
1466 make_number (lo_time (EMACS_SECS (t))),
799734b0 1467 make_number (EMACS_USECS (t)));
d940e0e4 1468}
4211ee7d 1469
a7ca3326 1470DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
4211ee7d
EZ
1471 0, 0, 0,
1472 doc: /* Return the current run time used by Emacs.
1473The time is returned as a list of three integers. The first has the
1474most significant 16 bits of the seconds, while the second has the
1475least significant 16 bits. The third integer gives the microsecond
1476count.
1477
9671c13a
JB
1478On systems that can't determine the run time, `get-internal-run-time'
1479does the same thing as `current-time'. The microsecond count is zero
1480on systems that do not provide resolution finer than a second. */)
5842a27b 1481 (void)
4211ee7d
EZ
1482{
1483#ifdef HAVE_GETRUSAGE
1484 struct rusage usage;
b8d9bd41
PE
1485 time_t secs;
1486 int usecs;
4211ee7d
EZ
1487
1488 if (getrusage (RUSAGE_SELF, &usage) < 0)
1489 /* This shouldn't happen. What action is appropriate? */
8a0ff744 1490 xsignal0 (Qerror);
4211ee7d
EZ
1491
1492 /* Sum up user time and system time. */
1493 secs = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
1494 usecs = usage.ru_utime.tv_usec + usage.ru_stime.tv_usec;
1495 if (usecs >= 1000000)
1496 {
1497 usecs -= 1000000;
1498 secs++;
1499 }
1500
b8d9bd41
PE
1501 return list3 (make_number (hi_time (secs)),
1502 make_number (lo_time (secs)),
799734b0 1503 make_number (usecs));
c433c134 1504#else /* ! HAVE_GETRUSAGE */
43db14bb 1505#ifdef WINDOWSNT
c433c134
JR
1506 return w32_get_internal_run_time ();
1507#else /* ! WINDOWSNT */
4211ee7d 1508 return Fcurrent_time ();
c433c134
JR
1509#endif /* WINDOWSNT */
1510#endif /* HAVE_GETRUSAGE */
4211ee7d 1511}
d940e0e4
JB
1512\f
1513
8be6f318
PE
1514/* Make a Lisp list that represents the time T. */
1515Lisp_Object
1516make_time (time_t t)
1517{
b8d9bd41
PE
1518 return list2 (make_number (hi_time (t)),
1519 make_number (lo_time (t)));
8be6f318
PE
1520}
1521
1522/* Decode a Lisp list SPECIFIED_TIME that represents a time.
1523 If SPECIFIED_TIME is nil, use the current time.
1524 Set *RESULT to seconds since the Epoch.
1525 If USEC is not null, set *USEC to the microseconds component.
1526 Return nonzero if successful. */
5c5718b6 1527int
971de7fb 1528lisp_time_argument (Lisp_Object specified_time, time_t *result, int *usec)
e3120ab5
JB
1529{
1530 if (NILP (specified_time))
34a7a267
SS
1531 {
1532 if (usec)
1533 {
1534 EMACS_TIME t;
1535
c0261b5e 1536 EMACS_GET_TIME (t);
34a7a267
SS
1537 *usec = EMACS_USECS (t);
1538 *result = EMACS_SECS (t);
1539 return 1;
1540 }
1541 else
1542 return time (result) != -1;
1543 }
e3120ab5
JB
1544 else
1545 {
1546 Lisp_Object high, low;
313c1e54 1547 EMACS_INT hi;
e3120ab5 1548 high = Fcar (specified_time);
b7826503 1549 CHECK_NUMBER (high);
e3120ab5 1550 low = Fcdr (specified_time);
ae683129 1551 if (CONSP (low))
34a7a267
SS
1552 {
1553 if (usec)
1554 {
1555 Lisp_Object usec_l = Fcdr (low);
1556 if (CONSP (usec_l))
1557 usec_l = Fcar (usec_l);
1558 if (NILP (usec_l))
1559 *usec = 0;
1560 else
1561 {
b7826503 1562 CHECK_NUMBER (usec_l);
34a7a267
SS
1563 *usec = XINT (usec_l);
1564 }
1565 }
1566 low = Fcar (low);
1567 }
1568 else if (usec)
1569 *usec = 0;
b7826503 1570 CHECK_NUMBER (low);
313c1e54
PE
1571 hi = XINT (high);
1572
1573 /* Check for overflow, helping the compiler for common cases
1574 where no runtime check is needed, and taking care not to
1575 convert negative numbers to unsigned before comparing them. */
1576 if (! ((TYPE_SIGNED (time_t)
1577 ? (TIME_T_MIN >> 16 <= MOST_NEGATIVE_FIXNUM
1578 || TIME_T_MIN >> 16 <= hi)
1579 : 0 <= hi)
1580 && (MOST_POSITIVE_FIXNUM <= TIME_T_MAX >> 16
1581 || hi <= TIME_T_MAX >> 16)))
1582 return 0;
1583
1584 *result = (hi << 16) + (XINT (low) & 0xffff);
1585 return 1;
e3120ab5
JB
1586 }
1587}
1588
34a7a267 1589DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0,
7ee72033 1590 doc: /* Return the current time, as a float number of seconds since the epoch.
412f1fab 1591If SPECIFIED-TIME is given, it is the time to convert to float
5668fbb8 1592instead of the current time. The argument should have the form
c6493cdd 1593(HIGH LOW) or (HIGH LOW USEC). Thus, you can use times obtained from
5668fbb8
LT
1594`current-time' and from `file-attributes'. SPECIFIED-TIME can also
1595have the form (HIGH . LOW), but this is considered obsolete.
a1f17501
PJ
1596
1597WARNING: Since the result is floating point, it may not be exact.
d427a9fa
EZ
1598If precise time stamps are required, use either `current-time',
1599or (if you need time as a string) `format-time-string'. */)
5842a27b 1600 (Lisp_Object specified_time)
34a7a267
SS
1601{
1602 time_t sec;
1603 int usec;
1604
1605 if (! lisp_time_argument (specified_time, &sec, &usec))
1606 error ("Invalid time specification");
1607
26fad6e5 1608 return make_float ((sec * 1e6 + usec) / 1e6);
34a7a267
SS
1609}
1610
70ebbe5f
PE
1611/* Write information into buffer S of size MAXSIZE, according to the
1612 FORMAT of length FORMAT_LEN, using time information taken from *TP.
68c45bf0 1613 Default to Universal Time if UT is nonzero, local time otherwise.
a4180391 1614 Use NS as the number of nanoseconds in the %N directive.
70ebbe5f
PE
1615 Return the number of bytes written, not including the terminating
1616 '\0'. If S is NULL, nothing will be written anywhere; so to
1617 determine how many bytes would be written, use NULL for S and
1618 ((size_t) -1) for MAXSIZE.
1619
16c3e636
PE
1620 This function behaves like nstrftime, except it allows null
1621 bytes in FORMAT and it does not support nanoseconds. */
70ebbe5f 1622static size_t
a4180391
PE
1623emacs_nmemftime (char *s, size_t maxsize, const char *format,
1624 size_t format_len, const struct tm *tp, int ut, int ns)
70ebbe5f
PE
1625{
1626 size_t total = 0;
1627
be09e6e6
PE
1628 /* Loop through all the null-terminated strings in the format
1629 argument. Normally there's just one null-terminated string, but
1630 there can be arbitrarily many, concatenated together, if the
16c3e636 1631 format contains '\0' bytes. nstrftime stops at the first
be09e6e6 1632 '\0' byte so we must invoke it separately for each such string. */
70ebbe5f
PE
1633 for (;;)
1634 {
1635 size_t len;
1636 size_t result;
1637
1638 if (s)
1639 s[0] = '\1';
1640
a4180391 1641 result = nstrftime (s, maxsize, format, tp, ut, ns);
70ebbe5f
PE
1642
1643 if (s)
1644 {
1645 if (result == 0 && s[0] != '\0')
1646 return 0;
1647 s += result + 1;
1648 }
1649
1650 maxsize -= result + 1;
1651 total += result;
1652 len = strlen (format);
1653 if (len == format_len)
1654 return total;
1655 total++;
1656 format += len + 1;
1657 format_len -= len + 1;
1658 }
1659}
1660
3efcc98a 1661DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 3, 0,
7ee72033 1662 doc: /* Use FORMAT-STRING to format the time TIME, or now if omitted.
5668fbb8
LT
1663TIME is specified as (HIGH LOW . IGNORED), as returned by
1664`current-time' or `file-attributes'. The obsolete form (HIGH . LOW)
1665is also still accepted.
a1f17501
PJ
1666The third, optional, argument UNIVERSAL, if non-nil, means describe TIME
1667as Universal Time; nil means describe TIME in the local time zone.
1668The value is a copy of FORMAT-STRING, but with certain constructs replaced
1669by text that describes the specified date and time in TIME:
1670
1671%Y is the year, %y within the century, %C the century.
1672%G is the year corresponding to the ISO week, %g within the century.
1673%m is the numeric month.
1674%b and %h are the locale's abbreviated month name, %B the full name.
1675%d is the day of the month, zero-padded, %e is blank-padded.
1676%u is the numeric day of week from 1 (Monday) to 7, %w from 0 (Sunday) to 6.
1677%a is the locale's abbreviated name of the day of week, %A the full name.
1678%U is the week number starting on Sunday, %W starting on Monday,
1679 %V according to ISO 8601.
1680%j is the day of the year.
1681
1682%H is the hour on a 24-hour clock, %I is on a 12-hour clock, %k is like %H
1683 only blank-padded, %l is like %I blank-padded.
1684%p is the locale's equivalent of either AM or PM.
1685%M is the minute.
1686%S is the second.
a4180391 1687%N is the nanosecond, %6N the microsecond, %3N the millisecond, etc.
a1f17501
PJ
1688%Z is the time zone name, %z is the numeric form.
1689%s is the number of seconds since 1970-01-01 00:00:00 +0000.
1690
1691%c is the locale's date and time format.
1692%x is the locale's "preferred" date format.
1693%D is like "%m/%d/%y".
1694
1695%R is like "%H:%M", %T is like "%H:%M:%S", %r is like "%I:%M:%S %p".
1696%X is the locale's "preferred" time format.
1697
1698Finally, %n is a newline, %t is a tab, %% is a literal %.
1699
1700Certain flags and modifiers are available with some format controls.
1701The flags are `_', `-', `^' and `#'. For certain characters X,
1702%_X is like %X, but padded with blanks; %-X is like %X,
a67a233b
MR
1703but without padding. %^X is like %X, but with all textual
1704characters up-cased; %#X is like %X, but with letter-case of
a1f17501
PJ
1705all textual characters reversed.
1706%NX (where N stands for an integer) is like %X,
1707but takes up at least N (a number) positions.
1708The modifiers are `E' and `O'. For certain characters X,
1709%EX is a locale's alternative version of %X;
1710%OX is like %X, but uses the locale's number symbols.
1711
7ee72033 1712For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". */)
545b49b4 1713 (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
a82d387c
RS
1714{
1715 time_t value;
1716 int size;
a4180391
PE
1717 int usec;
1718 int ns;
177ea5f1 1719 struct tm *tm;
68c45bf0 1720 int ut = ! NILP (universal);
a82d387c 1721
b7826503 1722 CHECK_STRING (format_string);
a82d387c 1723
545b49b4 1724 if (! (lisp_time_argument (timeval, &value, &usec)
a4180391 1725 && 0 <= usec && usec < 1000000))
a82d387c 1726 error ("Invalid time specification");
a4180391 1727 ns = usec * 1000;
a82d387c 1728
68c45bf0
PE
1729 format_string = code_convert_string_norecord (format_string,
1730 Vlocale_coding_system, 1);
1731
a82d387c 1732 /* This is probably enough. */
d5db4077 1733 size = SBYTES (format_string) * 6 + 50;
a82d387c 1734
bcda42c8 1735 BLOCK_INPUT;
68c45bf0 1736 tm = ut ? gmtime (&value) : localtime (&value);
bcda42c8 1737 UNBLOCK_INPUT;
177ea5f1 1738 if (! tm)
fe31d94c 1739 time_overflow ();
177ea5f1 1740
ca9c0567 1741 synchronize_system_time_locale ();
68c45bf0 1742
a82d387c
RS
1743 while (1)
1744 {
b48382a0
RS
1745 char *buf = (char *) alloca (size + 1);
1746 int result;
1747
bfbcc5ee 1748 buf[0] = '\1';
bcda42c8 1749 BLOCK_INPUT;
a4180391 1750 result = emacs_nmemftime (buf, size, SSDATA (format_string),
d5db4077 1751 SBYTES (format_string),
a4180391 1752 tm, ut, ns);
bcda42c8 1753 UNBLOCK_INPUT;
bfbcc5ee 1754 if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
04e28558 1755 return code_convert_string_norecord (make_unibyte_string (buf, result),
68c45bf0 1756 Vlocale_coding_system, 0);
b48382a0
RS
1757
1758 /* If buffer was too small, make it bigger and try again. */
bcda42c8 1759 BLOCK_INPUT;
a4180391 1760 result = emacs_nmemftime (NULL, (size_t) -1,
42a5b22f 1761 SSDATA (format_string),
d5db4077 1762 SBYTES (format_string),
a4180391 1763 tm, ut, ns);
bcda42c8 1764 UNBLOCK_INPUT;
b48382a0 1765 size = result + 1;
a82d387c
RS
1766 }
1767}
1768
4691c06d 1769DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 1, 0,
7ee72033 1770 doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).
5668fbb8 1771The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED),
9671c13a 1772as from `current-time' and `file-attributes', or nil to use the
5668fbb8
LT
1773current time. The obsolete form (HIGH . LOW) is also still accepted.
1774The list has the following nine members: SEC is an integer between 0
1775and 60; SEC is 60 for a leap second, which only some operating systems
1776support. MINUTE is an integer between 0 and 59. HOUR is an integer
1777between 0 and 23. DAY is an integer between 1 and 31. MONTH is an
1778integer between 1 and 12. YEAR is an integer indicating the
1779four-digit year. DOW is the day of week, an integer between 0 and 6,
f1767e2b 1780where 0 is Sunday. DST is t if daylight saving time is in effect,
5668fbb8
LT
1781otherwise nil. ZONE is an integer indicating the number of seconds
1782east of Greenwich. (Note that Common Lisp has different meanings for
1783DOW and ZONE.) */)
5842a27b 1784 (Lisp_Object specified_time)
4691c06d
RS
1785{
1786 time_t time_spec;
3c887943 1787 struct tm save_tm;
4691c06d
RS
1788 struct tm *decoded_time;
1789 Lisp_Object list_args[9];
34a7a267
SS
1790
1791 if (! lisp_time_argument (specified_time, &time_spec, NULL))
4691c06d
RS
1792 error ("Invalid time specification");
1793
bcda42c8 1794 BLOCK_INPUT;
4691c06d 1795 decoded_time = localtime (&time_spec);
bcda42c8 1796 UNBLOCK_INPUT;
b8d9bd41
PE
1797 if (! (decoded_time
1798 && MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= decoded_time->tm_year
1799 && decoded_time->tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE))
fe31d94c 1800 time_overflow ();
3c887943
KH
1801 XSETFASTINT (list_args[0], decoded_time->tm_sec);
1802 XSETFASTINT (list_args[1], decoded_time->tm_min);
1803 XSETFASTINT (list_args[2], decoded_time->tm_hour);
1804 XSETFASTINT (list_args[3], decoded_time->tm_mday);
1805 XSETFASTINT (list_args[4], decoded_time->tm_mon + 1);
71c3f28f
EZ
1806 /* On 64-bit machines an int is narrower than EMACS_INT, thus the
1807 cast below avoids overflow in int arithmetics. */
aac18aa4 1808 XSETINT (list_args[5], TM_YEAR_BASE + (EMACS_INT) decoded_time->tm_year);
3c887943 1809 XSETFASTINT (list_args[6], decoded_time->tm_wday);
4691c06d 1810 list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil;
3c887943
KH
1811
1812 /* Make a copy, in case gmtime modifies the struct. */
1813 save_tm = *decoded_time;
bcda42c8 1814 BLOCK_INPUT;
3c887943 1815 decoded_time = gmtime (&time_spec);
bcda42c8 1816 UNBLOCK_INPUT;
3c887943
KH
1817 if (decoded_time == 0)
1818 list_args[8] = Qnil;
1819 else
94751666 1820 XSETINT (list_args[8], tm_diff (&save_tm, decoded_time));
4691c06d
RS
1821 return Flist (9, list_args);
1822}
1823
b8d9bd41
PE
1824/* Return OBJ - OFFSET, checking that OBJ is a valid fixnum and that
1825 the result is representable as an int. Assume OFFSET is small and
1826 nonnegative. */
1827static int
1828check_tm_member (Lisp_Object obj, int offset)
1829{
1830 EMACS_INT n;
1831 CHECK_NUMBER (obj);
1832 n = XINT (obj);
1833 if (! (INT_MIN + offset <= n && n - offset <= INT_MAX))
1834 time_overflow ();
1835 return n - offset;
1836}
1837
6ee9061c 1838DEFUN ("encode-time", Fencode_time, Sencode_time, 6, MANY, 0,
7ee72033 1839 doc: /* Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.
a1f17501
PJ
1840This is the reverse operation of `decode-time', which see.
1841ZONE defaults to the current time zone rule. This can
1842be a string or t (as from `set-time-zone-rule'), or it can be a list
b57c2708 1843\(as from `current-time-zone') or an integer (as from `decode-time')
9c279ddf 1844applied without consideration for daylight saving time.
a1f17501
PJ
1845
1846You can pass more than 7 arguments; then the first six arguments
1847are used as SECOND through YEAR, and the *last* argument is used as ZONE.
1848The intervening arguments are ignored.
1849This feature lets (apply 'encode-time (decode-time ...)) work.
1850
412f1fab 1851Out-of-range values for SECOND, MINUTE, HOUR, DAY, or MONTH are allowed;
a1f17501
PJ
1852for example, a DAY of 0 means the day preceding the given month.
1853Year numbers less than 100 are treated just like other year numbers.
4bfbe194
MB
1854If you want them to stand for years in this century, you must do that yourself.
1855
f555f8cf
KH
1856Years before 1970 are not guaranteed to work. On some systems,
1857year values as low as 1901 do work.
1858
4bfbe194 1859usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
c5101a77 1860 (size_t nargs, register Lisp_Object *args)
cce7b8a0 1861{
545b49b4 1862 time_t value;
c59b5089 1863 struct tm tm;
60653898 1864 Lisp_Object zone = (nargs > 6 ? args[nargs - 1] : Qnil);
6ee9061c 1865
b8d9bd41
PE
1866 tm.tm_sec = check_tm_member (args[0], 0);
1867 tm.tm_min = check_tm_member (args[1], 0);
1868 tm.tm_hour = check_tm_member (args[2], 0);
1869 tm.tm_mday = check_tm_member (args[3], 0);
1870 tm.tm_mon = check_tm_member (args[4], 1);
1871 tm.tm_year = check_tm_member (args[5], TM_YEAR_BASE);
c59b5089
PE
1872 tm.tm_isdst = -1;
1873
1874 if (CONSP (zone))
1875 zone = Fcar (zone);
1b8fa736 1876 if (NILP (zone))
bcda42c8
YM
1877 {
1878 BLOCK_INPUT;
545b49b4 1879 value = mktime (&tm);
bcda42c8
YM
1880 UNBLOCK_INPUT;
1881 }
c59b5089 1882 else
1b8fa736 1883 {
c59b5089 1884 char tzbuf[100];
8ea90aa3 1885 const char *tzstring;
c59b5089 1886 char **oldenv = environ, **newenv;
34a7a267 1887
2e34157c 1888 if (EQ (zone, Qt))
085e9fcb
EN
1889 tzstring = "UTC0";
1890 else if (STRINGP (zone))
51b59d79 1891 tzstring = SSDATA (zone);
c59b5089 1892 else if (INTEGERP (zone))
1b8fa736 1893 {
1ea40aa2 1894 int abszone = eabs (XINT (zone));
c59b5089
PE
1895 sprintf (tzbuf, "XXX%s%d:%02d:%02d", "-" + (XINT (zone) < 0),
1896 abszone / (60*60), (abszone/60) % 60, abszone % 60);
1897 tzstring = tzbuf;
1b8fa736 1898 }
c59b5089
PE
1899 else
1900 error ("Invalid time zone specification");
1901
34a7a267 1902 /* Set TZ before calling mktime; merely adjusting mktime's returned
c59b5089
PE
1903 value doesn't suffice, since that would mishandle leap seconds. */
1904 set_time_zone_rule (tzstring);
1905
bcda42c8 1906 BLOCK_INPUT;
545b49b4 1907 value = mktime (&tm);
bcda42c8 1908 UNBLOCK_INPUT;
c59b5089
PE
1909
1910 /* Restore TZ to previous value. */
1911 newenv = environ;
1912 environ = oldenv;
c0efcacf 1913 xfree (newenv);
c59b5089
PE
1914#ifdef LOCALTIME_CACHE
1915 tzset ();
1916#endif
1b8fa736 1917 }
1b8fa736 1918
545b49b4 1919 if (value == (time_t) -1)
fe31d94c 1920 time_overflow ();
c59b5089 1921
545b49b4 1922 return make_time (value);
cce7b8a0
RS
1923}
1924
2148f2b4 1925DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
244b023e 1926 doc: /* Return the current local time, as a human-readable string.
a1f17501 1927Programs can use this function to decode a time,
d65b4235
PE
1928since the number of columns in each field is fixed
1929if the year is in the range 1000-9999.
a1f17501
PJ
1930The format is `Sun Sep 16 01:03:52 1973'.
1931However, see also the functions `decode-time' and `format-time-string'
1932which provide a much more powerful and general facility.
1933
5668fbb8
LT
1934If SPECIFIED-TIME is given, it is a time to format instead of the
1935current time. The argument should have the form (HIGH LOW . IGNORED).
1936Thus, you can use times obtained from `current-time' and from
1937`file-attributes'. SPECIFIED-TIME can also have the form (HIGH . LOW),
1938but this is considered obsolete. */)
5842a27b 1939 (Lisp_Object specified_time)
2148f2b4 1940{
e3120ab5 1941 time_t value;
aac18aa4 1942 struct tm *tm;
2148f2b4
RS
1943 register char *tem;
1944
34a7a267 1945 if (! lisp_time_argument (specified_time, &value, NULL))
aac18aa4 1946 error ("Invalid time specification");
d65b4235
PE
1947
1948 /* Convert to a string, checking for out-of-range time stamps.
1949 Don't use 'ctime', as that might dump core if VALUE is out of
1950 range. */
bcda42c8 1951 BLOCK_INPUT;
aac18aa4 1952 tm = localtime (&value);
bcda42c8 1953 UNBLOCK_INPUT;
d65b4235 1954 if (! (tm && TM_YEAR_IN_ASCTIME_RANGE (tm->tm_year) && (tem = asctime (tm))))
fe31d94c 1955 time_overflow ();
35692fe0 1956
d65b4235
PE
1957 /* Remove the trailing newline. */
1958 tem[strlen (tem) - 1] = '\0';
35692fe0 1959
d65b4235 1960 return build_string (tem);
35692fe0 1961}
c2662aea 1962
94751666
PE
1963/* Yield A - B, measured in seconds.
1964 This function is copied from the GNU C Library. */
1965static int
971de7fb 1966tm_diff (struct tm *a, struct tm *b)
e3120ab5 1967{
94751666
PE
1968 /* Compute intervening leap days correctly even if year is negative.
1969 Take care to avoid int overflow in leap day calculations,
1970 but it's OK to assume that A and B are close to each other. */
1971 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
1972 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
1973 int a100 = a4 / 25 - (a4 % 25 < 0);
1974 int b100 = b4 / 25 - (b4 % 25 < 0);
1975 int a400 = a100 >> 2;
1976 int b400 = b100 >> 2;
1977 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
1978 int years = a->tm_year - b->tm_year;
1979 int days = (365 * years + intervening_leap_days
1980 + (a->tm_yday - b->tm_yday));
1981 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
1982 + (a->tm_min - b->tm_min))
8e718b4e 1983 + (a->tm_sec - b->tm_sec));
e3120ab5
JB
1984}
1985
1986DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 1, 0,
7ee72033 1987 doc: /* Return the offset and name for the local time zone.
a1f17501
PJ
1988This returns a list of the form (OFFSET NAME).
1989OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).
1990 A negative value means west of Greenwich.
1991NAME is a string giving the name of the time zone.
412f1fab 1992If SPECIFIED-TIME is given, the time zone offset is determined from it
5668fbb8
LT
1993instead of using the current time. The argument should have the form
1994(HIGH LOW . IGNORED). Thus, you can use times obtained from
1995`current-time' and from `file-attributes'. SPECIFIED-TIME can also
1996have the form (HIGH . LOW), but this is considered obsolete.
a1f17501
PJ
1997
1998Some operating systems cannot provide all this information to Emacs;
1999in this case, `current-time-zone' returns a list containing nil for
7ee72033 2000the data it can't find. */)
5842a27b 2001 (Lisp_Object specified_time)
c2662aea 2002{
e3120ab5
JB
2003 time_t value;
2004 struct tm *t;
177ea5f1 2005 struct tm gmt;
c2662aea 2006
bcda42c8
YM
2007 if (!lisp_time_argument (specified_time, &value, NULL))
2008 t = NULL;
2009 else
2010 {
2011 BLOCK_INPUT;
2012 t = gmtime (&value);
2013 if (t)
2014 {
2015 gmt = *t;
2016 t = localtime (&value);
2017 }
2018 UNBLOCK_INPUT;
2019 }
2020
2021 if (t)
e3120ab5 2022 {
177ea5f1
PE
2023 int offset = tm_diff (t, &gmt);
2024 char *s = 0;
2025 char buf[6];
42c4c67a 2026
e3120ab5
JB
2027#ifdef HAVE_TM_ZONE
2028 if (t->tm_zone)
5fd4de15 2029 s = (char *)t->tm_zone;
a7971c39
RS
2030#else /* not HAVE_TM_ZONE */
2031#ifdef HAVE_TZNAME
2032 if (t->tm_isdst == 0 || t->tm_isdst == 1)
2033 s = tzname[t->tm_isdst];
c2662aea 2034#endif
a7971c39 2035#endif /* not HAVE_TM_ZONE */
cda0f4da 2036
e3120ab5
JB
2037 if (!s)
2038 {
2039 /* No local time zone name is available; use "+-NNNN" instead. */
00fc94d0 2040 int am = (offset < 0 ? -offset : offset) / 60;
e3120ab5
JB
2041 sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
2042 s = buf;
2043 }
42c4c67a 2044
e3120ab5
JB
2045 return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
2046 }
2047 else
09dbcf71 2048 return Fmake_list (make_number (2), Qnil);
c2662aea
JB
2049}
2050
260e2e2a
KH
2051/* This holds the value of `environ' produced by the previous
2052 call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule
2053 has never been called. */
2054static char **environbuf;
2055
a03fc5a6
JR
2056/* This holds the startup value of the TZ environment variable so it
2057 can be restored if the user calls set-time-zone-rule with a nil
2058 argument. */
2059static char *initial_tz;
2060
143cb9a9 2061DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
7ee72033 2062 doc: /* Set the local time zone using TZ, a string specifying a time zone rule.
a1f17501 2063If TZ is nil, use implementation-defined default time zone information.
7ee72033 2064If TZ is t, use Universal Time. */)
5842a27b 2065 (Lisp_Object tz)
143cb9a9 2066{
8ea90aa3 2067 const char *tzstring;
143cb9a9 2068
a03fc5a6
JR
2069 /* When called for the first time, save the original TZ. */
2070 if (!environbuf)
2071 initial_tz = (char *) getenv ("TZ");
2072
143cb9a9 2073 if (NILP (tz))
a03fc5a6 2074 tzstring = initial_tz;
2e34157c 2075 else if (EQ (tz, Qt))
085e9fcb 2076 tzstring = "UTC0";
143cb9a9
RS
2077 else
2078 {
b7826503 2079 CHECK_STRING (tz);
51b59d79 2080 tzstring = SSDATA (tz);
143cb9a9
RS
2081 }
2082
c59b5089 2083 set_time_zone_rule (tzstring);
c2cd06e6 2084 free (environbuf);
c59b5089
PE
2085 environbuf = environ;
2086
2087 return Qnil;
2088}
2089
e0bf9faf
PE
2090#ifdef LOCALTIME_CACHE
2091
2092/* These two values are known to load tz files in buggy implementations,
2093 i.e. Solaris 1 executables running under either Solaris 1 or Solaris 2.
1155c453 2094 Their values shouldn't matter in non-buggy implementations.
34a7a267 2095 We don't use string literals for these strings,
1155c453
RS
2096 since if a string in the environment is in readonly
2097 storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
2098 See Sun bugs 1113095 and 1114114, ``Timezone routines
2099 improperly modify environment''. */
2100
e0bf9faf
PE
2101static char set_time_zone_rule_tz1[] = "TZ=GMT+0";
2102static char set_time_zone_rule_tz2[] = "TZ=GMT+1";
2103
2104#endif
1155c453 2105
c59b5089
PE
2106/* Set the local time zone rule to TZSTRING.
2107 This allocates memory into `environ', which it is the caller's
2108 responsibility to free. */
acb7cc89 2109
a92ae0ce 2110void
a8fe7202 2111set_time_zone_rule (const char *tzstring)
c59b5089
PE
2112{
2113 int envptrs;
2114 char **from, **to, **newenv;
2115
aafe5147 2116 /* Make the ENVIRON vector longer with room for TZSTRING. */
143cb9a9
RS
2117 for (from = environ; *from; from++)
2118 continue;
2119 envptrs = from - environ + 2;
2120 newenv = to = (char **) xmalloc (envptrs * sizeof (char *)
2121 + (tzstring ? strlen (tzstring) + 4 : 0));
aafe5147
RS
2122
2123 /* Add TZSTRING to the end of environ, as a value for TZ. */
143cb9a9
RS
2124 if (tzstring)
2125 {
2126 char *t = (char *) (to + envptrs);
2127 strcpy (t, "TZ=");
2128 strcat (t, tzstring);
2129 *to++ = t;
2130 }
2131
aafe5147
RS
2132 /* Copy the old environ vector elements into NEWENV,
2133 but don't copy the TZ variable.
2134 So we have only one definition of TZ, which came from TZSTRING. */
143cb9a9
RS
2135 for (from = environ; *from; from++)
2136 if (strncmp (*from, "TZ=", 3) != 0)
2137 *to++ = *from;
2138 *to = 0;
2139
2140 environ = newenv;
143cb9a9 2141
aafe5147
RS
2142 /* If we do have a TZSTRING, NEWENV points to the vector slot where
2143 the TZ variable is stored. If we do not have a TZSTRING,
2144 TO points to the vector slot which has the terminating null. */
2145
143cb9a9 2146#ifdef LOCALTIME_CACHE
aafe5147
RS
2147 {
2148 /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
2149 "US/Pacific" that loads a tz file, then changes to a value like
2150 "XXX0" that does not load a tz file, and then changes back to
2151 its original value, the last change is (incorrectly) ignored.
2152 Also, if TZ changes twice in succession to values that do
2153 not load a tz file, tzset can dump core (see Sun bug#1225179).
2154 The following code works around these bugs. */
2155
aafe5147
RS
2156 if (tzstring)
2157 {
2158 /* Temporarily set TZ to a value that loads a tz file
2159 and that differs from tzstring. */
2160 char *tz = *newenv;
1155c453
RS
2161 *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
2162 ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
aafe5147
RS
2163 tzset ();
2164 *newenv = tz;
2165 }
2166 else
2167 {
2168 /* The implied tzstring is unknown, so temporarily set TZ to
2169 two different values that each load a tz file. */
1155c453 2170 *to = set_time_zone_rule_tz1;
aafe5147
RS
2171 to[1] = 0;
2172 tzset ();
1155c453 2173 *to = set_time_zone_rule_tz2;
aafe5147
RS
2174 tzset ();
2175 *to = 0;
2176 }
2177
2178 /* Now TZ has the desired value, and tzset can be invoked safely. */
2179 }
2180
143cb9a9
RS
2181 tzset ();
2182#endif
143cb9a9 2183}
35692fe0 2184\f
fb8106e8
KH
2185/* Insert NARGS Lisp objects in the array ARGS by calling INSERT_FUNC
2186 (if a type of object is Lisp_Int) or INSERT_FROM_STRING_FUNC (if a
2187 type of object is Lisp_String). INHERIT is passed to
2188 INSERT_FROM_STRING_FUNC as the last argument. */
2189
acb7cc89 2190static void
9628fed7 2191general_insert_function (void (*insert_func)
b68864e5 2192 (const char *, EMACS_INT),
9628fed7
SM
2193 void (*insert_from_string_func)
2194 (Lisp_Object, EMACS_INT, EMACS_INT,
2195 EMACS_INT, EMACS_INT, int),
c5101a77 2196 int inherit, size_t nargs, Lisp_Object *args)
fb8106e8 2197{
c5101a77 2198 register size_t argnum;
fb8106e8
KH
2199 register Lisp_Object val;
2200
2201 for (argnum = 0; argnum < nargs; argnum++)
2202 {
2203 val = args[argnum];
1b9c91ed 2204 if (CHARACTERP (val))
fb8106e8 2205 {
d5c2c403 2206 unsigned char str[MAX_MULTIBYTE_LENGTH];
fb8106e8
KH
2207 int len;
2208
4b4deea2 2209 if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
d5c2c403 2210 len = CHAR_STRING (XFASTINT (val), str);
fb8106e8 2211 else
13c148b8 2212 {
0f8ea88f 2213 str[0] = (ASCII_CHAR_P (XINT (val))
d5c2c403 2214 ? XINT (val)
461c2ab9 2215 : multibyte_char_to_unibyte (XINT (val)));
13c148b8
KH
2216 len = 1;
2217 }
b68864e5 2218 (*insert_func) ((char *) str, len);
fb8106e8
KH
2219 }
2220 else if (STRINGP (val))
2221 {
1f24f4fd 2222 (*insert_from_string_func) (val, 0, 0,
d5db4077
KR
2223 SCHARS (val),
2224 SBYTES (val),
1f24f4fd 2225 inherit);
fb8106e8
KH
2226 }
2227 else
b7f34213 2228 wrong_type_argument (Qchar_or_string_p, val);
fb8106e8
KH
2229 }
2230}
2231
35692fe0 2232void
971de7fb 2233insert1 (Lisp_Object arg)
35692fe0
JB
2234{
2235 Finsert (1, &arg);
2236}
2237
52b14ac0
JB
2238
2239/* Callers passing one argument to Finsert need not gcpro the
2240 argument "array", since the only element of the array will
2241 not be used after calling insert or insert_from_string, so
2242 we don't care if it gets trashed. */
2243
a7ca3326 2244DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
7ee72033 2245 doc: /* Insert the arguments, either strings or characters, at point.
a1f17501
PJ
2246Point and before-insertion markers move forward to end up
2247 after the inserted text.
2248Any other markers at the point of insertion remain before the text.
2249
2250If the current buffer is multibyte, unibyte strings are converted
72bb55c6 2251to multibyte for insertion (see `string-make-multibyte').
a1f17501 2252If the current buffer is unibyte, multibyte strings are converted
72bb55c6
KS
2253to unibyte for insertion (see `string-make-unibyte').
2254
2255When operating on binary data, it may be necessary to preserve the
2256original bytes of a unibyte string when inserting it into a multibyte
2257buffer; to accomplish this, apply `string-as-multibyte' to the string
2258and insert the result.
4bfbe194
MB
2259
2260usage: (insert &rest ARGS) */)
c5101a77 2261 (size_t nargs, register Lisp_Object *args)
35692fe0 2262{
fb8106e8 2263 general_insert_function (insert, insert_from_string, 0, nargs, args);
be91036a
RS
2264 return Qnil;
2265}
2266
2267DEFUN ("insert-and-inherit", Finsert_and_inherit, Sinsert_and_inherit,
2268 0, MANY, 0,
7ee72033 2269 doc: /* Insert the arguments at point, inheriting properties from adjoining text.
a1f17501
PJ
2270Point and before-insertion markers move forward to end up
2271 after the inserted text.
2272Any other markers at the point of insertion remain before the text.
2273
2274If the current buffer is multibyte, unibyte strings are converted
2275to multibyte for insertion (see `unibyte-char-to-multibyte').
2276If the current buffer is unibyte, multibyte strings are converted
4bfbe194
MB
2277to unibyte for insertion.
2278
2279usage: (insert-and-inherit &rest ARGS) */)
c5101a77 2280 (size_t nargs, register Lisp_Object *args)
be91036a 2281{
fb8106e8
KH
2282 general_insert_function (insert_and_inherit, insert_from_string, 1,
2283 nargs, args);
35692fe0
JB
2284 return Qnil;
2285}
2286
2287DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0,
7ee72033 2288 doc: /* Insert strings or characters at point, relocating markers after the text.
a1f17501
PJ
2289Point and markers move forward to end up after the inserted text.
2290
2291If the current buffer is multibyte, unibyte strings are converted
2292to multibyte for insertion (see `unibyte-char-to-multibyte').
2293If the current buffer is unibyte, multibyte strings are converted
4bfbe194
MB
2294to unibyte for insertion.
2295
2296usage: (insert-before-markers &rest ARGS) */)
c5101a77 2297 (size_t nargs, register Lisp_Object *args)
35692fe0 2298{
fb8106e8
KH
2299 general_insert_function (insert_before_markers,
2300 insert_from_string_before_markers, 0,
2301 nargs, args);
be91036a
RS
2302 return Qnil;
2303}
2304
a0d76c27
EN
2305DEFUN ("insert-before-markers-and-inherit", Finsert_and_inherit_before_markers,
2306 Sinsert_and_inherit_before_markers, 0, MANY, 0,
7ee72033 2307 doc: /* Insert text at point, relocating markers and inheriting properties.
a1f17501
PJ
2308Point and markers move forward to end up after the inserted text.
2309
2310If the current buffer is multibyte, unibyte strings are converted
2311to multibyte for insertion (see `unibyte-char-to-multibyte').
2312If the current buffer is unibyte, multibyte strings are converted
4bfbe194
MB
2313to unibyte for insertion.
2314
2315usage: (insert-before-markers-and-inherit &rest ARGS) */)
c5101a77 2316 (size_t nargs, register Lisp_Object *args)
be91036a 2317{
fb8106e8
KH
2318 general_insert_function (insert_before_markers_and_inherit,
2319 insert_from_string_before_markers, 1,
2320 nargs, args);
35692fe0
JB
2321 return Qnil;
2322}
2323\f
a7ca3326 2324DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 3, 0,
9671c13a 2325 doc: /* Insert COUNT copies of CHARACTER.
a1f17501
PJ
2326Point, and before-insertion markers, are relocated as in the function `insert'.
2327The optional third arg INHERIT, if non-nil, says to inherit text properties
7ee72033 2328from adjoining text, if those properties are sticky. */)
5842a27b 2329 (Lisp_Object character, Lisp_Object count, Lisp_Object inherit)
35692fe0 2330{
b68864e5 2331 register char *string;
545b49b4 2332 register EMACS_INT stringlen;
29cdc13e
EZ
2333 register int i;
2334 register EMACS_INT n;
fb8106e8 2335 int len;
d5c2c403 2336 unsigned char str[MAX_MULTIBYTE_LENGTH];
35692fe0 2337
b7826503
PJ
2338 CHECK_NUMBER (character);
2339 CHECK_NUMBER (count);
35692fe0 2340
4b4deea2 2341 if (!NILP (BVAR (current_buffer, enable_multibyte_characters)))
d5c2c403 2342 len = CHAR_STRING (XFASTINT (character), str);
fb8106e8 2343 else
d5c2c403 2344 str[0] = XFASTINT (character), len = 1;
d1f3d2af 2345 if (BUF_BYTES_MAX / len < XINT (count))
29cdc13e 2346 error ("Maximum buffer size would be exceeded");
fb8106e8 2347 n = XINT (count) * len;
35692fe0
JB
2348 if (n <= 0)
2349 return Qnil;
545b49b4
PE
2350 stringlen = min (n, 256 * len);
2351 string = (char *) alloca (stringlen);
2352 for (i = 0; i < stringlen; i++)
fb8106e8 2353 string[i] = str[i % len];
545b49b4 2354 while (n >= stringlen)
35692fe0 2355 {
54e42e2d 2356 QUIT;
e2eeabbb 2357 if (!NILP (inherit))
545b49b4 2358 insert_and_inherit (string, stringlen);
e2eeabbb 2359 else
545b49b4
PE
2360 insert (string, stringlen);
2361 n -= stringlen;
35692fe0
JB
2362 }
2363 if (n > 0)
83951f1e
KH
2364 {
2365 if (!NILP (inherit))
2366 insert_and_inherit (string, n);
2367 else
2368 insert (string, n);
2369 }
35692fe0
JB
2370 return Qnil;
2371}
2372
48ef988f
KH
2373DEFUN ("insert-byte", Finsert_byte, Sinsert_byte, 2, 3, 0,
2374 doc: /* Insert COUNT (second arg) copies of BYTE (first arg).
2375Both arguments are required.
2376BYTE is a number of the range 0..255.
2377
2378If BYTE is 128..255 and the current buffer is multibyte, the
2379corresponding eight-bit character is inserted.
2380
2381Point, and before-insertion markers, are relocated as in the function `insert'.
2382The optional third arg INHERIT, if non-nil, says to inherit text properties
2383from adjoining text, if those properties are sticky. */)
5842a27b 2384 (Lisp_Object byte, Lisp_Object count, Lisp_Object inherit)
48ef988f
KH
2385{
2386 CHECK_NUMBER (byte);
2387 if (XINT (byte) < 0 || XINT (byte) > 255)
2388 args_out_of_range_3 (byte, make_number (0), make_number (255));
2389 if (XINT (byte) >= 128
4b4deea2 2390 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
48ef988f 2391 XSETFASTINT (byte, BYTE8_TO_CHAR (XINT (byte)));
ed398b0a 2392 return Finsert_char (byte, count, inherit);
48ef988f
KH
2393}
2394
35692fe0 2395\f
ffd56f97
JB
2396/* Making strings from buffer contents. */
2397
2398/* Return a Lisp_String containing the text of the current buffer from
74d6d8c5 2399 START to END. If text properties are in use and the current buffer
eb8c3be9 2400 has properties in the range specified, the resulting string will also
260e2e2a 2401 have them, if PROPS is nonzero.
ffd56f97
JB
2402
2403 We don't want to use plain old make_string here, because it calls
2404 make_uninit_string, which can cause the buffer arena to be
2405 compacted. make_string has no way of knowing that the data has
2406 been moved, and thus copies the wrong data into the string. This
2407 doesn't effect most of the other users of make_string, so it should
2408 be left as is. But we should use this function when conjuring
2409 buffer substrings. */
74d6d8c5 2410
ffd56f97 2411Lisp_Object
413d18e7 2412make_buffer_string (EMACS_INT start, EMACS_INT end, int props)
ffd56f97 2413{
413d18e7
EZ
2414 EMACS_INT start_byte = CHAR_TO_BYTE (start);
2415 EMACS_INT end_byte = CHAR_TO_BYTE (end);
ffd56f97 2416
88441c8e
RS
2417 return make_buffer_string_both (start, start_byte, end, end_byte, props);
2418}
2419
2420/* Return a Lisp_String containing the text of the current buffer from
2421 START / START_BYTE to END / END_BYTE.
2422
2423 If text properties are in use and the current buffer
2424 has properties in the range specified, the resulting string will also
2425 have them, if PROPS is nonzero.
2426
2427 We don't want to use plain old make_string here, because it calls
2428 make_uninit_string, which can cause the buffer arena to be
2429 compacted. make_string has no way of knowing that the data has
2430 been moved, and thus copies the wrong data into the string. This
2431 doesn't effect most of the other users of make_string, so it should
2432 be left as is. But we should use this function when conjuring
2433 buffer substrings. */
2434
2435Lisp_Object
413d18e7
EZ
2436make_buffer_string_both (EMACS_INT start, EMACS_INT start_byte,
2437 EMACS_INT end, EMACS_INT end_byte, int props)
88441c8e
RS
2438{
2439 Lisp_Object result, tem, tem1;
2440
ffd56f97
JB
2441 if (start < GPT && GPT < end)
2442 move_gap (start);
2443
4b4deea2 2444 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
5f75e666
RS
2445 result = make_uninit_multibyte_string (end - start, end_byte - start_byte);
2446 else
2447 result = make_uninit_string (end - start);
72af86bd 2448 memcpy (SDATA (result), BYTE_POS_ADDR (start_byte), end_byte - start_byte);
ffd56f97 2449
260e2e2a 2450 /* If desired, update and copy the text properties. */
260e2e2a
KH
2451 if (props)
2452 {
2453 update_buffer_properties (start, end);
2454
2455 tem = Fnext_property_change (make_number (start), Qnil, make_number (end));
2456 tem1 = Ftext_properties_at (make_number (start), Qnil);
2457
2458 if (XINT (tem) != end || !NILP (tem1))
ec1c14f6
RS
2459 copy_intervals_to_string (result, current_buffer, start,
2460 end - start);
260e2e2a 2461 }
74d6d8c5 2462
ffd56f97
JB
2463 return result;
2464}
35692fe0 2465
260e2e2a
KH
2466/* Call Vbuffer_access_fontify_functions for the range START ... END
2467 in the current buffer, if necessary. */
2468
2469static void
29cdc13e 2470update_buffer_properties (EMACS_INT start, EMACS_INT end)
260e2e2a 2471{
260e2e2a
KH
2472 /* If this buffer has some access functions,
2473 call them, specifying the range of the buffer being accessed. */
2474 if (!NILP (Vbuffer_access_fontify_functions))
2475 {
2476 Lisp_Object args[3];
2477 Lisp_Object tem;
2478
2479 args[0] = Qbuffer_access_fontify_functions;
2480 XSETINT (args[1], start);
2481 XSETINT (args[2], end);
2482
2483 /* But don't call them if we can tell that the work
2484 has already been done. */
2485 if (!NILP (Vbuffer_access_fontified_property))
2486 {
2487 tem = Ftext_property_any (args[1], args[2],
2488 Vbuffer_access_fontified_property,
2489 Qnil, Qnil);
2490 if (! NILP (tem))
ced1d19a 2491 Frun_hook_with_args (3, args);
260e2e2a
KH
2492 }
2493 else
ced1d19a 2494 Frun_hook_with_args (3, args);
260e2e2a 2495 }
260e2e2a
KH
2496}
2497
a7ca3326 2498DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
7ee72033 2499 doc: /* Return the contents of part of the current buffer as a string.
a1f17501
PJ
2500The two arguments START and END are character positions;
2501they can be in either order.
2502The string returned is multibyte if the buffer is multibyte.
2503
2504This function copies the text properties of that part of the buffer
2505into the result string; if you don't want the text properties,
7ee72033 2506use `buffer-substring-no-properties' instead. */)
5842a27b 2507 (Lisp_Object start, Lisp_Object end)
35692fe0 2508{
413d18e7 2509 register EMACS_INT b, e;
35692fe0 2510
2591ec64
EN
2511 validate_region (&start, &end);
2512 b = XINT (start);
2513 e = XINT (end);
35692fe0 2514
2591ec64 2515 return make_buffer_string (b, e, 1);
260e2e2a
KH
2516}
2517
2518DEFUN ("buffer-substring-no-properties", Fbuffer_substring_no_properties,
2519 Sbuffer_substring_no_properties, 2, 2, 0,
7ee72033 2520 doc: /* Return the characters of part of the buffer, without the text properties.
a1f17501 2521The two arguments START and END are character positions;
7ee72033 2522they can be in either order. */)
5842a27b 2523 (Lisp_Object start, Lisp_Object end)
260e2e2a 2524{
413d18e7 2525 register EMACS_INT b, e;
260e2e2a 2526
2591ec64
EN
2527 validate_region (&start, &end);
2528 b = XINT (start);
2529 e = XINT (end);
260e2e2a 2530
2591ec64 2531 return make_buffer_string (b, e, 0);
35692fe0
JB
2532}
2533
a7ca3326 2534DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
7ee72033 2535 doc: /* Return the contents of the current buffer as a string.
a1f17501 2536If narrowing is in effect, this function returns only the visible part
7ee72033 2537of the buffer. */)
5842a27b 2538 (void)
35692fe0 2539{
0daf6e8d 2540 return make_buffer_string (BEGV, ZV, 1);
35692fe0
JB
2541}
2542
2543DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
deb8e082 2544 1, 3, 0,
658ec670 2545 doc: /* Insert before point a substring of the contents of BUFFER.
a1f17501 2546BUFFER may be a buffer or a buffer name.
412f1fab
JB
2547Arguments START and END are character positions specifying the substring.
2548They default to the values of (point-min) and (point-max) in BUFFER. */)
5842a27b 2549 (Lisp_Object buffer, Lisp_Object start, Lisp_Object end)
35692fe0 2550{
29cdc13e 2551 register EMACS_INT b, e, temp;
260e2e2a 2552 register struct buffer *bp, *obuf;
658ec670 2553 Lisp_Object buf;
35692fe0 2554
658ec670
JB
2555 buf = Fget_buffer (buffer);
2556 if (NILP (buf))
2557 nsberror (buffer);
2558 bp = XBUFFER (buf);
4b4deea2 2559 if (NILP (BVAR (bp, name)))
93b62e82 2560 error ("Selecting deleted buffer");
35692fe0 2561
2591ec64
EN
2562 if (NILP (start))
2563 b = BUF_BEGV (bp);
35692fe0
JB
2564 else
2565 {
b7826503 2566 CHECK_NUMBER_COERCE_MARKER (start);
2591ec64 2567 b = XINT (start);
35692fe0 2568 }
2591ec64
EN
2569 if (NILP (end))
2570 e = BUF_ZV (bp);
35692fe0
JB
2571 else
2572 {
b7826503 2573 CHECK_NUMBER_COERCE_MARKER (end);
2591ec64 2574 e = XINT (end);
35692fe0
JB
2575 }
2576
2591ec64
EN
2577 if (b > e)
2578 temp = b, b = e, e = temp;
35692fe0 2579
2591ec64
EN
2580 if (!(BUF_BEGV (bp) <= b && e <= BUF_ZV (bp)))
2581 args_out_of_range (start, end);
35692fe0 2582
260e2e2a
KH
2583 obuf = current_buffer;
2584 set_buffer_internal_1 (bp);
2591ec64 2585 update_buffer_properties (b, e);
260e2e2a
KH
2586 set_buffer_internal_1 (obuf);
2587
2591ec64 2588 insert_from_buffer (bp, b, e - b, 0);
35692fe0
JB
2589 return Qnil;
2590}
e9cf2084
RS
2591
2592DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings,
deb8e082 2593 6, 6, 0,
7ee72033 2594 doc: /* Compare two substrings of two buffers; return result as number.
a1f17501
PJ
2595the value is -N if first string is less after N-1 chars,
2596+N if first string is greater after N-1 chars, or 0 if strings match.
2597Each substring is represented as three arguments: BUFFER, START and END.
2598That makes six args in all, three for each substring.
2599
2600The value of `case-fold-search' in the current buffer
7ee72033 2601determines whether case is significant or ignored. */)
5842a27b 2602 (Lisp_Object buffer1, Lisp_Object start1, Lisp_Object end1, Lisp_Object buffer2, Lisp_Object start2, Lisp_Object end2)
e9cf2084 2603{
29cdc13e 2604 register EMACS_INT begp1, endp1, begp2, endp2, temp;
e9cf2084 2605 register struct buffer *bp1, *bp2;
1149fd6f 2606 register Lisp_Object trt
4b4deea2
TT
2607 = (!NILP (BVAR (current_buffer, case_fold_search))
2608 ? BVAR (current_buffer, case_canon_table) : Qnil);
29cdc13e
EZ
2609 EMACS_INT chars = 0;
2610 EMACS_INT i1, i2, i1_byte, i2_byte;
e9cf2084
RS
2611
2612 /* Find the first buffer and its substring. */
2613
2614 if (NILP (buffer1))
2615 bp1 = current_buffer;
2616 else
2617 {
3fff2dfa
RS
2618 Lisp_Object buf1;
2619 buf1 = Fget_buffer (buffer1);
2620 if (NILP (buf1))
2621 nsberror (buffer1);
2622 bp1 = XBUFFER (buf1);
4b4deea2 2623 if (NILP (BVAR (bp1, name)))
93b62e82 2624 error ("Selecting deleted buffer");
e9cf2084
RS
2625 }
2626
2627 if (NILP (start1))
2628 begp1 = BUF_BEGV (bp1);
2629 else
2630 {
b7826503 2631 CHECK_NUMBER_COERCE_MARKER (start1);
e9cf2084
RS
2632 begp1 = XINT (start1);
2633 }
2634 if (NILP (end1))
2635 endp1 = BUF_ZV (bp1);
2636 else
2637 {
b7826503 2638 CHECK_NUMBER_COERCE_MARKER (end1);
e9cf2084
RS
2639 endp1 = XINT (end1);
2640 }
2641
2642 if (begp1 > endp1)
2643 temp = begp1, begp1 = endp1, endp1 = temp;
2644
2645 if (!(BUF_BEGV (bp1) <= begp1
2646 && begp1 <= endp1
2647 && endp1 <= BUF_ZV (bp1)))
2648 args_out_of_range (start1, end1);
2649
2650 /* Likewise for second substring. */
2651
2652 if (NILP (buffer2))
2653 bp2 = current_buffer;
2654 else
2655 {
3fff2dfa
RS
2656 Lisp_Object buf2;
2657 buf2 = Fget_buffer (buffer2);
2658 if (NILP (buf2))
2659 nsberror (buffer2);
3b1fdd85 2660 bp2 = XBUFFER (buf2);
4b4deea2 2661 if (NILP (BVAR (bp2, name)))
93b62e82 2662 error ("Selecting deleted buffer");
e9cf2084
RS
2663 }
2664
2665 if (NILP (start2))
2666 begp2 = BUF_BEGV (bp2);
2667 else
2668 {
b7826503 2669 CHECK_NUMBER_COERCE_MARKER (start2);
e9cf2084
RS
2670 begp2 = XINT (start2);
2671 }
2672 if (NILP (end2))
2673 endp2 = BUF_ZV (bp2);
2674 else
2675 {
b7826503 2676 CHECK_NUMBER_COERCE_MARKER (end2);
e9cf2084
RS
2677 endp2 = XINT (end2);
2678 }
2679
2680 if (begp2 > endp2)
2681 temp = begp2, begp2 = endp2, endp2 = temp;
2682
2683 if (!(BUF_BEGV (bp2) <= begp2
2684 && begp2 <= endp2
2685 && endp2 <= BUF_ZV (bp2)))
2686 args_out_of_range (start2, end2);
2687
07422a12
RS
2688 i1 = begp1;
2689 i2 = begp2;
2690 i1_byte = buf_charpos_to_bytepos (bp1, i1);
2691 i2_byte = buf_charpos_to_bytepos (bp2, i2);
e9cf2084 2692
07422a12 2693 while (i1 < endp1 && i2 < endp2)
e9cf2084 2694 {
07422a12
RS
2695 /* When we find a mismatch, we must compare the
2696 characters, not just the bytes. */
2697 int c1, c2;
ec1c14f6 2698
2221451f
RS
2699 QUIT;
2700
4b4deea2 2701 if (! NILP (BVAR (bp1, enable_multibyte_characters)))
07422a12
RS
2702 {
2703 c1 = BUF_FETCH_MULTIBYTE_CHAR (bp1, i1_byte);
2704 BUF_INC_POS (bp1, i1_byte);
2705 i1++;
2706 }
2707 else
2708 {
2709 c1 = BUF_FETCH_BYTE (bp1, i1);
4c0354d7 2710 MAKE_CHAR_MULTIBYTE (c1);
07422a12
RS
2711 i1++;
2712 }
2713
4b4deea2 2714 if (! NILP (BVAR (bp2, enable_multibyte_characters)))
07422a12
RS
2715 {
2716 c2 = BUF_FETCH_MULTIBYTE_CHAR (bp2, i2_byte);
2717 BUF_INC_POS (bp2, i2_byte);
2718 i2++;
2719 }
2720 else
2721 {
2722 c2 = BUF_FETCH_BYTE (bp2, i2);
4c0354d7 2723 MAKE_CHAR_MULTIBYTE (c2);
07422a12
RS
2724 i2++;
2725 }
ec1c14f6 2726
1149fd6f 2727 if (!NILP (trt))
e9cf2084 2728 {
1149fd6f
SM
2729 c1 = CHAR_TABLE_TRANSLATE (trt, c1);
2730 c2 = CHAR_TABLE_TRANSLATE (trt, c2);
e9cf2084
RS
2731 }
2732 if (c1 < c2)
ec1c14f6 2733 return make_number (- 1 - chars);
e9cf2084 2734 if (c1 > c2)
ec1c14f6 2735 return make_number (chars + 1);
07422a12
RS
2736
2737 chars++;
e9cf2084
RS
2738 }
2739
2740 /* The strings match as far as they go.
2741 If one is shorter, that one is less. */
07422a12 2742 if (chars < endp1 - begp1)
ec1c14f6 2743 return make_number (chars + 1);
07422a12 2744 else if (chars < endp2 - begp2)
ec1c14f6 2745 return make_number (- chars - 1);
e9cf2084
RS
2746
2747 /* Same length too => they are equal. */
2748 return make_number (0);
2749}
35692fe0 2750\f
d5a539cd 2751static Lisp_Object
971de7fb 2752subst_char_in_region_unwind (Lisp_Object arg)
d5a539cd 2753{
4b4deea2 2754 return BVAR (current_buffer, undo_list) = arg;
d5a539cd
RS
2755}
2756
c8e76b47 2757static Lisp_Object
971de7fb 2758subst_char_in_region_unwind_1 (Lisp_Object arg)
c8e76b47 2759{
4b4deea2 2760 return BVAR (current_buffer, filename) = arg;
c8e76b47
RS
2761}
2762
35692fe0 2763DEFUN ("subst-char-in-region", Fsubst_char_in_region,
deb8e082 2764 Ssubst_char_in_region, 4, 5, 0,
7ee72033 2765 doc: /* From START to END, replace FROMCHAR with TOCHAR each time it occurs.
a1f17501
PJ
2766If optional arg NOUNDO is non-nil, don't record this change for undo
2767and don't mark the buffer as really changed.
7ee72033 2768Both characters must have the same length of multi-byte form. */)
5842a27b 2769 (Lisp_Object start, Lisp_Object end, Lisp_Object fromchar, Lisp_Object tochar, Lisp_Object noundo)
35692fe0 2770{
c8a66ab8 2771 register EMACS_INT pos, pos_byte, stop, i, len, end_byte;
0f2e2a3b
SM
2772 /* Keep track of the first change in the buffer:
2773 if 0 we haven't found it yet.
2774 if < 0 we've found it and we've run the before-change-function.
2775 if > 0 we've actually performed it and the value is its position. */
29cdc13e 2776 EMACS_INT changed = 0;
d5c2c403
KH
2777 unsigned char fromstr[MAX_MULTIBYTE_LENGTH], tostr[MAX_MULTIBYTE_LENGTH];
2778 unsigned char *p;
aed13378 2779 int count = SPECPDL_INDEX ();
aa801467
KH
2780#define COMBINING_NO 0
2781#define COMBINING_BEFORE 1
2782#define COMBINING_AFTER 2
2783#define COMBINING_BOTH (COMBINING_BEFORE | COMBINING_AFTER)
2784 int maybe_byte_combining = COMBINING_NO;
29cdc13e 2785 EMACS_INT last_changed = 0;
4b4deea2 2786 int multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
35692fe0 2787
0f2e2a3b
SM
2788 restart:
2789
35692fe0 2790 validate_region (&start, &end);
b7826503
PJ
2791 CHECK_NUMBER (fromchar);
2792 CHECK_NUMBER (tochar);
35692fe0 2793
7439e5b9 2794 if (multibyte_p)
fb8106e8 2795 {
d5c2c403
KH
2796 len = CHAR_STRING (XFASTINT (fromchar), fromstr);
2797 if (CHAR_STRING (XFASTINT (tochar), tostr) != len)
fdd6025e 2798 error ("Characters in `subst-char-in-region' have different byte-lengths");
aa801467
KH
2799 if (!ASCII_BYTE_P (*tostr))
2800 {
2801 /* If *TOSTR is in the range 0x80..0x9F and TOCHAR is not a
2802 complete multibyte character, it may be combined with the
2803 after bytes. If it is in the range 0xA0..0xFF, it may be
2804 combined with the before and after bytes. */
2805 if (!CHAR_HEAD_P (*tostr))
2806 maybe_byte_combining = COMBINING_BOTH;
2807 else if (BYTES_BY_CHAR_HEAD (*tostr) > len)
2808 maybe_byte_combining = COMBINING_AFTER;
2809 }
fb8106e8
KH
2810 }
2811 else
2812 {
2813 len = 1;
d5c2c403
KH
2814 fromstr[0] = XFASTINT (fromchar);
2815 tostr[0] = XFASTINT (tochar);
fb8106e8
KH
2816 }
2817
84246b95
KH
2818 pos = XINT (start);
2819 pos_byte = CHAR_TO_BYTE (pos);
ec1c14f6
RS
2820 stop = CHAR_TO_BYTE (XINT (end));
2821 end_byte = stop;
35692fe0 2822
d5a539cd
RS
2823 /* If we don't want undo, turn off putting stuff on the list.
2824 That's faster than getting rid of things,
c8e76b47
RS
2825 and it prevents even the entry for a first change.
2826 Also inhibit locking the file. */
0f2e2a3b 2827 if (!changed && !NILP (noundo))
d5a539cd
RS
2828 {
2829 record_unwind_protect (subst_char_in_region_unwind,
4b4deea2
TT
2830 BVAR (current_buffer, undo_list));
2831 BVAR (current_buffer, undo_list) = Qt;
c8e76b47
RS
2832 /* Don't do file-locking. */
2833 record_unwind_protect (subst_char_in_region_unwind_1,
4b4deea2
TT
2834 BVAR (current_buffer, filename));
2835 BVAR (current_buffer, filename) = Qnil;
d5a539cd
RS
2836 }
2837
84246b95 2838 if (pos_byte < GPT_BYTE)
ec1c14f6 2839 stop = min (stop, GPT_BYTE);
fb8106e8 2840 while (1)
35692fe0 2841 {
c8a66ab8 2842 EMACS_INT pos_byte_next = pos_byte;
a3360ff9 2843
84246b95 2844 if (pos_byte >= stop)
fb8106e8 2845 {
84246b95 2846 if (pos_byte >= end_byte) break;
ec1c14f6 2847 stop = end_byte;
fb8106e8 2848 }
84246b95 2849 p = BYTE_POS_ADDR (pos_byte);
7439e5b9
GM
2850 if (multibyte_p)
2851 INC_POS (pos_byte_next);
2852 else
2853 ++pos_byte_next;
a3360ff9
KH
2854 if (pos_byte_next - pos_byte == len
2855 && p[0] == fromstr[0]
fb8106e8
KH
2856 && (len == 1
2857 || (p[1] == fromstr[1]
2858 && (len == 2 || (p[2] == fromstr[2]
2859 && (len == 3 || p[3] == fromstr[3]))))))
35692fe0 2860 {
0f2e2a3b
SM
2861 if (changed < 0)
2862 /* We've already seen this and run the before-change-function;
2863 this time we only need to record the actual position. */
2864 changed = pos;
2865 else if (!changed)
60b96ee7 2866 {
0f2e2a3b 2867 changed = -1;
3e145152 2868 modify_region (current_buffer, pos, XINT (end), 0);
7653d030
RS
2869
2870 if (! NILP (noundo))
2871 {
1e158d25
RS
2872 if (MODIFF - 1 == SAVE_MODIFF)
2873 SAVE_MODIFF++;
0b5397c2
SM
2874 if (MODIFF - 1 == BUF_AUTOSAVE_MODIFF (current_buffer))
2875 BUF_AUTOSAVE_MODIFF (current_buffer)++;
7653d030 2876 }
0f2e2a3b
SM
2877
2878 /* The before-change-function may have moved the gap
2879 or even modified the buffer so we should start over. */
2880 goto restart;
60b96ee7
RS
2881 }
2882
0c1e3b85 2883 /* Take care of the case where the new character
34a7a267 2884 combines with neighboring bytes. */
a3360ff9 2885 if (maybe_byte_combining
aa801467
KH
2886 && (maybe_byte_combining == COMBINING_AFTER
2887 ? (pos_byte_next < Z_BYTE
2888 && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte_next)))
2889 : ((pos_byte_next < Z_BYTE
2890 && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte_next)))
2891 || (pos_byte > BEG_BYTE
2892 && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1))))))
0c1e3b85
RS
2893 {
2894 Lisp_Object tem, string;
2895
2896 struct gcpro gcpro1;
2897
4b4deea2 2898 tem = BVAR (current_buffer, undo_list);
0c1e3b85
RS
2899 GCPRO1 (tem);
2900
aa801467 2901 /* Make a multibyte string containing this single character. */
e7f8264d 2902 string = make_multibyte_string ((char *) tostr, 1, len);
0c1e3b85
RS
2903 /* replace_range is less efficient, because it moves the gap,
2904 but it handles combining correctly. */
2905 replace_range (pos, pos + 1, string,
9869520f 2906 0, 0, 1);
a3360ff9
KH
2907 pos_byte_next = CHAR_TO_BYTE (pos);
2908 if (pos_byte_next > pos_byte)
2909 /* Before combining happened. We should not increment
3f5409d3
KH
2910 POS. So, to cancel the later increment of POS,
2911 decrease it now. */
2912 pos--;
a3360ff9 2913 else
3f5409d3 2914 INC_POS (pos_byte_next);
34a7a267 2915
0c1e3b85 2916 if (! NILP (noundo))
4b4deea2 2917 BVAR (current_buffer, undo_list) = tem;
0c1e3b85
RS
2918
2919 UNGCPRO;
2920 }
2921 else
2922 {
2923 if (NILP (noundo))
2924 record_change (pos, 1);
2925 for (i = 0; i < len; i++) *p++ = tostr[i];
2926 }
d5c2c403 2927 last_changed = pos + 1;
35692fe0 2928 }
3f5409d3
KH
2929 pos_byte = pos_byte_next;
2930 pos++;
35692fe0
JB
2931 }
2932
0f2e2a3b 2933 if (changed > 0)
d5c2c403
KH
2934 {
2935 signal_after_change (changed,
2936 last_changed - changed, last_changed - changed);
2937 update_compositions (changed, last_changed, CHECK_ALL);
2938 }
60b96ee7 2939
d5a539cd 2940 unbind_to (count, Qnil);
35692fe0
JB
2941 return Qnil;
2942}
2943
f555f8cf 2944
c8a66ab8
EZ
2945static Lisp_Object check_translation (EMACS_INT, EMACS_INT, EMACS_INT,
2946 Lisp_Object);
f555f8cf
KH
2947
2948/* Helper function for Ftranslate_region_internal.
2949
2950 Check if a character sequence at POS (POS_BYTE) matches an element
2951 of VAL. VAL is a list (([FROM-CHAR ...] . TO) ...). If a matching
2952 element is found, return it. Otherwise return Qnil. */
2953
2954static Lisp_Object
c8a66ab8
EZ
2955check_translation (EMACS_INT pos, EMACS_INT pos_byte, EMACS_INT end,
2956 Lisp_Object val)
f555f8cf
KH
2957{
2958 int buf_size = 16, buf_used = 0;
2959 int *buf = alloca (sizeof (int) * buf_size);
2960
2961 for (; CONSP (val); val = XCDR (val))
2962 {
2963 Lisp_Object elt;
c8a66ab8 2964 EMACS_INT len, i;
f555f8cf
KH
2965
2966 elt = XCAR (val);
2967 if (! CONSP (elt))
2968 continue;
2969 elt = XCAR (elt);
2970 if (! VECTORP (elt))
2971 continue;
2972 len = ASIZE (elt);
2973 if (len <= end - pos)
2974 {
2975 for (i = 0; i < len; i++)
2976 {
2977 if (buf_used <= i)
2978 {
2979 unsigned char *p = BYTE_POS_ADDR (pos_byte);
c8a66ab8 2980 int len1;
f555f8cf
KH
2981
2982 if (buf_used == buf_size)
2983 {
2984 int *newbuf;
2985
2986 buf_size += 16;
2987 newbuf = alloca (sizeof (int) * buf_size);
2988 memcpy (newbuf, buf, sizeof (int) * buf_used);
2989 buf = newbuf;
2990 }
c8a66ab8
EZ
2991 buf[buf_used++] = STRING_CHAR_AND_LENGTH (p, len1);
2992 pos_byte += len1;
f555f8cf
KH
2993 }
2994 if (XINT (AREF (elt, i)) != buf[i])
2995 break;
2996 }
2997 if (i == len)
2998 return XCAR (val);
2999 }
3000 }
3001 return Qnil;
3002}
3003
3004
8583605b
KH
3005DEFUN ("translate-region-internal", Ftranslate_region_internal,
3006 Stranslate_region_internal, 3, 3, 0,
3007 doc: /* Internal use only.
3008From START to END, translate characters according to TABLE.
f555f8cf
KH
3009TABLE is a string or a char-table; the Nth character in it is the
3010mapping for the character with code N.
7ee72033 3011It returns the number of characters changed. */)
5842a27b 3012 (Lisp_Object start, Lisp_Object end, register Lisp_Object table)
35692fe0 3013{
35692fe0 3014 register unsigned char *tt; /* Trans table. */
35692fe0
JB
3015 register int nc; /* New character. */
3016 int cnt; /* Number of changes made. */
faf8b5bc 3017 EMACS_INT size; /* Size of translate table. */
c8a66ab8 3018 EMACS_INT pos, pos_byte, end_pos;
4b4deea2 3019 int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
9710023e 3020 int string_multibyte IF_LINT (= 0);
35692fe0
JB
3021
3022 validate_region (&start, &end);
8583605b 3023 if (CHAR_TABLE_P (table))
f555f8cf
KH
3024 {
3025 if (! EQ (XCHAR_TABLE (table)->purpose, Qtranslation_table))
3026 error ("Not a translation table");
eb3d9ec7 3027 size = MAX_CHAR;
f555f8cf
KH
3028 tt = NULL;
3029 }
8583605b
KH
3030 else
3031 {
3032 CHECK_STRING (table);
3033
eb3d9ec7
KH
3034 if (! multibyte && (SCHARS (table) < SBYTES (table)))
3035 table = string_make_unibyte (table);
8583605b
KH
3036 string_multibyte = SCHARS (table) < SBYTES (table);
3037 size = SBYTES (table);
3038 tt = SDATA (table);
3039 }
35692fe0 3040
1f24f4fd 3041 pos = XINT (start);
8583605b 3042 pos_byte = CHAR_TO_BYTE (pos);
e65837df 3043 end_pos = XINT (end);
af6ea8ad 3044 modify_region (current_buffer, pos, end_pos, 0);
35692fe0
JB
3045
3046 cnt = 0;
f555f8cf 3047 for (; pos < end_pos; )
35692fe0 3048 {
ec1c14f6 3049 register unsigned char *p = BYTE_POS_ADDR (pos_byte);
8583605b
KH
3050 unsigned char *str, buf[MAX_MULTIBYTE_LENGTH];
3051 int len, str_len;
1f24f4fd 3052 int oc;
f555f8cf 3053 Lisp_Object val;
ec1c14f6 3054
e8cce5af 3055 if (multibyte)
62a6e103 3056 oc = STRING_CHAR_AND_LENGTH (p, len);
e8cce5af 3057 else
eb3d9ec7
KH
3058 oc = *p, len = 1;
3059 if (oc < size)
35692fe0 3060 {
eb3d9ec7 3061 if (tt)
35692fe0 3062 {
fa056b08
KS
3063 /* Reload as signal_after_change in last iteration may GC. */
3064 tt = SDATA (table);
8583605b 3065 if (string_multibyte)
0c1e3b85 3066 {
8583605b 3067 str = tt + string_char_to_byte (table, oc);
62a6e103 3068 nc = STRING_CHAR_AND_LENGTH (str, str_len);
0c1e3b85
RS
3069 }
3070 else
3071 {
eb3d9ec7
KH
3072 nc = tt[oc];
3073 if (! ASCII_BYTE_P (nc) && multibyte)
3074 {
3075 str_len = BYTE8_STRING (nc, buf);
3076 str = buf;
3077 }
3078 else
3079 {
3080 str_len = 1;
3081 str = tt + oc;
3082 }
0c1e3b85 3083 }
35692fe0 3084 }
eb3d9ec7 3085 else
f555f8cf 3086 {
faf8b5bc 3087 EMACS_INT c;
eb3d9ec7
KH
3088
3089 nc = oc;
3090 val = CHAR_TABLE_REF (table, oc);
3091 if (CHARACTERP (val)
3092 && (c = XINT (val), CHAR_VALID_P (c, 0)))
3093 {
3094 nc = c;
3095 str_len = CHAR_STRING (nc, buf);
3096 str = buf;
3097 }
3098 else if (VECTORP (val) || (CONSP (val)))
3099 {
3100 /* VAL is [TO_CHAR ...] or (([FROM-CHAR ...] . TO) ...)
3101 where TO is TO-CHAR or [TO-CHAR ...]. */
3102 nc = -1;
3103 }
f555f8cf 3104 }
8583605b 3105
eb3d9ec7 3106 if (nc != oc && nc >= 0)
8583605b 3107 {
f555f8cf
KH
3108 /* Simple one char to one char translation. */
3109 if (len != str_len)
3110 {
3111 Lisp_Object string;
8583605b 3112
f555f8cf
KH
3113 /* This is less efficient, because it moves the gap,
3114 but it should handle multibyte characters correctly. */
e7f8264d 3115 string = make_multibyte_string ((char *) str, 1, str_len);
f555f8cf
KH
3116 replace_range (pos, pos + 1, string, 1, 0, 1);
3117 len = str_len;
3118 }
3119 else
3120 {
3121 record_change (pos, 1);
3122 while (str_len-- > 0)
3123 *p++ = *str++;
3124 signal_after_change (pos, 1, 1);
3125 update_compositions (pos, pos + 1, CHECK_BORDER);
3126 }
3127 ++cnt;
8583605b 3128 }
eb3d9ec7 3129 else if (nc < 0)
8583605b 3130 {
f555f8cf
KH
3131 Lisp_Object string;
3132
3133 if (CONSP (val))
3134 {
3135 val = check_translation (pos, pos_byte, end_pos, val);
3136 if (NILP (val))
3137 {
3138 pos_byte += len;
3139 pos++;
3140 continue;
3141 }
3142 /* VAL is ([FROM-CHAR ...] . TO). */
3143 len = ASIZE (XCAR (val));
3144 val = XCDR (val);
3145 }
3146 else
3147 len = 1;
3148
3149 if (VECTORP (val))
3150 {
bde25748 3151 string = Fconcat (1, &val);
f555f8cf
KH
3152 }
3153 else
3154 {
3155 string = Fmake_string (make_number (1), val);
3156 }
3157 replace_range (pos, pos + len, string, 1, 0, 1);
3158 pos_byte += SBYTES (string);
3159 pos += SCHARS (string);
3160 cnt += SCHARS (string);
3161 end_pos += SCHARS (string) - len;
3162 continue;
8583605b 3163 }
8583605b
KH
3164 }
3165 pos_byte += len;
3f5409d3 3166 pos++;
35692fe0
JB
3167 }
3168
ec1c14f6 3169 return make_number (cnt);
35692fe0
JB
3170}
3171
a7ca3326 3172DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
7ee72033 3173 doc: /* Delete the text between point and mark.
412f1fab 3174
a1f17501 3175When called from a program, expects two arguments,
7ee72033 3176positions (integers or markers) specifying the stretch to be deleted. */)
5842a27b 3177 (Lisp_Object start, Lisp_Object end)
35692fe0 3178{
2591ec64
EN
3179 validate_region (&start, &end);
3180 del_range (XINT (start), XINT (end));
35692fe0
JB
3181 return Qnil;
3182}
7dae4502
SM
3183
3184DEFUN ("delete-and-extract-region", Fdelete_and_extract_region,
3185 Sdelete_and_extract_region, 2, 2, 0,
7ee72033 3186 doc: /* Delete the text between START and END and return it. */)
5842a27b 3187 (Lisp_Object start, Lisp_Object end)
7dae4502
SM
3188{
3189 validate_region (&start, &end);
8550b998 3190 if (XINT (start) == XINT (end))
977f6cfb 3191 return empty_unibyte_string;
7dae4502
SM
3192 return del_range_1 (XINT (start), XINT (end), 1, 1);
3193}
35692fe0 3194\f
a7ca3326 3195DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
7ee72033
MB
3196 doc: /* Remove restrictions (narrowing) from current buffer.
3197This allows the buffer's full text to be seen and edited. */)
5842a27b 3198 (void)
35692fe0 3199{
2cad2e34
RS
3200 if (BEG != BEGV || Z != ZV)
3201 current_buffer->clip_changed = 1;
35692fe0 3202 BEGV = BEG;
ec1c14f6
RS
3203 BEGV_BYTE = BEG_BYTE;
3204 SET_BUF_ZV_BOTH (current_buffer, Z, Z_BYTE);
52b14ac0
JB
3205 /* Changing the buffer bounds invalidates any recorded current column. */
3206 invalidate_current_column ();
35692fe0
JB
3207 return Qnil;
3208}
3209
a7ca3326 3210DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
7ee72033 3211 doc: /* Restrict editing in this buffer to the current region.
a1f17501
PJ
3212The rest of the text becomes temporarily invisible and untouchable
3213but is not deleted; if you save the buffer in a file, the invisible
3214text is included in the file. \\[widen] makes all visible again.
3215See also `save-restriction'.
3216
3217When calling from a program, pass two arguments; positions (integers
7ee72033 3218or markers) bounding the text that should remain visible. */)
5842a27b 3219 (register Lisp_Object start, Lisp_Object end)
35692fe0 3220{
b7826503
PJ
3221 CHECK_NUMBER_COERCE_MARKER (start);
3222 CHECK_NUMBER_COERCE_MARKER (end);
35692fe0 3223
2591ec64 3224 if (XINT (start) > XINT (end))
35692fe0 3225 {
b5a6948e 3226 Lisp_Object tem;
2591ec64 3227 tem = start; start = end; end = tem;
35692fe0
JB
3228 }
3229
2591ec64
EN
3230 if (!(BEG <= XINT (start) && XINT (start) <= XINT (end) && XINT (end) <= Z))
3231 args_out_of_range (start, end);
35692fe0 3232
2cad2e34
RS
3233 if (BEGV != XFASTINT (start) || ZV != XFASTINT (end))
3234 current_buffer->clip_changed = 1;
3235
ec1c14f6 3236 SET_BUF_BEGV (current_buffer, XFASTINT (start));
2591ec64 3237 SET_BUF_ZV (current_buffer, XFASTINT (end));
6ec8bbd2 3238 if (PT < XFASTINT (start))
2591ec64 3239 SET_PT (XFASTINT (start));
6ec8bbd2 3240 if (PT > XFASTINT (end))
2591ec64 3241 SET_PT (XFASTINT (end));
52b14ac0
JB
3242 /* Changing the buffer bounds invalidates any recorded current column. */
3243 invalidate_current_column ();
35692fe0
JB
3244 return Qnil;
3245}
3246
3247Lisp_Object
971de7fb 3248save_restriction_save (void)
35692fe0 3249{
d6abb4c7
MB
3250 if (BEGV == BEG && ZV == Z)
3251 /* The common case that the buffer isn't narrowed.
3252 We return just the buffer object, which save_restriction_restore
3253 recognizes as meaning `no restriction'. */
3254 return Fcurrent_buffer ();
3255 else
3256 /* We have to save a restriction, so return a pair of markers, one
3257 for the beginning and one for the end. */
3258 {
3259 Lisp_Object beg, end;
3260
3261 beg = buildmark (BEGV, BEGV_BYTE);
3262 end = buildmark (ZV, ZV_BYTE);
35692fe0 3263
d6abb4c7
MB
3264 /* END must move forward if text is inserted at its exact location. */
3265 XMARKER(end)->insertion_type = 1;
3266
3267 return Fcons (beg, end);
3268 }
35692fe0
JB
3269}
3270
3271Lisp_Object
971de7fb 3272save_restriction_restore (Lisp_Object data)
35692fe0 3273{
d528b1ce
SM
3274 struct buffer *cur = NULL;
3275 struct buffer *buf = (CONSP (data)
3276 ? XMARKER (XCAR (data))->buffer
3277 : XBUFFER (data));
3278
4b4deea2 3279 if (buf && buf != current_buffer && !NILP (BVAR (buf, pt_marker)))
d528b1ce
SM
3280 { /* If `buf' uses markers to keep track of PT, BEGV, and ZV (as
3281 is the case if it is or has an indirect buffer), then make
3282 sure it is current before we update BEGV, so
3283 set_buffer_internal takes care of managing those markers. */
3284 cur = current_buffer;
3285 set_buffer_internal (buf);
3286 }
3287
d6abb4c7
MB
3288 if (CONSP (data))
3289 /* A pair of marks bounding a saved restriction. */
35692fe0 3290 {
d6abb4c7
MB
3291 struct Lisp_Marker *beg = XMARKER (XCAR (data));
3292 struct Lisp_Marker *end = XMARKER (XCDR (data));
d528b1ce 3293 eassert (buf == end->buffer);
2cad2e34 3294
63884563
RS
3295 if (buf /* Verify marker still points to a buffer. */
3296 && (beg->charpos != BUF_BEGV (buf) || end->charpos != BUF_ZV (buf)))
d6abb4c7
MB
3297 /* The restriction has changed from the saved one, so restore
3298 the saved restriction. */
3299 {
faf8b5bc 3300 EMACS_INT pt = BUF_PT (buf);
d6abb4c7
MB
3301
3302 SET_BUF_BEGV_BOTH (buf, beg->charpos, beg->bytepos);
3303 SET_BUF_ZV_BOTH (buf, end->charpos, end->bytepos);
3304
3305 if (pt < beg->charpos || pt > end->charpos)
3306 /* The point is outside the new visible range, move it inside. */
3307 SET_BUF_PT_BOTH (buf,
3308 clip_to_bounds (beg->charpos, pt, end->charpos),
63884563 3309 clip_to_bounds (beg->bytepos, BUF_PT_BYTE (buf),
d6abb4c7 3310 end->bytepos));
177c0ea7 3311
d6abb4c7
MB
3312 buf->clip_changed = 1; /* Remember that the narrowing changed. */
3313 }
3314 }
3315 else
3316 /* A buffer, which means that there was no old restriction. */
3317 {
63884563
RS
3318 if (buf /* Verify marker still points to a buffer. */
3319 && (BUF_BEGV (buf) != BUF_BEG (buf) || BUF_ZV (buf) != BUF_Z (buf)))
d6abb4c7
MB
3320 /* The buffer has been narrowed, get rid of the narrowing. */
3321 {
63884563
RS
3322 SET_BUF_BEGV_BOTH (buf, BUF_BEG (buf), BUF_BEG_BYTE (buf));
3323 SET_BUF_ZV_BOTH (buf, BUF_Z (buf), BUF_Z_BYTE (buf));
35692fe0 3324
d6abb4c7
MB
3325 buf->clip_changed = 1; /* Remember that the narrowing changed. */
3326 }
3327 }
35692fe0 3328
aca092ac
SM
3329 /* Changing the buffer bounds invalidates any recorded current column. */
3330 invalidate_current_column ();
3331
d528b1ce
SM
3332 if (cur)
3333 set_buffer_internal (cur);
3334
35692fe0
JB
3335 return Qnil;
3336}
3337
3338DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
7ee72033 3339 doc: /* Execute BODY, saving and restoring current buffer's restrictions.
a1f17501 3340The buffer's restrictions make parts of the beginning and end invisible.
9671c13a 3341\(They are set up with `narrow-to-region' and eliminated with `widen'.)
a1f17501
PJ
3342This special form, `save-restriction', saves the current buffer's restrictions
3343when it is entered, and restores them when it is exited.
3344So any `narrow-to-region' within BODY lasts only until the end of the form.
3345The old restrictions settings are restored
3346even in case of abnormal exit (throw or error).
3347
3348The value returned is the value of the last form in BODY.
3349
3350Note: if you are using both `save-excursion' and `save-restriction',
3351use `save-excursion' outermost:
33c2d29f
MB
3352 (save-excursion (save-restriction ...))
3353
3354usage: (save-restriction &rest BODY) */)
5842a27b 3355 (Lisp_Object body)
35692fe0
JB
3356{
3357 register Lisp_Object val;
aed13378 3358 int count = SPECPDL_INDEX ();
35692fe0
JB
3359
3360 record_unwind_protect (save_restriction_restore, save_restriction_save ());
3361 val = Fprogn (body);
3362 return unbind_to (count, val);
3363}
3364\f
0ae83348 3365/* Buffer for the most recent text displayed by Fmessage_box. */
671fbc4d
KH
3366static char *message_text;
3367
3368/* Allocated length of that buffer. */
3369static int message_length;
3370
a7ca3326 3371DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
db18da59 3372 doc: /* Display a message at the bottom of the screen.
281c1721
RS
3373The message also goes into the `*Messages*' buffer.
3374\(In keyboard macros, that's all it does.)
db18da59 3375Return the message.
281c1721 3376
a1f17501
PJ
3377The first argument is a format control string, and the rest are data
3378to be formatted under control of the string. See `format' for details.
3379
7bd5bcfb
KS
3380Note: Use (message "%s" VALUE) to print the value of expressions and
3381variables to avoid accidentally interpreting `%' as format specifiers.
3382
fa056b08
KS
3383If the first argument is nil or the empty string, the function clears
3384any existing message; this lets the minibuffer contents show. See
3385also `current-message'.
4bfbe194 3386
867b9600 3387usage: (message FORMAT-STRING &rest ARGS) */)
c5101a77 3388 (size_t nargs, Lisp_Object *args)
35692fe0 3389{
6076e561
RS
3390 if (NILP (args[0])
3391 || (STRINGP (args[0])
3392 && SBYTES (args[0]) == 0))
f0250249
JB
3393 {
3394 message (0);
674a954a 3395 return args[0];
f0250249 3396 }
ccdac5be
JB
3397 else
3398 {
3399 register Lisp_Object val;
304f1f12 3400 val = Fformat (nargs, args);
d5db4077 3401 message3 (val, SBYTES (val), STRING_MULTIBYTE (val));
ccdac5be
JB
3402 return val;
3403 }
35692fe0
JB
3404}
3405
cacc3e2c 3406DEFUN ("message-box", Fmessage_box, Smessage_box, 1, MANY, 0,
7ee72033 3407 doc: /* Display a message, in a dialog box if possible.
a1f17501
PJ
3408If a dialog box is not available, use the echo area.
3409The first argument is a format control string, and the rest are data
3410to be formatted under control of the string. See `format' for details.
3411
fa056b08
KS
3412If the first argument is nil or the empty string, clear any existing
3413message; let the minibuffer contents show.
4bfbe194 3414
867b9600 3415usage: (message-box FORMAT-STRING &rest ARGS) */)
c5101a77 3416 (size_t nargs, Lisp_Object *args)
cacc3e2c
RS
3417{
3418 if (NILP (args[0]))
3419 {
3420 message (0);
3421 return Qnil;
3422 }
3423 else
3424 {
3425 register Lisp_Object val;
3426 val = Fformat (nargs, args);
f8250f01 3427#ifdef HAVE_MENUS
0ae83348
EZ
3428 /* The MS-DOS frames support popup menus even though they are
3429 not FRAME_WINDOW_P. */
3430 if (FRAME_WINDOW_P (XFRAME (selected_frame))
3431 || FRAME_MSDOS_P (XFRAME (selected_frame)))
cacc3e2c 3432 {
f838ed7b 3433 Lisp_Object pane, menu;
cacc3e2c
RS
3434 struct gcpro gcpro1;
3435 pane = Fcons (Fcons (build_string ("OK"), Qt), Qnil);
3436 GCPRO1 (pane);
3437 menu = Fcons (val, pane);
f838ed7b 3438 Fx_popup_dialog (Qt, menu, Qt);
cacc3e2c
RS
3439 UNGCPRO;
3440 return val;
3441 }
0ae83348 3442#endif /* HAVE_MENUS */
cacc3e2c
RS
3443 /* Copy the data so that it won't move when we GC. */
3444 if (! message_text)
3445 {
3446 message_text = (char *)xmalloc (80);
3447 message_length = 80;
3448 }
d5db4077 3449 if (SBYTES (val) > message_length)
cacc3e2c 3450 {
d5db4077 3451 message_length = SBYTES (val);
cacc3e2c
RS
3452 message_text = (char *)xrealloc (message_text, message_length);
3453 }
72af86bd 3454 memcpy (message_text, SDATA (val), SBYTES (val));
d5db4077 3455 message2 (message_text, SBYTES (val),
d13a8480 3456 STRING_MULTIBYTE (val));
cacc3e2c 3457 return val;
cacc3e2c
RS
3458 }
3459}
f8250f01 3460
cacc3e2c 3461DEFUN ("message-or-box", Fmessage_or_box, Smessage_or_box, 1, MANY, 0,
7ee72033 3462 doc: /* Display a message in a dialog box or in the echo area.
a1f17501
PJ
3463If this command was invoked with the mouse, use a dialog box if
3464`use-dialog-box' is non-nil.
3465Otherwise, use the echo area.
3466The first argument is a format control string, and the rest are data
3467to be formatted under control of the string. See `format' for details.
3468
fa056b08
KS
3469If the first argument is nil or the empty string, clear any existing
3470message; let the minibuffer contents show.
4bfbe194 3471
867b9600 3472usage: (message-or-box FORMAT-STRING &rest ARGS) */)
c5101a77 3473 (size_t nargs, Lisp_Object *args)
cacc3e2c 3474{
f8250f01 3475#ifdef HAVE_MENUS
5920df33 3476 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
c01fbf95 3477 && use_dialog_box)
0a56ee6b 3478 return Fmessage_box (nargs, args);
cacc3e2c
RS
3479#endif
3480 return Fmessage (nargs, args);
3481}
3482
a7ca3326 3483DEFUN ("current-message", Fcurrent_message, Scurrent_message, 0, 0, 0,
7ee72033 3484 doc: /* Return the string currently displayed in the echo area, or nil if none. */)
5842a27b 3485 (void)
b14dda8a 3486{
0634a78e 3487 return current_message ();
b14dda8a
RS
3488}
3489
2d9811c4 3490
d2936d21 3491DEFUN ("propertize", Fpropertize, Spropertize, 1, MANY, 0,
7ee72033 3492 doc: /* Return a copy of STRING with text properties added.
a1f17501
PJ
3493First argument is the string to copy.
3494Remaining arguments form a sequence of PROPERTY VALUE pairs for text
4bfbe194
MB
3495properties to add to the result.
3496usage: (propertize STRING &rest PROPERTIES) */)
c5101a77 3497 (size_t nargs, Lisp_Object *args)
2d9811c4
GM
3498{
3499 Lisp_Object properties, string;
3500 struct gcpro gcpro1, gcpro2;
c5101a77 3501 size_t i;
2d9811c4
GM
3502
3503 /* Number of args must be odd. */
c5101a77 3504 if ((nargs & 1) == 0)
2d9811c4
GM
3505 error ("Wrong number of arguments");
3506
3507 properties = string = Qnil;
3508 GCPRO2 (properties, string);
34a7a267 3509
2d9811c4 3510 /* First argument must be a string. */
b7826503 3511 CHECK_STRING (args[0]);
2d9811c4
GM
3512 string = Fcopy_sequence (args[0]);
3513
3514 for (i = 1; i < nargs; i += 2)
9b7a2369 3515 properties = Fcons (args[i], Fcons (args[i + 1], properties));
2d9811c4
GM
3516
3517 Fadd_text_properties (make_number (0),
d5db4077 3518 make_number (SCHARS (string)),
2d9811c4
GM
3519 properties, string);
3520 RETURN_UNGCPRO (string);
3521}
3522
37910ab2
PE
3523/* pWIDE is a conversion for printing large decimal integers (possibly with a
3524 trailing "d" that is ignored). pWIDElen is its length. signed_wide and
3525 unsigned_wide are signed and unsigned types for printing them. Use widest
3526 integers if available so that more floating point values can be converted. */
3527#ifdef PRIdMAX
3528# define pWIDE PRIdMAX
3529enum { pWIDElen = sizeof PRIdMAX - 2 }; /* Don't count trailing "d". */
3530typedef intmax_t signed_wide;
3531typedef uintmax_t unsigned_wide;
3532#else
3533# define pWIDE pI
3534enum { pWIDElen = sizeof pI - 1 };
3535typedef EMACS_INT signed_wide;
3536typedef EMACS_UINT unsigned_wide;
3537#endif
1f24f4fd 3538
a7ca3326 3539DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
867b9600
JL
3540 doc: /* Format a string out of a format-string and arguments.
3541The first argument is a format control string.
a1f17501 3542The other arguments are substituted into it to make the result, a string.
575b782f
CY
3543
3544The format control string may contain %-sequences meaning to substitute
3545the next available argument:
3546
a1f17501
PJ
3547%s means print a string argument. Actually, prints any object, with `princ'.
3548%d means print as number in decimal (%o octal, %x hex).
3549%X is like %x, but uses upper case.
3550%e means print a number in exponential notation.
3551%f means print a number in decimal-point notation.
3552%g means print a number in exponential notation
3553 or decimal-point notation, whichever uses fewer characters.
3554%c means print a number as a single character.
3555%S means print any object as an s-expression (using `prin1').
575b782f
CY
3556
3557The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.
4bfbe194
MB
3558Use %% to put a single % into the output.
3559
575b782f
CY
3560A %-sequence may contain optional flag, width, and precision
3561specifiers, as follows:
3562
3563 %<flags><width><precision>character
3564
3565where flags is [+ #-0]+, width is [0-9]+, and precision is .[0-9]+
3566
3567The + flag character inserts a + before any positive number, while a
3568space inserts a space before any positive number; these flags only
3569affect %d, %e, %f, and %g sequences, and the + flag takes precedence.
3570The # flag means to use an alternate display form for %o, %x, %X, %e,
3571%f, and %g sequences. The - and 0 flags affect the width specifier,
3572as described below.
3573
3574The width specifier supplies a lower limit for the length of the
3575printed representation. The padding, if any, normally goes on the
3576left, but it goes on the right if the - flag is present. The padding
3577character is normally a space, but it is 0 if the 0 flag is present.
3578The - flag takes precedence over the 0 flag.
3579
3580For %e, %f, and %g sequences, the number after the "." in the
3581precision specifier says how many decimal places to show; if zero, the
3582decimal point itself is omitted. For %s and %S, the precision
3583specifier truncates the string to the given width.
f555f8cf 3584
4bfbe194 3585usage: (format STRING &rest OBJECTS) */)
c5101a77 3586 (size_t nargs, register Lisp_Object *args)
35692fe0 3587{
37910ab2
PE
3588 EMACS_INT n; /* The number of the next arg to substitute */
3589 char initial_buffer[4000];
3590 char *buf = initial_buffer;
3591 EMACS_INT bufsize = sizeof initial_buffer;
d1f3d2af 3592 EMACS_INT max_bufsize = STRING_BYTES_MAX + 1;
37910ab2
PE
3593 char *p;
3594 Lisp_Object buf_save_value IF_LINT (= {0});
e7f8264d 3595 register char *format, *end, *format_start;
37910ab2
PE
3596 EMACS_INT formatlen, nchars;
3597 /* Nonzero if the format is multibyte. */
3598 int multibyte_format = 0;
1f24f4fd
RS
3599 /* Nonzero if the output should be a multibyte string,
3600 which is true if any of the inputs is one. */
3601 int multibyte = 0;
8f2917e4
KH
3602 /* When we make a multibyte string, we must pay attention to the
3603 byte combining problem, i.e., a byte may be combined with a
3b59c351 3604 multibyte character of the previous string. This flag tells if we
8f2917e4
KH
3605 must consider such a situation or not. */
3606 int maybe_combine_byte;
8d6179dc 3607 Lisp_Object val;
d147ee84 3608 int arg_intervals = 0;
7e2c051b 3609 USE_SAFE_ALLOCA;
d147ee84
RS
3610
3611 /* discarded[I] is 1 if byte I of the format
3612 string was not copied into the output.
3613 It is 2 if byte I was not the first byte of its character. */
37910ab2 3614 char *discarded;
d147ee84
RS
3615
3616 /* Each element records, for one argument,
3617 the start and end bytepos in the output string,
37910ab2 3618 whether the argument has been converted to string (e.g., due to "%S"),
d147ee84
RS
3619 and whether the argument is a string with intervals.
3620 info[0] is unused. Unused elements have -1 for start. */
5e6d5493
GM
3621 struct info
3622 {
37910ab2
PE
3623 EMACS_INT start, end;
3624 int converted_to_string;
3625 int intervals;
5e6d5493 3626 } *info = 0;
1f24f4fd 3627
35692fe0
JB
3628 /* It should not be necessary to GCPRO ARGS, because
3629 the caller in the interpreter should take care of that. */
3630
37910ab2
PE
3631 CHECK_STRING (args[0]);
3632 format_start = SSDATA (args[0]);
3633 formatlen = SBYTES (args[0]);
3634
3635 /* Allocate the info and discarded tables. */
3636 {
3637 EMACS_INT i;
3638 if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs)
531b0165 3639 memory_full (SIZE_MAX);
37910ab2
PE
3640 SAFE_ALLOCA (info, struct info *, (nargs + 1) * sizeof *info + formatlen);
3641 discarded = (char *) &info[nargs + 1];
3642 for (i = 0; i < nargs + 1; i++)
3643 {
3644 info[i].start = -1;
3645 info[i].intervals = info[i].converted_to_string = 0;
3646 }
3647 memset (discarded, 0, formatlen);
3648 }
3649
e781c49e
RS
3650 /* Try to determine whether the result should be multibyte.
3651 This is not always right; sometimes the result needs to be multibyte
3652 because of an object that we will pass through prin1,
3653 and in that case, we won't know it here. */
37910ab2
PE
3654 multibyte_format = STRING_MULTIBYTE (args[0]);
3655 multibyte = multibyte_format;
3656 for (n = 1; !multibyte && n < nargs; n++)
3657 if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
3658 multibyte = 1;
67965a98 3659
e781c49e 3660 /* If we start out planning a unibyte result,
37910ab2 3661 then discover it has to be multibyte, we jump back to retry. */
e781c49e
RS
3662 retry:
3663
37910ab2
PE
3664 p = buf;
3665 nchars = 0;
3666 n = 0;
d147ee84 3667
37910ab2
PE
3668 /* Scan the format and store result in BUF. */
3669 format = format_start;
3670 end = format + formatlen;
3671 maybe_combine_byte = 0;
35692fe0 3672
35692fe0 3673 while (format != end)
37910ab2
PE
3674 {
3675 /* The values of N and FORMAT when the loop body is entered. */
3676 EMACS_INT n0 = n;
3677 char *format0 = format;
35692fe0 3678
37910ab2
PE
3679 /* Bytes needed to represent the output of this conversion. */
3680 EMACS_INT convbytes;
537dfb13 3681
37910ab2
PE
3682 if (*format == '%')
3683 {
3684 /* General format specifications look like
a432bfe5 3685
37910ab2 3686 '%' [flags] [field-width] [precision] format
a432bfe5 3687
37910ab2 3688 where
a432bfe5 3689
37910ab2
PE
3690 flags ::= [-+0# ]+
3691 field-width ::= [0-9]+
3692 precision ::= '.' [0-9]*
a432bfe5 3693
37910ab2
PE
3694 If a field-width is specified, it specifies to which width
3695 the output should be padded with blanks, if the output
3696 string is shorter than field-width.
a432bfe5 3697
37910ab2
PE
3698 If precision is specified, it specifies the number of
3699 digits to print after the '.' for floats, or the max.
3700 number of chars to print from a string. */
a432bfe5 3701
37910ab2
PE
3702 int minus_flag = 0;
3703 int plus_flag = 0;
3704 int space_flag = 0;
3705 int sharp_flag = 0;
3706 int zero_flag = 0;
3707 EMACS_INT field_width;
3708 int precision_given;
3709 uintmax_t precision = UINTMAX_MAX;
3710 char *num_end;
3711 char conversion;
a432bfe5 3712
37910ab2
PE
3713 while (1)
3714 {
3715 switch (*++format)
3716 {
3717 case '-': minus_flag = 1; continue;
3718 case '+': plus_flag = 1; continue;
3719 case ' ': space_flag = 1; continue;
3720 case '#': sharp_flag = 1; continue;
3721 case '0': zero_flag = 1; continue;
3722 }
3723 break;
3724 }
35692fe0 3725
37910ab2
PE
3726 /* Ignore flags when sprintf ignores them. */
3727 space_flag &= ~ plus_flag;
3728 zero_flag &= ~ minus_flag;
1f24f4fd 3729
35692fe0 3730 {
37910ab2
PE
3731 uintmax_t w = strtoumax (format, &num_end, 10);
3732 if (max_bufsize <= w)
3733 string_overflow ();
3734 field_width = w;
35692fe0 3735 }
37910ab2
PE
3736 precision_given = *num_end == '.';
3737 if (precision_given)
3738 precision = strtoumax (num_end + 1, &num_end, 10);
3739 format = num_end;
3740
3741 if (format == end)
3742 error ("Format string ends in middle of format specifier");
3743
3744 memset (&discarded[format0 - format_start], 1, format - format0);
3745 conversion = *format;
3746 if (conversion == '%')
3747 goto copy_char;
d147ee84 3748 discarded[format - format_start] = 1;
1f24f4fd 3749 format++;
fb893977 3750
37910ab2
PE
3751 ++n;
3752 if (! (n < nargs))
3753 error ("Not enough arguments for format string");
3754
3755 /* For 'S', prin1 the argument, and then treat like 's'.
3756 For 's', princ any argument that is not a string or
3757 symbol. But don't do this conversion twice, which might
3758 happen after retrying. */
3759 if ((conversion == 'S'
3760 || (conversion == 's'
3761 && ! STRINGP (args[n]) && ! SYMBOLP (args[n]))))
f555f8cf 3762 {
37910ab2 3763 if (! info[n].converted_to_string)
f555f8cf 3764 {
37910ab2
PE
3765 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
3766 args[n] = Fprin1_to_string (args[n], noescape);
3767 info[n].converted_to_string = 1;
3768 if (STRING_MULTIBYTE (args[n]) && ! multibyte)
3769 {
3770 multibyte = 1;
3771 goto retry;
3772 }
f555f8cf 3773 }
37910ab2 3774 conversion = 's';
f555f8cf 3775 }
37910ab2
PE
3776 else if (conversion == 'c')
3777 {
3778 if (FLOATP (args[n]))
3779 {
3780 double d = XFLOAT_DATA (args[n]);
3781 args[n] = make_number (FIXNUM_OVERFLOW_P (d) ? -1 : d);
3782 }
f555f8cf 3783
37910ab2
PE
3784 if (INTEGERP (args[n]) && ! ASCII_CHAR_P (XINT (args[n])))
3785 {
3786 if (!multibyte)
3787 {
3788 multibyte = 1;
3789 goto retry;
3790 }
3791 args[n] = Fchar_to_string (args[n]);
3792 info[n].converted_to_string = 1;
3793 }
f555f8cf 3794
37910ab2
PE
3795 if (info[n].converted_to_string)
3796 conversion = 's';
3797 zero_flag = 0;
d147ee84 3798 }
35692fe0 3799
37910ab2 3800 if (SYMBOLP (args[n]))
1f24f4fd 3801 {
37910ab2
PE
3802 args[n] = SYMBOL_NAME (args[n]);
3803 if (STRING_MULTIBYTE (args[n]) && ! multibyte)
3804 {
3805 multibyte = 1;
3806 goto retry;
3807 }
1f24f4fd
RS
3808 }
3809
37910ab2 3810 if (conversion == 's')
1f24f4fd 3811 {
ac42d7b9
KG
3812 /* handle case (precision[n] >= 0) */
3813
37910ab2 3814 EMACS_INT width, padding, nbytes;
579c18d0 3815 EMACS_INT nchars_string;
ac42d7b9 3816
37910ab2
PE
3817 EMACS_INT prec = -1;
3818 if (precision_given && precision <= TYPE_MAXIMUM (EMACS_INT))
3819 prec = precision;
3820
ac42d7b9
KG
3821 /* lisp_string_width ignores a precision of 0, but GNU
3822 libc functions print 0 characters when the precision
3823 is 0. Imitate libc behavior here. Changing
3824 lisp_string_width is the right thing, and will be
3825 done, but meanwhile we work with it. */
3826
37910ab2 3827 if (prec == 0)
ac42d7b9 3828 width = nchars_string = nbytes = 0;
ac42d7b9 3829 else
37910ab2
PE
3830 {
3831 EMACS_INT nch, nby;
3832 width = lisp_string_width (args[n], prec, &nch, &nby);
3833 if (prec < 0)
3834 {
3835 nchars_string = SCHARS (args[n]);
3836 nbytes = SBYTES (args[n]);
3837 }
3838 else
3839 {
3840 nchars_string = nch;
3841 nbytes = nby;
3842 }
ac42d7b9 3843 }
25c9e7fb 3844
37910ab2
PE
3845 convbytes = nbytes;
3846 if (convbytes && multibyte && ! STRING_MULTIBYTE (args[n]))
3847 convbytes = count_size_as_multibyte (SDATA (args[n]), nbytes);
1f24f4fd 3848
37910ab2 3849 padding = width < field_width ? field_width - width : 0;
ac42d7b9 3850
37910ab2
PE
3851 if (max_bufsize - padding <= convbytes)
3852 string_overflow ();
3853 convbytes += padding;
3854 if (convbytes <= buf + bufsize - p)
3855 {
3856 if (! minus_flag)
3857 {
3858 memset (p, ' ', padding);
3859 p += padding;
3860 nchars += padding;
3861 }
ac42d7b9 3862
37910ab2
PE
3863 if (p > buf
3864 && multibyte
3865 && !ASCII_BYTE_P (*((unsigned char *) p - 1))
3866 && STRING_MULTIBYTE (args[n])
3867 && !CHAR_HEAD_P (SREF (args[n], 0)))
3868 maybe_combine_byte = 1;
1f24f4fd 3869
37910ab2
PE
3870 p += copy_text (SDATA (args[n]), (unsigned char *) p,
3871 nbytes,
3872 STRING_MULTIBYTE (args[n]), multibyte);
8f2c9ed8 3873
37910ab2
PE
3874 info[n].start = nchars;
3875 nchars += nchars_string;
3876 info[n].end = nchars;
3877
3878 if (minus_flag)
3879 {
3880 memset (p, ' ', padding);
3881 p += padding;
3882 nchars += padding;
3883 }
5e6d5493 3884
37910ab2
PE
3885 /* If this argument has text properties, record where
3886 in the result string it appears. */
3887 if (STRING_INTERVALS (args[n]))
3888 info[n].intervals = arg_intervals = 1;
3889
3890 continue;
3891 }
1f24f4fd 3892 }
37910ab2
PE
3893 else if (! (conversion == 'c' || conversion == 'd'
3894 || conversion == 'e' || conversion == 'f'
3895 || conversion == 'g' || conversion == 'i'
3896 || conversion == 'o' || conversion == 'x'
3897 || conversion == 'X'))
3898 error ("Invalid format operation %%%c",
3899 STRING_CHAR ((unsigned char *) format - 1));
3900 else if (! (INTEGERP (args[n]) || FLOATP (args[n])))
3901 error ("Format specifier doesn't match argument type");
3902 else
1f24f4fd 3903 {
37910ab2
PE
3904 enum
3905 {
3906 /* Maximum precision for a %f conversion such that the
3907 trailing output digit might be nonzero. Any precisions
3908 larger than this will not yield useful information. */
3909 USEFUL_PRECISION_MAX =
3910 ((1 - DBL_MIN_EXP)
3911 * (FLT_RADIX == 2 || FLT_RADIX == 10 ? 1
3912 : FLT_RADIX == 16 ? 4
3913 : -1)),
3914
3915 /* Maximum number of bytes generated by any format, if
3916 precision is no more than DBL_USEFUL_PRECISION_MAX.
3917 On all practical hosts, %f is the worst case. */
3918 SPRINTF_BUFSIZE =
3919 sizeof "-." + (DBL_MAX_10_EXP + 1) + USEFUL_PRECISION_MAX
3920 };
3921 verify (0 < USEFUL_PRECISION_MAX);
3922
3923 int prec;
3924 EMACS_INT padding, sprintf_bytes;
3925 uintmax_t excess_precision, numwidth;
3926 uintmax_t leading_zeros = 0, trailing_zeros = 0;
3927
3928 char sprintf_buf[SPRINTF_BUFSIZE];
3929
3930 /* Copy of conversion specification, modified somewhat.
3931 At most three flags F can be specified at once. */
3932 char convspec[sizeof "%FFF.*d" + pWIDElen];
3933
3934 /* Avoid undefined behavior in underlying sprintf. */
3935 if (conversion == 'd' || conversion == 'i')
3936 sharp_flag = 0;
3937
3938 /* Create the copy of the conversion specification, with
3939 any width and precision removed, with ".*" inserted,
3940 and with pWIDE inserted for integer formats. */
3941 {
3942 char *f = convspec;
3943 *f++ = '%';
3944 *f = '-'; f += minus_flag;
3945 *f = '+'; f += plus_flag;
3946 *f = ' '; f += space_flag;
3947 *f = '#'; f += sharp_flag;
3948 *f = '0'; f += zero_flag;
3949 *f++ = '.';
3950 *f++ = '*';
3951 if (conversion == 'd' || conversion == 'i'
3952 || conversion == 'o' || conversion == 'x'
3953 || conversion == 'X')
3954 {
3955 memcpy (f, pWIDE, pWIDElen);
3956 f += pWIDElen;
3957 zero_flag &= ~ precision_given;
3958 }
3959 *f++ = conversion;
3960 *f = '\0';
3961 }
1f24f4fd 3962
37910ab2
PE
3963 prec = -1;
3964 if (precision_given)
3965 prec = min (precision, USEFUL_PRECISION_MAX);
3966
3967 /* Use sprintf to format this number into sprintf_buf. Omit
3968 padding and excess precision, though, because sprintf limits
3969 output length to INT_MAX.
3970
3971 There are four types of conversion: double, unsigned
3972 char (passed as int), wide signed int, and wide
3973 unsigned int. Treat them separately because the
3974 sprintf ABI is sensitive to which type is passed. Be
3975 careful about integer overflow, NaNs, infinities, and
3976 conversions; for example, the min and max macros are
3977 not suitable here. */
3978 if (conversion == 'e' || conversion == 'f' || conversion == 'g')
3979 {
3980 double x = (INTEGERP (args[n])
3981 ? XINT (args[n])
3982 : XFLOAT_DATA (args[n]));
3983 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
3984 }
3985 else if (conversion == 'c')
3986 {
3987 /* Don't use sprintf here, as it might mishandle prec. */
3988 sprintf_buf[0] = XINT (args[n]);
3989 sprintf_bytes = prec != 0;
3990 }
3991 else if (conversion == 'd')
3992 {
3993 /* For float, maybe we should use "%1.0f"
3994 instead so it also works for values outside
3995 the integer range. */
3996 signed_wide x;
3997 if (INTEGERP (args[n]))
3998 x = XINT (args[n]);
3999 else
4000 {
4001 double d = XFLOAT_DATA (args[n]);
4002 if (d < 0)
4003 {
4004 x = TYPE_MINIMUM (signed_wide);
4005 if (x < d)
4006 x = d;
4007 }
4008 else
4009 {
4010 x = TYPE_MAXIMUM (signed_wide);
4011 if (d < x)
4012 x = d;
4013 }
4014 }
4015 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
4016 }
0f860bd7 4017 else
de92d4d4 4018 {
37910ab2
PE
4019 /* Don't sign-extend for octal or hex printing. */
4020 unsigned_wide x;
4021 if (INTEGERP (args[n]))
4022 x = XUINT (args[n]);
4023 else
0f860bd7 4024 {
37910ab2
PE
4025 double d = XFLOAT_DATA (args[n]);
4026 if (d < 0)
4027 x = 0;
4028 else
4029 {
4030 x = TYPE_MAXIMUM (unsigned_wide);
4031 if (d < x)
4032 x = d;
4033 }
0f860bd7 4034 }
37910ab2
PE
4035 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
4036 }
0f860bd7 4037
37910ab2
PE
4038 /* Now the length of the formatted item is known, except it omits
4039 padding and excess precision. Deal with excess precision
4040 first. This happens only when the format specifies
4041 ridiculously large precision. */
4042 excess_precision = precision - prec;
4043 if (excess_precision)
4044 {
4045 if (conversion == 'e' || conversion == 'f'
4046 || conversion == 'g')
ff6e6ac8 4047 {
37910ab2
PE
4048 if ((conversion == 'g' && ! sharp_flag)
4049 || ! ('0' <= sprintf_buf[sprintf_bytes - 1]
4050 && sprintf_buf[sprintf_bytes - 1] <= '9'))
4051 excess_precision = 0;
ff6e6ac8 4052 else
37910ab2
PE
4053 {
4054 if (conversion == 'g')
4055 {
4056 char *dot = strchr (sprintf_buf, '.');
4057 if (!dot)
4058 excess_precision = 0;
4059 }
4060 }
4061 trailing_zeros = excess_precision;
ff6e6ac8 4062 }
de92d4d4 4063 else
37910ab2 4064 leading_zeros = excess_precision;
de92d4d4 4065 }
1f24f4fd 4066
37910ab2
PE
4067 /* Compute the total bytes needed for this item, including
4068 excess precision and padding. */
4069 numwidth = sprintf_bytes + excess_precision;
4070 padding = numwidth < field_width ? field_width - numwidth : 0;
4071 if (max_bufsize - sprintf_bytes <= excess_precision
4072 || max_bufsize - padding <= numwidth)
4073 string_overflow ();
4074 convbytes = numwidth + padding;
4075
4076 if (convbytes <= buf + bufsize - p)
4077 {
4078 /* Copy the formatted item from sprintf_buf into buf,
4079 inserting padding and excess-precision zeros. */
4080
4081 char *src = sprintf_buf;
4082 char src0 = src[0];
4083 int exponent_bytes = 0;
4084 int signedp = src0 == '-' || src0 == '+' || src0 == ' ';
4085 int significand_bytes;
172418ad
AS
4086 if (zero_flag
4087 && ((src[signedp] >= '0' && src[signedp] <= '9')
4088 || (src[signedp] >= 'a' && src[signedp] <= 'f')
4089 || (src[signedp] >= 'A' && src[signedp] <= 'F')))
37910ab2
PE
4090 {
4091 leading_zeros += padding;
4092 padding = 0;
4093 }
4094
4095 if (excess_precision
4096 && (conversion == 'e' || conversion == 'g'))
4097 {
4098 char *e = strchr (src, 'e');
4099 if (e)
4100 exponent_bytes = src + sprintf_bytes - e;
4101 }
4102
4103 if (! minus_flag)
4104 {
4105 memset (p, ' ', padding);
4106 p += padding;
4107 nchars += padding;
4108 }
4109
4110 *p = src0;
4111 src += signedp;
4112 p += signedp;
4113 memset (p, '0', leading_zeros);
4114 p += leading_zeros;
4115 significand_bytes = sprintf_bytes - signedp - exponent_bytes;
4116 memcpy (p, src, significand_bytes);
4117 p += significand_bytes;
4118 src += significand_bytes;
4119 memset (p, '0', trailing_zeros);
4120 p += trailing_zeros;
4121 memcpy (p, src, exponent_bytes);
4122 p += exponent_bytes;
4123
4124 info[n].start = nchars;
4125 nchars += leading_zeros + sprintf_bytes + trailing_zeros;
4126 info[n].end = nchars;
4127
4128 if (minus_flag)
4129 {
4130 memset (p, ' ', padding);
4131 p += padding;
4132 nchars += padding;
4133 }
4134
4135 continue;
4136 }
4137 }
4138 }
4139 else
4140 copy_char:
4141 {
4142 /* Copy a single character from format to buf. */
4143
4144 char *src = format;
4145 unsigned char str[MAX_MULTIBYTE_LENGTH];
4146
4147 if (multibyte_format)
4148 {
4149 /* Copy a whole multibyte character. */
8f2917e4 4150 if (p > buf
25aa5d64 4151 && !ASCII_BYTE_P (*((unsigned char *) p - 1))
37910ab2 4152 && !CHAR_HEAD_P (*format))
8f2917e4 4153 maybe_combine_byte = 1;
37910ab2
PE
4154
4155 do
4156 format++;
4157 while (! CHAR_HEAD_P (*format));
4158
4159 convbytes = format - format0;
4160 memset (&discarded[format0 + 1 - format_start], 2, convbytes - 1);
4161 }
4162 else
4163 {
4164 unsigned char uc = *format++;
4165 if (! multibyte || ASCII_BYTE_P (uc))
4166 convbytes = 1;
9a599130 4167 else
37910ab2
PE
4168 {
4169 int c = BYTE8_TO_CHAR (uc);
4170 convbytes = CHAR_STRING (c, str);
4171 src = (char *) str;
4172 }
1f24f4fd 4173 }
d147ee84 4174
37910ab2 4175 if (convbytes <= buf + bufsize - p)
d147ee84 4176 {
37910ab2
PE
4177 memcpy (p, src, convbytes);
4178 p += convbytes;
4179 nchars++;
4180 continue;
d147ee84 4181 }
7df74da6 4182 }
1f24f4fd 4183
37910ab2
PE
4184 /* There wasn't enough room to store this conversion or single
4185 character. CONVBYTES says how much room is needed. Allocate
4186 enough room (and then some) and do it again. */
4187 {
4188 EMACS_INT used = p - buf;
4189
4190 if (max_bufsize - used < convbytes)
4191 string_overflow ();
4192 bufsize = used + convbytes;
4193 bufsize = bufsize < max_bufsize / 2 ? bufsize * 2 : max_bufsize;
4194
4195 if (buf == initial_buffer)
4196 {
4197 buf = xmalloc (bufsize);
4198 sa_must_free = 1;
4199 buf_save_value = make_save_value (buf, 0);
4200 record_unwind_protect (safe_alloca_unwind, buf_save_value);
4201 memcpy (buf, initial_buffer, used);
4202 }
4203 else
4204 XSAVE_VALUE (buf_save_value)->pointer = buf = xrealloc (buf, bufsize);
4205
4206 p = buf + used;
4207 }
4208
4209 format = format0;
4210 n = n0;
1f24f4fd
RS
4211 }
4212
37910ab2 4213 if (bufsize < p - buf)
a432bfe5
GM
4214 abort ();
4215
8f2917e4 4216 if (maybe_combine_byte)
e7f8264d 4217 nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf);
5f75e666 4218 val = make_specified_string (buf, nchars, p - buf, multibyte);
8d6179dc 4219
1f24f4fd 4220 /* If we allocated BUF with malloc, free it too. */
e65837df 4221 SAFE_FREE ();
35692fe0 4222
5e6d5493
GM
4223 /* If the format string has text properties, or any of the string
4224 arguments has text properties, set up text properties of the
4225 result string. */
34a7a267 4226
d147ee84 4227 if (STRING_INTERVALS (args[0]) || arg_intervals)
5e6d5493
GM
4228 {
4229 Lisp_Object len, new_len, props;
4230 struct gcpro gcpro1;
34a7a267 4231
5e6d5493 4232 /* Add text properties from the format string. */
d5db4077 4233 len = make_number (SCHARS (args[0]));
5e6d5493
GM
4234 props = text_property_list (args[0], make_number (0), len, Qnil);
4235 GCPRO1 (props);
34a7a267 4236
5e6d5493
GM
4237 if (CONSP (props))
4238 {
29cdc13e 4239 EMACS_INT bytepos = 0, position = 0, translated = 0;
37910ab2 4240 EMACS_INT argn = 1;
d147ee84
RS
4241 Lisp_Object list;
4242
4243 /* Adjust the bounds of each text property
4244 to the proper start and end in the output string. */
d147ee84 4245
15fad037
KS
4246 /* Put the positions in PROPS in increasing order, so that
4247 we can do (effectively) one scan through the position
4248 space of the format string. */
4249 props = Fnreverse (props);
4250
4251 /* BYTEPOS is the byte position in the format string,
d147ee84
RS
4252 POSITION is the untranslated char position in it,
4253 TRANSLATED is the translated char position in BUF,
4254 and ARGN is the number of the next arg we will come to. */
4255 for (list = props; CONSP (list); list = XCDR (list))
4256 {
f3ce1df8 4257 Lisp_Object item;
29cdc13e 4258 EMACS_INT pos;
d147ee84
RS
4259
4260 item = XCAR (list);
4261
4262 /* First adjust the property start position. */
4263 pos = XINT (XCAR (item));
4264
4265 /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN
4266 up to this position. */
4267 for (; position < pos; bytepos++)
4268 {
4269 if (! discarded[bytepos])
4270 position++, translated++;
4271 else if (discarded[bytepos] == 1)
4272 {
4273 position++;
4274 if (translated == info[argn].start)
4275 {
4276 translated += info[argn].end - info[argn].start;
4277 argn++;
4278 }
4279 }
4280 }
4281
4282 XSETCAR (item, make_number (translated));
4283
4284 /* Likewise adjust the property end position. */
4285 pos = XINT (XCAR (XCDR (item)));
4286
d40ec4a0 4287 for (; position < pos; bytepos++)
d147ee84
RS
4288 {
4289 if (! discarded[bytepos])
4290 position++, translated++;
4291 else if (discarded[bytepos] == 1)
4292 {
4293 position++;
4294 if (translated == info[argn].start)
4295 {
4296 translated += info[argn].end - info[argn].start;
4297 argn++;
4298 }
4299 }
4300 }
4301
4302 XSETCAR (XCDR (item), make_number (translated));
4303 }
4304
5e6d5493
GM
4305 add_text_properties_from_list (val, props, make_number (0));
4306 }
4307
4308 /* Add text properties from arguments. */
d147ee84 4309 if (arg_intervals)
5e6d5493 4310 for (n = 1; n < nargs; ++n)
d147ee84 4311 if (info[n].intervals)
5e6d5493 4312 {
d5db4077 4313 len = make_number (SCHARS (args[n]));
5e6d5493
GM
4314 new_len = make_number (info[n].end - info[n].start);
4315 props = text_property_list (args[n], make_number (0), len, Qnil);
e398c61c
CY
4316 props = extend_property_ranges (props, new_len);
4317 /* If successive arguments have properties, be sure that
be17069b
KH
4318 the value of `composition' property be the copy. */
4319 if (n > 1 && info[n - 1].end)
4320 make_composition_value_copy (props);
5e6d5493
GM
4321 add_text_properties_from_list (val, props,
4322 make_number (info[n].start));
4323 }
4324
4325 UNGCPRO;
4326 }
4327
8d6179dc 4328 return val;
35692fe0
JB
4329}
4330
35692fe0 4331Lisp_Object
a8fe7202 4332format2 (const char *string1, Lisp_Object arg0, Lisp_Object arg1)
d40dc1d0
RS
4333{
4334 Lisp_Object args[3];
d40dc1d0
RS
4335 args[0] = build_string (string1);
4336 args[1] = arg0;
4337 args[2] = arg1;
4338 return Fformat (3, args);
35692fe0
JB
4339}
4340\f
4341DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
7ee72033 4342 doc: /* Return t if two characters match, optionally ignoring case.
a1f17501 4343Both arguments must be characters (i.e. integers).
7ee72033 4344Case is ignored if `case-fold-search' is non-nil in the current buffer. */)
5842a27b 4345 (register Lisp_Object c1, Lisp_Object c2)
35692fe0 4346{
1b5d98bb 4347 int i1, i2;
253c3c82 4348 /* Check they're chars, not just integers, otherwise we could get array
5da9919f 4349 bounds violations in downcase. */
253c3c82
SM
4350 CHECK_CHARACTER (c1);
4351 CHECK_CHARACTER (c2);
35692fe0 4352
1b5d98bb 4353 if (XINT (c1) == XINT (c2))
35692fe0 4354 return Qt;
4b4deea2 4355 if (NILP (BVAR (current_buffer, case_fold_search)))
1b5d98bb
RS
4356 return Qnil;
4357
e5112ecb 4358 i1 = XFASTINT (c1);
4b4deea2 4359 if (NILP (BVAR (current_buffer, enable_multibyte_characters))
e5112ecb
KH
4360 && ! ASCII_CHAR_P (i1))
4361 {
4362 MAKE_CHAR_MULTIBYTE (i1);
4363 }
4364 i2 = XFASTINT (c2);
4b4deea2 4365 if (NILP (BVAR (current_buffer, enable_multibyte_characters))
e5112ecb
KH
4366 && ! ASCII_CHAR_P (i2))
4367 {
4368 MAKE_CHAR_MULTIBYTE (i2);
4369 }
0da09c43 4370 return (downcase (i1) == downcase (i2) ? Qt : Qnil);
35692fe0 4371}
b229b8d1
RS
4372\f
4373/* Transpose the markers in two regions of the current buffer, and
4374 adjust the ones between them if necessary (i.e.: if the regions
4375 differ in size).
4376
ec1c14f6
RS
4377 START1, END1 are the character positions of the first region.
4378 START1_BYTE, END1_BYTE are the byte positions.
4379 START2, END2 are the character positions of the second region.
4380 START2_BYTE, END2_BYTE are the byte positions.
4381
b229b8d1
RS
4382 Traverses the entire marker list of the buffer to do so, adding an
4383 appropriate amount to some, subtracting from some, and leaving the
4384 rest untouched. Most of this is copied from adjust_markers in insdel.c.
34a7a267 4385
ec1c14f6 4386 It's the caller's job to ensure that START1 <= END1 <= START2 <= END2. */
b229b8d1 4387
acb7cc89 4388static void
29cdc13e
EZ
4389transpose_markers (EMACS_INT start1, EMACS_INT end1,
4390 EMACS_INT start2, EMACS_INT end2,
4391 EMACS_INT start1_byte, EMACS_INT end1_byte,
4392 EMACS_INT start2_byte, EMACS_INT end2_byte)
b229b8d1 4393{
29cdc13e 4394 register EMACS_INT amt1, amt1_byte, amt2, amt2_byte, diff, diff_byte, mpos;
12038f9f 4395 register struct Lisp_Marker *marker;
b229b8d1 4396
03240d11 4397 /* Update point as if it were a marker. */
8de1d5f0
KH
4398 if (PT < start1)
4399 ;
4400 else if (PT < end1)
ec1c14f6
RS
4401 TEMP_SET_PT_BOTH (PT + (end2 - end1),
4402 PT_BYTE + (end2_byte - end1_byte));
8de1d5f0 4403 else if (PT < start2)
ec1c14f6
RS
4404 TEMP_SET_PT_BOTH (PT + (end2 - start2) - (end1 - start1),
4405 (PT_BYTE + (end2_byte - start2_byte)
4406 - (end1_byte - start1_byte)));
8de1d5f0 4407 else if (PT < end2)
ec1c14f6
RS
4408 TEMP_SET_PT_BOTH (PT - (start2 - start1),
4409 PT_BYTE - (start2_byte - start1_byte));
8de1d5f0 4410
03240d11
KH
4411 /* We used to adjust the endpoints here to account for the gap, but that
4412 isn't good enough. Even if we assume the caller has tried to move the
4413 gap out of our way, it might still be at start1 exactly, for example;
4414 and that places it `inside' the interval, for our purposes. The amount
4415 of adjustment is nontrivial if there's a `denormalized' marker whose
4416 position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
4417 the dirty work to Fmarker_position, below. */
b229b8d1
RS
4418
4419 /* The difference between the region's lengths */
4420 diff = (end2 - start2) - (end1 - start1);
ec1c14f6 4421 diff_byte = (end2_byte - start2_byte) - (end1_byte - start1_byte);
34a7a267 4422
b229b8d1 4423 /* For shifting each marker in a region by the length of the other
ec1c14f6 4424 region plus the distance between the regions. */
b229b8d1
RS
4425 amt1 = (end2 - start2) + (start2 - end1);
4426 amt2 = (end1 - start1) + (start2 - end1);
ec1c14f6
RS
4427 amt1_byte = (end2_byte - start2_byte) + (start2_byte - end1_byte);
4428 amt2_byte = (end1_byte - start1_byte) + (start2_byte - end1_byte);
b229b8d1 4429
12038f9f 4430 for (marker = BUF_MARKERS (current_buffer); marker; marker = marker->next)
b229b8d1 4431 {
12038f9f 4432 mpos = marker->bytepos;
ec1c14f6
RS
4433 if (mpos >= start1_byte && mpos < end2_byte)
4434 {
4435 if (mpos < end1_byte)
4436 mpos += amt1_byte;
4437 else if (mpos < start2_byte)
4438 mpos += diff_byte;
4439 else
4440 mpos -= amt2_byte;
12038f9f 4441 marker->bytepos = mpos;
ec1c14f6 4442 }
12038f9f 4443 mpos = marker->charpos;
03240d11
KH
4444 if (mpos >= start1 && mpos < end2)
4445 {
4446 if (mpos < end1)
4447 mpos += amt1;
4448 else if (mpos < start2)
4449 mpos += diff;
4450 else
4451 mpos -= amt2;
03240d11 4452 }
12038f9f 4453 marker->charpos = mpos;
b229b8d1
RS
4454 }
4455}
4456
4457DEFUN ("transpose-regions", Ftranspose_regions, Stranspose_regions, 4, 5, 0,
412f1fab 4458 doc: /* Transpose region STARTR1 to ENDR1 with STARTR2 to ENDR2.
27a69fd9 4459The regions should not be overlapping, because the size of the buffer is
a1f17501
PJ
4460never changed in a transposition.
4461
412f1fab 4462Optional fifth arg LEAVE-MARKERS, if non-nil, means don't update
a1f17501
PJ
4463any markers that happen to be located in the regions.
4464
7ee72033 4465Transposing beyond buffer boundaries is an error. */)
5842a27b 4466 (Lisp_Object startr1, Lisp_Object endr1, Lisp_Object startr2, Lisp_Object endr2, Lisp_Object leave_markers)
b229b8d1 4467{
d47ecf8b
SM
4468 register EMACS_INT start1, end1, start2, end2;
4469 EMACS_INT start1_byte, start2_byte, len1_byte, len2_byte;
4470 EMACS_INT gap, len1, len_mid, len2;
3c6bc7d0 4471 unsigned char *start1_addr, *start2_addr, *temp;
b229b8d1 4472
6cd0f478 4473 INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2, tmp_interval3;
916480c4
CY
4474 Lisp_Object buf;
4475
4476 XSETBUFFER (buf, current_buffer);
1e158d25 4477 cur_intv = BUF_INTERVALS (current_buffer);
b229b8d1
RS
4478
4479 validate_region (&startr1, &endr1);
4480 validate_region (&startr2, &endr2);
4481
4482 start1 = XFASTINT (startr1);
4483 end1 = XFASTINT (endr1);
4484 start2 = XFASTINT (startr2);
4485 end2 = XFASTINT (endr2);
4486 gap = GPT;
4487
4488 /* Swap the regions if they're reversed. */
4489 if (start2 < end1)
4490 {
29cdc13e 4491 register EMACS_INT glumph = start1;
b229b8d1
RS
4492 start1 = start2;
4493 start2 = glumph;
4494 glumph = end1;
4495 end1 = end2;
4496 end2 = glumph;
4497 }
4498
b229b8d1
RS
4499 len1 = end1 - start1;
4500 len2 = end2 - start2;
4501
4502 if (start2 < end1)
dc3620af 4503 error ("Transposed regions overlap");
0f4aebc0
LL
4504 /* Nothing to change for adjacent regions with one being empty */
4505 else if ((start1 == end1 || start2 == end2) && end1 == start2)
4506 return Qnil;
b229b8d1
RS
4507
4508 /* The possibilities are:
4509 1. Adjacent (contiguous) regions, or separate but equal regions
4510 (no, really equal, in this case!), or
4511 2. Separate regions of unequal size.
34a7a267 4512
b229b8d1
RS
4513 The worst case is usually No. 2. It means that (aside from
4514 potential need for getting the gap out of the way), there also
4515 needs to be a shifting of the text between the two regions. So
4516 if they are spread far apart, we are that much slower... sigh. */
4517
4518 /* It must be pointed out that the really studly thing to do would
4519 be not to move the gap at all, but to leave it in place and work
4520 around it if necessary. This would be extremely efficient,
4521 especially considering that people are likely to do
4522 transpositions near where they are working interactively, which
4523 is exactly where the gap would be found. However, such code
4524 would be much harder to write and to read. So, if you are
4525 reading this comment and are feeling squirrely, by all means have
4526 a go! I just didn't feel like doing it, so I will simply move
4527 the gap the minimum distance to get it out of the way, and then
4528 deal with an unbroken array. */
3c6bc7d0
RS
4529
4530 /* Make sure the gap won't interfere, by moving it out of the text
4531 we will operate on. */
4532 if (start1 < gap && gap < end2)
4533 {
4534 if (gap - start1 < end2 - gap)
4535 move_gap (start1);
4536 else
4537 move_gap (end2);
4538 }
ec1c14f6
RS
4539
4540 start1_byte = CHAR_TO_BYTE (start1);
4541 start2_byte = CHAR_TO_BYTE (start2);
4542 len1_byte = CHAR_TO_BYTE (end1) - start1_byte;
4543 len2_byte = CHAR_TO_BYTE (end2) - start2_byte;
dc3620af 4544
9a599130 4545#ifdef BYTE_COMBINING_DEBUG
dc3620af
RS
4546 if (end1 == start2)
4547 {
9a599130
KH
4548 if (count_combining_before (BYTE_POS_ADDR (start2_byte),
4549 len2_byte, start1, start1_byte)
4550 || count_combining_before (BYTE_POS_ADDR (start1_byte),
4551 len1_byte, end2, start2_byte + len2_byte)
4552 || count_combining_after (BYTE_POS_ADDR (start1_byte),
4553 len1_byte, end2, start2_byte + len2_byte))
4554 abort ();
dc3620af
RS
4555 }
4556 else
4557 {
9a599130
KH
4558 if (count_combining_before (BYTE_POS_ADDR (start2_byte),
4559 len2_byte, start1, start1_byte)
4560 || count_combining_before (BYTE_POS_ADDR (start1_byte),
4561 len1_byte, start2, start2_byte)
4562 || count_combining_after (BYTE_POS_ADDR (start2_byte),
4563 len2_byte, end1, start1_byte + len1_byte)
4564 || count_combining_after (BYTE_POS_ADDR (start1_byte),
4565 len1_byte, end2, start2_byte + len2_byte))
4566 abort ();
dc3620af 4567 }
9a599130 4568#endif
dc3620af 4569
b229b8d1
RS
4570 /* Hmmm... how about checking to see if the gap is large
4571 enough to use as the temporary storage? That would avoid an
4572 allocation... interesting. Later, don't fool with it now. */
4573
4574 /* Working without memmove, for portability (sigh), so must be
4575 careful of overlapping subsections of the array... */
4576
4577 if (end1 == start2) /* adjacent regions */
4578 {
3e145152 4579 modify_region (current_buffer, start1, end2, 0);
b229b8d1
RS
4580 record_change (start1, len1 + len2);
4581
b229b8d1
RS
4582 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4583 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
916480c4
CY
4584 /* Don't use Fset_text_properties: that can cause GC, which can
4585 clobber objects stored in the tmp_intervals. */
6cd0f478
CY
4586 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4587 if (!NULL_INTERVAL_P (tmp_interval3))
4588 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1
RS
4589
4590 /* First region smaller than second. */
ec1c14f6 4591 if (len1_byte < len2_byte)
b229b8d1 4592 {
7e2c051b
KS
4593 USE_SAFE_ALLOCA;
4594
4595 SAFE_ALLOCA (temp, unsigned char *, len2_byte);
03240d11
KH
4596
4597 /* Don't precompute these addresses. We have to compute them
4598 at the last minute, because the relocating allocator might
4599 have moved the buffer around during the xmalloc. */
23017390
KH
4600 start1_addr = BYTE_POS_ADDR (start1_byte);
4601 start2_addr = BYTE_POS_ADDR (start2_byte);
03240d11 4602
72af86bd
AS
4603 memcpy (temp, start2_addr, len2_byte);
4604 memcpy (start1_addr + len2_byte, start1_addr, len1_byte);
4605 memcpy (start1_addr, temp, len2_byte);
e65837df 4606 SAFE_FREE ();
b229b8d1
RS
4607 }
4608 else
4609 /* First region not smaller than second. */
4610 {
7e2c051b
KS
4611 USE_SAFE_ALLOCA;
4612
4613 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4614 start1_addr = BYTE_POS_ADDR (start1_byte);
4615 start2_addr = BYTE_POS_ADDR (start2_byte);
72af86bd
AS
4616 memcpy (temp, start1_addr, len1_byte);
4617 memcpy (start1_addr, start2_addr, len2_byte);
4618 memcpy (start1_addr + len2_byte, temp, len1_byte);
e65837df 4619 SAFE_FREE ();
b229b8d1 4620 }
b229b8d1
RS
4621 graft_intervals_into_buffer (tmp_interval1, start1 + len2,
4622 len1, current_buffer, 0);
4623 graft_intervals_into_buffer (tmp_interval2, start1,
4624 len2, current_buffer, 0);
d5c2c403
KH
4625 update_compositions (start1, start1 + len2, CHECK_BORDER);
4626 update_compositions (start1 + len2, end2, CHECK_TAIL);
b229b8d1
RS
4627 }
4628 /* Non-adjacent regions, because end1 != start2, bleagh... */
4629 else
4630 {
ec1c14f6
RS
4631 len_mid = start2_byte - (start1_byte + len1_byte);
4632
4633 if (len1_byte == len2_byte)
b229b8d1
RS
4634 /* Regions are same size, though, how nice. */
4635 {
7e2c051b
KS
4636 USE_SAFE_ALLOCA;
4637
3e145152
CY
4638 modify_region (current_buffer, start1, end1, 0);
4639 modify_region (current_buffer, start2, end2, 0);
b229b8d1
RS
4640 record_change (start1, len1);
4641 record_change (start2, len2);
b229b8d1
RS
4642 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4643 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4644
4645 tmp_interval3 = validate_interval_range (buf, &startr1, &endr1, 0);
4646 if (!NULL_INTERVAL_P (tmp_interval3))
4647 set_text_properties_1 (startr1, endr1, Qnil, buf, tmp_interval3);
4648
4649 tmp_interval3 = validate_interval_range (buf, &startr2, &endr2, 0);
4650 if (!NULL_INTERVAL_P (tmp_interval3))
4651 set_text_properties_1 (startr2, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4652
7e2c051b 4653 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4654 start1_addr = BYTE_POS_ADDR (start1_byte);
4655 start2_addr = BYTE_POS_ADDR (start2_byte);
72af86bd
AS
4656 memcpy (temp, start1_addr, len1_byte);
4657 memcpy (start1_addr, start2_addr, len2_byte);
4658 memcpy (start2_addr, temp, len1_byte);
e65837df 4659 SAFE_FREE ();
7e2c051b 4660
b229b8d1
RS
4661 graft_intervals_into_buffer (tmp_interval1, start2,
4662 len1, current_buffer, 0);
4663 graft_intervals_into_buffer (tmp_interval2, start1,
4664 len2, current_buffer, 0);
b229b8d1
RS
4665 }
4666
ec1c14f6 4667 else if (len1_byte < len2_byte) /* Second region larger than first */
b229b8d1
RS
4668 /* Non-adjacent & unequal size, area between must also be shifted. */
4669 {
7e2c051b
KS
4670 USE_SAFE_ALLOCA;
4671
3e145152 4672 modify_region (current_buffer, start1, end2, 0);
b229b8d1 4673 record_change (start1, (end2 - start1));
b229b8d1
RS
4674 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4675 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
4676 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4677
4678 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4679 if (!NULL_INTERVAL_P (tmp_interval3))
4680 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4681
3c6bc7d0 4682 /* holds region 2 */
7e2c051b 4683 SAFE_ALLOCA (temp, unsigned char *, len2_byte);
23017390
KH
4684 start1_addr = BYTE_POS_ADDR (start1_byte);
4685 start2_addr = BYTE_POS_ADDR (start2_byte);
72af86bd
AS
4686 memcpy (temp, start2_addr, len2_byte);
4687 memcpy (start1_addr + len_mid + len2_byte, start1_addr, len1_byte);
4688 memmove (start1_addr + len2_byte, start1_addr + len1_byte, len_mid);
4689 memcpy (start1_addr, temp, len2_byte);
e65837df 4690 SAFE_FREE ();
7e2c051b 4691
b229b8d1
RS
4692 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
4693 len1, current_buffer, 0);
4694 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
4695 len_mid, current_buffer, 0);
4696 graft_intervals_into_buffer (tmp_interval2, start1,
4697 len2, current_buffer, 0);
b229b8d1
RS
4698 }
4699 else
4700 /* Second region smaller than first. */
4701 {
7e2c051b
KS
4702 USE_SAFE_ALLOCA;
4703
b229b8d1 4704 record_change (start1, (end2 - start1));
3e145152 4705 modify_region (current_buffer, start1, end2, 0);
b229b8d1 4706
b229b8d1
RS
4707 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4708 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
4709 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4710
4711 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4712 if (!NULL_INTERVAL_P (tmp_interval3))
4713 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4714
3c6bc7d0 4715 /* holds region 1 */
7e2c051b 4716 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4717 start1_addr = BYTE_POS_ADDR (start1_byte);
4718 start2_addr = BYTE_POS_ADDR (start2_byte);
72af86bd
AS
4719 memcpy (temp, start1_addr, len1_byte);
4720 memcpy (start1_addr, start2_addr, len2_byte);
4721 memcpy (start1_addr + len2_byte, start1_addr + len1_byte, len_mid);
4722 memcpy (start1_addr + len2_byte + len_mid, temp, len1_byte);
e65837df 4723 SAFE_FREE ();
7e2c051b 4724
b229b8d1
RS
4725 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
4726 len1, current_buffer, 0);
4727 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
4728 len_mid, current_buffer, 0);
4729 graft_intervals_into_buffer (tmp_interval2, start1,
4730 len2, current_buffer, 0);
b229b8d1 4731 }
d5c2c403
KH
4732
4733 update_compositions (start1, start1 + len2, CHECK_BORDER);
4734 update_compositions (end2 - len1, end2, CHECK_BORDER);
b229b8d1
RS
4735 }
4736
ec1c14f6
RS
4737 /* When doing multiple transpositions, it might be nice
4738 to optimize this. Perhaps the markers in any one buffer
4739 should be organized in some sorted data tree. */
b229b8d1 4740 if (NILP (leave_markers))
8de1d5f0 4741 {
ec1c14f6
RS
4742 transpose_markers (start1, end1, start2, end2,
4743 start1_byte, start1_byte + len1_byte,
4744 start2_byte, start2_byte + len2_byte);
6b61353c 4745 fix_start_end_in_overlays (start1, end2);
8de1d5f0 4746 }
b229b8d1 4747
c10b2810 4748 signal_after_change (start1, end2 - start1, end2 - start1);
b229b8d1
RS
4749 return Qnil;
4750}
35692fe0 4751
35692fe0
JB
4752\f
4753void
971de7fb 4754syms_of_editfns (void)
35692fe0 4755{
260e2e2a 4756 environbuf = 0;
a03fc5a6 4757 initial_tz = 0;
260e2e2a
KH
4758
4759 Qbuffer_access_fontify_functions
d67b4f80 4760 = intern_c_string ("buffer-access-fontify-functions");
260e2e2a
KH
4761 staticpro (&Qbuffer_access_fontify_functions);
4762
29208e82 4763 DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
7dcece14 4764 doc: /* Non-nil means text motion commands don't notice fields. */);
9a74e7e5
GM
4765 Vinhibit_field_text_motion = Qnil;
4766
260e2e2a 4767 DEFVAR_LISP ("buffer-access-fontify-functions",
29208e82 4768 Vbuffer_access_fontify_functions,
7ee72033 4769 doc: /* List of functions called by `buffer-substring' to fontify if necessary.
a1f17501
PJ
4770Each function is called with two arguments which specify the range
4771of the buffer being accessed. */);
260e2e2a
KH
4772 Vbuffer_access_fontify_functions = Qnil;
4773
af209db8
RS
4774 {
4775 Lisp_Object obuf;
af209db8
RS
4776 obuf = Fcurrent_buffer ();
4777 /* Do this here, because init_buffer_once is too early--it won't work. */
4778 Fset_buffer (Vprin1_to_string_buffer);
4779 /* Make sure buffer-access-fontify-functions is nil in this buffer. */
d67b4f80 4780 Fset (Fmake_local_variable (intern_c_string ("buffer-access-fontify-functions")),
af209db8
RS
4781 Qnil);
4782 Fset_buffer (obuf);
4783 }
4784
0b6fd023 4785 DEFVAR_LISP ("buffer-access-fontified-property",
29208e82 4786 Vbuffer_access_fontified_property,
7ee72033 4787 doc: /* Property which (if non-nil) indicates text has been fontified.
a1f17501
PJ
4788`buffer-substring' need not call the `buffer-access-fontify-functions'
4789functions if all the text being accessed has this property. */);
260e2e2a
KH
4790 Vbuffer_access_fontified_property = Qnil;
4791
29208e82 4792 DEFVAR_LISP ("system-name", Vsystem_name,
1a7e0117 4793 doc: /* The host name of the machine Emacs is running on. */);
34a7a267 4794
29208e82 4795 DEFVAR_LISP ("user-full-name", Vuser_full_name,
7ee72033 4796 doc: /* The full name of the user logged in. */);
f43754f6 4797
29208e82 4798 DEFVAR_LISP ("user-login-name", Vuser_login_name,
7ee72033 4799 doc: /* The user's name, taken from environment variables if possible. */);
f43754f6 4800
29208e82 4801 DEFVAR_LISP ("user-real-login-name", Vuser_real_login_name,
7ee72033 4802 doc: /* The user's name, based upon the real uid only. */);
35692fe0 4803
29208e82 4804 DEFVAR_LISP ("operating-system-release", Voperating_system_release,
3bb9abc8
ST
4805 doc: /* The release of the operating system Emacs is running on. */);
4806
0963334d 4807 defsubr (&Spropertize);
35692fe0
JB
4808 defsubr (&Schar_equal);
4809 defsubr (&Sgoto_char);
4810 defsubr (&Sstring_to_char);
4811 defsubr (&Schar_to_string);
c3bb441d 4812 defsubr (&Sbyte_to_string);
35692fe0 4813 defsubr (&Sbuffer_substring);
260e2e2a 4814 defsubr (&Sbuffer_substring_no_properties);
35692fe0
JB
4815 defsubr (&Sbuffer_string);
4816
4817 defsubr (&Spoint_marker);
4818 defsubr (&Smark_marker);
4819 defsubr (&Spoint);
4820 defsubr (&Sregion_beginning);
4821 defsubr (&Sregion_end);
7df74da6 4822
0daf6e8d 4823 staticpro (&Qfield);
d67b4f80 4824 Qfield = intern_c_string ("field");
ee547125 4825 staticpro (&Qboundary);
d67b4f80 4826 Qboundary = intern_c_string ("boundary");
0daf6e8d
GM
4827 defsubr (&Sfield_beginning);
4828 defsubr (&Sfield_end);
4829 defsubr (&Sfield_string);
4830 defsubr (&Sfield_string_no_properties);
8bf64fe8 4831 defsubr (&Sdelete_field);
0daf6e8d
GM
4832 defsubr (&Sconstrain_to_field);
4833
7df74da6
RS
4834 defsubr (&Sline_beginning_position);
4835 defsubr (&Sline_end_position);
4836
35692fe0
JB
4837/* defsubr (&Smark); */
4838/* defsubr (&Sset_mark); */
4839 defsubr (&Ssave_excursion);
4bc8c7d2 4840 defsubr (&Ssave_current_buffer);
35692fe0
JB
4841
4842 defsubr (&Sbufsize);
4843 defsubr (&Spoint_max);
4844 defsubr (&Spoint_min);
4845 defsubr (&Spoint_min_marker);
4846 defsubr (&Spoint_max_marker);
c86212b9
RS
4847 defsubr (&Sgap_position);
4848 defsubr (&Sgap_size);
7df74da6 4849 defsubr (&Sposition_bytes);
3ab0732d 4850 defsubr (&Sbyte_to_position);
c9ed721d 4851
35692fe0
JB
4852 defsubr (&Sbobp);
4853 defsubr (&Seobp);
4854 defsubr (&Sbolp);
4855 defsubr (&Seolp);
850a8179
JB
4856 defsubr (&Sfollowing_char);
4857 defsubr (&Sprevious_char);
35692fe0 4858 defsubr (&Schar_after);
fb8106e8 4859 defsubr (&Schar_before);
35692fe0
JB
4860 defsubr (&Sinsert);
4861 defsubr (&Sinsert_before_markers);
be91036a
RS
4862 defsubr (&Sinsert_and_inherit);
4863 defsubr (&Sinsert_and_inherit_before_markers);
35692fe0 4864 defsubr (&Sinsert_char);
48ef988f 4865 defsubr (&Sinsert_byte);
35692fe0
JB
4866
4867 defsubr (&Suser_login_name);
4868 defsubr (&Suser_real_login_name);
4869 defsubr (&Suser_uid);
4870 defsubr (&Suser_real_uid);
4871 defsubr (&Suser_full_name);
7fd233b3 4872 defsubr (&Semacs_pid);
d940e0e4 4873 defsubr (&Scurrent_time);
4211ee7d 4874 defsubr (&Sget_internal_run_time);
a82d387c 4875 defsubr (&Sformat_time_string);
34a7a267 4876 defsubr (&Sfloat_time);
4691c06d 4877 defsubr (&Sdecode_time);
cce7b8a0 4878 defsubr (&Sencode_time);
35692fe0 4879 defsubr (&Scurrent_time_string);
c2662aea 4880 defsubr (&Scurrent_time_zone);
143cb9a9 4881 defsubr (&Sset_time_zone_rule);
35692fe0 4882 defsubr (&Ssystem_name);
35692fe0 4883 defsubr (&Smessage);
cacc3e2c
RS
4884 defsubr (&Smessage_box);
4885 defsubr (&Smessage_or_box);
b14dda8a 4886 defsubr (&Scurrent_message);
35692fe0 4887 defsubr (&Sformat);
35692fe0
JB
4888
4889 defsubr (&Sinsert_buffer_substring);
e9cf2084 4890 defsubr (&Scompare_buffer_substrings);
35692fe0 4891 defsubr (&Ssubst_char_in_region);
8583605b 4892 defsubr (&Stranslate_region_internal);
35692fe0 4893 defsubr (&Sdelete_region);
7dae4502 4894 defsubr (&Sdelete_and_extract_region);
35692fe0
JB
4895 defsubr (&Swiden);
4896 defsubr (&Snarrow_to_region);
4897 defsubr (&Ssave_restriction);
b229b8d1 4898 defsubr (&Stranspose_regions);
35692fe0 4899}