Replace `iff' in comments.
[bpt/emacs.git] / src / editfns.c
index dce7276..6c6742d 100644 (file)
@@ -1,13 +1,13 @@
 /* Lisp functions pertaining to editing.
    Copyright (C) 1985, 1986, 1987, 1989, 1993, 1994, 1995, 1996,
                  1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006 Free Software Foundation, Inc.
+                 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs 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)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -274,7 +274,9 @@ clip_to_bounds (lower, num, upper)
 
 DEFUN ("goto-char", Fgoto_char, Sgoto_char, 1, 1, "NGoto char: ",
        doc: /* Set point to POSITION, a number or marker.
-Beginning of buffer is position (point-min), end is (point-max).  */)
+Beginning of buffer is position (point-min), end is (point-max).
+
+The return value is POSITION.  */)
      (position)
      register Lisp_Object position;
 {
@@ -1314,7 +1316,10 @@ DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
 Value is an integer or float, depending on the value.  */)
      ()
 {
-  return make_fixnum_or_float (geteuid ());
+  /* Assignment to EMACS_INT stops GCC whining about limited range of
+     data type.  */
+  EMACS_INT euid = geteuid ();
+  return make_fixnum_or_float (euid);
 }
 
 DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
@@ -1322,7 +1327,10 @@ DEFUN ("user-real-uid", Fuser_real_uid, Suser_real_uid, 0, 0, 0,
 Value is an integer or float, depending on the value.  */)
      ()
 {
-  return make_fixnum_or_float (getuid ());
+  /* Assignment to EMACS_INT stops GCC whining about limited range of
+     data type.  */
+  EMACS_INT uid = getuid ();
+  return make_fixnum_or_float (uid);
 }
 
 DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 1, 0,
@@ -1450,9 +1458,9 @@ most significant 16 bits of the seconds, while the second has the
 least significant 16 bits.  The third integer gives the microsecond
 count.
 
-On systems that can't determine the run time, get-internal-run-time
-does the same thing as current-time.  The microsecond count is zero on
-systems that do not provide resolution finer than a second.  */)
+On systems that can't determine the run time, `get-internal-run-time'
+does the same thing as `current-time'.  The microsecond count is zero
+on systems that do not provide resolution finer than a second.  */)
      ()
 {
 #ifdef HAVE_GETRUSAGE
@@ -1678,7 +1686,9 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".  */)
   /* This is probably enough.  */
   size = SBYTES (format_string) * 6 + 50;
 
+  BLOCK_INPUT;
   tm = ut ? gmtime (&value) : localtime (&value);
+  UNBLOCK_INPUT;
   if (! tm)
     error ("Specified time is not representable");
 
@@ -1690,18 +1700,22 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".  */)
       int result;
 
       buf[0] = '\1';
+      BLOCK_INPUT;
       result = emacs_memftimeu (buf, size, SDATA (format_string),
                                SBYTES (format_string),
                                tm, ut);
+      UNBLOCK_INPUT;
       if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
        return code_convert_string_norecord (make_unibyte_string (buf, result),
                                             Vlocale_coding_system, 0);
 
       /* If buffer was too small, make it bigger and try again.  */
+      BLOCK_INPUT;
       result = emacs_memftimeu (NULL, (size_t) -1,
                                SDATA (format_string),
                                SBYTES (format_string),
                                tm, ut);
+      UNBLOCK_INPUT;
       size = result + 1;
     }
 }
@@ -1709,7 +1723,7 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".  */)
 DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 1, 0,
        doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).
 The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED),
-as from `current-time' and `file-attributes', or `nil' to use the
+as from `current-time' and `file-attributes', or nil to use the
 current time.  The obsolete form (HIGH . LOW) is also still accepted.
 The list has the following nine members: SEC is an integer between 0
 and 60; SEC is 60 for a leap second, which only some operating systems
@@ -1717,7 +1731,7 @@ support.  MINUTE is an integer between 0 and 59.  HOUR is an integer
 between 0 and 23.  DAY is an integer between 1 and 31.  MONTH is an
 integer between 1 and 12.  YEAR is an integer indicating the
 four-digit year.  DOW is the day of week, an integer between 0 and 6,
