*** empty log message ***
[bpt/emacs.git] / src / editfns.c
1 /* Lisp functions pertaining to editing.
2 Copyright (C) 1985, 1986, 1987, 1989 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 #include "config.h"
22
23 #ifdef VMS
24 #include "pwd.h"
25 #else
26 #include <pwd.h>
27 #endif
28
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
46 Lisp_Object Vsystem_name;
47 Lisp_Object Vuser_real_name; /* login name of current user ID */
48 Lisp_Object Vuser_full_name; /* full name of current user */
49 Lisp_Object Vuser_name; /* user name from USER or LOGNAME. */
50
51 void
52 init_editfns ()
53 {
54 char *user_name;
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
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");
83 if (!user_name)
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);
91
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. */
94 tem = Fstring_equal (Vuser_name, Vuser_real_name);
95 if (NULL (tem))
96 pw = (struct passwd *) getpwnam (XSTRING (Vuser_name)->data);
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;
111 strcat (r, XSTRING (Vuser_name)->data);
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
119 DEFUN ("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
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.")
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
148 static Lisp_Object
149 buildmark (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
158 DEFUN ("point", Fpoint, Spoint, 0, 0, 0,
159 "Return value of point, as an integer.\n\
160 Beginning of buffer is position (point-min)")
161 ()
162 {
163 Lisp_Object temp;
164 XFASTINT (temp) = point;
165 return temp;
166 }
167
168 DEFUN ("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
175 int
176 clip_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
187 DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
188 "Set point to POSITION, a number or marker.\n\
189 Beginning 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
199 static Lisp_Object
200 region_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
212 DEFUN ("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
219 DEFUN ("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 */
227 DEFUN ("mark", Fmark, Smark, 0, 0, 0,
228 "Return this buffer's mark value as integer, or nil if no mark.\n\
229 If you are using this in an editing command, you are most likely making\n\
230 a mistake; see the documentation of `set-mark'.")
231 ()
232 {
233 return Fmarker_position (current_buffer->mark);
234 }
235 #endif /* commented out code */
236
237 DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
238 "Return this buffer's mark, as a marker object.\n\
239 Watch out! Moving this marker changes the mark position.\n\
240 If 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 */
247 DEFUN ("set-mark", Fset_mark, Sset_mark, 1, 1, 0,
248 "Set this buffer's mark to POS. Don't use this function!\n\
249 That is to say, don't use this function unless you want\n\
250 the user to see that the mark has moved, and you want the previous\n\
251 mark position to be lost.\n\
252 \n\
253 Normally, when a new mark is set, the old one should go on the stack.\n\
254 This is why most applications should use push-mark, not set-mark.\n\
255 \n\
256 Novice programmers often try to use the mark for the wrong purposes.\n\
257 The mark saves a location for the user's convenience.\n\
258 Most editing commands should not alter the mark.\n\
259 To remember a location for internal use in the Lisp program,\n\
260 store 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
281 Lisp_Object
282 save_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
290 Lisp_Object
291 save_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
316 DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
317 "Save point, mark, and current buffer; execute BODY; restore those things.\n\
318 Executes BODY just like `progn'.\n\
319 The values of point, mark and the current buffer are restored\n\
320 even 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
333 DEFUN ("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
342 DEFUN ("point-min", Fpoint_min, Spoint_min, 0, 0, 0,
343 "Return the minimum permissible value of point in the current buffer.\n\
344 This is 1, unless a clipping restriction is in effect.")
345 ()
346 {
347 Lisp_Object temp;
348 XFASTINT (temp) = BEGV;
349 return temp;
350 }
351
352 DEFUN ("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\
354 This is the beginning, unless a clipping restriction is in effect.")
355 ()
356 {
357 return buildmark (BEGV);
358 }
359
360 DEFUN ("point-max", Fpoint_max, Spoint_max, 0, 0, 0,
361 "Return the maximum permissible value of point in the current buffer.\n\
362 This is (1+ (buffer-size)), unless a clipping restriction is in effect,\n\
363 in which case it is less.")
364 ()
365 {
366 Lisp_Object temp;
367 XFASTINT (temp) = ZV;
368 return temp;
369 }
370
371 DEFUN ("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\
373 This is (1+ (buffer-size)), unless a clipping restriction is in effect,\n\
374 in which case it is less.")
375 ()
376 {
377 return buildmark (ZV);
378 }
379
380 DEFUN ("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
389 DEFUN ("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
401 DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0,
402 "Return T if point is at the beginning of the buffer.\n\
403 If 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
411 DEFUN ("eobp", Feobp, Seobp, 0, 0, 0,
412 "Return T if point is at the end of the buffer.\n\
413 If 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
421 DEFUN ("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
430 DEFUN ("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
440 DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0,
441 "Return character in current buffer at position POS.\n\
442 POS is an integer or a buffer pointer.\n\
443 If 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
459 DEFUN ("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\
461 This is based on the effective uid, not the real uid.\n\
462 Also, if the environment variable USER or LOGNAME is set,\n\
463 that determines the value of this function.")
464 ()
465 {
466 return Vuser_name;
467 }
468
469 DEFUN ("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\
472 Differs from `user-login-name' when running under `su'.")
473 ()
474 {
475 return Vuser_real_name;
476 }
477
478 DEFUN ("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
485 DEFUN ("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
492 DEFUN ("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
499 DEFUN ("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
506 DEFUN ("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
514 DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 0, 0,
515 "Return the current time, as a human-readable string.\n\
516 Programs can use it too, since the number of columns in each field is fixed.\n\
517 The format is `Sun Sep 16 01:03:52 1973'.\n\
518 In a future Emacs version, the time zone may be added at the end,\n\
519 if 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
534 DEFUN ("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\
536 The `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
544 DEFUN ("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
554 void
555 insert1 (arg)
556 Lisp_Object arg;
557 {
558 Finsert (1, &arg);
559 }
560
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
567 DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
568 "Insert the arguments, either strings or characters, at point.\n\
569 Point moves forward so that it ends up after the inserted text.\n\
570 Any 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];
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
599 return Qnil;
600 }
601
602 DEFUN ("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\
604 Point moves forward so that it ends up after the inserted text.\n\
605 Any 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];
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
634 return Qnil;
635 }
636 \f
637 DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 2, 0,
638 "Insert COUNT (second arg) copies of CHAR (first arg).\n\
639 Point and all markers are affected as in the function `insert'.\n\
640 Both 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
671 DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
672 "Return the contents of part of the current buffer as a string.\n\
673 The two arguments START and END are character positions;\n\
674 they 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
699 DEFUN ("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
708 DEFUN ("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\
711 BUFFER may be a buffer or a buffer name.\n\
712 Arguments START and END are character numbers specifying the substring.\n\
713 They 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
766 DEFUN ("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\
769 If optional arg NOUNDO is non-nil, don't record this change for undo\n\
770 and 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
809 DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0,
810 "From START to END, translate characters according to TABLE.\n\
811 TABLE is a string; the Nth character in it is the mapping\n\
812 for 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
857 DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
858 "Delete the text between point and mark.\n\
859 When called from a program, expects two arguments,\n\
860 positions (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
869 DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
870 "Remove restrictions (narrowing) from current buffer.\n\
871 This 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;
877 /* Changing the buffer bounds invalidates any recorded current column. */
878 invalidate_current_column ();
879 return Qnil;
880 }
881
882 DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
883 "Restrict editing in this buffer to the current region.\n\
884 The rest of the text becomes temporarily invisible and untouchable\n\
885 but is not deleted; if you save the buffer in a file, the invisible\n\
886 text is included in the file. \\[widen] makes all visible again.\n\
887 See also `save-restriction'.\n\
888 \n\
889 When calling from a program, pass two arguments; positions (integers\n\
890 or 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;
916 /* Changing the buffer bounds invalidates any recorded current column. */
917 invalidate_current_column ();
918 return Qnil;
919 }
920
921 Lisp_Object
922 save_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
934 Lisp_Object
935 save_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
966 DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
967 "Execute BODY, saving and restoring current buffer's restrictions.\n\
968 The 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\
970 This special form, `save-restriction', saves the current buffer's restrictions\n\
971 when it is entered, and restores them when it is exited.\n\
972 So any `narrow-to-region' within BODY lasts only until the end of the form.\n\
973 The old restrictions settings are restored\n\
974 even in case of abnormal exit (throw or error).\n\
975 \n\
976 The 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\
979 and then make changes outside the area within the saved restrictions.\n\
980 \n\
981 Note: if you are using both `save-excursion' and `save-restriction',\n\
982 use `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
995 DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
996 "Print a one-line message at the bottom of the screen.\n\
997 The first argument is a control string.\n\
998 It 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\
1001 The argument used by %s must be a string or a symbol;\n\
1002 the 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
1009 val = Fformat (nargs, args);
1010 message ("%s", XSTRING (val)->data);
1011 return val;
1012 }
1013
1014 DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
1015 "Format a string out of a control-string and arguments.\n\
1016 The first argument is a control string.\n\
1017 The other arguments are substituted into it to make the result, a string.\n\
1018 It 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\
1023 The argument used for %d, %o, %x or %c must be a number.\n\
1024 Use %% to put a single % into the output.")
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 */
1151 Lisp_Object
1152 #ifdef NO_ARG_ARRAY
1153 format1 (string1, arg0, arg1, arg2, arg3, arg4)
1154 int arg0, arg1, arg2, arg3, arg4;
1155 #else
1156 format1 (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
1175 DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
1176 "Return t if two characters match, optionally ignoring case.\n\
1177 Both arguments must be characters (i.e. integers).\n\
1178 Case 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 */
1194 DEFUN ("getenv", Fgetenv, Sgetenv, 1, 2, 0,
1195 "Return the value of environment variable VAR, as a string.\n\
1196 VAR 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
1209 void
1210 syms_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);
1262 defsubr (&Scurrent_time);
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 }