(setenv): Call set-time-zone-rule when setting TZ.
[bpt/emacs.git] / src / editfns.c
index f2ed73c..42fb68a 100644 (file)
@@ -5,7 +5,7 @@ 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 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -44,9 +44,9 @@ static long difftm ();
 /* Some static data, and a function to initialize it for each run */
 
 Lisp_Object Vsystem_name;
-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 */
+Lisp_Object Vuser_real_login_name;     /* login name of current user ID */
+Lisp_Object Vuser_full_name;           /* full name of current user */
+Lisp_Object Vuser_login_name;          /* user name from LOGNAME or USER */
 
 void
 init_editfns ()
@@ -71,9 +71,9 @@ init_editfns ()
   /* We let the real user name default to "root" because that's quite
      accurate on MSDOG and because it lets Emacs find the init file.
      (The DVX libraries override the Djgpp libraries here.)  */
-  Vuser_real_name = build_string (pw ? pw->pw_name : "root");
+  Vuser_real_login_name = build_string (pw ? pw->pw_name : "root");
 #else
-  Vuser_real_name = build_string (pw ? pw->pw_name : "unknown");
+  Vuser_real_login_name = build_string (pw ? pw->pw_name : "unknown");
 #endif
 
   /* Get the effective user name, by consulting environment variables,
@@ -90,13 +90,13 @@ init_editfns ()
       pw = (struct passwd *) getpwuid (geteuid ());
       user_name = (char *) (pw ? pw->pw_name : "unknown");
     }
-  Vuser_name = build_string (user_name);
+  Vuser_login_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);
+  tem = Fstring_equal (Vuser_login_name, Vuser_real_login_name);
   if (NILP (tem))
-    pw = (struct passwd *) getpwnam (XSTRING (Vuser_name)->data);
+    pw = (struct passwd *) getpwnam (XSTRING (Vuser_login_name)->data);
   
   p = (unsigned char *) (pw ? USER_FULL_NAME : "unknown");
   q = (unsigned char *) index (p, ',');
@@ -108,10 +108,11 @@ init_editfns ()
   /* Substitute the login name for the &, upcasing the first character.  */
   if (q)
     {
-      r = (unsigned char *) alloca (strlen (p) + XSTRING (Vuser_name)->size + 1);
+      r = (unsigned char *) alloca (strlen (p)
+                                   + XSTRING (Vuser_login_name)->size + 1);
       bcopy (p, r, q - p);
       r[q - p] = 0;
-      strcat (r, XSTRING (Vuser_name)->data);
+      strcat (r, XSTRING (Vuser_login_name)->data);
       r[q - p] = UPCASE (r[q - p]);
       strcat (r, q + 1);
       Vuser_full_name = build_string (r);
@@ -234,17 +235,6 @@ DEFUN ("region-end", Fregion_end, Sregion_end, 0, 0, 0,
   return (region_limit (0));
 }
 
-#if 0 /* now in lisp code */
-DEFUN ("mark", Fmark, Smark, 0, 0, 0,
-  "Return this buffer's mark value as integer, or nil if no mark.\n\
-If you are using this in an editing command, you are most likely making\n\
-a mistake; see the documentation of `set-mark'.")
-  ()
-{
-  return Fmarker_position (current_buffer->mark);
-}
-#endif /* commented out code */
-
 DEFUN ("mark-marker", Fmark_marker, Smark_marker, 0, 0, 0,
   "Return this buffer's mark, as a marker object.\n\
 Watch out!  Moving this marker changes the mark position.\n\
@@ -254,41 +244,6 @@ If you set the marker not to point anywhere, the buffer will have no mark.")
   return current_buffer->mark;
 }
 
