(lm): Use "p" not "P" for interactive spec.
[bpt/emacs.git] / src / editfns.c
index dcc6445..e50ef45 100644 (file)
@@ -1,5 +1,5 @@
 /* Lisp functions pertaining to editing.
-   Copyright (C) 1985,86,87,89,93,94,95,96,97,98, 1999, 2000
+   Copyright (C) 1985,86,87,89,93,94,95,96,97,98, 1999, 2000, 2001
        Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -167,7 +167,9 @@ DEFUN ("char-to-string", Fchar_to_string, Schar_to_string, 1, 1, 0,
 
   CHECK_NUMBER (character, 0);
 
-  len = CHAR_STRING (XFASTINT (character), str);
+  len = (SINGLE_BYTE_CHAR_P (XFASTINT (character))
+        ? (*str = (unsigned char)(XFASTINT (character)), 1)
+        : char_to_string (XFASTINT (character), str));
   return make_string_from_bytes (str, 1, len);
 }
 
@@ -442,7 +444,8 @@ find_field (pos, merge_at_boundary, beg, end)
           also eat insertions here, but then they will overlap, and
           there's not much we can do.  */
        stickiness = -1;
-      else if (aop && XMARKER(OVERLAY_END(after_overlay))->insertion_type == 0)
+      else if (aop
+              && XMARKER (OVERLAY_START (after_overlay))->insertion_type == 0)
        /* after_field is from an overlay, which expand to contain
           start-insertions.  */
        stickiness = 1;
@@ -613,7 +616,7 @@ DEFUN ("constrain-to-field", Fconstrain_to_field, Sconstrain_to_field, 2, 5, 0,
 \n\
 A field is a region of text with the same `field' property.\n\
 If NEW-POS is nil, then the current point is used instead, and set to the\n\
-constrained position if that is is different.\n\
+constrained position if that is different.\n\
 \n\
 If OLD-POS is at the boundary of two fields, then the allowable\n\
 positions for NEW-POS depends on the value of the optional argument\n\
@@ -840,12 +843,16 @@ save_excursion_restore (info)
     }
 
   /* If buffer was visible in a window, and a different window was
-     selected, and the old selected window is still live, restore
-     point in that window.  */
+     selected, and the old selected window is still showing this
+     buffer, restore point in that window.  */
   tem = XCDR (info);
   if (visible_p
       && !EQ (tem, selected_window)
-      && !NILP (Fwindow_live_p (tem)))
+      && (tem1 = XWINDOW (tem)->buffer,
+         (/* Window is live...  */
+          BUFFERP (tem1)
+          /* ...and it shows the current buffer.  */
+          && XBUFFER (tem1) == current_buffer)))
     Fset_window_point (tem, make_number (PT));
 
   UNGCPRO;
@@ -1354,7 +1361,10 @@ If an argument is given, it specifies a time to convert to float\n\
 instead of the current time.  The argument should have the forms:\n\
  (HIGH . LOW) or (HIGH LOW USEC) or (HIGH LOW . USEC).\n\
 Thus, you can use times obtained from `current-time'\n\
-and from `file-attributes'.")
+and from `file-attributes'.\n\
+\n\
+WARNING: Since the result is floating point, it may not be exact.\n\
+Do not use this function if precise time stamps are required.")
   (specified_time)
      Lisp_Object specified_time;
 {
@@ -1364,7 +1374,7 @@ and from `file-attributes'.")
   if (! lisp_time_argument (specified_time, &sec, &usec))
     error ("Invalid time specification");
 
-  return make_float (sec + usec * 0.0000001);
+  return make_float ((sec * 1e6 + usec) / 1e6);
 }
 
 /* Write information into buffer S of size MAXSIZE, according to the
@@ -1460,8 +1470,11 @@ by text that describes the specified date and time in TIME:\n\
 Finally, %n is a newline, %t is a tab, %% is a literal %.\n\
 \n\
 Certain flags and modifiers are available with some format controls.\n\
-The flags are `_' and `-'.  For certain characters X, %_X is like %X,\n\
-but padded with blanks; %-X is like %X, but without padding.\n\
+The flags are `_', `-', `^' and `#'.  For certain characters X,\n\
+%_X is like %X, but padded with blanks; %-X is like %X,\n\
+ut without padding.  %^X is like %X but with all textual\n\
+characters up-cased; %#X is like %X but with letter-case of\n\
+all textual characters reversed.\n\
 %NX (where N stands for an integer) is like %X,\n\
 but takes up at least N (a number) positions.\n\
 The modifiers are `E' and `O'.  For certain characters X,\n\
@@ -1750,6 +1763,20 @@ the data it can't find.")
        s = tzname[t->tm_isdst];
 #endif
 #endif /* not HAVE_TM_ZONE */
