Include charset.h.
[bpt/emacs.git] / src / editfns.c
1 /* Lisp functions pertaining to editing.
2 Copyright (C) 1985,86,87,89,93,94,95,96,97 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 <sys/types.h>
23
24 #include <config.h>
25
26 #ifdef VMS
27 #include "vms-pwd.h"
28 #else
29 #include <pwd.h>
30 #endif
31
32 #include "lisp.h"
33 #include "intervals.h"
34 #include "buffer.h"
35 #include "charset.h"
36 #include "window.h"
37
38 #include "systime.h"
39
40 #define min(a, b) ((a) < (b) ? (a) : (b))
41 #define max(a, b) ((a) > (b) ? (a) : (b))
42
43 extern char **environ;
44 extern Lisp_Object make_time ();
45 extern void insert_from_buffer ();
46 static int tm_diff ();
47 static void update_buffer_properties ();
48 void set_time_zone_rule ();
49
50 Lisp_Object Vbuffer_access_fontify_functions;
51 Lisp_Object Qbuffer_access_fontify_functions;
52 Lisp_Object Vbuffer_access_fontified_property;
53
54 /* Some static data, and a function to initialize it for each run */
55
56 Lisp_Object Vsystem_name;
57 Lisp_Object Vuser_real_login_name; /* login name of current user ID */
58 Lisp_Object Vuser_full_name; /* full name of current user */
59 Lisp_Object Vuser_login_name; /* user name from LOGNAME or USER */
60
61 void
62 init_editfns ()
63 {
64 char *user_name;
65 register unsigned char *p, *q, *r;
66 struct passwd *pw; /* password entry for the current user */
67 Lisp_Object tem;
68
69 /* Set up system_name even when dumping. */
70 init_system_name ();
71
72 #ifndef CANNOT_DUMP
73 /* Don't bother with this on initial start when just dumping out */
74 if (!initialized)
75 return;
76 #endif /* not CANNOT_DUMP */
77
78 pw = (struct passwd *) getpwuid (getuid ());
79 #ifdef MSDOS
80 /* We let the real user name default to "root" because that's quite
81 accurate on MSDOG and because it lets Emacs find the init file.
82 (The DVX libraries override the Djgpp libraries here.) */
83 Vuser_real_login_name = build_string (pw ? pw->pw_name : "root");
84 #else
85 Vuser_real_login_name = build_string (pw ? pw->pw_name : "unknown");
86 #endif
87
88 /* Get the effective user name, by consulting environment variables,
89 or the effective uid if those are unset. */
90 user_name = (char *) getenv ("LOGNAME");
91 if (!user_name)
92 #ifdef WINDOWSNT
93 user_name = (char *) getenv ("USERNAME"); /* it's USERNAME on NT */
94 #else /* WINDOWSNT */
95 user_name = (char *) getenv ("USER");
96 #endif /* WINDOWSNT */
97 if (!user_name)
98 {
99 pw = (struct passwd *) getpwuid (geteuid ());
100 user_name = (char *) (pw ? pw->pw_name : "unknown");
101 }
102 Vuser_login_name = build_string (user_name);
103
104 /* If the user name claimed in the environment vars differs from
105 the real uid, use the claimed name to find the full name. */
106 tem = Fstring_equal (Vuser_login_name, Vuser_real_login_name);
107 Vuser_full_name = Fuser_full_name (NILP (tem)? make_number (geteuid())
108 : Vuser_login_name);
109
110 p = (unsigned char *) getenv ("NAME");
111 if (p)
112 Vuser_full_name = build_string (p);
113 else if (NILP (Vuser_full_name))
114 Vuser_full_name = build_string ("unknown");
115 }
116 \f
117 DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
118 "Convert arg CHAR to a string containing multi-byte form of that character.")
119 (character)
120 Lisp_Object character;
121 {
122 int len;
123 char workbuf[4], *str;
124
125 CHECK_NUMBER (character, 0);
126
127 len = CHAR_STRING (XFASTINT (character), workbuf, str);
128 return make_string (str, len);
129 }
130
131 DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
132 "Convert arg STRING to a character, the first character of that string.\n\
133 A multibyte character is handled correctly.")
134 (string)
135 register Lisp_Object string;
136 {
137 register Lisp_Object val;
138 register struct Lisp_String *p;
139 CHECK_STRING (string, 0);
140 p = XSTRING (string);
141 if (p->size)
142 XSETFASTINT (val, STRING_CHAR (p->data, p->size));
143 else
144 XSETFASTINT (val, 0);
145 return val;
146 }
147
148 DEFUN ("sref", Fsref, Ssref, 2, 2, 0,
149 "Return the character in STRING at INDEX. INDEX starts at 0.\n\
150 A multibyte character is handled correctly.\n\
151 INDEX not pointing at character boundary is an error.")
152 (str, idx)
153 Lisp_Object str, idx;
154 {
155 register int idxval, len;
156 register unsigned char *p;
157 register Lisp_Object val;
158
159 CHECK_STRING (str, 0);
160 CHECK_NUMBER (idx, 1);
161 idxval = XINT (idx);
162 if (idxval < 0 || idxval >= (len = XVECTOR (str)->size))
163 args_out_of_range (str, idx);
164 p = XSTRING (str)->data + idxval;
165 if (!CHAR_HEAD_P (p))
166 error ("Not character boundary");
167
168 len = XSTRING (str)->size - idxval;
169 XSETFASTINT (val, STRING_CHAR (p, len));
170 return val;
171 }
172
173 \f
174 static Lisp_Object
175 buildmark (val)
176 int val;
177 {
178 register Lisp_Object mark;
179 mark = Fmake_marker ();
180 Fset_marker (mark, make_number (val), Qnil);
181 return mark;
182 }
183
184 DEFUN ("point", Fpoint, Spoint, 0, 0, 0,
185 "Return value of point, as an integer.\n\
186 Beginning of buffer is position (point-min)")
187 ()
188 {
189 Lisp_Object temp;
190 XSETFASTINT (temp, PT);
191 return temp;
192 }
193
194 DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
195 "Return value of point, as a marker object.")
196 ()
197 {
198 return buildmark (PT);
199 }
200
201 int
202 clip_to_bounds (lower, num, upper)
203 int lower, num, upper;
204 {
205 if (num < lower)
206 return lower;
207 else if (num > upper)
208 return upper;
209 else
210 return num;
211 }
212
213 DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
214 "Set point to POSITION, a number or marker.\n\
215 Beginning of buffer is position (point-min), end is (point-max).\n\
216 If the position is in the middle of a multibyte form,\n\
217 the actual point is set at the head of the multibyte form\n\
218 except in the case that `enable-multibyte-characters' is nil.")
219 (position)
220 register Lisp_Object position;
221 {
222 int pos;
223 unsigned char *p;
224
225 CHECK_NUMBER_COERCE_MARKER (position, 0);
226
227 pos = clip_to_bounds (BEGV, XINT (position), ZV);
228 /* If POS is in a middle of multi-byte form (i.e. *P >= 0xA0), we
229 must decrement POS until it points the head of the multi-byte
230 form. */
231 if (!NILP (current_buffer->enable_multibyte_characters)
232 && *(p = POS_ADDR (pos)) >= 0xA0
233 && pos > BEGV)
234 {
235 /* Since a multi-byte form does not contain the gap, POS should
236 not stride over the gap while it is being decreased. So, we
237 set the limit as below. */
238 unsigned char *p_min = pos < GPT ? BEG_ADDR : GAP_END_ADDR;
239 unsigned int saved_pos = pos;
240
241 do {
242 p--, pos--;
243 } while (p > p_min && *p >= 0xA0);
244 if (*p < 0x80)
245 /* This was an invalid multi-byte form. */
246 pos = saved_pos;
247 XSETFASTINT (position, pos);
248 }
249 SET_PT (pos);
250 return position;
251 }
252
253 static Lisp_Object
254 region_limit (beginningp)
255 int beginningp;
256 {
257 extern Lisp_Object Vmark_even_if_inactive; /* Defined in callint.c. */
258 register Lisp_Object m;
259 if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
260 && NILP (current_buffer->mark_active))
261 Fsignal (Qmark_inactive, Qnil);
262 m = Fmarker_position (current_buffer->mark);
263 if (NILP (m)) error ("There is no region now");
264 if ((PT < XFASTINT (m)) == beginningp)
265 return (make_number (PT));
266 else
267 return (m);
268 }
269
270 DEFUN ("region-beginning", Fregion_beginning, Sregion_beginning, 0, 0, 0,
271 "Return position of beginning of region, as an integer.")
272 ()
273 {
274 return (region_limit (1));
275 }
276
277 DEFUN ("region-end", Fregion_end, Sregion_end, 0, 0, 0,
278 "Return position of end of region, as an integer.")
279 ()
280 {
281 return (region_limit (0));
282 }
283
284 DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
285 "Return this buffer's mark, as a marker object.\n\
286 Watch out! Moving this marker changes the mark position.\n\
287 If you set the marker not to point anywhere, the buffer will have no mark.")
288 ()
289 {
290 return current_buffer->mark;
291 }
292 \f
293 DEFUN ("line-beginning-position", Fline_beginning_position, Sline_beginning_position,
294 0, 1, 0,
295 "Return the character position of the first character on the current line.\n\
296 With argument N not nil or 1, move forward N - 1 lines first.\n\
297 If scan reaches end of buffer, return that position.\n\
298 This function does not move point.")
299 (n)
300 Lisp_Object n;
301 {
302 register int orig, end;
303
304 if (NILP (n))
305 XSETFASTINT (n, 1);
306 else
307 CHECK_NUMBER (n, 0);
308
309 orig = PT;
310 Fforward_line (make_number (XINT (n) - 1));
311 end = PT;
312 SET_PT (orig);
313
314 return make_number (end);
315 }
316
317 DEFUN ("line-end-position", Fline_end_position, Sline_end_position,
318 0, 1, 0,
319 "Return the character position of the last character on the current line.\n\
320 With argument N not nil or 1, move forward N - 1 lines first.\n\
321 If scan reaches end of buffer, return that position.\n\
322 This function does not move point.")
323 (n)
324 Lisp_Object n;
325 {
326 if (NILP (n))
327 XSETFASTINT (n, 1);
328 else
329 CHECK_NUMBER (n, 0);
330
331 return make_number (find_before_next_newline
332 (PT, 0, XINT (n) - (XINT (n) <= 0)));
333 }
334 \f
335 Lisp_Object
336 save_excursion_save ()
337 {
338 register int visible = (XBUFFER (XWINDOW (selected_window)->buffer)
339 == current_buffer);
340
341 return Fcons (Fpoint_marker (),
342 Fcons (Fcopy_marker (current_buffer->mark, Qnil),
343 Fcons (visible ? Qt : Qnil,
344 current_buffer->mark_active)));
345 }
346
347 Lisp_Object
348 save_excursion_restore (info)
349 Lisp_Object info;
350 {
351 Lisp_Object tem, tem1, omark, nmark;
352 struct gcpro gcpro1, gcpro2, gcpro3;
353
354 tem = Fmarker_buffer (Fcar (info));
355 /* If buffer being returned to is now deleted, avoid error */
356 /* Otherwise could get error here while unwinding to top level
357 and crash */
358 /* In that case, Fmarker_buffer returns nil now. */
359 if (NILP (tem))
360 return Qnil;
361
362 omark = nmark = Qnil;
363 GCPRO3 (info, omark, nmark);
364
365 Fset_buffer (tem);
366 tem = Fcar (info);
367 Fgoto_char (tem);
368 unchain_marker (tem);
369 tem = Fcar (Fcdr (info));
370 omark = Fmarker_position (current_buffer->mark);
371 Fset_marker (current_buffer->mark, tem, Fcurrent_buffer ());
372 nmark = Fmarker_position (tem);
373 unchain_marker (tem);
374 tem = Fcdr (Fcdr (info));
375 #if 0 /* We used to make the current buffer visible in the selected window
376 if that was true previously. That avoids some anomalies.
377 But it creates others, and it wasn't documented, and it is simpler
378 and cleaner never to alter the window/buffer connections. */
379 tem1 = Fcar (tem);
380 if (!NILP (tem1)
381 && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
382 Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
383 #endif /* 0 */
384
385 tem1 = current_buffer->mark_active;
386 current_buffer->mark_active = Fcdr (tem);
387 if (!NILP (Vrun_hooks))
388 {
389 /* If mark is active now, and either was not active
390 or was at a different place, run the activate hook. */
391 if (! NILP (current_buffer->mark_active))
392 {
393 if (! EQ (omark, nmark))
394 call1 (Vrun_hooks, intern ("activate-mark-hook"));
395 }
396 /* If mark has ceased to be active, run deactivate hook. */
397 else if (! NILP (tem1))
398 call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
399 }
400 UNGCPRO;
401 return Qnil;
402 }
403
404 DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
405 "Save point, mark, and current buffer; execute BODY; restore those things.\n\
406 Executes BODY just like `progn'.\n\
407 The values of point, mark and the current buffer are restored\n\
408 even in case of abnormal exit (throw or error).\n\
409 The state of activation of the mark is also restored.")
410 (args)
411 Lisp_Object args;
412 {
413 register Lisp_Object val;
414 int count = specpdl_ptr - specpdl;
415
416 record_unwind_protect (save_excursion_restore, save_excursion_save ());
417
418 val = Fprogn (args);
419 return unbind_to (count, val);
420 }
421
422 DEFUN ("save-current-buffer", Fsave_current_buffer, Ssave_current_buffer, 0, UNEVALLED, 0,
423 "Save the current buffer; execute BODY; restore the current buffer.\n\
424 Executes BODY just like `progn'.")
425 (args)
426 Lisp_Object args;
427 {
428 register Lisp_Object val;
429 int count = specpdl_ptr - specpdl;
430
431 record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
432
433 val = Fprogn (args);
434 return unbind_to (count, val);
435 }
436 \f
437 DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 0, 0,
438 "Return the number of characters in the current buffer.")
439 ()
440 {
441 Lisp_Object temp;
442 XSETFASTINT (temp, Z - BEG);
443 return temp;
444 }
445
446 DEFUN ("point-min", Fpoint_min, Spoint_min, 0, 0, 0,
447 "Return the minimum permissible value of point in the current buffer.\n\
448 This is 1, unless narrowing (a buffer restriction) is in effect.")
449 ()
450 {
451 Lisp_Object temp;
452 XSETFASTINT (temp, BEGV);
453 return temp;
454 }
455
456 DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 0, 0,
457 "Return a marker to the minimum permissible value of point in this buffer.\n\
458 This is the beginning, unless narrowing (a buffer restriction) is in effect.")
459 ()
460 {
461 return buildmark (BEGV);
462 }
463
464 DEFUN ("point-max", Fpoint_max, Spoint_max, 0, 0, 0,
465 "Return the maximum permissible value of point in the current buffer.\n\
466 This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
467 is in effect, in which case it is less.")
468 ()
469 {
470 Lisp_Object temp;
471 XSETFASTINT (temp, ZV);
472 return temp;
473 }
474
475 DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 0, 0,
476 "Return a marker to the maximum permissible value of point in this buffer.\n\
477 This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
478 is in effect, in which case it is less.")
479 ()
480 {
481 return buildmark (ZV);
482 }
483
484 DEFUN ("following-char", Ffollowing_char, Sfollowing_char, 0, 0, 0,
485 "Return the character following point, as a number.\n\
486 At the end of the buffer or accessible region, return 0.\n\
487 If `enable-multibyte-characters' is nil or point is not\n\
488 at character boundary, multibyte form is ignored,\n\
489 and only one byte following point is returned as a character.")
490 ()
491 {
492 Lisp_Object temp;
493 if (PT >= ZV)
494 XSETFASTINT (temp, 0);
495 else
496 XSETFASTINT (temp, FETCH_CHAR (PT));
497 return temp;
498 }
499
500 DEFUN ("preceding-char", Fprevious_char, Sprevious_char, 0, 0, 0,
501 "Return the character preceding point, as a number.\n\
502 At the beginning of the buffer or accessible region, return 0.\n\
503 If `enable-multibyte-characters' is nil or point is not\n\
504 at character boundary, multi-byte form is ignored,\n\
505 and only one byte preceding point is returned as a character.")
506 ()
507 {
508 Lisp_Object temp;
509 if (PT <= BEGV)
510 XSETFASTINT (temp, 0);
511 else if (!NILP (current_buffer->enable_multibyte_characters))
512 {
513 int pos = PT;
514 DEC_POS (pos);
515 XSETFASTINT (temp, FETCH_CHAR (pos));
516 }
517 else
518 XSETFASTINT (temp, FETCH_BYTE (point - 1));
519 return temp;
520 }
521
522 DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0,
523 "Return T if point is at the beginning of the buffer.\n\
524 If the buffer is narrowed, this means the beginning of the narrowed part.")
525 ()
526 {
527 if (PT == BEGV)
528 return Qt;
529 return Qnil;
530 }
531
532 DEFUN ("eobp", Feobp, Seobp, 0, 0, 0,
533 "Return T if point is at the end of the buffer.\n\
534 If the buffer is narrowed, this means the end of the narrowed part.")
535 ()
536 {
537 if (PT == ZV)
538 return Qt;
539 return Qnil;
540 }
541
542 DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0,
543 "Return T if point is at the beginning of a line.")
544 ()
545 {
546 if (PT == BEGV || FETCH_BYTE (PT - 1) == '\n')
547 return Qt;
548 return Qnil;
549 }
550
551 DEFUN ("eolp", Feolp, Seolp, 0, 0, 0,
552 "Return T if point is at the end of a line.\n\
553 `End of a line' includes point being at the end of the buffer.")
554 ()
555 {
556 if (PT == ZV || FETCH_BYTE (PT) == '\n')
557 return Qt;
558 return Qnil;
559 }
560
561 DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0,
562 "Return character in current buffer at position POS.\n\
563 POS is an integer or a buffer pointer.\n\
564 If POS is out of range, the value is nil.\n\
565 If `enable-multibyte-characters' is nil or POS is not at character boundary,\n\
566 multi-byte form is ignored, and only one byte at POS\n\
567 is returned as a character.")
568 (pos)
569 Lisp_Object pos;
570 {
571 register Lisp_Object val;
572 register int n;
573
574 CHECK_NUMBER_COERCE_MARKER (pos, 0);
575
576 n = XINT (pos);
577 if (n < BEGV || n >= ZV) return Qnil;
578
579 XSETFASTINT (val, FETCH_CHAR (n));
580 return val;
581 }
582
583 DEFUN ("char-before", Fchar_before, Schar_before, 1, 1, 0,
584 "Return character in current buffer preceding position POS.\n\
585 POS is an integer or a buffer pointer.\n\
586 If POS is out of range, the value is nil.\n\
587 If `enable-multibyte-characters' is nil or POS is not at character boundary,\n\
588 multi-byte form is ignored, and only one byte preceding POS\n\
589 is returned as a character.")
590 (pos)
591 Lisp_Object pos;
592 {
593 register Lisp_Object val;
594 register int n;
595
596 CHECK_NUMBER_COERCE_MARKER (pos, 0);
597
598 n = XINT (pos);
599 if (n <= BEGV || n > ZV) return Qnil;
600
601 if (!NILP (current_buffer->enable_multibyte_characters))
602 {
603 DEC_POS (pos);
604 XSETFASTINT (val, FETCH_CHAR (pos));
605 }
606 else
607 {
608 pos--;
609 XSETFASTINT (val, FETCH_BYTE (pos));
610 }
611 return val;
612 }
613 \f
614 DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 1, 0,
615 "Return the name under which the user logged in, as a string.\n\
616 This is based on the effective uid, not the real uid.\n\
617 Also, if the environment variable LOGNAME or USER is set,\n\
618 that determines the value of this function.\n\n\
619 If optional argument UID is an integer, return the login name of the user\n\
620 with that uid, or nil if there is no such user.")
621 (uid)
622 Lisp_Object uid;
623 {
624 struct passwd *pw;
625
626 /* Set up the user name info if we didn't do it before.
627 (That can happen if Emacs is dumpable
628 but you decide to run `temacs -l loadup' and not dump. */
629 if (INTEGERP (Vuser_login_name))
630 init_editfns ();
631
632 if (NILP (uid))
633 return Vuser_login_name;
634
635 CHECK_NUMBER (uid, 0);
636 pw = (struct passwd *) getpwuid (XINT (uid));
637 return (pw ? build_string (pw->pw_name) : Qnil);
638 }
639
640 DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
641 0, 0, 0,
642 "Return the name of the user's real uid, as a string.\n\
643 This ignores the environment variables LOGNAME and USER, so it differs from\n\
644 `user-login-name' when running under `su'.")
645 ()
646 {
647 /* Set up the user name info if we didn't do it before.
648 (That can happen if Emacs is dumpable
649 but you decide to run `temacs -l loadup' and not dump. */
650 if (INTEGERP (Vuser_login_name))
651 init_editfns ();
652 return Vuser_real_login_name;
653 }
654
655 DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
656 "Return the effective uid of Emacs, as an integer.")
657 ()
658 {
659 return make_number (geteuid ());
660 }
661
662 DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
663 "Return the real uid of Emacs, as an integer.")
664 ()
665 {
666 return make_number (getuid ());
667 }
668
669 DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 1, 0,
670 "Return the full name of the user logged in, as a string.\n\
671 If optional argument UID is an integer, return the full name of the user\n\
672 with that uid, or \"unknown\" if there is no such user.
673 If UID is a string, return the full name of the user with that login\n\
674 name, or \"unknown\" if no such user could be found.")
675 (uid)
676 Lisp_Object uid;
677 {
678 struct passwd *pw;
679 register char *p, *q;
680 extern char *index ();
681 Lisp_Object full;
682
683 if (NILP (uid))
684 return Vuser_full_name;
685 else if (NUMBERP (uid))
686 pw = (struct passwd *) getpwuid (XINT (uid));
687 else if (STRINGP (uid))
688 pw = (struct passwd *) getpwnam (XSTRING (uid)->data);
689 else
690 error ("Invalid UID specification");
691
692 if (!pw)
693 return Qnil;
694
695 p = (unsigned char *) USER_FULL_NAME;
696 /* Chop off everything after the first comma. */
697 q = (unsigned char *) index (p, ',');
698 full = make_string (p, q ? q - p : strlen (p));
699
700 #ifdef AMPERSAND_FULL_NAME
701 p = XSTRING (full)->data;
702 q = (unsigned char *) index (p, '&');
703 /* Substitute the login name for the &, upcasing the first character. */
704 if (q)
705 {
706 register char *r;
707 Lisp_Object login;
708
709 login = Fuser_login_name (make_number (pw->pw_uid));
710 r = (unsigned char *) alloca (strlen (p) + XSTRING (login)->size + 1);
711 bcopy (p, r, q - p);
712 r[q - p] = 0;
713 strcat (r, XSTRING (login)->data);
714 r[q - p] = UPCASE (r[q - p]);
715 strcat (r, q + 1);
716 full = build_string (r);
717 }
718 #endif /* AMPERSAND_FULL_NAME */
719
720 return full;
721 }
722
723 DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
724 "Return the name of the machine you are running on, as a string.")
725 ()
726 {
727 return Vsystem_name;
728 }
729
730 /* For the benefit of callers who don't want to include lisp.h */
731 char *
732 get_system_name ()
733 {
734 return (char *) XSTRING (Vsystem_name)->data;
735 }
736
737 DEFUN ("emacs-pid", Femacs_pid, Semacs_pid, 0, 0, 0,
738 "Return the process ID of Emacs, as an integer.")
739 ()
740 {
741 return make_number (getpid ());
742 }
743
744 DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
745 "Return the current time, as the number of seconds since 1970-01-01 00:00:00.\n\
746 The time is returned as a list of three integers. The first has the\n\
747 most significant 16 bits of the seconds, while the second has the\n\
748 least significant 16 bits. The third integer gives the microsecond\n\
749 count.\n\
750 \n\
751 The microsecond count is zero on systems that do not provide\n\
752 resolution finer than a second.")
753 ()
754 {
755 EMACS_TIME t;
756 Lisp_Object result[3];
757
758 EMACS_GET_TIME (t);
759 XSETINT (result[0], (EMACS_SECS (t) >> 16) & 0xffff);
760 XSETINT (result[1], (EMACS_SECS (t) >> 0) & 0xffff);
761 XSETINT (result[2], EMACS_USECS (t));
762
763 return Flist (3, result);
764 }
765 \f
766
767 static int
768 lisp_time_argument (specified_time, result)
769 Lisp_Object specified_time;
770 time_t *result;
771 {
772 if (NILP (specified_time))
773 return time (result) != -1;
774 else
775 {
776 Lisp_Object high, low;
777 high = Fcar (specified_time);
778 CHECK_NUMBER (high, 0);
779 low = Fcdr (specified_time);
780 if (CONSP (low))
781 low = Fcar (low);
782 CHECK_NUMBER (low, 0);
783 *result = (XINT (high) << 16) + (XINT (low) & 0xffff);
784 return *result >> 16 == XINT (high);
785 }
786 }
787
788 DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 2, 0,
789 "Use FORMAT-STRING to format the time TIME.\n\
790 TIME is specified as (HIGH LOW . IGNORED) or (HIGH . LOW), as from\n\
791 `current-time' and `file-attributes'.\n\
792 FORMAT-STRING may contain %-sequences to substitute parts of the time.\n\
793 %a is replaced by the abbreviated name of the day of week.\n\
794 %A is replaced by the full name of the day of week.\n\
795 %b is replaced by the abbreviated name of the month.\n\
796 %B is replaced by the full name of the month.\n\
797 %c stands for the preferred date/time format of the C locale.\n\
798 %d is replaced by the day of month, zero-padded.\n\
799 %D is a synonym for \"%m/%d/%y\".\n\
800 %e is replaced by the day of month, blank-padded.\n\
801 %h is a synonym for \"%b\".\n\
802 %H is replaced by the hour (00-23).\n\
803 %I is replaced by the hour (00-12).\n\
804 %j is replaced by the day of the year (001-366).\n\
805 %k is replaced by the hour (0-23), blank padded.\n\
806 %l is replaced by the hour (1-12), blank padded.\n\
807 %m is replaced by the month (01-12).\n\
808 %M is replaced by the minute (00-59).\n\
809 %n is a synonym for \"\\n\".\n\
810 %p is replaced by AM or PM, as appropriate.\n\
811 %r is a synonym for \"%I:%M:%S %p\".\n\
812 %R is a synonym for \"%H:%M\".\n\
813 %S is replaced by the second (00-60).\n\
814 %t is a synonym for \"\\t\".\n\
815 %T is a synonym for \"%H:%M:%S\".\n\
816 %U is replaced by the week of the year (00-53), first day of week is Sunday.\n\
817 %w is replaced by the day of week (0-6), Sunday is day 0.\n\
818 %W is replaced by the week of the year (00-53), first day of week is Monday.\n\
819 %x is a locale-specific synonym, which defaults to \"%D\" in the C locale.\n\
820 %X is a locale-specific synonym, which defaults to \"%T\" in the C locale.\n\
821 %y is replaced by the year without century (00-99).\n\
822 %Y is replaced by the year with century.\n\
823 %Z is replaced by the time zone abbreviation.\n\
824 \n\
825 The number of options reflects the `strftime' function.")
826 (format_string, time)
827 Lisp_Object format_string, time;
828 {
829 time_t value;
830 int size;
831
832 CHECK_STRING (format_string, 1);
833
834 if (! lisp_time_argument (time, &value))
835 error ("Invalid time specification");
836
837 /* This is probably enough. */
838 size = XSTRING (format_string)->size * 6 + 50;
839
840 while (1)
841 {
842 char *buf = (char *) alloca (size);
843 *buf = 1;
844 if (emacs_strftime (buf, size, XSTRING (format_string)->data,
845 localtime (&value))
846 || !*buf)
847 return build_string (buf);
848 /* If buffer was too small, make it bigger. */
849 size *= 2;
850 }
851 }
852
853 DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 1, 0,
854 "Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).\n\
855 The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED)\n\
856 or (HIGH . LOW), as from `current-time' and `file-attributes', or `nil'\n\
857 to use the current time. The list has the following nine members:\n\
858 SEC is an integer between 0 and 60; SEC is 60 for a leap second, which\n\
859 only some operating systems support. MINUTE is an integer between 0 and 59.\n\
860 HOUR is an integer between 0 and 23. DAY is an integer between 1 and 31.\n\
861 MONTH is an integer between 1 and 12. YEAR is an integer indicating the\n\
862 four-digit year. DOW is the day of week, an integer between 0 and 6, where\n\
863 0 is Sunday. DST is t if daylight savings time is effect, otherwise nil.\n\
864 ZONE is an integer indicating the number of seconds east of Greenwich.\n\
865 \(Note that Common Lisp has different meanings for DOW and ZONE.)")
866 (specified_time)
867 Lisp_Object specified_time;
868 {
869 time_t time_spec;
870 struct tm save_tm;
871 struct tm *decoded_time;
872 Lisp_Object list_args[9];
873
874 if (! lisp_time_argument (specified_time, &time_spec))
875 error ("Invalid time specification");
876
877 decoded_time = localtime (&time_spec);
878 XSETFASTINT (list_args[0], decoded_time->tm_sec);
879 XSETFASTINT (list_args[1], decoded_time->tm_min);
880 XSETFASTINT (list_args[2], decoded_time->tm_hour);
881 XSETFASTINT (list_args[3], decoded_time->tm_mday);
882 XSETFASTINT (list_args[4], decoded_time->tm_mon + 1);
883 XSETINT (list_args[5], decoded_time->tm_year + 1900);
884 XSETFASTINT (list_args[6], decoded_time->tm_wday);
885 list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil;
886
887 /* Make a copy, in case gmtime modifies the struct. */
888 save_tm = *decoded_time;
889 decoded_time = gmtime (&time_spec);
890 if (decoded_time == 0)
891 list_args[8] = Qnil;
892 else
893 XSETINT (list_args[8], tm_diff (&save_tm, decoded_time));
894 return Flist (9, list_args);
895 }
896
897 DEFUN ("encode-time", Fencode_time, Sencode_time, 6, MANY, 0,
898 "Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.\n\
899 This is the reverse operation of `decode-time', which see.\n\
900 ZONE defaults to the current time zone rule. This can\n\
901 be a string or t (as from `set-time-zone-rule'), or it can be a list\n\
902 \(as from `current-time-zone') or an integer (as from `decode-time')\n\
903 applied without consideration for daylight savings time.\n\
904 \n\
905 You can pass more than 7 arguments; then the first six arguments\n\
906 are used as SECOND through YEAR, and the *last* argument is used as ZONE.\n\
907 The intervening arguments are ignored.\n\
908 This feature lets (apply 'encode-time (decode-time ...)) work.\n\
909 \n\
910 Out-of-range values for SEC, MINUTE, HOUR, DAY, or MONTH are allowed;\n\
911 for example, a DAY of 0 means the day preceding the given month.\n\
912 Year numbers less than 100 are treated just like other year numbers.\n\
913 If you want them to stand for years in this century, you must do that yourself.")
914 (nargs, args)
915 int nargs;
916 register Lisp_Object *args;
917 {
918 time_t time;
919 struct tm tm;
920 Lisp_Object zone = (nargs > 6 ? args[nargs - 1] : Qnil);
921
922 CHECK_NUMBER (args[0], 0); /* second */
923 CHECK_NUMBER (args[1], 1); /* minute */
924 CHECK_NUMBER (args[2], 2); /* hour */
925 CHECK_NUMBER (args[3], 3); /* day */
926 CHECK_NUMBER (args[4], 4); /* month */
927 CHECK_NUMBER (args[5], 5); /* year */
928
929 tm.tm_sec = XINT (args[0]);
930 tm.tm_min = XINT (args[1]);
931 tm.tm_hour = XINT (args[2]);
932 tm.tm_mday = XINT (args[3]);
933 tm.tm_mon = XINT (args[4]) - 1;
934 tm.tm_year = XINT (args[5]) - 1900;
935 tm.tm_isdst = -1;
936
937 if (CONSP (zone))
938 zone = Fcar (zone);
939 if (NILP (zone))
940 time = mktime (&tm);
941 else
942 {
943 char tzbuf[100];
944 char *tzstring;
945 char **oldenv = environ, **newenv;
946
947 if (zone == Qt)
948 tzstring = "UTC0";
949 else if (STRINGP (zone))
950 tzstring = (char *) XSTRING (zone)->data;
951 else if (INTEGERP (zone))
952 {
953 int abszone = abs (XINT (zone));
954 sprintf (tzbuf, "XXX%s%d:%02d:%02d", "-" + (XINT (zone) < 0),
955 abszone / (60*60), (abszone/60) % 60, abszone % 60);
956 tzstring = tzbuf;
957 }
958 else
959 error ("Invalid time zone specification");
960
961 /* Set TZ before calling mktime; merely adjusting mktime's returned
962 value doesn't suffice, since that would mishandle leap seconds. */
963 set_time_zone_rule (tzstring);
964
965 time = mktime (&tm);
966
967 /* Restore TZ to previous value. */
968 newenv = environ;
969 environ = oldenv;
970 xfree (newenv);
971 #ifdef LOCALTIME_CACHE
972 tzset ();
973 #endif
974 }
975
976 if (time == (time_t) -1)
977 error ("Specified time is not representable");
978
979 return make_time (time);
980 }
981
982 DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
983 "Return the current time, as a human-readable string.\n\
984 Programs can use this function to decode a time,\n\
985 since the number of columns in each field is fixed.\n\
986 The format is `Sun Sep 16 01:03:52 1973'.\n\
987 If an argument is given, it specifies a time to format\n\
988 instead of the current time. The argument should have the form:\n\
989 (HIGH . LOW)\n\
990 or the form:\n\
991 (HIGH LOW . IGNORED).\n\
992 Thus, you can use times obtained from `current-time'\n\
993 and from `file-attributes'.")
994 (specified_time)
995 Lisp_Object specified_time;
996 {
997 time_t value;
998 char buf[30];
999 register char *tem;
1000
1001 if (! lisp_time_argument (specified_time, &value))
1002 value = -1;
1003 tem = (char *) ctime (&value);
1004
1005 strncpy (buf, tem, 24);
1006 buf[24] = 0;
1007
1008 return build_string (buf);
1009 }
1010
1011 #define TM_YEAR_BASE 1900
1012
1013 /* Yield A - B, measured in seconds.
1014 This function is copied from the GNU C Library. */
1015 static int
1016 tm_diff (a, b)
1017 struct tm *a, *b;
1018 {
1019 /* Compute intervening leap days correctly even if year is negative.
1020 Take care to avoid int overflow in leap day calculations,
1021 but it's OK to assume that A and B are close to each other. */
1022 int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3);
1023 int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3);
1024 int a100 = a4 / 25 - (a4 % 25 < 0);
1025 int b100 = b4 / 25 - (b4 % 25 < 0);
1026 int a400 = a100 >> 2;
1027 int b400 = b100 >> 2;
1028 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
1029 int years = a->tm_year - b->tm_year;
1030 int days = (365 * years + intervening_leap_days
1031 + (a->tm_yday - b->tm_yday));
1032 return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
1033 + (a->tm_min - b->tm_min))
1034 + (a->tm_sec - b->tm_sec));
1035 }
1036
1037 DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 1, 0,
1038 "Return the offset and name for the local time zone.\n\
1039 This returns a list of the form (OFFSET NAME).\n\
1040 OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).\n\
1041 A negative value means west of Greenwich.\n\
1042 NAME is a string giving the name of the time zone.\n\
1043 If an argument is given, it specifies when the time zone offset is determined\n\
1044 instead of using the current time. The argument should have the form:\n\
1045 (HIGH . LOW)\n\
1046 or the form:\n\
1047 (HIGH LOW . IGNORED).\n\
1048 Thus, you can use times obtained from `current-time'\n\
1049 and from `file-attributes'.\n\
1050 \n\
1051 Some operating systems cannot provide all this information to Emacs;\n\
1052 in this case, `current-time-zone' returns a list containing nil for\n\
1053 the data it can't find.")
1054 (specified_time)
1055 Lisp_Object specified_time;
1056 {
1057 time_t value;
1058 struct tm *t;
1059
1060 if (lisp_time_argument (specified_time, &value)
1061 && (t = gmtime (&value)) != 0)
1062 {
1063 struct tm gmt;
1064 int offset;
1065 char *s, buf[6];
1066
1067 gmt = *t; /* Make a copy, in case localtime modifies *t. */
1068 t = localtime (&value);
1069 offset = tm_diff (t, &gmt);
1070 s = 0;
1071 #ifdef HAVE_TM_ZONE
1072 if (t->tm_zone)
1073 s = (char *)t->tm_zone;
1074 #else /* not HAVE_TM_ZONE */
1075 #ifdef HAVE_TZNAME
1076 if (t->tm_isdst == 0 || t->tm_isdst == 1)
1077 s = tzname[t->tm_isdst];
1078 #endif
1079 #endif /* not HAVE_TM_ZONE */
1080 if (!s)
1081 {
1082 /* No local time zone name is available; use "+-NNNN" instead. */
1083 int am = (offset < 0 ? -offset : offset) / 60;
1084 sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
1085 s = buf;
1086 }
1087 return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
1088 }
1089 else
1090 return Fmake_list (2, Qnil);
1091 }
1092
1093 /* This holds the value of `environ' produced by the previous
1094 call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule
1095 has never been called. */
1096 static char **environbuf;
1097
1098 DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
1099 "Set the local time zone using TZ, a string specifying a time zone rule.\n\
1100 If TZ is nil, use implementation-defined default time zone information.\n\
1101 If TZ is t, use Universal Time.")
1102 (tz)
1103 Lisp_Object tz;
1104 {
1105 char *tzstring;
1106
1107 if (NILP (tz))
1108 tzstring = 0;
1109 else if (tz == Qt)
1110 tzstring = "UTC0";
1111 else
1112 {
1113 CHECK_STRING (tz, 0);
1114 tzstring = (char *) XSTRING (tz)->data;
1115 }
1116
1117 set_time_zone_rule (tzstring);
1118 if (environbuf)
1119 free (environbuf);
1120 environbuf = environ;
1121
1122 return Qnil;
1123 }
1124
1125 #ifdef LOCALTIME_CACHE
1126
1127 /* These two values are known to load tz files in buggy implementations,
1128 i.e. Solaris 1 executables running under either Solaris 1 or Solaris 2.
1129 Their values shouldn't matter in non-buggy implementations.
1130 We don't use string literals for these strings,
1131 since if a string in the environment is in readonly
1132 storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
1133 See Sun bugs 1113095 and 1114114, ``Timezone routines
1134 improperly modify environment''. */
1135
1136 static char set_time_zone_rule_tz1[] = "TZ=GMT+0";
1137 static char set_time_zone_rule_tz2[] = "TZ=GMT+1";
1138
1139 #endif
1140
1141 /* Set the local time zone rule to TZSTRING.
1142 This allocates memory into `environ', which it is the caller's
1143 responsibility to free. */
1144 void
1145 set_time_zone_rule (tzstring)
1146 char *tzstring;
1147 {
1148 int envptrs;
1149 char **from, **to, **newenv;
1150
1151 /* Make the ENVIRON vector longer with room for TZSTRING. */
1152 for (from = environ; *from; from++)
1153 continue;
1154 envptrs = from - environ + 2;
1155 newenv = to = (char **) xmalloc (envptrs * sizeof (char *)
1156 + (tzstring ? strlen (tzstring) + 4 : 0));
1157
1158 /* Add TZSTRING to the end of environ, as a value for TZ. */
1159 if (tzstring)
1160 {
1161 char *t = (char *) (to + envptrs);
1162 strcpy (t, "TZ=");
1163 strcat (t, tzstring);
1164 *to++ = t;
1165 }
1166
1167 /* Copy the old environ vector elements into NEWENV,
1168 but don't copy the TZ variable.
1169 So we have only one definition of TZ, which came from TZSTRING. */
1170 for (from = environ; *from; from++)
1171 if (strncmp (*from, "TZ=", 3) != 0)
1172 *to++ = *from;
1173 *to = 0;
1174
1175 environ = newenv;
1176
1177 /* If we do have a TZSTRING, NEWENV points to the vector slot where
1178 the TZ variable is stored. If we do not have a TZSTRING,
1179 TO points to the vector slot which has the terminating null. */
1180
1181 #ifdef LOCALTIME_CACHE
1182 {
1183 /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
1184 "US/Pacific" that loads a tz file, then changes to a value like
1185 "XXX0" that does not load a tz file, and then changes back to
1186 its original value, the last change is (incorrectly) ignored.
1187 Also, if TZ changes twice in succession to values that do
1188 not load a tz file, tzset can dump core (see Sun bug#1225179).
1189 The following code works around these bugs. */
1190
1191 if (tzstring)
1192 {
1193 /* Temporarily set TZ to a value that loads a tz file
1194 and that differs from tzstring. */
1195 char *tz = *newenv;
1196 *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
1197 ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
1198 tzset ();
1199 *newenv = tz;
1200 }
1201 else
1202 {
1203 /* The implied tzstring is unknown, so temporarily set TZ to
1204 two different values that each load a tz file. */
1205 *to = set_time_zone_rule_tz1;
1206 to[1] = 0;
1207 tzset ();
1208 *to = set_time_zone_rule_tz2;
1209 tzset ();
1210 *to = 0;
1211 }
1212
1213 /* Now TZ has the desired value, and tzset can be invoked safely. */
1214 }
1215
1216 tzset ();
1217 #endif
1218 }
1219 \f
1220 /* Insert NARGS Lisp objects in the array ARGS by calling INSERT_FUNC
1221 (if a type of object is Lisp_Int) or INSERT_FROM_STRING_FUNC (if a
1222 type of object is Lisp_String). INHERIT is passed to
1223 INSERT_FROM_STRING_FUNC as the last argument. */
1224
1225 general_insert_function (insert_func, insert_from_string_func,
1226 inherit, nargs, args)
1227 int (*insert_func)(), (*insert_from_string_func)();
1228 int inherit, nargs;
1229 register Lisp_Object *args;
1230 {
1231 register int argnum;
1232 register Lisp_Object val;
1233
1234 for (argnum = 0; argnum < nargs; argnum++)
1235 {
1236 val = args[argnum];
1237 retry:
1238 if (INTEGERP (val))
1239 {
1240 char workbuf[4], *str;
1241 int len;
1242
1243 if (!NILP (current_buffer->enable_multibyte_characters))
1244 len = CHAR_STRING (XFASTINT (val), workbuf, str);
1245 else
1246 workbuf[0] = XINT (val), str = workbuf, len = 1;
1247 (*insert_func) (str, len);
1248 }
1249 else if (STRINGP (val))
1250 {
1251 (*insert_from_string_func) (val, 0, XSTRING (val)->size, inherit);
1252 }
1253 else
1254 {
1255 val = wrong_type_argument (Qchar_or_string_p, val);
1256 goto retry;
1257 }
1258 }
1259 }
1260
1261 void
1262 insert1 (arg)
1263 Lisp_Object arg;
1264 {
1265 Finsert (1, &arg);
1266 }
1267
1268
1269 /* Callers passing one argument to Finsert need not gcpro the
1270 argument "array", since the only element of the array will
1271 not be used after calling insert or insert_from_string, so
1272 we don't care if it gets trashed. */
1273
1274 DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
1275 "Insert the arguments, either strings or characters, at point.\n\
1276 Point and before-insertion-markers move forward so that it ends up\n\
1277 after the inserted text.\n\
1278 Any other markers at the point of insertion remain before the text.")
1279 (nargs, args)
1280 int nargs;
1281 register Lisp_Object *args;
1282 {
1283 general_insert_function (insert, insert_from_string, 0, nargs, args);
1284 return Qnil;
1285 }
1286
1287 DEFUN ("insert-and-inherit", Finsert_and_inherit, Sinsert_and_inherit,
1288 0, MANY, 0,
1289 "Insert the arguments at point, inheriting properties from adjoining text.\n\
1290 Point and before-insertion-markers move forward so that it ends up\n\
1291 after the inserted text.\n\
1292 Any other markers at the point of insertion remain before the text.")
1293 (nargs, args)
1294 int nargs;
1295 register Lisp_Object *args;
1296 {
1297 general_insert_function (insert_and_inherit, insert_from_string, 1,
1298 nargs, args);
1299 return Qnil;
1300 }
1301
1302 DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0,
1303 "Insert strings or characters at point, relocating markers after the text.\n\
1304 Point and before-insertion-markers move forward so that it ends up\n\
1305 after the inserted text.\n\
1306 Any other markers at the point of insertion also end up after the text.")
1307 (nargs, args)
1308 int nargs;
1309 register Lisp_Object *args;
1310 {
1311 general_insert_function (insert_before_markers,
1312 insert_from_string_before_markers, 0,
1313 nargs, args);
1314 return Qnil;
1315 }
1316
1317 DEFUN ("insert-before-markers-and-inherit", Finsert_and_inherit_before_markers,
1318 Sinsert_and_inherit_before_markers, 0, MANY, 0,
1319 "Insert text at point, relocating markers and inheriting properties.\n\
1320 Point moves forward so that it ends up after the inserted text.\n\
1321 Any other markers at the point of insertion also end up after the text.")
1322 (nargs, args)
1323 int nargs;
1324 register Lisp_Object *args;
1325 {
1326 general_insert_function (insert_before_markers_and_inherit,
1327 insert_from_string_before_markers, 1,
1328 nargs, args);
1329 return Qnil;
1330 }
1331 \f
1332 DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 3, 0,
1333 "Insert COUNT (second arg) copies of CHARACTER (first arg).\n\
1334 Point and before-insertion-markers are affected as in the function `insert'.\n\
1335 Both arguments are required.\n\
1336 The optional third arg INHERIT, if non-nil, says to inherit text properties\n\
1337 from adjoining text, if those properties are sticky.")
1338 (character, count, inherit)
1339 Lisp_Object character, count, inherit;
1340 {
1341 register unsigned char *string;
1342 register int strlen;
1343 register int i, n;
1344 int len;
1345 unsigned char workbuf[4], *str;
1346
1347 CHECK_NUMBER (character, 0);
1348 CHECK_NUMBER (count, 1);
1349
1350 if (!NILP (current_buffer->enable_multibyte_characters))
1351 len = CHAR_STRING (XFASTINT (character), workbuf, str);
1352 else
1353 workbuf[0] = XFASTINT (character), str = workbuf, len = 1;
1354 n = XINT (count) * len;
1355 if (n <= 0)
1356 return Qnil;
1357 strlen = min (n, 256 * len);
1358 string = (unsigned char *) alloca (strlen);
1359 for (i = 0; i < strlen; i++)
1360 string[i] = str[i % len];
1361 while (n >= strlen)
1362 {
1363 if (!NILP (inherit))
1364 insert_and_inherit (string, strlen);
1365 else
1366 insert (string, strlen);
1367 n -= strlen;
1368 }
1369 if (n > 0)
1370 {
1371 if (!NILP (inherit))
1372 insert_and_inherit (string, n);
1373 else
1374 insert (string, n);
1375 }
1376 return Qnil;
1377 }
1378
1379 \f
1380 /* Making strings from buffer contents. */
1381
1382 /* Return a Lisp_String containing the text of the current buffer from
1383 START to END. If text properties are in use and the current buffer
1384 has properties in the range specified, the resulting string will also
1385 have them, if PROPS is nonzero.
1386
1387 We don't want to use plain old make_string here, because it calls
1388 make_uninit_string, which can cause the buffer arena to be
1389 compacted. make_string has no way of knowing that the data has
1390 been moved, and thus copies the wrong data into the string. This
1391 doesn't effect most of the other users of make_string, so it should
1392 be left as is. But we should use this function when conjuring
1393 buffer substrings. */
1394
1395 Lisp_Object
1396 make_buffer_string (start, end, props)
1397 int start, end;
1398 int props;
1399 {
1400 Lisp_Object result, tem, tem1;
1401
1402 if (start < GPT && GPT < end)
1403 move_gap (start);
1404
1405 result = make_uninit_string (end - start);
1406 bcopy (POS_ADDR (start), XSTRING (result)->data, end - start);
1407
1408 /* If desired, update and copy the text properties. */
1409 #ifdef USE_TEXT_PROPERTIES
1410 if (props)
1411 {
1412 update_buffer_properties (start, end);
1413
1414 tem = Fnext_property_change (make_number (start), Qnil, make_number (end));
1415 tem1 = Ftext_properties_at (make_number (start), Qnil);
1416
1417 if (XINT (tem) != end || !NILP (tem1))
1418 copy_intervals_to_string (result, current_buffer, start, end - start);
1419 }
1420 #endif
1421
1422 return result;
1423 }
1424
1425 /* Call Vbuffer_access_fontify_functions for the range START ... END
1426 in the current buffer, if necessary. */
1427
1428 static void
1429 update_buffer_properties (start, end)
1430 int start, end;
1431 {
1432 #ifdef USE_TEXT_PROPERTIES
1433 /* If this buffer has some access functions,
1434 call them, specifying the range of the buffer being accessed. */
1435 if (!NILP (Vbuffer_access_fontify_functions))
1436 {
1437 Lisp_Object args[3];
1438 Lisp_Object tem;
1439
1440 args[0] = Qbuffer_access_fontify_functions;
1441 XSETINT (args[1], start);
1442 XSETINT (args[2], end);
1443
1444 /* But don't call them if we can tell that the work
1445 has already been done. */
1446 if (!NILP (Vbuffer_access_fontified_property))
1447 {
1448 tem = Ftext_property_any (args[1], args[2],
1449 Vbuffer_access_fontified_property,
1450 Qnil, Qnil);
1451 if (! NILP (tem))
1452 Frun_hook_with_args (3, args);
1453 }
1454 else
1455 Frun_hook_with_args (3, args);
1456 }
1457 #endif
1458 }
1459
1460 DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
1461 "Return the contents of part of the current buffer as a string.\n\
1462 The two arguments START and END are character positions;\n\
1463 they can be in either order.")
1464 (start, end)
1465 Lisp_Object start, end;
1466 {
1467 register int b, e;
1468
1469 validate_region (&start, &end);
1470 b = XINT (start);
1471 e = XINT (end);
1472
1473 return make_buffer_string (b, e, 1);
1474 }
1475
1476 DEFUN ("buffer-substring-no-properties", Fbuffer_substring_no_properties,
1477 Sbuffer_substring_no_properties, 2, 2, 0,
1478 "Return the characters of part of the buffer, without the text properties.\n\
1479 The two arguments START and END are character positions;\n\
1480 they can be in either order.")
1481 (start, end)
1482 Lisp_Object start, end;
1483 {
1484 register int b, e;
1485
1486 validate_region (&start, &end);
1487 b = XINT (start);
1488 e = XINT (end);
1489
1490 return make_buffer_string (b, e, 0);
1491 }
1492
1493 DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
1494 "Return the contents of the current buffer as a string.\n\
1495 If narrowing is in effect, this function returns only the visible part\n\
1496 of the buffer.")
1497 ()
1498 {
1499 return make_buffer_string (BEGV, ZV, 1);
1500 }
1501
1502 DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
1503 1, 3, 0,
1504 "Insert before point a substring of the contents of buffer BUFFER.\n\
1505 BUFFER may be a buffer or a buffer name.\n\
1506 Arguments START and END are character numbers specifying the substring.\n\
1507 They default to the beginning and the end of BUFFER.")
1508 (buf, start, end)
1509 Lisp_Object buf, start, end;
1510 {
1511 register int b, e, temp;
1512 register struct buffer *bp, *obuf;
1513 Lisp_Object buffer;
1514
1515 buffer = Fget_buffer (buf);
1516 if (NILP (buffer))
1517 nsberror (buf);
1518 bp = XBUFFER (buffer);
1519 if (NILP (bp->name))
1520 error ("Selecting deleted buffer");
1521
1522 if (NILP (start))
1523 b = BUF_BEGV (bp);
1524 else
1525 {
1526 CHECK_NUMBER_COERCE_MARKER (start, 0);
1527 b = XINT (start);
1528 }
1529 if (NILP (end))
1530 e = BUF_ZV (bp);
1531 else
1532 {
1533 CHECK_NUMBER_COERCE_MARKER (end, 1);
1534 e = XINT (end);
1535 }
1536
1537 if (b > e)
1538 temp = b, b = e, e = temp;
1539
1540 if (!(BUF_BEGV (bp) <= b && e <= BUF_ZV (bp)))
1541 args_out_of_range (start, end);
1542
1543 obuf = current_buffer;
1544 set_buffer_internal_1 (bp);
1545 update_buffer_properties (b, e);
1546 set_buffer_internal_1 (obuf);
1547
1548 insert_from_buffer (bp, b, e - b, 0);
1549 return Qnil;
1550 }
1551
1552 DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings,
1553 6, 6, 0,
1554 "Compare two substrings of two buffers; return result as number.\n\
1555 the value is -N if first string is less after N-1 chars,\n\
1556 +N if first string is greater after N-1 chars, or 0 if strings match.\n\
1557 Each substring is represented as three arguments: BUFFER, START and END.\n\
1558 That makes six args in all, three for each substring.\n\n\
1559 The value of `case-fold-search' in the current buffer\n\
1560 determines whether case is significant or ignored.")
1561 (buffer1, start1, end1, buffer2, start2, end2)
1562 Lisp_Object buffer1, start1, end1, buffer2, start2, end2;
1563 {
1564 register int begp1, endp1, begp2, endp2, temp, len1, len2, length, i;
1565 register struct buffer *bp1, *bp2;
1566 register Lisp_Object *trt
1567 = (!NILP (current_buffer->case_fold_search)
1568 ? XCHAR_TABLE (current_buffer->case_canon_table)->contents : 0);
1569
1570 /* Find the first buffer and its substring. */
1571
1572 if (NILP (buffer1))
1573 bp1 = current_buffer;
1574 else
1575 {
1576 Lisp_Object buf1;
1577 buf1 = Fget_buffer (buffer1);
1578 if (NILP (buf1))
1579 nsberror (buffer1);
1580 bp1 = XBUFFER (buf1);
1581 if (NILP (bp1->name))
1582 error ("Selecting deleted buffer");
1583 }
1584
1585 if (NILP (start1))
1586 begp1 = BUF_BEGV (bp1);
1587 else
1588 {
1589 CHECK_NUMBER_COERCE_MARKER (start1, 1);
1590 begp1 = XINT (start1);
1591 }
1592 if (NILP (end1))
1593 endp1 = BUF_ZV (bp1);
1594 else
1595 {
1596 CHECK_NUMBER_COERCE_MARKER (end1, 2);
1597 endp1 = XINT (end1);
1598 }
1599
1600 if (begp1 > endp1)
1601 temp = begp1, begp1 = endp1, endp1 = temp;
1602
1603 if (!(BUF_BEGV (bp1) <= begp1
1604 && begp1 <= endp1
1605 && endp1 <= BUF_ZV (bp1)))
1606 args_out_of_range (start1, end1);
1607
1608 /* Likewise for second substring. */
1609
1610 if (NILP (buffer2))
1611 bp2 = current_buffer;
1612 else
1613 {
1614 Lisp_Object buf2;
1615 buf2 = Fget_buffer (buffer2);
1616 if (NILP (buf2))
1617 nsberror (buffer2);
1618 bp2 = XBUFFER (buf2);
1619 if (NILP (bp2->name))
1620 error ("Selecting deleted buffer");
1621 }
1622
1623 if (NILP (start2))
1624 begp2 = BUF_BEGV (bp2);
1625 else
1626 {
1627 CHECK_NUMBER_COERCE_MARKER (start2, 4);
1628 begp2 = XINT (start2);
1629 }
1630 if (NILP (end2))
1631 endp2 = BUF_ZV (bp2);
1632 else
1633 {
1634 CHECK_NUMBER_COERCE_MARKER (end2, 5);
1635 endp2 = XINT (end2);
1636 }
1637
1638 if (begp2 > endp2)
1639 temp = begp2, begp2 = endp2, endp2 = temp;
1640
1641 if (!(BUF_BEGV (bp2) <= begp2
1642 && begp2 <= endp2
1643 && endp2 <= BUF_ZV (bp2)))
1644 args_out_of_range (start2, end2);
1645
1646 len1 = endp1 - begp1;
1647 len2 = endp2 - begp2;
1648 length = len1;
1649 if (len2 < length)
1650 length = len2;
1651
1652 for (i = 0; i < length; i++)
1653 {
1654 int c1 = *BUF_CHAR_ADDRESS (bp1, begp1 + i);
1655 int c2 = *BUF_CHAR_ADDRESS (bp2, begp2 + i);
1656 if (trt)
1657 {
1658 c1 = trt[c1];
1659 c2 = trt[c2];
1660 }
1661 if (c1 < c2)
1662 return make_number (- 1 - i);
1663 if (c1 > c2)
1664 return make_number (i + 1);
1665 }
1666
1667 /* The strings match as far as they go.
1668 If one is shorter, that one is less. */
1669 if (length < len1)
1670 return make_number (length + 1);
1671 else if (length < len2)
1672 return make_number (- length - 1);
1673
1674 /* Same length too => they are equal. */
1675 return make_number (0);
1676 }
1677 \f
1678 static Lisp_Object
1679 subst_char_in_region_unwind (arg)
1680 Lisp_Object arg;
1681 {
1682 return current_buffer->undo_list = arg;
1683 }
1684
1685 static Lisp_Object
1686 subst_char_in_region_unwind_1 (arg)
1687 Lisp_Object arg;
1688 {
1689 return current_buffer->filename = arg;
1690 }
1691
1692 DEFUN ("subst-char-in-region", Fsubst_char_in_region,
1693 Ssubst_char_in_region, 4, 5, 0,
1694 "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\
1695 If optional arg NOUNDO is non-nil, don't record this change for undo\n\
1696 and don't mark the buffer as really changed.\n\
1697 Both characters must have the same length of multi-byte form.")
1698 (start, end, fromchar, tochar, noundo)
1699 Lisp_Object start, end, fromchar, tochar, noundo;
1700 {
1701 register int pos, stop, i, len;
1702 int changed = 0;
1703 unsigned char fromwork[4], *fromstr, towork[4], *tostr, *p;
1704 int count = specpdl_ptr - specpdl;
1705
1706 validate_region (&start, &end);
1707 CHECK_NUMBER (fromchar, 2);
1708 CHECK_NUMBER (tochar, 3);
1709
1710 if (! NILP (current_buffer->enable_multibyte_characters))
1711 {
1712 len = CHAR_STRING (XFASTINT (fromchar), fromwork, fromstr);
1713 if (CHAR_STRING (XFASTINT (tochar), towork, tostr) != len)
1714 error ("Characters in subst-char-in-region have different byte-lengths");
1715 }
1716 else
1717 {
1718 len = 1;
1719 fromwork[0] = XFASTINT (fromchar), fromstr = fromwork;
1720 towork[0] = XFASTINT (tochar), tostr = towork;
1721 }
1722
1723 pos = XINT (start);
1724 stop = XINT (end);
1725
1726 /* If we don't want undo, turn off putting stuff on the list.
1727 That's faster than getting rid of things,
1728 and it prevents even the entry for a first change.
1729 Also inhibit locking the file. */
1730 if (!NILP (noundo))
1731 {
1732 record_unwind_protect (subst_char_in_region_unwind,
1733 current_buffer->undo_list);
1734 current_buffer->undo_list = Qt;
1735 /* Don't do file-locking. */
1736 record_unwind_protect (subst_char_in_region_unwind_1,
1737 current_buffer->filename);
1738 current_buffer->filename = Qnil;
1739 }
1740
1741 if (pos < GPT)
1742 stop = min(stop, GPT);
1743 p = POS_ADDR (pos);
1744 while (1)
1745 {
1746 if (pos >= stop)
1747 {
1748 if (pos >= XINT (end)) break;
1749 stop = XINT (end);
1750 p = POS_ADDR (pos);
1751 }
1752 if (p[0] == fromstr[0]
1753 && (len == 1
1754 || (p[1] == fromstr[1]
1755 && (len == 2 || (p[2] == fromstr[2]
1756 && (len == 3 || p[3] == fromstr[3]))))))
1757 {
1758 if (! changed)
1759 {
1760 modify_region (current_buffer, XINT (start), XINT (end));
1761
1762 if (! NILP (noundo))
1763 {
1764 if (MODIFF - 1 == SAVE_MODIFF)
1765 SAVE_MODIFF++;
1766 if (MODIFF - 1 == current_buffer->auto_save_modified)
1767 current_buffer->auto_save_modified++;
1768 }
1769
1770 changed = 1;
1771 }
1772
1773 if (NILP (noundo))
1774 record_change (pos, len);
1775 for (i = 0; i < len; i++) *p++ = tostr[i];
1776 pos += len;
1777 }
1778 else
1779 pos++, p++;
1780 }
1781
1782 if (changed)
1783 signal_after_change (XINT (start),
1784 stop - XINT (start), stop - XINT (start));
1785
1786 unbind_to (count, Qnil);
1787 return Qnil;
1788 }
1789
1790 DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0,
1791 "From START to END, translate characters according to TABLE.\n\
1792 TABLE is a string; the Nth character in it is the mapping\n\
1793 for the character with code N. Returns the number of characters changed.")
1794 (start, end, table)
1795 Lisp_Object start;
1796 Lisp_Object end;
1797 register Lisp_Object table;
1798 {
1799 register int pos, stop; /* Limits of the region. */
1800 register unsigned char *tt; /* Trans table. */
1801 register int oc; /* Old character. */
1802 register int nc; /* New character. */
1803 int cnt; /* Number of changes made. */
1804 Lisp_Object z; /* Return. */
1805 int size; /* Size of translate table. */
1806
1807 validate_region (&start, &end);
1808 CHECK_STRING (table, 2);
1809
1810 size = XSTRING (table)->size;
1811 tt = XSTRING (table)->data;
1812
1813 pos = XINT (start);
1814 stop = XINT (end);
1815 modify_region (current_buffer, pos, stop);
1816
1817 cnt = 0;
1818 for (; pos < stop; ++pos)
1819 {
1820 oc = FETCH_BYTE (pos);
1821 if (oc < size)
1822 {
1823 nc = tt[oc];
1824 if (nc != oc)
1825 {
1826 record_change (pos, 1);
1827 *(POS_ADDR (pos)) = nc;
1828 signal_after_change (pos, 1, 1);
1829 ++cnt;
1830 }
1831 }
1832 }
1833
1834 XSETFASTINT (z, cnt);
1835 return (z);
1836 }
1837
1838 DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
1839 "Delete the text between point and mark.\n\
1840 When called from a program, expects two arguments,\n\
1841 positions (integers or markers) specifying the stretch to be deleted.")
1842 (start, end)
1843 Lisp_Object start, end;
1844 {
1845 validate_region (&start, &end);
1846 del_range (XINT (start), XINT (end));
1847 return Qnil;
1848 }
1849 \f
1850 DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
1851 "Remove restrictions (narrowing) from current buffer.\n\
1852 This allows the buffer's full text to be seen and edited.")
1853 ()
1854 {
1855 BEGV = BEG;
1856 SET_BUF_ZV (current_buffer, Z);
1857 current_buffer->clip_changed = 1;
1858 /* Changing the buffer bounds invalidates any recorded current column. */
1859 invalidate_current_column ();
1860 return Qnil;
1861 }
1862
1863 DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
1864 "Restrict editing in this buffer to the current region.\n\
1865 The rest of the text becomes temporarily invisible and untouchable\n\
1866 but is not deleted; if you save the buffer in a file, the invisible\n\
1867 text is included in the file. \\[widen] makes all visible again.\n\
1868 See also `save-restriction'.\n\
1869 \n\
1870 When calling from a program, pass two arguments; positions (integers\n\
1871 or markers) bounding the text that should remain visible.")
1872 (start, end)
1873 register Lisp_Object start, end;
1874 {
1875 CHECK_NUMBER_COERCE_MARKER (start, 0);
1876 CHECK_NUMBER_COERCE_MARKER (end, 1);
1877
1878 if (XINT (start) > XINT (end))
1879 {
1880 Lisp_Object tem;
1881 tem = start; start = end; end = tem;
1882 }
1883
1884 if (!(BEG <= XINT (start) && XINT (start) <= XINT (end) && XINT (end) <= Z))
1885 args_out_of_range (start, end);
1886
1887 BEGV = XFASTINT (start);
1888 SET_BUF_ZV (current_buffer, XFASTINT (end));
1889 if (PT < XFASTINT (start))
1890 SET_PT (XFASTINT (start));
1891 if (PT > XFASTINT (end))
1892 SET_PT (XFASTINT (end));
1893 current_buffer->clip_changed = 1;
1894 /* Changing the buffer bounds invalidates any recorded current column. */
1895 invalidate_current_column ();
1896 return Qnil;
1897 }
1898
1899 Lisp_Object
1900 save_restriction_save ()
1901 {
1902 register Lisp_Object bottom, top;
1903 /* Note: I tried using markers here, but it does not win
1904 because insertion at the end of the saved region
1905 does not advance mh and is considered "outside" the saved region. */
1906 XSETFASTINT (bottom, BEGV - BEG);
1907 XSETFASTINT (top, Z - ZV);
1908
1909 return Fcons (Fcurrent_buffer (), Fcons (bottom, top));
1910 }
1911
1912 Lisp_Object
1913 save_restriction_restore (data)
1914 Lisp_Object data;
1915 {
1916 register struct buffer *buf;
1917 register int newhead, newtail;
1918 register Lisp_Object tem;
1919
1920 buf = XBUFFER (XCONS (data)->car);
1921
1922 data = XCONS (data)->cdr;
1923
1924 tem = XCONS (data)->car;
1925 newhead = XINT (tem);
1926 tem = XCONS (data)->cdr;
1927 newtail = XINT (tem);
1928 if (newhead + newtail > BUF_Z (buf) - BUF_BEG (buf))
1929 {
1930 newhead = 0;
1931 newtail = 0;
1932 }
1933 BUF_BEGV (buf) = BUF_BEG (buf) + newhead;
1934 SET_BUF_ZV (buf, BUF_Z (buf) - newtail);
1935 current_buffer->clip_changed = 1;
1936
1937 /* If point is outside the new visible range, move it inside. */
1938 SET_BUF_PT (buf,
1939 clip_to_bounds (BUF_BEGV (buf), BUF_PT (buf), BUF_ZV (buf)));
1940
1941 return Qnil;
1942 }
1943
1944 DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
1945 "Execute BODY, saving and restoring current buffer's restrictions.\n\
1946 The buffer's restrictions make parts of the beginning and end invisible.\n\
1947 \(They are set up with `narrow-to-region' and eliminated with `widen'.)\n\
1948 This special form, `save-restriction', saves the current buffer's restrictions\n\
1949 when it is entered, and restores them when it is exited.\n\
1950 So any `narrow-to-region' within BODY lasts only until the end of the form.\n\
1951 The old restrictions settings are restored\n\
1952 even in case of abnormal exit (throw or error).\n\
1953 \n\
1954 The value returned is the value of the last form in BODY.\n\
1955 \n\
1956 `save-restriction' can get confused if, within the BODY, you widen\n\
1957 and then make changes outside the area within the saved restrictions.\n\
1958 \n\
1959 Note: if you are using both `save-excursion' and `save-restriction',\n\
1960 use `save-excursion' outermost:\n\
1961 (save-excursion (save-restriction ...))")
1962 (body)
1963 Lisp_Object body;
1964 {
1965 register Lisp_Object val;
1966 int count = specpdl_ptr - specpdl;
1967
1968 record_unwind_protect (save_restriction_restore, save_restriction_save ());
1969 val = Fprogn (body);
1970 return unbind_to (count, val);
1971 }
1972 \f
1973 /* Buffer for the most recent text displayed by Fmessage. */
1974 static char *message_text;
1975
1976 /* Allocated length of that buffer. */
1977 static int message_length;
1978
1979 DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
1980 "Print a one-line message at the bottom of the screen.\n\
1981 The first argument is a format control string, and the rest are data\n\
1982 to be formatted under control of the string. See `format' for details.\n\
1983 \n\
1984 If the first argument is nil, clear any existing message; let the\n\
1985 minibuffer contents show.")
1986 (nargs, args)
1987 int nargs;
1988 Lisp_Object *args;
1989 {
1990 if (NILP (args[0]))
1991 {
1992 message (0);
1993 return Qnil;
1994 }
1995 else
1996 {
1997 register Lisp_Object val;
1998 val = Fformat (nargs, args);
1999 /* Copy the data so that it won't move when we GC. */
2000 if (! message_text)
2001 {
2002 message_text = (char *)xmalloc (80);
2003 message_length = 80;
2004 }
2005 if (XSTRING (val)->size > message_length)
2006 {
2007 message_length = XSTRING (val)->size;
2008 message_text = (char *)xrealloc (message_text, message_length);
2009 }
2010 bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size);
2011 message2 (message_text, XSTRING (val)->size);
2012 return val;
2013 }
2014 }
2015
2016 DEFUN ("message-box", Fmessage_box, Smessage_box, 1, MANY, 0,
2017 "Display a message, in a dialog box if possible.\n\
2018 If a dialog box is not available, use the echo area.\n\
2019 The first argument is a format control string, and the rest are data\n\
2020 to be formatted under control of the string. See `format' for details.\n\
2021 \n\
2022 If the first argument is nil, clear any existing message; let the\n\
2023 minibuffer contents show.")
2024 (nargs, args)
2025 int nargs;
2026 Lisp_Object *args;
2027 {
2028 if (NILP (args[0]))
2029 {
2030 message (0);
2031 return Qnil;
2032 }
2033 else
2034 {
2035 register Lisp_Object val;
2036 val = Fformat (nargs, args);
2037 #ifdef HAVE_MENUS
2038 {
2039 Lisp_Object pane, menu, obj;
2040 struct gcpro gcpro1;
2041 pane = Fcons (Fcons (build_string ("OK"), Qt), Qnil);
2042 GCPRO1 (pane);
2043 menu = Fcons (val, pane);
2044 obj = Fx_popup_dialog (Qt, menu);
2045 UNGCPRO;
2046 return val;
2047 }
2048 #else /* not HAVE_MENUS */
2049 /* Copy the data so that it won't move when we GC. */
2050 if (! message_text)
2051 {
2052 message_text = (char *)xmalloc (80);
2053 message_length = 80;
2054 }
2055 if (XSTRING (val)->size > message_length)
2056 {
2057 message_length = XSTRING (val)->size;
2058 message_text = (char *)xrealloc (message_text, message_length);
2059 }
2060 bcopy (XSTRING (val)->data, message_text, XSTRING (val)->size);
2061 message2 (message_text, XSTRING (val)->size);
2062 return val;
2063 #endif /* not HAVE_MENUS */
2064 }
2065 }
2066 #ifdef HAVE_MENUS
2067 extern Lisp_Object last_nonmenu_event;
2068 #endif
2069
2070 DEFUN ("message-or-box", Fmessage_or_box, Smessage_or_box, 1, MANY, 0,
2071 "Display a message in a dialog box or in the echo area.\n\
2072 If this command was invoked with the mouse, use a dialog box.\n\
2073 Otherwise, use the echo area.\n\
2074 The first argument is a format control string, and the rest are data\n\
2075 to be formatted under control of the string. See `format' for details.\n\
2076 \n\
2077 If the first argument is nil, clear any existing message; let the\n\
2078 minibuffer contents show.")
2079 (nargs, args)
2080 int nargs;
2081 Lisp_Object *args;
2082 {
2083 #ifdef HAVE_MENUS
2084 if (NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2085 return Fmessage_box (nargs, args);
2086 #endif
2087 return Fmessage (nargs, args);
2088 }
2089
2090 DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
2091 "Format a string out of a control-string and arguments.\n\
2092 The first argument is a control string.\n\
2093 The other arguments are substituted into it to make the result, a string.\n\
2094 It may contain %-sequences meaning to substitute the next argument.\n\
2095 %s means print a string argument. Actually, prints any object, with `princ'.\n\
2096 %d means print as number in decimal (%o octal, %x hex).\n\
2097 %e means print a number in exponential notation.\n\
2098 %f means print a number in decimal-point notation.\n\
2099 %g means print a number in exponential notation\n\
2100 or decimal-point notation, whichever uses fewer characters.\n\
2101 %c means print a number as a single character.\n\
2102 %S means print any object as an s-expression (using prin1).\n\
2103 The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.\n\
2104 Use %% to put a single % into the output.")
2105 (nargs, args)
2106 int nargs;
2107 register Lisp_Object *args;
2108 {
2109 register int n; /* The number of the next arg to substitute */
2110 register int total = 5; /* An estimate of the final length */
2111 char *buf;
2112 register unsigned char *format, *end;
2113 int length;
2114 extern char *index ();
2115 /* It should not be necessary to GCPRO ARGS, because
2116 the caller in the interpreter should take care of that. */
2117
2118 CHECK_STRING (args[0], 0);
2119 format = XSTRING (args[0])->data;
2120 end = format + XSTRING (args[0])->size;
2121
2122 n = 0;
2123 while (format != end)
2124 if (*format++ == '%')
2125 {
2126 int minlen;
2127
2128 /* Process a numeric arg and skip it. */
2129 minlen = atoi (format);
2130 if (minlen < 0)
2131 minlen = - minlen;
2132
2133 while ((*format >= '0' && *format <= '9')
2134 || *format == '-' || *format == ' ' || *format == '.')
2135 format++;
2136
2137 if (*format == '%')
2138 format++;
2139 else if (++n >= nargs)
2140 error ("Not enough arguments for format string");
2141 else if (*format == 'S')
2142 {
2143 /* For `S', prin1 the argument and then treat like a string. */
2144 register Lisp_Object tem;
2145 tem = Fprin1_to_string (args[n], Qnil);
2146 args[n] = tem;
2147 goto string;
2148 }
2149 else if (SYMBOLP (args[n]))
2150 {
2151 XSETSTRING (args[n], XSYMBOL (args[n])->name);
2152 goto string;
2153 }
2154 else if (STRINGP (args[n]))
2155 {
2156 string:
2157 if (*format != 's' && *format != 'S')
2158 error ("format specifier doesn't match argument type");
2159 total += XSTRING (args[n])->size;
2160 /* We have to put an arbitrary limit on minlen
2161 since otherwise it could make alloca fail. */
2162 if (minlen < XSTRING (args[n])->size + 1000)
2163 total += minlen;
2164 }
2165 /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */
2166 else if (INTEGERP (args[n]) && *format != 's')
2167 {
2168 #ifdef LISP_FLOAT_TYPE
2169 /* The following loop assumes the Lisp type indicates
2170 the proper way to pass the argument.
2171 So make sure we have a flonum if the argument should
2172 be a double. */
2173 if (*format == 'e' || *format == 'f' || *format == 'g')
2174 args[n] = Ffloat (args[n]);
2175 #endif
2176 total += 30;
2177 /* We have to put an arbitrary limit on minlen
2178 since otherwise it could make alloca fail. */
2179 if (minlen < 1000)
2180 total += minlen;
2181 }
2182 #ifdef LISP_FLOAT_TYPE
2183 else if (FLOATP (args[n]) && *format != 's')
2184 {
2185 if (! (*format == 'e' || *format == 'f' || *format == 'g'))
2186 args[n] = Ftruncate (args[n]);
2187 total += 30;
2188 /* We have to put an arbitrary limit on minlen
2189 since otherwise it could make alloca fail. */
2190 if (minlen < 1000)
2191 total += minlen;
2192 }
2193 #endif
2194 else
2195 {
2196 /* Anything but a string, convert to a string using princ. */
2197 register Lisp_Object tem;
2198 tem = Fprin1_to_string (args[n], Qt);
2199 args[n] = tem;
2200 goto string;
2201 }
2202 }
2203
2204 {
2205 register int nstrings = n + 1;
2206
2207 /* Allocate twice as many strings as we have %-escapes; floats occupy
2208 two slots, and we're not sure how many of those we have. */
2209 register unsigned char **strings
2210 = (unsigned char **) alloca (2 * nstrings * sizeof (unsigned char *));
2211 int i;
2212
2213 i = 0;
2214 for (n = 0; n < nstrings; n++)
2215 {
2216 if (n >= nargs)
2217 strings[i++] = (unsigned char *) "";
2218 else if (INTEGERP (args[n]))
2219 /* We checked above that the corresponding format effector
2220 isn't %s, which would cause MPV. */
2221 strings[i++] = (unsigned char *) XINT (args[n]);
2222 #ifdef LISP_FLOAT_TYPE
2223 else if (FLOATP (args[n]))
2224 {
2225 union { double d; char *half[2]; } u;
2226
2227 u.d = XFLOAT (args[n])->data;
2228 strings[i++] = (unsigned char *) u.half[0];
2229 strings[i++] = (unsigned char *) u.half[1];
2230 }
2231 #endif
2232 else if (i == 0)
2233 /* The first string is treated differently
2234 because it is the format string. */
2235 strings[i++] = XSTRING (args[n])->data;
2236 else
2237 strings[i++] = (unsigned char *) XSTRING (args[n]);
2238 }
2239
2240 /* Make room in result for all the non-%-codes in the control string. */
2241 total += XSTRING (args[0])->size;
2242
2243 /* Format it in bigger and bigger buf's until it all fits. */
2244 while (1)
2245 {
2246 buf = (char *) alloca (total + 1);
2247 buf[total - 1] = 0;
2248
2249 length = doprnt_lisp (buf, total + 1, strings[0],
2250 end, i-1, strings + 1);
2251 if (buf[total - 1] == 0)
2252 break;
2253
2254 total *= 2;
2255 }
2256 }
2257
2258 /* UNGCPRO; */
2259 return make_string (buf, length);
2260 }
2261
2262 /* VARARGS 1 */
2263 Lisp_Object
2264 #ifdef NO_ARG_ARRAY
2265 format1 (string1, arg0, arg1, arg2, arg3, arg4)
2266 EMACS_INT arg0, arg1, arg2, arg3, arg4;
2267 #else
2268 format1 (string1)
2269 #endif
2270 char *string1;
2271 {
2272 char buf[100];
2273 #ifdef NO_ARG_ARRAY
2274 EMACS_INT args[5];
2275 args[0] = arg0;
2276 args[1] = arg1;
2277 args[2] = arg2;
2278 args[3] = arg3;
2279 args[4] = arg4;
2280 doprnt (buf, sizeof buf, string1, (char *)0, 5, args);
2281 #else
2282 doprnt (buf, sizeof buf, string1, (char *)0, 5, &string1 + 1);
2283 #endif
2284 return build_string (buf);
2285 }
2286 \f
2287 DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
2288 "Return t if two characters match, optionally ignoring case.\n\
2289 Both arguments must be characters (i.e. integers).\n\
2290 Case is ignored if `case-fold-search' is non-nil in the current buffer.")
2291 (c1, c2)
2292 register Lisp_Object c1, c2;
2293 {
2294 Lisp_Object *downcase = DOWNCASE_TABLE;
2295 CHECK_NUMBER (c1, 0);
2296 CHECK_NUMBER (c2, 1);
2297
2298 if ((!NILP (current_buffer->case_fold_search)
2299 && SINGLE_BYTE_CHAR_P (c1) /* For the moment, downcase table is */
2300 && SINGLE_BYTE_CHAR_P (c2) /* implemented only for ASCII characters. */
2301 )
2302 ? ((XINT (downcase[0xff & XFASTINT (c1)])
2303 == XINT (downcase[0xff & XFASTINT (c2)]))
2304 && (XFASTINT (c1) & ~0xff) == (XFASTINT (c2) & ~0xff))
2305 : XINT (c1) == XINT (c2))
2306 return Qt;
2307 return Qnil;
2308 }
2309 \f
2310 /* Transpose the markers in two regions of the current buffer, and
2311 adjust the ones between them if necessary (i.e.: if the regions
2312 differ in size).
2313
2314 Traverses the entire marker list of the buffer to do so, adding an
2315 appropriate amount to some, subtracting from some, and leaving the
2316 rest untouched. Most of this is copied from adjust_markers in insdel.c.
2317
2318 It's the caller's job to see that (start1 <= end1 <= start2 <= end2). */
2319
2320 void
2321 transpose_markers (start1, end1, start2, end2)
2322 register int start1, end1, start2, end2;
2323 {
2324 register int amt1, amt2, diff, mpos;
2325 register Lisp_Object marker;
2326
2327 /* Update point as if it were a marker. */
2328 if (PT < start1)
2329 ;
2330 else if (PT < end1)
2331 TEMP_SET_PT (PT + (end2 - end1));
2332 else if (PT < start2)
2333 TEMP_SET_PT (PT + (end2 - start2) - (end1 - start1));
2334 else if (PT < end2)
2335 TEMP_SET_PT (PT - (start2 - start1));
2336
2337 /* We used to adjust the endpoints here to account for the gap, but that
2338 isn't good enough. Even if we assume the caller has tried to move the
2339 gap out of our way, it might still be at start1 exactly, for example;
2340 and that places it `inside' the interval, for our purposes. The amount
2341 of adjustment is nontrivial if there's a `denormalized' marker whose
2342 position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
2343 the dirty work to Fmarker_position, below. */
2344
2345 /* The difference between the region's lengths */
2346 diff = (end2 - start2) - (end1 - start1);
2347
2348 /* For shifting each marker in a region by the length of the other
2349 * region plus the distance between the regions.
2350 */
2351 amt1 = (end2 - start2) + (start2 - end1);
2352 amt2 = (end1 - start1) + (start2 - end1);
2353
2354 for (marker = BUF_MARKERS (current_buffer); !NILP (marker);
2355 marker = XMARKER (marker)->chain)
2356 {
2357 mpos = Fmarker_position (marker);
2358 if (mpos >= start1 && mpos < end2)
2359 {
2360 if (mpos < end1)
2361 mpos += amt1;
2362 else if (mpos < start2)
2363 mpos += diff;
2364 else
2365 mpos -= amt2;
2366 if (mpos > GPT) mpos += GAP_SIZE;
2367 XMARKER (marker)->bufpos = mpos;
2368 }
2369 }
2370 }
2371
2372 DEFUN ("transpose-regions", Ftranspose_regions, Stranspose_regions, 4, 5, 0,
2373 "Transpose region START1 to END1 with START2 to END2.\n\
2374 The regions may not be overlapping, because the size of the buffer is\n\
2375 never changed in a transposition.\n\
2376 \n\
2377 Optional fifth arg LEAVE_MARKERS, if non-nil, means don't transpose\n\
2378 any markers that happen to be located in the regions.\n\
2379 \n\
2380 Transposing beyond buffer boundaries is an error.")
2381 (startr1, endr1, startr2, endr2, leave_markers)
2382 Lisp_Object startr1, endr1, startr2, endr2, leave_markers;
2383 {
2384 register int start1, end1, start2, end2,
2385 gap, len1, len_mid, len2;
2386 unsigned char *start1_addr, *start2_addr, *temp;
2387
2388 #ifdef USE_TEXT_PROPERTIES
2389 INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2;
2390 cur_intv = BUF_INTERVALS (current_buffer);
2391 #endif /* USE_TEXT_PROPERTIES */
2392
2393 validate_region (&startr1, &endr1);
2394 validate_region (&startr2, &endr2);
2395
2396 start1 = XFASTINT (startr1);
2397 end1 = XFASTINT (endr1);
2398 start2 = XFASTINT (startr2);
2399 end2 = XFASTINT (endr2);
2400 gap = GPT;
2401
2402 /* Swap the regions if they're reversed. */
2403 if (start2 < end1)
2404 {
2405 register int glumph = start1;
2406 start1 = start2;
2407 start2 = glumph;
2408 glumph = end1;
2409 end1 = end2;
2410 end2 = glumph;
2411 }
2412
2413 len1 = end1 - start1;
2414 len2 = end2 - start2;
2415
2416 if (start2 < end1)
2417 error ("transposed regions not properly ordered");
2418 else if (start1 == end1 || start2 == end2)
2419 error ("transposed region may not be of length 0");
2420
2421 /* The possibilities are:
2422 1. Adjacent (contiguous) regions, or separate but equal regions
2423 (no, really equal, in this case!), or
2424 2. Separate regions of unequal size.
2425
2426 The worst case is usually No. 2. It means that (aside from
2427 potential need for getting the gap out of the way), there also
2428 needs to be a shifting of the text between the two regions. So
2429 if they are spread far apart, we are that much slower... sigh. */
2430
2431 /* It must be pointed out that the really studly thing to do would
2432 be not to move the gap at all, but to leave it in place and work
2433 around it if necessary. This would be extremely efficient,
2434 especially considering that people are likely to do
2435 transpositions near where they are working interactively, which
2436 is exactly where the gap would be found. However, such code
2437 would be much harder to write and to read. So, if you are
2438 reading this comment and are feeling squirrely, by all means have
2439 a go! I just didn't feel like doing it, so I will simply move
2440 the gap the minimum distance to get it out of the way, and then
2441 deal with an unbroken array. */
2442
2443 /* Make sure the gap won't interfere, by moving it out of the text
2444 we will operate on. */
2445 if (start1 < gap && gap < end2)
2446 {
2447 if (gap - start1 < end2 - gap)
2448 move_gap (start1);
2449 else
2450 move_gap (end2);
2451 }
2452
2453 /* Hmmm... how about checking to see if the gap is large
2454 enough to use as the temporary storage? That would avoid an
2455 allocation... interesting. Later, don't fool with it now. */
2456
2457 /* Working without memmove, for portability (sigh), so must be
2458 careful of overlapping subsections of the array... */
2459
2460 if (end1 == start2) /* adjacent regions */
2461 {
2462 modify_region (current_buffer, start1, end2);
2463 record_change (start1, len1 + len2);
2464
2465 #ifdef USE_TEXT_PROPERTIES
2466 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
2467 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
2468 Fset_text_properties (start1, end2, Qnil, Qnil);
2469 #endif /* USE_TEXT_PROPERTIES */
2470
2471 /* First region smaller than second. */
2472 if (len1 < len2)
2473 {
2474 /* We use alloca only if it is small,
2475 because we want to avoid stack overflow. */
2476 if (len2 > 20000)
2477 temp = (unsigned char *) xmalloc (len2);
2478 else
2479 temp = (unsigned char *) alloca (len2);
2480
2481 /* Don't precompute these addresses. We have to compute them
2482 at the last minute, because the relocating allocator might
2483 have moved the buffer around during the xmalloc. */
2484 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
2485 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
2486
2487 bcopy (start2_addr, temp, len2);
2488 bcopy (start1_addr, start1_addr + len2, len1);
2489 bcopy (temp, start1_addr, len2);
2490 if (len2 > 20000)
2491 free (temp);
2492 }
2493 else
2494 /* First region not smaller than second. */
2495 {
2496 if (len1 > 20000)
2497 temp = (unsigned char *) xmalloc (len1);
2498 else
2499 temp = (unsigned char *) alloca (len1);
2500 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
2501 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
2502 bcopy (start1_addr, temp, len1);
2503 bcopy (start2_addr, start1_addr, len2);
2504 bcopy (temp, start1_addr + len2, len1);
2505 if (len1 > 20000)
2506 free (temp);
2507 }
2508 #ifdef USE_TEXT_PROPERTIES
2509 graft_intervals_into_buffer (tmp_interval1, start1 + len2,
2510 len1, current_buffer, 0);
2511 graft_intervals_into_buffer (tmp_interval2, start1,
2512 len2, current_buffer, 0);
2513 #endif /* USE_TEXT_PROPERTIES */
2514 }
2515 /* Non-adjacent regions, because end1 != start2, bleagh... */
2516 else
2517 {
2518 if (len1 == len2)
2519 /* Regions are same size, though, how nice. */
2520 {
2521 modify_region (current_buffer, start1, end1);
2522 modify_region (current_buffer, start2, end2);
2523 record_change (start1, len1);
2524 record_change (start2, len2);
2525 #ifdef USE_TEXT_PROPERTIES
2526 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
2527 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
2528 Fset_text_properties (start1, end1, Qnil, Qnil);
2529 Fset_text_properties (start2, end2, Qnil, Qnil);
2530 #endif /* USE_TEXT_PROPERTIES */
2531
2532 if (len1 > 20000)
2533 temp = (unsigned char *) xmalloc (len1);
2534 else
2535 temp = (unsigned char *) alloca (len1);
2536 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
2537 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
2538 bcopy (start1_addr, temp, len1);
2539 bcopy (start2_addr, start1_addr, len2);
2540 bcopy (temp, start2_addr, len1);
2541 if (len1 > 20000)
2542 free (temp);
2543 #ifdef USE_TEXT_PROPERTIES
2544 graft_intervals_into_buffer (tmp_interval1, start2,
2545 len1, current_buffer, 0);
2546 graft_intervals_into_buffer (tmp_interval2, start1,
2547 len2, current_buffer, 0);
2548 #endif /* USE_TEXT_PROPERTIES */
2549 }
2550
2551 else if (len1 < len2) /* Second region larger than first */
2552 /* Non-adjacent & unequal size, area between must also be shifted. */
2553 {
2554 len_mid = start2 - end1;
2555 modify_region (current_buffer, start1, end2);
2556 record_change (start1, (end2 - start1));
2557 #ifdef USE_TEXT_PROPERTIES
2558 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
2559 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
2560 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
2561 Fset_text_properties (start1, end2, Qnil, Qnil);
2562 #endif /* USE_TEXT_PROPERTIES */
2563
2564 /* holds region 2 */
2565 if (len2 > 20000)
2566 temp = (unsigned char *) xmalloc (len2);
2567 else
2568 temp = (unsigned char *) alloca (len2);
2569 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
2570 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
2571 bcopy (start2_addr, temp, len2);
2572 bcopy (start1_addr, start1_addr + len_mid + len2, len1);
2573 safe_bcopy (start1_addr + len1, start1_addr + len2, len_mid);
2574 bcopy (temp, start1_addr, len2);
2575 if (len2 > 20000)
2576 free (temp);
2577 #ifdef USE_TEXT_PROPERTIES
2578 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
2579 len1, current_buffer, 0);
2580 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
2581 len_mid, current_buffer, 0);
2582 graft_intervals_into_buffer (tmp_interval2, start1,
2583 len2, current_buffer, 0);
2584 #endif /* USE_TEXT_PROPERTIES */
2585 }
2586 else
2587 /* Second region smaller than first. */
2588 {
2589 len_mid = start2 - end1;
2590 record_change (start1, (end2 - start1));
2591 modify_region (current_buffer, start1, end2);
2592
2593 #ifdef USE_TEXT_PROPERTIES
2594 tmp_interval1 = copy_intervals (cur_intv, start1, len1);
2595 tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
2596 tmp_interval2 = copy_intervals (cur_intv, start2, len2);
2597 Fset_text_properties (start1, end2, Qnil, Qnil);
2598 #endif /* USE_TEXT_PROPERTIES */
2599
2600 /* holds region 1 */
2601 if (len1 > 20000)
2602 temp = (unsigned char *) xmalloc (len1);
2603 else
2604 temp = (unsigned char *) alloca (len1);
2605 start1_addr = BUF_CHAR_ADDRESS (current_buffer, start1);
2606 start2_addr = BUF_CHAR_ADDRESS (current_buffer, start2);
2607 bcopy (start1_addr, temp, len1);
2608 bcopy (start2_addr, start1_addr, len2);
2609 bcopy (start1_addr + len1, start1_addr + len2, len_mid);
2610 bcopy (temp, start1_addr + len2 + len_mid, len1);
2611 if (len1 > 20000)
2612 free (temp);
2613 #ifdef USE_TEXT_PROPERTIES
2614 graft_intervals_into_buffer (tmp_interval1, end2 - len1,
2615 len1, current_buffer, 0);
2616 graft_intervals_into_buffer (tmp_interval_mid, start1 + len2,
2617 len_mid, current_buffer, 0);
2618 graft_intervals_into_buffer (tmp_interval2, start1,
2619 len2, current_buffer, 0);
2620 #endif /* USE_TEXT_PROPERTIES */
2621 }
2622 }
2623
2624 /* todo: this will be slow, because for every transposition, we
2625 traverse the whole friggin marker list. Possible solutions:
2626 somehow get a list of *all* the markers across multiple
2627 transpositions and do it all in one swell phoop. Or maybe modify
2628 Emacs' marker code to keep an ordered list or tree. This might
2629 be nicer, and more beneficial in the long run, but would be a
2630 bunch of work. Plus the way they're arranged now is nice. */
2631 if (NILP (leave_markers))
2632 {
2633 transpose_markers (start1, end1, start2, end2);
2634 fix_overlays_in_range (start1, end2);
2635 }
2636
2637 return Qnil;
2638 }
2639
2640 \f
2641 void
2642 syms_of_editfns ()
2643 {
2644 environbuf = 0;
2645
2646 Qbuffer_access_fontify_functions
2647 = intern ("buffer-access-fontify-functions");
2648 staticpro (&Qbuffer_access_fontify_functions);
2649
2650 DEFVAR_LISP ("buffer-access-fontify-functions",
2651 &Vbuffer_access_fontify_functions,
2652 "List of functions called by `buffer-substring' to fontify if necessary.\n\
2653 Each function is called with two arguments which specify the range\n\
2654 of the buffer being accessed.");
2655 Vbuffer_access_fontify_functions = Qnil;
2656
2657 {
2658 Lisp_Object obuf;
2659 extern Lisp_Object Vprin1_to_string_buffer;
2660 obuf = Fcurrent_buffer ();
2661 /* Do this here, because init_buffer_once is too early--it won't work. */
2662 Fset_buffer (Vprin1_to_string_buffer);
2663 /* Make sure buffer-access-fontify-functions is nil in this buffer. */
2664 Fset (Fmake_local_variable (intern ("buffer-access-fontify-functions")),
2665 Qnil);
2666 Fset_buffer (obuf);
2667 }
2668
2669 DEFVAR_LISP ("buffer-access-fontified-property",
2670 &Vbuffer_access_fontified_property,
2671 "Property which (if non-nil) indicates text has been fontified.\n\
2672 `buffer-substring' need not call the `buffer-access-fontify-functions'\n\
2673 functions if all the text being accessed has this property.");
2674 Vbuffer_access_fontified_property = Qnil;
2675
2676 DEFVAR_LISP ("system-name", &Vsystem_name,
2677 "The name of the machine Emacs is running on.");
2678
2679 DEFVAR_LISP ("user-full-name", &Vuser_full_name,
2680 "The full name of the user logged in.");
2681
2682 DEFVAR_LISP ("user-login-name", &Vuser_login_name,
2683 "The user's name, taken from environment variables if possible.");
2684
2685 DEFVAR_LISP ("user-real-login-name", &Vuser_real_login_name,
2686 "The user's name, based upon the real uid only.");
2687
2688 defsubr (&Schar_equal);
2689 defsubr (&Sgoto_char);
2690 defsubr (&Sstring_to_char);
2691 defsubr (&Schar_to_string);
2692 defsubr (&Ssref);
2693 defsubr (&Sbuffer_substring);
2694 defsubr (&Sbuffer_substring_no_properties);
2695 defsubr (&Sbuffer_string);
2696
2697 defsubr (&Spoint_marker);
2698 defsubr (&Smark_marker);
2699 defsubr (&Spoint);
2700 defsubr (&Sregion_beginning);
2701 defsubr (&Sregion_end);
2702 /* defsubr (&Smark); */
2703 /* defsubr (&Sset_mark); */
2704 defsubr (&Ssave_excursion);
2705 defsubr (&Ssave_current_buffer);
2706
2707 defsubr (&Sbufsize);
2708 defsubr (&Spoint_max);
2709 defsubr (&Spoint_min);
2710 defsubr (&Spoint_min_marker);
2711 defsubr (&Spoint_max_marker);
2712
2713 defsubr (&Sline_beginning_position);
2714 defsubr (&Sline_end_position);
2715
2716 defsubr (&Sbobp);
2717 defsubr (&Seobp);
2718 defsubr (&Sbolp);
2719 defsubr (&Seolp);
2720 defsubr (&Sfollowing_char);
2721 defsubr (&Sprevious_char);
2722 defsubr (&Schar_after);
2723 defsubr (&Schar_before);
2724 defsubr (&Sinsert);
2725 defsubr (&Sinsert_before_markers);
2726 defsubr (&Sinsert_and_inherit);
2727 defsubr (&Sinsert_and_inherit_before_markers);
2728 defsubr (&Sinsert_char);
2729
2730 defsubr (&Suser_login_name);
2731 defsubr (&Suser_real_login_name);
2732 defsubr (&Suser_uid);
2733 defsubr (&Suser_real_uid);
2734 defsubr (&Suser_full_name);
2735 defsubr (&Semacs_pid);
2736 defsubr (&Scurrent_time);
2737 defsubr (&Sformat_time_string);
2738 defsubr (&Sdecode_time);
2739 defsubr (&Sencode_time);
2740 defsubr (&Scurrent_time_string);
2741 defsubr (&Scurrent_time_zone);
2742 defsubr (&Sset_time_zone_rule);
2743 defsubr (&Ssystem_name);
2744 defsubr (&Smessage);
2745 defsubr (&Smessage_box);
2746 defsubr (&Smessage_or_box);
2747 defsubr (&Sformat);
2748
2749 defsubr (&Sinsert_buffer_substring);
2750 defsubr (&Scompare_buffer_substrings);
2751 defsubr (&Ssubst_char_in_region);
2752 defsubr (&Stranslate_region);
2753 defsubr (&Sdelete_region);
2754 defsubr (&Swiden);
2755 defsubr (&Snarrow_to_region);
2756 defsubr (&Ssave_restriction);
2757 defsubr (&Stranspose_regions);
2758 }