diff options
| author | John Wiegley | 2016-01-18 22:59:51 -0800 |
|---|---|---|
| committer | John Wiegley | 2016-01-18 22:59:51 -0800 |
| commit | 1b76d9168336ede8976b980aeaed64ae2908501a (patch) | |
| tree | 749e3c082a8575eee1888ba9e61e1aeaa70d0dbc /src | |
| parent | bca49307c8ea3f96d6eede375a7f42091ae5d5af (diff) | |
| parent | 2e5a89fad151f8efa97aea3f400823a95bee6289 (diff) | |
| download | emacs-1b76d9168336ede8976b980aeaed64ae2908501a.tar.gz emacs-1b76d9168336ede8976b980aeaed64ae2908501a.zip | |
-
Diffstat (limited to 'src')
| -rw-r--r-- | src/conf_post.h | 28 | ||||
| -rw-r--r-- | src/emacs-module.c | 3 | ||||
| -rw-r--r-- | src/fns.c | 3 | ||||
| -rw-r--r-- | src/gnutls.c | 10 | ||||
| -rw-r--r-- | src/gnutls.h | 1 | ||||
| -rw-r--r-- | src/sysdep.c | 66 | ||||
| -rw-r--r-- | src/window.c | 64 |
7 files changed, 121 insertions, 54 deletions
diff --git a/src/conf_post.h b/src/conf_post.h index 98ff12e5a53..5c332a05a5c 100644 --- a/src/conf_post.h +++ b/src/conf_post.h | |||
| @@ -51,10 +51,21 @@ typedef bool bool_bf; | |||
| 51 | #endif | 51 | #endif |
| 52 | #endif | 52 | #endif |
| 53 | 53 | ||
| 54 | /* When not using Clang, assume its attributes and features are absent. */ | 54 | /* Simulate __has_attribute on compilers that lack it. It is used only |
| 55 | on arguments like alloc_size that are handled in this simulation. */ | ||
| 55 | #ifndef __has_attribute | 56 | #ifndef __has_attribute |
| 56 | # define __has_attribute(a) false | 57 | # define __has_attribute(a) __has_attribute_##a |
| 57 | #endif | 58 | # define __has_attribute_alloc_size (4 < __GNUC__ + (3 <= __GNUC_MINOR__)) |
| 59 | # define __has_attribute_cleanup (3 < __GNUC__ + (4 <= __GNUC_MINOR__)) | ||
| 60 | # define __has_attribute_externally_visible \ | ||
| 61 | (4 < __GNUC__ + (1 <= __GNUC_MINOR__)) | ||
| 62 | # define __has_attribute_no_address_safety_analysis false | ||
| 63 | # define __has_attribute_no_sanitize_address \ | ||
| 64 | (4 < __GNUC__ + (8 <= __GNUC_MINOR__)) | ||
| 65 | #endif | ||
| 66 | |||
| 67 | /* Simulate __has_feature on compilers that lack it. It is used only | ||
| 68 | to define ADDRESS_SANITIZER below. */ | ||
| 58 | #ifndef __has_feature | 69 | #ifndef __has_feature |
| 59 | # define __has_feature(a) false | 70 | # define __has_feature(a) false |
| 60 | #endif | 71 | #endif |
| @@ -222,9 +233,7 @@ extern int emacs_setenv_TZ (char const *); | |||
| 222 | #define NO_INLINE | 233 | #define NO_INLINE |
| 223 | #endif | 234 | #endif |
| 224 | 235 | ||
| 225 | #if (__clang__ \ | 236 | #if __has_attribute (externally_visible) |
| 226 | ? __has_attribute (externally_visible) \ | ||
| 227 | : (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))) | ||
| 228 | #define EXTERNALLY_VISIBLE __attribute__((externally_visible)) | 237 | #define EXTERNALLY_VISIBLE __attribute__((externally_visible)) |
| 229 | #else | 238 | #else |
| 230 | #define EXTERNALLY_VISIBLE | 239 | #define EXTERNALLY_VISIBLE |
| @@ -253,9 +262,7 @@ extern int emacs_setenv_TZ (char const *); | |||
| 253 | # define ATTRIBUTE_MALLOC | 262 | # define ATTRIBUTE_MALLOC |
| 254 | #endif | 263 | #endif |
| 255 | 264 | ||
| 256 | #if (__clang__ \ | 265 | #if __has_attribute (alloc_size) |
| 257 | ? __has_attribute (alloc_size) \ | ||
| 258 | : 4 < __GNUC__ + (3 <= __GNUC_MINOR__)) | ||
| 259 | # define ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args)) | 266 | # define ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args)) |
| 260 | #else | 267 | #else |
| 261 | # define ATTRIBUTE_ALLOC_SIZE(args) | 268 | # define ATTRIBUTE_ALLOC_SIZE(args) |
| @@ -278,8 +285,7 @@ extern int emacs_setenv_TZ (char const *); | |||
| 278 | /* Attribute of functions whose code should not have addresses | 285 | /* Attribute of functions whose code should not have addresses |
| 279 | sanitized. */ | 286 | sanitized. */ |
| 280 | 287 | ||
| 281 | #if (__has_attribute (no_sanitize_address) \ | 288 | #if __has_attribute (no_sanitize_address) |
| 282 | || 4 < __GNUC__ + (8 <= __GNUC_MINOR__)) | ||
| 283 | # define ATTRIBUTE_NO_SANITIZE_ADDRESS \ | 289 | # define ATTRIBUTE_NO_SANITIZE_ADDRESS \ |
| 284 | __attribute__ ((no_sanitize_address)) ADDRESS_SANITIZER_WORKAROUND | 290 | __attribute__ ((no_sanitize_address)) ADDRESS_SANITIZER_WORKAROUND |
| 285 | #elif __has_attribute (no_address_safety_analysis) | 291 | #elif __has_attribute (no_address_safety_analysis) |
diff --git a/src/emacs-module.c b/src/emacs-module.c index b5e044e758f..79a077b3cb4 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c | |||
| @@ -35,8 +35,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 35 | 35 | ||
| 36 | /* Feature tests. */ | 36 | /* Feature tests. */ |
| 37 | 37 | ||
| 38 | /* True if __attribute__ ((cleanup (...))) works, false otherwise. */ | 38 | #if __has_attribute (cleanup) |
| 39 | #ifdef HAVE_VAR_ATTRIBUTE_CLEANUP | ||
| 40 | enum { module_has_cleanup = true }; | 39 | enum { module_has_cleanup = true }; |
| 41 | #else | 40 | #else |
| 42 | enum { module_has_cleanup = false }; | 41 | enum { module_has_cleanup = false }; |
| @@ -50,7 +50,8 @@ All integers representable in Lisp, i.e. between `most-negative-fixnum' | |||
| 50 | and `most-positive-fixnum', inclusive, are equally likely. | 50 | and `most-positive-fixnum', inclusive, are equally likely. |
| 51 | 51 | ||
| 52 | With positive integer LIMIT, return random number in interval [0,LIMIT). | 52 | With positive integer LIMIT, return random number in interval [0,LIMIT). |
| 53 | With argument t, set the random number seed from the current time and pid. | 53 | With argument t, set the random number seed from the system's entropy |
| 54 | pool if available, otherwise from less-random volatile data such as the time. | ||
| 54 | With a string argument, set the seed based on the string's contents. | 55 | With a string argument, set the seed based on the string's contents. |
| 55 | Other values of LIMIT are ignored. | 56 | Other values of LIMIT are ignored. |
| 56 | 57 | ||
diff --git a/src/gnutls.c b/src/gnutls.c index a1d058fcd48..01a5983d3b0 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -1112,15 +1112,17 @@ The return value is a property list with top-level keys :warnings and | |||
| 1112 | /* Initialize global GnuTLS state to defaults. | 1112 | /* Initialize global GnuTLS state to defaults. |
| 1113 | Call `gnutls-global-deinit' when GnuTLS usage is no longer needed. | 1113 | Call `gnutls-global-deinit' when GnuTLS usage is no longer needed. |
| 1114 | Return zero on success. */ | 1114 | Return zero on success. */ |
| 1115 | static Lisp_Object | 1115 | Lisp_Object |
| 1116 | emacs_gnutls_global_init (void) | 1116 | emacs_gnutls_global_init (void) |
| 1117 | { | 1117 | { |
| 1118 | int ret = GNUTLS_E_SUCCESS; | 1118 | int ret = GNUTLS_E_SUCCESS; |
| 1119 | 1119 | ||
| 1120 | if (!gnutls_global_initialized) | 1120 | if (!gnutls_global_initialized) |
| 1121 | ret = gnutls_global_init (); | 1121 | { |
| 1122 | 1122 | ret = gnutls_global_init (); | |
| 1123 | gnutls_global_initialized = 1; | 1123 | if (ret == GNUTLS_E_SUCCESS) |
| 1124 | gnutls_global_initialized = 1; | ||
| 1125 | } | ||
| 1124 | 1126 | ||
| 1125 | return gnutls_make_error (ret); | 1127 | return gnutls_make_error (ret); |
| 1126 | } | 1128 | } |
diff --git a/src/gnutls.h b/src/gnutls.h index c4fe738bfa0..8e879c168bd 100644 --- a/src/gnutls.h +++ b/src/gnutls.h | |||
| @@ -83,6 +83,7 @@ extern ptrdiff_t emacs_gnutls_record_check_pending (gnutls_session_t state); | |||
| 83 | extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err); | 83 | extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err); |
| 84 | #endif | 84 | #endif |
| 85 | extern Lisp_Object emacs_gnutls_deinit (Lisp_Object); | 85 | extern Lisp_Object emacs_gnutls_deinit (Lisp_Object); |
| 86 | extern Lisp_Object emacs_gnutls_global_init (void); | ||
| 86 | 87 | ||
| 87 | #endif | 88 | #endif |
| 88 | 89 | ||
diff --git a/src/sysdep.c b/src/sysdep.c index e73acec733e..a86b53642f2 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -99,6 +99,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 99 | #include "process.h" | 99 | #include "process.h" |
| 100 | #include "cm.h" | 100 | #include "cm.h" |
| 101 | 101 | ||
| 102 | #include "gnutls.h" | ||
| 103 | #if 0x020c00 <= GNUTLS_VERSION_NUMBER && !defined WINDOWSNT | ||
| 104 | # include <gnutls/crypto.h> | ||
| 105 | #else | ||
| 106 | # define emacs_gnutls_global_init() Qnil | ||
| 107 | # define gnutls_rnd(level, data, len) (-1) | ||
| 108 | #endif | ||
| 109 | |||
| 102 | #ifdef WINDOWSNT | 110 | #ifdef WINDOWSNT |
| 103 | #include <direct.h> | 111 | #include <direct.h> |
| 104 | /* In process.h which conflicts with the local copy. */ | 112 | /* In process.h which conflicts with the local copy. */ |
| @@ -2071,36 +2079,56 @@ init_signals (bool dumping) | |||
| 2071 | # endif /* !HAVE_RANDOM */ | 2079 | # endif /* !HAVE_RANDOM */ |
| 2072 | #endif /* !RAND_BITS */ | 2080 | #endif /* !RAND_BITS */ |
| 2073 | 2081 | ||
| 2082 | #ifdef HAVE_RANDOM | ||
| 2083 | typedef unsigned int random_seed; | ||
| 2084 | static void set_random_seed (random_seed arg) { srandom (arg); } | ||
| 2085 | #elif defined HAVE_LRAND48 | ||
| 2086 | /* Although srand48 uses a long seed, this is unsigned long to avoid | ||
| 2087 | undefined behavior on signed integer overflow in init_random. */ | ||
| 2088 | typedef unsigned long int random_seed; | ||
| 2089 | static void set_random_seed (random_seed arg) { srand48 (arg); } | ||
| 2090 | #else | ||
| 2091 | typedef unsigned int random_seed; | ||
| 2092 | static void set_random_seed (random_seed arg) { srand (arg); } | ||
| 2093 | #endif | ||
| 2094 | |||
| 2074 | void | 2095 | void |
| 2075 | seed_random (void *seed, ptrdiff_t seed_size) | 2096 | seed_random (void *seed, ptrdiff_t seed_size) |
| 2076 | { | 2097 | { |
| 2077 | #if defined HAVE_RANDOM || ! defined HAVE_LRAND48 | 2098 | random_seed arg = 0; |
| 2078 | unsigned int arg = 0; | ||
| 2079 | #else | ||
| 2080 | long int arg = 0; | ||
| 2081 | #endif | ||
| 2082 | unsigned char *argp = (unsigned char *) &arg; | 2099 | unsigned char *argp = (unsigned char *) &arg; |
| 2083 | unsigned char *seedp = seed; | 2100 | unsigned char *seedp = seed; |
| 2084 | ptrdiff_t i; | 2101 | for (ptrdiff_t i = 0; i < seed_size; i++) |
| 2085 | for (i = 0; i < seed_size; i++) | ||
| 2086 | argp[i % sizeof arg] ^= seedp[i]; | 2102 | argp[i % sizeof arg] ^= seedp[i]; |
| 2087 | #ifdef HAVE_RANDOM | 2103 | set_random_seed (arg); |
| 2088 | srandom (arg); | ||
| 2089 | #else | ||
| 2090 | # ifdef HAVE_LRAND48 | ||
| 2091 | srand48 (arg); | ||
| 2092 | # else | ||
| 2093 | srand (arg); | ||
| 2094 | # endif | ||
| 2095 | #endif | ||
| 2096 | } | 2104 | } |
| 2097 | 2105 | ||
| 2098 | void | 2106 | void |
| 2099 | init_random (void) | 2107 | init_random (void) |
| 2100 | { | 2108 | { |
| 2101 | struct timespec t = current_timespec (); | 2109 | random_seed v; |
| 2102 | uintmax_t v = getpid () ^ t.tv_sec ^ t.tv_nsec; | 2110 | if (! (EQ (emacs_gnutls_global_init (), Qt) |
| 2103 | seed_random (&v, sizeof v); | 2111 | && gnutls_rnd (GNUTLS_RND_NONCE, &v, sizeof v) == 0)) |
| 2112 | { | ||
| 2113 | bool success = false; | ||
| 2114 | #ifndef WINDOWSNT | ||
| 2115 | int fd = emacs_open ("/dev/urandom", O_RDONLY | O_BINARY, 0); | ||
| 2116 | if (0 <= fd) | ||
| 2117 | { | ||
| 2118 | success = emacs_read (fd, &v, sizeof v) == sizeof v; | ||
| 2119 | emacs_close (fd); | ||
| 2120 | } | ||
| 2121 | #else | ||
| 2122 | success = w32_init_random (&v, sizeof v) == 0; | ||
| 2123 | #endif | ||
| 2124 | if (! success) | ||
| 2125 | { | ||
| 2126 | /* Fall back to current time value + PID. */ | ||
| 2127 | struct timespec t = current_timespec (); | ||
| 2128 | v = getpid () ^ t.tv_sec ^ t.tv_nsec; | ||
| 2129 | } | ||
| 2130 | } | ||
| 2131 | set_random_seed (v); | ||
| 2104 | } | 2132 | } |
| 2105 | 2133 | ||
| 2106 | /* | 2134 | /* |
diff --git a/src/window.c b/src/window.c index bb414e7d311..4aeb8b39a70 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -4979,27 +4979,34 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 4979 | 4979 | ||
| 4980 | if (n > 0) | 4980 | if (n > 0) |
| 4981 | { | 4981 | { |
| 4982 | int last_y = it.last_visible_y - this_scroll_margin - 1; | ||
| 4983 | |||
| 4982 | /* We moved the window start towards ZV, so PT may be now | 4984 | /* We moved the window start towards ZV, so PT may be now |
| 4983 | in the scroll margin at the top. */ | 4985 | in the scroll margin at the top. */ |
| 4984 | move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); | 4986 | move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS); |
| 4985 | if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin | 4987 | if (IT_CHARPOS (it) == PT |
| 4988 | && it.current_y >= this_scroll_margin | ||
| 4989 | && it.current_y <= last_y - WINDOW_HEADER_LINE_HEIGHT (w) | ||
| 4986 | && (NILP (Vscroll_preserve_screen_position) | 4990 | && (NILP (Vscroll_preserve_screen_position) |
| 4987 | || EQ (Vscroll_preserve_screen_position, Qt))) | 4991 | || EQ (Vscroll_preserve_screen_position, Qt))) |
| 4988 | /* We found PT at a legitimate height. Leave it alone. */ | 4992 | /* We found PT at a legitimate height. Leave it alone. */ |
| 4989 | ; | 4993 | ; |
| 4990 | else if (window_scroll_pixel_based_preserve_y >= 0) | ||
| 4991 | { | ||
| 4992 | /* If we have a header line, take account of it. | ||
| 4993 | This is necessary because we set it.current_y to 0, above. */ | ||
| 4994 | move_it_to (&it, -1, | ||
| 4995 | window_scroll_pixel_based_preserve_x, | ||
| 4996 | (window_scroll_pixel_based_preserve_y | ||
| 4997 | - WINDOW_WANTS_HEADER_LINE_P (w)), | ||
| 4998 | -1, MOVE_TO_Y | MOVE_TO_X); | ||
| 4999 | SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); | ||
| 5000 | } | ||
| 5001 | else | 4994 | else |
| 5002 | { | 4995 | { |
| 4996 | if (window_scroll_pixel_based_preserve_y >= 0) | ||
| 4997 | { | ||
| 4998 | /* Don't enter the scroll margin at the end of the window. */ | ||
| 4999 | int goal_y = min (last_y, window_scroll_pixel_based_preserve_y); | ||
| 5000 | |||
| 5001 | /* If we have a header line, take account of it. This | ||
| 5002 | is necessary because we set it.current_y to 0, above. */ | ||
| 5003 | move_it_to (&it, -1, | ||
| 5004 | window_scroll_pixel_based_preserve_x, | ||
| 5005 | goal_y - WINDOW_HEADER_LINE_HEIGHT (w), | ||
| 5006 | -1, MOVE_TO_Y | MOVE_TO_X); | ||
| 5007 | } | ||
| 5008 | |||
| 5009 | /* Get out of the scroll margin at the top of the window. */ | ||
| 5003 | while (it.current_y < this_scroll_margin) | 5010 | while (it.current_y < this_scroll_margin) |
| 5004 | { | 5011 | { |
| 5005 | int prev = it.current_y; | 5012 | int prev = it.current_y; |
| @@ -5023,7 +5030,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5023 | /* We moved the window start towards BEGV, so PT may be now | 5030 | /* We moved the window start towards BEGV, so PT may be now |
| 5024 | in the scroll margin at the bottom. */ | 5031 | in the scroll margin at the bottom. */ |
| 5025 | move_it_to (&it, PT, -1, | 5032 | move_it_to (&it, PT, -1, |
| 5026 | (it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w) | 5033 | (it.last_visible_y - WINDOW_HEADER_LINE_HEIGHT (w) |
| 5027 | - this_scroll_margin - 1), | 5034 | - this_scroll_margin - 1), |
| 5028 | -1, | 5035 | -1, |
| 5029 | MOVE_TO_POS | MOVE_TO_Y); | 5036 | MOVE_TO_POS | MOVE_TO_Y); |
| @@ -5074,14 +5081,20 @@ window_scroll_pixel_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5074 | ; | 5081 | ; |
| 5075 | else if (window_scroll_pixel_based_preserve_y >= 0) | 5082 | else if (window_scroll_pixel_based_preserve_y >= 0) |
| 5076 | { | 5083 | { |
| 5084 | int goal_y = min (it.last_visible_y - this_scroll_margin - 1, | ||
| 5085 | window_scroll_pixel_based_preserve_y); | ||
| 5086 | |||
| 5087 | /* Don't let the preserved screen Y coordinate put us inside | ||
| 5088 | any of the two margins. */ | ||
| 5089 | if (goal_y < this_scroll_margin) | ||
| 5090 | goal_y = this_scroll_margin; | ||
| 5077 | SET_TEXT_POS_FROM_MARKER (start, w->start); | 5091 | SET_TEXT_POS_FROM_MARKER (start, w->start); |
| 5078 | start_display (&it, w, start); | 5092 | start_display (&it, w, start); |
| 5079 | /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT | 5093 | /* It would be wrong to subtract CURRENT_HEADER_LINE_HEIGHT |
| 5080 | here because we called start_display again and did not | 5094 | here because we called start_display again and did not |
| 5081 | alter it.current_y this time. */ | 5095 | alter it.current_y this time. */ |
| 5082 | move_it_to (&it, -1, window_scroll_pixel_based_preserve_x, | 5096 | move_it_to (&it, -1, window_scroll_pixel_based_preserve_x, |
| 5083 | window_scroll_pixel_based_preserve_y, -1, | 5097 | goal_y, -1, MOVE_TO_Y | MOVE_TO_X); |
| 5084 | MOVE_TO_Y | MOVE_TO_X); | ||
| 5085 | SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); | 5098 | SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it)); |
| 5086 | } | 5099 | } |
| 5087 | else | 5100 | else |
| @@ -5197,6 +5210,7 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5197 | w->force_start = true; | 5210 | w->force_start = true; |
| 5198 | 5211 | ||
| 5199 | if (!NILP (Vscroll_preserve_screen_position) | 5212 | if (!NILP (Vscroll_preserve_screen_position) |
| 5213 | && this_scroll_margin == 0 | ||
| 5200 | && (whole || !EQ (Vscroll_preserve_screen_position, Qt))) | 5214 | && (whole || !EQ (Vscroll_preserve_screen_position, Qt))) |
| 5201 | { | 5215 | { |
| 5202 | SET_PT_BOTH (pos, pos_byte); | 5216 | SET_PT_BOTH (pos, pos_byte); |
| @@ -5222,8 +5236,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5222 | marker_byte_position (opoint_marker)); | 5236 | marker_byte_position (opoint_marker)); |
| 5223 | else if (!NILP (Vscroll_preserve_screen_position)) | 5237 | else if (!NILP (Vscroll_preserve_screen_position)) |
| 5224 | { | 5238 | { |
| 5239 | int nlines = window_scroll_preserve_vpos; | ||
| 5240 | |||
| 5225 | SET_PT_BOTH (pos, pos_byte); | 5241 | SET_PT_BOTH (pos, pos_byte); |
| 5226 | Fvertical_motion (original_pos, window, Qnil); | 5242 | if (window_scroll_preserve_vpos < this_scroll_margin) |
| 5243 | nlines = this_scroll_margin; | ||
| 5244 | else if (window_scroll_preserve_vpos | ||
| 5245 | >= w->total_lines - this_scroll_margin) | ||
| 5246 | nlines = w->total_lines - this_scroll_margin - 1; | ||
| 5247 | Fvertical_motion (Fcons (make_number (window_scroll_preserve_hpos), | ||
| 5248 | make_number (nlines)), window, Qnil); | ||
| 5227 | } | 5249 | } |
| 5228 | else | 5250 | else |
| 5229 | SET_PT (top_margin); | 5251 | SET_PT (top_margin); |
| @@ -5249,8 +5271,16 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror) | |||
| 5249 | { | 5271 | { |
| 5250 | if (!NILP (Vscroll_preserve_screen_position)) | 5272 | if (!NILP (Vscroll_preserve_screen_position)) |
| 5251 | { | 5273 | { |
| 5274 | int nlines = window_scroll_preserve_vpos; | ||
| 5275 | |||
| 5252 | SET_PT_BOTH (pos, pos_byte); | 5276 | SET_PT_BOTH (pos, pos_byte); |
| 5253 | Fvertical_motion (original_pos, window, Qnil); | 5277 | if (window_scroll_preserve_vpos < this_scroll_margin) |
| 5278 | nlines = this_scroll_margin; | ||
| 5279 | else if (window_scroll_preserve_vpos | ||
| 5280 | >= ht - this_scroll_margin) | ||
| 5281 | nlines = ht - this_scroll_margin - 1; | ||
| 5282 | Fvertical_motion (Fcons (make_number (window_scroll_preserve_hpos), | ||
| 5283 | make_number (nlines)), window, Qnil); | ||
| 5254 | } | 5284 | } |
| 5255 | else | 5285 | else |
| 5256 | Fvertical_motion (make_number (-1), window, Qnil); | 5286 | Fvertical_motion (make_number (-1), window, Qnil); |