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