*** empty log message ***
[bpt/emacs.git] / src / editfns.c
CommitLineData
35692fe0
JB
1/* Lisp functions pertaining to editing.
2 Copyright (C) 1985, 1986, 1987, 1989 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
bfb61299
JB
22
23#ifdef VMS
24#include "pwd.h"
25#else
35692fe0 26#include <pwd.h>
bfb61299
JB
27#endif
28
35692fe0
JB
29#include "lisp.h"
30#include "buffer.h"
31#include "window.h"
32
33#ifdef NEED_TIME_H
34#include <time.h>
35#else /* not NEED_TIME_H */
36#ifdef HAVE_TIMEVAL
37#include <sys/time.h>
38#endif /* HAVE_TIMEVAL */
39#endif /* not NEED_TIME_H */
40
41#define min(a, b) ((a) < (b) ? (a) : (b))
42#define max(a, b) ((a) > (b) ? (a) : (b))
43
44/* Some static data, and a function to initialize it for each run */
45
46Lisp_Object Vsystem_name;
47Lisp_Object Vuser_real_name; /* login name of current user ID */
48Lisp_Object Vuser_full_name; /* full name of current user */
49Lisp_Object Vuser_name; /* user name from USER or LOGNAME. */
50
51void
52init_editfns ()
53{
52b14ac0 54 char *user_name;
35692fe0
JB
55 register unsigned char *p, *q, *r;
56 struct passwd *pw; /* password entry for the current user */
57 extern char *index ();
58 Lisp_Object tem;
59
60 /* Set up system_name even when dumping. */
61
62 Vsystem_name = build_string (get_system_name ());
63 p = XSTRING (Vsystem_name)->data;
64 while (*p)
65 {
66 if (*p == ' ' || *p == '\t')
67 *p = '-';
68 p++;
69 }
70
71#ifndef CANNOT_DUMP
72 /* Don't bother with this on initial start when just dumping out */
73 if (!initialized)
74 return;
75#endif /* not CANNOT_DUMP */
76
77 pw = (struct passwd *) getpwuid (getuid ());
78 Vuser_real_name = build_string (pw ? pw->pw_name : "unknown");
79
52b14ac0
JB
80 /* Get the effective user name, by consulting environment variables,
81 or the effective uid if those are unset. */
82 user_name = (char *) getenv ("USER");
35692fe0 83 if (!user_name)
52b14ac0
JB
84 user_name = (char *) getenv ("LOGNAME");
85 if (!user_name)
86 {
87 pw = (struct passwd *) getpwuid (geteuid ());
88 user_name = (char *) (pw ? pw->pw_name : "unknown");
89 }
90 Vuser_name = build_string (user_name);
35692fe0 91
52b14ac0
JB
92 /* If the user name claimed in the environment vars differs from
93 the real uid, use the claimed name to find the full name. */
35692fe0 94 tem = Fstring_equal (Vuser_name, Vuser_real_name);
52b14ac0
JB
95 if (NULL (tem))
96 pw = (struct passwd *) getpwnam (XSTRING (Vuser_name)->data);
35692fe0
JB
97
98 p = (unsigned char *) (pw ? USER_FULL_NAME : "unknown");
99 q = (unsigned char *) index (p, ',');
100 Vuser_full_name = make_string (p, q ? q - p : strlen (p));
101
102#ifdef AMPERSAND_FULL_NAME
103 p = XSTRING (Vuser_full_name)->data;
104 q = (char *) index (p, '&');
105 /* Substitute the login name for the &, upcasing the first character. */
106 if (q)
107 {
108 r = (char *) alloca (strlen (p) + XSTRING (Vuser_name)->size + 1);
109 bcopy (p, r, q - p);
110 r[q - p] = 0;
52b14ac0 111 strcat (r, XSTRING (Vuser_name)->data);
35692fe0
JB
112 r[q - p] = UPCASE (r[q - p]);
113 strcat (r, q + 1);
114 Vuser_full_name = build_string (r);
115 }
116#endif /* AMPERSAND_FULL_NAME */
117}
118\f
119DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
120 "Convert arg CHAR to a one-character string containing that character.")
121 (n)
122 Lisp_Object n;
123{
124 char c;
125 CHECK_NUMBER (n, 0);
126
127 c = XINT (n);
128 return make_string (&c, 1);
129}
130
131DEFUN ("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.")
133 (str)
134 register Lisp_Object str;
135{
136 register Lisp_Object val;
137 register struct Lisp_String *p;
138 CHECK_STRING (str, 0);
139
140 p = XSTRING (str);
141 if (p->size)
142 XFASTINT (val) = ((unsigned char *) p->data)[0];
143 else
144 XFASTINT (val) = 0;
145 return val;
146}
147\f
148static Lisp_Object
149buildmark (val)
150 int val;
151{
152 register Lisp_Object mark;
153 mark = Fmake_marker ();
154 Fset_marker (mark, make_number (val), Qnil);
155 return mark;
156}
157
158DEFUN ("point", Fpoint, Spoint, 0, 0, 0,
159 "Return value of point, as an integer.\n\
160Beginning of buffer is position (point-min)")
161 ()
162{
163 Lisp_Object temp;
164 XFASTINT (temp) = point;
165 return temp;
166}
167
168DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
169 "Return value of point, as a marker object.")
170 ()
171{
172 return buildmark (point);
173}
174
175int
176clip_to_bounds (lower, num, upper)
177 int lower, num, upper;
178{
179 if (num < lower)
180 return lower;
181 else if (num > upper)
182 return upper;
183 else
184 return num;
185}
186
187DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
188 "Set point to POSITION, a number or marker.\n\
189Beginning of buffer is position (point-min), end is (point-max).")
190 (n)
191 register Lisp_Object n;
192{
193 CHECK_NUMBER_COERCE_MARKER (n, 0);
194
195 SET_PT (clip_to_bounds (BEGV, XINT (n), ZV));
196 return n;
197}
198
199static Lisp_Object
200region_limit (beginningp)
201 int beginningp;
202{
203 register Lisp_Object m;
204 m = Fmarker_position (current_buffer->mark);
205 if (NULL (m)) error ("There is no region now");
206 if ((point < XFASTINT (m)) == beginningp)
207 return (make_number (point));
208 else
209 return (m);
210}
211
212DEFUN ("region-beginning", Fregion_beginning, Sregion_beginning, 0, 0, 0,
213 "Return position of beginning of region, as an integer.")
214 ()
215{
216 return (region_limit (1));
217}
218
219DEFUN ("region-end", Fregion_end, Sregion_end, 0, 0, 0,
220 "Return position of end of region, as an integer.")
221 ()
222{
223 return (region_limit (0));
224}
225
226#if 0 /* now in lisp code */
227DEFUN ("mark", Fmark, Smark, 0, 0, 0,
228 "Return this buffer's mark value as integer, or nil if no mark.\n\
229If you are using this in an editing command, you are most likely making\n\
230a mistake; see the documentation of `set-mark'.")
231 ()
232{
233 return Fmarker_position (current_buffer->mark);
234}
235#endif /* commented out code */
236
237DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
238 "Return this buffer's mark, as a marker object.\n\
239Watch out! Moving this marker changes the mark position.\n\
240If you set the marker not to point anywhere, the buffer will have no mark.")
241 ()
242{
243 return current_buffer->mark;
244}
245
246#if 0 /* this is now in lisp code */
247DEFUN ("set-mark", Fset_mark, Sset_mark, 1, 1, 0,
248 "Set this buffer's mark to POS. Don't use this function!\n\
249That is to say, don't use this function unless you want\n\
250the user to see that the mark has moved, and you want the previous\n\
251mark position to be lost.\n\
252\n\
253Normally, when a new mark is set, the old one should go on the stack.\n\
254This is why most applications should use push-mark, not set-mark.\n\
255\n\
256Novice programmers often try to use the mark for the wrong purposes.\n\
257The mark saves a location for the user's convenience.\n\
258Most editing commands should not alter the mark.\n\
259To remember a location for internal use in the Lisp program,\n\
260store it in a Lisp variable. Example:\n\
261\n\
262 (let ((beg (point))) (forward-line 1) (delete-region beg (point))).")
263 (pos)
264 Lisp_Object pos;
265{
266 if (NULL (pos))
267 {
268 current_buffer->mark = Qnil;
269 return Qnil;
270 }
271 CHECK_NUMBER_COERCE_MARKER (pos, 0);
272
273 if (NULL (current_buffer->mark))
274 current_buffer->mark = Fmake_marker ();
275
276 Fset_marker (current_buffer->mark, pos, Qnil);
277 return pos;
278}
279#endif /* commented-out code */
280
281Lisp_Object
282save_excursion_save ()
283{
284 register int visible = XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer;
285
286 return Fcons (Fpoint_marker (),
287 Fcons (Fcopy_marker (current_buffer->mark), visible ? Qt : Qnil));
288}
289
290Lisp_Object
291save_excursion_restore (info)
292 register Lisp_Object info;
293{
294 register Lisp_Object tem;
295
296 tem = Fmarker_buffer (Fcar (info));
297 /* If buffer being returned to is now deleted, avoid error */
298 /* Otherwise could get error here while unwinding to top level
299 and crash */
300 /* In that case, Fmarker_buffer returns nil now. */
301 if (NULL (tem))
302 return Qnil;
303 Fset_buffer (tem);
304 tem = Fcar (info);
305 Fgoto_char (tem);
306 unchain_marker (tem);
307 tem = Fcar (Fcdr (info));
308 Fset_marker (current_buffer->mark, tem, Fcurrent_buffer ());
309 unchain_marker (tem);
310 tem = Fcdr (Fcdr (info));
311 if (!NULL (tem) && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
312 Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
313 return Qnil;
314}
315
316DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
317 "Save point, mark, and current buffer; execute BODY; restore those things.\n\
318Executes BODY just like `progn'.\n\
319The values of point, mark and the current buffer are restored\n\
320even in case of abnormal exit (throw or error).")
321 (args)
322 Lisp_Object args;
323{
324 register Lisp_Object val;
325 int count = specpdl_ptr - specpdl;
326
327 record_unwind_protect (save_excursion_restore, save_excursion_save ());
328
329 val = Fprogn (args);
330 return unbind_to (count, val);
331}
332\f
333DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 0, 0,
334 "Return the number of characters in the current buffer.")
335 ()
336{
337 Lisp_Object temp;
338 XFASTINT (temp) = Z - BEG;
339 return temp;
340}
341
342DEFUN ("point-min", Fpoint_min, Spoint_min, 0, 0, 0,
343 "Return the minimum permissible value of point in the current buffer.\n\
344This is 1, unless a clipping restriction is in effect.")
345 ()
346{
347 Lisp_Object temp;
348 XFASTINT (temp) = BEGV;
349 return temp;
350}
351
352DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 0, 0,
353 "Return a marker to the minimum permissible value of point in this buffer.\n\
354This is the beginning, unless a clipping restriction is in effect.")
355 ()
356{
357 return buildmark (BEGV);
358}
359
360DEFUN ("point-max", Fpoint_max, Spoint_max, 0, 0, 0,
361 "Return the maximum permissible value of point in the current buffer.\n\
362This is (1+ (buffer-size)), unless a clipping restriction is in effect,\n\
363in which case it is less.")
364 ()
365{
366 Lisp_Object temp;
367 XFASTINT (temp) = ZV;
368 return temp;
369}
370
371DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 0, 0,
372 "Return a marker to the maximum permissible value of point in this buffer.\n\
373This is (1+ (buffer-size)), unless a clipping restriction is in effect,\n\
374in which case it is less.")
375 ()
376{
377 return buildmark (ZV);
378}
379
380DEFUN ("following-char", Ffollchar, Sfollchar, 0, 0, 0,
381 "Return the character following point, as a number.")
382 ()
383{
384 Lisp_Object temp;
385 XFASTINT (temp) = FETCH_CHAR (point);
386 return temp;
387}
388
389DEFUN ("preceding-char", Fprevchar, Sprevchar, 0, 0, 0,
390 "Return the character preceding point, as a number.")
391 ()
392{
393 Lisp_Object temp;
394 if (point <= BEGV)
395 XFASTINT (temp) = 0;
396 else
397 XFASTINT (temp) = FETCH_CHAR (point - 1);
398 return temp;
399}
400
401DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0,
402 "Return T if point is at the beginning of the buffer.\n\
403If the buffer is narrowed, this means the beginning of the narrowed part.")
404 ()
405{
406 if (point == BEGV)
407 return Qt;
408 return Qnil;
409}
410
411DEFUN ("eobp", Feobp, Seobp, 0, 0, 0,
412 "Return T if point is at the end of the buffer.\n\
413If the buffer is narrowed, this means the end of the narrowed part.")
414 ()
415{
416 if (point == ZV)
417 return Qt;
418 return Qnil;
419}
420
421DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0,
422 "Return T if point is at the beginning of a line.")
423 ()
424{
425 if (point == BEGV || FETCH_CHAR (point - 1) == '\n')
426 return Qt;
427 return Qnil;
428}
429
430DEFUN ("eolp", Feolp, Seolp, 0, 0, 0,
431 "Return T if point is at the end of a line.\n\
432`End of a line' includes point being at the end of the buffer.")
433 ()
434{
435 if (point == ZV || FETCH_CHAR (point) == '\n')
436 return Qt;
437 return Qnil;
438}
439
440DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0,
441 "Return character in current buffer at position POS.\n\
442POS is an integer or a buffer pointer.\n\
443If POS is out of range, the value is nil.")
444 (pos)
445 Lisp_Object pos;
446{
447 register Lisp_Object val;
448 register int n;
449
450 CHECK_NUMBER_COERCE_MARKER (pos, 0);
451
452 n = XINT (pos);
453 if (n < BEGV || n >= ZV) return Qnil;
454
455 XFASTINT (val) = FETCH_CHAR (n);
456 return val;
457}
458\f
459DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 0, 0,
460 "Return the name under which the user logged in, as a string.\n\
461This is based on the effective uid, not the real uid.\n\
462Also, if the environment variable USER or LOGNAME is set,\n\
463that determines the value of this function.")
464 ()
465{
466 return Vuser_name;
467}
468
469DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
470 0, 0, 0,
471 "Return the name of the user's real uid, as a string.\n\
472Differs from `user-login-name' when running under `su'.")
473 ()
474{
475 return Vuser_real_name;
476}
477
478DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
479 "Return the effective uid of Emacs, as an integer.")
480 ()
481{
482 return make_number (geteuid ());
483}
484
485DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
486 "Return the real uid of Emacs, as an integer.")
487 ()
488{
489 return make_number (getuid ());
490}
491
492DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 0, 0,
493 "Return the full name of the user logged in, as a string.")
494 ()
495{
496 return Vuser_full_name;
497}
498
499DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
500 "Return the name of the machine you are running on, as a string.")
501 ()
502{
503 return Vsystem_name;
504}
505
d940e0e4
JB
506DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
507 "Return the current time, as an integer.")
508 ()
509{
510 return make_number (time(0));
511}
512\f
513
35692fe0
JB
514DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 0, 0,
515 "Return the current time, as a human-readable string.\n\
516Programs can use it too, since the number of columns in each field is fixed.\n\
517The format is `Sun Sep 16 01:03:52 1973'.\n\
518In a future Emacs version, the time zone may be added at the end,\n\
519if we can figure out a reasonably easy way to get that information.")
520 ()
521{
522 long current_time = time ((long *) 0);
523 char buf[30];
524 register char *tem = (char *) ctime (&current_time);
525
526 strncpy (buf, tem, 24);
527 buf[24] = 0;
528
529 return build_string (buf);
530}
531
532#ifdef unix
533
534DEFUN ("set-default-file-mode", Fset_default_file_mode, Sset_default_file_mode, 1, 1, "p",
535 "Set Unix `umask' value to ARGUMENT, and return old value.\n\
536The `umask' value is the default protection mode for new files.")
537 (nmask)
538 Lisp_Object nmask;
539{
540 CHECK_NUMBER (nmask, 0);
541 return make_number (umask (XINT (nmask)));
542}
543
544DEFUN ("unix-sync", Funix_sync, Sunix_sync, 0, 0, "",
545 "Tell Unix to finish all pending disk updates.")
546 ()
547{
548 sync ();
549 return Qnil;
550}
551
552#endif /* unix */
553\f
554void
555insert1 (arg)
556 Lisp_Object arg;
557{
558 Finsert (1, &arg);
559}
560
52b14ac0
JB
561
562/* Callers passing one argument to Finsert need not gcpro the
563 argument "array", since the only element of the array will
564 not be used after calling insert or insert_from_string, so
565 we don't care if it gets trashed. */
566
35692fe0
JB
567DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
568 "Insert the arguments, either strings or characters, at point.\n\
569Point moves forward so that it ends up after the inserted text.\n\
570Any other markers at the point of insertion remain before the text.")
571 (nargs, args)
572 int nargs;
573 register Lisp_Object *args;
574{
575 register int argnum;
576 register Lisp_Object tem;
577 char str[1];
35692fe0
JB
578
579 for (argnum = 0; argnum < nargs; argnum++)
580 {
581 tem = args[argnum];
582 retry:
583 if (XTYPE (tem) == Lisp_Int)
584 {
585 str[0] = XINT (tem);
586 insert (str, 1);
587 }
588 else if (XTYPE (tem) == Lisp_String)
589 {
590 insert_from_string (tem, 0, XSTRING (tem)->size);
591 }
592 else
593 {
594 tem = wrong_type_argument (Qchar_or_string_p, tem);
595 goto retry;
596 }
597 }
598
35692fe0
JB
599 return Qnil;
600}
601
602DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0,
603 "Insert strings or characters at point, relocating markers after the text.\n\
604Point moves forward so that it ends up after the inserted text.\n\
605Any other markers at the point of insertion also end up after the text.")
606 (nargs, args)
607 int nargs;
608 register Lisp_Object *args;
609{
610 register int argnum;
611 register Lisp_Object tem;
612 char str[1];
35692fe0
JB
613
614 for (argnum = 0; argnum < nargs; argnum++)
615 {
616 tem = args[argnum];
617 retry:
618 if (XTYPE (tem) == Lisp_Int)
619 {
620 str[0] = XINT (tem);
621 insert_before_markers (str, 1);
622 }
623 else if (XTYPE (tem) == Lisp_String)
624 {
625 insert_from_string_before_markers (tem, 0, XSTRING (tem)->size);
626 }
627 else
628 {
629 tem = wrong_type_argument (Qchar_or_string_p, tem);
630 goto retry;
631 }
632 }
633
35692fe0
JB
634 return Qnil;
635}
636\f
637DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 2, 0,
638 "Insert COUNT (second arg) copies of CHAR (first arg).\n\
639Point and all markers are affected as in the function `insert'.\n\
640Both arguments are required.")
641 (chr, count)
642 Lisp_Object chr, count;
643{
644 register unsigned char *string;
645 register int strlen;
646 register int i, n;
647
648 CHECK_NUMBER (chr, 0);
649 CHECK_NUMBER (count, 1);
650
651 n = XINT (count);
652 if (n <= 0)
653 return Qnil;
654 strlen = min (n, 256);
655 string = (unsigned char *) alloca (strlen);
656 for (i = 0; i < strlen; i++)
657 string[i] = XFASTINT (chr);
658 while (n >= strlen)
659 {
660 insert (string, strlen);
661 n -= strlen;
662 }
663 if (n > 0)
664 insert (string, n);
665 return Qnil;
666}
667
668\f
669/* Return a string with the contents of the current region */
670
671DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
672 "Return the contents of part of the current buffer as a string.\n\
673The two arguments START and END are character positions;\n\
674they can be in either order.")
675 (b, e)
676 Lisp_Object b, e;
677{
678 register int beg, end;
679 Lisp_Object result;
680
681 validate_region (&b, &e);
682 beg = XINT (b);
683 end = XINT (e);
684
685 if (beg < GPT && end > GPT)
686 move_gap (beg);
687
688 /* Plain old make_string calls make_uninit_string, which can cause
689 the buffer arena to be compacted. make_string has no way of
690 knowing that the data has been moved, and thus copies the wrong
691 data into the string. This doesn't effect most of the other
692 users of make_string, so it should be left as is. */
693 result = make_uninit_string (end - beg);
694 bcopy (&FETCH_CHAR (beg), XSTRING (result)->data, end - beg);
695
696 return result;
697}
698
699DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
700 "Return the contents of the current buffer as a string.")
701 ()
702{
703 if (BEGV < GPT && ZV > GPT)
704 move_gap (BEGV);
705 return make_string (BEGV_ADDR, ZV - BEGV);
706}
707
708DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
709 1, 3, 0,
710 "Insert before point a substring of the contents buffer BUFFER.\n\
711BUFFER may be a buffer or a buffer name.\n\
712Arguments START and END are character numbers specifying the substring.\n\
713They default to the beginning and the end of BUFFER.")
714 (buf, b, e)
715 Lisp_Object buf, b, e;
716{
717 register int beg, end, exch;
718 register struct buffer *bp;
719
720 buf = Fget_buffer (buf);
721 bp = XBUFFER (buf);
722
723 if (NULL (b))
724 beg = BUF_BEGV (bp);
725 else
726 {
727 CHECK_NUMBER_COERCE_MARKER (b, 0);
728 beg = XINT (b);
729 }
730 if (NULL (e))
731 end = BUF_ZV (bp);
732 else
733 {
734 CHECK_NUMBER_COERCE_MARKER (e, 1);
735 end = XINT (e);
736 }
737
738 if (beg > end)
739 exch = beg, beg = end, end = exch;
740
741 /* Move the gap or create enough gap in the current buffer. */
742
743 if (point != GPT)
744 move_gap (point);
745 if (GAP_SIZE < end - beg)
746 make_gap (end - beg - GAP_SIZE);
747
748 if (!(BUF_BEGV (bp) <= beg
749 && beg <= end
750 && end <= BUF_ZV (bp)))
751 args_out_of_range (b, e);
752
753 /* Now the actual insertion will not do any gap motion,
754 so it matters not if BUF is the current buffer. */
755 if (beg < BUF_GPT (bp))
756 {
757 insert (BUF_CHAR_ADDRESS (bp, beg), min (end, BUF_GPT (bp)) - beg);
758 beg = min (end, BUF_GPT (bp));
759 }
760 if (beg < end)
761 insert (BUF_CHAR_ADDRESS (bp, beg), end - beg);
762
763 return Qnil;
764}
765\f
766DEFUN ("subst-char-in-region", Fsubst_char_in_region,
767 Ssubst_char_in_region, 4, 5, 0,
768 "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\
769If optional arg NOUNDO is non-nil, don't record this change for undo\n\
770and don't mark the buffer as really changed.")
771 (start, end, fromchar, tochar, noundo)
772 Lisp_Object start, end, fromchar, tochar, noundo;
773{
774 register int pos, stop, look;
775
776 validate_region (&start, &end);
777 CHECK_NUMBER (fromchar, 2);
778 CHECK_NUMBER (tochar, 3);
779
780 pos = XINT (start);
781 stop = XINT (end);
782 look = XINT (fromchar);
783
784 modify_region (pos, stop);
785 if (! NULL (noundo))
786 {
787 if (MODIFF - 1 == current_buffer->save_modified)
788 current_buffer->save_modified++;
789 if (MODIFF - 1 == current_buffer->auto_save_modified)
790 current_buffer->auto_save_modified++;
791 }
792
793 while (pos < stop)
794 {
795 if (FETCH_CHAR (pos) == look)
796 {
797 if (NULL (noundo))
798 record_change (pos, 1);
799 FETCH_CHAR (pos) = XINT (tochar);
800 if (NULL (noundo))
801 signal_after_change (pos, 1, 1);
802 }
803 pos++;
804 }
805
806 return Qnil;
807}
808
809DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0,
810 "From START to END, translate characters according to TABLE.\n\
811TABLE is a string; the Nth character in it is the mapping\n\
812for the character with code N. Returns the number of characters changed.")
813 (start, end, table)
814 Lisp_Object start;
815 Lisp_Object end;
816 register Lisp_Object table;
817{
818 register int pos, stop; /* Limits of the region. */
819 register unsigned char *tt; /* Trans table. */
820 register int oc; /* Old character. */
821 register int nc; /* New character. */
822 int cnt; /* Number of changes made. */
823 Lisp_Object z; /* Return. */
824 int size; /* Size of translate table. */
825
826 validate_region (&start, &end);
827 CHECK_STRING (table, 2);
828
829 size = XSTRING (table)->size;
830 tt = XSTRING (table)->data;
831
832 pos = XINT (start);
833 stop = XINT (end);
834 modify_region (pos, stop);
835
836 cnt = 0;
837 for (; pos < stop; ++pos)
838 {
839 oc = FETCH_CHAR (pos);
840 if (oc < size)
841 {
842 nc = tt[oc];
843 if (nc != oc)
844 {
845 record_change (pos, 1);
846 FETCH_CHAR (pos) = nc;
847 signal_after_change (pos, 1, 1);
848 ++cnt;
849 }
850 }
851 }
852
853 XFASTINT (z) = cnt;
854 return (z);
855}
856
857DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
858 "Delete the text between point and mark.\n\
859When called from a program, expects two arguments,\n\
860positions (integers or markers) specifying the stretch to be deleted.")
861 (b, e)
862 Lisp_Object b, e;
863{
864 validate_region (&b, &e);
865 del_range (XINT (b), XINT (e));
866 return Qnil;
867}
868\f
869DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
870 "Remove restrictions (narrowing) from current buffer.\n\
871This allows the buffer's full text to be seen and edited.")
872 ()
873{
874 BEGV = BEG;
875 SET_BUF_ZV (current_buffer, Z);
876 clip_changed = 1;
52b14ac0
JB
877 /* Changing the buffer bounds invalidates any recorded current column. */
878 invalidate_current_column ();
35692fe0
JB
879 return Qnil;
880}
881
882DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
883 "Restrict editing in this buffer to the current region.\n\
884The rest of the text becomes temporarily invisible and untouchable\n\
885but is not deleted; if you save the buffer in a file, the invisible\n\
886text is included in the file. \\[widen] makes all visible again.\n\
887See also `save-restriction'.\n\
888\n\
889When calling from a program, pass two arguments; positions (integers\n\
890or markers) bounding the text that should remain visible.")
891 (b, e)
892 register Lisp_Object b, e;
893{
894 register int i;
895
896 CHECK_NUMBER_COERCE_MARKER (b, 0);
897 CHECK_NUMBER_COERCE_MARKER (e, 1);
898
899 if (XINT (b) > XINT (e))
900 {
901 i = XFASTINT (b);
902 b = e;
903 XFASTINT (e) = i;
904 }
905
906 if (!(BEG <= XINT (b) && XINT (b) <= XINT (e) && XINT (e) <= Z))
907 args_out_of_range (b, e);
908
909 BEGV = XFASTINT (b);
910 SET_BUF_ZV (current_buffer, XFASTINT (e));
911 if (point < XFASTINT (b))
912 SET_PT (XFASTINT (b));
913 if (point > XFASTINT (e))
914 SET_PT (XFASTINT (e));
915 clip_changed = 1;
52b14ac0
JB
916 /* Changing the buffer bounds invalidates any recorded current column. */
917 invalidate_current_column ();
35692fe0
JB
918 return Qnil;
919}
920
921Lisp_Object
922save_restriction_save ()
923{
924 register Lisp_Object bottom, top;
925 /* Note: I tried using markers here, but it does not win
926 because insertion at the end of the saved region
927 does not advance mh and is considered "outside" the saved region. */
928 XFASTINT (bottom) = BEGV - BEG;
929 XFASTINT (top) = Z - ZV;
930
931 return Fcons (Fcurrent_buffer (), Fcons (bottom, top));
932}
933
934Lisp_Object
935save_restriction_restore (data)
936 Lisp_Object data;
937{
938 register struct buffer *buf;
939 register int newhead, newtail;
940 register Lisp_Object tem;
941
942 buf = XBUFFER (XCONS (data)->car);
943
944 data = XCONS (data)->cdr;
945
946 tem = XCONS (data)->car;
947 newhead = XINT (tem);
948 tem = XCONS (data)->cdr;
949 newtail = XINT (tem);
950 if (newhead + newtail > BUF_Z (buf) - BUF_BEG (buf))
951 {
952 newhead = 0;
953 newtail = 0;
954 }
955 BUF_BEGV (buf) = BUF_BEG (buf) + newhead;
956 SET_BUF_ZV (buf, BUF_Z (buf) - newtail);
957 clip_changed = 1;
958
959 /* If point is outside the new visible range, move it inside. */
960 SET_BUF_PT (buf,
961 clip_to_bounds (BUF_BEGV (buf), BUF_PT (buf), BUF_ZV (buf)));
962
963 return Qnil;
964}
965
966DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
967 "Execute BODY, saving and restoring current buffer's restrictions.\n\
968The buffer's restrictions make parts of the beginning and end invisible.\n\
969\(They are set up with `narrow-to-region' and eliminated with `widen'.)\n\
970This special form, `save-restriction', saves the current buffer's restrictions\n\
971when it is entered, and restores them when it is exited.\n\
972So any `narrow-to-region' within BODY lasts only until the end of the form.\n\
973The old restrictions settings are restored\n\
974even in case of abnormal exit (throw or error).\n\
975\n\
976The value returned is the value of the last form in BODY.\n\
977\n\
978`save-restriction' can get confused if, within the BODY, you widen\n\
979and then make changes outside the area within the saved restrictions.\n\
980\n\
981Note: if you are using both `save-excursion' and `save-restriction',\n\
982use `save-excursion' outermost:\n\
983 (save-excursion (save-restriction ...))")
984 (body)
985 Lisp_Object body;
986{
987 register Lisp_Object val;
988 int count = specpdl_ptr - specpdl;
989
990 record_unwind_protect (save_restriction_restore, save_restriction_save ());
991 val = Fprogn (body);
992 return unbind_to (count, val);
993}
994\f
995DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
996 "Print a one-line message at the bottom of the screen.\n\
997The first argument is a control string.\n\
998It may contain %s or %d or %c to print successive following arguments.\n\
999%s means print an argument as a string, %d means print as number in decimal,\n\
1000%c means print a number as a single character.\n\
1001The argument used by %s must be a string or a symbol;\n\
1002the argument used by %d or %c must be a number.")
1003 (nargs, args)
1004 int nargs;
1005 Lisp_Object *args;
1006{
1007 register Lisp_Object val;
1008
35692fe0
JB
1009 val = Fformat (nargs, args);
1010 message ("%s", XSTRING (val)->data);
1011 return val;
1012}
1013
1014DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
1015 "Format a string out of a control-string and arguments.\n\
1016The first argument is a control string.\n\
1017The other arguments are substituted into it to make the result, a string.\n\
1018It may contain %-sequences meaning to substitute the next argument.\n\
1019%s means print a string argument. Actually, prints any object, with `princ'.\n\
1020%d means print as number in decimal (%o octal, %x hex).\n\
1021%c means print a number as a single character.\n\
1022%S means print any object as an s-expression (using prin1).\n\
52b14ac0
JB
1023 The argument used for %d, %o, %x or %c must be a number.\n\
1024Use %% to put a single % into the output.")
35692fe0
JB
1025 (nargs, args)
1026 int nargs;
1027 register Lisp_Object *args;
1028{
1029 register int n; /* The number of the next arg to substitute */
1030 register int total = 5; /* An estimate of the final length */
1031 char *buf;
1032 register unsigned char *format, *end;
1033 int length;
1034 extern char *index ();
1035 /* It should not be necessary to GCPRO ARGS, because
1036 the caller in the interpreter should take care of that. */
1037
1038 CHECK_STRING (args[0], 0);
1039 format = XSTRING (args[0])->data;
1040 end = format + XSTRING (args[0])->size;
1041
1042 n = 0;
1043 while (format != end)
1044 if (*format++ == '%')
1045 {
1046 int minlen;
1047
1048 /* Process a numeric arg and skip it. */
1049 minlen = atoi (format);
1050 if (minlen > 0)
1051 total += minlen;
1052 else
1053 total -= minlen;
1054 while ((*format >= '0' && *format <= '9')
1055 || *format == '-' || *format == ' ' || *format == '.')
1056 format++;
1057
1058 if (*format == '%')
1059 format++;
1060 else if (++n >= nargs)
1061 ;
1062 else if (*format == 'S')
1063 {
1064 /* For `S', prin1 the argument and then treat like a string. */
1065 register Lisp_Object tem;
1066 tem = Fprin1_to_string (args[n], Qnil);
1067 args[n] = tem;
1068 goto string;
1069 }
1070 else if (XTYPE (args[n]) == Lisp_Symbol)
1071 {
1072 XSET (args[n], Lisp_String, XSYMBOL (args[n])->name);
1073 goto string;
1074 }
1075 else if (XTYPE (args[n]) == Lisp_String)
1076 {
1077 string:
1078 total += XSTRING (args[n])->size;
1079 }
1080 /* Would get MPV otherwise, since Lisp_Int's `point' to low memory. */
1081 else if (XTYPE (args[n]) == Lisp_Int && *format != 's')
1082 {
1083 /* The following loop issumes the Lisp type indicates
1084 the proper way to pass the argument.
1085 So make sure we have a flonum if the argument should
1086 be a double. */
1087 if (*format == 'e' || *format == 'f' || *format == 'g')
1088 args[n] = Ffloat (args[n]);
1089 total += 10;
1090 }
1091 else if (XTYPE (args[n]) == Lisp_Float && *format != 's')
1092 {
1093 if (! (*format == 'e' || *format == 'f' || *format == 'g'))
1094 args[n] = Ftruncate (args[n]);
1095 total += 20;
1096 }
1097 else
1098 {
1099 /* Anything but a string, convert to a string using princ. */
1100 register Lisp_Object tem;
1101 tem = Fprin1_to_string (args[n], Qt);
1102 args[n] = tem;
1103 goto string;
1104 }
1105 }
1106
1107 {
1108 register int nstrings = n + 1;
1109 register unsigned char **strings
1110 = (unsigned char **) alloca (nstrings * sizeof (unsigned char *));
1111
1112 for (n = 0; n < nstrings; n++)
1113 {
1114 if (n >= nargs)
1115 strings[n] = (unsigned char *) "";
1116 else if (XTYPE (args[n]) == Lisp_Int)
1117 /* We checked above that the corresponding format effector
1118 isn't %s, which would cause MPV. */
1119 strings[n] = (unsigned char *) XINT (args[n]);
1120 else if (XTYPE (args[n]) == Lisp_Float)
1121 {
1122 union { double d; int half[2]; } u;
1123
1124 u.d = XFLOAT (args[n])->data;
1125 strings[n++] = (unsigned char *) u.half[0];
1126 strings[n] = (unsigned char *) u.half[1];
1127 }
1128 else
1129 strings[n] = XSTRING (args[n])->data;
1130 }
1131
1132 /* Format it in bigger and bigger buf's until it all fits. */
1133 while (1)
1134 {
1135 buf = (char *) alloca (total + 1);
1136 buf[total - 1] = 0;
1137
1138 length = doprnt (buf, total + 1, strings[0], end, nargs, strings + 1);
1139 if (buf[total - 1] == 0)
1140 break;
1141
1142 total *= 2;
1143 }
1144 }
1145
1146 /* UNGCPRO; */
1147 return make_string (buf, length);
1148}
1149
1150/* VARARGS 1 */
1151Lisp_Object
1152#ifdef NO_ARG_ARRAY
1153format1 (string1, arg0, arg1, arg2, arg3, arg4)
1154 int arg0, arg1, arg2, arg3, arg4;
1155#else
1156format1 (string1)
1157#endif
1158 char *string1;
1159{
1160 char buf[100];
1161#ifdef NO_ARG_ARRAY
1162 int args[5];
1163 args[0] = arg0;
1164 args[1] = arg1;
1165 args[2] = arg2;
1166 args[3] = arg3;
1167 args[4] = arg4;
1168 doprnt (buf, sizeof buf, string1, 0, 5, args);
1169#else
1170 doprnt (buf, sizeof buf, string1, 0, 5, &string1 + 1);
1171#endif
1172 return build_string (buf);
1173}
1174\f
1175DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
1176 "Return t if two characters match, optionally ignoring case.\n\
1177Both arguments must be characters (i.e. integers).\n\
1178Case is ignored if `case-fold-search' is non-nil in the current buffer.")
1179 (c1, c2)
1180 register Lisp_Object c1, c2;
1181{
1182 unsigned char *downcase = DOWNCASE_TABLE;
1183 CHECK_NUMBER (c1, 0);
1184 CHECK_NUMBER (c2, 1);
1185
1186 if (!NULL (current_buffer->case_fold_search)
1187 ? downcase[0xff & XFASTINT (c1)] == downcase[0xff & XFASTINT (c2)]
1188 : XINT (c1) == XINT (c2))
1189 return Qt;
1190 return Qnil;
1191}
1192
1193#ifndef MAINTAIN_ENVIRONMENT /* it is done in environ.c in that case */
1194DEFUN ("getenv", Fgetenv, Sgetenv, 1, 2, 0,
1195 "Return the value of environment variable VAR, as a string.\n\
1196VAR should be a string. Value is nil if VAR is undefined in the environment.")
1197 (str)
1198 Lisp_Object str;
1199{
1200 register char *val;
1201 CHECK_STRING (str, 0);
1202 val = (char *) egetenv (XSTRING (str)->data);
1203 if (!val)
1204 return Qnil;
1205 return build_string (val);
1206}
1207#endif /* MAINTAIN_ENVIRONMENT */
1208\f
1209void
1210syms_of_editfns ()
1211{
1212 DEFVAR_LISP ("system-name", &Vsystem_name,
1213 "The name of the machine Emacs is running on.");
1214
1215 DEFVAR_LISP ("user-full-name", &Vuser_full_name,
1216 "The full name of the user logged in.");
1217
1218 DEFVAR_LISP ("user-name", &Vuser_name,
1219 "The user's name, based on the effective uid.");
1220
1221 DEFVAR_LISP ("user-real-name", &Vuser_real_name,
1222 "The user's name, base upon the real uid.");
1223
1224 defsubr (&Schar_equal);
1225 defsubr (&Sgoto_char);
1226 defsubr (&Sstring_to_char);
1227 defsubr (&Schar_to_string);
1228 defsubr (&Sbuffer_substring);
1229 defsubr (&Sbuffer_string);
1230
1231 defsubr (&Spoint_marker);
1232 defsubr (&Smark_marker);
1233 defsubr (&Spoint);
1234 defsubr (&Sregion_beginning);
1235 defsubr (&Sregion_end);
1236/* defsubr (&Smark); */
1237/* defsubr (&Sset_mark); */
1238 defsubr (&Ssave_excursion);
1239
1240 defsubr (&Sbufsize);
1241 defsubr (&Spoint_max);
1242 defsubr (&Spoint_min);
1243 defsubr (&Spoint_min_marker);
1244 defsubr (&Spoint_max_marker);
1245
1246 defsubr (&Sbobp);
1247 defsubr (&Seobp);
1248 defsubr (&Sbolp);
1249 defsubr (&Seolp);
1250 defsubr (&Sfollchar);
1251 defsubr (&Sprevchar);
1252 defsubr (&Schar_after);
1253 defsubr (&Sinsert);
1254 defsubr (&Sinsert_before_markers);
1255 defsubr (&Sinsert_char);
1256
1257 defsubr (&Suser_login_name);
1258 defsubr (&Suser_real_login_name);
1259 defsubr (&Suser_uid);
1260 defsubr (&Suser_real_uid);
1261 defsubr (&Suser_full_name);
d940e0e4 1262 defsubr (&Scurrent_time);
35692fe0
JB
1263 defsubr (&Scurrent_time_string);
1264 defsubr (&Ssystem_name);
1265 defsubr (&Sset_default_file_mode);
1266 defsubr (&Sunix_sync);
1267 defsubr (&Smessage);
1268 defsubr (&Sformat);
1269#ifndef MAINTAIN_ENVIRONMENT /* in environ.c */
1270 defsubr (&Sgetenv);
1271#endif
1272
1273 defsubr (&Sinsert_buffer_substring);
1274 defsubr (&Ssubst_char_in_region);
1275 defsubr (&Stranslate_region);
1276 defsubr (&Sdelete_region);
1277 defsubr (&Swiden);
1278 defsubr (&Snarrow_to_region);
1279 defsubr (&Ssave_restriction);
1280}