Fix recently-introduced typos in Windows port.
[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
6195f384
DA
824/* Record buffer state before entering Fsave_excursion. */
825
35692fe0 826Lisp_Object
971de7fb 827save_excursion_save (void)
35692fe0 828{
6195f384
DA
829 Lisp_Object excursion;
830 struct buffer *b = current_buffer;
831 struct window *w = XWINDOW (selected_window);
832 struct Lisp_Excursion *ex = xmalloc (sizeof *ex);
833 struct Lisp_Marker *m = XMARKER (BVAR (b, mark));
834
835 ex->size = 0;
836 ex->buffer = b;
837 ex->window = w;
838 ex->visible = (XBUFFER (w->buffer) == b);
839 ex->active = !NILP (BVAR (b, mark_active));
840
841 /* We do not initialize type and gcmarkbit since this marker
842 is never referenced via Lisp_Object and invisible for GC. */
843 init_marker (&ex->point, b, PT, PT_BYTE, 0);
844
845 /* Likewise. Note that charpos and bytepos may be zero. */
846 init_marker (&ex->mark, m->buffer, m->charpos,
847 m->bytepos, m->insertion_type);
848
849 /* Make it a pseudovector and return excursion object. */
850 XSETTYPED_PVECTYPE (ex, size, PVEC_EXCURSION);
851 XSETEXCURSION (excursion, ex);
852 return excursion;
35692fe0
JB
853}
854
6195f384
DA
855/* Restore buffer state before leaving Fsave_excursion. */
856
35692fe0 857Lisp_Object
6195f384 858save_excursion_restore (Lisp_Object obj)
35692fe0 859{
6195f384
DA
860 struct Lisp_Excursion *ex = XEXCURSION (obj);
861 struct buffer *b = ex->buffer;
862
863 eassert (b != NULL);
864 eassert (ex->window != NULL);
865
866 /* Restore buffer state only if the buffer is live.
867 Otherwise, just cancel an excursion state. */
868
869 if (!NILP (BVAR (b, name)))
dee091a3 870 {
6195f384
DA
871 int active;
872 struct Lisp_Marker *m;
873 ptrdiff_t oldpos, newpos;
874
875 /* Restore current buffer. */
876 set_buffer_internal (b);
877
878 /* Restore buffer position. */
879 SET_PT_BOTH (clip_to_bounds (BEGV, ex->point.charpos, ZV),
880 clip_to_bounds (BEGV_BYTE, ex->point.bytepos, ZV_BYTE));
881 unchain_marker (&ex->point);
882
883 /* Restore mark if it was non-zero. */
884 m = XMARKER (BVAR (b, mark));
885 oldpos = m->charpos;
886 if (BEGV <= ex->mark.charpos)
887 attach_marker (m, b, ex->mark.charpos, ex->mark.bytepos);
888 newpos = ex->mark.charpos;
889 unchain_marker (&ex->mark);
890
891 /* If mark and region was active, restore them. */
892 active = !NILP (BVAR (b, mark_active));
893 BVAR (b, mark_active) = ex->active ? Qt : Qnil;
894
895 /* If mark is active now, and either was not active
896 or was at a different place, run the activate hook. */
897 if (ex->active && oldpos != newpos)
898 {
899 obj = intern ("activate-mark-hook");
900 Frun_hooks (1, &obj);
901 }
902 /* If mark has ceased to be active, run deactivate hook. */
903 else if (active)
904 {
905 obj = intern ("deactivate-mark-hook");
906 Frun_hooks (1, &obj);
907 }
908
909 /* If buffer was visible in a window, and a different window
910 was selected, and the old selected window is still showing
911 this buffer, restore point in that window. */
912 if (ex->visible)
913 {
914 struct window *w = ex->window;
915
916 if (w != XWINDOW (selected_window) && XBUFFER (w->buffer) == b)
917 attach_marker (XMARKER (w->pointm), b, PT, PT_BYTE);
918 }
9fed2b18 919 }
2483cf58 920
6195f384 921 xfree (ex);
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 }
3628596a
DA
3382 /* These aren't needed anymore, so don't wait for GC. */
3383 free_marker (XCAR (data));
3384 free_marker (XCDR (data));
3385 free_cons (XCONS (data));
d6abb4c7
MB
3386 }
3387 else
3388 /* A buffer, which means that there was no old restriction. */
3389 {
63884563
RS
3390 if (buf /* Verify marker still points to a buffer. */
3391 && (BUF_BEGV (buf) != BUF_BEG (buf) || BUF_ZV (buf) != BUF_Z (buf)))
d6abb4c7
MB
3392 /* The buffer has been narrowed, get rid of the narrowing. */
3393 {
63884563
RS
3394 SET_BUF_BEGV_BOTH (buf, BUF_BEG (buf), BUF_BEG_BYTE (buf));
3395 SET_BUF_ZV_BOTH (buf, BUF_Z (buf), BUF_Z_BYTE (buf));
35692fe0 3396
d6abb4c7
MB
3397 buf->clip_changed = 1; /* Remember that the narrowing changed. */
3398 }
3399 }
35692fe0 3400
aca092ac
SM
3401 /* Changing the buffer bounds invalidates any recorded current column. */
3402 invalidate_current_column ();
3403
d528b1ce
SM
3404 if (cur)
3405 set_buffer_internal (cur);
3406
35692fe0
JB
3407 return Qnil;
3408}
3409
3410DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
7ee72033 3411 doc: /* Execute BODY, saving and restoring current buffer's restrictions.
a1f17501 3412The buffer's restrictions make parts of the beginning and end invisible.
9671c13a 3413\(They are set up with `narrow-to-region' and eliminated with `widen'.)
a1f17501
PJ
3414This special form, `save-restriction', saves the current buffer's restrictions
3415when it is entered, and restores them when it is exited.
3416So any `narrow-to-region' within BODY lasts only until the end of the form.
3417The old restrictions settings are restored
3418even in case of abnormal exit (throw or error).
3419
3420The value returned is the value of the last form in BODY.
3421
3422Note: if you are using both `save-excursion' and `save-restriction',
3423use `save-excursion' outermost:
33c2d29f
MB
3424 (save-excursion (save-restriction ...))
3425
3426usage: (save-restriction &rest BODY) */)
5842a27b 3427 (Lisp_Object body)
35692fe0
JB
3428{
3429 register Lisp_Object val;
d311d28c 3430 ptrdiff_t count = SPECPDL_INDEX ();
35692fe0
JB
3431
3432 record_unwind_protect (save_restriction_restore, save_restriction_save ());
3433 val = Fprogn (body);
3434 return unbind_to (count, val);
3435}
3436\f
0ae83348 3437/* Buffer for the most recent text displayed by Fmessage_box. */
671fbc4d
KH
3438static char *message_text;
3439
3440/* Allocated length of that buffer. */
c9f8d652 3441static ptrdiff_t message_length;
671fbc4d 3442
a7ca3326 3443DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
db18da59 3444 doc: /* Display a message at the bottom of the screen.
281c1721
RS
3445The message also goes into the `*Messages*' buffer.
3446\(In keyboard macros, that's all it does.)
db18da59 3447Return the message.
281c1721 3448
a1f17501
PJ
3449The first argument is a format control string, and the rest are data
3450to be formatted under control of the string. See `format' for details.
3451
7bd5bcfb
KS
3452Note: Use (message "%s" VALUE) to print the value of expressions and
3453variables to avoid accidentally interpreting `%' as format specifiers.
3454
fa056b08
KS
3455If the first argument is nil or the empty string, the function clears
3456any existing message; this lets the minibuffer contents show. See
3457also `current-message'.
4bfbe194 3458
867b9600 3459usage: (message FORMAT-STRING &rest ARGS) */)
f66c7cf8 3460 (ptrdiff_t nargs, Lisp_Object *args)
35692fe0 3461{
6076e561
RS
3462 if (NILP (args[0])
3463 || (STRINGP (args[0])
3464 && SBYTES (args[0]) == 0))
f0250249
JB
3465 {
3466 message (0);
674a954a 3467 return args[0];
f0250249 3468 }
ccdac5be
JB
3469 else
3470 {
3471 register Lisp_Object val;
304f1f12 3472 val = Fformat (nargs, args);
d5db4077 3473 message3 (val, SBYTES (val), STRING_MULTIBYTE (val));
ccdac5be
JB
3474 return val;
3475 }
35692fe0
JB
3476}
3477
cacc3e2c 3478DEFUN ("message-box", Fmessage_box, Smessage_box, 1, MANY, 0,
7ee72033 3479 doc: /* Display a message, in a dialog box if possible.
a1f17501
PJ
3480If a dialog box is not available, use the echo area.
3481The first argument is a format control string, and the rest are data
3482to be formatted under control of the string. See `format' for details.
3483
fa056b08
KS
3484If the first argument is nil or the empty string, clear any existing
3485message; let the minibuffer contents show.
4bfbe194 3486
867b9600 3487usage: (message-box FORMAT-STRING &rest ARGS) */)
f66c7cf8 3488 (ptrdiff_t nargs, Lisp_Object *args)
cacc3e2c
RS
3489{
3490 if (NILP (args[0]))
3491 {
3492 message (0);
3493 return Qnil;
3494 }
3495 else
3496 {
3497 register Lisp_Object val;
3498 val = Fformat (nargs, args);
f8250f01 3499#ifdef HAVE_MENUS
0ae83348
EZ
3500 /* The MS-DOS frames support popup menus even though they are
3501 not FRAME_WINDOW_P. */
3502 if (FRAME_WINDOW_P (XFRAME (selected_frame))
3503 || FRAME_MSDOS_P (XFRAME (selected_frame)))
cacc3e2c 3504 {
f838ed7b 3505 Lisp_Object pane, menu;
cacc3e2c
RS
3506 struct gcpro gcpro1;
3507 pane = Fcons (Fcons (build_string ("OK"), Qt), Qnil);
3508 GCPRO1 (pane);
3509 menu = Fcons (val, pane);
f838ed7b 3510 Fx_popup_dialog (Qt, menu, Qt);
cacc3e2c
RS
3511 UNGCPRO;
3512 return val;
3513 }
0ae83348 3514#endif /* HAVE_MENUS */
cacc3e2c 3515 /* Copy the data so that it won't move when we GC. */
d5db4077 3516 if (SBYTES (val) > message_length)
cacc3e2c 3517 {
38182d90
PE
3518 ptrdiff_t new_length = SBYTES (val) + 80;
3519 message_text = xrealloc (message_text, new_length);
3520 message_length = new_length;
cacc3e2c 3521 }
72af86bd 3522 memcpy (message_text, SDATA (val), SBYTES (val));
d5db4077 3523 message2 (message_text, SBYTES (val),
d13a8480 3524 STRING_MULTIBYTE (val));
cacc3e2c 3525 return val;
cacc3e2c
RS
3526 }
3527}
f8250f01 3528
cacc3e2c 3529DEFUN ("message-or-box", Fmessage_or_box, Smessage_or_box, 1, MANY, 0,
7ee72033 3530 doc: /* Display a message in a dialog box or in the echo area.
a1f17501
PJ
3531If this command was invoked with the mouse, use a dialog box if
3532`use-dialog-box' is non-nil.
3533Otherwise, use the echo area.
3534The first argument is a format control string, and the rest are data
3535to be formatted under control of the string. See `format' for details.
3536
fa056b08
KS
3537If the first argument is nil or the empty string, clear any existing
3538message; let the minibuffer contents show.
4bfbe194 3539
867b9600 3540usage: (message-or-box FORMAT-STRING &rest ARGS) */)
f66c7cf8 3541 (ptrdiff_t nargs, Lisp_Object *args)
cacc3e2c 3542{
f8250f01 3543#ifdef HAVE_MENUS
5920df33 3544 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
c01fbf95 3545 && use_dialog_box)
0a56ee6b 3546 return Fmessage_box (nargs, args);
cacc3e2c
RS
3547#endif
3548 return Fmessage (nargs, args);
3549}
3550
a7ca3326 3551DEFUN ("current-message", Fcurrent_message, Scurrent_message, 0, 0, 0,
7ee72033 3552 doc: /* Return the string currently displayed in the echo area, or nil if none. */)
5842a27b 3553 (void)
b14dda8a 3554{
0634a78e 3555 return current_message ();
b14dda8a
RS
3556}
3557
2d9811c4 3558
d2936d21 3559DEFUN ("propertize", Fpropertize, Spropertize, 1, MANY, 0,
7ee72033 3560 doc: /* Return a copy of STRING with text properties added.
a1f17501
PJ
3561First argument is the string to copy.
3562Remaining arguments form a sequence of PROPERTY VALUE pairs for text
4bfbe194
MB
3563properties to add to the result.
3564usage: (propertize STRING &rest PROPERTIES) */)
f66c7cf8 3565 (ptrdiff_t nargs, Lisp_Object *args)
2d9811c4
GM
3566{
3567 Lisp_Object properties, string;
3568 struct gcpro gcpro1, gcpro2;
f66c7cf8 3569 ptrdiff_t i;
2d9811c4
GM
3570
3571 /* Number of args must be odd. */
c5101a77 3572 if ((nargs & 1) == 0)
2d9811c4
GM
3573 error ("Wrong number of arguments");
3574
3575 properties = string = Qnil;
3576 GCPRO2 (properties, string);
34a7a267 3577
2d9811c4 3578 /* First argument must be a string. */
b7826503 3579 CHECK_STRING (args[0]);
2d9811c4
GM
3580 string = Fcopy_sequence (args[0]);
3581
3582 for (i = 1; i < nargs; i += 2)
9b7a2369 3583 properties = Fcons (args[i], Fcons (args[i + 1], properties));
2d9811c4
GM
3584
3585 Fadd_text_properties (make_number (0),
d5db4077 3586 make_number (SCHARS (string)),
2d9811c4
GM
3587 properties, string);
3588 RETURN_UNGCPRO (string);
3589}
3590
a7ca3326 3591DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
867b9600
JL
3592 doc: /* Format a string out of a format-string and arguments.
3593The first argument is a format control string.
a1f17501 3594The other arguments are substituted into it to make the result, a string.
575b782f
CY
3595
3596The format control string may contain %-sequences meaning to substitute
3597the next available argument:
3598
a1f17501
PJ
3599%s means print a string argument. Actually, prints any object, with `princ'.
3600%d means print as number in decimal (%o octal, %x hex).
3601%X is like %x, but uses upper case.
3602%e means print a number in exponential notation.
3603%f means print a number in decimal-point notation.
3604%g means print a number in exponential notation
3605 or decimal-point notation, whichever uses fewer characters.
3606%c means print a number as a single character.
3607%S means print any object as an s-expression (using `prin1').
575b782f
CY
3608
3609The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.
4bfbe194
MB
3610Use %% to put a single % into the output.
3611
575b782f
CY
3612A %-sequence may contain optional flag, width, and precision
3613specifiers, as follows:
3614
3615 %<flags><width><precision>character
3616
3617where flags is [+ #-0]+, width is [0-9]+, and precision is .[0-9]+
3618
3619The + flag character inserts a + before any positive number, while a
3620space inserts a space before any positive number; these flags only
3621affect %d, %e, %f, and %g sequences, and the + flag takes precedence.
3622The # flag means to use an alternate display form for %o, %x, %X, %e,
3623%f, and %g sequences. The - and 0 flags affect the width specifier,
3624as described below.
3625
3626The width specifier supplies a lower limit for the length of the
3627printed representation. The padding, if any, normally goes on the
3628left, but it goes on the right if the - flag is present. The padding
3629character is normally a space, but it is 0 if the 0 flag is present.
a9ab721e
LMI
3630The 0 flag is ignored if the - flag is present, or the format sequence
3631is something other than %d, %e, %f, and %g.
575b782f
CY
3632
3633For %e, %f, and %g sequences, the number after the "." in the
3634precision specifier says how many decimal places to show; if zero, the
3635decimal point itself is omitted. For %s and %S, the precision
3636specifier truncates the string to the given width.
f555f8cf 3637
4bfbe194 3638usage: (format STRING &rest OBJECTS) */)
f66c7cf8 3639 (ptrdiff_t nargs, Lisp_Object *args)
35692fe0 3640{
f66c7cf8 3641 ptrdiff_t n; /* The number of the next arg to substitute */
37910ab2
PE
3642 char initial_buffer[4000];
3643 char *buf = initial_buffer;
d311d28c
PE
3644 ptrdiff_t bufsize = sizeof initial_buffer;
3645 ptrdiff_t max_bufsize = STRING_BYTES_BOUND + 1;
37910ab2
PE
3646 char *p;
3647 Lisp_Object buf_save_value IF_LINT (= {0});
e7f8264d 3648 register char *format, *end, *format_start;
d311d28c 3649 ptrdiff_t formatlen, nchars;
37910ab2
PE
3650 /* Nonzero if the format is multibyte. */
3651 int multibyte_format = 0;
1f24f4fd
RS
3652 /* Nonzero if the output should be a multibyte string,
3653 which is true if any of the inputs is one. */
3654 int multibyte = 0;
8f2917e4
KH
3655 /* When we make a multibyte string, we must pay attention to the
3656 byte combining problem, i.e., a byte may be combined with a
3b59c351 3657 multibyte character of the previous string. This flag tells if we
8f2917e4
KH
3658 must consider such a situation or not. */
3659 int maybe_combine_byte;
8d6179dc 3660 Lisp_Object val;
d147ee84 3661 int arg_intervals = 0;
7e2c051b 3662 USE_SAFE_ALLOCA;
d147ee84
RS
3663
3664 /* discarded[I] is 1 if byte I of the format
3665 string was not copied into the output.
3666 It is 2 if byte I was not the first byte of its character. */
37910ab2 3667 char *discarded;
d147ee84
RS
3668
3669 /* Each element records, for one argument,
3670 the start and end bytepos in the output string,
37910ab2 3671 whether the argument has been converted to string (e.g., due to "%S"),
d147ee84
RS
3672 and whether the argument is a string with intervals.
3673 info[0] is unused. Unused elements have -1 for start. */
5e6d5493
GM
3674 struct info
3675 {
d311d28c 3676 ptrdiff_t start, end;
37910ab2
PE
3677 int converted_to_string;
3678 int intervals;
5e6d5493 3679 } *info = 0;
1f24f4fd 3680
35692fe0
JB
3681 /* It should not be necessary to GCPRO ARGS, because
3682 the caller in the interpreter should take care of that. */
3683
37910ab2
PE
3684 CHECK_STRING (args[0]);
3685 format_start = SSDATA (args[0]);
3686 formatlen = SBYTES (args[0]);
3687
3688 /* Allocate the info and discarded tables. */
3689 {
f66c7cf8 3690 ptrdiff_t i;
37910ab2 3691 if ((SIZE_MAX - formatlen) / sizeof (struct info) <= nargs)
531b0165 3692 memory_full (SIZE_MAX);
37910ab2
PE
3693 SAFE_ALLOCA (info, struct info *, (nargs + 1) * sizeof *info + formatlen);
3694 discarded = (char *) &info[nargs + 1];
3695 for (i = 0; i < nargs + 1; i++)
3696 {
3697 info[i].start = -1;
3698 info[i].intervals = info[i].converted_to_string = 0;
3699 }
3700 memset (discarded, 0, formatlen);
3701 }
3702
e781c49e
RS
3703 /* Try to determine whether the result should be multibyte.
3704 This is not always right; sometimes the result needs to be multibyte
3705 because of an object that we will pass through prin1,
3706 and in that case, we won't know it here. */
37910ab2
PE
3707 multibyte_format = STRING_MULTIBYTE (args[0]);
3708 multibyte = multibyte_format;
3709 for (n = 1; !multibyte && n < nargs; n++)
3710 if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
3711 multibyte = 1;
67965a98 3712
e781c49e 3713 /* If we start out planning a unibyte result,
37910ab2 3714 then discover it has to be multibyte, we jump back to retry. */
e781c49e
RS
3715 retry:
3716
37910ab2
PE
3717 p = buf;
3718 nchars = 0;
3719 n = 0;
d147ee84 3720
37910ab2
PE
3721 /* Scan the format and store result in BUF. */
3722 format = format_start;
3723 end = format + formatlen;
3724 maybe_combine_byte = 0;
35692fe0 3725
35692fe0 3726 while (format != end)
37910ab2
PE
3727 {
3728 /* The values of N and FORMAT when the loop body is entered. */
f66c7cf8 3729 ptrdiff_t n0 = n;
37910ab2 3730 char *format0 = format;
35692fe0 3731
37910ab2 3732 /* Bytes needed to represent the output of this conversion. */
d311d28c 3733 ptrdiff_t convbytes;
537dfb13 3734
37910ab2
PE
3735 if (*format == '%')
3736 {
3737 /* General format specifications look like
a432bfe5 3738
37910ab2 3739 '%' [flags] [field-width] [precision] format
a432bfe5 3740
37910ab2 3741 where
a432bfe5 3742
37910ab2
PE
3743 flags ::= [-+0# ]+
3744 field-width ::= [0-9]+
3745 precision ::= '.' [0-9]*
a432bfe5 3746
37910ab2
PE
3747 If a field-width is specified, it specifies to which width
3748 the output should be padded with blanks, if the output
3749 string is shorter than field-width.
a432bfe5 3750
37910ab2
PE
3751 If precision is specified, it specifies the number of
3752 digits to print after the '.' for floats, or the max.
3753 number of chars to print from a string. */
a432bfe5 3754
37910ab2
PE
3755 int minus_flag = 0;
3756 int plus_flag = 0;
3757 int space_flag = 0;
3758 int sharp_flag = 0;
3759 int zero_flag = 0;
d311d28c 3760 ptrdiff_t field_width;
37910ab2
PE
3761 int precision_given;
3762 uintmax_t precision = UINTMAX_MAX;
3763 char *num_end;
3764 char conversion;
a432bfe5 3765
37910ab2
PE
3766 while (1)
3767 {
3768 switch (*++format)
3769 {
3770 case '-': minus_flag = 1; continue;
3771 case '+': plus_flag = 1; continue;
3772 case ' ': space_flag = 1; continue;
3773 case '#': sharp_flag = 1; continue;
3774 case '0': zero_flag = 1; continue;
3775 }
3776 break;
3777 }
35692fe0 3778
37910ab2
PE
3779 /* Ignore flags when sprintf ignores them. */
3780 space_flag &= ~ plus_flag;
3781 zero_flag &= ~ minus_flag;
1f24f4fd 3782
35692fe0 3783 {
37910ab2
PE
3784 uintmax_t w = strtoumax (format, &num_end, 10);
3785 if (max_bufsize <= w)
3786 string_overflow ();
3787 field_width = w;
35692fe0 3788 }
37910ab2
PE
3789 precision_given = *num_end == '.';
3790 if (precision_given)
3791 precision = strtoumax (num_end + 1, &num_end, 10);
3792 format = num_end;
3793
3794 if (format == end)
3795 error ("Format string ends in middle of format specifier");
3796
3797 memset (&discarded[format0 - format_start], 1, format - format0);
3798 conversion = *format;
3799 if (conversion == '%')
7812ba2d 3800 goto copy_char;
d147ee84 3801 discarded[format - format_start] = 1;
1f24f4fd 3802 format++;
fb893977 3803
37910ab2
PE
3804 ++n;
3805 if (! (n < nargs))
3806 error ("Not enough arguments for format string");
3807
3808 /* For 'S', prin1 the argument, and then treat like 's'.
3809 For 's', princ any argument that is not a string or
3810 symbol. But don't do this conversion twice, which might
3811 happen after retrying. */
3812 if ((conversion == 'S'
3813 || (conversion == 's'
3814 && ! STRINGP (args[n]) && ! SYMBOLP (args[n]))))
f555f8cf 3815 {
37910ab2 3816 if (! info[n].converted_to_string)
f555f8cf 3817 {
37910ab2
PE
3818 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
3819 args[n] = Fprin1_to_string (args[n], noescape);
3820 info[n].converted_to_string = 1;
3821 if (STRING_MULTIBYTE (args[n]) && ! multibyte)
3822 {
3823 multibyte = 1;
3824 goto retry;
3825 }
f555f8cf 3826 }
37910ab2 3827 conversion = 's';
f555f8cf 3828 }
37910ab2
PE
3829 else if (conversion == 'c')
3830 {
3831 if (FLOATP (args[n]))
3832 {
3833 double d = XFLOAT_DATA (args[n]);
3834 args[n] = make_number (FIXNUM_OVERFLOW_P (d) ? -1 : d);
3835 }
f555f8cf 3836
37910ab2
PE
3837 if (INTEGERP (args[n]) && ! ASCII_CHAR_P (XINT (args[n])))
3838 {
3839 if (!multibyte)
3840 {
3841 multibyte = 1;
3842 goto retry;
3843 }
3844 args[n] = Fchar_to_string (args[n]);
3845 info[n].converted_to_string = 1;
3846 }
f555f8cf 3847
37910ab2
PE
3848 if (info[n].converted_to_string)
3849 conversion = 's';
3850 zero_flag = 0;
d147ee84 3851 }
35692fe0 3852
37910ab2 3853 if (SYMBOLP (args[n]))
1f24f4fd 3854 {
37910ab2
PE
3855 args[n] = SYMBOL_NAME (args[n]);
3856 if (STRING_MULTIBYTE (args[n]) && ! multibyte)
3857 {
3858 multibyte = 1;
3859 goto retry;
3860 }
1f24f4fd
RS
3861 }
3862
37910ab2 3863 if (conversion == 's')
1f24f4fd 3864 {
ac42d7b9
KG
3865 /* handle case (precision[n] >= 0) */
3866
d311d28c
PE
3867 ptrdiff_t width, padding, nbytes;
3868 ptrdiff_t nchars_string;
ac42d7b9 3869
d311d28c
PE
3870 ptrdiff_t prec = -1;
3871 if (precision_given && precision <= TYPE_MAXIMUM (ptrdiff_t))
37910ab2
PE
3872 prec = precision;
3873
ac42d7b9
KG
3874 /* lisp_string_width ignores a precision of 0, but GNU
3875 libc functions print 0 characters when the precision
3876 is 0. Imitate libc behavior here. Changing
3877 lisp_string_width is the right thing, and will be
3878 done, but meanwhile we work with it. */
3879
37910ab2 3880 if (prec == 0)
ac42d7b9 3881 width = nchars_string = nbytes = 0;
ac42d7b9 3882 else
37910ab2 3883 {
d311d28c 3884 ptrdiff_t nch, nby;
37910ab2
PE
3885 width = lisp_string_width (args[n], prec, &nch, &nby);
3886 if (prec < 0)
3887 {
3888 nchars_string = SCHARS (args[n]);
3889 nbytes = SBYTES (args[n]);
3890 }
3891 else
3892 {
3893 nchars_string = nch;
3894 nbytes = nby;
3895 }
ac42d7b9 3896 }
25c9e7fb 3897
37910ab2
PE
3898 convbytes = nbytes;
3899 if (convbytes && multibyte && ! STRING_MULTIBYTE (args[n]))
3900 convbytes = count_size_as_multibyte (SDATA (args[n]), nbytes);
1f24f4fd 3901
37910ab2 3902 padding = width < field_width ? field_width - width : 0;
ac42d7b9 3903
37910ab2
PE
3904 if (max_bufsize - padding <= convbytes)
3905 string_overflow ();
3906 convbytes += padding;
3907 if (convbytes <= buf + bufsize - p)
3908 {
3909 if (! minus_flag)
3910 {
3911 memset (p, ' ', padding);
3912 p += padding;
3913 nchars += padding;
3914 }
ac42d7b9 3915
37910ab2
PE
3916 if (p > buf
3917 && multibyte
3918 && !ASCII_BYTE_P (*((unsigned char *) p - 1))
3919 && STRING_MULTIBYTE (args[n])
3920 && !CHAR_HEAD_P (SREF (args[n], 0)))
3921 maybe_combine_byte = 1;
1f24f4fd 3922
37910ab2
PE
3923 p += copy_text (SDATA (args[n]), (unsigned char *) p,
3924 nbytes,
3925 STRING_MULTIBYTE (args[n]), multibyte);
8f2c9ed8 3926
37910ab2
PE
3927 info[n].start = nchars;
3928 nchars += nchars_string;
3929 info[n].end = nchars;
3930
3931 if (minus_flag)
3932 {
3933 memset (p, ' ', padding);
3934 p += padding;
3935 nchars += padding;
3936 }
5e6d5493 3937
37910ab2
PE
3938 /* If this argument has text properties, record where
3939 in the result string it appears. */
3940 if (STRING_INTERVALS (args[n]))
3941 info[n].intervals = arg_intervals = 1;
3942
3943 continue;
3944 }
1f24f4fd 3945 }
37910ab2
PE
3946 else if (! (conversion == 'c' || conversion == 'd'
3947 || conversion == 'e' || conversion == 'f'
3948 || conversion == 'g' || conversion == 'i'
3949 || conversion == 'o' || conversion == 'x'
3950 || conversion == 'X'))
3951 error ("Invalid format operation %%%c",
3952 STRING_CHAR ((unsigned char *) format - 1));
3953 else if (! (INTEGERP (args[n]) || FLOATP (args[n])))
3954 error ("Format specifier doesn't match argument type");
3955 else
1f24f4fd 3956 {
37910ab2
PE
3957 enum
3958 {
3959 /* Maximum precision for a %f conversion such that the
333f9019 3960 trailing output digit might be nonzero. Any precision
37910ab2
PE
3961 larger than this will not yield useful information. */
3962 USEFUL_PRECISION_MAX =
3963 ((1 - DBL_MIN_EXP)
3964 * (FLT_RADIX == 2 || FLT_RADIX == 10 ? 1
3965 : FLT_RADIX == 16 ? 4
3966 : -1)),
3967
3968 /* Maximum number of bytes generated by any format, if
81f7c12e 3969 precision is no more than USEFUL_PRECISION_MAX.
37910ab2
PE
3970 On all practical hosts, %f is the worst case. */
3971 SPRINTF_BUFSIZE =
a81d11a3
PE
3972 sizeof "-." + (DBL_MAX_10_EXP + 1) + USEFUL_PRECISION_MAX,
3973
3974 /* Length of pM (that is, of pMd without the
3975 trailing "d"). */
3976 pMlen = sizeof pMd - 2
37910ab2
PE
3977 };
3978 verify (0 < USEFUL_PRECISION_MAX);
3979
3980 int prec;
d311d28c 3981 ptrdiff_t padding, sprintf_bytes;
37910ab2
PE
3982 uintmax_t excess_precision, numwidth;
3983 uintmax_t leading_zeros = 0, trailing_zeros = 0;
3984
3985 char sprintf_buf[SPRINTF_BUFSIZE];
3986
3987 /* Copy of conversion specification, modified somewhat.
3988 At most three flags F can be specified at once. */
a81d11a3 3989 char convspec[sizeof "%FFF.*d" + pMlen];
37910ab2
PE
3990
3991 /* Avoid undefined behavior in underlying sprintf. */
3992 if (conversion == 'd' || conversion == 'i')
3993 sharp_flag = 0;
3994
3995 /* Create the copy of the conversion specification, with
3996 any width and precision removed, with ".*" inserted,
a81d11a3 3997 and with pM inserted for integer formats. */
37910ab2
PE
3998 {
3999 char *f = convspec;
4000 *f++ = '%';
4001 *f = '-'; f += minus_flag;
4002 *f = '+'; f += plus_flag;
4003 *f = ' '; f += space_flag;
4004 *f = '#'; f += sharp_flag;
4005 *f = '0'; f += zero_flag;
4006 *f++ = '.';
4007 *f++ = '*';
4008 if (conversion == 'd' || conversion == 'i'
4009 || conversion == 'o' || conversion == 'x'
4010 || conversion == 'X')
4011 {
a81d11a3
PE
4012 memcpy (f, pMd, pMlen);
4013 f += pMlen;
37910ab2
PE
4014 zero_flag &= ~ precision_given;
4015 }
4016 *f++ = conversion;
4017 *f = '\0';
4018 }
1f24f4fd 4019
37910ab2
PE
4020 prec = -1;
4021 if (precision_given)
4022 prec = min (precision, USEFUL_PRECISION_MAX);
4023
4024 /* Use sprintf to format this number into sprintf_buf. Omit
4025 padding and excess precision, though, because sprintf limits
4026 output length to INT_MAX.
4027
4028 There are four types of conversion: double, unsigned
4029 char (passed as int), wide signed int, and wide
4030 unsigned int. Treat them separately because the
4031 sprintf ABI is sensitive to which type is passed. Be
4032 careful about integer overflow, NaNs, infinities, and
4033 conversions; for example, the min and max macros are
4034 not suitable here. */
4035 if (conversion == 'e' || conversion == 'f' || conversion == 'g')
4036 {
4037 double x = (INTEGERP (args[n])
4038 ? XINT (args[n])
4039 : XFLOAT_DATA (args[n]));
4040 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
4041 }
4042 else if (conversion == 'c')
4043 {
4044 /* Don't use sprintf here, as it might mishandle prec. */
4045 sprintf_buf[0] = XINT (args[n]);
4046 sprintf_bytes = prec != 0;
4047 }
4048 else if (conversion == 'd')
4049 {
4050 /* For float, maybe we should use "%1.0f"
4051 instead so it also works for values outside
4052 the integer range. */
a81d11a3 4053 printmax_t x;
37910ab2
PE
4054 if (INTEGERP (args[n]))
4055 x = XINT (args[n]);
4056 else
4057 {
4058 double d = XFLOAT_DATA (args[n]);
4059 if (d < 0)
4060 {
a81d11a3 4061 x = TYPE_MINIMUM (printmax_t);
37910ab2
PE
4062 if (x < d)
4063 x = d;
4064 }
4065 else
4066 {
a81d11a3 4067 x = TYPE_MAXIMUM (printmax_t);
37910ab2
PE
4068 if (d < x)
4069 x = d;
4070 }
4071 }
4072 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
4073 }
0f860bd7 4074 else
de92d4d4 4075 {
37910ab2 4076 /* Don't sign-extend for octal or hex printing. */
a81d11a3 4077 uprintmax_t x;
37910ab2
PE
4078 if (INTEGERP (args[n]))
4079 x = XUINT (args[n]);
4080 else
0f860bd7 4081 {
37910ab2
PE
4082 double d = XFLOAT_DATA (args[n]);
4083 if (d < 0)
4084 x = 0;
4085 else
4086 {
a81d11a3 4087 x = TYPE_MAXIMUM (uprintmax_t);
37910ab2
PE
4088 if (d < x)
4089 x = d;
4090 }
0f860bd7 4091 }
37910ab2
PE
4092 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
4093 }
0f860bd7 4094
37910ab2
PE
4095 /* Now the length of the formatted item is known, except it omits
4096 padding and excess precision. Deal with excess precision
4097 first. This happens only when the format specifies
4098 ridiculously large precision. */
4099 excess_precision = precision - prec;
4100 if (excess_precision)
4101 {
4102 if (conversion == 'e' || conversion == 'f'
4103 || conversion == 'g')
ff6e6ac8 4104 {
37910ab2
PE
4105 if ((conversion == 'g' && ! sharp_flag)
4106 || ! ('0' <= sprintf_buf[sprintf_bytes - 1]
4107 && sprintf_buf[sprintf_bytes - 1] <= '9'))
4108 excess_precision = 0;
ff6e6ac8 4109 else
37910ab2
PE
4110 {
4111 if (conversion == 'g')
4112 {
4113 char *dot = strchr (sprintf_buf, '.');
4114 if (!dot)
4115 excess_precision = 0;
4116 }
4117 }
4118 trailing_zeros = excess_precision;
ff6e6ac8 4119 }
de92d4d4 4120 else
37910ab2 4121 leading_zeros = excess_precision;
de92d4d4 4122 }
1f24f4fd 4123
37910ab2
PE
4124 /* Compute the total bytes needed for this item, including
4125 excess precision and padding. */
4126 numwidth = sprintf_bytes + excess_precision;
4127 padding = numwidth < field_width ? field_width - numwidth : 0;
4128 if (max_bufsize - sprintf_bytes <= excess_precision
4129 || max_bufsize - padding <= numwidth)
4130 string_overflow ();
4131 convbytes = numwidth + padding;
4132
4133 if (convbytes <= buf + bufsize - p)
4134 {
4135 /* Copy the formatted item from sprintf_buf into buf,
4136 inserting padding and excess-precision zeros. */
4137
4138 char *src = sprintf_buf;
4139 char src0 = src[0];
4140 int exponent_bytes = 0;
4141 int signedp = src0 == '-' || src0 == '+' || src0 == ' ';
4142 int significand_bytes;
172418ad
AS
4143 if (zero_flag
4144 && ((src[signedp] >= '0' && src[signedp] <= '9')
4145 || (src[signedp] >= 'a' && src[signedp] <= 'f')
4146 || (src[signedp] >= 'A' && src[signedp] <= 'F')))
37910ab2
PE
4147 {
4148 leading_zeros += padding;
4149 padding = 0;
4150 }
4151
4152 if (excess_precision
4153 && (conversion == 'e' || conversion == 'g'))
4154 {
4155 char *e = strchr (src, 'e');
4156 if (e)
4157 exponent_bytes = src + sprintf_bytes - e;
4158 }
4159
4160 if (! minus_flag)
4161 {
4162 memset (p, ' ', padding);
4163 p += padding;
4164 nchars += padding;
4165 }
4166
4167 *p = src0;
4168 src += signedp;
4169 p += signedp;
4170 memset (p, '0', leading_zeros);
4171 p += leading_zeros;
4172 significand_bytes = sprintf_bytes - signedp - exponent_bytes;
4173 memcpy (p, src, significand_bytes);
4174 p += significand_bytes;
4175 src += significand_bytes;
4176 memset (p, '0', trailing_zeros);
4177 p += trailing_zeros;
4178 memcpy (p, src, exponent_bytes);
4179 p += exponent_bytes;
4180
4181 info[n].start = nchars;
4182 nchars += leading_zeros + sprintf_bytes + trailing_zeros;
4183 info[n].end = nchars;
4184
4185 if (minus_flag)
4186 {
4187 memset (p, ' ', padding);
4188 p += padding;
4189 nchars += padding;
4190 }
4191
4192 continue;
4193 }
4194 }
4195 }
4196 else
4197 copy_char:
4198 {
4199 /* Copy a single character from format to buf. */
4200
4201 char *src = format;
4202 unsigned char str[MAX_MULTIBYTE_LENGTH];
4203
4204 if (multibyte_format)
4205 {
4206 /* Copy a whole multibyte character. */
8f2917e4 4207 if (p > buf
25aa5d64 4208 && !ASCII_BYTE_P (*((unsigned char *) p - 1))
37910ab2 4209 && !CHAR_HEAD_P (*format))
8f2917e4 4210 maybe_combine_byte = 1;
37910ab2
PE
4211
4212 do
4213 format++;
4214 while (! CHAR_HEAD_P (*format));
4215
a02719a3 4216 convbytes = format - src;
7812ba2d 4217 memset (&discarded[src + 1 - format_start], 2, convbytes - 1);
37910ab2
PE
4218 }
4219 else
4220 {
4221 unsigned char uc = *format++;
4222 if (! multibyte || ASCII_BYTE_P (uc))
4223 convbytes = 1;
9a599130 4224 else
37910ab2
PE
4225 {
4226 int c = BYTE8_TO_CHAR (uc);
4227 convbytes = CHAR_STRING (c, str);
4228 src = (char *) str;
4229 }
1f24f4fd 4230 }
d147ee84 4231
37910ab2 4232 if (convbytes <= buf + bufsize - p)
d147ee84 4233 {
37910ab2
PE
4234 memcpy (p, src, convbytes);
4235 p += convbytes;
4236 nchars++;
4237 continue;
d147ee84 4238 }
7df74da6 4239 }
1f24f4fd 4240
37910ab2
PE
4241 /* There wasn't enough room to store this conversion or single
4242 character. CONVBYTES says how much room is needed. Allocate
4243 enough room (and then some) and do it again. */
4244 {
c9f8d652 4245 ptrdiff_t used = p - buf;
37910ab2
PE
4246
4247 if (max_bufsize - used < convbytes)
4248 string_overflow ();
4249 bufsize = used + convbytes;
4250 bufsize = bufsize < max_bufsize / 2 ? bufsize * 2 : max_bufsize;
4251
4252 if (buf == initial_buffer)
4253 {
4254 buf = xmalloc (bufsize);
4255 sa_must_free = 1;
4256 buf_save_value = make_save_value (buf, 0);
4257 record_unwind_protect (safe_alloca_unwind, buf_save_value);
4258 memcpy (buf, initial_buffer, used);
4259 }
4260 else
4261 XSAVE_VALUE (buf_save_value)->pointer = buf = xrealloc (buf, bufsize);
4262
4263 p = buf + used;
4264 }
4265
4266 format = format0;
4267 n = n0;
1f24f4fd
RS
4268 }
4269
37910ab2 4270 if (bufsize < p - buf)
a432bfe5
GM
4271 abort ();
4272
8f2917e4 4273 if (maybe_combine_byte)
e7f8264d 4274 nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf);
5f75e666 4275 val = make_specified_string (buf, nchars, p - buf, multibyte);
8d6179dc 4276
1f24f4fd 4277 /* If we allocated BUF with malloc, free it too. */
e65837df 4278 SAFE_FREE ();
35692fe0 4279
5e6d5493
GM
4280 /* If the format string has text properties, or any of the string
4281 arguments has text properties, set up text properties of the
4282 result string. */
34a7a267 4283
d147ee84 4284 if (STRING_INTERVALS (args[0]) || arg_intervals)
5e6d5493
GM
4285 {
4286 Lisp_Object len, new_len, props;
4287 struct gcpro gcpro1;
34a7a267 4288
5e6d5493 4289 /* Add text properties from the format string. */
d5db4077 4290 len = make_number (SCHARS (args[0]));
5e6d5493
GM
4291 props = text_property_list (args[0], make_number (0), len, Qnil);
4292 GCPRO1 (props);
34a7a267 4293
5e6d5493
GM
4294 if (CONSP (props))
4295 {
d311d28c
PE
4296 ptrdiff_t bytepos = 0, position = 0, translated = 0;
4297 ptrdiff_t argn = 1;
d147ee84
RS
4298 Lisp_Object list;
4299
4300 /* Adjust the bounds of each text property
4301 to the proper start and end in the output string. */
d147ee84 4302
15fad037
KS
4303 /* Put the positions in PROPS in increasing order, so that
4304 we can do (effectively) one scan through the position
4305 space of the format string. */
4306 props = Fnreverse (props);
4307
4308 /* BYTEPOS is the byte position in the format string,
d147ee84
RS
4309 POSITION is the untranslated char position in it,
4310 TRANSLATED is the translated char position in BUF,
4311 and ARGN is the number of the next arg we will come to. */
4312 for (list = props; CONSP (list); list = XCDR (list))
4313 {
f3ce1df8 4314 Lisp_Object item;
d311d28c 4315 ptrdiff_t pos;
d147ee84
RS
4316
4317 item = XCAR (list);
4318
4319 /* First adjust the property start position. */
4320 pos = XINT (XCAR (item));
4321
4322 /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN
4323 up to this position. */
4324 for (; position < pos; bytepos++)
4325 {
4326 if (! discarded[bytepos])
4327 position++, translated++;
4328 else if (discarded[bytepos] == 1)
4329 {
4330 position++;
4331 if (translated == info[argn].start)
4332 {
4333 translated += info[argn].end - info[argn].start;
4334 argn++;
4335 }
4336 }
4337 }
4338
4339 XSETCAR (item, make_number (translated));
4340
4341 /* Likewise adjust the property end position. */
4342 pos = XINT (XCAR (XCDR (item)));
4343
d40ec4a0 4344 for (; position < pos; bytepos++)
d147ee84
RS
4345 {
4346 if (! discarded[bytepos])
4347 position++, translated++;
4348 else if (discarded[bytepos] == 1)
4349 {
4350 position++;
4351 if (translated == info[argn].start)
4352 {
4353 translated += info[argn].end - info[argn].start;
4354 argn++;
4355 }
4356 }
4357 }
4358
4359 XSETCAR (XCDR (item), make_number (translated));
4360 }
4361
5e6d5493
GM
4362 add_text_properties_from_list (val, props, make_number (0));
4363 }
4364
4365 /* Add text properties from arguments. */
d147ee84 4366 if (arg_intervals)
5e6d5493 4367 for (n = 1; n < nargs; ++n)
d147ee84 4368 if (info[n].intervals)
5e6d5493 4369 {
d5db4077 4370 len = make_number (SCHARS (args[n]));
5e6d5493
GM
4371 new_len = make_number (info[n].end - info[n].start);
4372 props = text_property_list (args[n], make_number (0), len, Qnil);
e398c61c
CY
4373 props = extend_property_ranges (props, new_len);
4374 /* If successive arguments have properties, be sure that
be17069b
KH
4375 the value of `composition' property be the copy. */
4376 if (n > 1 && info[n - 1].end)
4377 make_composition_value_copy (props);
5e6d5493
GM
4378 add_text_properties_from_list (val, props,
4379 make_number (info[n].start));
4380 }
4381
4382 UNGCPRO;
4383 }
4384
8d6179dc 4385 return val;
35692fe0
JB
4386}
4387
35692fe0 4388Lisp_Object
a8fe7202 4389format2 (const char *string1, Lisp_Object arg0, Lisp_Object arg1)
d40dc1d0
RS
4390{
4391 Lisp_Object args[3];
d40dc1d0
RS
4392 args[0] = build_string (string1);
4393 args[1] = arg0;
4394 args[2] = arg1;
4395 return Fformat (3, args);
35692fe0
JB
4396}
4397\f
4398DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
7ee72033 4399 doc: /* Return t if two characters match, optionally ignoring case.
a1f17501 4400Both arguments must be characters (i.e. integers).
7ee72033 4401Case is ignored if `case-fold-search' is non-nil in the current buffer. */)
5842a27b 4402 (register Lisp_Object c1, Lisp_Object c2)
35692fe0 4403{
1b5d98bb 4404 int i1, i2;
253c3c82 4405 /* Check they're chars, not just integers, otherwise we could get array
5da9919f 4406 bounds violations in downcase. */
253c3c82
SM
4407 CHECK_CHARACTER (c1);
4408 CHECK_CHARACTER (c2);
35692fe0 4409
1b5d98bb 4410 if (XINT (c1) == XINT (c2))
35692fe0 4411 return Qt;
4b4deea2 4412 if (NILP (BVAR (current_buffer, case_fold_search)))
1b5d98bb
RS
4413 return Qnil;
4414
e5112ecb 4415 i1 = XFASTINT (c1);
4b4deea2 4416 if (NILP (BVAR (current_buffer, enable_multibyte_characters))
e5112ecb
KH
4417 && ! ASCII_CHAR_P (i1))
4418 {
4419 MAKE_CHAR_MULTIBYTE (i1);
4420 }
4421 i2 = XFASTINT (c2);
4b4deea2 4422 if (NILP (BVAR (current_buffer, enable_multibyte_characters))
e5112ecb
KH
4423 && ! ASCII_CHAR_P (i2))
4424 {
4425 MAKE_CHAR_MULTIBYTE (i2);
4426 }
0da09c43 4427 return (downcase (i1) == downcase (i2) ? Qt : Qnil);
35692fe0 4428}
b229b8d1
RS
4429\f
4430/* Transpose the markers in two regions of the current buffer, and
4431 adjust the ones between them if necessary (i.e.: if the regions
4432 differ in size).
4433
ec1c14f6
RS
4434 START1, END1 are the character positions of the first region.
4435 START1_BYTE, END1_BYTE are the byte positions.
4436 START2, END2 are the character positions of the second region.
4437 START2_BYTE, END2_BYTE are the byte positions.
4438
b229b8d1
RS
4439 Traverses the entire marker list of the buffer to do so, adding an
4440 appropriate amount to some, subtracting from some, and leaving the
4441 rest untouched. Most of this is copied from adjust_markers in insdel.c.
34a7a267 4442
ec1c14f6 4443 It's the caller's job to ensure that START1 <= END1 <= START2 <= END2. */
b229b8d1 4444
acb7cc89 4445static void
d311d28c
PE
4446transpose_markers (ptrdiff_t start1, ptrdiff_t end1,
4447 ptrdiff_t start2, ptrdiff_t end2,
4448 ptrdiff_t start1_byte, ptrdiff_t end1_byte,
4449 ptrdiff_t start2_byte, ptrdiff_t end2_byte)
b229b8d1 4450{
d311d28c 4451 register ptrdiff_t amt1, amt1_byte, amt2, amt2_byte, diff, diff_byte, mpos;
12038f9f 4452 register struct Lisp_Marker *marker;
b229b8d1 4453
03240d11 4454 /* Update point as if it were a marker. */
8de1d5f0
KH
4455 if (PT < start1)
4456 ;
4457 else if (PT < end1)
ec1c14f6
RS
4458 TEMP_SET_PT_BOTH (PT + (end2 - end1),
4459 PT_BYTE + (end2_byte - end1_byte));
8de1d5f0 4460 else if (PT < start2)
ec1c14f6
RS
4461 TEMP_SET_PT_BOTH (PT + (end2 - start2) - (end1 - start1),
4462 (PT_BYTE + (end2_byte - start2_byte)
4463 - (end1_byte - start1_byte)));
8de1d5f0 4464 else if (PT < end2)
ec1c14f6
RS
4465 TEMP_SET_PT_BOTH (PT - (start2 - start1),
4466 PT_BYTE - (start2_byte - start1_byte));
8de1d5f0 4467
03240d11
KH
4468 /* We used to adjust the endpoints here to account for the gap, but that
4469 isn't good enough. Even if we assume the caller has tried to move the
4470 gap out of our way, it might still be at start1 exactly, for example;
4471 and that places it `inside' the interval, for our purposes. The amount
4472 of adjustment is nontrivial if there's a `denormalized' marker whose
4473 position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
4474 the dirty work to Fmarker_position, below. */
b229b8d1
RS
4475
4476 /* The difference between the region's lengths */
4477 diff = (end2 - start2) - (end1 - start1);
ec1c14f6 4478 diff_byte = (end2_byte - start2_byte) - (end1_byte - start1_byte);
34a7a267 4479
b229b8d1 4480 /* For shifting each marker in a region by the length of the other
ec1c14f6 4481 region plus the distance between the regions. */
b229b8d1
RS
4482 amt1 = (end2 - start2) + (start2 - end1);
4483 amt2 = (end1 - start1) + (start2 - end1);
ec1c14f6
RS
4484 amt1_byte = (end2_byte - start2_byte) + (start2_byte - end1_byte);
4485 amt2_byte = (end1_byte - start1_byte) + (start2_byte - end1_byte);
b229b8d1 4486
12038f9f 4487 for (marker = BUF_MARKERS (current_buffer); marker; marker = marker->next)
b229b8d1 4488 {
12038f9f 4489 mpos = marker->bytepos;
ec1c14f6
RS
4490 if (mpos >= start1_byte && mpos < end2_byte)
4491 {
4492 if (mpos < end1_byte)
4493 mpos += amt1_byte;
4494 else if (mpos < start2_byte)
4495 mpos += diff_byte;
4496 else
4497 mpos -= amt2_byte;
12038f9f 4498 marker->bytepos = mpos;
ec1c14f6 4499 }
12038f9f 4500 mpos = marker->charpos;
03240d11
KH
4501 if (mpos >= start1 && mpos < end2)
4502 {
4503 if (mpos < end1)
4504 mpos += amt1;
4505 else if (mpos < start2)
4506 mpos += diff;
4507 else
4508 mpos -= amt2;
03240d11 4509 }
12038f9f 4510 marker->charpos = mpos;
b229b8d1
RS
4511 }
4512}
4513
4514DEFUN ("transpose-regions", Ftranspose_regions, Stranspose_regions, 4, 5, 0,
412f1fab 4515 doc: /* Transpose region STARTR1 to ENDR1 with STARTR2 to ENDR2.
27a69fd9 4516The regions should not be overlapping, because the size of the buffer is
a1f17501
PJ
4517never changed in a transposition.
4518
412f1fab 4519Optional fifth arg LEAVE-MARKERS, if non-nil, means don't update
a1f17501
PJ
4520any markers that happen to be located in the regions.
4521
7ee72033 4522Transposing beyond buffer boundaries is an error. */)
5842a27b 4523 (Lisp_Object startr1, Lisp_Object endr1, Lisp_Object startr2, Lisp_Object endr2, Lisp_Object leave_markers)
b229b8d1 4524{
d311d28c
PE
4525 register ptrdiff_t start1, end1, start2, end2;
4526 ptrdiff_t start1_byte, start2_byte, len1_byte, len2_byte;
4527 ptrdiff_t gap, len1, len_mid, len2;
3c6bc7d0 4528 unsigned char *start1_addr, *start2_addr, *temp;
b229b8d1 4529
6cd0f478 4530 INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2, tmp_interval3;
916480c4
CY
4531 Lisp_Object buf;
4532
4533 XSETBUFFER (buf, current_buffer);
1e158d25 4534 cur_intv = BUF_INTERVALS (current_buffer);
b229b8d1
RS
4535
4536 validate_region (&startr1, &endr1);
4537 validate_region (&startr2, &endr2);
4538
4539 start1 = XFASTINT (startr1);
4540 end1 = XFASTINT (endr1);
4541 start2 = XFASTINT (startr2);
4542 end2 = XFASTINT (endr2);
4543 gap = GPT;
4544
4545 /* Swap the regions if they're reversed. */
4546 if (start2 < end1)
4547 {
d311d28c 4548 register ptrdiff_t glumph = start1;
b229b8d1
RS
4549 start1 = start2;
4550 start2 = glumph;
4551 glumph = end1;
4552 end1 = end2;
4553 end2 = glumph;
4554 }
4555
b229b8d1
RS
4556 len1 = end1 - start1;
4557 len2 = end2 - start2;
4558
4559 if (start2 < end1)
dc3620af 4560 error ("Transposed regions overlap");
0f4aebc0
LL
4561 /* Nothing to change for adjacent regions with one being empty */
4562 else if ((start1 == end1 || start2 == end2) && end1 == start2)
4563 return Qnil;
b229b8d1
RS
4564
4565 /* The possibilities are:
4566 1. Adjacent (contiguous) regions, or separate but equal regions
4567 (no, really equal, in this case!), or
4568 2. Separate regions of unequal size.
34a7a267 4569
b229b8d1
RS
4570 The worst case is usually No. 2. It means that (aside from
4571 potential need for getting the gap out of the way), there also
4572 needs to be a shifting of the text between the two regions. So
4573 if they are spread far apart, we are that much slower... sigh. */
4574
4575 /* It must be pointed out that the really studly thing to do would
4576 be not to move the gap at all, but to leave it in place and work
4577 around it if necessary. This would be extremely efficient,
4578 especially considering that people are likely to do
4579 transpositions near where they are working interactively, which
4580 is exactly where the gap would be found. However, such code
4581 would be much harder to write and to read. So, if you are
4582 reading this comment and are feeling squirrely, by all means have
4583 a go! I just didn't feel like doing it, so I will simply move
4584 the gap the minimum distance to get it out of the way, and then
4585 deal with an unbroken array. */
3c6bc7d0
RS
4586
4587 /* Make sure the gap won't interfere, by moving it out of the text
4588 we will operate on. */
4589 if (start1 < gap && gap < end2)
4590 {
4591 if (gap - start1 < end2 - gap)
4592 move_gap (start1);
4593 else
4594 move_gap (end2);
4595 }
ec1c14f6
RS
4596
4597 start1_byte = CHAR_TO_BYTE (start1);
4598 start2_byte = CHAR_TO_BYTE (start2);
4599 len1_byte = CHAR_TO_BYTE (end1) - start1_byte;
4600 len2_byte = CHAR_TO_BYTE (end2) - start2_byte;
dc3620af 4601
9a599130 4602#ifdef BYTE_COMBINING_DEBUG
dc3620af
RS
4603 if (end1 == start2)
4604 {
9a599130
KH
4605 if (count_combining_before (BYTE_POS_ADDR (start2_byte),
4606 len2_byte, start1, start1_byte)
4607 || count_combining_before (BYTE_POS_ADDR (start1_byte),
4608 len1_byte, end2, start2_byte + len2_byte)
4609 || count_combining_after (BYTE_POS_ADDR (start1_byte),
4610 len1_byte, end2, start2_byte + len2_byte))
4611 abort ();
dc3620af
RS
4612 }
4613 else
4614 {
9a599130
KH
4615 if (count_combining_before (BYTE_POS_ADDR (start2_byte),
4616 len2_byte, start1, start1_byte)
4617 || count_combining_before (BYTE_POS_ADDR (start1_byte),
4618 len1_byte, start2, start2_byte)
4619 || count_combining_after (BYTE_POS_ADDR (start2_byte),
4620 len2_byte, end1, start1_byte + len1_byte)
4621 || count_combining_after (BYTE_POS_ADDR (start1_byte),
4622 len1_byte, end2, start2_byte + len2_byte))
4623 abort ();
dc3620af 4624 }
9a599130 4625#endif
dc3620af 4626
b229b8d1
RS
4627 /* Hmmm... how about checking to see if the gap is large
4628 enough to use as the temporary storage? That would avoid an
4629 allocation... interesting. Later, don't fool with it now. */
4630
4631 /* Working without memmove, for portability (sigh), so must be
4632 careful of overlapping subsections of the array... */
4633
4634 if (end1 == start2) /* adjacent regions */
4635 {
3e145152 4636 modify_region (current_buffer, start1, end2, 0);
b229b8d1
RS
4637 record_change (start1, len1 + len2);
4638
b229b8d1
RS
4639 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4640 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
916480c4
CY
4641 /* Don't use Fset_text_properties: that can cause GC, which can
4642 clobber objects stored in the tmp_intervals. */
6cd0f478
CY
4643 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4644 if (!NULL_INTERVAL_P (tmp_interval3))
4645 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1
RS
4646
4647 /* First region smaller than second. */
ec1c14f6 4648 if (len1_byte < len2_byte)
b229b8d1 4649 {
7e2c051b
KS
4650 USE_SAFE_ALLOCA;
4651
4652 SAFE_ALLOCA (temp, unsigned char *, len2_byte);
03240d11
KH
4653
4654 /* Don't precompute these addresses. We have to compute them
4655 at the last minute, because the relocating allocator might
4656 have moved the buffer around during the xmalloc. */
23017390
KH
4657 start1_addr = BYTE_POS_ADDR (start1_byte);
4658 start2_addr = BYTE_POS_ADDR (start2_byte);
03240d11 4659
72af86bd
AS
4660 memcpy (temp, start2_addr, len2_byte);
4661 memcpy (start1_addr + len2_byte, start1_addr, len1_byte);
4662 memcpy (start1_addr, temp, len2_byte);
e65837df 4663 SAFE_FREE ();
b229b8d1
RS
4664 }
4665 else
4666 /* First region not smaller than second. */
4667 {
7e2c051b
KS
4668 USE_SAFE_ALLOCA;
4669
4670 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4671 start1_addr = BYTE_POS_ADDR (start1_byte);
4672 start2_addr = BYTE_POS_ADDR (start2_byte);
72af86bd
AS
4673 memcpy (temp, start1_addr, len1_byte);
4674 memcpy (start1_addr, start2_addr, len2_byte);
4675 memcpy (start1_addr + len2_byte, temp, len1_byte);
e65837df 4676 SAFE_FREE ();
b229b8d1 4677 }
b229b8d1
RS
4678 graft_intervals_into_buffer (tmp_interval1, start1 + len2,
4679 len1, current_buffer, 0);
4680 graft_intervals_into_buffer (tmp_interval2, start1,
4681 len2, current_buffer, 0);
d5c2c403
KH
4682 update_compositions (start1, start1 + len2, CHECK_BORDER);
4683 update_compositions (start1 + len2, end2, CHECK_TAIL);
b229b8d1
RS
4684 }
4685 /* Non-adjacent regions, because end1 != start2, bleagh... */
4686 else
4687 {
ec1c14f6
RS
4688 len_mid = start2_byte - (start1_byte + len1_byte);
4689
4690 if (len1_byte == len2_byte)
b229b8d1
RS
4691 /* Regions are same size, though, how nice. */
4692 {
7e2c051b
KS
4693 USE_SAFE_ALLOCA;
4694
3e145152
CY
4695 modify_region (current_buffer, start1, end1, 0);
4696 modify_region (current_buffer, start2, end2, 0);
b229b8d1
RS
4697 record_change (start1, len1);
4698 record_change (start2, len2);
b229b8d1
RS
4699 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4700 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4701
4702 tmp_interval3 = validate_interval_range (buf, &startr1, &endr1, 0);
4703 if (!NULL_INTERVAL_P (tmp_interval3))
4704 set_text_properties_1 (startr1, endr1, Qnil, buf, tmp_interval3);
4705
4706 tmp_interval3 = validate_interval_range (buf, &startr2, &endr2, 0);
4707 if (!NULL_INTERVAL_P (tmp_interval3))
4708 set_text_properties_1 (startr2, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4709
7e2c051b 4710 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4711 start1_addr = BYTE_POS_ADDR (start1_byte);
4712 start2_addr = BYTE_POS_ADDR (start2_byte);
72af86bd
AS
4713 memcpy (temp, start1_addr, len1_byte);
4714 memcpy (start1_addr, start2_addr, len2_byte);
4715 memcpy (start2_addr, temp, len1_byte);
e65837df 4716 SAFE_FREE ();
7e2c051b 4717
b229b8d1
RS
4718 graft_intervals_into_buffer (tmp_interval1, start2,
4719 len1, current_buffer, 0);
4720 graft_intervals_into_buffer (tmp_interval2, start1,
4721 len2, current_buffer, 0);
b229b8d1
RS
4722 }
4723
ec1c14f6 4724 else if (len1_byte < len2_byte) /* Second region larger than first */
b229b8d1
RS
4725 /* Non-adjacent & unequal size, area between must also be shifted. */
4726 {
7e2c051b
KS
4727 USE_SAFE_ALLOCA;
4728
3e145152 4729 modify_region (current_buffer, start1, end2, 0);
b229b8d1 4730 record_change (start1, (end2 - start1));
b229b8d1
RS
4731 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4732 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
4733 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4734
4735 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4736 if (!NULL_INTERVAL_P (tmp_interval3))
4737 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4738
3c6bc7d0 4739 /* holds region 2 */
7e2c051b 4740 SAFE_ALLOCA (temp, unsigned char *, len2_byte);
23017390
KH
4741 start1_addr = BYTE_POS_ADDR (start1_byte);
4742 start2_addr = BYTE_POS_ADDR (start2_byte);
72af86bd
AS
4743 memcpy (temp, start2_addr, len2_byte);
4744 memcpy (start1_addr + len_mid + len2_byte, start1_addr, len1_byte);
4745 memmove (start1_addr + len2_byte, start1_addr + len1_byte, len_mid);
4746 memcpy (start1_addr, temp, len2_byte);
e65837df 4747 SAFE_FREE ();
7e2c051b 4748
b229b8d1
RS
4749 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
4750 len1, current_buffer, 0);
4751 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
4752 len_mid, current_buffer, 0);
4753 graft_intervals_into_buffer (tmp_interval2, start1,
4754 len2, current_buffer, 0);
b229b8d1
RS
4755 }
4756 else
4757 /* Second region smaller than first. */
4758 {
7e2c051b
KS
4759 USE_SAFE_ALLOCA;
4760
b229b8d1 4761 record_change (start1, (end2 - start1));
3e145152 4762 modify_region (current_buffer, start1, end2, 0);
b229b8d1 4763
b229b8d1
RS
4764 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4765 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
4766 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4767
4768 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4769 if (!NULL_INTERVAL_P (tmp_interval3))
4770 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4771
3c6bc7d0 4772 /* holds region 1 */
7e2c051b 4773 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4774 start1_addr = BYTE_POS_ADDR (start1_byte);
4775 start2_addr = BYTE_POS_ADDR (start2_byte);
72af86bd
AS
4776 memcpy (temp, start1_addr, len1_byte);
4777 memcpy (start1_addr, start2_addr, len2_byte);
4778 memcpy (start1_addr + len2_byte, start1_addr + len1_byte, len_mid);
4779 memcpy (start1_addr + len2_byte + len_mid, temp, len1_byte);
e65837df 4780 SAFE_FREE ();
7e2c051b 4781
b229b8d1
RS
4782 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
4783 len1, current_buffer, 0);
4784 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
4785 len_mid, current_buffer, 0);
4786 graft_intervals_into_buffer (tmp_interval2, start1,
4787 len2, current_buffer, 0);
b229b8d1 4788 }
d5c2c403
KH
4789
4790 update_compositions (start1, start1 + len2, CHECK_BORDER);
4791 update_compositions (end2 - len1, end2, CHECK_BORDER);
b229b8d1
RS
4792 }
4793
ec1c14f6
RS
4794 /* When doing multiple transpositions, it might be nice
4795 to optimize this. Perhaps the markers in any one buffer
4796 should be organized in some sorted data tree. */
b229b8d1 4797 if (NILP (leave_markers))
8de1d5f0 4798 {
ec1c14f6
RS
4799 transpose_markers (start1, end1, start2, end2,
4800 start1_byte, start1_byte + len1_byte,
4801 start2_byte, start2_byte + len2_byte);
6b61353c 4802 fix_start_end_in_overlays (start1, end2);
8de1d5f0 4803 }
b229b8d1 4804
c10b2810 4805 signal_after_change (start1, end2 - start1, end2 - start1);
b229b8d1
RS
4806 return Qnil;
4807}
35692fe0 4808
35692fe0
JB
4809\f
4810void
971de7fb 4811syms_of_editfns (void)
35692fe0 4812{
260e2e2a 4813 environbuf = 0;
a03fc5a6 4814 initial_tz = 0;
260e2e2a 4815
cd3520a4 4816 DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions");
260e2e2a 4817
29208e82 4818 DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
7dcece14 4819 doc: /* Non-nil means text motion commands don't notice fields. */);
9a74e7e5
GM
4820 Vinhibit_field_text_motion = Qnil;
4821
260e2e2a 4822 DEFVAR_LISP ("buffer-access-fontify-functions",
29208e82 4823 Vbuffer_access_fontify_functions,
7ee72033 4824 doc: /* List of functions called by `buffer-substring' to fontify if necessary.
a1f17501
PJ
4825Each function is called with two arguments which specify the range
4826of the buffer being accessed. */);
260e2e2a
KH
4827 Vbuffer_access_fontify_functions = Qnil;
4828
af209db8
RS
4829 {
4830 Lisp_Object obuf;
af209db8
RS
4831 obuf = Fcurrent_buffer ();
4832 /* Do this here, because init_buffer_once is too early--it won't work. */
4833 Fset_buffer (Vprin1_to_string_buffer);
4834 /* Make sure buffer-access-fontify-functions is nil in this buffer. */
d67b4f80 4835 Fset (Fmake_local_variable (intern_c_string ("buffer-access-fontify-functions")),
af209db8
RS
4836 Qnil);
4837 Fset_buffer (obuf);
4838 }
4839
0b6fd023 4840 DEFVAR_LISP ("buffer-access-fontified-property",
29208e82 4841 Vbuffer_access_fontified_property,
7ee72033 4842 doc: /* Property which (if non-nil) indicates text has been fontified.
a1f17501
PJ
4843`buffer-substring' need not call the `buffer-access-fontify-functions'
4844functions if all the text being accessed has this property. */);
260e2e2a
KH
4845 Vbuffer_access_fontified_property = Qnil;
4846
29208e82 4847 DEFVAR_LISP ("system-name", Vsystem_name,
1a7e0117 4848 doc: /* The host name of the machine Emacs is running on. */);
34a7a267 4849
29208e82 4850 DEFVAR_LISP ("user-full-name", Vuser_full_name,
7ee72033 4851 doc: /* The full name of the user logged in. */);
f43754f6 4852
29208e82 4853 DEFVAR_LISP ("user-login-name", Vuser_login_name,
7ee72033 4854 doc: /* The user's name, taken from environment variables if possible. */);
f43754f6 4855
29208e82 4856 DEFVAR_LISP ("user-real-login-name", Vuser_real_login_name,
7ee72033 4857 doc: /* The user's name, based upon the real uid only. */);
35692fe0 4858
29208e82 4859 DEFVAR_LISP ("operating-system-release", Voperating_system_release,
3bb9abc8
ST
4860 doc: /* The release of the operating system Emacs is running on. */);
4861
0963334d 4862 defsubr (&Spropertize);
35692fe0
JB
4863 defsubr (&Schar_equal);
4864 defsubr (&Sgoto_char);
4865 defsubr (&Sstring_to_char);
4866 defsubr (&Schar_to_string);
c3bb441d 4867 defsubr (&Sbyte_to_string);
35692fe0 4868 defsubr (&Sbuffer_substring);
260e2e2a 4869 defsubr (&Sbuffer_substring_no_properties);
35692fe0
JB
4870 defsubr (&Sbuffer_string);
4871
4872 defsubr (&Spoint_marker);
4873 defsubr (&Smark_marker);
4874 defsubr (&Spoint);
4875 defsubr (&Sregion_beginning);
4876 defsubr (&Sregion_end);
7df74da6 4877
cd3520a4
JB
4878 DEFSYM (Qfield, "field");
4879 DEFSYM (Qboundary, "boundary");
0daf6e8d
GM
4880 defsubr (&Sfield_beginning);
4881 defsubr (&Sfield_end);
4882 defsubr (&Sfield_string);
4883 defsubr (&Sfield_string_no_properties);
8bf64fe8 4884 defsubr (&Sdelete_field);
0daf6e8d
GM
4885 defsubr (&Sconstrain_to_field);
4886
7df74da6
RS
4887 defsubr (&Sline_beginning_position);
4888 defsubr (&Sline_end_position);
4889
35692fe0
JB
4890/* defsubr (&Smark); */
4891/* defsubr (&Sset_mark); */
4892 defsubr (&Ssave_excursion);
4bc8c7d2 4893 defsubr (&Ssave_current_buffer);
35692fe0
JB
4894
4895 defsubr (&Sbufsize);
4896 defsubr (&Spoint_max);
4897 defsubr (&Spoint_min);
4898 defsubr (&Spoint_min_marker);
4899 defsubr (&Spoint_max_marker);
c86212b9
RS
4900 defsubr (&Sgap_position);
4901 defsubr (&Sgap_size);
7df74da6 4902 defsubr (&Sposition_bytes);
3ab0732d 4903 defsubr (&Sbyte_to_position);
c9ed721d 4904
35692fe0
JB
4905 defsubr (&Sbobp);
4906 defsubr (&Seobp);
4907 defsubr (&Sbolp);
4908 defsubr (&Seolp);
850a8179
JB
4909 defsubr (&Sfollowing_char);
4910 defsubr (&Sprevious_char);
35692fe0 4911 defsubr (&Schar_after);
fb8106e8 4912 defsubr (&Schar_before);
35692fe0
JB
4913 defsubr (&Sinsert);
4914 defsubr (&Sinsert_before_markers);
be91036a
RS
4915 defsubr (&Sinsert_and_inherit);
4916 defsubr (&Sinsert_and_inherit_before_markers);
35692fe0 4917 defsubr (&Sinsert_char);
48ef988f 4918 defsubr (&Sinsert_byte);
35692fe0
JB
4919
4920 defsubr (&Suser_login_name);
4921 defsubr (&Suser_real_login_name);
4922 defsubr (&Suser_uid);
4923 defsubr (&Suser_real_uid);
4924 defsubr (&Suser_full_name);
7fd233b3 4925 defsubr (&Semacs_pid);
d940e0e4 4926 defsubr (&Scurrent_time);
4211ee7d 4927 defsubr (&Sget_internal_run_time);
a82d387c 4928 defsubr (&Sformat_time_string);
34a7a267 4929 defsubr (&Sfloat_time);
4691c06d 4930 defsubr (&Sdecode_time);
cce7b8a0 4931 defsubr (&Sencode_time);
35692fe0 4932 defsubr (&Scurrent_time_string);
c2662aea 4933 defsubr (&Scurrent_time_zone);
143cb9a9 4934 defsubr (&Sset_time_zone_rule);
35692fe0 4935 defsubr (&Ssystem_name);
35692fe0 4936 defsubr (&Smessage);
cacc3e2c
RS
4937 defsubr (&Smessage_box);
4938 defsubr (&Smessage_or_box);
b14dda8a 4939 defsubr (&Scurrent_message);
35692fe0 4940 defsubr (&Sformat);
35692fe0
JB
4941
4942 defsubr (&Sinsert_buffer_substring);
e9cf2084 4943 defsubr (&Scompare_buffer_substrings);
35692fe0 4944 defsubr (&Ssubst_char_in_region);
8583605b 4945 defsubr (&Stranslate_region_internal);
35692fe0 4946 defsubr (&Sdelete_region);
7dae4502 4947 defsubr (&Sdelete_and_extract_region);
35692fe0
JB
4948 defsubr (&Swiden);
4949 defsubr (&Snarrow_to_region);
4950 defsubr (&Ssave_restriction);
b229b8d1 4951 defsubr (&Stranspose_regions);
35692fe0 4952}