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