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