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