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