]> code.delx.au - gnu-emacs/blobdiff - src/editfns.c
Gnus: Improve parts deletion and stripping behavior
[gnu-emacs] / src / editfns.c
index cd15f6569aa62ad01ed33e1b8e648fc8b65e2c03..dbcb3160b2734e60bb28b17ffce254e259c54b5c 100644 (file)
@@ -1395,6 +1395,19 @@ invalid_time (void)
   error ("Invalid time specification");
 }
 
+/* Check a return value compatible with that of decode_time_components.  */
+static void
+check_time_validity (int validity)
+{
+  if (validity <= 0)
+    {
+      if (validity < 0)
+       time_overflow ();
+      else
+       invalid_time ();
+    }
+}
+
 /* A substitute for mktime_z on platforms that lack it.  It's not
    thread-safe, but should be good enough for Emacs in typical use.  */
 #ifndef HAVE_TZALLOC
@@ -1698,9 +1711,9 @@ decode_float_time (double t, struct lisp_time *result)
    If *DRESULT is not null, store into *DRESULT the number of
    seconds since the start of the POSIX Epoch.
 
-   Return true if successful, false if the components are of the
-   wrong type or represent a time out of range.  */
-bool
+   Return 1 if successful, 0 if the components are of the
+   wrong type, and -1 if the time is out of range.  */
+int
 decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
                        Lisp_Object psec,
                        struct lisp_time *result, double *dresult)
@@ -1708,17 +1721,17 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
   EMACS_INT hi, lo, us, ps;
   if (! (INTEGERP (high)
         && INTEGERP (usec) && INTEGERP (psec)))
-    return false;
+    return 0;
   if (! INTEGERP (low))
     {
       if (FLOATP (low))
        {
          double t = XFLOAT_DATA (low);
          if (result && ! decode_float_time (t, result))
-           return false;
+           return -1;
          if (dresult)
            *dresult = t;
-         return true;
+         return 1;
        }
       else if (NILP (low))
        {
@@ -1732,10 +1745,10 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
            }
          if (dresult)
            *dresult = now.tv_sec + now.tv_nsec / 1e9;
-         return true;
+         return 1;
        }
       else
-       return false;
+       return 0;
     }
 
   hi = XINT (high);
@@ -1755,7 +1768,7 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
   if (result)
     {
       if (! (MOST_NEGATIVE_FIXNUM <= hi && hi <= MOST_POSITIVE_FIXNUM))
-       return false;
+       return -1;
       result->hi = hi;
       result->lo = lo;
       result->us = us;
@@ -1768,7 +1781,7 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
       *dresult = (us * 1e6 + ps) / 1e12 + lo + dhi * (1 << LO_TIME_BITS);
     }
 
-  return true;
+  return 1;
 }
 
 struct timespec
@@ -1792,8 +1805,8 @@ lisp_time_struct (Lisp_Object specified_time, int *plen)
   Lisp_Object high, low, usec, psec;
   struct lisp_time t;
   int len = disassemble_lisp_time (specified_time, &high, &low, &usec, &psec);
-  if (! (len && decode_time_components (high, low, usec, psec, &t, 0)))
-    invalid_time ();
+  int val = len ? decode_time_components (high, low, usec, psec, &t, 0) : 0;
+  check_time_validity (val);
   *plen = len;
   return t;
 }
@@ -1818,13 +1831,20 @@ lisp_seconds_argument (Lisp_Object specified_time)
 {
   Lisp_Object high, low, usec, psec;
   struct lisp_time t;
-  if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
-        && decode_time_components (high, low, make_number (0),
-                                   make_number (0), &t, 0)))
-    invalid_time ();
-  if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> LO_TIME_BITS <= t.hi : 0 <= t.hi)
-        && t.hi <= TIME_T_MAX >> LO_TIME_BITS))
-    time_overflow ();
+
+  int val = disassemble_lisp_time (specified_time, &high, &low, &usec, &psec);
+  if (val != 0)
+    {
+      val = decode_time_components (high, low, make_number (0),
+                                   make_number (0), &t, 0);
+      if (0 < val
+         && ! ((TYPE_SIGNED (time_t)
+                ? TIME_T_MIN >> LO_TIME_BITS <= t.hi
+                : 0 <= t.hi)
+               && t.hi <= TIME_T_MAX >> LO_TIME_BITS))
+       val = -1;
+    }
+  check_time_validity (val);
   return (t.hi << LO_TIME_BITS) + t.lo;
 }
 
