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