|
|
1.1 root 1: /* Lisp functions pertaining to editing.
2: Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU Emacs.
5:
6: GNU Emacs is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU Emacs General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU Emacs, but only under the conditions described in the
15: GNU Emacs General Public License. A copy of this license is
16: supposed to have been given to you along with GNU Emacs so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: #include "config.h"
23: #include <pwd.h>
24: #include "lisp.h"
25: #include "buffer.h"
26: #include "window.h"
27:
28: #define min(a, b) ((a) < (b) ? (a) : (b))
29: #define max(a, b) ((a) > (b) ? (a) : (b))
30:
31: /* Some static data, and a function to initialize it for each run */
32:
33: static char user_real_name[33]; /* login ID of current user */
34: static char user_full_name[50]; /* full name of current user */
35:
36: static char system_name[40];
37: static char *user_name;
38:
39: void
40: init_editfns ()
41: {
42: register char *p;
43: struct passwd *pw; /* password entry for the current user */
44: extern char *index ();
45:
46: /* Set up system_name even when dumping. */
47:
48: p = (char *) get_system_name ();
49: if (p == 0 || *p == 0)
50: p = "Bogus System Name";
51: strncpy (system_name, p, sizeof system_name);
52: p = system_name;
53: while (*p)
54: {
55: if (*p < ' ')
56: *p = 0;
57: else
58: if (*p == ' ')
59: *p = '-';
60: p++;
61: }
62:
63: #ifndef CANNOT_DUMP
64: /* Don't bother with this on initial start when just dumping out */
65: if (!initialized)
66: return;
67: #endif /* not CANNOT_DUMP */
68:
69: pw = (struct passwd *) getpwuid (getuid ());
70: if (pw == 0)
71: strcpy (user_real_name, "unknown");
72: else
73: strncpy (user_real_name, pw->pw_name, sizeof user_real_name);
74:
75: user_name = (char *) getenv ("USER");
76: if (!user_name)
77: user_name = (char *) getenv ("LOGNAME"); /* USG equivalent */
78: if (!user_name)
79: user_name = user_real_name;
80:
81: if (strcmp (user_name, user_real_name))
82: pw = (struct passwd *) getpwnam (user_name);
83:
84: #ifndef AMPERSAND_FULL_NAME
85: if (pw == 0)
86: strcpy (user_full_name, "unknown");
87: else
88: strncpy (user_full_name, USER_FULL_NAME, sizeof user_full_name);
89: p = index (user_full_name, ',');
90: if (p) *p = 0;
91: #else
92: if (pw == 0)
93: p = "unknown";
94: else
95: p = USER_FULL_NAME;
96: {
97: int first = 1;
98: register char *q, *r;
99:
100: q = user_full_name; r = user_name;
101:
102: for (; (*p != 0) && (*p != ','); p++)
103: {
104: if (*p == '&')
105: {
106: if (*r != 0)
107: {
108: *q = *r++;
109: *q = UPCASE (*q);
110: for (q++; *r != 0; r++)
111: {
112: if (q == &user_full_name[sizeof user_full_name - 1])
113: break;
114: *q++ = *r;
115: }
116: }
117: }
118: else
119: *q++ = *p;
120: if (q == &user_full_name[sizeof user_full_name - 2])
121: break;
122: }
123: *q = 0;
124: }
125: #endif /* AMPERSAND_FULL_NAME */
126: }
127:
128: DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
129: "Convert arg CHAR to a string containing that character.")
130: (n)
131: Lisp_Object n;
132: {
133: char c;
134: CHECK_NUMBER (n, 0);
135:
136: c = XINT (n);
137: return make_string (&c, 1);
138: }
139:
140: DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
141: "Convert arg STRING to a character, the first character of that string.")
142: (str)
143: register Lisp_Object str;
144: {
145: register Lisp_Object val;
146: register struct Lisp_String *p;
147: CHECK_STRING (str, 0);
148:
149: p = XSTRING (str);
150: if (p->size)
151: XFASTINT (val) = ((unsigned char *) p->data)[0];
152: else
153: XFASTINT (val) = 0;
154: return val;
155: }
156:
157: static Lisp_Object
158: buildmark (val)
159: int val;
160: {
161: register Lisp_Object mark;
162: mark = Fmake_marker ();
163: Fset_marker (mark, make_number (val), Qnil);
164: return mark;
165: }
166:
167: DEFSIMPLE ("point", Fpoint, Spoint,
168: "Return value of point, as an integer.\n\
169: Beginning of buffer is position (point-min)",
170: Lisp_Int, XSETINT, point)
171:
172: DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
173: "Return value of point, as a marker object.")
174: ()
175: {
176: return buildmark (point);
177: }
178:
179: DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
180: "One arg, a number. Set point to that number.\n\
181: Beginning of buffer is position (point-min), end is (point-max).")
182: (n)
183: register Lisp_Object n;
184: {
185: register int charno;
186: CHECK_NUMBER_COERCE_MARKER (n, 0);
187: charno = XINT (n);
188: if (charno < FirstCharacter) charno = FirstCharacter;
189: if (charno > NumCharacters) charno = NumCharacters + 1;
190: SetPoint (charno);
191: return n;
192: }
193:
194: static Lisp_Object
195: region_limit (beginningp)
196: int beginningp;
197: {
198: register Lisp_Object m;
199: m = Fmarker_position (bf_cur->mark);
200: if (NULL (m)) error ("There is no region now");
201: if ((point < XFASTINT (m)) == beginningp)
202: return (make_number (point));
203: else
204: return (m);
205: }
206:
207: DEFUN ("region-beginning", Fregion_beginning, Sregion_beginning, 0, 0, 0,
208: "Return position of beginning of region, as an integer.")
209: ()
210: {
211: return (region_limit (1));
212: }
213:
214: DEFUN ("region-end", Fregion_end, Sregion_end, 0, 0, 0,
215: "Return position of end of region, as an integer.")
216: ()
217: {
218: return (region_limit (0));
219: }
220:
221: #if 0 /* now in lisp code */
222: DEFUN ("mark", Fmark, Smark, 0, 0, 0,
223: "Return this buffer's mark value as integer, or nil if no mark.\n\
224: If you are using this in an editing command, you are most likely making\n\
225: a mistake; see the documentation of `set-mark'.")
226: ()
227: {
228: return Fmarker_position (bf_cur->mark);
229: }
230: #endif /* commented out code */
231:
232: DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
233: "Return this buffer's mark, as a marker object.\n\
234: Watch out! Moving this marker changes the mark position.\n\
235: The marker will not point anywhere if mark is not set.")
236: ()
237: {
238: return bf_cur->mark;
239: }
240:
241: #if 0 /* this is now in lisp code */
242: DEFUN ("set-mark", Fset_mark, Sset_mark, 1, 1, 0,
243: "Set this buffer's mark to POS. Don't use this function!\n\
244: That is to say, don't use this function unless you want\n\
245: the user to see that the mark has moved, and you want the previous\n\
246: mark position to be lost.\n\
247: \n\
248: Normally, when a new mark is set, the old one should go on the stack.\n\
249: This is why most applications should use push-mark, not set-mark.\n\
250: \n\
251: Novice programmers often try to use the mark for the wrong purposes.\n\
252: The mark saves a location for the user's convenience.\n\
253: Most editing commands should not alter the mark.\n\
254: To remember a location for internal use in the Lisp program,\n\
255: store it in a Lisp variable. Example:\n\
256: \n\
257: (let ((beg (point))) (forward-line 1) (delete-region beg (point))).")
258: (pos)
259: Lisp_Object pos;
260: {
261: if (NULL (pos))
262: {
263: bf_cur->mark = Qnil;
264: return Qnil;
265: }
266: CHECK_NUMBER_COERCE_MARKER (pos, 0);
267:
268: if (NULL (bf_cur->mark))
269: bf_cur->mark = Fmake_marker ();
270:
271: Fset_marker (bf_cur->mark, pos, Qnil);
272: return pos;
273: }
274: #endif /* commented-out code */
275:
276: Lisp_Object
277: save_excursion_save ()
278: {
279: register Lisp_Object oldpoint, oldmark;
280: register int visible = XBUFFER (XWINDOW (selected_window)->buffer) == bf_cur;
281:
282: oldpoint = Fpoint_marker ();
283: oldmark = Fcopy_marker (bf_cur->mark);
284: return Fcons (oldpoint, Fcons (oldmark, visible ? Qt : Qnil));
285: }
286:
287: Lisp_Object
288: save_excursion_restore (info)
289: register Lisp_Object info;
290: {
291: register Lisp_Object tem;
292:
293: tem = Fmarker_buffer (Fcar (info));
294: /* If buffer being returned to is now deleted, avoid error */
295: /* Otherwise could get error here while unwinding to top level
296: and crash */
297: /* In that case, Fmarker_buffer returns nil now. */
298: if (NULL (tem))
299: return Qnil;
300: Fset_buffer (tem);
301: tem = Fcar (info);
302: Fgoto_char (tem);
303: unchain_marker (tem);
304: tem = Fcar (Fcdr (info));
305: Fset_marker (bf_cur->mark, tem, Fcurrent_buffer ());
306: unchain_marker (tem);
307: tem = Fcdr (Fcdr (info));
308: if (!NULL (tem) && bf_cur != XBUFFER (XWINDOW (selected_window)->buffer))
309: Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
310: return Qnil;
311: }
312:
313: DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
314: "Save point (and mark), execute BODY, then restore point and mark.\n\
315: Executes BODY just like PROGN. Point and mark values are restored\n\
316: even in case of abnormal exit (throw or error).")
317: (args)
318: Lisp_Object args;
319: {
320: register Lisp_Object val;
321: int count = specpdl_ptr - specpdl;
322:
323: record_unwind_protect (save_excursion_restore, save_excursion_save ());
324:
325: val = Fprogn (args);
326: unbind_to (count);
327: return val;
328: }
329:
330: DEFSIMPLE ("buffer-size", Fbufsize, Sbufsize,
331: "Return the number of characters in the current buffer.",
332: Lisp_Int, XSETINT, bf_s1 + bf_s2)
333:
334: DEFSIMPLE ("point-min", Fpoint_min, Spoint_min,
335: "Return the minimum permissible value of point in the current buffer.\n\
336: This is 1, unless a clipping restriction is in effect.",
337: Lisp_Int, XSETINT, FirstCharacter)
338:
339: DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 0, 0,
340: "Return a marker to the beginning of the currently visible part of the buffer.\n\
341: This is the beginning, unless a clipping restriction is in effect.")
342: ()
343: {
344: return buildmark (FirstCharacter);
345: }
346:
347: DEFSIMPLE ("point-max", Fpoint_max, Spoint_max,
348: "Return the maximum permissible value of point in the current buffer.\n\
349: This is (1+ (buffer-size)), unless a clipping restriction is in effect,\n\
350: in which case it is less.",
351: Lisp_Int, XSETINT, NumCharacters+1)
352:
353: DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 0, 0,
354: "Return a marker to the end of the currently visible part of the buffer.\n\
355: This is the actual end, unless a clipping restriction is in effect.")
356: ()
357: {
358: return buildmark (NumCharacters+1);
359: }
360:
361: DEFSIMPLE ("following-char", Ffollchar, Sfollchar,
362: "Return the character following point, as a number.",
363: Lisp_Int, XSETINT, point>NumCharacters ? 0 : CharAt(point))
364: DEFSIMPLE ("preceding-char", Fprevchar, Sprevchar,
365: "Return the character preceding point, as a number.",
366: Lisp_Int, XSETINT, point<=FirstCharacter ? 0 : CharAt(point-1))
367:
368: DEFPRED ("bobp", Fbobp, Sbobp,
369: "Return T if point is at the beginning of the buffer.\n\
370: If the buffer is narrowed, this means the beginning of the narrowed part.",
371: point<=FirstCharacter)
372: DEFPRED ("eobp", Feobp, Seobp,
373: "Return T if point is at the end of the buffer.\n\
374: If the buffer is narrowed, this means the end of the narrowed part.",
375: point>NumCharacters)
376: DEFPRED ("bolp", Fbolp, Sbolp,
377: "Return T if point is at the beginning of a line.",
378: point<=FirstCharacter || CharAt(point-1)=='\n')
379: DEFPRED ("eolp", Feolp, Seolp,
380: "Return T if point is at the end of a line.\n\
381: `End of a line' includes point being at the end of the buffer.",
382: point>NumCharacters || CharAt(point)=='\n')
383:
384: DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0,
385: "One arg, POS, a number. Return the character in the current buffer\n\
386: at position POS.\n\
387: If POS is out of range, the value is NIL.")
388: (pos)
389: Lisp_Object pos;
390: {
391: register Lisp_Object val;
392: register int n = XINT (pos);
393: CHECK_NUMBER_COERCE_MARKER (pos, 0);
394: if (n < FirstCharacter || n > NumCharacters) return Qnil;
395:
396: XFASTINT (val) = CharAt (n);
397: return val;
398: }
399:
400: DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 0, 0,
401: "Return the name under which user logged in, as a string.\n\
402: This is based on the effective uid, not the real uid.")
403: ()
404: {
405: return build_string (user_name);
406: }
407:
408: DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
409: 0, 0, 0,
410: "Return the name of the user's real uid, as a string.\n\
411: Differs from user-login-name when running under su.")
412: ()
413: {
414: return build_string (user_real_name);
415: }
416:
417: DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
418: "Return the effective uid of Emacs, as an integer.")
419: ()
420: {
421: return make_number (geteuid ());
422: }
423:
424: DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
425: "Return the real uid of Emacs, as an integer.")
426: ()
427: {
428: return make_number (getuid ());
429: }
430:
431: DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 0, 0,
432: "Return the full name of the user logged in, as a string.")
433: ()
434: {
435: return build_string (user_full_name);
436: }
437:
438: DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
439: "Return the name of the machine you are running on, as a string.")
440: ()
441: {
442: return build_string (system_name);
443: }
444:
445: DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 0, 0,
446: "Return the current time, as a human-readable string.")
447: ()
448: {
449: long now = time ( (long *) 0);
450: register char *tem = (char *) ctime (&now);
451: tem [24] = 0;
452: return build_string (tem);
453: }
454:
455: DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
456: "Any number of args, strings or chars. Insert them after point, moving point forward.")
457: (nargs, args)
458: int nargs;
459: register Lisp_Object *args;
460: {
461: register int argnum;
462: register Lisp_Object tem;
463: char str[1];
464:
465: for (argnum = 0; argnum < nargs; argnum++)
466: {
467: tem = args[argnum];
468: retry:
469: if (XTYPE (tem) == Lisp_Int)
470: {
471: str[0] = XINT (tem);
472: InsCStr (str, 1);
473: }
474: else if (XTYPE (tem) == Lisp_String)
475: {
476: InsCStr (XSTRING (tem)->data, XSTRING (tem)->size);
477: }
478: else
479: {
480: tem = wrong_type_argument (Qchar_or_string_p, tem);
481: goto retry;
482: }
483: }
484: return Qnil;
485: }
486:
487: DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0,
488: "Any number of args, strings or chars. Insert them after point,\n\
489: moving point forward. Also, any markers pointing at the insertion point\n\
490: get relocated to point after the newly inserted text.")
491: (nargs, args)
492: int nargs;
493: register Lisp_Object *args;
494: {
495: register int argnum;
496: register Lisp_Object tem;
497: char str[1];
498:
499: for (argnum = 0; argnum < nargs; argnum++)
500: {
501: tem = args[argnum];
502: retry:
503: if (XTYPE (tem) == Lisp_Int)
504: {
505: str[0] = XINT (tem);
506: insert_before_markers (str, 1);
507: }
508: else if (XTYPE (tem) == Lisp_String)
509: {
510: insert_before_markers (XSTRING (tem)->data, XSTRING (tem)->size);
511: }
512: else
513: {
514: tem = wrong_type_argument (Qchar_or_string_p, tem);
515: goto retry;
516: }
517: }
518: return Qnil;
519: }
520:
521: DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 2, 0,
522: "Insert COUNT (second arg) copies of CHAR (first arg).\n\
523: Both arguments are required.")
524: (chr, count)
525: Lisp_Object chr, count;
526: {
527: register unsigned char *string;
528: register int strlen;
529: register int i, n;
530:
531: CHECK_NUMBER (chr, 0);
532: CHECK_NUMBER (count, 1);
533:
534: n = XINT (count);
535: if (n <= 0)
536: return Qnil;
537: strlen = max (n, 256);
538: string = (unsigned char *) alloca (strlen);
539: for (i = 0; i < strlen; i++)
540: string[i] = XFASTINT (chr);
541: while (n >= strlen)
542: {
543: InsCStr (string, strlen);
544: n -= strlen;
545: }
546: if (n > 0)
547: InsCStr (string, n);
548: return Qnil;
549: }
550:
551:
552: /* Return a string with the contents of the current region */
553:
554: DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
555: "Return the contents of part of the current buffer as a string.\n\
556: The two arguments specify the start and end, as character numbers.")
557: (b, e)
558: Lisp_Object b, e;
559: {
560: register int beg, end;
561:
562: validate_region (&b, &e);
563: beg = XINT (b);
564: end = XINT (e);
565:
566: if (beg <= bf_s1 && end > bf_s1)
567: move_gap (beg);
568: return make_string (&CharAt (beg), end - beg);
569: }
570:
571: DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
572: "Return the contents of the current buffer as a string.")
573: ()
574: {
575: if (FirstCharacter <= bf_s1 && NumCharacters + 1 > bf_s1)
576: move_gap (FirstCharacter);
577: return make_string (&CharAt (FirstCharacter), NumCharacters + 1 - FirstCharacter);
578: }
579:
580: DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
581: 1, 3, 0,
582: "Insert before point a substring of the contents buffer BUFFER.\n\
583: BUFFER may be a buffer or a buffer name.\n\
584: Arguments START and END are character numbers specifying the substring.\n\
585: They default to the beginning and the end of BUFFER.")
586: (buf, b, e)
587: Lisp_Object buf, b, e;
588: {
589: register int beg, end, exch;
590: register struct buffer *bp;
591:
592: buf = Fget_buffer (buf);
593: bp = XBUFFER (buf);
594:
595: if (NULL (b))
596: beg = bp->text.head_clip - 1;
597: else
598: {
599: CHECK_NUMBER_COERCE_MARKER (b, 0);
600: beg = XINT (b) - 1;
601: }
602: if (NULL (e))
603: end = bp->text.size1 + bp->text.size2
604: - bp->text.tail_clip;
605: else
606: {
607: CHECK_NUMBER_COERCE_MARKER (e, 1);
608: end = XINT (e) - 1;
609: }
610:
611: if (beg > end)
612: exch = beg, beg = end, end = exch;
613:
614: /* Move the gap or create enough gap in the current buffer. */
615:
616: if (point != bf_s1 + 1)
617: move_gap (point);
618: if (bf_gap < end - beg)
619: make_gap (end - beg);
620: /* Make sure buf->text is up to date in case buf is the current buffer. */
621: bf_cur->text = bf_text;
622:
623: if (!(bp->text.head_clip - 1 <= beg
624: && beg <= end
625: && end <= bp->text.size1 + bp->text.size2 - bp->text.tail_clip))
626: args_out_of_range (b, e);
627:
628: /* Now the actual insertion will not do any gap motion,
629: so it matters not if BUF is the current buffer. */
630:
631: if (beg < bp->text.size1)
632: {
633: InsCStr (bp->text.p1 + 1 + beg, min (end, bp->text.size1) - beg);
634: beg = min (end, bp->text.size1);
635: }
636: if (beg < end)
637: InsCStr (bp->text.p2 + 1 + beg, end - beg);
638:
639: return Qnil;
640: }
641:
642: DEFUN ("subst-char-in-region", Fsubst_char_in_region,
643: Ssubst_char_in_region, 4, 5, 0,
644: "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\
645: If optional arg NOUNDO is non-nil, don't record this change for undo\n\
646: and don't mark the buffer as really changed.")
647: (start, end, fromchar, tochar, noundo)
648: Lisp_Object start, end, fromchar, tochar, noundo;
649: {
650: register int pos, stop, look;
651:
652: validate_region (&start, &end);
653: CHECK_NUMBER (fromchar, 2);
654: CHECK_NUMBER (tochar, 3);
655:
656: pos = XINT (start);
657: stop = XINT (end);
658: look = XINT (fromchar);
659:
660: modify_region (pos, stop);
661: if (! NULL (noundo))
662: {
663: if (bf_modified - 1 == bf_cur->save_modified)
664: bf_cur->save_modified++;
665: if (bf_modified - 1 == bf_cur->auto_save_modified)
666: bf_cur->auto_save_modified++;
667: }
668:
669: while (pos < stop)
670: {
671: if (CharAt (pos) == look)
672: {
673: if (NULL (noundo))
674: record_change (pos, 1);
675: CharAt (pos) = XINT (tochar);
676: }
677: pos++;
678: }
679:
680: return Qnil;
681: }
682:
683: DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
684: "Delete the text between point and mark.\n\
685: When called from a program, expects two arguments,\n\
686: character numbers specifying the stretch to be deleted.")
687: (b, e)
688: Lisp_Object b, e;
689: {
690: validate_region (&b, &e);
691: del_range (XINT (b), XINT (e));
692: return Qnil;
693: }
694:
695: DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
696: "Remove restrictions from current buffer, allowing full text to be seen and edited.")
697: ()
698: {
699: bf_cur->text.head_clip = bf_head_clip = 1;
700: bf_cur->text.tail_clip = bf_tail_clip = 0;
701: clip_changed = 1;
702: return Qnil;
703: }
704:
705: DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
706: "Restrict editing in this buffer to the current region.\n\
707: The rest of the text becomes temporarily invisible and untouchable\n\
708: but is not deleted; if you save the buffer in a file, the invisible\n\
709: text is included in the file. \\[widen] makes all visible again.\n\
710: \n\
711: When calling from a program, pass two arguments; character numbers\n\
712: bounding the text that should remain visible.")
713: (b, e)
714: register Lisp_Object b, e;
715: {
716: register int i;
717:
718: CHECK_NUMBER_COERCE_MARKER (b, 0);
719: CHECK_NUMBER_COERCE_MARKER (e, 1);
720:
721: if (XINT (b) > XINT (e))
722: {
723: i = XFASTINT (b);
724: b = e;
725: XFASTINT (e) = i;
726: }
727:
728: if (!(1 <= XINT (b) && XINT (b) <= XINT (e)
729: && XINT (e) <= bf_s1 + bf_s2 + 1))
730: args_out_of_range (b, e);
731:
732: bf_cur->text.head_clip = bf_head_clip = XFASTINT (b);
733: bf_cur->text.tail_clip = bf_tail_clip = bf_s1 + bf_s2 + 1 - XFASTINT (e);
734: if (point < XFASTINT (b))
735: SetPoint (XFASTINT (b));
736: if (point > XFASTINT (e))
737: SetPoint (XFASTINT (e));
738: clip_changed = 1;
739: return Qnil;
740: }
741:
742: Lisp_Object
743: save_restriction_save ()
744: {
745: register Lisp_Object ml, mh;
746: /* Note: I tried using markers here, but it does not win
747: because insertion at the end of the saved region
748: does not advance mh and is considered "outside" the saved region. */
749: XFASTINT (ml) = bf_head_clip;
750: XFASTINT (mh) = bf_tail_clip;
751:
752: return Fcons (Fcurrent_buffer (), Fcons (ml, mh));
753: }
754:
755: Lisp_Object
756: save_restriction_restore (data)
757: Lisp_Object data;
758: {
759: register struct buffer *old = bf_cur;
760: register int newhead, newtail;
761: register Lisp_Object tem;
762:
763: Fset_buffer (XCONS (data)->car);
764:
765: data = XCONS (data)->cdr;
766:
767: tem = XCONS (data)->car;
768: newhead = XINT (tem);
769: tem = XCONS (data)->cdr;
770: newtail = XINT (tem);
771: if (newhead + newtail > bf_s1 + bf_s2 + 1)
772: {
773: newhead = 1;
774: newtail = 0;
775: }
776: bf_cur->text.head_clip = bf_head_clip = newhead;
777: bf_cur->text.tail_clip = bf_tail_clip = newtail;
778: clip_changed = 1;
779:
780: /* If point is outside the new visible range, move it inside. */
781: if (point < FirstCharacter)
782: SetPoint (FirstCharacter);
783: if (point > NumCharacters+1)
784: SetPoint (NumCharacters+1);
785:
786: SetBfp (old);
787: return Qnil;
788: }
789:
790: DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
791: "Execute the body, undoing at the end any changes to current buffer's restrictions.\n\
792: Changes to restrictions are made by narrow-to-region or by widen.\n\
793: Thus, the restrictions are the same after this function as they were before it.\n\
794: The value returned is that returned by the last form in the body.\n\
795: \n\
796: This function can be confused if, within the body, you widen\n\
797: and then make changes outside the area within the saved restrictions.\n\
798: \n\
799: Note: if you are using both save-excursion and save-restriction,\n\
800: use save-excursion outermost.")
801: (body)
802: Lisp_Object body;
803: {
804: register Lisp_Object val;
805: int count = specpdl_ptr - specpdl;
806:
807: record_unwind_protect (save_restriction_restore, save_restriction_save ());
808: val = Fprogn (body);
809: unbind_to (count);
810: return val;
811: }
812:
813: DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
814: "Print a one-line message at the bottom of the screen.\n\
815: The first argument is a control string.\n\
816: It may contain %s or %d or %c to print successive following arguments.\n\
817: %s means print an argument as a string, %d means print as number in decimal,\n\
818: %c means print a number as a single character.\n\
819: The argument used by %s must be a string or a symbol;\n\
820: the argument used by %d or %c must be a number.")
821: (nargs, args)
822: int nargs;
823: Lisp_Object *args;
824: {
825: register Lisp_Object val;
826:
827: val = Fformat (nargs, args);
828: message ("%s", XSTRING (val)->data);
829: return val;
830: }
831:
832: DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
833: "Format a string out of a control-string and arguments.\n\
834: The first argument is a control string.\n\
835: It, and subsequent arguments substituted into it, become the value, which is a string.\n\
836: It may contain %s or %d or %c to substitute successive following arguments.\n\
837: %s means print an argument as a string, %d means print as number in decimal,\n\
838: %c means print a number as a single character.\n\
839: The argument used by %s must be a string or a symbol;\n\
840: the argument used by %d, %b, %o, %x or %c must be a number.")
841: (nargs, args)
842: int nargs;
843: register Lisp_Object *args;
844: {
845: register int n;
846: register int total = 5;
847: char *buf;
848: register unsigned char *format;
849: register unsigned char **strings;
850: extern char *index ();
851: /* struct gcpro gcpro1; */
852:
853: CHECK_STRING (args[0], 0);
854: format = XSTRING (args[0])->data;
855:
856: /* This should be unnecessary. We don't call eval, so we cannot gc. */
857: /* GCPRO1 (*args);
858: gcpro1.nvars = nargs; */
859:
860: /* We have to do so much work in oder to prepare to call doprnt
861: that we might as well do all of it ourself... (Which would also
862: circumvent C asciz cretinism by allowing ascii 000 chars to appear)
863: */
864: n = 0;
865: while (format = (unsigned char *) index (format, '%'))
866: {
867: format++;
868: while ((*format >= '0' && *format <= '9')
869: || *format == '-' || *format == ' ')
870: format++;
871: if (*format == '%')
872: format++;
873: else if (++n >= nargs)
874: ;
875: else if (XTYPE (args[n]) == Lisp_Symbol)
876: {
877: XSET (args[n], Lisp_String, XSYMBOL (args[n])->name);
878: goto string;
879: }
880: else if (XTYPE (args[n]) == Lisp_String)
881: {
882: string:
883: total += XSTRING (args[n])->size;
884: }
885: /* would get MPV otherwise, since Lisp_Int's `point' to low memory */
886: else if (XTYPE (args[n]) == Lisp_Int && *format != 's')
887: total += 10;
888: else
889: {
890: register Lisp_Object tem;
891: tem = Fprin1_to_string (args[n]);
892: args[n] = tem;
893: goto string;
894: }
895: }
896:
897: strings = (unsigned char **) alloca ((n + 1) * sizeof (unsigned char *));
898: for (; n >= 0; n--)
899: {
900: if (n >= nargs)
901: strings[n] = (unsigned char *) "";
902: else if (XTYPE (args[n]) == Lisp_Int)
903: /* We checked above that the correspondiong format effector
904: isn't %s, which would cause MPV */
905: strings[n] = (unsigned char *) XINT (args[n]);
906: else
907: strings[n] = XSTRING (args[n])->data;
908: }
909:
910: /* Format it in bigger and bigger buf's until it all fits. */
911: while (1)
912: {
913: buf = (char *) alloca (total + 1);
914: buf[total - 1] = 0;
915:
916: doprnt (buf, total + 1, strings[0], nargs, strings + 1);
917: if (buf[total - 1] == 0)
918: break;
919:
920: total *= 2;
921: }
922:
923: /* UNGCPRO; */
924: return build_string (buf);
925: }
926:
927: /* VARARGS 1 */
928: Lisp_Object
929: #ifdef NO_ARG_ARRAY
930: format1 (string1, arg0, arg1, arg2, arg3, arg4)
931: int arg0, arg1, arg2, arg3, arg4;
932: #else
933: format1 (string1)
934: #endif
935: char *string1;
936: {
937: char buf[100];
938: #ifdef NO_ARG_ARRAY
939: int args[5];
940: args[0] = arg0;
941: args[1] = arg1;
942: args[2] = arg2;
943: args[3] = arg3;
944: args[4] = arg4;
945: doprnt (buf, sizeof buf, string1, 5, args);
946: #else
947: doprnt (buf, sizeof buf, string1, 5, &string1 + 1);
948: #endif
949: return build_string (buf);
950: }
951:
952: DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
953: "T if args (both characters (numbers)) match. May ignore case.\n\
954: Case is ignored if the current buffer specifies to do so.")
955: (c1, c2)
956: register Lisp_Object c1, c2;
957: {
958: CHECK_NUMBER (c1, 0);
959: CHECK_NUMBER (c2, 1);
960:
961: if (!NULL (bf_cur->case_fold_search)
962: ? downcase_table[0xff & XFASTINT (c1)] == downcase_table[0xff & XFASTINT (c2)]
963: : XINT (c1) == XINT (c2))
964: return Qt;
965: return Qnil;
966: }
967:
968: #ifndef MAINTAIN_ENVIRONMENT /* it is done in environ.c in that case */
969: DEFUN ("getenv", Fgetenv, Sgetenv, 1, 2, 0,
970: "One arg VAR, a string. Return the value of environment variable VAR, as a string.")
971: (str)
972: Lisp_Object str;
973: {
974: register char *val;
975: CHECK_STRING (str, 0);
976: val = (char *) egetenv (XSTRING (str)->data);
977: if (!val)
978: return Qnil;
979: return build_string (val);
980: }
981: #endif MAINTAIN_ENVIRONMENT
982:
983: void
984: syms_of_editfns ()
985: {
986: defsubr (&Schar_equal);
987: defsubr (&Sgoto_char);
988: defsubr (&Sstring_to_char);
989: defsubr (&Schar_to_string);
990: defsubr (&Sbuffer_substring);
991: defsubr (&Sbuffer_string);
992:
993: defsubr (&Spoint_marker);
994: defsubr (&Smark_marker);
995: defsubr (&Spoint);
996: defsubr (&Sregion_beginning);
997: defsubr (&Sregion_end);
998: /* defsubr (&Smark); */
999: /* defsubr (&Sset_mark); */
1000: defsubr (&Ssave_excursion);
1001:
1002: defsubr (&Sbufsize);
1003: defsubr (&Spoint_max);
1004: defsubr (&Spoint_min);
1005: defsubr (&Spoint_min_marker);
1006: defsubr (&Spoint_max_marker);
1007:
1008: defsubr (&Sbobp);
1009: defsubr (&Seobp);
1010: defsubr (&Sbolp);
1011: defsubr (&Seolp);
1012: defsubr (&Sfollchar);
1013: defsubr (&Sprevchar);
1014: defsubr (&Schar_after);
1015: defsubr (&Sinsert);
1016: defsubr (&Sinsert_before_markers);
1017: defsubr (&Sinsert_char);
1018:
1019: defsubr (&Suser_login_name);
1020: defsubr (&Suser_real_login_name);
1021: defsubr (&Suser_uid);
1022: defsubr (&Suser_real_uid);
1023: defsubr (&Suser_full_name);
1024: defsubr (&Scurrent_time_string);
1025: defsubr (&Ssystem_name);
1026: defsubr (&Smessage);
1027: defsubr (&Sformat);
1028: #ifndef MAINTAIN_ENVIRONMENT /* in environ.c */
1029: defsubr (&Sgetenv);
1030: #endif
1031:
1032: defsubr (&Sinsert_buffer_substring);
1033: defsubr (&Ssubst_char_in_region);
1034: defsubr (&Sdelete_region);
1035: defsubr (&Swiden);
1036: defsubr (&Snarrow_to_region);
1037: defsubr (&Ssave_restriction);
1038: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.