(read_minibuf_unwind): Clear last_overlay_modified field.
[bpt/emacs.git] / src / editfns.c
index 6f18997..92daf88 100644 (file)
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include <sys/types.h>
@@ -177,7 +178,7 @@ Beginning of buffer is position (point-min)")
   ()
 {
   Lisp_Object temp;
-  XSETFASTINT (temp, point);
+  XSETFASTINT (temp, PT);
   return temp;
 }
 
@@ -185,7 +186,7 @@ DEFUN ("point-marker", Fpoint_marker, Spoint_marker, 0, 0, 0,
    "Return value of point, as a marker object.")
   ()
 {
-  return buildmark (point);
+  return buildmark (PT);
 }
 
 int
@@ -223,8 +224,8 @@ region_limit (beginningp)
     Fsignal (Qmark_inactive, Qnil);
   m = Fmarker_position (current_buffer->mark);
   if (NILP (m)) error ("There is no region now");
-  if ((point < XFASTINT (m)) == beginningp)
-    return (make_number (point));
+  if ((PT < XFASTINT (m)) == beginningp)
+    return (make_number (PT));
   else
     return (m);
 }
@@ -266,9 +267,10 @@ save_excursion_save ()
 
 Lisp_Object
 save_excursion_restore (info)
-     register Lisp_Object info;
+     Lisp_Object info;
 {
-  register Lisp_Object tem, tem1, omark, nmark;
+  Lisp_Object tem, tem1, omark, nmark;
+  struct gcpro gcpro1, gcpro2, gcpro3;
 
   tem = Fmarker_buffer (Fcar (info));
   /* If buffer being returned to is now deleted, avoid error */
@@ -277,6 +279,10 @@ save_excursion_restore (info)
   /* In that case, Fmarker_buffer returns nil now.  */
   if (NILP (tem))
     return Qnil;
+
+  omark = nmark = Qnil;
+  GCPRO3 (info, omark, nmark);
+
   Fset_buffer (tem);
   tem = Fcar (info);
   Fgoto_char (tem);
@@ -312,6 +318,7 @@ save_excursion_restore (info)
       else if (! NILP (tem1))
        call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
     }
+  UNGCPRO;
   return Qnil;
 }
 
@@ -386,10 +393,10 @@ At the end of the buffer or accessible region, return 0.")
   ()
 {
   Lisp_Object temp;
-  if (point >= ZV)
+  if (PT >= ZV)
     XSETFASTINT (temp, 0);
   else
-    XSETFASTINT (temp, FETCH_CHAR (point));
+    XSETFASTINT (temp, FETCH_CHAR (PT));
   return temp;
 }
 
@@ -399,10 +406,10 @@ At the beginning of the buffer or accessible region, return 0.")
   ()
 {
   Lisp_Object temp;
-  if (point <= BEGV)
+  if (PT <= BEGV)
     XSETFASTINT (temp, 0);
   else
-    XSETFASTINT (temp, FETCH_CHAR (point - 1));
+    XSETFASTINT (temp, FETCH_CHAR (PT - 1));
   return temp;
 }
 
