X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/68fa05fd936aeb5ed4d39a48c570b1d4c29e8f9c..c8b7a6abd90aab76185202def7049a0ea981d335:/src/editfns.c diff --git a/src/editfns.c b/src/editfns.c index 2f46cfeb2b..afcf1cab72 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -6,8 +6,8 @@ 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 3 of the License, or -(at your option) any later version. +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -146,8 +146,6 @@ xtzfree (timezone_t tz) static timezone_t tzlookup (Lisp_Object zone, bool settz) { - static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d"; - char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)]; char const *zone_string; timezone_t new_tz; @@ -160,16 +158,53 @@ tzlookup (Lisp_Object zone, bool settz) } else { + static char const tzbuf_format[] = "<%+.*"pI"d>%s%"pI"d:%02d:%02d"; + char const *trailing_tzbuf_format = tzbuf_format + sizeof "<%+.*"pI"d" - 1; + char tzbuf[sizeof tzbuf_format + 2 * INT_STRLEN_BOUND (EMACS_INT)]; + bool plain_integer = INTEGERP (zone); + if (EQ (zone, Qwall)) zone_string = 0; else if (STRINGP (zone)) - zone_string = SSDATA (zone); - else if (INTEGERP (zone)) + zone_string = SSDATA (ENCODE_SYSTEM (zone)); + else if (plain_integer || (CONSP (zone) && INTEGERP (XCAR (zone)) + && CONSP (XCDR (zone)))) { + Lisp_Object abbr; + if (!plain_integer) + { + abbr = XCAR (XCDR (zone)); + zone = XCAR (zone); + } + EMACS_INT abszone = eabs (XINT (zone)), hour = abszone / (60 * 60); - int min = (abszone / 60) % 60, sec = abszone % 60; - sprintf (tzbuf, tzbuf_format, &"-"[XINT (zone) < 0], hour, min, sec); - zone_string = tzbuf; + int hour_remainder = abszone % (60 * 60); + int min = hour_remainder / 60, sec = hour_remainder % 60; + + if (plain_integer) + { + int prec = 2; + EMACS_INT numzone = hour; + if (hour_remainder != 0) + { + prec += 2, numzone = 100 * numzone + min; + if (sec != 0) + prec += 2, numzone = 100 * numzone + sec; + } + sprintf (tzbuf, tzbuf_format, prec, numzone, + &"-"[XINT (zone) < 0], hour, min, sec); + zone_string = tzbuf; + } + else + { + AUTO_STRING (leading, "<"); + AUTO_STRING_WITH_LEN (trailing, tzbuf, + sprintf (tzbuf, trailing_tzbuf_format, + &"-"[XINT (zone) < 0], + hour, min, sec)); + zone_string = SSDATA (concat3 (leading, ENCODE_SYSTEM (abbr), + trailing)); + } } else xsignal2 (Qerror, build_string ("Invalid time zone specification"), @@ -1456,7 +1491,7 @@ time_overflow (void) error ("Specified time is not representable"); } -static void +static _Noreturn void invalid_time (void) { error ("Invalid time specification"); @@ -1848,7 +1883,9 @@ 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); - int val = len ? decode_time_components (high, low, usec, psec, &t, 0) : 0; + if (!len) + invalid_time (); + int val = decode_time_components (high, low, usec, psec, &t, 0); check_time_validity (val); *plen = len; return t; @@ -1895,7 +1932,7 @@ DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0, doc: /* Return the current time, as a float number of seconds since the epoch. If SPECIFIED-TIME is given, it is the time to convert to float instead of the current time. The argument should have the form -(HIGH LOW) or (HIGH LOW USEC) or (HIGH LOW USEC PSEC). Thus, +\(HIGH LOW) or (HIGH LOW USEC) or (HIGH LOW USEC PSEC). Thus, you can use times from `current-time' and from `file-attributes'. SPECIFIED-TIME can also have the form (HIGH . LOW), but this is considered obsolete. @@ -1968,9 +2005,13 @@ DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 3, 0, TIME is specified as (HIGH LOW USEC PSEC), as returned by `current-time' or `file-attributes'. The obsolete form (HIGH . LOW) is also still accepted. + The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in -`set-time-zone-rule' for a time zone rule. +the TZ environment variable. It can also be a list (as from +`current-time-zone') or an integer (as from `decode-time') applied +without consideration for daylight saving time. + The value is a copy of FORMAT-STRING, but with certain constructs replaced by text that describes the specified date and time in TIME: @@ -2040,7 +2081,6 @@ format_time_string (char const *format, ptrdiff_t formatlen, char *buf = buffer; ptrdiff_t size = sizeof buffer; size_t len; - Lisp_Object bufstring; int ns = t.tv_nsec; USE_SAFE_ALLOCA; @@ -2072,9 +2112,11 @@ format_time_string (char const *format, ptrdiff_t formatlen, } xtzfree (tz); - bufstring = make_unibyte_string (buf, len); + AUTO_STRING_WITH_LEN (bufstring, buf, len); + Lisp_Object result = code_convert_string_norecord (bufstring, + Vlocale_coding_system, 0); SAFE_FREE (); - return code_convert_string_norecord (bufstring, Vlocale_coding_system, 0); + return result; } DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0, @@ -2082,9 +2124,12 @@ DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0, The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED), as from `current-time' and `file-attributes', or nil to use the current time. The obsolete form (HIGH . LOW) is also still accepted. + The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in -`set-time-zone-rule' for a time zone rule. +the TZ environment variable. It can also be a list (as from +`current-time-zone') or an integer (as from `decode-time') applied +without consideration for daylight saving time. 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 @@ -2147,11 +2192,12 @@ check_tm_member (Lisp_Object obj, int offset) 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. + The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in -`set-time-zone-rule' for a time zone rule. It can also be a list (as -from `current-time-zone') or an integer (as from `decode-time') -applied without consideration for daylight saving time. +the TZ environment variable. It can also be a list (as from +`current-time-zone') or an integer (as from `decode-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. @@ -2181,8 +2227,6 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) tm.tm_year = check_tm_member (args[5], TM_YEAR_BASE); tm.tm_isdst = -1; - if (CONSP (zone)) - zone = XCAR (zone); timezone_t tz = tzlookup (zone, false); value = emacs_mktime_z (tz, &tm); xtzfree (tz); @@ -2211,7 +2255,9 @@ but this is considered obsolete. The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in -`set-time-zone-rule' for a time zone rule. */) +the TZ environment variable. It can also be a list (as from +`current-time-zone') or an integer (as from `decode-time') applied +without consideration for daylight saving time. */) (Lisp_Object specified_time, Lisp_Object zone) { time_t value = lisp_seconds_argument (specified_time); @@ -2284,11 +2330,15 @@ OFFSET is an integer number of seconds ahead of UTC (east of Greenwich). NAME is a string giving the name of the time zone. If SPECIFIED-TIME is given, the time zone offset is determined from it instead of using the current time. The argument should have the form -(HIGH LOW . IGNORED). Thus, you can use times obtained from +\(HIGH LOW . IGNORED). Thus, you can use times obtained from `current-time' and from `file-attributes'. SPECIFIED-TIME can also have the form (HIGH . LOW), but this is considered obsolete. -Optional second arg ZONE is omitted or nil for the local time zone, or -a string as in `set-time-zone-rule'. + +The optional ZONE is omitted or nil for Emacs local time, t for +Universal Time, `wall' for system wall clock time, or a string as in +the TZ environment variable. It can also be a list (as from +`current-time-zone') or an integer (as from `decode-time') applied +without consideration for daylight saving time. Some operating systems cannot provide all this information to Emacs; in this case, `current-time-zone' returns a list containing nil for @@ -2312,15 +2362,18 @@ the data it can't find. */) zone_offset = make_number (offset); if (SCHARS (zone_name) == 0) { - /* No local time zone name is available; use "+-NNNN" instead. */ - long int m = offset / 60; - long int am = offset < 0 ? - m : m; - long int hour = am / 60; - int min = am % 60; - char buf[sizeof "+00" + INT_STRLEN_BOUND (long int)]; - zone_name = make_formatted_string (buf, "%c%02ld%02d", + /* No local time zone name is available; use numeric zone instead. */ + long int hour = offset / 3600; + int min_sec = offset % 3600; + int amin_sec = min_sec < 0 ? - min_sec : min_sec; + int min = amin_sec / 60; + int sec = amin_sec % 60; + int min_prec = min_sec ? 2 : 0; + int sec_prec = sec ? 2 : 0; + char buf[sizeof "+0000" + INT_STRLEN_BOUND (long int)]; + zone_name = make_formatted_string (buf, "%c%.2ld%.*d%.*d", (offset < 0 ? '-' : '+'), - hour, min); + hour, min_prec, min, sec_prec, sec); } } @@ -2329,8 +2382,11 @@ 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 Emacs local time zone using TZ, a string specifying a time zone rule. -If TZ is nil or `wall', use system wall clock time. If TZ is t, use -Universal Time. If TZ is an integer, treat it as in `encode-time'. +If TZ is nil or `wall', use system wall clock time; this differs from +the usual Emacs convention where nil means current local time. If TZ +is t, use Universal Time. If TZ is a list (as from +`current-time-zone') or an integer (as from `decode-time'), use the +specified time zone without consideration for daylight saving time. Instead of calling this function, you typically want something else. To temporarily use a different time zone rule for just one invocation @@ -2479,7 +2535,7 @@ insert1 (Lisp_Object arg) DEFUN ("insert", Finsert, Sinsert, 0, MANY, 0, doc: /* Insert the arguments, either strings or characters, at point. -Point and before-insertion markers move forward to end up +Point and after-insertion markers move forward to end up after the inserted text. Any other markers at the point of insertion remain before the text. @@ -2503,7 +2559,7 @@ usage: (insert &rest ARGS) */) DEFUN ("insert-and-inherit", Finsert_and_inherit, Sinsert_and_inherit, 0, MANY, 0, doc: /* Insert the arguments at point, inheriting properties from adjoining text. -Point and before-insertion markers move forward to end up +Point and after-insertion markers move forward to end up after the inserted text. Any other markers at the point of insertion remain before the text. @@ -2877,10 +2933,9 @@ DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_ 6, 6, 0, doc: /* Compare two substrings of two buffers; return result as number. Return -N if first string is less after N-1 chars, +N if first string is -greater after N-1 chars, or 0 if strings match. Each substring is -represented as three arguments: BUFFER, START and END. That makes six -args in all, three for each substring. - +greater after N-1 chars, or 0 if strings match. +The first substring is in BUFFER1 from START1 to END1 and the second +is in BUFFER2 from START2 to END2. The value of `case-fold-search' in the current buffer determines whether case is significant or ignored. */) (Lisp_Object buffer1, Lisp_Object start1, Lisp_Object end1, Lisp_Object buffer2, Lisp_Object start2, Lisp_Object end2) @@ -3627,7 +3682,7 @@ save_restriction_restore (Lisp_Object 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. @@ -3661,10 +3716,11 @@ In batch mode, the message is printed to the standard error stream, followed by a newline. 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. +to be formatted under control of the string. See `format-message' for +details. -Note: Use (message "%s" VALUE) to print the value of expressions and -variables to avoid accidentally interpreting `%' as format specifiers. +Note: (message "%s" VALUE) displays the string VALUE without +interpreting format characters like `%', `\\=`', and `\\=''. If the first argument is nil or the empty string, the function clears any existing message; this lets the minibuffer contents show. See @@ -3692,7 +3748,8 @@ DEFUN ("message-box", Fmessage_box, Smessage_box, 1, MANY, 0, doc: /* Display a message, in a dialog box if possible. If a dialog box is not available, use the echo area. 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. +to be formatted under control of the string. See `format-message' for +details. If the first argument is nil or the empty string, clear any existing message; let the minibuffer contents show. @@ -3723,7 +3780,8 @@ If this command was invoked with the mouse, use a dialog box if `use-dialog-box' is non-nil. Otherwise, use the echo area. 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. +to be formatted under control of the string. See `format-message' for +details. If the first argument is nil or the empty string, clear any existing message; let the minibuffer contents show. @@ -3919,6 +3977,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) multibyte = true; int quoting_style = message ? text_quoting_style () : -1; + if (quoting_style == LEAVE_QUOTING_STYLE) + quoting_style = -1; /* If we start out planning a unibyte result, then discover it has to be multibyte, we jump back to retry. */