@@ -2033,20 +2053,20 @@ DOW and ZONE.)  */)
   /* Avoid overflow when INT_MAX < EMACS_INT_MAX.  */
   EMACS_INT tm_year_base = TM_YEAR_BASE;
 
-  return Flist (9, ((Lisp_Object [])
-                   {make_number (local_tm.tm_sec),
-                    make_number (local_tm.tm_min),
-                    make_number (local_tm.tm_hour),
-                    make_number (local_tm.tm_mday),
-                    make_number (local_tm.tm_mon + 1),
-                    make_number (local_tm.tm_year + tm_year_base),
-                    make_number (local_tm.tm_wday),
-                    local_tm.tm_isdst ? Qt : Qnil,
-                    (HAVE_TM_GMTOFF
-                     ? make_number (tm_gmtoff (&local_tm))
-                     : gmtime_r (&time_spec, &gmt_tm)
-                     ? make_number (tm_diff (&local_tm, &gmt_tm))
-                     : Qnil)}));
+  return CALLN (Flist,
+               make_number (local_tm.tm_sec),
+               make_number (local_tm.tm_min),
+               make_number (local_tm.tm_hour),
+               make_number (local_tm.tm_mday),
+               make_number (local_tm.tm_mon + 1),
+               make_number (local_tm.tm_year + tm_year_base),
+               make_number (local_tm.tm_wday),
+               local_tm.tm_isdst ? Qt : Qnil,
+               (HAVE_TM_GMTOFF
+                ? make_number (tm_gmtoff (&local_tm))
+                : gmtime_r (&time_spec, &gmt_tm)
+                ? make_number (tm_diff (&local_tm, &gmt_tm))
+                : Qnil));
 }
 
 /* Return OBJ - OFFSET, checking that OBJ is a valid fixnum and that
@@ -2063,6 +2083,29 @@ check_tm_member (Lisp_Object obj, int offset)
   return n - offset;
 }
 
+/* Decode ZONE as a time zone specification.  */
+
+static Lisp_Object
+decode_time_zone (Lisp_Object zone)
+{
+  if (EQ (zone, Qt))
+    return build_string ("UTC0");
+  else if (STRINGP (zone))
+    return zone;
+  else if (INTEGERP (zone))
+    {
+      static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d";
+      char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)];
+      EMACS_INT abszone = eabs (XINT (zone)), zone_hr = abszone / (60 * 60);
+      int zone_min = (abszone / 60) % 60, zone_sec = abszone % 60;
+
+      return make_formatted_string (tzbuf, tzbuf_format, &"-"[XINT (zone) < 0],
+                                   zone_hr, zone_min, zone_sec);
+    }
+  else
+    xsignal2 (Qerror, build_string ("Invalid time zone specification"), zone);
+}
+
 DEFUN ("encode-time", Fencode_time, Sencode_time, 6, MANY, 0,
        doc: /* Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.
 This is the reverse operation of `decode-time', which see.
@@ -2105,30 +2148,7 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE)  */)
     value = mktime (&tm);
   else
     {
-      static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d";
-      char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)];
-      const char *tzstring;
-
-      if (EQ (zone, Qt))
-       tzstring = "UTC0";
-      else if (STRINGP (zone))
-       tzstring = SSDATA (zone);
-      else if (INTEGERP (zone))
-       {
-         EMACS_INT abszone = eabs (XINT (zone));
-         EMACS_INT zone_hr = abszone / (60*60);
-         int zone_min = (abszone/60) % 60;
-         int zone_sec = abszone % 60;
-         sprintf (tzbuf, tzbuf_format, &"-"[XINT (zone) < 0],
-                  zone_hr, zone_min, zone_sec);
-         tzstring = tzbuf;
-       }
-      else
-       tzstring = 0;
-
-      timezone_t tz = tzstring ? tzalloc (tzstring) : 0;
-      if (! tz)
-       error ("Invalid time zone specification");
+      timezone_t tz = tzalloc (SSDATA (decode_time_zone (zone)));
       value = mktime_z (tz, &tm);
       tzfree (tz);
     }
