comparison src/editfns.c @ 305:75f54c84f733

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