Annotation of GNUtools/emacs/src/editfns.c, revision 1.1.1.1

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 (&current_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: }

unix.superglobalmegacorp.com

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