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