+
+#if defined HAVE_TM_ZONE || defined HAVE_TZNAME
+      if (s)
+       {
+         /* On Japanese w32, we can get a Japanese string as time
+            zone name.  Don't accept that.  */
+         char *p;
+         for (p = s; *p && (isalnum (*p) || *p == ' '); ++p)
+           ;
+         if (p == s || *p)
+           s = NULL;
+       }
+#endif
+
       if (!s)
        {
          /* No local time zone name is available; use "+-NNNN" instead.  */
@@ -2190,7 +2217,11 @@ DEFUN ("buffer-substring", Fbuffer_substring, Sbuffer_substring, 2, 2, 0,
   "Return the contents of part of the current buffer as a string.\n\
 The two arguments START and END are character positions;\n\
 they can be in either order.\n\
-The string returned is multibyte if the buffer is multibyte.")
+The string returned is multibyte if the buffer is multibyte.\n\
+\n\
+This function copies the text properties of that part of the buffer\n\
+into the result string; if you don't want the text properties,\n\
+use `buffer-substring-no-properties' instead.")
   (start, end)
      Lisp_Object start, end;
 {
@@ -3053,6 +3084,7 @@ 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\
+%X is like %x, but uses upper case.\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\
@@ -3116,17 +3148,45 @@ Use %% to put a single % into the output.")
   while (format != end)
     if (*format++ == '%')
       {
-       int minlen, thissize = 0;
+       int thissize = 0;
        unsigned char *this_format_start = format - 1;
+       int field_width, precision;
 
-       /* Process a numeric arg and skip it.  */
-       minlen = atoi (format);
-       if (minlen < 0)
-         minlen = - minlen;
+       /* General format specifications look like
 
-       while ((*format >= '0' && *format <= '9')
-              || *format == '-' || *format == ' ' || *format == '.')
-         format++;
+          '%' [flags] [field-width] [precision] format
+
+          where
+
+          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
+          string is shorter than field-width.
+
+          if precision is specified, it specifies the number of
+          digits to print after the '.' for floats, or the max.
+          number of chars to print from a string.  */
+
+       precision = field_width = 0;
+       
+       while (index ("-*# 0", *format))
+         ++format;
+
+       if (*format >= '0' && *format <= '9')
+         {
+           for (field_width = 0; *format >= '0' && *format <= '9'; ++format)
+             field_width = 10 * field_width + *format - '0';
+         }
+
+       if (*format == '.')
+         {
+           ++format;
+           for (precision = 0; *format >= '0' && *format <= '9'; ++format)
+             precision = 10 * precision + *format - '0';
+         }
 
        if (format - this_format_start + 1 > longest_format)
          longest_format = format - this_format_start + 1;
@@ -3202,7 +3262,11 @@ Use %% to put a single % into the output.")
          {
            if (! (*format == 'e' || *format == 'f' || *format == 'g'))
              args[n] = Ftruncate (args[n], Qnil);
-           thissize = 200;
+
+           /* Note that we're using sprintf to print floats,
+              so we have to take into account what that function
+              prints.  */
+           thissize = 200 + precision;
          }
        else
          {
@@ -3218,9 +3282,7 @@ Use %% to put a single % into the output.")
            goto string;
          }
 
-       if (thissize < minlen)
-         thissize = minlen;
-
+       thissize = max (field_width, thissize);
        total += thissize + 4;
       }
 
@@ -3273,10 +3335,8 @@ Use %% to put a single % into the output.")
 
          if (STRINGP (args[n]))
            {
-             int padding, nbytes;
-             int width = strwidth (XSTRING (args[n])->data,
-                                   STRING_BYTES (XSTRING (args[n])));
-             int start = nchars;
+             int padding, nbytes, start, end;
+             int width = lisp_string_width (args[n], -1, NULL, NULL);
 
              /* If spec requires it, pad on right with spaces.  */
              padding = minlen - width;
@@ -3284,9 +3344,11 @@ Use %% to put a single % into the output.")
                while (padding-- > 0)
                  {
                    *p++ = ' ';
-                   nchars++;
+                   ++nchars;
                  }
 
+             start = nchars;
+             
              if (p > buf
                  && multibyte
                  && !ASCII_BYTE_P (*((unsigned char *) p - 1))
@@ -3298,6 +3360,7 @@ Use %% to put a single % into the output.")
                                  STRING_MULTIBYTE (args[n]), multibyte);
              p += nbytes;
              nchars += XSTRING (args[n])->size;
+             end = nchars;
 
              if (negative)
                while (padding-- > 0)
@@ -3318,7 +3381,7 @@ Use %% to put a single % into the output.")
                    }
 
                  info[n].start = start;
-                 info[n].end = nchars;
+                 info[n].end = end;
                }
            }
          else if (INTEGERP (args[n]) || FLOATP (args[n]))
@@ -3372,6 +3435,9 @@ Use %% to put a single % into the output.")
        *p++ = *format++, nchars++;
     }
 
+  if (p > buf + total + 1)
+    abort ();
+
   if (maybe_combine_byte)
     nchars = multibyte_chars_in_text (buf, p - buf);
   val = make_specified_string (buf, nchars, p - buf, multibyte);
@@ -3575,7 +3641,6 @@ Transposing beyond buffer boundaries is an error.")
   int start1_byte, start2_byte, len1_byte, len2_byte;
   int gap, len1, len_mid, len2;
   unsigned char *start1_addr, *start2_addr, *temp;
-  struct gcpro gcpro1, gcpro2;
 
   INTERVAL cur_intv, tmp_interval1, tmp_interval_mid, tmp_interval2;
   cur_intv = BUF_INTERVALS (current_buffer);