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