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