Mercurial > emacs
annotate src/xdisp.c @ 1785:19755499df90
* window.c (window_internal_width): New function, which accounts
for scrollbars if present.
* lisp.h (window_internal_height, window_internal_width): Add
extern declarations for these.
* dispnew.c (direct_output_for_insert, direct_output_forward_char,
buffer_posn_from_coords): Use window_internal_width instead of
writing out its definition.
* indent.c (compute_motion): Doc fix; mention scrollbars and
window_internal_width.
(pos_tab_offset, Fvertical_motion): Use window_internal_width
instead of writing it out.
* window.c (Fpos_visible_in_window_p, Fwindow_width, Fscroll_left,
Fscroll_right): Same.
* xdisp.c (redisplay, try_window, try_window_id,
display_text_line): Same.
* xdisp.c (display_string): Add new variable `f', to be W's
frame. Use it to set desired_glyphs, and to get the frame's width
to decide whether or not to draw vertical bars.
* xdisp.c (display_text_line): If we're using vertical scrollbars,
don't draw the vertical bars separating side-by-side windows.
(display_string): Same thing. Draw spaces to fill in the part of
the mode line that is under the scrollbar in partial-width
windows.
* xdisp.c (display_text_line): Use the usable internal width of
the window, as calculated above, as the limit on the length of the
overlay arrow's image, rather than using the window's width field,
less one.
* xdisp.c (redisplay): Call condemn_scrollbars_hook and
judge_scrollbars_hook whenever they are set, not just when the
frame has vertical scrollbars.
* termhooks.h (mouse_position_hook): Doc fix.
(set_vertical_scrollbar_hook): This doesn't return anything any
more, and doesn't take a struct scrollbar * argument any more.
(condemn_scrollbars_hook, redeem_scrollbar_hook,
judge_scrollbars_hook): Doc fixes.
* term.c (mouse_position_hook): Doc fix.
(set_vertical_scrollbar_hook): This doesn't return
anything any more. Doc fixes.
* keyboard.c (kbd_buffer_get_event): Receive the scrollbar's
window from *mouse_position_hook and pass it to
make_lispy_movement, instead of working with a pointer to a struct
scrollbar.
(make_lispy_event): We don't need a window_from_scrollbar function
anymore; we are given the window directly in *EVENT.
Unify the code which generates
text-area mouse clicks and scrollbar clicks; use the same code to
distinguish clicks from drags on the scrollbar as in the text area.
Distinguish clicks from drags by storing a copy of the lispy
position list returned as part of the event.
(button_down_location): Make this a lisp vector, rather than an
array of random structures.
(struct mouse_position): Remove this; it's been replaced by a lisp
list.
(make_lispy_movement): Accept the scrollbar's window as a
parameter, rather than the scrollbar itself.
If FRAME is zero, assume that the other arguments are garbage.
(syms_of_keyboard): No need to staticpro each window of
button_down_location now; just initialize and staticpro it.
* window.c (window_from_scrollbar): Function deleted; no longer
needed.
* xdisp.c (redisplay_window): Just pass the window to
set_vertical_scrollbar hook; don't pass the scrollbar object too.
* xterm.c (XTmouse_position): Don't return a pointer to the
scrollbar for scrollbar motion; instead, return the scrollbar's
window.
* xdisp.c (echo_area_display): Move the assignment of f and the
check for visibility out of the "#ifdef MULTI_FRAME" clause; they
should work under any circumstances.
* xdisp.c (redisplay_window): If we're not going to redisplay this
window because it's a minibuffer whose contents have already been
updated, go ahead and jump to the scrollbar refreshing code
anyway; they still need to be updated. Initialize opoint, so it's
known to be valid when we jump. Calculate the scrollbar settings
properly for minibuffers, no matter what they are displaying at
the time.
* xdisp.c (redisplay_windows): Don't restore the current buffer
and its point before refreshing the scrollbars; we need the buffer
accurate.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Thu, 14 Jan 1993 15:18:53 +0000 |
parents | f80c1f73f5b9 |
children | c5038f47c602 |
rev | line source |
---|---|
277 | 1 /* Display generation from window structure and buffer text. |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2 Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993 Free Software Foundation, Inc. |
277 | 3 |
4 This file is part of GNU Emacs. | |
5 | |
6 GNU Emacs is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
8 the Free Software Foundation; either version 2, or (at your option) |
277 | 9 any later version. |
10 | |
11 GNU Emacs is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GNU Emacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | |
20 | |
21 #include "config.h" | |
22 #include <stdio.h> | |
23 /*#include <ctype.h>*/ | |
24 #undef NULL | |
25 #include "lisp.h" | |
769 | 26 #include "frame.h" |
277 | 27 #include "window.h" |
28 #include "termchar.h" | |
29 #include "dispextern.h" | |
30 #include "buffer.h" | |
31 #include "indent.h" | |
32 #include "commands.h" | |
33 #include "macros.h" | |
34 #include "disptab.h" | |
1718
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
35 #include "termhooks.h" |
277 | 36 |
37 extern int interrupt_input; | |
38 extern int command_loop_level; | |
39 | |
40 /* Nonzero means print newline before next minibuffer message. */ | |
41 | |
42 int noninteractive_need_newline; | |
43 | |
44 #define min(a, b) ((a) < (b) ? (a) : (b)) | |
45 #define max(a, b) ((a) > (b) ? (a) : (b)) | |
46 | |
47 /* The buffer position of the first character appearing | |
769 | 48 entirely or partially on the current frame line. |
49 Or zero, which disables the optimization for the current frame line. */ | |
277 | 50 static int this_line_bufpos; |
51 | |
52 /* Number of characters past the end of this line, | |
53 including the terminating newline */ | |
54 static int this_line_endpos; | |
55 | |
769 | 56 /* The vertical position of this frame line. */ |
277 | 57 static int this_line_vpos; |
58 | |
769 | 59 /* Hpos value for start of display on this frame line. |
277 | 60 Usually zero, but negative if first character really began |
61 on previous line */ | |
62 static int this_line_start_hpos; | |
63 | |
64 /* Buffer that this_line variables are describing. */ | |
65 static struct buffer *this_line_buffer; | |
66 | |
67 /* Set by try_window_id to the vpos of first of any lines | |
769 | 68 scrolled on to the bottom of the frame. These lines should |
277 | 69 not be included in any general scroll computation. */ |
70 static int scroll_bottom_vpos; | |
71 | |
72 /* Value of echo_area_glyphs when it was last acted on. | |
769 | 73 If this is nonzero, there is a message on the frame |
277 | 74 in the minibuffer and it should be erased as soon |
75 as it is no longer requested to appear. */ | |
76 char *previous_echo_glyphs; | |
77 | |
769 | 78 /* Nonzero means truncate lines in all windows less wide than the frame */ |
277 | 79 int truncate_partial_width_windows; |
80 | |
81 Lisp_Object Vglobal_mode_string; | |
82 | |
83 /* Marker for where to display an arrow on top of the buffer text. */ | |
84 Lisp_Object Voverlay_arrow_position; | |
85 | |
86 /* String to display for the arrow. */ | |
87 Lisp_Object Voverlay_arrow_string; | |
88 | |
89 /* Values of those variables at last redisplay. */ | |
1527
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
90 static Lisp_Object last_arrow_position, last_arrow_string; |
277 | 91 |
92 /* Nonzero if overlay arrow has been displayed once in this window. */ | |
93 static int overlay_arrow_seen; | |
94 | |
769 | 95 /* If cursor motion alone moves point off frame, |
277 | 96 Try scrolling this many lines up or down if that will bring it back. */ |
97 int scroll_step; | |
98 | |
99 /* Nonzero if try_window_id has made blank lines at window bottom | |
100 since the last redisplay that paused */ | |
101 static int blank_end_of_window; | |
102 | |
103 /* Number of windows showing the buffer of the selected window. | |
104 keyboard.c refers to this. */ | |
105 int buffer_shared; | |
106 | |
769 | 107 /* display_text_line sets these to the frame position (origin 0) of point, |
277 | 108 whether the window is selected or not. |
109 Set one to -1 first to determine whether point was found afterwards. */ | |
110 | |
111 static int cursor_vpos; | |
112 static int cursor_hpos; | |
113 | |
114 int debug_end_pos; | |
115 | |
116 /* Nonzero means display mode line highlighted */ | |
117 int mode_line_inverse_video; | |
118 | |
119 static void echo_area_display (); | |
120 void mark_window_display_accurate (); | |
121 static void redisplay_windows (); | |
122 static void redisplay_window (); | |
123 static void try_window (); | |
124 static int try_window_id (); | |
125 static struct position *display_text_line (); | |
126 static void display_mode_line (); | |
127 static int display_mode_element (); | |
128 static char *fmodetrunc (); | |
129 static char *decode_mode_spec (); | |
130 static int display_string (); | |
131 | |
132 /* Prompt to display in front of the minibuffer contents */ | |
133 char *minibuf_prompt; | |
134 | |
135 /* Width in columns of current minibuffer prompt. */ | |
136 int minibuf_prompt_width; | |
137 | |
138 /* Message to display instead of minibuffer contents | |
139 This is what the functions error and message make, | |
140 and command echoing uses it as well. | |
141 It overrides the minibuf_prompt as well as the buffer. */ | |
142 char *echo_area_glyphs; | |
143 | |
144 /* true iff we should redraw the mode lines on the next redisplay */ | |
145 int update_mode_lines; | |
146 | |
147 /* Smallest number of characters before the gap | |
148 at any time since last redisplay that finished. | |
149 Valid for current buffer when try_window_id can be called. */ | |
150 int beg_unchanged; | |
151 | |
152 /* Smallest number of characters after the gap | |
153 at any time since last redisplay that finished. | |
154 Valid for current buffer when try_window_id can be called. */ | |
155 int end_unchanged; | |
156 | |
157 /* MODIFF as of last redisplay that finished; | |
158 if it matches MODIFF, beg_unchanged and end_unchanged | |
159 contain no useful information */ | |
160 int unchanged_modified; | |
161 | |
162 /* Nonzero if head_clip or tail_clip of current buffer has changed | |
163 since last redisplay that finished */ | |
164 int clip_changed; | |
165 | |
166 /* Nonzero if window sizes or contents have changed | |
167 since last redisplay that finished */ | |
168 int windows_or_buffers_changed; | |
169 | |
170 | |
1527
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
171 /* Specify m, a string, as a message in the minibuf. If m is 0, clear out |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
172 any existing message, and let the minibuffer text show through. */ |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
173 void |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
174 message1 (m) |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
175 char *m; |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
176 { |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
177 if (noninteractive) |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
178 { |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
179 if (noninteractive_need_newline) |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
180 putc ('\n', stderr); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
181 noninteractive_need_newline = 0; |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
182 fprintf (stderr, "%s\n", m); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
183 fflush (stderr); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
184 } |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
185 /* A null message buffer means that the frame hasn't really been |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
186 initialized yet. Error messages get reported properly by |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
187 cmd_error, so this must be just an informative message; toss it. */ |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
188 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame)) |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
189 { |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
190 #ifdef MULTI_FRAME |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
191 Lisp_Object minibuf_frame; |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
192 |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
193 choose_minibuf_frame (); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
194 minibuf_frame = WINDOW_FRAME (XWINDOW (minibuf_window)); |
1656
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
195 FRAME_SAMPLE_VISIBILITY (XFRAME (minibuf_frame)); |
1527
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
196 if (FRAME_VISIBLE_P (selected_frame) |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
197 && ! FRAME_VISIBLE_P (XFRAME (minibuf_frame))) |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
198 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (minibuf_window))); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
199 #endif |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
200 |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
201 if (m) |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
202 echo_area_glyphs = m; |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
203 else |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
204 echo_area_glyphs = previous_echo_glyphs = 0; |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
205 |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
206 do_pending_window_change (); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
207 echo_area_display (); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
208 update_frame (XFRAME (XWINDOW (minibuf_window)->frame), 1, 1); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
209 do_pending_window_change (); |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
210 } |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
211 } |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
212 |
769 | 213 /* Nonzero if FRAME_MESSAGE_BUF (selected_frame) is being used by print; |
331 | 214 zero if being used by message. */ |
215 int message_buf_print; | |
216 | |
1446
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
217 /* Dump an informative message to the minibuf. If m is 0, clear out |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
218 any existing message, and let the minibuffer text show through. */ |
277 | 219 /* VARARGS 1 */ |
220 void | |
221 message (m, a1, a2, a3) | |
222 char *m; | |
223 { | |
224 if (noninteractive) | |
225 { | |
1446
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
226 if (m) |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
227 { |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
228 if (noninteractive_need_newline) |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
229 putc ('\n', stderr); |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
230 noninteractive_need_newline = 0; |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
231 fprintf (stderr, m, a1, a2, a3); |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
232 fprintf (stderr, "\n"); |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
233 fflush (stderr); |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
234 } |
277 | 235 } |
769 | 236 /* A null message buffer means that the frame hasn't really been |
433 | 237 initialized yet. Error messages get reported properly by |
238 cmd_error, so this must be just an informative message; toss it. */ | |
769 | 239 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame)) |
277 | 240 { |
1446
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
241 if (m) |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
242 { |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
243 { |
277 | 244 #ifdef NO_ARG_ARRAY |
1446
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
245 int a[3]; |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
246 a[0] = a1; |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
247 a[1] = a2; |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
248 a[2] = a3; |
277 | 249 |
1446
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
250 doprnt (FRAME_MESSAGE_BUF (selected_frame), |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
251 FRAME_WIDTH (selected_frame), m, 0, 3, a); |
277 | 252 #else |
1446
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
253 doprnt (FRAME_MESSAGE_BUF (selected_frame), |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
254 FRAME_WIDTH (selected_frame), m, 0, 3, &a1); |
368 | 255 #endif /* NO_ARG_ARRAY */ |
1446
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
256 } |
277 | 257 |
1527
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
258 message1 (FRAME_MESSAGE_BUF (selected_frame)); |
1446
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
259 } |
37b3c2981b40
* xdisp.c (message): If M is zero, clear echo_area_glyphs and
Jim Blandy <jimb@redhat.com>
parents:
1124
diff
changeset
|
260 else |
1527
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
261 message1 (0); |
331 | 262 |
263 /* Print should start at the beginning of the message | |
264 buffer next time. */ | |
265 message_buf_print = 0; | |
277 | 266 } |
267 } | |
268 | |
269 static void | |
270 echo_area_display () | |
271 { | |
272 register int vpos; | |
769 | 273 FRAME_PTR f; |
277 | 274 |
769 | 275 #ifdef MULTI_FRAME |
276 choose_minibuf_frame (); | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
277 #endif |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
278 |
769 | 279 f = XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window))); |
277 | 280 |
769 | 281 if (! FRAME_VISIBLE_P (f)) |
277 | 282 return; |
283 | |
769 | 284 if (frame_garbaged) |
277 | 285 { |
286 Fredraw_display (); | |
769 | 287 frame_garbaged = 0; |
277 | 288 } |
289 | |
290 if (echo_area_glyphs || minibuf_level == 0) | |
291 { | |
292 vpos = XFASTINT (XWINDOW (minibuf_window)->top); | |
769 | 293 get_display_line (f, vpos, 0); |
277 | 294 display_string (XWINDOW (minibuf_window), vpos, |
295 echo_area_glyphs ? echo_area_glyphs : "", | |
769 | 296 0, 0, 0, FRAME_WIDTH (f)); |
277 | 297 |
298 /* If desired cursor location is on this line, put it at end of text */ | |
769 | 299 if (FRAME_CURSOR_Y (f) == vpos) |
300 FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos]; | |
727 | 301 |
302 /* Fill the rest of the minibuffer window with blank lines. */ | |
303 { | |
304 int i; | |
305 | |
306 for (i = vpos + 1; i < vpos + XWINDOW (minibuf_window)->height; i++) | |
307 { | |
769 | 308 get_display_line (f, i, 0); |
727 | 309 display_string (XWINDOW (minibuf_window), vpos, |
769 | 310 "", 0, 0, 0, FRAME_WIDTH (f)); |
727 | 311 } |
312 } | |
277 | 313 } |
314 else if (!EQ (minibuf_window, selected_window)) | |
315 windows_or_buffers_changed++; | |
316 | |
317 if (EQ (minibuf_window, selected_window)) | |
318 this_line_bufpos = 0; | |
319 | |
320 previous_echo_glyphs = echo_area_glyphs; | |
321 } | |
322 | |
769 | 323 /* Do a frame update, taking possible shortcuts into account. |
277 | 324 This is the main external entry point for redisplay. |
325 | |
326 If the last redisplay displayed an echo area message and that | |
327 message is no longer requested, we clear the echo area | |
328 or bring back the minibuffer if that is in use. | |
329 | |
330 Everyone would like to have a hook here to call eval, | |
331 but that cannot be done safely without a lot of changes elsewhere. | |
332 This can be called from signal handlers; with alarms set up; | |
333 or with synchronous processes running. | |
334 See the function `echo' in keyboard.c. | |
335 See Fcall_process; if you called it from here, it could be | |
336 entered recursively. */ | |
337 | |
338 void | |
339 redisplay () | |
340 { | |
341 register struct window *w = XWINDOW (selected_window); | |
342 register int pause; | |
343 int must_finish = 0; | |
344 int all_windows; | |
345 register int tlbufpos, tlendpos; | |
346 struct position pos; | |
347 extern int input_pending; | |
348 | |
349 if (noninteractive) | |
350 return; | |
351 | |
1656
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
352 /* Set the visible flags for all frames. |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
353 Do this before checking for resized or garbaged frames; they want |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
354 to know if their frames are visible. |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
355 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */ |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
356 { |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
357 Lisp_Object tail; |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
358 FRAME_PTR f; |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
359 |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
360 FOR_EACH_FRAME (tail, f) |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
361 FRAME_SAMPLE_VISIBILITY (f); |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
362 } |
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
363 |
769 | 364 /* Notice any pending interrupt request to change frame size. */ |
277 | 365 do_pending_window_change (); |
366 | |
769 | 367 if (frame_garbaged) |
277 | 368 { |
369 Fredraw_display (); | |
769 | 370 frame_garbaged = 0; |
277 | 371 } |
372 | |
368 | 373 /* Normally the message* functions will have already displayed and |
769 | 374 updated the echo area, but the frame may have been trashed, or |
368 | 375 the update may have been preempted, so display the echo area |
376 again here. */ | |
277 | 377 if (echo_area_glyphs || previous_echo_glyphs) |
378 { | |
379 echo_area_display (); | |
380 must_finish = 1; | |
381 } | |
382 | |
383 if (clip_changed || windows_or_buffers_changed) | |
384 update_mode_lines++; | |
385 | |
386 /* Detect case that we need to write a star in the mode line. */ | |
387 if (XFASTINT (w->last_modified) < MODIFF | |
388 && XFASTINT (w->last_modified) <= current_buffer->save_modified) | |
389 { | |
390 w->update_mode_line = Qt; | |
391 if (buffer_shared > 1) | |
392 update_mode_lines++; | |
393 } | |
394 | |
769 | 395 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1; |
277 | 396 |
397 all_windows = update_mode_lines || buffer_shared > 1; | |
398 | |
399 /* If specs for an arrow have changed, do thorough redisplay | |
400 to ensure we remove any arrow that should no longer exist. */ | |
1527
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
401 if (! EQ (Voverlay_arrow_position, last_arrow_position) |
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
402 || ! EQ (Voverlay_arrow_string, last_arrow_string)) |
277 | 403 all_windows = 1, clip_changed = 1; |
404 | |
405 tlbufpos = this_line_bufpos; | |
406 tlendpos = this_line_endpos; | |
485 | 407 if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line) |
769 | 408 && FRAME_VISIBLE_P (XFRAME (w->frame)) |
277 | 409 /* Make sure recorded data applies to current buffer, etc */ |
410 && this_line_buffer == current_buffer | |
411 && current_buffer == XBUFFER (w->buffer) | |
485 | 412 && NILP (w->force_start) |
277 | 413 /* Point must be on the line that we have info recorded about */ |
414 && point >= tlbufpos | |
415 && point <= Z - tlendpos | |
416 /* All text outside that line, including its final newline, | |
417 must be unchanged */ | |
418 && (XFASTINT (w->last_modified) >= MODIFF | |
419 || (beg_unchanged >= tlbufpos - 1 | |
420 && GPT >= tlbufpos | |
528 | 421 /* If selective display, can't optimize |
422 if the changes start at the beginning of the line. */ | |
423 && ((XTYPE (current_buffer->selective_display) == Lisp_Int | |
424 && XINT (current_buffer->selective_display) > 0 | |
425 ? (beg_unchanged >= tlbufpos | |
426 && GPT > tlbufpos) | |
427 : 1)) | |
277 | 428 && end_unchanged >= tlendpos |
429 && Z - GPT >= tlendpos))) | |
430 { | |
431 if (tlbufpos > BEGV && FETCH_CHAR (tlbufpos - 1) != '\n' | |
432 && (tlbufpos == ZV | |
433 || FETCH_CHAR (tlbufpos) == '\n')) | |
434 /* Former continuation line has disappeared by becoming empty */ | |
435 goto cancel; | |
436 else if (XFASTINT (w->last_modified) < MODIFF | |
437 || MINI_WINDOW_P (w)) | |
438 { | |
439 cursor_vpos = -1; | |
440 overlay_arrow_seen = 0; | |
441 display_text_line (w, tlbufpos, this_line_vpos, this_line_start_hpos, | |
442 pos_tab_offset (w, tlbufpos)); | |
443 /* If line contains point, is not continued, | |
444 and ends at same distance from eob as before, we win */ | |
445 if (cursor_vpos >= 0 && this_line_bufpos | |
446 && this_line_endpos == tlendpos) | |
447 { | |
769 | 448 if (XFASTINT (w->width) != FRAME_WIDTH (XFRAME (WINDOW_FRAME (w)))) |
277 | 449 preserve_other_columns (w); |
450 goto update; | |
451 } | |
452 else | |
453 goto cancel; | |
454 } | |
455 else if (point == XFASTINT (w->last_point)) | |
456 { | |
457 if (!must_finish) | |
458 { | |
459 do_pending_window_change (); | |
460 return; | |
461 } | |
462 goto update; | |
463 } | |
464 else | |
465 { | |
466 pos = *compute_motion (tlbufpos, 0, | |
467 XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0, | |
468 point, 2, - (1 << (SHORTBITS - 1)), | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
469 window_internal_width (w) - 1, |
574 | 470 XINT (w->hscroll), |
471 pos_tab_offset (w, tlbufpos)); | |
277 | 472 if (pos.vpos < 1) |
473 { | |
769 | 474 FRAME_CURSOR_X (selected_frame) |
277 | 475 = XFASTINT (w->left) + max (pos.hpos, 0); |
769 | 476 FRAME_CURSOR_Y (selected_frame) = this_line_vpos; |
277 | 477 goto update; |
478 } | |
479 else | |
480 goto cancel; | |
481 } | |
482 cancel: | |
483 /* Text changed drastically or point moved off of line */ | |
769 | 484 cancel_line (this_line_vpos, selected_frame); |
277 | 485 } |
486 | |
487 this_line_bufpos = 0; | |
488 all_windows |= buffer_shared > 1; | |
489 | |
490 if (all_windows) | |
491 { | |
492 Lisp_Object tail; | |
1656
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
493 FRAME_PTR f; |
277 | 494 |
495 /* Recompute # windows showing selected buffer. | |
433 | 496 This will be incremented each time such a window is displayed. */ |
277 | 497 buffer_shared = 0; |
498 | |
1656
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
499 FOR_EACH_FRAME (tail, f) |
1718
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
500 { |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
501 /* Mark all the scrollbars to be removed; we'll redeem the ones |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
502 we want when we redisplay their windows. */ |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
503 if (condemn_scrollbars_hook) |
1718
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
504 (*condemn_scrollbars_hook) (f); |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
505 |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
506 if (FRAME_VISIBLE_P (f)) |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
507 redisplay_windows (FRAME_ROOT_WINDOW (f)); |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
508 |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
509 /* Any scrollbars which redisplay_windows should have nuked |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
510 should now go away. */ |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
511 if (judge_scrollbars_hook) |
1718
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
512 (*judge_scrollbars_hook) (f); |
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
513 } |
277 | 514 } |
769 | 515 else if (FRAME_VISIBLE_P (selected_frame)) |
277 | 516 { |
517 redisplay_window (selected_window, 1); | |
769 | 518 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame)) |
277 | 519 preserve_other_columns (w); |
520 } | |
521 | |
522 update: | |
523 /* Prevent various kinds of signals during display update. | |
524 stdio is not robust about handling signals, | |
525 which can cause an apparent I/O error. */ | |
526 if (interrupt_input) | |
527 unrequest_sigio (); | |
528 stop_polling (); | |
529 | |
769 | 530 #ifdef MULTI_FRAME |
277 | 531 if (all_windows) |
532 { | |
533 Lisp_Object tail; | |
534 | |
535 pause = 0; | |
536 | |
769 | 537 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) |
277 | 538 { |
769 | 539 FRAME_PTR f; |
277 | 540 |
769 | 541 if (XTYPE (XCONS (tail)->car) != Lisp_Frame) |
277 | 542 continue; |
543 | |
769 | 544 f = XFRAME (XCONS (tail)->car); |
1718
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
545 if (FRAME_VISIBLE_P (f)) |
277 | 546 { |
769 | 547 pause |= update_frame (f, 0, 0); |
277 | 548 if (!pause) |
769 | 549 mark_window_display_accurate (f->root_window, 1); |
277 | 550 } |
551 } | |
552 } | |
553 else | |
769 | 554 #endif /* MULTI_FRAME */ |
368 | 555 { |
769 | 556 if (FRAME_VISIBLE_P (selected_frame)) |
557 pause = update_frame (selected_frame, 0, 0); | |
1656
a532c5a23984
* xdisp.c (redisplay): Call FRAME_SAMPLE_VISIBILITY to set the
Jim Blandy <jimb@redhat.com>
parents:
1600
diff
changeset
|
558 |
433 | 559 /* We may have called echo_area_display at the top of this |
769 | 560 function. If the echo area is on another frame, that may |
561 have put text on a frame other than the selected one, so the | |
562 above call to update_frame would not have caught it. Catch | |
433 | 563 it here. */ |
564 { | |
769 | 565 FRAME_PTR mini_frame = |
566 XFRAME (WINDOW_FRAME (XWINDOW (minibuf_window))); | |
433 | 567 |
769 | 568 if (mini_frame != selected_frame) |
569 pause |= update_frame (mini_frame, 0, 0); | |
433 | 570 } |
368 | 571 } |
277 | 572 |
769 | 573 /* If frame does not match, prevent doing single-line-update next time. |
277 | 574 Also, don't forget to check every line to update the arrow. */ |
575 if (pause) | |
576 { | |
577 this_line_bufpos = 0; | |
485 | 578 if (!NILP (last_arrow_position)) |
277 | 579 { |
580 last_arrow_position = Qt; | |
581 last_arrow_string = Qt; | |
582 } | |
769 | 583 /* If we pause after scrolling, some lines in current_frame |
277 | 584 may be null, so preserve_other_columns won't be able to |
585 preserve all the vertical-bar separators. So, avoid using it | |
586 in that case. */ | |
769 | 587 if (XFASTINT (w->width) != FRAME_WIDTH (selected_frame)) |
277 | 588 update_mode_lines = 1; |
589 } | |
590 | |
769 | 591 /* Now text on frame agrees with windows, so |
277 | 592 put info into the windows for partial redisplay to follow */ |
593 | |
594 if (!pause) | |
595 { | |
596 register struct buffer *b = XBUFFER (w->buffer); | |
597 | |
598 blank_end_of_window = 0; | |
599 clip_changed = 0; | |
600 unchanged_modified = BUF_MODIFF (b); | |
601 beg_unchanged = BUF_GPT (b) - BUF_BEG (b); | |
602 end_unchanged = BUF_Z (b) - BUF_GPT (b); | |
603 | |
604 XFASTINT (w->last_point) = BUF_PT (b); | |
769 | 605 XFASTINT (w->last_point_x) = FRAME_CURSOR_X (selected_frame); |
606 XFASTINT (w->last_point_y) = FRAME_CURSOR_Y (selected_frame); | |
277 | 607 |
608 if (all_windows) | |
1017
d42877206c0a
* xdisp.c (display_mode_line): Use x_implicitly_set_name here.
Jim Blandy <jimb@redhat.com>
parents:
973
diff
changeset
|
609 mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1); |
277 | 610 else |
611 { | |
612 w->update_mode_line = Qnil; | |
613 XFASTINT (w->last_modified) = BUF_MODIFF (b); | |
614 w->window_end_valid = Qt; | |
615 last_arrow_position = Voverlay_arrow_position; | |
616 last_arrow_string = Voverlay_arrow_string; | |
617 } | |
618 update_mode_lines = 0; | |
619 windows_or_buffers_changed = 0; | |
620 } | |
621 | |
622 /* Start SIGIO interrupts coming again. | |
623 Having them off during the code above | |
624 makes it less likely one will discard output, | |
625 but not impossible, since there might be stuff | |
626 in the system buffer here. | |
627 But it is much hairier to try to do anything about that. */ | |
628 | |
629 if (interrupt_input) | |
630 request_sigio (); | |
631 start_polling (); | |
632 | |
769 | 633 /* Change frame size now if a change is pending. */ |
277 | 634 do_pending_window_change (); |
635 } | |
636 | |
637 /* Redisplay, but leave alone any recent echo area message | |
638 unless another message has been requested in its place. | |
639 | |
640 This is useful in situations where you need to redisplay but no | |
641 user action has occurred, making it inappropriate for the message | |
642 area to be cleared. See tracking_off and | |
643 wait_reading_process_input for examples of these situations. */ | |
644 | |
645 redisplay_preserve_echo_area () | |
646 { | |
647 if (echo_area_glyphs == 0 && previous_echo_glyphs != 0) | |
648 { | |
649 echo_area_glyphs = previous_echo_glyphs; | |
650 redisplay (); | |
651 echo_area_glyphs = 0; | |
652 } | |
653 else | |
654 redisplay (); | |
655 } | |
656 | |
657 void | |
658 mark_window_display_accurate (window, flag) | |
659 Lisp_Object window; | |
660 int flag; | |
661 { | |
662 register struct window *w; | |
663 | |
485 | 664 for (;!NILP (window); window = w->next) |
277 | 665 { |
1527
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
666 if (XTYPE (window) != Lisp_Window) abort (); |
277 | 667 w = XWINDOW (window); |
668 | |
485 | 669 if (!NILP (w->buffer)) |
277 | 670 XFASTINT (w->last_modified) |
671 = !flag ? 0 | |
672 : XBUFFER (w->buffer) == current_buffer | |
673 ? MODIFF : BUF_MODIFF (XBUFFER (w->buffer)); | |
674 w->window_end_valid = Qt; | |
675 w->update_mode_line = Qnil; | |
676 | |
485 | 677 if (!NILP (w->vchild)) |
277 | 678 mark_window_display_accurate (w->vchild, flag); |
485 | 679 if (!NILP (w->hchild)) |
277 | 680 mark_window_display_accurate (w->hchild, flag); |
681 } | |
682 | |
683 if (flag) | |
684 { | |
685 last_arrow_position = Voverlay_arrow_position; | |
686 last_arrow_string = Voverlay_arrow_string; | |
687 } | |
688 else | |
689 { | |
690 /* t is unequal to any useful value of Voverlay_arrow_... */ | |
691 last_arrow_position = Qt; | |
692 last_arrow_string = Qt; | |
693 } | |
694 } | |
695 | |
696 int do_id = 1; | |
697 | |
698 static void | |
699 redisplay_windows (window) | |
700 Lisp_Object window; | |
701 { | |
485 | 702 for (; !NILP (window); window = XWINDOW (window)->next) |
277 | 703 redisplay_window (window, 0); |
704 } | |
705 | |
706 static void | |
707 redisplay_window (window, just_this_one) | |
708 Lisp_Object window; | |
709 int just_this_one; | |
710 { | |
711 register struct window *w = XWINDOW (window); | |
1718
f80c1f73f5b9
* xdisp.c: #include "termhooks.h".
Jim Blandy <jimb@redhat.com>
parents:
1656
diff
changeset
|
712 FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); |
277 | 713 int height; |
714 register int lpoint = point; | |
715 struct buffer *old = current_buffer; | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
716 register int width = window_internal_width (w) - 1; |
277 | 717 register int startp; |
718 register int hscroll = XINT (w->hscroll); | |
719 struct position pos; | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
720 int opoint = point; |
277 | 721 int tem; |
722 int window_needs_modeline; | |
723 | |
769 | 724 if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */ |
277 | 725 |
726 /* If this is a combination window, do its children; that's all. */ | |
727 | |
485 | 728 if (!NILP (w->vchild)) |
277 | 729 { |
730 redisplay_windows (w->vchild); | |
731 return; | |
732 } | |
485 | 733 if (!NILP (w->hchild)) |
277 | 734 { |
735 redisplay_windows (w->hchild); | |
736 return; | |
737 } | |
485 | 738 if (NILP (w->buffer)) |
277 | 739 abort (); |
433 | 740 |
741 height = window_internal_height (w); | |
742 | |
743 if (MINI_WINDOW_P (w)) | |
744 { | |
745 if (w == XWINDOW (minibuf_window)) | |
746 { | |
747 if (echo_area_glyphs) | |
748 /* We've already displayed the echo area glyphs, if any. */ | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
749 goto finish_scrollbars; |
433 | 750 } |
751 else | |
752 { | |
753 /* This is a minibuffer, but it's not the currently active one, so | |
754 clear it. */ | |
769 | 755 int vpos = XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top); |
433 | 756 int i; |
757 | |
758 for (i = 0; i < height; i++) | |
759 { | |
769 | 760 get_display_line (f, vpos + i, 0); |
433 | 761 display_string (w, vpos + i, "", 0, 0, 0, width); |
762 } | |
763 | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
764 goto finish_scrollbars; |
433 | 765 } |
766 } | |
277 | 767 |
768 if (update_mode_lines) | |
769 w->update_mode_line = Qt; | |
770 | |
771 /* Otherwise set up data on this window; select its buffer and point value */ | |
772 | |
773 current_buffer = XBUFFER (w->buffer); | |
774 opoint = point; | |
775 | |
776 /* Count number of windows showing the selected buffer. */ | |
777 | |
778 if (!just_this_one | |
779 && current_buffer == XBUFFER (XWINDOW (selected_window)->buffer)) | |
780 buffer_shared++; | |
781 | |
782 /* POINT refers normally to the selected window. | |
783 For any other window, set up appropriate value. */ | |
784 | |
785 if (!EQ (window, selected_window)) | |
786 { | |
787 SET_PT (marker_position (w->pointm)); | |
788 if (point < BEGV) | |
789 { | |
485 | 790 SET_PT (BEGV); |
277 | 791 Fset_marker (w->pointm, make_number (point), Qnil); |
792 } | |
793 else if (point > (ZV - 1)) | |
794 { | |
485 | 795 SET_PT (ZV); |
277 | 796 Fset_marker (w->pointm, make_number (point), Qnil); |
797 } | |
798 } | |
799 | |
800 /* If window-start is screwed up, choose a new one. */ | |
801 if (XMARKER (w->start)->buffer != current_buffer) | |
802 goto recenter; | |
803 | |
804 startp = marker_position (w->start); | |
805 | |
433 | 806 /* Handle case where place to start displaying has been specified, |
807 unless the specified location is outside the visible range. */ | |
485 | 808 if (!NILP (w->force_start)) |
277 | 809 { |
810 w->update_mode_line = Qt; | |
811 w->force_start = Qnil; | |
812 XFASTINT (w->last_modified) = 0; | |
433 | 813 if (startp < BEGV) startp = BEGV; |
814 if (startp > ZV) startp = ZV; | |
277 | 815 try_window (window, startp); |
816 if (cursor_vpos < 0) | |
817 { | |
818 /* If point does not appear, move point so it does appear */ | |
819 pos = *compute_motion (startp, 0, | |
820 ((EQ (window, minibuf_window) && startp == 1) | |
821 ? minibuf_prompt_width : 0) | |
822 + | |
823 (hscroll ? 1 - hscroll : 0), | |
824 ZV, height / 2, | |
825 - (1 << (SHORTBITS - 1)), | |
826 width, hscroll, pos_tab_offset (w, startp)); | |
827 SET_PT (pos.bufpos); | |
769 | 828 if (w != XWINDOW (FRAME_SELECTED_WINDOW (f))) |
277 | 829 Fset_marker (w->pointm, make_number (point), Qnil); |
830 else | |
831 { | |
832 lpoint = point; | |
769 | 833 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left); |
834 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top); | |
277 | 835 } |
836 } | |
837 goto done; | |
838 } | |
839 | |
840 /* Handle case where text has not changed, only point, | |
769 | 841 and it has not moved off the frame */ |
277 | 842 |
843 /* This code is not used for minibuffer for the sake of | |
844 the case of redisplaying to replace an echo area message; | |
845 since in that case the minibuffer contents per se are usually unchanged. | |
846 This code is of no real use in the minibuffer since | |
847 the handling of this_line_bufpos, etc., | |
848 in redisplay handles the same cases. */ | |
849 | |
850 if (XFASTINT (w->last_modified) >= MODIFF | |
851 && point >= startp && !clip_changed | |
769 | 852 && (just_this_one || XFASTINT (w->width) == FRAME_WIDTH (f)) |
277 | 853 && !EQ (window, minibuf_window)) |
854 { | |
855 pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), | |
856 point, height + 1, 10000, width, hscroll, | |
857 pos_tab_offset (w, startp)); | |
858 | |
859 if (pos.vpos < height) | |
860 { | |
769 | 861 /* Ok, point is still on frame */ |
862 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | |
277 | 863 { |
864 /* These variables are supposed to be origin 1 */ | |
769 | 865 FRAME_CURSOR_X (f) = max (0, pos.hpos) + XFASTINT (w->left); |
866 FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top); | |
277 | 867 } |
868 /* This doesn't do the trick, because if a window to the right of | |
869 this one must be redisplayed, this does nothing because there | |
769 | 870 is nothing in DesiredFrame yet, and then the other window is |
277 | 871 redisplayed, making likes that are empty in this window's columns. |
769 | 872 if (XFASTINT (w->width) != FRAME_WIDTH (f)) |
277 | 873 preserve_my_columns (w); |
874 */ | |
875 goto done; | |
876 } | |
877 /* Don't bother trying redisplay with same start; | |
878 we already know it will lose */ | |
879 } | |
880 /* If current starting point was originally the beginning of a line | |
881 but no longer is, find a new starting point. */ | |
485 | 882 else if (!NILP (w->start_at_line_beg) |
277 | 883 && !(startp == BEGV |
884 || FETCH_CHAR (startp - 1) == '\n')) | |
885 { | |
886 goto recenter; | |
887 } | |
888 else if (just_this_one && !MINI_WINDOW_P (w) | |
889 && point >= startp | |
890 && XFASTINT (w->last_modified) | |
891 && ! EQ (w->window_end_valid, Qnil) | |
892 && do_id && !clip_changed | |
893 && !blank_end_of_window | |
769 | 894 && XFASTINT (w->width) == FRAME_WIDTH (f) |
277 | 895 && EQ (last_arrow_position, Voverlay_arrow_position) |
896 && EQ (last_arrow_string, Voverlay_arrow_string) | |
769 | 897 && (tem = try_window_id (FRAME_SELECTED_WINDOW (f))) |
277 | 898 && tem != -2) |
899 { | |
900 /* tem > 0 means success. tem == -1 means choose new start. | |
901 tem == -2 means try again with same start, | |
902 and nothing but whitespace follows the changed stuff. | |
903 tem == 0 means try again with same start. */ | |
904 if (tem > 0) | |
905 goto done; | |
906 } | |
907 else if (startp >= BEGV && startp <= ZV | |
908 /* Avoid starting display at end of buffer! */ | |
433 | 909 && (startp < ZV || startp == BEGV |
277 | 910 || (XFASTINT (w->last_modified) >= MODIFF))) |
911 { | |
912 /* Try to redisplay starting at same place as before */ | |
769 | 913 /* If point has not moved off frame, accept the results */ |
277 | 914 try_window (window, startp); |
915 if (cursor_vpos >= 0) | |
916 goto done; | |
917 else | |
918 cancel_my_columns (w); | |
919 } | |
920 | |
921 XFASTINT (w->last_modified) = 0; | |
922 w->update_mode_line = Qt; | |
923 | |
924 /* Try to scroll by specified few lines */ | |
925 | |
926 if (scroll_step && !clip_changed) | |
927 { | |
928 if (point > startp) | |
929 { | |
930 pos = *vmotion (Z - XFASTINT (w->window_end_pos), | |
931 scroll_step, width, hscroll, window); | |
932 if (pos.vpos >= height) | |
933 goto scroll_fail; | |
934 } | |
935 | |
936 pos = *vmotion (startp, point < startp ? - scroll_step : scroll_step, | |
937 width, hscroll, window); | |
938 | |
939 if (point >= pos.bufpos) | |
940 { | |
941 try_window (window, pos.bufpos); | |
942 if (cursor_vpos >= 0) | |
943 goto done; | |
944 else | |
945 cancel_my_columns (w); | |
946 } | |
947 scroll_fail: ; | |
948 } | |
949 | |
950 /* Finally, just choose place to start which centers point */ | |
951 | |
952 recenter: | |
953 pos = *vmotion (point, - height / 2, width, hscroll, window); | |
954 try_window (window, pos.bufpos); | |
955 | |
956 startp = marker_position (w->start); | |
957 w->start_at_line_beg = | |
958 (startp == BEGV || FETCH_CHAR (startp - 1) == '\n') ? Qt : Qnil; | |
959 | |
960 done: | |
961 /* If window not full width, must redo its mode line | |
962 if the window to its side is being redone */ | |
485 | 963 if ((!NILP (w->update_mode_line) |
769 | 964 || (!just_this_one && width < FRAME_WIDTH (f) - 1)) |
277 | 965 && height != XFASTINT (w->height)) |
966 display_mode_line (w); | |
967 | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
968 finish_scrollbars: |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
969 if (FRAME_HAS_VERTICAL_SCROLLBARS (f)) |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
970 { |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
971 int start, end, whole; |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
972 |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
973 /* Calculate the start and end positions for the current window. |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
974 Note that minibuffers sometimes aren't displaying any text. */ |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
975 if (! MINI_WINDOW_P (w) |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
976 || (w == XWINDOW (minibuf_window) && ! echo_area_glyphs)) |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
977 { |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
978 start = startp; |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
979 /* I don't think this is guaranteed to be right. For the |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
980 moment, we'll pretend it is. */ |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
981 end = Z - XINT (w->window_end_pos); |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
982 whole = Z - BEG; |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
983 } |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
984 else |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
985 start = end = whole = 0; |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
986 |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
987 /* Indicate what this scrollbar ought to be displaying now. */ |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
988 (*set_vertical_scrollbar_hook) (w, end - start, whole, start - 1); |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
989 |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
990 /* Note that we actually used the scrollbar attached to this window, |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
991 so it shouldn't be deleted at the end of redisplay. */ |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
992 (*redeem_scrollbar_hook) (w); |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
993 } |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
994 |
277 | 995 SET_PT (opoint); |
996 current_buffer = old; | |
997 SET_PT (lpoint); | |
998 } | |
999 | |
1000 /* Do full redisplay on one window, starting at position `pos'. */ | |
1001 | |
1002 static void | |
1003 try_window (window, pos) | |
1004 Lisp_Object window; | |
1005 register int pos; | |
1006 { | |
1007 register struct window *w = XWINDOW (window); | |
1008 register int height = window_internal_height (w); | |
1009 register int vpos = XFASTINT (w->top); | |
1010 register int last_text_vpos = vpos; | |
1011 int tab_offset = pos_tab_offset (w, pos); | |
769 | 1012 FRAME_PTR f = XFRAME (w->frame); |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1013 int width = window_internal_width (w) - 1; |
277 | 1014 struct position val; |
1015 | |
1016 Fset_marker (w->start, make_number (pos), Qnil); | |
1017 cursor_vpos = -1; | |
1018 overlay_arrow_seen = 0; | |
1019 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0; | |
1020 | |
1021 while (--height >= 0) | |
1022 { | |
1023 val = *display_text_line (w, pos, vpos, val.hpos, tab_offset); | |
1024 tab_offset += width; | |
1025 if (val.vpos) tab_offset = 0; | |
1026 vpos++; | |
1027 if (pos != val.bufpos) | |
1028 last_text_vpos | |
1029 /* Next line, unless prev line ended in end of buffer with no cr */ | |
1030 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n'); | |
1031 pos = val.bufpos; | |
1032 } | |
1033 | |
1034 /* If last line is continued in middle of character, | |
769 | 1035 include the split character in the text considered on the frame */ |
277 | 1036 if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)) |
1037 pos++; | |
1038 | |
769 | 1039 /* If bottom just moved off end of frame, change mode line percentage. */ |
277 | 1040 if (XFASTINT (w->window_end_pos) == 0 |
1041 && Z != pos) | |
1042 w->update_mode_line = Qt; | |
1043 | |
769 | 1044 /* Say where last char on frame will be, once redisplay is finished. */ |
277 | 1045 XFASTINT (w->window_end_pos) = Z - pos; |
1046 XFASTINT (w->window_end_vpos) = last_text_vpos - XFASTINT (w->top); | |
1047 /* But that is not valid info until redisplay finishes. */ | |
1048 w->window_end_valid = Qnil; | |
1049 } | |
1050 | |
1051 /* Try to redisplay when buffer is modified locally, | |
1052 computing insert/delete line to preserve text outside | |
1053 the bounds of the changes. | |
1054 Return 1 if successful, 0 if if cannot tell what to do, | |
1055 or -1 to tell caller to find a new window start, | |
1056 or -2 to tell caller to do normal redisplay with same window start. */ | |
1057 | |
1058 static int | |
1059 try_window_id (window) | |
1060 Lisp_Object window; | |
1061 { | |
1062 int pos; | |
1063 register struct window *w = XWINDOW (window); | |
1064 register int height = window_internal_height (w); | |
769 | 1065 FRAME_PTR f = XFRAME (w->frame); |
277 | 1066 int top = XFASTINT (w->top); |
1067 int start = marker_position (w->start); | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1068 int width = window_internal_width (w) - 1; |
277 | 1069 int hscroll = XINT (w->hscroll); |
1070 int lmargin = hscroll > 0 ? 1 - hscroll : 0; | |
1071 register int vpos; | |
1072 register int i, tem; | |
1073 int last_text_vpos = 0; | |
1074 int stop_vpos; | |
1075 | |
1076 struct position val, bp, ep, xp, pp; | |
1077 int scroll_amount = 0; | |
1078 int delta; | |
1079 int tab_offset, epto; | |
1080 | |
1081 if (GPT - BEG < beg_unchanged) | |
1082 beg_unchanged = GPT - BEG; | |
1083 if (Z - GPT < end_unchanged) | |
1084 end_unchanged = Z - GPT; | |
1085 | |
1086 if (beg_unchanged + 1 < start) | |
1087 return 0; /* Give up if changes go above top of window */ | |
1088 | |
1089 /* Find position before which nothing is changed. */ | |
1090 bp = *compute_motion (start, 0, lmargin, | |
371 | 1091 beg_unchanged + 1, height + 1, 0, width, hscroll, |
277 | 1092 pos_tab_offset (w, start)); |
1093 if (bp.vpos >= height) | |
368 | 1094 { |
1095 if (point < bp.bufpos && !bp.contin) | |
1096 { | |
769 | 1097 /* All changes are below the frame, and point is on the frame. |
1098 We don't need to change the frame at all. | |
368 | 1099 But we need to update window_end_pos to account for |
1100 any change in buffer size. */ | |
371 | 1101 bp = *compute_motion (start, 0, lmargin, |
1102 Z, height, 0, | |
1103 width, hscroll, pos_tab_offset (w, start)); | |
368 | 1104 XFASTINT (w->window_end_vpos) = height; |
1105 XFASTINT (w->window_end_pos) = Z - bp.bufpos; | |
1106 return 1; | |
1107 } | |
1108 return 0; | |
1109 } | |
277 | 1110 |
1111 vpos = bp.vpos; | |
1112 | |
769 | 1113 /* Find beginning of that frame line. Must display from there. */ |
277 | 1114 bp = *vmotion (bp.bufpos, 0, width, hscroll, window); |
1115 | |
1116 pos = bp.bufpos; | |
1117 val.hpos = lmargin; | |
1118 if (pos < start) | |
1119 return -1; | |
1120 | |
1121 /* If about to start displaying at the beginning of a continuation line, | |
769 | 1122 really start with previous frame line, in case it was not |
277 | 1123 continued when last redisplayed */ |
528 | 1124 if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0) |
1125 || | |
1126 /* Likewise if we have to worry about selective display. */ | |
1127 (XTYPE (current_buffer->selective_display) == Lisp_Int | |
1128 && XINT (current_buffer->selective_display) > 0 | |
1129 && bp.bufpos - 1 == beg_unchanged && vpos > 0)) | |
277 | 1130 { |
1131 bp = *vmotion (bp.bufpos, -1, width, hscroll, window); | |
1132 --vpos; | |
1133 pos = bp.bufpos; | |
1134 } | |
1135 | |
1136 if (bp.contin && bp.hpos != lmargin) | |
1137 { | |
1138 val.hpos = bp.prevhpos - width + lmargin; | |
1139 pos--; | |
1140 } | |
1141 | |
1142 bp.vpos = vpos; | |
1143 | |
1144 /* Find first visible newline after which no more is changed. */ | |
1145 tem = find_next_newline (Z - max (end_unchanged, Z - ZV), 1); | |
1146 if (XTYPE (current_buffer->selective_display) == Lisp_Int | |
1147 && XINT (current_buffer->selective_display) > 0) | |
1148 while (tem < ZV - 1 | |
1149 && (position_indentation (tem) | |
1150 >= XINT (current_buffer->selective_display))) | |
1151 tem = find_next_newline (tem, 1); | |
1152 | |
1153 /* Compute the cursor position after that newline. */ | |
1154 ep = *compute_motion (pos, vpos, val.hpos, tem, | |
1155 height, - (1 << (SHORTBITS - 1)), | |
1156 width, hscroll, pos_tab_offset (w, bp.bufpos)); | |
1157 | |
769 | 1158 /* If changes reach past the text available on the frame, |
1159 just display rest of frame. */ | |
277 | 1160 if (ep.bufpos > Z - XFASTINT (w->window_end_pos)) |
1161 stop_vpos = height; | |
1162 else | |
1163 stop_vpos = ep.vpos; | |
1164 | |
1165 /* If no newline before ep, the line ep is on includes some changes | |
1166 that must be displayed. Make sure we don't stop before it. */ | |
1167 /* Also, if changes reach all the way until ep.bufpos, | |
1168 it is possible that something was deleted after the | |
1169 newline before it, so the following line must be redrawn. */ | |
1170 if (stop_vpos == ep.vpos | |
1171 && (ep.bufpos == BEGV | |
1172 || FETCH_CHAR (ep.bufpos - 1) != '\n' | |
1173 || ep.bufpos == Z - end_unchanged)) | |
1174 stop_vpos = ep.vpos + 1; | |
1175 | |
1176 cursor_vpos = -1; | |
1177 overlay_arrow_seen = 0; | |
1178 | |
1179 /* If changes do not reach to bottom of window, | |
1180 figure out how much to scroll the rest of the window */ | |
1181 if (stop_vpos < height) | |
1182 { | |
1183 /* Now determine how far up or down the rest of the window has moved */ | |
1184 epto = pos_tab_offset (w, ep.bufpos); | |
1185 xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, | |
1186 Z - XFASTINT (w->window_end_pos), | |
1187 10000, 0, width, hscroll, epto); | |
1188 scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos); | |
1189 | |
769 | 1190 /* Is everything on frame below the changes whitespace? |
277 | 1191 If so, no scrolling is really necessary. */ |
1192 for (i = ep.bufpos; i < xp.bufpos; i++) | |
1193 { | |
1194 tem = FETCH_CHAR (i); | |
1195 if (tem != ' ' && tem != '\n' && tem != '\t') | |
1196 break; | |
1197 } | |
1198 if (i == xp.bufpos) | |
1199 return -2; | |
1200 | |
1201 XFASTINT (w->window_end_vpos) += scroll_amount; | |
1202 | |
769 | 1203 /* Before doing any scrolling, verify that point will be on frame. */ |
277 | 1204 if (point > ep.bufpos && !(point <= xp.bufpos && xp.bufpos < height)) |
1205 { | |
1206 if (point <= xp.bufpos) | |
1207 { | |
1208 pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, | |
1209 point, height, - (1 << (SHORTBITS - 1)), | |
1210 width, hscroll, epto); | |
1211 } | |
1212 else | |
1213 { | |
1214 pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, | |
1215 point, height, - (1 << (SHORTBITS - 1)), | |
1216 width, hscroll, pos_tab_offset (w, xp.bufpos)); | |
1217 } | |
1218 if (pp.bufpos < point || pp.vpos == height) | |
1219 return 0; | |
1220 cursor_vpos = pp.vpos + top; | |
1221 cursor_hpos = pp.hpos + XFASTINT (w->left); | |
1222 } | |
1223 | |
1224 if (stop_vpos - scroll_amount >= height | |
1225 || ep.bufpos == xp.bufpos) | |
1226 { | |
1227 if (scroll_amount < 0) | |
1228 stop_vpos -= scroll_amount; | |
1229 scroll_amount = 0; | |
1230 /* In this path, we have altered window_end_vpos | |
1231 and not left it negative. | |
1232 We must make sure that, in case display is preempted | |
769 | 1233 before the frame changes to reflect what we do here, |
277 | 1234 further updates will not come to try_window_id |
769 | 1235 and assume the frame and window_end_vpos match. */ |
277 | 1236 blank_end_of_window = 1; |
1237 } | |
1238 else if (!scroll_amount) | |
1239 {} | |
1240 else if (bp.bufpos == Z - end_unchanged) | |
1241 { | |
1242 /* If reprinting everything is nearly as fast as scrolling, | |
1243 don't bother scrolling. Can happen if lines are short. */ | |
769 | 1244 if (scroll_cost (f, bp.vpos + top - scroll_amount, |
277 | 1245 top + height - max (0, scroll_amount), |
1246 scroll_amount) | |
1247 > xp.bufpos - bp.bufpos - 20) | |
1248 /* Return "try normal display with same window-start." | |
1249 Too bad we can't prevent further scroll-thinking. */ | |
1250 return -2; | |
1251 /* If pure deletion, scroll up as many lines as possible. | |
1252 In common case of killing a line, this can save the | |
1253 following line from being overwritten by scrolling | |
1254 and therefore having to be redrawn. */ | |
769 | 1255 tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount, |
277 | 1256 top + height - max (0, scroll_amount), |
1257 scroll_amount); | |
1258 if (!tem) stop_vpos = height; | |
1259 } | |
1260 else if (scroll_amount) | |
1261 { | |
1262 /* If reprinting everything is nearly as fast as scrolling, | |
1263 don't bother scrolling. Can happen if lines are short. */ | |
1264 /* Note that if scroll_amount > 0, xp.bufpos - bp.bufpos is an | |
1265 overestimate of cost of reprinting, since xp.bufpos | |
1266 would end up below the bottom of the window. */ | |
769 | 1267 if (scroll_cost (f, ep.vpos + top - scroll_amount, |
277 | 1268 top + height - max (0, scroll_amount), |
1269 scroll_amount) | |
1270 > xp.bufpos - ep.bufpos - 20) | |
1271 /* Return "try normal display with same window-start." | |
1272 Too bad we can't prevent further scroll-thinking. */ | |
1273 return -2; | |
769 | 1274 tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount, |
277 | 1275 top + height - max (0, scroll_amount), |
1276 scroll_amount); | |
1277 if (!tem) stop_vpos = height; | |
1278 } | |
1279 } | |
1280 | |
1281 /* In any case, do not display past bottom of window */ | |
1282 if (stop_vpos >= height) | |
1283 { | |
1284 stop_vpos = height; | |
1285 scroll_amount = 0; | |
1286 } | |
1287 | |
1288 /* Handle case where pos is before w->start -- | |
1289 can happen if part of line had been clipped and is not clipped now */ | |
1290 if (vpos == 0 && pos < marker_position (w->start)) | |
1291 Fset_marker (w->start, make_number (pos), Qnil); | |
1292 | |
1293 /* Redisplay the lines where the text was changed */ | |
1294 last_text_vpos = vpos; | |
1295 tab_offset = pos_tab_offset (w, pos); | |
1296 /* If we are starting display in mid-character, correct tab_offset | |
1297 to account for passing the line that that character really starts in. */ | |
1298 if (val.hpos < lmargin) | |
1299 tab_offset += width; | |
1300 while (vpos < stop_vpos) | |
1301 { | |
1302 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset); | |
1303 tab_offset += width; | |
1304 if (val.vpos) tab_offset = 0; | |
1305 if (pos != val.bufpos) | |
1306 last_text_vpos | |
1307 /* Next line, unless prev line ended in end of buffer with no cr */ | |
1308 = vpos - (val.vpos && FETCH_CHAR (val.bufpos - 1) != '\n'); | |
1309 pos = val.bufpos; | |
1310 } | |
1311 | |
1312 /* There are two cases: | |
1313 1) we have displayed down to the bottom of the window | |
1314 2) we have scrolled lines below stop_vpos by scroll_amount */ | |
1315 | |
1316 if (vpos == height) | |
1317 { | |
1318 /* If last line is continued in middle of character, | |
769 | 1319 include the split character in the text considered on the frame */ |
277 | 1320 if (val.hpos < lmargin) |
1321 val.bufpos++; | |
1322 XFASTINT (w->window_end_vpos) = last_text_vpos; | |
1323 XFASTINT (w->window_end_pos) = Z - val.bufpos; | |
1324 } | |
1325 | |
1326 /* If scrolling made blank lines at window bottom, | |
1327 redisplay to fill those lines */ | |
1328 if (scroll_amount < 0) | |
1329 { | |
1330 /* Don't consider these lines for general-purpose scrolling. | |
1331 That will save time in the scrolling computation. */ | |
769 | 1332 FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos; |
277 | 1333 vpos = xp.vpos; |
1334 pos = xp.bufpos; | |
1335 val.hpos = lmargin; | |
1336 if (pos == ZV) | |
1337 vpos = height + scroll_amount; | |
1338 else if (xp.contin && xp.hpos != lmargin) | |
1339 { | |
1340 val.hpos = xp.prevhpos - width + lmargin; | |
1341 pos--; | |
1342 } | |
1343 | |
1344 blank_end_of_window = 1; | |
1345 tab_offset = pos_tab_offset (w, pos); | |
1346 /* If we are starting display in mid-character, correct tab_offset | |
1347 to account for passing the line that that character starts in. */ | |
1348 if (val.hpos < lmargin) | |
1349 tab_offset += width; | |
1350 | |
1351 while (vpos < height) | |
1352 { | |
1353 val = *display_text_line (w, pos, top + vpos++, val.hpos, tab_offset); | |
1354 tab_offset += width; | |
1355 if (val.vpos) tab_offset = 0; | |
1356 pos = val.bufpos; | |
1357 } | |
1358 | |
1359 /* Here is a case where display_text_line sets cursor_vpos wrong. | |
1360 Make it be fixed up, below. */ | |
1361 if (xp.bufpos == ZV | |
1362 && xp.bufpos == point) | |
1363 cursor_vpos = -1; | |
1364 } | |
1365 | |
769 | 1366 /* If bottom just moved off end of frame, change mode line percentage. */ |
277 | 1367 if (XFASTINT (w->window_end_pos) == 0 |
1368 && Z != val.bufpos) | |
1369 w->update_mode_line = Qt; | |
1370 | |
1371 /* Attempt to adjust end-of-text positions to new bottom line */ | |
1372 if (scroll_amount) | |
1373 { | |
1374 delta = height - xp.vpos; | |
1375 if (delta < 0 | |
1376 || (delta > 0 && xp.bufpos <= ZV) | |
1377 || (delta == 0 && xp.hpos)) | |
1378 { | |
1379 val = *vmotion (Z - XFASTINT (w->window_end_pos), | |
1380 delta, width, hscroll, window); | |
1381 XFASTINT (w->window_end_pos) = Z - val.bufpos; | |
1382 XFASTINT (w->window_end_vpos) += val.vpos; | |
1383 } | |
1384 } | |
1385 | |
1386 w->window_end_valid = Qnil; | |
1387 | |
1388 /* If point was not in a line that was displayed, find it */ | |
1389 if (cursor_vpos < 0) | |
1390 { | |
1391 val = *compute_motion (start, 0, lmargin, point, 10000, 10000, | |
1392 width, hscroll, pos_tab_offset (w, start)); | |
769 | 1393 /* Admit failure if point is off frame now */ |
277 | 1394 if (val.vpos >= height) |
1395 { | |
1396 for (vpos = 0; vpos < height; vpos++) | |
769 | 1397 cancel_line (vpos + top, f); |
277 | 1398 return 0; |
1399 } | |
1400 cursor_vpos = val.vpos + top; | |
1401 cursor_hpos = val.hpos + XFASTINT (w->left); | |
1402 } | |
1403 | |
769 | 1404 FRAME_CURSOR_X (f) = max (0, cursor_hpos); |
1405 FRAME_CURSOR_Y (f) = cursor_vpos; | |
277 | 1406 |
1407 if (debug_end_pos) | |
1408 { | |
1409 val = *compute_motion (start, 0, lmargin, ZV, | |
1410 height, - (1 << (SHORTBITS - 1)), | |
1411 width, hscroll, pos_tab_offset (w, start)); | |
1412 if (val.vpos != XFASTINT (w->window_end_vpos)) | |
1413 abort (); | |
1414 if (XFASTINT (w->window_end_pos) | |
1415 != Z - val.bufpos) | |
1416 abort (); | |
1417 } | |
1418 | |
1419 return 1; | |
1420 } | |
1421 | |
301 | 1422 /* Copy glyphs from the rope FROM to T. |
1423 But don't actually copy the parts that would come in before S. | |
277 | 1424 Value is T, advanced past the copied data. |
1425 | |
1426 Characters in FROM are grouped into units of `sizeof GLYPH' chars; | |
1427 any extra chars at the end of FROM are ignored. */ | |
1428 | |
1429 GLYPH * | |
1430 copy_rope (t, s, from) | |
1431 register GLYPH *t; /* Copy to here. */ | |
1432 register GLYPH *s; /* Starting point. */ | |
1433 Lisp_Object from; /* Data to copy; known to be a string. */ | |
1434 { | |
1435 register int n = XSTRING (from)->size / sizeof (GLYPH); | |
1436 register GLYPH *f = (GLYPH *) XSTRING (from)->data; | |
1437 | |
1438 while (n--) | |
1439 { | |
1440 if (t >= s) *t = *f; | |
1441 ++t; | |
1442 ++f; | |
1443 } | |
1444 return t; | |
1445 } | |
1446 | |
1447 /* Display one line of window w, starting at position START in W's buffer. | |
1448 Display starting at horizontal position HPOS, which is normally zero | |
1449 or negative. A negative value causes output up to hpos = 0 to be discarded. | |
1450 This is done for negative hscroll, or when this is a continuation line | |
1451 and the continuation occurred in the middle of a multi-column character. | |
1452 | |
1453 TABOFFSET is an offset for ostensible hpos, used in tab stop calculations. | |
1454 | |
769 | 1455 Display on position VPOS on the frame. (origin 0). |
277 | 1456 |
1457 Returns a STRUCT POSITION giving character to start next line with | |
1458 and where to display it, including a zero or negative hpos. | |
1459 The vpos field is not really a vpos; it is 1 unless the line is continued */ | |
1460 | |
1461 struct position val_display_text_line; | |
1462 | |
1463 static struct position * | |
1464 display_text_line (w, start, vpos, hpos, taboffset) | |
1465 struct window *w; | |
1466 int start; | |
1467 int vpos; | |
1468 int hpos; | |
1469 int taboffset; | |
1470 { | |
1471 register int pos = start; | |
1472 register int c; | |
1473 register GLYPH *p1; | |
1474 int end; | |
1475 register int pause; | |
1476 register unsigned char *p; | |
1477 GLYPH *endp; | |
1478 register GLYPH *startp; | |
1479 register GLYPH *p1prev; | |
769 | 1480 FRAME_PTR f = XFRAME (w->frame); |
277 | 1481 int tab_width = XINT (current_buffer->tab_width); |
485 | 1482 int ctl_arrow = !NILP (current_buffer->ctl_arrow); |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1483 int width = window_internal_width (w) - 1; |
277 | 1484 struct position val; |
1485 int lastpos; | |
1486 int invis; | |
1487 int hscroll = XINT (w->hscroll); | |
1488 int truncate = hscroll | |
1489 || (truncate_partial_width_windows | |
769 | 1490 && XFASTINT (w->width) < FRAME_WIDTH (f)) |
485 | 1491 || !NILP (current_buffer->truncate_lines); |
277 | 1492 int selective |
1493 = XTYPE (current_buffer->selective_display) == Lisp_Int | |
1494 ? XINT (current_buffer->selective_display) | |
485 | 1495 : !NILP (current_buffer->selective_display) ? -1 : 0; |
277 | 1496 #ifndef old |
485 | 1497 int selective_e = selective && !NILP (current_buffer->selective_display_ellipses); |
277 | 1498 #endif |
769 | 1499 register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f); |
277 | 1500 register struct Lisp_Vector *dp = window_display_table (w); |
1501 int selective_rlen | |
1502 = (selective && dp && XTYPE (DISP_INVIS_ROPE (dp)) == Lisp_String | |
1503 ? XSTRING (DISP_INVIS_ROPE (dp))->size / sizeof (GLYPH) : 0); | |
1504 GLYPH truncator = (dp == 0 || XTYPE (DISP_TRUNC_GLYPH (dp)) != Lisp_Int | |
1505 ? '$' : XINT (DISP_TRUNC_GLYPH (dp))); | |
1506 GLYPH continuer = (dp == 0 || XTYPE (DISP_CONTINUE_GLYPH (dp)) != Lisp_Int | |
1507 ? '\\' : XINT (DISP_CONTINUE_GLYPH (dp))); | |
1508 | |
1509 hpos += XFASTINT (w->left); | |
769 | 1510 get_display_line (f, vpos, XFASTINT (w->left)); |
277 | 1511 if (tab_width <= 0 || tab_width > 20) tab_width = 8; |
1512 | |
1513 if (MINI_WINDOW_P (w) && start == 1 | |
1514 && vpos == XFASTINT (w->top)) | |
1515 { | |
1516 if (minibuf_prompt) | |
1517 hpos = display_string (w, vpos, minibuf_prompt, hpos, | |
1518 (!truncate ? continuer : truncator), | |
1519 -1, -1); | |
1520 minibuf_prompt_width = hpos; | |
1521 } | |
1522 | |
1523 desired_glyphs->bufp[vpos] = pos; | |
1524 p1 = desired_glyphs->glyphs[vpos] + hpos; | |
1525 end = ZV; | |
1526 startp = desired_glyphs->glyphs[vpos] + XFASTINT (w->left); | |
1527 endp = startp + width; | |
1528 | |
1529 /* Loop generating characters. | |
1530 Stop at end of buffer, before newline, | |
1531 or if reach or pass continuation column. */ | |
1532 | |
1533 pause = pos; | |
1534 while (p1 < endp) | |
1535 { | |
1536 p1prev = p1; | |
1537 if (pos == pause) | |
1538 { | |
1539 if (pos == end) | |
1540 break; | |
1541 if (pos == point && cursor_vpos < 0) | |
1542 { | |
1543 cursor_vpos = vpos; | |
1544 cursor_hpos = p1 - startp; | |
1545 } | |
1546 | |
1547 pause = end; | |
1548 if (pos < point && point < pause) | |
1549 pause = point; | |
1550 if (pos < GPT && GPT < pause) | |
1551 pause = GPT; | |
1552 | |
1553 p = &FETCH_CHAR (pos); | |
1554 } | |
1555 c = *p++; | |
1556 if (c >= 040 && c < 0177 | |
1557 && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String)) | |
1558 { | |
1559 if (p1 >= startp) | |
1560 *p1 = c; | |
1561 p1++; | |
1562 } | |
1563 else if (c == '\n') | |
1564 { | |
1565 invis = 0; | |
1566 while (pos < end | |
1567 && selective > 0 | |
1568 && position_indentation (pos + 1) >= selective) | |
1569 { | |
1570 invis = 1; | |
1571 pos = find_next_newline (pos + 1, 1); | |
1572 if (FETCH_CHAR (pos - 1) == '\n') | |
1573 pos--; | |
1574 } | |
1575 if (invis && selective_rlen > 0 && p1 >= startp) | |
1576 { | |
1577 p1 += selective_rlen; | |
1578 if (p1 - startp > width) | |
1579 p1 = endp; | |
1580 bcopy (XSTRING (DISP_INVIS_ROPE (dp))->data, p1prev, | |
1581 (p1 - p1prev) * sizeof (GLYPH)); | |
1582 } | |
1583 break; | |
1584 } | |
1585 else if (c == '\t') | |
1586 { | |
1587 do | |
1588 { | |
1589 if (p1 >= startp && p1 < endp) | |
1590 *p1 = SPACEGLYPH; | |
1591 p1++; | |
1592 } | |
1593 while ((p1 - startp + taboffset + hscroll - (hscroll > 0)) | |
1594 % tab_width); | |
1595 } | |
368 | 1596 else if (c == Ctl ('M') && selective == -1) |
277 | 1597 { |
1598 pos = find_next_newline (pos, 1); | |
1599 if (FETCH_CHAR (pos - 1) == '\n') | |
1600 pos--; | |
1601 if (selective_rlen > 0) | |
1602 { | |
1603 p1 += selective_rlen; | |
1604 if (p1 - startp > width) | |
1605 p1 = endp; | |
1606 bcopy (XSTRING (DISP_INVIS_ROPE (dp))->data, p1prev, | |
1607 (p1 - p1prev) * sizeof (GLYPH)); | |
1608 } | |
1609 break; | |
1610 } | |
1611 else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String) | |
1612 { | |
1613 p1 = copy_rope (p1, startp, DISP_CHAR_ROPE (dp, c)); | |
1614 } | |
1615 else if (c < 0200 && ctl_arrow) | |
1616 { | |
1617 if (p1 >= startp) | |
1618 *p1 = (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int | |
1619 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'); | |
1620 p1++; | |
368 | 1621 if (p1 >= startp && p1 < endp) |
277 | 1622 *p1 = c ^ 0100; |
1623 p1++; | |
1624 } | |
1625 else | |
1626 { | |
1627 if (p1 >= startp) | |
1628 *p1 = (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int | |
1629 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'); | |
1630 p1++; | |
368 | 1631 if (p1 >= startp && p1 < endp) |
277 | 1632 *p1 = (c >> 6) + '0'; |
1633 p1++; | |
368 | 1634 if (p1 >= startp && p1 < endp) |
277 | 1635 *p1 = (7 & (c >> 3)) + '0'; |
1636 p1++; | |
368 | 1637 if (p1 >= startp && p1 < endp) |
277 | 1638 *p1 = (7 & c) + '0'; |
1639 p1++; | |
1640 } | |
1641 pos++; | |
1642 } | |
1643 | |
1644 val.hpos = - XINT (w->hscroll); | |
1645 if (val.hpos) | |
1646 val.hpos++; | |
1647 | |
1648 val.vpos = 1; | |
1649 | |
1650 lastpos = pos; | |
1651 | |
1652 /* Handle continuation in middle of a character */ | |
1653 /* by backing up over it */ | |
1654 if (p1 > endp) | |
1655 { | |
1656 /* Start the next line with that same character */ | |
1657 pos--; | |
1658 /* but at a negative hpos, to skip the columns output on this line. */ | |
1659 val.hpos += p1prev - endp; | |
1660 /* Keep in this line everything up to the continuation column. */ | |
1661 p1 = endp; | |
1662 } | |
1663 | |
1664 /* Finish deciding which character to start the next line on, | |
1665 and what hpos to start it at. | |
1666 Also set `lastpos' to the last position which counts as "on this line" | |
1667 for cursor-positioning. */ | |
1668 | |
1669 if (pos < ZV) | |
1670 { | |
1671 if (FETCH_CHAR (pos) == '\n') | |
1672 /* If stopped due to a newline, start next line after it */ | |
1673 pos++; | |
1674 else | |
1675 /* Stopped due to right margin of window */ | |
1676 { | |
1677 if (truncate) | |
1678 { | |
1679 *p1++ = truncator; | |
1680 /* Truncating => start next line after next newline, | |
1681 and point is on this line if it is before the newline, | |
1682 and skip none of first char of next line */ | |
1683 pos = find_next_newline (pos, 1); | |
1684 val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0; | |
1685 | |
1686 lastpos = pos - (FETCH_CHAR (pos - 1) == '\n'); | |
1687 } | |
1688 else | |
1689 { | |
1690 *p1++ = continuer; | |
1691 val.vpos = 0; | |
1692 lastpos--; | |
1693 } | |
1694 } | |
1695 } | |
1696 | |
1697 /* If point is at eol or in invisible text at eol, | |
769 | 1698 record its frame location now. */ |
277 | 1699 |
1700 if (start <= point && point <= lastpos && cursor_vpos < 0) | |
1701 { | |
1702 cursor_vpos = vpos; | |
1703 cursor_hpos = p1 - startp; | |
1704 } | |
1705 | |
1706 if (cursor_vpos == vpos) | |
1707 { | |
1708 if (cursor_hpos < 0) cursor_hpos = 0; | |
1709 if (cursor_hpos > width) cursor_hpos = width; | |
1710 cursor_hpos += XFASTINT (w->left); | |
769 | 1711 if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) |
277 | 1712 { |
769 | 1713 FRAME_CURSOR_Y (f) = cursor_vpos; |
1714 FRAME_CURSOR_X (f) = cursor_hpos; | |
277 | 1715 |
1716 if (w == XWINDOW (selected_window)) | |
1717 { | |
1718 /* Line is not continued and did not start | |
1719 in middle of character */ | |
1720 if ((hpos - XFASTINT (w->left) | |
1721 == (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0)) | |
1722 && val.vpos) | |
1723 { | |
1724 this_line_bufpos = start; | |
1725 this_line_buffer = current_buffer; | |
1726 this_line_vpos = cursor_vpos; | |
1727 this_line_start_hpos = hpos; | |
1728 this_line_endpos = Z - lastpos; | |
1729 } | |
1730 else | |
1731 this_line_bufpos = 0; | |
1732 } | |
1733 } | |
1734 } | |
1735 | |
1736 /* If hscroll and line not empty, insert truncation-at-left marker */ | |
1737 if (hscroll && lastpos != start) | |
1738 { | |
1739 *startp = truncator; | |
1740 if (p1 <= startp) | |
1741 p1 = startp + 1; | |
1742 } | |
1743 | |
769 | 1744 if (XFASTINT (w->width) + XFASTINT (w->left) != FRAME_WIDTH (f)) |
277 | 1745 { |
1746 endp++; | |
1747 if (p1 < startp) p1 = startp; | |
1748 while (p1 < endp) *p1++ = SPACEGLYPH; | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1749 |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1750 /* Don't draw vertical bars if we're using scrollbars. They're |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1751 covered up by the scrollbars, and it's distracting to see |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1752 them when the scrollbar windows are flickering around to be |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1753 reconfigured. */ |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1754 *p1++ = (FRAME_HAS_VERTICAL_SCROLLBARS (f) |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1755 ? ' ' : '|'); |
277 | 1756 } |
1757 desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos], | |
1758 p1 - desired_glyphs->glyphs[vpos]); | |
1759 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0; | |
1760 | |
1761 /* If the start of this line is the overlay arrow-position, | |
1762 then put the arrow string into the display-line. */ | |
1763 | |
1764 if (XTYPE (Voverlay_arrow_position) == Lisp_Marker | |
1765 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer | |
1766 && start == marker_position (Voverlay_arrow_position) | |
1767 && XTYPE (Voverlay_arrow_string) == Lisp_String | |
1768 && ! overlay_arrow_seen) | |
1769 { | |
1770 unsigned char *p = XSTRING (Voverlay_arrow_string)->data; | |
1771 int i; | |
1772 int len = XSTRING (Voverlay_arrow_string)->size; | |
1773 | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1774 if (len > width) |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
1775 len = width; |
277 | 1776 for (i = 0; i < len; i++) |
1777 startp[i] = p[i]; | |
1778 if (desired_glyphs->used[vpos] < | |
1779 (len + startp - desired_glyphs->glyphs[vpos])) | |
1780 desired_glyphs->used[vpos] = len + startp - desired_glyphs->glyphs[vpos]; | |
1781 | |
1782 overlay_arrow_seen = 1; | |
1783 } | |
1784 | |
1785 val.bufpos = pos; | |
1786 val_display_text_line = val; | |
1787 return &val_display_text_line; | |
1788 } | |
1789 | |
1790 /* Display the mode line for window w */ | |
1791 | |
1792 static void | |
1793 display_mode_line (w) | |
1794 struct window *w; | |
1795 { | |
1796 register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1; | |
1797 register int left = XFASTINT (w->left); | |
1798 register int right = XFASTINT (w->width) + left; | |
769 | 1799 register FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); |
277 | 1800 |
769 | 1801 get_display_line (f, vpos, left); |
277 | 1802 display_mode_element (w, vpos, left, 0, right, right, |
1803 current_buffer->mode_line_format); | |
769 | 1804 FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0; |
277 | 1805 |
1806 /* Make the mode line inverse video if the entire line | |
1807 is made of mode lines. | |
1808 I.e. if this window is full width, | |
1809 or if it is the child of a full width window | |
1810 (which implies that that window is split side-by-side | |
1811 and the rest of this line is mode lines of the sibling windows). */ | |
769 | 1812 if (XFASTINT (w->width) == FRAME_WIDTH (f) |
1813 || XFASTINT (XWINDOW (w->parent)->width) == FRAME_WIDTH (f)) | |
1814 FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video; | |
277 | 1815 |
1816 #ifdef HAVE_X_WINDOWS | |
1817 /* I'm trying this out because I saw Unimpress use it, but it's | |
1124
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1818 possible that this may mess adversely with some window managers. -jla |
277 | 1819 |
1124
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1820 Wouldn't it be nice to use something like mode-line-format to |
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1821 describe frame titles? -JimB */ |
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1822 |
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1823 /* Change the title of the frame to the name of the buffer displayed |
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1824 in the currently selected window. Don't do this for minibuffer frames, |
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1825 and don't do it when there's only one non-minibuffer frame. */ |
973
52267046b144
* xdisp.c (FRAME_IS_TERMCAP, FRAME_IS_X, FRAME_HAS_MINIBUF):
Jim Blandy <jimb@redhat.com>
parents:
831
diff
changeset
|
1826 if (FRAME_X_P (f) |
769 | 1827 && ! FRAME_MINIBUF_ONLY_P (f) |
831 | 1828 && w == XWINDOW (f->selected_window)) |
1124
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1829 x_implicitly_set_name (f, (EQ (Fnext_frame (WINDOW_FRAME (w), Qnil), |
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1830 WINDOW_FRAME (w)) |
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1831 ? Qnil |
453c24f2bdaa
* xdisp.c (display_mode_line): If the only other frames are
Jim Blandy <jimb@redhat.com>
parents:
1017
diff
changeset
|
1832 : XBUFFER (w->buffer)->name), |
1017
d42877206c0a
* xdisp.c (display_mode_line): Use x_implicitly_set_name here.
Jim Blandy <jimb@redhat.com>
parents:
973
diff
changeset
|
1833 Qnil); |
277 | 1834 #endif |
1835 } | |
1836 | |
1837 /* Contribute ELT to the mode line for window W. | |
1838 How it translates into text depends on its data type. | |
1839 | |
1840 VPOS is the position of the mode line being displayed. | |
1841 | |
769 | 1842 HPOS is the position (absolute on frame) where this element's text |
277 | 1843 should start. The output is truncated automatically at the right |
1844 edge of window W. | |
1845 | |
1846 DEPTH is the depth in recursion. It is used to prevent | |
1847 infinite recursion here. | |
1848 | |
1849 MINENDCOL is the hpos before which the element may not end. | |
1850 The element is padded at the right with spaces if nec | |
1851 to reach this column. | |
1852 | |
1853 MAXENDCOL is the hpos past which this element may not extend. | |
1854 If MINENDCOL is > MAXENDCOL, MINENDCOL takes priority. | |
1855 (This is necessary to make nested padding and truncation work.) | |
1856 | |
1857 Returns the hpos of the end of the text generated by ELT. | |
1858 The next element will receive that value as its HPOS arg, | |
1859 so as to concatenate the elements. */ | |
1860 | |
1861 static int | |
1862 display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt) | |
1863 struct window *w; | |
1864 register int vpos, hpos; | |
1865 int depth; | |
1866 int minendcol; | |
1867 register int maxendcol; | |
1868 register Lisp_Object elt; | |
1869 { | |
1870 tail_recurse: | |
1871 if (depth > 10) | |
1872 goto invalid; | |
1873 | |
1874 depth++; | |
1875 | |
1876 #ifdef SWITCH_ENUM_BUG | |
1877 switch ((int) XTYPE (elt)) | |
1878 #else | |
1879 switch (XTYPE (elt)) | |
1880 #endif | |
1881 { | |
1882 case Lisp_String: | |
1883 { | |
1884 /* A string: output it and check for %-constructs within it. */ | |
1885 register unsigned char c; | |
1886 register unsigned char *this = XSTRING (elt)->data; | |
1887 | |
1888 while (hpos < maxendcol && *this) | |
1889 { | |
1890 unsigned char *last = this; | |
1891 while ((c = *this++) != '\0' && c != '%') | |
1892 ; | |
1893 if (this - 1 != last) | |
1894 { | |
1895 register int lim = --this - last + hpos; | |
1896 hpos = display_string (w, vpos, last, hpos, 0, hpos, | |
1897 min (lim, maxendcol)); | |
1898 } | |
1899 else /* c == '%' */ | |
1900 { | |
1901 register int spec_width = 0; | |
1902 | |
1903 /* We can't allow -ve args due to the "%-" construct */ | |
1904 /* Argument specifies minwidth but not maxwidth | |
1905 (maxwidth can be specified by | |
1906 (<negative-number> . <stuff>) mode-line elements) */ | |
1907 | |
1908 while ((c = *this++) >= '0' && c <= '9') | |
1909 { | |
1910 spec_width = spec_width * 10 + (c - '0'); | |
1911 } | |
1912 | |
1913 spec_width += hpos; | |
1914 if (spec_width > maxendcol) | |
1915 spec_width = maxendcol; | |
1916 | |
1917 if (c == 'M') | |
1918 hpos = display_mode_element (w, vpos, hpos, depth, | |
1919 spec_width, maxendcol, | |
1920 Vglobal_mode_string); | |
1921 else if (c != 0) | |
1922 hpos = display_string (w, vpos, | |
1923 decode_mode_spec (w, c, | |
1924 maxendcol - hpos), | |
1925 hpos, 0, spec_width, maxendcol); | |
1926 } | |
1927 } | |
1928 } | |
1929 break; | |
1930 | |
1931 case Lisp_Symbol: | |
1932 /* A symbol: process the value of the symbol recursively | |
1933 as if it appeared here directly. Avoid error if symbol void. | |
1934 Special case: if value of symbol is a string, output the string | |
1935 literally. */ | |
1936 { | |
1937 register Lisp_Object tem; | |
1938 tem = Fboundp (elt); | |
485 | 1939 if (!NILP (tem)) |
277 | 1940 { |
1941 tem = Fsymbol_value (elt); | |
1942 /* If value is a string, output that string literally: | |
1943 don't check for % within it. */ | |
1944 if (XTYPE (tem) == Lisp_String) | |
1945 hpos = display_string (w, vpos, XSTRING (tem)->data, | |
1946 hpos, 0, minendcol, maxendcol); | |
1947 /* Give up right away for nil or t. */ | |
1948 else if (!EQ (tem, elt)) | |
1949 { elt = tem; goto tail_recurse; } | |
1950 } | |
1951 } | |
1952 break; | |
1953 | |
1954 case Lisp_Cons: | |
1955 { | |
1956 register Lisp_Object car, tem; | |
1957 | |
1958 /* A cons cell: three distinct cases. | |
1959 If first element is a string or a cons, process all the elements | |
1960 and effectively concatenate them. | |
1961 If first element is a negative number, truncate displaying cdr to | |
1962 at most that many characters. If positive, pad (with spaces) | |
1963 to at least that many characters. | |
1964 If first element is a symbol, process the cadr or caddr recursively | |
1965 according to whether the symbol's value is non-nil or nil. */ | |
1966 car = XCONS (elt)->car; | |
1967 if (XTYPE (car) == Lisp_Symbol) | |
1968 { | |
1969 tem = Fboundp (car); | |
1970 elt = XCONS (elt)->cdr; | |
1971 if (XTYPE (elt) != Lisp_Cons) | |
1972 goto invalid; | |
1973 /* elt is now the cdr, and we know it is a cons cell. | |
1974 Use its car if CAR has a non-nil value. */ | |
485 | 1975 if (!NILP (tem)) |
277 | 1976 { |
1977 tem = Fsymbol_value (car); | |
485 | 1978 if (!NILP (tem)) |
277 | 1979 { elt = XCONS (elt)->car; goto tail_recurse; } |
1980 } | |
1981 /* Symbol's value is nil (or symbol is unbound) | |
1982 Get the cddr of the original list | |
1983 and if possible find the caddr and use that. */ | |
1984 elt = XCONS (elt)->cdr; | |
485 | 1985 if (NILP (elt)) |
277 | 1986 break; |
1987 else if (XTYPE (elt) != Lisp_Cons) | |
1988 goto invalid; | |
1989 elt = XCONS (elt)->car; | |
1990 goto tail_recurse; | |
1991 } | |
1992 else if (XTYPE (car) == Lisp_Int) | |
1993 { | |
1994 register int lim = XINT (car); | |
1995 elt = XCONS (elt)->cdr; | |
1996 if (lim < 0) | |
1997 /* Negative int means reduce maximum width. | |
1998 DO NOT change MINENDCOL here! | |
1999 (20 -10 . foo) should truncate foo to 10 col | |
2000 and then pad to 20. */ | |
2001 maxendcol = min (maxendcol, hpos - lim); | |
2002 else if (lim > 0) | |
2003 { | |
2004 /* Padding specified. Don't let it be more than | |
2005 current maximum. */ | |
2006 lim += hpos; | |
2007 if (lim > maxendcol) | |
2008 lim = maxendcol; | |
2009 /* If that's more padding than already wanted, queue it. | |
2010 But don't reduce padding already specified even if | |
2011 that is beyond the current truncation point. */ | |
2012 if (lim > minendcol) | |
2013 minendcol = lim; | |
2014 } | |
2015 goto tail_recurse; | |
2016 } | |
2017 else if (XTYPE (car) == Lisp_String || XTYPE (car) == Lisp_Cons) | |
2018 { | |
2019 register int limit = 50; | |
2020 /* LIMIT is to protect against circular lists. */ | |
2021 while (XTYPE (elt) == Lisp_Cons && --limit > 0 | |
2022 && hpos < maxendcol) | |
2023 { | |
2024 hpos = display_mode_element (w, vpos, hpos, depth, | |
2025 hpos, maxendcol, | |
2026 XCONS (elt)->car); | |
2027 elt = XCONS (elt)->cdr; | |
2028 } | |
2029 } | |
2030 } | |
2031 break; | |
2032 | |
2033 default: | |
2034 invalid: | |
2035 return (display_string (w, vpos, "*invalid*", hpos, 0, | |
2036 minendcol, maxendcol)); | |
2037 } | |
2038 | |
2039 end: | |
2040 if (minendcol > hpos) | |
2041 hpos = display_string (w, vpos, "", hpos, 0, minendcol, -1); | |
2042 return hpos; | |
2043 } | |
2044 | |
2045 /* Return a string for the output of a mode line %-spec for window W, | |
2046 generated by character C and width MAXWIDTH. */ | |
2047 | |
1017
d42877206c0a
* xdisp.c (display_mode_line): Use x_implicitly_set_name here.
Jim Blandy <jimb@redhat.com>
parents:
973
diff
changeset
|
2048 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------"; |
d42877206c0a
* xdisp.c (display_mode_line): Use x_implicitly_set_name here.
Jim Blandy <jimb@redhat.com>
parents:
973
diff
changeset
|
2049 |
277 | 2050 static char * |
2051 decode_mode_spec (w, c, maxwidth) | |
2052 struct window *w; | |
2053 register char c; | |
2054 register int maxwidth; | |
2055 { | |
2056 Lisp_Object obj = Qnil; | |
769 | 2057 FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); |
2058 char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents; | |
277 | 2059 |
769 | 2060 if (maxwidth > FRAME_WIDTH (f)) |
2061 maxwidth = FRAME_WIDTH (f); | |
277 | 2062 |
2063 switch (c) | |
2064 { | |
2065 case 'b': | |
2066 obj = current_buffer->name; | |
2067 #if 0 | |
2068 if (maxwidth >= 3 && XSTRING (obj)->size > maxwidth) | |
2069 { | |
2070 bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1); | |
2071 decode_mode_spec_buf[maxwidth - 1] = '\\'; | |
2072 decode_mode_spec_buf[maxwidth] = '\0'; | |
2073 return decode_mode_spec_buf; | |
2074 } | |
2075 #endif | |
2076 break; | |
2077 | |
2078 case 'f': | |
2079 obj = current_buffer->filename; | |
2080 #if 0 | |
485 | 2081 if (NILP (obj)) |
277 | 2082 return "[none]"; |
2083 else if (XTYPE (obj) == Lisp_String && XSTRING (obj)->size > maxwidth) | |
2084 { | |
2085 bcopy ("...", decode_mode_spec_buf, 3); | |
2086 bcopy (XSTRING (obj)->data + XSTRING (obj)->size - maxwidth + 3, | |
2087 decode_mode_spec_buf + 3, maxwidth - 3); | |
2088 return decode_mode_spec_buf; | |
2089 } | |
2090 #endif | |
2091 break; | |
2092 | |
2093 case 'm': | |
2094 obj = current_buffer->mode_name; | |
2095 break; | |
2096 | |
2097 case 'n': | |
2098 if (BEGV > BEG || ZV < Z) | |
2099 return " Narrow"; | |
2100 break; | |
2101 | |
2102 case '*': | |
485 | 2103 if (!NILP (current_buffer->read_only)) |
277 | 2104 return "%"; |
2105 if (MODIFF > current_buffer->save_modified) | |
2106 return "*"; | |
2107 return "-"; | |
2108 | |
2109 case 's': | |
2110 /* status of process */ | |
2111 obj = Fget_buffer_process (Fcurrent_buffer ()); | |
485 | 2112 if (NILP (obj)) |
277 | 2113 return "no process"; |
2114 obj = Fsymbol_name (Fprocess_status (obj)); | |
2115 break; | |
2116 | |
2117 case 'p': | |
2118 { | |
2119 int pos = marker_position (w->start); | |
2120 int total = ZV - BEGV; | |
2121 | |
2122 if (XFASTINT (w->window_end_pos) <= Z - ZV) | |
2123 { | |
2124 if (pos <= BEGV) | |
2125 return "All"; | |
2126 else | |
2127 return "Bottom"; | |
2128 } | |
2129 else if (pos <= BEGV) | |
2130 return "Top"; | |
2131 else | |
2132 { | |
2133 total = ((pos - BEGV) * 100 + total - 1) / total; | |
2134 /* We can't normally display a 3-digit number, | |
2135 so get us a 2-digit number that is close. */ | |
2136 if (total == 100) | |
2137 total = 99; | |
2138 sprintf (decode_mode_spec_buf, "%2d%%", total); | |
2139 return decode_mode_spec_buf; | |
2140 } | |
2141 } | |
2142 | |
2143 case '%': | |
2144 return "%"; | |
2145 | |
2146 case '[': | |
2147 { | |
2148 int i; | |
2149 char *p; | |
2150 | |
2151 if (command_loop_level > 5) | |
2152 return "[[[... "; | |
2153 p = decode_mode_spec_buf; | |
2154 for (i = 0; i < command_loop_level; i++) | |
2155 *p++ = '['; | |
2156 *p = 0; | |
2157 return decode_mode_spec_buf; | |
2158 } | |
2159 | |
2160 case ']': | |
2161 { | |
2162 int i; | |
2163 char *p; | |
2164 | |
2165 if (command_loop_level > 5) | |
2166 return " ...]]]"; | |
2167 p = decode_mode_spec_buf; | |
2168 for (i = 0; i < command_loop_level; i++) | |
2169 *p++ = ']'; | |
2170 *p = 0; | |
2171 return decode_mode_spec_buf; | |
2172 } | |
2173 | |
2174 case '-': | |
2175 { | |
2176 register char *p; | |
2177 register int i; | |
2178 | |
2179 if (maxwidth < sizeof (lots_of_dashes)) | |
2180 return lots_of_dashes; | |
2181 else | |
2182 { | |
2183 for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--) | |
2184 *p++ = '-'; | |
2185 *p = '\0'; | |
2186 } | |
2187 return decode_mode_spec_buf; | |
2188 } | |
2189 } | |
2190 | |
2191 if (XTYPE (obj) == Lisp_String) | |
2192 return (char *) XSTRING (obj)->data; | |
2193 else | |
2194 return ""; | |
2195 } | |
2196 | |
2197 /* Display STRING on one line of window W, starting at HPOS. | |
2198 Display at position VPOS. Caller should have done get_display_line. | |
1017
d42877206c0a
* xdisp.c (display_mode_line): Use x_implicitly_set_name here.
Jim Blandy <jimb@redhat.com>
parents:
973
diff
changeset
|
2199 If VPOS == -1, display it as the current frame's title. |
277 | 2200 |
2201 TRUNCATE is GLYPH to display at end if truncated. Zero for none. | |
2202 | |
2203 MINCOL is the first column ok to end at. (Pad with spaces to this col.) | |
2204 MAXCOL is the last column ok to end at. Truncate here. | |
2205 -1 for MINCOL or MAXCOL means no explicit minimum or maximum. | |
769 | 2206 Both count from the left edge of the frame, as does HPOS. |
277 | 2207 The right edge of W is an implicit maximum. |
2208 If TRUNCATE is nonzero, the implicit maximum is one column before the edge. | |
2209 | |
2210 Returns ending hpos */ | |
2211 | |
2212 static int | |
2213 display_string (w, vpos, string, hpos, truncate, mincol, maxcol) | |
2214 struct window *w; | |
2215 unsigned char *string; | |
2216 int vpos, hpos; | |
2217 GLYPH truncate; | |
2218 int mincol, maxcol; | |
2219 { | |
2220 register int c; | |
2221 register GLYPH *p1; | |
2222 int hscroll = XINT (w->hscroll); | |
1600
775c2ab9800f
* xdisp.c (display_string): Use w's buffer's value of
Jim Blandy <jimb@redhat.com>
parents:
1527
diff
changeset
|
2223 int tab_width = XINT (XBUFFER (w->buffer)->tab_width); |
277 | 2224 register GLYPH *start; |
2225 register GLYPH *end; | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2226 FRAME_PTR f = XFRAME (WINDOW_FRAME (w)); |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2227 struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f); |
277 | 2228 GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos; |
2229 int window_width = XFASTINT (w->width); | |
2230 | |
2231 /* Use the standard display table, not the window's display table. | |
2232 We don't want the mode line in rot13. */ | |
2233 register struct Lisp_Vector *dp = 0; | |
2234 | |
2235 if (XTYPE (Vstandard_display_table) == Lisp_Vector | |
2236 && XVECTOR (Vstandard_display_table)->size == DISP_TABLE_SIZE) | |
2237 dp = XVECTOR (Vstandard_display_table); | |
2238 | |
2239 if (tab_width <= 0 || tab_width > 20) tab_width = 8; | |
2240 | |
2241 p1 = p1start; | |
2242 start = desired_glyphs->glyphs[vpos] + XFASTINT (w->left); | |
2243 end = start + window_width - (truncate != 0); | |
2244 | |
1785
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2245 if ((window_width + XFASTINT (w->left)) != FRAME_WIDTH (f)) |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2246 { |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2247 if (FRAME_HAS_VERTICAL_SCROLLBARS (f)) |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2248 { |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2249 int i; |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2250 |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2251 for (i = 0; i < VERTICAL_SCROLLBAR_WIDTH; i++) |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2252 *end-- = ' '; |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2253 } |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2254 else |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2255 *end-- = '|'; |
19755499df90
* window.c (window_internal_width): New function, which accounts
Jim Blandy <jimb@redhat.com>
parents:
1718
diff
changeset
|
2256 } |
277 | 2257 |
2258 if (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol) | |
2259 end = desired_glyphs->glyphs[vpos] + maxcol; | |
2260 if (maxcol >= 0 && mincol > maxcol) | |
2261 mincol = maxcol; | |
2262 | |
2263 while (p1 < end) | |
2264 { | |
2265 c = *string++; | |
2266 if (!c) break; | |
2267 if (c >= 040 && c < 0177 | |
2268 && (dp == 0 || XTYPE (DISP_CHAR_ROPE (dp, c)) != Lisp_String)) | |
2269 { | |
2270 if (p1 >= start) | |
2271 *p1 = c; | |
2272 p1++; | |
2273 } | |
2274 else if (c == '\t') | |
2275 { | |
2276 do | |
2277 { | |
2278 if (p1 >= start && p1 < end) | |
2279 *p1 = SPACEGLYPH; | |
2280 p1++; | |
2281 } | |
2282 while ((p1 - start + hscroll - (hscroll > 0)) % tab_width); | |
2283 } | |
2284 else if (dp != 0 && XTYPE (DISP_CHAR_ROPE (dp, c)) == Lisp_String) | |
2285 p1 = copy_rope (p1, start, DISP_CHAR_ROPE (dp, c)); | |
1527
00109911b040
* xdisp.c (redisplay): Use ! EQ to compare the old and new arrow
Jim Blandy <jimb@redhat.com>
parents:
1446
diff
changeset
|
2286 else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow)) |
277 | 2287 { |
2288 if (p1 >= start) | |
2289 *p1 = (dp && XTYPE (DISP_CTRL_GLYPH (dp)) == Lisp_Int | |
2290 ? XINT (DISP_CTRL_GLYPH (dp)) : '^'); | |
2291 p1++; | |
368 | 2292 if (p1 >= start && p1 < end) |
277 | 2293 *p1 = c ^ 0100; |
2294 p1++; | |
2295 } | |
2296 else | |
2297 { | |
2298 if (p1 >= start) | |
2299 *p1 = (dp && XTYPE (DISP_ESCAPE_GLYPH (dp)) == Lisp_Int | |
2300 ? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'); | |
2301 p1++; | |
368 | 2302 if (p1 >= start && p1 < end) |
277 | 2303 *p1 = (c >> 6) + '0'; |
2304 p1++; | |
368 | 2305 if (p1 >= start && p1 < end) |
277 | 2306 *p1 = (7 & (c >> 3)) + '0'; |
2307 p1++; | |
368 | 2308 if (p1 >= start && p1 < end) |
277 | 2309 *p1 = (7 & c) + '0'; |
2310 p1++; | |
2311 } | |
2312 } | |
2313 | |
2314 if (c) | |
2315 { | |
2316 p1 = end; | |
2317 if (truncate) *p1++ = truncate; | |
2318 } | |
2319 else if (mincol >= 0) | |
2320 { | |
2321 end = desired_glyphs->glyphs[vpos] + mincol; | |
2322 while (p1 < end) | |
2323 *p1++ = SPACEGLYPH; | |
2324 } | |
2325 | |
2326 { | |
2327 register int len = p1 - desired_glyphs->glyphs[vpos]; | |
2328 | |
2329 if (len > desired_glyphs->used[vpos]) | |
2330 desired_glyphs->used[vpos] = len; | |
2331 desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0; | |
2332 | |
2333 return len; | |
2334 } | |
2335 } | |
2336 | |
2337 void | |
2338 syms_of_xdisp () | |
2339 { | |
2340 staticpro (&last_arrow_position); | |
2341 staticpro (&last_arrow_string); | |
2342 last_arrow_position = Qnil; | |
2343 last_arrow_string = Qnil; | |
2344 | |
2345 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string, | |
782
a6d00bdb2b60
*** empty log message ***
Richard M. Stallman <rms@gnu.org>
parents:
781
diff
changeset
|
2346 "String (or mode line construct) included (normally) in `mode-line-format'."); |
277 | 2347 Vglobal_mode_string = Qnil; |
2348 | |
2349 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position, | |
2350 "Marker for where to display an arrow on top of the buffer text.\n\ | |
2351 This must be the beginning of a line in order to work.\n\ | |
2352 See also `overlay-arrow-string'."); | |
2353 Voverlay_arrow_position = Qnil; | |
2354 | |
2355 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string, | |
2356 "String to display as an arrow. See also `overlay-arrow-position'."); | |
2357 Voverlay_arrow_string = Qnil; | |
2358 | |
2359 DEFVAR_INT ("scroll-step", &scroll_step, | |
2360 "*The number of lines to try scrolling a window by when point moves out.\n\ | |
769 | 2361 If that fails to bring point back on frame, point is centered instead.\n\ |
2362 If this is zero, point is always centered after it moves off frame."); | |
277 | 2363 |
2364 DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask"); | |
2365 | |
2366 DEFVAR_BOOL ("truncate-partial-width-windows", | |
2367 &truncate_partial_width_windows, | |
769 | 2368 "*Non-nil means truncate lines in all windows less than full frame wide."); |
277 | 2369 truncate_partial_width_windows = 1; |
2370 | |
2371 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video, | |
2372 "*Non-nil means use inverse video for the mode line."); | |
2373 mode_line_inverse_video = 1; | |
2374 } | |
2375 | |
2376 /* initialize the window system */ | |
2377 init_xdisp () | |
2378 { | |
2379 Lisp_Object root_window; | |
2380 #ifndef COMPILER_REGISTER_BUG | |
2381 register | |
2382 #endif /* COMPILER_REGISTER_BUG */ | |
2383 struct window *mini_w; | |
2384 | |
2385 this_line_bufpos = 0; | |
2386 | |
2387 mini_w = XWINDOW (minibuf_window); | |
1017
d42877206c0a
* xdisp.c (display_mode_line): Use x_implicitly_set_name here.
Jim Blandy <jimb@redhat.com>
parents:
973
diff
changeset
|
2388 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w))); |
277 | 2389 |
2390 echo_area_glyphs = 0; | |
2391 previous_echo_glyphs = 0; | |
2392 | |
2393 if (!noninteractive) | |
2394 { | |
769 | 2395 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window))); |
277 | 2396 XFASTINT (XWINDOW (root_window)->top) = 0; |
769 | 2397 set_window_height (root_window, FRAME_HEIGHT (f) - 1, 0); |
2398 XFASTINT (mini_w->top) = FRAME_HEIGHT (f) - 1; | |
277 | 2399 set_window_height (minibuf_window, 1, 0); |
2400 | |
769 | 2401 XFASTINT (XWINDOW (root_window)->width) = FRAME_WIDTH (f); |
2402 XFASTINT (mini_w->width) = FRAME_WIDTH (f); | |
277 | 2403 } |
2404 } |