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