-where 0 is Sunday.  DST is t if daylight savings time is effect,
+where 0 is Sunday.  DST is t if daylight saving time is in effect,
 otherwise nil.  ZONE is an integer indicating the number of seconds
 east of Greenwich.  (Note that Common Lisp has different meanings for
 DOW and ZONE.)  */)
@@ -1732,7 +1746,9 @@ DOW and ZONE.)  */)
   if (! lisp_time_argument (specified_time, &time_spec, NULL))
     error ("Invalid time specification");
 
+  BLOCK_INPUT;
   decoded_time = localtime (&time_spec);
+  UNBLOCK_INPUT;
   if (! decoded_time)
     error ("Specified time is not representable");
   XSETFASTINT (list_args[0], decoded_time->tm_sec);
@@ -1748,7 +1764,9 @@ DOW and ZONE.)  */)
 
   /* Make a copy, in case gmtime modifies the struct.  */
   save_tm = *decoded_time;
+  BLOCK_INPUT;
   decoded_time = gmtime (&time_spec);
+  UNBLOCK_INPUT;
   if (decoded_time == 0)
     list_args[8] = Qnil;
   else
@@ -1762,7 +1780,7 @@ This is the reverse operation of `decode-time', which see.
 ZONE defaults to the current time zone rule.  This can
 be a string or t (as from `set-time-zone-rule'), or it can be a list
 \(as from `current-time-zone') or an integer (as from `decode-time')
-applied without consideration for daylight savings time.
+applied without consideration for daylight saving time.
 
 You can pass more than 7 arguments; then the first six arguments
 are used as SECOND through YEAR, and the *last* argument is used as ZONE.
@@ -1804,7 +1822,11 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE)  */)
   if (CONSP (zone))
     zone = Fcar (zone);
   if (NILP (zone))
-    time = mktime (&tm);
+    {
+      BLOCK_INPUT;
+      time = mktime (&tm);
+      UNBLOCK_INPUT;
+    }
   else
     {
       char tzbuf[100];
@@ -1829,7 +1851,9 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE)  */)
         value doesn't suffice, since that would mishandle leap seconds.  */
       set_time_zone_rule (tzstring);
 
+      BLOCK_INPUT;
       time = mktime (&tm);
+      UNBLOCK_INPUT;
 
       /* Restore TZ to previous value.  */
       newenv = environ;
@@ -1873,7 +1897,9 @@ but this is considered obsolete.  */)
   /* Convert to a string, checking for out-of-range time stamps.
      Don't use 'ctime', as that might dump core if VALUE is out of
      range.  */
+  BLOCK_INPUT;
   tm = localtime (&value);
+  UNBLOCK_INPUT;
   if (! (tm && TM_YEAR_IN_ASCTIME_RANGE (tm->tm_year) && (tem = asctime (tm))))
     error ("Specified time is not representable");
 
@@ -1929,9 +1955,21 @@ the data it can't find.  */)
   struct tm *t;
   struct tm gmt;
 
-  if (lisp_time_argument (specified_time, &value, NULL)
-      && (t = gmtime (&value)) != 0
-      && (gmt = *t, t = localtime (&value)) != 0)
+  if (!lisp_time_argument (specified_time, &value, NULL))
+    t = NULL;
+  else
+    {
+      BLOCK_INPUT;
+      t = gmtime (&value);
+      if (t)
+       {
+         gmt = *t;
+         t = localtime (&value);
+       }
+      UNBLOCK_INPUT;
+    }
+
+  if (t)
     {
       int offset = tm_diff (t, &gmt);
       char *s = 0;
@@ -2249,8 +2287,7 @@ usage: (insert-before-markers-and-inherit &rest ARGS)  */)
 }
 \f
 DEFUN ("insert-char", Finsert_char, Sinsert_char, 2, 3, 0,
-       doc: /* Insert COUNT (second arg) copies of CHARACTER (first arg).
-Both arguments are required.
+       doc: /* Insert COUNT copies of CHARACTER.
 Point, and before-insertion markers, are relocated as in the function `insert'.
 The optional third arg INHERIT, if non-nil, says to inherit text properties
 from adjoining text, if those properties are sticky.  */)
