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