home *** CD-ROM | disk | FTP | other *** search
- /* Lisp functions pertaining to editing.
- Copyright (C) 1985-1987, 1989, 1992-1994 Free Software Foundation, Inc.
- Copyright (C) 1994, 1995 Amdahl Corporation.
- Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Mule 2.0, FSF 19.28. */
-
- /* This file has been Mule-ized except as noted. */
-
- /* Hacked on for Mule by Ben Wing, December 1994. */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "buffer.h"
- #include "commands.h"
- #include "events.h" /* for EVENTP */
- #include "extents.h"
- #include "frame.h"
- #include "insdel.h"
- #include "window.h"
-
- #include "systime.h"
- #include "sysdep.h"
- #include "syspwd.h"
-
- /* Some static data, and a function to initialize it for each run */
-
- Lisp_Object Vsystem_name; /* >>>> - I don't see why this should be */
- /* static, either... --Stig */
- #if 0 /* XEmacs - this is now dynamic */
- /* if at some point it's deemed desirable to
- use lisp variables here, then they can be
- initialized to nil and then set to their
- real values upon the first call to the
- functions that generate them. --stig */
- Lisp_Object Vuser_real_name; /* login name of current user ID */
- Lisp_Object Vuser_full_name; /* full name of current user */
- Lisp_Object Vuser_name; /* user name from LOGNAME or USER. */
- #endif
-
- extern char *get_system_name (void);
-
- Lisp_Object Qformat;
-
- Lisp_Object Qpoint, Qmark, Qregion_beginning, Qregion_end;
-
- void
- init_editfns (void)
- {
- /* Only used in removed code below. */
- #if 0
- char *user_name;
- Bufbyte *p, *q;
- struct passwd *pw; /* password entry for the current user */
- Lisp_Object tem;
- #endif
-
- /* Set up system_name even when dumping. */
- init_system_name ();
-
- #if 0 /* this is now dynamic */
- /* don't lose utterly if someone uses these during loadup. */
- Vuser_real_name = Qnil;
- Vuser_name = Qnil;
- Vuser_full_name = Qnil;
-
- #ifndef CANNOT_DUMP
- /* Don't bother with this on initial start when just dumping out */
- if (!initialized)
- return;
- #endif /* not CANNOT_DUMP */
-
- pw = (struct passwd *) getpwuid (getuid ());
- Vuser_real_name = build_string (pw ? pw->pw_name : "unknown");
-
- /* Get the effective user name, by consulting environment variables,
- or the effective uid if those are unset. */
- user_name = getenv ("LOGNAME");
- if (!user_name)
- user_name = getenv ("USER");
- if (!user_name)
- {
- /* #### - do we really want the EFFECTIVE uid here? Are these flipped? */
- /* I ask because LOGNAME and USER vars WILL NOT MATCH the euid. --Stig */
- pw = (struct passwd *) getpwuid (geteuid ());
- user_name = (char *) (pw ? pw->pw_name : "unknown");
- }
- Vuser_name = build_string (user_name);
-
- /* If the user name claimed in the environment vars differs from
- the real uid, use the claimed name to find the full name. */
- tem = Fstring_equal (Vuser_name, Vuser_real_name);
- if (NILP (tem))
- {
- /* Jamie reports that IRIX gets wedged by SIGIO/SIGALARM occurring
- in select(), called from getpwnam(). */
- slow_down_interrupts ();
- pw = (struct passwd *)
- getpwnam ((char *) string_data (XSTRING (Vuser_name)));
- speed_up_interrupts ();
- }
-
- p = (Bufbyte *) ((pw) ? USER_FULL_NAME : "unknown"); /* don't gettext here */
- q = (Bufbyte *) strchr ((char *) p, ',');
- Vuser_full_name = make_string (p, (q ? q - p : strlen ((char *) p)));
-
- #ifdef AMPERSAND_FULL_NAME
- p = string_data (XSTRING (Vuser_full_name));
- q = (Bufbyte *) strchr ((char *) p, '&');
- /* Substitute the login name for the &, upcasing the first character. */
- if (q)
- {
- char *r = (char *)
- alloca (strlen ((char *) p) + string_length (XSTRING (Vuser_name)) +
- 1);
- Charcount fullname_off = bytecount_to_charcount (p, q - p);
- memcpy (r, p, q - p);
- r[q - p] = 0;
- strcat (r, (char *) string_data (XSTRING (Vuser_name)));
- strcat (r, q + 1);
- Vuser_full_name = build_string (r);
- set_string_char (XSTRING (Vuser_full_name), fullname_off,
- UPCASE (current_buffer,
- string_char (XSTRING (Vuser_full_name),
- fullname_off)));
- }
- #endif /* AMPERSAND_FULL_NAME */
- #endif /* 0 */
- }
-
- DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
- "Convert arg CH to a one-character string containing that character.")
- (ch)
- Lisp_Object ch;
- {
- Bytecount len;
- Bufbyte str[MAX_EMCHAR_LEN];
-
- if (EVENTP (ch))
- {
- Lisp_Object ch2 = Fevent_to_character (ch, Qt, Qnil, Qnil);
- if (NILP (ch2))
- return
- signal_simple_continuable_error
- ("character has no ASCII equivalent:", Fcopy_event (ch, Qnil));
- ch = ch2;
- }
-
- CHECK_COERCE_CHAR (ch, 0);
-
- len = emchar_to_charptr (XINT (ch), str);
- return make_string (str, len);
- }
-
- DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
- "Convert arg STRING to a character, the first character of that string.")
- (str)
- Lisp_Object str;
- {
- struct Lisp_String *p;
- CHECK_STRING (str, 0);
-
- p = XSTRING (str);
- if (string_length (p) != 0)
- {
- return (make_number (string_char (p, 0)));
- }
- else /* #### Gag me! */
- return (Qzero);
- }
-
-
- static Lisp_Object
- buildmark (Bufpos val)
- {
- Lisp_Object mark;
- mark = Fmake_marker ();
- Fset_marker (mark, make_number (val), Qnil);
- return mark;
- }
-
- DEFUN ("point", Fpoint, Spoint, 0, 1, 0,
- "Return value of point, as an integer.\n\
- Beginning of buffer is position (point-min).\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- return (make_number (BUF_PT (b)));
- }
-
- DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 2, 0,
- "Return value of point, as a marker object.\n\
- This marker is a copy; you may modify it with reckless abandon.\n\
- If the argument to this function is non-nil, then it returns the real\n\
- point-marker; modifying the position of this marker will move point.\n\
- It is illegal to change the buffer of it, or make it point nowhere.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (dont_copy_p, buffer)
- Lisp_Object dont_copy_p, buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- if (NILP (dont_copy_p))
- return Fcopy_marker (b->point_marker);
- return b->point_marker;
- }
-
- /* The following two functions end up being identical but it's
- cleaner to declare them separately. */
-
- Bufpos
- bufpos_clip_to_bounds (Bufpos lower, Bufpos num, Bufpos upper)
- {
- if (num < lower)
- return lower;
- else if (num > upper)
- return upper;
- else
- return num;
- }
-
- Bytind
- bytind_clip_to_bounds (Bytind lower, Bytind num, Bytind upper)
- {
- if (num < lower)
- return lower;
- else if (num > upper)
- return upper;
- else
- return num;
- }
-
- /*
- * Chuck says:
- * There is no absolute way to determine if goto-char is the function
- * being run. this-command doesn't work because it is often eval'd
- * and this-command ends up set to eval-expression. So this flag gets
- * added for now.
- *
- * Jamie thinks he's wrong, but we'll leave this in for now.
- */
- int atomic_extent_goto_char_p;
-
- DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 2, "NGoto char: ",
- "Set point to POSITION, a number or marker.\n\
- Beginning of buffer is position (point-min), end is (point-max).\n\
- If BUFFER is nil, the current buffer is assumed.\n\
- Return value of POSITION, as an integer.")
- (position, buffer)
- Lisp_Object position, buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- Bufpos n = get_bufpos (b, position, GB_COERCE_RANGE);
- BUF_SET_PT (b, n);
- atomic_extent_goto_char_p = 1;
- return (make_number (n));
- }
-
- static Lisp_Object
- region_limit (int beginningp, struct buffer *b)
- {
- Lisp_Object m;
-
- #if 0 /* FSFmacs */
- if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
- && NILP (b->mark_active))
- Fsignal (Qmark_inactive, Qnil);
- #endif
- m = Fmarker_position (b->mark);
- if (NILP (m)) error ("There is no region now");
- if (!!(BUF_PT (b) < XINT (m)) == !!beginningp)
- return (make_number (BUF_PT (b)));
- else
- return (m);
- }
-
- DEFUN ("region-beginning", Fregion_beginning, Sregion_beginning, 0, 1, 0,
- "Return position of beginning of region, as an integer.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- return (region_limit (1, decode_buffer (buffer, 1)));
- }
-
- DEFUN ("region-end", Fregion_end, Sregion_end, 0, 1, 0,
- "Return position of end of region, as an integer.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- return (region_limit (0, decode_buffer (buffer, 1)));
- }
-
- /* Whether to use lispm-style active-regions */
- int zmacs_regions;
-
- /* Whether the zmacs region is active. This is not per-buffer because
- there can be only one active region at a time. #### Now that the
- zmacs region are not directly tied to the X selections this may not
- necessarily have to be true. */
- int zmacs_region_active_p;
-
- int zmacs_region_stays;
-
- Lisp_Object Qzmacs_update_region, Qzmacs_deactivate_region;
-
- void
- zmacs_update_region (void)
- {
- /* This function can GC */
- if (zmacs_region_active_p)
- call0 (Qzmacs_update_region);
- }
-
- void
- zmacs_deactivate_region (void)
- {
- /* This function can GC */
- if (zmacs_region_active_p)
- call0 (Qzmacs_deactivate_region);
- }
-
- DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 2, 0,
- "Return this buffer's mark, as a marker object.\n\
- If `zmacs-regions' is true, then this returns nil unless the region is\n\
- currently in the active (highlighted) state. With an argument of t, this\n\
- returns the mark (if there is one) regardless of the zmacs-region state.\n\
- You should *generally* not use the mark unless the region is active, if\n\
- the user has expressed a preference for the zmacs-region model.\n\
- Watch out! Moving this marker changes the mark position.\n\
- If you set the marker not to point anywhere, the buffer will have no mark.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (inactive_p, buffer)
- Lisp_Object inactive_p, buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- if (! zmacs_regions || zmacs_region_active_p || !NILP (inactive_p))
- return b->mark;
- return Qnil;
- }
-
-
- Lisp_Object
- save_excursion_save (void)
- {
- struct buffer *b = current_buffer;
- int visible = (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer)
- == b);
- Lisp_Object tem = ((visible) ? Qt : Qnil);
-
- #ifdef ERROR_CHECK_BUFPOS
- assert (XINT (Fpoint (Qnil)) ==
- XINT (Fmarker_position (Fpoint_marker (Qt, Qnil))));
- #endif
-
- #if 0 /* FSFmacs */
- tem = Fcons (tem, b->mark_active);
- #endif
-
- return Fcons (Fpoint_marker (Qnil, Qnil),
- Fcons (Fcopy_marker (b->mark),
- tem));
- }
-
- Lisp_Object
- save_excursion_restore (Lisp_Object info)
- {
- Lisp_Object tem;
- int visible;
- struct gcpro gcpro1, gcpro2;
-
- tem = Fmarker_buffer (Fcar (info));
- /* If buffer being returned to is now deleted, avoid error */
- /* Otherwise could get error here while unwinding to top level
- and crash */
- /* In that case, Fmarker_buffer returns nil now. */
- if (NILP (tem))
- return Qnil;
- /* Need gcpro in case Lisp hooks get run */
- GCPRO2 (info, tem);
- Fset_buffer (tem);
- tem = Fcar (info);
- Fgoto_char (tem, Fcurrent_buffer ());
- unchain_marker (tem);
- tem = Fcar (Fcdr (info));
- Fset_marker (current_buffer->mark, tem, Fcurrent_buffer ());
- unchain_marker (tem);
- tem = Fcdr (Fcdr (info));
- visible = !NILP (tem);
-
- #if 0 /* We used to make the current buffer visible in the selected window
- if that was true previously. That avoids some anomalies.
- But it creates others, and it wasn't documented, and it is simpler
- and cleaner never to alter the window/buffer connections. */
- /* #### I'm certain some code somewhere depends on this behavior. --jwz */
-
- if (visible
- && (current_buffer != XBUFFER (XWINDOW (selected_window)->buffer)))
- Fswitch_to_buffer (Fcurrent_buffer (), Qnil);
- #endif
-
-
- while (CONSP (info))
- {
- struct Lisp_Cons *victim = XCONS (info);
- info = victim->cdr;
- free_cons (victim);
- }
- UNGCPRO;
- return Qnil;
- }
-
- DEFUN ("save-excursion", Fsave_excursion, Ssave_excursion, 0, UNEVALLED, 0,
- "Save point, mark, and current buffer; execute BODY; restore those things.\n\
- Executes BODY just like `progn'.\n\
- The values of point, mark and the current buffer are restored\n\
- even in case of abnormal exit (throw or error).")
- (args)
- Lisp_Object args;
- {
- /* This function can GC */
- int speccount = specpdl_depth ();
-
- record_unwind_protect (save_excursion_restore, save_excursion_save ());
-
- return unbind_to (speccount, Fprogn (args));
- }
-
- DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 1, 0,
- "Return the number of characters in BUFFER.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- return (make_number (BUF_SIZE (b)));
- }
-
- DEFUN ("point-min", Fpoint_min, Spoint_min, 0, 1, 0,
- "Return the minimum permissible value of point in BUFFER.\n\
- This is 1, unless narrowing (a buffer restriction) is in effect.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- return (make_number (BUF_BEGV (b)));
- }
-
- DEFUN ("point-min-marker", Fpoint_min_marker, Spoint_min_marker, 0, 1, 0,
- "Return a marker to the minimum permissible value of point in BUFFER.\n\
- This is the beginning, unless narrowing (a buffer restriction) is in effect.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- return buildmark (BUF_BEGV (b));
- }
-
- DEFUN ("point-max", Fpoint_max, Spoint_max, 0, 1, 0,
- "Return the maximum permissible value of point in BUFFER.\n\
- This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
- is in effect, in which case it is less.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- return (make_number (BUF_ZV (b)));
- }
-
- DEFUN ("point-max-marker", Fpoint_max_marker, Spoint_max_marker, 0, 1, 0,
- "Return a marker to the maximum permissible value of point BUFFER.\n\
- This is (1+ (buffer-size)), unless narrowing (a buffer restriction)\n\
- is in effect, in which case it is less.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- return buildmark (BUF_ZV (b));
- }
-
- DEFUN ("following-char", Ffollowing_char, Sfollowing_char, 0, 1, 0,
- "Return the character following point, as a number.\n\
- At the end of the buffer or accessible region, return 0.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- if (BUF_PT (b) >= BUF_ZV (b))
- return (Qzero); /* #### Gag me! */
- else
- return (make_number (BUF_FETCH_CHAR (b, BUF_PT (b))));
- }
-
- DEFUN ("preceding-char", Fprevious_char, Sprevious_char, 0, 1, 0,
- "Return the character preceding point, as a number.\n\
- At the beginning of the buffer or accessible region, return 0.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- if (BUF_PT (b) <= BUF_BEGV (b))
- return (Qzero); /* #### Gag me! */
- else
- return (make_number (BUF_FETCH_CHAR (b, BUF_PT (b) - 1)));
- }
-
- DEFUN ("bobp", Fbobp, Sbobp, 0, 1, 0,
- "Return T if point is at the beginning of the buffer.\n\
- If the buffer is narrowed, this means the beginning of the narrowed part.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- if (BUF_PT (b) == BUF_BEGV (b))
- return Qt;
- return Qnil;
- }
-
- DEFUN ("eobp", Feobp, Seobp, 0, 1, 0,
- "Return T if point is at the end of the buffer.\n\
- If the buffer is narrowed, this means the end of the narrowed part.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- if (BUF_PT (b) == BUF_ZV (b))
- return Qt;
- return Qnil;
- }
-
- DEFUN ("bolp", Fbolp, Sbolp, 0, 1, 0,
- "Return T if point is at the beginning of a line.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
-
- if (BUF_PT (b) == BUF_BEGV (b) || BUF_FETCH_CHAR (b, BUF_PT (b) - 1) == '\n')
- return Qt;
- return Qnil;
- }
-
- DEFUN ("eolp", Feolp, Seolp, 0, 1, 0,
- "Return T if point is at the end of a line.\n\
- `End of a line' includes point being at the end of the buffer.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- if (BUF_PT (b) == BUF_ZV (b) || BUF_FETCH_CHAR (b, BUF_PT (b)) == '\n')
- return Qt;
- return Qnil;
- }
-
- DEFUN ("char-after", Fchar_after, Schar_after, 1, 2, 0,
- "Return character in BUFFER at position POS.\n\
- POS is an integer or a buffer pointer.\n\
- If POS is out of range, the value is nil.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (pos, buffer)
- Lisp_Object pos, buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- Bufpos n = get_bufpos (b, pos, GB_NO_ERROR_IF_BAD);
-
- if (n == 0 || n == BUF_ZV (b))
- return Qnil;
- return (make_number (BUF_FETCH_CHAR (b, n)));
- }
-
-
- DEFUN ("user-login-name", Fuser_login_name, Suser_login_name, 0, 1, 0,
- "Return the name under which the user logged in, as a string.\n\
- This is based on the effective uid, not the real uid.\n\
- Also, if the environment variable LOGNAME or USER is set,\n\
- that determines the value of this function.\n\
- If the optional argument UID is present, then environment variables are\n\
- ignored and this function returns the login name for that UID, or nil.")
- (uid)
- Lisp_Object uid;
- {
- struct passwd *pw = NULL;
-
- if (!NILP (uid))
- {
- CHECK_INT (uid, 0);
- pw = (struct passwd *) getpwuid (XINT (uid));
- }
- else
- {
- char *user_name;
- /* #### - when euid != uid, then LOGNAME and USER are leftovers from the
- old environment (I site observed behavior on sunos and linux), so the
- environment variables should be disregarded in that case. --Stig */
- user_name = getenv ("LOGNAME");
- if (!user_name)
- user_name = getenv ("USER");
- if (user_name)
- return (build_string (user_name));
- else
- pw = (struct passwd *) getpwuid (geteuid ());
- }
- /* #### - I believe this should return nil instead of "unknown" when pw==0 */
- return (pw ? build_string (pw->pw_name) : Qnil);
- }
-
- DEFUN ("user-real-login-name", Fuser_real_login_name, Suser_real_login_name,
- 0, 0, 0,
- "Return the name of the user's real uid, as a string.\n\
- This ignores the environment variables LOGNAME and USER, so it differs from\n\
- `user-login-name' when running under `su'.")
- ()
- {
- struct passwd *pw = (struct passwd *) getpwuid (getuid ());
- /* #### - I believe this should return nil instead of "unknown" when pw==0 */
- Lisp_Object tem = build_string (pw ? pw->pw_name : "unknown");/* no gettext */
- return (tem);
- }
-
- DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
- "Return the effective uid of Emacs, as an integer.")
- ()
- {
- return make_number (geteuid ());
- }
-
- DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
- "Return the real uid of Emacs, as an integer.")
- ()
- {
- return make_number (getuid ());
- }
-
- DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 1, 0,
- "Return the full name of the user logged in, as a string.\n\
- If the optional argument USER is given, then the full name for that\n\
- user is returned, or nil. USER may be either a login name or a uid.")
- (user)
- Lisp_Object user;
- {
- Lisp_Object uname = (STRINGP (user) ? user : Fuser_login_name (user));
- struct passwd *pw = NULL;
- Lisp_Object tem;
- char *p, *q;
-
- if (!NILP (uname)) /* nil when nonexistent UID passed as arg */
- {
- /* Fuck me. getpwnam() can call select() and (under IRIX at least)
- things get wedged if a SIGIO arrives during this time. */
- slow_down_interrupts ();
- pw = (struct passwd *) getpwnam (string_ext_data (XSTRING (uname)));
- speed_up_interrupts ();
- }
-
- /* #### - Stig sez: this should return nil instead of "unknown" when pw==0 */
- /* Ben sez: bad idea because it's likely to break something */
- #ifndef AMPERSAND_FULL_NAME
- p = (char *) ((pw) ? USER_FULL_NAME : "unknown"); /* don't gettext */
- q = (char *) strchr ((char *) p, ',');
- #else
- p = (char *) ((pw) ? USER_FULL_NAME : "unknown"); /* don't gettext */
- q = (char *) strchr ((char *) p, ',');
- #endif
- tem = ((!NILP (user) && !pw)
- ? Qnil
- : make_ext_string ((char *) p, (q ? q - p : strlen (p))));
-
- #ifdef AMPERSAND_FULL_NAME
- if (!NILP (tem))
- {
- p = (char *) string_data (XSTRING (tem));
- q = strchr (p, '&');
- /* Substitute the login name for the &, upcasing the first character. */
- if (q)
- {
- char *r = (char *) alloca (strlen (p) +
- string_length (XSTRING (uname)) + 1);
- memcpy (r, p, q - p);
- r[q - p] = 0;
- strcat (r, (char *) string_data (XSTRING (uname)));
- r[q - p] = UPCASE (r[q - p]);
- strcat (r, q + 1);
- tem = build_string (r);
- }
- }
- #endif /* AMPERSAND_FULL_NAME */
- return (tem);
- }
-
- DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
- "Return the name of the machine you are running on, as a string.")
- ()
- {
- return (Fcopy_sequence (Vsystem_name));
- }
-
- /* For the benefit of callers who don't want to include lisp.h.
- Caller must free! */
- char *
- get_system_name (void)
- {
- return xstrdup ((char *) string_data (XSTRING (Vsystem_name)));
- }
-
- DEFUN ("emacs-pid", Femacs_pid, Semacs_pid, 0, 0, 0,
- "Return the process ID of Emacs, as an integer.")
- ()
- {
- return make_number (getpid ());
- }
-
- DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
- "Return the current time, as the number of seconds since 12:00 AM January 1970.\n\
- The time is returned as a list of three integers. The first has the\n\
- most significant 16 bits of the seconds, while the second has the\n\
- least significant 16 bits. The third integer gives the microsecond\n\
- count.\n\
- \n\
- The microsecond count is zero on systems that do not provide\n\
- resolution finer than a second.")
- ()
- {
- EMACS_TIME t;
- Lisp_Object result[3];
-
- EMACS_GET_TIME (t);
- XSETINT (result[0], (EMACS_SECS (t) >> 16) & 0xffff);
- XSETINT (result[1], (EMACS_SECS (t) >> 0) & 0xffff);
- XSETINT (result[2], EMACS_USECS (t));
-
- return Flist (3, result);
- }
-
-
- int
- lisp_to_time (Lisp_Object specified_time, time_t *result)
- {
- if (NILP (specified_time))
- return time (result) != -1;
- else
- {
- Lisp_Object high, low;
- high = Fcar (specified_time);
- CHECK_INT (high, 0);
- low = Fcdr (specified_time);
- if (CONSP (low))
- low = Fcar (low);
- CHECK_INT (low, 0);
- *result = (XINT (high) << 16) + (XINT (low) & 0xffff);
- return *result >> 16 == XINT (high);
- }
- }
-
- Lisp_Object
- time_to_lisp (time_t the_time)
- {
- unsigned int item = (unsigned int) the_time;
- return Fcons (make_number (item >> 16), make_number (item & 0xffff));
- }
-
- DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
- "Return the current time, as a human-readable string.\n\
- Programs can use this function to decode a time,\n\
- since the number of columns in each field is fixed.\n\
- The format is `Sun Sep 16 01:03:52 1973'.\n\
- If an argument is given, it specifies a time to format\n\
- instead of the current time. The argument should have the form:\n\
- (HIGH . LOW)\n\
- or the form:\n\
- (HIGH LOW . IGNORED).\n\
- Thus, you can use times obtained from `current-time'\n\
- and from `file-attributes'.")
- (specified_time)
- Lisp_Object specified_time;
- {
- /* !!#### This function has not been Mule-ized. */
- time_t value;
- char buf[30];
- char *tem;
-
- if (! lisp_to_time (specified_time, &value))
- value = -1;
- tem = (char *) ctime (&value);
-
- strncpy (buf, tem, 24);
- buf[24] = 0;
-
- return build_string (buf);
- }
-
- DEFUN ("current-locale-time-string", Fcurrent_locale_time_string,
- Scurrent_locale_time_string, 0, 1, 0,
- "Return the current time, as a human-readable string.\n\
- Programs can use this function to decode a time,\n\
- since the number of columns in each field is fixed.\n\
- The format is `Sun Sep 16 01:03:52 1973'.\n\
- If an argument is given, it specifies a time to format\n\
- instead of the current time. The argument should have the form:\n\
- (HIGH . LOW)\n\
- or the form:\n\
- (HIGH LOW . IGNORED).\n\
- Thus, you can use times obtained from `current-time'\n\
- and from `file-attributes'.")
- (specified_time)
- Lisp_Object specified_time;
- {
- /* !!#### This function has not been Mule-ized. */
- #ifdef I18N2
- time_t value;
- char buf[301];
-
- if (! lisp_to_time (specified_time, &value))
- value = -1;
- /* #### should check the return value to see if we need more space?
- (highly unlikely) */
- strftime (buf, 300, "%c", localtime (&value));
-
- return build_string (buf);
- #else
- return Fcurrent_time_string (specified_time);
- #endif
- }
-
- #define TM_YEAR_ORIGIN 1900
-
- /* Yield A - B, measured in seconds. */
- static long
- difftm (CONST struct tm *a, CONST struct tm *b)
- {
- int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
- int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
- /* Some compilers can't handle this as a single return statement. */
- long days = (
- /* difference in day of year */
- a->tm_yday - b->tm_yday
- /* + intervening leap days */
- + ((ay >> 2) - (by >> 2))
- - (ay/100 - by/100)
- + ((ay/100 >> 2) - (by/100 >> 2))
- /* + difference in years * 365 */
- + (long)(ay-by) * 365
- );
- return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
- + (a->tm_min - b->tm_min))
- + (a->tm_sec - b->tm_sec));
- }
-
- DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 1, 0,
- "Return the offset and name for the local time zone.\n\
- This returns a list of the form (OFFSET NAME).\n\
- OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).\n\
- A negative value means west of Greenwich.\n\
- NAME is a string giving the name of the time zone.\n\
- If an argument is given, it specifies when the time zone offset is determined\n\
- instead of using the current time. The argument should have the form:\n\
- (HIGH . LOW)\n\
- or the form:\n\
- (HIGH LOW . IGNORED).\n\
- Thus, you can use times obtained from `current-time'\n\
- and from `file-attributes'.\n\
- \n\
- Some operating systems cannot provide all this information to Emacs;\n\
- in this case, `current-time-zone' returns a list containing nil for\n\
- the data it can't find.")
- (specified_time)
- Lisp_Object specified_time;
- {
- time_t value;
- struct tm *t;
-
- if (lisp_to_time (specified_time, &value)
- && (t = gmtime (&value)) != 0)
- {
- struct tm gmt;
- long offset;
- char *s, buf[6];
-
- gmt = *t; /* Make a copy, in case localtime modifies *t. */
- t = localtime (&value);
- offset = difftm (t, &gmt);
- s = 0;
- #ifdef HAVE_TM_ZONE
- if (t->tm_zone)
- s = (char *)t->tm_zone;
- #else /* not HAVE_TM_ZONE */
- #ifdef HAVE_TZNAME
- if (t->tm_isdst == 0 || t->tm_isdst == 1)
- s = tzname[t->tm_isdst];
- #endif
- #endif /* not HAVE_TM_ZONE */
- if (!s)
- {
- /* No local time zone name is available; use "+-NNNN" instead. */
- int am = (offset < 0 ? -offset : offset) / 60;
- sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
- s = buf;
- }
- return list2 (make_number (offset), build_string (s));
- }
- else
- return list2 (Qnil, Qnil);
- }
-
-
- void
- buffer_insert1 (struct buffer *buf, Lisp_Object arg)
- {
- /* This function can GC */
- struct gcpro gcpro1;
- GCPRO1 (arg);
- retry:
- if (INTP (arg))
- {
- buffer_insert_emacs_char (buf, XINT (arg));
- }
- else if (STRINGP (arg))
- {
- buffer_insert_lisp_string (buf, arg);
- }
- else
- {
- arg = wrong_type_argument (Qchar_or_string_p, arg);
- goto retry;
- }
- zmacs_region_stays = 0;
- UNGCPRO;
- }
-
-
- /* Callers passing one argument to Finsert need not gcpro the
- argument "array", since the only element of the array will
- not be used after calling insert_emacs_char or insert_lisp_string,
- so we don't care if it gets trashed. */
-
- DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0,
- "Insert the arguments, either strings or characters, at point.\n\
- Point moves forward so that it ends up after the inserted text.\n\
- Any other markers at the point of insertion remain before the text.\n\
- If a string has non-null string-extent-data, new extents will be created.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
- {
- /* This function can GC */
- REGISTER int argnum;
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- buffer_insert1 (current_buffer, args[argnum]);
- }
-
- return Qnil;
- }
-
- DEFUN ("insert-before-markers", Finsert_before_markers, Sinsert_before_markers, 0, MANY, 0,
- "Insert strings or characters at point, relocating markers after the text.\n\
- Point moves forward so that it ends up after the inserted text.\n\
- Any other markers at the point of insertion also end up after the text.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
- {
- /* This function can GC */
- REGISTER int argnum;
- REGISTER Lisp_Object tem;
-
- for (argnum = 0; argnum < nargs; argnum++)
- {
- tem = args[argnum];
- retry:
- if (INTP (tem))
- {
- buffer_insert_emacs_char_1 (current_buffer, -1, XINT (tem),
- INSDEL_BEFORE_MARKERS);
- }
- else if (STRINGP (tem))
- {
- buffer_insert_lisp_string_1 (current_buffer, -1, tem,
- INSDEL_BEFORE_MARKERS);
- }
- else
- {
- tem = wrong_type_argument (Qchar_or_string_p, tem);
- goto retry;
- }
- }
- zmacs_region_stays = 0;
- return Qnil;
- }
-
- DEFUN ("insert-string", Finsert_string, Sinsert_string, 1, 2, 0,
- "Insert STRING into BUFFER at BUFFER's point.\n\
- Point moves forward so that it ends up after the inserted text.\n\
- Any other markers at the point of insertion remain before the text.\n\
- If a string has non-null string-extent-data, new extents will be created.\n\
- BUFFER defaults to the current buffer.")
- (string, buffer)
- Lisp_Object string, buffer;
- {
- struct buffer *buf = decode_buffer (buffer, 1);
- CHECK_STRING (string, 0);
- buffer_insert_lisp_string (buf, string);
- zmacs_region_stays = 0;
- return Qnil;
- }
-
- /* Third argument in FSF is INHERIT:
-
- "The optional third arg INHERIT, if non-nil, says to inherit text properties\n\
- from adjoining text, if those properties are sticky."
-
- Jamie thinks this is bogus. */
-
-
- DEFUN ("insert-char", Finsert_char, Sinsert_char, 1, 3, 0,
- "Insert COUNT (second arg) copies of CHR (first arg).\n\
- Point and all markers are affected as in the function `insert'.\n\
- COUNT defaults to 1 if omitted.\n\
- The optional third arg BUFFER specifies the buffer to insert the\n\
- text into. If BUFFER is nil, the current buffer is assumed.")
- (chr, count, buffer)
- Lisp_Object chr, count, buffer;
- {
- /* This function can GC */
- REGISTER Bufbyte *string;
- REGISTER int strlen;
- REGISTER int i, j;
- REGISTER Bytecount n;
- REGISTER Bytecount charlen;
- Bufbyte str[MAX_EMCHAR_LEN];
- struct buffer *buf = decode_buffer (buffer, 1);
- int cou;
-
- CHECK_COERCE_CHAR (chr, 0);
- if (NILP (count))
- cou = 1;
- else
- {
- CHECK_INT (count, 1);
- cou = XINT (count);
- }
-
- charlen = emchar_to_charptr (XINT (chr), str);
- n = cou * charlen;
- if (n <= 0)
- return Qnil;
- strlen = min (n, 768);
- string = (Bufbyte *) alloca (strlen * sizeof (Bufbyte));
- /* Write as many copies of the character into the temp string as will fit. */
- for (i = 0; i + charlen <= strlen; i += charlen)
- for (j = 0; j < charlen; j++)
- string[i + j] = str[j];
- strlen = i;
- while (n >= strlen)
- {
- buffer_insert_raw_string (buf, string, strlen);
- n -= strlen;
- }
- if (n > 0)
- buffer_insert_raw_string (buf, string, n);
-
- zmacs_region_stays = 0;
- return Qnil;
- }
-
-
- /* Making strings from buffer contents. */
-
- DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 0, 3, 0,
- "Return the contents of part of BUFFER as a string.\n\
- The two arguments START and END are character positions;\n\
- they can be in either order. If omitted, they default to the beginning\n\
- and end of BUFFER, respectively.\n\
- If there are duplicable extents in the region, the string remembers\n\
- them in its string-extent-data.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (start, end, buffer)
- Lisp_Object start, end, buffer;
- {
- /* This function can GC */
- Bufpos begv, zv;
- struct buffer *b = decode_buffer (buffer, 1);
-
- get_bufrange (b, start, end, &begv, &zv, GB_ALLOW_NIL);
- return make_string_from_buffer (b, begv, zv - begv);
- }
-
- DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring,
- 1, 3, 0,
- "Insert before point a substring of the contents of buffer BUFFER.\n\
- BUFFER may be a buffer or a buffer name.\n\
- Arguments START and END are character numbers specifying the substring.\n\
- They default to the beginning and the end of BUFFER.")
- (buffer, start, end)
- Lisp_Object buffer, start, end;
- {
- /* This function can GC */
- Bufpos b, e;
- struct buffer *bp;
-
- bp = XBUFFER (get_buffer (buffer, 1));
- get_bufrange (bp, start, end, &b, &e, GB_ALLOW_NIL);
-
- if (b < e)
- buffer_insert_from_buffer (current_buffer, bp, b, e - b);
-
- return Qnil;
- }
-
- DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings,
- 6, 6, 0,
- "Compare two substrings of two buffers; return result as number.\n\
- the value is -N if first string is less after N-1 chars,\n\
- +N if first string is greater after N-1 chars, or 0 if strings match.\n\
- Each substring is represented as three arguments: BUFFER, START and END.\n\
- That makes six args in all, three for each substring.\n\n\
- The value of `case-fold-search' in the current buffer\n\
- determines whether case is significant or ignored.")
- (buffer1, start1, end1, buffer2, start2, end2)
- Lisp_Object buffer1, start1, end1, buffer2, start2, end2;
- {
- Bufpos begp1, endp1, begp2, endp2;
- REGISTER Charcount len1, len2, length, i;
- struct buffer *bp1, *bp2;
- Lisp_Object trt = ((!NILP (current_buffer->case_fold_search)) ?
- current_buffer->case_canon_table : Qnil);
-
- /* Find the first buffer and its substring. */
-
- bp1 = decode_buffer (buffer1, 1);
- get_bufrange (bp1, start1, end1, &begp1, &endp1, GB_ALLOW_NIL);
-
- /* Likewise for second substring. */
-
- bp2 = decode_buffer (buffer2, 1);
- get_bufrange (bp2, start2, end2, &begp2, &endp2, GB_ALLOW_NIL);
-
- len1 = endp1 - begp1;
- len2 = endp2 - begp2;
- length = len1;
- if (len2 < length)
- length = len2;
-
- for (i = 0; i < length; i++)
- {
- Emchar c1 = BUF_FETCH_CHAR (bp1, begp1 + i);
- Emchar c2 = BUF_FETCH_CHAR (bp2, begp2 + i);
- if (!NILP (trt))
- {
- c1 = TRT_TABLE_OF (trt, c1);
- c2 = TRT_TABLE_OF (trt, c2);
- }
- if (c1 < c2)
- return make_number (- 1 - i);
- if (c1 > c2)
- return make_number (i + 1);
- }
-
- /* The strings match as far as they go.
- If one is shorter, that one is less. */
- if (length < len1)
- return make_number (length + 1);
- else if (length < len2)
- return make_number (- length - 1);
-
- /* Same length too => they are equal. */
- return Qzero;
- }
-
-
- DEFUN ("subst-char-in-region", Fsubst_char_in_region,
- Ssubst_char_in_region, 4, 5, 0,
- "From START to END, replace FROMCHAR with TOCHAR each time it occurs.\n\
- If optional arg NOUNDO is non-nil, don't record this change for undo\n\
- and don't mark the buffer as really changed.")
- (start, end, fromchar, tochar, noundo)
- Lisp_Object start, end, fromchar, tochar, noundo;
- {
- /* This function can GC */
- Bufpos pos, stop;
- Emchar fromc, toc;
- int mc_count;
- struct buffer *buf = current_buffer;
-
- get_bufrange (buf, start, end, &pos, &stop, 0);
- CHECK_COERCE_CHAR (fromchar, 2);
- CHECK_COERCE_CHAR (tochar, 3);
-
- fromc = XINT (fromchar);
- toc = XINT (tochar);
-
- mc_count = begin_multiple_change (buf, pos, stop);
- while (pos < stop)
- {
- if (BUF_FETCH_CHAR (buf, pos) == fromc)
- {
- /* There used to be some code here that set the buffer to
- unmodified if NOUNDO was specified and there was only
- one change to the buffer since it was last saved.
- This is a crock of shit, so I'm not duplicating this
- behavior. I think this was left over from when
- prepare_to_modify_buffer() actually bumped MODIFF,
- so that code was supposed to undo this change. --ben */
- buffer_replace_char (buf, pos, toc, !NILP (noundo), 0);
-
- /* If noundo is not nil then we don't mark the buffer as
- modified. In reality that needs to happen externally
- only. Internally redisplay needs to know that the actual
- contents it should be displaying have changed. */
- if (!NILP (noundo))
- Fset_buffer_modified_p (Fbuffer_modified_p (Qnil), Qnil);
- }
- pos++;
- }
- end_multiple_change (buf, mc_count);
-
- return Qnil;
- }
-
- DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0,
- "From START to END, translate characters according to TABLE.\n\
- TABLE is a string; the Nth character in it is the mapping\n\
- for the character with code N. Returns the number of characters changed.")
- (start, end, table)
- Lisp_Object start;
- Lisp_Object end;
- Lisp_Object table;
- {
- /* This function can GC */
- Bufpos pos, stop; /* Limits of the region. */
- REGISTER Emchar oc; /* Old character. */
- REGISTER Emchar nc; /* New character. */
- int cnt; /* Number of changes made. */
- Charcount size; /* Size of translate table. */
- int mc_count;
- struct buffer *buf = current_buffer;
-
- get_bufrange (buf, start, end, &pos, &stop, 0);
- CHECK_STRING (table, 2);
-
- size = string_char_length (XSTRING (table));
-
- cnt = 0;
- mc_count = begin_multiple_change (buf, pos, stop);
- for (; pos < stop; pos++)
- {
- oc = BUF_FETCH_CHAR (buf, pos);
- if (oc >= 0 && oc < size)
- {
- nc = string_char (XSTRING (table), oc);
- if (nc != oc)
- {
- buffer_replace_char (buf, pos, nc, 0, 0);
- ++cnt;
- }
- }
- }
- end_multiple_change (buf, mc_count);
-
- return make_number (cnt);
- }
-
- DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 3, "r",
- "Delete the text between point and mark.\n\
- When called from a program, expects two arguments,\n\
- positions (integers or markers) specifying the stretch to be deleted.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (b, e, buffer)
- Lisp_Object b, e, buffer;
- {
- /* This function can GC */
- Bufpos start, end;
- struct buffer *buf = decode_buffer (buffer, 1);
-
- get_bufrange (buf, b, e, &start, &end, 0);
- buffer_delete_range (buf, start, end, 0);
- zmacs_region_stays = 0;
- return Qnil;
- }
-
- void
- widen_buffer (struct buffer *b, int no_clip)
- {
- if (BUF_BEGV (b) != BUF_BEG (b))
- {
- clip_changed = 1;
- SET_BUF_BEGV (b, BUF_BEG (b));
- }
- if (BUF_ZV (b) != BUF_Z (b))
- {
- clip_changed = 1;
- SET_BUF_ZV (b, BUF_Z (b));
- }
- if (clip_changed)
- {
- if (!no_clip)
- MARK_CLIP_CHANGED;
- /* Changing the buffer bounds invalidates any recorded current
- column. */
- invalidate_current_column ();
- }
- }
-
- DEFUN ("widen", Fwiden, Swiden, 0, 1, "",
- "Remove restrictions (narrowing) from BUFFER.\n\
- This allows the buffer's full text to be seen and edited.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (buffer)
- Lisp_Object buffer;
- {
- struct buffer *b = decode_buffer (buffer, 1);
- widen_buffer (b, 0);
- zmacs_region_stays = 0;
- return Qnil;
- }
-
- DEFUN ("narrow-to-region", Fnarrow_to_region, Snarrow_to_region, 2, 3, "r",
- "Restrict editing in BUFFER to the current region.\n\
- The rest of the text becomes temporarily invisible and untouchable\n\
- but is not deleted; if you save the buffer in a file, the invisible\n\
- text is included in the file. \\[widen] makes all visible again.\n\
- If BUFFER is nil, the current buffer is assumed.\n\
- See also `save-restriction'.\n\
- \n\
- When calling from a program, pass two arguments; positions (integers\n\
- or markers) bounding the text that should remain visible.")
- (b, e, buffer)
- Lisp_Object b, e, buffer;
- {
- Bufpos start, end;
- struct buffer *buf = decode_buffer (buffer, 1);
-
- get_bufrange (buf, b, e, &start, &end, GB_ALLOW_PAST_ACCESSIBLE);
-
- SET_BUF_BEGV (buf, start);
- SET_BUF_ZV (buf, end);
- if (BUF_PT (buf) < start)
- BUF_SET_PT (buf, start);
- if (BUF_PT (buf) > end)
- BUF_SET_PT (buf, end);
- MARK_CLIP_CHANGED;
- /* Changing the buffer bounds invalidates any recorded current column. */
- invalidate_current_column ();
- zmacs_region_stays = 0;
- return Qnil;
- }
-
- Lisp_Object
- save_restriction_save (void)
- {
- Lisp_Object bottom, top;
- /* Note: I tried using markers here, but it does not win
- because insertion at the end of the saved region
- does not advance mh and is considered "outside" the saved region. */
- bottom = make_number (BUF_BEGV (current_buffer) - BUF_BEG (current_buffer));
- top = make_number (BUF_Z (current_buffer) - BUF_ZV (current_buffer));
-
- return Fcons (Fcurrent_buffer (), Fcons (bottom, top));
- }
-
- Lisp_Object
- save_restriction_restore (Lisp_Object data)
- {
- struct buffer *buf;
- Charcount newhead, newtail;
- Lisp_Object tem;
- int clip_changed = 0;
-
- buf = XBUFFER (Fcar (data));
- if (!BUFFER_LIVE_P (buf))
- /* someone could have killed the buffer in the meantime ... */
- return Qnil;
- tem = Fcdr (data);
- newhead = XINT (Fcar (tem));
- newtail = XINT (Fcdr (tem));
- while (CONSP (data))
- {
- struct Lisp_Cons *victim = XCONS (data);
- data = victim->cdr;
- free_cons (victim);
- }
-
- if (newhead + newtail > BUF_Z (buf) - BUF_BEG (buf))
- {
- newhead = 0;
- newtail = 0;
- }
- if (BUF_BEGV (buf) != BUF_BEG (buf) + newhead)
- {
- clip_changed = 1;
- SET_BUF_BEGV (buf, BUF_BEG (buf) + newhead);
- }
- if (BUF_ZV (buf) != BUF_Z (buf) - newtail)
- {
- clip_changed = 1;
- SET_BUF_ZV (buf, BUF_Z (buf) - newtail);
- }
- if (clip_changed)
- MARK_CLIP_CHANGED;
-
- /* If point is outside the new visible range, move it inside. */
- BUF_SET_PT (buf,
- bufpos_clip_to_bounds (BUF_BEGV (buf),
- BUF_PT (buf),
- BUF_ZV (buf)));
-
- return Qnil;
- }
-
- DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
- "Execute BODY, saving and restoring current buffer's restrictions.\n\
- The buffer's restrictions make parts of the beginning and end invisible.\n\
- \(They are set up with `narrow-to-region' and eliminated with `widen'.)\n\
- This special form, `save-restriction', saves the current buffer's restrictions\n\
- when it is entered, and restores them when it is exited.\n\
- So any `narrow-to-region' within BODY lasts only until the end of the form.\n\
- The old restrictions settings are restored\n\
- even in case of abnormal exit (throw or error).\n\
- \n\
- The value returned is the value of the last form in BODY.\n\
- \n\
- `save-restriction' can get confused if, within the BODY, you widen\n\
- and then make changes outside the area within the saved restrictions.\n\
- \n\
- Note: if you are using both `save-excursion' and `save-restriction',\n\
- use `save-excursion' outermost:\n\
- (save-excursion (save-restriction ...))")
- (body)
- Lisp_Object body;
- {
- /* This function can GC */
- int speccount = specpdl_depth ();
-
- record_unwind_protect (save_restriction_restore, save_restriction_save ());
-
- return unbind_to (speccount, Fprogn (body));
- }
-
-
- DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
- "Format a string out of a control-string and arguments.\n\
- The first argument is a control string.\n\
- The other arguments are substituted into it to make the result, a string.\n\
- It may contain %-sequences meaning to substitute the next argument.\n\
- %s means print all objects as-is, using `princ'.\n\
- %S means print all objects as s-expressions, using `prin1'.\n\
- %d or %i means print as an integer in decimal (%o octal, %x lowercase hex,\n\
- %X uppercase hex).\n\
- %c means print as a single character.\n\
- %f means print as a floating-point number in fixed notation (e.g. 785.200).\n\
- %e or %E means print as a floating-point number in scientific notation\n\
- (e.g. 7.85200e+03).\n\
- %g or %G means print as a floating-point number in \"pretty format\";\n\
- depending on the number, either %f or %e/%E format will be used, and\n\
- trailing zeroes are removed from the fractional part.\n\
- The argument used for all but %s and %S must be a number. It will be\n\
- converted to an integer or a floating-point number as necessary.\n\
- \n\
- %$ means reposition to read a specific numbered argument; for example,\n\
- %3$%s would apply the `%s' and all following format directives\n\
- to the third argument after the control string. (There must be a\n\
- positive integer between the % and the $).\n\
- Zero or more of the flag characters `-', `+', ` ', `0', and `#' may be\n\
- specified between the optional repositioning spec and the conversion\n\
- character; see below.\n\
- An optional minimum field width may be specified after any flag characters\n\
- and before the conversion character; it specifies the minimum number of\n\
- characters that the converted argument will take up. Padding will be\n\
- added on the left (or on the right, if the `-' flag is specified), as\n\
- necessary. Padding is done with spaces, or with zeroes if the `0' flag\n\
- is specified.\n\
- An optional period character and precision may be specified after any\n\
- minimum field width. It specifies the minimum number of digits to\n\
- appear in %d, %i, %o, %x, and %X conversions (the number is padded\n\
- on the left with zeroes as necessary); the number of digits printed\n\
- after the decimal point for %f, %e, and %E conversions; the number\n\
- of significant digits printed in %g and %G conversions; and the\n\
- maximum number of non-padding characters printed in %s and %S\n\
- conversions. The default precision for floating-point conversions\n\
- is six.\n\
- \n\
- The ` ' and `+' flags mean prefix non-negative numbers with a space or\n\
- plus sign, respectively.\n\
- The `#' flag means print numbers in an alternate, more verbose format:\n\
- octal numbers begin with zero; hex numbers begin with a 0x or 0X;\n\
- a decimal point is printed in %f, %e, and %E conversions even if no\n\
- numbers are printed after it; and trailing zeroes are not omitted in\n\
- %g and %G conversions.\n\
- \n\
- Use %% to put a single % into the output.")
- (nargs, args)
- int nargs;
- Lisp_Object *args;
- {
- /* It should not be necessary to GCPRO ARGS, because
- the caller in the interpreter should take care of that. */
-
- CHECK_STRING (args[0], 0);
- return emacs_doprnt_string_lisp (0, args[0], 0, nargs - 1, args + 1);
- }
-
-
- DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 3, 0,
- "Return t if two characters match, optionally ignoring case.\n\
- Both arguments must be characters (i.e. integers).\n\
- Case is ignored if `case-fold-search' is non-nil in BUFFER.\n\
- If BUFFER is nil, the current buffer is assumed.")
- (c1, c2, buffer)
- Lisp_Object c1, c2, buffer;
- {
- Emchar x1, x2;
- struct buffer *buf = decode_buffer (buffer, 1);
-
- CHECK_COERCE_CHAR (c1, 0);
- CHECK_COERCE_CHAR (c2, 1);
- x1 = XINT (c1);
- x2 = XINT (c2);
-
- if (!NILP (buf->case_fold_search)
- ? DOWNCASE (buf, x1) == DOWNCASE (buf, x2)
- : x1 == x2)
- return Qt;
- return Qnil;
- }
-
- #if 0 /* Undebugged FSFmacs code */
- /* Transpose the markers in two regions of the current buffer, and
- adjust the ones between them if necessary (i.e.: if the regions
- differ in size).
-
- Traverses the entire marker list of the buffer to do so, adding an
- appropriate amount to some, subtracting from some, and leaving the
- rest untouched. Most of this is copied from adjust_markers in insdel.c.
-
- It's the caller's job to see that (start1 <= end1 <= start2 <= end2). */
-
- void
- transpose_markers (Bufpos start1, Bufpos end1, Bufpos start2, Bufpos end2)
- {
- Charcount amt1, amt2, diff;
- Bufpos mpos;
- Lisp_Object marker;
- struct buffer *buf = current_buffer;
-
- /* Update point as if it were a marker. */
- if (BUF_PT (buf) < start1)
- ;
- else if (BUF_PT (buf) < end1)
- BUF_SET_PT (buf, BUF_PT (buf) + (end2 - end1));
- else if (BUF_PT (buf) < start2)
- BUF_SET_PT (buf, BUF_PT (buf) + (end2 - start2) - (end1 - start1));
- else if (BUF_PT (buf) < end2)
- BUF_SET_PT (buf, BUF_PT (buf) - (start2 - start1));
-
- /* We used to adjust the endpoints here to account for the gap, but that
- isn't good enough. Even if we assume the caller has tried to move the
- gap out of our way, it might still be at start1 exactly, for example;
- and that places it `inside' the interval, for our purposes. The amount
- of adjustment is nontrivial if there's a `denormalized' marker whose
- position is between GPT and GPT + GAP_SIZE, so it's simpler to leave
- the dirty work to Fmarker_position, below. */
-
- /* The difference between the region's lengths */
- diff = (end2 - start2) - (end1 - start1);
-
- /* For shifting each marker in a region by the length of the other
- * region plus the distance between the regions.
- */
- amt1 = (end2 - start2) + (start2 - end1);
- amt2 = (end1 - start1) + (start2 - end1);
-
- for (marker = buf->markers; !NILP (marker);
- marker = XMARKER (marker)->chain)
- {
- mpos = marker_position (marker);
- if (mpos >= start1 && mpos < end2)
- {
- if (mpos < end1)
- mpos += amt1;
- else if (mpos < start2)
- mpos += diff;
- else
- mpos -= amt2;
- set_marker_position (marker, mpos);
- }
- }
- }
-
- #endif
-
- DEFUN ("transpose-regions", Ftranspose_regions, Stranspose_regions, 4, 5, 0,
- "Transpose region START1 to END1 with START2 to END2.\n\
- The regions may not be overlapping, because the size of the buffer is\n\
- never changed in a transposition.\n\
- \n\
- Optional fifth arg LEAVE_MARKERS, if non-nil, means don't transpose\n\
- any markers that happen to be located in the regions. (#### BUG: currently\n\
- this function always acts as if LEAVE_MARKERS is non-nil.)\n\
- \n\
- Transposing beyond buffer boundaries is an error.")
- (startr1, endr1, startr2, endr2, leave_markers)
- Lisp_Object startr1, endr1, startr2, endr2, leave_markers;
- {
- Bufpos start1, end1, start2, end2;
- Charcount len1, len2;
- Lisp_Object string1, string2;
- struct buffer *buf = current_buffer;
-
- get_bufrange (buf, startr1, endr1, &start1, &end1, 0);
- get_bufrange (buf, startr2, endr2, &start2, &end2, 0);
-
- len1 = end1 - start1;
- len2 = end2 - start2;
-
- if (start2 < end1)
- error ("transposed regions not properly ordered");
- else if (start1 == end1 || start2 == end2)
- error ("transposed region may not be of length 0");
-
- string1 = make_string_from_buffer (buf, start1, len1);
- string2 = make_string_from_buffer (buf, start2, len2);
- buffer_delete_range (buf, start2, end2, 0);
- buffer_insert_lisp_string_1 (buf, start2, string1, 0);
- buffer_delete_range (buf, start1, end1, 0);
- buffer_insert_lisp_string_1 (buf, start1, string2, 0);
-
- /* In FSFmacs there is a whole bunch of really ugly code here
- to attempt to transpose the regions without using up any
- extra memory. Although the intent may be good, the result
- was highly bogus. */
-
- return Qnil;
- }
-
-
- /************************************************************************/
- /* initialization */
- /************************************************************************/
-
- void
- syms_of_editfns (void)
- {
- defsymbol (&Qpoint, "point");
- defsymbol (&Qmark, "mark");
- defsymbol (&Qregion_beginning, "region-beginning");
- defsymbol (&Qregion_end, "region-end");
- defsymbol (&Qformat, "format");
-
- defsubr (&Schar_equal);
- defsubr (&Sgoto_char);
- defsubr (&Sstring_to_char);
- defsubr (&Schar_to_string);
- defsubr (&Sbuffer_substring);
-
- defsubr (&Spoint_marker);
- defsubr (&Smark_marker);
- defsubr (&Spoint);
- defsubr (&Sregion_beginning);
- defsubr (&Sregion_end);
- defsubr (&Ssave_excursion);
-
- defsubr (&Sbufsize);
- defsubr (&Spoint_max);
- defsubr (&Spoint_min);
- defsubr (&Spoint_min_marker);
- defsubr (&Spoint_max_marker);
-
- defsubr (&Sbobp);
- defsubr (&Seobp);
- defsubr (&Sbolp);
- defsubr (&Seolp);
- defsubr (&Sfollowing_char);
- defsubr (&Sprevious_char);
- defsubr (&Schar_after);
- defsubr (&Sinsert);
- defsubr (&Sinsert_string);
- defsubr (&Sinsert_before_markers);
- defsubr (&Sinsert_char);
-
- defsubr (&Suser_login_name);
- defsubr (&Suser_real_login_name);
- defsubr (&Suser_uid);
- defsubr (&Suser_real_uid);
- defsubr (&Suser_full_name);
- defsubr (&Semacs_pid);
- defsubr (&Scurrent_time);
- defsubr (&Scurrent_time_string);
- defsubr (&Scurrent_locale_time_string);
- defsubr (&Scurrent_time_zone);
- defsubr (&Ssystem_name);
- defsubr (&Sformat);
-
- defsubr (&Sinsert_buffer_substring);
- defsubr (&Scompare_buffer_substrings);
- defsubr (&Ssubst_char_in_region);
- defsubr (&Stranslate_region);
- defsubr (&Sdelete_region);
- defsubr (&Swiden);
- defsubr (&Snarrow_to_region);
- defsubr (&Ssave_restriction);
- defsubr (&Stranspose_regions);
-
- defsymbol (&Qzmacs_update_region, "zmacs-update-region");
- defsymbol (&Qzmacs_deactivate_region, "zmacs-deactivate-region");
- }
-
- void
- vars_of_editfns (void)
- {
- staticpro (&Vsystem_name);
- #if 0
- staticpro (&Vuser_full_name);
- staticpro (&Vuser_name);
- staticpro (&Vuser_real_name);
- #endif
- DEFVAR_BOOL ("zmacs-regions", &zmacs_regions,
- "*Whether LISPM-style active regions should be used.\n\
- This means that commands which operate on the region (the area between the\n\
- point and the mark) will only work while the region is in the ``active''\n\
- state, which is indicated by highlighting. Executing most commands causes\n\
- the region to not be in the active state, so (for example) \\[kill-region] will only\n\
- work immediately after activating the region.\n\
- \n\
- More specifically:\n\
- \n\
- - Commands which operate on the region only work if the region is active.\n\
- - Only a very small set of commands cause the region to become active:\n\
- Those commands whose semantics are to mark an area, like mark-defun.\n\
- - The region is deactivated after each command that is executed, except that:\n\
- - \"Motion\" commands do not change whether the region is active or not.\n\
- \n\
- set-mark-command (C-SPC) pushes a mark and activates the region. Moving the\n\
- cursor with normal motion commands (C-n, C-p, etc) will cause the region\n\
- between point and the recently-pushed mark to be highlighted. It will\n\
- remain highlighted until some non-motion comand is executed.\n\
- \n\
- exchange-point-and-mark (\\[exchange-point-and-mark]) activates the region. So if you mark a\n\
- region and execute a command that operates on it, you can reactivate the\n\
- same region with \\[exchange-point-and-mark] (or perhaps \\[exchange-point-and-mark] \\[exchange-point-and-mark]) to operate on it\n\
- again.\n\
- \n\
- Generally, commands which push marks as a means of navigation (like\n\
- beginning-of-buffer and end-of-buffer (M-< and M->)) do not activate the\n\
- region. But commands which push marks as a means of marking an area of\n\
- text (like mark-defun (\\[mark-defun]), mark-word (\\[mark-word]) or mark-whole-buffer (\\[mark-whole-buffer]))\n\
- do activate the region.\n\
- \n\
- The way the command loop actually works with regard to deactivating the\n\
- region is as follows:\n\
- \n\
- - If the variable `zmacs-region-stays' has been set to t during the command\n\
- just executed, the region is left alone (this is how the motion commands\n\
- make the region stay around; see the `_' flag in the `interactive'\n\
- specification). `zmacs-region-stays' is reset to nil before each command\n\
- is executed.\n\
- - If the function `zmacs-activate-region' has been called during the command\n\
- just executed, the region is left alone. Very few functions should\n\
- actually call this function.\n\
- - Otherwise, if the region is active, the region is deactivated and\n\
- the `zmacs-deactivate-region-hook' is called.");
- /* Zmacs style active regions are now ON by default */
- zmacs_regions = 1;
-
- DEFVAR_BOOL ("zmacs-region-active-p", &zmacs_region_active_p,
- "Do not alter this. It is for internal use only.");
- zmacs_region_active_p = 0;
-
- DEFVAR_BOOL ("zmacs-region-stays", &zmacs_region_stays,
- "Commands which do not wish to affect whether the region is currently\n\
- highlighted should set this to t. Normally, the region is turned off after\n\
- executing each command that did not explicitly turn it on with the function\n\
- zmacs-activate-region. Setting this to true lets a command be non-intrusive.\n\
- See the variable `zmacs-regions'.");
- zmacs_region_stays = 0;
-
- DEFVAR_BOOL ("atomic-extent-goto-char-p", &atomic_extent_goto_char_p,
- "Do not use this -- it will be going away soon.\n\
- Indicates if `goto-char' has just been run. This information is allegedly\n\
- needed to get the desired behavior for atomic extents and unfortunately\n\
- is not available by any other means.");
- atomic_extent_goto_char_p = 0;
- }
-