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