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