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