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