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