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