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