|
|
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.