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