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