@@ -3139,7 +3176,7 @@ save_restriction_restore (data)
 DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0,
        doc: /* Execute BODY, saving and restoring current buffer's restrictions.
 The buffer's restrictions make parts of the beginning and end invisible.
-(They are set up with `narrow-to-region' and eliminated with `widen'.)
+\(They are set up with `narrow-to-region' and eliminated with `widen'.)
 This special form, `save-restriction', saves the current buffer's restrictions
 when it is entered, and restores them when it is exited.
 So any `narrow-to-region' within BODY lasts only until the end of the form.
@@ -3171,13 +3208,17 @@ static char *message_text;
 static int message_length;
 
 DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
-       doc: /* Print a one-line message at the bottom of the screen.
+       doc: /* Display a message at the bottom of the screen.
 The message also goes into the `*Messages*' buffer.
 \(In keyboard macros, that's all it does.)
+Return the message.
 
 The first argument is a format control string, and the rest are data
 to be formatted under control of the string.  See `format' for details.
 
+Note: Use (message "%s" VALUE) to print the value of expressions and
+variables to avoid accidentally interpreting `%' as format specifiers.
+
 If the first argument is nil or the empty string, the function clears
 any existing message; this lets the minibuffer contents show.  See
 also `current-message'.
@@ -3357,7 +3398,7 @@ Use %% to put a single % into the output.
 
 The basic structure of a %-sequence is
   % <flags> <width> <precision> character
-where flags is [- #0]+, width is [0-9]+, and precision is .[0-9]+
+where flags is [-+ #0]+, width is [0-9]+, and precision is .[0-9]+
 
 usage: (format STRING &rest OBJECTS)  */)
      (nargs, args)
@@ -3470,12 +3511,12 @@ usage: (format STRING &rest OBJECTS)  */)
 
           where
 
-          flags        ::= [- #0]+
+          flags        ::= [-+ #0]+
           field-width  ::= [0-9]+
           precision    ::= '.' [0-9]*
 
           If a field-width is specified, it specifies to which width
-          the output should be padded with blanks, iff the output
+          the output should be padded with blanks, if the output
           string is shorter than field-width.
 
           If precision is specified, it specifies the number of
@@ -3484,7 +3525,7 @@ usage: (format STRING &rest OBJECTS)  */)
 
        while (format != end
               && (*format == '-' || *format == '0' || *format == '#'
-                  || * format == ' '))
+                  || * format == ' ' || *format == '+'))
          ++format;
 
        if (*format >= '0' && *format <= '9')
@@ -3597,7 +3638,12 @@ usage: (format STRING &rest OBJECTS)  */)
                if (*format != 'd' && *format != 'o' && *format != 'x'
                    && *format != 'i' && *format != 'X' && *format != 'c')
                  error ("Invalid format operation %%%c", *format);
-               args[n] = Ftruncate (args[n], Qnil);
+               /* This fails unnecessarily if args[n] is bigger than
+                  most-positive-fixnum but smaller than MAXINT.
+                  These cases are important because we sometimes use floats
+                  to represent such integer values (typically such values
+                  come from UIDs or PIDs).  */
+               /* args[n] = Ftruncate (args[n], Qnil); */
              }
 
            /* Note that we're using sprintf to print floats,
@@ -3656,7 +3702,7 @@ usage: (format STRING &rest OBJECTS)  */)
          discarded[format - format_start] = 1;
          format++;
 
-         while (index("-0# ", *format))
+         while (index("-+0# ", *format))
            {
              if (*format == '-')
                {
@@ -3765,8 +3811,15 @@ usage: (format STRING &rest OBJECTS)  */)
                  else
                    sprintf (p, this_format, XUINT (args[n]));
                }
-             else
+             else if (format[-1] == 'e' || format[-1] == 'f' || format[-1] == 'g')
                sprintf (p, this_format, XFLOAT_DATA (args[n]));
