Add 2012 to FSF copyright years for Emacs files (do not merge to trunk)
[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,
49f70d46 5 2009, 2010, 2011, 2012 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
aca092ac
SM
3350 /* Changing the buffer bounds invalidates any recorded current column. */
3351 invalidate_current_column ();
3352
d528b1ce
SM
3353 if (cur)
3354 set_buffer_internal (cur);
3355
35692fe0
JB
3356 return Qnil;
3357}
3358
3359DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
7ee72033 3360 doc: /* Execute BODY, saving and restoring current buffer's restrictions.
a1f17501 3361The buffer's restrictions make parts of the beginning and end invisible.
9671c13a 3362\(They are set up with `narrow-to-region' and eliminated with `widen'.)
a1f17501
PJ
3363This special form, `save-restriction', saves the current buffer's restrictions
3364when it is entered, and restores them when it is exited.
3365So any `narrow-to-region' within BODY lasts only until the end of the form.
3366The old restrictions settings are restored
3367even in case of abnormal exit (throw or error).
3368
3369The value returned is the value of the last form in BODY.
3370
3371Note: if you are using both `save-excursion' and `save-restriction',
3372use `save-excursion' outermost:
33c2d29f
MB
3373 (save-excursion (save-restriction ...))
3374
3375usage: (save-restriction &rest BODY) */)
7ee72033 3376 (body)
35692fe0
JB
3377 Lisp_Object body;
3378{
3379 register Lisp_Object val;
aed13378 3380 int count = SPECPDL_INDEX ();
35692fe0
JB
3381
3382 record_unwind_protect (save_restriction_restore, save_restriction_save ());
3383 val = Fprogn (body);
3384 return unbind_to (count, val);
3385}
3386\f
0ae83348 3387/* Buffer for the most recent text displayed by Fmessage_box. */
671fbc4d
KH
3388static char *message_text;
3389
3390/* Allocated length of that buffer. */
3391static int message_length;
3392
35692fe0 3393DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
db18da59 3394 doc: /* Display a message at the bottom of the screen.
281c1721
RS
3395The message also goes into the `*Messages*' buffer.
3396\(In keyboard macros, that's all it does.)
db18da59 3397Return the message.
281c1721 3398
a1f17501
PJ
3399The first argument is a format control string, and the rest are data
3400to be formatted under control of the string. See `format' for details.
3401
7bd5bcfb
KS
3402Note: Use (message "%s" VALUE) to print the value of expressions and
3403variables to avoid accidentally interpreting `%' as format specifiers.
3404
fa056b08
KS
3405If the first argument is nil or the empty string, the function clears
3406any existing message; this lets the minibuffer contents show. See
3407also `current-message'.
4bfbe194 3408
867b9600 3409usage: (message FORMAT-STRING &rest ARGS) */)
7ee72033 3410 (nargs, args)
35692fe0
JB
3411 int nargs;
3412 Lisp_Object *args;
3413{
6076e561
RS
3414 if (NILP (args[0])
3415 || (STRINGP (args[0])
3416 && SBYTES (args[0]) == 0))
f0250249
JB
3417 {
3418 message (0);
674a954a 3419 return args[0];
f0250249 3420 }
ccdac5be
JB
3421 else
3422 {
3423 register Lisp_Object val;
304f1f12 3424 val = Fformat (nargs, args);
d5db4077 3425 message3 (val, SBYTES (val), STRING_MULTIBYTE (val));
ccdac5be
JB
3426 return val;
3427 }
35692fe0
JB
3428}
3429
cacc3e2c 3430DEFUN ("message-box", Fmessage_box, Smessage_box, 1, MANY, 0,
7ee72033 3431 doc: /* Display a message, in a dialog box if possible.
a1f17501
PJ
3432If a dialog box is not available, use the echo area.
3433The first argument is a format control string, and the rest are data
3434to be formatted under control of the string. See `format' for details.
3435
fa056b08
KS
3436If the first argument is nil or the empty string, clear any existing
3437message; let the minibuffer contents show.
4bfbe194 3438
867b9600 3439usage: (message-box FORMAT-STRING &rest ARGS) */)
7ee72033 3440 (nargs, args)
cacc3e2c
RS
3441 int nargs;
3442 Lisp_Object *args;
3443{
3444 if (NILP (args[0]))
3445 {
3446 message (0);
3447 return Qnil;
3448 }
3449 else
3450 {
3451 register Lisp_Object val;
3452 val = Fformat (nargs, args);
f8250f01 3453#ifdef HAVE_MENUS
0ae83348
EZ
3454 /* The MS-DOS frames support popup menus even though they are
3455 not FRAME_WINDOW_P. */
3456 if (FRAME_WINDOW_P (XFRAME (selected_frame))
3457 || FRAME_MSDOS_P (XFRAME (selected_frame)))
cacc3e2c
RS
3458 {
3459 Lisp_Object pane, menu, obj;
3460 struct gcpro gcpro1;
3461 pane = Fcons (Fcons (build_string ("OK"), Qt), Qnil);
3462 GCPRO1 (pane);
3463 menu = Fcons (val, pane);
87944384 3464 obj = Fx_popup_dialog (Qt, menu, Qt);
cacc3e2c
RS
3465 UNGCPRO;
3466 return val;
3467 }
0ae83348 3468#endif /* HAVE_MENUS */
cacc3e2c
RS
3469 /* Copy the data so that it won't move when we GC. */
3470 if (! message_text)
3471 {
3472 message_text = (char *)xmalloc (80);
3473 message_length = 80;
3474 }
d5db4077 3475 if (SBYTES (val) > message_length)
cacc3e2c 3476 {
d5db4077 3477 message_length = SBYTES (val);
cacc3e2c
RS
3478 message_text = (char *)xrealloc (message_text, message_length);
3479 }
d5db4077
KR
3480 bcopy (SDATA (val), message_text, SBYTES (val));
3481 message2 (message_text, SBYTES (val),
d13a8480 3482 STRING_MULTIBYTE (val));
cacc3e2c 3483 return val;
cacc3e2c
RS
3484 }
3485}
f8250f01 3486#ifdef HAVE_MENUS
cacc3e2c
RS
3487extern Lisp_Object last_nonmenu_event;
3488#endif
f8250f01 3489
cacc3e2c 3490DEFUN ("message-or-box", Fmessage_or_box, Smessage_or_box, 1, MANY, 0,
7ee72033 3491 doc: /* Display a message in a dialog box or in the echo area.
a1f17501
PJ
3492If this command was invoked with the mouse, use a dialog box if
3493`use-dialog-box' is non-nil.
3494Otherwise, use the echo area.
3495The first argument is a format control string, and the rest are data
3496to be formatted under control of the string. See `format' for details.
3497
fa056b08
KS
3498If the first argument is nil or the empty string, clear any existing
3499message; let the minibuffer contents show.
4bfbe194 3500
867b9600 3501usage: (message-or-box FORMAT-STRING &rest ARGS) */)
7ee72033 3502 (nargs, args)
cacc3e2c
RS
3503 int nargs;
3504 Lisp_Object *args;
3505{
f8250f01 3506#ifdef HAVE_MENUS
5920df33 3507 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
c01fbf95 3508 && use_dialog_box)
0a56ee6b 3509 return Fmessage_box (nargs, args);
cacc3e2c
RS
3510#endif
3511 return Fmessage (nargs, args);
3512}
3513
b14dda8a 3514DEFUN ("current-message", Fcurrent_message, Scurrent_message, 0, 0, 0,
7ee72033
MB
3515 doc: /* Return the string currently displayed in the echo area, or nil if none. */)
3516 ()
b14dda8a 3517{
0634a78e 3518 return current_message ();
b14dda8a
RS
3519}
3520
2d9811c4 3521
d2936d21 3522DEFUN ("propertize", Fpropertize, Spropertize, 1, MANY, 0,
7ee72033 3523 doc: /* Return a copy of STRING with text properties added.
a1f17501
PJ
3524First argument is the string to copy.
3525Remaining arguments form a sequence of PROPERTY VALUE pairs for text
4bfbe194
MB
3526properties to add to the result.
3527usage: (propertize STRING &rest PROPERTIES) */)
7ee72033 3528 (nargs, args)
2d9811c4
GM
3529 int nargs;
3530 Lisp_Object *args;
3531{
3532 Lisp_Object properties, string;
3533 struct gcpro gcpro1, gcpro2;
3534 int i;
3535
3536 /* Number of args must be odd. */
d2936d21 3537 if ((nargs & 1) == 0 || nargs < 1)
2d9811c4
GM
3538 error ("Wrong number of arguments");
3539
3540 properties = string = Qnil;
3541 GCPRO2 (properties, string);
34a7a267 3542
2d9811c4 3543 /* First argument must be a string. */
b7826503 3544 CHECK_STRING (args[0]);
2d9811c4
GM
3545 string = Fcopy_sequence (args[0]);
3546
3547 for (i = 1; i < nargs; i += 2)
9b7a2369 3548 properties = Fcons (args[i], Fcons (args[i + 1], properties));
2d9811c4
GM
3549
3550 Fadd_text_properties (make_number (0),
d5db4077 3551 make_number (SCHARS (string)),
2d9811c4
GM
3552 properties, string);
3553 RETURN_UNGCPRO (string);
3554}
3555
3556
1f24f4fd
RS
3557/* Number of bytes that STRING will occupy when put into the result.
3558 MULTIBYTE is nonzero if the result should be multibyte. */
3559
3560#define CONVERTED_BYTE_SIZE(MULTIBYTE, STRING) \
3561 (((MULTIBYTE) && ! STRING_MULTIBYTE (STRING)) \
d5db4077
KR
3562 ? count_size_as_multibyte (SDATA (STRING), SBYTES (STRING)) \
3563 : SBYTES (STRING))
1f24f4fd 3564
35692fe0 3565DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
867b9600
JL
3566 doc: /* Format a string out of a format-string and arguments.
3567The first argument is a format control string.
a1f17501 3568The other arguments are substituted into it to make the result, a string.
575b782f
CY
3569
3570The format control string may contain %-sequences meaning to substitute
3571the next available argument:
3572
a1f17501
PJ
3573%s means print a string argument. Actually, prints any object, with `princ'.
3574%d means print as number in decimal (%o octal, %x hex).
3575%X is like %x, but uses upper case.
3576%e means print a number in exponential notation.
3577%f means print a number in decimal-point notation.
3578%g means print a number in exponential notation
3579 or decimal-point notation, whichever uses fewer characters.
3580%c means print a number as a single character.
3581%S means print any object as an s-expression (using `prin1').
575b782f
CY
3582
3583The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.
4bfbe194
MB
3584Use %% to put a single % into the output.
3585
575b782f
CY
3586A %-sequence may contain optional flag, width, and precision
3587specifiers, as follows:
3588
3589 %<flags><width><precision>character
3590
3591where flags is [+ #-0]+, width is [0-9]+, and precision is .[0-9]+
3592
3593The + flag character inserts a + before any positive number, while a
3594space inserts a space before any positive number; these flags only
3595affect %d, %e, %f, and %g sequences, and the + flag takes precedence.
3596The # flag means to use an alternate display form for %o, %x, %X, %e,
3597%f, and %g sequences. The - and 0 flags affect the width specifier,
3598as described below.
3599
3600The width specifier supplies a lower limit for the length of the
3601printed representation. The padding, if any, normally goes on the
3602left, but it goes on the right if the - flag is present. The padding
3603character is normally a space, but it is 0 if the 0 flag is present.
3604The - flag takes precedence over the 0 flag.
3605
3606For %e, %f, and %g sequences, the number after the "." in the
3607precision specifier says how many decimal places to show; if zero, the
3608decimal point itself is omitted. For %s and %S, the precision
3609specifier truncates the string to the given width.
f555f8cf 3610
4bfbe194 3611usage: (format STRING &rest OBJECTS) */)
7ee72033 3612 (nargs, args)
35692fe0
JB
3613 int nargs;
3614 register Lisp_Object *args;
3615{
3616 register int n; /* The number of the next arg to substitute */
e781c49e 3617 register int total; /* An estimate of the final length */
1f24f4fd 3618 char *buf, *p;
d147ee84 3619 register unsigned char *format, *end, *format_start;
2ea0266e 3620 int nchars;
1f24f4fd
RS
3621 /* Nonzero if the output should be a multibyte string,
3622 which is true if any of the inputs is one. */
3623 int multibyte = 0;
8f2917e4
KH
3624 /* When we make a multibyte string, we must pay attention to the
3625 byte combining problem, i.e., a byte may be combined with a
8307f923 3626 multibyte character of the previous string. This flag tells if we
8f2917e4
KH
3627 must consider such a situation or not. */
3628 int maybe_combine_byte;
1f24f4fd 3629 unsigned char *this_format;
ac42d7b9 3630 /* Precision for each spec, or -1, a flag value meaning no precision
8307f923 3631 was given in that spec. Element 0, corresponding to the format
ac42d7b9
KG
3632 string itself, will not be used. Element NARGS, corresponding to
3633 no argument, *will* be assigned to in the case that a `%' and `.'
3634 occur after the final format specifier. */
6b61353c 3635 int *precision = (int *) (alloca((nargs + 1) * sizeof (int)));
e781c49e 3636 int longest_format;
8d6179dc 3637 Lisp_Object val;
d147ee84 3638 int arg_intervals = 0;
7e2c051b 3639 USE_SAFE_ALLOCA;
d147ee84
RS
3640
3641 /* discarded[I] is 1 if byte I of the format
3642 string was not copied into the output.
3643 It is 2 if byte I was not the first byte of its character. */
e65837df 3644 char *discarded = 0;
d147ee84
RS
3645
3646 /* Each element records, for one argument,
3647 the start and end bytepos in the output string,
3648 and whether the argument is a string with intervals.
3649 info[0] is unused. Unused elements have -1 for start. */
5e6d5493
GM
3650 struct info
3651 {
d147ee84 3652 int start, end, intervals;
5e6d5493 3653 } *info = 0;
1f24f4fd 3654
35692fe0
JB
3655 /* It should not be necessary to GCPRO ARGS, because
3656 the caller in the interpreter should take care of that. */
3657
e781c49e
RS
3658 /* Try to determine whether the result should be multibyte.
3659 This is not always right; sometimes the result needs to be multibyte
3660 because of an object that we will pass through prin1,
3661 and in that case, we won't know it here. */
d147ee84
RS
3662 for (n = 0; n < nargs; n++)
3663 {
3664 if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
3665 multibyte = 1;
3666 /* Piggyback on this loop to initialize precision[N]. */
3667 precision[n] = -1;
3668 }
7c111482 3669 precision[nargs] = -1;
1f24f4fd 3670
b7826503 3671 CHECK_STRING (args[0]);
aa8b70ae
KH
3672 /* We may have to change "%S" to "%s". */
3673 args[0] = Fcopy_sequence (args[0]);
e781c49e 3674
67965a98
RS
3675 /* GC should never happen here, so abort if it does. */
3676 abort_on_gc++;
3677
e781c49e 3678 /* If we start out planning a unibyte result,
67965a98
RS
3679 then discover it has to be multibyte, we jump back to retry.
3680 That can only happen from the first large while loop below. */
e781c49e
RS
3681 retry:
3682
d5db4077 3683 format = SDATA (args[0]);
d147ee84 3684 format_start = format;
d5db4077 3685 end = format + SBYTES (args[0]);
e781c49e 3686 longest_format = 0;
1f24f4fd
RS
3687
3688 /* Make room in result for all the non-%-codes in the control string. */
7e2c051b 3689 total = 5 + CONVERTED_BYTE_SIZE (multibyte, args[0]) + 1;
1f24f4fd 3690
6b61353c 3691 /* Allocate the info and discarded tables. */
d147ee84 3692 {
7c111482 3693 int nbytes = (nargs+1) * sizeof *info;
d147ee84 3694 int i;
e65837df
KS
3695 if (!info)
3696 info = (struct info *) alloca (nbytes);
d147ee84 3697 bzero (info, nbytes);
7c111482 3698 for (i = 0; i <= nargs; i++)
d147ee84 3699 info[i].start = -1;
e65837df
KS
3700 if (!discarded)
3701 SAFE_ALLOCA (discarded, char *, SBYTES (args[0]));
d147ee84
RS
3702 bzero (discarded, SBYTES (args[0]));
3703 }
3704
1f24f4fd 3705 /* Add to TOTAL enough space to hold the converted arguments. */
35692fe0
JB
3706
3707 n = 0;
3708 while (format != end)
3709 if (*format++ == '%')
3710 {
a432bfe5 3711 int thissize = 0;
308dd672 3712 int actual_width = 0;
1f24f4fd 3713 unsigned char *this_format_start = format - 1;
ac42d7b9 3714 int field_width = 0;
35692fe0 3715
a432bfe5 3716 /* General format specifications look like
537dfb13 3717
a432bfe5
GM
3718 '%' [flags] [field-width] [precision] format
3719
3720 where
3721
cb06e570 3722 flags ::= [-+ #0]+
a432bfe5
GM
3723 field-width ::= [0-9]+
3724 precision ::= '.' [0-9]*
3725
3726 If a field-width is specified, it specifies to which width
e0f24100 3727 the output should be padded with blanks, if the output
a432bfe5
GM
3728 string is shorter than field-width.
3729
ac42d7b9 3730 If precision is specified, it specifies the number of
a432bfe5
GM
3731 digits to print after the '.' for floats, or the max.
3732 number of chars to print from a string. */
3733
913f73d4
RS
3734 while (format != end
3735 && (*format == '-' || *format == '0' || *format == '#'
cb06e570 3736 || * format == ' ' || *format == '+'))
a432bfe5
GM
3737 ++format;
3738
3739 if (*format >= '0' && *format <= '9')
3740 {
3741 for (field_width = 0; *format >= '0' && *format <= '9'; ++format)
3742 field_width = 10 * field_width + *format - '0';
3743 }
3744
ac42d7b9
KG
3745 /* N is not incremented for another few lines below, so refer to
3746 element N+1 (which might be precision[NARGS]). */
a432bfe5
GM
3747 if (*format == '.')
3748 {
3749 ++format;
ac42d7b9
KG
3750 for (precision[n+1] = 0; *format >= '0' && *format <= '9'; ++format)
3751 precision[n+1] = 10 * precision[n+1] + *format - '0';
a432bfe5 3752 }
35692fe0 3753
6e1ada1b
AS
3754 /* Extra +1 for 'l' that we may need to insert into the
3755 format. */
3756 if (format - this_format_start + 2 > longest_format)
3757 longest_format = format - this_format_start + 2;
1f24f4fd 3758
bf6ab66c
KH
3759 if (format == end)
3760 error ("Format string ends in middle of format specifier");
35692fe0
JB
3761 if (*format == '%')
3762 format++;
3763 else if (++n >= nargs)
537dfb13 3764 error ("Not enough arguments for format string");
35692fe0
JB
3765 else if (*format == 'S')
3766 {
3767 /* For `S', prin1 the argument and then treat like a string. */
3768 register Lisp_Object tem;
3769 tem = Fprin1_to_string (args[n], Qnil);
e781c49e
RS
3770 if (STRING_MULTIBYTE (tem) && ! multibyte)
3771 {
3772 multibyte = 1;
3773 goto retry;
3774 }
35692fe0 3775 args[n] = tem;
aa8b70ae
KH
3776 /* If we restart the loop, we should not come here again
3777 because args[n] is now a string and calling
3778 Fprin1_to_string on it produces superflous double
3779 quotes. So, change "%S" to "%s" now. */
3780 *format = 's';
35692fe0
JB
3781 goto string;
3782 }
ae683129 3783 else if (SYMBOLP (args[n]))
35692fe0 3784 {
1e5d9116 3785 args[n] = SYMBOL_NAME (args[n]);
7df74da6
RS
3786 if (STRING_MULTIBYTE (args[n]) && ! multibyte)
3787 {
3788 multibyte = 1;
3789 goto retry;
3790 }
35692fe0
JB
3791 goto string;
3792 }
ae683129 3793 else if (STRINGP (args[n]))
35692fe0
JB
3794 {
3795 string:
b22e7ecc 3796 if (*format != 's' && *format != 'S')
bf6ab66c 3797 error ("Format specifier doesn't match argument type");
ac42d7b9
KG
3798 /* In the case (PRECISION[N] > 0), THISSIZE may not need
3799 to be as large as is calculated here. Easy check for
3800 the case PRECISION = 0. */
3801 thissize = precision[n] ? CONVERTED_BYTE_SIZE (multibyte, args[n]) : 0;
35cd7cd6
CY
3802 /* The precision also constrains how much of the argument
3803 string will finally appear (Bug#5710). */
308dd672 3804 actual_width = lisp_string_width (args[n], -1, NULL, NULL);
35cd7cd6
CY
3805 if (precision[n] != -1)
3806 actual_width = min(actual_width,precision[n]);
35692fe0
JB
3807 }
3808 /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */
ae683129 3809 else if (INTEGERP (args[n]) && *format != 's')
35692fe0 3810 {
eb8c3be9 3811 /* The following loop assumes the Lisp type indicates
35692fe0
JB
3812 the proper way to pass the argument.
3813 So make sure we have a flonum if the argument should
3814 be a double. */
3815 if (*format == 'e' || *format == 'f' || *format == 'g')
3816 args[n] = Ffloat (args[n]);
4224cb62 3817 else
4224cb62 3818 if (*format != 'd' && *format != 'o' && *format != 'x'
00d65216 3819 && *format != 'i' && *format != 'X' && *format != 'c')
4224cb62
KH
3820 error ("Invalid format operation %%%c", *format);
3821
0e4df721 3822 thissize = 30 + (precision[n] > 0 ? precision[n] : 0);
063b53b1 3823 if (*format == 'c')
f49a2d74 3824 {
8f924df7 3825 if (! ASCII_CHAR_P (XINT (args[n]))
231a3316
KH
3826 /* Note: No one can remeber why we have to treat
3827 the character 0 as a multibyte character here.
3828 But, until it causes a real problem, let's
3829 don't change it. */
063b53b1 3830 || XINT (args[n]) == 0)
f49a2d74 3831 {
063b53b1
KH
3832 if (! multibyte)
3833 {
3834 multibyte = 1;
3835 goto retry;
3836 }
3837 args[n] = Fchar_to_string (args[n]);
3838 thissize = SBYTES (args[n]);
3839 }
3840 else if (! ASCII_BYTE_P (XINT (args[n])) && multibyte)
3841 {
3842 args[n]
3843 = Fchar_to_string (Funibyte_char_to_multibyte (args[n]));
3844 thissize = SBYTES (args[n]);
f49a2d74 3845 }
f49a2d74 3846 }
35692fe0 3847 }
ae683129 3848 else if (FLOATP (args[n]) && *format != 's')
35692fe0
JB
3849 {
3850 if (! (*format == 'e' || *format == 'f' || *format == 'g'))
f98176d2
RS
3851 {
3852 if (*format != 'd' && *format != 'o' && *format != 'x'
3853 && *format != 'i' && *format != 'X' && *format != 'c')
3854 error ("Invalid format operation %%%c", *format);
c5c6b2cc
SM
3855 /* This fails unnecessarily if args[n] is bigger than
3856 most-positive-fixnum but smaller than MAXINT.
3857 These cases are important because we sometimes use floats
3858 to represent such integer values (typically such values
3859 come from UIDs or PIDs). */
3860 /* args[n] = Ftruncate (args[n], Qnil); */
f98176d2 3861 }
a432bfe5
GM
3862
3863 /* Note that we're using sprintf to print floats,
3864 so we have to take into account what that function
3865 prints. */
b11f1d8a 3866 /* Filter out flag value of -1. */
6b381c3a
RS
3867 thissize = (MAX_10_EXP + 100
3868 + (precision[n] > 0 ? precision[n] : 0));
35692fe0
JB
3869 }
3870 else
3871 {
3872 /* Anything but a string, convert to a string using princ. */
3873 register Lisp_Object tem;
3874 tem = Fprin1_to_string (args[n], Qt);
f555f8cf 3875 if (STRING_MULTIBYTE (tem) && ! multibyte)
e781c49e
RS
3876 {
3877 multibyte = 1;
3878 goto retry;
3879 }
35692fe0
JB
3880 args[n] = tem;
3881 goto string;
3882 }
34a7a267 3883
308dd672 3884 thissize += max (0, field_width - actual_width);
1f24f4fd 3885 total += thissize + 4;
35692fe0
JB
3886 }
3887
67965a98
RS
3888 abort_on_gc--;
3889
e781c49e
RS
3890 /* Now we can no longer jump to retry.
3891 TOTAL and LONGEST_FORMAT are known for certain. */
3892
1f24f4fd 3893 this_format = (unsigned char *) alloca (longest_format + 1);
50aa2f90 3894
1f24f4fd
RS
3895 /* Allocate the space for the result.
3896 Note that TOTAL is an overestimate. */
7e2c051b 3897 SAFE_ALLOCA (buf, char *, total);
35692fe0 3898
1f24f4fd
RS
3899 p = buf;
3900 nchars = 0;
3901 n = 0;
35692fe0 3902
1f24f4fd 3903 /* Scan the format and store result in BUF. */
d5db4077 3904 format = SDATA (args[0]);
67965a98
RS
3905 format_start = format;
3906 end = format + SBYTES (args[0]);
8f2917e4 3907 maybe_combine_byte = 0;
1f24f4fd
RS
3908 while (format != end)
3909 {
3910 if (*format == '%')
3911 {
3912 int minlen;
25c9e7fb 3913 int negative = 0;
1f24f4fd 3914 unsigned char *this_format_start = format;
35692fe0 3915
d147ee84 3916 discarded[format - format_start] = 1;
1f24f4fd 3917 format++;
fb893977 3918
cb06e570 3919 while (index("-+0# ", *format))
f555f8cf
KH
3920 {
3921 if (*format == '-')
3922 {
3923 negative = 1;
3924 }
3925 discarded[format - format_start] = 1;
3926 ++format;
3927 }
3928
1f24f4fd 3929 minlen = atoi (format);
f555f8cf
KH
3930
3931 while ((*format >= '0' && *format <= '9') || *format == '.')
d147ee84
RS
3932 {
3933 discarded[format - format_start] = 1;
3934 format++;
3935 }
35692fe0 3936
1f24f4fd
RS
3937 if (*format++ == '%')
3938 {
3939 *p++ = '%';
3940 nchars++;
3941 continue;
3942 }
3943
3944 ++n;
3945
d147ee84
RS
3946 discarded[format - format_start - 1] = 1;
3947 info[n].start = nchars;
3948
1f24f4fd
RS
3949 if (STRINGP (args[n]))
3950 {
ac42d7b9
KG
3951 /* handle case (precision[n] >= 0) */
3952
3953 int width, padding;
3954 int nbytes, start, end;
3955 int nchars_string;
3956
3957 /* lisp_string_width ignores a precision of 0, but GNU
3958 libc functions print 0 characters when the precision
3959 is 0. Imitate libc behavior here. Changing
3960 lisp_string_width is the right thing, and will be
3961 done, but meanwhile we work with it. */
3962
3963 if (precision[n] == 0)
3964 width = nchars_string = nbytes = 0;
3965 else if (precision[n] > 0)
3966 width = lisp_string_width (args[n], precision[n], &nchars_string, &nbytes);
3967 else
3968 { /* no precision spec given for this argument */
3969 width = lisp_string_width (args[n], -1, NULL, NULL);
3970 nbytes = SBYTES (args[n]);
3971 nchars_string = SCHARS (args[n]);
3972 }
25c9e7fb
RS
3973
3974 /* If spec requires it, pad on right with spaces. */
3975 padding = minlen - width;
3976 if (! negative)
3977 while (padding-- > 0)
3978 {
3979 *p++ = ' ';
50606b4c 3980 ++nchars;
25c9e7fb 3981 }
1f24f4fd 3982
8f2c9ed8 3983 info[n].start = start = nchars;
ac42d7b9
KG
3984 nchars += nchars_string;
3985 end = nchars;
3986
8f2917e4
KH
3987 if (p > buf
3988 && multibyte
25aa5d64 3989 && !ASCII_BYTE_P (*((unsigned char *) p - 1))
8f2917e4 3990 && STRING_MULTIBYTE (args[n])
d5db4077 3991 && !CHAR_HEAD_P (SREF (args[n], 0)))
8f2917e4 3992 maybe_combine_byte = 1;
ac42d7b9
KG
3993
3994 p += copy_text (SDATA (args[n]), p,
3995 nbytes,
3996 STRING_MULTIBYTE (args[n]), multibyte);
1f24f4fd 3997
8f2c9ed8
RS
3998 info[n].end = nchars;
3999
25c9e7fb
RS
4000 if (negative)
4001 while (padding-- > 0)
4002 {
4003 *p++ = ' ';
4004 nchars++;
4005 }
5e6d5493
GM
4006
4007 /* If this argument has text properties, record where
4008 in the result string it appears. */
d5db4077 4009 if (STRING_INTERVALS (args[n]))
d147ee84 4010 info[n].intervals = arg_intervals = 1;
1f24f4fd
RS
4011 }
4012 else if (INTEGERP (args[n]) || FLOATP (args[n]))
4013 {
4014 int this_nchars;
4015
4016 bcopy (this_format_start, this_format,
4017 format - this_format_start);
4018 this_format[format - this_format_start] = 0;
4019
0f860bd7
AS
4020 if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g')
4021 sprintf (p, this_format, XFLOAT_DATA (args[n]));
4022 else
de92d4d4 4023 {
ff6e6ac8
AS
4024 if (sizeof (EMACS_INT) > sizeof (int)
4025 && format[-1] != 'c')
0f860bd7
AS
4026 {
4027 /* Insert 'l' before format spec. */
4028 this_format[format - this_format_start]
4029 = this_format[format - this_format_start - 1];
4030 this_format[format - this_format_start - 1] = 'l';
4031 this_format[format - this_format_start + 1] = 0;
4032 }
4033
ff6e6ac8
AS
4034 if (INTEGERP (args[n]))
4035 {
4036 if (format[-1] == 'c')
4037 sprintf (p, this_format, (int) XINT (args[n]));
4038 else if (format[-1] == 'd')
4039 sprintf (p, this_format, XINT (args[n]));
4040 /* Don't sign-extend for octal or hex printing. */
4041 else
4042 sprintf (p, this_format, XUINT (args[n]));
4043 }
4044 else if (format[-1] == 'c')
4045 sprintf (p, this_format, (int) XFLOAT_DATA (args[n]));
4046 else if (format[-1] == 'd')
4047 /* Maybe we should use "%1.0f" instead so it also works
4048 for values larger than MAXINT. */
4049 sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n]));
de92d4d4 4050 else
0f860bd7 4051 /* Don't sign-extend for octal or hex printing. */
ff6e6ac8 4052 sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA (args[n]));
de92d4d4 4053 }
1f24f4fd 4054
8f2917e4
KH
4055 if (p > buf
4056 && multibyte
25aa5d64
KH
4057 && !ASCII_BYTE_P (*((unsigned char *) p - 1))
4058 && !CHAR_HEAD_P (*((unsigned char *) p)))
8f2917e4 4059 maybe_combine_byte = 1;
1f24f4fd 4060 this_nchars = strlen (p);
9a599130 4061 if (multibyte)
7e2c051b 4062 p += str_to_multibyte (p, buf + total - 1 - p, this_nchars);
9a599130
KH
4063 else
4064 p += this_nchars;
1f24f4fd 4065 nchars += this_nchars;
8f2c9ed8 4066 info[n].end = nchars;
1f24f4fd 4067 }
d147ee84 4068
1f24f4fd 4069 }
7df74da6
RS
4070 else if (STRING_MULTIBYTE (args[0]))
4071 {
4072 /* Copy a whole multibyte character. */
8f2917e4
KH
4073 if (p > buf
4074 && multibyte
25aa5d64
KH
4075 && !ASCII_BYTE_P (*((unsigned char *) p - 1))
4076 && !CHAR_HEAD_P (*format))
8f2917e4 4077 maybe_combine_byte = 1;
7df74da6 4078 *p++ = *format++;
d147ee84
RS
4079 while (! CHAR_HEAD_P (*format))
4080 {
4081 discarded[format - format_start] = 2;
4082 *p++ = *format++;
4083 }
7df74da6
RS
4084 nchars++;
4085 }
4086 else if (multibyte)
1f24f4fd
RS
4087 {
4088 /* Convert a single-byte character to multibyte. */
4089 int len = copy_text (format, p, 1, 0, 1);
4090
4091 p += len;
4092 format++;
4093 nchars++;
4094 }
4095 else
4096 *p++ = *format++, nchars++;
4097 }
4098
7e2c051b 4099 if (p > buf + total)
a432bfe5
GM
4100 abort ();
4101
8f2917e4
KH
4102 if (maybe_combine_byte)
4103 nchars = multibyte_chars_in_text (buf, p - buf);
5f75e666 4104 val = make_specified_string (buf, nchars, p - buf, multibyte);
8d6179dc 4105
1f24f4fd 4106 /* If we allocated BUF with malloc, free it too. */
e65837df 4107 SAFE_FREE ();
35692fe0 4108
5e6d5493
GM
4109 /* If the format string has text properties, or any of the string
4110 arguments has text properties, set up text properties of the
4111 result string. */
34a7a267 4112
d147ee84 4113 if (STRING_INTERVALS (args[0]) || arg_intervals)
5e6d5493
GM
4114 {
4115 Lisp_Object len, new_len, props;
4116 struct gcpro gcpro1;
34a7a267 4117
5e6d5493 4118 /* Add text properties from the format string. */
d5db4077 4119 len = make_number (SCHARS (args[0]));
5e6d5493
GM
4120 props = text_property_list (args[0], make_number (0), len, Qnil);
4121 GCPRO1 (props);
34a7a267 4122
5e6d5493
GM
4123 if (CONSP (props))
4124 {
d147ee84
RS
4125 int bytepos = 0, position = 0, translated = 0, argn = 1;
4126 Lisp_Object list;
4127
4128 /* Adjust the bounds of each text property
4129 to the proper start and end in the output string. */
d147ee84 4130
15fad037
KS
4131 /* Put the positions in PROPS in increasing order, so that
4132 we can do (effectively) one scan through the position
4133 space of the format string. */
4134 props = Fnreverse (props);
4135
4136 /* BYTEPOS is the byte position in the format string,
d147ee84
RS
4137 POSITION is the untranslated char position in it,
4138 TRANSLATED is the translated char position in BUF,
4139 and ARGN is the number of the next arg we will come to. */
4140 for (list = props; CONSP (list); list = XCDR (list))
4141 {
f3ce1df8
SM
4142 Lisp_Object item;
4143 int pos;
d147ee84
RS
4144
4145 item = XCAR (list);
4146
4147 /* First adjust the property start position. */
4148 pos = XINT (XCAR (item));
4149
4150 /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN
4151 up to this position. */
4152 for (; position < pos; bytepos++)
4153 {
4154 if (! discarded[bytepos])
4155 position++, translated++;
4156 else if (discarded[bytepos] == 1)
4157 {
4158 position++;
4159 if (translated == info[argn].start)
4160 {
4161 translated += info[argn].end - info[argn].start;
4162 argn++;
4163 }
4164 }
4165 }
4166
4167 XSETCAR (item, make_number (translated));
4168
4169 /* Likewise adjust the property end position. */
4170 pos = XINT (XCAR (XCDR (item)));
4171
d40ec4a0 4172 for (; position < pos; bytepos++)
d147ee84
RS
4173 {
4174 if (! discarded[bytepos])
4175 position++, translated++;
4176 else if (discarded[bytepos] == 1)
4177 {
4178 position++;
4179 if (translated == info[argn].start)
4180 {
4181 translated += info[argn].end - info[argn].start;
4182 argn++;
4183 }
4184 }
4185 }
4186
4187 XSETCAR (XCDR (item), make_number (translated));
4188 }
4189
5e6d5493
GM
4190 add_text_properties_from_list (val, props, make_number (0));
4191 }
4192
4193 /* Add text properties from arguments. */
d147ee84 4194 if (arg_intervals)
5e6d5493 4195 for (n = 1; n < nargs; ++n)
d147ee84 4196 if (info[n].intervals)
5e6d5493 4197 {
d5db4077 4198 len = make_number (SCHARS (args[n]));
5e6d5493
GM
4199 new_len = make_number (info[n].end - info[n].start);
4200 props = text_property_list (args[n], make_number (0), len, Qnil);
e398c61c
CY
4201 props = extend_property_ranges (props, new_len);
4202 /* If successive arguments have properties, be sure that
be17069b
KH
4203 the value of `composition' property be the copy. */
4204 if (n > 1 && info[n - 1].end)
4205 make_composition_value_copy (props);
5e6d5493
GM
4206 add_text_properties_from_list (val, props,
4207 make_number (info[n].start));
4208 }
4209
4210 UNGCPRO;
4211 }
4212
8d6179dc 4213 return val;
35692fe0
JB
4214}
4215
35692fe0 4216Lisp_Object
d40dc1d0 4217format2 (string1, arg0, arg1)
35692fe0 4218 char *string1;
d40dc1d0
RS
4219 Lisp_Object arg0, arg1;
4220{
4221 Lisp_Object args[3];
d40dc1d0
RS
4222 args[0] = build_string (string1);
4223 args[1] = arg0;
4224 args[2] = arg1;
4225 return Fformat (3, args);
35692fe0
JB
4226}
4227\f
4228DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
7ee72033 4229 doc: /* Return t if two characters match, optionally ignoring case.
a1f17501 4230Both arguments must be characters (i.e. integers).
7ee72033
MB
4231Case is ignored if `case-fold-search' is non-nil in the current buffer. */)
4232 (c1, c2)
35692fe0
JB
4233 register Lisp_Object c1, c2;
4234{
1b5d98bb 4235 int i1, i2;
253c3c82
SM
4236 /* Check they're chars, not just integers, otherwise we could get array
4237 bounds violations in DOWNCASE. */
4238 CHECK_CHARACTER (c1);
4239 CHECK_CHARACTER (c2);
35692fe0 4240
1b5d98bb 4241 if (XINT (c1) == XINT (c2))
35692fe0 4242 return Qt;
1b5d98bb
RS
4243 if (NILP (current_buffer->case_fold_search))
4244 return Qnil;
4245
4246 /* Do these in separate statements,
4247 then compare the variables.
4248 because of the way DOWNCASE uses temp variables. */
e5112ecb
KH
4249 i1 = XFASTINT (c1);
4250 if (NILP (current_buffer->enable_multibyte_characters)
4251 && ! ASCII_CHAR_P (i1))
4252 {
4253 MAKE_CHAR_MULTIBYTE (i1);
4254 }
4255 i2 = XFASTINT (c2);
4256 if (NILP (current_buffer->enable_multibyte_characters)
4257 && ! ASCII_CHAR_P (i2))
4258 {
4259 MAKE_CHAR_MULTIBYTE (i2);
4260 }
4261 i1 = DOWNCASE (i1);
4262 i2 = DOWNCASE (i2);
1b5d98bb 4263 return (i1 == i2 ? Qt : Qnil);
35692fe0 4264}
b229b8d1
RS
4265\f
4266/* Transpose the markers in two regions of the current buffer, and
4267 adjust the ones between them if necessary (i.e.: if the regions
4268 differ in size).
4269
ec1c14f6
RS
4270 START1, END1 are the character positions of the first region.
4271 START1_BYTE, END1_BYTE are the byte positions.
4272 START2, END2 are the character positions of the second region.
4273 START2_BYTE, END2_BYTE are the byte positions.
4274
b229b8d1
RS
4275 Traverses the entire marker list of the buffer to do so, adding an
4276 appropriate amount to some, subtracting from some, and leaving the
4277 rest untouched. Most of this is copied from adjust_markers in insdel.c.
34a7a267 4278
ec1c14f6 4279 It's the caller's job to ensure that START1 <= END1 <= START2 <= END2. */
b229b8d1 4280
acb7cc89 4281static void
ec1c14f6
RS
4282transpose_markers (start1, end1, start2, end2,
4283 start1_byte, end1_byte, start2_byte, end2_byte)
b229b8d1 4284 register int start1, end1, start2, end2;
ec1c14f6 4285 register int start1_byte, end1_byte, start2_byte, end2_byte;
b229b8d1 4286{
ec1c14f6 4287 register int amt1, amt1_byte, amt2, amt2_byte, diff, diff_byte, mpos;
12038f9f 4288 register struct Lisp_Marker *marker;
b229b8d1 4289
03240d11 4290 /* Update point as if it were a marker. */
8de1d5f0
KH
4291 if (PT < start1)
4292 ;
4293 else if (PT < end1)
ec1c14f6
RS
4294 TEMP_SET_PT_BOTH (PT + (end2 - end1),
4295 PT_BYTE + (end2_byte - end1_byte));
8de1d5f0 4296 else if (PT < start2)
ec1c14f6
RS
4297 TEMP_SET_PT_BOTH (PT + (end2 - start2) - (end1 - start1),
4298 (PT_BYTE + (end2_byte - start2_byte)
4299 - (end1_byte - start1_byte)));
8de1d5f0 4300 else if (PT < end2)
ec1c14f6
RS
4301 TEMP_SET_PT_BOTH (PT - (start2 - start1),
4302 PT_BYTE - (start2_byte - start1_byte));
8de1d5f0 4303
03240d11
KH
4304 /* We used to adjust the endpoints here to account for the gap, but that
4305 isn't good enough. Even if we assume the caller has tried to move the
4306 gap out of our way, it might still be at start1 exactly, for example;
4307 and that places it `inside' the interval, for our purposes. The amount
4308 of adjustment is nontrivial if there's a `denormalized' marker whose
4309 position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
4310 the dirty work to Fmarker_position, below. */
b229b8d1
RS
4311
4312 /* The difference between the region's lengths */
4313 diff = (end2 - start2) - (end1 - start1);
ec1c14f6 4314 diff_byte = (end2_byte - start2_byte) - (end1_byte - start1_byte);
34a7a267 4315
b229b8d1 4316 /* For shifting each marker in a region by the length of the other
ec1c14f6 4317 region plus the distance between the regions. */
b229b8d1
RS
4318 amt1 = (end2 - start2) + (start2 - end1);
4319 amt2 = (end1 - start1) + (start2 - end1);
ec1c14f6
RS
4320 amt1_byte = (end2_byte - start2_byte) + (start2_byte - end1_byte);
4321 amt2_byte = (end1_byte - start1_byte) + (start2_byte - end1_byte);
b229b8d1 4322
12038f9f 4323 for (marker = BUF_MARKERS (current_buffer); marker; marker = marker->next)
b229b8d1 4324 {
12038f9f 4325 mpos = marker->bytepos;
ec1c14f6
RS
4326 if (mpos >= start1_byte && mpos < end2_byte)
4327 {
4328 if (mpos < end1_byte)
4329 mpos += amt1_byte;
4330 else if (mpos < start2_byte)
4331 mpos += diff_byte;
4332 else
4333 mpos -= amt2_byte;
12038f9f 4334 marker->bytepos = mpos;
ec1c14f6 4335 }
12038f9f 4336 mpos = marker->charpos;
03240d11
KH
4337 if (mpos >= start1 && mpos < end2)
4338 {
4339 if (mpos < end1)
4340 mpos += amt1;
4341 else if (mpos < start2)
4342 mpos += diff;
4343 else
4344 mpos -= amt2;
03240d11 4345 }
12038f9f 4346 marker->charpos = mpos;
b229b8d1
RS
4347 }
4348}
4349
4350DEFUN ("transpose-regions", Ftranspose_regions, Stranspose_regions, 4, 5, 0,
412f1fab 4351 doc: /* Transpose region STARTR1 to ENDR1 with STARTR2 to ENDR2.
27a69fd9 4352The regions should not be overlapping, because the size of the buffer is
a1f17501
PJ
4353never changed in a transposition.
4354
412f1fab 4355Optional fifth arg LEAVE-MARKERS, if non-nil, means don't update
a1f17501
PJ
4356any markers that happen to be located in the regions.
4357
7ee72033
MB
4358Transposing beyond buffer boundaries is an error. */)
4359 (startr1, endr1, startr2, endr2, leave_markers)
b229b8d1
RS
4360 Lisp_Object startr1, endr1, startr2, endr2, leave_markers;
4361{
d47ecf8b
SM
4362 register EMACS_INT start1, end1, start2, end2;
4363 EMACS_INT start1_byte, start2_byte, len1_byte, len2_byte;
4364 EMACS_INT gap, len1, len_mid, len2;
3c6bc7d0 4365 unsigned char *start1_addr, *start2_addr, *temp;
b229b8d1 4366
6cd0f478 4367 INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2, tmp_interval3;
916480c4
CY
4368 Lisp_Object buf;
4369
4370 XSETBUFFER (buf, current_buffer);
1e158d25 4371 cur_intv = BUF_INTERVALS (current_buffer);
b229b8d1
RS
4372
4373 validate_region (&startr1, &endr1);
4374 validate_region (&startr2, &endr2);
4375
4376 start1 = XFASTINT (startr1);
4377 end1 = XFASTINT (endr1);
4378 start2 = XFASTINT (startr2);
4379 end2 = XFASTINT (endr2);
4380 gap = GPT;
4381
4382 /* Swap the regions if they're reversed. */
4383 if (start2 < end1)
4384 {
4385 register int glumph = start1;
4386 start1 = start2;
4387 start2 = glumph;
4388 glumph = end1;
4389 end1 = end2;
4390 end2 = glumph;
4391 }
4392
b229b8d1
RS
4393 len1 = end1 - start1;
4394 len2 = end2 - start2;
4395
4396 if (start2 < end1)
dc3620af 4397 error ("Transposed regions overlap");
b229b8d1 4398 else if (start1 == end1 || start2 == end2)
dc3620af 4399 error ("Transposed region has length 0");
b229b8d1
RS
4400
4401 /* The possibilities are:
4402 1. Adjacent (contiguous) regions, or separate but equal regions
4403 (no, really equal, in this case!), or
4404 2. Separate regions of unequal size.
34a7a267 4405
b229b8d1
RS
4406 The worst case is usually No. 2. It means that (aside from
4407 potential need for getting the gap out of the way), there also
4408 needs to be a shifting of the text between the two regions. So
4409 if they are spread far apart, we are that much slower... sigh. */
4410
4411 /* It must be pointed out that the really studly thing to do would
4412 be not to move the gap at all, but to leave it in place and work
4413 around it if necessary. This would be extremely efficient,
4414 especially considering that people are likely to do
4415 transpositions near where they are working interactively, which
4416 is exactly where the gap would be found. However, such code
4417 would be much harder to write and to read. So, if you are
4418 reading this comment and are feeling squirrely, by all means have
4419 a go! I just didn't feel like doing it, so I will simply move
4420 the gap the minimum distance to get it out of the way, and then
4421 deal with an unbroken array. */
3c6bc7d0
RS
4422
4423 /* Make sure the gap won't interfere, by moving it out of the text
4424 we will operate on. */
4425 if (start1 < gap && gap < end2)
4426 {
4427 if (gap - start1 < end2 - gap)
4428 move_gap (start1);
4429 else
4430 move_gap (end2);
4431 }
ec1c14f6
RS
4432
4433 start1_byte = CHAR_TO_BYTE (start1);
4434 start2_byte = CHAR_TO_BYTE (start2);
4435 len1_byte = CHAR_TO_BYTE (end1) - start1_byte;
4436 len2_byte = CHAR_TO_BYTE (end2) - start2_byte;
dc3620af 4437
9a599130 4438#ifdef BYTE_COMBINING_DEBUG
dc3620af
RS
4439 if (end1 == start2)
4440 {
9a599130
KH
4441 if (count_combining_before (BYTE_POS_ADDR (start2_byte),
4442 len2_byte, start1, start1_byte)
4443 || count_combining_before (BYTE_POS_ADDR (start1_byte),
4444 len1_byte, end2, start2_byte + len2_byte)
4445 || count_combining_after (BYTE_POS_ADDR (start1_byte),
4446 len1_byte, end2, start2_byte + len2_byte))
4447 abort ();
dc3620af
RS
4448 }
4449 else
4450 {
9a599130
KH
4451 if (count_combining_before (BYTE_POS_ADDR (start2_byte),
4452 len2_byte, start1, start1_byte)
4453 || count_combining_before (BYTE_POS_ADDR (start1_byte),
4454 len1_byte, start2, start2_byte)
4455 || count_combining_after (BYTE_POS_ADDR (start2_byte),
4456 len2_byte, end1, start1_byte + len1_byte)
4457 || count_combining_after (BYTE_POS_ADDR (start1_byte),
4458 len1_byte, end2, start2_byte + len2_byte))
4459 abort ();
dc3620af 4460 }
9a599130 4461#endif
dc3620af 4462
b229b8d1
RS
4463 /* Hmmm... how about checking to see if the gap is large
4464 enough to use as the temporary storage? That would avoid an
4465 allocation... interesting. Later, don't fool with it now. */
4466
4467 /* Working without memmove, for portability (sigh), so must be
4468 careful of overlapping subsections of the array... */
4469
4470 if (end1 == start2) /* adjacent regions */
4471 {
3e145152 4472 modify_region (current_buffer, start1, end2, 0);
b229b8d1
RS
4473 record_change (start1, len1 + len2);
4474
b229b8d1
RS
4475 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4476 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
916480c4
CY
4477 /* Don't use Fset_text_properties: that can cause GC, which can
4478 clobber objects stored in the tmp_intervals. */
6cd0f478
CY
4479 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4480 if (!NULL_INTERVAL_P (tmp_interval3))
4481 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1
RS
4482
4483 /* First region smaller than second. */
ec1c14f6 4484 if (len1_byte < len2_byte)
b229b8d1 4485 {
7e2c051b
KS
4486 USE_SAFE_ALLOCA;
4487
4488 SAFE_ALLOCA (temp, unsigned char *, len2_byte);
03240d11
KH
4489
4490 /* Don't precompute these addresses. We have to compute them
4491 at the last minute, because the relocating allocator might
4492 have moved the buffer around during the xmalloc. */
23017390
KH
4493 start1_addr = BYTE_POS_ADDR (start1_byte);
4494 start2_addr = BYTE_POS_ADDR (start2_byte);
03240d11 4495
ec1c14f6
RS
4496 bcopy (start2_addr, temp, len2_byte);
4497 bcopy (start1_addr, start1_addr + len2_byte, len1_byte);
4498 bcopy (temp, start1_addr, len2_byte);
e65837df 4499 SAFE_FREE ();
b229b8d1
RS
4500 }
4501 else
4502 /* First region not smaller than second. */
4503 {
7e2c051b
KS
4504 USE_SAFE_ALLOCA;
4505
4506 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4507 start1_addr = BYTE_POS_ADDR (start1_byte);
4508 start2_addr = BYTE_POS_ADDR (start2_byte);
ec1c14f6
RS
4509 bcopy (start1_addr, temp, len1_byte);
4510 bcopy (start2_addr, start1_addr, len2_byte);
4511 bcopy (temp, start1_addr + len2_byte, len1_byte);
e65837df 4512 SAFE_FREE ();
b229b8d1 4513 }
b229b8d1
RS
4514 graft_intervals_into_buffer (tmp_interval1, start1 + len2,
4515 len1, current_buffer, 0);
4516 graft_intervals_into_buffer (tmp_interval2, start1,
4517 len2, current_buffer, 0);
d5c2c403
KH
4518 update_compositions (start1, start1 + len2, CHECK_BORDER);
4519 update_compositions (start1 + len2, end2, CHECK_TAIL);
b229b8d1
RS
4520 }
4521 /* Non-adjacent regions, because end1 != start2, bleagh... */
4522 else
4523 {
ec1c14f6
RS
4524 len_mid = start2_byte - (start1_byte + len1_byte);
4525
4526 if (len1_byte == len2_byte)
b229b8d1
RS
4527 /* Regions are same size, though, how nice. */
4528 {
7e2c051b
KS
4529 USE_SAFE_ALLOCA;
4530
3e145152
CY
4531 modify_region (current_buffer, start1, end1, 0);
4532 modify_region (current_buffer, start2, end2, 0);
b229b8d1
RS
4533 record_change (start1, len1);
4534 record_change (start2, len2);
b229b8d1
RS
4535 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4536 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4537
4538 tmp_interval3 = validate_interval_range (buf, &startr1, &endr1, 0);
4539 if (!NULL_INTERVAL_P (tmp_interval3))
4540 set_text_properties_1 (startr1, endr1, Qnil, buf, tmp_interval3);
4541
4542 tmp_interval3 = validate_interval_range (buf, &startr2, &endr2, 0);
4543 if (!NULL_INTERVAL_P (tmp_interval3))
4544 set_text_properties_1 (startr2, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4545
7e2c051b 4546 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4547 start1_addr = BYTE_POS_ADDR (start1_byte);
4548 start2_addr = BYTE_POS_ADDR (start2_byte);
ec1c14f6
RS
4549 bcopy (start1_addr, temp, len1_byte);
4550 bcopy (start2_addr, start1_addr, len2_byte);
4551 bcopy (temp, start2_addr, len1_byte);
e65837df 4552 SAFE_FREE ();
7e2c051b 4553
b229b8d1
RS
4554 graft_intervals_into_buffer (tmp_interval1, start2,
4555 len1, current_buffer, 0);
4556 graft_intervals_into_buffer (tmp_interval2, start1,
4557 len2, current_buffer, 0);
b229b8d1
RS
4558 }
4559
ec1c14f6 4560 else if (len1_byte < len2_byte) /* Second region larger than first */
b229b8d1
RS
4561 /* Non-adjacent & unequal size, area between must also be shifted. */
4562 {
7e2c051b
KS
4563 USE_SAFE_ALLOCA;
4564
3e145152 4565 modify_region (current_buffer, start1, end2, 0);
b229b8d1 4566 record_change (start1, (end2 - start1));
b229b8d1
RS
4567 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4568 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
4569 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4570
4571 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4572 if (!NULL_INTERVAL_P (tmp_interval3))
4573 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4574
3c6bc7d0 4575 /* holds region 2 */
7e2c051b 4576 SAFE_ALLOCA (temp, unsigned char *, len2_byte);
23017390
KH
4577 start1_addr = BYTE_POS_ADDR (start1_byte);
4578 start2_addr = BYTE_POS_ADDR (start2_byte);
ec1c14f6
RS
4579 bcopy (start2_addr, temp, len2_byte);
4580 bcopy (start1_addr, start1_addr + len_mid + len2_byte, len1_byte);
4581 safe_bcopy (start1_addr + len1_byte, start1_addr + len2_byte, len_mid);
4582 bcopy (temp, start1_addr, len2_byte);
e65837df 4583 SAFE_FREE ();
7e2c051b 4584
b229b8d1
RS
4585 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
4586 len1, current_buffer, 0);
4587 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
4588 len_mid, current_buffer, 0);
4589 graft_intervals_into_buffer (tmp_interval2, start1,
4590 len2, current_buffer, 0);
b229b8d1
RS
4591 }
4592 else
4593 /* Second region smaller than first. */
4594 {
7e2c051b
KS
4595 USE_SAFE_ALLOCA;
4596
b229b8d1 4597 record_change (start1, (end2 - start1));
3e145152 4598 modify_region (current_buffer, start1, end2, 0);
b229b8d1 4599
b229b8d1
RS
4600 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
4601 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
4602 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
6cd0f478
CY
4603
4604 tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
4605 if (!NULL_INTERVAL_P (tmp_interval3))
4606 set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
b229b8d1 4607
3c6bc7d0 4608 /* holds region 1 */
7e2c051b 4609 SAFE_ALLOCA (temp, unsigned char *, len1_byte);
23017390
KH
4610 start1_addr = BYTE_POS_ADDR (start1_byte);
4611 start2_addr = BYTE_POS_ADDR (start2_byte);
ec1c14f6
RS
4612 bcopy (start1_addr, temp, len1_byte);
4613 bcopy (start2_addr, start1_addr, len2_byte);
4614 bcopy (start1_addr + len1_byte, start1_addr + len2_byte, len_mid);
4615 bcopy (temp, start1_addr + len2_byte + len_mid, len1_byte);
e65837df 4616 SAFE_FREE ();
7e2c051b 4617
b229b8d1
RS
4618 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
4619 len1, current_buffer, 0);
4620 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
4621 len_mid, current_buffer, 0);
4622 graft_intervals_into_buffer (tmp_interval2, start1,
4623 len2, current_buffer, 0);
b229b8d1 4624 }
d5c2c403
KH
4625
4626 update_compositions (start1, start1 + len2, CHECK_BORDER);
4627 update_compositions (end2 - len1, end2, CHECK_BORDER);
b229b8d1
RS
4628 }
4629
ec1c14f6
RS
4630 /* When doing multiple transpositions, it might be nice
4631 to optimize this. Perhaps the markers in any one buffer
4632 should be organized in some sorted data tree. */
b229b8d1 4633 if (NILP (leave_markers))
8de1d5f0 4634 {
ec1c14f6
RS
4635 transpose_markers (start1, end1, start2, end2,
4636 start1_byte, start1_byte + len1_byte,
4637 start2_byte, start2_byte + len2_byte);
6b61353c 4638 fix_start_end_in_overlays (start1, end2);
8de1d5f0 4639 }
b229b8d1 4640
c10b2810 4641 signal_after_change (start1, end2 - start1, end2 - start1);
b229b8d1
RS
4642 return Qnil;
4643}
35692fe0 4644
35692fe0
JB
4645\f
4646void
4647syms_of_editfns ()
4648{
260e2e2a 4649 environbuf = 0;
a03fc5a6 4650 initial_tz = 0;
260e2e2a
KH
4651
4652 Qbuffer_access_fontify_functions
d67b4f80 4653 = intern_c_string ("buffer-access-fontify-functions");
260e2e2a
KH
4654 staticpro (&Qbuffer_access_fontify_functions);
4655
7ee72033 4656 DEFVAR_LISP ("inhibit-field-text-motion", &Vinhibit_field_text_motion,
7dcece14 4657 doc: /* Non-nil means text motion commands don't notice fields. */);
9a74e7e5
GM
4658 Vinhibit_field_text_motion = Qnil;
4659
260e2e2a 4660 DEFVAR_LISP ("buffer-access-fontify-functions",
7ee72033
MB
4661 &Vbuffer_access_fontify_functions,
4662 doc: /* List of functions called by `buffer-substring' to fontify if necessary.
a1f17501
PJ
4663Each function is called with two arguments which specify the range
4664of the buffer being accessed. */);
260e2e2a
KH
4665 Vbuffer_access_fontify_functions = Qnil;
4666
af209db8
RS
4667 {
4668 Lisp_Object obuf;
4669 extern Lisp_Object Vprin1_to_string_buffer;
4670 obuf = Fcurrent_buffer ();
4671 /* Do this here, because init_buffer_once is too early--it won't work. */
4672 Fset_buffer (Vprin1_to_string_buffer);
4673 /* Make sure buffer-access-fontify-functions is nil in this buffer. */
d67b4f80 4674 Fset (Fmake_local_variable (intern_c_string ("buffer-access-fontify-functions")),
af209db8
RS
4675 Qnil);
4676 Fset_buffer (obuf);
4677 }
4678
0b6fd023 4679 DEFVAR_LISP ("buffer-access-fontified-property",
7ee72033
MB
4680 &Vbuffer_access_fontified_property,
4681 doc: /* Property which (if non-nil) indicates text has been fontified.
a1f17501
PJ
4682`buffer-substring' need not call the `buffer-access-fontify-functions'
4683functions if all the text being accessed has this property. */);
260e2e2a
KH
4684 Vbuffer_access_fontified_property = Qnil;
4685
7ee72033 4686 DEFVAR_LISP ("system-name", &Vsystem_name,
1a7e0117 4687 doc: /* The host name of the machine Emacs is running on. */);
34a7a267 4688
7ee72033
MB
4689 DEFVAR_LISP ("user-full-name", &Vuser_full_name,
4690 doc: /* The full name of the user logged in. */);
f43754f6 4691
7ee72033
MB
4692 DEFVAR_LISP ("user-login-name", &Vuser_login_name,
4693 doc: /* The user's name, taken from environment variables if possible. */);
f43754f6 4694
7ee72033
MB
4695 DEFVAR_LISP ("user-real-login-name", &Vuser_real_login_name,
4696 doc: /* The user's name, based upon the real uid only. */);
35692fe0 4697
3bb9abc8
ST
4698 DEFVAR_LISP ("operating-system-release", &Voperating_system_release,
4699 doc: /* The release of the operating system Emacs is running on. */);
4700
0963334d 4701 defsubr (&Spropertize);
35692fe0
JB
4702 defsubr (&Schar_equal);
4703 defsubr (&Sgoto_char);
4704 defsubr (&Sstring_to_char);
4705 defsubr (&Schar_to_string);
c3bb441d 4706 defsubr (&Sbyte_to_string);
35692fe0 4707 defsubr (&Sbuffer_substring);
260e2e2a 4708 defsubr (&Sbuffer_substring_no_properties);
35692fe0
JB
4709 defsubr (&Sbuffer_string);
4710
4711 defsubr (&Spoint_marker);
4712 defsubr (&Smark_marker);
4713 defsubr (&Spoint);
4714 defsubr (&Sregion_beginning);
4715 defsubr (&Sregion_end);
7df74da6 4716
0daf6e8d 4717 staticpro (&Qfield);
d67b4f80 4718 Qfield = intern_c_string ("field");
ee547125 4719 staticpro (&Qboundary);
d67b4f80 4720 Qboundary = intern_c_string ("boundary");
0daf6e8d
GM
4721 defsubr (&Sfield_beginning);
4722 defsubr (&Sfield_end);
4723 defsubr (&Sfield_string);
4724 defsubr (&Sfield_string_no_properties);
8bf64fe8 4725 defsubr (&Sdelete_field);
0daf6e8d
GM
4726 defsubr (&Sconstrain_to_field);
4727
7df74da6
RS
4728 defsubr (&Sline_beginning_position);
4729 defsubr (&Sline_end_position);
4730
35692fe0
JB
4731/* defsubr (&Smark); */
4732/* defsubr (&Sset_mark); */
4733 defsubr (&Ssave_excursion);
4bc8c7d2 4734 defsubr (&Ssave_current_buffer);
35692fe0
JB
4735
4736 defsubr (&Sbufsize);
4737 defsubr (&Spoint_max);
4738 defsubr (&Spoint_min);
4739 defsubr (&Spoint_min_marker);
4740 defsubr (&Spoint_max_marker);
c86212b9
RS
4741 defsubr (&Sgap_position);
4742 defsubr (&Sgap_size);
7df74da6 4743 defsubr (&Sposition_bytes);
3ab0732d 4744 defsubr (&Sbyte_to_position);
c9ed721d 4745
35692fe0
JB
4746 defsubr (&Sbobp);
4747 defsubr (&Seobp);
4748 defsubr (&Sbolp);
4749 defsubr (&Seolp);
850a8179
JB
4750 defsubr (&Sfollowing_char);
4751 defsubr (&Sprevious_char);
35692fe0 4752 defsubr (&Schar_after);
fb8106e8 4753 defsubr (&Schar_before);
35692fe0
JB
4754 defsubr (&Sinsert);
4755 defsubr (&Sinsert_before_markers);
be91036a
RS
4756 defsubr (&Sinsert_and_inherit);
4757 defsubr (&Sinsert_and_inherit_before_markers);
35692fe0 4758 defsubr (&Sinsert_char);
48ef988f 4759 defsubr (&Sinsert_byte);
35692fe0
JB
4760
4761 defsubr (&Suser_login_name);
4762 defsubr (&Suser_real_login_name);
4763 defsubr (&Suser_uid);
4764 defsubr (&Suser_real_uid);
4765 defsubr (&Suser_full_name);
7fd233b3 4766 defsubr (&Semacs_pid);
d940e0e4 4767 defsubr (&Scurrent_time);
4211ee7d 4768 defsubr (&Sget_internal_run_time);
a82d387c 4769 defsubr (&Sformat_time_string);
34a7a267 4770 defsubr (&Sfloat_time);
4691c06d 4771 defsubr (&Sdecode_time);
cce7b8a0 4772 defsubr (&Sencode_time);
35692fe0 4773 defsubr (&Scurrent_time_string);
c2662aea 4774 defsubr (&Scurrent_time_zone);
143cb9a9 4775 defsubr (&Sset_time_zone_rule);
35692fe0 4776 defsubr (&Ssystem_name);
35692fe0 4777 defsubr (&Smessage);
cacc3e2c
RS
4778 defsubr (&Smessage_box);
4779 defsubr (&Smessage_or_box);
b14dda8a 4780 defsubr (&Scurrent_message);
35692fe0 4781 defsubr (&Sformat);
35692fe0
JB
4782
4783 defsubr (&Sinsert_buffer_substring);
e9cf2084 4784 defsubr (&Scompare_buffer_substrings);
35692fe0 4785 defsubr (&Ssubst_char_in_region);
8583605b 4786 defsubr (&Stranslate_region_internal);
35692fe0 4787 defsubr (&Sdelete_region);
7dae4502 4788 defsubr (&Sdelete_and_extract_region);
35692fe0
JB
4789 defsubr (&Swiden);
4790 defsubr (&Snarrow_to_region);
4791 defsubr (&Ssave_restriction);
b229b8d1 4792 defsubr (&Stranspose_regions);
35692fe0 4793}
f555f8cf
KH
4794
4795/* arch-tag: fc3827d8-6f60-4067-b11e-c3218031b018
4796 (do not change this comment) */