(cvs-menu): Don't move point. Use popup-menu.
[emacs.git] / src / editfns.c
blobd3fa9c54f4763bf0f1f3886d8423c7c0bfc60dd7
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)
9 any later version.
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. */
22 #include <config.h>
23 #include <sys/types.h>
25 #ifdef VMS
26 #include "vms-pwd.h"
27 #else
28 #include <pwd.h>
29 #endif
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
35 #include "lisp.h"
36 #include "intervals.h"
37 #include "buffer.h"
38 #include "charset.h"
39 #include "coding.h"
40 #include "window.h"
42 #include "systime.h"
44 #define min(a, b) ((a) < (b) ? (a) : (b))
45 #define max(a, b) ((a) > (b) ? (a) : (b))
47 #ifndef NULL
48 #define NULL 0
49 #endif
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 */
77 void
78 init_editfns ()
80 char *user_name;
81 register unsigned char *p;
82 struct passwd *pw; /* password entry for the current user */
83 Lisp_Object tem;
85 /* Set up system_name even when dumping. */
86 init_system_name ();
88 #ifndef CANNOT_DUMP
89 /* Don't bother with this on initial start when just dumping out */
90 if (!initialized)
91 return;
92 #endif /* not CANNOT_DUMP */
94 pw = (struct passwd *) getpwuid (getuid ());
95 #ifdef MSDOS
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");
100 #else
101 Vuser_real_login_name = build_string (pw ? pw->pw_name : "unknown");
102 #endif
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");
107 if (!user_name)
108 #ifdef WINDOWSNT
109 user_name = (char *) getenv ("USERNAME"); /* it's USERNAME on NT */
110 #else /* WINDOWSNT */
111 user_name = (char *) getenv ("USER");
112 #endif /* WINDOWSNT */
113 if (!user_name)
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())
124 : Vuser_login_name);
126 p = (unsigned char *) getenv ("NAME");
127 if (p)
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.")
135 (character)
136 Lisp_Object character;
138 int len;
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.")
150 (string)
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);
157 if (p->size)
159 if (STRING_MULTIBYTE (string))
160 XSETFASTINT (val, STRING_CHAR (p->data, STRING_BYTES (p)));
161 else
162 XSETFASTINT (val, p->data[0]);
164 else
165 XSETFASTINT (val, 0);
166 return val;
169 static Lisp_Object
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);
176 return mark;
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)")
184 Lisp_Object temp;
185 XSETFASTINT (temp, PT);
186 return temp;
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;
200 if (num < lower)
201 return lower;
202 else if (num > upper)
203 return upper;
204 else
205 return num;
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.")
214 (position)
215 register Lisp_Object position;
217 int pos;
219 if (MARKERP (position)
220 && current_buffer == XMARKER (position)->buffer)
222 pos = marker_position (position);
223 if (pos < BEGV)
224 SET_PT_BOTH (BEGV, BEGV_BYTE);
225 else if (pos > ZV)
226 SET_PT_BOTH (ZV, ZV_BYTE);
227 else
228 SET_PT_BOTH (pos, marker_byte_position (position));
230 return position;
233 CHECK_NUMBER_COERCE_MARKER (position, 0);
235 pos = clip_to_bounds (BEGV, XINT (position), ZV);
236 SET_PT (pos);
237 return position;
240 static Lisp_Object
241 region_limit (beginningp)
242 int 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));
253 else
254 return (m);
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. */
283 static int
284 char_property_eq (prop, pos1, pos2)
285 Lisp_Object prop;
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. */
301 static int
302 char_property_stickiness (prop, pos)
303 Lisp_Object prop;
304 Lisp_Object 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. */
321 return -1;
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. */
331 return 1;
333 /* PROP is not inherited from either side. */
334 return 0;
337 /* Symbol for the text property used to mark fields. */
338 Lisp_Object Qfield;
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
357 is not stored. */
359 void
360 find_field (pos, merge_at_boundary, beg, end)
361 Lisp_Object pos;
362 Lisp_Object merge_at_boundary;
363 int *beg, *end;
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;
372 if (NILP (pos))
373 XSETFASTINT (pos, PT);
374 else
375 CHECK_NUMBER_COERCE_MARKER (pos, 0);
377 after_field =
378 Fget_char_property (pos, Qfield, Qnil);
379 before_field =
380 (XFASTINT (pos) > BEGV
381 ? Fget_char_property (make_number (XINT (pos) - 1), Qfield, Qnil)
382 : 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
389 specially. */
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);
396 if (stickiness > 0)
397 at_field_start = 1;
398 else if (stickiness < 0)
399 at_field_end = 1;
400 else
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':
417 xxxx.yyyy
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:
428 xxx.BBBByyyy
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. */
435 if (beg)
436 if (at_field_start)
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);
440 else
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);
451 if (end)
452 if (at_field_end)
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);
456 else
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.")
472 (pos)
473 Lisp_Object pos;
475 int beg, end;
476 find_field (pos, Qnil, &beg, &end);
477 if (beg != end)
478 del_range (beg, end);
479 return Qnil;
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.")
486 (pos)
487 Lisp_Object pos;
489 int beg, end;
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.")
498 (pos)
499 Lisp_Object pos;
501 int beg, end;
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;
515 int beg;
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;
529 int end;
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. */
566 int orig_point = 0;
568 if (NILP (new_pos))
569 /* Use the current point, and afterwards, set it. */
571 orig_point = PT;
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. */
583 int fwd, shortage;
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));
591 if (fwd)
592 field_bound = Ffield_end (old_pos, escape_from_edge);
593 else
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
599 to FIELD_BOUND. */
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),
612 shortage != 0)))
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));
621 return new_pos;
624 DEFUN ("line-beginning-position", Fline_beginning_position, Sline_beginning_position,
625 0, 1, 0,
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.")
636 Lisp_Object n;
638 register int orig, orig_byte, end;
640 if (NILP (n))
641 XSETFASTINT (n, 1);
642 else
643 CHECK_NUMBER (n, 0);
645 orig = PT;
646 orig_byte = PT_BYTE;
647 Fforward_line (make_number (XINT (n) - 1));
648 end = PT;
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,
655 Qt, Qnil);
658 DEFUN ("line-end-position", Fline_end_position, Sline_end_position,
659 0, 1, 0,
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.")
665 Lisp_Object n;
667 int end_pos;
668 register int orig = PT;
670 if (NILP (n))
671 XSETFASTINT (n, 1);
672 else
673 CHECK_NUMBER (n, 0);
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),
679 Qnil, Qt, Qnil);
682 Lisp_Object
683 save_excursion_save ()
685 register int visible = (XBUFFER (XWINDOW (selected_window)->buffer)
686 == current_buffer);
688 return Fcons (Fpoint_marker (),
689 Fcons (Fcopy_marker (current_buffer->mark, Qnil),
690 Fcons (visible ? Qt : Qnil,
691 current_buffer->mark_active)));
694 Lisp_Object
695 save_excursion_restore (info)
696 Lisp_Object 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
704 and crash */
705 /* In that case, Fmarker_buffer returns nil now. */
706 if (NILP (tem))
707 return Qnil;
709 omark = nmark = Qnil;
710 GCPRO3 (info, omark, nmark);
712 Fset_buffer (tem);
713 tem = Fcar (info);
714 Fgoto_char (tem);
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. */
726 tem1 = Fcar (tem);
727 if (!NILP (tem1)
728 && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
729 Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
730 #endif /* 0 */
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"));
747 UNGCPRO;
748 return Qnil;
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'.")
762 (args)
763 Lisp_Object args;
765 register Lisp_Object val;
766 int count = specpdl_ptr - specpdl;
768 record_unwind_protect (save_excursion_restore, save_excursion_save ());
770 val = Fprogn (args);
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'.")
777 (args)
778 Lisp_Object args;
780 register Lisp_Object val;
781 int count = specpdl_ptr - specpdl;
783 record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
785 val = Fprogn (args);
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.")
792 (buffer)
793 Lisp_Object buffer;
795 if (NILP (buffer))
796 return make_number (Z - BEG);
797 else
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.")
810 Lisp_Object temp;
811 XSETFASTINT (temp, BEGV);
812 return temp;
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.")
829 Lisp_Object temp;
830 XSETFASTINT (temp, ZV);
831 return temp;
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'.")
848 Lisp_Object temp;
849 XSETFASTINT (temp, GPT);
850 return temp;
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'.")
858 Lisp_Object temp;
859 XSETFASTINT (temp, GAP_SIZE);
860 return temp;
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.")
866 (position)
867 Lisp_Object position;
869 CHECK_NUMBER_COERCE_MARKER (position, 1);
870 if (XINT (position) < BEG || XINT (position) > Z)
871 return Qnil;
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.")
878 (bytepos)
879 Lisp_Object bytepos;
881 CHECK_NUMBER (bytepos, 1);
882 if (XINT (bytepos) < BEG_BYTE || XINT (bytepos) > Z_BYTE)
883 return Qnil;
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.")
892 Lisp_Object temp;
893 if (PT >= ZV)
894 XSETFASTINT (temp, 0);
895 else
896 XSETFASTINT (temp, FETCH_CHAR (PT_BYTE));
897 return temp;
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.")
905 Lisp_Object temp;
906 if (PT <= BEGV)
907 XSETFASTINT (temp, 0);
908 else if (!NILP (current_buffer->enable_multibyte_characters))
910 int pos = PT_BYTE;
911 DEC_POS (pos);
912 XSETFASTINT (temp, FETCH_CHAR (pos));
914 else
915 XSETFASTINT (temp, FETCH_BYTE (PT_BYTE - 1));
916 return temp;
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.")
924 if (PT == BEGV)
925 return Qt;
926 return Qnil;
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.")
934 if (PT == ZV)
935 return Qt;
936 return Qnil;
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')
944 return Qt;
945 return Qnil;
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')
954 return Qt;
955 return Qnil;
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.")
962 (pos)
963 Lisp_Object pos;
965 register int pos_byte;
967 if (NILP (pos))
969 pos_byte = PT_BYTE;
970 XSETFASTINT (pos, PT);
973 if (MARKERP (pos))
975 pos_byte = marker_byte_position (pos);
976 if (pos_byte < BEGV_BYTE || pos_byte >= ZV_BYTE)
977 return Qnil;
979 else
981 CHECK_NUMBER_COERCE_MARKER (pos, 0);
982 if (XINT (pos) < BEGV || XINT (pos) >= ZV)
983 return Qnil;
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.")
995 (pos)
996 Lisp_Object pos;
998 register Lisp_Object val;
999 register int pos_byte;
1001 if (NILP (pos))
1003 pos_byte = PT_BYTE;
1004 XSETFASTINT (pos, PT);
1007 if (MARKERP (pos))
1009 pos_byte = marker_byte_position (pos);
1011 if (pos_byte <= BEGV_BYTE || pos_byte > ZV_BYTE)
1012 return Qnil;
1014 else
1016 CHECK_NUMBER_COERCE_MARKER (pos, 0);
1018 if (XINT (pos) <= BEGV || XINT (pos) > ZV)
1019 return Qnil;
1021 pos_byte = CHAR_TO_BYTE (XINT (pos));
1024 if (!NILP (current_buffer->enable_multibyte_characters))
1026 DEC_POS (pos_byte);
1027 XSETFASTINT (val, FETCH_CHAR (pos_byte));
1029 else
1031 pos_byte--;
1032 XSETFASTINT (val, FETCH_BYTE (pos_byte));
1034 return val;
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.")
1044 (uid)
1045 Lisp_Object uid;
1047 struct passwd *pw;
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))
1053 init_editfns ();
1055 if (NILP (uid))
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,
1064 0, 0, 0,
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))
1074 init_editfns ();
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.")
1101 (uid)
1102 Lisp_Object uid;
1104 struct passwd *pw;
1105 register unsigned char *p, *q;
1106 extern char *index ();
1107 Lisp_Object full;
1109 if (NILP (uid))
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);
1115 else
1116 error ("Invalid UID specification");
1118 if (!pw)
1119 return Qnil;
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. */
1130 if (q)
1132 register unsigned char *r;
1133 Lisp_Object login;
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);
1138 r[q - p] = 0;
1139 strcat (r, XSTRING (login)->data);
1140 r[q - p] = UPCASE (r[q - p]);
1141 strcat (r, q + 1);
1142 full = build_string (r);
1144 #endif /* AMPERSAND_FULL_NAME */
1146 return full;
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 */
1157 char *
1158 get_system_name ()
1160 if (STRINGP (Vsystem_name))
1161 return (char *) XSTRING (Vsystem_name)->data;
1162 else
1163 return "";
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\
1178 count.\n\
1180 The microsecond count is zero on systems that do not provide\n\
1181 resolution finer than a second.")
1184 EMACS_TIME t;
1185 Lisp_Object result[3];
1187 EMACS_GET_TIME (t);
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);
1196 static int
1197 lisp_time_argument (specified_time, result, usec)
1198 Lisp_Object specified_time;
1199 time_t *result;
1200 int *usec;
1202 if (NILP (specified_time))
1204 if (usec)
1206 EMACS_TIME t;
1208 EMACS_GET_TIME (t);
1209 *usec = EMACS_USECS (t);
1210 *result = EMACS_SECS (t);
1211 return 1;
1213 else
1214 return time (result) != -1;
1216 else
1218 Lisp_Object high, low;
1219 high = Fcar (specified_time);
1220 CHECK_NUMBER (high, 0);
1221 low = Fcdr (specified_time);
1222 if (CONSP (low))
1224 if (usec)
1226 Lisp_Object usec_l = Fcdr (low);
1227 if (CONSP (usec_l))
1228 usec_l = Fcar (usec_l);
1229 if (NILP (usec_l))
1230 *usec = 0;
1231 else
1233 CHECK_NUMBER (usec_l, 0);
1234 *usec = XINT (usec_l);
1237 low = Fcar (low);
1239 else if (usec)
1240 *usec = 0;
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'.")
1254 (specified_time)
1255 Lisp_Object specified_time;
1257 time_t sec;
1258 int usec;
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
1275 bytes in FORMAT. */
1276 static size_t
1277 emacs_memftimeu (s, maxsize, format, format_len, tp, ut)
1278 char *s;
1279 size_t maxsize;
1280 const char *format;
1281 size_t format_len;
1282 const struct tm *tp;
1283 int ut;
1285 size_t total = 0;
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. */
1292 for (;;)
1294 size_t len;
1295 size_t result;
1297 if (s)
1298 s[0] = '\1';
1300 result = emacs_strftimeu (s, maxsize, format, tp, ut);
1302 if (s)
1304 if (result == 0 && s[0] != '\0')
1305 return 0;
1306 s += result + 1;
1309 maxsize -= result + 1;
1310 total += result;
1311 len = strlen (format);
1312 if (len == format_len)
1313 return total;
1314 total++;
1315 format += len + 1;
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;
1376 time_t value;
1377 int size;
1378 struct tm *tm;
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);
1393 if (! tm)
1394 error ("Specified time is not representable");
1396 synchronize_system_time_locale ();
1398 while (1)
1400 char *buf = (char *) alloca (size + 1);
1401 int result;
1403 buf[0] = '\1';
1404 result = emacs_memftimeu (buf, size, XSTRING (format_string)->data,
1405 STRING_BYTES (XSTRING (format_string)),
1406 tm, ut);
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)),
1415 tm, ut);
1416 size = result + 1;
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.)")
1433 (specified_time)
1434 Lisp_Object specified_time;
1436 time_t time_spec;
1437 struct tm save_tm;
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);
1445 if (! decoded_time)
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;
1461 else
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.")
1483 (nargs, args)
1484 int nargs;
1485 register Lisp_Object *args;
1487 time_t time;
1488 struct tm tm;
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;
1504 tm.tm_isdst = -1;
1506 if (CONSP (zone))
1507 zone = Fcar (zone);
1508 if (NILP (zone))
1509 time = mktime (&tm);
1510 else
1512 char tzbuf[100];
1513 char *tzstring;
1514 char **oldenv = environ, **newenv;
1516 if (EQ (zone, Qt))
1517 tzstring = "UTC0";
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);
1525 tzstring = tzbuf;
1527 else
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. */
1537 newenv = environ;
1538 environ = oldenv;
1539 xfree (newenv);
1540 #ifdef LOCALTIME_CACHE
1541 tzset ();
1542 #endif
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\
1561 (HIGH . LOW)\n\
1562 or the form:\n\
1563 (HIGH LOW . IGNORED).\n\
1564 Thus, you can use times obtained from `current-time'\n\
1565 and from `file-attributes'.")
1566 (specified_time)
1567 Lisp_Object specified_time;
1569 time_t value;
1570 char buf[30];
1571 register char *tem;
1573 if (! lisp_time_argument (specified_time, &value, NULL))
1574 value = -1;
1575 tem = (char *) ctime (&value);
1577 strncpy (buf, tem, 24);
1578 buf[24] = 0;
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. */
1587 static int
1588 tm_diff (a, b)
1589 struct tm *a, *b;
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\
1617 (HIGH . LOW)\n\
1618 or 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.")
1626 (specified_time)
1627 Lisp_Object specified_time;
1629 time_t value;
1630 struct tm *t;
1631 struct tm gmt;
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);
1638 char *s = 0;
1639 char buf[6];
1640 #ifdef HAVE_TM_ZONE
1641 if (t->tm_zone)
1642 s = (char *)t->tm_zone;
1643 #else /* not HAVE_TM_ZONE */
1644 #ifdef HAVE_TZNAME
1645 if (t->tm_isdst == 0 || t->tm_isdst == 1)
1646 s = tzname[t->tm_isdst];
1647 #endif
1648 #endif /* not HAVE_TM_ZONE */
1649 if (!s)
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);
1654 s = buf;
1656 return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
1658 else
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.")
1671 (tz)
1672 Lisp_Object tz;
1674 char *tzstring;
1676 if (NILP (tz))
1677 tzstring = 0;
1678 else if (EQ (tz, Qt))
1679 tzstring = "UTC0";
1680 else
1682 CHECK_STRING (tz, 0);
1683 tzstring = (char *) XSTRING (tz)->data;
1686 set_time_zone_rule (tzstring);
1687 if (environbuf)
1688 free (environbuf);
1689 environbuf = environ;
1691 return Qnil;
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";
1708 #endif
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. */
1713 void
1714 set_time_zone_rule (tzstring)
1715 char *tzstring;
1717 int envptrs;
1718 char **from, **to, **newenv;
1720 /* Make the ENVIRON vector longer with room for TZSTRING. */
1721 for (from = environ; *from; from++)
1722 continue;
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. */
1728 if (tzstring)
1730 char *t = (char *) (to + envptrs);
1731 strcpy (t, "TZ=");
1732 strcat (t, tzstring);
1733 *to++ = t;
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)
1741 *to++ = *from;
1742 *to = 0;
1744 environ = newenv;
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. */
1760 if (tzstring)
1762 /* Temporarily set TZ to a value that loads a tz file
1763 and that differs from tzstring. */
1764 char *tz = *newenv;
1765 *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
1766 ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
1767 tzset ();
1768 *newenv = tz;
1770 else
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;
1775 to[1] = 0;
1776 tzset ();
1777 *to = set_time_zone_rule_tz2;
1778 tzset ();
1779 *to = 0;
1782 /* Now TZ has the desired value, and tzset can be invoked safely. */
1785 tzset ();
1786 #endif
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. */
1794 void
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));
1799 int inherit, nargs;
1800 register Lisp_Object *args;
1802 register int argnum;
1803 register Lisp_Object val;
1805 for (argnum = 0; argnum < nargs; argnum++)
1807 val = args[argnum];
1808 retry:
1809 if (INTEGERP (val))
1811 unsigned char str[MAX_MULTIBYTE_LENGTH];
1812 int len;
1814 if (!NILP (current_buffer->enable_multibyte_characters))
1815 len = CHAR_STRING (XFASTINT (val), str);
1816 else
1818 str[0] = (SINGLE_BYTE_CHAR_P (XINT (val))
1819 ? XINT (val)
1820 : multibyte_char_to_unibyte (XINT (val), Qnil));
1821 len = 1;
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)),
1830 inherit);
1832 else
1834 val = wrong_type_argument (Qchar_or_string_p, val);
1835 goto retry;
1840 void
1841 insert1 (arg)
1842 Lisp_Object arg;
1844 Finsert (1, &arg);
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.")
1863 (nargs, args)
1864 int nargs;
1865 register Lisp_Object *args;
1867 general_insert_function (insert, insert_from_string, 0, nargs, args);
1868 return Qnil;
1871 DEFUN ("insert-and-inherit", Finsert_and_inherit, Sinsert_and_inherit,
1872 0, MANY, 0,
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.")
1882 (nargs, args)
1883 int nargs;
1884 register Lisp_Object *args;
1886 general_insert_function (insert_and_inherit, insert_from_string, 1,
1887 nargs, args);
1888 return Qnil;
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.")
1899 (nargs, args)
1900 int nargs;
1901 register Lisp_Object *args;
1903 general_insert_function (insert_before_markers,
1904 insert_from_string_before_markers, 0,
1905 nargs, args);
1906 return Qnil;
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.")
1918 (nargs, args)
1919 int nargs;
1920 register Lisp_Object *args;
1922 general_insert_function (insert_before_markers_and_inherit,
1923 insert_from_string_before_markers, 1,
1924 nargs, args);
1925 return Qnil;
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;
1939 register int i, n;
1940 int len;
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);
1948 else
1949 str[0] = XFASTINT (character), len = 1;
1950 n = XINT (count) * len;
1951 if (n <= 0)
1952 return Qnil;
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];
1957 while (n >= strlen)
1959 QUIT;
1960 if (!NILP (inherit))
1961 insert_and_inherit (string, strlen);
1962 else
1963 insert (string, strlen);
1964 n -= strlen;
1966 if (n > 0)
1968 if (!NILP (inherit))
1969 insert_and_inherit (string, n);
1970 else
1971 insert (string, n);
1973 return Qnil;
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. */
1992 Lisp_Object
1993 make_buffer_string (start, end, props)
1994 int start, end;
1995 int 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. */
2018 Lisp_Object
2019 make_buffer_string_both (start, start_byte, end, end_byte, props)
2020 int start, start_byte, end, end_byte;
2021 int props;
2023 Lisp_Object result, tem, tem1;
2025 if (start < GPT && GPT < end)
2026 move_gap (start);
2028 if (! NILP (current_buffer->enable_multibyte_characters))
2029 result = make_uninit_multibyte_string (end - start, end_byte - start_byte);
2030 else
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. */
2036 if (props)
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,
2045 end - start);
2048 return result;
2051 /* Call Vbuffer_access_fontify_functions for the range START ... END
2052 in the current buffer, if necessary. */
2054 static void
2055 update_buffer_properties (start, end)
2056 int 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];
2063 Lisp_Object tem;
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,
2075 Qnil, Qnil);
2076 if (! NILP (tem))
2077 Frun_hook_with_args (3, args);
2079 else
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.")
2089 (start, end)
2090 Lisp_Object start, end;
2092 register int b, e;
2094 validate_region (&start, &end);
2095 b = XINT (start);
2096 e = XINT (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.")
2106 (start, end)
2107 Lisp_Object start, end;
2109 register int b, e;
2111 validate_region (&start, &end);
2112 b = XINT (start);
2113 e = XINT (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\
2122 string returned.")
2125 return make_buffer_string (BEGV, ZV, 1);
2128 DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
2129 1, 3, 0,
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.")
2134 (buf, start, end)
2135 Lisp_Object buf, start, end;
2137 register int b, e, temp;
2138 register struct buffer *bp, *obuf;
2139 Lisp_Object buffer;
2141 buffer = Fget_buffer (buf);
2142 if (NILP (buffer))
2143 nsberror (buf);
2144 bp = XBUFFER (buffer);
2145 if (NILP (bp->name))
2146 error ("Selecting deleted buffer");
2148 if (NILP (start))
2149 b = BUF_BEGV (bp);
2150 else
2152 CHECK_NUMBER_COERCE_MARKER (start, 0);
2153 b = XINT (start);
2155 if (NILP (end))
2156 e = BUF_ZV (bp);
2157 else
2159 CHECK_NUMBER_COERCE_MARKER (end, 1);
2160 e = XINT (end);
2163 if (b > e)
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);
2175 return Qnil;
2178 DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings,
2179 6, 6, 0,
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);
2195 int chars = 0;
2196 int i1, i2, i1_byte, i2_byte;
2198 /* Find the first buffer and its substring. */
2200 if (NILP (buffer1))
2201 bp1 = current_buffer;
2202 else
2204 Lisp_Object buf1;
2205 buf1 = Fget_buffer (buffer1);
2206 if (NILP (buf1))
2207 nsberror (buffer1);
2208 bp1 = XBUFFER (buf1);
2209 if (NILP (bp1->name))
2210 error ("Selecting deleted buffer");
2213 if (NILP (start1))
2214 begp1 = BUF_BEGV (bp1);
2215 else
2217 CHECK_NUMBER_COERCE_MARKER (start1, 1);
2218 begp1 = XINT (start1);
2220 if (NILP (end1))
2221 endp1 = BUF_ZV (bp1);
2222 else
2224 CHECK_NUMBER_COERCE_MARKER (end1, 2);
2225 endp1 = XINT (end1);
2228 if (begp1 > endp1)
2229 temp = begp1, begp1 = endp1, endp1 = temp;
2231 if (!(BUF_BEGV (bp1) <= begp1
2232 && begp1 <= endp1
2233 && endp1 <= BUF_ZV (bp1)))
2234 args_out_of_range (start1, end1);
2236 /* Likewise for second substring. */
2238 if (NILP (buffer2))
2239 bp2 = current_buffer;
2240 else
2242 Lisp_Object buf2;
2243 buf2 = Fget_buffer (buffer2);
2244 if (NILP (buf2))
2245 nsberror (buffer2);
2246 bp2 = XBUFFER (buf2);
2247 if (NILP (bp2->name))
2248 error ("Selecting deleted buffer");
2251 if (NILP (start2))
2252 begp2 = BUF_BEGV (bp2);
2253 else
2255 CHECK_NUMBER_COERCE_MARKER (start2, 4);
2256 begp2 = XINT (start2);
2258 if (NILP (end2))
2259 endp2 = BUF_ZV (bp2);
2260 else
2262 CHECK_NUMBER_COERCE_MARKER (end2, 5);
2263 endp2 = XINT (end2);
2266 if (begp2 > endp2)
2267 temp = begp2, begp2 = endp2, endp2 = temp;
2269 if (!(BUF_BEGV (bp2) <= begp2
2270 && begp2 <= endp2
2271 && endp2 <= BUF_ZV (bp2)))
2272 args_out_of_range (start2, end2);
2274 i1 = begp1;
2275 i2 = begp2;
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. */
2283 int c1, c2;
2285 if (! NILP (bp1->enable_multibyte_characters))
2287 c1 = BUF_FETCH_MULTIBYTE_CHAR (bp1, i1_byte);
2288 BUF_INC_POS (bp1, i1_byte);
2289 i1++;
2291 else
2293 c1 = BUF_FETCH_BYTE (bp1, i1);
2294 c1 = unibyte_char_to_multibyte (c1);
2295 i1++;
2298 if (! NILP (bp2->enable_multibyte_characters))
2300 c2 = BUF_FETCH_MULTIBYTE_CHAR (bp2, i2_byte);
2301 BUF_INC_POS (bp2, i2_byte);
2302 i2++;
2304 else
2306 c2 = BUF_FETCH_BYTE (bp2, i2);
2307 c2 = unibyte_char_to_multibyte (c2);
2308 i2++;
2311 if (trt)
2313 c1 = XINT (trt[c1]);
2314 c2 = XINT (trt[c2]);
2316 if (c1 < c2)
2317 return make_number (- 1 - chars);
2318 if (c1 > c2)
2319 return make_number (chars + 1);
2321 chars++;
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);
2335 static Lisp_Object
2336 subst_char_in_region_unwind (arg)
2337 Lisp_Object arg;
2339 return current_buffer->undo_list = arg;
2342 static Lisp_Object
2343 subst_char_in_region_unwind_1 (arg)
2344 Lisp_Object 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;
2359 int changed = 0;
2360 unsigned char fromstr[MAX_MULTIBYTE_LENGTH], tostr[MAX_MULTIBYTE_LENGTH];
2361 unsigned char *p;
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;
2368 int last_changed;
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);
2375 if (multibyte_p)
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;
2392 else
2394 len = 1;
2395 fromstr[0] = XFASTINT (fromchar);
2396 tostr[0] = XFASTINT (tochar);
2399 pos = XINT (start);
2400 pos_byte = CHAR_TO_BYTE (pos);
2401 stop = CHAR_TO_BYTE (XINT (end));
2402 end_byte = stop;
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. */
2408 if (!NILP (noundo))
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);
2421 while (1)
2423 int pos_byte_next = pos_byte;
2425 if (pos_byte >= stop)
2427 if (pos_byte >= end_byte) break;
2428 stop = end_byte;
2430 p = BYTE_POS_ADDR (pos_byte);
2431 if (multibyte_p)
2432 INC_POS (pos_byte_next);
2433 else
2434 ++pos_byte_next;
2435 if (pos_byte_next - pos_byte == len
2436 && p[0] == fromstr[0]
2437 && (len == 1
2438 || (p[1] == fromstr[1]
2439 && (len == 2 || (p[2] == fromstr[2]
2440 && (len == 3 || p[3] == fromstr[3]))))))
2442 if (! changed)
2444 changed = pos;
2445 modify_region (current_buffer, changed, XINT (end));
2447 if (! NILP (noundo))
2449 if (MODIFF - 1 == SAVE_MODIFF)
2450 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;
2472 GCPRO1 (tem);
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,
2479 0, 0, 1);
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,
2484 decrease it now. */
2485 pos--;
2486 else
2487 INC_POS (pos_byte_next);
2489 if (! NILP (noundo))
2490 current_buffer->undo_list = tem;
2492 UNGCPRO;
2494 else
2496 if (NILP (noundo))
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;
2503 pos++;
2506 if (changed)
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);
2514 return 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.")
2523 (start, end, table)
2524 Lisp_Object start;
2525 Lisp_Object end;
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. */
2533 int pos;
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));
2545 pos = XINT (start);
2547 cnt = 0;
2548 for (; pos_byte < stop; )
2550 register unsigned char *p = BYTE_POS_ADDR (pos_byte);
2551 int len;
2552 int oc;
2553 int pos_byte_next;
2555 if (multibyte)
2556 oc = STRING_CHAR_AND_LENGTH (p, stop - pos_byte, len);
2557 else
2558 oc = *p, len = 1;
2559 pos_byte_next = pos_byte + len;
2560 if (oc < size && len == 1)
2562 nc = tt[oc];
2563 if (nc != oc)
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)))))
2573 Lisp_Object string;
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,
2579 1, 0, 1);
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. */
2585 pos--;
2586 else
2587 INC_POS (pos_byte_next);
2589 else
2591 record_change (pos, 1);
2592 *p = nc;
2593 signal_after_change (pos, 1, 1);
2594 update_compositions (pos, pos + 1, CHECK_BORDER);
2596 ++cnt;
2599 pos_byte = pos_byte_next;
2600 pos++;
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.")
2610 (start, end)
2611 Lisp_Object start, end;
2613 validate_region (&start, &end);
2614 del_range (XINT (start), XINT (end));
2615 return Qnil;
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.")
2621 (start, end)
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;
2635 BEGV = BEG;
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 ();
2640 return Qnil;
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.")
2652 (start, end)
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))
2660 Lisp_Object tem;
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 ();
2678 return Qnil;
2681 Lisp_Object
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));
2694 Lisp_Object
2695 save_restriction_restore (data)
2696 Lisp_Object data;
2698 register struct buffer *buf;
2699 register int newhead, newtail;
2700 register Lisp_Object tem;
2701 int obegv, ozv;
2703 buf = XBUFFER (XCAR (data));
2705 data = XCDR (data);
2707 tem = XCAR (data);
2708 newhead = XINT (tem);
2709 tem = XCDR (data);
2710 newtail = XINT (tem);
2711 if (newhead + newtail > BUF_Z (buf) - BUF_BEG (buf))
2713 newhead = 0;
2714 newtail = 0;
2717 obegv = BUF_BEGV (buf);
2718 ozv = BUF_ZV (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)));
2732 return Qnil;
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 ...))")
2754 (body)
2755 Lisp_Object body;
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);
2765 #ifndef HAVE_MENUS
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.")
2782 (nargs, args)
2783 int nargs;
2784 Lisp_Object *args;
2786 if (NILP (args[0]))
2788 message (0);
2789 return Qnil;
2791 else
2793 register Lisp_Object val;
2794 val = Fformat (nargs, args);
2795 message3 (val, STRING_BYTES (XSTRING (val)), STRING_MULTIBYTE (val));
2796 return 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.")
2808 (nargs, args)
2809 int nargs;
2810 Lisp_Object *args;
2812 if (NILP (args[0]))
2814 message (0);
2815 return Qnil;
2817 else
2819 register Lisp_Object val;
2820 val = Fformat (nargs, args);
2821 #ifdef HAVE_MENUS
2823 Lisp_Object pane, menu, obj;
2824 struct gcpro gcpro1;
2825 pane = Fcons (Fcons (build_string ("OK"), Qt), Qnil);
2826 GCPRO1 (pane);
2827 menu = Fcons (val, pane);
2828 obj = Fx_popup_dialog (Qt, menu);
2829 UNGCPRO;
2830 return val;
2832 #else /* not HAVE_MENUS */
2833 /* Copy the data so that it won't move when we GC. */
2834 if (! message_text)
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));
2847 return val;
2848 #endif /* not HAVE_MENUS */
2851 #ifdef HAVE_MENUS
2852 extern Lisp_Object last_nonmenu_event;
2853 #endif
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.")
2864 (nargs, args)
2865 int nargs;
2866 Lisp_Object *args;
2868 #ifdef HAVE_MENUS
2869 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2870 && use_dialog_box)
2871 return Fmessage_box (nargs, args);
2872 #endif
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 ")
2889 (nargs, args)
2890 int nargs;
2891 Lisp_Object *args;
2893 Lisp_Object properties, string;
2894 struct gcpro gcpro1, gcpro2;
2895 int i;
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.")
2945 (nargs, args)
2946 int nargs;
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 */
2951 char *buf, *p;
2952 register unsigned char *format, *end;
2953 int nchars;
2954 /* Nonzero if the output should be a multibyte string,
2955 which is true if any of the inputs is one. */
2956 int multibyte = 0;
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;
2963 int longest_format;
2964 Lisp_Object val;
2965 struct info
2967 int start, end;
2968 } *info = 0;
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]))
2981 multibyte = 1;
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. */
2987 retry:
2989 format = XSTRING (args[0])->data;
2990 end = format + STRING_BYTES (XSTRING (args[0]));
2991 longest_format = 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. */
2998 n = 0;
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);
3007 if (minlen < 0)
3008 minlen = - minlen;
3010 while ((*format >= '0' && *format <= '9')
3011 || *format == '-' || *format == ' ' || *format == '.')
3012 format++;
3014 if (format - this_format_start + 1 > longest_format)
3015 longest_format = format - this_format_start + 1;
3017 if (format == end)
3018 error ("Format string ends in middle of format specifier");
3019 if (*format == '%')
3020 format++;
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)
3030 multibyte = 1;
3031 goto retry;
3033 args[n] = tem;
3034 goto string;
3036 else if (SYMBOLP (args[n]))
3038 /* Use a temp var to avoid problems when ENABLE_CHECKING
3039 is turned on. */
3040 struct Lisp_String *t = XSYMBOL (args[n])->name;
3041 XSETSTRING (args[n], t);
3042 if (STRING_MULTIBYTE (args[n]) && ! multibyte)
3044 multibyte = 1;
3045 goto retry;
3047 goto string;
3049 else if (STRINGP (args[n]))
3051 string:
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
3062 be a double. */
3063 if (*format == 'e' || *format == 'f' || *format == 'g')
3064 args[n] = Ffloat (args[n]);
3065 else
3066 if (*format != 'd' && *format != 'o' && *format != 'x'
3067 && *format != 'i' && *format != 'X' && *format != 'c')
3068 error ("Invalid format operation %%%c", *format);
3070 thissize = 30;
3071 if (*format == 'c'
3072 && (! SINGLE_BYTE_CHAR_P (XINT (args[n]))
3073 || XINT (args[n]) == 0))
3075 if (! multibyte)
3077 multibyte = 1;
3078 goto retry;
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);
3088 thissize = 200;
3090 else
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)
3097 multibyte = 1;
3098 goto retry;
3100 args[n] = tem;
3101 goto string;
3104 if (thissize < minlen)
3105 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. */
3117 if (total < 1000)
3118 buf = (char *) alloca (total + 1);
3119 else
3120 buf = (char *) xmalloc (total + 1);
3122 p = buf;
3123 nchars = 0;
3124 n = 0;
3126 /* Scan the format and store result in BUF. */
3127 format = XSTRING (args[0])->data;
3128 maybe_combine_byte = 0;
3129 while (format != end)
3131 if (*format == '%')
3133 int minlen;
3134 int negative = 0;
3135 unsigned char *this_format_start = format;
3137 format++;
3139 /* Process a numeric arg and skip it. */
3140 minlen = atoi (format);
3141 if (minlen < 0)
3142 minlen = - minlen, negative = 1;
3144 while ((*format >= '0' && *format <= '9')
3145 || *format == '-' || *format == ' ' || *format == '.')
3146 format++;
3148 if (*format++ == '%')
3150 *p++ = '%';
3151 nchars++;
3152 continue;
3155 ++n;
3157 if (STRINGP (args[n]))
3159 int padding, nbytes;
3160 int width = strwidth (XSTRING (args[n])->data,
3161 STRING_BYTES (XSTRING (args[n])));
3162 int start = nchars;
3164 /* If spec requires it, pad on right with spaces. */
3165 padding = minlen - width;
3166 if (! negative)
3167 while (padding-- > 0)
3169 *p++ = ' ';
3170 nchars++;
3173 if (p > buf
3174 && multibyte
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);
3182 p += nbytes;
3183 nchars += XSTRING (args[n])->size;
3185 if (negative)
3186 while (padding-- > 0)
3188 *p++ = ' ';
3189 nchars++;
3192 /* If this argument has text properties, record where
3193 in the result string it appears. */
3194 if (XSTRING (args[n])->intervals)
3196 if (!info)
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]))
3209 int this_nchars;
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]));
3217 else
3218 sprintf (p, this_format, XFLOAT_DATA (args[n]));
3220 if (p > buf
3221 && multibyte
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);
3226 if (multibyte)
3227 p += str_to_multibyte (p, buf + total - p, this_nchars);
3228 else
3229 p += this_nchars;
3230 nchars += this_nchars;
3233 else if (STRING_MULTIBYTE (args[0]))
3235 /* Copy a whole multibyte character. */
3236 if (p > buf
3237 && multibyte
3238 && !ASCII_BYTE_P (*((unsigned char *) p - 1))
3239 && !CHAR_HEAD_P (*format))
3240 maybe_combine_byte = 1;
3241 *p++ = *format++;
3242 while (! CHAR_HEAD_P (*format)) *p++ = *format++;
3243 nchars++;
3245 else if (multibyte)
3247 /* Convert a single-byte character to multibyte. */
3248 int len = copy_text (format, p, 1, 0, 1);
3250 p += len;
3251 format++;
3252 nchars++;
3254 else
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. */
3263 if (total >= 1000)
3264 xfree (buf);
3266 /* If the format string has text properties, or any of the string
3267 arguments has text properties, set up text properties of the
3268 result string. */
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);
3278 GCPRO1 (props);
3280 if (CONSP (props))
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. */
3288 if (info)
3289 for (n = 1; n < nargs; ++n)
3290 if (info[n].end)
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));
3304 UNGCPRO;
3307 return val;
3311 /* VARARGS 1 */
3312 Lisp_Object
3313 #ifdef NO_ARG_ARRAY
3314 format1 (string1, arg0, arg1, arg2, arg3, arg4)
3315 EMACS_INT arg0, arg1, arg2, arg3, arg4;
3316 #else
3317 format1 (string1)
3318 #endif
3319 char *string1;
3321 char buf[100];
3322 #ifdef NO_ARG_ARRAY
3323 EMACS_INT args[5];
3324 args[0] = arg0;
3325 args[1] = arg1;
3326 args[2] = arg2;
3327 args[3] = arg3;
3328 args[4] = arg4;
3329 doprnt (buf, sizeof buf, string1, (char *)0, 5, (char **) args);
3330 #else
3331 doprnt (buf, sizeof buf, string1, (char *)0, 5, &string1 + 1);
3332 #endif
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.")
3340 (c1, c2)
3341 register Lisp_Object c1, c2;
3343 int i1, i2;
3344 CHECK_NUMBER (c1, 0);
3345 CHECK_NUMBER (c2, 1);
3347 if (XINT (c1) == XINT (c2))
3348 return Qt;
3349 if (NILP (current_buffer->case_fold_search))
3350 return Qnil;
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
3362 differ in size).
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. */
3375 void
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. */
3385 if (PT < start1)
3387 else if (PT < end1)
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)));
3394 else if (PT < end2)
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)
3424 mpos += amt1_byte;
3425 else if (mpos < start2_byte)
3426 mpos += diff_byte;
3427 else
3428 mpos -= amt2_byte;
3429 XMARKER (marker)->bytepos = mpos;
3431 mpos = XMARKER (marker)->charpos;
3432 if (mpos >= start1 && mpos < end2)
3434 if (mpos < end1)
3435 mpos += amt1;
3436 else if (mpos < start2)
3437 mpos += diff;
3438 else
3439 mpos -= amt2;
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);
3473 gap = GPT;
3475 /* Swap the regions if they're reversed. */
3476 if (start2 < end1)
3478 register int glumph = start1;
3479 start1 = start2;
3480 start2 = glumph;
3481 glumph = end1;
3482 end1 = end2;
3483 end2 = glumph;
3486 len1 = end1 - start1;
3487 len2 = end2 - start2;
3489 if (start2 < end1)
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)
3521 move_gap (start1);
3522 else
3523 move_gap (end2);
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
3532 if (end1 == start2)
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))
3540 abort ();
3542 else
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))
3552 abort ();
3554 #endif
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),
3571 Qnil, Qnil);
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);
3580 else
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)
3593 xfree (temp);
3595 else
3596 /* First region not smaller than second. */
3598 if (len1_byte > 20000)
3599 temp = (unsigned char *) xmalloc (len1_byte);
3600 else
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)
3608 xfree (temp);
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... */
3618 else
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),
3632 Qnil, Qnil);
3633 Fset_text_properties (make_number (start2), make_number (end2),
3634 Qnil, Qnil);
3636 if (len1_byte > 20000)
3637 temp = (unsigned char *) xmalloc (len1_byte);
3638 else
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)
3646 xfree (temp);
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),
3662 Qnil, Qnil);
3664 /* holds region 2 */
3665 if (len2_byte > 20000)
3666 temp = (unsigned char *) xmalloc (len2_byte);
3667 else
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)
3676 xfree (temp);
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);
3684 else
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),
3694 Qnil, Qnil);
3696 /* holds region 1 */
3697 if (len1_byte > 20000)
3698 temp = (unsigned char *) xmalloc (len1_byte);
3699 else
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)
3708 xfree (temp);
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);
3732 return Qnil;
3736 void
3737 syms_of_editfns ()
3739 environbuf = 0;
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;
3757 Lisp_Object obuf;
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")),
3764 Qnil);
3765 Fset_buffer (obuf);
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);
3798 defsubr (&Spoint);
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);
3831 defsubr (&Sbobp);
3832 defsubr (&Seobp);
3833 defsubr (&Sbolp);
3834 defsubr (&Seolp);
3835 defsubr (&Sfollowing_char);
3836 defsubr (&Sprevious_char);
3837 defsubr (&Schar_after);
3838 defsubr (&Schar_before);
3839 defsubr (&Sinsert);
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);
3864 defsubr (&Sformat);
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);
3872 defsubr (&Swiden);
3873 defsubr (&Snarrow_to_region);
3874 defsubr (&Ssave_restriction);
3875 defsubr (&Stranspose_regions);