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