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