Annotation of 43BSDReno/contrib/emacs-18.55/src/editfns.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.