diff options
Diffstat (limited to 'src/editfns.c')
| -rw-r--r-- | src/editfns.c | 415 |
1 files changed, 202 insertions, 213 deletions
diff --git a/src/editfns.c b/src/editfns.c index 8122ffdd0d4..d0cca6f3d7b 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* Lisp functions pertaining to editing. | 1 | /* Lisp functions pertaining to editing. |
| 2 | 2 | ||
| 3 | Copyright (C) 1985-1987, 1989, 1993-2012 Free Software Foundation, Inc. | 3 | Copyright (C) 1985-1987, 1989, 1993-2013 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 6 | 6 | ||
| @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 24 | 24 | ||
| 25 | #ifdef HAVE_PWD_H | 25 | #ifdef HAVE_PWD_H |
| 26 | #include <pwd.h> | 26 | #include <pwd.h> |
| 27 | #include <grp.h> | ||
| 27 | #endif | 28 | #endif |
| 28 | 29 | ||
| 29 | #include <unistd.h> | 30 | #include <unistd.h> |
| @@ -78,6 +79,15 @@ Lisp_Object Qfield; | |||
| 78 | 79 | ||
| 79 | static Lisp_Object Qboundary; | 80 | static Lisp_Object Qboundary; |
| 80 | 81 | ||
| 82 | /* The startup value of the TZ environment variable so it can be | ||
| 83 | restored if the user calls set-time-zone-rule with a nil | ||
| 84 | argument. If null, the TZ environment variable was unset. */ | ||
| 85 | static char const *initial_tz; | ||
| 86 | |||
| 87 | /* True if the static variable tzvalbuf (defined in | ||
| 88 | set_time_zone_rule) is part of 'environ'. */ | ||
| 89 | static bool tzvalbuf_in_environ; | ||
| 90 | |||
| 81 | 91 | ||
| 82 | void | 92 | void |
| 83 | init_editfns (void) | 93 | init_editfns (void) |
| @@ -96,6 +106,9 @@ init_editfns (void) | |||
| 96 | return; | 106 | return; |
| 97 | #endif /* not CANNOT_DUMP */ | 107 | #endif /* not CANNOT_DUMP */ |
| 98 | 108 | ||
| 109 | initial_tz = getenv ("TZ"); | ||
| 110 | tzvalbuf_in_environ = 0; | ||
| 111 | |||
| 99 | pw = getpwuid (getuid ()); | 112 | pw = getpwuid (getuid ()); |
| 100 | #ifdef MSDOS | 113 | #ifdef MSDOS |
| 101 | /* We let the real user name default to "root" because that's quite | 114 | /* We let the real user name default to "root" because that's quite |
| @@ -360,7 +373,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o | |||
| 360 | if (NILP (object)) | 373 | if (NILP (object)) |
| 361 | XSETBUFFER (object, current_buffer); | 374 | XSETBUFFER (object, current_buffer); |
| 362 | else if (WINDOWP (object)) | 375 | else if (WINDOWP (object)) |
| 363 | object = XWINDOW (object)->buffer; | 376 | object = XWINDOW (object)->contents; |
| 364 | 377 | ||
| 365 | if (!BUFFERP (object)) | 378 | if (!BUFFERP (object)) |
| 366 | /* pos-property only makes sense in buffers right now, since strings | 379 | /* pos-property only makes sense in buffers right now, since strings |
| @@ -373,6 +386,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o | |||
| 373 | ptrdiff_t noverlays; | 386 | ptrdiff_t noverlays; |
| 374 | Lisp_Object *overlay_vec, tem; | 387 | Lisp_Object *overlay_vec, tem; |
| 375 | struct buffer *obuf = current_buffer; | 388 | struct buffer *obuf = current_buffer; |
| 389 | USE_SAFE_ALLOCA; | ||
| 376 | 390 | ||
| 377 | set_buffer_temp (XBUFFER (object)); | 391 | set_buffer_temp (XBUFFER (object)); |
| 378 | 392 | ||
| @@ -385,7 +399,7 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o | |||
| 385 | make enough space for all, and try again. */ | 399 | make enough space for all, and try again. */ |
| 386 | if (noverlays > 40) | 400 | if (noverlays > 40) |
| 387 | { | 401 | { |
| 388 | overlay_vec = alloca (noverlays * sizeof *overlay_vec); | 402 | SAFE_ALLOCA_LISP (overlay_vec, noverlays); |
| 389 | noverlays = overlays_around (posn, overlay_vec, noverlays); | 403 | noverlays = overlays_around (posn, overlay_vec, noverlays); |
| 390 | } | 404 | } |
| 391 | noverlays = sort_overlays (overlay_vec, noverlays, NULL); | 405 | noverlays = sort_overlays (overlay_vec, noverlays, NULL); |
| @@ -408,10 +422,12 @@ get_pos_property (Lisp_Object position, register Lisp_Object prop, Lisp_Object o | |||
| 408 | ; /* The overlay will not cover a char inserted at point. */ | 422 | ; /* The overlay will not cover a char inserted at point. */ |
| 409 | else | 423 | else |
| 410 | { | 424 | { |
| 425 | SAFE_FREE (); | ||
| 411 | return tem; | 426 | return tem; |
| 412 | } | 427 | } |
| 413 | } | 428 | } |
| 414 | } | 429 | } |
| 430 | SAFE_FREE (); | ||
| 415 | 431 | ||
| 416 | { /* Now check the text properties. */ | 432 | { /* Now check the text properties. */ |
| 417 | int stickiness = text_property_stickiness (prop, position, object); | 433 | int stickiness = text_property_stickiness (prop, position, object); |
| @@ -653,7 +669,8 @@ If the optional argument INHIBIT-CAPTURE-PROPERTY is non-nil, and OLD-POS has | |||
| 653 | a non-nil property of that name, then any field boundaries are ignored. | 669 | a non-nil property of that name, then any field boundaries are ignored. |
| 654 | 670 | ||
| 655 | Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) | 671 | Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) |
| 656 | (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge, Lisp_Object only_in_line, Lisp_Object inhibit_capture_property) | 672 | (Lisp_Object new_pos, Lisp_Object old_pos, Lisp_Object escape_from_edge, |
| 673 | Lisp_Object only_in_line, Lisp_Object inhibit_capture_property) | ||
| 657 | { | 674 | { |
| 658 | /* If non-zero, then the original point, before re-positioning. */ | 675 | /* If non-zero, then the original point, before re-positioning. */ |
| 659 | ptrdiff_t orig_point = 0; | 676 | ptrdiff_t orig_point = 0; |
| @@ -719,9 +736,9 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) | |||
| 719 | /* This is the ONLY_IN_LINE case, check that NEW_POS and | 736 | /* This is the ONLY_IN_LINE case, check that NEW_POS and |
| 720 | FIELD_BOUND are on the same line by seeing whether | 737 | FIELD_BOUND are on the same line by seeing whether |
| 721 | there's an intervening newline or not. */ | 738 | there's an intervening newline or not. */ |
| 722 | || (scan_buffer ('\n', | 739 | || (find_newline (XFASTINT (new_pos), -1, |
| 723 | XFASTINT (new_pos), XFASTINT (field_bound), | 740 | XFASTINT (field_bound), -1, |
| 724 | fwd ? -1 : 1, &shortage, 1), | 741 | fwd ? -1 : 1, &shortage, NULL, 1), |
| 725 | shortage != 0))) | 742 | shortage != 0))) |
| 726 | /* Constrain NEW_POS to FIELD_BOUND. */ | 743 | /* Constrain NEW_POS to FIELD_BOUND. */ |
| 727 | new_pos = field_bound; | 744 | new_pos = field_bound; |
| @@ -806,45 +823,47 @@ This function does not move point. */) | |||
| 806 | CHECK_NUMBER (n); | 823 | CHECK_NUMBER (n); |
| 807 | 824 | ||
| 808 | clipped_n = clip_to_bounds (PTRDIFF_MIN + 1, XINT (n), PTRDIFF_MAX); | 825 | clipped_n = clip_to_bounds (PTRDIFF_MIN + 1, XINT (n), PTRDIFF_MAX); |
| 809 | end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0)); | 826 | end_pos = find_before_next_newline (orig, 0, clipped_n - (clipped_n <= 0), |
| 827 | NULL); | ||
| 810 | 828 | ||
| 811 | /* Return END_POS constrained to the current input field. */ | 829 | /* Return END_POS constrained to the current input field. */ |
| 812 | return Fconstrain_to_field (make_number (end_pos), make_number (orig), | 830 | return Fconstrain_to_field (make_number (end_pos), make_number (orig), |
| 813 | Qnil, Qt, Qnil); | 831 | Qnil, Qt, Qnil); |
| 814 | } | 832 | } |
| 815 | 833 | ||
| 816 | 834 | /* Save current buffer state for `save-excursion' special form. | |
| 835 | We (ab)use Lisp_Misc_Save_Value to allow explicit free and so | ||
| 836 | offload some work from GC. */ | ||
| 837 | |||
| 817 | Lisp_Object | 838 | Lisp_Object |
| 818 | save_excursion_save (void) | 839 | save_excursion_save (void) |
| 819 | { | 840 | { |
| 820 | bool visible = (XBUFFER (XWINDOW (selected_window)->buffer) | 841 | return make_save_value |
| 821 | == current_buffer); | 842 | (SAVE_TYPE_OBJ_OBJ_OBJ_OBJ, |
| 822 | /* Do not copy the mark if it points to nowhere. */ | 843 | Fpoint_marker (), |
| 823 | Lisp_Object mark = (XMARKER (BVAR (current_buffer, mark))->buffer | 844 | /* Do not copy the mark if it points to nowhere. */ |
| 824 | ? Fcopy_marker (BVAR (current_buffer, mark), Qnil) | 845 | (XMARKER (BVAR (current_buffer, mark))->buffer |
| 825 | : Qnil); | 846 | ? Fcopy_marker (BVAR (current_buffer, mark), Qnil) |
| 826 | 847 | : Qnil), | |
| 827 | return Fcons (Fpoint_marker (), | 848 | /* Selected window if current buffer is shown in it, nil otherwise. */ |
| 828 | Fcons (mark, | 849 | (EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ()) |
| 829 | Fcons (visible ? Qt : Qnil, | 850 | ? selected_window : Qnil), |
| 830 | Fcons (BVAR (current_buffer, mark_active), | 851 | BVAR (current_buffer, mark_active)); |
| 831 | selected_window)))); | ||
| 832 | } | 852 | } |
| 833 | 853 | ||
| 854 | /* Restore saved buffer before leaving `save-excursion' special form. */ | ||
| 855 | |||
| 834 | Lisp_Object | 856 | Lisp_Object |
| 835 | save_excursion_restore (Lisp_Object info) | 857 | save_excursion_restore (Lisp_Object info) |
| 836 | { | 858 | { |
| 837 | Lisp_Object tem, tem1, omark, nmark; | 859 | Lisp_Object tem, tem1, omark, nmark; |
| 838 | struct gcpro gcpro1, gcpro2, gcpro3; | 860 | struct gcpro gcpro1, gcpro2, gcpro3; |
| 839 | bool visible_p; | ||
| 840 | 861 | ||
| 841 | tem = Fmarker_buffer (XCAR (info)); | 862 | tem = Fmarker_buffer (XSAVE_OBJECT (info, 0)); |
| 842 | /* If buffer being returned to is now deleted, avoid error */ | 863 | /* If we're unwinding to top level, saved buffer may be deleted. This |
| 843 | /* Otherwise could get error here while unwinding to top level | 864 | means that all of its markers are unchained and so tem is nil. */ |
| 844 | and crash */ | ||
| 845 | /* In that case, Fmarker_buffer returns nil now. */ | ||
| 846 | if (NILP (tem)) | 865 | if (NILP (tem)) |
| 847 | return Qnil; | 866 | goto out; |
| 848 | 867 | ||
| 849 | omark = nmark = Qnil; | 868 | omark = nmark = Qnil; |
| 850 | GCPRO3 (info, omark, nmark); | 869 | GCPRO3 (info, omark, nmark); |
| @@ -852,13 +871,12 @@ save_excursion_restore (Lisp_Object info) | |||
| 852 | Fset_buffer (tem); | 871 | Fset_buffer (tem); |
| 853 | 872 | ||
| 854 | /* Point marker. */ | 873 | /* Point marker. */ |
| 855 | tem = XCAR (info); | 874 | tem = XSAVE_OBJECT (info, 0); |
| 856 | Fgoto_char (tem); | 875 | Fgoto_char (tem); |
| 857 | unchain_marker (XMARKER (tem)); | 876 | unchain_marker (XMARKER (tem)); |
| 858 | 877 | ||
| 859 | /* Mark marker. */ | 878 | /* Mark marker. */ |
| 860 | info = XCDR (info); | 879 | tem = XSAVE_OBJECT (info, 1); |
| 861 | tem = XCAR (info); | ||
| 862 | omark = Fmarker_position (BVAR (current_buffer, mark)); | 880 | omark = Fmarker_position (BVAR (current_buffer, mark)); |
| 863 | if (NILP (tem)) | 881 | if (NILP (tem)) |
| 864 | unchain_marker (XMARKER (BVAR (current_buffer, mark))); | 882 | unchain_marker (XMARKER (BVAR (current_buffer, mark))); |
| @@ -869,23 +887,8 @@ save_excursion_restore (Lisp_Object info) | |||
| 869 | unchain_marker (XMARKER (tem)); | 887 | unchain_marker (XMARKER (tem)); |
| 870 | } | 888 | } |
| 871 | 889 | ||
| 872 | /* visible */ | 890 | /* Mark active. */ |
| 873 | info = XCDR (info); | 891 | tem = XSAVE_OBJECT (info, 3); |
| 874 | visible_p = !NILP (XCAR (info)); | ||
| 875 | |||
| 876 | #if 0 /* We used to make the current buffer visible in the selected window | ||
| 877 | if that was true previously. That avoids some anomalies. | ||
| 878 | But it creates others, and it wasn't documented, and it is simpler | ||
| 879 | and cleaner never to alter the window/buffer connections. */ | ||
| 880 | tem1 = Fcar (tem); | ||
| 881 | if (!NILP (tem1) | ||
| 882 | && current_buffer != XBUFFER (XWINDOW (selected_window)->buffer)) | ||
| 883 | Fswitch_to_buffer (Fcurrent_buffer (), Qnil); | ||
| 884 | #endif /* 0 */ | ||
| 885 | |||
| 886 | /* Mark active */ | ||
| 887 | info = XCDR (info); | ||
| 888 | tem = XCAR (info); | ||
| 889 | tem1 = BVAR (current_buffer, mark_active); | 892 | tem1 = BVAR (current_buffer, mark_active); |
| 890 | bset_mark_active (current_buffer, tem); | 893 | bset_mark_active (current_buffer, tem); |
| 891 | 894 | ||
| @@ -909,10 +912,10 @@ save_excursion_restore (Lisp_Object info) | |||
| 909 | /* If buffer was visible in a window, and a different window was | 912 | /* If buffer was visible in a window, and a different window was |
| 910 | selected, and the old selected window is still showing this | 913 | selected, and the old selected window is still showing this |
| 911 | buffer, restore point in that window. */ | 914 | buffer, restore point in that window. */ |
| 912 | tem = XCDR (info); | 915 | tem = XSAVE_OBJECT (info, 2); |
| 913 | if (visible_p | 916 | if (WINDOWP (tem) |
| 914 | && !EQ (tem, selected_window) | 917 | && !EQ (tem, selected_window) |
| 915 | && (tem1 = XWINDOW (tem)->buffer, | 918 | && (tem1 = XWINDOW (tem)->contents, |
| 916 | (/* Window is live... */ | 919 | (/* Window is live... */ |
| 917 | BUFFERP (tem1) | 920 | BUFFERP (tem1) |
| 918 | /* ...and it shows the current buffer. */ | 921 | /* ...and it shows the current buffer. */ |
| @@ -920,6 +923,10 @@ save_excursion_restore (Lisp_Object info) | |||
| 920 | Fset_window_point (tem, make_number (PT)); | 923 | Fset_window_point (tem, make_number (PT)); |
| 921 | 924 | ||
| 922 | UNGCPRO; | 925 | UNGCPRO; |
| 926 | |||
| 927 | out: | ||
| 928 | |||
| 929 | free_misc (info); | ||
| 923 | return Qnil; | 930 | return Qnil; |
| 924 | } | 931 | } |
| 925 | 932 | ||
| @@ -962,7 +969,7 @@ usage: (save-current-buffer &rest BODY) */) | |||
| 962 | return unbind_to (count, Fprogn (args)); | 969 | return unbind_to (count, Fprogn (args)); |
| 963 | } | 970 | } |
| 964 | 971 | ||
| 965 | DEFUN ("buffer-size", Fbufsize, Sbufsize, 0, 1, 0, | 972 | DEFUN ("buffer-size", Fbuffer_size, Sbuffer_size, 0, 1, 0, |
| 966 | doc: /* Return the number of characters in the current buffer. | 973 | doc: /* Return the number of characters in the current buffer. |
| 967 | If BUFFER, return the number of characters in that buffer instead. */) | 974 | If BUFFER, return the number of characters in that buffer instead. */) |
| 968 | (Lisp_Object buffer) | 975 | (Lisp_Object buffer) |
| @@ -1267,6 +1274,24 @@ Value is an integer or a float, depending on the value. */) | |||
| 1267 | return make_fixnum_or_float (uid); | 1274 | return make_fixnum_or_float (uid); |
| 1268 | } | 1275 | } |
| 1269 | 1276 | ||
| 1277 | DEFUN ("group-gid", Fgroup_gid, Sgroup_gid, 0, 0, 0, | ||
| 1278 | doc: /* Return the effective gid of Emacs. | ||
| 1279 | Value is an integer or a float, depending on the value. */) | ||
| 1280 | (void) | ||
| 1281 | { | ||
| 1282 | gid_t egid = getegid (); | ||
| 1283 | return make_fixnum_or_float (egid); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | DEFUN ("group-real-gid", Fgroup_real_gid, Sgroup_real_gid, 0, 0, 0, | ||
| 1287 | doc: /* Return the real gid of Emacs. | ||
| 1288 | Value is an integer or a float, depending on the value. */) | ||
| 1289 | (void) | ||
| 1290 | { | ||
| 1291 | gid_t gid = getgid (); | ||
| 1292 | return make_fixnum_or_float (gid); | ||
| 1293 | } | ||
| 1294 | |||
| 1270 | DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 1, 0, | 1295 | DEFUN ("user-full-name", Fuser_full_name, Suser_full_name, 0, 1, 0, |
| 1271 | doc: /* Return the full name of the user logged in, as a string. | 1296 | doc: /* Return the full name of the user logged in, as a string. |
| 1272 | If the full name corresponding to Emacs's userid is not known, | 1297 | If the full name corresponding to Emacs's userid is not known, |
| @@ -1373,8 +1398,8 @@ hi_time (time_t t) | |||
| 1373 | no runtime check is needed, and taking care not to convert | 1398 | no runtime check is needed, and taking care not to convert |
| 1374 | negative numbers to unsigned before comparing them. */ | 1399 | negative numbers to unsigned before comparing them. */ |
| 1375 | if (! ((! TYPE_SIGNED (time_t) | 1400 | if (! ((! TYPE_SIGNED (time_t) |
| 1376 | || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> 16 | 1401 | || TIME_T_MIN >> 16 >= MOST_NEGATIVE_FIXNUM |
| 1377 | || MOST_NEGATIVE_FIXNUM <= hi) | 1402 | || hi >= MOST_NEGATIVE_FIXNUM) |
| 1378 | && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM | 1403 | && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM |
| 1379 | || hi <= MOST_POSITIVE_FIXNUM))) | 1404 | || hi <= MOST_POSITIVE_FIXNUM))) |
| 1380 | time_overflow (); | 1405 | time_overflow (); |
| @@ -1461,9 +1486,7 @@ Lisp_Object | |||
| 1461 | make_lisp_time (EMACS_TIME t) | 1486 | make_lisp_time (EMACS_TIME t) |
| 1462 | { | 1487 | { |
| 1463 | int ns = EMACS_NSECS (t); | 1488 | int ns = EMACS_NSECS (t); |
| 1464 | return make_time_tail (EMACS_SECS (t), | 1489 | return make_time_tail (EMACS_SECS (t), list2i (ns / 1000, ns % 1000 * 1000)); |
| 1465 | list2 (make_number (ns / 1000), | ||
| 1466 | make_number (ns % 1000 * 1000))); | ||
| 1467 | } | 1490 | } |
| 1468 | 1491 | ||
| 1469 | /* Decode a Lisp list SPECIFIED_TIME that represents a time. | 1492 | /* Decode a Lisp list SPECIFIED_TIME that represents a time. |
| @@ -1538,7 +1561,7 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, | |||
| 1538 | 1561 | ||
| 1539 | if (result) | 1562 | if (result) |
| 1540 | { | 1563 | { |
| 1541 | if ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> 16 <= hi : 0 <= hi) | 1564 | if (hi >= (TYPE_SIGNED (time_t) ? TIME_T_MIN >> 16 : 0) |
| 1542 | && hi <= TIME_T_MAX >> 16) | 1565 | && hi <= TIME_T_MAX >> 16) |
| 1543 | { | 1566 | { |
| 1544 | /* Return the greatest representable time that is not greater | 1567 | /* Return the greatest representable time that is not greater |
| @@ -1907,9 +1930,11 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) | |||
| 1907 | } | 1930 | } |
| 1908 | else | 1931 | else |
| 1909 | { | 1932 | { |
| 1910 | char tzbuf[100]; | 1933 | static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d"; |
| 1934 | char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)]; | ||
| 1935 | char *old_tzstring; | ||
| 1911 | const char *tzstring; | 1936 | const char *tzstring; |
| 1912 | char **oldenv = environ, **newenv; | 1937 | USE_SAFE_ALLOCA; |
| 1913 | 1938 | ||
| 1914 | if (EQ (zone, Qt)) | 1939 | if (EQ (zone, Qt)) |
| 1915 | tzstring = "UTC0"; | 1940 | tzstring = "UTC0"; |
| @@ -1921,13 +1946,20 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) | |||
| 1921 | EMACS_INT zone_hr = abszone / (60*60); | 1946 | EMACS_INT zone_hr = abszone / (60*60); |
| 1922 | int zone_min = (abszone/60) % 60; | 1947 | int zone_min = (abszone/60) % 60; |
| 1923 | int zone_sec = abszone % 60; | 1948 | int zone_sec = abszone % 60; |
| 1924 | sprintf (tzbuf, "XXX%s%"pI"d:%02d:%02d", "-" + (XINT (zone) < 0), | 1949 | sprintf (tzbuf, tzbuf_format, "-" + (XINT (zone) < 0), |
| 1925 | zone_hr, zone_min, zone_sec); | 1950 | zone_hr, zone_min, zone_sec); |
| 1926 | tzstring = tzbuf; | 1951 | tzstring = tzbuf; |
| 1927 | } | 1952 | } |
| 1928 | else | 1953 | else |
| 1929 | error ("Invalid time zone specification"); | 1954 | error ("Invalid time zone specification"); |
| 1930 | 1955 | ||
| 1956 | old_tzstring = getenv ("TZ"); | ||
| 1957 | if (old_tzstring) | ||
| 1958 | { | ||
| 1959 | char *buf = SAFE_ALLOCA (strlen (old_tzstring) + 1); | ||
| 1960 | old_tzstring = strcpy (buf, old_tzstring); | ||
| 1961 | } | ||
| 1962 | |||
| 1931 | block_input (); | 1963 | block_input (); |
| 1932 | 1964 | ||
| 1933 | /* Set TZ before calling mktime; merely adjusting mktime's returned | 1965 | /* Set TZ before calling mktime; merely adjusting mktime's returned |
| @@ -1936,15 +1968,12 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */) | |||
| 1936 | 1968 | ||
| 1937 | value = mktime (&tm); | 1969 | value = mktime (&tm); |
| 1938 | 1970 | ||
| 1939 | /* Restore TZ to previous value. */ | 1971 | set_time_zone_rule (old_tzstring); |
| 1940 | newenv = environ; | ||
| 1941 | environ = oldenv; | ||
| 1942 | #ifdef LOCALTIME_CACHE | 1972 | #ifdef LOCALTIME_CACHE |
| 1943 | tzset (); | 1973 | tzset (); |
| 1944 | #endif | 1974 | #endif |
| 1945 | unblock_input (); | 1975 | unblock_input (); |
| 1946 | 1976 | SAFE_FREE (); | |
| 1947 | xfree (newenv); | ||
| 1948 | } | 1977 | } |
| 1949 | 1978 | ||
| 1950 | if (value == (time_t) -1) | 1979 | if (value == (time_t) -1) |
| @@ -2074,16 +2103,6 @@ the data it can't find. */) | |||
| 2074 | return list2 (zone_offset, zone_name); | 2103 | return list2 (zone_offset, zone_name); |
| 2075 | } | 2104 | } |
| 2076 | 2105 | ||
| 2077 | /* This holds the value of `environ' produced by the previous | ||
| 2078 | call to Fset_time_zone_rule, or 0 if Fset_time_zone_rule | ||
| 2079 | has never been called. */ | ||
| 2080 | static char **environbuf; | ||
| 2081 | |||
| 2082 | /* This holds the startup value of the TZ environment variable so it | ||
| 2083 | can be restored if the user calls set-time-zone-rule with a nil | ||
| 2084 | argument. */ | ||
| 2085 | static char *initial_tz; | ||
| 2086 | |||
| 2087 | DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0, | 2106 | DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0, |
| 2088 | doc: /* Set the local time zone using TZ, a string specifying a time zone rule. | 2107 | doc: /* Set the local time zone using TZ, a string specifying a time zone rule. |
| 2089 | If TZ is nil, use implementation-defined default time zone information. | 2108 | If TZ is nil, use implementation-defined default time zone information. |
| @@ -2096,18 +2115,10 @@ only the former. */) | |||
| 2096 | (Lisp_Object tz) | 2115 | (Lisp_Object tz) |
| 2097 | { | 2116 | { |
| 2098 | const char *tzstring; | 2117 | const char *tzstring; |
| 2099 | char **old_environbuf; | ||
| 2100 | 2118 | ||
| 2101 | if (! (NILP (tz) || EQ (tz, Qt))) | 2119 | if (! (NILP (tz) || EQ (tz, Qt))) |
| 2102 | CHECK_STRING (tz); | 2120 | CHECK_STRING (tz); |
| 2103 | 2121 | ||
| 2104 | block_input (); | ||
| 2105 | |||
| 2106 | /* When called for the first time, save the original TZ. */ | ||
| 2107 | old_environbuf = environbuf; | ||
| 2108 | if (!old_environbuf) | ||
| 2109 | initial_tz = (char *) getenv ("TZ"); | ||
| 2110 | |||
| 2111 | if (NILP (tz)) | 2122 | if (NILP (tz)) |
| 2112 | tzstring = initial_tz; | 2123 | tzstring = initial_tz; |
| 2113 | else if (EQ (tz, Qt)) | 2124 | else if (EQ (tz, Qt)) |
| @@ -2115,106 +2126,98 @@ only the former. */) | |||
| 2115 | else | 2126 | else |
| 2116 | tzstring = SSDATA (tz); | 2127 | tzstring = SSDATA (tz); |
| 2117 | 2128 | ||
| 2129 | block_input (); | ||
| 2118 | set_time_zone_rule (tzstring); | 2130 | set_time_zone_rule (tzstring); |
| 2119 | environbuf = environ; | ||
| 2120 | |||
| 2121 | unblock_input (); | 2131 | unblock_input (); |
| 2122 | 2132 | ||
| 2123 | xfree (old_environbuf); | ||
| 2124 | return Qnil; | 2133 | return Qnil; |
| 2125 | } | 2134 | } |
| 2126 | 2135 | ||
| 2127 | #ifdef LOCALTIME_CACHE | ||
| 2128 | |||
| 2129 | /* These two values are known to load tz files in buggy implementations, | ||
| 2130 | i.e. Solaris 1 executables running under either Solaris 1 or Solaris 2. | ||
| 2131 | Their values shouldn't matter in non-buggy implementations. | ||
| 2132 | We don't use string literals for these strings, | ||
| 2133 | since if a string in the environment is in readonly | ||
| 2134 | storage, it runs afoul of bugs in SVR4 and Solaris 2.3. | ||
| 2135 | See Sun bugs 1113095 and 1114114, ``Timezone routines | ||
| 2136 | improperly modify environment''. */ | ||
| 2137 | |||
| 2138 | static char set_time_zone_rule_tz1[] = "TZ=GMT+0"; | ||
| 2139 | static char set_time_zone_rule_tz2[] = "TZ=GMT+1"; | ||
| 2140 | |||
| 2141 | #endif | ||
| 2142 | |||
| 2143 | /* Set the local time zone rule to TZSTRING. | 2136 | /* Set the local time zone rule to TZSTRING. |
| 2144 | This allocates memory into `environ', which it is the caller's | 2137 | |
| 2145 | responsibility to free. */ | 2138 | This function is not thread-safe, partly because putenv, unsetenv |
| 2139 | and tzset are not, and partly because of the static storage it | ||
| 2140 | updates. Other threads that invoke localtime etc. may be adversely | ||
| 2141 | affected while this function is executing. */ | ||
| 2146 | 2142 | ||
| 2147 | void | 2143 | void |
| 2148 | set_time_zone_rule (const char *tzstring) | 2144 | set_time_zone_rule (const char *tzstring) |
| 2149 | { | 2145 | { |
| 2150 | ptrdiff_t envptrs; | 2146 | /* A buffer holding a string of the form "TZ=value", intended |
| 2151 | char **from, **to, **newenv; | 2147 | to be part of the environment. */ |
| 2148 | static char *tzvalbuf; | ||
| 2149 | static ptrdiff_t tzvalbufsize; | ||
| 2152 | 2150 | ||
| 2153 | /* Make the ENVIRON vector longer with room for TZSTRING. */ | 2151 | int tzeqlen = sizeof "TZ=" - 1; |
| 2154 | for (from = environ; *from; from++) | 2152 | |
| 2155 | continue; | 2153 | #ifdef LOCALTIME_CACHE |
| 2156 | envptrs = from - environ + 2; | 2154 | /* These two values are known to load tz files in buggy implementations, |
| 2157 | newenv = to = xmalloc (envptrs * sizeof *newenv | 2155 | i.e., Solaris 1 executables running under either Solaris 1 or Solaris 2. |
| 2158 | + (tzstring ? strlen (tzstring) + 4 : 0)); | 2156 | Their values shouldn't matter in non-buggy implementations. |
| 2157 | We don't use string literals for these strings, | ||
| 2158 | since if a string in the environment is in readonly | ||
| 2159 | storage, it runs afoul of bugs in SVR4 and Solaris 2.3. | ||
| 2160 | See Sun bugs 1113095 and 1114114, ``Timezone routines | ||
| 2161 | improperly modify environment''. */ | ||
| 2162 | |||
| 2163 | static char set_time_zone_rule_tz[][sizeof "TZ=GMT+0"] | ||
| 2164 | = { "TZ=GMT+0", "TZ=GMT+1" }; | ||
| 2165 | |||
| 2166 | /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like | ||
| 2167 | "US/Pacific" that loads a tz file, then changes to a value like | ||
| 2168 | "XXX0" that does not load a tz file, and then changes back to | ||
| 2169 | its original value, the last change is (incorrectly) ignored. | ||
| 2170 | Also, if TZ changes twice in succession to values that do | ||
| 2171 | not load a tz file, tzset can dump core (see Sun bug#1225179). | ||
| 2172 | The following code works around these bugs. */ | ||
| 2159 | 2173 | ||
| 2160 | /* Add TZSTRING to the end of environ, as a value for TZ. */ | ||
| 2161 | if (tzstring) | 2174 | if (tzstring) |
| 2162 | { | 2175 | { |
| 2163 | char *t = (char *) (to + envptrs); | 2176 | /* Temporarily set TZ to a value that loads a tz file |
| 2164 | strcpy (t, "TZ="); | 2177 | and that differs from tzstring. */ |
| 2165 | strcat (t, tzstring); | 2178 | bool eq0 = strcmp (tzstring, set_time_zone_rule_tz[0] + tzeqlen) == 0; |
| 2166 | *to++ = t; | 2179 | xputenv (set_time_zone_rule_tz[eq0]); |
| 2180 | } | ||
| 2181 | else | ||
| 2182 | { | ||
| 2183 | /* The implied tzstring is unknown, so temporarily set TZ to | ||
| 2184 | two different values that each load a tz file. */ | ||
| 2185 | xputenv (set_time_zone_rule_tz[0]); | ||
| 2186 | tzset (); | ||
| 2187 | xputenv (set_time_zone_rule_tz[1]); | ||
| 2167 | } | 2188 | } |
| 2189 | tzset (); | ||
| 2190 | tzvalbuf_in_environ = 0; | ||
| 2191 | #endif | ||
| 2168 | 2192 | ||
| 2169 | /* Copy the old environ vector elements into NEWENV, | 2193 | if (!tzstring) |
| 2170 | but don't copy the TZ variable. | 2194 | { |
| 2171 | So we have only one definition of TZ, which came from TZSTRING. */ | 2195 | unsetenv ("TZ"); |
| 2172 | for (from = environ; *from; from++) | 2196 | tzvalbuf_in_environ = 0; |
| 2173 | if (strncmp (*from, "TZ=", 3) != 0) | 2197 | } |
| 2174 | *to++ = *from; | 2198 | else |
| 2175 | *to = 0; | 2199 | { |
| 2200 | ptrdiff_t tzstringlen = strlen (tzstring); | ||
| 2176 | 2201 | ||
| 2177 | environ = newenv; | 2202 | if (tzvalbufsize <= tzeqlen + tzstringlen) |
| 2203 | { | ||
| 2204 | unsetenv ("TZ"); | ||
| 2205 | tzvalbuf_in_environ = 0; | ||
| 2206 | tzvalbuf = xpalloc (tzvalbuf, &tzvalbufsize, | ||
| 2207 | tzeqlen + tzstringlen - tzvalbufsize + 1, -1, 1); | ||
| 2208 | memcpy (tzvalbuf, "TZ=", tzeqlen); | ||
| 2209 | } | ||
| 2178 | 2210 | ||
| 2179 | /* If we do have a TZSTRING, NEWENV points to the vector slot where | 2211 | strcpy (tzvalbuf + tzeqlen, tzstring); |
| 2180 | the TZ variable is stored. If we do not have a TZSTRING, | ||
| 2181 | TO points to the vector slot which has the terminating null. */ | ||
| 2182 | 2212 | ||
| 2183 | #ifdef LOCALTIME_CACHE | 2213 | if (!tzvalbuf_in_environ) |
| 2184 | { | 2214 | { |
| 2185 | /* In SunOS 4.1.3_U1 and 4.1.4, if TZ has a value like | 2215 | xputenv (tzvalbuf); |
| 2186 | "US/Pacific" that loads a tz file, then changes to a value like | 2216 | tzvalbuf_in_environ = 1; |
| 2187 | "XXX0" that does not load a tz file, and then changes back to | 2217 | } |
| 2188 | its original value, the last change is (incorrectly) ignored. | 2218 | } |
| 2189 | Also, if TZ changes twice in succession to values that do | ||
| 2190 | not load a tz file, tzset can dump core (see Sun bug#1225179). | ||
| 2191 | The following code works around these bugs. */ | ||
| 2192 | |||
| 2193 | if (tzstring) | ||
| 2194 | { | ||
| 2195 | /* Temporarily set TZ to a value that loads a tz file | ||
| 2196 | and that differs from tzstring. */ | ||
| 2197 | char *tz = *newenv; | ||
| 2198 | *newenv = (strcmp (tzstring, set_time_zone_rule_tz1 + 3) == 0 | ||
| 2199 | ? set_time_zone_rule_tz2 : set_time_zone_rule_tz1); | ||
| 2200 | tzset (); | ||
| 2201 | *newenv = tz; | ||
| 2202 | } | ||
| 2203 | else | ||
| 2204 | { | ||
| 2205 | /* The implied tzstring is unknown, so temporarily set TZ to | ||
| 2206 | two different values that each load a tz file. */ | ||
| 2207 | *to = set_time_zone_rule_tz1; | ||
| 2208 | to[1] = 0; | ||
| 2209 | tzset (); | ||
| 2210 | *to = set_time_zone_rule_tz2; | ||
| 2211 | tzset (); | ||
| 2212 | *to = 0; | ||
| 2213 | } | ||
| 2214 | |||
| 2215 | /* Now TZ has the desired value, and tzset can be invoked safely. */ | ||
| 2216 | } | ||
| 2217 | 2219 | ||
| 2220 | #ifdef LOCALTIME_CACHE | ||
| 2218 | tzset (); | 2221 | tzset (); |
| 2219 | #endif | 2222 | #endif |
| 2220 | } | 2223 | } |
| @@ -2359,8 +2362,8 @@ usage: (insert-before-markers-and-inherit &rest ARGS) */) | |||
| 2359 | 2362 | ||
| 2360 | DEFUN ("insert-char", Finsert_char, Sinsert_char, 1, 3, | 2363 | DEFUN ("insert-char", Finsert_char, Sinsert_char, 1, 3, |
| 2361 | "(list (read-char-by-name \"Insert character (Unicode name or hex): \")\ | 2364 | "(list (read-char-by-name \"Insert character (Unicode name or hex): \")\ |
| 2362 | (prefix-numeric-value current-prefix-arg)\ | 2365 | (prefix-numeric-value current-prefix-arg)\ |
| 2363 | t))", | 2366 | t))", |
| 2364 | doc: /* Insert COUNT copies of CHARACTER. | 2367 | doc: /* Insert COUNT copies of CHARACTER. |
| 2365 | Interactively, prompt for CHARACTER. You can specify CHARACTER in one | 2368 | Interactively, prompt for CHARACTER. You can specify CHARACTER in one |
| 2366 | of these ways: | 2369 | of these ways: |
| @@ -2497,7 +2500,7 @@ make_buffer_string_both (ptrdiff_t start, ptrdiff_t start_byte, | |||
| 2497 | Lisp_Object result, tem, tem1; | 2500 | Lisp_Object result, tem, tem1; |
| 2498 | 2501 | ||
| 2499 | if (start < GPT && GPT < end) | 2502 | if (start < GPT && GPT < end) |
| 2500 | move_gap (start); | 2503 | move_gap_both (start, start_byte); |
| 2501 | 2504 | ||
| 2502 | if (! NILP (BVAR (current_buffer, enable_multibyte_characters))) | 2505 | if (! NILP (BVAR (current_buffer, enable_multibyte_characters))) |
| 2503 | result = make_uninit_multibyte_string (end - start, end_byte - start_byte); | 2506 | result = make_uninit_multibyte_string (end - start, end_byte - start_byte); |
| @@ -2595,7 +2598,7 @@ If narrowing is in effect, this function returns only the visible part | |||
| 2595 | of the buffer. */) | 2598 | of the buffer. */) |
| 2596 | (void) | 2599 | (void) |
| 2597 | { | 2600 | { |
| 2598 | return make_buffer_string (BEGV, ZV, 1); | 2601 | return make_buffer_string_both (BEGV, BEGV_BYTE, ZV, ZV_BYTE, 1); |
| 2599 | } | 2602 | } |
| 2600 | 2603 | ||
| 2601 | DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring, | 2604 | DEFUN ("insert-buffer-substring", Finsert_buffer_substring, Sinsert_buffer_substring, |
| @@ -2650,10 +2653,10 @@ They default to the values of (point-min) and (point-max) in BUFFER. */) | |||
| 2650 | DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings, | 2653 | DEFUN ("compare-buffer-substrings", Fcompare_buffer_substrings, Scompare_buffer_substrings, |
| 2651 | 6, 6, 0, | 2654 | 6, 6, 0, |
| 2652 | doc: /* Compare two substrings of two buffers; return result as number. | 2655 | doc: /* Compare two substrings of two buffers; return result as number. |
| 2653 | the value is -N if first string is less after N-1 chars, | 2656 | Return -N if first string is less after N-1 chars, +N if first string is |
| 2654 | +N if first string is greater after N-1 chars, or 0 if strings match. | 2657 | greater after N-1 chars, or 0 if strings match. Each substring is |
| 2655 | Each substring is represented as three arguments: BUFFER, START and END. | 2658 | represented as three arguments: BUFFER, START and END. That makes six |
| 2656 | That makes six args in all, three for each substring. | 2659 | args in all, three for each substring. |
| 2657 | 2660 | ||
| 2658 | The value of `case-fold-search' in the current buffer | 2661 | The value of `case-fold-search' in the current buffer |
| 2659 | determines whether case is significant or ignored. */) | 2662 | determines whether case is significant or ignored. */) |
| @@ -2929,7 +2932,7 @@ Both characters must have the same length of multi-byte form. */) | |||
| 2929 | else if (!changed) | 2932 | else if (!changed) |
| 2930 | { | 2933 | { |
| 2931 | changed = -1; | 2934 | changed = -1; |
| 2932 | modify_region (current_buffer, pos, XINT (end), 0); | 2935 | modify_region_1 (pos, XINT (end), false); |
| 2933 | 2936 | ||
| 2934 | if (! NILP (noundo)) | 2937 | if (! NILP (noundo)) |
| 2935 | { | 2938 | { |
| @@ -3105,7 +3108,7 @@ It returns the number of characters changed. */) | |||
| 3105 | pos = XINT (start); | 3108 | pos = XINT (start); |
| 3106 | pos_byte = CHAR_TO_BYTE (pos); | 3109 | pos_byte = CHAR_TO_BYTE (pos); |
| 3107 | end_pos = XINT (end); | 3110 | end_pos = XINT (end); |
| 3108 | modify_region (current_buffer, pos, end_pos, 0); | 3111 | modify_region_1 (pos, end_pos, false); |
| 3109 | 3112 | ||
| 3110 | cnt = 0; | 3113 | cnt = 0; |
| 3111 | for (; pos < end_pos; ) | 3114 | for (; pos < end_pos; ) |
| @@ -3426,12 +3429,6 @@ usage: (save-restriction &rest BODY) */) | |||
| 3426 | return unbind_to (count, val); | 3429 | return unbind_to (count, val); |
| 3427 | } | 3430 | } |
| 3428 | 3431 | ||
| 3429 | /* Buffer for the most recent text displayed by Fmessage_box. */ | ||
| 3430 | static char *message_text; | ||
| 3431 | |||
| 3432 | /* Allocated length of that buffer. */ | ||
| 3433 | static ptrdiff_t message_length; | ||
| 3434 | |||
| 3435 | DEFUN ("message", Fmessage, Smessage, 1, MANY, 0, | 3432 | DEFUN ("message", Fmessage, Smessage, 1, MANY, 0, |
| 3436 | doc: /* Display a message at the bottom of the screen. | 3433 | doc: /* Display a message at the bottom of the screen. |
| 3437 | The message also goes into the `*Messages*' buffer, if `message-log-max' | 3434 | The message also goes into the `*Messages*' buffer, if `message-log-max' |
| @@ -3455,14 +3452,14 @@ usage: (message FORMAT-STRING &rest ARGS) */) | |||
| 3455 | || (STRINGP (args[0]) | 3452 | || (STRINGP (args[0]) |
| 3456 | && SBYTES (args[0]) == 0)) | 3453 | && SBYTES (args[0]) == 0)) |
| 3457 | { | 3454 | { |
| 3458 | message (0); | 3455 | message1 (0); |
| 3459 | return args[0]; | 3456 | return args[0]; |
| 3460 | } | 3457 | } |
| 3461 | else | 3458 | else |
| 3462 | { | 3459 | { |
| 3463 | register Lisp_Object val; | 3460 | register Lisp_Object val; |
| 3464 | val = Fformat (nargs, args); | 3461 | val = Fformat (nargs, args); |
| 3465 | message3 (val, SBYTES (val), STRING_MULTIBYTE (val)); | 3462 | message3 (val); |
| 3466 | return val; | 3463 | return val; |
| 3467 | } | 3464 | } |
| 3468 | } | 3465 | } |
| @@ -3481,13 +3478,12 @@ usage: (message-box FORMAT-STRING &rest ARGS) */) | |||
| 3481 | { | 3478 | { |
| 3482 | if (NILP (args[0])) | 3479 | if (NILP (args[0])) |
| 3483 | { | 3480 | { |
| 3484 | message (0); | 3481 | message1 (0); |
| 3485 | return Qnil; | 3482 | return Qnil; |
| 3486 | } | 3483 | } |
| 3487 | else | 3484 | else |
| 3488 | { | 3485 | { |
| 3489 | register Lisp_Object val; | 3486 | Lisp_Object val = Fformat (nargs, args); |
| 3490 | val = Fformat (nargs, args); | ||
| 3491 | #ifdef HAVE_MENUS | 3487 | #ifdef HAVE_MENUS |
| 3492 | /* The MS-DOS frames support popup menus even though they are | 3488 | /* The MS-DOS frames support popup menus even though they are |
| 3493 | not FRAME_WINDOW_P. */ | 3489 | not FRAME_WINDOW_P. */ |
| @@ -3504,16 +3500,7 @@ usage: (message-box FORMAT-STRING &rest ARGS) */) | |||
| 3504 | return val; | 3500 | return val; |
| 3505 | } | 3501 | } |
| 3506 | #endif /* HAVE_MENUS */ | 3502 | #endif /* HAVE_MENUS */ |
| 3507 | /* Copy the data so that it won't move when we GC. */ | 3503 | message3 (val); |
| 3508 | if (SBYTES (val) > message_length) | ||
| 3509 | { | ||
| 3510 | ptrdiff_t new_length = SBYTES (val) + 80; | ||
| 3511 | message_text = xrealloc (message_text, new_length); | ||
| 3512 | message_length = new_length; | ||
| 3513 | } | ||
| 3514 | memcpy (message_text, SDATA (val), SBYTES (val)); | ||
| 3515 | message2 (message_text, SBYTES (val), | ||
| 3516 | STRING_MULTIBYTE (val)); | ||
| 3517 | return val; | 3504 | return val; |
| 3518 | } | 3505 | } |
| 3519 | } | 3506 | } |
| @@ -3971,7 +3958,7 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 3971 | trailing "d"). */ | 3958 | trailing "d"). */ |
| 3972 | pMlen = sizeof pMd - 2 | 3959 | pMlen = sizeof pMd - 2 |
| 3973 | }; | 3960 | }; |
| 3974 | verify (0 < USEFUL_PRECISION_MAX); | 3961 | verify (USEFUL_PRECISION_MAX > 0); |
| 3975 | 3962 | ||
| 3976 | int prec; | 3963 | int prec; |
| 3977 | ptrdiff_t padding, sprintf_bytes; | 3964 | ptrdiff_t padding, sprintf_bytes; |
| @@ -4249,12 +4236,15 @@ usage: (format STRING &rest OBJECTS) */) | |||
| 4249 | { | 4236 | { |
| 4250 | buf = xmalloc (bufsize); | 4237 | buf = xmalloc (bufsize); |
| 4251 | sa_must_free = 1; | 4238 | sa_must_free = 1; |
| 4252 | buf_save_value = make_save_value (buf, 0); | 4239 | buf_save_value = make_save_pointer (buf); |
| 4253 | record_unwind_protect (safe_alloca_unwind, buf_save_value); | 4240 | record_unwind_protect (safe_alloca_unwind, buf_save_value); |
| 4254 | memcpy (buf, initial_buffer, used); | 4241 | memcpy (buf, initial_buffer, used); |
| 4255 | } | 4242 | } |
| 4256 | else | 4243 | else |
| 4257 | XSAVE_VALUE (buf_save_value)->pointer = buf = xrealloc (buf, bufsize); | 4244 | { |
| 4245 | buf = xrealloc (buf, bufsize); | ||
| 4246 | set_save_pointer (buf_save_value, 0, buf); | ||
| 4247 | } | ||
| 4258 | 4248 | ||
| 4259 | p = buf + used; | 4249 | p = buf + used; |
| 4260 | } | 4250 | } |
| @@ -4519,7 +4509,7 @@ Transposing beyond buffer boundaries is an error. */) | |||
| 4519 | (Lisp_Object startr1, Lisp_Object endr1, Lisp_Object startr2, Lisp_Object endr2, Lisp_Object leave_markers) | 4509 | (Lisp_Object startr1, Lisp_Object endr1, Lisp_Object startr2, Lisp_Object endr2, Lisp_Object leave_markers) |
| 4520 | { | 4510 | { |
| 4521 | register ptrdiff_t start1, end1, start2, end2; | 4511 | register ptrdiff_t start1, end1, start2, end2; |
| 4522 | ptrdiff_t start1_byte, start2_byte, len1_byte, len2_byte; | 4512 | ptrdiff_t start1_byte, start2_byte, len1_byte, len2_byte, end2_byte; |
| 4523 | ptrdiff_t gap, len1, len_mid, len2; | 4513 | ptrdiff_t gap, len1, len_mid, len2; |
| 4524 | unsigned char *start1_addr, *start2_addr, *temp; | 4514 | unsigned char *start1_addr, *start2_addr, *temp; |
| 4525 | 4515 | ||
| @@ -4580,20 +4570,22 @@ Transposing beyond buffer boundaries is an error. */) | |||
| 4580 | the gap the minimum distance to get it out of the way, and then | 4570 | the gap the minimum distance to get it out of the way, and then |
| 4581 | deal with an unbroken array. */ | 4571 | deal with an unbroken array. */ |
| 4582 | 4572 | ||
| 4573 | start1_byte = CHAR_TO_BYTE (start1); | ||
| 4574 | end2_byte = CHAR_TO_BYTE (end2); | ||
| 4575 | |||
| 4583 | /* Make sure the gap won't interfere, by moving it out of the text | 4576 | /* Make sure the gap won't interfere, by moving it out of the text |
| 4584 | we will operate on. */ | 4577 | we will operate on. */ |
| 4585 | if (start1 < gap && gap < end2) | 4578 | if (start1 < gap && gap < end2) |
| 4586 | { | 4579 | { |
| 4587 | if (gap - start1 < end2 - gap) | 4580 | if (gap - start1 < end2 - gap) |
| 4588 | move_gap (start1); | 4581 | move_gap_both (start1, start1_byte); |
| 4589 | else | 4582 | else |
| 4590 | move_gap (end2); | 4583 | move_gap_both (end2, end2_byte); |
| 4591 | } | 4584 | } |
| 4592 | 4585 | ||
| 4593 | start1_byte = CHAR_TO_BYTE (start1); | ||
| 4594 | start2_byte = CHAR_TO_BYTE (start2); | 4586 | start2_byte = CHAR_TO_BYTE (start2); |
| 4595 | len1_byte = CHAR_TO_BYTE (end1) - start1_byte; | 4587 | len1_byte = CHAR_TO_BYTE (end1) - start1_byte; |
| 4596 | len2_byte = CHAR_TO_BYTE (end2) - start2_byte; | 4588 | len2_byte = end2_byte - start2_byte; |
| 4597 | 4589 | ||
| 4598 | #ifdef BYTE_COMBINING_DEBUG | 4590 | #ifdef BYTE_COMBINING_DEBUG |
| 4599 | if (end1 == start2) | 4591 | if (end1 == start2) |
| @@ -4629,7 +4621,7 @@ Transposing beyond buffer boundaries is an error. */) | |||
| 4629 | 4621 | ||
| 4630 | if (end1 == start2) /* adjacent regions */ | 4622 | if (end1 == start2) /* adjacent regions */ |
| 4631 | { | 4623 | { |
| 4632 | modify_region (current_buffer, start1, end2, 0); | 4624 | modify_region_1 (start1, end2, false); |
| 4633 | record_change (start1, len1 + len2); | 4625 | record_change (start1, len1 + len2); |
| 4634 | 4626 | ||
| 4635 | tmp_interval1 = copy_intervals (cur_intv, start1, len1); | 4627 | tmp_interval1 = copy_intervals (cur_intv, start1, len1); |
| @@ -4688,8 +4680,8 @@ Transposing beyond buffer boundaries is an error. */) | |||
| 4688 | { | 4680 | { |
| 4689 | USE_SAFE_ALLOCA; | 4681 | USE_SAFE_ALLOCA; |
| 4690 | 4682 | ||
| 4691 | modify_region (current_buffer, start1, end1, 0); | 4683 | modify_region_1 (start1, end1, false); |
| 4692 | modify_region (current_buffer, start2, end2, 0); | 4684 | modify_region_1 (start2, end2, false); |
| 4693 | record_change (start1, len1); | 4685 | record_change (start1, len1); |
| 4694 | record_change (start2, len2); | 4686 | record_change (start2, len2); |
| 4695 | tmp_interval1 = copy_intervals (cur_intv, start1, len1); | 4687 | tmp_interval1 = copy_intervals (cur_intv, start1, len1); |
| @@ -4722,7 +4714,7 @@ Transposing beyond buffer boundaries is an error. */) | |||
| 4722 | { | 4714 | { |
| 4723 | USE_SAFE_ALLOCA; | 4715 | USE_SAFE_ALLOCA; |
| 4724 | 4716 | ||
| 4725 | modify_region (current_buffer, start1, end2, 0); | 4717 | modify_region_1 (start1, end2, false); |
| 4726 | record_change (start1, (end2 - start1)); | 4718 | record_change (start1, (end2 - start1)); |
| 4727 | tmp_interval1 = copy_intervals (cur_intv, start1, len1); | 4719 | tmp_interval1 = copy_intervals (cur_intv, start1, len1); |
| 4728 | tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid); | 4720 | tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid); |
| @@ -4755,7 +4747,7 @@ Transposing beyond buffer boundaries is an error. */) | |||
| 4755 | USE_SAFE_ALLOCA; | 4747 | USE_SAFE_ALLOCA; |
| 4756 | 4748 | ||
| 4757 | record_change (start1, (end2 - start1)); | 4749 | record_change (start1, (end2 - start1)); |
| 4758 | modify_region (current_buffer, start1, end2, 0); | 4750 | modify_region_1 (start1, end2, false); |
| 4759 | 4751 | ||
| 4760 | tmp_interval1 = copy_intervals (cur_intv, start1, len1); | 4752 | tmp_interval1 = copy_intervals (cur_intv, start1, len1); |
| 4761 | tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid); | 4753 | tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid); |
| @@ -4806,9 +4798,6 @@ Transposing beyond buffer boundaries is an error. */) | |||
| 4806 | void | 4798 | void |
| 4807 | syms_of_editfns (void) | 4799 | syms_of_editfns (void) |
| 4808 | { | 4800 | { |
| 4809 | environbuf = 0; | ||
| 4810 | initial_tz = 0; | ||
| 4811 | |||
| 4812 | DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions"); | 4801 | DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions"); |
| 4813 | 4802 | ||
| 4814 | DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion, | 4803 | DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion, |
| @@ -4883,12 +4872,10 @@ functions if all the text being accessed has this property. */); | |||
| 4883 | defsubr (&Sline_beginning_position); | 4872 | defsubr (&Sline_beginning_position); |
| 4884 | defsubr (&Sline_end_position); | 4873 | defsubr (&Sline_end_position); |
| 4885 | 4874 | ||
| 4886 | /* defsubr (&Smark); */ | ||
| 4887 | /* defsubr (&Sset_mark); */ | ||
| 4888 | defsubr (&Ssave_excursion); | 4875 | defsubr (&Ssave_excursion); |
| 4889 | defsubr (&Ssave_current_buffer); | 4876 | defsubr (&Ssave_current_buffer); |
| 4890 | 4877 | ||
| 4891 | defsubr (&Sbufsize); | 4878 | defsubr (&Sbuffer_size); |
| 4892 | defsubr (&Spoint_max); | 4879 | defsubr (&Spoint_max); |
| 4893 | defsubr (&Spoint_min); | 4880 | defsubr (&Spoint_min); |
| 4894 | defsubr (&Spoint_min_marker); | 4881 | defsubr (&Spoint_min_marker); |
| @@ -4917,6 +4904,8 @@ functions if all the text being accessed has this property. */); | |||
| 4917 | defsubr (&Suser_real_login_name); | 4904 | defsubr (&Suser_real_login_name); |
| 4918 | defsubr (&Suser_uid); | 4905 | defsubr (&Suser_uid); |
| 4919 | defsubr (&Suser_real_uid); | 4906 | defsubr (&Suser_real_uid); |
| 4907 | defsubr (&Sgroup_gid); | ||
| 4908 | defsubr (&Sgroup_real_gid); | ||
| 4920 | defsubr (&Suser_full_name); | 4909 | defsubr (&Suser_full_name); |
| 4921 | defsubr (&Semacs_pid); | 4910 | defsubr (&Semacs_pid); |
| 4922 | defsubr (&Scurrent_time); | 4911 | defsubr (&Scurrent_time); |