+             else if (format[-1] == 'd')
+               /* Maybe we should use "%1.0f" instead so it also works
+                  for values larger than MAXINT.  */
+               sprintf (p, this_format, (EMACS_INT) XFLOAT_DATA (args[n]));
+             else
+               /* Don't sign-extend for octal or hex printing.  */
+               sprintf (p, this_format, (EMACS_UINT) XFLOAT_DATA (args[n]));
 
              if (p > buf
                  && multibyte
@@ -4066,7 +4119,10 @@ Transposing beyond buffer boundaries is an error.  */)
   int gap, len1, len_mid, len2;
   unsigned char *start1_addr, *start2_addr, *temp;
 
-  INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2;
+  INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2, tmp_interval3;
+  Lisp_Object buf;
+
+  XSETBUFFER (buf, current_buffer);
   cur_intv = BUF_INTERVALS (current_buffer);
 
   validate_region (&startr1, &endr1);
@@ -4173,8 +4229,11 @@ Transposing beyond buffer boundaries is an error.  */)
 
       tmp_interval1 = copy_intervals (cur_intv, start1, len1);
       tmp_interval2 = copy_intervals (cur_intv, start2, len2);
-      Fset_text_properties (make_number (start1), make_number (end2),
-                           Qnil, Qnil);
+      /* Don't use Fset_text_properties: that can cause GC, which can
+        clobber objects stored in the tmp_intervals.  */
+      tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
+      if (!NULL_INTERVAL_P (tmp_interval3))
+       set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
 
       /* First region smaller than second.  */
       if (len1_byte < len2_byte)
@@ -4230,10 +4289,14 @@ Transposing beyond buffer boundaries is an error.  */)
           record_change (start2, len2);
           tmp_interval1 = copy_intervals (cur_intv, start1, len1);
           tmp_interval2 = copy_intervals (cur_intv, start2, len2);
-          Fset_text_properties (make_number (start1), make_number (end1),
-                               Qnil, Qnil);
-          Fset_text_properties (make_number (start2), make_number (end2),
-                               Qnil, Qnil);
+
+         tmp_interval3 = validate_interval_range (buf, &startr1, &endr1, 0);
+         if (!NULL_INTERVAL_P (tmp_interval3))
+           set_text_properties_1 (startr1, endr1, Qnil, buf, tmp_interval3);
+
+         tmp_interval3 = validate_interval_range (buf, &startr2, &endr2, 0);
+         if (!NULL_INTERVAL_P (tmp_interval3))
+           set_text_properties_1 (startr2, endr2, Qnil, buf, tmp_interval3);
 
          SAFE_ALLOCA (temp, unsigned char *, len1_byte);
          start1_addr = BYTE_POS_ADDR (start1_byte);
@@ -4259,8 +4322,10 @@ Transposing beyond buffer boundaries is an error.  */)
           tmp_interval1 = copy_intervals (cur_intv, start1, len1);
           tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
           tmp_interval2 = copy_intervals (cur_intv, start2, len2);
-          Fset_text_properties (make_number (start1), make_number (end2),
-                               Qnil, Qnil);
+
+         tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
+         if (!NULL_INTERVAL_P (tmp_interval3))
+           set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
 
          /* holds region 2 */
          SAFE_ALLOCA (temp, unsigned char *, len2_byte);
@@ -4290,8 +4355,10 @@ Transposing beyond buffer boundaries is an error.  */)
           tmp_interval1 = copy_intervals (cur_intv, start1, len1);
           tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
           tmp_interval2 = copy_intervals (cur_intv, start2, len2);
-          Fset_text_properties (make_number (start1), make_number (end2),
-                               Qnil, Qnil);
+
+         tmp_interval3 = validate_interval_range (buf, &startr1, &endr2, 0);
+         if (!NULL_INTERVAL_P (tmp_interval3))
+           set_text_properties_1 (startr1, endr2, Qnil, buf, tmp_interval3);
 
          /* holds region 1 */
          SAFE_ALLOCA (temp, unsigned char *, len1_byte);
@@ -4326,6 +4393,7 @@ Transposing beyond buffer boundaries is an error.  */)
       fix_start_end_in_overlays (start1, end2);
     }
 
+  signal_after_change (start1, end2 - start1, end2 - start1);
   return Qnil;
 }