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