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