-#if 0 /* this is now in lisp code */
-DEFUN ("set-mark", Fset_mark, Sset_mark, 1, 1, 0,
-  "Set this buffer's mark to POS.  Don't use this function!\n\
-That is to say, don't use this function unless you want\n\
-the user to see that the mark has moved, and you want the previous\n\
-mark position to be lost.\n\
-\n\
-Normally, when a new mark is set, the old one should go on the stack.\n\
-This is why most applications should use push-mark, not set-mark.\n\
-\n\
-Novice programmers often try to use the mark for the wrong purposes.\n\
-The mark saves a location for the user's convenience.\n\
-Most editing commands should not alter the mark.\n\
-To remember a location for internal use in the Lisp program,\n\
-store it in a Lisp variable.  Example:\n\
-\n\
-   (let ((beg (point))) (forward-line 1) (delete-region beg (point))).")
-  (pos)
-     Lisp_Object pos;
-{
-  if (NILP (pos))
-    {
-      current_buffer->mark = Qnil;
-      return Qnil;
-    }
-  CHECK_NUMBER_COERCE_MARKER (pos, 0);
-
-  if (NILP (current_buffer->mark))
-    current_buffer->mark = Fmake_marker ();
-
-  Fset_marker (current_buffer->mark, pos, Qnil);
-  return pos;
-}
-#endif /* commented-out code */
-
 Lisp_Object
 save_excursion_save ()
 {
@@ -296,7 +251,7 @@ save_excursion_save ()
                          == current_buffer);
 
   return Fcons (Fpoint_marker (),
-               Fcons (Fcopy_marker (current_buffer->mark),
+               Fcons (Fcopy_marker (current_buffer->mark, Qnil),
                       Fcons (visible ? Qt : Qnil,
                              current_buffer->mark_active)));                  
 }
@@ -516,11 +471,11 @@ with that uid, or nil if there is no such user.")
   /* Set up the user name info if we didn't do it before.
      (That can happen if Emacs is dumpable
      but you decide to run `temacs -l loadup' and not dump.  */
-  if (INTEGERP (Vuser_name))
+  if (INTEGERP (Vuser_login_name))
     init_editfns ();
 
   if (NILP (uid))
-    return Vuser_name;
+    return Vuser_login_name;
 
   CHECK_NUMBER (uid, 0);
   pw = (struct passwd *) getpwuid (XINT (uid));
@@ -537,9 +492,9 @@ This ignores the environment variables LOGNAME and USER, so it differs from\n\
   /* Set up the user name info if we didn't do it before.
      (That can happen if Emacs is dumpable
      but you decide to run `temacs -l loadup' and not dump.  */
-  if (INTEGERP (Vuser_name))
+  if (INTEGERP (Vuser_login_name))
     init_editfns ();
-  return Vuser_real_name;
+  return Vuser_real_login_name;
 }
 
 DEFUN ("user-uid", Fuser_uid, Suser_uid, 0, 0, 0,
@@ -697,13 +652,14 @@ DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 1, 0,
 The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED)\n\
 or (HIGH . LOW), as from `current-time' and `file-attributes', or `nil'\n\
 to use the current time.  The list has the following nine members:\n\
-SEC is an integer between 0 and 59.  MINUTE is an integer between 0 and 59.\n\
+SEC is an integer between 0 and 60; SEC is 60 for a leap second, which\n\
+only some operating systems support.  MINUTE is an integer between 0 and 59.\n\
 HOUR is an integer between 0 and 23.  DAY is an integer between 1 and 31.\n\
 MONTH is an integer between 1 and 12.  YEAR is an integer indicating the\n\
 four-digit year.  DOW is the day of week, an integer between 0 and 6, where\n\
 0 is Sunday.  DST is t if daylight savings time is effect, otherwise nil.\n\
 ZONE is an integer indicating the number of seconds east of Greenwich.\n\
-(Note that Common Lisp has different meanings for DOW and ZONE.)")
+\(Note that Common Lisp has different meanings for DOW and ZONE.)")
   (specified_time)
      Lisp_Object specified_time;
 {
@@ -735,6 +691,9 @@ ZONE is an integer indicating the number of seconds east of Greenwich.\n\
   return Flist (9, list_args);
 }
 
