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