diff options
| author | Richard M. Stallman | 1993-03-21 23:04:18 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1993-03-21 23:04:18 +0000 |
| commit | aa6d10fafd1aa7680a5942d86d5de781e8b65e6a (patch) | |
| tree | c96d5ca0acae9e1242a43aa883a3b8cad028a8f1 | |
| parent | 427aa35a107e1eb9cfd734ee9f51821f08f259b5 (diff) | |
| download | emacs-aa6d10fafd1aa7680a5942d86d5de781e8b65e6a.tar.gz emacs-aa6d10fafd1aa7680a5942d86d5de781e8b65e6a.zip | |
(decode_mode_spec): Handle `%l'.
(display_count_lines): New function.
(redisplay_window): Update base_line_number and base_line_pos fields.
Always update mode line if it's an integer.
| -rw-r--r-- | src/xdisp.c | 165 |
1 files changed, 159 insertions, 6 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index ee8d744958e..5308e9d217b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -129,6 +129,7 @@ static char *fmodetrunc (); | |||
| 129 | static char *decode_mode_spec (); | 129 | static char *decode_mode_spec (); |
| 130 | static int display_string (); | 130 | static int display_string (); |
| 131 | static void display_menu_bar (); | 131 | static void display_menu_bar (); |
| 132 | static int display_count_lines (); | ||
| 132 | 133 | ||
| 133 | /* Prompt to display in front of the minibuffer contents */ | 134 | /* Prompt to display in front of the minibuffer contents */ |
| 134 | char *minibuf_prompt; | 135 | char *minibuf_prompt; |
| @@ -168,6 +169,12 @@ int clip_changed; | |||
| 168 | since last redisplay that finished */ | 169 | since last redisplay that finished */ |
| 169 | int windows_or_buffers_changed; | 170 | int windows_or_buffers_changed; |
| 170 | 171 | ||
| 172 | /* Nonzero after display_mode_line if %l was used | ||
| 173 | and it displayed a line number. */ | ||
| 174 | int line_number_displayed; | ||
| 175 | |||
| 176 | /* Maximum buffer size for which to display line numbers. */ | ||
| 177 | int line_number_display_limit; | ||
| 171 | 178 | ||
| 172 | /* Specify m, a string, as a message in the minibuf. If m is 0, clear out | 179 | /* Specify m, a string, as a message in the minibuf. If m is 0, clear out |
| 173 | any existing message, and let the minibuffer text show through. */ | 180 | any existing message, and let the minibuffer text show through. */ |
| @@ -819,9 +826,11 @@ redisplay_window (window, just_this_one) | |||
| 819 | startp = marker_position (w->start); | 826 | startp = marker_position (w->start); |
| 820 | 827 | ||
| 821 | /* Handle case where place to start displaying has been specified, | 828 | /* Handle case where place to start displaying has been specified, |
| 822 | unless the specified location is outside the visible range. */ | 829 | unless the specified location is outside the accessible range. */ |
| 823 | if (!NILP (w->force_start)) | 830 | if (!NILP (w->force_start)) |
| 824 | { | 831 | { |
| 832 | /* Forget any recorded base line for line number display. */ | ||
| 833 | w->base_line_number = Qnil; | ||
| 825 | w->update_mode_line = Qt; | 834 | w->update_mode_line = Qt; |
| 826 | w->force_start = Qnil; | 835 | w->force_start = Qnil; |
| 827 | XFASTINT (w->last_modified) = 0; | 836 | XFASTINT (w->last_modified) = 0; |
| @@ -928,7 +937,12 @@ redisplay_window (window, just_this_one) | |||
| 928 | /* If point has not moved off frame, accept the results */ | 937 | /* If point has not moved off frame, accept the results */ |
| 929 | try_window (window, startp); | 938 | try_window (window, startp); |
| 930 | if (cursor_vpos >= 0) | 939 | if (cursor_vpos >= 0) |
| 931 | goto done; | 940 | { |
| 941 | if (!just_this_one || clip_changed || beg_unchanged < startp) | ||
| 942 | /* Forget any recorded base line for line number display. */ | ||
| 943 | w->base_line_number = Qnil; | ||
| 944 | goto done; | ||
| 945 | } | ||
| 932 | else | 946 | else |
| 933 | cancel_my_columns (w); | 947 | cancel_my_columns (w); |
| 934 | } | 948 | } |
| @@ -955,7 +969,12 @@ redisplay_window (window, just_this_one) | |||
| 955 | { | 969 | { |
| 956 | try_window (window, pos.bufpos); | 970 | try_window (window, pos.bufpos); |
| 957 | if (cursor_vpos >= 0) | 971 | if (cursor_vpos >= 0) |
| 958 | goto done; | 972 | { |
| 973 | if (!just_this_one || clip_changed || beg_unchanged < startp) | ||
| 974 | /* Forget any recorded base line for line number display. */ | ||
| 975 | w->base_line_number = Qnil; | ||
| 976 | goto done; | ||
| 977 | } | ||
| 959 | else | 978 | else |
| 960 | cancel_my_columns (w); | 979 | cancel_my_columns (w); |
| 961 | } | 980 | } |
| @@ -965,6 +984,9 @@ redisplay_window (window, just_this_one) | |||
| 965 | /* Finally, just choose place to start which centers point */ | 984 | /* Finally, just choose place to start which centers point */ |
| 966 | 985 | ||
| 967 | recenter: | 986 | recenter: |
| 987 | /* Forget any previously recorded base line for line number display. */ | ||
| 988 | w->base_line_number = Qnil; | ||
| 989 | |||
| 968 | pos = *vmotion (point, - height / 2, width, hscroll, window); | 990 | pos = *vmotion (point, - height / 2, width, hscroll, window); |
| 969 | try_window (window, pos.bufpos); | 991 | try_window (window, pos.bufpos); |
| 970 | 992 | ||
| @@ -973,12 +995,19 @@ recenter: | |||
| 973 | (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil; | 995 | (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil; |
| 974 | 996 | ||
| 975 | done: | 997 | done: |
| 976 | /* If window not full width, must redo its mode line | ||
| 977 | if the window to its side is being redone */ | ||
| 978 | if ((!NILP (w->update_mode_line) | 998 | if ((!NILP (w->update_mode_line) |
| 979 | || (!just_this_one && width < FRAME_WIDTH (f) - 1)) | 999 | /* If window not full width, must redo its mode line |
| 1000 | if the window to its side is being redone */ | ||
| 1001 | || (!just_this_one && width < FRAME_WIDTH (f) - 1) | ||
| 1002 | || INTEGERP (w->base_line_pos)) | ||
| 980 | && height != XFASTINT (w->height)) | 1003 | && height != XFASTINT (w->height)) |
| 981 | display_mode_line (w); | 1004 | display_mode_line (w); |
| 1005 | if (! line_number_displayed | ||
| 1006 | && ! BUFFERP (w->base_line_pos)) | ||
| 1007 | { | ||
| 1008 | w->base_line_pos = Qnil; | ||
| 1009 | w->base_line_number = Qnil; | ||
| 1010 | } | ||
| 982 | 1011 | ||
| 983 | /* When we reach a frame's selected window, redo the frame's menu bar. */ | 1012 | /* When we reach a frame's selected window, redo the frame's menu bar. */ |
| 984 | if (!NILP (w->update_mode_line) | 1013 | if (!NILP (w->update_mode_line) |
| @@ -1889,6 +1918,8 @@ display_mode_line (w) | |||
| 1889 | register int right = XFASTINT (w->width) + left; | 1918 | register int right = XFASTINT (w->width) + left; |
| 1890 | register FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); | 1919 | register FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); |
| 1891 | 1920 | ||
| 1921 | line_number_displayed = 0; | ||
| 1922 | |||
| 1892 | get_display_line (f, vpos, left); | 1923 | get_display_line (f, vpos, left); |
| 1893 | display_mode_element (w, vpos, left, 0, right, right, | 1924 | display_mode_element (w, vpos, left, 0, right, right, |
| 1894 | current_buffer->mode_line_format); | 1925 | current_buffer->mode_line_format); |
| @@ -2181,6 +2212,93 @@ decode_mode_spec (w, c, maxwidth) | |||
| 2181 | #endif | 2212 | #endif |
| 2182 | break; | 2213 | break; |
| 2183 | 2214 | ||
| 2215 | case 'l': | ||
| 2216 | { | ||
| 2217 | int startpos = marker_position (w->start); | ||
| 2218 | int line, linepos, topline; | ||
| 2219 | int nlines, junk; | ||
| 2220 | Lisp_Object tem; | ||
| 2221 | int height = XFASTINT (w->height); | ||
| 2222 | |||
| 2223 | /* If we decided that this buffer isn't suitable for line numbers, | ||
| 2224 | don't forget that too fast. */ | ||
| 2225 | if (EQ (w->base_line_pos, w->buffer)) | ||
| 2226 | return "??"; | ||
| 2227 | |||
| 2228 | /* If the buffer is very big, don't waste time. */ | ||
| 2229 | if (ZV - BEGV > line_number_display_limit) | ||
| 2230 | { | ||
| 2231 | w->base_line_pos = Qnil; | ||
| 2232 | w->base_line_number = Qnil; | ||
| 2233 | return "??"; | ||
| 2234 | } | ||
| 2235 | |||
| 2236 | if (!NILP (w->base_line_number) | ||
| 2237 | && !NILP (w->base_line_pos) | ||
| 2238 | && XFASTINT (w->base_line_pos) <= marker_position (w->start)) | ||
| 2239 | { | ||
| 2240 | line = XFASTINT (w->base_line_number); | ||
| 2241 | linepos = XFASTINT (w->base_line_pos); | ||
| 2242 | } | ||
| 2243 | else | ||
| 2244 | { | ||
| 2245 | line = 1; | ||
| 2246 | linepos = BEGV; | ||
| 2247 | } | ||
| 2248 | |||
| 2249 | /* Count lines from base line to window start position. */ | ||
| 2250 | nlines = display_count_lines (linepos, startpos, startpos, &junk); | ||
| 2251 | |||
| 2252 | topline = nlines + line; | ||
| 2253 | |||
| 2254 | /* Determine a new base line, if the old one is too close | ||
| 2255 | or too far away, or if we did not have one. | ||
| 2256 | "Too close" means it's plausible a scroll-down would | ||
| 2257 | go back past it. */ | ||
| 2258 | if (startpos == BEGV) | ||
| 2259 | { | ||
| 2260 | XFASTINT (w->base_line_number) = topline; | ||
| 2261 | XFASTINT (w->base_line_pos) = BEGV; | ||
| 2262 | } | ||
| 2263 | else if (nlines < height + 25 || nlines > height * 3 + 50 | ||
| 2264 | || linepos == BEGV) | ||
| 2265 | { | ||
| 2266 | int limit = BEGV; | ||
| 2267 | int position; | ||
| 2268 | int distance = (height * 2 + 30) * 200; | ||
| 2269 | |||
| 2270 | if (startpos - distance > limit) | ||
| 2271 | limit = startpos - distance; | ||
| 2272 | |||
| 2273 | nlines = display_count_lines (startpos, limit, | ||
| 2274 | -(height * 2 + 30), | ||
| 2275 | &position); | ||
| 2276 | /* If we couldn't find the lines we wanted within | ||
| 2277 | 200 chars per line, | ||
| 2278 | give up on line numbers for this window. */ | ||
| 2279 | if (position == startpos - distance) | ||
| 2280 | { | ||
| 2281 | w->base_line_pos = w->buffer; | ||
| 2282 | w->base_line_number = Qnil; | ||
| 2283 | return "??"; | ||
| 2284 | } | ||
| 2285 | |||
| 2286 | XFASTINT (w->base_line_number) = topline - nlines; | ||
| 2287 | XFASTINT (w->base_line_pos) = position; | ||
| 2288 | } | ||
| 2289 | |||
| 2290 | /* Now count lines from the start pos to point. */ | ||
| 2291 | nlines = display_count_lines (startpos, PT, PT, &junk); | ||
| 2292 | |||
| 2293 | /* Record that we did display the line number. */ | ||
| 2294 | line_number_displayed = 1; | ||
| 2295 | |||
| 2296 | /* Make the string to show. */ | ||
| 2297 | sprintf (decode_mode_spec_buf, "%d", topline + nlines); | ||
| 2298 | return decode_mode_spec_buf; | ||
| 2299 | } | ||
| 2300 | break; | ||
| 2301 | |||
| 2184 | case 'm': | 2302 | case 'm': |
| 2185 | obj = current_buffer->mode_name; | 2303 | obj = current_buffer->mode_name; |
| 2186 | break; | 2304 | break; |
| @@ -2284,6 +2402,37 @@ decode_mode_spec (w, c, maxwidth) | |||
| 2284 | else | 2402 | else |
| 2285 | return ""; | 2403 | return ""; |
| 2286 | } | 2404 | } |
| 2405 | |||
| 2406 | /* Count up to N lines starting from FROM. | ||
| 2407 | But don't go beyond LIMIT. | ||
| 2408 | Return the number of lines thus found (always positive). | ||
| 2409 | Store the position after what was found into *POS_PTR. */ | ||
| 2410 | |||
| 2411 | static int | ||
| 2412 | display_count_lines (from, limit, n, pos_ptr) | ||
| 2413 | int from, limit, n; | ||
| 2414 | int *pos_ptr; | ||
| 2415 | { | ||
| 2416 | int oldbegv = BEGV; | ||
| 2417 | int oldzv = ZV; | ||
| 2418 | int shortage = 0; | ||
| 2419 | |||
| 2420 | if (limit < from) | ||
| 2421 | BEGV = limit; | ||
| 2422 | else | ||
| 2423 | ZV = limit; | ||
| 2424 | |||
| 2425 | *pos_ptr = scan_buffer ('\n', from, n, &shortage); | ||
| 2426 | |||
| 2427 | ZV = oldzv; | ||
| 2428 | BEGV = oldbegv; | ||
| 2429 | |||
| 2430 | if (n < 0) | ||
| 2431 | /* When scanning backwards, scan_buffer stops *after* the last newline | ||
| 2432 | it finds, but does count it. Compensate for that. */ | ||
| 2433 | return - n - shortage - (*pos_ptr != limit); | ||
| 2434 | return n - shortage; | ||
| 2435 | } | ||
| 2287 | 2436 | ||
| 2288 | /* Display STRING on one line of window W, starting at HPOS. | 2437 | /* Display STRING on one line of window W, starting at HPOS. |
| 2289 | Display at position VPOS. Caller should have done get_display_line. | 2438 | Display at position VPOS. Caller should have done get_display_line. |
| @@ -2462,6 +2611,10 @@ If this is zero, point is always centered after it moves off frame."); | |||
| 2462 | DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video, | 2611 | DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video, |
| 2463 | "*Non-nil means use inverse video for the mode line."); | 2612 | "*Non-nil means use inverse video for the mode line."); |
| 2464 | mode_line_inverse_video = 1; | 2613 | mode_line_inverse_video = 1; |
| 2614 | |||
| 2615 | DEFVAR_INT ("line-number-display-limit", &line_number_display_limit, | ||
| 2616 | "*Maximum buffer size for which line number should be displayed."); | ||
| 2617 | line_number_display_limit = 1000000; | ||
| 2465 | } | 2618 | } |
| 2466 | 2619 | ||
| 2467 | /* initialize the window system */ | 2620 | /* initialize the window system */ |