+static char days_per_month[11]
+  = { 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 };
+
 DEFUN ("encode-time", Fencode_time, Sencode_time, 6, 7, 0,
   "Convert SEC, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.\n\
 This is the reverse operation of `decode-time', which see.  ZONE defaults\n\
@@ -743,13 +702,12 @@ specified, it can be either a list (as from `current-time-zone') or an\n\
 integer (as from `decode-time'), and is applied without consideration for\n\
 daylight savings time.\n\
 Year numbers less than 100 are treated just like other year numbers.\n\
-If you them to stand for years above 1900, you must do that yourself.")
+If you want them to stand for years above 1900, you must do that yourself.")
   (sec, minute, hour, day, month, year, zone)
      Lisp_Object sec, minute, hour, day, month, year, zone;
 {
   time_t time;
   int fullyear, mon, days, seconds, tz = 0;
-  static char days_per_month[11] = { 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 };
 
   CHECK_NATNUM (sec, 0);
   CHECK_NATNUM (minute, 1);
@@ -1375,6 +1333,13 @@ subst_char_in_region_unwind (arg)
   return current_buffer->undo_list = arg;
 }
 
+static Lisp_Object
+subst_char_in_region_unwind_1 (arg)
+     Lisp_Object arg;
+{
+  return current_buffer->filename = arg;
+}
+
 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\
@@ -1397,12 +1362,17 @@ and don't mark the buffer as really changed.")
 
   /* If we don't want undo, turn off putting stuff on the list.
      That's faster than getting rid of things,
-     and it prevents even the entry for a first change.  */
+     and it prevents even the entry for a first change.
+     Also inhibit locking the file.  */
   if (!NILP (noundo))
     {
       record_unwind_protect (subst_char_in_region_unwind,
                             current_buffer->undo_list);
       current_buffer->undo_list = Qt;
+      /* Don't do file-locking.  */
+      record_unwind_protect (subst_char_in_region_unwind_1,
+                            current_buffer->filename);
+      current_buffer->filename = Qnil;
     }
 
   while (pos < stop)
@@ -1506,7 +1476,7 @@ This allows the buffer's full text to be seen and edited.")
 {
   BEGV = BEG;
   SET_BUF_ZV (current_buffer, Z);
-  clip_changed = 1;
+  current_buffer->clip_changed = 1;
   /* Changing the buffer bounds invalidates any recorded current column.  */
   invalidate_current_column ();
   return Qnil;
@@ -1542,7 +1512,7 @@ or markers) bounding the text that should remain visible.")
     SET_PT (XFASTINT (b));
   if (point > XFASTINT (e))
     SET_PT (XFASTINT (e));
-  clip_changed = 1;
+  current_buffer->clip_changed = 1;
   /* Changing the buffer bounds invalidates any recorded current column.  */
   invalidate_current_column ();
   return Qnil;
@@ -1584,7 +1554,7 @@ save_restriction_restore (data)
     }
   BUF_BEGV (buf) = BUF_BEG (buf) + newhead;
   SET_BUF_ZV (buf, BUF_Z (buf) - newtail);
-  clip_changed = 1;
+  current_buffer->clip_changed = 1;
 
   /* If point is outside the new visible range, move it inside. */
   SET_BUF_PT (buf,
@@ -1630,12 +1600,9 @@ static int message_length;
 
 DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
   "Print a one-line message at the bottom of the screen.\n\
-The first argument is a control string.\n\
-It may contain %s or %d or %c to print successive following arguments.\n\
-%s means print an argument as a string, %d means print as number in decimal,\n\
-%c means print a number as a single character.\n\
-The argument used by %s must be a string or a symbol;\n\
-the argument used by %d or %c must be a number.\n\
+The first argument is a format control string, and the rest are data\n\
+to be formatted under control of the string.  See `format' for details.\n\
+\n\
 If the first argument is nil, clear any existing message; let the\n\
 minibuffer contents show.")
   (nargs, args)
@@ -1755,9 +1722,13 @@ 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 a string argument.  Actually, prints any object, with `princ'.\n\
 %d means print as number in decimal (%o octal, %x hex).\n\
+%e means print a number in exponential notation.\n\
+%f means print a number in decimal-point notation.\n\
+%g means print a number in exponential notation\n\
+  or decimal-point notation, whichever uses fewer characters.\n\
 %c means print a number as a single character.\n\
 %S means print any object as an s-expression (using prin1).\n\
-  The argument used for %d, %o, %x or %c must be a number.\n\
+  The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.\n\
 Use %% to put a single % into the output.")
   (nargs, args)
      int nargs;
@@ -1784,10 +1755,9 @@ Use %% to put a single % into the output.")
 
        /* Process a numeric arg and skip it.  */
        minlen = atoi (format);
-       if (minlen > 0)
-         total += minlen;
-       else
-         total -= minlen;
+       if (minlen < 0)
+         minlen = - minlen;
+
        while ((*format >= '0' && *format <= '9')
               || *format == '-' || *format == ' ' || *format == '.')
          format++;
@@ -1795,7 +1765,7 @@ Use %% to put a single % into the output.")
        if (*format == '%')
          format++;
        else if (++n >= nargs)
-         error ("not enough arguments for format string");
+         error ("Not enough arguments for format string");
        else if (*format == 'S')
          {
            /* For `S', prin1 the argument and then treat like a string.  */