@@ -411,7 +418,7 @@ DEFUN ("bobp", Fbobp, Sbobp, 0, 0, 0,
 If the buffer is narrowed, this means the beginning of the narrowed part.")
   ()
 {
-  if (point == BEGV)
+  if (PT == BEGV)
     return Qt;
   return Qnil;
 }
@@ -421,7 +428,7 @@ DEFUN ("eobp", Feobp, Seobp, 0, 0, 0,
 If the buffer is narrowed, this means the end of the narrowed part.")
   ()
 {
-  if (point == ZV)
+  if (PT == ZV)
     return Qt;
   return Qnil;
 }
@@ -430,7 +437,7 @@ DEFUN ("bolp", Fbolp, Sbolp, 0, 0, 0,
   "Return T if point is at the beginning of a line.")
   ()
 {
-  if (point == BEGV || FETCH_CHAR (point - 1) == '\n')
+  if (PT == BEGV || FETCH_CHAR (PT - 1) == '\n')
     return Qt;
   return Qnil;
 }
@@ -440,7 +447,7 @@ DEFUN ("eolp", Feolp, Seolp, 0, 0, 0,
 `End of a line' includes point being at the end of the buffer.")
   ()
 {
-  if (point == ZV || FETCH_CHAR (point) == '\n')
+  if (PT == ZV || FETCH_CHAR (PT) == '\n')
     return Qt;
   return Qnil;
 }
@@ -600,8 +607,7 @@ FORMAT-STRING may contain %-sequences to substitute parts of the time.\n\
 %A is replaced by the full name of the day of week.\n\
 %b is replaced by the abbreviated name of the month.\n\
 %B is replaced by the full name of the month.\n\
-%c is a synonym for \"%x %X\".\n\
-%C is a locale-specific synonym, which defaults to \"%A, %B %e, %Y\" in the C locale.\n\
+%c stands for the preferred date/time format of the C locale.\n\
 %d is replaced by the day of month, zero-padded.\n\
 %D is a synonym for \"%m/%d/%y\".\n\
 %e is replaced by the day of month, blank-padded.\n\
@@ -620,9 +626,9 @@ FORMAT-STRING may contain %-sequences to substitute parts of the time.\n\
 %S is replaced by the second (00-60).\n\
 %t is a synonym for \"\\t\".\n\
 %T is a synonym for \"%H:%M:%S\".\n\
-%U is replaced by the week of the year (01-52), first day of week is Sunday.\n\
+%U is replaced by the week of the year (00-53), first day of week is Sunday.\n\
 %w is replaced by the day of week (0-6), Sunday is day 0.\n\
-%W is replaced by the week of the year (01-52), first day of week is Monday.\n\
+%W is replaced by the week of the year (00-53), first day of week is Monday.\n\
 %x is a locale-specific synonym, which defaults to \"%D\" in the C locale.\n\
 %X is a locale-specific synonym, which defaults to \"%T\" in the C locale.\n\
 %y is replaced by the year without century (00-99).\n\
@@ -687,7 +693,7 @@ ZONE is an integer indicating the number of seconds east of Greenwich.\n\
   XSETFASTINT (list_args[2], decoded_time->tm_hour);
   XSETFASTINT (list_args[3], decoded_time->tm_mday);
   XSETFASTINT (list_args[4], decoded_time->tm_mon + 1);
-  XSETFASTINT (list_args[5], decoded_time->tm_year + 1900);
+  XSETINT (list_args[5], decoded_time->tm_year + 1900);
   XSETFASTINT (list_args[6], decoded_time->tm_wday);
   list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil;
 
@@ -701,36 +707,44 @@ ZONE is an integer indicating the number of seconds east of Greenwich.\n\
   return Flist (9, list_args);
 }
 
-DEFUN ("encode-time", Fencode_time, Sencode_time, 6, 7, 0,
+DEFUN ("encode-time", Fencode_time, Sencode_time, 6, MANY, 0,
   "Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.\n\
-This is the reverse operation of `decode-time', which see.  ZONE defaults\n\
-to the current time zone rule if not specified; if specified, it can\n\
-be a string (as from `set-time-zone-rule'), or it can be a list\n\
+This is the reverse operation of `decode-time', which see.\n\
+ZONE defaults to the current time zone rule.  This can\n\
+be a string or t (as from `set-time-zone-rule'), or it can be a list\n\
 (as from `current-time-zone') or an integer (as from `decode-time')\n\
 applied without consideration for daylight savings time.\n\
+\n\
+You can pass more than 7 arguments; then the first six arguments\n\
+are used as SECOND through YEAR, and the *last* argument is used as ZONE.\n\
+The intervening arguments are ignored.\n\
+This feature lets (apply 'encode-time (decode-time ...)) work.\n\
+\n\
 Out-of-range values for SEC, MINUTE, HOUR, DAY, or MONTH are allowed;\n\
 for example, a DAY of 0 means the day preceding the given month.\n\
 Year numbers less than 100 are treated just like other year numbers.\n\
 If you want them to stand for years in this century, you must do that yourself.")
-  (second, minute, hour, day, month, year, zone)
-     Lisp_Object second, minute, hour, day, month, year, zone;
+  (nargs, args)
+     int nargs;
+     register Lisp_Object *args;
 {
   time_t time;
   struct tm tm;
-
-  CHECK_NUMBER (second, 0);
-  CHECK_NUMBER (minute, 1);
-  CHECK_NUMBER (hour, 2);
-  CHECK_NUMBER (day, 3);
-  CHECK_NUMBER (month, 4);
-  CHECK_NUMBER (year, 5);
-
-  tm.tm_sec = XINT (second);
-  tm.tm_min = XINT (minute);
-  tm.tm_hour = XINT (hour);
-  tm.tm_mday = XINT (day);
-  tm.tm_mon = XINT (month) - 1;
-  tm.tm_year = XINT (year) - 1900;
+  Lisp_Object zone = (nargs > 6)? args[nargs - 1] : Qnil;
+
+  CHECK_NUMBER (args[0], 0);   /* second */
+  CHECK_NUMBER (args[1], 1);   /* minute */
+  CHECK_NUMBER (args[2], 2);   /* hour */
+  CHECK_NUMBER (args[3], 3);   /* day */
+  CHECK_NUMBER (args[4], 4);   /* month */
+  CHECK_NUMBER (args[5], 5);   /* year */
+
+  tm.tm_sec = XINT (args[0]);
+  tm.tm_min = XINT (args[1]);
+  tm.tm_hour = XINT (args[2]);
+  tm.tm_mday = XINT (args[3]);
+  tm.tm_mon = XINT (args[4]) - 1;
+  tm.tm_year = XINT (args[5]) - 1900;
   tm.tm_isdst = -1;
 
   if (CONSP (zone))
@@ -743,7 +757,9 @@ If you want them to stand for years in this century, you must do that yourself."
       char *tzstring;
       char **oldenv = environ, **newenv;
       
-      if (STRINGP (zone))
+      if (zone == Qt)
+       tzstring = "UTC0";
+      else if (STRINGP (zone))
        tzstring = (char *) XSTRING (zone)->data;
       else if (INTEGERP (zone))
        {
@@ -814,14 +830,17 @@ difftm (a, b)
 {
   int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
   int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+  /* Divide years by 100, rounding towards minus infinity.  */
+  int ac = ay / 100 - (ay % 100 < 0);
+  int bc = by / 100 - (by % 100 < 0);
   /* 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))
+             -  (ac - bc)
+             +  ((ac >> 2) - (bc >> 2))
              /* + difference in years * 365 */
              +  (long)(ay-by) * 365
              );
@@ -893,7 +912,8 @@ static char **environbuf;
 
 DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
   "Set the local time zone using TZ, a string specifying a time zone rule.\n\
-If TZ is nil, use implementation-defined default time zone information.")
+If TZ is nil, use implementation-defined default time zone information.\n\
+If TZ is t, use Universal Time.")
   (tz)
      Lisp_Object tz;
 {
@@ -901,6 +921,8 @@ If TZ is nil, use implementation-defined default time zone information.")
 
   if (NILP (tz))
     tzstring = 0;
+  else if (tz == Qt)
+    tzstring = "UTC0";
   else
     {
       CHECK_STRING (tz, 0);
@@ -915,6 +937,17 @@ If TZ is nil, use implementation-defined default time zone information.")
   return Qnil;
 }
 
+/* These two values are known to load tz files in buggy implementations.
+   Their values shouldn't matter in non-buggy implementations.
+   We don't use string literals for these strings, 
+   since if a string in the environment is in readonly
+   storage, it runs afoul of bugs in SVR4 and Solaris 2.3.
+   See Sun bugs 1113095 and 1114114, ``Timezone routines
+   improperly modify environment''.  */
+
+static char set_time_zone_rule_tz1[] = "TZ=GMT0";
+static char set_time_zone_rule_tz2[] = "TZ=GMT1";
+
 /* Set the local time zone rule to TZSTRING.
    This allocates memory into `environ', which it is the caller's
    responsibility to free.  */
@@ -925,11 +958,14 @@ set_time_zone_rule (tzstring)
   int envptrs;
   char **from, **to, **newenv;
 
+  /* Make the ENVIRON vector longer with room for TZSTRING.  */
   for (from = environ; *from; from++)
     continue;
   envptrs = from - environ + 2;
   newenv = to = (char **) xmalloc (envptrs * sizeof (char *)
                                   + (tzstring ? strlen (tzstring) + 4 : 0));
+
+  /* Add TZSTRING to the end of environ, as a value for TZ.  */
   if (tzstring)
     {
       char *t = (char *) (to + envptrs);
@@ -938,6 +974,9 @@ set_time_zone_rule (tzstring)
       *to++ = t;
     }
 
+  /* Copy the old environ vector elements into NEWENV,
+     but don't copy the TZ variable.
+     So we have only one definition of TZ, which came from TZSTRING.  */
   for (from = environ; *from; from++)
     if (strncmp (*from, "TZ=", 3) != 0)
       *to++ = *from;
@@ -945,7 +984,45 @@ set_time_zone_rule (tzstring)
 
   environ = newenv;
 
+  /* If we do have a TZSTRING, NEWENV points to the vector slot where
+     the TZ variable is stored.  If we do not have a TZSTRING,
+     TO points to the vector slot which has the terminating null.  */
+
 #ifdef LOCALTIME_CACHE
+  {
+    /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like
+       "US/Pacific" that loads a tz file, then changes to a value like
+       "XXX0" that does not load a tz file, and then changes back to
+       its original value, the last change is (incorrectly) ignored.
+       Also, if TZ changes twice in succession to values that do
+       not load a tz file, tzset can dump core (see Sun bug#1225179).
+       The following code works around these bugs.  */
+
+    if (tzstring)
+      {
+       /* Temporarily set TZ to a value that loads a tz file
+          and that differs from tzstring.  */
+       char *tz = *newenv;
+       *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0
+                  ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1);
+       tzset ();
+       *newenv = tz;
+      }
+    else
+      {
+       /* The implied tzstring is unknown, so temporarily set TZ to
+          two different values that each load a tz file.  */
+       *to = set_time_zone_rule_tz1;
+       to[1] = 0;
+       tzset ();
+       *to = set_time_zone_rule_tz2;
+       tzset ();
+       *to = 0;
+      }
+
+    /* Now TZ has the desired value, and tzset can be invoked safely.  */
+  }
+
   tzset ();
 #endif
 }
@@ -1287,6 +1364,8 @@ They default to the beginning and the end of BUFFER.")
   if (NILP (buffer))
     nsberror (buf);
   bp = XBUFFER (buffer);
+  if (NILP (bp->name))
+    error ("Selecting deleted buffer");
 
   if (NILP (start))
     b = BUF_BEGV (bp);
@@ -1347,6 +1426,8 @@ determines whether case is significant or ignored.")
       if (NILP (buf1))
        nsberror (buffer1);
       bp1 = XBUFFER (buf1);
+      if (NILP (bp1->name))
+       error ("Selecting deleted buffer");
     }
 
   if (NILP (start1))
