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: }