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