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