|
|
1.1 root 1: /* Lisp functions pertaining to editing.
2: Copyright (C) 1985 Richard M. Stallman.
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: Lisp_Object ml_apply ();
32:
33: /* Some static data, and a function to initialize it for each run */
34:
35: static char user_real_name[12]; /* login ID of current user */
36: static char user_full_name[50]; /* full name of current user */
37:
38: static char system_name[40];
39: static char *user_name;
40:
41: void
42: init_editfns ()
43: {
44: register char *p, *q, *r;
45: register int c;
46: int first;
47: struct passwd *pw; /* password entry for the current user */
48: extern char *index ();
49:
50: /* Don't bother with this on initial start when just dumping out */
51: if (!NULL (Vpurify_flag))
52: return;
53:
54: pw = (struct passwd *) getpwuid (getuid ());
55: strncpy (user_real_name, pw->pw_name, sizeof user_real_name);
56:
57: user_name = (char *) getenv ("USER");
58: #ifdef USG
59: if (!user_name)
60: user_name = (char *) getenv ("LOGNAME"); /* USG equivalent */
61: #endif
62: if (!user_name)
63: user_name = user_real_name;
64:
65: if (strcmp (user_name, user_real_name))
66: pw = (struct passwd *) getpwnam (user_name);
67:
68: #ifndef AMPERSAND_FULL_NAME
69: if (pw == 0)
70: strcpy (user_full_name, "unknown");
71: else
72: strncpy (user_full_name, USER_FULL_NAME, sizeof user_full_name);
73: p = index (user_full_name, ',');
74: if (p) *p = 0;
75: #else
76: if (pw == 0)
77: p = "unknown";
78: else
79: p = USER_FULL_NAME;
80: q = user_full_name; r = user_name; first = 1;
81:
82: for (; (*p != 0) && (*p != ','); p++)
83: {
84: if (*p == '&')
85: {
86: if (*r != 0)
87: {
88: *q = *r++;
89: if ((*q >= 'a') && (*q <= 'z'))
90: *q -= 32;
91: for (q++; *r != 0; r++)
92: {
93: if (q == &user_full_name[sizeof user_full_name - 1])
94: break;
95: *q++ = *r;
96: }
97: }
98: }
99: else
100: *q++ = *p;
101: if (q == &user_full_name[sizeof user_full_name - 2])
102: break;
103: }
104: *q = 0;
105: #endif /* AMPERSAND_FULL_NAME */
106:
107: p = (char *) get_system_name ();
108: if (p == 0 || *p == 0)
109: p = "Bogus System Name";
110: strncpy (system_name, p, sizeof system_name);
111: p = system_name;
112: while (*p)
113: {
114: if (*p < ' ')
115: *p = 0;
116: else
117: if (*p == ' ')
118: *p = '-';
119: p++;
120: }
121: }
122:
123: DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
124: "Convert arg CHAR to a string containing that character.")
125: (n)
126: Lisp_Object n;
127: {
128: char c;
129: CHECK_NUMBER (n, 0);
130:
131: c = XINT (n);
132: return make_string (&c, 1);
133: }
134:
135: DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
136: "Convert arg STRING to a character, the first character of that string.")
137: (str)
138: Lisp_Object str;
139: {
140: Lisp_Object val;
141: CHECK_STRING (str, 0);
142:
143: if (XSTRING (str)->size)
144: XFASTINT (val) = ((unsigned char *) XSTRING (str)->data)[0];
145: else
146: XFASTINT (val) = 0;
147: return val;
148: }
149:
150: static Lisp_Object
151: buildmark (val)
152: {
153: Lisp_Object mark;
154: mark = Fmake_marker ();
155: Fset_marker (mark, make_number (val), Qnil);
156: return mark;
157: }
158:
159: DEFSIMPLE ("point", Fpoint, Spoint,
160: "Return value of point, as an integer.\n\
161: Beginning of buffer is position (point-min)",
162: Lisp_Int, XSETINT, point)
163:
164: DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
165: "Return value of point, as a marker object.")
166: ()
167: {
168: return buildmark (point);
169: }
170:
171: DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "nGoto char: ",
172: "One arg, a number. Set point to that number.\n\
173: Beginning of buffer is position (point-min), end is (point-max).")
174: (n)
175: Lisp_Object n;
176: {
177: int charno;
178: CHECK_NUMBER_COERCE_MARKER (n, 0);
179: charno = XINT (n);
180: if (charno < FirstCharacter) charno = FirstCharacter;
181: if (charno > NumCharacters) charno = NumCharacters + 1;
182: SetPoint (charno);
183: return n;
184: }
185:
186: DEFUN ("region-beginning", Fregion_beginning, Sregion_beginning, 0, 0, 0,
187: "Return position of beginning of region, as an integer.")
188: ()
189: {
190: register int tem;
191: if (NULL (bf_cur->mark))
192: error ("There is no region now");
193: tem = marker_position (bf_cur->mark);
194: return make_number (min (point, tem));
195: }
196:
197: DEFUN ("region-end", Fregion_end, Sregion_end, 0, 0, 0,
198: "Return position of end of region, as an integer.")
199: ()
200: {
201: register int tem;
202: if (NULL (bf_cur->mark))
203: error ("There is no region now");
204: tem = marker_position (bf_cur->mark);
205: return make_number (max (point, tem));
206: }
207:
208: DEFUN ("mark", Fmark, Smark, 0, 0, 0,
209: "Return this buffer's mark value as integer, or nil if no mark.")
210: ()
211: {
212: if (!NULL (bf_cur->mark))
213: return Fmarker_position (bf_cur->mark);
214: return Qnil;
215: }
216:
217: DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
218: "Return this buffer's mark, as a marker object, or nil if no mark.\n\
219: Watch out! Moving this marker changes the buffer's mark.")
220: ()
221: {
222: return bf_cur->mark;
223: }
224:
225: DEFUN ("set-mark", Fset_mark, Sset_mark, 1, 1, "",
226: "Set this buffer's mark to POS;\n\
227: Argument is character position, or nil to clear out the mark.")
228: (pos)
229: Lisp_Object pos;
230: {
231: if (NULL (pos))
232: {
233: bf_cur->mark = Qnil;
234: return Qnil;
235: }
236: CHECK_NUMBER_COERCE_MARKER (pos, 0);
237:
238: if (NULL (bf_cur->mark))
239: bf_cur->mark = Fmake_marker ();
240:
241: Fset_marker (bf_cur->mark, pos, Qnil);
242: return pos;
243: }
244:
245: Lisp_Object
246: save_excursion_save ()
247: {
248: Lisp_Object oldpoint, oldmark;
249: int visible = XBUFFER (XWINDOW (selected_window)->buffer) == bf_cur;
250:
251: oldpoint = Fpoint_marker ();
252:
253: if (!NULL (bf_cur->mark))
254: oldmark = Fcopy_marker (bf_cur->mark);
255: else
256: oldmark = Qnil;
257:
258: return Fcons (oldpoint, Fcons (oldmark, visible ? Qt : Qnil));
259: }
260:
261: Lisp_Object
262: save_excursion_restore (info)
263: Lisp_Object info;
264: {
265: Lisp_Object tem;
266:
267: tem = Fmarker_buffer (Fcar (info));
268: /* If buffer being returned to is now deleted, avoid error */
269: /* Otherwise could get error here while unwinding to top level
270: and crash */
271: /* In that case, Fmarker_buffer returns nil now. */
272: if (NULL (tem))
273: return Qnil;
274: Fset_buffer (tem);
275: Fgoto_char (Fcar (info));
276: unchain_marker (Fcar (info));
277: tem = Fcar (Fcdr (info));
278: Fset_mark (tem);
279: if (!NULL (tem))
280: unchain_marker (tem);
281: tem = Fcdr (Fcdr (info));
282: if (!NULL (tem) && bf_cur != XBUFFER (XWINDOW (selected_window)->buffer))
283: Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
284: return Qnil;
285: }
286:
287: DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
288: "Save point (and mark), execute BODY, then restore point and mark.\n\
289: Executes BODY just like PROGN. Point and mark values are restored\n\
290: even in case of abnormal exit (throw or error).")
291: (args)
292: Lisp_Object args;
293: {
294: Lisp_Object val;
295: int count = specpdl_ptr - specpdl;
296:
297: record_unwind_protect (save_excursion_restore, save_excursion_save ());
298:
299: val = Fprogn (args);
300: unbind_to (count);
301: return val;
302: }
303:
304: DEFSIMPLE ("buffer-size", Fbufsize, Sbufsize,
305: "Return the number of characters in the current buffer.",
306: Lisp_Int, XSETINT, bf_s1 + bf_s2)
307:
308: DEFSIMPLE ("point-min", Fpoint_min, Spoint_min,
309: "Return the minimum permissible value of point in the current buffer.\n\
310: This is 1, unless a clipping restriction is in effect.",
311: Lisp_Int, XSETINT, FirstCharacter)
312:
313: DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 0, 0,
314: "Return a marker to the beginning of the currently visible part of the buffer.\n\
315: This is the beginning, unless a clipping restriction is in effect.")
316: ()
317: {
318: return buildmark (FirstCharacter);
319: }
320:
321: DEFSIMPLE ("point-max", Fpoint_max, Spoint_max,
322: "Return the maximum permissible value of point in the current buffer.\n\
323: This is (1+ (buffer-size)), unless a clipping restriction is in effect,\n\
324: in which case it is less.",
325: Lisp_Int, XSETINT, NumCharacters+1)
326:
327: DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 0, 0,
328: "Return a marker to the end of the currently visible part of the buffer.\n\
329: This is the actual end, unless a clipping restriction is in effect.")
330: ()
331: {
332: return buildmark (NumCharacters+1);
333: }
334:
335: DEFSIMPLE ("following-char", Ffollchar, Sfollchar,
336: "Return the character following point, as a number.",
337: Lisp_Int, XSETINT, point>NumCharacters ? 0 : CharAt(point))
338: DEFSIMPLE ("preceding-char", Fprevchar, Sprevchar,
339: "Return the character preceding point, as a number.",
340: Lisp_Int, XSETINT, point<=FirstCharacter ? 0 : CharAt(point-1))
341:
342: DEFPRED ("bobp", Fbobp, Sbobp,
343: "Return T if point is at the beginning of the buffer.\n\
344: If the buffer is narrowed, this means the beginning of the narrowed part.",
345: point<=FirstCharacter)
346: DEFPRED ("eobp", Feobp, Seobp,
347: "Return T if point is at the end of the buffer.\n\
348: If the buffer is narrowed, this means the end of the narrowed part.",
349: point>NumCharacters)
350: DEFPRED ("bolp", Fbolp, Sbolp,
351: "Return T if point is at the beginning of a line.",
352: point<=FirstCharacter || CharAt(point-1)=='\n')
353: DEFPRED ("eolp", Feolp, Seolp,
354: "Return T if point is at the end of a line.\n\
355: `End of a line' includes point being at the end of the buffer.",
356: point>NumCharacters || CharAt(point)=='\n')
357:
358: DEFUN ("char-after", Fchar_after, Schar_after, 1, 1, 0,
359: "One arg, POS, a number. Return the character in the current buffer\n\
360: at position POS.\n\
361: If POS is out of range, the value is NIL.")
362: (pos)
363: Lisp_Object pos;
364: {
365: Lisp_Object val;
366: CHECK_NUMBER_COERCE_MARKER (pos, 0);
367: if (XINT (pos) < FirstCharacter || XINT (pos) > NumCharacters) return Qnil;
368:
369: XFASTINT (val) = CharAt(XINT (pos));
370: return val;
371: }
372:
373: DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 0, "",
374: "Return the name under which user logged in, as a string.")
375: ()
376: {
377: return build_string (user_name);
378: }
379:
380: DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
381: 0, 0, "",
382: "Return the name of the user's real uid, as a string.\n\
383: Differs from user-login-name when running under su.")
384: ()
385: {
386: return build_string (user_real_name);
387: }
388:
389: DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 0, "",
390: "Return the full name of the user logged in, as a string.")
391: ()
392: {
393: return build_string (user_full_name);
394: }
395:
396: DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, "",
397: "Return the name of the machine you are running on, as a string.")
398: ()
399: {
400: return build_string (system_name);
401: }
402:
403: DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 0, 0,
404: "Return the current time, as a human-readable string.")
405: ()
406: {
407: long now = time ( (long *) 0);
408: char *tem = (char *) ctime (&now);
409: tem [24] = 0;
410: return build_string (tem);
411: }
412:
413: DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
414: "Any number of args, strings or chars. Insert them after point, moving point forward.")
415: (nargs, args)
416: int nargs;
417: Lisp_Object *args;
418: {
419: int argnum;
420: Lisp_Object tem;
421: char str[1];
422:
423: for (argnum = 0; argnum < nargs; argnum++)
424: {
425: tem = args[argnum];
426: retry:
427: if (XTYPE (tem) == Lisp_Int)
428: {
429: str[0] = XINT (tem);
430: InsCStr (str, 1);
431: }
432: else if (XTYPE (tem) == Lisp_String)
433: {
434: InsCStr (XSTRING (tem)->data, XSTRING (tem)->size);
435: }
436: else
437: {
438: tem = wrong_type_argument (Qchar_or_string_p, tem);
439: goto retry;
440: }
441: }
442: return Qnil;
443: }
444:
445: DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0,
446: "Any number of args, strings or chars. Insert them after point,\n\
447: moving point forward. Also, any markers pointing at the insertion point\n\
448: get relocated to point after the newly inserted text.")
449: (nargs, args)
450: int nargs;
451: Lisp_Object *args;
452: {
453: int argnum;
454: Lisp_Object tem;
455: char str[1];
456:
457: for (argnum = 0; argnum < nargs; argnum++)
458: {
459: tem = args[argnum];
460: retry:
461: if (XTYPE (tem) == Lisp_Int)
462: {
463: str[0] = XINT (tem);
464: insert_before_markers (str, 1);
465: }
466: else if (XTYPE (tem) == Lisp_String)
467: {
468: insert_before_markers (XSTRING (tem)->data, XSTRING (tem)->size);
469: }
470: else
471: {
472: tem = wrong_type_argument (Qchar_or_string_p, tem);
473: goto retry;
474: }
475: }
476: return Qnil;
477: }
478:
479: /* Return a string with the contents of the current region */
480:
481: DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
482: "Return the contents of part of the current buffer as a string.\n\
483: The two arguments specify the start and end, as character numbers.")
484: (b, e)
485: Lisp_Object b, e;
486: {
487: int beg, end;
488:
489: validate_region (&b, &e);
490: beg = XINT (b);
491: end = XINT (e);
492:
493: if (beg <= bf_s1 && end > bf_s1)
494: GapTo (beg);
495: return make_string (&CharAt (beg), end - beg);
496: }
497:
498: DEFUN ("buffer-string", Fbuffer_string, Sbuffer_string, 0, 0, 0,
499: "Return the contents of the current buffer as a string.")
500: ()
501: {
502: if (FirstCharacter <= bf_s1 && NumCharacters + 1 > bf_s1)
503: GapTo (FirstCharacter);
504: return make_string (&CharAt (FirstCharacter), NumCharacters + 1 - FirstCharacter);
505: }
506:
507: DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
508: 1, 3, 0,
509: "Insert before point a substring of the contents buffer BUFFER.\n\
510: BUFFER may be a buffer or a buffer name.\n\
511: Arguments START and END are character numbers specifying the substring.\n\
512: They default to the beginning and the end of BUFFER.")
513: (buf, b, e)
514: Lisp_Object buf, b, e;
515: {
516: int beg, end, exch;
517:
518: buf = Fget_buffer (buf);
519: if (XBUFFER (buf) == bf_cur)
520: error ("Cannot insert buffer into itself");
521:
522: if (NULL (b))
523: beg = XBUFFER (buf)->text.head_clip - 1;
524: else
525: {
526: CHECK_NUMBER_COERCE_MARKER (b, 0);
527: beg = XINT (b) - 1;
528: }
529: if (NULL (e))
530: end = XBUFFER (buf)->text.size1 + XBUFFER (buf)->text.size2
531: - XBUFFER (buf)->text.tail_clip;
532: else
533: {
534: CHECK_NUMBER_COERCE_MARKER (e, 1);
535: end = XINT (e) - 1;
536: }
537:
538: if (beg > end)
539: exch = beg, beg = end, end = exch;
540:
541: if (!(XBUFFER (buf)->text.head_clip - 1 <= beg
542: && beg <= end
543: && end <= XBUFFER (buf)->text.size1 + XBUFFER (buf)->text.size2
544: - XBUFFER (buf)->text.tail_clip))
545: args_out_of_range (b, e);
546:
547: if (beg < XBUFFER (buf)->text.size1)
548: {
549: InsCStr (XBUFFER (buf)->text.p1 + 1 + beg, min (end, XBUFFER (buf)->text.size1) - beg);
550: beg = min (end, XBUFFER (buf)->text.size1);
551: }
552: if (beg < end)
553: InsCStr (XBUFFER (buf)->text.p2 + 1 + beg, end - beg);
554:
555: return Qnil;
556: }
557:
558: DEFUN ("subst-char-in-region", Fsubst_char_in_region,
559: Ssubst_char_in_region, 4, 5, 0,
560: "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\
561: If optional arg NOUNDO is non-nil, don't record this change for undo\n\
562: and don't mark the buffer as really changed.")
563: (start, end, fromchar, tochar, noundo)
564: Lisp_Object start, end, fromchar, tochar, noundo;
565: {
566: register int pos, stop, look;
567:
568: validate_region (&start, &end);
569: CHECK_NUMBER (fromchar, 2);
570: CHECK_NUMBER (tochar, 3);
571:
572: pos = XINT (start);
573: stop = XINT (end);
574: if (!NULL (bf_cur->read_only))
575: Fbarf_if_buffer_read_only();
576:
577: look = XINT (fromchar);
578:
579: while (pos < stop)
580: {
581: if (CharAt (pos) == look)
582: {
583: if (NULL (noundo))
584: RecordChange (pos, 1);
585: CharAt (pos) = XINT (tochar);
586: }
587: pos++;
588: }
589: modify_region (pos, stop);
590:
591: return Qnil;
592: }
593:
594: DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
595: "Delete the text between point and mark.\n\
596: When called from a program, expects two arguments,\n\
597: character numbers specifying the stretch to be deleted.")
598: (b, e)
599: Lisp_Object b, e;
600: {
601: validate_region (&b, &e);
602: del_range (XINT (b), XINT (e));
603: return Qnil;
604: }
605:
606: DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
607: "Remove restrictions from current buffer, allowing full text to be seen and edited.")
608: ()
609: {
610: bf_cur->text.head_clip = bf_head_clip = 1;
611: bf_cur->text.tail_clip = bf_tail_clip = 0;
612: clip_changed = 1;
613: return Qnil;
614: }
615:
616: DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 2, "r",
617: "Restrict editing in current buffer to text between present values of point and mark.\n\
618: Use widen to undo the effects of this command.\n\
619: Called non-interactively, takes two arguments; character numbers which\n\
620: specify the stretch to which to restrict.")
621: (b, e)
622: Lisp_Object b, e;
623: {
624: int i;
625:
626: CHECK_NUMBER_COERCE_MARKER (b, 0);
627: CHECK_NUMBER_COERCE_MARKER (e, 1);
628:
629: if (XINT (b) > XINT (e))
630: {
631: i = XFASTINT (b);
632: b = e;
633: XFASTINT (e) = i;
634: }
635:
636: if (!(1 <= XINT (b) && XINT (b) <= XINT (e)
637: && XINT (e) <= bf_s1 + bf_s2 + 1))
638: args_out_of_range (b, e);
639:
640: bf_cur->text.head_clip = bf_head_clip = XFASTINT (b);
641: bf_cur->text.tail_clip = bf_tail_clip = bf_s1 + bf_s2 + 1 - XFASTINT (e);
642: if (point < XFASTINT (b))
643: SetPoint (XFASTINT (b));
644: if (point > XFASTINT (e))
645: SetPoint (XFASTINT (e));
646: clip_changed = 1;
647: return Qnil;
648: }
649:
650: Lisp_Object
651: save_restriction_save ()
652: {
653: Lisp_Object ml, mh;
654: /* Note: I tried using markers here, but it does not win
655: because insertion at the end of the saved region
656: does not advance mh and is considered "outside" the saved region. */
657: XFASTINT (ml) = bf_head_clip;
658: XFASTINT (mh) = bf_tail_clip;
659:
660: return Fcons (Fcurrent_buffer (), Fcons (ml, mh));
661: }
662:
663: Lisp_Object
664: save_restriction_restore (data)
665: Lisp_Object data;
666: {
667: register struct buffer *old = bf_cur;
668: register int newhead, newtail;
669:
670: Fset_buffer (XCONS (data)->car);
671:
672: data = XCONS (data)->cdr;
673:
674: newhead = XINT (XCONS (data)->car);
675: newtail = XINT (XCONS (data)->cdr);
676: if (newhead + newtail > bf_s1 + bf_s2 + 1)
677: {
678: newhead = 1;
679: newtail = 0;
680: }
681: bf_cur->text.head_clip = bf_head_clip = newhead;
682: bf_cur->text.tail_clip = bf_tail_clip = newtail;
683: clip_changed = 1;
684:
685: /* If point is outside the new visible range, move it inside. */
686: if (point < FirstCharacter)
687: SetPoint (FirstCharacter);
688: if (point > NumCharacters+1)
689: SetPoint (NumCharacters+1);
690:
691: SetBfp (old);
692: return Qnil;
693: }
694:
695: DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
696: "Execute the body, undoing at the end any changes to current buffer's restrictions.\n\
697: Changes to restrictions are made by narrow-to-region or by widen.\n\
698: Thus, the restrictions are the same after this function as they were before it.\n\
699: The value returned is that returned by the last form in the body.\n\
700: \n\
701: This function can be confused if, within the body, you widen\n\
702: and then make changes outside the area within the saved restrictions.\n\
703: \n\
704: Note: if you are using both save-excursion and save-restriction,\n\
705: use save-excursion outermost.")
706: (body)
707: Lisp_Object body;
708: {
709: Lisp_Object val;
710: int count = specpdl_ptr - specpdl;
711:
712: record_unwind_protect (save_restriction_restore, save_restriction_save ());
713: val = Fprogn (body);
714: unbind_to (count);
715: return val;
716: }
717:
718: DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
719: "Print a one-line message at the bottom of the screen.\n\
720: The first argument is a control string.\n\
721: It may contain %s or %d or %c to print successive following arguments.\n\
722: %s means print an argument as a string, %d means print as number in decimal,\n\
723: %c means print a number as a single character.\n\
724: The argument used by %s must be a string or a symbol;\n\
725: the argument used by %d or %c must be a number.")
726: (nargs, args)
727: int nargs;
728: Lisp_Object *args;
729: {
730: Lisp_Object val;
731:
732: val = Fformat (nargs, args);
733: message ("%s", XSTRING (val)->data);
734: return val;
735: }
736:
737: DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
738: "Format a string out of a control-string and arguments.\n\
739: The first argument is a control string.\n\
740: It, and subsequent arguments substituted into it, become the value, which is a string.\n\
741: It may contain %s or %d or %c to substitute successive following arguments.\n\
742: %s means print an argument as a string, %d means print as number in decimal,\n\
743: %c means print a number as a single character.\n\
744: The argument used by %s must be a string or a symbol;\n\
745: the argument used by %d, %b, %o, %x or %c must be a number.")
746: (nargs, args)
747: int nargs;
748: register Lisp_Object *args;
749: {
750: register int i;
751: register int total = 5;
752: char *buf;
753: register unsigned char **strings = (unsigned char **) alloca (nargs * sizeof (char *));
754:
755: for (i = 0; i < nargs; i++)
756: {
757: if (XTYPE (args[i]) == Lisp_Symbol)
758: {
759: strings[i] = XSYMBOL (args[i])->name->data;
760: total += XSYMBOL (args[i])->name->size;
761: }
762: else if (XTYPE (args[i]) == Lisp_String)
763: {
764: strings[i] = XSTRING (args[i])->data;
765: total += XSTRING (args[i])->size;
766: }
767: else if (XTYPE (args[i]) == Lisp_Int)
768: {
769: strings[i] = (unsigned char *) XINT (args[i]);
770: total += 10;
771: }
772: else
773: {
774: strings[i] = (unsigned char *) "??";
775: total += 2;
776: }
777: }
778:
779: /* Format it in bigger and bigger buf's until it all fits. */
780:
781: while (1)
782: {
783: buf = (char *) alloca (total + 1);
784: buf[total - 1] = 0;
785:
786: doprnt (buf, total + 1, strings[0], strings + 1);
787: if (buf[total - 1] == 0)
788: break;
789:
790: total *= 2;
791: }
792:
793: return build_string (buf);
794: }
795:
796: /* VARARGS 1 */
797: Lisp_Object
798: #ifdef NO_ARG_ARRAY
799: format1 (string1, arg0, arg1, arg2, arg3, arg4)
800: Lisp_Object arg0, arg1, arg2, arg3, arg4;
801: #else
802: format1 (string1)
803: #endif
804: char *string1;
805: {
806: char buf[100];
807: #ifdef NO_ARG_ARRAY
808: Lisp_Object args[5];
809: args[0] = arg0;
810: args[1] = arg1;
811: args[2] = arg2;
812: args[3] = arg3;
813: args[4] = arg4;
814: doprnt (buf, sizeof buf, string1, args);
815: #else
816: doprnt (buf, sizeof buf, string1, &string1 + 1);
817: #endif
818: return build_string (buf);
819: }
820:
821: DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
822: "T if args (both characters (numbers)) match. May ignore case.\n\
823: Case is ignored if the current buffer specifies to do so.")
824: (c1, c2)
825: Lisp_Object c1, c2;
826: {
827: extern char downcase_table[]; /* From search.c */
828:
829: CHECK_NUMBER (c1, 0);
830: CHECK_NUMBER (c2, 1);
831:
832: if (!NULL (bf_cur->case_fold_search)
833: ? downcase_table[XINT (c1)] == downcase_table[XINT (c2)]
834: : XINT (c1) == XINT (c2))
835: return Qt;
836: return Qnil;
837: }
838:
839: DEFUN ("getenv", Fgetenv, Sgetenv, 1, 1, "sEnvironment variable: ",
840: "One arg VAR, a string. Return the value of environment variable VAR, as a string.")
841: (str)
842: Lisp_Object str;
843: {
844: char *val;
845: CHECK_STRING (str, 0);
846: val = (char *) getenv (XSTRING (str)->data);
847: if (!val)
848: return Qnil;
849: return build_string (val);
850: }
851:
852: void
853: syms_of_editfns ()
854: {
855: defsubr (&Schar_equal);
856: defsubr (&Sgoto_char);
857: defsubr (&Sstring_to_char);
858: defsubr (&Schar_to_string);
859: defsubr (&Sbuffer_substring);
860: defsubr (&Sbuffer_string);
861:
862: defsubr (&Spoint_marker);
863: defalias (&Spoint_marker, "dot-marker");
864: defsubr (&Smark_marker);
865: defsubr (&Spoint);
866: defalias (&Spoint, "dot");
867: defsubr (&Sregion_beginning);
868: defsubr (&Sregion_end);
869: defsubr (&Smark);
870: defsubr (&Sset_mark);
871: defsubr (&Ssave_excursion);
872:
873: defsubr (&Sbufsize);
874: defsubr (&Spoint_max);
875: defsubr (&Spoint_min);
876: defalias (&Spoint_max, "dot-max");
877: defalias (&Spoint_min, "dot-min");
878: defsubr (&Spoint_min_marker);
879: defsubr (&Spoint_max_marker);
880:
881: defsubr (&Sbobp);
882: defsubr (&Seobp);
883: defsubr (&Sbolp);
884: defsubr (&Seolp);
885: defsubr (&Sfollchar);
886: defsubr (&Sprevchar);
887: defsubr (&Schar_after);
888: defsubr (&Sinsert);
889: defsubr (&Sinsert_before_markers);
890:
891: defsubr (&Suser_login_name);
892: defsubr (&Suser_real_login_name);
893: defsubr (&Suser_full_name);
894: defsubr (&Scurrent_time_string);
895: defsubr (&Sgetenv);
896: defsubr (&Ssystem_name);
897: defsubr (&Smessage);
898: defsubr (&Sformat);
899:
900: defsubr (&Sinsert_buffer_substring);
901: defsubr (&Ssubst_char_in_region);
902: defsubr (&Sdelete_region);
903: defsubr (&Swiden);
904: defsubr (&Snarrow_to_region);
905: defsubr (&Ssave_restriction);
906: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.