1 /* Lisp functions pertaining to editing.
2 Copyright (C) 1985,86,87,89,93,94,95,96,97,98, 1999 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
23 #include <sys/types.h>
36 #include "intervals.h"
44 #define min(a, b) ((a) < (b) ? (a) : (b))
45 #define max(a, b) ((a) > (b) ? (a) : (b))
51 extern char **environ
;
52 extern int use_dialog_box
;
53 extern Lisp_Object
make_time ();
54 extern void insert_from_buffer ();
55 static int tm_diff ();
56 static void update_buffer_properties ();
57 size_t emacs_strftimeu ();
58 void set_time_zone_rule ();
60 Lisp_Object Vbuffer_access_fontify_functions
;
61 Lisp_Object Qbuffer_access_fontify_functions
;
62 Lisp_Object Vbuffer_access_fontified_property
;
64 Lisp_Object
Fuser_full_name ();
66 /* Non-nil means don't stop at field boundary in text motion commands. */
68 Lisp_Object Vinhibit_field_text_motion
;
70 /* Some static data, and a function to initialize it for each run */
72 Lisp_Object Vsystem_name
;
73 Lisp_Object Vuser_real_login_name
; /* login name of current user ID */
74 Lisp_Object Vuser_full_name
; /* full name of current user */
75 Lisp_Object Vuser_login_name
; /* user name from LOGNAME or USER */
81 register unsigned char *p
;
82 struct passwd
*pw
; /* password entry for the current user */
85 /* Set up system_name even when dumping. */
89 /* Don't bother with this on initial start when just dumping out */
92 #endif /* not CANNOT_DUMP */
94 pw
= (struct passwd
*) getpwuid (getuid ());
96 /* We let the real user name default to "root" because that's quite
97 accurate on MSDOG and because it lets Emacs find the init file.
98 (The DVX libraries override the Djgpp libraries here.) */
99 Vuser_real_login_name
= build_string (pw
? pw
->pw_name
: "root");
101 Vuser_real_login_name
= build_string (pw
? pw
->pw_name
: "unknown");
104 /* Get the effective user name, by consulting environment variables,
105 or the effective uid if those are unset. */
106 user_name
= (char *) getenv ("LOGNAME");
109 user_name
= (char *) getenv ("USERNAME"); /* it's USERNAME on NT */
110 #else /* WINDOWSNT */
111 user_name
= (char *) getenv ("USER");
112 #endif /* WINDOWSNT */
115 pw
= (struct passwd
*) getpwuid (geteuid ());
116 user_name
= (char *) (pw
? pw
->pw_name
: "unknown");
118 Vuser_login_name
= build_string (user_name
);
120 /* If the user name claimed in the environment vars differs from
121 the real uid, use the claimed name to find the full name. */
122 tem
= Fstring_equal (Vuser_login_name
, Vuser_real_login_name
);
123 Vuser_full_name
= Fuser_full_name (NILP (tem
)? make_number (geteuid())
126 p
= (unsigned char *) getenv ("NAME");
128 Vuser_full_name
= build_string (p
);
129 else if (NILP (Vuser_full_name
))
130 Vuser_full_name
= build_string ("unknown");
133 DEFUN ("char-to-string", Fchar_to_string
, Schar_to_string
, 1, 1, 0,
134 "Convert arg CHAR to a string containing that character.")
136 Lisp_Object character
;
139 unsigned char str
[MAX_MULTIBYTE_LENGTH
];
141 CHECK_NUMBER (character
, 0);
143 len
= CHAR_STRING (XFASTINT (character
), str
);
144 return make_string_from_bytes (str
, 1, len
);
147 DEFUN ("string-to-char", Fstring_to_char
, Sstring_to_char
, 1, 1, 0,
148 "Convert arg STRING to a character, the first character of that string.\n\
149 A multibyte character is handled correctly.")
151 register Lisp_Object string
;
153 register Lisp_Object val
;
154 register struct Lisp_String
*p
;
155 CHECK_STRING (string
, 0);
156 p
= XSTRING (string
);
159 if (STRING_MULTIBYTE (string
))
160 XSETFASTINT (val
, STRING_CHAR (p
->data
, STRING_BYTES (p
)));
162 XSETFASTINT (val
, p
->data
[0]);
165 XSETFASTINT (val
, 0);
170 buildmark (charpos
, bytepos
)
171 int charpos
, bytepos
;
173 register Lisp_Object mark
;
174 mark
= Fmake_marker ();
175 set_marker_both (mark
, Qnil
, charpos
, bytepos
);
179 DEFUN ("point", Fpoint
, Spoint
, 0, 0, 0,
180 "Return value of point, as an integer.\n\
181 Beginning of buffer is position (point-min)")
185 XSETFASTINT (temp
, PT
);
189 DEFUN ("point-marker", Fpoint_marker
, Spoint_marker
, 0, 0, 0,
190 "Return value of point, as a marker object.")
193 return buildmark (PT
, PT_BYTE
);
197 clip_to_bounds (lower
, num
, upper
)
198 int lower
, num
, upper
;
202 else if (num
> upper
)
208 DEFUN ("goto-char", Fgoto_char
, Sgoto_char
, 1, 1, "NGoto char: ",
209 "Set point to POSITION, a number or marker.\n\
210 Beginning of buffer is position (point-min), end is (point-max).\n\
211 If the position is in the middle of a multibyte form,\n\
212 the actual point is set at the head of the multibyte form\n\
213 except in the case that `enable-multibyte-characters' is nil.")
215 register Lisp_Object position
;
219 if (MARKERP (position
)
220 && current_buffer
== XMARKER (position
)->buffer
)
222 pos
= marker_position (position
);
224 SET_PT_BOTH (BEGV
, BEGV_BYTE
);
226 SET_PT_BOTH (ZV
, ZV_BYTE
);
228 SET_PT_BOTH (pos
, marker_byte_position (position
));
233 CHECK_NUMBER_COERCE_MARKER (position
, 0);
235 pos
= clip_to_bounds (BEGV
, XINT (position
), ZV
);
241 region_limit (beginningp
)
244 extern Lisp_Object Vmark_even_if_inactive
; /* Defined in callint.c. */
245 register Lisp_Object m
;
246 if (!NILP (Vtransient_mark_mode
) && NILP (Vmark_even_if_inactive
)
247 && NILP (current_buffer
->mark_active
))
248 Fsignal (Qmark_inactive
, Qnil
);
249 m
= Fmarker_position (current_buffer
->mark
);
250 if (NILP (m
)) error ("There is no region now");
251 if ((PT
< XFASTINT (m
)) == beginningp
)
252 return (make_number (PT
));
257 DEFUN ("region-beginning", Fregion_beginning
, Sregion_beginning
, 0, 0, 0,
258 "Return position of beginning of region, as an integer.")
261 return (region_limit (1));
264 DEFUN ("region-end", Fregion_end
, Sregion_end
, 0, 0, 0,
265 "Return position of end of region, as an integer.")
268 return (region_limit (0));
271 DEFUN ("mark-marker", Fmark_marker
, Smark_marker
, 0, 0, 0,
272 "Return this buffer's mark, as a marker object.\n\
273 Watch out! Moving this marker changes the mark position.\n\
274 If you set the marker not to point anywhere, the buffer will have no mark.")
277 return current_buffer
->mark
;
280 /* Return nonzero if POS1 and POS2 have the same value
281 for the text property PROP. */
284 char_property_eq (prop
, pos1
, pos2
)
286 Lisp_Object pos1
, pos2
;
288 Lisp_Object pval1
, pval2
;
290 pval1
= Fget_char_property (pos1
, prop
, Qnil
);
291 pval2
= Fget_char_property (pos2
, prop
, Qnil
);
293 return EQ (pval1
, pval2
);
296 /* Return the direction from which the char-property PROP would be
297 inherited by any new text inserted at POS: 1 if it would be
298 inherited from the char after POS, -1 if it would be inherited from
299 the char before POS, and 0 if from neither. */
302 char_property_stickiness (prop
, pos
)
306 Lisp_Object front_sticky
;
308 if (XINT (pos
) > BEGV
)
309 /* Consider previous character. */
311 Lisp_Object prev_pos
, rear_non_sticky
;
313 prev_pos
= make_number (XINT (pos
) - 1);
314 rear_non_sticky
= Fget_char_property (prev_pos
, Qrear_nonsticky
, Qnil
);
316 if (EQ (rear_non_sticky
, Qnil
)
317 || (CONSP (rear_non_sticky
)
318 && NILP (Fmemq (prop
, rear_non_sticky
))))
319 /* PROP is not rear-non-sticky, and since this takes precedence over
320 any front-stickiness, PROP is inherited from before. */
324 /* Consider following character. */
325 front_sticky
= Fget_char_property (pos
, Qfront_sticky
, Qnil
);
327 if (EQ (front_sticky
, Qt
)
328 || (CONSP (front_sticky
)
329 && !NILP (Fmemq (prop
, front_sticky
))))
330 /* PROP is inherited from after. */
333 /* PROP is not inherited from either side. */
337 /* Symbol for the text property used to mark fields. */
340 /* A special value for Qfield properties. */
341 Lisp_Object Qboundary
;
343 /* Find the field surrounding POS in *BEG and *END. If POS is nil,
344 the value of point is used instead.
346 If MERGE_AT_BOUNDARY is nonzero, then if POS is at the very first
347 position of a field, then the beginning of the previous field is
348 returned instead of the beginning of POS's field (since the end of a
349 field is actually also the beginning of the next input field, this
350 behavior is sometimes useful). Additionally in the MERGE_AT_BOUNDARY
351 true case, if two fields are separated by a field with the special
352 value `boundary', and POS lies within it, then the two separated
353 fields are considered to be adjacent, and POS between them, when
354 finding the beginning and ending of the "merged" field.
356 Either BEG or END may be 0, in which case the corresponding value
360 find_field (pos
, merge_at_boundary
, beg
, end
)
362 Lisp_Object merge_at_boundary
;
365 /* Fields right before and after the point. */
366 Lisp_Object before_field
, after_field
;
367 /* 1 if POS counts as the start of a field. */
368 int at_field_start
= 0;
369 /* 1 if POS counts as the end of a field. */
370 int at_field_end
= 0;
373 XSETFASTINT (pos
, PT
);
375 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
378 Fget_char_property (pos
, Qfield
, Qnil
);
380 (XFASTINT (pos
) > BEGV
381 ? Fget_char_property (make_number (XINT (pos
) - 1), Qfield
, Qnil
)
384 /* See if we need to handle the case where MERGE_AT_BOUNDARY is nil
385 and POS is at beginning of a field, which can also be interpreted
386 as the end of the previous field. Note that the case where if
387 MERGE_AT_BOUNDARY is non-nil (see function comment) is actually the
388 more natural one; then we avoid treating the beginning of a field
390 if (NILP (merge_at_boundary
) && !EQ (after_field
, before_field
))
391 /* We are at a boundary, see which direction is inclusive. We
392 decide by seeing which field the `field' property sticks to. */
394 int stickiness
= char_property_stickiness (Qfield
, pos
);
398 else if (stickiness
< 0)
401 /* STICKINESS == 0 means that any inserted text will get a
402 `field' char-property of nil, so check to see if that
403 matches either of the adjacent characters (this being a
404 kind of "stickiness by default"). */
406 if (NILP (before_field
))
407 at_field_end
= 1; /* Sticks to the left. */
408 else if (NILP (after_field
))
409 at_field_start
= 1; /* Sticks to the right. */
413 /* Note about special `boundary' fields:
415 Consider the case where the point (`.') is between the fields `x' and `y':
419 In this situation, if merge_at_boundary is true, we consider the
420 `x' and `y' fields as forming one big merged field, and so the end
421 of the field is the end of `y'.
423 However, if `x' and `y' are separated by a special `boundary' field
424 (a field with a `field' char-property of 'boundary), then we ignore
425 this special field when merging adjacent fields. Here's the same
426 situation, but with a `boundary' field between the `x' and `y' fields:
430 Here, if point is at the end of `x', the beginning of `y', or
431 anywhere in-between (within the `boundary' field), we merge all
432 three fields and consider the beginning as being the beginning of
433 the `x' field, and the end as being the end of the `y' field. */
437 /* POS is at the edge of a field, and we should consider it as
438 the beginning of the following field. */
439 *beg
= XFASTINT (pos
);
441 /* Find the previous field boundary. */
443 if (!NILP (merge_at_boundary
) && EQ (before_field
, Qboundary
))
444 /* Skip a `boundary' field. */
445 pos
= Fprevious_single_char_property_change (pos
, Qfield
, Qnil
,Qnil
);
447 pos
= Fprevious_single_char_property_change (pos
, Qfield
, Qnil
, Qnil
);
448 *beg
= NILP (pos
) ? BEGV
: XFASTINT (pos
);
453 /* POS is at the edge of a field, and we should consider it as
454 the end of the previous field. */
455 *end
= XFASTINT (pos
);
457 /* Find the next field boundary. */
459 if (!NILP (merge_at_boundary
) && EQ (after_field
, Qboundary
))
460 /* Skip a `boundary' field. */
461 pos
= Fnext_single_char_property_change (pos
, Qfield
, Qnil
, Qnil
);
463 pos
= Fnext_single_char_property_change (pos
, Qfield
, Qnil
, Qnil
);
464 *end
= NILP (pos
) ? ZV
: XFASTINT (pos
);
468 DEFUN ("delete-field", Fdelete_field
, Sdelete_field
, 0, 1, 0,
469 "Delete the field surrounding POS.\n\
470 A field is a region of text with the same `field' property.\n\
471 If POS is nil, the value of point is used for POS.")
476 find_field (pos
, Qnil
, &beg
, &end
);
478 del_range (beg
, end
);
482 DEFUN ("field-string", Ffield_string
, Sfield_string
, 0, 1, 0,
483 "Return the contents of the field surrounding POS as a string.\n\
484 A field is a region of text with the same `field' property.\n\
485 If POS is nil, the value of point is used for POS.")
490 find_field (pos
, Qnil
, &beg
, &end
);
491 return make_buffer_string (beg
, end
, 1);
494 DEFUN ("field-string-no-properties", Ffield_string_no_properties
, Sfield_string_no_properties
, 0, 1, 0,
495 "Return the contents of the field around POS, without text-properties.\n\
496 A field is a region of text with the same `field' property.\n\
497 If POS is nil, the value of point is used for POS.")
502 find_field (pos
, Qnil
, &beg
, &end
);
503 return make_buffer_string (beg
, end
, 0);
506 DEFUN ("field-beginning", Ffield_beginning
, Sfield_beginning
, 0, 2, 0,
507 "Return the beginning of the field surrounding POS.\n\
508 A field is a region of text with the same `field' property.\n\
509 If POS is nil, the value of point is used for POS.\n\
510 If ESCAPE-FROM-EDGE is non-nil and POS is at the beginning of its\n\
511 field, then the beginning of the *previous* field is returned.")
512 (pos
, escape_from_edge
)
513 Lisp_Object pos
, escape_from_edge
;
516 find_field (pos
, escape_from_edge
, &beg
, 0);
517 return make_number (beg
);
520 DEFUN ("field-end", Ffield_end
, Sfield_end
, 0, 2, 0,
521 "Return the end of the field surrounding POS.\n\
522 A field is a region of text with the same `field' property.\n\
523 If POS is nil, the value of point is used for POS.\n\
524 If ESCAPE-FROM-EDGE is non-nil and POS is at the end of its field,\n\
525 then the end of the *following* field is returned.")
526 (pos
, escape_from_edge
)
527 Lisp_Object pos
, escape_from_edge
;
530 find_field (pos
, escape_from_edge
, 0, &end
);
531 return make_number (end
);
534 DEFUN ("constrain-to-field", Fconstrain_to_field
, Sconstrain_to_field
, 2, 5, 0,
535 "Return the position closest to NEW-POS that is in the same field as OLD-POS.\n\
537 A field is a region of text with the same `field' property.\n\
538 If NEW-POS is nil, then the current point is used instead, and set to the\n\
539 constrained position if that is is different.\n\
541 If OLD-POS is at the boundary of two fields, then the allowable\n\
542 positions for NEW-POS depends on the value of the optional argument\n\
543 ESCAPE-FROM-EDGE: If ESCAPE-FROM-EDGE is nil, then NEW-POS is\n\
544 constrained to the field that has the same `field' char-property\n\
545 as any new characters inserted at OLD-POS, whereas if ESCAPE-FROM-EDGE\n\
546 is non-nil, NEW-POS is constrained to the union of the two adjacent\n\
547 fields. Additionally, if two fields are separated by another field with\n\
548 the special value `boundary', then any point within this special field is\n\
549 also considered to be `on the boundary'.\n\
551 If the optional argument ONLY-IN-LINE is non-nil and constraining\n\
552 NEW-POS would move it to a different line, NEW-POS is returned\n\
553 unconstrained. This useful for commands that move by line, like\n\
554 \\[next-line] or \\[beginning-of-line], which should generally respect field boundaries\n\
555 only in the case where they can still move to the right line.\n\
557 If the optional argument INHIBIT-CAPTURE-PROPERTY is non-nil, and OLD-POS has\n\
558 a non-nil property of that name, then any field boundaries are ignored.\n\
560 Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil.")
561 (new_pos
, old_pos
, escape_from_edge
, only_in_line
, inhibit_capture_property
)
562 Lisp_Object new_pos
, old_pos
;
563 Lisp_Object escape_from_edge
, only_in_line
, inhibit_capture_property
;
565 /* If non-zero, then the original point, before re-positioning. */
569 /* Use the current point, and afterwards, set it. */
572 XSETFASTINT (new_pos
, PT
);
575 if (NILP (Vinhibit_field_text_motion
)
576 && !EQ (new_pos
, old_pos
)
577 && !char_property_eq (Qfield
, new_pos
, old_pos
)
578 && (NILP (inhibit_capture_property
)
579 || NILP (Fget_char_property(old_pos
, inhibit_capture_property
, Qnil
))))
580 /* NEW_POS is not within the same field as OLD_POS; try to
581 move NEW_POS so that it is. */
584 Lisp_Object field_bound
;
586 CHECK_NUMBER_COERCE_MARKER (new_pos
, 0);
587 CHECK_NUMBER_COERCE_MARKER (old_pos
, 0);
589 fwd
= (XFASTINT (new_pos
) > XFASTINT (old_pos
));
592 field_bound
= Ffield_end (old_pos
, escape_from_edge
);
594 field_bound
= Ffield_beginning (old_pos
, escape_from_edge
);
596 if (/* See if ESCAPE_FROM_EDGE caused FIELD_BOUND to jump to the
597 other side of NEW_POS, which would mean that NEW_POS is
598 already acceptable, and it's not necessary to constrain it
600 ((XFASTINT (field_bound
) < XFASTINT (new_pos
)) ? fwd
: !fwd
)
601 /* NEW_POS should be constrained, but only if either
602 ONLY_IN_LINE is nil (in which case any constraint is OK),
603 or NEW_POS and FIELD_BOUND are on the same line (in which
604 case the constraint is OK even if ONLY_IN_LINE is non-nil). */
605 && (NILP (only_in_line
)
606 /* This is the ONLY_IN_LINE case, check that NEW_POS and
607 FIELD_BOUND are on the same line by seeing whether
608 there's an intervening newline or not. */
609 || (scan_buffer ('\n',
610 XFASTINT (new_pos
), XFASTINT (field_bound
),
611 fwd
? -1 : 1, &shortage
, 1),
613 /* Constrain NEW_POS to FIELD_BOUND. */
614 new_pos
= field_bound
;
616 if (orig_point
&& XFASTINT (new_pos
) != orig_point
)
617 /* The NEW_POS argument was originally nil, so automatically set PT. */
618 SET_PT (XFASTINT (new_pos
));
624 DEFUN ("line-beginning-position", Fline_beginning_position
, Sline_beginning_position
,
626 "Return the character position of the first character on the current line.\n\
627 With argument N not nil or 1, move forward N - 1 lines first.\n\
628 If scan reaches end of buffer, return that position.\n\
629 The scan does not cross a field boundary unless it would move\n\
630 beyond there to a different line. Field boundaries are not noticed if\n\
631 `inhibit-field-text-motion' is non-nil. .And if N is nil or 1,\n\
632 and scan starts at a field boundary, the scan stops as soon as it starts.\n\
634 This function does not move point.")
638 register int orig
, orig_byte
, end
;
647 Fforward_line (make_number (XINT (n
) - 1));
650 SET_PT_BOTH (orig
, orig_byte
);
652 /* Return END constrained to the current input field. */
653 return Fconstrain_to_field (make_number (end
), make_number (orig
),
654 XINT (n
) != 1 ? Qt
: Qnil
,
658 DEFUN ("line-end-position", Fline_end_position
, Sline_end_position
,
660 "Return the character position of the last character on the current line.\n\
661 With argument N not nil or 1, move forward N - 1 lines first.\n\
662 If scan reaches end of buffer, return that position.\n\
663 This function does not move point.")
668 register int orig
= PT
;
675 end_pos
= find_before_next_newline (orig
, 0, XINT (n
) - (XINT (n
) <= 0));
677 /* Return END_POS constrained to the current input field. */
678 return Fconstrain_to_field (make_number (end_pos
), make_number (orig
),
683 save_excursion_save ()
685 register int visible
= (XBUFFER (XWINDOW (selected_window
)->buffer
)
688 return Fcons (Fpoint_marker (),
689 Fcons (Fcopy_marker (current_buffer
->mark
, Qnil
),
690 Fcons (visible
? Qt
: Qnil
,
691 current_buffer
->mark_active
)));
695 save_excursion_restore (info
)
698 Lisp_Object tem
, tem1
, omark
, nmark
;
699 struct gcpro gcpro1
, gcpro2
, gcpro3
;
701 tem
= Fmarker_buffer (Fcar (info
));
702 /* If buffer being returned to is now deleted, avoid error */
703 /* Otherwise could get error here while unwinding to top level
705 /* In that case, Fmarker_buffer returns nil now. */
709 omark
= nmark
= Qnil
;
710 GCPRO3 (info
, omark
, nmark
);
715 unchain_marker (tem
);
716 tem
= Fcar (Fcdr (info
));
717 omark
= Fmarker_position (current_buffer
->mark
);
718 Fset_marker (current_buffer
->mark
, tem
, Fcurrent_buffer ());
719 nmark
= Fmarker_position (tem
);
720 unchain_marker (tem
);
721 tem
= Fcdr (Fcdr (info
));
722 #if 0 /* We used to make the current buffer visible in the selected window
723 if that was true previously. That avoids some anomalies.
724 But it creates others, and it wasn't documented, and it is simpler
725 and cleaner never to alter the window/buffer connections. */
728 && current_buffer
!= XBUFFER (XWINDOW (selected_window
)->buffer
))
729 Fswitch_to_buffer (Fcurrent_buffer (), Qnil
);
732 tem1
= current_buffer
->mark_active
;
733 current_buffer
->mark_active
= Fcdr (tem
);
734 if (!NILP (Vrun_hooks
))
736 /* If mark is active now, and either was not active
737 or was at a different place, run the activate hook. */
738 if (! NILP (current_buffer
->mark_active
))
740 if (! EQ (omark
, nmark
))
741 call1 (Vrun_hooks
, intern ("activate-mark-hook"));
743 /* If mark has ceased to be active, run deactivate hook. */
744 else if (! NILP (tem1
))
745 call1 (Vrun_hooks
, intern ("deactivate-mark-hook"));
751 DEFUN ("save-excursion", Fsave_excursion
, Ssave_excursion
, 0, UNEVALLED
, 0,
752 "Save point, mark, and current buffer; execute BODY; restore those things.\n\
753 Executes BODY just like `progn'.\n\
754 The values of point, mark and the current buffer are restored\n\
755 even in case of abnormal exit (throw or error).\n\
756 The state of activation of the mark is also restored.\n\
758 This construct does not save `deactivate-mark', and therefore\n\
759 functions that change the buffer will still cause deactivation\n\
760 of the mark at the end of the command. To prevent that, bind\n\
761 `deactivate-mark' with `let'.")
765 register Lisp_Object val
;
766 int count
= specpdl_ptr
- specpdl
;
768 record_unwind_protect (save_excursion_restore
, save_excursion_save ());
771 return unbind_to (count
, val
);
774 DEFUN ("save-current-buffer", Fsave_current_buffer
, Ssave_current_buffer
, 0, UNEVALLED
, 0,
775 "Save the current buffer; execute BODY; restore the current buffer.\n\
776 Executes BODY just like `progn'.")
780 register Lisp_Object val
;
781 int count
= specpdl_ptr
- specpdl
;
783 record_unwind_protect (set_buffer_if_live
, Fcurrent_buffer ());
786 return unbind_to (count
, val
);
789 DEFUN ("buffer-size", Fbufsize
, Sbufsize
, 0, 1, 0,
790 "Return the number of characters in the current buffer.\n\
791 If BUFFER, return the number of characters in that buffer instead.")
796 return make_number (Z
- BEG
);
799 CHECK_BUFFER (buffer
, 1);
800 return make_number (BUF_Z (XBUFFER (buffer
))
801 - BUF_BEG (XBUFFER (buffer
)));
805 DEFUN ("point-min", Fpoint_min
, Spoint_min
, 0, 0, 0,
806 "Return the minimum permissible value of point in the current buffer.\n\
807 This is 1, unless narrowing (a buffer restriction) is in effect.")
811 XSETFASTINT (temp
, BEGV
);
815 DEFUN ("point-min-marker", Fpoint_min_marker
, Spoint_min_marker
, 0, 0, 0,
816 "Return a marker to the minimum permissible value of point in this buffer.\n\
817 This is the beginning, unless narrowing (a buffer restriction) is in effect.")
820 return buildmark (BEGV
, BEGV_BYTE
);
823 DEFUN ("point-max", Fpoint_max
, Spoint_max
, 0, 0, 0,
824 "Return the maximum permissible value of point in the current buffer.\n\
825 This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
826 is in effect, in which case it is less.")
830 XSETFASTINT (temp
, ZV
);
834 DEFUN ("point-max-marker", Fpoint_max_marker
, Spoint_max_marker
, 0, 0, 0,
835 "Return a marker to the maximum permissible value of point in this buffer.\n\
836 This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
837 is in effect, in which case it is less.")
840 return buildmark (ZV
, ZV_BYTE
);
843 DEFUN ("gap-position", Fgap_position
, Sgap_position
, 0, 0, 0,
844 "Return the position of the gap, in the current buffer.\n\
845 See also `gap-size'.")
849 XSETFASTINT (temp
, GPT
);
853 DEFUN ("gap-size", Fgap_size
, Sgap_size
, 0, 0, 0,
854 "Return the size of the current buffer's gap.\n\
855 See also `gap-position'.")
859 XSETFASTINT (temp
, GAP_SIZE
);
863 DEFUN ("position-bytes", Fposition_bytes
, Sposition_bytes
, 1, 1, 0,
864 "Return the byte position for character position POSITION.\n\
865 If POSITION is out of range, the value is nil.")
867 Lisp_Object position
;
869 CHECK_NUMBER_COERCE_MARKER (position
, 1);
870 if (XINT (position
) < BEG
|| XINT (position
) > Z
)
872 return make_number (CHAR_TO_BYTE (XINT (position
)));
875 DEFUN ("byte-to-position", Fbyte_to_position
, Sbyte_to_position
, 1, 1, 0,
876 "Return the character position for byte position BYTEPOS.\n\
877 If BYTEPOS is out of range, the value is nil.")
881 CHECK_NUMBER (bytepos
, 1);
882 if (XINT (bytepos
) < BEG_BYTE
|| XINT (bytepos
) > Z_BYTE
)
884 return make_number (BYTE_TO_CHAR (XINT (bytepos
)));
887 DEFUN ("following-char", Ffollowing_char
, Sfollowing_char
, 0, 0, 0,
888 "Return the character following point, as a number.\n\
889 At the end of the buffer or accessible region, return 0.")
894 XSETFASTINT (temp
, 0);
896 XSETFASTINT (temp
, FETCH_CHAR (PT_BYTE
));
900 DEFUN ("preceding-char", Fprevious_char
, Sprevious_char
, 0, 0, 0,
901 "Return the character preceding point, as a number.\n\
902 At the beginning of the buffer or accessible region, return 0.")
907 XSETFASTINT (temp
, 0);
908 else if (!NILP (current_buffer
->enable_multibyte_characters
))
912 XSETFASTINT (temp
, FETCH_CHAR (pos
));
915 XSETFASTINT (temp
, FETCH_BYTE (PT_BYTE
- 1));
919 DEFUN ("bobp", Fbobp
, Sbobp
, 0, 0, 0,
920 "Return t if point is at the beginning of the buffer.\n\
921 If the buffer is narrowed, this means the beginning of the narrowed part.")
929 DEFUN ("eobp", Feobp
, Seobp
, 0, 0, 0,
930 "Return t if point is at the end of the buffer.\n\
931 If the buffer is narrowed, this means the end of the narrowed part.")
939 DEFUN ("bolp", Fbolp
, Sbolp
, 0, 0, 0,
940 "Return t if point is at the beginning of a line.")
943 if (PT
== BEGV
|| FETCH_BYTE (PT_BYTE
- 1) == '\n')
948 DEFUN ("eolp", Feolp
, Seolp
, 0, 0, 0,
949 "Return t if point is at the end of a line.\n\
950 `End of a line' includes point being at the end of the buffer.")
953 if (PT
== ZV
|| FETCH_BYTE (PT_BYTE
) == '\n')
958 DEFUN ("char-after", Fchar_after
, Schar_after
, 0, 1, 0,
959 "Return character in current buffer at position POS.\n\
960 POS is an integer or a marker.\n\
961 If POS is out of range, the value is nil.")
965 register int pos_byte
;
970 XSETFASTINT (pos
, PT
);
975 pos_byte
= marker_byte_position (pos
);
976 if (pos_byte
< BEGV_BYTE
|| pos_byte
>= ZV_BYTE
)
981 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
982 if (XINT (pos
) < BEGV
|| XINT (pos
) >= ZV
)
985 pos_byte
= CHAR_TO_BYTE (XINT (pos
));
988 return make_number (FETCH_CHAR (pos_byte
));
991 DEFUN ("char-before", Fchar_before
, Schar_before
, 0, 1, 0,
992 "Return character in current buffer preceding position POS.\n\
993 POS is an integer or a marker.\n\
994 If POS is out of range, the value is nil.")
998 register Lisp_Object val
;
999 register int pos_byte
;
1004 XSETFASTINT (pos
, PT
);
1009 pos_byte
= marker_byte_position (pos
);
1011 if (pos_byte
<= BEGV_BYTE
|| pos_byte
> ZV_BYTE
)
1016 CHECK_NUMBER_COERCE_MARKER (pos
, 0);
1018 if (XINT (pos
) <= BEGV
|| XINT (pos
) > ZV
)
1021 pos_byte
= CHAR_TO_BYTE (XINT (pos
));
1024 if (!NILP (current_buffer
->enable_multibyte_characters
))
1027 XSETFASTINT (val
, FETCH_CHAR (pos_byte
));
1032 XSETFASTINT (val
, FETCH_BYTE (pos_byte
));
1037 DEFUN ("user-login-name", Fuser_login_name
, Suser_login_name
, 0, 1, 0,
1038 "Return the name under which the user logged in, as a string.\n\
1039 This is based on the effective uid, not the real uid.\n\
1040 Also, if the environment variable LOGNAME or USER is set,\n\
1041 that determines the value of this function.\n\n\
1042 If optional argument UID is an integer, return the login name of the user\n\
1043 with that uid, or nil if there is no such user.")
1049 /* Set up the user name info if we didn't do it before.
1050 (That can happen if Emacs is dumpable
1051 but you decide to run `temacs -l loadup' and not dump. */
1052 if (INTEGERP (Vuser_login_name
))
1056 return Vuser_login_name
;
1058 CHECK_NUMBER (uid
, 0);
1059 pw
= (struct passwd
*) getpwuid (XINT (uid
));
1060 return (pw
? build_string (pw
->pw_name
) : Qnil
);
1063 DEFUN ("user-real-login-name", Fuser_real_login_name
, Suser_real_login_name
,
1065 "Return the name of the user's real uid, as a string.\n\
1066 This ignores the environment variables LOGNAME and USER, so it differs from\n\
1067 `user-login-name' when running under `su'.")
1070 /* Set up the user name info if we didn't do it before.
1071 (That can happen if Emacs is dumpable
1072 but you decide to run `temacs -l loadup' and not dump. */
1073 if (INTEGERP (Vuser_login_name
))
1075 return Vuser_real_login_name
;
1078 DEFUN ("user-uid", Fuser_uid
, Suser_uid
, 0, 0, 0,
1079 "Return the effective uid of Emacs, as an integer.")
1082 return make_number (geteuid ());
1085 DEFUN ("user-real-uid", Fuser_real_uid
, Suser_real_uid
, 0, 0, 0,
1086 "Return the real uid of Emacs, as an integer.")
1089 return make_number (getuid ());
1092 DEFUN ("user-full-name", Fuser_full_name
, Suser_full_name
, 0, 1, 0,
1093 "Return the full name of the user logged in, as a string.\n\
1094 If the full name corresponding to Emacs's userid is not known,\n\
1095 return \"unknown\".\n\
1097 If optional argument UID is an integer, return the full name of the user\n\
1098 with that uid, or nil if there is no such user.\n\
1099 If UID is a string, return the full name of the user with that login\n\
1100 name, or nil if there is no such user.")
1105 register unsigned char *p
, *q
;
1106 extern char *index ();
1110 return Vuser_full_name
;
1111 else if (NUMBERP (uid
))
1112 pw
= (struct passwd
*) getpwuid (XINT (uid
));
1113 else if (STRINGP (uid
))
1114 pw
= (struct passwd
*) getpwnam (XSTRING (uid
)->data
);
1116 error ("Invalid UID specification");
1121 p
= (unsigned char *) USER_FULL_NAME
;
1122 /* Chop off everything after the first comma. */
1123 q
= (unsigned char *) index (p
, ',');
1124 full
= make_string (p
, q
? q
- p
: strlen (p
));
1126 #ifdef AMPERSAND_FULL_NAME
1127 p
= XSTRING (full
)->data
;
1128 q
= (unsigned char *) index (p
, '&');
1129 /* Substitute the login name for the &, upcasing the first character. */
1132 register unsigned char *r
;
1135 login
= Fuser_login_name (make_number (pw
->pw_uid
));
1136 r
= (unsigned char *) alloca (strlen (p
) + XSTRING (login
)->size
+ 1);
1137 bcopy (p
, r
, q
- p
);
1139 strcat (r
, XSTRING (login
)->data
);
1140 r
[q
- p
] = UPCASE (r
[q
- p
]);
1142 full
= build_string (r
);
1144 #endif /* AMPERSAND_FULL_NAME */
1149 DEFUN ("system-name", Fsystem_name
, Ssystem_name
, 0, 0, 0,
1150 "Return the name of the machine you are running on, as a string.")
1153 return Vsystem_name
;
1156 /* For the benefit of callers who don't want to include lisp.h */
1160 if (STRINGP (Vsystem_name
))
1161 return (char *) XSTRING (Vsystem_name
)->data
;
1166 DEFUN ("emacs-pid", Femacs_pid
, Semacs_pid
, 0, 0, 0,
1167 "Return the process ID of Emacs, as an integer.")
1170 return make_number (getpid ());
1173 DEFUN ("current-time", Fcurrent_time
, Scurrent_time
, 0, 0, 0,
1174 "Return the current time, as the number of seconds since 1970-01-01 00:00:00.\n\
1175 The time is returned as a list of three integers. The first has the\n\
1176 most significant 16 bits of the seconds, while the second has the\n\
1177 least significant 16 bits. The third integer gives the microsecond\n\
1180 The microsecond count is zero on systems that do not provide\n\
1181 resolution finer than a second.")
1185 Lisp_Object result
[3];
1188 XSETINT (result
[0], (EMACS_SECS (t
) >> 16) & 0xffff);
1189 XSETINT (result
[1], (EMACS_SECS (t
) >> 0) & 0xffff);
1190 XSETINT (result
[2], EMACS_USECS (t
));
1192 return Flist (3, result
);
1197 lisp_time_argument (specified_time
, result
, usec
)
1198 Lisp_Object specified_time
;
1202 if (NILP (specified_time
))
1209 *usec
= EMACS_USECS (t
);
1210 *result
= EMACS_SECS (t
);
1214 return time (result
) != -1;
1218 Lisp_Object high
, low
;
1219 high
= Fcar (specified_time
);
1220 CHECK_NUMBER (high
, 0);
1221 low
= Fcdr (specified_time
);
1226 Lisp_Object usec_l
= Fcdr (low
);
1228 usec_l
= Fcar (usec_l
);
1233 CHECK_NUMBER (usec_l
, 0);
1234 *usec
= XINT (usec_l
);
1241 CHECK_NUMBER (low
, 0);
1242 *result
= (XINT (high
) << 16) + (XINT (low
) & 0xffff);
1243 return *result
>> 16 == XINT (high
);
1247 DEFUN ("float-time", Ffloat_time
, Sfloat_time
, 0, 1, 0,
1248 "Return the current time, as a float number of seconds since the epoch.\n\
1249 If an argument is given, it specifies a time to convert to float\n\
1250 instead of the current time. The argument should have the forms:\n\
1251 (HIGH . LOW) or (HIGH LOW USEC) or (HIGH LOW . USEC).\n\
1252 Thus, you can use times obtained from `current-time'\n\
1253 and from `file-attributes'.")
1255 Lisp_Object specified_time
;
1260 if (! lisp_time_argument (specified_time
, &sec
, &usec
))
1261 error ("Invalid time specification");
1263 return make_float (sec
+ usec
* 0.0000001);
1266 /* Write information into buffer S of size MAXSIZE, according to the
1267 FORMAT of length FORMAT_LEN, using time information taken from *TP.
1268 Default to Universal Time if UT is nonzero, local time otherwise.
1269 Return the number of bytes written, not including the terminating
1270 '\0'. If S is NULL, nothing will be written anywhere; so to
1271 determine how many bytes would be written, use NULL for S and
1272 ((size_t) -1) for MAXSIZE.
1274 This function behaves like emacs_strftimeu, except it allows null
1277 emacs_memftimeu (s
, maxsize
, format
, format_len
, tp
, ut
)
1282 const struct tm
*tp
;
1287 /* Loop through all the null-terminated strings in the format
1288 argument. Normally there's just one null-terminated string, but
1289 there can be arbitrarily many, concatenated together, if the
1290 format contains '\0' bytes. emacs_strftimeu stops at the first
1291 '\0' byte so we must invoke it separately for each such string. */
1300 result
= emacs_strftimeu (s
, maxsize
, format
, tp
, ut
);
1304 if (result
== 0 && s
[0] != '\0')
1309 maxsize
-= result
+ 1;
1311 len
= strlen (format
);
1312 if (len
== format_len
)
1316 format_len
-= len
+ 1;
1321 DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 3, 0,
1322 "Use FORMAT-STRING to format the time TIME, or now if omitted.\n\
1323 TIME is specified as (HIGH LOW . IGNORED) or (HIGH . LOW), as returned by\n\
1324 `current-time' or `file-attributes'.\n\
1325 The third, optional, argument UNIVERSAL, if non-nil, means describe TIME\n\
1326 as Universal Time; nil means describe TIME in the local time zone.\n\
1327 The value is a copy of FORMAT-STRING, but with certain constructs replaced\n\
1328 by text that describes the specified date and time in TIME:\n\
1330 %Y is the year, %y within the century, %C the century.\n\
1331 %G is the year corresponding to the ISO week, %g within the century.\n\
1332 %m is the numeric month.\n\
1333 %b and %h are the locale's abbreviated month name, %B the full name.\n\
1334 %d is the day of the month, zero-padded, %e is blank-padded.\n\
1335 %u is the numeric day of week from 1 (Monday) to 7, %w from 0 (Sunday) to 6.\n\
1336 %a is the locale's abbreviated name of the day of week, %A the full name.\n\
1337 %U is the week number starting on Sunday, %W starting on Monday,\n\
1338 %V according to ISO 8601.\n\
1339 %j is the day of the year.\n\
1341 %H is the hour on a 24-hour clock, %I is on a 12-hour clock, %k is like %H\n\
1342 only blank-padded, %l is like %I blank-padded.\n\
1343 %p is the locale's equivalent of either AM or PM.\n\
1344 %M is the minute.\n\
1345 %S is the second.\n\
1346 %Z is the time zone name, %z is the numeric form.\n\
1347 %s is the number of seconds since 1970-01-01 00:00:00 +0000.\n\
1349 %c is the locale's date and time format.\n\
1350 %x is the locale's \"preferred\" date format.\n\
1351 %D is like \"%m/%d/%y\".\n\
1353 %R is like \"%H:%M\", %T is like \"%H:%M:%S\", %r is like \"%I:%M:%S %p\".\n\
1354 %X is the locale's \"preferred\" time format.\n\
1356 Finally, %n is a newline, %t is a tab, %% is a literal %.\n\
1358 Certain flags and modifiers are available with some format controls.\n\
1359 The flags are `_' and `-'. For certain characters X, %_X is like %X,\n\
1360 but padded with blanks; %-X is like %X, but without padding.\n\
1361 %NX (where N stands for an integer) is like %X,\n\
1362 but takes up at least N (a number) positions.\n\
1363 The modifiers are `E' and `O'. For certain characters X,\n\
1364 %EX is a locale's alternative version of %X;\n\
1365 %OX is like %X, but uses the locale's number symbols.\n\
1367 For example, to produce full ISO 8601 format, use \"%Y-%m-%dT%T%z\".")
1368 (format_string, time, universal)
1371 DEFUN ("format-time-string", Fformat_time_string
, Sformat_time_string
, 1, 3, 0,
1372 0 /* See immediately above */)
1373 (format_string
, time
, universal
)
1374 Lisp_Object format_string
, time
, universal
;
1379 int ut
= ! NILP (universal
);
1381 CHECK_STRING (format_string
, 1);
1383 if (! lisp_time_argument (time
, &value
, NULL
))
1384 error ("Invalid time specification");
1386 format_string
= code_convert_string_norecord (format_string
,
1387 Vlocale_coding_system
, 1);
1389 /* This is probably enough. */
1390 size
= STRING_BYTES (XSTRING (format_string
)) * 6 + 50;
1392 tm
= ut
? gmtime (&value
) : localtime (&value
);
1394 error ("Specified time is not representable");
1396 synchronize_system_time_locale ();
1400 char *buf
= (char *) alloca (size
+ 1);
1404 result
= emacs_memftimeu (buf
, size
, XSTRING (format_string
)->data
,
1405 STRING_BYTES (XSTRING (format_string
)),
1407 if ((result
> 0 && result
< size
) || (result
== 0 && buf
[0] == '\0'))
1408 return code_convert_string_norecord (make_string (buf
, result
),
1409 Vlocale_coding_system
, 0);
1411 /* If buffer was too small, make it bigger and try again. */
1412 result
= emacs_memftimeu (NULL
, (size_t) -1,
1413 XSTRING (format_string
)->data
,
1414 STRING_BYTES (XSTRING (format_string
)),
1420 DEFUN ("decode-time", Fdecode_time
, Sdecode_time
, 0, 1, 0,
1421 "Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).\n\
1422 The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED)\n\
1423 or (HIGH . LOW), as from `current-time' and `file-attributes', or `nil'\n\
1424 to use the current time. The list has the following nine members:\n\
1425 SEC is an integer between 0 and 60; SEC is 60 for a leap second, which\n\
1426 only some operating systems support. MINUTE is an integer between 0 and 59.\n\
1427 HOUR is an integer between 0 and 23. DAY is an integer between 1 and 31.\n\
1428 MONTH is an integer between 1 and 12. YEAR is an integer indicating the\n\
1429 four-digit year. DOW is the day of week, an integer between 0 and 6, where\n\
1430 0 is Sunday. DST is t if daylight savings time is effect, otherwise nil.\n\
1431 ZONE is an integer indicating the number of seconds east of Greenwich.\n\
1432 \(Note that Common Lisp has different meanings for DOW and ZONE.)")
1434 Lisp_Object specified_time
;
1438 struct tm
*decoded_time
;
1439 Lisp_Object list_args
[9];
1441 if (! lisp_time_argument (specified_time
, &time_spec
, NULL
))
1442 error ("Invalid time specification");
1444 decoded_time
= localtime (&time_spec
);
1446 error ("Specified time is not representable");
1447 XSETFASTINT (list_args
[0], decoded_time
->tm_sec
);
1448 XSETFASTINT (list_args
[1], decoded_time
->tm_min
);
1449 XSETFASTINT (list_args
[2], decoded_time
->tm_hour
);
1450 XSETFASTINT (list_args
[3], decoded_time
->tm_mday
);
1451 XSETFASTINT (list_args
[4], decoded_time
->tm_mon
+ 1);
1452 XSETINT (list_args
[5], decoded_time
->tm_year
+ 1900);
1453 XSETFASTINT (list_args
[6], decoded_time
->tm_wday
);
1454 list_args
[7] = (decoded_time
->tm_isdst
)? Qt
: Qnil
;
1456 /* Make a copy, in case gmtime modifies the struct. */
1457 save_tm
= *decoded_time
;
1458 decoded_time
= gmtime (&time_spec
);
1459 if (decoded_time
== 0)
1460 list_args
[8] = Qnil
;
1462 XSETINT (list_args
[8], tm_diff (&save_tm
, decoded_time
));
1463 return Flist (9, list_args
);
1466 DEFUN ("encode-time", Fencode_time
, Sencode_time
, 6, MANY
, 0,
1467 "Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.\n\
1468 This is the reverse operation of `decode-time', which see.\n\
1469 ZONE defaults to the current time zone rule. This can\n\
1470 be a string or t (as from `set-time-zone-rule'), or it can be a list\n\
1471 \(as from `current-time-zone') or an integer (as from `decode-time')\n\
1472 applied without consideration for daylight savings time.\n\
1474 You can pass more than 7 arguments; then the first six arguments\n\
1475 are used as SECOND through YEAR, and the *last* argument is used as ZONE.\n\
1476 The intervening arguments are ignored.\n\
1477 This feature lets (apply 'encode-time (decode-time ...)) work.\n\
1479 Out-of-range values for SEC, MINUTE, HOUR, DAY, or MONTH are allowed;\n\
1480 for example, a DAY of 0 means the day preceding the given month.\n\
1481 Year numbers less than 100 are treated just like other year numbers.\n\
1482 If you want them to stand for years in this century, you must do that yourself.")
1485 register Lisp_Object
*args
;
1489 Lisp_Object zone
= (nargs
> 6 ? args
[nargs
- 1] : Qnil
);
1491 CHECK_NUMBER (args
[0], 0); /* second */
1492 CHECK_NUMBER (args
[1], 1); /* minute */
1493 CHECK_NUMBER (args
[2], 2); /* hour */
1494 CHECK_NUMBER (args
[3], 3); /* day */
1495 CHECK_NUMBER (args
[4], 4); /* month */
1496 CHECK_NUMBER (args
[5], 5); /* year */
1498 tm
.tm_sec
= XINT (args
[0]);
1499 tm
.tm_min
= XINT (args
[1]);
1500 tm
.tm_hour
= XINT (args
[2]);
1501 tm
.tm_mday
= XINT (args
[3]);
1502 tm
.tm_mon
= XINT (args
[4]) - 1;
1503 tm
.tm_year
= XINT (args
[5]) - 1900;
1509 time
= mktime (&tm
);
1514 char **oldenv
= environ
, **newenv
;
1518 else if (STRINGP (zone
))
1519 tzstring
= (char *) XSTRING (zone
)->data
;
1520 else if (INTEGERP (zone
))
1522 int abszone
= abs (XINT (zone
));
1523 sprintf (tzbuf
, "XXX%s%d:%02d:%02d", "-" + (XINT (zone
) < 0),
1524 abszone
/ (60*60), (abszone
/60) % 60, abszone
% 60);
1528 error ("Invalid time zone specification");
1530 /* Set TZ before calling mktime; merely adjusting mktime's returned
1531 value doesn't suffice, since that would mishandle leap seconds. */
1532 set_time_zone_rule (tzstring
);
1534 time
= mktime (&tm
);
1536 /* Restore TZ to previous value. */
1540 #ifdef LOCALTIME_CACHE
1545 if (time
== (time_t) -1)
1546 error ("Specified time is not representable");
1548 return make_time (time
);
1551 DEFUN ("current-time-string", Fcurrent_time_string
, Scurrent_time_string
, 0, 1, 0,
1552 "Return the current time, as a human-readable string.\n\
1553 Programs can use this function to decode a time,\n\
1554 since the number of columns in each field is fixed.\n\
1555 The format is `Sun Sep 16 01:03:52 1973'.\n\
1556 However, see also the functions `decode-time' and `format-time-string'\n\
1557 which provide a much more powerful and general facility.\n\
1559 If an argument is given, it specifies a time to format\n\
1560 instead of the current time. The argument should have the form:\n\
1563 (HIGH LOW . IGNORED).\n\
1564 Thus, you can use times obtained from `current-time'\n\
1565 and from `file-attributes'.")
1567 Lisp_Object specified_time
;
1573 if (! lisp_time_argument (specified_time
, &value
, NULL
))
1575 tem
= (char *) ctime (&value
);
1577 strncpy (buf
, tem
, 24);
1580 return build_string (buf
);
1583 #define TM_YEAR_BASE 1900
1585 /* Yield A - B, measured in seconds.
1586 This function is copied from the GNU C Library. */
1591 /* Compute intervening leap days correctly even if year is negative.
1592 Take care to avoid int overflow in leap day calculations,
1593 but it's OK to assume that A and B are close to each other. */
1594 int a4
= (a
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (a
->tm_year
& 3);
1595 int b4
= (b
->tm_year
>> 2) + (TM_YEAR_BASE
>> 2) - ! (b
->tm_year
& 3);
1596 int a100
= a4
/ 25 - (a4
% 25 < 0);
1597 int b100
= b4
/ 25 - (b4
% 25 < 0);
1598 int a400
= a100
>> 2;
1599 int b400
= b100
>> 2;
1600 int intervening_leap_days
= (a4
- b4
) - (a100
- b100
) + (a400
- b400
);
1601 int years
= a
->tm_year
- b
->tm_year
;
1602 int days
= (365 * years
+ intervening_leap_days
1603 + (a
->tm_yday
- b
->tm_yday
));
1604 return (60 * (60 * (24 * days
+ (a
->tm_hour
- b
->tm_hour
))
1605 + (a
->tm_min
- b
->tm_min
))
1606 + (a
->tm_sec
- b
->tm_sec
));
1609 DEFUN ("current-time-zone", Fcurrent_time_zone
, Scurrent_time_zone
, 0, 1, 0,
1610 "Return the offset and name for the local time zone.\n\
1611 This returns a list of the form (OFFSET NAME).\n\
1612 OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).\n\
1613 A negative value means west of Greenwich.\n\
1614 NAME is a string giving the name of the time zone.\n\
1615 If an argument is given, it specifies when the time zone offset is determined\n\
1616 instead of using the current time. The argument should have the form:\n\
1619 (HIGH LOW . IGNORED).\n\
1620 Thus, you can use times obtained from `current-time'\n\
1621 and from `file-attributes'.\n\
1623 Some operating systems cannot provide all this information to Emacs;\n\
1624 in this case, `current-time-zone' returns a list containing nil for\n\
1625 the data it can't find.")
1627 Lisp_Object specified_time
;
1633 if (lisp_time_argument (specified_time
, &value
, NULL
)
1634 && (t
= gmtime (&value
)) != 0
1635 && (gmt
= *t
, t
= localtime (&value
)) != 0)
1637 int offset
= tm_diff (t
, &gmt
);
1642 s
= (char *)t
->tm_zone
;
1643 #else /* not HAVE_TM_ZONE */
1645 if (t
->tm_isdst
== 0 || t
->tm_isdst
== 1)
1646 s
= tzname
[t
->tm_isdst
];
1648 #endif /* not HAVE_TM_ZONE */
1651 /* No local time zone name is available; use "+-NNNN" instead. */
1652 int am
= (offset
< 0 ? -offset
: offset
) / 60;
1653 sprintf (buf
, "%c%02d%02d", (offset
< 0 ? '-' : '+'), am
/60, am
%60);
1656 return Fcons (make_number (offset
), Fcons (build_string (s
), Qnil
));
1659 return Fmake_list (make_number (2), Qnil
);
1662 /* This holds the value of `environ' produced by the previous
1663 call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule
1664 has never been called. */
1665 static char **environbuf
;
1667 DEFUN ("set-time-zone-rule", Fset_time_zone_rule
, Sset_time_zone_rule
, 1, 1, 0,
1668 "Set the local time zone using TZ, a string specifying a time zone rule.\n\
1669 If TZ is nil, use implementation-defined default time zone information.\n\
1670 If TZ is t, use Universal Time.")
1678 else if (EQ (tz
, Qt
))
1682 CHECK_STRING (tz
, 0);
1683 tzstring
= (char *) XSTRING (tz
)->data
;
1686 set_time_zone_rule (tzstring
);
1689 environbuf
= environ
;
1694 #ifdef LOCALTIME_CACHE
1696 /* These two values are known to load tz files in buggy implementations,
1697 i.e. Solaris 1 executables running under either Solaris 1 or Solaris 2.
1698 Their values shouldn't matter in non-buggy implementations.
1699 We don't use string literals for these strings,
1700 since if a string in the environment is in readonly
1701 storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
1702 See Sun bugs 1113095 and 1114114, ``Timezone routines
1703 improperly modify environment''. */
1705 static char set_time_zone_rule_tz1
[] = "TZ=GMT+0";
1706 static char set_time_zone_rule_tz2
[] = "TZ=GMT+1";
1710 /* Set the local time zone rule to TZSTRING.
1711 This allocates memory into `environ', which it is the caller's
1712 responsibility to free. */
1714 set_time_zone_rule (tzstring
)
1718 char **from
, **to
, **newenv
;
1720 /* Make the ENVIRON vector longer with room for TZSTRING. */
1721 for (from
= environ
; *from
; from
++)
1723 envptrs
= from
- environ
+ 2;
1724 newenv
= to
= (char **) xmalloc (envptrs
* sizeof (char *)
1725 + (tzstring
? strlen (tzstring
) + 4 : 0));
1727 /* Add TZSTRING to the end of environ, as a value for TZ. */
1730 char *t
= (char *) (to
+ envptrs
);
1732 strcat (t
, tzstring
);
1736 /* Copy the old environ vector elements into NEWENV,
1737 but don't copy the TZ variable.
1738 So we have only one definition of TZ, which came from TZSTRING. */
1739 for (from
= environ
; *from
; from
++)
1740 if (strncmp (*from
, "TZ=", 3) != 0)
1746 /* If we do have a TZSTRING, NEWENV points to the vector slot where
1747 the TZ variable is stored. If we do not have a TZSTRING,
1748 TO points to the vector slot which has the terminating null. */
1750 #ifdef LOCALTIME_CACHE
1752 /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
1753 "US/Pacific" that loads a tz file, then changes to a value like
1754 "XXX0" that does not load a tz file, and then changes back to
1755 its original value, the last change is (incorrectly) ignored.
1756 Also, if TZ changes twice in succession to values that do
1757 not load a tz file, tzset can dump core (see Sun bug#1225179).
1758 The following code works around these bugs. */
1762 /* Temporarily set TZ to a value that loads a tz file
1763 and that differs from tzstring. */
1765 *newenv
= (strcmp (tzstring
, set_time_zone_rule_tz1
+ 3) == 0
1766 ? set_time_zone_rule_tz2
: set_time_zone_rule_tz1
);
1772 /* The implied tzstring is unknown, so temporarily set TZ to
1773 two different values that each load a tz file. */
1774 *to
= set_time_zone_rule_tz1
;
1777 *to
= set_time_zone_rule_tz2
;
1782 /* Now TZ has the desired value, and tzset can be invoked safely. */
1789 /* Insert NARGS Lisp objects in the array ARGS by calling INSERT_FUNC
1790 (if a type of object is Lisp_Int) or INSERT_FROM_STRING_FUNC (if a
1791 type of object is Lisp_String). INHERIT is passed to
1792 INSERT_FROM_STRING_FUNC as the last argument. */
1795 general_insert_function (insert_func
, insert_from_string_func
,
1796 inherit
, nargs
, args
)
1797 void (*insert_func
) P_ ((unsigned char *, int));
1798 void (*insert_from_string_func
) P_ ((Lisp_Object
, int, int, int, int, int));
1800 register Lisp_Object
*args
;
1802 register int argnum
;
1803 register Lisp_Object val
;
1805 for (argnum
= 0; argnum
< nargs
; argnum
++)
1811 unsigned char str
[MAX_MULTIBYTE_LENGTH
];
1814 if (!NILP (current_buffer
->enable_multibyte_characters
))
1815 len
= CHAR_STRING (XFASTINT (val
), str
);
1818 str
[0] = (SINGLE_BYTE_CHAR_P (XINT (val
))
1820 : multibyte_char_to_unibyte (XINT (val
), Qnil
));
1823 (*insert_func
) (str
, len
);
1825 else if (STRINGP (val
))
1827 (*insert_from_string_func
) (val
, 0, 0,
1828 XSTRING (val
)->size
,
1829 STRING_BYTES (XSTRING (val
)),
1834 val
= wrong_type_argument (Qchar_or_string_p
, val
);
1848 /* Callers passing one argument to Finsert need not gcpro the
1849 argument "array", since the only element of the array will
1850 not be used after calling insert or insert_from_string, so
1851 we don't care if it gets trashed. */
1853 DEFUN ("insert", Finsert
, Sinsert
, 0, MANY
, 0,
1854 "Insert the arguments, either strings or characters, at point.\n\
1855 Point and before-insertion markers move forward to end up\n\
1856 after the inserted text.\n\
1857 Any other markers at the point of insertion remain before the text.\n\
1859 If the current buffer is multibyte, unibyte strings are converted\n\
1860 to multibyte for insertion (see `unibyte-char-to-multibyte').\n\
1861 If the current buffer is unibyte, multibyte strings are converted\n\
1862 to unibyte for insertion.")
1865 register Lisp_Object
*args
;
1867 general_insert_function (insert
, insert_from_string
, 0, nargs
, args
);
1871 DEFUN ("insert-and-inherit", Finsert_and_inherit
, Sinsert_and_inherit
,
1873 "Insert the arguments at point, inheriting properties from adjoining text.\n\
1874 Point and before-insertion markers move forward to end up\n\
1875 after the inserted text.\n\
1876 Any other markers at the point of insertion remain before the text.\n\
1878 If the current buffer is multibyte, unibyte strings are converted\n\
1879 to multibyte for insertion (see `unibyte-char-to-multibyte').\n\
1880 If the current buffer is unibyte, multibyte strings are converted\n\
1881 to unibyte for insertion.")
1884 register Lisp_Object
*args
;
1886 general_insert_function (insert_and_inherit
, insert_from_string
, 1,
1891 DEFUN ("insert-before-markers", Finsert_before_markers
, Sinsert_before_markers
, 0, MANY
, 0,
1892 "Insert strings or characters at point, relocating markers after the text.\n\
1893 Point and markers move forward to end up after the inserted text.\n\
1895 If the current buffer is multibyte, unibyte strings are converted\n\
1896 to multibyte for insertion (see `unibyte-char-to-multibyte').\n\
1897 If the current buffer is unibyte, multibyte strings are converted\n\
1898 to unibyte for insertion.")
1901 register Lisp_Object
*args
;
1903 general_insert_function (insert_before_markers
,
1904 insert_from_string_before_markers
, 0,
1909 DEFUN ("insert-before-markers-and-inherit", Finsert_and_inherit_before_markers
,
1910 Sinsert_and_inherit_before_markers
, 0, MANY
, 0,
1911 "Insert text at point, relocating markers and inheriting properties.\n\
1912 Point and markers move forward to end up after the inserted text.\n\
1914 If the current buffer is multibyte, unibyte strings are converted\n\
1915 to multibyte for insertion (see `unibyte-char-to-multibyte').\n\
1916 If the current buffer is unibyte, multibyte strings are converted\n\
1917 to unibyte for insertion.")
1920 register Lisp_Object
*args
;
1922 general_insert_function (insert_before_markers_and_inherit
,
1923 insert_from_string_before_markers
, 1,
1928 DEFUN ("insert-char", Finsert_char
, Sinsert_char
, 2, 3, 0,
1929 "Insert COUNT (second arg) copies of CHARACTER (first arg).\n\
1930 Both arguments are required.\n\
1931 Point, and before-insertion markers, are relocated as in the function `insert'.\n\
1932 The optional third arg INHERIT, if non-nil, says to inherit text properties\n\
1933 from adjoining text, if those properties are sticky.")
1934 (character
, count
, inherit
)
1935 Lisp_Object character
, count
, inherit
;
1937 register unsigned char *string
;
1938 register int strlen
;
1941 unsigned char str
[MAX_MULTIBYTE_LENGTH
];
1943 CHECK_NUMBER (character
, 0);
1944 CHECK_NUMBER (count
, 1);
1946 if (!NILP (current_buffer
->enable_multibyte_characters
))
1947 len
= CHAR_STRING (XFASTINT (character
), str
);
1949 str
[0] = XFASTINT (character
), len
= 1;
1950 n
= XINT (count
) * len
;
1953 strlen
= min (n
, 256 * len
);
1954 string
= (unsigned char *) alloca (strlen
);
1955 for (i
= 0; i
< strlen
; i
++)
1956 string
[i
] = str
[i
% len
];
1960 if (!NILP (inherit
))
1961 insert_and_inherit (string
, strlen
);
1963 insert (string
, strlen
);
1968 if (!NILP (inherit
))
1969 insert_and_inherit (string
, n
);
1977 /* Making strings from buffer contents. */
1979 /* Return a Lisp_String containing the text of the current buffer from
1980 START to END. If text properties are in use and the current buffer
1981 has properties in the range specified, the resulting string will also
1982 have them, if PROPS is nonzero.
1984 We don't want to use plain old make_string here, because it calls
1985 make_uninit_string, which can cause the buffer arena to be
1986 compacted. make_string has no way of knowing that the data has
1987 been moved, and thus copies the wrong data into the string. This
1988 doesn't effect most of the other users of make_string, so it should
1989 be left as is. But we should use this function when conjuring
1990 buffer substrings. */
1993 make_buffer_string (start
, end
, props
)
1997 int start_byte
= CHAR_TO_BYTE (start
);
1998 int end_byte
= CHAR_TO_BYTE (end
);
2000 return make_buffer_string_both (start
, start_byte
, end
, end_byte
, props
);
2003 /* Return a Lisp_String containing the text of the current buffer from
2004 START / START_BYTE to END / END_BYTE.
2006 If text properties are in use and the current buffer
2007 has properties in the range specified, the resulting string will also
2008 have them, if PROPS is nonzero.
2010 We don't want to use plain old make_string here, because it calls
2011 make_uninit_string, which can cause the buffer arena to be
2012 compacted. make_string has no way of knowing that the data has
2013 been moved, and thus copies the wrong data into the string. This
2014 doesn't effect most of the other users of make_string, so it should
2015 be left as is. But we should use this function when conjuring
2016 buffer substrings. */
2019 make_buffer_string_both (start
, start_byte
, end
, end_byte
, props
)
2020 int start
, start_byte
, end
, end_byte
;
2023 Lisp_Object result
, tem
, tem1
;
2025 if (start
< GPT
&& GPT
< end
)
2028 if (! NILP (current_buffer
->enable_multibyte_characters
))
2029 result
= make_uninit_multibyte_string (end
- start
, end_byte
- start_byte
);
2031 result
= make_uninit_string (end
- start
);
2032 bcopy (BYTE_POS_ADDR (start_byte
), XSTRING (result
)->data
,
2033 end_byte
- start_byte
);
2035 /* If desired, update and copy the text properties. */
2038 update_buffer_properties (start
, end
);
2040 tem
= Fnext_property_change (make_number (start
), Qnil
, make_number (end
));
2041 tem1
= Ftext_properties_at (make_number (start
), Qnil
);
2043 if (XINT (tem
) != end
|| !NILP (tem1
))
2044 copy_intervals_to_string (result
, current_buffer
, start
,
2051 /* Call Vbuffer_access_fontify_functions for the range START ... END
2052 in the current buffer, if necessary. */
2055 update_buffer_properties (start
, end
)
2058 /* If this buffer has some access functions,
2059 call them, specifying the range of the buffer being accessed. */
2060 if (!NILP (Vbuffer_access_fontify_functions
))
2062 Lisp_Object args
[3];
2065 args
[0] = Qbuffer_access_fontify_functions
;
2066 XSETINT (args
[1], start
);
2067 XSETINT (args
[2], end
);
2069 /* But don't call them if we can tell that the work
2070 has already been done. */
2071 if (!NILP (Vbuffer_access_fontified_property
))
2073 tem
= Ftext_property_any (args
[1], args
[2],
2074 Vbuffer_access_fontified_property
,
2077 Frun_hook_with_args (3, args
);
2080 Frun_hook_with_args (3, args
);
2084 DEFUN ("buffer-substring", Fbuffer_substring
, Sbuffer_substring
, 2, 2, 0,
2085 "Return the contents of part of the current buffer as a string.\n\
2086 The two arguments START and END are character positions;\n\
2087 they can be in either order.\n\
2088 The string returned is multibyte if the buffer is multibyte.")
2090 Lisp_Object start
, end
;
2094 validate_region (&start
, &end
);
2098 return make_buffer_string (b
, e
, 1);
2101 DEFUN ("buffer-substring-no-properties", Fbuffer_substring_no_properties
,
2102 Sbuffer_substring_no_properties
, 2, 2, 0,
2103 "Return the characters of part of the buffer, without the text properties.\n\
2104 The two arguments START and END are character positions;\n\
2105 they can be in either order.")
2107 Lisp_Object start
, end
;
2111 validate_region (&start
, &end
);
2115 return make_buffer_string (b
, e
, 0);
2118 DEFUN ("buffer-string", Fbuffer_string
, Sbuffer_string
, 0, 0, 0,
2119 "Return the contents of the current buffer as a string.\n\
2120 If narrowing is in effect, this function returns only the visible part\n\
2121 of the buffer. If in a mini-buffer, don't include the prompt in the\n\
2125 return make_buffer_string (BEGV
, ZV
, 1);
2128 DEFUN ("insert-buffer-substring", Finsert_buffer_substring
, Sinsert_buffer_substring
,
2130 "Insert before point a substring of the contents of buffer BUFFER.\n\
2131 BUFFER may be a buffer or a buffer name.\n\
2132 Arguments START and END are character numbers specifying the substring.\n\
2133 They default to the beginning and the end of BUFFER.")
2135 Lisp_Object buf
, start
, end
;
2137 register int b
, e
, temp
;
2138 register struct buffer
*bp
, *obuf
;
2141 buffer
= Fget_buffer (buf
);
2144 bp
= XBUFFER (buffer
);
2145 if (NILP (bp
->name
))
2146 error ("Selecting deleted buffer");
2152 CHECK_NUMBER_COERCE_MARKER (start
, 0);
2159 CHECK_NUMBER_COERCE_MARKER (end
, 1);
2164 temp
= b
, b
= e
, e
= temp
;
2166 if (!(BUF_BEGV (bp
) <= b
&& e
<= BUF_ZV (bp
)))
2167 args_out_of_range (start
, end
);
2169 obuf
= current_buffer
;
2170 set_buffer_internal_1 (bp
);
2171 update_buffer_properties (b
, e
);
2172 set_buffer_internal_1 (obuf
);
2174 insert_from_buffer (bp
, b
, e
- b
, 0);
2178 DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings
, Scompare_buffer_substrings
,
2180 "Compare two substrings of two buffers; return result as number.\n\
2181 the value is -N if first string is less after N-1 chars,\n\
2182 +N if first string is greater after N-1 chars, or 0 if strings match.\n\
2183 Each substring is represented as three arguments: BUFFER, START and END.\n\
2184 That makes six args in all, three for each substring.\n\n\
2185 The value of `case-fold-search' in the current buffer\n\
2186 determines whether case is significant or ignored.")
2187 (buffer1
, start1
, end1
, buffer2
, start2
, end2
)
2188 Lisp_Object buffer1
, start1
, end1
, buffer2
, start2
, end2
;
2190 register int begp1
, endp1
, begp2
, endp2
, temp
;
2191 register struct buffer
*bp1
, *bp2
;
2192 register Lisp_Object
*trt
2193 = (!NILP (current_buffer
->case_fold_search
)
2194 ? XCHAR_TABLE (current_buffer
->case_canon_table
)->contents
: 0);
2196 int i1
, i2
, i1_byte
, i2_byte
;
2198 /* Find the first buffer and its substring. */
2201 bp1
= current_buffer
;
2205 buf1
= Fget_buffer (buffer1
);
2208 bp1
= XBUFFER (buf1
);
2209 if (NILP (bp1
->name
))
2210 error ("Selecting deleted buffer");
2214 begp1
= BUF_BEGV (bp1
);
2217 CHECK_NUMBER_COERCE_MARKER (start1
, 1);
2218 begp1
= XINT (start1
);
2221 endp1
= BUF_ZV (bp1
);
2224 CHECK_NUMBER_COERCE_MARKER (end1
, 2);
2225 endp1
= XINT (end1
);
2229 temp
= begp1
, begp1
= endp1
, endp1
= temp
;
2231 if (!(BUF_BEGV (bp1
) <= begp1
2233 && endp1
<= BUF_ZV (bp1
)))
2234 args_out_of_range (start1
, end1
);
2236 /* Likewise for second substring. */
2239 bp2
= current_buffer
;
2243 buf2
= Fget_buffer (buffer2
);
2246 bp2
= XBUFFER (buf2
);
2247 if (NILP (bp2
->name
))
2248 error ("Selecting deleted buffer");
2252 begp2
= BUF_BEGV (bp2
);
2255 CHECK_NUMBER_COERCE_MARKER (start2
, 4);
2256 begp2
= XINT (start2
);
2259 endp2
= BUF_ZV (bp2
);
2262 CHECK_NUMBER_COERCE_MARKER (end2
, 5);
2263 endp2
= XINT (end2
);
2267 temp
= begp2
, begp2
= endp2
, endp2
= temp
;
2269 if (!(BUF_BEGV (bp2
) <= begp2
2271 && endp2
<= BUF_ZV (bp2
)))
2272 args_out_of_range (start2
, end2
);
2276 i1_byte
= buf_charpos_to_bytepos (bp1
, i1
);
2277 i2_byte
= buf_charpos_to_bytepos (bp2
, i2
);
2279 while (i1
< endp1
&& i2
< endp2
)
2281 /* When we find a mismatch, we must compare the
2282 characters, not just the bytes. */
2285 if (! NILP (bp1
->enable_multibyte_characters
))
2287 c1
= BUF_FETCH_MULTIBYTE_CHAR (bp1
, i1_byte
);
2288 BUF_INC_POS (bp1
, i1_byte
);
2293 c1
= BUF_FETCH_BYTE (bp1
, i1
);
2294 c1
= unibyte_char_to_multibyte (c1
);
2298 if (! NILP (bp2
->enable_multibyte_characters
))
2300 c2
= BUF_FETCH_MULTIBYTE_CHAR (bp2
, i2_byte
);
2301 BUF_INC_POS (bp2
, i2_byte
);
2306 c2
= BUF_FETCH_BYTE (bp2
, i2
);
2307 c2
= unibyte_char_to_multibyte (c2
);
2313 c1
= XINT (trt
[c1
]);
2314 c2
= XINT (trt
[c2
]);
2317 return make_number (- 1 - chars
);
2319 return make_number (chars
+ 1);
2324 /* The strings match as far as they go.
2325 If one is shorter, that one is less. */
2326 if (chars
< endp1
- begp1
)
2327 return make_number (chars
+ 1);
2328 else if (chars
< endp2
- begp2
)
2329 return make_number (- chars
- 1);
2331 /* Same length too => they are equal. */
2332 return make_number (0);
2336 subst_char_in_region_unwind (arg
)
2339 return current_buffer
->undo_list
= arg
;
2343 subst_char_in_region_unwind_1 (arg
)
2346 return current_buffer
->filename
= arg
;
2349 DEFUN ("subst-char-in-region", Fsubst_char_in_region
,
2350 Ssubst_char_in_region
, 4, 5, 0,
2351 "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\
2352 If optional arg NOUNDO is non-nil, don't record this change for undo\n\
2353 and don't mark the buffer as really changed.\n\
2354 Both characters must have the same length of multi-byte form.")
2355 (start
, end
, fromchar
, tochar
, noundo
)
2356 Lisp_Object start
, end
, fromchar
, tochar
, noundo
;
2358 register int pos
, pos_byte
, stop
, i
, len
, end_byte
;
2360 unsigned char fromstr
[MAX_MULTIBYTE_LENGTH
], tostr
[MAX_MULTIBYTE_LENGTH
];
2362 int count
= specpdl_ptr
- specpdl
;
2363 #define COMBINING_NO 0
2364 #define COMBINING_BEFORE 1
2365 #define COMBINING_AFTER 2
2366 #define COMBINING_BOTH (COMBINING_BEFORE | COMBINING_AFTER)
2367 int maybe_byte_combining
= COMBINING_NO
;
2369 int multibyte_p
= !NILP (current_buffer
->enable_multibyte_characters
);
2371 validate_region (&start
, &end
);
2372 CHECK_NUMBER (fromchar
, 2);
2373 CHECK_NUMBER (tochar
, 3);
2377 len
= CHAR_STRING (XFASTINT (fromchar
), fromstr
);
2378 if (CHAR_STRING (XFASTINT (tochar
), tostr
) != len
)
2379 error ("Characters in subst-char-in-region have different byte-lengths");
2380 if (!ASCII_BYTE_P (*tostr
))
2382 /* If *TOSTR is in the range 0x80..0x9F and TOCHAR is not a
2383 complete multibyte character, it may be combined with the
2384 after bytes. If it is in the range 0xA0..0xFF, it may be
2385 combined with the before and after bytes. */
2386 if (!CHAR_HEAD_P (*tostr
))
2387 maybe_byte_combining
= COMBINING_BOTH
;
2388 else if (BYTES_BY_CHAR_HEAD (*tostr
) > len
)
2389 maybe_byte_combining
= COMBINING_AFTER
;
2395 fromstr
[0] = XFASTINT (fromchar
);
2396 tostr
[0] = XFASTINT (tochar
);
2400 pos_byte
= CHAR_TO_BYTE (pos
);
2401 stop
= CHAR_TO_BYTE (XINT (end
));
2404 /* If we don't want undo, turn off putting stuff on the list.
2405 That's faster than getting rid of things,
2406 and it prevents even the entry for a first change.
2407 Also inhibit locking the file. */
2410 record_unwind_protect (subst_char_in_region_unwind
,
2411 current_buffer
->undo_list
);
2412 current_buffer
->undo_list
= Qt
;
2413 /* Don't do file-locking. */
2414 record_unwind_protect (subst_char_in_region_unwind_1
,
2415 current_buffer
->filename
);
2416 current_buffer
->filename
= Qnil
;
2419 if (pos_byte
< GPT_BYTE
)
2420 stop
= min (stop
, GPT_BYTE
);
2423 int pos_byte_next
= pos_byte
;
2425 if (pos_byte
>= stop
)
2427 if (pos_byte
>= end_byte
) break;
2430 p
= BYTE_POS_ADDR (pos_byte
);
2432 INC_POS (pos_byte_next
);
2435 if (pos_byte_next
- pos_byte
== len
2436 && p
[0] == fromstr
[0]
2438 || (p
[1] == fromstr
[1]
2439 && (len
== 2 || (p
[2] == fromstr
[2]
2440 && (len
== 3 || p
[3] == fromstr
[3]))))))
2445 modify_region (current_buffer
, changed
, XINT (end
));
2447 if (! NILP (noundo
))
2449 if (MODIFF
- 1 == SAVE_MODIFF
)
2451 if (MODIFF
- 1 == current_buffer
->auto_save_modified
)
2452 current_buffer
->auto_save_modified
++;
2456 /* Take care of the case where the new character
2457 combines with neighboring bytes. */
2458 if (maybe_byte_combining
2459 && (maybe_byte_combining
== COMBINING_AFTER
2460 ? (pos_byte_next
< Z_BYTE
2461 && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte_next
)))
2462 : ((pos_byte_next
< Z_BYTE
2463 && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte_next
)))
2464 || (pos_byte
> BEG_BYTE
2465 && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte
- 1))))))
2467 Lisp_Object tem
, string
;
2469 struct gcpro gcpro1
;
2471 tem
= current_buffer
->undo_list
;
2474 /* Make a multibyte string containing this single character. */
2475 string
= make_multibyte_string (tostr
, 1, len
);
2476 /* replace_range is less efficient, because it moves the gap,
2477 but it handles combining correctly. */
2478 replace_range (pos
, pos
+ 1, string
,
2480 pos_byte_next
= CHAR_TO_BYTE (pos
);
2481 if (pos_byte_next
> pos_byte
)
2482 /* Before combining happened. We should not increment
2483 POS. So, to cancel the later increment of POS,
2487 INC_POS (pos_byte_next
);
2489 if (! NILP (noundo
))
2490 current_buffer
->undo_list
= tem
;
2497 record_change (pos
, 1);
2498 for (i
= 0; i
< len
; i
++) *p
++ = tostr
[i
];
2500 last_changed
= pos
+ 1;
2502 pos_byte
= pos_byte_next
;
2508 signal_after_change (changed
,
2509 last_changed
- changed
, last_changed
- changed
);
2510 update_compositions (changed
, last_changed
, CHECK_ALL
);
2513 unbind_to (count
, Qnil
);
2517 DEFUN ("translate-region", Ftranslate_region
, Stranslate_region
, 3, 3, 0,
2518 "From START to END, translate characters according to TABLE.\n\
2519 TABLE is a string; the Nth character in it is the mapping\n\
2520 for the character with code N.\n\
2521 This function does not alter multibyte characters.\n\
2522 It returns the number of characters changed.")
2526 register Lisp_Object table
;
2528 register int pos_byte
, stop
; /* Limits of the region. */
2529 register unsigned char *tt
; /* Trans table. */
2530 register int nc
; /* New character. */
2531 int cnt
; /* Number of changes made. */
2532 int size
; /* Size of translate table. */
2534 int multibyte
= !NILP (current_buffer
->enable_multibyte_characters
);
2536 validate_region (&start
, &end
);
2537 CHECK_STRING (table
, 2);
2539 size
= STRING_BYTES (XSTRING (table
));
2540 tt
= XSTRING (table
)->data
;
2542 pos_byte
= CHAR_TO_BYTE (XINT (start
));
2543 stop
= CHAR_TO_BYTE (XINT (end
));
2544 modify_region (current_buffer
, XINT (start
), XINT (end
));
2548 for (; pos_byte
< stop
; )
2550 register unsigned char *p
= BYTE_POS_ADDR (pos_byte
);
2556 oc
= STRING_CHAR_AND_LENGTH (p
, stop
- pos_byte
, len
);
2559 pos_byte_next
= pos_byte
+ len
;
2560 if (oc
< size
&& len
== 1)
2565 /* Take care of the case where the new character
2566 combines with neighboring bytes. */
2567 if (!ASCII_BYTE_P (nc
)
2568 && (CHAR_HEAD_P (nc
)
2569 ? ! CHAR_HEAD_P (FETCH_BYTE (pos_byte
+ 1))
2570 : (pos_byte
> BEG_BYTE
2571 && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte
- 1)))))
2575 string
= make_multibyte_string (tt
+ oc
, 1, 1);
2576 /* This is less efficient, because it moves the gap,
2577 but it handles combining correctly. */
2578 replace_range (pos
, pos
+ 1, string
,
2580 pos_byte_next
= CHAR_TO_BYTE (pos
);
2581 if (pos_byte_next
> pos_byte
)
2582 /* Before combining happened. We should not
2583 increment POS. So, to cancel the later
2584 increment of POS, we decrease it now. */
2587 INC_POS (pos_byte_next
);
2591 record_change (pos
, 1);
2593 signal_after_change (pos
, 1, 1);
2594 update_compositions (pos
, pos
+ 1, CHECK_BORDER
);
2599 pos_byte
= pos_byte_next
;
2603 return make_number (cnt
);
2606 DEFUN ("delete-region", Fdelete_region
, Sdelete_region
, 2, 2, "r",
2607 "Delete the text between point and mark.\n\
2608 When called from a program, expects two arguments,\n\
2609 positions (integers or markers) specifying the stretch to be deleted.")
2611 Lisp_Object start
, end
;
2613 validate_region (&start
, &end
);
2614 del_range (XINT (start
), XINT (end
));
2618 DEFUN ("delete-and-extract-region", Fdelete_and_extract_region
,
2619 Sdelete_and_extract_region
, 2, 2, 0,
2620 "Delete the text between START and END and return it.")
2622 Lisp_Object start
, end
;
2624 validate_region (&start
, &end
);
2625 return del_range_1 (XINT (start
), XINT (end
), 1, 1);
2628 DEFUN ("widen", Fwiden
, Swiden
, 0, 0, "",
2629 "Remove restrictions (narrowing) from current buffer.\n\
2630 This allows the buffer's full text to be seen and edited.")
2633 if (BEG
!= BEGV
|| Z
!= ZV
)
2634 current_buffer
->clip_changed
= 1;
2636 BEGV_BYTE
= BEG_BYTE
;
2637 SET_BUF_ZV_BOTH (current_buffer
, Z
, Z_BYTE
);
2638 /* Changing the buffer bounds invalidates any recorded current column. */
2639 invalidate_current_column ();
2643 DEFUN ("narrow-to-region", Fnarrow_to_region
, Snarrow_to_region
, 2, 2, "r",
2644 "Restrict editing in this buffer to the current region.\n\
2645 The rest of the text becomes temporarily invisible and untouchable\n\
2646 but is not deleted; if you save the buffer in a file, the invisible\n\
2647 text is included in the file. \\[widen] makes all visible again.\n\
2648 See also `save-restriction'.\n\
2650 When calling from a program, pass two arguments; positions (integers\n\
2651 or markers) bounding the text that should remain visible.")
2653 register Lisp_Object start
, end
;
2655 CHECK_NUMBER_COERCE_MARKER (start
, 0);
2656 CHECK_NUMBER_COERCE_MARKER (end
, 1);
2658 if (XINT (start
) > XINT (end
))
2661 tem
= start
; start
= end
; end
= tem
;
2664 if (!(BEG
<= XINT (start
) && XINT (start
) <= XINT (end
) && XINT (end
) <= Z
))
2665 args_out_of_range (start
, end
);
2667 if (BEGV
!= XFASTINT (start
) || ZV
!= XFASTINT (end
))
2668 current_buffer
->clip_changed
= 1;
2670 SET_BUF_BEGV (current_buffer
, XFASTINT (start
));
2671 SET_BUF_ZV (current_buffer
, XFASTINT (end
));
2672 if (PT
< XFASTINT (start
))
2673 SET_PT (XFASTINT (start
));
2674 if (PT
> XFASTINT (end
))
2675 SET_PT (XFASTINT (end
));
2676 /* Changing the buffer bounds invalidates any recorded current column. */
2677 invalidate_current_column ();
2682 save_restriction_save ()
2684 register Lisp_Object bottom
, top
;
2685 /* Note: I tried using markers here, but it does not win
2686 because insertion at the end of the saved region
2687 does not advance mh and is considered "outside" the saved region. */
2688 XSETFASTINT (bottom
, BEGV
- BEG
);
2689 XSETFASTINT (top
, Z
- ZV
);
2691 return Fcons (Fcurrent_buffer (), Fcons (bottom
, top
));
2695 save_restriction_restore (data
)
2698 register struct buffer
*buf
;
2699 register int newhead
, newtail
;
2700 register Lisp_Object tem
;
2703 buf
= XBUFFER (XCAR (data
));
2708 newhead
= XINT (tem
);
2710 newtail
= XINT (tem
);
2711 if (newhead
+ newtail
> BUF_Z (buf
) - BUF_BEG (buf
))
2717 obegv
= BUF_BEGV (buf
);
2720 SET_BUF_BEGV (buf
, BUF_BEG (buf
) + newhead
);
2721 SET_BUF_ZV (buf
, BUF_Z (buf
) - newtail
);
2723 if (obegv
!= BUF_BEGV (buf
) || ozv
!= BUF_ZV (buf
))
2724 current_buffer
->clip_changed
= 1;
2726 /* If point is outside the new visible range, move it inside. */
2727 SET_BUF_PT_BOTH (buf
,
2728 clip_to_bounds (BUF_BEGV (buf
), BUF_PT (buf
), BUF_ZV (buf
)),
2729 clip_to_bounds (BUF_BEGV_BYTE (buf
), BUF_PT_BYTE (buf
),
2730 BUF_ZV_BYTE (buf
)));
2735 DEFUN ("save-restriction", Fsave_restriction
, Ssave_restriction
, 0, UNEVALLED
, 0,
2736 "Execute BODY, saving and restoring current buffer's restrictions.\n\
2737 The buffer's restrictions make parts of the beginning and end invisible.\n\
2738 \(They are set up with `narrow-to-region' and eliminated with `widen'.)\n\
2739 This special form, `save-restriction', saves the current buffer's restrictions\n\
2740 when it is entered, and restores them when it is exited.\n\
2741 So any `narrow-to-region' within BODY lasts only until the end of the form.\n\
2742 The old restrictions settings are restored\n\
2743 even in case of abnormal exit (throw or error).\n\
2745 The value returned is the value of the last form in BODY.\n\
2747 `save-restriction' can get confused if, within the BODY, you widen\n\
2748 and then make changes outside the area within the saved restrictions.\n\
2749 See Info node `(elisp)Narrowing' for details and an appropriate technique.\n\
2751 Note: if you are using both `save-excursion' and `save-restriction',\n\
2752 use `save-excursion' outermost:\n\
2753 (save-excursion (save-restriction ...))")
2757 register Lisp_Object val
;
2758 int count
= specpdl_ptr
- specpdl
;
2760 record_unwind_protect (save_restriction_restore
, save_restriction_save ());
2761 val
= Fprogn (body
);
2762 return unbind_to (count
, val
);
2767 /* Buffer for the most recent text displayed by Fmessage. */
2768 static char *message_text
;
2770 /* Allocated length of that buffer. */
2771 static int message_length
;
2773 #endif /* not HAVE_MENUS */
2775 DEFUN ("message", Fmessage
, Smessage
, 1, MANY
, 0,
2776 "Print a one-line message at the bottom of the screen.\n\
2777 The first argument is a format control string, and the rest are data\n\
2778 to be formatted under control of the string. See `format' for details.\n\
2780 If the first argument is nil, clear any existing message; let the\n\
2781 minibuffer contents show.")
2793 register Lisp_Object val
;
2794 val
= Fformat (nargs
, args
);
2795 message3 (val
, STRING_BYTES (XSTRING (val
)), STRING_MULTIBYTE (val
));
2800 DEFUN ("message-box", Fmessage_box
, Smessage_box
, 1, MANY
, 0,
2801 "Display a message, in a dialog box if possible.\n\
2802 If a dialog box is not available, use the echo area.\n\
2803 The first argument is a format control string, and the rest are data\n\
2804 to be formatted under control of the string. See `format' for details.\n\
2806 If the first argument is nil, clear any existing message; let the\n\
2807 minibuffer contents show.")
2819 register Lisp_Object val
;
2820 val
= Fformat (nargs
, args
);
2823 Lisp_Object pane
, menu
, obj
;
2824 struct gcpro gcpro1
;
2825 pane
= Fcons (Fcons (build_string ("OK"), Qt
), Qnil
);
2827 menu
= Fcons (val
, pane
);
2828 obj
= Fx_popup_dialog (Qt
, menu
);
2832 #else /* not HAVE_MENUS */
2833 /* Copy the data so that it won't move when we GC. */
2836 message_text
= (char *)xmalloc (80);
2837 message_length
= 80;
2839 if (STRING_BYTES (XSTRING (val
)) > message_length
)
2841 message_length
= STRING_BYTES (XSTRING (val
));
2842 message_text
= (char *)xrealloc (message_text
, message_length
);
2844 bcopy (XSTRING (val
)->data
, message_text
, STRING_BYTES (XSTRING (val
)));
2845 message2 (message_text
, STRING_BYTES (XSTRING (val
)),
2846 STRING_MULTIBYTE (val
));
2848 #endif /* not HAVE_MENUS */
2852 extern Lisp_Object last_nonmenu_event
;
2855 DEFUN ("message-or-box", Fmessage_or_box
, Smessage_or_box
, 1, MANY
, 0,
2856 "Display a message in a dialog box or in the echo area.\n\
2857 If this command was invoked with the mouse, use a dialog box.\n\
2858 Otherwise, use the echo area.\n\
2859 The first argument is a format control string, and the rest are data\n\
2860 to be formatted under control of the string. See `format' for details.\n\
2862 If the first argument is nil, clear any existing message; let the\n\
2863 minibuffer contents show.")
2869 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
2871 return Fmessage_box (nargs
, args
);
2873 return Fmessage (nargs
, args
);
2876 DEFUN ("current-message", Fcurrent_message
, Scurrent_message
, 0, 0, 0,
2877 "Return the string currently displayed in the echo area, or nil if none.")
2880 return current_message ();
2884 DEFUN ("propertize", Fpropertize
, Spropertize
, 3, MANY
, 0,
2885 "Return a copy of STRING with text properties added.\n\
2886 First argument is the string to copy.\n\
2887 Remaining arguments form a sequence of PROPERTY VALUE pairs for text\n\
2888 properties to add to the result ")
2893 Lisp_Object properties
, string
;
2894 struct gcpro gcpro1
, gcpro2
;
2897 /* Number of args must be odd. */
2898 if ((nargs
& 1) == 0 || nargs
< 3)
2899 error ("Wrong number of arguments");
2901 properties
= string
= Qnil
;
2902 GCPRO2 (properties
, string
);
2904 /* First argument must be a string. */
2905 CHECK_STRING (args
[0], 0);
2906 string
= Fcopy_sequence (args
[0]);
2908 for (i
= 1; i
< nargs
; i
+= 2)
2910 CHECK_SYMBOL (args
[i
], i
);
2911 properties
= Fcons (args
[i
], Fcons (args
[i
+ 1], properties
));
2914 Fadd_text_properties (make_number (0),
2915 make_number (XSTRING (string
)->size
),
2916 properties
, string
);
2917 RETURN_UNGCPRO (string
);
2921 /* Number of bytes that STRING will occupy when put into the result.
2922 MULTIBYTE is nonzero if the result should be multibyte. */
2924 #define CONVERTED_BYTE_SIZE(MULTIBYTE, STRING) \
2925 (((MULTIBYTE) && ! STRING_MULTIBYTE (STRING)) \
2926 ? count_size_as_multibyte (XSTRING (STRING)->data, \
2927 STRING_BYTES (XSTRING (STRING))) \
2928 : STRING_BYTES (XSTRING (STRING)))
2930 DEFUN ("format", Fformat
, Sformat
, 1, MANY
, 0,
2931 "Format a string out of a control-string and arguments.\n\
2932 The first argument is a control string.\n\
2933 The other arguments are substituted into it to make the result, a string.\n\
2934 It may contain %-sequences meaning to substitute the next argument.\n\
2935 %s means print a string argument. Actually, prints any object, with `princ'.\n\
2936 %d means print as number in decimal (%o octal, %x hex).\n\
2937 %e means print a number in exponential notation.\n\
2938 %f means print a number in decimal-point notation.\n\
2939 %g means print a number in exponential notation\n\
2940 or decimal-point notation, whichever uses fewer characters.\n\
2941 %c means print a number as a single character.\n\
2942 %S means print any object as an s-expression (using `prin1').\n\
2943 The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.\n\
2944 Use %% to put a single % into the output.")
2947 register Lisp_Object
*args
;
2949 register int n
; /* The number of the next arg to substitute */
2950 register int total
; /* An estimate of the final length */
2952 register unsigned char *format
, *end
;
2954 /* Nonzero if the output should be a multibyte string,
2955 which is true if any of the inputs is one. */
2957 /* When we make a multibyte string, we must pay attention to the
2958 byte combining problem, i.e., a byte may be combined with a
2959 multibyte charcter of the previous string. This flag tells if we
2960 must consider such a situation or not. */
2961 int maybe_combine_byte
;
2962 unsigned char *this_format
;
2970 extern char *index ();
2972 /* It should not be necessary to GCPRO ARGS, because
2973 the caller in the interpreter should take care of that. */
2975 /* Try to determine whether the result should be multibyte.
2976 This is not always right; sometimes the result needs to be multibyte
2977 because of an object that we will pass through prin1,
2978 and in that case, we won't know it here. */
2979 for (n
= 0; n
< nargs
; n
++)
2980 if (STRINGP (args
[n
]) && STRING_MULTIBYTE (args
[n
]))
2983 CHECK_STRING (args
[0], 0);
2985 /* If we start out planning a unibyte result,
2986 and later find it has to be multibyte, we jump back to retry. */
2989 format
= XSTRING (args
[0])->data
;
2990 end
= format
+ STRING_BYTES (XSTRING (args
[0]));
2993 /* Make room in result for all the non-%-codes in the control string. */
2994 total
= 5 + CONVERTED_BYTE_SIZE (multibyte
, args
[0]);
2996 /* Add to TOTAL enough space to hold the converted arguments. */
2999 while (format
!= end
)
3000 if (*format
++ == '%')
3002 int minlen
, thissize
= 0;
3003 unsigned char *this_format_start
= format
- 1;
3005 /* Process a numeric arg and skip it. */
3006 minlen
= atoi (format
);
3010 while ((*format
>= '0' && *format
<= '9')
3011 || *format
== '-' || *format
== ' ' || *format
== '.')
3014 if (format
- this_format_start
+ 1 > longest_format
)
3015 longest_format
= format
- this_format_start
+ 1;
3018 error ("Format string ends in middle of format specifier");
3021 else if (++n
>= nargs
)
3022 error ("Not enough arguments for format string");
3023 else if (*format
== 'S')
3025 /* For `S', prin1 the argument and then treat like a string. */
3026 register Lisp_Object tem
;
3027 tem
= Fprin1_to_string (args
[n
], Qnil
);
3028 if (STRING_MULTIBYTE (tem
) && ! multibyte
)
3036 else if (SYMBOLP (args
[n
]))
3038 /* Use a temp var to avoid problems when ENABLE_CHECKING
3040 struct Lisp_String
*t
= XSYMBOL (args
[n
])->name
;
3041 XSETSTRING (args
[n
], t
);
3042 if (STRING_MULTIBYTE (args
[n
]) && ! multibyte
)
3049 else if (STRINGP (args
[n
]))
3052 if (*format
!= 's' && *format
!= 'S')
3053 error ("Format specifier doesn't match argument type");
3054 thissize
= CONVERTED_BYTE_SIZE (multibyte
, args
[n
]);
3056 /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */
3057 else if (INTEGERP (args
[n
]) && *format
!= 's')
3059 /* The following loop assumes the Lisp type indicates
3060 the proper way to pass the argument.
3061 So make sure we have a flonum if the argument should
3063 if (*format
== 'e' || *format
== 'f' || *format
== 'g')
3064 args
[n
] = Ffloat (args
[n
]);
3066 if (*format
!= 'd' && *format
!= 'o' && *format
!= 'x'
3067 && *format
!= 'i' && *format
!= 'X' && *format
!= 'c')
3068 error ("Invalid format operation %%%c", *format
);
3072 && (! SINGLE_BYTE_CHAR_P (XINT (args
[n
]))
3073 || XINT (args
[n
]) == 0))
3080 args
[n
] = Fchar_to_string (args
[n
]);
3081 thissize
= STRING_BYTES (XSTRING (args
[n
]));
3084 else if (FLOATP (args
[n
]) && *format
!= 's')
3086 if (! (*format
== 'e' || *format
== 'f' || *format
== 'g'))
3087 args
[n
] = Ftruncate (args
[n
], Qnil
);
3092 /* Anything but a string, convert to a string using princ. */
3093 register Lisp_Object tem
;
3094 tem
= Fprin1_to_string (args
[n
], Qt
);
3095 if (STRING_MULTIBYTE (tem
) & ! multibyte
)
3104 if (thissize
< minlen
)
3107 total
+= thissize
+ 4;
3110 /* Now we can no longer jump to retry.
3111 TOTAL and LONGEST_FORMAT are known for certain. */
3113 this_format
= (unsigned char *) alloca (longest_format
+ 1);
3115 /* Allocate the space for the result.
3116 Note that TOTAL is an overestimate. */
3118 buf
= (char *) alloca (total
+ 1);
3120 buf
= (char *) xmalloc (total
+ 1);
3126 /* Scan the format and store result in BUF. */
3127 format
= XSTRING (args
[0])->data
;
3128 maybe_combine_byte
= 0;
3129 while (format
!= end
)
3135 unsigned char *this_format_start
= format
;
3139 /* Process a numeric arg and skip it. */
3140 minlen
= atoi (format
);
3142 minlen
= - minlen
, negative
= 1;
3144 while ((*format
>= '0' && *format
<= '9')
3145 || *format
== '-' || *format
== ' ' || *format
== '.')
3148 if (*format
++ == '%')
3157 if (STRINGP (args
[n
]))
3159 int padding
, nbytes
;
3160 int width
= strwidth (XSTRING (args
[n
])->data
,
3161 STRING_BYTES (XSTRING (args
[n
])));
3164 /* If spec requires it, pad on right with spaces. */
3165 padding
= minlen
- width
;
3167 while (padding
-- > 0)
3175 && !ASCII_BYTE_P (*((unsigned char *) p
- 1))
3176 && STRING_MULTIBYTE (args
[n
])
3177 && !CHAR_HEAD_P (XSTRING (args
[n
])->data
[0]))
3178 maybe_combine_byte
= 1;
3179 nbytes
= copy_text (XSTRING (args
[n
])->data
, p
,
3180 STRING_BYTES (XSTRING (args
[n
])),
3181 STRING_MULTIBYTE (args
[n
]), multibyte
);
3183 nchars
+= XSTRING (args
[n
])->size
;
3186 while (padding
-- > 0)
3192 /* If this argument has text properties, record where
3193 in the result string it appears. */
3194 if (XSTRING (args
[n
])->intervals
)
3198 int nbytes
= nargs
* sizeof *info
;
3199 info
= (struct info
*) alloca (nbytes
);
3200 bzero (info
, nbytes
);
3203 info
[n
].start
= start
;
3204 info
[n
].end
= nchars
;
3207 else if (INTEGERP (args
[n
]) || FLOATP (args
[n
]))
3211 bcopy (this_format_start
, this_format
,
3212 format
- this_format_start
);
3213 this_format
[format
- this_format_start
] = 0;
3215 if (INTEGERP (args
[n
]))
3216 sprintf (p
, this_format
, XINT (args
[n
]));
3218 sprintf (p
, this_format
, XFLOAT_DATA (args
[n
]));
3222 && !ASCII_BYTE_P (*((unsigned char *) p
- 1))
3223 && !CHAR_HEAD_P (*((unsigned char *) p
)))
3224 maybe_combine_byte
= 1;
3225 this_nchars
= strlen (p
);
3227 p
+= str_to_multibyte (p
, buf
+ total
- p
, this_nchars
);
3230 nchars
+= this_nchars
;
3233 else if (STRING_MULTIBYTE (args
[0]))
3235 /* Copy a whole multibyte character. */
3238 && !ASCII_BYTE_P (*((unsigned char *) p
- 1))
3239 && !CHAR_HEAD_P (*format
))
3240 maybe_combine_byte
= 1;
3242 while (! CHAR_HEAD_P (*format
)) *p
++ = *format
++;
3247 /* Convert a single-byte character to multibyte. */
3248 int len
= copy_text (format
, p
, 1, 0, 1);
3255 *p
++ = *format
++, nchars
++;
3258 if (maybe_combine_byte
)
3259 nchars
= multibyte_chars_in_text (buf
, p
- buf
);
3260 val
= make_specified_string (buf
, nchars
, p
- buf
, multibyte
);
3262 /* If we allocated BUF with malloc, free it too. */
3266 /* If the format string has text properties, or any of the string
3267 arguments has text properties, set up text properties of the
3270 if (XSTRING (args
[0])->intervals
|| info
)
3272 Lisp_Object len
, new_len
, props
;
3273 struct gcpro gcpro1
;
3275 /* Add text properties from the format string. */
3276 len
= make_number (XSTRING (args
[0])->size
);
3277 props
= text_property_list (args
[0], make_number (0), len
, Qnil
);
3282 new_len
= make_number (XSTRING (val
)->size
);
3283 extend_property_ranges (props
, len
, new_len
);
3284 add_text_properties_from_list (val
, props
, make_number (0));
3287 /* Add text properties from arguments. */
3289 for (n
= 1; n
< nargs
; ++n
)
3292 len
= make_number (XSTRING (args
[n
])->size
);
3293 new_len
= make_number (info
[n
].end
- info
[n
].start
);
3294 props
= text_property_list (args
[n
], make_number (0), len
, Qnil
);
3295 extend_property_ranges (props
, len
, new_len
);
3296 /* If successive arguments have properites, be sure that
3297 the value of `composition' property be the copy. */
3298 if (n
> 1 && info
[n
- 1].end
)
3299 make_composition_value_copy (props
);
3300 add_text_properties_from_list (val
, props
,
3301 make_number (info
[n
].start
));
3314 format1 (string1
, arg0
, arg1
, arg2
, arg3
, arg4
)
3315 EMACS_INT arg0
, arg1
, arg2
, arg3
, arg4
;
3329 doprnt (buf
, sizeof buf
, string1
, (char *)0, 5, (char **) args
);
3331 doprnt (buf
, sizeof buf
, string1
, (char *)0, 5, &string1
+ 1);
3333 return build_string (buf
);
3336 DEFUN ("char-equal", Fchar_equal
, Schar_equal
, 2, 2, 0,
3337 "Return t if two characters match, optionally ignoring case.\n\
3338 Both arguments must be characters (i.e. integers).\n\
3339 Case is ignored if `case-fold-search' is non-nil in the current buffer.")
3341 register Lisp_Object c1
, c2
;
3344 CHECK_NUMBER (c1
, 0);
3345 CHECK_NUMBER (c2
, 1);
3347 if (XINT (c1
) == XINT (c2
))
3349 if (NILP (current_buffer
->case_fold_search
))
3352 /* Do these in separate statements,
3353 then compare the variables.
3354 because of the way DOWNCASE uses temp variables. */
3355 i1
= DOWNCASE (XFASTINT (c1
));
3356 i2
= DOWNCASE (XFASTINT (c2
));
3357 return (i1
== i2
? Qt
: Qnil
);
3360 /* Transpose the markers in two regions of the current buffer, and
3361 adjust the ones between them if necessary (i.e.: if the regions
3364 START1, END1 are the character positions of the first region.
3365 START1_BYTE, END1_BYTE are the byte positions.
3366 START2, END2 are the character positions of the second region.
3367 START2_BYTE, END2_BYTE are the byte positions.
3369 Traverses the entire marker list of the buffer to do so, adding an
3370 appropriate amount to some, subtracting from some, and leaving the
3371 rest untouched. Most of this is copied from adjust_markers in insdel.c.
3373 It's the caller's job to ensure that START1 <= END1 <= START2 <= END2. */
3376 transpose_markers (start1
, end1
, start2
, end2
,
3377 start1_byte
, end1_byte
, start2_byte
, end2_byte
)
3378 register int start1
, end1
, start2
, end2
;
3379 register int start1_byte
, end1_byte
, start2_byte
, end2_byte
;
3381 register int amt1
, amt1_byte
, amt2
, amt2_byte
, diff
, diff_byte
, mpos
;
3382 register Lisp_Object marker
;
3384 /* Update point as if it were a marker. */
3388 TEMP_SET_PT_BOTH (PT
+ (end2
- end1
),
3389 PT_BYTE
+ (end2_byte
- end1_byte
));
3390 else if (PT
< start2
)
3391 TEMP_SET_PT_BOTH (PT
+ (end2
- start2
) - (end1
- start1
),
3392 (PT_BYTE
+ (end2_byte
- start2_byte
)
3393 - (end1_byte
- start1_byte
)));
3395 TEMP_SET_PT_BOTH (PT
- (start2
- start1
),
3396 PT_BYTE
- (start2_byte
- start1_byte
));
3398 /* We used to adjust the endpoints here to account for the gap, but that
3399 isn't good enough. Even if we assume the caller has tried to move the
3400 gap out of our way, it might still be at start1 exactly, for example;
3401 and that places it `inside' the interval, for our purposes. The amount
3402 of adjustment is nontrivial if there's a `denormalized' marker whose
3403 position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
3404 the dirty work to Fmarker_position, below. */
3406 /* The difference between the region's lengths */
3407 diff
= (end2
- start2
) - (end1
- start1
);
3408 diff_byte
= (end2_byte
- start2_byte
) - (end1_byte
- start1_byte
);
3410 /* For shifting each marker in a region by the length of the other
3411 region plus the distance between the regions. */
3412 amt1
= (end2
- start2
) + (start2
- end1
);
3413 amt2
= (end1
- start1
) + (start2
- end1
);
3414 amt1_byte
= (end2_byte
- start2_byte
) + (start2_byte
- end1_byte
);
3415 amt2_byte
= (end1_byte
- start1_byte
) + (start2_byte
- end1_byte
);
3417 for (marker
= BUF_MARKERS (current_buffer
); !NILP (marker
);
3418 marker
= XMARKER (marker
)->chain
)
3420 mpos
= marker_byte_position (marker
);
3421 if (mpos
>= start1_byte
&& mpos
< end2_byte
)
3423 if (mpos
< end1_byte
)
3425 else if (mpos
< start2_byte
)
3429 XMARKER (marker
)->bytepos
= mpos
;
3431 mpos
= XMARKER (marker
)->charpos
;
3432 if (mpos
>= start1
&& mpos
< end2
)
3436 else if (mpos
< start2
)
3441 XMARKER (marker
)->charpos
= mpos
;
3445 DEFUN ("transpose-regions", Ftranspose_regions
, Stranspose_regions
, 4, 5, 0,
3446 "Transpose region START1 to END1 with START2 to END2.\n\
3447 The regions may not be overlapping, because the size of the buffer is\n\
3448 never changed in a transposition.\n\
3450 Optional fifth arg LEAVE_MARKERS, if non-nil, means don't update\n\
3451 any markers that happen to be located in the regions.\n\
3453 Transposing beyond buffer boundaries is an error.")
3454 (startr1
, endr1
, startr2
, endr2
, leave_markers
)
3455 Lisp_Object startr1
, endr1
, startr2
, endr2
, leave_markers
;
3457 register int start1
, end1
, start2
, end2
;
3458 int start1_byte
, start2_byte
, len1_byte
, len2_byte
;
3459 int gap
, len1
, len_mid
, len2
;
3460 unsigned char *start1_addr
, *start2_addr
, *temp
;
3461 struct gcpro gcpro1
, gcpro2
;
3463 INTERVAL cur_intv
, tmp_interval1
, tmp_interval_mid
, tmp_interval2
;
3464 cur_intv
= BUF_INTERVALS (current_buffer
);
3466 validate_region (&startr1
, &endr1
);
3467 validate_region (&startr2
, &endr2
);
3469 start1
= XFASTINT (startr1
);
3470 end1
= XFASTINT (endr1
);
3471 start2
= XFASTINT (startr2
);
3472 end2
= XFASTINT (endr2
);
3475 /* Swap the regions if they're reversed. */
3478 register int glumph
= start1
;
3486 len1
= end1
- start1
;
3487 len2
= end2
- start2
;
3490 error ("Transposed regions overlap");
3491 else if (start1
== end1
|| start2
== end2
)
3492 error ("Transposed region has length 0");
3494 /* The possibilities are:
3495 1. Adjacent (contiguous) regions, or separate but equal regions
3496 (no, really equal, in this case!), or
3497 2. Separate regions of unequal size.
3499 The worst case is usually No. 2. It means that (aside from
3500 potential need for getting the gap out of the way), there also
3501 needs to be a shifting of the text between the two regions. So
3502 if they are spread far apart, we are that much slower... sigh. */
3504 /* It must be pointed out that the really studly thing to do would
3505 be not to move the gap at all, but to leave it in place and work
3506 around it if necessary. This would be extremely efficient,
3507 especially considering that people are likely to do
3508 transpositions near where they are working interactively, which
3509 is exactly where the gap would be found. However, such code
3510 would be much harder to write and to read. So, if you are
3511 reading this comment and are feeling squirrely, by all means have
3512 a go! I just didn't feel like doing it, so I will simply move
3513 the gap the minimum distance to get it out of the way, and then
3514 deal with an unbroken array. */
3516 /* Make sure the gap won't interfere, by moving it out of the text
3517 we will operate on. */
3518 if (start1
< gap
&& gap
< end2
)
3520 if (gap
- start1
< end2
- gap
)
3526 start1_byte
= CHAR_TO_BYTE (start1
);
3527 start2_byte
= CHAR_TO_BYTE (start2
);
3528 len1_byte
= CHAR_TO_BYTE (end1
) - start1_byte
;
3529 len2_byte
= CHAR_TO_BYTE (end2
) - start2_byte
;
3531 #ifdef BYTE_COMBINING_DEBUG
3534 if (count_combining_before (BYTE_POS_ADDR (start2_byte
),
3535 len2_byte
, start1
, start1_byte
)
3536 || count_combining_before (BYTE_POS_ADDR (start1_byte
),
3537 len1_byte
, end2
, start2_byte
+ len2_byte
)
3538 || count_combining_after (BYTE_POS_ADDR (start1_byte
),
3539 len1_byte
, end2
, start2_byte
+ len2_byte
))
3544 if (count_combining_before (BYTE_POS_ADDR (start2_byte
),
3545 len2_byte
, start1
, start1_byte
)
3546 || count_combining_before (BYTE_POS_ADDR (start1_byte
),
3547 len1_byte
, start2
, start2_byte
)
3548 || count_combining_after (BYTE_POS_ADDR (start2_byte
),
3549 len2_byte
, end1
, start1_byte
+ len1_byte
)
3550 || count_combining_after (BYTE_POS_ADDR (start1_byte
),
3551 len1_byte
, end2
, start2_byte
+ len2_byte
))
3556 /* Hmmm... how about checking to see if the gap is large
3557 enough to use as the temporary storage? That would avoid an
3558 allocation... interesting. Later, don't fool with it now. */
3560 /* Working without memmove, for portability (sigh), so must be
3561 careful of overlapping subsections of the array... */
3563 if (end1
== start2
) /* adjacent regions */
3565 modify_region (current_buffer
, start1
, end2
);
3566 record_change (start1
, len1
+ len2
);
3568 tmp_interval1
= copy_intervals (cur_intv
, start1
, len1
);
3569 tmp_interval2
= copy_intervals (cur_intv
, start2
, len2
);
3570 Fset_text_properties (make_number (start1
), make_number (end2
),
3573 /* First region smaller than second. */
3574 if (len1_byte
< len2_byte
)
3576 /* We use alloca only if it is small,
3577 because we want to avoid stack overflow. */
3578 if (len2_byte
> 20000)
3579 temp
= (unsigned char *) xmalloc (len2_byte
);
3581 temp
= (unsigned char *) alloca (len2_byte
);
3583 /* Don't precompute these addresses. We have to compute them
3584 at the last minute, because the relocating allocator might
3585 have moved the buffer around during the xmalloc. */
3586 start1_addr
= BYTE_POS_ADDR (start1_byte
);
3587 start2_addr
= BYTE_POS_ADDR (start2_byte
);
3589 bcopy (start2_addr
, temp
, len2_byte
);
3590 bcopy (start1_addr
, start1_addr
+ len2_byte
, len1_byte
);
3591 bcopy (temp
, start1_addr
, len2_byte
);
3592 if (len2_byte
> 20000)
3596 /* First region not smaller than second. */
3598 if (len1_byte
> 20000)
3599 temp
= (unsigned char *) xmalloc (len1_byte
);
3601 temp
= (unsigned char *) alloca (len1_byte
);
3602 start1_addr
= BYTE_POS_ADDR (start1_byte
);
3603 start2_addr
= BYTE_POS_ADDR (start2_byte
);
3604 bcopy (start1_addr
, temp
, len1_byte
);
3605 bcopy (start2_addr
, start1_addr
, len2_byte
);
3606 bcopy (temp
, start1_addr
+ len2_byte
, len1_byte
);
3607 if (len1_byte
> 20000)
3610 graft_intervals_into_buffer (tmp_interval1
, start1
+ len2
,
3611 len1
, current_buffer
, 0);
3612 graft_intervals_into_buffer (tmp_interval2
, start1
,
3613 len2
, current_buffer
, 0);
3614 update_compositions (start1
, start1
+ len2
, CHECK_BORDER
);
3615 update_compositions (start1
+ len2
, end2
, CHECK_TAIL
);
3617 /* Non-adjacent regions, because end1 != start2, bleagh... */
3620 len_mid
= start2_byte
- (start1_byte
+ len1_byte
);
3622 if (len1_byte
== len2_byte
)
3623 /* Regions are same size, though, how nice. */
3625 modify_region (current_buffer
, start1
, end1
);
3626 modify_region (current_buffer
, start2
, end2
);
3627 record_change (start1
, len1
);
3628 record_change (start2
, len2
);
3629 tmp_interval1
= copy_intervals (cur_intv
, start1
, len1
);
3630 tmp_interval2
= copy_intervals (cur_intv
, start2
, len2
);
3631 Fset_text_properties (make_number (start1
), make_number (end1
),
3633 Fset_text_properties (make_number (start2
), make_number (end2
),
3636 if (len1_byte
> 20000)
3637 temp
= (unsigned char *) xmalloc (len1_byte
);
3639 temp
= (unsigned char *) alloca (len1_byte
);
3640 start1_addr
= BYTE_POS_ADDR (start1_byte
);
3641 start2_addr
= BYTE_POS_ADDR (start2_byte
);
3642 bcopy (start1_addr
, temp
, len1_byte
);
3643 bcopy (start2_addr
, start1_addr
, len2_byte
);
3644 bcopy (temp
, start2_addr
, len1_byte
);
3645 if (len1_byte
> 20000)
3647 graft_intervals_into_buffer (tmp_interval1
, start2
,
3648 len1
, current_buffer
, 0);
3649 graft_intervals_into_buffer (tmp_interval2
, start1
,
3650 len2
, current_buffer
, 0);
3653 else if (len1_byte
< len2_byte
) /* Second region larger than first */
3654 /* Non-adjacent & unequal size, area between must also be shifted. */
3656 modify_region (current_buffer
, start1
, end2
);
3657 record_change (start1
, (end2
- start1
));
3658 tmp_interval1
= copy_intervals (cur_intv
, start1
, len1
);
3659 tmp_interval_mid
= copy_intervals (cur_intv
, end1
, len_mid
);
3660 tmp_interval2
= copy_intervals (cur_intv
, start2
, len2
);
3661 Fset_text_properties (make_number (start1
), make_number (end2
),
3664 /* holds region 2 */
3665 if (len2_byte
> 20000)
3666 temp
= (unsigned char *) xmalloc (len2_byte
);
3668 temp
= (unsigned char *) alloca (len2_byte
);
3669 start1_addr
= BYTE_POS_ADDR (start1_byte
);
3670 start2_addr
= BYTE_POS_ADDR (start2_byte
);
3671 bcopy (start2_addr
, temp
, len2_byte
);
3672 bcopy (start1_addr
, start1_addr
+ len_mid
+ len2_byte
, len1_byte
);
3673 safe_bcopy (start1_addr
+ len1_byte
, start1_addr
+ len2_byte
, len_mid
);
3674 bcopy (temp
, start1_addr
, len2_byte
);
3675 if (len2_byte
> 20000)
3677 graft_intervals_into_buffer (tmp_interval1
, end2
- len1
,
3678 len1
, current_buffer
, 0);
3679 graft_intervals_into_buffer (tmp_interval_mid
, start1
+ len2
,
3680 len_mid
, current_buffer
, 0);
3681 graft_intervals_into_buffer (tmp_interval2
, start1
,
3682 len2
, current_buffer
, 0);
3685 /* Second region smaller than first. */
3687 record_change (start1
, (end2
- start1
));
3688 modify_region (current_buffer
, start1
, end2
);
3690 tmp_interval1
= copy_intervals (cur_intv
, start1
, len1
);
3691 tmp_interval_mid
= copy_intervals (cur_intv
, end1
, len_mid
);
3692 tmp_interval2
= copy_intervals (cur_intv
, start2
, len2
);
3693 Fset_text_properties (make_number (start1
), make_number (end2
),
3696 /* holds region 1 */
3697 if (len1_byte
> 20000)
3698 temp
= (unsigned char *) xmalloc (len1_byte
);
3700 temp
= (unsigned char *) alloca (len1_byte
);
3701 start1_addr
= BYTE_POS_ADDR (start1_byte
);
3702 start2_addr
= BYTE_POS_ADDR (start2_byte
);
3703 bcopy (start1_addr
, temp
, len1_byte
);
3704 bcopy (start2_addr
, start1_addr
, len2_byte
);
3705 bcopy (start1_addr
+ len1_byte
, start1_addr
+ len2_byte
, len_mid
);
3706 bcopy (temp
, start1_addr
+ len2_byte
+ len_mid
, len1_byte
);
3707 if (len1_byte
> 20000)
3709 graft_intervals_into_buffer (tmp_interval1
, end2
- len1
,
3710 len1
, current_buffer
, 0);
3711 graft_intervals_into_buffer (tmp_interval_mid
, start1
+ len2
,
3712 len_mid
, current_buffer
, 0);
3713 graft_intervals_into_buffer (tmp_interval2
, start1
,
3714 len2
, current_buffer
, 0);
3717 update_compositions (start1
, start1
+ len2
, CHECK_BORDER
);
3718 update_compositions (end2
- len1
, end2
, CHECK_BORDER
);
3721 /* When doing multiple transpositions, it might be nice
3722 to optimize this. Perhaps the markers in any one buffer
3723 should be organized in some sorted data tree. */
3724 if (NILP (leave_markers
))
3726 transpose_markers (start1
, end1
, start2
, end2
,
3727 start1_byte
, start1_byte
+ len1_byte
,
3728 start2_byte
, start2_byte
+ len2_byte
);
3729 fix_overlays_in_range (start1
, end2
);
3741 Qbuffer_access_fontify_functions
3742 = intern ("buffer-access-fontify-functions");
3743 staticpro (&Qbuffer_access_fontify_functions
);
3745 DEFVAR_LISP ("inhibit-field-text-motion", &Vinhibit_field_text_motion
,
3746 "Non-nil means.text motion commands don't notice fields.");
3747 Vinhibit_field_text_motion
= Qnil
;
3749 DEFVAR_LISP ("buffer-access-fontify-functions",
3750 &Vbuffer_access_fontify_functions
,
3751 "List of functions called by `buffer-substring' to fontify if necessary.\n\
3752 Each function is called with two arguments which specify the range\n\
3753 of the buffer being accessed.");
3754 Vbuffer_access_fontify_functions
= Qnil
;
3758 extern Lisp_Object Vprin1_to_string_buffer
;
3759 obuf
= Fcurrent_buffer ();
3760 /* Do this here, because init_buffer_once is too early--it won't work. */
3761 Fset_buffer (Vprin1_to_string_buffer
);
3762 /* Make sure buffer-access-fontify-functions is nil in this buffer. */
3763 Fset (Fmake_local_variable (intern ("buffer-access-fontify-functions")),
3768 DEFVAR_LISP ("buffer-access-fontified-property",
3769 &Vbuffer_access_fontified_property
,
3770 "Property which (if non-nil) indicates text has been fontified.\n\
3771 `buffer-substring' need not call the `buffer-access-fontify-functions'\n\
3772 functions if all the text being accessed has this property.");
3773 Vbuffer_access_fontified_property
= Qnil
;
3775 DEFVAR_LISP ("system-name", &Vsystem_name
,
3776 "The name of the machine Emacs is running on.");
3778 DEFVAR_LISP ("user-full-name", &Vuser_full_name
,
3779 "The full name of the user logged in.");
3781 DEFVAR_LISP ("user-login-name", &Vuser_login_name
,
3782 "The user's name, taken from environment variables if possible.");
3784 DEFVAR_LISP ("user-real-login-name", &Vuser_real_login_name
,
3785 "The user's name, based upon the real uid only.");
3787 defsubr (&Spropertize
);
3788 defsubr (&Schar_equal
);
3789 defsubr (&Sgoto_char
);
3790 defsubr (&Sstring_to_char
);
3791 defsubr (&Schar_to_string
);
3792 defsubr (&Sbuffer_substring
);
3793 defsubr (&Sbuffer_substring_no_properties
);
3794 defsubr (&Sbuffer_string
);
3796 defsubr (&Spoint_marker
);
3797 defsubr (&Smark_marker
);
3799 defsubr (&Sregion_beginning
);
3800 defsubr (&Sregion_end
);
3802 staticpro (&Qfield
);
3803 Qfield
= intern ("field");
3804 staticpro (&Qboundary
);
3805 Qboundary
= intern ("boundary");
3806 defsubr (&Sfield_beginning
);
3807 defsubr (&Sfield_end
);
3808 defsubr (&Sfield_string
);
3809 defsubr (&Sfield_string_no_properties
);
3810 defsubr (&Sdelete_field
);
3811 defsubr (&Sconstrain_to_field
);
3813 defsubr (&Sline_beginning_position
);
3814 defsubr (&Sline_end_position
);
3816 /* defsubr (&Smark); */
3817 /* defsubr (&Sset_mark); */
3818 defsubr (&Ssave_excursion
);
3819 defsubr (&Ssave_current_buffer
);
3821 defsubr (&Sbufsize
);
3822 defsubr (&Spoint_max
);
3823 defsubr (&Spoint_min
);
3824 defsubr (&Spoint_min_marker
);
3825 defsubr (&Spoint_max_marker
);
3826 defsubr (&Sgap_position
);
3827 defsubr (&Sgap_size
);
3828 defsubr (&Sposition_bytes
);
3829 defsubr (&Sbyte_to_position
);
3835 defsubr (&Sfollowing_char
);
3836 defsubr (&Sprevious_char
);
3837 defsubr (&Schar_after
);
3838 defsubr (&Schar_before
);
3840 defsubr (&Sinsert_before_markers
);
3841 defsubr (&Sinsert_and_inherit
);
3842 defsubr (&Sinsert_and_inherit_before_markers
);
3843 defsubr (&Sinsert_char
);
3845 defsubr (&Suser_login_name
);
3846 defsubr (&Suser_real_login_name
);
3847 defsubr (&Suser_uid
);
3848 defsubr (&Suser_real_uid
);
3849 defsubr (&Suser_full_name
);
3850 defsubr (&Semacs_pid
);
3851 defsubr (&Scurrent_time
);
3852 defsubr (&Sformat_time_string
);
3853 defsubr (&Sfloat_time
);
3854 defsubr (&Sdecode_time
);
3855 defsubr (&Sencode_time
);
3856 defsubr (&Scurrent_time_string
);
3857 defsubr (&Scurrent_time_zone
);
3858 defsubr (&Sset_time_zone_rule
);
3859 defsubr (&Ssystem_name
);
3860 defsubr (&Smessage
);
3861 defsubr (&Smessage_box
);
3862 defsubr (&Smessage_or_box
);
3863 defsubr (&Scurrent_message
);
3866 defsubr (&Sinsert_buffer_substring
);
3867 defsubr (&Scompare_buffer_substrings
);
3868 defsubr (&Ssubst_char_in_region
);
3869 defsubr (&Stranslate_region
);
3870 defsubr (&Sdelete_region
);
3871 defsubr (&Sdelete_and_extract_region
);
3873 defsubr (&Snarrow_to_region
);
3874 defsubr (&Ssave_restriction
);
3875 defsubr (&Stranspose_regions
);