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