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