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