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