@@ -1382,7 +1463,9 @@ determines whether case is significant or ignored.")
       buf2 = Fget_buffer (buffer2);
       if (NILP (buf2))
        nsberror (buffer2);
-      bp2 = XBUFFER (buffer2);
+      bp2 = XBUFFER (buf2);
+      if (NILP (bp2->name))
+       error ("Selecting deleted buffer");
     }
 
   if (NILP (start2))
@@ -1622,9 +1705,9 @@ or markers) bounding the text that should remain visible.")
 
   BEGV = XFASTINT (start);
   SET_BUF_ZV (current_buffer, XFASTINT (end));
-  if (point < XFASTINT (start))
+  if (PT < XFASTINT (start))
     SET_PT (XFASTINT (start));
-  if (point > XFASTINT (end))
+  if (PT > XFASTINT (end))
     SET_PT (XFASTINT (end));
   current_buffer->clip_changed = 1;
   /* Changing the buffer bounds invalidates any recorded current column.  */
@@ -1970,7 +2053,7 @@ Use %% to put a single % into the output.")
             because it is the format string.  */
          strings[i++] = XSTRING (args[n])->data;
        else
-         strings[i++] = (unsigned char *) XFASTINT (args[n]);
+         strings[i++] = (unsigned char *) XSTRING (args[n]);
       }
 
     /* Make room in result for all the non-%-codes in the control string.  */
@@ -2387,6 +2470,18 @@ Each function is called with two arguments which specify the range\n\
 of the buffer being accessed.");
   Vbuffer_access_fontify_functions = Qnil;
 
+  {
+    Lisp_Object obuf;
+    extern Lisp_Object Vprin1_to_string_buffer;
+    obuf = Fcurrent_buffer ();
+    /* 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 ("buffer-access-fontify-functions")),
+         Qnil);
+    Fset_buffer (obuf);
+  }
+
   DEFVAR_LISP ("buffer-access-fontified-property",
               &Vbuffer_access_fontified_property,
        "Property which (if non-nil) indicates text has been fontified.\n\