@@ -2265,7 +2285,8 @@ the data it can't find.  */)
 DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
        doc: /* Set the local time zone using TZ, a string specifying a time zone rule.
 If TZ is nil, use implementation-defined default time zone information.
-If TZ is t, use Universal Time.
+If TZ is t, use Universal Time.  If TZ is an integer, it is treated as in
+`encode-time'.
 
 Instead of calling this function, you typically want (setenv "TZ" TZ).
 That changes both the environment of the Emacs process and the
@@ -2273,17 +2294,7 @@ variable `process-environment', whereas `set-time-zone-rule' affects
 only the former.  */)
   (Lisp_Object tz)
 {
-  const char *tzstring;
-
-  if (! (NILP (tz) || EQ (tz, Qt)))
-    CHECK_STRING (tz);
-
-  if (NILP (tz))
-    tzstring = initial_tz;
-  else if (EQ (tz, Qt))
-    tzstring = "UTC0";
-  else
-    tzstring = SSDATA (tz);
+  const char *tzstring = NILP (tz) ? initial_tz : SSDATA (decode_time_zone (tz));
 
   block_input ();
   set_time_zone_rule (tzstring);
@@ -2633,15 +2644,34 @@ make_buffer_string_both (ptrdiff_t start, ptrdiff_t start_byte,
                         ptrdiff_t end, ptrdiff_t end_byte, bool props)
 {
   Lisp_Object result, tem, tem1;
+  ptrdiff_t beg0, end0, beg1, end1, size;
 
-  if (start < GPT && GPT < end)
-    move_gap_both (start, start_byte);
+  if (start_byte < GPT_BYTE && GPT_BYTE < end_byte)
+    {
+      /* Two regions, before and after the gap.  */
+      beg0 = start_byte;
+      end0 = GPT_BYTE;
+      beg1 = GPT_BYTE + GAP_SIZE - BEG_BYTE;
+      end1 = end_byte + GAP_SIZE - BEG_BYTE;
+    }
+  else
+    {
+      /* The only region.  */
+      beg0 = start_byte;
+      end0 = end_byte;
+      beg1 = -1;
+      end1 = -1;
+    }
 
   if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
     result = make_uninit_multibyte_string (end - start, end_byte - start_byte);
   else
     result = make_uninit_string (end - start);
-  memcpy (SDATA (result), BYTE_POS_ADDR (start_byte), end_byte - start_byte);
+
+  size = end0 - beg0;
+  memcpy (SDATA (result), BYTE_POS_ADDR (beg0), size);
+  if (beg1 != -1)
+    memcpy (SDATA (result) + size, BEG_ADDR + beg1, end1 - beg1);
 
   /* If desired, update and copy the text properties.  */
   if (props)
@@ -2669,25 +2699,20 @@ update_buffer_properties (ptrdiff_t start, ptrdiff_t end)
      call them, specifying the range of the buffer being accessed.  */
   if (!NILP (Vbuffer_access_fontify_functions))
     {
-      Lisp_Object args[3];
-      Lisp_Object tem;
-
-      args[0] = Qbuffer_access_fontify_functions;
-      XSETINT (args[1], start);
-      XSETINT (args[2], end);
-
       /* But don't call them if we can tell that the work
         has already been done.  */
       if (!NILP (Vbuffer_access_fontified_property))
        {
-         tem = Ftext_property_any (args[1], args[2],
-                                   Vbuffer_access_fontified_property,
-                                   Qnil, Qnil);
-         if (! NILP (tem))
-           Frun_hook_with_args (3, args);
+         Lisp_Object tem
+           = Ftext_property_any (make_number (start), make_number (end),
+                                 Vbuffer_access_fontified_property,
+                                 Qnil, Qnil);
+         if (NILP (tem))
+           return;
        }
-      else
-       Frun_hook_with_args (3, args);
+
+      CALLN (Frun_hook_with_args, Qbuffer_access_fontify_functions,
+            make_number (start), make_number (end));
     }
 }
 
@@ -4506,7 +4531,7 @@ Lisp_Object
 format2 (const char *string1, Lisp_Object arg0, Lisp_Object arg1)
 {
   AUTO_STRING (format, string1);
-  return Fformat (3, (Lisp_Object []) {format, arg0, arg1});
+  return CALLN (Fformat, format, arg0, arg1);
 }
 \f
 DEFUN ("char-equal", Fchar_equal, Schar_equal, 2, 2, 0,
@@ -4948,8 +4973,7 @@ of the buffer being accessed.  */);
     /* Do this here, because init_buffer_once is too early--it won't work.  */
     Fset_buffer (Vprin1_to_string_buffer);
     /* Make sure buffer-access-fontify-functions is nil in this buffer.  */
-    Fset (Fmake_local_variable (intern_c_string ("buffer-access-fontify-functions")),
-         Qnil);
+    Fset (Fmake_local_variable (Qbuffer_access_fontify_functions), Qnil);
     Fset_buffer (obuf);
   }