@@ -1815,6 +1785,10 @@ Use %% to put a single % into the output.")
            if (*format != 's' && *format != 'S')
              error ("format specifier doesn't match argument type");
            total += XSTRING (args[n])->size;
+           /* We have to put an arbitrary limit on minlen
+              since otherwise it could make alloca fail.  */
+           if (minlen < XSTRING (args[n])->size + 1000)
+             total += minlen;
          }
        /* Would get MPV otherwise, since Lisp_Int's `point' to low memory.  */
        else if (INTEGERP (args[n]) && *format != 's')
@@ -1828,6 +1802,10 @@ Use %% to put a single % into the output.")
              args[n] = Ffloat (args[n]);
 #endif
            total += 30;
+           /* We have to put an arbitrary limit on minlen
+              since otherwise it could make alloca fail.  */
+           if (minlen < 1000)
+             total += minlen;
          }
 #ifdef LISP_FLOAT_TYPE
        else if (FLOATP (args[n]) && *format != 's')
@@ -1835,6 +1813,10 @@ Use %% to put a single % into the output.")
            if (! (*format == 'e' || *format == 'f' || *format == 'g'))
              args[n] = Ftruncate (args[n]);
            total += 30;
+           /* We have to put an arbitrary limit on minlen
+              since otherwise it could make alloca fail.  */
+           if (minlen < 1000)
+             total += minlen;
          }
 #endif
        else
@@ -1868,17 +1850,20 @@ Use %% to put a single % into the output.")
 #ifdef LISP_FLOAT_TYPE
        else if (FLOATP (args[n]))
          {
-           union { double d; int half[2]; } u;
+           union { double d; char *half[2]; } u;
 
            u.d = XFLOAT (args[n])->data;
-           strings[i++] = (unsigned char *) (EMACS_INT) u.half[0];
-           strings[i++] = (unsigned char *) (EMACS_INT) u.half[1];
+           strings[i++] = (unsigned char *) u.half[0];
+           strings[i++] = (unsigned char *) u.half[1];
          }
 #endif
        else
          strings[i++] = XSTRING (args[n])->data;
       }
 
+    /* Make room in result for all the non-%-codes in the control string.  */
+    total += XSTRING (args[0])->size;
+
     /* Format it in bigger and bigger buf's until it all fits. */
     while (1)
       {
@@ -1915,9 +1900,9 @@ format1 (string1)
   args[2] = arg2;
   args[3] = arg3;
   args[4] = arg4;
-  doprnt (buf, sizeof buf, string1, 0, 5, args);
+  doprnt (buf, sizeof buf, string1, (char *)0, 5, args);
 #else
-  doprnt (buf, sizeof buf, string1, 0, 5, &string1 + 1);
+  doprnt (buf, sizeof buf, string1, (char *)0, 5, &string1 + 1);
 #endif
   return build_string (buf);
 }
@@ -2281,10 +2266,10 @@ syms_of_editfns ()
   DEFVAR_LISP ("user-full-name", &Vuser_full_name,
               "The full name of the user logged in.");
 
-  DEFVAR_LISP ("user-name", &Vuser_name,
+  DEFVAR_LISP ("user-login-name", &Vuser_login_name,
               "The user's name, taken from environment variables if possible.");
 
-  DEFVAR_LISP ("user-real-name", &Vuser_real_name,
+  DEFVAR_LISP ("user-real-login-name", &Vuser_real_login_name,
               "The user's name, based upon the real uid only.");
 
   defsubr (&Schar_equal);