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