Mercurial > hg > xemacs-beta
annotate src/redisplay.c @ 4967:0d4c9d0f6a8d
rewrite dynarr code
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-03 Ben Wing <ben@xemacs.org>
* device-x.c (x_get_resource_prefix):
* device-x.c (Fx_get_resource):
* device-x.c (Fx_get_resource_prefix):
* device-x.c (Fx_put_resource):
* dialog-msw.c:
* dialog-msw.c (handle_question_dialog_box):
* dired-msw.c (mswindows_sort_files):
* dired-msw.c (mswindows_get_files):
* extents.c (extent_fragment_sort_by_priority):
* extents.c (Fset_extent_parent):
* file-coding.c (coding_reader):
* file-coding.c (coding_writer):
* file-coding.c (gzip_convert):
* frame.c (generate_title_string):
* gutter.c (calculate_gutter_size_from_display_lines):
* indent.c (vmotion_1):
* lread.c (read_bit_vector):
* mule-coding.c (iso2022_decode):
* rangetab.c:
* rangetab.c (Fcopy_range_table):
* rangetab.c (Fget_range_table):
* rangetab.c (unified_range_table_copy_data):
* redisplay-msw.c (mswindows_output_string):
* redisplay-output.c (output_display_line):
* redisplay-output.c (redisplay_move_cursor):
* redisplay-output.c (redisplay_clear_bottom_of_window):
* redisplay-tty.c (tty_output_ichar_dynarr):
* redisplay-tty.c (set_foreground_to):
* redisplay-tty.c (set_background_to):
* redisplay-xlike-inc.c (XLIKE_output_string):
* redisplay.c (redisplay_window_text_width_string):
* redisplay.c (redisplay_text_width_string):
* redisplay.c (create_text_block):
* redisplay.c (SET_CURRENT_MODE_CHARS_PIXSIZE):
* redisplay.c (generate_fstring_runes):
* redisplay.c (regenerate_modeline):
* redisplay.c (ensure_modeline_generated):
* redisplay.c (real_current_modeline_height):
* redisplay.c (create_string_text_block):
* redisplay.c (regenerate_window):
* redisplay.c (REGEN_INC_FIND_START_END):
* redisplay.c (point_visible):
* redisplay.c (redisplay_window):
* redisplay.c (mark_glyph_block_dynarr):
* redisplay.c (line_start_cache_start):
* redisplay.c (start_with_line_at_pixpos):
* redisplay.c (update_line_start_cache):
* redisplay.c (glyph_to_pixel_translation):
* redisplay.c (pixel_to_glyph_translation):
* sysdep.c (qxe_readdir):
* text.c (dfc_convert_to_external_format):
* text.c (dfc_convert_to_internal_format):
* toolbar-common.c (common_output_toolbar_button):
* window.c (window_modeline_height):
* window.c (Fwindow_last_line_visible_height):
* window.c (window_displayed_height):
* window.c (window_scroll):
* window.c (get_current_pixel_pos):
Use Dynarr_begin() in place of Dynarr_atp (foo, 0).
* dynarr.c (Dynarr_realloc):
* dynarr.c (Dynarr_lisp_realloc):
* dynarr.c (Dynarr_resize):
* dynarr.c (Dynarr_insert_many):
* dynarr.c (Dynarr_delete_many):
* dynarr.c (Dynarr_memory_usage):
* dynarr.c (stack_like_malloc):
* dynarr.c (stack_like_free):
* lisp.h:
* lisp.h (DECLARE_DYNARR_LISP_IMP):
* lisp.h (XD_DYNARR_DESC):
* lisp.h (Dynarr_pop):
* gutter.c (output_gutter):
* redisplay-output.c (sync_rune_structs):
* redisplay-output.c (redisplay_output_window):
Redo the dynarr code, add greater checks.
Rename the `len', `largest' and `max' members to `len_',
`largest_' and `max_' to try and catch existing places that might
directly modify these values. Make new accessors Dynarr_largest()
and Dynarr_max() and make them and existing Dynarr_length() be
non-lvalues by adding '+ 0' to them; fix a couple of places in the
redisplay code that tried to modify the length directly by setting
Dynarr_length(). Use the accessors whenever possible even in the
dynarr code itself. The accessors also verify that 0 <= len <=
largest <= max. Rename settor function Dynarr_set_size() to
Dynarr_set_length() and use it more consistently; also create
lower-level Dynarr_set_length_1(). This latter function should be
the only function that directly modifies the `len_' member of a
Dynarr, and in the process makes sure that the `largest' value is
kept correct.
Consistently use ERROR_CHECK_STRUCTURES instead of
ERROR_CHECK_TYPES for error-checking code. Reintroduce the
temporarily disabled verification code on the positions of
Dynarr_at(), Dynarr_atp() and Dynarr_atp_past_end().
Also create Dynarr_resize_if() in place of a repeated
code fragment. Clean up all the functions that modify Dynarrs to
use the new macros and functions and verify the correctness of the
Dynarr both before and after the change.
Note that there are two kinds of verification -- one for accessing
and one for modifying. The difference is that the modify
verification additionally checks to make sure that the Dynarr
isn't locked. (This is used in redisplay to check for problems
with reentrancy.)
* lrecord.h: Move XD_DYNARR_DESC to lisp.h, grouping with the dynarr code.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 03 Feb 2010 20:51:18 -0600 |
parents | 19a72041c5ed |
children | 4d35e52790f8 |
rev | line source |
---|---|
428 | 1 /* Display generation from window structure and buffer text. |
2 Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1995 Free Software Foundation, Inc. | |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
4 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2005, 2010 Ben Wing. |
428 | 5 Copyright (C) 1995 Sun Microsystems, Inc. |
6 Copyright (C) 1996 Chuck Thompson. | |
7 | |
8 This file is part of XEmacs. | |
9 | |
10 XEmacs is free software; you can redistribute it and/or modify it | |
11 under the terms of the GNU General Public License as published by the | |
12 Free Software Foundation; either version 2, or (at your option) any | |
13 later version. | |
14 | |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
21 along with XEmacs; see the file COPYING. If not, write to | |
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 Boston, MA 02111-1307, USA. */ | |
24 | |
25 /* Synched up with: Not in FSF. */ | |
26 | |
27 /* Author: Chuck Thompson */ | |
28 | |
29 /* Fixed up by Ben Wing for Mule */ | |
30 | |
31 /* This file has been Mule-ized. */ | |
32 | |
33 /***************************************************************************** | |
34 The Golden Rules of Redisplay | |
35 | |
853 | 36 First: It Is Better To Be Correct Than Fast |
37 Second: Thou Shalt Use Due Caution When Running Elisp From Within Redisplay | |
38 Third: It Is Better To Be Fast Than Not To Be | |
428 | 39 ****************************************************************************/ |
40 | |
1318 | 41 /* Note: The second rule used to prohibit running Elisp from within |
42 redisplay, but that's not correct any more -- use | |
43 call*_trapping_problems() or call_with_suspended_errors() instead. | |
853 | 44 |
45 --ben | |
46 */ | |
47 | |
428 | 48 #include <config.h> |
49 #include "lisp.h" | |
50 | |
51 #include "buffer.h" | |
52 #include "commands.h" | |
53 #include "debug.h" | |
872 | 54 #include "device-impl.h" |
428 | 55 #include "elhash.h" |
853 | 56 #include "events.h" |
872 | 57 #include "extents-impl.h" |
428 | 58 #include "faces.h" |
872 | 59 #include "frame-impl.h" |
428 | 60 #include "glyphs.h" |
61 #include "gutter.h" | |
62 #include "insdel.h" | |
63 #include "menubar.h" | |
872 | 64 #include "objects-impl.h" |
1318 | 65 #include "opaque.h" |
428 | 66 #include "process.h" |
1292 | 67 #include "profile.h" |
428 | 68 #include "redisplay.h" |
69 #include "toolbar.h" | |
872 | 70 #include "window-impl.h" |
428 | 71 #include "line-number.h" |
72 #include "file-coding.h" | |
73 | |
442 | 74 #include "sysfile.h" |
75 | |
428 | 76 #ifdef HAVE_TTY |
77 #include "console-tty.h" | |
78 #endif /* HAVE_TTY */ | |
79 | |
80 /* Note: We have to be careful throughout this code to properly handle | |
867 | 81 and differentiate between Ibytes and Ichars. |
82 | |
83 Since strings are generally composed of Ibytes, I've taken the tack | |
84 that any contiguous set of Ibytes is called a "string", while | |
85 any contiguous set of Ichars is called an "array". */ | |
428 | 86 |
87 /* Return value to indicate a failure by an add_*_rune routine to add | |
88 a rune, but no propagation information needs to be returned. */ | |
89 #define ADD_FAILED (prop_block_dynarr *) 1 | |
90 | |
91 #define BEGIN_GLYPHS 0 | |
92 #define END_GLYPHS 1 | |
93 #define LEFT_GLYPHS 2 | |
94 #define RIGHT_GLYPHS 3 | |
95 | |
96 #define VERTICAL_CLIP(w, display) \ | |
442 | 97 ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \ |
428 | 98 ? INT_MAX \ |
442 | 99 : vertical_clip) |
428 | 100 |
101 /* The following structures are completely private to redisplay.c so | |
102 we put them here instead of in a header file, for modularity. */ | |
103 | |
826 | 104 /* NOTE: Bytexpos's not Charxpos's in this structure. */ |
428 | 105 |
106 typedef struct position_redisplay_data_type | |
107 { | |
108 /* This information is normally filled in by the create_*_block | |
109 routines and is used by the add_*_rune routines. */ | |
110 Lisp_Object window; | |
111 /* if we are working with strings rather than buffers we need a | |
112 handle to the string */ | |
113 Lisp_Object string; | |
114 struct device *d; | |
115 struct display_block *db; | |
116 struct display_line *dl; | |
867 | 117 Ichar ch; /* Character that is to be added. This is |
428 | 118 used to communicate this information to |
867 | 119 add_ichar_rune(). */ |
428 | 120 Lisp_Object last_charset; /* The charset of the previous character. |
121 Used to optimize some lookups -- we | |
122 only have to do some things when | |
123 the charset changes. */ | |
124 face_index last_findex; /* The face index of the previous character. | |
125 Needed to ensure the validity of the | |
126 last_charset optimization. */ | |
127 | |
128 int last_char_width; /* The width of the previous character. */ | |
129 int font_is_bogus; /* If true, it means we couldn't instantiate | |
130 the font for this charset, so we substitute | |
131 ~'s from the ASCII charset. */ | |
826 | 132 Bytexpos byte_charpos; /* Position of character we are processing. This |
133 is a Bytexpos, meaning it refers to bytes (not | |
134 chars) and can refer to either buffers (1-based) | |
135 or strings (0-based). We need to be careful | |
136 when doing anything that references the text in | |
137 the buffer or string. */ | |
138 Bytexpos byte_endpos; /* ????? Unknown, under-used. */ | |
428 | 139 int pixpos; |
140 int max_pixpos; | |
141 int blank_width; /* Width of the blank that is to be added. | |
142 This is used to communicate this information | |
143 to add_blank_rune(). | |
144 | |
145 This is also used rather cheesily to | |
146 communicate the width of the eol-cursor-size | |
147 blank that exists at the end of the line. | |
867 | 148 add_ichar_rune() is called cheesily with |
428 | 149 the non-printing char '\n', which is stuck |
150 in the output routines with its width being | |
151 BLANK_WIDTH. */ | |
826 | 152 Bytexpos byte_cursor_charpos; /* This stores the buffer position of the |
153 cursor. */ | |
428 | 154 unsigned int cursor_type :3; |
155 int cursor_x; /* rune block cursor is at */ | |
156 int start_col; /* Number of character columns (each column has | |
157 a width of the default char width) that still | |
158 need to be skipped. This is used for horizontal | |
159 scrolling, where a certain number of columns | |
160 (those off the left side of the screen) need | |
161 to be skipped before anything is displayed. */ | |
826 | 162 Bytexpos byte_start_col_enabled; |
428 | 163 int start_col_xoffset; /* Number of pixels that still need to |
4187 | 164 be skipped. This is used for |
165 horizontal scrolling of glyphs, where we want | |
166 to be able to scroll over part of the glyph. */ | |
428 | 167 |
168 int hscroll_glyph_width_adjust; /* how much the width of the hscroll | |
169 glyph differs from space_width (w). | |
170 0 if no hscroll glyph was used, | |
171 i.e. the window is not scrolled | |
172 horizontally. Used in tab | |
173 calculations. */ | |
174 | |
175 /* Information about the face the text should be displayed in and | |
176 any begin-glyphs and end-glyphs. */ | |
177 struct extent_fragment *ef; | |
178 face_index findex; | |
179 | |
819 | 180 /* The height of a pixmap may either be predetermined if the user has set a |
181 baseline value, or it may be dependent on whatever the line ascent and | |
182 descent values end up being, based just on font and pixmap-ascent | |
183 information. In the first case we can immediately update the values, thus | |
184 their inclusion here. In the last case we cannot determine the actual | |
185 contribution to the line height until we have finished laying out all text | |
186 on the line. Thus we propagate the max height of such pixmaps and do a | |
187 final calculation (in calculate_baseline()) after all text has been added | |
188 to the line. */ | |
428 | 189 int new_ascent; |
190 int new_descent; | |
191 int max_pixmap_height; | |
819 | 192 int need_baseline_computation; |
193 int end_glyph_width; /* Well, it is the kitchen sink after all ... */ | |
428 | 194 |
195 Lisp_Object result_str; /* String where we put the result of | |
196 generating a formatted string in the modeline. */ | |
197 int is_modeline; /* Non-zero if we're generating the modeline. */ | |
198 Charcount modeline_charpos; /* Number of chars used in result_str so far; | |
199 corresponds to bytepos. */ | |
200 Bytecount bytepos; /* Number of bytes used in result_str so far. | |
4187 | 201 We don't actually copy the bytes into result_str |
428 | 202 until the end because we don't know how big the |
203 string is going to be until then. */ | |
204 } pos_data; | |
205 | |
206 enum prop_type | |
207 { | |
208 PROP_STRING, | |
209 PROP_CHAR, | |
210 PROP_MINIBUF_PROMPT, | |
819 | 211 PROP_BLANK, |
212 PROP_GLYPH | |
428 | 213 }; |
214 | |
215 /* Data that should be propagated to the next line. Either a single | |
867 | 216 Ichar, a string of Ibyte's or a glyph. |
428 | 217 |
218 The actual data that is propagated ends up as a Dynarr of these | |
219 blocks. | |
220 | |
819 | 221 prop_blocks are used to indicate that data that was supposed to go |
222 on the previous line couldn't actually be displayed. Generally this | |
223 shouldn't happen if we are clipping the end of lines. If we are | |
224 wrapping then we need to display the propagation data before moving | |
225 on. Its questionable whether we should wrap or clip glyphs in this | |
226 instance. Most e-lisp relies on clipping so we preserve this | |
227 behavior. | |
228 | |
867 | 229 #### It's unclean that both Ichars and Ibytes are here. |
428 | 230 */ |
231 | |
232 typedef struct prop_block prop_block; | |
233 struct prop_block | |
234 { | |
235 enum prop_type type; | |
236 | |
237 union data | |
238 { | |
239 struct | |
240 { | |
867 | 241 Ibyte *str; |
428 | 242 Bytecount len; /* length of the string. */ |
243 } p_string; | |
244 | |
245 struct | |
246 { | |
867 | 247 Ichar ch; |
826 | 248 Bytebpos byte_cursor_charpos; /* NOTE: is in Bytebpos's */ |
428 | 249 unsigned int cursor_type :3; |
250 } p_char; | |
251 | |
252 struct | |
253 { | |
254 int width; | |
255 face_index findex; | |
256 } p_blank; | |
819 | 257 |
258 struct | |
259 { | |
260 /* Not used as yet, but could be used to wrap rather than clip glyphs. */ | |
4187 | 261 int width; |
819 | 262 Lisp_Object glyph; |
263 } p_glyph; | |
264 | |
428 | 265 } data; |
266 }; | |
267 | |
268 typedef struct | |
269 { | |
270 Dynarr_declare (prop_block); | |
271 } prop_block_dynarr; | |
272 | |
273 | |
274 static Charcount generate_fstring_runes (struct window *w, pos_data *data, | |
275 Charcount pos, Charcount min_pos, | |
276 Charcount max_pos, Lisp_Object elt, | |
277 int depth, int max_pixsize, | |
438 | 278 face_index findex, int type, |
279 Charcount *offset, | |
280 Lisp_Object cur_ext); | |
428 | 281 static prop_block_dynarr *add_glyph_rune (pos_data *data, |
282 struct glyph_block *gb, | |
283 int pos_type, int allow_cursor, | |
284 struct glyph_cachel *cachel); | |
665 | 285 static Bytebpos create_text_block (struct window *w, struct display_line *dl, |
826 | 286 Bytebpos byte_start_pos, |
287 prop_block_dynarr **prop, | |
288 int type); | |
428 | 289 static int create_overlay_glyph_block (struct window *w, |
290 struct display_line *dl); | |
291 static void create_left_glyph_block (struct window *w, | |
292 struct display_line *dl, | |
293 int overlay_width); | |
294 static void create_right_glyph_block (struct window *w, | |
295 struct display_line *dl); | |
296 static void redisplay_windows (Lisp_Object window, int skip_selected); | |
867 | 297 static void decode_mode_spec (struct window *w, Ichar spec, int type); |
428 | 298 static void free_display_line (struct display_line *dl); |
826 | 299 static void update_line_start_cache (struct window *w, Charbpos from, |
300 Charbpos to, Charbpos point, | |
301 int no_regen); | |
665 | 302 static int point_visible (struct window *w, Charbpos point, int type); |
819 | 303 static void calculate_yoffset (struct display_line *dl, |
4187 | 304 struct display_block *fixup); |
819 | 305 static void calculate_baseline (pos_data *data); |
428 | 306 |
1204 | 307 #ifdef ERROR_CHECK_DISPLAY |
800 | 308 static void sledgehammer_check_redisplay_structs (void); |
1204 | 309 #endif /* ERROR_CHECK_DISPLAY */ |
800 | 310 |
428 | 311 /* This used to be 10 but 30 seems to give much better performance. */ |
312 #define INIT_MAX_PREEMPTS 30 | |
1268 | 313 static Fixnum max_preempts; |
314 | |
315 #define QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION 4 | |
428 | 316 |
1318 | 317 /* Note that doing this can call Lisp. */ |
428 | 318 #define REDISPLAY_PREEMPTION_CHECK \ |
319 ((void) \ | |
320 (preempted = \ | |
321 (!disable_preemption && \ | |
322 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \ | |
4187 | 323 (!INTERACTIVE || \ |
1268 | 324 detect_input_pending (QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION))))) |
428 | 325 |
326 /* | |
327 * Redisplay global variables. | |
328 */ | |
329 | |
330 /* We need a third set of display structures for the cursor motion | |
331 routines. We used to just give each window a third set. However, | |
332 we always fully regenerate the structures when needed so there | |
333 isn't any reason we need more than a single set. */ | |
334 display_line_dynarr *cmotion_display_lines; | |
335 | |
336 /* We store the extents that we need to generate in a Dynarr and then | |
337 frob them all on at the end of generating the string. We do it | |
338 this way rather than adding them as we generate the string because | |
339 we don't store the text into the resulting string until we're done | |
340 (to avoid having to resize the string multiple times), and we don't | |
341 want to go around adding extents to a string when the extents might | |
342 stretch off the end of the string. */ | |
343 static EXTENT_dynarr *formatted_string_extent_dynarr; | |
344 static Bytecount_dynarr *formatted_string_extent_start_dynarr; | |
345 static Bytecount_dynarr *formatted_string_extent_end_dynarr; | |
346 | |
347 | |
348 /* #### probably temporary */ | |
458 | 349 Fixnum cache_adjustment; |
428 | 350 |
351 /* This holds a string representing the text corresponding to a single | |
352 modeline % spec. */ | |
867 | 353 static Ibyte_dynarr *mode_spec_ibyte_string; |
428 | 354 |
355 int in_display; /* 1 if in redisplay. */ | |
356 | |
1318 | 357 /* Whether we should delay size changes. Broken out of |
358 enter_redisplay_critical_section(). */ | |
359 int hold_frame_size_changes; | |
360 | |
428 | 361 int disable_preemption; /* Used for debugging redisplay and for |
362 force-redisplay. */ | |
363 | |
364 /* We only allow max_preempts preemptions before we force a redisplay. */ | |
365 static int preemption_count; | |
366 | |
367 /* Minimum pixel height of clipped bottom display line. */ | |
458 | 368 Fixnum vertical_clip; |
428 | 369 |
370 /* Minimum visible pixel width of clipped glyphs at right margin. */ | |
458 | 371 Fixnum horizontal_clip; |
428 | 372 |
373 /* Nonzero means reading single-character input with prompt | |
374 so put cursor on minibuffer after the prompt. */ | |
375 int cursor_in_echo_area; | |
376 Lisp_Object Qcursor_in_echo_area; | |
377 | |
378 /* Nonzero means truncate lines in all windows less wide than the frame */ | |
379 int truncate_partial_width_windows; | |
380 | |
381 /* non-nil if a buffer has changed since the last time redisplay completed */ | |
382 int buffers_changed; | |
383 int buffers_changed_set; | |
384 | |
385 /* non-nil if hscroll has changed somewhere or a buffer has been | |
386 narrowed or widened */ | |
387 int clip_changed; | |
388 int clip_changed_set; | |
389 | |
390 /* non-nil if any extent has changed since the last time redisplay completed */ | |
391 int extents_changed; | |
392 int extents_changed_set; | |
393 | |
394 /* non-nil if any face has changed since the last time redisplay completed */ | |
395 int faces_changed; | |
396 | |
397 /* Nonzero means some frames have been marked as garbaged */ | |
398 int frame_changed; | |
399 | |
400 /* non-zero if any of the builtin display glyphs (continuation, | |
401 hscroll, control-arrow, etc) is in need of updating | |
402 somewhere. */ | |
403 int glyphs_changed; | |
404 int glyphs_changed_set; | |
405 | |
442 | 406 /* non-zero if any subwindow has been deleted. */ |
428 | 407 int subwindows_changed; |
408 int subwindows_changed_set; | |
409 | |
410 /* non-zero if any displayed subwindow is in need of updating | |
411 somewhere. */ | |
412 int subwindows_state_changed; | |
413 int subwindows_state_changed_set; | |
414 | |
415 /* This variable is 1 if the icon has to be updated. | |
416 It is set to 1 when `frame-icon-glyph' changes. */ | |
417 int icon_changed; | |
418 int icon_changed_set; | |
419 | |
420 /* This variable is 1 if the menubar widget has to be updated. | |
421 It is set to 1 by set-menubar-dirty-flag and cleared when the widget | |
422 has been updated. */ | |
423 int menubar_changed; | |
424 int menubar_changed_set; | |
425 | |
426 /* true iff we should redraw the modelines on the next redisplay */ | |
427 int modeline_changed; | |
428 int modeline_changed_set; | |
429 | |
430 /* non-nil if point has changed in some buffer since the last time | |
431 redisplay completed */ | |
432 int point_changed; | |
433 int point_changed_set; | |
434 | |
435 /* non-nil if some frame has changed its size */ | |
436 int size_changed; | |
437 | |
438 /* non-nil if some device has signaled that it wants to change size */ | |
439 int asynch_device_change_pending; | |
440 | |
441 /* non-nil if any toolbar has changed */ | |
442 int toolbar_changed; | |
443 int toolbar_changed_set; | |
444 | |
905 | 445 /* Nonzero if some frame has changed the layout of internal elements |
446 (gutters or toolbars). */ | |
447 int frame_layout_changed; | |
448 | |
428 | 449 /* non-nil if any gutter has changed */ |
450 int gutter_changed; | |
451 int gutter_changed_set; | |
452 | |
453 /* non-nil if any window has changed since the last time redisplay completed */ | |
454 int windows_changed; | |
455 | |
456 /* non-nil if any frame's window structure has changed since the last | |
457 time redisplay completed */ | |
458 int windows_structure_changed; | |
459 | |
460 /* If non-nil, use vertical bar cursor. */ | |
461 Lisp_Object Vbar_cursor; | |
462 Lisp_Object Qbar_cursor; | |
463 | |
442 | 464 Lisp_Object Vvisible_bell; /* If true and the terminal will support it |
465 then the frame will flash instead of | |
466 beeping when an error occurs */ | |
428 | 467 |
468 /* Nonzero means no need to redraw the entire frame on resuming | |
469 a suspended Emacs. This is useful on terminals with multiple pages, | |
470 where one page is used for Emacs and another for all else. */ | |
471 int no_redraw_on_reenter; | |
472 | |
3360 | 473 Lisp_Object Vwindow_system; /* #### this variable is deprecated |
474 nil or a symbol naming the window system | |
428 | 475 under which emacs is running |
3360 | 476 (`x', `gtk', `mswindows', and `tty' are |
477 supported -- yes, TTYs are window systems | |
478 for this purpose. */ | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
479 Lisp_Object Vinitial_device_type; |
428 | 480 |
481 Lisp_Object Vglobal_mode_string; | |
482 | |
483 /* The number of lines scroll a window by when point leaves the window; if | |
484 it is <=0 then point is centered in the window */ | |
458 | 485 Fixnum scroll_step; |
428 | 486 |
487 /* Scroll up to this many lines, to bring point back on screen. */ | |
458 | 488 Fixnum scroll_conservatively; |
428 | 489 |
490 /* Marker for where to display an arrow on top of the buffer text. */ | |
491 Lisp_Object Voverlay_arrow_position; | |
492 /* String to display for the arrow. */ | |
493 Lisp_Object Voverlay_arrow_string; | |
494 | |
442 | 495 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook; |
496 | |
458 | 497 static Fixnum last_display_warning_tick; |
498 static Fixnum display_warning_tick; | |
428 | 499 Lisp_Object Qdisplay_warning_buffer; |
500 int inhibit_warning_display; | |
501 | |
502 Lisp_Object Vleft_margin_width, Vright_margin_width; | |
503 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; | |
504 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; | |
505 Lisp_Object Vtext_cursor_visible_p; | |
506 | |
1292 | 507 static Lisp_Object QSin_redisplay; |
508 | |
1318 | 509 static Lisp_Object Vpost_redisplay_actions; |
510 | |
428 | 511 int column_number_start_at_one; |
512 | |
442 | 513 Lisp_Object Qtop_bottom; |
514 | |
444 | 515 #define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset) |
428 | 516 |
1204 | 517 static const struct memory_description rune_dglyph_description_1[] = { |
518 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, glyph) }, | |
519 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, extent) }, | |
520 { XD_END } | |
521 }; | |
522 | |
523 static const struct sized_memory_description rune_dglyph_description = { | |
524 sizeof (struct rune_dglyph), rune_dglyph_description_1 | |
525 }; | |
526 | |
527 static const struct memory_description rune_object_description_1[] = { | |
2551 | 528 { XD_BLOCK_ARRAY, RUNE_DGLYPH, 1, { &rune_dglyph_description } }, |
1204 | 529 { XD_END } |
530 }; | |
531 | |
532 static const struct sized_memory_description rune_object_description = { | |
533 0, rune_object_description_1 | |
534 }; | |
535 | |
536 static const struct memory_description rune_description_1[] = { | |
537 { XD_INT, offsetof (rune, type) }, | |
538 { XD_UNION, offsetof (rune, object), | |
2551 | 539 XD_INDIRECT (0, 0), { &rune_object_description } }, |
1204 | 540 { XD_END } |
541 }; | |
542 | |
543 static const struct sized_memory_description rune_description = { | |
544 sizeof (rune), | |
545 rune_description_1 | |
546 }; | |
547 | |
548 static const struct memory_description rune_dynarr_description_1[] = { | |
549 XD_DYNARR_DESC (rune_dynarr, &rune_description), | |
550 { XD_END } | |
551 }; | |
552 | |
553 static const struct sized_memory_description rune_dynarr_description = { | |
554 sizeof (rune_dynarr), | |
555 rune_dynarr_description_1 | |
556 }; | |
557 | |
558 static const struct memory_description display_block_description_1[] = { | |
2367 | 559 { XD_BLOCK_PTR, offsetof (display_block, runes), |
2551 | 560 1, { &rune_dynarr_description } }, |
1204 | 561 { XD_END } |
562 }; | |
563 | |
564 static const struct sized_memory_description display_block_description = { | |
565 sizeof (display_block), | |
566 display_block_description_1 | |
567 }; | |
568 | |
569 static const struct memory_description display_block_dynarr_description_1[] = { | |
570 XD_DYNARR_DESC (display_block_dynarr, &display_block_description), | |
571 { XD_END } | |
572 }; | |
573 | |
574 static const struct sized_memory_description display_block_dynarr_description = { | |
575 sizeof (display_block_dynarr), | |
576 display_block_dynarr_description_1 | |
577 }; | |
578 | |
579 static const struct memory_description glyph_block_description_1[] = { | |
580 { XD_LISP_OBJECT, offsetof (glyph_block, glyph) }, | |
581 { XD_LISP_OBJECT, offsetof (glyph_block, extent) }, | |
582 { XD_END } | |
583 }; | |
584 | |
585 static const struct sized_memory_description glyph_block_description = { | |
586 sizeof (glyph_block), | |
587 glyph_block_description_1 | |
588 }; | |
589 | |
590 static const struct memory_description glyph_block_dynarr_description_1[] = { | |
591 XD_DYNARR_DESC (glyph_block_dynarr, &glyph_block_description), | |
592 { XD_END } | |
593 }; | |
594 | |
595 static const struct sized_memory_description glyph_block_dynarr_description = { | |
596 sizeof (glyph_block_dynarr), | |
597 glyph_block_dynarr_description_1 | |
598 }; | |
599 | |
600 static const struct memory_description display_line_description_1[] = { | |
2367 | 601 { XD_BLOCK_PTR, offsetof (display_line, display_blocks), |
2551 | 602 1, { &display_block_dynarr_description } }, |
2367 | 603 { XD_BLOCK_PTR, offsetof (display_line, left_glyphs), |
2551 | 604 1, { &glyph_block_dynarr_description } }, |
2367 | 605 { XD_BLOCK_PTR, offsetof (display_line, right_glyphs), |
2551 | 606 1, { &glyph_block_dynarr_description } }, |
1204 | 607 { XD_END } |
608 }; | |
609 | |
610 static const struct sized_memory_description display_line_description = { | |
611 sizeof (display_line), | |
612 display_line_description_1 | |
613 }; | |
614 | |
615 static const struct memory_description display_line_dynarr_description_1[] = { | |
616 XD_DYNARR_DESC (display_line_dynarr, &display_line_description), | |
617 { XD_END } | |
618 }; | |
619 | |
620 const struct sized_memory_description display_line_dynarr_description = { | |
621 sizeof (display_line_dynarr), | |
622 display_line_dynarr_description_1 | |
623 }; | |
624 | |
428 | 625 |
626 /***************************************************************************/ | |
627 /* */ | |
628 /* low-level interfaces onto device routines */ | |
629 /* */ | |
630 /***************************************************************************/ | |
631 | |
632 static int | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
633 redisplay_window_text_width_ichar_string (struct window *w, int findex, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
634 Ichar *str, Charcount len) |
428 | 635 { |
636 unsigned char charsets[NUM_LEADING_BYTES]; | |
637 Lisp_Object window; | |
638 | |
867 | 639 find_charsets_in_ichar_string (charsets, str, len); |
793 | 640 window = wrap_window (w); |
428 | 641 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window, |
642 charsets); | |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
643 return DEVMETH (WINDOW_XDEVICE (w), |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
644 text_width, (w, WINDOW_FACE_CACHEL (w, findex), str, |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
645 len)); |
428 | 646 } |
647 | |
867 | 648 static Ichar_dynarr *rtw_ichar_dynarr; |
428 | 649 |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
650 static int |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
651 redisplay_window_text_width_string (struct window *w, int findex, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
652 Ibyte *nonreloc, Lisp_Object reloc, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
653 Bytecount offset, Bytecount len) |
428 | 654 { |
867 | 655 if (!rtw_ichar_dynarr) |
656 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
657 Dynarr_reset (rtw_ichar_dynarr); | |
428 | 658 |
659 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
660 if (STRINGP (reloc)) | |
661 nonreloc = XSTRING_DATA (reloc); | |
867 | 662 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
663 return redisplay_window_text_width_ichar_string |
4967 | 664 (w, findex, Dynarr_begin (rtw_ichar_dynarr), |
867 | 665 Dynarr_length (rtw_ichar_dynarr)); |
428 | 666 } |
667 | |
668 int | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
669 redisplay_text_width_string (Lisp_Object domain, Lisp_Object face, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
670 Ibyte *nonreloc, Lisp_Object reloc, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
671 Bytecount offset, Bytecount len) |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
672 { |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
673 Lisp_Object window = DOMAIN_WINDOW (domain); |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
674 Lisp_Object frame = DOMAIN_FRAME (domain); |
428 | 675 unsigned char charsets[NUM_LEADING_BYTES]; |
676 struct face_cachel cachel; | |
677 | |
867 | 678 if (!rtw_ichar_dynarr) |
679 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
680 Dynarr_reset (rtw_ichar_dynarr); | |
428 | 681 |
682 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
683 if (STRINGP (reloc)) | |
684 nonreloc = XSTRING_DATA (reloc); | |
867 | 685 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
686 find_charsets_in_ibyte_string (charsets, nonreloc, len); | |
428 | 687 reset_face_cachel (&cachel); |
688 cachel.face = face; | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
689 ensure_face_cachel_complete (&cachel, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
690 NILP (window) ? frame : window, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
691 charsets); |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
692 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (frame))), |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
693 /* #### Not clear if we're always passed a window, but |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
694 I think so. If not, we will get an abort here, |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
695 and then we need to either fix the callers to pass in |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
696 a window, or change *text_width() to take a domain |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
697 argument. */ |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
698 text_width, (XWINDOW (window), |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
699 &cachel, |
4967 | 700 Dynarr_begin (rtw_ichar_dynarr), |
867 | 701 Dynarr_length (rtw_ichar_dynarr))); |
428 | 702 } |
703 | |
704 /* Return the display block from DL of the given TYPE. A display line | |
705 can have only one display block of each possible type. If DL does | |
706 not have a block of type TYPE, one will be created and added to DL. */ | |
707 | |
708 struct display_block * | |
709 get_display_block_from_line (struct display_line *dl, enum display_type type) | |
710 { | |
711 int elt; | |
712 struct display_block db; | |
713 | |
714 /* Check if this display line already has a block of the desired type and | |
715 if so, return it. */ | |
716 if (dl->display_blocks) | |
717 { | |
718 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++) | |
719 { | |
720 if (Dynarr_at (dl->display_blocks, elt).type == type) | |
721 return Dynarr_atp (dl->display_blocks, elt); | |
722 } | |
723 | |
724 /* There isn't an active block of the desired type, but there | |
4187 | 725 might still be allocated blocks we need to reuse. */ |
428 | 726 if (elt < Dynarr_largest (dl->display_blocks)) |
727 { | |
728 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt); | |
729 | |
3025 | 730 /* "add" the block to the list */ |
428 | 731 Dynarr_increment (dl->display_blocks); |
732 | |
733 /* initialize and return */ | |
734 dbp->type = type; | |
735 return dbp; | |
736 } | |
737 } | |
738 else | |
739 { | |
740 /* This line doesn't have any display blocks, so initialize the display | |
4187 | 741 bock array. */ |
428 | 742 dl->display_blocks = Dynarr_new (display_block); |
743 } | |
744 | |
745 /* The line doesn't have a block of the desired type so go ahead and create | |
746 one and add it to the line. */ | |
747 xzero (db); | |
748 db.type = type; | |
749 db.runes = Dynarr_new (rune); | |
750 Dynarr_add (dl->display_blocks, db); | |
751 | |
752 /* Return the newly added display block. */ | |
753 elt = Dynarr_length (dl->display_blocks) - 1; | |
754 | |
755 return Dynarr_atp (dl->display_blocks, elt); | |
756 } | |
757 | |
758 static int | |
759 tab_char_width (struct window *w) | |
760 { | |
761 struct buffer *b = XBUFFER (w->buffer); | |
762 int char_tab_width = XINT (b->tab_width); | |
763 | |
764 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8; | |
765 | |
766 return char_tab_width; | |
767 } | |
768 | |
769 static int | |
770 space_width (struct window *w) | |
771 { | |
3659 | 772 /* While tabs are traditionally composed of spaces, for variable-width |
428 | 773 fonts the space character tends to give too narrow a value. So |
774 we use 'n' instead. Except that we don't. We use the default | |
775 character width for the default face. If this is actually | |
776 defined by the font then it is probably the best thing to | |
777 actually use. If it isn't, we have assumed it is 'n' and have | |
778 already calculated its width. Thus we can avoid a call to | |
779 XTextWidth on X frames by just querying the default width. */ | |
780 return XFONT_INSTANCE | |
781 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width; | |
782 } | |
783 | |
784 static int | |
785 tab_pix_width (struct window *w) | |
786 { | |
787 return space_width (w) * tab_char_width (w); | |
788 } | |
789 | |
790 /* Given a pixel position in a window, return the pixel location of | |
791 the next tabstop. Tabs are calculated from the left window edge in | |
792 terms of spaces displayed in the default face. Formerly the space | |
793 width was determined using the currently active face. That method | |
794 leads to tabstops which do not line up. */ | |
795 | |
796 static int | |
797 next_tab_position (struct window *w, int start_pixpos, int left_pixpos) | |
798 { | |
799 int n_pos = left_pixpos; | |
800 int pix_tab_width = tab_pix_width (w); | |
801 | |
802 /* Adjust n_pos for any hscrolling which has happened. */ | |
803 if (WINDOW_SCROLLED (w)) | |
804 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset; | |
805 | |
806 while (n_pos <= start_pixpos) | |
807 n_pos += pix_tab_width; | |
808 | |
809 return n_pos; | |
810 } | |
811 | |
812 /* For the given window, calculate the outside and margin boundaries for a | |
813 display line. The whitespace boundaries must be calculated by the text | |
814 layout routines. */ | |
815 | |
816 layout_bounds | |
817 calculate_display_line_boundaries (struct window *w, int modeline) | |
818 { | |
819 layout_bounds bounds; | |
820 | |
821 /* Set the outermost boundaries which are the boundaries of the | |
822 window itself minus the gutters (and minus the scrollbars if this | |
823 is for the modeline). */ | |
824 if (!modeline) | |
825 { | |
826 bounds.left_out = WINDOW_TEXT_LEFT (w); | |
827 bounds.right_out = WINDOW_TEXT_RIGHT (w); | |
828 } | |
829 else | |
830 { | |
831 bounds.left_out = WINDOW_MODELINE_LEFT (w); | |
832 bounds.right_out = WINDOW_MODELINE_RIGHT (w); | |
833 } | |
834 | |
835 /* The inner boundaries mark where the glyph margins are located. */ | |
836 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
837 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
838 | |
839 /* We cannot fully calculate the whitespace boundaries as they | |
840 depend on the contents of the line being displayed. */ | |
841 bounds.left_white = bounds.left_in; | |
842 bounds.right_white = bounds.right_in; | |
843 | |
844 return bounds; | |
845 } | |
846 | |
819 | 847 /* This takes a display_block and its containing line and corrects the yoffset |
848 of each glyph in the block to cater for the ascent of the line as a | |
849 whole. Must be called *after* the line-ascent is known! */ | |
850 | |
851 static void | |
852 calculate_yoffset (struct display_line *dl, struct display_block *fixup) | |
853 { | |
854 int i; | |
855 for (i=0; i<Dynarr_length (fixup->runes); i++) | |
856 { | |
857 struct rune *r = Dynarr_atp (fixup->runes,i); | |
858 if (r->type == RUNE_DGLYPH) | |
4187 | 859 { |
860 if (r->object.dglyph.ascent < dl->ascent) | |
861 r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent + | |
819 | 862 r->object.dglyph.descent; |
4187 | 863 } |
819 | 864 } |
865 } | |
866 | |
867 /* Calculate the textual baseline (the ascent and descent values for the | |
868 display_line as a whole). | |
869 | |
870 If the baseline is completely blank, or contains no manually positioned | |
871 glyphs, then the textual baseline is simply the baseline of the default font. | |
872 (The `contains no manually positioned glyphs' part is actually done for | |
867 | 873 us by `add_ichar_rune'.) |
819 | 874 |
875 If the baseline contains pixmaps, and they're all manually positioned, then | |
876 the textual baseline location is constrained that way, and we need do no | |
877 work. | |
878 | |
879 If the baseline contains pixmaps, and at least one is automatically | |
880 positioned, then the textual ascent is the largest ascent on the line, and | |
881 the textual descent is the largest descent (which is how things are set up at | |
882 entry to this function anyway): except that if the max_ascent + max_descent | |
883 is too small for the height of the line (say you've adjusted the baseline of | |
884 a short glyph, and there's a tall one next to it), then take the ascent and | |
885 descent for the line individually from the largest of the explicitly set | |
886 ascent/descent, and the rescaled ascent/descent of the default font, scaled | |
887 such that the largest glyph will fit. | |
888 | |
889 This means that if you have a short glyph (but taller than the default | |
890 font's descent) forced right under the baseline, and a really tall | |
891 automatically positioned glyph, that the descent for the line is just big | |
892 enough for the manually positioned short glyph, and the tall one uses as | |
893 much of that space as the default font would were it as tall as the tall | |
894 glyph; but that the ascent is big enough for the tall glyph to fit. | |
895 | |
896 This behaviour means that under no circumstances will changing the baseline | |
897 of a short glyph cause a tall glyph to move around; nor will it move the | |
898 textual baseline more than necessary. (Changing a tall glyph's baseline | |
899 might move the text's baseline arbitrarily, of course.) */ | |
900 | |
901 static void | |
902 calculate_baseline (pos_data *data) | |
903 { | |
904 /* Blank line: baseline is default font's baseline. */ | |
905 | |
906 if (!data->new_ascent && !data->new_descent) | |
907 { | |
908 /* We've got a blank line so initialize these values from the default | |
4187 | 909 face. */ |
819 | 910 default_face_font_info (data->window, &data->new_ascent, |
911 &data->new_descent, 0, 0, 0); | |
912 } | |
4187 | 913 |
819 | 914 /* No automatically positioned glyphs? Return at once. */ |
915 if (!data->need_baseline_computation) | |
916 return; | |
917 | |
918 /* Is the tallest glyph on the line automatically positioned? | |
919 If it's manually positioned, or it's automatically positioned | |
920 and there's enough room for it anyway, we need do no more work. */ | |
921 if (data->max_pixmap_height > data->new_ascent + data->new_descent) | |
922 { | |
923 int default_font_ascent, default_font_descent, default_font_height; | |
924 int scaled_default_font_ascent, scaled_default_font_descent; | |
4187 | 925 |
819 | 926 default_face_font_info (data->window, &default_font_ascent, |
927 &default_font_descent, &default_font_height, | |
928 0, 0); | |
929 | |
930 scaled_default_font_ascent = data->max_pixmap_height * | |
931 default_font_ascent / default_font_height; | |
932 | |
933 data->new_ascent = max (data->new_ascent, scaled_default_font_ascent); | |
934 | |
935 /* The ascent may have expanded now. Do we still need to grow the descent, | |
4187 | 936 or are things big enough? |
937 | |
938 The +1 caters for the baseline row itself. */ | |
819 | 939 if (data->max_pixmap_height > data->new_ascent + data->new_descent) |
4187 | 940 { |
941 scaled_default_font_descent = (data->max_pixmap_height * | |
819 | 942 default_font_descent / default_font_height) + 1; |
943 | |
4187 | 944 data->new_descent = max (data->new_descent, scaled_default_font_descent); |
945 } | |
819 | 946 } |
947 } | |
948 | |
428 | 949 /* Given a display line and a starting position, ensure that the |
950 contents of the display line accurately represent the visual | |
951 representation of the buffer contents starting from the given | |
952 position when displayed in the given window. The display line ends | |
953 when the contents of the line reach the right boundary of the given | |
954 window. */ | |
955 | |
665 | 956 static Charbpos |
428 | 957 generate_display_line (struct window *w, struct display_line *dl, int bounds, |
665 | 958 Charbpos start_pos, prop_block_dynarr **prop, |
428 | 959 int type) |
960 { | |
826 | 961 Charbpos ret_charpos; |
428 | 962 int overlay_width; |
963 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); | |
964 | |
965 /* If our caller hasn't already set the boundaries, then do so now. */ | |
966 if (!bounds) | |
967 dl->bounds = calculate_display_line_boundaries (w, 0); | |
968 | |
969 /* Reset what this line is using. */ | |
970 if (dl->display_blocks) | |
971 Dynarr_reset (dl->display_blocks); | |
972 if (dl->left_glyphs) | |
973 { | |
974 Dynarr_free (dl->left_glyphs); | |
975 dl->left_glyphs = 0; | |
976 } | |
977 if (dl->right_glyphs) | |
978 { | |
979 Dynarr_free (dl->right_glyphs); | |
980 dl->right_glyphs = 0; | |
981 } | |
982 | |
983 /* We aren't generating a modeline at the moment. */ | |
984 dl->modeline = 0; | |
985 | |
986 /* Create a display block for the text region of the line. */ | |
987 { | |
988 /* #### urk urk urk!!! Chuck fix this shit! */ | |
665 | 989 Bytebpos hacked_up_bytebpos = |
990 create_text_block (w, dl, charbpos_to_bytebpos (b, start_pos), | |
428 | 991 prop, type); |
826 | 992 if (hacked_up_bytebpos > BYTE_BUF_ZV (b)) |
993 ret_charpos = BUF_ZV (b) + 1; | |
428 | 994 else |
826 | 995 ret_charpos = bytebpos_to_charbpos (b, hacked_up_bytebpos); |
428 | 996 } |
826 | 997 dl->charpos = start_pos; |
998 if (dl->end_charpos < dl->charpos) | |
999 dl->end_charpos = dl->charpos; | |
428 | 1000 |
1001 if (MARKERP (Voverlay_arrow_position) | |
1002 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position)) | |
1003 && start_pos == marker_position (Voverlay_arrow_position) | |
1004 && (STRINGP (Voverlay_arrow_string) | |
1005 || GLYPHP (Voverlay_arrow_string))) | |
1006 { | |
1007 overlay_width = create_overlay_glyph_block (w, dl); | |
1008 } | |
1009 else | |
1010 overlay_width = 0; | |
1011 | |
1012 /* If there are left glyphs associated with any character in the | |
1013 text block, then create a display block to handle them. */ | |
1014 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
1015 create_left_glyph_block (w, dl, overlay_width); | |
1016 | |
1017 /* If there are right glyphs associated with any character in the | |
1018 text block, then create a display block to handle them. */ | |
1019 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
1020 create_right_glyph_block (w, dl); | |
1021 | |
1022 /* In the future additional types of display blocks may be generated | |
1023 here. */ | |
1024 | |
826 | 1025 w->last_redisplay_pos = ret_charpos; |
1026 | |
1027 return ret_charpos; | |
428 | 1028 } |
1029 | |
1030 /* Adds an hscroll glyph to a display block. If this is called, then | |
1031 the block had better be empty. | |
1032 | |
1033 Yes, there are multiple places where this function is called but | |
1034 that is the way it has to be. Each calling function has to deal | |
826 | 1035 with byte_start_col_enabled a little differently depending on the |
428 | 1036 object being worked with. */ |
1037 | |
1038 static prop_block_dynarr * | |
1039 add_hscroll_rune (pos_data *data) | |
1040 { | |
1041 struct glyph_block gb; | |
1042 prop_block_dynarr *retval; | |
826 | 1043 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
647 | 1044 int old_cursor_type = data->cursor_type; |
826 | 1045 Bytebpos byte_old_charpos = data->byte_charpos; |
428 | 1046 |
1047 if (data->cursor_type == CURSOR_ON | |
826 | 1048 && data->byte_cursor_charpos >= data->byte_start_col_enabled |
1049 && data->byte_cursor_charpos <= data->byte_charpos) | |
1050 { | |
1051 data->byte_cursor_charpos = data->byte_start_col_enabled; | |
428 | 1052 } |
1053 else | |
1054 { | |
1055 data->cursor_type = NO_CURSOR; | |
1056 } | |
1057 | |
826 | 1058 data->byte_endpos = data->byte_charpos; |
1059 data->byte_charpos = data->byte_start_col_enabled; | |
428 | 1060 |
1061 gb.extent = Qnil; | |
1062 gb.glyph = Vhscroll_glyph; | |
1063 { | |
1064 int oldpixpos = data->pixpos; | |
442 | 1065 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, |
428 | 1066 GLYPH_CACHEL (XWINDOW (data->window), |
1067 HSCROLL_GLYPH_INDEX)); | |
1068 data->hscroll_glyph_width_adjust = | |
1069 data->pixpos - oldpixpos - space_width (XWINDOW (data->window)); | |
1070 } | |
826 | 1071 data->byte_endpos = 0; |
1072 data->byte_cursor_charpos = byte_old_cursor_charpos; | |
428 | 1073 data->cursor_type = old_cursor_type; |
826 | 1074 data->byte_charpos = byte_old_charpos; |
1075 | |
1076 data->byte_start_col_enabled = 0; | |
428 | 1077 return retval; |
1078 } | |
1079 | |
793 | 1080 /* Adds a character rune to a display block. If there is not enough room |
1081 to fit the rune on the display block (as determined by the MAX_PIXPOS) | |
1082 then it adds nothing and returns ADD_FAILED. If | |
1083 NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't allow the char's height | |
867 | 1084 to affect the total line height. (See add_ibyte_string_runes()). */ |
428 | 1085 |
1086 static prop_block_dynarr * | |
867 | 1087 add_ichar_rune_1 (pos_data *data, int no_contribute_to_line_height) |
428 | 1088 { |
1089 struct rune rb, *crb; | |
1090 int width, local; | |
1091 | |
1092 if (data->start_col) | |
1093 { | |
1094 data->start_col--; | |
1095 | |
1096 if (data->start_col) | |
1097 return NULL; | |
1098 } | |
1099 | |
826 | 1100 if (data->byte_start_col_enabled) |
428 | 1101 { |
1102 return add_hscroll_rune (data); | |
1103 } | |
1104 | |
1105 if (data->ch == '\n') | |
1106 { | |
1107 data->font_is_bogus = 0; | |
1108 /* Cheesy end-of-line pseudo-character. */ | |
1109 width = data->blank_width; | |
1110 } | |
1111 else | |
1112 { | |
867 | 1113 Lisp_Object charset = ichar_charset (data->ch); |
428 | 1114 if (!EQ (charset, data->last_charset) || |
1115 data->findex != data->last_findex) | |
1116 { | |
1117 /* OK, we need to do things the hard way. */ | |
1118 struct window *w = XWINDOW (data->window); | |
1119 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex); | |
1120 Lisp_Object font_instance = | |
1121 ensure_face_cachel_contains_charset (cachel, data->window, | |
1122 charset); | |
440 | 1123 Lisp_Font_Instance *fi; |
428 | 1124 |
1125 if (EQ (font_instance, Vthe_null_font_instance)) | |
1126 { | |
1127 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); | |
1128 data->font_is_bogus = 1; | |
1129 } | |
1130 else | |
1131 data->font_is_bogus = 0; | |
1132 | |
1133 fi = XFONT_INSTANCE (font_instance); | |
771 | 1134 if (!fi->proportional_p || data->font_is_bogus) |
1135 { | |
867 | 1136 Ichar ch = data->font_is_bogus ? '~' : data->ch; |
771 | 1137 |
1138 data->last_char_width = | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1139 redisplay_window_text_width_ichar_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1140 (XWINDOW (data->window), data->findex, &ch, 1); |
771 | 1141 } |
428 | 1142 else |
1143 data->last_char_width = -1; | |
819 | 1144 |
793 | 1145 if (!no_contribute_to_line_height) |
1146 { | |
1147 data->new_ascent = max (data->new_ascent, (int) fi->ascent); | |
1148 data->new_descent = max (data->new_descent, (int) fi->descent); | |
1149 } | |
819 | 1150 |
428 | 1151 data->last_charset = charset; |
1152 data->last_findex = data->findex; | |
1153 } | |
1154 | |
1155 width = data->last_char_width; | |
771 | 1156 if (width < 0) /* proportional fonts */ |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1157 width = redisplay_window_text_width_ichar_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1158 (XWINDOW (data->window), data->findex, &data->ch, 1); |
428 | 1159 } |
1160 | |
1161 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos)) | |
1162 { | |
1163 return ADD_FAILED; | |
1164 } | |
1165 | |
1166 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes)) | |
1167 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
1168 crb = Dynarr_past_lastp (data->db->runes); |
428 | 1169 local = 0; |
1170 } | |
1171 else | |
1172 { | |
1173 crb = &rb; | |
1174 local = 1; | |
1175 } | |
1176 | |
1177 crb->findex = data->findex; | |
1178 crb->xpos = data->pixpos; | |
1179 crb->width = width; | |
826 | 1180 if (data->byte_charpos) |
428 | 1181 { |
1182 if (NILP (data->string)) | |
826 | 1183 crb->charpos = |
793 | 1184 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER |
1185 (XWINDOW (data->window))), | |
826 | 1186 data->byte_charpos); |
428 | 1187 else |
826 | 1188 crb->charpos = |
1189 string_index_byte_to_char (data->string, data->byte_charpos); | |
428 | 1190 } |
1191 else if (data->is_modeline) | |
826 | 1192 crb->charpos = data->modeline_charpos; |
428 | 1193 else |
442 | 1194 /* Text but not in buffer */ |
826 | 1195 crb->charpos = 0; |
428 | 1196 crb->type = RUNE_CHAR; |
1197 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch; | |
1198 crb->endpos = 0; | |
1199 | |
1200 if (data->cursor_type == CURSOR_ON) | |
1201 { | |
826 | 1202 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 1203 { |
1204 crb->cursor_type = CURSOR_ON; | |
1205 data->cursor_x = Dynarr_length (data->db->runes); | |
1206 } | |
1207 else | |
1208 crb->cursor_type = CURSOR_OFF; | |
1209 } | |
1210 else if (data->cursor_type == NEXT_CURSOR) | |
1211 { | |
1212 crb->cursor_type = CURSOR_ON; | |
1213 data->cursor_x = Dynarr_length (data->db->runes); | |
1214 data->cursor_type = NO_CURSOR; | |
1215 } | |
1216 else if (data->cursor_type == IGNORE_CURSOR) | |
1217 crb->cursor_type = IGNORE_CURSOR; | |
1218 else | |
1219 crb->cursor_type = CURSOR_OFF; | |
1220 | |
1221 if (local) | |
1222 Dynarr_add (data->db->runes, *crb); | |
1223 else | |
1224 Dynarr_increment (data->db->runes); | |
1225 | |
1226 data->pixpos += width; | |
1227 | |
1228 return NULL; | |
1229 } | |
1230 | |
793 | 1231 static prop_block_dynarr * |
867 | 1232 add_ichar_rune (pos_data *data) |
1233 { | |
1234 return add_ichar_rune_1 (data, 0); | |
1235 } | |
1236 | |
1237 /* Given a string C_STRING of length C_LENGTH, call add_ichar_rune for | |
793 | 1238 each character in the string. Propagate any left-over data unless |
1239 NO_PROP is non-zero. If NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't | |
1240 allow this character to increase the total height of the line. (This is | |
1241 used when the character is part of a text glyph. In that case, the | |
1242 glyph code itself adjusts the line height as necessary, depending on | |
1243 whether glyph-contrib-p is true.) */ | |
428 | 1244 |
1245 static prop_block_dynarr * | |
867 | 1246 add_ibyte_string_runes (pos_data *data, Ibyte *c_string, |
793 | 1247 Bytecount c_length, int no_prop, |
1248 int no_contribute_to_line_height) | |
428 | 1249 { |
867 | 1250 Ibyte *pos, *end = c_string + c_length; |
428 | 1251 prop_block_dynarr *prop; |
1252 | |
1253 /* #### This function is too simplistic. It needs to do the same | |
1254 sort of character interpretation (display-table lookup, | |
1255 ctl-arrow checking), etc. that create_text_block() does. | |
1256 The functionality to do this in that routine needs to be | |
1257 modularized. */ | |
1258 | |
1259 for (pos = c_string; pos < end;) | |
1260 { | |
867 | 1261 Ibyte *old_pos = pos; |
1262 | |
1263 data->ch = itext_ichar (pos); | |
1264 | |
1265 prop = add_ichar_rune_1 (data, no_contribute_to_line_height); | |
428 | 1266 |
1267 if (prop) | |
1268 { | |
1269 if (no_prop) | |
1270 return ADD_FAILED; | |
1271 else | |
1272 { | |
1273 struct prop_block pb; | |
1274 Bytecount len = end - pos; | |
1275 prop = Dynarr_new (prop_block); | |
1276 | |
1277 pb.type = PROP_STRING; | |
867 | 1278 pb.data.p_string.str = xnew_array (Ibyte, len); |
428 | 1279 strncpy ((char *) pb.data.p_string.str, (char *) pos, len); |
1280 pb.data.p_string.len = len; | |
1281 | |
1282 Dynarr_add (prop, pb); | |
1283 return prop; | |
1284 } | |
1285 } | |
867 | 1286 INC_IBYTEPTR (pos); |
428 | 1287 assert (pos <= end); |
464 | 1288 /* #### Duplicate code from add_string_to_fstring_db_runes |
1289 should we do more?*/ | |
1290 data->bytepos += pos - old_pos; | |
428 | 1291 } |
1292 | |
1293 return NULL; | |
1294 } | |
1295 | |
1296 /* Add a single rune of the specified width. The area covered by this | |
1297 rune will be displayed in the foreground color of the associated | |
1298 face. */ | |
1299 | |
1300 static prop_block_dynarr * | |
1301 add_blank_rune (pos_data *data, struct window *w, int char_tab_width) | |
1302 { | |
1303 struct rune rb; | |
1304 | |
1305 /* If data->start_col is not 0 then this call to add_blank_rune must have | |
1306 been to add it as a tab. */ | |
1307 if (data->start_col) | |
1308 { | |
1309 /* assert (w != NULL) */ | |
1310 prop_block_dynarr *retval; | |
1311 | |
1312 /* If we have still not fully scrolled horizontally, subtract | |
4187 | 1313 the width of this tab and return. */ |
428 | 1314 if (char_tab_width < data->start_col) |
1315 { | |
1316 data->start_col -= char_tab_width; | |
1317 return NULL; | |
1318 } | |
1319 else if (char_tab_width == data->start_col) | |
1320 data->blank_width = 0; | |
1321 else | |
1322 { | |
1323 int spcwid = space_width (w); | |
1324 | |
1325 if (spcwid >= data->blank_width) | |
1326 data->blank_width = 0; | |
1327 else | |
1328 data->blank_width -= spcwid; | |
1329 } | |
1330 | |
1331 data->start_col = 0; | |
1332 retval = add_hscroll_rune (data); | |
1333 | |
1334 /* Could be caused by the handling of the hscroll rune. */ | |
1335 if (retval != NULL || !data->blank_width) | |
1336 return retval; | |
1337 } | |
1338 | |
1339 /* Blank runes are always calculated to fit. */ | |
1340 assert (data->pixpos + data->blank_width <= data->max_pixpos); | |
1341 | |
1342 rb.findex = data->findex; | |
1343 rb.xpos = data->pixpos; | |
1344 rb.width = data->blank_width; | |
826 | 1345 if (data->byte_charpos) |
1346 rb.charpos = | |
665 | 1347 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))), |
826 | 1348 data->byte_charpos); |
428 | 1349 else |
1350 /* #### and this is really correct too? */ | |
826 | 1351 rb.charpos = 0; |
428 | 1352 rb.endpos = 0; |
1353 rb.type = RUNE_BLANK; | |
1354 | |
1355 if (data->cursor_type == CURSOR_ON) | |
1356 { | |
826 | 1357 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 1358 { |
1359 rb.cursor_type = CURSOR_ON; | |
1360 data->cursor_x = Dynarr_length (data->db->runes); | |
1361 } | |
1362 else | |
1363 rb.cursor_type = CURSOR_OFF; | |
1364 } | |
1365 else if (data->cursor_type == NEXT_CURSOR) | |
1366 { | |
1367 rb.cursor_type = CURSOR_ON; | |
1368 data->cursor_x = Dynarr_length (data->db->runes); | |
1369 data->cursor_type = NO_CURSOR; | |
1370 } | |
1371 else | |
1372 rb.cursor_type = CURSOR_OFF; | |
1373 | |
1374 Dynarr_add (data->db->runes, rb); | |
1375 data->pixpos += data->blank_width; | |
1376 | |
1377 return NULL; | |
1378 } | |
1379 | |
1380 /* Add runes representing a character in octal. */ | |
1381 | |
1382 #define ADD_NEXT_OCTAL_RUNE_CHAR do \ | |
1383 { \ | |
867 | 1384 if (add_failed || (add_failed = add_ichar_rune (data))) \ |
428 | 1385 { \ |
1386 struct prop_block pb; \ | |
1387 if (!prop) \ | |
1388 prop = Dynarr_new (prop_block); \ | |
1389 \ | |
1390 pb.type = PROP_CHAR; \ | |
1391 pb.data.p_char.ch = data->ch; \ | |
1392 pb.data.p_char.cursor_type = data->cursor_type; \ | |
1393 Dynarr_add (prop, pb); \ | |
1394 } \ | |
1395 } while (0) | |
1396 | |
1397 static prop_block_dynarr * | |
1398 add_octal_runes (pos_data *data) | |
1399 { | |
819 | 1400 prop_block_dynarr *add_failed, *prop = 0; |
867 | 1401 Ichar orig_char = data->ch; |
647 | 1402 int orig_cursor_type = data->cursor_type; |
428 | 1403 |
1404 /* Initialize */ | |
1405 add_failed = NULL; | |
1406 | |
1407 if (data->start_col) | |
1408 data->start_col--; | |
1409 | |
1410 if (!data->start_col) | |
1411 { | |
826 | 1412 if (data->byte_start_col_enabled) |
428 | 1413 { |
1414 add_failed = add_hscroll_rune (data); | |
1415 } | |
1416 else | |
1417 { | |
1418 struct glyph_block gb; | |
1419 struct window *w = XWINDOW (data->window); | |
1420 | |
1421 gb.extent = Qnil; | |
1422 gb.glyph = Voctal_escape_glyph; | |
1423 add_failed = | |
1424 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
1425 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX)); | |
1426 } | |
1427 } | |
1428 | |
1429 /* We only propagate information if the glyph was partially | |
1430 added. */ | |
1431 if (add_failed) | |
1432 return add_failed; | |
1433 | |
1434 data->cursor_type = IGNORE_CURSOR; | |
1435 | |
1436 if (data->ch >= 0x100) | |
1437 { | |
1438 /* If the character is an extended Mule character, it could have | |
3498 | 1439 up to 21 bits. For the moment, we treat it as a seven-digit |
428 | 1440 octal number. This is not that pretty, but whatever. */ |
1441 data->ch = (7 & (orig_char >> 18)) + '0'; | |
1442 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1443 | |
1444 data->ch = (7 & (orig_char >> 15)) + '0'; | |
1445 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1446 | |
1447 data->ch = (7 & (orig_char >> 12)) + '0'; | |
1448 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1449 | |
1450 data->ch = (7 & (orig_char >> 9)) + '0'; | |
1451 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1452 } | |
1453 | |
1454 data->ch = (7 & (orig_char >> 6)) + '0'; | |
1455 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1456 | |
1457 data->ch = (7 & (orig_char >> 3)) + '0'; | |
1458 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1459 | |
1460 data->ch = (7 & orig_char) + '0'; | |
1461 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1462 | |
1463 data->cursor_type = orig_cursor_type; | |
819 | 1464 return NULL; |
428 | 1465 } |
1466 | |
1467 #undef ADD_NEXT_OCTAL_RUNE_CHAR | |
1468 | |
1469 /* Add runes representing a control character to a display block. */ | |
1470 | |
1471 static prop_block_dynarr * | |
1472 add_control_char_runes (pos_data *data, struct buffer *b) | |
1473 { | |
1474 if (!NILP (b->ctl_arrow)) | |
1475 { | |
1476 prop_block_dynarr *prop; | |
867 | 1477 Ichar orig_char = data->ch; |
647 | 1478 int old_cursor_type = data->cursor_type; |
428 | 1479 |
1480 /* Initialize */ | |
1481 prop = NULL; | |
1482 | |
1483 if (data->start_col) | |
1484 data->start_col--; | |
1485 | |
1486 if (!data->start_col) | |
1487 { | |
826 | 1488 if (data->byte_start_col_enabled) |
428 | 1489 { |
1490 prop_block_dynarr *retval; | |
1491 | |
1492 retval = add_hscroll_rune (data); | |
1493 if (retval) | |
1494 return retval; | |
1495 } | |
1496 else | |
1497 { | |
1498 struct glyph_block gb; | |
1499 struct window *w = XWINDOW (data->window); | |
1500 | |
1501 gb.extent = Qnil; | |
1502 gb.glyph = Vcontrol_arrow_glyph; | |
1503 | |
1504 /* We only propagate information if the glyph was partially | |
1505 added. */ | |
1506 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
1507 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX))) | |
1508 return ADD_FAILED; | |
1509 } | |
1510 } | |
1511 | |
1512 if (orig_char == 0177) | |
1513 data->ch = '?'; | |
1514 else | |
1515 data->ch = orig_char ^ 0100; | |
1516 data->cursor_type = IGNORE_CURSOR; | |
1517 | |
867 | 1518 if (add_ichar_rune (data)) |
428 | 1519 { |
1520 struct prop_block pb; | |
1521 if (!prop) | |
1522 prop = Dynarr_new (prop_block); | |
1523 | |
1524 pb.type = PROP_CHAR; | |
1525 pb.data.p_char.ch = data->ch; | |
1526 pb.data.p_char.cursor_type = data->cursor_type; | |
1527 Dynarr_add (prop, pb); | |
1528 } | |
1529 | |
1530 data->cursor_type = old_cursor_type; | |
1531 return prop; | |
1532 } | |
1533 else | |
1534 { | |
1535 return add_octal_runes (data); | |
1536 } | |
1537 } | |
1538 | |
1539 static prop_block_dynarr * | |
1540 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) | |
1541 { | |
1542 prop_block_dynarr *prop = NULL; | |
1543 | |
1544 if (STRINGP (entry)) | |
1545 { | |
867 | 1546 prop = add_ibyte_string_runes (data, |
428 | 1547 XSTRING_DATA (entry), |
1548 XSTRING_LENGTH (entry), | |
793 | 1549 0, 0); |
428 | 1550 } |
1551 else if (GLYPHP (entry)) | |
1552 { | |
1553 if (data->start_col) | |
1554 data->start_col--; | |
1555 | |
826 | 1556 if (!data->start_col && data->byte_start_col_enabled) |
428 | 1557 { |
1558 prop = add_hscroll_rune (data); | |
1559 } | |
1560 else | |
1561 { | |
1562 struct glyph_block gb; | |
1563 | |
1564 gb.glyph = entry; | |
1565 gb.extent = Qnil; | |
1566 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); | |
1567 } | |
1568 } | |
1569 else if (CHAR_OR_CHAR_INTP (entry)) | |
1570 { | |
1571 data->ch = XCHAR_OR_CHAR_INT (entry); | |
867 | 1572 prop = add_ichar_rune (data); |
428 | 1573 } |
1574 else if (CONSP (entry)) | |
1575 { | |
1576 if (EQ (XCAR (entry), Qformat) | |
1577 && CONSP (XCDR (entry)) | |
1578 && STRINGP (XCAR (XCDR (entry)))) | |
1579 { | |
1580 Lisp_Object format = XCAR (XCDR (entry)); | |
665 | 1581 Bytebpos len = XSTRING_LENGTH (format); |
867 | 1582 Ibyte *src = XSTRING_DATA (format), *end = src + len; |
2367 | 1583 Ibyte *result = alloca_ibytes (len); |
867 | 1584 Ibyte *dst = result; |
428 | 1585 |
1586 while (src < end) | |
1587 { | |
867 | 1588 Ichar c = itext_ichar (src); |
1589 INC_IBYTEPTR (src); | |
428 | 1590 if (c != '%' || src == end) |
867 | 1591 dst += set_itext_ichar (dst, c); |
428 | 1592 else |
1593 { | |
867 | 1594 c = itext_ichar (src); |
1595 INC_IBYTEPTR (src); | |
428 | 1596 switch (c) |
1597 { | |
1598 /*case 'x': | |
1599 dst += long_to_string_base ((char *)dst, data->ch, 16); | |
1600 break;*/ | |
1601 case '%': | |
867 | 1602 dst += set_itext_ichar (dst, '%'); |
428 | 1603 break; |
442 | 1604 /* #### unimplemented */ |
428 | 1605 } |
1606 } | |
1607 } | |
867 | 1608 prop = add_ibyte_string_runes (data, result, dst - result, 0, 0); |
428 | 1609 } |
1610 } | |
1611 | |
1612 /* Else blow it off because someone added a bad entry and we don't | |
1613 have any safe way of signaling an error. */ | |
1614 return prop; | |
1615 } | |
1616 | |
1617 /* Given a display table entry, call the appropriate functions to | |
1618 display each element of the entry. */ | |
1619 | |
1620 static prop_block_dynarr * | |
1621 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) | |
1622 { | |
1623 prop_block_dynarr *prop = NULL; | |
1624 if (VECTORP (entry)) | |
1625 { | |
440 | 1626 Lisp_Vector *de = XVECTOR (entry); |
428 | 1627 EMACS_INT len = vector_length (de); |
1628 int elt; | |
1629 | |
1630 for (elt = 0; elt < len; elt++) | |
1631 { | |
1632 if (NILP (vector_data (de)[elt])) | |
1633 continue; | |
1634 else | |
1635 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]); | |
1636 /* Else blow it off because someone added a bad entry and we | |
1637 don't have any safe way of signaling an error. Hey, this | |
1638 comment sounds familiar. */ | |
1639 | |
1640 /* #### Still need to add any remaining elements to the | |
4187 | 1641 propagation information. */ |
428 | 1642 if (prop) |
1643 return prop; | |
1644 } | |
1645 } | |
1646 else | |
1647 prop = add_disp_table_entry_runes_1 (data, entry); | |
1648 return prop; | |
1649 } | |
1650 | |
1651 /* Add runes which were propagated from the previous line. */ | |
1652 | |
1653 static prop_block_dynarr * | |
1654 add_propagation_runes (prop_block_dynarr **prop, pos_data *data) | |
1655 { | |
1656 /* #### Remember to handle start_col parameter of data when the rest of | |
1657 this is finished. */ | |
1658 /* #### Chuck -- I've redone this function a bit. It looked like the | |
1659 case of not all the propagation blocks being added was not handled | |
1660 well. */ | |
1661 /* #### Chuck -- I also think the double indirection of PROP is kind | |
1662 of bogus. A cleaner solution is just to check for | |
1663 Dynarr_length (prop) > 0. */ | |
1664 /* #### This function also doesn't even pay attention to ADD_FAILED! | |
1665 This is seriously fucked! Seven ####'s in 130 lines -- is that a | |
1666 record? */ | |
1667 int elt; | |
1668 prop_block_dynarr *add_failed; | |
826 | 1669 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
647 | 1670 int old_cursor_type = data->cursor_type; |
428 | 1671 |
1672 for (elt = 0; elt < Dynarr_length (*prop); elt++) | |
1673 { | |
1674 struct prop_block *pb = Dynarr_atp (*prop, elt); | |
1675 | |
1676 switch (pb->type) | |
1677 { | |
1678 case PROP_CHAR: | |
1679 data->ch = pb->data.p_char.ch; | |
826 | 1680 data->byte_cursor_charpos = pb->data.p_char.byte_cursor_charpos; |
428 | 1681 data->cursor_type = pb->data.p_char.cursor_type; |
867 | 1682 add_failed = add_ichar_rune (data); |
428 | 1683 |
1684 if (add_failed) | |
1685 goto oops_no_more_space; | |
1686 break; | |
1687 case PROP_STRING: | |
1688 if (pb->data.p_string.str) | |
1726 | 1689 xfree (pb->data.p_string.str, Ibyte *); |
428 | 1690 /* #### bogus bogus -- this doesn't do anything! |
867 | 1691 Should probably call add_ibyte_string_runes(), |
428 | 1692 once that function is fixed. */ |
1693 break; | |
1694 case PROP_MINIBUF_PROMPT: | |
1695 { | |
1696 face_index old_findex = data->findex; | |
826 | 1697 Bytebpos byte_old_charpos = data->byte_charpos; |
428 | 1698 |
1699 data->findex = DEFAULT_INDEX; | |
826 | 1700 data->byte_charpos = 0; |
428 | 1701 data->cursor_type = NO_CURSOR; |
1702 | |
1703 while (pb->data.p_string.len > 0) | |
1704 { | |
867 | 1705 data->ch = itext_ichar (pb->data.p_string.str); |
1706 add_failed = add_ichar_rune (data); | |
428 | 1707 |
1708 if (add_failed) | |
1709 { | |
1710 data->findex = old_findex; | |
826 | 1711 data->byte_charpos = byte_old_charpos; |
428 | 1712 goto oops_no_more_space; |
1713 } | |
1714 else | |
1715 { | |
1716 /* Complicated equivalent of ptr++, len-- */ | |
867 | 1717 Ibyte *oldpos = pb->data.p_string.str; |
1718 INC_IBYTEPTR (pb->data.p_string.str); | |
428 | 1719 pb->data.p_string.len -= pb->data.p_string.str - oldpos; |
1720 } | |
1721 } | |
1722 | |
1723 data->findex = old_findex; | |
1724 /* ##### FIXME FIXME FIXME -- Upon successful return from | |
826 | 1725 this function, data->byte_charpos is automatically incremented. |
428 | 1726 However, we don't want that to happen if we were adding |
1727 the minibuffer prompt. */ | |
1728 { | |
1729 struct buffer *buf = | |
1730 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))); | |
1731 /* #### Chuck fix this shit or I'm gonna scream! */ | |
826 | 1732 if (byte_old_charpos > BYTE_BUF_BEGV (buf)) |
4187 | 1733 data->byte_charpos = prev_bytebpos (buf, byte_old_charpos); |
1734 else | |
428 | 1735 /* #### is this correct? Does anyone know? |
1736 Does anyone care? Is this a cheesy hack or what? */ | |
4187 | 1737 data->byte_charpos = BYTE_BUF_BEGV (buf) - 1; |
428 | 1738 } |
1739 } | |
1740 break; | |
1741 case PROP_BLANK: | |
1742 { | |
1743 /* #### I think it's unnecessary and misleading to preserve | |
1744 the blank_width, as it implies that the value carries | |
1745 over from one rune to the next, which is wrong. */ | |
1746 int old_width = data->blank_width; | |
1747 face_index old_findex = data->findex; | |
1748 | |
1749 data->findex = pb->data.p_blank.findex; | |
1750 data->blank_width = pb->data.p_blank.width; | |
826 | 1751 data->byte_cursor_charpos = 0; |
428 | 1752 data->cursor_type = IGNORE_CURSOR; |
1753 | |
1754 if (data->pixpos + data->blank_width > data->max_pixpos) | |
1755 data->blank_width = data->max_pixpos - data->pixpos; | |
1756 | |
1757 /* We pass a bogus value of char_tab_width. It shouldn't | |
4187 | 1758 matter because unless something is really screwed up |
1759 this call won't cause that arg to be used. */ | |
428 | 1760 add_failed = add_blank_rune (data, XWINDOW (data->window), 0); |
1761 | |
1762 /* This can happen in the case where we have a tab which | |
4187 | 1763 is wider than the window. */ |
428 | 1764 if (data->blank_width != pb->data.p_blank.width) |
1765 { | |
1766 pb->data.p_blank.width -= data->blank_width; | |
1767 add_failed = ADD_FAILED; | |
1768 } | |
1769 | |
1770 data->findex = old_findex; | |
1771 data->blank_width = old_width; | |
1772 | |
1773 if (add_failed) | |
1774 goto oops_no_more_space; | |
1775 } | |
1776 break; | |
1777 default: | |
2500 | 1778 ABORT (); |
428 | 1779 } |
1780 } | |
1781 | |
1782 oops_no_more_space: | |
1783 | |
826 | 1784 data->byte_cursor_charpos = byte_old_cursor_charpos; |
428 | 1785 data->cursor_type = old_cursor_type; |
1786 if (elt < Dynarr_length (*prop)) | |
1787 { | |
1788 Dynarr_delete_many (*prop, 0, elt); | |
1789 return *prop; | |
1790 } | |
1791 else | |
1792 { | |
1793 Dynarr_free (*prop); | |
1794 return NULL; | |
1795 } | |
1796 } | |
1797 | |
3025 | 1798 /* Add `text' layout glyphs at position POS_TYPE that are contained to |
428 | 1799 the display block, but add all other types to the appropriate list |
1800 of the display line. They will be added later by different | |
1801 routines. */ | |
1802 | |
1803 static prop_block_dynarr * | |
1804 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, | |
1805 int allow_cursor, struct glyph_cachel *cachel) | |
1806 { | |
1807 struct window *w = XWINDOW (data->window); | |
1808 | |
440 | 1809 /* If window faces changed, and glyph instance is text, then |
1810 glyph sizes might have changed too */ | |
1811 invalidate_glyph_geometry_maybe (gb->glyph, w); | |
1812 | |
442 | 1813 /* This makes sure the glyph is in the cachels. |
1814 | |
1815 #### We do this to make sure the glyph is in the glyph cachels, | |
1816 so that the dirty flag can be reset after redisplay has | |
1817 finished. We should do this some other way, maybe by iterating | |
1818 over the window cache of subwindows. */ | |
1819 get_glyph_cachel_index (w, gb->glyph); | |
1820 | |
428 | 1821 /* A nil extent indicates a special glyph (ex. truncator). */ |
1822 if (NILP (gb->extent) | |
1823 || (pos_type == BEGIN_GLYPHS && | |
1824 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) | |
1825 || (pos_type == END_GLYPHS && | |
442 | 1826 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) |
1827 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) | |
428 | 1828 { |
1829 struct rune rb; | |
1830 int width; | |
1831 int xoffset = 0; | |
1832 int ascent, descent; | |
1833 Lisp_Object baseline; | |
1834 Lisp_Object face; | |
442 | 1835 Lisp_Object instance; |
1836 face_index findex; | |
819 | 1837 prop_block_dynarr *retval = 0; |
428 | 1838 |
1839 if (cachel) | |
1840 width = cachel->width; | |
1841 else | |
438 | 1842 width = glyph_width (gb->glyph, data->window); |
428 | 1843 |
1844 if (!width) | |
1845 return NULL; | |
1846 | |
1847 if (data->start_col || data->start_col_xoffset) | |
1848 { | |
1849 int glyph_char_width = width / space_width (w); | |
1850 | |
1851 /* If we still have not fully scrolled horizontally after | |
4187 | 1852 taking into account the width of the glyph, subtract its |
1853 width and return. */ | |
428 | 1854 if (glyph_char_width < data->start_col) |
1855 { | |
1856 data->start_col -= glyph_char_width; | |
1857 return NULL; | |
1858 } | |
1859 else if (glyph_char_width == data->start_col) | |
1860 width = 0; | |
1861 else | |
1862 { | |
1863 xoffset = space_width (w) * data->start_col; | |
1864 width -= xoffset; | |
1865 | |
1866 /* #### Can this happen? */ | |
1867 if (width < 0) | |
1868 width = 0; | |
1869 } | |
1870 | |
1871 data->start_col = 0; | |
1872 retval = add_hscroll_rune (data); | |
1873 | |
1874 /* Could be caused by the handling of the hscroll rune. */ | |
1875 if (retval != NULL || !width) | |
1876 return retval; | |
1877 } | |
1878 else | |
1879 xoffset = 0; | |
1880 | |
1881 if (data->pixpos + width > data->max_pixpos) | |
1882 { | |
1883 /* If this is the first object we are attempting to add to | |
819 | 1884 the line then we ignore the horizontal_clip threshold. |
1885 Otherwise we will loop until the bottom of the window | |
1886 continually failing to add this glyph because it is wider | |
1887 than the window. We could alternatively just completely | |
1888 ignore the glyph and proceed from there but I think that | |
1889 this is a better solution. | |
4187 | 1890 |
819 | 1891 This does, however, create a different problem in that we |
1892 can end up adding the object to every single line, never | |
1893 getting any further - for instance an extent with a long | |
1894 start-glyph that covers multitple following | |
1895 characters. */ | |
428 | 1896 if (Dynarr_length (data->db->runes) |
1897 && data->max_pixpos - data->pixpos < horizontal_clip) | |
1898 return ADD_FAILED; | |
819 | 1899 else { |
1900 struct prop_block pb; | |
1901 | |
1902 /* We need to account for the width of the end-of-line | |
1903 glyph if there is nothing more in the line to display, | |
1904 since we will not display it in this instance. It seems | |
1905 kind of gross doing it here, but otherwise we have to | |
1906 search the runes in create_text_block(). */ | |
1907 if (data->ch == '\n') | |
1908 data->max_pixpos += data->end_glyph_width; | |
428 | 1909 width = data->max_pixpos - data->pixpos; |
819 | 1910 /* Add the glyph we are displaying, but clipping, to the |
1911 propagation data so that we don't try and do it | |
4187 | 1912 again. */ |
819 | 1913 retval = Dynarr_new (prop_block); |
1914 pb.type = PROP_GLYPH; | |
1915 pb.data.p_glyph.glyph = gb->glyph; | |
1916 pb.data.p_glyph.width = width; | |
1917 Dynarr_add (retval, pb); | |
1918 } | |
428 | 1919 } |
1920 | |
1921 if (cachel) | |
1922 { | |
1923 ascent = cachel->ascent; | |
1924 descent = cachel->descent; | |
1925 } | |
1926 else | |
1927 { | |
438 | 1928 ascent = glyph_ascent (gb->glyph, data->window); |
1929 descent = glyph_descent (gb->glyph, data->window); | |
428 | 1930 } |
1931 | |
1932 baseline = glyph_baseline (gb->glyph, data->window); | |
1933 | |
819 | 1934 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ |
1935 | |
428 | 1936 if (glyph_contrib_p (gb->glyph, data->window)) |
1937 { | |
1938 /* A pixmap that has not had a baseline explicitly set. Its | |
1939 contribution will be determined later. */ | |
1940 if (NILP (baseline)) | |
1941 { | |
1942 int height = ascent + descent; | |
819 | 1943 data->need_baseline_computation = 1; |
428 | 1944 data->max_pixmap_height = max (data->max_pixmap_height, height); |
1945 } | |
1946 | |
1947 /* A string so determine contribution normally. */ | |
1948 else if (EQ (baseline, Qt)) | |
1949 { | |
1950 data->new_ascent = max (data->new_ascent, ascent); | |
1951 data->new_descent = max (data->new_descent, descent); | |
1952 } | |
1953 | |
1954 /* A pixmap with an explicitly set baseline. We determine the | |
1955 contribution here. */ | |
1956 else if (INTP (baseline)) | |
1957 { | |
1958 int height = ascent + descent; | |
1959 int pix_ascent, pix_descent; | |
1960 | |
1961 pix_ascent = height * XINT (baseline) / 100; | |
1962 pix_descent = height - pix_ascent; | |
1963 | |
1964 data->new_ascent = max (data->new_ascent, pix_ascent); | |
1965 data->new_descent = max (data->new_descent, pix_descent); | |
819 | 1966 data->max_pixmap_height = max (data->max_pixmap_height, height); |
4187 | 1967 |
819 | 1968 rb.object.dglyph.descent = pix_descent; |
428 | 1969 } |
1970 | |
1971 /* Otherwise something is screwed up. */ | |
1972 else | |
2500 | 1973 ABORT (); |
428 | 1974 } |
1975 | |
1976 face = glyph_face (gb->glyph, data->window); | |
1977 if (NILP (face)) | |
442 | 1978 findex = data->findex; |
428 | 1979 else |
442 | 1980 findex = get_builtin_face_cache_index (w, face); |
1981 | |
1982 instance = glyph_image_instance (gb->glyph, data->window, | |
793 | 1983 ERROR_ME_DEBUG_WARN, 1); |
442 | 1984 if (TEXT_IMAGE_INSTANCEP (instance)) |
1985 { | |
1986 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); | |
1987 face_index orig_findex = data->findex; | |
826 | 1988 Bytebpos orig_charpos = data->byte_charpos; |
1989 Bytebpos orig_start_col_enabled = data->byte_start_col_enabled; | |
442 | 1990 |
1991 data->findex = findex; | |
826 | 1992 data->byte_start_col_enabled = 0; |
442 | 1993 if (!allow_cursor) |
826 | 1994 data->byte_charpos = 0; |
867 | 1995 add_ibyte_string_runes (data, XSTRING_DATA (string), |
793 | 1996 XSTRING_LENGTH (string), 0, 1); |
442 | 1997 data->findex = orig_findex; |
826 | 1998 data->byte_charpos = orig_charpos; |
1999 data->byte_start_col_enabled = orig_start_col_enabled; | |
819 | 2000 return retval; |
442 | 2001 } |
2002 | |
2003 rb.findex = findex; | |
428 | 2004 rb.xpos = data->pixpos; |
2005 rb.width = width; | |
826 | 2006 rb.charpos = 0; /* glyphs are never "at" anywhere */ |
2007 if (data->byte_endpos) | |
428 | 2008 /* #### is this necessary at all? */ |
665 | 2009 rb.endpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
826 | 2010 data->byte_endpos); |
428 | 2011 else |
4187 | 2012 rb.endpos = 0; |
428 | 2013 rb.type = RUNE_DGLYPH; |
2014 rb.object.dglyph.glyph = gb->glyph; | |
2015 rb.object.dglyph.extent = gb->extent; | |
2016 rb.object.dglyph.xoffset = xoffset; | |
819 | 2017 rb.object.dglyph.ascent = ascent; |
2018 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has | |
2019 a normal (textual) baseline. */ | |
428 | 2020 |
2021 if (allow_cursor) | |
2022 { | |
826 | 2023 rb.charpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
2024 data->byte_charpos); | |
428 | 2025 |
2026 if (data->cursor_type == CURSOR_ON) | |
2027 { | |
826 | 2028 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 2029 { |
2030 rb.cursor_type = CURSOR_ON; | |
2031 data->cursor_x = Dynarr_length (data->db->runes); | |
2032 } | |
2033 else | |
2034 rb.cursor_type = CURSOR_OFF; | |
2035 } | |
2036 else if (data->cursor_type == NEXT_CURSOR) | |
2037 { | |
2038 rb.cursor_type = CURSOR_ON; | |
2039 data->cursor_x = Dynarr_length (data->db->runes); | |
2040 data->cursor_type = NO_CURSOR; | |
2041 } | |
2042 else if (data->cursor_type == IGNORE_CURSOR) | |
2043 rb.cursor_type = IGNORE_CURSOR; | |
2044 else if (data->cursor_type == NO_CURSOR) | |
2045 rb.cursor_type = NO_CURSOR; | |
2046 else | |
2047 rb.cursor_type = CURSOR_OFF; | |
2048 } | |
2049 else | |
2050 rb.cursor_type = CURSOR_OFF; | |
2051 | |
2052 Dynarr_add (data->db->runes, rb); | |
2053 data->pixpos += width; | |
2054 | |
819 | 2055 return retval; |
428 | 2056 } |
2057 else | |
2058 { | |
2059 if (!NILP (glyph_face (gb->glyph, data->window))) | |
2060 gb->findex = | |
2061 get_builtin_face_cache_index (w, glyph_face (gb->glyph, | |
2062 data->window)); | |
2063 else | |
2064 gb->findex = data->findex; | |
2065 | |
2066 if (pos_type == BEGIN_GLYPHS) | |
2067 { | |
2068 if (!data->dl->left_glyphs) | |
2069 data->dl->left_glyphs = Dynarr_new (glyph_block); | |
2070 Dynarr_add (data->dl->left_glyphs, *gb); | |
2071 return NULL; | |
2072 } | |
2073 else if (pos_type == END_GLYPHS) | |
2074 { | |
2075 if (!data->dl->right_glyphs) | |
2076 data->dl->right_glyphs = Dynarr_new (glyph_block); | |
2077 Dynarr_add (data->dl->right_glyphs, *gb); | |
2078 return NULL; | |
2079 } | |
2080 else | |
2500 | 2081 ABORT (); /* there are no unknown types */ |
428 | 2082 } |
2083 | |
819 | 2084 return NULL; |
428 | 2085 } |
2086 | |
2087 /* Add all glyphs at position POS_TYPE that are contained in the given | |
2088 data. */ | |
2089 | |
2090 static prop_block_dynarr * | |
2091 add_glyph_runes (pos_data *data, int pos_type) | |
2092 { | |
2093 /* #### This still needs to handle the start_col parameter. Duh, Chuck, | |
2094 why didn't you just modify add_glyph_rune in the first place? */ | |
2095 int elt; | |
2096 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS | |
2097 ? data->ef->begin_glyphs | |
2098 : data->ef->end_glyphs); | |
2099 prop_block_dynarr *prop; | |
2100 | |
2101 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++) | |
2102 { | |
2103 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0, | |
2104 0); | |
2105 | |
2106 if (prop) | |
2107 { | |
2108 /* #### Add some propagation information. */ | |
2109 return prop; | |
2110 } | |
2111 } | |
2112 | |
2113 Dynarr_reset (glyph_arr); | |
2114 | |
2115 return NULL; | |
2116 } | |
2117 | |
2118 /* Given a position for a buffer in a window, ensure that the given | |
2119 display line DL accurately represents the text on a line starting | |
2120 at the given position. | |
2121 | |
826 | 2122 NOTE NOTE NOTE NOTE: This function works with and returns Bytebpos's. |
428 | 2123 You must do appropriate conversion. */ |
2124 | |
665 | 2125 static Bytebpos |
428 | 2126 create_text_block (struct window *w, struct display_line *dl, |
826 | 2127 Bytebpos byte_start_pos, prop_block_dynarr **prop, |
428 | 2128 int type) |
2129 { | |
2130 struct frame *f = XFRAME (w->frame); | |
2131 struct buffer *b = XBUFFER (w->buffer); | |
2132 struct device *d = XDEVICE (f->device); | |
2133 | |
2134 pos_data data; | |
2135 | |
2136 /* Don't display anything in the minibuffer if this window is not on | |
2137 a selected frame. We consider all other windows to be active | |
2138 minibuffers as it simplifies the coding. */ | |
2139 int active_minibuffer = (!MINI_WINDOW_P (w) || | |
2140 (f == device_selected_frame (d)) || | |
2141 is_surrogate_for_selected_frame (f)); | |
2142 | |
2143 int truncate_win = window_truncation_on (w); | |
2144 | |
2145 /* If the buffer's value of selective_display is an integer then | |
2146 only lines that start with less than selective_display columns of | |
2147 space will be displayed. If selective_display is t then all text | |
2148 after a ^M is invisible. */ | |
2149 int selective = (INTP (b->selective_display) | |
2150 ? XINT (b->selective_display) | |
434 | 2151 : (!NILP (b->selective_display) ? -1 : 0)); |
428 | 2152 |
2153 /* The variable ctl-arrow allows the user to specify what characters | |
2154 can actually be displayed and which octal should be used for. | |
2155 #### This variable should probably have some rethought done to | |
2156 it. | |
2157 | |
2367 | 2158 See also |
2159 | |
2160 (Info-goto-node "(internals)Future Work -- Display Tables") | |
2161 | |
2162 */ | |
867 | 2163 Ichar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
428 | 2164 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
2165 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
2166 ? 255 : 160)); | |
2167 | |
2168 Lisp_Object face_dt, window_dt; | |
2169 | |
2170 /* The text display block for this display line. */ | |
2171 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
2172 | |
2173 /* The first time through the main loop we need to force the glyph | |
2174 data to be updated. */ | |
2175 int initial = 1; | |
2176 | |
2177 /* Apparently the new extent_fragment_update returns an end position | |
2178 equal to the position passed in if there are no more runs to be | |
2179 displayed. */ | |
2180 int no_more_frags = 0; | |
2181 | |
2182 Lisp_Object synch_minibuffers_value = | |
2183 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer); | |
2184 | |
2185 dl->used_prop_data = 0; | |
2186 dl->num_chars = 0; | |
442 | 2187 dl->line_continuation = 0; |
428 | 2188 |
2189 xzero (data); | |
2190 data.ef = extent_fragment_new (w->buffer, f); | |
2191 | |
2192 /* These values are used by all of the rune addition routines. We add | |
2193 them to this structure for ease of passing. */ | |
2194 data.d = d; | |
793 | 2195 data.window = wrap_window (w); |
428 | 2196 data.string = Qnil; |
2197 data.db = db; | |
2198 data.dl = dl; | |
2199 | |
826 | 2200 data.byte_charpos = byte_start_pos; |
428 | 2201 data.pixpos = dl->bounds.left_in; |
2202 data.last_charset = Qunbound; | |
2203 data.last_findex = DEFAULT_INDEX; | |
2204 data.result_str = Qnil; | |
2205 | |
2206 /* Set the right boundary adjusting it to take into account any end | |
2207 glyph. Save the width of the end glyph for later use. */ | |
2208 data.max_pixpos = dl->bounds.right_in; | |
2209 if (truncate_win) | |
819 | 2210 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); |
428 | 2211 else |
819 | 2212 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); |
2213 data.max_pixpos -= data.end_glyph_width; | |
428 | 2214 |
2215 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f)) | |
2216 { | |
826 | 2217 data.byte_cursor_charpos = BYTE_BUF_ZV (b); |
428 | 2218 data.cursor_type = CURSOR_ON; |
2219 } | |
2220 else if (MINI_WINDOW_P (w) && !active_minibuffer) | |
2221 data.cursor_type = NO_CURSOR; | |
2222 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) && | |
2223 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
2224 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&& | |
2225 f == XFRAME(DEVICE_SELECTED_FRAME(d))) | |
2226 { | |
826 | 2227 data.byte_cursor_charpos = BYTE_BUF_PT (b); |
428 | 2228 data.cursor_type = CURSOR_ON; |
2229 } | |
2230 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | |
2231 { | |
826 | 2232 data.byte_cursor_charpos = byte_marker_position (w->pointm[type]); |
428 | 2233 data.cursor_type = CURSOR_ON; |
2234 } | |
2235 else | |
2236 data.cursor_type = NO_CURSOR; | |
2237 data.cursor_x = -1; | |
2238 | |
2239 data.start_col = w->hscroll; | |
2240 data.start_col_xoffset = w->left_xoffset; | |
826 | 2241 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
428 | 2242 data.hscroll_glyph_width_adjust = 0; |
2243 | |
2244 /* We regenerate the line from the very beginning. */ | |
2245 Dynarr_reset (db->runes); | |
2246 | |
2247 /* Why is this less than or equal and not just less than? If the | |
2248 starting position is already equal to the maximum we can't add | |
2249 anything else, right? Wrong. We might still have a newline to | |
2250 add. A newline can use the room allocated for an end glyph since | |
2251 if we add it we know we aren't going to be adding any end | |
2252 glyph. */ | |
2253 | |
2254 /* #### Chuck -- I think this condition should be while (1). | |
2255 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
2256 and the begin-glyph ends exactly at the end of the window, the | |
2257 end-glyph and text might not be displayed. while (1) ensures | |
2258 that the loop terminates only when either (a) there is | |
2259 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
2260 | |
2261 #### Also I think you need to ensure that the operation | |
2262 "add begin glyphs; add end glyphs; add text" is atomic and | |
2263 can't get interrupted in the middle. If you run off the end | |
2264 of the line during that operation, then you keep accumulating | |
2265 propagation data until you're done. Otherwise, if the (e.g.) | |
2266 there's a begin glyph at a particular position and attempting | |
2267 to display that glyph results in window-end being hit and | |
2268 propagation data being generated, then the character at that | |
2269 position won't be displayed. | |
2270 | |
2271 #### See also the comment after the end of this loop, below. | |
2272 */ | |
2273 while (data.pixpos <= data.max_pixpos | |
2274 && (active_minibuffer || !NILP (synch_minibuffers_value))) | |
2275 { | |
2276 /* #### This check probably should not be necessary. */ | |
826 | 2277 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
428 | 2278 { |
2279 /* #### urk! More of this lossage! */ | |
826 | 2280 data.byte_charpos--; |
428 | 2281 goto done; |
2282 } | |
2283 | |
2284 /* If selective display was an integer and we aren't working on | |
4187 | 2285 a continuation line then find the next line we are actually |
2286 supposed to display. */ | |
428 | 2287 if (selective > 0 |
826 | 2288 && (data.byte_charpos == BYTE_BUF_BEGV (b) |
2289 || BUF_FETCH_CHAR (b, prev_bytebpos (b, data.byte_charpos)) == '\n')) | |
2290 { | |
2291 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
428 | 2292 { |
826 | 2293 data.byte_charpos = |
2294 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2295 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
428 | 2296 { |
826 | 2297 data.byte_charpos = BYTE_BUF_ZV (b); |
428 | 2298 goto done; |
2299 } | |
2300 } | |
2301 } | |
2302 | |
2303 /* Check for face changes. */ | |
826 | 2304 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
428 | 2305 { |
819 | 2306 Lisp_Object last_glyph = Qnil; |
2307 | |
2308 /* Deal with glyphs that we have already displayed. The | |
2309 theory is that if we end up with a PROP_GLYPH in the | |
2310 propagation data then we are clipping the glyph and there | |
2311 can be no propagation data before that point. The theory | |
2312 works because we always recalculate the extent-fragments | |
2313 for propagated data, we never actually propagate the | |
2314 fragments that still need to be displayed. */ | |
4967 | 2315 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
2316 { | |
2317 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
819 | 2318 Dynarr_free (*prop); |
2319 *prop = 0; | |
2320 } | |
428 | 2321 /* Now compute the face and begin/end-glyph information. */ |
2322 data.findex = | |
665 | 2323 /* Remember that the extent-fragment routines deal in Bytebpos's. */ |
826 | 2324 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
428 | 2325 |
2326 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
2327 | |
826 | 2328 if (data.byte_charpos == data.ef->end) |
428 | 2329 no_more_frags = 1; |
2330 } | |
2331 initial = 0; | |
2332 | |
2333 /* Determine what is next to be displayed. We first handle any | |
4187 | 2334 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
2335 display then we determine what to do based on the character at the | |
2336 current buffer position. */ | |
428 | 2337 |
2338 /* If the current position is covered by an invisible extent, do | |
4187 | 2339 nothing (except maybe add some ellipses). |
428 | 2340 |
2341 #### The behavior of begin and end-glyphs at the edge of an | |
2342 invisible extent should be investigated further. This is | |
2343 fairly low priority though. */ | |
2344 if (data.ef->invisible) | |
2345 { | |
2346 /* #### Chuck, perhaps you could look at this code? I don't | |
2347 really know what I'm doing. */ | |
2348 if (*prop) | |
2349 { | |
2350 Dynarr_free (*prop); | |
2351 *prop = 0; | |
2352 } | |
2353 | |
2354 /* The extent fragment code only sets this when we should | |
2355 really display the ellipses. It makes sure the ellipses | |
2356 don't get displayed more than once in a row. */ | |
2357 if (data.ef->invisible_ellipses) | |
2358 { | |
2359 struct glyph_block gb; | |
2360 | |
2361 data.ef->invisible_ellipses_already_displayed = 1; | |
2362 data.ef->invisible_ellipses = 0; | |
2363 gb.extent = Qnil; | |
2364 gb.glyph = Vinvisible_text_glyph; | |
2365 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2366 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2367 /* Perhaps they shouldn't propagate if the very next thing | |
2368 is to display a newline (for compatibility with | |
2369 selective-display-ellipses)? Maybe that's too | |
2370 abstruse. */ | |
2371 if (*prop) | |
2372 goto done; | |
2373 } | |
2374 | |
2375 /* If point is in an invisible region we place it on the | |
4187 | 2376 next visible character. */ |
428 | 2377 if (data.cursor_type == CURSOR_ON |
826 | 2378 && data.byte_charpos == data.byte_cursor_charpos) |
428 | 2379 { |
2380 data.cursor_type = NEXT_CURSOR; | |
2381 } | |
2382 | |
2383 /* #### What if we we're dealing with a display table? */ | |
2384 if (data.start_col) | |
2385 data.start_col--; | |
2386 | |
826 | 2387 if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2388 goto done; |
2389 else | |
826 | 2390 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2391 } |
2392 | |
2393 /* If there is propagation data, then it represents the current | |
819 | 2394 buffer position being displayed. Add them and advance the |
2395 position counter. This might also add the minibuffer | |
2396 prompt. */ | |
428 | 2397 else if (*prop) |
2398 { | |
2399 dl->used_prop_data = 1; | |
2400 *prop = add_propagation_runes (prop, &data); | |
2401 | |
2402 if (*prop) | |
2403 goto done; /* gee, a really narrow window */ | |
826 | 2404 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2405 goto done; |
826 | 2406 else if (data.byte_charpos < BYTE_BUF_BEGV (b)) |
428 | 2407 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
826 | 2408 data.byte_charpos = BYTE_BUF_BEGV (b); |
428 | 2409 else |
826 | 2410 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2411 } |
2412 | |
2413 /* If there are end glyphs, add them to the line. These are | |
2414 the end glyphs for the previous run of text. We add them | |
2415 here rather than doing them at the end of handling the | |
2416 previous run so that glyphs at the beginning and end of | |
2417 a line are handled correctly. */ | |
819 | 2418 else if (Dynarr_length (data.ef->end_glyphs) > 0 |
2419 || Dynarr_length (data.ef->begin_glyphs) > 0) | |
2420 { | |
2421 glyph_block_dynarr* tmpglyphs = 0; | |
2422 /* #### I think this is safe, but could be wrong. */ | |
826 | 2423 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
819 | 2424 |
4187 | 2425 if (Dynarr_length (data.ef->end_glyphs) > 0) |
819 | 2426 { |
2427 *prop = add_glyph_runes (&data, END_GLYPHS); | |
2428 tmpglyphs = data.ef->end_glyphs; | |
2429 } | |
2430 | |
2431 /* If there are begin glyphs, add them to the line. */ | |
4187 | 2432 if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0) |
819 | 2433 { |
2434 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); | |
2435 tmpglyphs = data.ef->begin_glyphs; | |
2436 } | |
2437 | |
4187 | 2438 if (*prop) |
819 | 2439 { |
2440 /* If we just clipped a glyph and we are at the end of a | |
2441 line and there are more glyphs to display then do | |
2442 appropriate processing to not get a continuation | |
2443 glyph. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2444 if (*prop != ADD_FAILED |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2445 && Dynarr_begin (*prop)->type == PROP_GLYPH |
819 | 2446 && data.ch == '\n') |
4187 | 2447 { |
819 | 2448 /* If there are no more glyphs then do the normal |
4187 | 2449 processing. |
819 | 2450 |
2451 #### This doesn't actually work if the same glyph is | |
2452 present more than once in the block. To solve | |
2453 this we would have to carry the index around | |
2454 which might be problematic since the fragment is | |
2455 recalculated for each line. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2456 if (EQ (Dynarr_lastp (tmpglyphs)->glyph, |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2457 Dynarr_begin (*prop)->data.p_glyph.glyph)) |
819 | 2458 { |
2459 Dynarr_free (*prop); | |
2460 *prop = 0; | |
2461 } | |
2462 else { | |
2463 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2464 add_ichar_rune (&data); /* discard prop data. */ |
819 | 2465 goto done; |
2466 } | |
2467 } | |
2468 else | |
2469 goto done; | |
2470 } | |
428 | 2471 } |
2472 | |
2473 /* If at end-of-buffer, we've already processed begin and | |
2474 end-glyphs at this point and there's no text to process, | |
2475 so we're done. */ | |
826 | 2476 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2477 goto done; |
2478 | |
2479 else | |
2480 { | |
2481 Lisp_Object entry = Qnil; | |
2482 /* Get the character at the current buffer position. */ | |
826 | 2483 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
428 | 2484 if (!NILP (face_dt) || !NILP (window_dt)) |
2485 entry = display_table_entry (data.ch, face_dt, window_dt); | |
2486 | |
2487 /* If there is a display table entry for it, hand it off to | |
4187 | 2488 add_disp_table_entry_runes and let it worry about it. */ |
428 | 2489 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
2490 { | |
2491 *prop = add_disp_table_entry_runes (&data, entry); | |
2492 | |
2493 if (*prop) | |
2494 goto done; | |
2495 } | |
2496 | |
2497 /* Check if we have hit a newline character. If so, add a marker | |
4187 | 2498 to the line and end this loop. */ |
428 | 2499 else if (data.ch == '\n') |
2500 { | |
2501 /* We aren't going to be adding an end glyph so give its | |
4187 | 2502 space back in order to make sure that the cursor can |
2503 fit. */ | |
819 | 2504 data.max_pixpos += data.end_glyph_width; |
428 | 2505 |
2506 if (selective > 0 | |
826 | 2507 && (byte_spaces_at_point |
2508 (b, next_bytebpos (b, data.byte_charpos)) | |
428 | 2509 >= selective)) |
2510 { | |
2511 if (!NILP (b->selective_display_ellipses)) | |
2512 { | |
2513 struct glyph_block gb; | |
2514 | |
2515 gb.extent = Qnil; | |
2516 gb.glyph = Vinvisible_text_glyph; | |
2517 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2518 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2519 } | |
2520 else | |
2521 { | |
2522 /* Cheesy, cheesy, cheesy. We mark the end of the | |
2523 line with a special "character rune" whose width | |
2524 is the EOL cursor width and whose character is | |
2525 the non-printing character '\n'. */ | |
2526 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2527 *prop = add_ichar_rune (&data); |
428 | 2528 } |
2529 | |
826 | 2530 /* We need to set data.byte_charpos to the start of the |
4187 | 2531 next visible region in order to make this line |
2532 appear to contain all of the invisible area. | |
2533 Otherwise, the line cache won't work | |
2534 correctly. */ | |
826 | 2535 INC_BYTEBPOS (b, data.byte_charpos); |
2536 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
428 | 2537 { |
826 | 2538 data.byte_charpos = |
2539 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2540 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
428 | 2541 { |
826 | 2542 data.byte_charpos = BYTE_BUF_ZV (b); |
428 | 2543 break; |
2544 } | |
2545 } | |
826 | 2546 if (BYTE_BUF_FETCH_CHAR |
2547 (b, prev_bytebpos (b, data.byte_charpos)) == '\n') | |
2548 DEC_BYTEBPOS (b, data.byte_charpos); | |
428 | 2549 } |
2550 else | |
2551 { | |
2552 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2553 *prop = add_ichar_rune (&data); |
428 | 2554 } |
2555 | |
2556 goto done; | |
2557 } | |
2558 | |
2559 /* If the current character is ^M, and selective display is | |
4187 | 2560 enabled, then add the invisible-text-glyph if |
2561 selective-display-ellipses is set. In any case, this | |
2562 line is done. */ | |
428 | 2563 else if (data.ch == (('M' & 037)) && selective == -1) |
2564 { | |
826 | 2565 Bytebpos byte_next_charpos; |
428 | 2566 |
2567 /* Find the buffer position at the end of the line. */ | |
826 | 2568 byte_next_charpos = |
2569 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2570 if (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_next_charpos)) | |
428 | 2571 == '\n') |
826 | 2572 DEC_BYTEBPOS (b, byte_next_charpos); |
428 | 2573 |
2574 /* If the cursor is somewhere in the elided text make | |
4187 | 2575 sure that the cursor gets drawn appropriately. */ |
428 | 2576 if (data.cursor_type == CURSOR_ON |
826 | 2577 && (data.byte_cursor_charpos >= data.byte_charpos && |
2578 data.byte_cursor_charpos < byte_next_charpos)) | |
428 | 2579 { |
2580 data.cursor_type = NEXT_CURSOR; | |
2581 } | |
2582 | |
2583 /* We won't be adding a truncation or continuation glyph | |
4187 | 2584 so give up the room allocated for them. */ |
819 | 2585 data.max_pixpos += data.end_glyph_width; |
428 | 2586 |
2587 if (!NILP (b->selective_display_ellipses)) | |
2588 { | |
2589 /* We don't propagate anything from the invisible | |
4187 | 2590 text glyph if it fails to fit. This is |
2591 intentional. */ | |
428 | 2592 struct glyph_block gb; |
2593 | |
2594 gb.extent = Qnil; | |
2595 gb.glyph = Vinvisible_text_glyph; | |
2596 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, | |
2597 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2598 } | |
2599 | |
2600 /* Set the buffer position to the end of the line. We | |
4187 | 2601 need to do this before potentially adding a newline |
2602 so that the cursor flag will get set correctly (if | |
2603 needed). */ | |
826 | 2604 data.byte_charpos = byte_next_charpos; |
428 | 2605 |
2606 if (NILP (b->selective_display_ellipses) | |
826 | 2607 || data.byte_cursor_charpos == byte_next_charpos) |
428 | 2608 { |
2609 /* We have to at least add a newline character so | |
4187 | 2610 that the cursor shows up properly. */ |
428 | 2611 data.ch = '\n'; |
2612 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2613 data.findex = DEFAULT_INDEX; | |
2614 data.start_col = 0; | |
2615 data.start_col_xoffset = 0; | |
826 | 2616 data.byte_start_col_enabled = 0; |
428 | 2617 |
867 | 2618 add_ichar_rune (&data); |
428 | 2619 } |
2620 | |
2621 /* This had better be a newline but doing it this way | |
4187 | 2622 we'll see obvious incorrect results if it isn't. No |
2623 need to abort here. */ | |
826 | 2624 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
428 | 2625 |
2626 goto done; | |
2627 } | |
2628 | |
2629 /* If the current character is considered to be printable, then | |
4187 | 2630 just add it. */ |
428 | 2631 else if (data.ch >= printable_min) |
2632 { | |
867 | 2633 *prop = add_ichar_rune (&data); |
428 | 2634 if (*prop) |
2635 goto done; | |
2636 } | |
2637 | |
2638 /* If the current character is a tab, determine the next tab | |
4187 | 2639 starting position and add a blank rune which extends from the |
2640 current pixel position to that starting position. */ | |
428 | 2641 else if (data.ch == '\t') |
2642 { | |
2643 int tab_start_pixpos = data.pixpos; | |
2644 int next_tab_start; | |
2645 int char_tab_width; | |
2646 int prop_width = 0; | |
2647 | |
2648 if (data.start_col > 1) | |
434 | 2649 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)) |
428 | 2650 + data.start_col_xoffset; |
2651 | |
2652 next_tab_start = | |
2653 next_tab_position (w, tab_start_pixpos, | |
2654 dl->bounds.left_in + | |
2655 data.hscroll_glyph_width_adjust); | |
2656 if (next_tab_start > data.max_pixpos) | |
2657 { | |
2658 prop_width = next_tab_start - data.max_pixpos; | |
2659 next_tab_start = data.max_pixpos; | |
2660 } | |
2661 data.blank_width = next_tab_start - data.pixpos; | |
2662 char_tab_width = | |
2663 (next_tab_start - tab_start_pixpos) / space_width (w); | |
2664 | |
2665 *prop = add_blank_rune (&data, w, char_tab_width); | |
2666 | |
2667 /* add_blank_rune is only supposed to be called with | |
4187 | 2668 sizes guaranteed to fit in the available space. */ |
428 | 2669 assert (!(*prop)); |
2670 | |
2671 if (prop_width) | |
2672 { | |
2673 struct prop_block pb; | |
2674 *prop = Dynarr_new (prop_block); | |
2675 | |
2676 pb.type = PROP_BLANK; | |
2677 pb.data.p_blank.width = prop_width; | |
2678 pb.data.p_blank.findex = data.findex; | |
2679 Dynarr_add (*prop, pb); | |
2680 | |
2681 goto done; | |
2682 } | |
2683 } | |
2684 | |
2685 /* If character is a control character, pass it off to | |
4187 | 2686 add_control_char_runes. |
428 | 2687 |
2688 The is_*() routines have undefined results on | |
2689 arguments outside of the range [-1, 255]. (This | |
2690 often bites people who carelessly use `char' instead | |
2691 of `unsigned char'.) | |
2692 */ | |
867 | 2693 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
428 | 2694 { |
2695 *prop = add_control_char_runes (&data, b); | |
2696 | |
2697 if (*prop) | |
2698 goto done; | |
2699 } | |
2700 | |
2701 /* If the character is above the ASCII range and we have not | |
4187 | 2702 already handled it, then print it as an octal number. */ |
428 | 2703 else if (data.ch >= 0200) |
2704 { | |
2705 *prop = add_octal_runes (&data); | |
2706 | |
2707 if (*prop) | |
2708 goto done; | |
2709 } | |
2710 | |
2711 /* Assume the current character is considered to be printable, | |
4187 | 2712 then just add it. */ |
428 | 2713 else |
2714 { | |
867 | 2715 *prop = add_ichar_rune (&data); |
428 | 2716 if (*prop) |
2717 goto done; | |
2718 } | |
2719 | |
826 | 2720 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2721 } |
2722 } | |
2723 | |
2724 done: | |
2725 | |
2726 /* Determine the starting point of the next line if we did not hit the | |
2727 end of the buffer. */ | |
826 | 2728 if (data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 2729 && (active_minibuffer || !NILP (synch_minibuffers_value))) |
2730 { | |
2731 /* #### This check is not correct. If the line terminated | |
2732 due to a begin-glyph or end-glyph hitting window-end, then | |
826 | 2733 data.ch will not point to the character at data.byte_charpos. If |
428 | 2734 you make the two changes mentioned at the top of this loop, |
2735 you should be able to say '(if (*prop))'. That should also | |
826 | 2736 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 2737 check. */ |
2738 | |
2739 /* The common case is that the line ended because we hit a newline. | |
4187 | 2740 In that case, the next character is just the next buffer |
2741 position. */ | |
428 | 2742 if (data.ch == '\n') |
2743 { | |
2744 /* If data.start_col_enabled is still true, then the window is | |
4187 | 2745 scrolled far enough so that nothing on this line is visible. |
2746 We need to stick a truncation glyph at the beginning of the | |
2747 line in that case unless the line is completely blank. */ | |
826 | 2748 if (data.byte_start_col_enabled) |
428 | 2749 { |
2750 if (data.cursor_type == CURSOR_ON) | |
2751 { | |
826 | 2752 if (data.byte_cursor_charpos >= byte_start_pos |
2753 && data.byte_cursor_charpos <= data.byte_charpos) | |
2754 data.byte_cursor_charpos = data.byte_charpos; | |
428 | 2755 } |
2756 data.findex = DEFAULT_INDEX; | |
2757 data.start_col = 0; | |
826 | 2758 data.byte_start_col_enabled = 0; |
2759 | |
2760 if (data.byte_charpos != byte_start_pos) | |
428 | 2761 { |
2762 struct glyph_block gb; | |
2763 | |
2764 gb.extent = Qnil; | |
2765 gb.glyph = Vhscroll_glyph; | |
2766 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2767 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX)); | |
2768 } | |
2769 else | |
2770 { | |
2771 /* This duplicates code down below to add a newline to | |
4187 | 2772 the end of an otherwise empty line.*/ |
428 | 2773 data.ch = '\n'; |
2774 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2775 | |
867 | 2776 add_ichar_rune (&data); |
428 | 2777 } |
2778 } | |
2779 | |
826 | 2780 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2781 } |
2782 | |
2783 /* Otherwise we have a buffer line which cannot fit on one display | |
4187 | 2784 line. */ |
428 | 2785 else |
2786 { | |
2787 struct glyph_block gb; | |
2788 struct glyph_cachel *cachel; | |
2789 | |
2790 /* If the line is to be truncated then we actually have to look | |
4187 | 2791 for the next newline. We also add the end-of-line glyph which |
2792 we know will fit because we adjusted the right border before | |
2793 we starting laying out the line. */ | |
819 | 2794 data.max_pixpos += data.end_glyph_width; |
428 | 2795 data.findex = DEFAULT_INDEX; |
2796 gb.extent = Qnil; | |
2797 | |
2798 if (truncate_win) | |
2799 { | |
826 | 2800 Bytebpos byte_pos; |
428 | 2801 |
2802 /* Now find the start of the next line. */ | |
826 | 2803 byte_pos = byte_find_next_newline_no_quit (b, data.byte_charpos, 1); |
428 | 2804 |
2805 /* If the cursor is past the truncation line then we | |
4187 | 2806 make it appear on the truncation glyph. If we've hit |
2807 the end of the buffer then we also make the cursor | |
2808 appear unless eob is immediately preceded by a | |
2809 newline. In that case the cursor should actually | |
2810 appear on the next line. */ | |
428 | 2811 if (data.cursor_type == CURSOR_ON |
826 | 2812 && data.byte_cursor_charpos >= data.byte_charpos |
2813 && (data.byte_cursor_charpos < byte_pos || | |
2814 (byte_pos == BYTE_BUF_ZV (b) | |
2815 && (byte_pos == BYTE_BUF_BEGV (b) | |
2816 || (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_pos)) | |
428 | 2817 != '\n'))))) |
826 | 2818 data.byte_cursor_charpos = byte_pos; |
428 | 2819 else |
2820 data.cursor_type = NO_CURSOR; | |
2821 | |
826 | 2822 data.byte_charpos = byte_pos; |
428 | 2823 gb.glyph = Vtruncation_glyph; |
2824 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
2825 } | |
2826 else | |
2827 { | |
2828 /* The cursor can never be on the continuation glyph. */ | |
2829 data.cursor_type = NO_CURSOR; | |
2830 | |
826 | 2831 /* data.byte_charpos is already at the start of the next line. */ |
428 | 2832 |
442 | 2833 dl->line_continuation = 1; |
428 | 2834 gb.glyph = Vcontinuation_glyph; |
2835 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
2836 } | |
2837 | |
442 | 2838 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
428 | 2839 |
826 | 2840 if (truncate_win && data.byte_charpos == BYTE_BUF_ZV (b) |
2841 && BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, BYTE_BUF_ZV (b))) != '\n') | |
428 | 2842 /* #### Damn this losing shit. */ |
826 | 2843 data.byte_charpos++; |
428 | 2844 } |
2845 } | |
2846 else if ((active_minibuffer || !NILP (synch_minibuffers_value)) | |
826 | 2847 && (!echo_area_active (f) || data.byte_charpos == BYTE_BUF_ZV (b))) |
428 | 2848 { |
2849 /* We need to add a marker to the end of the line since there is no | |
4187 | 2850 newline character in order for the cursor to get drawn. We label |
2851 it as a newline so that it gets handled correctly by the | |
2852 whitespace routines below. */ | |
428 | 2853 |
2854 data.ch = '\n'; | |
2855 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2856 data.findex = DEFAULT_INDEX; | |
2857 data.start_col = 0; | |
2858 data.start_col_xoffset = 0; | |
826 | 2859 data.byte_start_col_enabled = 0; |
428 | 2860 |
2861 data.max_pixpos += data.blank_width; | |
867 | 2862 add_ichar_rune (&data); |
428 | 2863 data.max_pixpos -= data.blank_width; |
2864 | |
2865 /* #### urk! Chuck, this shit is bad news. Going around | |
2866 manipulating invalid positions is guaranteed to result in | |
2867 trouble sooner or later. */ | |
826 | 2868 data.byte_charpos = BYTE_BUF_ZV (b) + 1; |
428 | 2869 } |
2870 | |
2871 /* Calculate left whitespace boundary. */ | |
2872 { | |
2873 int elt = 0; | |
2874 | |
2875 /* Whitespace past a newline is considered right whitespace. */ | |
2876 while (elt < Dynarr_length (db->runes)) | |
2877 { | |
2878 struct rune *rb = Dynarr_atp (db->runes, elt); | |
2879 | |
2880 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
2881 || rb->type == RUNE_BLANK) | |
2882 { | |
2883 dl->bounds.left_white += rb->width; | |
2884 elt++; | |
2885 } | |
2886 else | |
2887 elt = Dynarr_length (db->runes); | |
2888 } | |
2889 } | |
2890 | |
2891 /* Calculate right whitespace boundary. */ | |
2892 { | |
2893 int elt = Dynarr_length (db->runes) - 1; | |
2894 int done = 0; | |
2895 | |
2896 while (!done && elt >= 0) | |
2897 { | |
2898 struct rune *rb = Dynarr_atp (db->runes, elt); | |
2899 | |
2900 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
2901 && isspace (rb->object.chr.ch)) | |
2902 && !rb->type == RUNE_BLANK) | |
2903 { | |
2904 dl->bounds.right_white = rb->xpos + rb->width; | |
2905 done = 1; | |
2906 } | |
2907 | |
2908 elt--; | |
2909 | |
2910 } | |
2911 | |
2912 /* The line is blank so everything is considered to be right | |
2913 whitespace. */ | |
2914 if (!done) | |
2915 dl->bounds.right_white = dl->bounds.left_in; | |
2916 } | |
2917 | |
2918 /* Set the display blocks bounds. */ | |
2919 db->start_pos = dl->bounds.left_in; | |
2920 if (Dynarr_length (db->runes)) | |
2921 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2922 struct rune *rb = Dynarr_lastp (db->runes); |
428 | 2923 |
2924 db->end_pos = rb->xpos + rb->width; | |
2925 } | |
2926 else | |
2927 db->end_pos = dl->bounds.right_white; | |
2928 | |
819 | 2929 calculate_baseline (&data); |
428 | 2930 |
2931 dl->ascent = data.new_ascent; | |
2932 dl->descent = data.new_descent; | |
2933 | |
2934 { | |
2935 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
2936 | |
2937 if (dl->ascent < ascent) | |
2938 dl->ascent = ascent; | |
2939 } | |
2940 { | |
2941 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
2942 | |
2943 if (dl->descent < descent) | |
2944 dl->descent = descent; | |
2945 } | |
2946 | |
819 | 2947 calculate_yoffset (dl, db); |
2948 | |
428 | 2949 dl->cursor_elt = data.cursor_x; |
2950 /* #### lossage lossage lossage! Fix this shit! */ | |
826 | 2951 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
2952 dl->end_charpos = BUF_ZV (b); | |
428 | 2953 else |
826 | 2954 dl->end_charpos = bytebpos_to_charbpos (b, data.byte_charpos) - 1; |
428 | 2955 if (truncate_win) |
826 | 2956 data.dl->num_chars = column_at_point (b, dl->end_charpos, 0); |
428 | 2957 else |
2958 /* This doesn't correctly take into account tabs and control | |
2959 characters but if the window isn't being truncated then this | |
2960 value isn't going to end up being used anyhow. */ | |
826 | 2961 data.dl->num_chars = dl->end_charpos - dl->charpos; |
428 | 2962 |
2963 /* #### handle horizontally scrolled line with text none of which | |
2964 was actually laid out. */ | |
2965 | |
2966 /* #### handle any remainder of overlay arrow */ | |
2967 | |
2968 if (*prop == ADD_FAILED) | |
2969 *prop = NULL; | |
2970 | |
2971 if (truncate_win && *prop) | |
2972 { | |
2973 Dynarr_free (*prop); | |
2974 *prop = NULL; | |
2975 } | |
2976 | |
2977 extent_fragment_delete (data.ef); | |
2978 | |
2979 /* #### If we started at EOB, then make sure we return a value past | |
2980 it so that regenerate_window will exit properly. This is bogus. | |
2981 The main loop should get fixed so that it isn't necessary to call | |
2982 this function if we are already at EOB. */ | |
2983 | |
826 | 2984 if (data.byte_charpos == BYTE_BUF_ZV (b) && byte_start_pos == BYTE_BUF_ZV (b)) |
2985 return data.byte_charpos + 1; /* Yuck! */ | |
428 | 2986 else |
826 | 2987 return data.byte_charpos; |
428 | 2988 } |
2989 | |
2990 /* Display the overlay arrow at the beginning of the given line. */ | |
2991 | |
2992 static int | |
2993 create_overlay_glyph_block (struct window *w, struct display_line *dl) | |
2994 { | |
2995 struct frame *f = XFRAME (w->frame); | |
2996 struct device *d = XDEVICE (f->device); | |
2997 pos_data data; | |
2998 | |
2999 /* If Voverlay_arrow_string isn't valid then just fail silently. */ | |
3000 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string)) | |
3001 return 0; | |
3002 | |
3003 xzero (data); | |
3004 data.ef = NULL; | |
3005 data.d = d; | |
793 | 3006 data.window = wrap_window (w); |
428 | 3007 data.db = get_display_block_from_line (dl, OVERWRITE); |
3008 data.dl = dl; | |
3009 data.pixpos = dl->bounds.left_in; | |
3010 data.max_pixpos = dl->bounds.right_in; | |
3011 data.cursor_type = NO_CURSOR; | |
3012 data.cursor_x = -1; | |
3013 data.findex = DEFAULT_INDEX; | |
3014 data.last_charset = Qunbound; | |
3015 data.last_findex = DEFAULT_INDEX; | |
3016 data.result_str = Qnil; | |
3017 data.string = Qnil; | |
3018 | |
3019 Dynarr_reset (data.db->runes); | |
3020 | |
3021 if (STRINGP (Voverlay_arrow_string)) | |
3022 { | |
867 | 3023 add_ibyte_string_runes |
428 | 3024 (&data, |
3025 XSTRING_DATA (Voverlay_arrow_string), | |
3026 XSTRING_LENGTH (Voverlay_arrow_string), | |
793 | 3027 1, 0); |
428 | 3028 } |
3029 else if (GLYPHP (Voverlay_arrow_string)) | |
3030 { | |
3031 struct glyph_block gb; | |
3032 | |
3033 gb.glyph = Voverlay_arrow_string; | |
3034 gb.extent = Qnil; | |
3035 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0); | |
3036 } | |
4187 | 3037 |
428 | 3038 if (data.max_pixmap_height) |
3039 { | |
3040 int height = data.new_ascent + data.new_descent; | |
3041 int pix_ascent, pix_descent; | |
4187 | 3042 |
428 | 3043 pix_descent = data.max_pixmap_height * data.new_descent / height; |
3044 pix_ascent = data.max_pixmap_height - pix_descent; | |
819 | 3045 calculate_baseline (&data); |
428 | 3046 |
3047 data.new_ascent = max (data.new_ascent, pix_ascent); | |
3048 data.new_descent = max (data.new_descent, pix_descent); | |
3049 } | |
3050 | |
3051 dl->ascent = data.new_ascent; | |
3052 dl->descent = data.new_descent; | |
3053 | |
3054 data.db->start_pos = dl->bounds.left_in; | |
3055 data.db->end_pos = data.pixpos; | |
3056 | |
819 | 3057 calculate_yoffset (dl, data.db); |
3058 | |
428 | 3059 return data.pixpos - dl->bounds.left_in; |
3060 } | |
3061 | |
3062 /* Add a type of glyph to a margin display block. */ | |
3063 | |
3064 static int | |
3065 add_margin_runes (struct display_line *dl, struct display_block *db, int start, | |
3066 int count, enum glyph_layout layout, int side, Lisp_Object window) | |
3067 { | |
3068 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS | |
3069 ? dl->left_glyphs | |
3070 : dl->right_glyphs); | |
3071 int elt, end; | |
3072 int reverse; | |
442 | 3073 struct window *w = XWINDOW (window); |
3074 struct frame *f = XFRAME (w->frame); | |
3075 struct device *d = XDEVICE (f->device); | |
3076 pos_data data; | |
3077 | |
3078 xzero (data); | |
3079 data.d = d; | |
3080 data.window = window; | |
3081 data.db = db; | |
3082 data.dl = dl; | |
3083 data.pixpos = start; | |
3084 data.cursor_type = NO_CURSOR; | |
3085 data.cursor_x = -1; | |
3086 data.last_charset = Qunbound; | |
3087 data.last_findex = DEFAULT_INDEX; | |
3088 data.result_str = Qnil; | |
3089 data.string = Qnil; | |
3090 data.new_ascent = dl->ascent; | |
3091 data.new_descent = dl->descent; | |
428 | 3092 |
3093 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) | |
3094 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) | |
3095 { | |
3096 reverse = 1; | |
3097 elt = Dynarr_length (gbd) - 1; | |
3098 end = 0; | |
3099 } | |
3100 else | |
3101 { | |
3102 reverse = 0; | |
3103 elt = 0; | |
3104 end = Dynarr_length (gbd); | |
3105 } | |
3106 | |
3107 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) | |
3108 { | |
3109 struct glyph_block *gb = Dynarr_atp (gbd, elt); | |
3110 | |
3111 if (NILP (gb->extent)) | |
2500 | 3112 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3113 |
3114 if (gb->active && | |
3115 ((side == LEFT_GLYPHS && | |
3116 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout) | |
3117 || (side == RIGHT_GLYPHS && | |
3118 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) | |
3119 { | |
442 | 3120 data.findex = gb->findex; |
3121 data.max_pixpos = data.pixpos + gb->width; | |
3122 add_glyph_rune (&data, gb, side, 0, NULL); | |
428 | 3123 count--; |
3124 gb->active = 0; | |
3125 } | |
3126 | |
3127 (reverse ? elt-- : elt++); | |
3128 } | |
3129 | |
819 | 3130 calculate_baseline (&data); |
442 | 3131 |
3132 dl->ascent = data.new_ascent; | |
3133 dl->descent = data.new_descent; | |
3134 | |
819 | 3135 calculate_yoffset (dl, data.db); |
3136 | |
442 | 3137 return data.pixpos; |
428 | 3138 } |
3139 | |
3140 /* Add a blank to a margin display block. */ | |
3141 | |
3142 static void | |
2286 | 3143 add_margin_blank (struct display_line *UNUSED (dl), struct display_block *db, |
428 | 3144 struct window *w, int xpos, int width, int side) |
3145 { | |
3146 struct rune rb; | |
3147 | |
3148 rb.findex = (side == LEFT_GLYPHS | |
3149 ? get_builtin_face_cache_index (w, Vleft_margin_face) | |
3150 : get_builtin_face_cache_index (w, Vright_margin_face)); | |
3151 rb.xpos = xpos; | |
3152 rb.width = width; | |
826 | 3153 rb.charpos = -1; |
428 | 3154 rb.endpos = 0; |
3155 rb.type = RUNE_BLANK; | |
3156 rb.cursor_type = CURSOR_OFF; | |
3157 | |
3158 Dynarr_add (db->runes, rb); | |
3159 } | |
3160 | |
3161 /* Display glyphs in the left outside margin, left inside margin and | |
3162 left whitespace area. */ | |
3163 | |
3164 static void | |
3165 create_left_glyph_block (struct window *w, struct display_line *dl, | |
3166 int overlay_width) | |
3167 { | |
3168 Lisp_Object window; | |
3169 | |
3170 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1); | |
3171 int elt, end_xpos; | |
3172 int out_end, in_out_start, in_in_end, white_out_start, white_in_start; | |
3173 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
3174 int left_in_start = dl->bounds.left_in; | |
3175 int left_in_end = dl->bounds.left_in + overlay_width; | |
3176 | |
3177 struct display_block *odb, *idb; | |
3178 | |
793 | 3179 window = wrap_window (w); |
428 | 3180 |
3181 /* We have to add the glyphs to the line in the order outside, | |
3182 inside, whitespace. However the precedence dictates that we | |
3183 determine how many will fit in the reverse order. */ | |
3184 | |
3185 /* Determine how many whitespace glyphs we can display and where | |
3186 they should start. */ | |
3187 white_in_start = dl->bounds.left_white; | |
3188 white_out_start = left_in_start; | |
3189 white_out_cnt = white_in_cnt = 0; | |
3190 elt = 0; | |
3191 | |
3192 while (elt < Dynarr_length (dl->left_glyphs)) | |
3193 { | |
3194 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3195 | |
3196 if (NILP (gb->extent)) | |
2500 | 3197 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3198 |
3199 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
3200 { | |
3201 int width; | |
3202 | |
438 | 3203 width = glyph_width (gb->glyph, window); |
428 | 3204 |
3205 if (white_in_start - width >= left_in_end) | |
3206 { | |
3207 white_in_cnt++; | |
3208 white_in_start -= width; | |
3209 gb->width = width; | |
3210 gb->active = 1; | |
3211 } | |
3212 else if (use_overflow | |
3213 && (white_out_start - width > dl->bounds.left_out)) | |
3214 { | |
3215 white_out_cnt++; | |
3216 white_out_start -= width; | |
3217 gb->width = width; | |
3218 gb->active = 1; | |
3219 } | |
3220 else | |
3221 gb->active = 0; | |
3222 } | |
3223 | |
3224 elt++; | |
3225 } | |
3226 | |
3227 /* Determine how many inside margin glyphs we can display and where | |
3228 they should start. The inside margin glyphs get whatever space | |
3229 is left after the whitespace glyphs have been displayed. These | |
3230 are tricky to calculate since if we decide to use the overflow | |
3231 area we basically have to start over. So for these we build up a | |
3232 list of just the inside margin glyphs and manipulate it to | |
3233 determine the needed info. */ | |
3234 { | |
3235 glyph_block_dynarr *ib; | |
3236 int avail_in, avail_out; | |
3237 int done = 0; | |
3238 int marker = 0; | |
3239 int used_in, used_out; | |
3240 | |
3241 elt = 0; | |
3242 used_in = used_out = 0; | |
3243 ib = Dynarr_new (glyph_block); | |
3244 while (elt < Dynarr_length (dl->left_glyphs)) | |
3245 { | |
3246 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3247 | |
3248 if (NILP (gb->extent)) | |
2500 | 3249 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3250 |
3251 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3252 GL_INSIDE_MARGIN) | |
3253 { | |
438 | 3254 gb->width = glyph_width (gb->glyph, window); |
428 | 3255 used_in += gb->width; |
3256 Dynarr_add (ib, *gb); | |
3257 } | |
3258 | |
3259 elt++; | |
3260 } | |
3261 | |
3262 if (white_out_cnt) | |
3263 avail_in = 0; | |
3264 else | |
3265 { | |
3266 avail_in = white_in_start - left_in_end; | |
3267 if (avail_in < 0) | |
3268 avail_in = 0; | |
3269 } | |
3270 | |
3271 if (!use_overflow) | |
3272 avail_out = 0; | |
3273 else | |
3274 avail_out = white_out_start - dl->bounds.left_out; | |
3275 | |
3276 marker = 0; | |
3277 while (!done && marker < Dynarr_length (ib)) | |
3278 { | |
3279 int width = Dynarr_atp (ib, marker)->width; | |
3280 | |
3281 /* If everything now fits in the available inside margin | |
4187 | 3282 space, we're done. */ |
428 | 3283 if (used_in <= avail_in) |
3284 done = 1; | |
3285 else | |
3286 { | |
3287 /* Otherwise see if we have room to move a glyph to the | |
4187 | 3288 outside. */ |
428 | 3289 if (used_out + width <= avail_out) |
3290 { | |
3291 used_out += width; | |
3292 used_in -= width; | |
3293 } | |
3294 else | |
3295 done = 1; | |
3296 } | |
3297 | |
3298 if (!done) | |
3299 marker++; | |
3300 } | |
3301 | |
3302 /* At this point we now know that everything from marker on goes in | |
3303 the inside margin and everything before it goes in the outside | |
3304 margin. The stuff going into the outside margin is guaranteed | |
3305 to fit, but we may have to trim some stuff from the inside. */ | |
3306 | |
3307 in_in_end = left_in_end; | |
3308 in_out_start = white_out_start; | |
3309 in_out_cnt = in_in_cnt = 0; | |
3310 | |
3311 Dynarr_free (ib); | |
3312 elt = 0; | |
3313 while (elt < Dynarr_length (dl->left_glyphs)) | |
3314 { | |
3315 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3316 | |
3317 if (NILP (gb->extent)) | |
2500 | 3318 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3319 |
3320 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3321 GL_INSIDE_MARGIN) | |
3322 { | |
438 | 3323 int width = glyph_width (gb->glyph, window); |
428 | 3324 |
3325 if (used_out) | |
3326 { | |
3327 in_out_cnt++; | |
3328 in_out_start -= width; | |
3329 gb->width = width; | |
3330 gb->active = 1; | |
3331 used_out -= width; | |
3332 } | |
3333 else if (in_in_end + width < white_in_start) | |
3334 { | |
3335 in_in_cnt++; | |
3336 in_in_end += width; | |
3337 gb->width = width; | |
3338 gb->active = 1; | |
3339 } | |
3340 else | |
3341 gb->active = 0; | |
3342 } | |
3343 | |
3344 elt++; | |
3345 } | |
3346 } | |
3347 | |
3348 /* Determine how many outside margin glyphs we can display. They | |
3349 always start at the left outside margin and can only use the | |
3350 outside margin space. */ | |
3351 out_end = dl->bounds.left_out; | |
3352 out_cnt = 0; | |
3353 elt = 0; | |
3354 | |
3355 while (elt < Dynarr_length (dl->left_glyphs)) | |
3356 { | |
3357 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3358 | |
3359 if (NILP (gb->extent)) | |
2500 | 3360 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3361 |
3362 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3363 GL_OUTSIDE_MARGIN) | |
3364 { | |
438 | 3365 int width = glyph_width (gb->glyph, window); |
428 | 3366 |
3367 if (out_end + width <= in_out_start) | |
3368 { | |
3369 out_cnt++; | |
3370 out_end += width; | |
3371 gb->width = width; | |
3372 gb->active = 1; | |
3373 } | |
3374 else | |
3375 gb->active = 0; | |
3376 } | |
3377 | |
3378 elt++; | |
3379 } | |
3380 | |
3381 /* Now that we know where everything goes, we add the glyphs as | |
3382 runes to the appropriate display blocks. */ | |
3383 if (out_cnt || in_out_cnt || white_out_cnt) | |
3384 { | |
3385 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN); | |
3386 odb->start_pos = dl->bounds.left_out; | |
3387 /* #### We should stop adding a blank to account for the space | |
4187 | 3388 between the end of the glyphs and the margin and instead set |
3389 this accordingly. */ | |
428 | 3390 odb->end_pos = dl->bounds.left_in; |
3391 Dynarr_reset (odb->runes); | |
3392 } | |
3393 else | |
3394 odb = 0; | |
3395 | |
3396 if (in_in_cnt || white_in_cnt) | |
3397 { | |
3398 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN); | |
3399 idb->start_pos = dl->bounds.left_in; | |
3400 /* #### See above comment for odb->end_pos */ | |
3401 idb->end_pos = dl->bounds.left_white; | |
3402 Dynarr_reset (idb->runes); | |
3403 } | |
3404 else | |
3405 idb = 0; | |
3406 | |
3407 /* First add the outside margin glyphs. */ | |
3408 if (out_cnt) | |
3409 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt, | |
3410 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window); | |
3411 else | |
3412 end_xpos = dl->bounds.left_out; | |
3413 | |
3414 /* There may be blank space between the outside margin glyphs and | |
3415 the inside margin glyphs. If so, add a blank. */ | |
3416 if (in_out_cnt && (in_out_start - end_xpos)) | |
3417 { | |
3418 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos, | |
3419 LEFT_GLYPHS); | |
3420 } | |
3421 | |
3422 /* Next add the inside margin glyphs which are actually in the | |
3423 outside margin. */ | |
3424 if (in_out_cnt) | |
3425 { | |
3426 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt, | |
3427 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
3428 } | |
3429 | |
3430 /* If we didn't add any inside margin glyphs to the outside margin, | |
3431 but are adding whitespace glyphs, then we need to add a blank | |
3432 here. */ | |
3433 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) | |
3434 { | |
3435 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos, | |
3436 LEFT_GLYPHS); | |
3437 } | |
3438 | |
3439 /* Next add the whitespace margin glyphs which are actually in the | |
3440 outside margin. */ | |
3441 if (white_out_cnt) | |
3442 { | |
3443 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt, | |
3444 GL_WHITESPACE, LEFT_GLYPHS, window); | |
3445 } | |
3446 | |
3447 /* We take care of clearing between the end of the glyphs and the | |
3448 start of the inside margin for lines which have glyphs. */ | |
3449 if (odb && (left_in_start - end_xpos)) | |
3450 { | |
3451 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos, | |
3452 LEFT_GLYPHS); | |
3453 } | |
3454 | |
3455 /* Next add the inside margin glyphs which are actually in the | |
3456 inside margin. */ | |
3457 if (in_in_cnt) | |
3458 { | |
3459 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt, | |
3460 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
3461 } | |
3462 else | |
3463 end_xpos = left_in_end; | |
3464 | |
3465 /* Make sure that the area between the end of the inside margin | |
3466 glyphs and the whitespace glyphs is cleared. */ | |
3467 if (idb && (white_in_start - end_xpos > 0)) | |
3468 { | |
3469 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos, | |
3470 LEFT_GLYPHS); | |
3471 } | |
3472 | |
3473 /* Next add the whitespace margin glyphs which are actually in the | |
3474 inside margin. */ | |
3475 if (white_in_cnt) | |
3476 { | |
3477 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE, | |
3478 LEFT_GLYPHS, window); | |
3479 } | |
3480 | |
3481 /* Whitespace glyphs always end right next to the text block so | |
3482 there is nothing we have to make sure is cleared after them. */ | |
3483 } | |
3484 | |
3485 /* Display glyphs in the right outside margin, right inside margin and | |
3486 right whitespace area. */ | |
3487 | |
3488 static void | |
3489 create_right_glyph_block (struct window *w, struct display_line *dl) | |
3490 { | |
3491 Lisp_Object window; | |
3492 | |
3493 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1); | |
3494 int elt, end_xpos; | |
3495 int out_start, in_out_end, in_in_start, white_out_end, white_in_end; | |
3496 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
3497 | |
3498 struct display_block *odb, *idb; | |
3499 | |
793 | 3500 window = wrap_window (w); |
428 | 3501 |
3502 /* We have to add the glyphs to the line in the order outside, | |
3503 inside, whitespace. However the precedence dictates that we | |
3504 determine how many will fit in the reverse order. */ | |
3505 | |
3506 /* Determine how many whitespace glyphs we can display and where | |
3507 they should start. */ | |
3508 white_in_end = dl->bounds.right_white; | |
3509 white_out_end = dl->bounds.right_in; | |
3510 white_out_cnt = white_in_cnt = 0; | |
3511 elt = 0; | |
3512 | |
3513 while (elt < Dynarr_length (dl->right_glyphs)) | |
3514 { | |
3515 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3516 | |
3517 if (NILP (gb->extent)) | |
2500 | 3518 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3519 |
3520 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
3521 { | |
438 | 3522 int width = glyph_width (gb->glyph, window); |
428 | 3523 |
3524 if (white_in_end + width <= dl->bounds.right_in) | |
3525 { | |
3526 white_in_cnt++; | |
3527 white_in_end += width; | |
3528 gb->width = width; | |
3529 gb->active = 1; | |
3530 } | |
3531 else if (use_overflow | |
3532 && (white_out_end + width <= dl->bounds.right_out)) | |
3533 { | |
3534 white_out_cnt++; | |
3535 white_out_end += width; | |
3536 gb->width = width; | |
3537 gb->active = 1; | |
3538 } | |
3539 else | |
3540 gb->active = 0; | |
3541 } | |
3542 | |
3543 elt++; | |
3544 } | |
3545 | |
3546 /* Determine how many inside margin glyphs we can display and where | |
3547 they should start. The inside margin glyphs get whatever space | |
3548 is left after the whitespace glyphs have been displayed. These | |
3549 are tricky to calculate since if we decide to use the overflow | |
3550 area we basically have to start over. So for these we build up a | |
3551 list of just the inside margin glyphs and manipulate it to | |
3552 determine the needed info. */ | |
3553 { | |
3554 glyph_block_dynarr *ib; | |
3555 int avail_in, avail_out; | |
3556 int done = 0; | |
3557 int marker = 0; | |
3558 int used_in, used_out; | |
3559 | |
3560 elt = 0; | |
3561 used_in = used_out = 0; | |
3562 ib = Dynarr_new (glyph_block); | |
3563 while (elt < Dynarr_length (dl->right_glyphs)) | |
3564 { | |
3565 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3566 | |
3567 if (NILP (gb->extent)) | |
2500 | 3568 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3569 |
3570 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
3571 { | |
438 | 3572 gb->width = glyph_width (gb->glyph, window); |
428 | 3573 used_in += gb->width; |
3574 Dynarr_add (ib, *gb); | |
3575 } | |
3576 | |
3577 elt++; | |
3578 } | |
3579 | |
3580 if (white_out_cnt) | |
3581 avail_in = 0; | |
3582 else | |
3583 avail_in = dl->bounds.right_in - white_in_end; | |
3584 | |
3585 if (!use_overflow) | |
3586 avail_out = 0; | |
3587 else | |
3588 avail_out = dl->bounds.right_out - white_out_end; | |
3589 | |
3590 marker = 0; | |
3591 while (!done && marker < Dynarr_length (ib)) | |
3592 { | |
3593 int width = Dynarr_atp (ib, marker)->width; | |
3594 | |
3595 /* If everything now fits in the available inside margin | |
4187 | 3596 space, we're done. */ |
428 | 3597 if (used_in <= avail_in) |
3598 done = 1; | |
3599 else | |
3600 { | |
3601 /* Otherwise see if we have room to move a glyph to the | |
4187 | 3602 outside. */ |
428 | 3603 if (used_out + width <= avail_out) |
3604 { | |
3605 used_out += width; | |
3606 used_in -= width; | |
3607 } | |
3608 else | |
3609 done = 1; | |
3610 } | |
3611 | |
3612 if (!done) | |
3613 marker++; | |
3614 } | |
3615 | |
3616 /* At this point we now know that everything from marker on goes in | |
3617 the inside margin and everything before it goes in the outside | |
3618 margin. The stuff going into the outside margin is guaranteed | |
3619 to fit, but we may have to trim some stuff from the inside. */ | |
3620 | |
3621 in_in_start = dl->bounds.right_in; | |
3622 in_out_end = dl->bounds.right_in; | |
3623 in_out_cnt = in_in_cnt = 0; | |
3624 | |
3625 Dynarr_free (ib); | |
3626 elt = 0; | |
3627 while (elt < Dynarr_length (dl->right_glyphs)) | |
3628 { | |
3629 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3630 | |
3631 if (NILP (gb->extent)) | |
2500 | 3632 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3633 |
3634 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
3635 { | |
438 | 3636 int width = glyph_width (gb->glyph, window); |
428 | 3637 |
3638 if (used_out) | |
3639 { | |
3640 in_out_cnt++; | |
3641 in_out_end += width; | |
3642 gb->width = width; | |
3643 gb->active = 1; | |
3644 used_out -= width; | |
3645 } | |
3646 else if (in_in_start - width >= white_in_end) | |
3647 { | |
3648 in_in_cnt++; | |
3649 in_in_start -= width; | |
3650 gb->width = width; | |
3651 gb->active = 1; | |
3652 } | |
3653 else | |
3654 gb->active = 0; | |
3655 } | |
3656 | |
3657 elt++; | |
3658 } | |
3659 } | |
3660 | |
3661 /* Determine how many outside margin glyphs we can display. They | |
3662 always start at the right outside margin and can only use the | |
3663 outside margin space. */ | |
3664 out_start = dl->bounds.right_out; | |
3665 out_cnt = 0; | |
3666 elt = 0; | |
3667 | |
3668 while (elt < Dynarr_length (dl->right_glyphs)) | |
3669 { | |
3670 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3671 | |
3672 if (NILP (gb->extent)) | |
2500 | 3673 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3674 |
3675 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) | |
3676 { | |
438 | 3677 int width = glyph_width (gb->glyph, window); |
428 | 3678 |
3679 if (out_start - width >= in_out_end) | |
3680 { | |
3681 out_cnt++; | |
3682 out_start -= width; | |
3683 gb->width = width; | |
3684 gb->active = 1; | |
3685 } | |
3686 else | |
3687 gb->active = 0; | |
3688 } | |
3689 | |
3690 elt++; | |
3691 } | |
3692 | |
3693 /* Now that we now where everything goes, we add the glyphs as runes | |
3694 to the appropriate display blocks. */ | |
3695 if (out_cnt || in_out_cnt || white_out_cnt) | |
3696 { | |
3697 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN); | |
3698 /* #### See comments before odb->start_pos init in | |
4187 | 3699 create_left_glyph_block */ |
428 | 3700 odb->start_pos = dl->bounds.right_in; |
3701 odb->end_pos = dl->bounds.right_out; | |
3702 Dynarr_reset (odb->runes); | |
3703 } | |
3704 else | |
3705 odb = 0; | |
3706 | |
3707 if (in_in_cnt || white_in_cnt) | |
3708 { | |
3709 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN); | |
3710 idb->start_pos = dl->bounds.right_white; | |
3711 /* #### See comments before odb->start_pos init in | |
4187 | 3712 create_left_glyph_block */ |
428 | 3713 idb->end_pos = dl->bounds.right_in; |
3714 Dynarr_reset (idb->runes); | |
3715 } | |
3716 else | |
3717 idb = 0; | |
3718 | |
3719 /* First add the whitespace margin glyphs which are actually in the | |
3720 inside margin. */ | |
3721 if (white_in_cnt) | |
3722 { | |
3723 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white, | |
3724 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS, | |
3725 window); | |
3726 } | |
3727 else | |
3728 end_xpos = dl->bounds.right_white; | |
3729 | |
3730 /* Make sure that the area between the end of the whitespace glyphs | |
3731 and the inside margin glyphs is cleared. */ | |
3732 if (in_in_cnt && (in_in_start - end_xpos)) | |
3733 { | |
3734 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos, | |
3735 RIGHT_GLYPHS); | |
3736 } | |
3737 | |
3738 /* Next add the inside margin glyphs which are actually in the | |
3739 inside margin. */ | |
3740 if (in_in_cnt) | |
3741 { | |
3742 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt, | |
3743 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
3744 } | |
3745 | |
3746 /* If we didn't add any inside margin glyphs then make sure the rest | |
3747 of the inside margin area gets cleared. */ | |
3748 if (idb && (dl->bounds.right_in - end_xpos)) | |
3749 { | |
3750 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos, | |
3751 RIGHT_GLYPHS); | |
3752 } | |
3753 | |
3754 /* Next add any whitespace glyphs in the outside margin. */ | |
3755 if (white_out_cnt) | |
3756 { | |
3757 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt, | |
3758 GL_WHITESPACE, RIGHT_GLYPHS, window); | |
3759 } | |
3760 else | |
3761 end_xpos = dl->bounds.right_in; | |
3762 | |
3763 /* Next add any inside margin glyphs in the outside margin. */ | |
3764 if (in_out_cnt) | |
3765 { | |
3766 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt, | |
3767 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
3768 } | |
3769 | |
3770 /* There may be space between any whitespace or inside margin glyphs | |
3771 in the outside margin and the actual outside margin glyphs. */ | |
3772 if (odb && (out_start - end_xpos)) | |
3773 { | |
3774 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos, | |
3775 RIGHT_GLYPHS); | |
3776 } | |
3777 | |
3778 /* Finally, add the outside margin glyphs. */ | |
3779 if (out_cnt) | |
3780 { | |
3781 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN, | |
3782 RIGHT_GLYPHS, window); | |
3783 } | |
3784 } | |
3785 | |
3786 | |
3787 /***************************************************************************/ | |
3788 /* */ | |
3789 /* modeline routines */ | |
3790 /* */ | |
3791 /***************************************************************************/ | |
3792 | |
438 | 3793 /* This function is also used in frame.c by `generate_title_string' */ |
3794 void | |
3795 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, | |
4187 | 3796 struct window *w, struct display_line *dl, |
3797 struct display_block *db, face_index findex, | |
3798 int min_pixpos, int max_pixpos, int type) | |
438 | 3799 { |
3800 struct frame *f = XFRAME (w->frame); | |
3801 struct device *d = XDEVICE (f->device); | |
3802 | |
3803 pos_data data; | |
3804 int c_pixpos; | |
3805 Charcount offset = 0; | |
3806 | |
3807 xzero (data); | |
3808 data.d = d; | |
3809 data.db = db; | |
3810 data.dl = dl; | |
3811 data.findex = findex; | |
3812 data.pixpos = min_pixpos; | |
3813 data.max_pixpos = max_pixpos; | |
3814 data.cursor_type = NO_CURSOR; | |
3815 data.last_charset = Qunbound; | |
3816 data.last_findex = DEFAULT_INDEX; | |
3817 data.result_str = result_str; | |
3818 data.is_modeline = 1; | |
3819 data.string = Qnil; | |
793 | 3820 data.window = wrap_window (w); |
438 | 3821 |
3822 Dynarr_reset (formatted_string_extent_dynarr); | |
3823 Dynarr_reset (formatted_string_extent_start_dynarr); | |
3824 Dynarr_reset (formatted_string_extent_end_dynarr); | |
3825 | |
3826 /* result_str is nil when we're building a frame or icon title. Otherwise, | |
3827 we're building a modeline, so the offset starts at the modeline | |
442 | 3828 horizontal scrolling amount */ |
438 | 3829 if (! NILP (result_str)) |
3830 offset = w->modeline_hscroll; | |
3831 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, | |
4187 | 3832 max_pixpos - min_pixpos, findex, type, &offset, |
438 | 3833 Qnil); |
3834 | |
3835 if (Dynarr_length (db->runes)) | |
3836 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3837 struct rune *rb = Dynarr_lastp (db->runes); |
438 | 3838 c_pixpos = rb->xpos + rb->width; |
3839 } | |
3840 else | |
3841 c_pixpos = min_pixpos; | |
3842 | |
3843 /* If we don't reach the right side of the window, add a blank rune | |
3844 to make up the difference. This usually only occurs if the | |
3845 modeline face is using a proportional width font or a fixed width | |
3846 font of a different size from the default face font. */ | |
3847 | |
3848 if (c_pixpos < max_pixpos) | |
3849 { | |
3850 data.pixpos = c_pixpos; | |
3851 data.blank_width = max_pixpos - data.pixpos; | |
3852 | |
3853 add_blank_rune (&data, NULL, 0); | |
3854 } | |
3855 | |
3856 /* Now create the result string and frob the extents into it. */ | |
3857 if (!NILP (result_str)) | |
3858 { | |
3859 int elt; | |
3860 Bytecount len; | |
867 | 3861 Ibyte *strdata; |
438 | 3862 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); |
3863 | |
442 | 3864 in_modeline_generation = 1; |
3865 | |
771 | 3866 sledgehammer_check_ascii_begin (result_str); |
438 | 3867 detach_all_extents (result_str); |
793 | 3868 resize_string (result_str, -1, |
4187 | 3869 data.bytepos - XSTRING_LENGTH (result_str)); |
438 | 3870 |
3871 strdata = XSTRING_DATA (result_str); | |
3872 | |
3873 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++) | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3874 { |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3875 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3876 { |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3877 len += (set_itext_ichar |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3878 (strdata + len, Dynarr_atp (db->runes, |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3879 elt)->object.chr.ch)); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3880 } |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3881 } |
438 | 3882 |
771 | 3883 init_string_ascii_begin (result_str); |
3884 bump_string_modiff (result_str); | |
3885 sledgehammer_check_ascii_begin (result_str); | |
3886 | |
438 | 3887 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr); |
4187 | 3888 elt++) |
3889 { | |
3890 Lisp_Object extent = Qnil; | |
3891 Lisp_Object child; | |
3892 | |
3893 extent = wrap_extent (Dynarr_at (formatted_string_extent_dynarr, elt)); | |
3894 child = Fgethash (extent, buf->modeline_extent_table, Qnil); | |
3895 if (NILP (child)) | |
3896 { | |
3897 child = Fmake_extent (Qnil, Qnil, result_str); | |
3898 Fputhash (extent, child, buf->modeline_extent_table); | |
3899 } | |
3900 Fset_extent_parent (child, extent); | |
3901 set_extent_endpoints | |
3902 (XEXTENT (child), | |
3903 Dynarr_at (formatted_string_extent_start_dynarr, elt), | |
3904 Dynarr_at (formatted_string_extent_end_dynarr, elt), | |
3905 result_str); | |
3906 } | |
442 | 3907 |
3908 in_modeline_generation = 0; | |
438 | 3909 } |
3910 } | |
3911 | |
428 | 3912 /* Ensure that the given display line DL accurately represents the |
3913 modeline for the given window. */ | |
3914 static void | |
3915 generate_modeline (struct window *w, struct display_line *dl, int type) | |
3916 { | |
3917 struct buffer *b = XBUFFER (w->buffer); | |
3918 struct frame *f = XFRAME (w->frame); | |
3919 struct device *d = XDEVICE (f->device); | |
3920 | |
3921 /* Unlike display line and rune pointers, this one can't change underneath | |
3922 our feet. */ | |
3923 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
3924 int max_pixpos, min_pixpos, ypos_adj; | |
3925 Lisp_Object font_inst; | |
3926 | |
3927 /* This will actually determine incorrect inside boundaries for the | |
3928 modeline since it ignores the margins. However being aware of this fact | |
3929 we never use those values anywhere so it doesn't matter. */ | |
3930 dl->bounds = calculate_display_line_boundaries (w, 1); | |
3931 | |
3932 /* We are generating a modeline. */ | |
3933 dl->modeline = 1; | |
3934 dl->cursor_elt = -1; | |
3935 | |
3936 /* Reset the runes on the modeline. */ | |
3937 Dynarr_reset (db->runes); | |
3938 | |
3939 if (!WINDOW_HAS_MODELINE_P (w)) | |
3940 { | |
3941 struct rune rb; | |
3942 | |
3943 /* If there is a horizontal scrollbar, don't add anything. */ | |
3944 if (window_scrollbar_height (w)) | |
3945 return; | |
3946 | |
3947 dl->ascent = DEVMETH (d, divider_height, ()); | |
3948 dl->descent = 0; | |
3949 /* The modeline is at the bottom of the gutters. */ | |
3950 dl->ypos = WINDOW_BOTTOM (w); | |
3951 | |
3952 rb.findex = MODELINE_INDEX; | |
3953 rb.xpos = dl->bounds.left_out; | |
3954 rb.width = dl->bounds.right_out - dl->bounds.left_out; | |
826 | 3955 rb.charpos = 0; |
428 | 3956 rb.endpos = 0; |
3957 rb.type = RUNE_HLINE; | |
3958 rb.object.hline.thickness = 1; | |
3959 rb.object.hline.yoffset = 0; | |
3960 rb.cursor_type = NO_CURSOR; | |
3961 | |
3962 if (!EQ (Qzero, w->modeline_shadow_thickness) | |
3963 && FRAME_WIN_P (f)) | |
3964 { | |
3965 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
3966 | |
3967 dl->ypos -= shadow_thickness; | |
3968 rb.xpos += shadow_thickness; | |
3969 rb.width -= 2 * shadow_thickness; | |
3970 } | |
3971 | |
3972 Dynarr_add (db->runes, rb); | |
3973 return; | |
3974 } | |
3975 | |
3976 /* !!#### not right; needs to compute the max height of | |
3977 all the charsets */ | |
3978 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); | |
3979 | |
3980 dl->ascent = XFONT_INSTANCE (font_inst)->ascent; | |
3981 dl->descent = XFONT_INSTANCE (font_inst)->descent; | |
3982 | |
3983 min_pixpos = dl->bounds.left_out; | |
3984 max_pixpos = dl->bounds.right_out; | |
3985 | |
3986 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
3987 { | |
3988 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
3989 | |
3990 ypos_adj = shadow_thickness; | |
3991 min_pixpos += shadow_thickness; | |
3992 max_pixpos -= shadow_thickness; | |
3993 } | |
3994 else | |
3995 ypos_adj = 0; | |
3996 | |
3997 generate_formatted_string_db (b->modeline_format, | |
3998 b->generated_modeline_string, w, dl, db, | |
3999 MODELINE_INDEX, min_pixpos, max_pixpos, type); | |
4000 | |
4001 /* The modeline is at the bottom of the gutters. We have to wait to | |
4002 set this until we've generated the modeline in order to account | |
4003 for any embedded faces. */ | |
4004 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj; | |
4005 } | |
4006 | |
4007 static Charcount | |
867 | 4008 add_string_to_fstring_db_runes (pos_data *data, const Ibyte *str, |
4187 | 4009 Charcount pos, Charcount min_pos, |
771 | 4010 Charcount max_pos) |
428 | 4011 { |
4012 /* This function has been Mule-ized. */ | |
4013 Charcount end; | |
867 | 4014 const Ibyte *cur_pos = str; |
428 | 4015 struct display_block *db = data->db; |
4016 | |
4017 data->blank_width = space_width (XWINDOW (data->window)); | |
4018 while (Dynarr_length (db->runes) < pos) | |
4019 add_blank_rune (data, NULL, 0); | |
4020 | |
4021 end = (Dynarr_length (db->runes) + | |
4187 | 4022 bytecount_to_charcount (str, strlen ((const char *) str))); |
428 | 4023 if (max_pos != -1) |
4024 end = min (max_pos, end); | |
4025 | |
4026 while (pos < end && *cur_pos) | |
4027 { | |
867 | 4028 const Ibyte *old_cur_pos = cur_pos; |
428 | 4029 int succeeded; |
4030 | |
867 | 4031 data->ch = itext_ichar (cur_pos); |
4032 succeeded = (add_ichar_rune (data) != ADD_FAILED); | |
4033 INC_IBYTEPTR (cur_pos); | |
428 | 4034 if (succeeded) |
4187 | 4035 { |
4036 pos++; | |
4037 data->modeline_charpos++; | |
4038 data->bytepos += cur_pos - old_cur_pos; | |
4039 } | |
428 | 4040 } |
4041 | |
4042 while (Dynarr_length (db->runes) < min_pos && | |
4187 | 4043 (data->pixpos + data->blank_width <= data->max_pixpos)) |
428 | 4044 add_blank_rune (data, NULL, 0); |
4045 | |
4046 return Dynarr_length (db->runes); | |
4047 } | |
4048 | |
4049 /* #### Urk! Should also handle begin-glyphs and end-glyphs in | |
4050 modeline extents. */ | |
4051 static Charcount | |
4052 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, | |
4187 | 4053 Charcount pos, Charcount UNUSED (min_pos), |
438 | 4054 Charcount max_pos, Lisp_Object extent) |
428 | 4055 { |
4056 /* This function has been Mule-ized. */ | |
4057 Charcount end; | |
4058 struct display_block *db = data->db; | |
4059 struct glyph_block gb; | |
4060 | |
4061 data->blank_width = space_width (XWINDOW (data->window)); | |
4062 while (Dynarr_length (db->runes) < pos) | |
4063 add_blank_rune (data, NULL, 0); | |
4064 | |
4065 end = Dynarr_length (db->runes) + 1; | |
4066 if (max_pos != -1) | |
4067 end = min (max_pos, end); | |
4068 | |
4069 gb.glyph = glyph; | |
438 | 4070 gb.extent = extent; |
428 | 4071 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); |
4072 pos++; | |
4073 | |
4074 while (Dynarr_length (db->runes) < pos && | |
4187 | 4075 (data->pixpos + data->blank_width <= data->max_pixpos)) |
428 | 4076 add_blank_rune (data, NULL, 0); |
4077 | |
4078 return Dynarr_length (db->runes); | |
4079 } | |
4080 | |
4081 /* If max_pos is == -1, it is considered to be infinite. The same is | |
4082 true of max_pixsize. */ | |
4083 #define SET_CURRENT_MODE_CHARS_PIXSIZE \ | |
4084 if (Dynarr_length (data->db->runes)) \ | |
4967 | 4085 cur_pixsize = data->pixpos - Dynarr_begin (data->db->runes)->xpos; \ |
428 | 4086 else \ |
4087 cur_pixsize = 0; | |
4088 | |
4089 /* Note that this function does "positions" in terms of characters and | |
4090 not in terms of columns. This is necessary to make the formatting | |
4091 work correctly when proportional width fonts are used in the | |
4092 modeline. */ | |
4093 static Charcount | |
4094 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, | |
4187 | 4095 Charcount min_pos, Charcount max_pos, |
4096 Lisp_Object elt, int depth, int max_pixsize, | |
4097 face_index findex, int type, Charcount *offset, | |
438 | 4098 Lisp_Object cur_ext) |
428 | 4099 { |
4100 /* This function has been Mule-ized. */ | |
4101 /* #### The other losing things in this function are: | |
4102 | |
4103 -- C zero-terminated-string lossage. | |
4104 -- Non-printable characters should be converted into something | |
4187 | 4105 appropriate (e.g. ^F) instead of blindly being printed anyway. |
428 | 4106 */ |
4107 | |
4108 tail_recurse: | |
4109 if (depth > 10) | |
4110 goto invalid; | |
4111 | |
4112 depth++; | |
4113 | |
4114 if (STRINGP (elt)) | |
4115 { | |
4116 /* A string. Add to the display line and check for %-constructs | |
4187 | 4117 within it. */ |
428 | 4118 |
2552 | 4119 Ibyte *this_str = XSTRING_DATA (elt); |
4120 | |
4121 while ((pos < max_pos || max_pos == -1) && *this_str) | |
4187 | 4122 { |
4123 Ibyte *last = this_str; | |
4124 | |
4125 while (*this_str && *this_str != '%') | |
4126 this_str++; | |
4127 | |
4128 if (this_str != last) | |
4129 { | |
4130 /* No %-construct */ | |
4131 Charcount size = | |
2552 | 4132 bytecount_to_charcount (last, this_str - last); |
438 | 4133 |
4134 if (size <= *offset) | |
4135 *offset -= size; | |
4136 else | |
4137 { | |
4138 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset : | |
4139 min (pos + size - *offset, max_pos)); | |
867 | 4140 const Ibyte *tmp_last = itext_n_addr (last, *offset); |
438 | 4141 |
4142 pos = add_string_to_fstring_db_runes (data, tmp_last, | |
4143 pos, pos, tmp_max); | |
4144 *offset = 0; | |
4145 } | |
4187 | 4146 } |
4147 else /* *this_str == '%' */ | |
4148 { | |
4149 Charcount spec_width = 0; | |
4150 | |
4151 this_str++; /* skip over '%' */ | |
4152 | |
4153 /* We can't allow -ve args due to the "%-" construct. | |
4154 * Argument specifies minwidth but not maxwidth | |
4155 * (maxwidth can be specified by | |
4156 * (<negative-number> . <stuff>) modeline elements) | |
4157 */ | |
4158 while (isdigit (*this_str)) | |
4159 { | |
4160 spec_width = spec_width * 10 + (*this_str - '0'); | |
4161 this_str++; | |
4162 } | |
4163 spec_width += pos; | |
4164 | |
4165 if (*this_str == 'M') | |
4166 { | |
4167 pos = generate_fstring_runes (w, data, pos, spec_width, | |
4168 max_pos, Vglobal_mode_string, | |
4169 depth, max_pixsize, findex, | |
4170 type, offset, cur_ext); | |
4171 } | |
4172 else if (*this_str == '-') | |
4173 { | |
4174 Charcount num_to_add; | |
4175 | |
4176 if (max_pixsize < 0) | |
4177 num_to_add = 0; | |
4178 else if (max_pos != -1) | |
4179 num_to_add = max_pos - pos; | |
4180 else | |
4181 { | |
4182 int cur_pixsize; | |
4183 int dash_pixsize; | |
4184 Ibyte ch = '-'; | |
4185 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
4186 | |
4187 dash_pixsize = | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4188 redisplay_window_text_width_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4189 (w, findex, &ch, Qnil, 0, 1); |
4187 | 4190 |
4191 if (dash_pixsize == 0) | |
3094 | 4192 num_to_add = 0; |
4193 else { | |
4194 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize; | |
4195 num_to_add++; | |
4196 } | |
4187 | 4197 } |
4198 | |
4199 while (num_to_add--) | |
4200 pos = add_string_to_fstring_db_runes | |
4201 (data, (const Ibyte *) "-", pos, pos, max_pos); | |
4202 } | |
4203 else if (*this_str != 0) | |
4204 { | |
4205 Ichar ch = itext_ichar (this_str); | |
4206 Ibyte *str; | |
438 | 4207 Charcount size; |
4208 | |
4187 | 4209 decode_mode_spec (w, ch, type); |
4210 | |
4967 | 4211 str = Dynarr_begin (mode_spec_ibyte_string); |
438 | 4212 size = bytecount_to_charcount |
4213 /* Skip the null character added by `decode_mode_spec' */ | |
867 | 4214 (str, Dynarr_length (mode_spec_ibyte_string)) - 1; |
438 | 4215 |
4216 if (size <= *offset) | |
4217 *offset -= size; | |
4218 else | |
4219 { | |
867 | 4220 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
438 | 4221 |
440 | 4222 /* #### NOTE: I don't understand why a tmp_max is not |
438 | 4223 computed and used here as in the plain string case |
4224 above. -- dv */ | |
4225 pos = add_string_to_fstring_db_runes (data, tmp_str, | |
4226 pos, pos, | |
4227 max_pos); | |
4228 *offset = 0; | |
4229 } | |
4187 | 4230 } |
4231 | |
4232 /* NOT this_str++. There could be any sort of character at | |
4233 the current position. */ | |
4234 INC_IBYTEPTR (this_str); | |
4235 } | |
4236 | |
4237 if (max_pixsize > 0) | |
4238 { | |
4239 int cur_pixsize; | |
4240 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
4241 | |
4242 if (cur_pixsize >= max_pixsize) | |
4243 break; | |
4244 } | |
4245 } | |
428 | 4246 } |
4247 else if (SYMBOLP (elt)) | |
4248 { | |
4249 /* A symbol: process the value of the symbol recursively | |
4187 | 4250 as if it appeared here directly. */ |
428 | 4251 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); |
4252 | |
4253 if (!UNBOUNDP (tem)) | |
4187 | 4254 { |
438 | 4255 /* If value is a string, output that string literally: |
4187 | 4256 don't check for % within it. */ |
4257 if (STRINGP (tem)) | |
4258 { | |
867 | 4259 Ibyte *str = XSTRING_DATA (tem); |
826 | 4260 Charcount size = string_char_length (tem); |
438 | 4261 |
4262 if (size <= *offset) | |
4263 *offset -= size; | |
4264 else | |
4265 { | |
867 | 4266 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
438 | 4267 |
440 | 4268 /* #### NOTE: I don't understand why a tmp_max is not |
438 | 4269 computed and used here as in the plain string case |
4270 above. -- dv */ | |
4271 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4272 min_pos, max_pos); | |
4273 *offset = 0; | |
4274 } | |
4187 | 4275 } |
4276 /* Give up right away for nil or t. */ | |
4277 else if (!EQ (tem, elt)) | |
4278 { | |
4279 elt = tem; | |
4280 goto tail_recurse; | |
4281 } | |
4282 } | |
428 | 4283 } |
4284 else if (GENERIC_SPECIFIERP (elt)) | |
4285 { | |
4286 Lisp_Object window, tem; | |
793 | 4287 window = wrap_window (w); |
428 | 4288 tem = specifier_instance_no_quit (elt, Qunbound, window, |
793 | 4289 ERROR_ME_DEBUG_WARN, 0, Qzero); |
428 | 4290 if (!UNBOUNDP (tem)) |
4291 { | |
4292 elt = tem; | |
4293 goto tail_recurse; | |
4294 } | |
4295 } | |
4296 else if (CONSP (elt)) | |
4297 { | |
4298 /* A cons cell: four distinct cases. | |
438 | 4299 * - If first element is a string or a cons, process all the elements |
4300 * and effectively concatenate them. | |
4301 * - If first element is a negative number, truncate displaying cdr to | |
4302 * at most that many characters. If positive, pad (with spaces) | |
4303 * to at least that many characters. | |
771 | 4304 * - If first element is another symbol or a boolean specifier, process |
4305 * the cadr or caddr recursively according to whether the symbol's | |
4306 * value or specifier's instance is non-nil or nil. | |
4307 * - If first element is , process the cadr or caddr | |
4308 * recursively according to whether the instance of the specifier in | |
4309 * the modeline's window is non-nil or nil. | |
442 | 4310 * - If first element is an extent, process the cdr recursively |
4311 * and handle the extent's face. | |
428 | 4312 */ |
438 | 4313 |
428 | 4314 Lisp_Object car, tem; |
4315 | |
4316 car = XCAR (elt); | |
771 | 4317 if (SYMBOLP (car) || BOOLEAN_SPECIFIERP (car)) |
438 | 4318 { |
4319 elt = XCDR (elt); | |
4320 if (!CONSP (elt)) | |
4321 goto invalid; | |
4322 | |
771 | 4323 if (SYMBOLP (car)) |
4324 tem = symbol_value_in_buffer (car, w->buffer); | |
4325 else | |
4326 tem = specifier_instance_no_quit (car, Qunbound, wrap_window (w), | |
793 | 4327 ERROR_ME_DEBUG_WARN, 0, Qzero); |
438 | 4328 /* elt is now the cdr, and we know it is a cons cell. |
4329 Use its car if CAR has a non-nil value. */ | |
771 | 4330 if (!UNBOUNDP (tem) && !NILP (tem)) |
438 | 4331 { |
771 | 4332 elt = XCAR (elt); |
4333 goto tail_recurse; | |
438 | 4334 } |
771 | 4335 /* Symbol's value or specifier's instance is nil or unbound |
438 | 4336 * Get the cddr of the original list |
4337 * and if possible find the caddr and use that. | |
4338 */ | |
4339 elt = XCDR (elt); | |
4340 if (NILP (elt)) | |
4341 ; | |
4342 else if (!CONSP (elt)) | |
4343 goto invalid; | |
4344 else | |
4345 { | |
4346 elt = XCAR (elt); | |
4347 goto tail_recurse; | |
4348 } | |
4349 } | |
428 | 4350 else if (INTP (car)) |
4187 | 4351 { |
4352 Charcount lim = XINT (car); | |
4353 | |
4354 elt = XCDR (elt); | |
4355 | |
4356 if (lim < 0) | |
4357 { | |
4358 /* Negative int means reduce maximum width. | |
4359 * DO NOT change MIN_PIXPOS here! | |
4360 * (20 -10 . foo) should truncate foo to 10 col | |
4361 * and then pad to 20. | |
4362 */ | |
4363 if (max_pos == -1) | |
4364 max_pos = pos - lim; | |
4365 else | |
4366 max_pos = min (max_pos, pos - lim); | |
4367 } | |
4368 else if (lim > 0) | |
4369 { | |
4370 /* Padding specified. Don't let it be more than | |
4371 * current maximum. | |
4372 */ | |
4373 lim += pos; | |
4374 if (max_pos != -1 && lim > max_pos) | |
4375 lim = max_pos; | |
4376 /* If that's more padding than already wanted, queue it. | |
4377 * But don't reduce padding already specified even if | |
4378 * that is beyond the current truncation point. | |
4379 */ | |
4380 if (lim > min_pos) | |
4381 min_pos = lim; | |
4382 } | |
4383 goto tail_recurse; | |
4384 } | |
428 | 4385 else if (STRINGP (car) || CONSP (car)) |
4187 | 4386 { |
4387 int limit = 50; | |
4388 | |
4389 /* LIMIT is to protect against circular lists. */ | |
4390 while (CONSP (elt) && --limit > 0 | |
4391 && (pos < max_pos || max_pos == -1)) | |
4392 { | |
4393 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
4394 XCAR (elt), depth, max_pixsize, | |
438 | 4395 findex, type, offset, cur_ext); |
4187 | 4396 elt = XCDR (elt); |
4397 } | |
4398 } | |
428 | 4399 else if (EXTENTP (car)) |
4187 | 4400 { |
4401 struct extent *ext = XEXTENT (car); | |
4402 | |
4403 if (EXTENT_LIVE_P (ext)) | |
4404 { | |
4405 face_index old_findex = data->findex; | |
4406 Lisp_Object face; | |
4407 Lisp_Object font_inst; | |
4408 face_index new_findex; | |
4409 Bytecount start = data->bytepos; | |
4410 | |
4411 face = extent_face (ext); | |
4412 if (FACEP (face)) | |
4413 { | |
4414 /* #### needs to merge faces, sigh */ | |
4415 /* #### needs to handle list of faces */ | |
4416 new_findex = get_builtin_face_cache_index (w, face); | |
4417 /* !!#### not right; needs to compute the max height of | |
4418 all the charsets */ | |
4419 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex, | |
4420 Vcharset_ascii); | |
4421 | |
4422 data->dl->ascent = max (data->dl->ascent, | |
4423 XFONT_INSTANCE (font_inst)->ascent); | |
4424 data->dl->descent = max (data->dl->descent, | |
4425 XFONT_INSTANCE (font_inst)-> | |
4426 descent); | |
4427 } | |
4428 else | |
4429 new_findex = old_findex; | |
4430 | |
4431 data->findex = new_findex; | |
4432 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
4433 XCDR (elt), depth - 1, | |
438 | 4434 max_pixsize, new_findex, type, |
4435 offset, car); | |
4187 | 4436 data->findex = old_findex; |
4437 Dynarr_add (formatted_string_extent_dynarr, ext); | |
4438 Dynarr_add (formatted_string_extent_start_dynarr, start); | |
4439 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); | |
4440 } | |
4441 } | |
428 | 4442 } |
4443 else if (GLYPHP (elt)) | |
4444 { | |
438 | 4445 /* Glyphs are considered as one character with respect to the modeline |
4446 horizontal scrolling facility. -- dv */ | |
4447 if (*offset > 0) | |
4448 *offset -= 1; | |
4449 else | |
4450 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos, | |
4451 cur_ext); | |
428 | 4452 } |
4453 else | |
4454 { | |
4455 invalid: | |
438 | 4456 { |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
4457 const char *str = GETTEXT ("*invalid*"); |
438 | 4458 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */ |
4459 | |
4460 if (size <= *offset) | |
4461 *offset -= size; | |
4462 else | |
4463 { | |
867 | 4464 const Ibyte *tmp_str = |
4465 itext_n_addr ((const Ibyte *) str, *offset); | |
438 | 4466 |
440 | 4467 /* #### NOTE: I don't understand why a tmp_max is not computed and |
438 | 4468 used here as in the plain string case above. -- dv */ |
4469 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4470 min_pos, max_pos); | |
4471 *offset = 0; | |
4472 } | |
4473 } | |
428 | 4474 } |
4475 | |
4476 if (min_pos > pos) | |
4477 { | |
867 | 4478 add_string_to_fstring_db_runes (data, (const Ibyte *) "", pos, |
438 | 4479 min_pos, -1); |
428 | 4480 } |
4481 | |
4482 return pos; | |
4483 } | |
4484 | |
4485 /* Update just the modeline. Assumes the desired display structs. If | |
4486 they do not have a modeline block, it does nothing. */ | |
4487 static void | |
4488 regenerate_modeline (struct window *w) | |
4489 { | |
4490 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP); | |
4491 | |
4967 | 4492 if (!Dynarr_length (dla) || !Dynarr_begin (dla)->modeline) |
428 | 4493 return; |
4494 else | |
4495 { | |
4967 | 4496 generate_modeline (w, Dynarr_begin (dla), DESIRED_DISP); |
428 | 4497 redisplay_update_line (w, 0, 0, 0); |
4498 } | |
4499 } | |
4500 | |
4501 /* Make sure that modeline display line is present in the given | |
4502 display structs if the window has a modeline and update that | |
4503 line. Returns true if a modeline was needed. */ | |
4504 static int | |
4505 ensure_modeline_generated (struct window *w, int type) | |
4506 { | |
4507 int need_modeline; | |
4508 | |
4509 /* minibuffer windows don't have modelines */ | |
4510 if (MINI_WINDOW_P (w)) | |
4511 need_modeline = 0; | |
4512 /* windows which haven't had it turned off do */ | |
4513 else if (WINDOW_HAS_MODELINE_P (w)) | |
4514 need_modeline = 1; | |
4515 /* windows which have it turned off don't have a divider if there is | |
4516 a horizontal scrollbar */ | |
4517 else if (window_scrollbar_height (w)) | |
4518 need_modeline = 0; | |
4519 /* and in this case there is none */ | |
4520 else | |
4521 need_modeline = 1; | |
4522 | |
4523 if (need_modeline) | |
4524 { | |
4525 display_line_dynarr *dla; | |
4526 | |
4527 dla = window_display_lines (w, type); | |
4528 | |
4529 /* We don't care if there is a display line which is not | |
4187 | 4530 currently a modeline because it is definitely going to become |
4531 one if we have gotten to this point. */ | |
428 | 4532 if (Dynarr_length (dla) == 0) |
4533 { | |
4534 if (Dynarr_largest (dla) > 0) | |
800 | 4535 Dynarr_increment (dla); |
428 | 4536 else |
4537 { | |
4538 struct display_line modeline; | |
4207 | 4539 |
4540 DISPLAY_LINE_INIT (modeline); | |
428 | 4541 Dynarr_add (dla, modeline); |
4542 } | |
4543 } | |
4544 | |
4545 /* If we're adding a new place marker go ahead and generate the | |
4187 | 4546 modeline so that it is available for use by |
4547 window_modeline_height. */ | |
4967 | 4548 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 4549 } |
4550 | |
4551 return need_modeline; | |
4552 } | |
4553 | |
4554 /* #### Kludge or not a kludge. I tend towards the former. */ | |
4555 int | |
4556 real_current_modeline_height (struct window *w) | |
4557 { | |
4558 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer); | |
4559 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer); | |
4560 | |
4561 if (ensure_modeline_generated (w, CMOTION_DISP)) | |
4562 { | |
4563 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP); | |
4564 | |
4565 if (Dynarr_length (dla)) | |
4566 { | |
4967 | 4567 if (Dynarr_begin (dla)->modeline) |
4568 return (Dynarr_begin (dla)->ascent + | |
4569 Dynarr_begin (dla)->descent); | |
428 | 4570 } |
4571 } | |
4572 return 0; | |
4573 } | |
4574 | |
4575 | |
4576 /***************************************************************************/ | |
819 | 4577 /* */ |
826 | 4578 /* displayable string routines */ |
819 | 4579 /* */ |
428 | 4580 /***************************************************************************/ |
4581 | |
4582 /* Given a position for a string in a window, ensure that the given | |
4583 display line DL accurately represents the text on a line starting | |
4584 at the given position. | |
4585 | |
4586 Yes, this is duplicating the code of create_text_block, but it | |
4587 looked just too hard to change create_text_block to handle strings | |
4588 *and* buffers. We already make a distinction between the two | |
4589 elsewhere in the code so I think unifying them would require a | |
4590 complete MULE rewrite. Besides, the other distinction is that these | |
4591 functions cover text that the user *cannot edit* so we can remove | |
4592 everything to do with cursors, minibuffers etc. Eventually the | |
4593 modeline routines should be modified to use this code as it copes | |
4594 with many more types of display situation. */ | |
4595 | |
665 | 4596 static Charbpos |
428 | 4597 create_string_text_block (struct window *w, Lisp_Object disp_string, |
4598 struct display_line *dl, | |
826 | 4599 Charcount start_pos, |
428 | 4600 prop_block_dynarr **prop, |
4601 face_index default_face) | |
4602 { | |
4603 struct frame *f = XFRAME (w->frame); | |
4604 /* Note that a lot of the buffer controlled stuff has been left in | |
4605 because you might well want to make use of it (selective display | |
4606 etc), its just the buffer text that we do not use. However, it | |
4607 seems to be possible for buffer to be nil sometimes so protect | |
4608 against this case. */ | |
4609 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; | |
4610 struct device *d = XDEVICE (f->device); | |
4611 | |
4612 /* we're working with these a lot so precalculate them */ | |
4613 Bytecount slen = XSTRING_LENGTH (disp_string); | |
826 | 4614 Bytecount byte_string_zv = slen; |
4615 Bytecount byte_start_pos = string_index_char_to_byte (disp_string, start_pos); | |
428 | 4616 |
4617 pos_data data; | |
4618 | |
4619 int truncate_win = b ? window_truncation_on (w) : 0; | |
4620 | |
442 | 4621 /* We're going to ditch selective display for static text, it's an |
4622 FSF thing and invisible extents are the way to go here. | |
4623 Implementing it also relies on a number of buffer-specific | |
428 | 4624 functions that we don't have the luxury of being able to use |
4625 here. */ | |
4626 | |
4627 /* The variable ctl-arrow allows the user to specify what characters | |
4628 can actually be displayed and which octal should be used for. | |
4629 #### This variable should probably have some rethought done to | |
4630 it. | |
4631 | |
4632 #### It would also be really nice if you could specify that | |
4633 the characters come out in hex instead of in octal. Mule | |
4634 does that by adding a ctl-hexa variable similar to ctl-arrow, | |
4635 but that's bogus -- we need a more general solution. I | |
4636 think you need to extend the concept of display tables | |
4637 into a more general conversion mechanism. Ideally you | |
4638 could specify a Lisp function that converts characters, | |
4639 but this violates the Second Golden Rule and besides would | |
4640 make things way way way way slow. | |
4641 | |
4642 So instead, we extend the display-table concept, which was | |
4643 historically limited to 256-byte vectors, to one of the | |
4644 following: | |
4645 | |
4646 a) A 256-entry vector, for backward compatibility; | |
4647 b) char-table, mapping characters to values; | |
4648 c) range-table, mapping ranges of characters to values; | |
4649 d) a list of the above. | |
4650 | |
4651 The (d) option allows you to specify multiple display tables | |
4652 instead of just one. Each display table can specify conversions | |
4653 for some characters and leave others unchanged. The way the | |
4654 character gets displayed is determined by the first display table | |
4655 with a binding for that character. This way, you could call a | |
4656 function `enable-hex-display' that adds a hex display-table to | |
4657 the list of display tables for the current buffer. | |
4658 | |
4659 #### ...not yet implemented... Also, we extend the concept of | |
4660 "mapping" to include a printf-like spec. Thus you can make all | |
4661 extended characters show up as hex with a display table like | |
4662 this: | |
4663 | |
4187 | 4664 #s(range-table data ((256 524288) (format "%x"))) |
428 | 4665 |
4666 Since more than one display table is possible, you have | |
4667 great flexibility in mapping ranges of characters. */ | |
867 | 4668 Ichar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
428 | 4669 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
4670 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
4671 ? 255 : 160)) : 255; | |
4672 | |
4673 Lisp_Object face_dt, window_dt; | |
4674 | |
4675 /* The text display block for this display line. */ | |
4676 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
4677 | |
4678 /* The first time through the main loop we need to force the glyph | |
4679 data to be updated. */ | |
4680 int initial = 1; | |
4681 | |
4682 /* Apparently the new extent_fragment_update returns an end position | |
4683 equal to the position passed in if there are no more runs to be | |
4684 displayed. */ | |
4685 int no_more_frags = 0; | |
4686 | |
4687 dl->used_prop_data = 0; | |
4688 dl->num_chars = 0; | |
442 | 4689 dl->line_continuation = 0; |
428 | 4690 |
4187 | 4691 /* Set up faces to use for clearing areas, used by output_display_line. */ |
428 | 4692 dl->default_findex = default_face; |
4187 | 4693 if (default_face > DEFAULT_INDEX) |
428 | 4694 { |
4695 dl->left_margin_findex = default_face; | |
4696 dl->right_margin_findex = default_face; | |
4697 } | |
4698 else | |
4699 { | |
434 | 4700 dl->left_margin_findex = |
428 | 4701 get_builtin_face_cache_index (w, Vleft_margin_face); |
434 | 4702 dl->right_margin_findex = |
428 | 4703 get_builtin_face_cache_index (w, Vright_margin_face); |
4704 } | |
4705 | |
4706 xzero (data); | |
4707 data.ef = extent_fragment_new (disp_string, f); | |
4708 | |
4709 /* These values are used by all of the rune addition routines. We add | |
4710 them to this structure for ease of passing. */ | |
4711 data.d = d; | |
793 | 4712 data.window = wrap_window (w); |
428 | 4713 data.db = db; |
4714 data.dl = dl; | |
4715 | |
826 | 4716 data.byte_charpos = byte_start_pos; |
428 | 4717 data.pixpos = dl->bounds.left_in; |
4718 data.last_charset = Qunbound; | |
4719 data.last_findex = default_face; | |
4720 data.result_str = Qnil; | |
4721 data.string = disp_string; | |
4722 | |
4723 /* Set the right boundary adjusting it to take into account any end | |
4724 glyph. Save the width of the end glyph for later use. */ | |
4725 data.max_pixpos = dl->bounds.right_in; | |
819 | 4726 data.max_pixpos -= data.end_glyph_width; |
428 | 4727 |
4728 data.cursor_type = NO_CURSOR; | |
4729 data.cursor_x = -1; | |
4730 | |
4731 data.start_col = 0; | |
4732 /* I don't think we want this, string areas should not scroll with | |
434 | 4733 the window |
428 | 4734 data.start_col = w->hscroll; |
826 | 4735 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
428 | 4736 */ |
826 | 4737 data.byte_start_col_enabled = 0; |
428 | 4738 data.hscroll_glyph_width_adjust = 0; |
4739 | |
4740 /* We regenerate the line from the very beginning. */ | |
4741 Dynarr_reset (db->runes); | |
4742 | |
4743 /* Why is this less than or equal and not just less than? If the | |
4744 starting position is already equal to the maximum we can't add | |
4745 anything else, right? Wrong. We might still have a newline to | |
4746 add. A newline can use the room allocated for an end glyph since | |
4747 if we add it we know we aren't going to be adding any end | |
4748 glyph. */ | |
4749 | |
4750 /* #### Chuck -- I think this condition should be while (1). | |
4751 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
4752 and the begin-glyph ends exactly at the end of the window, the | |
4753 end-glyph and text might not be displayed. while (1) ensures | |
4754 that the loop terminates only when either (a) there is | |
4755 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
4756 | |
4757 #### Also I think you need to ensure that the operation | |
4758 "add begin glyphs; add end glyphs; add text" is atomic and | |
4759 can't get interrupted in the middle. If you run off the end | |
4760 of the line during that operation, then you keep accumulating | |
4761 propagation data until you're done. Otherwise, if the (e.g.) | |
4762 there's a begin glyph at a particular position and attempting | |
4763 to display that glyph results in window-end being hit and | |
4764 propagation data being generated, then the character at that | |
4765 position won't be displayed. | |
4766 | |
4767 #### See also the comment after the end of this loop, below. | |
4768 */ | |
4769 while (data.pixpos <= data.max_pixpos) | |
4770 { | |
4771 /* #### This check probably should not be necessary. */ | |
826 | 4772 if (data.byte_charpos > byte_string_zv) |
428 | 4773 { |
4774 /* #### urk! More of this lossage! */ | |
826 | 4775 data.byte_charpos--; |
428 | 4776 goto done; |
4777 } | |
4778 | |
4779 /* Check for face changes. */ | |
826 | 4780 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
428 | 4781 { |
819 | 4782 Lisp_Object last_glyph = Qnil; |
4783 /* Deal with clipped glyphs that we have already displayed. */ | |
4967 | 4784 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
4785 { | |
4786 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
819 | 4787 Dynarr_free (*prop); |
4788 *prop = 0; | |
4789 } | |
428 | 4790 /* Now compute the face and begin/end-glyph information. */ |
4791 data.findex = | |
793 | 4792 /* Remember that the extent-fragment routines deal in |
4187 | 4793 Bytexpos's. */ |
826 | 4794 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
428 | 4795 /* This is somewhat cheesy but the alternative is to |
4187 | 4796 propagate default_face into extent_fragment_update. */ |
428 | 4797 if (data.findex == DEFAULT_INDEX) |
4798 data.findex = default_face; | |
4799 | |
4800 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
4801 | |
826 | 4802 if (data.byte_charpos == data.ef->end) |
428 | 4803 no_more_frags = 1; |
4804 } | |
4805 initial = 0; | |
4806 | |
4807 /* Determine what is next to be displayed. We first handle any | |
4187 | 4808 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
4809 display then we determine what to do based on the character at the | |
4810 current buffer position. */ | |
428 | 4811 |
4812 /* If the current position is covered by an invisible extent, do | |
4187 | 4813 nothing (except maybe add some ellipses). |
428 | 4814 |
4815 #### The behavior of begin and end-glyphs at the edge of an | |
4816 invisible extent should be investigated further. This is | |
4817 fairly low priority though. */ | |
4818 if (data.ef->invisible) | |
4819 { | |
4820 /* #### Chuck, perhaps you could look at this code? I don't | |
4821 really know what I'm doing. */ | |
4822 if (*prop) | |
4823 { | |
4824 Dynarr_free (*prop); | |
4825 *prop = 0; | |
4826 } | |
4827 | |
4828 /* The extent fragment code only sets this when we should | |
4829 really display the ellipses. It makes sure the ellipses | |
4830 don't get displayed more than once in a row. */ | |
4831 if (data.ef->invisible_ellipses) | |
4832 { | |
4833 struct glyph_block gb; | |
4834 | |
4835 data.ef->invisible_ellipses_already_displayed = 1; | |
4836 data.ef->invisible_ellipses = 0; | |
4837 gb.extent = Qnil; | |
4838 gb.glyph = Vinvisible_text_glyph; | |
4839 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
4840 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
4841 /* Perhaps they shouldn't propagate if the very next thing | |
4842 is to display a newline (for compatibility with | |
4843 selective-display-ellipses)? Maybe that's too | |
4844 abstruse. */ | |
4845 if (*prop) | |
4846 goto done; | |
4847 } | |
4848 | |
638 | 4849 /* #### What if we're dealing with a display table? */ |
428 | 4850 if (data.start_col) |
4851 data.start_col--; | |
4852 | |
826 | 4853 if (data.byte_charpos == byte_string_zv) |
428 | 4854 goto done; |
4855 else | |
826 | 4856 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 4857 } |
4858 | |
4859 /* If there is propagation data, then it represents the current | |
4187 | 4860 buffer position being displayed. Add them and advance the |
4861 position counter. This might also add the minibuffer | |
4862 prompt. */ | |
428 | 4863 else if (*prop) |
4864 { | |
4865 dl->used_prop_data = 1; | |
4866 *prop = add_propagation_runes (prop, &data); | |
4867 | |
4868 if (*prop) | |
4869 goto done; /* gee, a really narrow window */ | |
826 | 4870 else if (data.byte_charpos == byte_string_zv) |
428 | 4871 goto done; |
826 | 4872 else if (data.byte_charpos < 0) |
428 | 4873 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
826 | 4874 data.byte_charpos = 0; |
428 | 4875 else |
826 | 4876 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 4877 } |
4878 | |
4879 /* If there are end glyphs, add them to the line. These are | |
4880 the end glyphs for the previous run of text. We add them | |
4881 here rather than doing them at the end of handling the | |
4882 previous run so that glyphs at the beginning and end of | |
4883 a line are handled correctly. */ | |
4884 else if (Dynarr_length (data.ef->end_glyphs) > 0) | |
4885 { | |
867 | 4886 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4887 *prop = add_glyph_runes (&data, END_GLYPHS); |
819 | 4888 |
4889 if (*prop) { | |
428 | 4890 goto done; |
819 | 4891 } |
428 | 4892 } |
4893 | |
4894 /* If there are begin glyphs, add them to the line. */ | |
4895 else if (Dynarr_length (data.ef->begin_glyphs) > 0) | |
4896 { | |
867 | 4897 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4898 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); |
819 | 4899 |
4900 if (*prop) { | |
428 | 4901 goto done; |
819 | 4902 } |
428 | 4903 } |
4904 | |
4905 /* If at end-of-buffer, we've already processed begin and | |
4906 end-glyphs at this point and there's no text to process, | |
4907 so we're done. */ | |
826 | 4908 else if (data.byte_charpos == byte_string_zv) |
428 | 4909 goto done; |
4910 | |
4911 else | |
4912 { | |
4913 Lisp_Object entry = Qnil; | |
4914 /* Get the character at the current buffer position. */ | |
867 | 4915 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4916 if (!NILP (face_dt) || !NILP (window_dt)) |
4917 entry = display_table_entry (data.ch, face_dt, window_dt); | |
4918 | |
4919 /* If there is a display table entry for it, hand it off to | |
4187 | 4920 add_disp_table_entry_runes and let it worry about it. */ |
428 | 4921 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
4922 { | |
4923 *prop = add_disp_table_entry_runes (&data, entry); | |
4924 | |
4925 if (*prop) | |
4926 goto done; | |
4927 } | |
4928 | |
4929 /* Check if we have hit a newline character. If so, add a marker | |
4187 | 4930 to the line and end this loop. */ |
428 | 4931 else if (data.ch == '\n') |
4932 { | |
4933 /* We aren't going to be adding an end glyph so give its | |
4187 | 4934 space back in order to make sure that the cursor can |
4935 fit. */ | |
819 | 4936 data.max_pixpos += data.end_glyph_width; |
428 | 4937 goto done; |
4938 } | |
4939 | |
4940 /* If the current character is considered to be printable, then | |
4187 | 4941 just add it. */ |
428 | 4942 else if (data.ch >= printable_min) |
4943 { | |
867 | 4944 *prop = add_ichar_rune (&data); |
428 | 4945 if (*prop) |
4946 goto done; | |
4947 } | |
4948 | |
4949 /* If the current character is a tab, determine the next tab | |
4187 | 4950 starting position and add a blank rune which extends from the |
4951 current pixel position to that starting position. */ | |
428 | 4952 else if (data.ch == '\t') |
4953 { | |
4954 int tab_start_pixpos = data.pixpos; | |
4955 int next_tab_start; | |
4956 int char_tab_width; | |
4957 int prop_width = 0; | |
4958 | |
4959 if (data.start_col > 1) | |
4960 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); | |
4961 | |
4962 next_tab_start = | |
4963 next_tab_position (w, tab_start_pixpos, | |
4964 dl->bounds.left_in + | |
4965 data.hscroll_glyph_width_adjust); | |
4966 if (next_tab_start > data.max_pixpos) | |
4967 { | |
4968 prop_width = next_tab_start - data.max_pixpos; | |
4969 next_tab_start = data.max_pixpos; | |
4970 } | |
4971 data.blank_width = next_tab_start - data.pixpos; | |
4972 char_tab_width = | |
4973 (next_tab_start - tab_start_pixpos) / space_width (w); | |
4974 | |
4975 *prop = add_blank_rune (&data, w, char_tab_width); | |
4976 | |
4977 /* add_blank_rune is only supposed to be called with | |
819 | 4978 sizes guaranteed to fit in the available space. */ |
428 | 4979 assert (!(*prop)); |
4980 | |
4981 if (prop_width) | |
4982 { | |
4983 struct prop_block pb; | |
4984 *prop = Dynarr_new (prop_block); | |
4985 | |
4986 pb.type = PROP_BLANK; | |
4987 pb.data.p_blank.width = prop_width; | |
4988 pb.data.p_blank.findex = data.findex; | |
4989 Dynarr_add (*prop, pb); | |
4990 | |
4991 goto done; | |
4992 } | |
4993 } | |
4994 | |
4995 /* If character is a control character, pass it off to | |
4187 | 4996 add_control_char_runes. |
428 | 4997 |
4998 The is_*() routines have undefined results on | |
4999 arguments outside of the range [-1, 255]. (This | |
5000 often bites people who carelessly use `char' instead | |
5001 of `unsigned char'.) | |
5002 */ | |
867 | 5003 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
428 | 5004 { |
5005 *prop = add_control_char_runes (&data, b); | |
5006 | |
5007 if (*prop) | |
5008 goto done; | |
5009 } | |
5010 | |
5011 /* If the character is above the ASCII range and we have not | |
4187 | 5012 already handled it, then print it as an octal number. */ |
428 | 5013 else if (data.ch >= 0200) |
5014 { | |
5015 *prop = add_octal_runes (&data); | |
5016 | |
5017 if (*prop) | |
5018 goto done; | |
5019 } | |
5020 | |
5021 /* Assume the current character is considered to be printable, | |
4187 | 5022 then just add it. */ |
428 | 5023 else |
5024 { | |
867 | 5025 *prop = add_ichar_rune (&data); |
428 | 5026 if (*prop) |
5027 goto done; | |
5028 } | |
5029 | |
826 | 5030 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 5031 } |
5032 } | |
5033 | |
819 | 5034 done: |
428 | 5035 |
5036 /* Determine the starting point of the next line if we did not hit the | |
5037 end of the buffer. */ | |
826 | 5038 if (data.byte_charpos < byte_string_zv) |
428 | 5039 { |
5040 /* #### This check is not correct. If the line terminated | |
5041 due to a begin-glyph or end-glyph hitting window-end, then | |
826 | 5042 data.ch will not point to the character at data.byte_charpos. If |
428 | 5043 you make the two changes mentioned at the top of this loop, |
5044 you should be able to say '(if (*prop))'. That should also | |
826 | 5045 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 5046 check. */ |
5047 | |
5048 /* The common case is that the line ended because we hit a newline. | |
4187 | 5049 In that case, the next character is just the next buffer |
5050 position. */ | |
428 | 5051 if (data.ch == '\n') |
5052 { | |
826 | 5053 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 5054 } |
5055 | |
5056 /* Otherwise we have a buffer line which cannot fit on one display | |
4187 | 5057 line. */ |
428 | 5058 else |
5059 { | |
5060 struct glyph_block gb; | |
5061 struct glyph_cachel *cachel; | |
5062 | |
5063 /* If the line is to be truncated then we actually have to look | |
4187 | 5064 for the next newline. We also add the end-of-line glyph which |
5065 we know will fit because we adjusted the right border before | |
5066 we starting laying out the line. */ | |
819 | 5067 data.max_pixpos += data.end_glyph_width; |
428 | 5068 data.findex = default_face; |
5069 gb.extent = Qnil; | |
5070 | |
5071 if (truncate_win) | |
5072 { | |
826 | 5073 Bytecount byte_pos; |
428 | 5074 |
5075 /* Now find the start of the next line. */ | |
867 | 5076 byte_pos = byte_find_next_ichar_in_string (disp_string, '\n', |
826 | 5077 data.byte_charpos, 1); |
428 | 5078 |
5079 data.cursor_type = NO_CURSOR; | |
826 | 5080 data.byte_charpos = byte_pos; |
428 | 5081 gb.glyph = Vtruncation_glyph; |
5082 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
5083 } | |
5084 else | |
5085 { | |
5086 /* The cursor can never be on the continuation glyph. */ | |
5087 data.cursor_type = NO_CURSOR; | |
5088 | |
826 | 5089 /* data.byte_charpos is already at the start of the next line. */ |
428 | 5090 |
442 | 5091 dl->line_continuation = 1; |
428 | 5092 gb.glyph = Vcontinuation_glyph; |
5093 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
5094 } | |
5095 | |
819 | 5096 if (data.end_glyph_width) |
428 | 5097 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
5098 | |
826 | 5099 if (truncate_win && data.byte_charpos == byte_string_zv) |
428 | 5100 { |
867 | 5101 const Ibyte *endb = itext_n_addr (XSTRING_DATA (disp_string), |
826 | 5102 byte_string_zv); |
867 | 5103 DEC_IBYTEPTR (endb); |
5104 if (itext_ichar (endb) != '\n') | |
428 | 5105 { |
5106 /* #### Damn this losing shit. */ | |
826 | 5107 data.byte_charpos++; |
428 | 5108 } |
5109 } | |
5110 } | |
5111 } | |
826 | 5112 else if (data.byte_charpos == byte_string_zv) |
428 | 5113 { |
5114 /* create_text_block () adds a bogus \n marker here which screws | |
5115 up subwindow display. Since we never have a cursor in the | |
5116 gutter we can safely ignore it. */ | |
5117 } | |
5118 /* Calculate left whitespace boundary. */ | |
5119 { | |
5120 int elt = 0; | |
5121 | |
5122 /* Whitespace past a newline is considered right whitespace. */ | |
5123 while (elt < Dynarr_length (db->runes)) | |
5124 { | |
5125 struct rune *rb = Dynarr_atp (db->runes, elt); | |
5126 | |
5127 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
5128 || rb->type == RUNE_BLANK) | |
5129 { | |
5130 dl->bounds.left_white += rb->width; | |
5131 elt++; | |
5132 } | |
5133 else | |
5134 elt = Dynarr_length (db->runes); | |
5135 } | |
5136 } | |
5137 | |
5138 /* Calculate right whitespace boundary. */ | |
5139 { | |
5140 int elt = Dynarr_length (db->runes) - 1; | |
5141 int done = 0; | |
5142 | |
5143 while (!done && elt >= 0) | |
5144 { | |
5145 struct rune *rb = Dynarr_atp (db->runes, elt); | |
5146 | |
5147 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
5148 && isspace (rb->object.chr.ch)) | |
5149 && !rb->type == RUNE_BLANK) | |
5150 { | |
5151 dl->bounds.right_white = rb->xpos + rb->width; | |
5152 done = 1; | |
5153 } | |
5154 | |
5155 elt--; | |
5156 | |
5157 } | |
5158 | |
5159 /* The line is blank so everything is considered to be right | |
5160 whitespace. */ | |
5161 if (!done) | |
5162 dl->bounds.right_white = dl->bounds.left_in; | |
5163 } | |
5164 | |
5165 /* Set the display blocks bounds. */ | |
5166 db->start_pos = dl->bounds.left_in; | |
5167 if (Dynarr_length (db->runes)) | |
5168 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
5169 struct rune *rb = Dynarr_lastp (db->runes); |
428 | 5170 |
5171 db->end_pos = rb->xpos + rb->width; | |
5172 } | |
5173 else | |
5174 db->end_pos = dl->bounds.right_white; | |
5175 | |
819 | 5176 calculate_baseline (&data); |
428 | 5177 |
5178 dl->ascent = data.new_ascent; | |
5179 dl->descent = data.new_descent; | |
5180 | |
5181 { | |
5182 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
5183 | |
5184 if (dl->ascent < ascent) | |
5185 dl->ascent = ascent; | |
5186 } | |
5187 { | |
5188 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
5189 | |
5190 if (dl->descent < descent) | |
5191 dl->descent = descent; | |
5192 } | |
5193 | |
819 | 5194 calculate_yoffset (dl, db); |
5195 | |
428 | 5196 dl->cursor_elt = data.cursor_x; |
5197 /* #### lossage lossage lossage! Fix this shit! */ | |
826 | 5198 if (data.byte_charpos > byte_string_zv) |
5199 dl->end_charpos = buffer_or_string_bytexpos_to_charxpos (disp_string, | |
5200 byte_string_zv); | |
428 | 5201 else |
826 | 5202 dl->end_charpos = |
5203 buffer_or_string_bytexpos_to_charxpos (disp_string, | |
5204 data.byte_charpos) - 1; | |
428 | 5205 if (truncate_win) |
434 | 5206 data.dl->num_chars = |
826 | 5207 string_column_at_point (disp_string, dl->end_charpos, |
793 | 5208 b ? XINT (b->tab_width) : 8); |
428 | 5209 else |
5210 /* This doesn't correctly take into account tabs and control | |
5211 characters but if the window isn't being truncated then this | |
5212 value isn't going to end up being used anyhow. */ | |
826 | 5213 data.dl->num_chars = dl->end_charpos - dl->charpos; |
428 | 5214 |
5215 /* #### handle horizontally scrolled line with text none of which | |
5216 was actually laid out. */ | |
5217 | |
5218 /* #### handle any remainder of overlay arrow */ | |
5219 | |
5220 if (*prop == ADD_FAILED) | |
5221 *prop = NULL; | |
5222 | |
5223 if (truncate_win && *prop) | |
5224 { | |
5225 Dynarr_free (*prop); | |
5226 *prop = NULL; | |
5227 } | |
5228 | |
5229 extent_fragment_delete (data.ef); | |
5230 | |
5231 /* #### If we started at EOB, then make sure we return a value past | |
5232 it so that regenerate_window will exit properly. This is bogus. | |
5233 The main loop should get fixed so that it isn't necessary to call | |
5234 this function if we are already at EOB. */ | |
5235 | |
826 | 5236 if (data.byte_charpos == byte_string_zv && byte_start_pos == byte_string_zv) |
793 | 5237 return string_index_byte_to_char (disp_string, |
826 | 5238 data.byte_charpos) + 1; /* Yuck! */ |
428 | 5239 else |
826 | 5240 return string_index_byte_to_char (disp_string, data.byte_charpos); |
428 | 5241 } |
5242 | |
5243 /* Given a display line and a starting position, ensure that the | |
5244 contents of the display line accurately represent the visual | |
5245 representation of the buffer contents starting from the given | |
5246 position when displayed in the given window. The display line ends | |
5247 when the contents of the line reach the right boundary of the given | |
434 | 5248 window. |
5249 | |
428 | 5250 This is very similar to generate_display_line but with the same |
5251 limitations as create_string_text_block. I have taken the liberty | |
665 | 5252 of fixing the bytebpos stuff though.*/ |
5253 | |
5254 static Charbpos | |
428 | 5255 generate_string_display_line (struct window *w, Lisp_Object disp_string, |
5256 struct display_line *dl, | |
826 | 5257 Charcount start_pos, |
428 | 5258 prop_block_dynarr **prop, |
5259 face_index default_face) | |
5260 { | |
826 | 5261 Charcount ret_charcount; |
428 | 5262 |
5263 /* you must set bounds before calling this. */ | |
434 | 5264 |
428 | 5265 /* Reset what this line is using. */ |
5266 if (dl->display_blocks) | |
5267 Dynarr_reset (dl->display_blocks); | |
5268 if (dl->left_glyphs) | |
5269 { | |
5270 Dynarr_free (dl->left_glyphs); | |
5271 dl->left_glyphs = 0; | |
5272 } | |
5273 if (dl->right_glyphs) | |
5274 { | |
5275 Dynarr_free (dl->right_glyphs); | |
5276 dl->right_glyphs = 0; | |
5277 } | |
5278 | |
5279 /* We aren't generating a modeline at the moment. */ | |
5280 dl->modeline = 0; | |
5281 | |
5282 /* Create a display block for the text region of the line. */ | |
826 | 5283 ret_charcount = create_string_text_block (w, disp_string, dl, start_pos, |
5284 prop, default_face); | |
5285 dl->charpos = start_pos; | |
5286 if (dl->end_charpos < dl->charpos) | |
5287 dl->end_charpos = dl->charpos; | |
428 | 5288 |
5289 /* If there are left glyphs associated with any character in the | |
5290 text block, then create a display block to handle them. */ | |
5291 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
5292 create_left_glyph_block (w, dl, 0); | |
5293 | |
5294 /* If there are right glyphs associated with any character in the | |
5295 text block, then create a display block to handle them. */ | |
5296 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
5297 create_right_glyph_block (w, dl); | |
5298 | |
826 | 5299 return ret_charcount; |
428 | 5300 } |
5301 | |
2518 | 5302 /* |
5303 | |
5304 Info on Re-entrancy crashes, with backtraces given: | |
5305 | |
5306 (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT") | |
1318 | 5307 */ |
5308 | |
5309 | |
428 | 5310 /* This is ripped off from regenerate_window. All we want to do is |
5311 loop through elements in the string creating display lines until we | |
5312 have covered the provided area. Simple really. */ | |
5313 void | |
5314 generate_displayable_area (struct window *w, Lisp_Object disp_string, | |
5315 int xpos, int ypos, int width, int height, | |
5316 display_line_dynarr* dla, | |
826 | 5317 Charcount start_pos, |
428 | 5318 face_index default_face) |
5319 { | |
5320 int yend = ypos + height; | |
5321 Charcount s_zv; | |
5322 prop_block_dynarr *prop = 0; | |
5323 layout_bounds bounds; | |
2518 | 5324 int depth = -1; |
5325 | |
428 | 5326 /* if there's nothing to do then do nothing. code after this assumes |
5327 there is something to do. */ | |
5328 if (NILP (disp_string)) | |
5329 return; | |
5330 | |
2518 | 5331 /* See comment in regenerate_window() */ |
5332 if (!in_display) | |
5333 depth = enter_redisplay_critical_section (); | |
5334 | |
5335 assert (dla); | |
5336 Dynarr_reset (dla); | |
5337 | |
826 | 5338 s_zv = string_char_length (disp_string); |
428 | 5339 |
5340 bounds.left_out = xpos; | |
5341 bounds.right_out = xpos + width; | |
5342 /* The inner boundaries mark where the glyph margins are located. */ | |
5343 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
5344 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
5345 /* We cannot fully calculate the whitespace boundaries as they | |
5346 depend on the contents of the line being displayed. */ | |
5347 bounds.left_white = bounds.left_in; | |
5348 bounds.right_white = bounds.right_in; | |
5349 | |
5350 while (ypos < yend) | |
5351 { | |
5352 struct display_line dl; | |
5353 struct display_line *dlp; | |
826 | 5354 Charcount next_pos; |
428 | 5355 int local; |
851 | 5356 int pos_of_dlp = -1; |
428 | 5357 |
5358 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5359 { | |
851 | 5360 pos_of_dlp = Dynarr_length (dla); |
5361 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5362 local = 0; |
5363 } | |
5364 else | |
5365 { | |
4207 | 5366 DISPLAY_LINE_INIT (dl); |
428 | 5367 dlp = &dl; |
5368 local = 1; | |
5369 } | |
5370 | |
5371 dlp->bounds = bounds; | |
5372 dlp->offset = 0; | |
1318 | 5373 Dynarr_lock (dla); |
428 | 5374 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos, |
5375 &prop, default_face); | |
1318 | 5376 Dynarr_unlock (dla); |
428 | 5377 /* we need to make sure that we continue along the line if there |
4187 | 5378 is more left to display otherwise we just end up redisplaying |
5379 the same chunk over and over again. */ | |
428 | 5380 if (next_pos == start_pos && next_pos < s_zv) |
5381 start_pos++; | |
5382 else | |
5383 start_pos = next_pos; | |
5384 | |
5385 dlp->ypos = ypos + dlp->ascent; | |
5386 ypos = dlp->ypos + dlp->descent; | |
5387 | |
5388 if (ypos > yend) | |
5389 { | |
5390 int visible_height = dlp->ascent + dlp->descent; | |
5391 | |
5392 dlp->clip = (ypos - yend); | |
5393 visible_height -= dlp->clip; | |
5394 | |
5395 if (visible_height < VERTICAL_CLIP (w, 1)) | |
5396 { | |
5397 if (local) | |
5398 free_display_line (dlp); | |
5399 break; | |
5400 } | |
5401 } | |
5402 else | |
5403 dlp->clip = 0; | |
5404 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5405 if (pos_of_dlp < 0) |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5406 Dynarr_add (dla, *dlp); |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5407 else if (pos_of_dlp == Dynarr_length (dla)) |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5408 Dynarr_increment (dla); |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5409 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5410 ABORT (); |
428 | 5411 |
5412 /* #### This type of check needs to be done down in the | |
5413 generate_display_line call. */ | |
5414 if (start_pos >= s_zv) | |
5415 break; | |
5416 } | |
5417 | |
5418 if (prop) | |
5419 Dynarr_free (prop); | |
2518 | 5420 |
5421 if (depth >= 0) | |
5422 exit_redisplay_critical_section (depth); | |
428 | 5423 } |
5424 | |
5425 | |
5426 /***************************************************************************/ | |
5427 /* */ | |
5428 /* window-regeneration routines */ | |
5429 /* */ | |
5430 /***************************************************************************/ | |
5431 | |
5432 /* For a given window and starting position in the buffer it contains, | |
5433 ensure that the TYPE display lines accurately represent the | |
5434 presentation of the window. We pass the buffer instead of getting | |
5435 it from the window since redisplay_window may have temporarily | |
5436 changed it to the echo area buffer. */ | |
5437 | |
5438 static void | |
2518 | 5439 regenerate_window (struct window *w, Charbpos start_pos, Charbpos point, |
5440 int type) | |
428 | 5441 { |
5442 struct frame *f = XFRAME (w->frame); | |
5443 struct buffer *b = XBUFFER (w->buffer); | |
5444 int ypos = WINDOW_TEXT_TOP (w); | |
5445 int yend; /* set farther down */ | |
5446 int yclip = WINDOW_TEXT_TOP_CLIP (w); | |
442 | 5447 int force; |
2518 | 5448 int depth = -1; |
428 | 5449 |
5450 prop_block_dynarr *prop; | |
5451 layout_bounds bounds; | |
5452 display_line_dynarr *dla; | |
5453 int need_modeline; | |
5454 | |
5455 /* The lines had better exist by this point. */ | |
5456 if (!(dla = window_display_lines (w, type))) | |
2500 | 5457 ABORT (); |
2518 | 5458 |
5459 if (!in_display) | |
5460 depth = enter_redisplay_critical_section (); | |
5461 | |
5462 /* This is one spot where a re-entrancy crash will occur, due to a check | |
5463 in the dynarr to make sure it isn't "locked" */ | |
5464 /* | |
5465 | |
5466 Info on Re-entrancy crashes, with backtraces given: | |
5467 | |
5468 (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT") | |
5469 */ | |
5470 | |
428 | 5471 Dynarr_reset (dla); |
5472 w->max_line_len = 0; | |
5473 | |
5474 /* Normally these get updated in redisplay_window but it is possible | |
5475 for this function to get called from some other points where that | |
5476 update may not have occurred. This acts as a safety check. */ | |
5477 if (!Dynarr_length (w->face_cachels)) | |
5478 reset_face_cachels (w); | |
5479 if (!Dynarr_length (w->glyph_cachels)) | |
5480 reset_glyph_cachels (w); | |
5481 | |
5482 Fset_marker (w->start[type], make_int (start_pos), w->buffer); | |
5483 Fset_marker (w->pointm[type], make_int (point), w->buffer); | |
5484 w->last_point_x[type] = -1; | |
5485 w->last_point_y[type] = -1; | |
5486 | |
5487 /* Make sure a modeline is in the structs if needed. */ | |
5488 need_modeline = ensure_modeline_generated (w, type); | |
5489 | |
5490 /* Wait until here to set this so that the structs have a modeline | |
5491 generated in the case where one didn't exist. */ | |
5492 yend = WINDOW_TEXT_BOTTOM (w); | |
5493 | |
5494 bounds = calculate_display_line_boundaries (w, 0); | |
5495 | |
5496 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */ | |
5497 if (MINI_WINDOW_P (w) | |
5498 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt)) | |
5499 && !echo_area_active (f) | |
5500 && start_pos == BUF_BEGV (b)) | |
5501 { | |
5502 struct prop_block pb; | |
5503 Lisp_Object string; | |
5504 prop = Dynarr_new (prop_block); | |
5505 | |
5506 string = concat2(Vminibuf_preprompt, Vminibuf_prompt); | |
5507 pb.type = PROP_MINIBUF_PROMPT; | |
5508 pb.data.p_string.str = XSTRING_DATA(string); | |
5509 pb.data.p_string.len = XSTRING_LENGTH(string); | |
5510 Dynarr_add (prop, pb); | |
5511 } | |
5512 else | |
5513 prop = 0; | |
5514 | |
442 | 5515 /* When we are computing things for scrolling purposes, make |
5516 sure at least one line is always generated */ | |
5517 force = (type == CMOTION_DISP); | |
5518 | |
5519 /* Make sure this is set always */ | |
5520 /* Note the conversion at end */ | |
5521 w->window_end_pos[type] = start_pos; | |
5522 while (ypos < yend || force) | |
428 | 5523 { |
5524 struct display_line dl; | |
5525 struct display_line *dlp; | |
5526 int local; | |
851 | 5527 int pos_of_dlp = -1; |
428 | 5528 |
5529 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5530 { | |
851 | 5531 pos_of_dlp = Dynarr_length (dla); |
5532 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5533 local = 0; |
5534 } | |
5535 else | |
5536 { | |
4207 | 5537 DISPLAY_LINE_INIT (dl); |
428 | 5538 dlp = &dl; |
5539 local = 1; | |
5540 } | |
5541 | |
5542 dlp->bounds = bounds; | |
5543 dlp->offset = 0; | |
1318 | 5544 Dynarr_lock (dla); |
428 | 5545 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); |
1318 | 5546 Dynarr_unlock (dla); |
428 | 5547 |
5548 if (yclip > dlp->ascent) | |
5549 { | |
5550 /* this should never happen, but if it does just display the | |
5551 whole line */ | |
5552 yclip = 0; | |
5553 } | |
5554 | |
5555 dlp->ypos = (ypos + dlp->ascent) - yclip; | |
5556 ypos = dlp->ypos + dlp->descent; | |
5557 | |
5558 /* See if we've been asked to start midway through a line, for | |
4187 | 5559 partial display line scrolling. */ |
434 | 5560 if (yclip) |
428 | 5561 { |
5562 dlp->top_clip = yclip; | |
5563 yclip = 0; | |
5564 } | |
5565 else | |
5566 dlp->top_clip = 0; | |
5567 | |
5568 if (ypos > yend) | |
5569 { | |
5570 int visible_height = dlp->ascent + dlp->descent; | |
5571 | |
5572 dlp->clip = (ypos - yend); | |
5573 /* Although this seems strange we could have a single very | |
5574 tall line visible for which we need to account for both | |
5575 the top clip and the bottom clip. */ | |
5576 visible_height -= (dlp->clip + dlp->top_clip); | |
5577 | |
442 | 5578 if (visible_height < VERTICAL_CLIP (w, 1) && !force) |
428 | 5579 { |
5580 if (local) | |
5581 free_display_line (dlp); | |
5582 break; | |
5583 } | |
5584 } | |
5585 else | |
5586 dlp->clip = 0; | |
5587 | |
5588 if (dlp->cursor_elt != -1) | |
5589 { | |
5590 /* #### This check is steaming crap. Have to get things | |
4187 | 5591 fixed so when create_text_block hits EOB, we're done, |
5592 period. */ | |
428 | 5593 if (w->last_point_x[type] == -1) |
5594 { | |
5595 w->last_point_x[type] = dlp->cursor_elt; | |
5596 w->last_point_y[type] = Dynarr_length (dla); | |
5597 } | |
5598 else | |
5599 { | |
5600 /* #### This means that we've added a cursor at EOB | |
4187 | 5601 twice. Yuck oh yuck. */ |
1318 | 5602 struct display_block *db; |
5603 | |
5604 Dynarr_lock (dla); | |
5605 db = get_display_block_from_line (dlp, TEXT); | |
5606 Dynarr_unlock (dla); | |
428 | 5607 |
5608 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR; | |
5609 dlp->cursor_elt = -1; | |
5610 } | |
5611 } | |
5612 | |
5613 if (dlp->num_chars > w->max_line_len) | |
5614 w->max_line_len = dlp->num_chars; | |
5615 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5616 if (pos_of_dlp < 0) |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5617 Dynarr_add (dla, *dlp); |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5618 else if (pos_of_dlp == Dynarr_length (dla)) |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5619 Dynarr_increment (dla); |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5620 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5621 ABORT (); |
428 | 5622 |
5623 /* #### This isn't right, but it is close enough for now. */ | |
5624 w->window_end_pos[type] = start_pos; | |
5625 | |
5626 /* #### This type of check needs to be done down in the | |
5627 generate_display_line call. */ | |
5628 if (start_pos > BUF_ZV (b)) | |
5629 break; | |
442 | 5630 |
5631 force = 0; | |
428 | 5632 } |
5633 | |
5634 if (prop) | |
5635 Dynarr_free (prop); | |
5636 | |
5637 /* #### More not quite right, but close enough. */ | |
442 | 5638 /* Ben sez: apparently window_end_pos[] is measured |
428 | 5639 as the number of characters between the window end and the |
5640 end of the buffer? This seems rather weirdo. What's | |
442 | 5641 the justification for this? |
5642 | |
5643 JV sez: Because BUF_Z (b) would be a good initial value, however | |
5644 that can change. This representation allows initalizing with 0. | |
5645 */ | |
428 | 5646 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; |
5647 | |
5648 if (need_modeline) | |
5649 { | |
5650 /* We know that this is the right thing to use because we put it | |
4187 | 5651 there when we first started working in this function. */ |
4967 | 5652 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 5653 } |
2518 | 5654 |
5655 if (depth >= 0) | |
5656 exit_redisplay_critical_section (depth); | |
428 | 5657 } |
5658 | |
826 | 5659 #define REGEN_INC_FIND_START_END \ |
5660 do { \ | |
5661 /* Determine start and end of lines. */ \ | |
5662 if (!Dynarr_length (cdla)) \ | |
5663 return 0; \ | |
5664 else \ | |
5665 { \ | |
4967 | 5666 if (Dynarr_begin (cdla)->modeline && Dynarr_begin (ddla)->modeline) \ |
826 | 5667 { \ |
5668 dla_start = 1; \ | |
5669 } \ | |
4967 | 5670 else if (!Dynarr_begin (cdla)->modeline \ |
5671 && !Dynarr_begin (ddla)->modeline) \ | |
826 | 5672 { \ |
5673 dla_start = 0; \ | |
5674 } \ | |
5675 else \ | |
2500 | 5676 ABORT (); /* structs differ */ \ |
826 | 5677 \ |
5678 dla_end = Dynarr_length (cdla) - 1; \ | |
5679 } \ | |
5680 \ | |
5681 start_pos = (Dynarr_atp (cdla, dla_start)->charpos \ | |
5682 + Dynarr_atp (cdla, dla_start)->offset); \ | |
5683 /* If this isn't true, then startp has changed and we need to do a \ | |
5684 full regen. */ \ | |
5685 if (startp != start_pos) \ | |
5686 return 0; \ | |
5687 \ | |
5688 /* Point is outside the visible region so give up. */ \ | |
5689 if (pointm < start_pos) \ | |
5690 return 0; \ | |
5691 \ | |
428 | 5692 } while (0) |
5693 | |
5694 /* This attempts to incrementally update the display structures. It | |
5695 returns a boolean indicating success or failure. This function is | |
5696 very similar to regenerate_window_incrementally and is in fact only | |
5697 called from that function. However, because of the nature of the | |
5698 changes it deals with it sometimes makes different assumptions | |
5699 which can lead to success which are much more difficult to make | |
5700 when dealing with buffer changes. */ | |
5701 | |
5702 static int | |
665 | 5703 regenerate_window_extents_only_changed (struct window *w, Charbpos startp, |
5704 Charbpos pointm, | |
428 | 5705 Charcount beg_unchanged, |
5706 Charcount end_unchanged) | |
5707 { | |
5708 struct buffer *b = XBUFFER (w->buffer); | |
5709 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5710 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5711 | |
5712 int dla_start = 0; | |
5713 int dla_end, line; | |
5714 int first_line, last_line; | |
665 | 5715 Charbpos start_pos; |
428 | 5716 /* Don't define this in the loop where it is used because we |
5717 definitely want its value to survive between passes. */ | |
5718 prop_block_dynarr *prop = NULL; | |
5719 | |
5720 /* If we don't have any buffer change recorded but the modiff flag has | |
5721 been incremented, then fail. I'm not sure of the exact circumstances | |
5722 under which this can happen, but I believe that it is probably a | |
5723 reasonable happening. */ | |
5724 if (!point_visible (w, pointm, CURRENT_DISP) | |
5725 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)) | |
5726 return 0; | |
5727 | |
5728 /* If the cursor is moved we attempt to update it. If we succeed we | |
5729 go ahead and proceed with the optimization attempt. */ | |
5730 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5731 || pointm != marker_position (w->last_point[CURRENT_DISP])) | |
5732 { | |
5733 struct frame *f = XFRAME (w->frame); | |
5734 struct device *d = XDEVICE (f->device); | |
5735 struct frame *sel_f = device_selected_frame (d); | |
5736 int success = 0; | |
5737 | |
5738 if (w->last_point_x[CURRENT_DISP] != -1 | |
5739 && w->last_point_y[CURRENT_DISP] != -1) | |
5740 { | |
5741 | |
5742 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w))) | |
5743 { | |
5744 /* Always regenerate the modeline in case it is | |
4187 | 5745 displaying the current line or column. */ |
428 | 5746 regenerate_modeline (w); |
5747 success = 1; | |
5748 } | |
5749 } | |
5750 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f))) | |
5751 { | |
5752 if (f->modeline_changed) | |
5753 regenerate_modeline (w); | |
5754 success = 1; | |
5755 } | |
5756 | |
5757 if (!success) | |
5758 return 0; | |
5759 } | |
5760 | |
5761 if (beg_unchanged == -1 && end_unchanged == -1) | |
5762 return 1; | |
5763 | |
5764 /* assert: There are no buffer modifications or they are all below the | |
5765 visible region. We assume that regenerate_window_incrementally has | |
5766 not called us unless this is true. */ | |
5767 | |
5768 REGEN_INC_FIND_START_END; | |
5769 | |
5770 /* If the changed are starts before the visible area, give up. */ | |
5771 if (beg_unchanged < startp) | |
5772 return 0; | |
5773 | |
5774 /* Find what display line the extent changes first affect. */ | |
5775 line = dla_start; | |
5776 while (line <= dla_end) | |
5777 { | |
5778 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5779 Charbpos lstart = dl->charpos + dl->offset; |
5780 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5781 |
5782 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5783 break; | |
5784 | |
5785 line++; | |
5786 } | |
5787 | |
5788 /* If the changes are below the visible area then if point hasn't | |
5789 moved return success otherwise fail in order to be safe. */ | |
5790 if (line > dla_end) | |
5791 { | |
5792 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5793 && pointm == marker_position (w->last_point[CURRENT_DISP])) | |
5794 return 1; | |
5795 else | |
5796 return 0; | |
5797 } | |
5798 | |
5799 /* At this point we know what line the changes first affect. We now | |
5800 begin redrawing lines as long as we are still in the affected | |
5801 region and the line's size and positioning don't change. | |
5802 Otherwise we fail. If we fail we will have altered the desired | |
5803 structs which could lead to an assertion failure. However, if we | |
5804 fail the next thing that is going to happen is a full regen so we | |
5805 will actually end up being safe. */ | |
5806 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
5807 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
5808 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
5809 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
5810 | |
5811 first_line = last_line = line; | |
5812 while (line <= dla_end) | |
5813 { | |
2286 | 5814 Charbpos old_start, old_end; |
428 | 5815 struct display_line *cdl = Dynarr_atp (cdla, line); |
5816 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5817 struct display_block *db; | |
5818 int initial_size; | |
5819 | |
826 | 5820 assert (cdl->charpos == ddl->charpos); |
5821 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5822 assert (cdl->offset == ddl->offset); |
5823 | |
5824 db = get_display_block_from_line (ddl, TEXT); | |
5825 initial_size = Dynarr_length (db->runes); | |
826 | 5826 old_start = ddl->charpos + ddl->offset; |
5827 old_end = ddl->end_charpos + ddl->offset; | |
428 | 5828 |
5829 /* If this is the first line being updated and it used | |
4187 | 5830 propagation data, fail. Otherwise we'll be okay because |
5831 we'll have the necessary propagation data. */ | |
428 | 5832 if (line == first_line && ddl->used_prop_data) |
5833 return 0; | |
5834 | |
2286 | 5835 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
5836 &prop, DESIRED_DISP); | |
428 | 5837 ddl->offset = 0; |
5838 | |
5839 /* #### If there is propagated stuff the fail. We could | |
4187 | 5840 probably actually deal with this if the line had propagated |
5841 information when originally created by a full | |
5842 regeneration. */ | |
428 | 5843 if (prop) |
5844 { | |
5845 Dynarr_free (prop); | |
5846 return 0; | |
5847 } | |
5848 | |
5849 /* If any line position parameters have changed or a | |
4187 | 5850 cursor has disappeared or disappeared, fail. */ |
428 | 5851 db = get_display_block_from_line (ddl, TEXT); |
5852 if (cdl->ypos != ddl->ypos | |
5853 || cdl->ascent != ddl->ascent | |
5854 || cdl->descent != ddl->descent | |
5855 || cdl->top_clip != ddl->top_clip | |
5856 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
5857 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
826 | 5858 || old_start != ddl->charpos |
5859 || old_end != ddl->end_charpos | |
428 | 5860 || initial_size != Dynarr_length (db->runes)) |
5861 { | |
5862 return 0; | |
5863 } | |
5864 | |
5865 if (ddl->cursor_elt != -1) | |
5866 { | |
5867 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
5868 w->last_point_y[DESIRED_DISP] = line; | |
5869 } | |
5870 | |
5871 last_line = line; | |
5872 | |
5873 /* If the extent changes end on the line we just updated then | |
4187 | 5874 we're done. Otherwise go on to the next line. */ |
826 | 5875 if (end_unchanged <= ddl->end_charpos) |
428 | 5876 break; |
5877 else | |
5878 line++; | |
5879 } | |
5880 | |
5881 redisplay_update_line (w, first_line, last_line, 1); | |
5882 return 1; | |
5883 } | |
5884 | |
5885 /* Attempt to update the display data structures based on knowledge of | |
5886 the changed region in the buffer. Returns a boolean indicating | |
5887 success or failure. If this function returns a failure then a | |
5888 regenerate_window _must_ be performed next in order to maintain | |
5889 invariants located here. */ | |
5890 | |
5891 static int | |
665 | 5892 regenerate_window_incrementally (struct window *w, Charbpos startp, |
5893 Charbpos pointm) | |
428 | 5894 { |
5895 struct buffer *b = XBUFFER (w->buffer); | |
5896 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5897 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5898 Charcount beg_unchanged, end_unchanged; | |
5899 Charcount extent_beg_unchanged, extent_end_unchanged; | |
5900 | |
5901 int dla_start = 0; | |
5902 int dla_end, line; | |
665 | 5903 Charbpos start_pos; |
428 | 5904 |
5905 /* If this function is called, the current and desired structures | |
5906 had better be identical. If they are not, then that is a bug. */ | |
5907 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
5908 | |
5909 /* We don't handle minibuffer windows yet. The minibuffer prompt | |
5910 screws us up. */ | |
5911 if (MINI_WINDOW_P (w)) | |
5912 return 0; | |
5913 | |
5914 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b); | |
5915 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1 | |
5916 ? -1 | |
5917 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b)); | |
5918 | |
5919 /* If nothing has changed in the buffer, then make sure point is ok | |
5920 and succeed. */ | |
5921 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1) | |
5922 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5923 extent_beg_unchanged, | |
5924 extent_end_unchanged); | |
5925 | |
5926 /* We can't deal with deleted newlines. */ | |
5927 if (BUF_NEWLINE_WAS_DELETED (b)) | |
5928 return 0; | |
5929 | |
5930 beg_unchanged = BUF_BEGIN_UNCHANGED (b); | |
5931 end_unchanged = (BUF_END_UNCHANGED (b) == -1 | |
5932 ? -1 | |
5933 : BUF_Z (b) - BUF_END_UNCHANGED (b)); | |
5934 | |
5935 REGEN_INC_FIND_START_END; | |
5936 | |
5937 /* If the changed area starts before the visible area, give up. */ | |
5938 if (beg_unchanged < startp) | |
5939 return 0; | |
5940 | |
5941 /* Find what display line the buffer changes first affect. */ | |
5942 line = dla_start; | |
5943 while (line <= dla_end) | |
5944 { | |
5945 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5946 Charbpos lstart = dl->charpos + dl->offset; |
5947 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5948 |
5949 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5950 break; | |
5951 | |
5952 line++; | |
5953 } | |
5954 | |
5955 /* If the changes are below the visible area then if point hasn't | |
5956 moved return success otherwise fail in order to be safe. */ | |
5957 if (line > dla_end) | |
5958 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5959 extent_beg_unchanged, | |
5960 extent_end_unchanged); | |
5961 else | |
5962 /* At this point we know what line the changes first affect. We | |
5963 now redraw that line. If the changes are contained within it | |
5964 we are going to succeed and can update just that one line. | |
5965 Otherwise we fail. If we fail we will have altered the desired | |
5966 structs which could lead to an assertion failure. However, if | |
5967 we fail the next thing that is going to happen is a full regen | |
5968 so we will actually end up being safe. */ | |
5969 { | |
5970 prop_block_dynarr *prop = NULL; | |
5971 struct display_line *cdl = Dynarr_atp (cdla, line); | |
5972 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5973 | |
826 | 5974 assert (cdl->charpos == ddl->charpos); |
5975 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5976 assert (cdl->offset == ddl->offset); |
5977 | |
442 | 5978 /* If the line continues to next display line, fail. */ |
5979 if (ddl->line_continuation) | |
5980 return 0; | |
428 | 5981 |
5982 /* If the line was generated using propagation data, fail. */ | |
5983 if (ddl->used_prop_data) | |
5984 return 0; | |
5985 | |
2286 | 5986 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
5987 &prop, DESIRED_DISP); | |
428 | 5988 ddl->offset = 0; |
5989 | |
5990 /* If there is propagated stuff then it is pretty much a | |
4187 | 5991 guarantee that more than just the one line is affected. */ |
428 | 5992 if (prop) |
5993 { | |
5994 Dynarr_free (prop); | |
5995 return 0; | |
5996 } | |
5997 | |
442 | 5998 /* If the line continues to next display line, fail. */ |
5999 if (ddl->line_continuation) | |
6000 return 0; | |
428 | 6001 |
6002 /* If any line position parameters have changed or a | |
4187 | 6003 cursor has disappeared or disappeared, fail. */ |
428 | 6004 if (cdl->ypos != ddl->ypos |
6005 || cdl->ascent != ddl->ascent | |
6006 || cdl->descent != ddl->descent | |
6007 || cdl->top_clip != ddl->top_clip | |
6008 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
6009 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) | |
6010 { | |
6011 return 0; | |
6012 } | |
6013 | |
6014 /* If the changed area also ends on this line, then we may be in | |
4187 | 6015 business. Update everything and return success. */ |
826 | 6016 if (end_unchanged >= ddl->charpos && end_unchanged <= ddl->end_charpos) |
428 | 6017 { |
6018 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
6019 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
6020 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), | |
6021 w->buffer); | |
6022 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), | |
6023 w->buffer); | |
6024 | |
6025 if (ddl->cursor_elt != -1) | |
6026 { | |
6027 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
6028 w->last_point_y[DESIRED_DISP] = line; | |
6029 } | |
6030 | |
6031 redisplay_update_line (w, line, line, 1); | |
6032 regenerate_modeline (w); | |
6033 | |
6034 /* #### For now we just flush the cache until this has been | |
4187 | 6035 tested. After that is done, this should correct the |
6036 cache directly. */ | |
428 | 6037 Dynarr_reset (w->line_start_cache); |
6038 | |
6039 /* Adjust the extent changed boundaries to remove any | |
4187 | 6040 overlap with the buffer changes since we've just |
6041 successfully updated that area. */ | |
428 | 6042 if (extent_beg_unchanged != -1 |
6043 && extent_beg_unchanged >= beg_unchanged | |
6044 && extent_beg_unchanged < end_unchanged) | |
6045 extent_beg_unchanged = end_unchanged; | |
6046 | |
6047 if (extent_end_unchanged != -1 | |
6048 && extent_end_unchanged >= beg_unchanged | |
6049 && extent_end_unchanged < end_unchanged) | |
6050 extent_end_unchanged = beg_unchanged - 1; | |
6051 | |
6052 if (extent_end_unchanged <= extent_beg_unchanged) | |
6053 extent_beg_unchanged = extent_end_unchanged = -1; | |
6054 | |
6055 /* This could lead to odd results if it fails, but since the | |
4187 | 6056 buffer changes update succeeded this probably will to. |
6057 We already know that the extent changes start at or after | |
6058 the line because we checked before entering the loop. */ | |
428 | 6059 if (extent_beg_unchanged != -1 |
6060 && extent_end_unchanged != -1 | |
826 | 6061 && ((extent_beg_unchanged < ddl->charpos) |
6062 || (extent_end_unchanged > ddl->end_charpos))) | |
428 | 6063 return regenerate_window_extents_only_changed (w, startp, pointm, |
6064 extent_beg_unchanged, | |
6065 extent_end_unchanged); | |
6066 else | |
6067 return 1; | |
6068 } | |
6069 } | |
6070 | |
6071 /* Oh, well. */ | |
6072 return 0; | |
6073 } | |
6074 | |
6075 /* Given a window and a point, update the given display lines such | |
6076 that point is displayed in the middle of the window. | |
6077 Return the window's new start position. */ | |
6078 | |
665 | 6079 static Charbpos |
6080 regenerate_window_point_center (struct window *w, Charbpos point, int type) | |
428 | 6081 { |
665 | 6082 Charbpos startp; |
428 | 6083 |
6084 /* We need to make sure that the modeline is generated so that the | |
6085 window height can be calculated correctly. */ | |
6086 ensure_modeline_generated (w, type); | |
6087 | |
6088 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w)); | |
6089 regenerate_window (w, startp, point, type); | |
6090 Fset_marker (w->start[type], make_int (startp), w->buffer); | |
6091 | |
6092 return startp; | |
6093 } | |
6094 | |
6095 /* Given a window and a set of display lines, return a boolean | |
6096 indicating whether the given point is contained within. */ | |
6097 | |
6098 static int | |
665 | 6099 point_visible (struct window *w, Charbpos point, int type) |
428 | 6100 { |
6101 struct buffer *b = XBUFFER (w->buffer); | |
6102 display_line_dynarr *dla = window_display_lines (w, type); | |
6103 int first_line; | |
6104 | |
4967 | 6105 if (Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
428 | 6106 first_line = 1; |
6107 else | |
6108 first_line = 0; | |
6109 | |
6110 if (Dynarr_length (dla) > first_line) | |
6111 { | |
665 | 6112 Charbpos start, end; |
428 | 6113 struct display_line *dl = Dynarr_atp (dla, first_line); |
6114 | |
826 | 6115 start = dl->charpos; |
428 | 6116 end = BUF_Z (b) - w->window_end_pos[type] - 1; |
6117 | |
6118 if (point >= start && point <= end) | |
6119 { | |
6120 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines) | |
6121 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
6122 dl = Dynarr_lastp (dla); |
428 | 6123 |
826 | 6124 if (point >= (dl->charpos + dl->offset) |
6125 && point <= (dl->end_charpos + dl->offset)) | |
428 | 6126 return !dl->clip; |
6127 else | |
6128 return 1; | |
6129 } | |
6130 else | |
6131 return 1; | |
6132 } | |
6133 else | |
6134 return 0; | |
6135 } | |
6136 else | |
6137 return 0; | |
6138 } | |
6139 | |
6140 /* Return pixel position the middle of the window, not including the | |
6141 modeline and any potential horizontal scrollbar. */ | |
6142 | |
6143 int | |
6144 window_half_pixpos (struct window *w) | |
6145 { | |
6146 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1); | |
6147 } | |
6148 | |
6149 /* Return the display line which is currently in the middle of the | |
6150 window W for display lines TYPE. */ | |
6151 | |
6152 int | |
665 | 6153 line_at_center (struct window *w, int type, Charbpos start, Charbpos point) |
428 | 6154 { |
6155 display_line_dynarr *dla; | |
6156 int half; | |
6157 int elt; | |
6158 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1); | |
6159 | |
6160 if (type == CMOTION_DISP) | |
6161 regenerate_window (w, start, point, type); | |
6162 | |
6163 dla = window_display_lines (w, type); | |
6164 half = window_half_pixpos (w); | |
6165 | |
6166 for (elt = first_elt; elt < Dynarr_length (dla); elt++) | |
6167 { | |
6168 struct display_line *dl = Dynarr_atp (dla, elt); | |
6169 int line_bot = dl->ypos + dl->descent; | |
6170 | |
6171 if (line_bot > half) | |
6172 return elt; | |
6173 } | |
6174 | |
6175 /* We may not have a line at the middle if the end of the buffer is | |
6176 being displayed. */ | |
6177 return -1; | |
6178 } | |
6179 | |
6180 /* Return a value for point that would place it at the beginning of | |
6181 the line which is in the middle of the window. */ | |
6182 | |
665 | 6183 Charbpos |
6184 point_at_center (struct window *w, int type, Charbpos start, Charbpos point) | |
428 | 6185 { |
6186 /* line_at_center will regenerate the display structures, if necessary. */ | |
6187 int line = line_at_center (w, type, start, point); | |
6188 | |
6189 if (line == -1) | |
6190 return BUF_ZV (XBUFFER (w->buffer)); | |
6191 else | |
6192 { | |
6193 display_line_dynarr *dla = window_display_lines (w, type); | |
6194 struct display_line *dl = Dynarr_atp (dla, line); | |
6195 | |
826 | 6196 return dl->charpos; |
428 | 6197 } |
6198 } | |
6199 | |
6200 /* For a given window, ensure that the current visual representation | |
6201 is accurate. */ | |
6202 | |
6203 static void | |
6204 redisplay_window (Lisp_Object window, int skip_selected) | |
6205 { | |
6206 struct window *w = XWINDOW (window); | |
6207 struct frame *f = XFRAME (w->frame); | |
6208 struct device *d = XDEVICE (f->device); | |
6209 Lisp_Object old_buffer = w->buffer; | |
6210 Lisp_Object the_buffer = w->buffer; | |
6211 struct buffer *b; | |
6212 int echo_active = 0; | |
6213 int startp = 1; | |
6214 int pointm; | |
6215 int old_startp = 1; | |
6216 int old_pointm = 1; | |
6217 int selected_in_its_frame; | |
6218 int selected_globally; | |
6219 int skip_output = 0; | |
6220 int truncation_changed; | |
6221 int inactive_minibuffer = | |
6222 (MINI_WINDOW_P (w) && | |
6223 (f != device_selected_frame (d)) && | |
6224 !is_surrogate_for_selected_frame (f)); | |
6225 | |
6226 /* #### In the new world this function actually does a bunch of | |
6227 optimizations such as buffer-based scrolling, but none of that is | |
6228 implemented yet. */ | |
6229 | |
6230 /* If this is a combination window, do its children; that's all. | |
6231 The selected window is always a leaf so we don't check for | |
6232 skip_selected here. */ | |
6233 if (!NILP (w->vchild)) | |
6234 { | |
6235 redisplay_windows (w->vchild, skip_selected); | |
6236 return; | |
6237 } | |
6238 if (!NILP (w->hchild)) | |
6239 { | |
6240 redisplay_windows (w->hchild, skip_selected); | |
6241 return; | |
6242 } | |
6243 | |
6244 /* Is this window the selected window on its frame? */ | |
6245 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f))); | |
6246 selected_globally = | |
6247 selected_in_its_frame && | |
6248 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
6249 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d && | |
6250 XFRAME(DEVICE_SELECTED_FRAME(d)) == f; | |
6251 if (skip_selected && selected_in_its_frame) | |
6252 return; | |
6253 | |
6254 /* It is possible that the window is not fully initialized yet. */ | |
6255 if (NILP (w->buffer)) | |
6256 return; | |
6257 | |
6258 if (MINI_WINDOW_P (w) && echo_area_active (f)) | |
6259 { | |
6260 w->buffer = the_buffer = Vecho_area_buffer; | |
6261 echo_active = 1; | |
6262 } | |
6263 | |
6264 b = XBUFFER (w->buffer); | |
6265 | |
6266 if (echo_active) | |
6267 { | |
6268 old_pointm = selected_globally | |
4187 | 6269 ? BUF_PT (b) |
6270 : marker_position (w->pointm[CURRENT_DISP]); | |
428 | 6271 pointm = 1; |
6272 } | |
6273 else | |
6274 { | |
6275 if (selected_globally) | |
6276 { | |
6277 pointm = BUF_PT (b); | |
6278 } | |
6279 else | |
6280 { | |
6281 pointm = marker_position (w->pointm[CURRENT_DISP]); | |
6282 | |
6283 if (pointm < BUF_BEGV (b)) | |
6284 pointm = BUF_BEGV (b); | |
6285 else if (pointm > BUF_ZV (b)) | |
6286 pointm = BUF_ZV (b); | |
6287 } | |
6288 } | |
6289 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); | |
6290 | |
6291 /* If the buffer has changed we have to invalidate all of our face | |
6292 cache elements. */ | |
6293 if ((!echo_active && b != window_display_buffer (w)) | |
6294 || !Dynarr_length (w->face_cachels) | |
6295 || f->faces_changed) | |
6296 reset_face_cachels (w); | |
6297 else | |
6298 mark_face_cachels_as_not_updated (w); | |
6299 | |
6300 /* Ditto the glyph cache elements, although we do *not* invalidate | |
6301 the cache purely because glyphs have changed - this is now | |
6302 handled by the dirty flag.*/ | |
6303 if ((!echo_active && b != window_display_buffer (w)) | |
440 | 6304 || !Dynarr_length (w->glyph_cachels) || f->faces_changed) |
428 | 6305 reset_glyph_cachels (w); |
6306 else | |
6307 mark_glyph_cachels_as_not_updated (w); | |
6308 | |
6309 /* If the marker's buffer is not the window's buffer, then we need | |
6310 to find a new starting position. */ | |
6311 if (!MINI_WINDOW_P (w) | |
6312 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer)) | |
6313 { | |
6314 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6315 | |
6316 goto regeneration_done; | |
6317 } | |
6318 | |
6319 if (echo_active) | |
6320 { | |
6321 old_startp = marker_position (w->start[CURRENT_DISP]); | |
6322 startp = 1; | |
6323 } | |
6324 else | |
6325 { | |
6326 startp = marker_position (w->start[CURRENT_DISP]); | |
6327 if (startp < BUF_BEGV (b)) | |
6328 startp = BUF_BEGV (b); | |
6329 else if (startp > BUF_ZV (b)) | |
6330 startp = BUF_ZV (b); | |
6331 } | |
6332 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer); | |
6333 | |
6334 truncation_changed = (find_window_mirror (w)->truncate_win != | |
647 | 6335 (unsigned int) window_truncation_on (w)); |
428 | 6336 |
6337 /* If w->force_start is set, then some function set w->start and we | |
6338 should display from there and change point, if necessary, to | |
6339 ensure that it is visible. */ | |
6340 if (w->force_start || inactive_minibuffer) | |
6341 { | |
6342 w->force_start = 0; | |
6343 w->last_modified[DESIRED_DISP] = Qzero; | |
6344 w->last_facechange[DESIRED_DISP] = Qzero; | |
6345 | |
6346 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6347 | |
6348 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer) | |
6349 { | |
6350 pointm = point_at_center (w, DESIRED_DISP, 0, 0); | |
6351 | |
6352 if (selected_globally) | |
6353 BUF_SET_PT (b, pointm); | |
6354 | |
6355 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), | |
6356 the_buffer); | |
6357 | |
6358 /* #### BUFU amounts of overkill just to get the cursor | |
4187 | 6359 location marked properly. FIX ME FIX ME FIX ME */ |
428 | 6360 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6361 } | |
6362 | |
6363 goto regeneration_done; | |
6364 } | |
6365 | |
6366 /* If nothing has changed since the last redisplay, then we just | |
6367 need to make sure that point is still visible. */ | |
6368 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) | |
6369 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b) | |
6370 && pointm >= startp | |
6371 /* This check is to make sure we restore the minibuffer after a | |
4187 | 6372 temporary change to the echo area. */ |
428 | 6373 && !(MINI_WINDOW_P (w) && f->buffers_changed) |
6374 && !f->frame_changed | |
6375 && !truncation_changed | |
442 | 6376 /* check whether start is really at the beginning of a line GE */ |
428 | 6377 && (!w->start_at_line_beg || beginning_of_line_p (b, startp)) |
6378 ) | |
6379 { | |
6380 /* Check if the cursor has actually moved. */ | |
6381 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
6382 && pointm == marker_position (w->last_point[CURRENT_DISP]) | |
6383 && selected_globally | |
6384 && !w->windows_changed | |
6385 && !f->clip_changed | |
6386 && !f->extents_changed | |
6387 && !f->faces_changed | |
6388 && !f->glyphs_changed | |
6389 && !f->subwindows_changed | |
442 | 6390 /* && !f->subwindows_state_changed*/ |
428 | 6391 && !f->point_changed |
6392 && !f->windows_structure_changed) | |
6393 { | |
6394 /* If not, we're done. */ | |
6395 if (f->modeline_changed) | |
6396 regenerate_modeline (w); | |
6397 | |
6398 skip_output = 1; | |
6399 goto regeneration_done; | |
6400 } | |
6401 else | |
6402 { | |
6403 /* If the new point is visible in the redisplay structures, | |
4187 | 6404 then let the output update routines handle it, otherwise |
6405 do things the hard way. */ | |
428 | 6406 if (!w->windows_changed |
6407 && !f->clip_changed | |
6408 && !f->extents_changed | |
6409 && !f->faces_changed | |
6410 && !f->glyphs_changed | |
6411 && !f->subwindows_changed | |
442 | 6412 /* && !f->subwindows_state_changed*/ |
428 | 6413 && !f->windows_structure_changed) |
6414 { | |
6415 if (point_visible (w, pointm, CURRENT_DISP) | |
6416 && w->last_point_x[CURRENT_DISP] != -1 | |
6417 && w->last_point_y[CURRENT_DISP] != -1) | |
6418 { | |
6419 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f))) | |
6420 { | |
6421 /* Always regenerate in case it is displaying | |
4187 | 6422 the current line or column. */ |
428 | 6423 regenerate_modeline (w); |
6424 | |
6425 skip_output = 1; | |
6426 goto regeneration_done; | |
6427 } | |
6428 } | |
6429 else if (!selected_in_its_frame && !f->point_changed) | |
6430 { | |
6431 if (f->modeline_changed) | |
6432 regenerate_modeline (w); | |
6433 | |
6434 skip_output = 1; | |
6435 goto regeneration_done; | |
6436 } | |
6437 } | |
6438 | |
6439 /* If we weren't able to take the shortcut method, then use | |
4187 | 6440 the brute force method. */ |
428 | 6441 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6442 | |
6443 if (point_visible (w, pointm, DESIRED_DISP)) | |
6444 goto regeneration_done; | |
6445 } | |
6446 } | |
6447 | |
6448 /* Check if the starting point is no longer at the beginning of a | |
6449 line, in which case find a new starting point. We also recenter | |
6450 if our start position is equal to point-max. Otherwise we'll end | |
6451 up with a blank window. */ | |
6452 else if (((w->start_at_line_beg || MINI_WINDOW_P (w)) | |
6453 && !(startp == BUF_BEGV (b) | |
6454 || BUF_FETCH_CHAR (b, startp - 1) == '\n')) | |
6455 || (pointm == startp && | |
6456 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) && | |
6457 startp < marker_position (w->last_start[CURRENT_DISP])) | |
6458 || (startp == BUF_ZV (b))) | |
6459 { | |
6460 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6461 | |
6462 goto regeneration_done; | |
6463 } | |
6464 /* See if we can update the data structures locally based on | |
6465 knowledge of what changed in the buffer. */ | |
6466 else if (!w->windows_changed | |
6467 && !f->clip_changed | |
6468 && !f->faces_changed | |
6469 && !f->glyphs_changed | |
6470 && !f->subwindows_changed | |
442 | 6471 /* && !f->subwindows_state_changed*/ |
428 | 6472 && !f->windows_structure_changed |
6473 && !f->frame_changed | |
6474 && !truncation_changed | |
6475 && pointm >= startp | |
6476 && regenerate_window_incrementally (w, startp, pointm)) | |
6477 { | |
6478 if (f->modeline_changed | |
6479 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b) | |
6480 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b)) | |
6481 regenerate_modeline (w); | |
6482 | |
6483 skip_output = 1; | |
6484 goto regeneration_done; | |
6485 } | |
6486 /* #### This is where a check for structure based scrolling would go. */ | |
6487 /* If all else fails, try just regenerating and see what happens. */ | |
6488 else | |
6489 { | |
6490 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6491 | |
6492 if (point_visible (w, pointm, DESIRED_DISP)) | |
6493 goto regeneration_done; | |
6494 } | |
6495 | |
6496 /* We still haven't gotten the window regenerated with point | |
6497 visible. Next we try scrolling a little and see if point comes | |
6498 back onto the screen. */ | |
6499 if (scroll_step > 0) | |
6500 { | |
6501 int scrolled = scroll_conservatively; | |
6502 for (; scrolled >= 0; scrolled -= scroll_step) | |
6503 { | |
6504 startp = vmotion (w, startp, | |
6505 (pointm < startp) ? -scroll_step : scroll_step, 0); | |
6506 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6507 | |
6508 if (point_visible (w, pointm, DESIRED_DISP)) | |
6509 goto regeneration_done; | |
6510 } | |
6511 } | |
6512 | |
6513 /* We still haven't managed to get the screen drawn with point on | |
6514 the screen, so just center it and be done with it. */ | |
6515 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6516 | |
6517 | |
6518 regeneration_done: | |
6519 | |
6520 /* If the window's frame is changed then reset the current display | |
6521 lines in order to force a full repaint. */ | |
6522 if (f->frame_changed) | |
6523 { | |
6524 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
6525 | |
6526 Dynarr_reset (cla); | |
6527 } | |
6528 | |
6529 /* Must do this before calling redisplay_output_window because it | |
6530 sets some markers on the window. */ | |
6531 if (echo_active) | |
6532 { | |
6533 w->buffer = old_buffer; | |
6534 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer); | |
6535 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer); | |
6536 } | |
6537 | |
6538 /* These also have to be set before calling redisplay_output_window | |
6539 since it sets the CURRENT_DISP values based on them. */ | |
6540 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
6541 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
6542 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
6543 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
6544 | |
6545 if (!skip_output) | |
6546 { | |
665 | 6547 Charbpos start = marker_position (w->start[DESIRED_DISP]); |
6548 Charbpos end = (w->window_end_pos[DESIRED_DISP] == -1 | |
428 | 6549 ? BUF_ZV (b) |
6550 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1); | |
6551 /* Don't pollute the cache if not sure if we are correct */ | |
6552 if (w->start_at_line_beg) | |
6553 update_line_start_cache (w, start, end, pointm, 1); | |
6554 redisplay_output_window (w); | |
6555 /* | |
6556 * If we just displayed the echo area, the line start cache is | |
6557 * no longer valid, because the minibuffer window is associated | |
6558 * with the window now. | |
6559 */ | |
6560 if (echo_active) | |
6561 w->line_cache_last_updated = make_int (-1); | |
6562 } | |
6563 | |
6564 /* #### This should be dependent on face changes and will need to be | |
6565 somewhere else once tty updates occur on a per-frame basis. */ | |
6566 mark_face_cachels_as_clean (w); | |
6567 | |
438 | 6568 /* The glyph cachels only get dirty if someone changed something. |
6569 Since redisplay has now effectively ended we can reset the dirty | |
6570 flag since everything must be up-to-date. */ | |
428 | 6571 if (glyphs_changed) |
6572 mark_glyph_cachels_as_clean (w); | |
6573 | |
6574 w->windows_changed = 0; | |
6575 } | |
6576 | |
6577 /* Call buffer_reset_changes for all buffers present in any window | |
6578 currently visible in all frames on all devices. #### There has to | |
6579 be a better way to do this. */ | |
6580 | |
6581 static int | |
2286 | 6582 reset_buffer_changes_mapfun (struct window *w, void *UNUSED (closure)) |
428 | 6583 { |
6584 buffer_reset_changes (XBUFFER (w->buffer)); | |
6585 return 0; | |
6586 } | |
6587 | |
6588 static void | |
6589 reset_buffer_changes (void) | |
6590 { | |
6591 Lisp_Object frmcons, devcons, concons; | |
6592 | |
6593 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
6594 { | |
6595 struct frame *f = XFRAME (XCAR (frmcons)); | |
6596 | |
6597 if (FRAME_REPAINT_P (f)) | |
6598 map_windows (f, reset_buffer_changes_mapfun, 0); | |
6599 } | |
6600 } | |
6601 | |
6602 /* Ensure that all windows underneath the given window in the window | |
6603 hierarchy are correctly displayed. */ | |
6604 | |
6605 static void | |
6606 redisplay_windows (Lisp_Object window, int skip_selected) | |
6607 { | |
6608 for (; !NILP (window) ; window = XWINDOW (window)->next) | |
6609 { | |
6610 redisplay_window (window, skip_selected); | |
6611 } | |
6612 } | |
6613 | |
1318 | 6614 /* Register an action to be called at the end of redisplay. |
6615 in_display is 0 when this is called. | |
6616 This is used when it is discovered that an action needs to be taken, | |
6617 but it's during redisplay, so it's not safe. (Typically, it's an action | |
6618 that needs to enter redisplay, which can't happen reentrantly.) | |
6619 | |
6620 NEVER signal an error in these functions. | |
6621 */ | |
6622 | |
6623 void | |
6624 register_post_redisplay_action (void (*fun) (Lisp_Object), Lisp_Object arg) | |
6625 { | |
6626 Vpost_redisplay_actions = nconc2 (Vpost_redisplay_actions, | |
6627 list1 (Fcons (make_opaque_ptr | |
6628 ((void *) fun), arg))); | |
6629 } | |
6630 | |
1320 | 6631 static int running_post_redisplay_actions; |
6632 | |
1318 | 6633 static void |
6634 run_post_redisplay_actions (void) | |
6635 { | |
1320 | 6636 int depth; |
6637 | |
6638 if (running_post_redisplay_actions) | |
6639 return; | |
6640 | |
6641 depth = internal_bind_int (&running_post_redisplay_actions, 1); | |
6642 /* If the function pushes further actions, they will be tacked onto | |
6643 the end of the list, and we'll run them when we're done with the | |
6644 current ones. */ | |
1318 | 6645 while (!NILP (Vpost_redisplay_actions)) |
6646 { | |
6647 Lisp_Object car = XCAR (Vpost_redisplay_actions); | |
6648 void (*fun) (Lisp_Object) = | |
6649 (void (*)(Lisp_Object)) get_opaque_ptr (XCAR (car)); | |
6650 (*fun) (XCDR (car)); | |
6651 free_opaque_ptr (XCAR (car)); | |
6652 free_cons (car); | |
6653 Vpost_redisplay_actions = XCDR (Vpost_redisplay_actions); | |
6654 } | |
1320 | 6655 unbind_to (depth); |
1318 | 6656 } |
6657 | |
6658 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
6659 | |
6660 static Lisp_Object | |
2286 | 6661 commit_ritual_suicide (Lisp_Object UNUSED (ceci_nest_pas_une_pipe)) |
1318 | 6662 { |
6663 assert (!in_display); | |
6664 return Qnil; | |
6665 } | |
6666 | |
6667 #endif | |
6668 | |
6669 /* Within the guts of redisplay, we are defenseless and cannot allow any of | |
6670 the following to happen: | |
6671 | |
6672 1) garbage collection | |
6673 2) QUIT | |
6674 3) any non-local exits | |
6675 4) frame size changes | |
6676 5) deletion of any buffers, windows, frames, etc. | |
6677 6) modification of buffer text | |
6678 7) reentrant entry of redisplay (see the stack trace above | |
6679 generate_displayable_area()) | |
6680 | |
6681 The general reason is that the redisplay code is written to assume that | |
6682 it is the only code running, and thus (a) cannot tolerate structures | |
6683 changed out from under it (hence 1, 4, 5, 6, 7) and (b) at various points | |
6684 within redisplay the redisplay structures may be in an inconsistent | |
6685 state and there are no unwind-protects to clean the structures up in | |
6686 case of non-local exit (hence 2, 3). Fixing redisplay to address these | |
6687 issues is hard and perhaps not worth it (and might slow things down a | |
6688 fair amount). We address 1, 4, 5 and 6 ourselves inside of | |
6689 enter_redisplay_critical_section() by simply inhibiting them, but we | |
6690 cannot handle 2 and 3, which must be handled at the actual point where | |
6691 they may occur (especially, internal_equal() or any place that may call | |
6692 Lisp), by wrapping the code in call_trapping_problems() or | |
6693 call_with_suspended_errors(). [[ NOTE: We could address QUIT by inhibiting | |
6694 it but this would be anti-social because it would prevent the user from | |
6695 interrupting any Lisp code called within the critical section. With the | |
6696 call_*() wrapping, C-g will interrupt the Lisp code and throw back to | |
6697 the innermost wrapping. ]] In fact we do turn off QUIT handling, since | |
6698 it's just too dangerous otherwise. See below. | |
6699 | |
6700 Code calling enter_redisplay_critical_section() must check for reentrancy | |
6701 (#7) and take appropriate corrective action. | |
6702 | |
6703 To help debug potential problems, we arrange (when | |
6704 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every time | |
6705 we execute QUIT or call Lisp code unless proper wrapping is in place, as | |
6706 well as further checks when we actually Fsignal(), Fthrow(), | |
6707 garbage_collect_1(). | |
6708 | |
6709 #### If a frame-size change does occur we should probably actually be | |
6710 preempting redisplay. */ | |
6711 | |
6712 /* Count of number of recursive times we call | |
6713 enter_redisplay_critical_section() or | |
6714 enter_redisplay_critical_section_maybe(). | |
6715 enter_redisplay_critical_section() cannot occur reentrantly but we have | |
6716 to know in the *maybe() version whether to exit the section when we're | |
6717 done. */ | |
6718 static int in_display_nesting; | |
6719 | |
6720 static Lisp_Object | |
2286 | 6721 end_hold_frame_size_changes (Lisp_Object UNUSED (obj)) |
1318 | 6722 { |
6723 if (!hold_frame_size_changes) | |
6724 { | |
6725 /* we used to have a function to do this for only one frame, and | |
6726 it was typical to call it at the end of a critical section | |
6727 (which occurs once per frame); but what then happens if multiple | |
6728 frames have frame changes held up? | |
4187 | 6729 |
1318 | 6730 This means we are O(N^2) over frames. I seriously doubt it matters. |
6731 --ben */ | |
6732 Lisp_Object frmcons, devcons, concons; | |
4187 | 6733 |
1318 | 6734 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
6735 { | |
6736 struct frame *f = XFRAME (XCAR (frmcons)); | |
6737 if (f->size_change_pending) | |
6738 change_frame_size (f, f->new_height, f->new_width, 0); | |
6739 } | |
6740 } | |
6741 return Qnil; | |
6742 } | |
6743 | |
6744 /* Call this to temporarily prevent frame-size changes from being processed. | |
6745 To undo, use unbind_to(), passing it the value returned by this function. | |
6746 */ | |
6747 | |
6748 int | |
6749 begin_hold_frame_size_changes (void) | |
6750 { | |
6751 int depth = specpdl_depth (); | |
6752 record_unwind_protect (end_hold_frame_size_changes, Qnil); | |
6753 internal_bind_int (&hold_frame_size_changes, 1 + hold_frame_size_changes); | |
6754 return depth; | |
6755 } | |
6756 | |
6757 int | |
6758 enter_redisplay_critical_section (void) | |
6759 { | |
6760 int depth = specpdl_depth (); | |
6761 | |
6762 /* Reentrant entry is deadly. The calling function must check for this. */ | |
6763 assert (!in_display); | |
6764 begin_hold_frame_size_changes (); | |
6765 /* Make sure in_display gets reset, but don't set it yet so that | |
6766 commit_ritual_suicide() can be used. */ | |
6767 internal_bind_int (&in_display, 0); | |
6768 internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6769 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
6770 /* Force every call to QUIT to check for in_displayness. This will | |
6771 verify proper wrapping, as in the previous comment, aborting if not. */ | |
6772 something_happened++; | |
6773 /* Verify that no nonlocal exits blow past us. */ | |
6774 record_unwind_protect (commit_ritual_suicide, Qnil); | |
6775 #endif | |
6776 in_display++; | |
6777 | |
6778 set_trapping_problems_flags (INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY); | |
6779 /* Even checking for QUIT can cause arbitrary Lisp code to be executed, | |
6780 e.g. through a menu handler. We really don't want that happening | |
6781 inside of redisplay. Code that we `eval' is at least written with the | |
6782 expectation that it's inside of redisplay, and shouldn't try anything | |
6783 weird; but that's not the case for menu code (e.g. custom loads huge | |
6784 amounts of LISP FILES from a menu handler! FMH!). Safest just to turn | |
6785 this off. We could turn it on using UNINHIBIT_QUIT or | |
6786 begin_do_check_for_quit() in certain places if we want, if we know | |
6787 it's not in an especially tricky place. */ | |
6788 begin_dont_check_for_quit (); | |
6789 return depth; | |
6790 } | |
6791 | |
6792 void | |
6793 exit_redisplay_critical_section (int depth) | |
6794 { | |
6795 in_display--; | |
6796 assert (!in_display); | |
6797 unbind_to (depth); | |
6798 | |
6799 run_post_redisplay_actions (); | |
6800 } | |
6801 | |
6802 /* Enter the redisplay critical section if we're not already in it. This | |
6803 is for code that needs frame changes held up and other protections from | |
6804 being inside, but doesn't modify the redisplay structures, and doesn't | |
6805 look at them in a way that they will be confused by inconsistencies. */ | |
6806 | |
6807 int | |
6808 enter_redisplay_critical_section_maybe (void) | |
6809 { | |
6810 if (!in_display) | |
6811 return enter_redisplay_critical_section (); | |
6812 else | |
6813 return internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6814 } | |
6815 | |
6816 void | |
6817 exit_redisplay_critical_section_maybe (int depth) | |
6818 { | |
6819 if (in_display_nesting == 1) | |
6820 exit_redisplay_critical_section (depth); | |
6821 else | |
6822 unbind_to (depth); | |
6823 } | |
6824 | |
1279 | 6825 /* Ensure that all windows on the given frame are correctly displayed. |
6826 Return non-zero if pre-empted. */ | |
428 | 6827 |
442 | 6828 int |
428 | 6829 redisplay_frame (struct frame *f, int preemption_check) |
6830 { | |
6831 struct device *d = XDEVICE (f->device); | |
853 | 6832 int depth; |
428 | 6833 |
1279 | 6834 assert (f->init_finished); |
6835 | |
1318 | 6836 /* NOTE: Without sufficient checks for stream frames, we got weird |
6837 crashes in pdump. These came and went very easily -- adding the | |
6838 critical-section code for redisplay was enough to trigger them. | |
6839 Perhaps I should have debugged them but there didn't seem to be any | |
6840 point. --ben */ | |
1279 | 6841 if (FRAME_STREAM_P (f)) /* nothing to do */ |
6842 return 0; | |
6843 | |
1318 | 6844 /* Reentrancy into redisplay can be deadly. See stack trace above |
6845 generate_displayable_area(). */ | |
6846 if (in_display) | |
6847 return 1; | |
6848 | |
545 | 6849 if (preemption_check |
6850 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) | |
428 | 6851 { |
6852 /* The preemption check itself takes a lot of time, | |
6853 so normally don't do it here. We do it if called | |
6854 from Lisp, though (`redisplay-frame'). */ | |
6855 int preempted; | |
6856 | |
6857 REDISPLAY_PREEMPTION_CHECK; | |
6858 if (preempted) | |
6859 return 1; | |
6860 } | |
6861 | |
442 | 6862 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) |
6863 { | |
6864 Lisp_Object frame; | |
6865 | |
6866 f->old_buffer_alist = Freplace_list (f->old_buffer_alist, | |
6867 f->buffer_alist); | |
793 | 6868 frame = wrap_frame (f); |
442 | 6869 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); |
6870 } | |
6871 | |
428 | 6872 /* Before we put a hold on frame size changes, attempt to process |
6873 any which are already pending. */ | |
6874 if (f->size_change_pending) | |
6875 change_frame_size (f, f->new_height, f->new_width, 0); | |
6876 | |
6877 /* If frame size might need to be changed, due to changed size | |
6878 of toolbars, scrollbars etc, change it now */ | |
6879 if (f->size_slipped) | |
6880 { | |
6881 adjust_frame_size (f); | |
6882 assert (!f->size_slipped); | |
6883 } | |
6884 | |
1318 | 6885 /* The menubar, toolbar, and icon updates should be done before |
853 | 6886 enter_redisplay_critical_section is called and we are officially |
3025 | 6887 `in_display'. They is because they tend to eval Lisp code, which |
1318 | 6888 needs to be carefully wrapped within the critical section (and hence |
6889 is difficult to debug). */ | |
428 | 6890 |
6891 #ifdef HAVE_MENUBARS | |
6892 /* Update the menubar. It is done first since it could change | |
6893 the menubar's visibility. This way we avoid having flashing | |
6894 caused by an Expose event generated by the visibility change | |
6895 being handled. */ | |
6896 update_frame_menubars (f); | |
6897 #endif /* HAVE_MENUBARS */ | |
6898 #ifdef HAVE_TOOLBARS | |
905 | 6899 /* Update the toolbars geometry. We don't update the toolbars |
6900 themselves at this point since the space they are trying to | |
6901 occupy may currently by occupied by gutter elements. Instead we | |
6902 update the geometry, then update the gutter geometry, then update | |
6903 the gutters - which will cause mapped windows to be repositioned | |
6904 - and finally update the toolbars. */ | |
6905 update_frame_toolbars_geometry (f); | |
428 | 6906 #endif /* HAVE_TOOLBARS */ |
442 | 6907 /* Gutter update proper has to be done inside display when no frame |
6908 size changes can occur, thus we separately update the gutter | |
6909 geometry here if it needs it. */ | |
6910 update_frame_gutter_geometry (f); | |
428 | 6911 |
6912 /* If we clear the frame we have to force its contents to be redrawn. */ | |
6913 if (f->clear) | |
6914 f->frame_changed = 1; | |
6915 | |
442 | 6916 /* Invalidate the subwindow caches. We use subwindows_changed here |
6917 to cause subwindows to get instantiated. This is because | |
428 | 6918 subwindows_state_changed is less strict - dealing with things |
6919 like the clicked state of button. We have to do this before | |
6920 redisplaying the gutters as subwindows get unmapped in the | |
6921 process.*/ | |
442 | 6922 if (f->frame_changed) |
6923 reset_frame_subwindow_instance_cache (f); | |
6924 | |
6925 if (f->frame_changed || f->subwindows_changed) | |
6926 { | |
428 | 6927 /* we have to do this so the gutter gets regenerated. */ |
6928 reset_gutter_display_lines (f); | |
6929 } | |
6930 | |
853 | 6931 depth = enter_redisplay_critical_section (); |
428 | 6932 |
6933 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ | |
1318 | 6934 |
6935 /* See comments in enter_redisplay_critical_section() */ | |
428 | 6936 |
442 | 6937 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
6938 | |
6939 /* We can now update the gutters, safe in the knowledge that our | |
6940 efforts won't get undone. */ | |
6941 | |
6942 /* This can call lisp, but redisplay is protected by binding | |
6943 inhibit_quit. More importantly the code involving display lines | |
6944 *assumes* that GC will not happen and so does not GCPRO | |
6945 anything. Since we use this code the whole time with the gutters | |
1318 | 6946 we cannot allow GC to happen when manipulating the gutters. |
6947 | |
6948 This must be inside of the critical section for various reasons. | |
6949 For example, it messes with display structures, which be left in | |
6950 an inconsistent state. */ | |
442 | 6951 update_frame_gutters (f); |
6952 | |
428 | 6953 /* Erase the frame before outputting its contents. */ |
6954 if (f->clear) | |
6955 { | |
442 | 6956 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 6957 } |
6958 | |
6959 /* Do the selected window first. */ | |
6960 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); | |
6961 | |
6962 /* Then do the rest. */ | |
6963 redisplay_windows (f->root_window, 1); | |
6964 | |
442 | 6965 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 6966 |
6967 update_frame_title (f); | |
6968 | |
905 | 6969 #ifdef HAVE_TOOLBARS |
6970 /* Finally update the toolbars. It seems its possible to get in a | |
6971 cycle between updating the gutter and the toolbars. Basically we | |
6972 want to end up with both being up-to-date and this doesn't seem | |
6973 possible in a single pass. */ | |
6974 update_frame_toolbars (f); | |
6975 #endif /* HAVE_TOOLBARS */ | |
6976 | |
428 | 6977 CLASS_RESET_CHANGED_FLAGS (f); |
6978 f->window_face_cache_reset = 0; | |
6979 f->echo_area_garbaged = 0; | |
6980 f->clear = 0; | |
6981 | |
6982 if (!f->size_change_pending) | |
6983 f->size_changed = 0; | |
6984 | |
6985 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */ | |
6986 | |
853 | 6987 /* Allow frame size changes to occur again. */ |
6988 exit_redisplay_critical_section (depth); | |
428 | 6989 |
6990 return 0; | |
6991 } | |
6992 | |
440 | 6993 /* Ensure that all frames on the given device are correctly displayed. |
6994 If AUTOMATIC is non-zero, and the device implementation indicates | |
6995 no automatic redisplay, as printers do, then the device is not | |
6996 redisplayed. AUTOMATIC is set to zero when called from lisp | |
6997 functions (redraw-device) and (redisplay-device), and to non-zero | |
6998 when called from "lazy" redisplay(); | |
6999 */ | |
428 | 7000 |
7001 static int | |
440 | 7002 redisplay_device (struct device *d, int automatic) |
428 | 7003 { |
7004 Lisp_Object frame, frmcons; | |
7005 int size_change_failed = 0; | |
7006 struct frame *f; | |
7007 | |
545 | 7008 if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) |
440 | 7009 return 0; |
7010 | |
428 | 7011 if (DEVICE_STREAM_P (d)) /* nothing to do */ |
7012 return 0; | |
7013 | |
7014 /* It is possible that redisplay has been called before the | |
545 | 7015 device is fully initialized, or that the console implementation |
7016 allows frameless devices. If so then continue with the next | |
7017 device. */ | |
428 | 7018 if (NILP (DEVICE_SELECTED_FRAME (d))) |
7019 return 0; | |
7020 | |
545 | 7021 if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) |
7022 { | |
7023 int preempted; | |
7024 REDISPLAY_PREEMPTION_CHECK; | |
7025 if (preempted) | |
7026 return 1; | |
7027 } | |
428 | 7028 |
7029 /* Always do the selected frame first. */ | |
7030 frame = DEVICE_SELECTED_FRAME (d); | |
7031 | |
7032 f = XFRAME (frame); | |
7033 | |
7034 if (f->icon_changed || f->windows_changed) | |
7035 update_frame_icon (f); | |
7036 | |
7037 if (FRAME_REPAINT_P (f)) | |
7038 { | |
7039 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) | |
7040 { | |
588 | 7041 int preempted = redisplay_frame (f, 1); |
545 | 7042 if (preempted) |
7043 return 1; | |
7044 } | |
428 | 7045 |
7046 /* If the frame redisplay did not get preempted, then this flag | |
4187 | 7047 should have gotten set to 0. It might be possible for that |
7048 not to happen if a size change event were to occur at an odd | |
7049 time. To make sure we don't miss anything we simply don't | |
7050 reset the top level flags until the condition ends up being | |
7051 in the right state. */ | |
428 | 7052 if (f->size_changed) |
7053 size_change_failed = 1; | |
7054 } | |
7055 | |
7056 DEVICE_FRAME_LOOP (frmcons, d) | |
7057 { | |
7058 f = XFRAME (XCAR (frmcons)); | |
7059 | |
7060 if (f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
7061 continue; | |
7062 | |
7063 if (f->icon_changed || f->windows_changed) | |
7064 update_frame_icon (f); | |
7065 | |
7066 if (FRAME_REPAINT_P (f)) | |
7067 { | |
430 | 7068 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
428 | 7069 { |
588 | 7070 int preempted = redisplay_frame (f, 1); |
545 | 7071 if (preempted) |
7072 return 1; | |
428 | 7073 } |
7074 | |
7075 if (f->size_change_pending) | |
7076 size_change_failed = 1; | |
7077 } | |
7078 } | |
7079 | |
7080 /* If we get here then we redisplayed all of our frames without | |
7081 getting preempted so mark ourselves as clean. */ | |
7082 CLASS_RESET_CHANGED_FLAGS (d); | |
7083 | |
7084 if (!size_change_failed) | |
7085 d->size_changed = 0; | |
7086 | |
7087 return 0; | |
7088 } | |
7089 | |
7090 /* Ensure that all windows on all frames on all devices are displaying | |
7091 the current contents of their respective buffers. */ | |
7092 | |
7093 static void | |
7094 redisplay_without_hooks (void) | |
7095 { | |
7096 Lisp_Object devcons, concons; | |
7097 int size_change_failed = 0; | |
1292 | 7098 PROFILE_DECLARE (); |
7099 | |
7100 PROFILE_RECORD_ENTERING_SECTION (QSin_redisplay); | |
428 | 7101 |
7102 if (asynch_device_change_pending) | |
7103 handle_asynch_device_change (); | |
7104 | |
7105 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && | |
430 | 7106 !disable_preemption && preemption_count < max_preempts) |
428 | 7107 goto done; |
7108 | |
7109 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
7110 { | |
7111 struct device *d = XDEVICE (XCAR (devcons)); | |
7112 int preempted; | |
7113 | |
430 | 7114 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) |
428 | 7115 { |
440 | 7116 preempted = redisplay_device (d, 1); |
428 | 7117 |
7118 if (preempted) | |
7119 { | |
7120 preemption_count++; | |
7121 RESET_CHANGED_SET_FLAGS; | |
7122 goto done; | |
7123 } | |
7124 | |
7125 /* See comment in redisplay_device. */ | |
7126 if (d->size_changed) | |
7127 size_change_failed = 1; | |
7128 } | |
7129 } | |
7130 preemption_count = 0; | |
7131 | |
7132 /* Mark redisplay as accurate */ | |
7133 GLOBAL_RESET_CHANGED_FLAGS; | |
7134 RESET_CHANGED_SET_FLAGS; | |
7135 | |
7136 if (faces_changed) | |
7137 { | |
7138 mark_all_faces_as_clean (); | |
7139 faces_changed = 0; | |
7140 } | |
7141 | |
7142 if (!size_change_failed) | |
7143 size_changed = 0; | |
7144 | |
7145 reset_buffer_changes (); | |
7146 | |
7147 done: | |
800 | 7148 #ifdef ERROR_CHECK_DISPLAY |
7149 sledgehammer_check_redisplay_structs (); | |
7150 #endif /* ERROR_CHECK_DISPLAY */ | |
1292 | 7151 |
7152 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay); | |
428 | 7153 } |
7154 | |
1318 | 7155 /* Note: All places in the C code that call redisplay() are prepared to |
7156 handle GCing, which can happen from run_pre_idle_hook(). However, we | |
7157 can't currently handle GC inside the guts of redisplay; see | |
7158 enter_redisplay_critical_section(). | |
853 | 7159 |
7160 (#### What about other external entry points to the redisplay code? | |
7161 Someone should go through and make sure that all callers can handle | |
7162 GC there, too.) | |
7163 */ | |
7164 | |
428 | 7165 void |
7166 redisplay (void) | |
7167 { | |
853 | 7168 run_pre_idle_hook (); |
7169 redisplay_no_pre_idle_hook (); | |
7170 } | |
7171 | |
7172 void | |
7173 redisplay_no_pre_idle_hook (void) | |
7174 { | |
428 | 7175 if (last_display_warning_tick != display_warning_tick && |
7176 !inhibit_warning_display) | |
7177 { | |
7178 /* If an error occurs during this function, oh well. | |
4187 | 7179 If we report another warning, we could get stuck in an |
428 | 7180 infinite loop reporting warnings. */ |
853 | 7181 call0_trapping_problems |
7182 (0, Qdisplay_warning_buffer, | |
7183 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 7184 last_display_warning_tick = display_warning_tick; |
7185 } | |
7186 | |
7187 redisplay_without_hooks (); | |
7188 } | |
7189 | |
853 | 7190 Lisp_Object |
7191 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker) | |
7192 { | |
7193 return | |
7194 eval_in_buffer_trapping_problems | |
7195 ("Error calling function within redisplay", current_buffer, | |
1318 | 7196 dont_trust_this_damn_sucker, 0); |
853 | 7197 } |
428 | 7198 |
7199 /* Efficiently determine the window line number, and return a pointer | |
7200 to its printed representation. Do this regardless of whether | |
7201 line-number-mode is on. The first line in the buffer is counted as | |
7202 1. If narrowing is in effect, the lines are counted from the | |
7203 beginning of the visible portion of the buffer. */ | |
7204 static char * | |
7205 window_line_number (struct window *w, int type) | |
7206 { | |
7207 struct device *d = XDEVICE (XFRAME (w->frame)->device); | |
7208 struct buffer *b = XBUFFER (w->buffer); | |
7209 /* Be careful in the order of these tests. The first clause will | |
7210 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be). | |
7211 This can occur when the frame title is computed really early */ | |
665 | 7212 Charbpos pos = |
428 | 7213 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) && |
7214 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) && | |
7215 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
7216 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d ) | |
7217 ? BUF_PT (b) | |
7218 : marker_position (w->pointm[type])); | |
7219 EMACS_INT line; | |
7220 | |
7221 line = buffer_line_number (b, pos, 1); | |
7222 | |
603 | 7223 { |
7224 static char window_line_number_buf[DECIMAL_PRINT_SIZE (long)]; | |
7225 | |
7226 long_to_string (window_line_number_buf, line + 1); | |
7227 | |
7228 return window_line_number_buf; | |
7229 } | |
428 | 7230 } |
7231 | |
7232 | |
7233 /* Given a character representing an object in a modeline | |
7234 specification, return a string (stored into the global array | |
867 | 7235 `mode_spec_ibyte_string') with the information that object |
428 | 7236 represents. |
7237 | |
7238 This function is largely unchanged from previous versions of the | |
7239 redisplay engine. | |
7240 | |
7241 Warning! This code is also used for frame titles and can be called | |
7242 very early in the device/frame update process! JV | |
7243 */ | |
7244 | |
7245 static void | |
867 | 7246 decode_mode_spec (struct window *w, Ichar spec, int type) |
428 | 7247 { |
7248 Lisp_Object obj = Qnil; | |
442 | 7249 const char *str = NULL; |
428 | 7250 struct buffer *b = XBUFFER (w->buffer); |
7251 | |
867 | 7252 Dynarr_reset (mode_spec_ibyte_string); |
428 | 7253 |
7254 switch (spec) | |
7255 { | |
7256 /* print buffer name */ | |
7257 case 'b': | |
7258 obj = b->name; | |
7259 break; | |
7260 | |
7261 /* print visited file name */ | |
7262 case 'f': | |
7263 obj = b->filename; | |
7264 break; | |
7265 | |
7266 /* print the current column */ | |
7267 case 'c': | |
7268 { | |
4187 | 7269 Charbpos pt = (w == XWINDOW (Fselected_window (Qnil))) |
7270 ? BUF_PT (b) | |
7271 : marker_position (w->pointm[type]); | |
428 | 7272 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one; |
603 | 7273 char buf[DECIMAL_PRINT_SIZE (long)]; |
428 | 7274 |
7275 long_to_string (buf, col); | |
7276 | |
867 | 7277 Dynarr_add_many (mode_spec_ibyte_string, |
7278 (const Ibyte *) buf, strlen (buf)); | |
428 | 7279 |
7280 goto decode_mode_spec_done; | |
7281 } | |
7282 /* print the file coding system */ | |
7283 case 'C': | |
7284 { | |
4187 | 7285 Lisp_Object codesys = b->buffer_file_coding_system; |
7286 /* Be very careful here not to get an error. */ | |
428 | 7287 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys)) |
4187 | 7288 { |
7289 codesys = find_coding_system_for_text_file (codesys, 0); | |
428 | 7290 if (CODING_SYSTEMP (codesys)) |
4187 | 7291 obj = XCODING_SYSTEM_MNEMONIC (codesys); |
7292 } | |
428 | 7293 } |
7294 break; | |
7295 | |
7296 /* print the current line number */ | |
7297 case 'l': | |
7298 str = window_line_number (w, type); | |
7299 break; | |
7300 | |
7301 /* print value of mode-name (obsolete) */ | |
7302 case 'm': | |
7303 obj = b->mode_name; | |
7304 break; | |
7305 | |
7306 /* print hyphen and frame number, if != 1 */ | |
7307 case 'N': | |
7308 #ifdef HAVE_TTY | |
7309 { | |
7310 struct frame *f = XFRAME (w->frame); | |
7311 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999) | |
7312 { | |
7313 /* Naughty, naughty */ | |
7314 char * writable_str = alloca_array (char, 10); | |
7315 sprintf (writable_str, "-%d", f->order_count); | |
7316 str = writable_str; | |
7317 } | |
7318 } | |
7319 #endif /* HAVE_TTY */ | |
7320 break; | |
7321 | |
7322 /* print Narrow if appropriate */ | |
7323 case 'n': | |
7324 if (BUF_BEGV (b) > BUF_BEG (b) | |
7325 || BUF_ZV (b) < BUF_Z (b)) | |
7326 str = " Narrow"; | |
7327 break; | |
7328 | |
7329 /* print %, * or hyphen, if buffer is read-only, modified or neither */ | |
7330 case '*': | |
7331 str = (!NILP (b->read_only) | |
7332 ? "%" | |
7333 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7334 ? "*" | |
7335 : "-")); | |
7336 break; | |
7337 | |
7338 /* print * or hyphen -- XEmacs change to allow a buffer to be | |
4187 | 7339 read-only but still indicate whether it is modified. */ |
428 | 7340 case '+': |
7341 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7342 ? "*" | |
7343 : (!NILP (b->read_only) | |
7344 ? "%" | |
7345 : "-")); | |
7346 break; | |
7347 | |
7348 /* #### defined in 19.29 decode_mode_spec, but not in | |
4187 | 7349 modeline-format doc string. */ |
428 | 7350 /* This differs from %* in that it ignores read-only-ness. */ |
7351 case '&': | |
7352 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7353 ? "*" | |
7354 : "-"); | |
7355 break; | |
7356 | |
7357 /* print process status */ | |
7358 case 's': | |
7359 obj = Fget_buffer_process (w->buffer); | |
7360 if (NILP (obj)) | |
7361 str = GETTEXT ("no process"); | |
7362 else | |
7363 obj = Fsymbol_name (Fprocess_status (obj)); | |
7364 break; | |
7365 | |
7366 /* Print name of selected frame. */ | |
7367 case 'S': | |
7368 obj = XFRAME (w->frame)->name; | |
7369 break; | |
7370 | |
7371 /* indicate TEXT or BINARY */ | |
7372 case 't': | |
7373 /* #### NT does not use this any more. Now what? */ | |
7374 str = "T"; | |
7375 break; | |
7376 | |
7377 /* print percent of buffer above top of window, or Top, Bot or All */ | |
7378 case 'p': | |
7379 { | |
665 | 7380 Charbpos pos = marker_position (w->start[type]); |
428 | 7381 |
7382 /* This had better be while the desired lines are being done. */ | |
7383 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) | |
7384 { | |
7385 if (pos <= BUF_BEGV (b)) | |
7386 str = "All"; | |
7387 else | |
7388 str = "Bottom"; | |
7389 } | |
7390 else if (pos <= BUF_BEGV (b)) | |
7391 str = "Top"; | |
7392 else | |
7393 { | |
7394 /* This hard limit is ok since the string it will hold has a | |
4187 | 7395 fixed maximum length of 3. But just to be safe... */ |
428 | 7396 char buf[10]; |
7397 Charcount chars = pos - BUF_BEGV (b); | |
7398 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7399 | |
7400 /* Avoid overflow on big buffers */ | |
7401 int percent = total > LONG_MAX/200 ? | |
7402 (chars + total/200) / (total / 100) : | |
7403 (chars * 100 + total/2) / total; | |
7404 | |
7405 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7406 2-digit number that is close. */ |
428 | 7407 if (percent == 100) |
7408 percent = 99; | |
7409 | |
7410 sprintf (buf, "%d%%", percent); | |
867 | 7411 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7412 strlen (buf)); |
7413 | |
7414 goto decode_mode_spec_done; | |
7415 } | |
7416 break; | |
7417 } | |
7418 | |
7419 /* print percent of buffer above bottom of window, perhaps plus | |
7420 Top, or print Bottom or All */ | |
7421 case 'P': | |
7422 { | |
665 | 7423 Charbpos toppos = marker_position (w->start[type]); |
7424 Charbpos botpos = BUF_Z (b) - w->window_end_pos[type]; | |
428 | 7425 |
7426 /* botpos is only accurate as of the last redisplay, so we can | |
4187 | 7427 only treat it as a hint. In particular, after erase-buffer, |
7428 botpos may be negative. */ | |
428 | 7429 if (botpos < toppos) |
7430 botpos = toppos; | |
7431 | |
7432 if (botpos >= BUF_ZV (b)) | |
7433 { | |
7434 if (toppos <= BUF_BEGV (b)) | |
7435 str = "All"; | |
7436 else | |
7437 str = "Bottom"; | |
7438 } | |
7439 else | |
7440 { | |
7441 /* This hard limit is ok since the string it will hold has a | |
4187 | 7442 fixed maximum length of around 6. But just to be safe... */ |
428 | 7443 char buf[10]; |
7444 Charcount chars = botpos - BUF_BEGV (b); | |
7445 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7446 | |
7447 /* Avoid overflow on big buffers */ | |
7448 int percent = total > LONG_MAX/200 ? | |
7449 (chars + total/200) / (total / 100) : | |
7450 (chars * 100 + total/2) / max (total, 1); | |
7451 | |
7452 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7453 2-digit number that is close. */ |
428 | 7454 if (percent == 100) |
7455 percent = 99; | |
7456 | |
7457 if (toppos <= BUF_BEGV (b)) | |
7458 sprintf (buf, "Top%d%%", percent); | |
7459 else | |
7460 sprintf (buf, "%d%%", percent); | |
7461 | |
867 | 7462 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7463 strlen (buf)); |
7464 | |
7465 goto decode_mode_spec_done; | |
7466 } | |
7467 break; | |
7468 } | |
7469 | |
7470 /* print % */ | |
7471 case '%': | |
7472 str = "%"; | |
7473 break; | |
7474 | |
7475 /* print one [ for each recursive editing level. */ | |
7476 case '[': | |
7477 { | |
7478 int i; | |
7479 | |
7480 if (command_loop_level > 5) | |
7481 { | |
7482 str = "[[[... "; | |
7483 break; | |
7484 } | |
7485 | |
7486 for (i = 0; i < command_loop_level; i++) | |
867 | 7487 Dynarr_add (mode_spec_ibyte_string, '['); |
428 | 7488 |
7489 goto decode_mode_spec_done; | |
7490 } | |
7491 | |
7492 /* print one ] for each recursive editing level. */ | |
7493 case ']': | |
7494 { | |
7495 int i; | |
7496 | |
7497 if (command_loop_level > 5) | |
7498 { | |
7499 str = "...]]]"; | |
7500 break; | |
7501 } | |
7502 | |
7503 for (i = 0; i < command_loop_level; i++) | |
867 | 7504 Dynarr_add (mode_spec_ibyte_string, ']'); |
428 | 7505 |
7506 goto decode_mode_spec_done; | |
7507 } | |
7508 | |
7509 /* print infinitely many dashes -- handle at top level now */ | |
7510 case '-': | |
7511 break; | |
7512 | |
7513 } | |
7514 | |
7515 if (STRINGP (obj)) | |
867 | 7516 Dynarr_add_many (mode_spec_ibyte_string, |
428 | 7517 XSTRING_DATA (obj), |
7518 XSTRING_LENGTH (obj)); | |
7519 else if (str) | |
867 | 7520 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) str, strlen (str)); |
428 | 7521 |
7522 decode_mode_spec_done: | |
867 | 7523 Dynarr_add (mode_spec_ibyte_string, '\0'); |
428 | 7524 } |
7525 | |
7526 /* Given a display line, free all of its data structures. */ | |
7527 | |
7528 static void | |
7529 free_display_line (struct display_line *dl) | |
7530 { | |
7531 int block; | |
7532 | |
7533 if (dl->display_blocks) | |
7534 { | |
7535 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
4187 | 7536 { |
428 | 7537 struct display_block *db = Dynarr_atp (dl->display_blocks, block); |
7538 | |
7539 Dynarr_free (db->runes); | |
7540 } | |
7541 | |
7542 Dynarr_free (dl->display_blocks); | |
7543 dl->display_blocks = NULL; | |
7544 } | |
7545 | |
7546 if (dl->left_glyphs) | |
7547 { | |
7548 Dynarr_free (dl->left_glyphs); | |
7549 dl->left_glyphs = NULL; | |
7550 } | |
7551 | |
7552 if (dl->right_glyphs) | |
7553 { | |
7554 Dynarr_free (dl->right_glyphs); | |
7555 dl->right_glyphs = NULL; | |
7556 } | |
7557 } | |
7558 | |
7559 | |
7560 /* Given an array of display lines, free them and all data structures | |
7561 contained within them. */ | |
7562 | |
7563 void | |
7564 free_display_lines (display_line_dynarr *dla) | |
7565 { | |
7566 int line; | |
7567 | |
7568 for (line = 0; line < Dynarr_largest (dla); line++) | |
7569 { | |
7570 free_display_line (Dynarr_atp (dla, line)); | |
7571 } | |
7572 | |
7573 Dynarr_free (dla); | |
7574 } | |
7575 | |
7576 /* Call internal free routine for each set of display lines. */ | |
7577 | |
7578 void | |
7579 free_display_structs (struct window_mirror *mir) | |
7580 { | |
7581 if (mir->current_display_lines) | |
7582 { | |
7583 free_display_lines (mir->current_display_lines); | |
7584 mir->current_display_lines = 0; | |
7585 } | |
7586 | |
7587 if (mir->desired_display_lines) | |
7588 { | |
7589 free_display_lines (mir->desired_display_lines); | |
7590 mir->desired_display_lines = 0; | |
7591 } | |
7592 } | |
7593 | |
7594 | |
7595 static void | |
7596 mark_glyph_block_dynarr (glyph_block_dynarr *gba) | |
7597 { | |
7598 if (gba) | |
7599 { | |
4967 | 7600 glyph_block *gb = Dynarr_begin (gba); |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7601 glyph_block *gb_last = Dynarr_past_lastp (gba); |
428 | 7602 |
7603 for (; gb < gb_last; gb++) | |
7604 { | |
7605 if (!NILP (gb->glyph)) | |
7606 mark_object (gb->glyph); | |
7607 if (!NILP (gb->extent)) | |
7608 mark_object (gb->extent); | |
7609 } | |
7610 } | |
7611 } | |
7612 | |
442 | 7613 /* See the comment in image_instantiate_cache_result as to why marking |
7614 the glyph will also mark the image_instance. */ | |
7615 void | |
428 | 7616 mark_redisplay_structs (display_line_dynarr *dla) |
7617 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7618 display_line *dl = Dynarr_begin (dla); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7619 display_line *dl_last = Dynarr_past_lastp (dla); |
428 | 7620 |
7621 for (; dl < dl_last; dl++) | |
7622 { | |
7623 display_block_dynarr *dba = dl->display_blocks; | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7624 display_block *db = Dynarr_begin (dba); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7625 display_block *db_last = Dynarr_past_lastp (dba); |
428 | 7626 |
7627 for (; db < db_last; db++) | |
7628 { | |
7629 rune_dynarr *ra = db->runes; | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7630 rune *r = Dynarr_begin (ra); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7631 rune *r_last = Dynarr_past_lastp (ra); |
428 | 7632 |
7633 for (; r < r_last; r++) | |
7634 { | |
7635 if (r->type == RUNE_DGLYPH) | |
7636 { | |
7637 if (!NILP (r->object.dglyph.glyph)) | |
7638 mark_object (r->object.dglyph.glyph); | |
7639 if (!NILP (r->object.dglyph.extent)) | |
7640 mark_object (r->object.dglyph.extent); | |
7641 } | |
7642 } | |
7643 } | |
7644 | |
7645 mark_glyph_block_dynarr (dl->left_glyphs); | |
7646 mark_glyph_block_dynarr (dl->right_glyphs); | |
7647 } | |
7648 } | |
7649 | |
7650 | |
2367 | 7651 |
7652 /* | |
7653 | |
7654 Info on line-start cache: | |
7655 | |
7656 (Info-goto-node "(internals)Line Start Cache") | |
7657 */ | |
428 | 7658 |
7659 /* This will get used quite a bit so we don't want to be constantly | |
7660 allocating and freeing it. */ | |
7661 static line_start_cache_dynarr *internal_cache; | |
7662 | |
7663 /* Makes internal_cache represent the TYPE display structs and only | |
7664 the TYPE display structs. */ | |
7665 | |
7666 static void | |
7667 update_internal_cache_list (struct window *w, int type) | |
7668 { | |
7669 int line; | |
7670 display_line_dynarr *dla = window_display_lines (w, type); | |
7671 | |
7672 Dynarr_reset (internal_cache); | |
7673 for (line = 0; line < Dynarr_length (dla); line++) | |
7674 { | |
7675 struct display_line *dl = Dynarr_atp (dla, line); | |
7676 | |
7677 if (dl->modeline) | |
7678 continue; | |
7679 else | |
7680 { | |
7681 struct line_start_cache lsc; | |
434 | 7682 |
826 | 7683 lsc.start = dl->charpos; |
7684 lsc.end = dl->end_charpos; | |
428 | 7685 lsc.height = dl->ascent + dl->descent; |
7686 | |
7687 Dynarr_add (internal_cache, lsc); | |
7688 } | |
7689 } | |
7690 } | |
7691 | |
7692 /* Reset the line cache if necessary. This should be run at the | |
7693 beginning of any function which access the cache. */ | |
7694 | |
7695 static void | |
7696 validate_line_start_cache (struct window *w) | |
7697 { | |
7698 struct buffer *b = XBUFFER (w->buffer); | |
7699 struct frame *f = XFRAME (w->frame); | |
7700 | |
7701 if (!w->line_cache_validation_override) | |
7702 { | |
7703 /* f->extents_changed used to be in here because extent face and | |
4187 | 7704 size changes can cause text shifting. However, the extent |
7705 covering the region is constantly having its face set and | |
7706 priority altered by the mouse code. This means that the line | |
7707 start cache is constantly being invalidated. This is bad | |
7708 since the mouse code also triggers heavy usage of the cache. | |
7709 Since it is an unlikely that f->extents being changed | |
7710 indicates that the cache really needs to be updated and if it | |
7711 does redisplay will catch it pretty quickly we no longer | |
7712 invalidate the cache if it is set. This greatly speeds up | |
7713 dragging out regions with the mouse. */ | |
428 | 7714 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b) |
7715 || f->faces_changed | |
7716 || f->clip_changed) | |
7717 { | |
7718 Dynarr_reset (w->line_start_cache); | |
7719 } | |
7720 } | |
7721 } | |
7722 | |
7723 /* Return the very first buffer position contained in the given | |
7724 window's cache, or -1 if the cache is empty. Assumes that the | |
7725 cache is valid. */ | |
7726 | |
665 | 7727 static Charbpos |
428 | 7728 line_start_cache_start (struct window *w) |
7729 { | |
7730 line_start_cache_dynarr *cache = w->line_start_cache; | |
7731 | |
7732 if (!Dynarr_length (cache)) | |
7733 return -1; | |
7734 else | |
4967 | 7735 return Dynarr_begin (cache)->start; |
428 | 7736 } |
7737 | |
7738 /* Return the very last buffer position contained in the given | |
7739 window's cache, or -1 if the cache is empty. Assumes that the | |
7740 cache is valid. */ | |
7741 | |
665 | 7742 static Charbpos |
428 | 7743 line_start_cache_end (struct window *w) |
7744 { | |
7745 line_start_cache_dynarr *cache = w->line_start_cache; | |
7746 | |
7747 if (!Dynarr_length (cache)) | |
7748 return -1; | |
7749 else | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7750 return Dynarr_lastp (cache)->end; |
428 | 7751 } |
7752 | |
7753 /* Return the index of the line POINT is contained within in window | |
7754 W's line start cache. It will enlarge the cache or move the cache | |
7755 window in order to have POINT be present in the cache. MIN_PAST is | |
7756 a guarantee of the number of entries in the cache present on either | |
7757 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1 | |
7758 then it will be treated as 0, but the cache window will not be | |
7759 allowed to shift. Returns -1 if POINT cannot be found in the cache | |
7760 for any reason. */ | |
7761 | |
7762 int | |
665 | 7763 point_in_line_start_cache (struct window *w, Charbpos point, int min_past) |
428 | 7764 { |
7765 struct buffer *b = XBUFFER (w->buffer); | |
7766 line_start_cache_dynarr *cache = w->line_start_cache; | |
647 | 7767 int top, bottom, pos; |
428 | 7768 |
7769 validate_line_start_cache (w); | |
7770 w->line_cache_validation_override++; | |
7771 | |
7772 /* Let functions pass in negative values, but we still treat -1 | |
7773 specially. */ | |
7774 /* #### bogosity alert */ | |
7775 if (min_past < 0 && min_past != -1) | |
7776 min_past = -min_past; | |
7777 | |
7778 if (!Dynarr_length (cache) || line_start_cache_start (w) > point | |
7779 || line_start_cache_end (w) < point) | |
7780 { | |
7781 int loop; | |
7782 int win_char_height = window_char_height (w, 1); | |
7783 | |
7784 /* Occasionally we get here with a 0 height | |
4187 | 7785 window. find_next_newline_no_quit will abort if we pass it a |
7786 count of 0 so handle that case. */ | |
428 | 7787 if (!win_char_height) |
7788 win_char_height = 1; | |
7789 | |
7790 if (!Dynarr_length (cache)) | |
7791 { | |
665 | 7792 Charbpos from = find_next_newline_no_quit (b, point, -1); |
7793 Charbpos to = find_next_newline_no_quit (b, from, win_char_height); | |
428 | 7794 |
7795 update_line_start_cache (w, from, to, point, 0); | |
7796 | |
7797 if (!Dynarr_length (cache)) | |
7798 { | |
7799 w->line_cache_validation_override--; | |
7800 return -1; | |
7801 } | |
7802 } | |
7803 | |
7804 assert (Dynarr_length (cache)); | |
7805 | |
7806 loop = 0; | |
7807 while (line_start_cache_start (w) > point | |
7808 && (loop < cache_adjustment || min_past == -1)) | |
7809 { | |
665 | 7810 Charbpos from, to; |
428 | 7811 |
7812 from = line_start_cache_start (w); | |
7813 if (from <= BUF_BEGV (b)) | |
7814 break; | |
7815 | |
7816 from = find_next_newline_no_quit (b, from, -win_char_height); | |
7817 to = line_start_cache_end (w); | |
7818 | |
7819 update_line_start_cache (w, from, to, point, 0); | |
7820 loop++; | |
7821 } | |
7822 | |
7823 if (line_start_cache_start (w) > point) | |
7824 { | |
665 | 7825 Charbpos from, to; |
428 | 7826 |
7827 from = find_next_newline_no_quit (b, point, -1); | |
7828 if (from >= BUF_ZV (b)) | |
7829 { | |
7830 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7831 from = to; | |
7832 to = BUF_ZV (b); | |
7833 } | |
7834 else | |
7835 to = find_next_newline_no_quit (b, from, win_char_height); | |
7836 | |
7837 update_line_start_cache (w, from, to, point, 0); | |
7838 } | |
7839 | |
7840 loop = 0; | |
7841 while (line_start_cache_end (w) < point | |
7842 && (loop < cache_adjustment || min_past == -1)) | |
7843 { | |
665 | 7844 Charbpos from, to; |
428 | 7845 |
7846 to = line_start_cache_end (w); | |
7847 if (to >= BUF_ZV (b)) | |
7848 break; | |
7849 | |
7850 from = line_start_cache_end (w); | |
7851 to = find_next_newline_no_quit (b, from, win_char_height); | |
7852 | |
7853 update_line_start_cache (w, from, to, point, 0); | |
7854 loop++; | |
7855 } | |
7856 | |
7857 if (line_start_cache_end (w) < point) | |
7858 { | |
665 | 7859 Charbpos from, to; |
428 | 7860 |
7861 from = find_next_newline_no_quit (b, point, -1); | |
7862 if (from >= BUF_ZV (b)) | |
7863 { | |
7864 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7865 from = to; | |
7866 to = BUF_ZV (b); | |
7867 } | |
7868 else | |
7869 to = find_next_newline_no_quit (b, from, win_char_height); | |
7870 | |
7871 update_line_start_cache (w, from, to, point, 0); | |
7872 } | |
7873 } | |
7874 | |
7875 assert (Dynarr_length (cache)); | |
7876 | |
7877 if (min_past == -1) | |
7878 min_past = 0; | |
7879 | |
7880 /* This could happen if the buffer is narrowed. */ | |
7881 if (line_start_cache_start (w) > point | |
7882 || line_start_cache_end (w) < point) | |
7883 { | |
7884 w->line_cache_validation_override--; | |
7885 return -1; | |
7886 } | |
7887 | |
7888 find_point_loop: | |
7889 | |
7890 top = Dynarr_length (cache) - 1; | |
7891 bottom = 0; | |
7892 | |
7893 while (1) | |
7894 { | |
647 | 7895 int new_pos; |
665 | 7896 Charbpos start, end; |
428 | 7897 |
7898 pos = (bottom + top + 1) >> 1; | |
7899 start = Dynarr_atp (cache, pos)->start; | |
7900 end = Dynarr_atp (cache, pos)->end; | |
7901 | |
7902 if (point >= start && point <= end) | |
7903 { | |
7904 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b)) | |
7905 { | |
665 | 7906 Charbpos from = |
428 | 7907 find_next_newline_no_quit (b, line_start_cache_start (w), |
7908 -min_past - 1); | |
665 | 7909 Charbpos to = line_start_cache_end (w); |
428 | 7910 |
7911 update_line_start_cache (w, from, to, point, 0); | |
7912 goto find_point_loop; | |
7913 } | |
7914 else if ((Dynarr_length (cache) - pos - 1) < min_past | |
7915 && line_start_cache_end (w) < BUF_ZV (b)) | |
7916 { | |
665 | 7917 Charbpos from = line_start_cache_end (w); |
7918 Charbpos to = find_next_newline_no_quit (b, from, | |
428 | 7919 (min_past |
7920 ? min_past | |
7921 : 1)); | |
7922 | |
7923 update_line_start_cache (w, from, to, point, 0); | |
7924 goto find_point_loop; | |
7925 } | |
7926 else | |
7927 { | |
7928 w->line_cache_validation_override--; | |
7929 return pos; | |
7930 } | |
7931 } | |
7932 else if (point > end) | |
7933 bottom = pos + 1; | |
7934 else if (point < start) | |
7935 top = pos - 1; | |
7936 else | |
2500 | 7937 ABORT (); |
428 | 7938 |
7939 new_pos = (bottom + top + 1) >> 1; | |
7940 if (pos == new_pos) | |
7941 { | |
7942 w->line_cache_validation_override--; | |
7943 return -1; | |
7944 } | |
7945 } | |
7946 } | |
7947 | |
7948 /* Return a boolean indicating if POINT would be visible in window W | |
1708 | 7949 if display of the window was to begin at STARTP. If PARTIALLY is |
7950 zero, then if POINT has fewer visible pixels than the window clip, | |
7951 0 is returned; otherwise, 1 is returned if POINT has any visible | |
7952 pixels. */ | |
428 | 7953 int |
1708 | 7954 point_would_be_visible (struct window *w, Charbpos startp, Charbpos point, |
7955 int partially) | |
428 | 7956 { |
7957 struct buffer *b = XBUFFER (w->buffer); | |
430 | 7958 int pixpos = -WINDOW_TEXT_TOP_CLIP(w); |
428 | 7959 int bottom = WINDOW_TEXT_HEIGHT (w); |
7960 int start_elt; | |
7961 | |
7962 /* If point is before the intended start it obviously can't be visible. */ | |
7963 if (point < startp) | |
7964 return 0; | |
7965 | |
7966 /* If point or start are not in the accessible buffer range, then | |
7967 fail. */ | |
7968 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b) | |
7969 || point < BUF_BEGV (b) || point > BUF_ZV (b)) | |
7970 return 0; | |
7971 | |
7972 validate_line_start_cache (w); | |
7973 w->line_cache_validation_override++; | |
7974 | |
7975 start_elt = point_in_line_start_cache (w, startp, 0); | |
7976 if (start_elt == -1) | |
7977 { | |
7978 w->line_cache_validation_override--; | |
7979 return 0; | |
7980 } | |
7981 | |
7982 assert (line_start_cache_start (w) <= startp | |
7983 && line_start_cache_end (w) >= startp); | |
7984 | |
7985 while (1) | |
7986 { | |
7987 int height; | |
7988 | |
7989 /* Expand the cache if necessary. */ | |
7990 if (start_elt == Dynarr_length (w->line_start_cache)) | |
7991 { | |
665 | 7992 Charbpos old_startp = |
428 | 7993 Dynarr_atp (w->line_start_cache, start_elt - 1)->start; |
7994 | |
7995 start_elt = point_in_line_start_cache (w, old_startp, | |
7996 window_char_height (w, 0)); | |
7997 | |
7998 /* We've already actually processed old_startp, so increment | |
4187 | 7999 immediately. */ |
428 | 8000 start_elt++; |
8001 | |
8002 /* If this happens we didn't add any extra elements. Bummer. */ | |
8003 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8004 { | |
8005 w->line_cache_validation_override--; | |
8006 return 0; | |
8007 } | |
8008 } | |
8009 | |
8010 height = Dynarr_atp (w->line_start_cache, start_elt)->height; | |
8011 | |
8012 if (pixpos + height > bottom) | |
8013 { | |
1708 | 8014 if (bottom - pixpos < (partially ? 0 : VERTICAL_CLIP (w, 0))) |
428 | 8015 { |
8016 w->line_cache_validation_override--; | |
8017 return 0; | |
8018 } | |
8019 } | |
8020 | |
8021 pixpos += height; | |
8022 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end) | |
8023 { | |
8024 w->line_cache_validation_override--; | |
8025 return 1; | |
8026 } | |
8027 | |
8028 start_elt++; | |
8029 } | |
8030 } | |
8031 | |
8032 /* For the given window W, if display starts at STARTP, what will be | |
8033 the buffer position at the beginning or end of the last line | |
8034 displayed. The end of the last line is also know as the window end | |
8035 position. | |
8036 | |
442 | 8037 WARNING: It is possible that redisplay failed to layout any lines for the |
8038 windows. Under normal circumstances this is rare. However it seems that it | |
8039 does occur in the following situation: A mouse event has come in and we | |
8040 need to compute its location in a window. That code (in | |
8041 pixel_to_glyph_translation) already can handle 0 as an error return value. | |
8042 | |
428 | 8043 #### With a little work this could probably be reworked as just a |
8044 call to start_with_line_at_pixpos. */ | |
8045 | |
665 | 8046 static Charbpos |
8047 start_end_of_last_line (struct window *w, Charbpos startp, int end, | |
4187 | 8048 int may_error) |
428 | 8049 { |
8050 struct buffer *b = XBUFFER (w->buffer); | |
8051 line_start_cache_dynarr *cache = w->line_start_cache; | |
8052 int pixpos = 0; | |
8053 int bottom = WINDOW_TEXT_HEIGHT (w); | |
665 | 8054 Charbpos cur_start; |
428 | 8055 int start_elt; |
8056 | |
8057 validate_line_start_cache (w); | |
8058 w->line_cache_validation_override++; | |
8059 | |
8060 if (startp < BUF_BEGV (b)) | |
8061 startp = BUF_BEGV (b); | |
8062 else if (startp > BUF_ZV (b)) | |
8063 startp = BUF_ZV (b); | |
8064 cur_start = startp; | |
8065 | |
8066 start_elt = point_in_line_start_cache (w, cur_start, 0); | |
8067 if (start_elt == -1) | |
442 | 8068 return may_error ? 0 : startp; |
428 | 8069 |
8070 while (1) | |
8071 { | |
8072 int height = Dynarr_atp (cache, start_elt)->height; | |
8073 | |
8074 cur_start = Dynarr_atp (cache, start_elt)->start; | |
8075 | |
8076 if (pixpos + height > bottom) | |
8077 { | |
8078 /* Adjust for any possible clip. */ | |
8079 if (bottom - pixpos < VERTICAL_CLIP (w, 0)) | |
8080 start_elt--; | |
8081 | |
8082 if (start_elt < 0) | |
8083 { | |
8084 w->line_cache_validation_override--; | |
8085 if (end) | |
8086 return BUF_ZV (b); | |
8087 else | |
8088 return BUF_BEGV (b); | |
8089 } | |
8090 else | |
8091 { | |
8092 w->line_cache_validation_override--; | |
8093 if (end) | |
8094 return Dynarr_atp (cache, start_elt)->end; | |
8095 else | |
8096 return Dynarr_atp (cache, start_elt)->start; | |
8097 } | |
8098 } | |
8099 | |
8100 pixpos += height; | |
8101 start_elt++; | |
8102 if (start_elt == Dynarr_length (cache)) | |
8103 { | |
665 | 8104 Charbpos from = line_start_cache_end (w); |
428 | 8105 int win_char_height = window_char_height (w, 0); |
665 | 8106 Charbpos to = find_next_newline_no_quit (b, from, |
428 | 8107 (win_char_height |
8108 ? win_char_height | |
8109 : 1)); | |
8110 | |
8111 /* We've hit the end of the bottom so that's what it is. */ | |
8112 if (from >= BUF_ZV (b)) | |
8113 { | |
8114 w->line_cache_validation_override--; | |
8115 return BUF_ZV (b); | |
8116 } | |
8117 | |
8118 update_line_start_cache (w, from, to, BUF_PT (b), 0); | |
8119 | |
8120 /* Updating the cache invalidates any current indexes. */ | |
8121 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1; | |
8122 } | |
8123 } | |
8124 } | |
8125 | |
8126 /* For the given window W, if display starts at STARTP, what will be | |
8127 the buffer position at the beginning of the last line displayed. */ | |
8128 | |
665 | 8129 Charbpos |
8130 start_of_last_line (struct window *w, Charbpos startp) | |
428 | 8131 { |
442 | 8132 return start_end_of_last_line (w, startp, 0 , 0); |
428 | 8133 } |
8134 | |
8135 /* For the given window W, if display starts at STARTP, what will be | |
8136 the buffer position at the end of the last line displayed. This is | |
8137 also know as the window end position. */ | |
8138 | |
665 | 8139 Charbpos |
8140 end_of_last_line (struct window *w, Charbpos startp) | |
428 | 8141 { |
442 | 8142 return start_end_of_last_line (w, startp, 1, 0); |
428 | 8143 } |
8144 | |
665 | 8145 static Charbpos |
8146 end_of_last_line_may_error (struct window *w, Charbpos startp) | |
442 | 8147 { |
8148 return start_end_of_last_line (w, startp, 1, 1); | |
8149 } | |
8150 | |
8151 | |
428 | 8152 /* For window W, what does the starting position have to be so that |
8153 the line containing POINT will cover pixel position PIXPOS. */ | |
8154 | |
665 | 8155 Charbpos |
8156 start_with_line_at_pixpos (struct window *w, Charbpos point, int pixpos) | |
428 | 8157 { |
8158 struct buffer *b = XBUFFER (w->buffer); | |
8159 int cur_elt; | |
665 | 8160 Charbpos cur_pos, prev_pos = point; |
428 | 8161 int point_line_height; |
8162 int pixheight = pixpos - WINDOW_TEXT_TOP (w); | |
8163 | |
8164 validate_line_start_cache (w); | |
8165 w->line_cache_validation_override++; | |
8166 | |
8167 cur_elt = point_in_line_start_cache (w, point, 0); | |
8168 /* #### See comment in update_line_start_cache about big minibuffers. */ | |
8169 if (cur_elt < 0) | |
8170 { | |
8171 w->line_cache_validation_override--; | |
8172 return point; | |
8173 } | |
8174 | |
8175 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8176 | |
8177 while (1) | |
8178 { | |
8179 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8180 | |
8181 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8182 | |
8183 /* Do not take into account the value of vertical_clip here. | |
4187 | 8184 That is the responsibility of the calling functions. */ |
428 | 8185 if (pixheight < 0) |
8186 { | |
8187 w->line_cache_validation_override--; | |
8188 if (-pixheight > point_line_height) | |
8189 /* We can't make the target line cover pixpos, so put it | |
8190 above pixpos. That way it will at least be visible. */ | |
8191 return prev_pos; | |
8192 else | |
8193 return cur_pos; | |
8194 } | |
8195 | |
8196 cur_elt--; | |
8197 while (cur_elt < 0) | |
8198 { | |
665 | 8199 Charbpos from, to; |
428 | 8200 int win_char_height; |
8201 | |
8202 if (cur_pos <= BUF_BEGV (b)) | |
8203 { | |
8204 w->line_cache_validation_override--; | |
8205 return BUF_BEGV (b); | |
8206 } | |
8207 | |
8208 win_char_height = window_char_height (w, 0); | |
8209 if (!win_char_height) | |
8210 win_char_height = 1; | |
8211 | |
8212 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); | |
8213 to = line_start_cache_end (w); | |
8214 update_line_start_cache (w, from, to, point, 0); | |
8215 | |
8216 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; | |
8217 assert (cur_elt >= -1); | |
8218 /* This used to be cur_elt>=0 under the assumption that if | |
8219 point is in the top line and not at BUF_BEGV, then | |
434 | 8220 setting the window_start to a newline before the start of |
428 | 8221 the first line will always cause scrolling. |
8222 | |
8223 However in my (jv) opinion this is wrong. That new line | |
8224 can be hidden in various ways: invisible extents, an | |
8225 explicit window-start not at a newline character etc. | |
8226 The existence of those are indeed known to create crashes | |
8227 on that assert. So we have no option but to continue the | |
8228 search if we found point at the top of the line_start_cache | |
8229 again. */ | |
4967 | 8230 cur_pos = Dynarr_begin (w->line_start_cache)->start; |
428 | 8231 } |
8232 prev_pos = cur_pos; | |
8233 } | |
8234 } | |
8235 | |
8236 /* For window W, what does the starting position have to be so that | |
8237 the line containing point is on display line LINE. If LINE is | |
8238 positive it is considered to be the number of lines from the top of | |
8239 the window (0 is the top line). If it is negative the number is | |
8240 considered to be the number of lines from the bottom (-1 is the | |
8241 bottom line). */ | |
8242 | |
665 | 8243 Charbpos |
8244 start_with_point_on_display_line (struct window *w, Charbpos point, int line) | |
428 | 8245 { |
8246 validate_line_start_cache (w); | |
8247 w->line_cache_validation_override++; | |
8248 | |
8249 if (line >= 0) | |
8250 { | |
8251 int cur_elt = point_in_line_start_cache (w, point, line); | |
8252 | |
8253 if (cur_elt - line < 0) | |
8254 cur_elt = 0; /* Hit the top */ | |
8255 else | |
8256 cur_elt -= line; | |
8257 | |
8258 w->line_cache_validation_override--; | |
8259 return Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8260 } | |
8261 else | |
8262 { | |
8263 /* The calculated value of pixpos is correct for the bottom line | |
4187 | 8264 or what we want when line is -1. Therefore we subtract one |
8265 because we have already handled one line. */ | |
428 | 8266 int new_line = -line - 1; |
8267 int cur_elt = point_in_line_start_cache (w, point, new_line); | |
8268 int pixpos = WINDOW_TEXT_BOTTOM (w); | |
665 | 8269 Charbpos retval, search_point; |
428 | 8270 |
8271 /* If scroll_on_clipped_lines is false, the last "visible" line of | |
4187 | 8272 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1. |
8273 If s_o_c_l is true, then we don't want to count a clipped | |
8274 line, so back up from the bottom by the height of the line | |
8275 containing point. */ | |
428 | 8276 if (scroll_on_clipped_lines) |
8277 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8278 else | |
8279 pixpos -= 1; | |
8280 | |
8281 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache)) | |
8282 { | |
8283 /* Hit the bottom of the buffer. */ | |
8284 int adjustment = | |
8285 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1; | |
8286 Lisp_Object window; | |
8287 int defheight; | |
8288 | |
793 | 8289 window = wrap_window (w); |
428 | 8290 default_face_height_and_width (window, &defheight, 0); |
8291 | |
8292 cur_elt = Dynarr_length (w->line_start_cache) - 1; | |
8293 | |
8294 pixpos -= (adjustment * defheight); | |
8295 if (pixpos < WINDOW_TEXT_TOP (w)) | |
8296 pixpos = WINDOW_TEXT_TOP (w); | |
8297 } | |
8298 else | |
8299 cur_elt = cur_elt + new_line; | |
8300 | |
8301 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8302 | |
8303 retval = start_with_line_at_pixpos (w, search_point, pixpos); | |
8304 w->line_cache_validation_override--; | |
8305 return retval; | |
8306 } | |
8307 } | |
8308 | |
8309 /* This is used to speed up vertical scrolling by caching the known | |
8310 buffer starting positions for display lines. This allows the | |
8311 scrolling routines to avoid costly calls to regenerate_window. If | |
8312 NO_REGEN is true then it will only add the values in the DESIRED | |
8313 display structs which are in the given range. | |
8314 | |
8315 Note also that the FROM/TO values are minimums. It is possible | |
8316 that this function will actually add information outside of the | |
8317 lines containing those positions. This can't hurt but it could | |
8318 possibly help. | |
8319 | |
8320 #### We currently force the cache to have only 1 contiguous region. | |
8321 It might help to make the cache a dynarr of caches so that we can | |
8322 cover more areas. This might, however, turn out to be a lot of | |
8323 overhead for too little gain. */ | |
8324 | |
8325 static void | |
665 | 8326 update_line_start_cache (struct window *w, Charbpos from, Charbpos to, |
8327 Charbpos point, int no_regen) | |
428 | 8328 { |
8329 struct buffer *b = XBUFFER (w->buffer); | |
8330 line_start_cache_dynarr *cache = w->line_start_cache; | |
665 | 8331 Charbpos low_bound, high_bound; |
428 | 8332 |
8333 validate_line_start_cache (w); | |
8334 w->line_cache_validation_override++; | |
8335 | |
8336 if (from < BUF_BEGV (b)) | |
8337 from = BUF_BEGV (b); | |
8338 if (to > BUF_ZV (b)) | |
8339 to = BUF_ZV (b); | |
8340 | |
8341 if (from > to) | |
8342 { | |
8343 w->line_cache_validation_override--; | |
8344 return; | |
8345 } | |
8346 | |
8347 if (Dynarr_length (cache)) | |
8348 { | |
8349 low_bound = line_start_cache_start (w); | |
8350 high_bound = line_start_cache_end (w); | |
8351 | |
8352 /* Check to see if the desired range is already in the cache. */ | |
8353 if (from >= low_bound && to <= high_bound) | |
8354 { | |
8355 w->line_cache_validation_override--; | |
8356 return; | |
8357 } | |
8358 | |
8359 /* Check to make sure that the desired range is adjacent to the | |
8360 current cache. If not, invalidate the cache. */ | |
8361 if (to < low_bound || from > high_bound) | |
8362 { | |
8363 Dynarr_reset (cache); | |
8364 low_bound = high_bound = -1; | |
8365 } | |
8366 } | |
8367 else | |
8368 { | |
8369 low_bound = high_bound = -1; | |
8370 } | |
8371 | |
8372 w->line_cache_last_updated = make_int (BUF_MODIFF (b)); | |
8373 | |
8374 /* This could be integrated into the next two sections, but it is easier | |
8375 to follow what's going on by having it separate. */ | |
8376 if (no_regen) | |
8377 { | |
665 | 8378 Charbpos start, end; |
428 | 8379 |
8380 update_internal_cache_list (w, DESIRED_DISP); | |
8381 if (!Dynarr_length (internal_cache)) | |
8382 { | |
8383 w->line_cache_validation_override--; | |
8384 return; | |
8385 } | |
8386 | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8387 start = Dynarr_begin (internal_cache)->start; |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8388 end = Dynarr_lastp (internal_cache)->end; |
428 | 8389 |
8390 /* We aren't allowed to generate additional information to fill in | |
4187 | 8391 gaps, so if the DESIRED structs don't overlap the cache, reset the |
8392 cache. */ | |
428 | 8393 if (Dynarr_length (cache)) |
8394 { | |
8395 if (end < low_bound || start > high_bound) | |
8396 Dynarr_reset (cache); | |
8397 | |
8398 /* #### What should really happen if what we are doing is | |
4187 | 8399 extending a line (the last line)? */ |
428 | 8400 if (Dynarr_length (cache) == 1 |
8401 && Dynarr_length (internal_cache) == 1) | |
8402 Dynarr_reset (cache); | |
8403 } | |
8404 | |
8405 if (!Dynarr_length (cache)) | |
8406 { | |
4967 | 8407 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8408 Dynarr_length (internal_cache)); |
8409 w->line_cache_validation_override--; | |
8410 return; | |
8411 } | |
8412 | |
8413 /* An extra check just in case the calling function didn't pass in | |
4187 | 8414 the bounds of the DESIRED structs in the first place. */ |
428 | 8415 if (start >= low_bound && end <= high_bound) |
8416 { | |
8417 w->line_cache_validation_override--; | |
8418 return; | |
8419 } | |
8420 | |
8421 /* At this point we know that the internal cache partially overlaps | |
4187 | 8422 the main cache. */ |
428 | 8423 if (start < low_bound) |
8424 { | |
8425 int ic_elt = Dynarr_length (internal_cache) - 1; | |
8426 while (ic_elt >= 0) | |
8427 { | |
8428 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound) | |
8429 break; | |
8430 else | |
8431 ic_elt--; | |
8432 } | |
8433 | |
8434 if (!(ic_elt >= 0)) | |
8435 { | |
8436 Dynarr_reset (cache); | |
4967 | 8437 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8438 Dynarr_length (internal_cache)); |
8439 w->line_cache_validation_override--; | |
8440 return; | |
8441 } | |
8442 | |
4967 | 8443 Dynarr_insert_many_at_start (cache, Dynarr_begin (internal_cache), |
428 | 8444 ic_elt + 1); |
8445 } | |
8446 | |
8447 if (end > high_bound) | |
8448 { | |
8449 int ic_elt = 0; | |
8450 | |
8451 while (ic_elt < Dynarr_length (internal_cache)) | |
8452 { | |
8453 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound) | |
8454 break; | |
8455 else | |
8456 ic_elt++; | |
8457 } | |
8458 | |
8459 if (!(ic_elt < Dynarr_length (internal_cache))) | |
8460 { | |
8461 Dynarr_reset (cache); | |
4967 | 8462 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8463 Dynarr_length (internal_cache)); |
8464 w->line_cache_validation_override--; | |
8465 return; | |
8466 } | |
8467 | |
8468 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), | |
8469 Dynarr_length (internal_cache) - ic_elt); | |
8470 } | |
8471 | |
8472 w->line_cache_validation_override--; | |
8473 return; | |
8474 } | |
8475 | |
8476 if (!Dynarr_length (cache) || from < low_bound) | |
8477 { | |
665 | 8478 Charbpos startp = find_next_newline_no_quit (b, from, -1); |
428 | 8479 int marker = 0; |
8480 int old_lb = low_bound; | |
8481 | |
8482 while (startp < old_lb || low_bound == -1) | |
8483 { | |
8484 int ic_elt; | |
4187 | 8485 Charbpos new_startp; |
428 | 8486 |
8487 regenerate_window (w, startp, point, CMOTION_DISP); | |
8488 update_internal_cache_list (w, CMOTION_DISP); | |
8489 | |
8490 /* If this assert is triggered then regenerate_window failed | |
4187 | 8491 to layout a single line. This is not possible since we |
442 | 8492 force at least a single line to be layout for CMOTION_DISP */ |
8493 assert (Dynarr_length (internal_cache)); | |
4967 | 8494 assert (startp == Dynarr_begin (internal_cache)->start); |
428 | 8495 |
8496 ic_elt = Dynarr_length (internal_cache) - 1; | |
8497 if (low_bound != -1) | |
8498 { | |
8499 while (ic_elt >= 0) | |
8500 { | |
8501 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb) | |
8502 break; | |
8503 else | |
8504 ic_elt--; | |
8505 } | |
8506 } | |
8507 assert (ic_elt >= 0); | |
8508 | |
8509 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1; | |
8510 | |
4187 | 8511 /* |
8512 * Handle invisible text properly: | |
8513 * If the last line we're inserting has the same end as the | |
8514 * line before which it will be added, merge the two lines. | |
8515 */ | |
8516 if (Dynarr_length (cache) && | |
8517 Dynarr_atp (internal_cache, ic_elt)->end == | |
8518 Dynarr_atp (cache, marker)->end) | |
8519 { | |
8520 Dynarr_atp (cache, marker)->start | |
8521 = Dynarr_atp (internal_cache, ic_elt)->start; | |
8522 Dynarr_atp (cache, marker)->height | |
8523 = Dynarr_atp (internal_cache, ic_elt)->height; | |
8524 ic_elt--; | |
8525 } | |
8526 | |
8527 if (ic_elt >= 0) /* we still have lines to add.. */ | |
8528 { | |
4967 | 8529 Dynarr_insert_many (cache, Dynarr_begin (internal_cache), |
4187 | 8530 ic_elt + 1, marker); |
8531 marker += (ic_elt + 1); | |
8532 } | |
428 | 8533 |
8534 if (startp < low_bound || low_bound == -1) | |
8535 low_bound = startp; | |
8536 startp = new_startp; | |
8537 if (startp > BUF_ZV (b)) | |
8538 { | |
8539 w->line_cache_validation_override--; | |
8540 return; | |
8541 } | |
8542 } | |
8543 } | |
8544 | |
8545 assert (Dynarr_length (cache)); | |
8546 assert (from >= low_bound); | |
8547 | |
8548 /* Readjust the high_bound to account for any changes made while | |
8549 correcting the low_bound. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8550 high_bound = Dynarr_lastp (cache)->end; |
428 | 8551 |
8552 if (to > high_bound) | |
8553 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8554 Charbpos startp = Dynarr_lastp (cache)->end + 1; |
428 | 8555 |
8556 do | |
8557 { | |
8558 regenerate_window (w, startp, point, CMOTION_DISP); | |
8559 update_internal_cache_list (w, CMOTION_DISP); | |
8560 | |
8561 /* See comment above about regenerate_window failing. */ | |
8562 assert (Dynarr_length (internal_cache)); | |
8563 | |
4967 | 8564 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8565 Dynarr_length (internal_cache)); |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8566 high_bound = Dynarr_lastp (cache)->end; |
428 | 8567 startp = high_bound + 1; |
8568 } | |
8569 while (to > high_bound); | |
8570 } | |
8571 | |
8572 w->line_cache_validation_override--; | |
8573 assert (to <= high_bound); | |
8574 } | |
8575 | |
8576 | |
8577 /* Given x and y coordinates in characters, relative to a window, | |
8578 return the pixel location corresponding to those coordinates. The | |
8579 pixel location returned is the center of the given character | |
8580 position. The pixel values are generated relative to the window, | |
8581 not the frame. | |
8582 | |
8583 The modeline is considered to be part of the window. */ | |
8584 | |
8585 void | |
8586 glyph_to_pixel_translation (struct window *w, int char_x, int char_y, | |
8587 int *pix_x, int *pix_y) | |
8588 { | |
8589 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
8590 int num_disp_lines, modeline; | |
8591 Lisp_Object window; | |
8592 int defheight, defwidth; | |
8593 | |
793 | 8594 window = wrap_window (w); |
428 | 8595 default_face_height_and_width (window, &defheight, &defwidth); |
8596 | |
8597 /* If we get a bogus value indicating somewhere above or to the left of | |
8598 the window, use the first window line or character position | |
8599 instead. */ | |
8600 if (char_y < 0) | |
8601 char_y = 0; | |
8602 if (char_x < 0) | |
8603 char_x = 0; | |
8604 | |
8605 num_disp_lines = Dynarr_length (dla); | |
8606 modeline = 0; | |
8607 if (num_disp_lines) | |
8608 { | |
4967 | 8609 if (Dynarr_begin (dla)->modeline) |
428 | 8610 { |
8611 num_disp_lines--; | |
8612 modeline = 1; | |
8613 } | |
8614 } | |
8615 | |
8616 /* First check if the y position intersects the display lines. */ | |
8617 if (char_y < num_disp_lines) | |
8618 { | |
8619 struct display_line *dl = Dynarr_atp (dla, char_y + modeline); | |
8620 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
8621 | |
8622 *pix_y = (dl->ypos - dl->ascent + | |
647 | 8623 ((dl->ascent + dl->descent - dl->clip) >> 1)); |
428 | 8624 |
8625 if (char_x < Dynarr_length (db->runes)) | |
8626 { | |
8627 struct rune *rb = Dynarr_atp (db->runes, char_x); | |
8628 | |
8629 *pix_x = rb->xpos + (rb->width >> 1); | |
8630 } | |
8631 else | |
8632 { | |
8633 int last_rune = Dynarr_length (db->runes) - 1; | |
8634 struct rune *rb = Dynarr_atp (db->runes, last_rune); | |
8635 | |
8636 char_x -= last_rune; | |
8637 | |
8638 *pix_x = rb->xpos + rb->width; | |
8639 *pix_x += ((char_x - 1) * defwidth); | |
8640 *pix_x += (defwidth >> 1); | |
8641 } | |
8642 } | |
8643 else | |
8644 { | |
8645 /* It didn't intersect, so extrapolate. #### For now, we include the | |
8646 modeline in this since we don't have true character positions in | |
8647 it. */ | |
8648 | |
8649 if (!Dynarr_length (w->face_cachels)) | |
8650 reset_face_cachels (w); | |
8651 | |
8652 char_y -= num_disp_lines; | |
8653 | |
8654 if (Dynarr_length (dla)) | |
8655 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8656 struct display_line *dl = Dynarr_lastp (dla); |
428 | 8657 *pix_y = dl->ypos + dl->descent - dl->clip; |
8658 } | |
8659 else | |
8660 *pix_y = WINDOW_TEXT_TOP (w); | |
8661 | |
8662 *pix_y += (char_y * defheight); | |
8663 *pix_y += (defheight >> 1); | |
8664 | |
8665 *pix_x = WINDOW_TEXT_LEFT (w); | |
8666 /* Don't adjust by one because this is still the unadjusted value. */ | |
8667 *pix_x += (char_x * defwidth); | |
8668 *pix_x += (defwidth >> 1); | |
8669 } | |
8670 | |
8671 if (*pix_x > w->pixel_left + w->pixel_width) | |
8672 *pix_x = w->pixel_left + w->pixel_width; | |
8673 if (*pix_y > w->pixel_top + w->pixel_height) | |
8674 *pix_y = w->pixel_top + w->pixel_height; | |
8675 | |
8676 *pix_x -= w->pixel_left; | |
8677 *pix_y -= w->pixel_top; | |
8678 } | |
8679 | |
8680 /* Given a display line and a position, determine if there is a glyph | |
8681 there and return information about it if there is. */ | |
8682 | |
8683 static void | |
8684 get_position_object (struct display_line *dl, Lisp_Object *obj1, | |
8685 Lisp_Object *obj2, int x_coord, int *low_x_coord, | |
8686 int *high_x_coord) | |
8687 { | |
8688 struct display_block *db; | |
8689 int elt; | |
8690 int block = | |
8691 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0); | |
8692 | |
8693 /* We use get_next_display_block to get the actual display block | |
8694 that would be displayed at x_coord. */ | |
8695 | |
8696 if (block == NO_BLOCK) | |
8697 return; | |
8698 else | |
8699 db = Dynarr_atp (dl->display_blocks, block); | |
8700 | |
8701 for (elt = 0; elt < Dynarr_length (db->runes); elt++) | |
8702 { | |
8703 struct rune *rb = Dynarr_atp (db->runes, elt); | |
8704 | |
8705 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) | |
8706 { | |
8707 if (rb->type == RUNE_DGLYPH) | |
8708 { | |
8709 *obj1 = rb->object.dglyph.glyph; | |
8710 *obj2 = rb->object.dglyph.extent; | |
8711 } | |
8712 else | |
8713 { | |
8714 *obj1 = Qnil; | |
8715 *obj2 = Qnil; | |
8716 } | |
8717 | |
8718 if (low_x_coord) | |
8719 *low_x_coord = rb->xpos; | |
8720 if (high_x_coord) | |
8721 *high_x_coord = rb->xpos + rb->width; | |
8722 | |
8723 return; | |
8724 } | |
8725 } | |
8726 } | |
8727 | |
8728 #define UPDATE_CACHE_RETURN \ | |
8729 do { \ | |
8730 d->pixel_to_glyph_cache.valid = 1; \ | |
8731 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \ | |
8732 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \ | |
8733 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \ | |
8734 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \ | |
8735 d->pixel_to_glyph_cache.frame = f; \ | |
8736 d->pixel_to_glyph_cache.col = *col; \ | |
8737 d->pixel_to_glyph_cache.row = *row; \ | |
8738 d->pixel_to_glyph_cache.obj_x = *obj_x; \ | |
8739 d->pixel_to_glyph_cache.obj_y = *obj_y; \ | |
8740 d->pixel_to_glyph_cache.w = *w; \ | |
826 | 8741 d->pixel_to_glyph_cache.charpos = *charpos; \ |
428 | 8742 d->pixel_to_glyph_cache.closest = *closest; \ |
8743 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \ | |
8744 d->pixel_to_glyph_cache.obj1 = *obj1; \ | |
8745 d->pixel_to_glyph_cache.obj2 = *obj2; \ | |
8746 d->pixel_to_glyph_cache.retval = position; \ | |
8747 RETURN_SANS_WARNINGS position; \ | |
8748 } while (0) | |
8749 | |
8750 /* Given x and y coordinates in pixels relative to a frame, return | |
8751 information about what is located under those coordinates. | |
8752 | |
8753 The return value will be one of: | |
8754 | |
8755 OVER_TOOLBAR: over one of the 4 frame toolbars | |
8756 OVER_MODELINE: over a modeline | |
8757 OVER_BORDER: over an internal border | |
8758 OVER_NOTHING: over the text area, but not over text | |
8759 OVER_OUTSIDE: outside of the frame border | |
8760 OVER_TEXT: over text in the text area | |
8761 | |
8762 OBJ1 is one of | |
8763 | |
8764 -- a toolbar button | |
8765 -- a glyph | |
8766 -- nil if the coordinates are not over a glyph or a toolbar button. | |
8767 | |
8768 OBJ2 is one of | |
8769 | |
8770 -- an extent, if the coordinates are over a glyph in the text area | |
8771 -- nil otherwise. | |
8772 | |
8773 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the | |
8774 equivalent coordinates relative to the upper-left corner of the glyph. | |
8775 | |
8776 If the coordinates are over a character, OBJ_X and OBJ_Y give the | |
8777 equivalent coordinates relative to the upper-left corner of the character. | |
8778 | |
8779 Otherwise, OBJ_X and OBJ_Y are undefined. | |
8780 */ | |
8781 | |
8782 int | |
8783 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, | |
8784 int *col, int *row, int *obj_x, int *obj_y, | |
826 | 8785 struct window **w, Charbpos *charpos, |
665 | 8786 Charbpos *closest, Charcount *modeline_closest, |
428 | 8787 Lisp_Object *obj1, Lisp_Object *obj2) |
8788 { | |
8789 struct device *d; | |
8790 struct pixel_to_glyph_translation_cache *cache; | |
8791 Lisp_Object window; | |
8792 int frm_left, frm_right, frm_top, frm_bottom; | |
8793 int low_x_coord, high_x_coord, low_y_coord, high_y_coord; | |
8794 int position = OVER_NOTHING; | |
8795 int device_check_failed = 0; | |
8796 display_line_dynarr *dla; | |
8797 | |
8798 /* This is a safety valve in case this got called with a frame in | |
8799 the middle of being deleted. */ | |
8800 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device))) | |
8801 { | |
8802 device_check_failed = 1; | |
8803 d = NULL, cache = NULL; /* Warning suppression */ | |
8804 } | |
8805 else | |
8806 { | |
8807 d = XDEVICE (f->device); | |
8808 cache = &d->pixel_to_glyph_cache; | |
8809 } | |
8810 | |
8811 if (!device_check_failed | |
8812 && cache->valid | |
8813 && cache->frame == f | |
8814 && cache->low_x_coord <= x_coord | |
8815 && cache->high_x_coord > x_coord | |
8816 && cache->low_y_coord <= y_coord | |
8817 && cache->high_y_coord > y_coord) | |
8818 { | |
8819 *col = cache->col; | |
8820 *row = cache->row; | |
8821 *obj_x = cache->obj_x; | |
8822 *obj_y = cache->obj_y; | |
8823 *w = cache->w; | |
826 | 8824 *charpos = cache->charpos; |
428 | 8825 *closest = cache->closest; |
8826 *modeline_closest = cache->modeline_closest; | |
8827 *obj1 = cache->obj1; | |
8828 *obj2 = cache->obj2; | |
8829 | |
8830 return cache->retval; | |
8831 } | |
8832 else | |
8833 { | |
8834 *col = 0; | |
8835 *row = 0; | |
8836 *obj_x = 0; | |
8837 *obj_y = 0; | |
8838 *w = 0; | |
826 | 8839 *charpos = 0; |
428 | 8840 *closest = 0; |
8841 *modeline_closest = -1; | |
8842 *obj1 = Qnil; | |
8843 *obj2 = Qnil; | |
8844 | |
8845 low_x_coord = x_coord; | |
8846 high_x_coord = x_coord + 1; | |
8847 low_y_coord = y_coord; | |
8848 high_y_coord = y_coord + 1; | |
8849 } | |
8850 | |
8851 if (device_check_failed) | |
8852 return OVER_NOTHING; | |
8853 | |
8854 frm_left = FRAME_LEFT_BORDER_END (f); | |
8855 frm_right = FRAME_RIGHT_BORDER_START (f); | |
8856 frm_top = FRAME_TOP_BORDER_END (f); | |
8857 frm_bottom = FRAME_BOTTOM_BORDER_START (f); | |
8858 | |
8859 /* Check if the mouse is outside of the text area actually used by | |
8860 redisplay. */ | |
8861 if (y_coord < frm_top) | |
8862 { | |
8863 if (y_coord >= FRAME_TOP_BORDER_START (f)) | |
8864 { | |
8865 low_y_coord = FRAME_TOP_BORDER_START (f); | |
8866 high_y_coord = frm_top; | |
8867 position = OVER_BORDER; | |
8868 } | |
8869 else if (y_coord >= 0) | |
8870 { | |
8871 low_y_coord = 0; | |
8872 high_y_coord = FRAME_TOP_BORDER_START (f); | |
8873 position = OVER_TOOLBAR; | |
8874 } | |
8875 else | |
8876 { | |
8877 low_y_coord = y_coord; | |
8878 high_y_coord = 0; | |
8879 position = OVER_OUTSIDE; | |
8880 } | |
8881 } | |
8882 else if (y_coord >= frm_bottom) | |
8883 { | |
8884 if (y_coord < FRAME_BOTTOM_BORDER_END (f)) | |
8885 { | |
8886 low_y_coord = frm_bottom; | |
8887 high_y_coord = FRAME_BOTTOM_BORDER_END (f); | |
8888 position = OVER_BORDER; | |
8889 } | |
8890 else if (y_coord < FRAME_PIXHEIGHT (f)) | |
8891 { | |
8892 low_y_coord = FRAME_BOTTOM_BORDER_END (f); | |
8893 high_y_coord = FRAME_PIXHEIGHT (f); | |
8894 position = OVER_TOOLBAR; | |
8895 } | |
8896 else | |
8897 { | |
8898 low_y_coord = FRAME_PIXHEIGHT (f); | |
8899 high_y_coord = y_coord; | |
8900 position = OVER_OUTSIDE; | |
8901 } | |
8902 } | |
8903 | |
8904 if (position != OVER_TOOLBAR && position != OVER_BORDER) | |
8905 { | |
8906 if (x_coord < frm_left) | |
8907 { | |
8908 if (x_coord >= FRAME_LEFT_BORDER_START (f)) | |
8909 { | |
8910 low_x_coord = FRAME_LEFT_BORDER_START (f); | |
8911 high_x_coord = frm_left; | |
8912 position = OVER_BORDER; | |
8913 } | |
8914 else if (x_coord >= 0) | |
8915 { | |
8916 low_x_coord = 0; | |
8917 high_x_coord = FRAME_LEFT_BORDER_START (f); | |
8918 position = OVER_TOOLBAR; | |
8919 } | |
8920 else | |
8921 { | |
8922 low_x_coord = x_coord; | |
8923 high_x_coord = 0; | |
8924 position = OVER_OUTSIDE; | |
8925 } | |
8926 } | |
8927 else if (x_coord >= frm_right) | |
8928 { | |
8929 if (x_coord < FRAME_RIGHT_BORDER_END (f)) | |
8930 { | |
8931 low_x_coord = frm_right; | |
8932 high_x_coord = FRAME_RIGHT_BORDER_END (f); | |
8933 position = OVER_BORDER; | |
8934 } | |
8935 else if (x_coord < FRAME_PIXWIDTH (f)) | |
8936 { | |
8937 low_x_coord = FRAME_RIGHT_BORDER_END (f); | |
8938 high_x_coord = FRAME_PIXWIDTH (f); | |
8939 position = OVER_TOOLBAR; | |
8940 } | |
8941 else | |
8942 { | |
8943 low_x_coord = FRAME_PIXWIDTH (f); | |
8944 high_x_coord = x_coord; | |
8945 position = OVER_OUTSIDE; | |
8946 } | |
8947 } | |
8948 } | |
8949 | |
8950 #ifdef HAVE_TOOLBARS | |
8951 if (position == OVER_TOOLBAR) | |
8952 { | |
8953 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord); | |
8954 *obj2 = Qnil; | |
8955 *w = 0; | |
8956 UPDATE_CACHE_RETURN; | |
8957 } | |
8958 #endif /* HAVE_TOOLBARS */ | |
8959 | |
8960 /* We still have to return the window the pointer is next to and its | |
8961 relative y position even if it is outside the x boundary. */ | |
8962 if (x_coord < frm_left) | |
8963 x_coord = frm_left; | |
8964 else if (x_coord > frm_right) | |
8965 x_coord = frm_right; | |
8966 | |
8967 /* Same in reverse. */ | |
8968 if (y_coord < frm_top) | |
8969 y_coord = frm_top; | |
8970 else if (y_coord > frm_bottom) | |
8971 y_coord = frm_bottom; | |
8972 | |
8973 /* Find what window the given coordinates are actually in. */ | |
8974 window = f->root_window; | |
8975 *w = find_window_by_pixel_pos (x_coord, y_coord, window); | |
8976 | |
8977 /* If we didn't find a window, we're done. */ | |
8978 if (!*w) | |
8979 { | |
8980 UPDATE_CACHE_RETURN; | |
8981 } | |
8982 else if (position != OVER_NOTHING) | |
8983 { | |
8984 *closest = 0; | |
8985 *modeline_closest = -1; | |
8986 | |
8987 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) | |
8988 { | |
8989 *w = 0; | |
8990 UPDATE_CACHE_RETURN; | |
8991 } | |
8992 } | |
8993 | |
8994 /* Check if the window is a minibuffer but isn't active. */ | |
8995 if (MINI_WINDOW_P (*w) && !minibuf_level) | |
8996 { | |
8997 /* Must reset the window value since some callers will ignore | |
4187 | 8998 the return value if it is set. */ |
428 | 8999 *w = 0; |
9000 UPDATE_CACHE_RETURN; | |
9001 } | |
9002 | |
9003 /* See if the point is over window vertical divider */ | |
9004 if (window_needs_vertical_divider (*w)) | |
9005 { | |
9006 int div_x_high = WINDOW_RIGHT (*w); | |
9007 int div_x_low = div_x_high - window_divider_width (*w); | |
9008 int div_y_high = WINDOW_BOTTOM (*w); | |
9009 int div_y_low = WINDOW_TOP (*w); | |
9010 | |
9011 if (div_x_low < x_coord && x_coord <= div_x_high && | |
9012 div_y_low < y_coord && y_coord <= div_y_high) | |
9013 { | |
9014 low_x_coord = div_x_low; | |
9015 high_x_coord = div_x_high; | |
9016 low_y_coord = div_y_low; | |
9017 high_y_coord = div_y_high; | |
9018 position = OVER_V_DIVIDER; | |
9019 UPDATE_CACHE_RETURN; | |
9020 } | |
9021 } | |
9022 | |
9023 dla = window_display_lines (*w, CURRENT_DISP); | |
9024 | |
9025 for (*row = 0; *row < Dynarr_length (dla); (*row)++) | |
9026 { | |
9027 int really_over_nothing = 0; | |
9028 struct display_line *dl = Dynarr_atp (dla, *row); | |
9029 | |
9030 if ((int) (dl->ypos - dl->ascent) <= y_coord | |
9031 && y_coord <= (int) (dl->ypos + dl->descent)) | |
9032 { | |
9033 int check_margin_glyphs = 0; | |
9034 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
9035 struct rune *rb = 0; | |
9036 | |
9037 if (x_coord < dl->bounds.left_white | |
9038 || x_coord >= dl->bounds.right_white) | |
9039 check_margin_glyphs = 1; | |
9040 | |
9041 low_y_coord = dl->ypos - dl->ascent; | |
9042 high_y_coord = dl->ypos + dl->descent + 1; | |
9043 | |
9044 if (position == OVER_BORDER | |
9045 || position == OVER_OUTSIDE | |
9046 || check_margin_glyphs) | |
9047 { | |
9048 int x_check, left_bound; | |
9049 | |
9050 if (check_margin_glyphs) | |
9051 { | |
9052 x_check = x_coord; | |
9053 left_bound = dl->bounds.left_white; | |
9054 } | |
9055 else | |
9056 { | |
9057 x_check = high_x_coord; | |
9058 left_bound = frm_left; | |
9059 } | |
9060 | |
9061 if (Dynarr_length (db->runes)) | |
9062 { | |
9063 if (x_check <= left_bound) | |
9064 { | |
9065 if (dl->modeline) | |
4967 | 9066 *modeline_closest = Dynarr_begin (db->runes)->charpos; |
428 | 9067 else |
4967 | 9068 *closest = Dynarr_begin (db->runes)->charpos; |
428 | 9069 } |
9070 else | |
9071 { | |
9072 if (dl->modeline) | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9073 *modeline_closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9074 else |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9075 *closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9076 } |
9077 | |
9078 if (dl->modeline) | |
9079 *modeline_closest += dl->offset; | |
9080 else | |
9081 *closest += dl->offset; | |
9082 } | |
9083 else | |
9084 { | |
9085 /* #### What should be here. */ | |
9086 if (dl->modeline) | |
9087 *modeline_closest = 0; | |
9088 else | |
9089 *closest = 0; | |
9090 } | |
9091 | |
9092 if (check_margin_glyphs) | |
9093 { | |
9094 if (x_coord < dl->bounds.left_in | |
9095 || x_coord >= dl->bounds.right_in) | |
9096 { | |
9097 /* If we are over the outside margins then we | |
4187 | 9098 know the loop over the text block isn't going |
9099 to accomplish anything. So we go ahead and | |
9100 set what information we can right here and | |
9101 return. */ | |
428 | 9102 (*row)--; |
9103 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9104 get_position_object (dl, obj1, obj2, x_coord, | |
9105 &low_x_coord, &high_x_coord); | |
9106 | |
9107 UPDATE_CACHE_RETURN; | |
9108 } | |
9109 } | |
9110 else | |
9111 UPDATE_CACHE_RETURN; | |
9112 } | |
9113 | |
9114 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++) | |
9115 { | |
9116 int past_end = (*col == Dynarr_length (db->runes)); | |
9117 | |
9118 if (!past_end) | |
9119 rb = Dynarr_atp (db->runes, *col); | |
9120 | |
9121 if (past_end || | |
9122 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width)) | |
9123 { | |
9124 if (past_end) | |
9125 { | |
9126 (*col)--; | |
9127 rb = Dynarr_atp (db->runes, *col); | |
9128 } | |
9129 | |
826 | 9130 *charpos = rb->charpos + dl->offset; |
428 | 9131 low_x_coord = rb->xpos; |
9132 high_x_coord = rb->xpos + rb->width; | |
9133 | |
9134 if (rb->type == RUNE_DGLYPH) | |
9135 { | |
9136 int elt = *col + 1; | |
9137 | |
9138 /* Find the first character after the glyph. */ | |
9139 while (elt < Dynarr_length (db->runes)) | |
9140 { | |
9141 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH) | |
9142 { | |
9143 if (dl->modeline) | |
9144 *modeline_closest = | |
826 | 9145 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9146 dl->offset); |
9147 else | |
9148 *closest = | |
826 | 9149 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9150 dl->offset); |
9151 break; | |
9152 } | |
9153 | |
9154 elt++; | |
9155 } | |
9156 | |
9157 /* In this case we failed to find a non-glyph | |
4187 | 9158 character so we return the last position |
9159 displayed on the line. */ | |
428 | 9160 if (elt == Dynarr_length (db->runes)) |
9161 { | |
9162 if (dl->modeline) | |
826 | 9163 *modeline_closest = dl->end_charpos + dl->offset; |
428 | 9164 else |
826 | 9165 *closest = dl->end_charpos + dl->offset; |
428 | 9166 really_over_nothing = 1; |
9167 } | |
9168 } | |
9169 else | |
9170 { | |
9171 if (dl->modeline) | |
826 | 9172 *modeline_closest = rb->charpos + dl->offset; |
428 | 9173 else |
826 | 9174 *closest = rb->charpos + dl->offset; |
428 | 9175 } |
9176 | |
9177 if (dl->modeline) | |
9178 { | |
9179 *row = window_displayed_height (*w); | |
9180 | |
9181 if (position == OVER_NOTHING) | |
9182 position = OVER_MODELINE; | |
9183 | |
9184 if (rb->type == RUNE_DGLYPH) | |
9185 { | |
9186 *obj1 = rb->object.dglyph.glyph; | |
9187 *obj2 = rb->object.dglyph.extent; | |
9188 } | |
9189 else if (rb->type == RUNE_CHAR) | |
9190 { | |
9191 *obj1 = Qnil; | |
9192 *obj2 = Qnil; | |
9193 } | |
9194 else | |
9195 { | |
9196 *obj1 = Qnil; | |
9197 *obj2 = Qnil; | |
9198 } | |
9199 | |
9200 UPDATE_CACHE_RETURN; | |
9201 } | |
9202 else if (past_end | |
9203 || (rb->type == RUNE_CHAR | |
9204 && rb->object.chr.ch == '\n')) | |
9205 { | |
9206 (*row)--; | |
9207 /* At this point we may have glyphs in the right | |
4187 | 9208 inside margin. */ |
428 | 9209 if (check_margin_glyphs) |
9210 get_position_object (dl, obj1, obj2, x_coord, | |
9211 &low_x_coord, &high_x_coord); | |
9212 UPDATE_CACHE_RETURN; | |
9213 } | |
9214 else | |
9215 { | |
9216 (*row)--; | |
9217 if (rb->type == RUNE_DGLYPH) | |
9218 { | |
9219 *obj1 = rb->object.dglyph.glyph; | |
9220 *obj2 = rb->object.dglyph.extent; | |
9221 } | |
9222 else if (rb->type == RUNE_CHAR) | |
9223 { | |
9224 *obj1 = Qnil; | |
9225 *obj2 = Qnil; | |
9226 } | |
9227 else | |
9228 { | |
9229 *obj1 = Qnil; | |
9230 *obj2 = Qnil; | |
9231 } | |
9232 | |
9233 *obj_x = x_coord - rb->xpos; | |
9234 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9235 | |
9236 /* At this point we may have glyphs in the left | |
4187 | 9237 inside margin. */ |
428 | 9238 if (check_margin_glyphs) |
9239 get_position_object (dl, obj1, obj2, x_coord, 0, 0); | |
9240 | |
9241 if (position == OVER_NOTHING && !really_over_nothing) | |
9242 position = OVER_TEXT; | |
9243 | |
9244 UPDATE_CACHE_RETURN; | |
9245 } | |
9246 } | |
9247 } | |
9248 } | |
9249 } | |
9250 | |
9251 *row = Dynarr_length (dla) - 1; | |
9252 if (FRAME_WIN_P (f)) | |
9253 { | |
9254 int bot_elt = Dynarr_length (dla) - 1; | |
9255 | |
9256 if (bot_elt >= 0) | |
9257 { | |
9258 struct display_line *dl = Dynarr_atp (dla, bot_elt); | |
9259 int adj_area = y_coord - (dl->ypos + dl->descent); | |
9260 Lisp_Object lwin; | |
9261 int defheight; | |
9262 | |
793 | 9263 lwin = wrap_window (*w); |
428 | 9264 default_face_height_and_width (lwin, 0, &defheight); |
9265 | |
9266 *row += (adj_area / defheight); | |
9267 } | |
9268 } | |
9269 | |
9270 /* #### This should be checked out some more to determine what | |
9271 should really be going on. */ | |
9272 if (!MARKERP ((*w)->start[CURRENT_DISP])) | |
9273 *closest = 0; | |
9274 else | |
442 | 9275 *closest = end_of_last_line_may_error (*w, |
428 | 9276 marker_position ((*w)->start[CURRENT_DISP])); |
9277 *col = 0; | |
9278 UPDATE_CACHE_RETURN; | |
9279 } | |
9280 #undef UPDATE_CACHE_RETURN | |
9281 | |
9282 | |
9283 /***************************************************************************/ | |
9284 /* */ | |
9285 /* Lisp functions */ | |
9286 /* */ | |
9287 /***************************************************************************/ | |
9288 | |
9289 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /* | |
9290 Ensure that all minibuffers are correctly showing the echo area. | |
9291 */ | |
9292 ()) | |
9293 { | |
9294 Lisp_Object devcons, concons; | |
9295 | |
1318 | 9296 if (in_display) |
9297 return Qnil; | |
9298 | |
428 | 9299 DEVICE_LOOP_NO_BREAK (devcons, concons) |
9300 { | |
9301 struct device *d = XDEVICE (XCAR (devcons)); | |
9302 Lisp_Object frmcons; | |
9303 | |
1279 | 9304 if (DEVICE_STREAM_P (d)) |
9305 continue; | |
9306 | |
428 | 9307 DEVICE_FRAME_LOOP (frmcons, d) |
9308 { | |
9309 struct frame *f = XFRAME (XCAR (frmcons)); | |
853 | 9310 int depth; |
428 | 9311 |
9312 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) | |
9313 { | |
9314 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); | |
442 | 9315 |
9316 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
9317 | |
428 | 9318 /* |
9319 * If the frame size has changed, there may be random | |
9320 * chud on the screen left from previous messages | |
9321 * because redisplay_frame hasn't been called yet. | |
9322 * Clear the screen to get rid of the potential mess. | |
9323 */ | |
9324 if (f->echo_area_garbaged) | |
9325 { | |
442 | 9326 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 9327 f->echo_area_garbaged = 0; |
9328 } | |
853 | 9329 depth = enter_redisplay_critical_section (); |
428 | 9330 redisplay_window (window, 0); |
853 | 9331 exit_redisplay_critical_section (depth); |
442 | 9332 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 9333 } |
9334 } | |
9335 } | |
9336 | |
9337 return Qnil; | |
9338 } | |
9339 | |
9340 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /* | |
9341 Clear frame FRAME and output again what is supposed to appear on it. | |
9342 FRAME defaults to the selected frame if omitted. | |
9343 Normally, redisplay is preempted as normal if input arrives. However, | |
9344 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9345 input and is guaranteed to proceed to completion. | |
9346 */ | |
9347 (frame, no_preempt)) | |
9348 { | |
9349 struct frame *f = decode_frame (frame); | |
9350 int count = specpdl_depth (); | |
9351 | |
9352 if (!NILP (no_preempt)) | |
853 | 9353 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9354 |
9355 f->clear = 1; | |
9356 redisplay_frame (f, 1); | |
9357 | |
442 | 9358 /* See the comment in Fredisplay_frame. */ |
9359 RESET_CHANGED_SET_FLAGS; | |
9360 | |
771 | 9361 return unbind_to (count); |
428 | 9362 } |
9363 | |
9364 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* | |
9365 Ensure that FRAME's contents are correctly displayed. | |
9366 This differs from `redraw-frame' in that it only redraws what needs to | |
9367 be updated, as opposed to unconditionally clearing and redrawing | |
9368 the frame. | |
9369 FRAME defaults to the selected frame if omitted. | |
9370 Normally, redisplay is preempted as normal if input arrives. However, | |
9371 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9372 input and is guaranteed to proceed to completion. | |
9373 */ | |
9374 (frame, no_preempt)) | |
9375 { | |
9376 struct frame *f = decode_frame (frame); | |
9377 int count = specpdl_depth (); | |
9378 | |
9379 if (!NILP (no_preempt)) | |
853 | 9380 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9381 |
9382 redisplay_frame (f, 1); | |
9383 | |
442 | 9384 /* If we don't reset the global redisplay flags here, subsequent |
9385 changes to the display will not get registered by redisplay | |
9386 because it thinks it already has registered changes. If you | |
9387 really knew what you were doing you could confuse redisplay by | |
9388 calling Fredisplay_frame while updating another frame. We assume | |
9389 that if you know what you are doing you will not be that | |
9390 stupid. */ | |
9391 RESET_CHANGED_SET_FLAGS; | |
9392 | |
771 | 9393 return unbind_to (count); |
428 | 9394 } |
9395 | |
9396 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* | |
9397 Clear device DEVICE and output again what is supposed to appear on it. | |
9398 DEVICE defaults to the selected device if omitted. | |
9399 Normally, redisplay is preempted as normal if input arrives. However, | |
9400 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9401 input and is guaranteed to proceed to completion. | |
9402 */ | |
9403 (device, no_preempt)) | |
9404 { | |
9405 struct device *d = decode_device (device); | |
9406 Lisp_Object frmcons; | |
9407 int count = specpdl_depth (); | |
9408 | |
9409 if (!NILP (no_preempt)) | |
853 | 9410 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9411 |
9412 DEVICE_FRAME_LOOP (frmcons, d) | |
9413 { | |
9414 XFRAME (XCAR (frmcons))->clear = 1; | |
9415 } | |
440 | 9416 redisplay_device (d, 0); |
428 | 9417 |
442 | 9418 /* See the comment in Fredisplay_frame. */ |
9419 RESET_CHANGED_SET_FLAGS; | |
9420 | |
771 | 9421 return unbind_to (count); |
428 | 9422 } |
9423 | |
9424 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* | |
9425 Ensure that DEVICE's contents are correctly displayed. | |
9426 This differs from `redraw-device' in that it only redraws what needs to | |
9427 be updated, as opposed to unconditionally clearing and redrawing | |
9428 the device. | |
9429 DEVICE defaults to the selected device if omitted. | |
9430 Normally, redisplay is preempted as normal if input arrives. However, | |
9431 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9432 input and is guaranteed to proceed to completion. | |
853 | 9433 |
9434 Note: If you simply want everything redisplayed, the current idiom is | |
9435 `(sit-for 0)'. | |
428 | 9436 */ |
9437 (device, no_preempt)) | |
9438 { | |
9439 struct device *d = decode_device (device); | |
9440 int count = specpdl_depth (); | |
9441 | |
9442 if (!NILP (no_preempt)) | |
853 | 9443 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9444 |
440 | 9445 redisplay_device (d, 0); |
428 | 9446 |
442 | 9447 /* See the comment in Fredisplay_frame. */ |
9448 RESET_CHANGED_SET_FLAGS; | |
9449 | |
771 | 9450 return unbind_to (count); |
428 | 9451 } |
9452 | |
9453 /* Big lie. Big lie. This will force all modelines to be updated | |
9454 regardless if the all flag is set or not. It remains in existence | |
9455 solely for backwards compatibility. */ | |
9456 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /* | |
9457 Force the modeline of the current buffer to be redisplayed. | |
9458 With optional non-nil ALL, force redisplay of all modelines. | |
9459 */ | |
2286 | 9460 (UNUSED (all))) |
428 | 9461 { |
9462 MARK_MODELINE_CHANGED; | |
9463 return Qnil; | |
9464 } | |
9465 | |
9466 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /* | |
9467 Force an immediate update of the cursor on FRAME. | |
9468 FRAME defaults to the selected frame if omitted. | |
9469 */ | |
9470 (frame)) | |
9471 { | |
1279 | 9472 struct frame *f = decode_frame (frame); |
9473 | |
9474 if (!FRAME_STREAM_P (f)) | |
9475 redisplay_redraw_cursor (f, 1); | |
428 | 9476 return Qnil; |
9477 } | |
9478 | |
9479 | |
9480 /***************************************************************************/ | |
9481 /* */ | |
872 | 9482 /* Change flags */ |
428 | 9483 /* */ |
9484 /***************************************************************************/ | |
9485 | |
9486 static void | |
2286 | 9487 margin_width_changed_in_frame (Lisp_Object UNUSED (specifier), |
9488 struct frame *UNUSED (f), | |
9489 Lisp_Object UNUSED (oldval)) | |
428 | 9490 { |
9491 /* Nothing to be done? */ | |
9492 } | |
9493 | |
9494 int | |
2286 | 9495 redisplay_variable_changed (Lisp_Object UNUSED (sym), |
9496 Lisp_Object *UNUSED (val), | |
9497 Lisp_Object UNUSED (in_object), | |
9498 int UNUSED (flags)) | |
428 | 9499 { |
9500 /* #### clip_changed should really be renamed something like | |
9501 global_redisplay_change. */ | |
9502 MARK_CLIP_CHANGED; | |
9503 return 0; | |
9504 } | |
9505 | |
9506 /* This is called if the built-in glyphs have their properties | |
9507 changed. */ | |
9508 void | |
2286 | 9509 redisplay_glyph_changed (Lisp_Object UNUSED (glyph), |
9510 Lisp_Object UNUSED (property), Lisp_Object locale) | |
428 | 9511 { |
9512 if (WINDOWP (locale)) | |
9513 { | |
9514 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale)))); | |
9515 } | |
9516 else if (FRAMEP (locale)) | |
9517 { | |
9518 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale)); | |
9519 } | |
9520 else if (DEVICEP (locale)) | |
9521 { | |
9522 Lisp_Object frmcons; | |
9523 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale)) | |
9524 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9525 } | |
9526 else if (CONSOLEP (locale)) | |
9527 { | |
9528 Lisp_Object frmcons, devcons; | |
9529 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale)) | |
9530 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9531 } | |
9532 else /* global or buffer */ | |
9533 { | |
9534 Lisp_Object frmcons, devcons, concons; | |
9535 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
9536 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9537 } | |
9538 } | |
9539 | |
9540 static void | |
2286 | 9541 text_cursor_visible_p_changed (Lisp_Object UNUSED (specifier), |
9542 struct window *w, Lisp_Object UNUSED (oldval)) | |
428 | 9543 { |
9544 if (XFRAME (w->frame)->init_finished) | |
9545 Fforce_cursor_redisplay (w->frame); | |
9546 } | |
9547 | |
872 | 9548 void |
9549 mark_buffers_changed (void) | |
9550 { | |
9551 MARK_TYPE_CHANGED (buffers); | |
9552 } | |
9553 | |
9554 void | |
9555 mark_clip_changed (void) | |
9556 { | |
9557 MARK_TYPE_CHANGED (clip); | |
9558 } | |
9559 | |
9560 void | |
9561 mark_extents_changed (void) | |
9562 { | |
9563 MARK_TYPE_CHANGED (extents); | |
9564 } | |
9565 | |
9566 void | |
9567 mark_icon_changed (void) | |
9568 { | |
9569 MARK_TYPE_CHANGED (icon); | |
9570 } | |
9571 | |
9572 void | |
9573 mark_menubar_changed (void) | |
9574 { | |
9575 MARK_TYPE_CHANGED (menubar); | |
9576 } | |
9577 | |
9578 void | |
9579 mark_modeline_changed (void) | |
9580 { | |
9581 MARK_TYPE_CHANGED (modeline); | |
9582 } | |
9583 | |
9584 void | |
9585 mark_point_changed (void) | |
9586 { | |
9587 MARK_TYPE_CHANGED (point); | |
9588 } | |
9589 | |
9590 void | |
9591 mark_toolbar_changed (void) | |
9592 { | |
9593 MARK_TYPE_CHANGED (toolbar); | |
9594 } | |
9595 | |
9596 void | |
9597 mark_gutter_changed (void) | |
9598 { | |
9599 MARK_TYPE_CHANGED (gutter); | |
9600 } | |
9601 | |
9602 void | |
9603 mark_glyphs_changed (void) | |
9604 { | |
9605 MARK_TYPE_CHANGED (glyphs); | |
9606 } | |
9607 | |
9608 void | |
9609 mark_subwindows_changed (void) | |
9610 { | |
9611 MARK_TYPE_CHANGED (subwindows); | |
9612 } | |
9613 | |
9614 void | |
9615 mark_subwindows_state_changed (void) | |
9616 { | |
9617 MARK_TYPE_CHANGED (subwindows_state); | |
9618 } | |
9619 | |
428 | 9620 #ifdef MEMORY_USAGE_STATS |
9621 | |
9622 | |
9623 /***************************************************************************/ | |
9624 /* */ | |
9625 /* memory usage computation */ | |
9626 /* */ | |
9627 /***************************************************************************/ | |
9628 | |
9629 static int | |
9630 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats) | |
9631 { | |
9632 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
9633 } | |
9634 | |
9635 static int | |
9636 compute_display_block_dynarr_usage (display_block_dynarr *dyn, | |
9637 struct overhead_stats *ovstats) | |
9638 { | |
9639 int total, i; | |
9640 | |
9641 if (!dyn) | |
9642 return 0; | |
9643 | |
9644 total = Dynarr_memory_usage (dyn, ovstats); | |
9645 for (i = 0; i < Dynarr_largest (dyn); i++) | |
9646 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats); | |
9647 | |
9648 return total; | |
9649 } | |
9650 | |
9651 static int | |
9652 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn, | |
9653 struct overhead_stats *ovstats) | |
9654 { | |
9655 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
9656 } | |
9657 | |
9658 int | |
9659 compute_display_line_dynarr_usage (display_line_dynarr *dyn, | |
9660 struct overhead_stats *ovstats) | |
9661 { | |
9662 int total, i; | |
9663 | |
9664 if (!dyn) | |
9665 return 0; | |
9666 | |
9667 total = Dynarr_memory_usage (dyn, ovstats); | |
9668 for (i = 0; i < Dynarr_largest (dyn); i++) | |
9669 { | |
9670 struct display_line *dl = &Dynarr_at (dyn, i); | |
9671 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats); | |
9672 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats); | |
9673 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats); | |
9674 } | |
9675 | |
9676 return total; | |
9677 } | |
9678 | |
9679 int | |
9680 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn, | |
9681 struct overhead_stats *ovstats) | |
9682 { | |
9683 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
9684 } | |
9685 | |
9686 #endif /* MEMORY_USAGE_STATS */ | |
9687 | |
1204 | 9688 #ifdef ERROR_CHECK_DISPLAY |
9689 | |
800 | 9690 static int |
2286 | 9691 sledgehammer_check_redisplay_structs_1 (struct window *w, |
9692 void *UNUSED (closure)) | |
800 | 9693 { |
9694 int i, j; | |
9695 display_line_dynarr *dl; | |
9696 | |
9697 dl = window_display_lines (w, CURRENT_DISP); | |
4187 | 9698 |
800 | 9699 for (i = 0; i < Dynarr_largest (dl); i++) |
9700 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9701 assert (Dynarr_atp (dl, i)->display_blocks != | |
9702 Dynarr_atp (dl, j)->display_blocks); | |
9703 | |
9704 dl = window_display_lines (w, DESIRED_DISP); | |
9705 | |
9706 for (i = 0; i < Dynarr_largest (dl); i++) | |
9707 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9708 assert (Dynarr_atp (dl, i)->display_blocks != | |
9709 Dynarr_atp (dl, j)->display_blocks); | |
9710 | |
9711 return 0; | |
9712 } | |
9713 | |
9714 static void | |
9715 sledgehammer_check_redisplay_structs (void) | |
9716 { | |
9717 map_windows (0, sledgehammer_check_redisplay_structs_1, NULL); | |
9718 } | |
9719 | |
1204 | 9720 #endif /* ERROR_CHECK_DISPLAY */ |
9721 | |
428 | 9722 |
9723 /***************************************************************************/ | |
9724 /* */ | |
9725 /* initialization */ | |
9726 /* */ | |
9727 /***************************************************************************/ | |
9728 | |
9729 void | |
9730 init_redisplay (void) | |
9731 { | |
9732 disable_preemption = 0; | |
9733 preemption_count = 0; | |
9734 | |
9735 #ifndef PDUMP | |
9736 if (!initialized) | |
9737 #endif | |
9738 { | |
440 | 9739 if (!cmotion_display_lines) |
9740 cmotion_display_lines = Dynarr_new (display_line); | |
867 | 9741 if (!mode_spec_ibyte_string) |
9742 mode_spec_ibyte_string = Dynarr_new (Ibyte); | |
440 | 9743 if (!formatted_string_extent_dynarr) |
9744 formatted_string_extent_dynarr = Dynarr_new (EXTENT); | |
9745 if (!formatted_string_extent_start_dynarr) | |
9746 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); | |
9747 if (!formatted_string_extent_end_dynarr) | |
9748 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); | |
9749 if (!internal_cache) | |
9750 internal_cache = Dynarr_new (line_start_cache); | |
428 | 9751 } |
9752 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9753 if (!initialized) |
428 | 9754 return; |
9755 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9756 if (noninteractive) |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9757 { |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9758 Vinitial_device_type = Qstream; |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9759 return; |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9760 } |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9761 |
428 | 9762 /* If the user wants to use a window system, we shouldn't bother |
9763 initializing the terminal. This is especially important when the | |
9764 terminal is so dumb that emacs gives up before and doesn't bother | |
9765 using the window system. | |
9766 | |
9767 If the DISPLAY environment variable is set, try to use X, and die | |
9768 with an error message if that doesn't work. */ | |
9769 | |
9770 #ifdef HAVE_X_WINDOWS | |
9771 if (!strcmp (display_use, "x")) | |
9772 { | |
9773 /* Some stuff checks this way early. */ | |
9774 Vwindow_system = Qx; | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9775 Vinitial_device_type = Qx; |
428 | 9776 return; |
9777 } | |
9778 #endif /* HAVE_X_WINDOWS */ | |
9779 | |
462 | 9780 #ifdef HAVE_GTK |
9781 if (!strcmp (display_use, "gtk")) | |
9782 { | |
9783 Vwindow_system = Qgtk; | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9784 Vinitial_device_type = Qgtk; |
462 | 9785 return; |
9786 } | |
9787 #endif | |
9788 | |
428 | 9789 #ifdef HAVE_MS_WINDOWS |
9790 if (!strcmp (display_use, "mswindows")) | |
9791 { | |
9792 /* Some stuff checks this way early. */ | |
9793 Vwindow_system = Qmswindows; | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9794 Vinitial_device_type = Qmswindows; |
428 | 9795 return; |
9796 } | |
9797 #endif /* HAVE_MS_WINDOWS */ | |
9798 | |
9799 #ifdef HAVE_TTY | |
9800 /* If no window system has been specified, try to use the terminal. */ | |
9801 if (!isatty (0)) | |
9802 { | |
9803 stderr_out ("XEmacs: standard input is not a tty\n"); | |
9804 exit (1); | |
9805 } | |
9806 | |
9807 /* Look at the TERM variable */ | |
771 | 9808 if (!egetenv ("TERM")) |
428 | 9809 { |
9810 stderr_out ("Please set the environment variable TERM; see tset(1).\n"); | |
9811 exit (1); | |
9812 } | |
9813 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9814 Vinitial_device_type = Qtty; |
428 | 9815 return; |
9816 #else /* not HAVE_TTY */ | |
9817 /* No DISPLAY specified, and no TTY support. */ | |
9818 stderr_out ("XEmacs: Cannot open display.\n\ | |
9819 Please set the environmental variable DISPLAY to an appropriate value.\n"); | |
9820 exit (1); | |
9821 #endif | |
9822 /* Unreached. */ | |
9823 } | |
9824 | |
9825 void | |
9826 syms_of_redisplay (void) | |
9827 { | |
563 | 9828 DEFSYMBOL (Qcursor_in_echo_area); |
9829 DEFSYMBOL (Qdisplay_warning_buffer); | |
9830 DEFSYMBOL (Qbar_cursor); | |
9831 DEFSYMBOL (Qtop_bottom); | |
9832 DEFSYMBOL (Qbuffer_list_changed_hook); | |
428 | 9833 |
9834 DEFSUBR (Fredisplay_echo_area); | |
9835 DEFSUBR (Fredraw_frame); | |
9836 DEFSUBR (Fredisplay_frame); | |
9837 DEFSUBR (Fredraw_device); | |
9838 DEFSUBR (Fredisplay_device); | |
9839 DEFSUBR (Fredraw_modeline); | |
9840 DEFSUBR (Fforce_cursor_redisplay); | |
9841 } | |
9842 | |
9843 void | |
9844 vars_of_redisplay (void) | |
9845 { | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
9846 QSin_redisplay = build_defer_string ("(in redisplay)"); |
1292 | 9847 staticpro (&QSin_redisplay); |
428 | 9848 |
1318 | 9849 Vpost_redisplay_actions = Qnil; |
9850 staticpro (&Vpost_redisplay_actions); | |
9851 | |
428 | 9852 #if 0 |
9853 staticpro (&last_arrow_position); | |
9854 staticpro (&last_arrow_string); | |
9855 last_arrow_position = Qnil; | |
9856 last_arrow_string = Qnil; | |
9857 #endif /* 0 */ | |
9858 | |
9859 /* #### Probably temporary */ | |
9860 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* | |
9861 \(Temporary) Setting this will impact the performance of the internal | |
9862 line start cache. | |
9863 */ ); | |
9864 cache_adjustment = 2; | |
9865 | |
1268 | 9866 DEFVAR_INT ("maximum-preempts", &max_preempts /* |
9867 Maximum number of times redisplay can be preempted by user input. | |
9868 */ ); | |
9869 max_preempts = INIT_MAX_PREEMPTS; | |
9870 | |
428 | 9871 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /* |
9872 Minimum pixel height for clipped bottom display line. | |
9873 A clipped line shorter than this won't be displayed. | |
9874 */ , | |
9875 redisplay_variable_changed); | |
9876 vertical_clip = 5; | |
9877 | |
9878 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /* | |
9879 Minimum visible area for clipped glyphs at right boundary. | |
9880 Clipped glyphs shorter than this won't be displayed. | |
9881 Only pixmap glyph instances are currently allowed to be clipped. | |
9882 */ , | |
9883 redisplay_variable_changed); | |
9884 horizontal_clip = 5; | |
9885 | |
9886 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /* | |
9887 String displayed by modeline-format's "%m" specification. | |
9888 */ ); | |
9889 Vglobal_mode_string = Qnil; | |
9890 | |
9891 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /* | |
9892 Marker for where to display an arrow on top of the buffer text. | |
9893 This must be the beginning of a line in order to work. | |
9894 See also `overlay-arrow-string'. | |
9895 */ , | |
9896 redisplay_variable_changed); | |
9897 Voverlay_arrow_position = Qnil; | |
9898 | |
9899 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* | |
442 | 9900 String or glyph to display as an arrow. See also `overlay-arrow-position'. |
444 | 9901 \(Note that despite the name of this variable, it can be set to a glyph as |
442 | 9902 well as a string.) |
428 | 9903 */ , |
9904 redisplay_variable_changed); | |
9905 Voverlay_arrow_string = Qnil; | |
9906 | |
9907 DEFVAR_INT ("scroll-step", &scroll_step /* | |
9908 *The number of lines to try scrolling a window by when point moves out. | |
9909 If that fails to bring point back on frame, point is centered instead. | |
9910 If this is zero, point is always centered after it moves off screen. | |
9911 */ ); | |
9912 scroll_step = 0; | |
9913 | |
9914 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /* | |
9915 *Scroll up to this many lines, to bring point back on screen. | |
9916 */ ); | |
9917 scroll_conservatively = 0; | |
9918 | |
9919 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows", | |
9920 &truncate_partial_width_windows /* | |
9921 *Non-nil means truncate lines in all windows less than full frame wide. | |
9922 */ , | |
9923 redisplay_variable_changed); | |
9924 truncate_partial_width_windows = 1; | |
9925 | |
442 | 9926 DEFVAR_LISP ("visible-bell", &Vvisible_bell /* |
9927 *Non-nil substitutes a visual signal for the audible bell. | |
9928 | |
9929 Default behavior is to flash the whole screen. On some platforms, | |
9930 special effects are available using the following values: | |
9931 | |
3025 | 9932 `display' Flash the whole screen (ie, the default behavior). |
9933 `top-bottom' Flash only the top and bottom lines of the selected frame. | |
442 | 9934 |
9935 When effects are unavailable on a platform, the visual bell is the | |
9936 default, whole screen. (Currently only X supports any special effects.) | |
428 | 9937 */ ); |
442 | 9938 Vvisible_bell = Qnil; |
428 | 9939 |
9940 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* | |
9941 *Non-nil means no need to redraw entire frame after suspending. | |
9942 A non-nil value is useful if the terminal can automatically preserve | |
9943 Emacs's frame display when you reenter Emacs. | |
9944 It is up to you to set this variable if your terminal can do that. | |
9945 */ ); | |
9946 no_redraw_on_reenter = 0; | |
9947 | |
9948 DEFVAR_LISP ("window-system", &Vwindow_system /* | |
9949 A symbol naming the window-system under which Emacs is running, | |
9950 such as `x', or nil if emacs is running on an ordinary terminal. | |
9951 | |
9952 Do not use this variable, except for GNU Emacs compatibility, as it | |
9953 gives wrong values in a multi-device environment. Use `console-type' | |
9954 instead. | |
9955 */ ); | |
9956 Vwindow_system = Qnil; | |
9957 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9958 DEFVAR_CONST_LISP ("initial-device-type", &Vinitial_device_type /* |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9959 The type of the first XEmacs device to be created. |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9960 |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9961 This is constant; it's used by the command line handling code to communicate |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9962 to Lisp what type the initial device to be created should be. |
428 | 9963 */ ); |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9964 Vinitial_device_type = Qnil; |
428 | 9965 |
9966 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* | |
9967 Non-nil means put cursor in minibuffer, at end of any message there. | |
9968 */ ); | |
9969 cursor_in_echo_area = 0; | |
9970 | |
9971 /* #### Shouldn't this be generalized as follows: | |
9972 | |
9973 if nil, use block cursor. | |
9974 if a number, use a bar cursor of that width. | |
9975 Otherwise, use a 1-pixel bar cursor. | |
9976 | |
9977 #### Or better yet, this variable should be trashed entirely | |
9978 (use a Lisp-magic variable to maintain compatibility) | |
9979 and a specifier `cursor-shape' added, which allows a block | |
9980 cursor, a bar cursor, a flashing block or bar cursor, | |
9981 maybe a caret cursor, etc. */ | |
9982 | |
9983 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /* | |
448 | 9984 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. |
428 | 9985 */ ); |
9986 Vbar_cursor = Qnil; | |
9987 | |
442 | 9988 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* |
9989 Function or functions to call when a frame's buffer list has changed. | |
9990 This is called during redisplay, before redisplaying each frame. | |
9991 Functions on this hook are called with one argument, the frame. | |
9992 */ ); | |
9993 Vbuffer_list_changed_hook = Qnil; | |
9994 | |
428 | 9995 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* |
9996 Bump this to tell the C code to call `display-warning-buffer' | |
9997 at next redisplay. You should not normally change this; the function | |
9998 `display-warning' automatically does this at appropriate times. | |
9999 */ ); | |
10000 display_warning_tick = 0; | |
10001 | |
10002 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /* | |
10003 Non-nil means inhibit display of warning messages. | |
10004 You should *bind* this, not set it. Any pending warning messages | |
10005 will be displayed when the binding no longer applies. | |
10006 */ ); | |
10007 /* reset to 0 by startup.el after the splash screen has displayed. | |
10008 This way, the warnings don't obliterate the splash screen. */ | |
10009 inhibit_warning_display = 1; | |
10010 | |
10011 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /* | |
10012 *Non-nil means column display number starts at 1. | |
10013 */ ); | |
10014 column_number_start_at_one = 0; | |
10015 } | |
10016 | |
10017 void | |
10018 specifier_vars_of_redisplay (void) | |
10019 { | |
10020 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /* | |
10021 *Width of left margin. | |
10022 This is a specifier; use `set-specifier' to change it. | |
10023 */ ); | |
10024 Vleft_margin_width = Fmake_specifier (Qnatnum); | |
10025 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10026 set_specifier_caching (Vleft_margin_width, | |
438 | 10027 offsetof (struct window, left_margin_width), |
428 | 10028 some_window_value_changed, |
438 | 10029 offsetof (struct frame, left_margin_width), |
444 | 10030 margin_width_changed_in_frame, 0); |
428 | 10031 |
10032 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* | |
10033 *Width of right margin. | |
10034 This is a specifier; use `set-specifier' to change it. | |
10035 */ ); | |
10036 Vright_margin_width = Fmake_specifier (Qnatnum); | |
10037 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10038 set_specifier_caching (Vright_margin_width, | |
438 | 10039 offsetof (struct window, right_margin_width), |
428 | 10040 some_window_value_changed, |
438 | 10041 offsetof (struct frame, right_margin_width), |
444 | 10042 margin_width_changed_in_frame, 0); |
428 | 10043 |
10044 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* | |
10045 *Minimum ascent height of lines. | |
10046 This is a specifier; use `set-specifier' to change it. | |
10047 */ ); | |
10048 Vminimum_line_ascent = Fmake_specifier (Qnatnum); | |
10049 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); | |
10050 set_specifier_caching (Vminimum_line_ascent, | |
438 | 10051 offsetof (struct window, minimum_line_ascent), |
428 | 10052 some_window_value_changed, |
444 | 10053 0, 0, 0); |
428 | 10054 |
10055 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* | |
10056 *Minimum descent height of lines. | |
10057 This is a specifier; use `set-specifier' to change it. | |
10058 */ ); | |
10059 Vminimum_line_descent = Fmake_specifier (Qnatnum); | |
10060 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); | |
10061 set_specifier_caching (Vminimum_line_descent, | |
438 | 10062 offsetof (struct window, minimum_line_descent), |
428 | 10063 some_window_value_changed, |
444 | 10064 0, 0, 0); |
428 | 10065 |
10066 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* | |
10067 *Non-nil means use the left outside margin as extra whitespace when | |
3025 | 10068 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10069 This is a specifier; use `set-specifier' to change it. |
10070 */ ); | |
10071 Vuse_left_overflow = Fmake_specifier (Qboolean); | |
10072 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); | |
10073 set_specifier_caching (Vuse_left_overflow, | |
438 | 10074 offsetof (struct window, use_left_overflow), |
428 | 10075 some_window_value_changed, |
444 | 10076 0, 0, 0); |
428 | 10077 |
10078 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* | |
10079 *Non-nil means use the right outside margin as extra whitespace when | |
3025 | 10080 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10081 This is a specifier; use `set-specifier' to change it. |
10082 */ ); | |
10083 Vuse_right_overflow = Fmake_specifier (Qboolean); | |
10084 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); | |
10085 set_specifier_caching (Vuse_right_overflow, | |
438 | 10086 offsetof (struct window, use_right_overflow), |
428 | 10087 some_window_value_changed, |
444 | 10088 0, 0, 0); |
428 | 10089 |
10090 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* | |
10091 *Non-nil means the text cursor is visible (this is usually the case). | |
10092 This is a specifier; use `set-specifier' to change it. | |
10093 */ ); | |
10094 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); | |
10095 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); | |
10096 set_specifier_caching (Vtext_cursor_visible_p, | |
438 | 10097 offsetof (struct window, text_cursor_visible_p), |
428 | 10098 text_cursor_visible_p_changed, |
444 | 10099 0, 0, 0); |
428 | 10100 |
10101 } |