Mercurial > hg > xemacs-beta
annotate src/redisplay.c @ 4976:16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-04 Ben Wing <ben@xemacs.org>
* alloc.c (release_breathing_space):
* alloc.c (resize_string):
* alloc.c (sweep_lcrecords_1):
* alloc.c (SWEEP_FIXED_TYPE_BLOCK_1):
* alloc.c (ADDITIONAL_FREE_compiled_function):
* alloc.c (compact_string_chars):
* alloc.c (ADDITIONAL_FREE_string):
* alloc.c (sweep_strings):
* alloca.c (xemacs_c_alloca):
* alsaplay.c (alsa_play_sound_file):
* buffer.c (init_initial_directory):
* buffer.h:
* buffer.h (BUFFER_FREE):
* console-stream.c (stream_delete_console):
* console-tty.c (free_tty_console_struct):
* data.c (Fnumber_to_string):
* device-gtk.c (gtk_init_device):
* device-gtk.c (free_gtk_device_struct):
* device-gtk.c (gtk_delete_device):
* device-msw.c (mswindows_delete_device):
* device-msw.c (msprinter_delete_device):
* device-tty.c (free_tty_device_struct):
* device-tty.c (tty_delete_device):
* device-x.c (x_init_device):
* device-x.c (free_x_device_struct):
* device-x.c (x_delete_device):
* dialog-msw.c (handle_directory_dialog_box):
* dialog-x.c (dbox_descriptor_to_widget_value):
* dired-msw.c (Fmswindows_insert_directory):
* dired.c (free_user_cache):
* dired.c (user_name_completion_unwind):
* doc.c (unparesseuxify_doc_string):
* doc.c (Fsubstitute_command_keys):
* doprnt.c (emacs_doprnt_1):
* dumper.c (pdump_load_finish):
* dumper.c (pdump_file_free):
* dumper.c (pdump_file_unmap):
* dynarr.c:
* dynarr.c (Dynarr_free):
* editfns.c (uncache_home_directory):
* editfns.c (Fset_time_zone_rule):
* elhash.c:
* elhash.c (pdump_reorganize_hash_table):
* elhash.c (maphash_unwind):
* emacs.c (make_arg_list_1):
* emacs.c (free_argc_argv):
* emacs.c (sort_args):
* emacs.c (Frunning_temacs_p):
* emodules.c (attempt_module_delete):
* eval.c (free_pointer):
* event-Xt.c (unselect_filedesc):
* event-Xt.c (emacs_Xt_select_process):
* event-gtk.c (unselect_filedesc):
* event-gtk.c (dragndrop_data_received):
* event-msw.c (winsock_closer):
* event-msw.c (mswindows_dde_callback):
* event-msw.c (mswindows_wnd_proc):
* event-stream.c (finalize_command_builder):
* event-stream.c (free_command_builder):
* extents.c (free_gap_array):
* extents.c (free_extent_list):
* extents.c (free_soe):
* extents.c (extent_fragment_delete):
* extents.c (extent_priority_sort_function):
* file-coding.c (make_coding_system_1):
* file-coding.c (coding_finalizer):
* file-coding.c (set_coding_stream_coding_system):
* file-coding.c (chain_finalize_coding_stream_1):
* file-coding.c (chain_finalize):
* file-coding.c (free_detection_state):
* file-coding.c (coding_category_symbol_to_id):
* fileio.c:
* fileio.c (Ffile_name_directory):
* fileio.c (if):
* fileio.c (Ffile_symlink_p):
* filelock.c (FREE_LOCK_INFO):
* filelock.c (current_lock_owner):
* font-mgr.c (Ffc_name_unparse):
* font-mgr.c (Ffc_pattern_duplicate):
* frame-gtk.c (gtk_delete_frame):
* frame-msw.c (mswindows_delete_frame):
* frame-msw.c (msprinter_delete_frame):
* frame-x.c (x_cde_destroy_callback):
* frame-x.c (Fcde_start_drag_internal):
* frame-x.c (x_cde_transfer_callback):
* frame-x.c (x_delete_frame):
* frame.c (update_frame_title):
* frame.c (Fset_frame_pointer):
* gc.c (register_for_finalization):
* gccache-gtk.c (free_gc_cache):
* gccache-gtk.c (gc_cache_lookup):
* gccache-x.c (free_gc_cache):
* gccache-x.c (gc_cache_lookup):
* glyphs-eimage.c:
* glyphs-eimage.c (jpeg_instantiate_unwind):
* glyphs-eimage.c (gif_instantiate_unwind):
* glyphs-eimage.c (png_instantiate_unwind):
* glyphs-eimage.c (png_instantiate):
* glyphs-eimage.c (tiff_instantiate_unwind):
* glyphs-gtk.c (convert_EImage_to_GDKImage):
* glyphs-gtk.c (gtk_finalize_image_instance):
* glyphs-gtk.c (gtk_init_image_instance_from_eimage):
* glyphs-gtk.c (gtk_xpm_instantiate):
* glyphs-msw.c (convert_EImage_to_DIBitmap):
* glyphs-msw.c (mswindows_init_image_instance_from_eimage):
* glyphs-msw.c (mswindows_initialize_image_instance_mask):
* glyphs-msw.c (xpm_to_eimage):
* glyphs-msw.c (mswindows_xpm_instantiate):
* glyphs-msw.c (xbm_create_bitmap_from_data):
* glyphs-msw.c (mswindows_finalize_image_instance):
* glyphs-x.c (convert_EImage_to_XImage):
* glyphs-x.c (x_finalize_image_instance):
* glyphs-x.c (x_init_image_instance_from_eimage):
* glyphs-x.c (x_xpm_instantiate):
* gui-x.c (free_popup_widget_value_tree):
* hash.c (free_hash_table):
* hash.c (grow_hash_table):
* hash.c (pregrow_hash_table_if_necessary):
* imgproc.c (build_EImage_quantable):
* insdel.c (uninit_buffer_text):
* intl-win32.c (convert_multibyte_to_internal_malloc):
* intl.c:
* intl.c (Fset_current_locale):
* keymap.c:
* keymap.c (where_is_recursive_mapper):
* keymap.c (where_is_internal):
* lisp.h:
* lisp.h (xfree):
* lstream.c (Lstream_close):
* lstream.c (resizing_buffer_closer):
* mule-coding.c:
* mule-coding.c (iso2022_finalize_detection_state):
* nt.c:
* nt.c (mswindows_get_long_filename):
* nt.c (nt_get_resource):
* nt.c (init_mswindows_environment):
* nt.c (get_cached_volume_information):
* nt.c (mswindows_opendir):
* nt.c (mswindows_closedir):
* nt.c (mswindows_readdir):
* nt.c (mswindows_stat):
* nt.c (mswindows_getdcwd):
* nt.c (Fmswindows_long_file_name):
* ntplay.c (nt_play_sound_file):
* ntplay.c (play_sound_data_1):
* number-gmp.c (gmp_free):
* number-gmp.c (init_number_gmp):
* number-mp.c (bignum_to_string):
* number-mp.c (BIGNUM_TO_TYPE):
* number.c (bignum_print):
* number.c (bignum_convfree):
* number.c (ratio_print):
* number.c (bigfloat_print):
* number.c (bigfloat_finalize):
* objects-gtk.c (gtk_finalize_color_instance):
* objects-gtk.c (gtk_finalize_font_instance):
* objects-msw.c (mswindows_finalize_color_instance):
* objects-msw.c (mswindows_finalize_font_instance):
* objects-tty.c (tty_finalize_color_instance):
* objects-tty.c (tty_finalize_font_instance):
* objects-tty.c (tty_font_list):
* objects-x.c (x_finalize_color_instance):
* objects-x.c (x_finalize_font_instance):
* process.c:
* process.c (finalize_process):
* realpath.c:
* redisplay.c (add_propagation_runes):
* regex.c:
* regex.c (xfree):
* regex.c (REGEX_FREE_STACK):
* regex.c (FREE_STACK_RETURN):
* regex.c (regex_compile):
* regex.c (regexec):
* regex.c (regfree):
* scrollbar-gtk.c (gtk_free_scrollbar_instance):
* scrollbar-gtk.c (gtk_release_scrollbar_instance):
* scrollbar-msw.c (mswindows_free_scrollbar_instance):
* scrollbar-msw.c (unshow_that_mofo):
* scrollbar-x.c (x_free_scrollbar_instance):
* scrollbar-x.c (x_release_scrollbar_instance):
* select-gtk.c (emacs_gtk_selection_handle):
* select-msw.c (mswindows_own_selection):
* select-x.c:
* select-x.c (x_handle_selection_request):
* select-x.c (unexpect_property_change):
* select-x.c (x_handle_property_notify):
* select-x.c (receive_incremental_selection):
* select-x.c (x_get_window_property_as_lisp_data):
* select-x.c (Fx_get_cutbuffer_internal):
* specifier.c (finalize_specifier):
* syntax.c (uninit_buffer_syntax_cache):
* sysdep.c (qxe_allocating_getcwd):
* sysdep.c (qxe_lstat):
* sysdep.c (copy_in_passwd):
* sysdep.c (qxe_ctime):
* sysdep.c (closedir):
* sysdep.c (DIRSIZ):
* termcap.c (tgetent):
* termcap.c (tprint):
* tests.c (Ftest_data_format_conversion):
* text.c (new_dfc_convert_copy_data):
* text.h (eifree):
* text.h (eito_alloca):
* text.h (eito_external):
* toolbar-msw.c (mswindows_output_toolbar):
* ui-gtk.c (CONVERT_RETVAL):
* ui-gtk.c (__allocate_object_storage):
* unicode.c (free_from_unicode_table):
* unicode.c (free_to_unicode_table):
* unicode.c (free_charset_unicode_tables):
* win32.c (mswindows_read_link_1):
Rename: xfree(VAL, TYPE)->xfree(VAL)
Command used:
gr 'xfree *\((.*),.*\);' 'xfree (\1);' *.[ch]
Followed by grepping for 'xfree.*,' and fixing anything left.
Rationale: Having to specify the TYPE argument is annoying and
error-prone. It was originally put in to work around warnings
due to strict aliasing but years and years ago I rewrote it
in a way that doesn't use the TYPE argument at all and no one
has complained since then. (And anyway, XEmacs is far from
ever being in compliance with strict aliasing and would require
far-reaching changes to get that way.)
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Thu, 04 Feb 2010 07:28:14 -0600 |
parents | 5c89ceb69819 |
children | 9410323e4b0d d0c14ea98592 |
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); |
4970 | 1279 qxestrncpy (pb.data.p_string.str, pos, len); |
428 | 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) | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4970
diff
changeset
|
1689 xfree (pb->data.p_string.str); |
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) + | |
4970 | 4022 bytecount_to_charcount (str, qxestrlen (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 { |
4970 | 4457 const Ascbyte *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 | |
4968 | 5474 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
5475 because we initialized them at startup and the only way to reduce | |
5476 their number is through calling reset_face_cachels() or | |
5477 reset_glyph_cachels(), which as a side effect sets up a number of | |
5478 standard entries */ | |
5479 assert (Dynarr_length (w->face_cachels)); | |
5480 assert (Dynarr_length (w->glyph_cachels)); | |
5481 | |
5482 #if 0 | |
5483 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
5484 not needed */ | |
428 | 5485 /* Normally these get updated in redisplay_window but it is possible |
5486 for this function to get called from some other points where that | |
5487 update may not have occurred. This acts as a safety check. */ | |
5488 if (!Dynarr_length (w->face_cachels)) | |
5489 reset_face_cachels (w); | |
5490 if (!Dynarr_length (w->glyph_cachels)) | |
5491 reset_glyph_cachels (w); | |
4968 | 5492 #endif |
428 | 5493 |
5494 Fset_marker (w->start[type], make_int (start_pos), w->buffer); | |
5495 Fset_marker (w->pointm[type], make_int (point), w->buffer); | |
5496 w->last_point_x[type] = -1; | |
5497 w->last_point_y[type] = -1; | |
5498 | |
5499 /* Make sure a modeline is in the structs if needed. */ | |
5500 need_modeline = ensure_modeline_generated (w, type); | |
5501 | |
5502 /* Wait until here to set this so that the structs have a modeline | |
5503 generated in the case where one didn't exist. */ | |
5504 yend = WINDOW_TEXT_BOTTOM (w); | |
5505 | |
5506 bounds = calculate_display_line_boundaries (w, 0); | |
5507 | |
5508 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */ | |
5509 if (MINI_WINDOW_P (w) | |
5510 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt)) | |
5511 && !echo_area_active (f) | |
5512 && start_pos == BUF_BEGV (b)) | |
5513 { | |
5514 struct prop_block pb; | |
5515 Lisp_Object string; | |
5516 prop = Dynarr_new (prop_block); | |
5517 | |
5518 string = concat2(Vminibuf_preprompt, Vminibuf_prompt); | |
5519 pb.type = PROP_MINIBUF_PROMPT; | |
5520 pb.data.p_string.str = XSTRING_DATA(string); | |
5521 pb.data.p_string.len = XSTRING_LENGTH(string); | |
5522 Dynarr_add (prop, pb); | |
5523 } | |
5524 else | |
5525 prop = 0; | |
5526 | |
442 | 5527 /* When we are computing things for scrolling purposes, make |
5528 sure at least one line is always generated */ | |
5529 force = (type == CMOTION_DISP); | |
5530 | |
5531 /* Make sure this is set always */ | |
5532 /* Note the conversion at end */ | |
5533 w->window_end_pos[type] = start_pos; | |
5534 while (ypos < yend || force) | |
428 | 5535 { |
5536 struct display_line dl; | |
5537 struct display_line *dlp; | |
5538 int local; | |
851 | 5539 int pos_of_dlp = -1; |
428 | 5540 |
5541 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5542 { | |
851 | 5543 pos_of_dlp = Dynarr_length (dla); |
5544 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5545 local = 0; |
5546 } | |
5547 else | |
5548 { | |
4207 | 5549 DISPLAY_LINE_INIT (dl); |
428 | 5550 dlp = &dl; |
5551 local = 1; | |
5552 } | |
5553 | |
5554 dlp->bounds = bounds; | |
5555 dlp->offset = 0; | |
1318 | 5556 Dynarr_lock (dla); |
428 | 5557 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); |
1318 | 5558 Dynarr_unlock (dla); |
428 | 5559 |
5560 if (yclip > dlp->ascent) | |
5561 { | |
5562 /* this should never happen, but if it does just display the | |
5563 whole line */ | |
5564 yclip = 0; | |
5565 } | |
5566 | |
5567 dlp->ypos = (ypos + dlp->ascent) - yclip; | |
5568 ypos = dlp->ypos + dlp->descent; | |
5569 | |
5570 /* See if we've been asked to start midway through a line, for | |
4187 | 5571 partial display line scrolling. */ |
434 | 5572 if (yclip) |
428 | 5573 { |
5574 dlp->top_clip = yclip; | |
5575 yclip = 0; | |
5576 } | |
5577 else | |
5578 dlp->top_clip = 0; | |
5579 | |
5580 if (ypos > yend) | |
5581 { | |
5582 int visible_height = dlp->ascent + dlp->descent; | |
5583 | |
5584 dlp->clip = (ypos - yend); | |
5585 /* Although this seems strange we could have a single very | |
5586 tall line visible for which we need to account for both | |
5587 the top clip and the bottom clip. */ | |
5588 visible_height -= (dlp->clip + dlp->top_clip); | |
5589 | |
442 | 5590 if (visible_height < VERTICAL_CLIP (w, 1) && !force) |
428 | 5591 { |
5592 if (local) | |
5593 free_display_line (dlp); | |
5594 break; | |
5595 } | |
5596 } | |
5597 else | |
5598 dlp->clip = 0; | |
5599 | |
5600 if (dlp->cursor_elt != -1) | |
5601 { | |
5602 /* #### This check is steaming crap. Have to get things | |
4187 | 5603 fixed so when create_text_block hits EOB, we're done, |
5604 period. */ | |
428 | 5605 if (w->last_point_x[type] == -1) |
5606 { | |
5607 w->last_point_x[type] = dlp->cursor_elt; | |
5608 w->last_point_y[type] = Dynarr_length (dla); | |
5609 } | |
5610 else | |
5611 { | |
5612 /* #### This means that we've added a cursor at EOB | |
4187 | 5613 twice. Yuck oh yuck. */ |
1318 | 5614 struct display_block *db; |
5615 | |
5616 Dynarr_lock (dla); | |
5617 db = get_display_block_from_line (dlp, TEXT); | |
5618 Dynarr_unlock (dla); | |
428 | 5619 |
5620 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR; | |
5621 dlp->cursor_elt = -1; | |
5622 } | |
5623 } | |
5624 | |
5625 if (dlp->num_chars > w->max_line_len) | |
5626 w->max_line_len = dlp->num_chars; | |
5627 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5628 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
|
5629 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
|
5630 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
|
5631 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
|
5632 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5633 ABORT (); |
428 | 5634 |
5635 /* #### This isn't right, but it is close enough for now. */ | |
5636 w->window_end_pos[type] = start_pos; | |
5637 | |
5638 /* #### This type of check needs to be done down in the | |
5639 generate_display_line call. */ | |
5640 if (start_pos > BUF_ZV (b)) | |
5641 break; | |
442 | 5642 |
5643 force = 0; | |
428 | 5644 } |
5645 | |
5646 if (prop) | |
5647 Dynarr_free (prop); | |
5648 | |
5649 /* #### More not quite right, but close enough. */ | |
442 | 5650 /* Ben sez: apparently window_end_pos[] is measured |
428 | 5651 as the number of characters between the window end and the |
5652 end of the buffer? This seems rather weirdo. What's | |
442 | 5653 the justification for this? |
5654 | |
5655 JV sez: Because BUF_Z (b) would be a good initial value, however | |
5656 that can change. This representation allows initalizing with 0. | |
5657 */ | |
428 | 5658 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; |
5659 | |
5660 if (need_modeline) | |
5661 { | |
5662 /* We know that this is the right thing to use because we put it | |
4187 | 5663 there when we first started working in this function. */ |
4967 | 5664 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 5665 } |
2518 | 5666 |
5667 if (depth >= 0) | |
5668 exit_redisplay_critical_section (depth); | |
428 | 5669 } |
5670 | |
826 | 5671 #define REGEN_INC_FIND_START_END \ |
5672 do { \ | |
5673 /* Determine start and end of lines. */ \ | |
5674 if (!Dynarr_length (cdla)) \ | |
5675 return 0; \ | |
5676 else \ | |
5677 { \ | |
4967 | 5678 if (Dynarr_begin (cdla)->modeline && Dynarr_begin (ddla)->modeline) \ |
826 | 5679 { \ |
5680 dla_start = 1; \ | |
5681 } \ | |
4967 | 5682 else if (!Dynarr_begin (cdla)->modeline \ |
5683 && !Dynarr_begin (ddla)->modeline) \ | |
826 | 5684 { \ |
5685 dla_start = 0; \ | |
5686 } \ | |
5687 else \ | |
2500 | 5688 ABORT (); /* structs differ */ \ |
826 | 5689 \ |
5690 dla_end = Dynarr_length (cdla) - 1; \ | |
5691 } \ | |
5692 \ | |
5693 start_pos = (Dynarr_atp (cdla, dla_start)->charpos \ | |
5694 + Dynarr_atp (cdla, dla_start)->offset); \ | |
5695 /* If this isn't true, then startp has changed and we need to do a \ | |
5696 full regen. */ \ | |
5697 if (startp != start_pos) \ | |
5698 return 0; \ | |
5699 \ | |
5700 /* Point is outside the visible region so give up. */ \ | |
5701 if (pointm < start_pos) \ | |
5702 return 0; \ | |
5703 \ | |
428 | 5704 } while (0) |
5705 | |
5706 /* This attempts to incrementally update the display structures. It | |
5707 returns a boolean indicating success or failure. This function is | |
5708 very similar to regenerate_window_incrementally and is in fact only | |
5709 called from that function. However, because of the nature of the | |
5710 changes it deals with it sometimes makes different assumptions | |
5711 which can lead to success which are much more difficult to make | |
5712 when dealing with buffer changes. */ | |
5713 | |
5714 static int | |
665 | 5715 regenerate_window_extents_only_changed (struct window *w, Charbpos startp, |
5716 Charbpos pointm, | |
428 | 5717 Charcount beg_unchanged, |
5718 Charcount end_unchanged) | |
5719 { | |
5720 struct buffer *b = XBUFFER (w->buffer); | |
5721 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5722 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5723 | |
5724 int dla_start = 0; | |
5725 int dla_end, line; | |
5726 int first_line, last_line; | |
665 | 5727 Charbpos start_pos; |
428 | 5728 /* Don't define this in the loop where it is used because we |
5729 definitely want its value to survive between passes. */ | |
5730 prop_block_dynarr *prop = NULL; | |
5731 | |
5732 /* If we don't have any buffer change recorded but the modiff flag has | |
5733 been incremented, then fail. I'm not sure of the exact circumstances | |
5734 under which this can happen, but I believe that it is probably a | |
5735 reasonable happening. */ | |
5736 if (!point_visible (w, pointm, CURRENT_DISP) | |
5737 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)) | |
5738 return 0; | |
5739 | |
5740 /* If the cursor is moved we attempt to update it. If we succeed we | |
5741 go ahead and proceed with the optimization attempt. */ | |
5742 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5743 || pointm != marker_position (w->last_point[CURRENT_DISP])) | |
5744 { | |
5745 struct frame *f = XFRAME (w->frame); | |
5746 struct device *d = XDEVICE (f->device); | |
5747 struct frame *sel_f = device_selected_frame (d); | |
5748 int success = 0; | |
5749 | |
5750 if (w->last_point_x[CURRENT_DISP] != -1 | |
5751 && w->last_point_y[CURRENT_DISP] != -1) | |
5752 { | |
5753 | |
5754 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w))) | |
5755 { | |
5756 /* Always regenerate the modeline in case it is | |
4187 | 5757 displaying the current line or column. */ |
428 | 5758 regenerate_modeline (w); |
5759 success = 1; | |
5760 } | |
5761 } | |
5762 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f))) | |
5763 { | |
5764 if (f->modeline_changed) | |
5765 regenerate_modeline (w); | |
5766 success = 1; | |
5767 } | |
5768 | |
5769 if (!success) | |
5770 return 0; | |
5771 } | |
5772 | |
5773 if (beg_unchanged == -1 && end_unchanged == -1) | |
5774 return 1; | |
5775 | |
5776 /* assert: There are no buffer modifications or they are all below the | |
5777 visible region. We assume that regenerate_window_incrementally has | |
5778 not called us unless this is true. */ | |
5779 | |
5780 REGEN_INC_FIND_START_END; | |
5781 | |
5782 /* If the changed are starts before the visible area, give up. */ | |
5783 if (beg_unchanged < startp) | |
5784 return 0; | |
5785 | |
5786 /* Find what display line the extent changes first affect. */ | |
5787 line = dla_start; | |
5788 while (line <= dla_end) | |
5789 { | |
5790 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5791 Charbpos lstart = dl->charpos + dl->offset; |
5792 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5793 |
5794 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5795 break; | |
5796 | |
5797 line++; | |
5798 } | |
5799 | |
5800 /* If the changes are below the visible area then if point hasn't | |
5801 moved return success otherwise fail in order to be safe. */ | |
5802 if (line > dla_end) | |
5803 { | |
5804 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5805 && pointm == marker_position (w->last_point[CURRENT_DISP])) | |
5806 return 1; | |
5807 else | |
5808 return 0; | |
5809 } | |
5810 | |
5811 /* At this point we know what line the changes first affect. We now | |
5812 begin redrawing lines as long as we are still in the affected | |
5813 region and the line's size and positioning don't change. | |
5814 Otherwise we fail. If we fail we will have altered the desired | |
5815 structs which could lead to an assertion failure. However, if we | |
5816 fail the next thing that is going to happen is a full regen so we | |
5817 will actually end up being safe. */ | |
5818 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
5819 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
5820 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
5821 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
5822 | |
5823 first_line = last_line = line; | |
5824 while (line <= dla_end) | |
5825 { | |
2286 | 5826 Charbpos old_start, old_end; |
428 | 5827 struct display_line *cdl = Dynarr_atp (cdla, line); |
5828 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5829 struct display_block *db; | |
5830 int initial_size; | |
5831 | |
826 | 5832 assert (cdl->charpos == ddl->charpos); |
5833 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5834 assert (cdl->offset == ddl->offset); |
5835 | |
5836 db = get_display_block_from_line (ddl, TEXT); | |
5837 initial_size = Dynarr_length (db->runes); | |
826 | 5838 old_start = ddl->charpos + ddl->offset; |
5839 old_end = ddl->end_charpos + ddl->offset; | |
428 | 5840 |
5841 /* If this is the first line being updated and it used | |
4187 | 5842 propagation data, fail. Otherwise we'll be okay because |
5843 we'll have the necessary propagation data. */ | |
428 | 5844 if (line == first_line && ddl->used_prop_data) |
5845 return 0; | |
5846 | |
2286 | 5847 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
5848 &prop, DESIRED_DISP); | |
428 | 5849 ddl->offset = 0; |
5850 | |
5851 /* #### If there is propagated stuff the fail. We could | |
4187 | 5852 probably actually deal with this if the line had propagated |
5853 information when originally created by a full | |
5854 regeneration. */ | |
428 | 5855 if (prop) |
5856 { | |
5857 Dynarr_free (prop); | |
5858 return 0; | |
5859 } | |
5860 | |
5861 /* If any line position parameters have changed or a | |
4187 | 5862 cursor has disappeared or disappeared, fail. */ |
428 | 5863 db = get_display_block_from_line (ddl, TEXT); |
5864 if (cdl->ypos != ddl->ypos | |
5865 || cdl->ascent != ddl->ascent | |
5866 || cdl->descent != ddl->descent | |
5867 || cdl->top_clip != ddl->top_clip | |
5868 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
5869 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
826 | 5870 || old_start != ddl->charpos |
5871 || old_end != ddl->end_charpos | |
428 | 5872 || initial_size != Dynarr_length (db->runes)) |
5873 { | |
5874 return 0; | |
5875 } | |
5876 | |
5877 if (ddl->cursor_elt != -1) | |
5878 { | |
5879 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
5880 w->last_point_y[DESIRED_DISP] = line; | |
5881 } | |
5882 | |
5883 last_line = line; | |
5884 | |
5885 /* If the extent changes end on the line we just updated then | |
4187 | 5886 we're done. Otherwise go on to the next line. */ |
826 | 5887 if (end_unchanged <= ddl->end_charpos) |
428 | 5888 break; |
5889 else | |
5890 line++; | |
5891 } | |
5892 | |
5893 redisplay_update_line (w, first_line, last_line, 1); | |
5894 return 1; | |
5895 } | |
5896 | |
5897 /* Attempt to update the display data structures based on knowledge of | |
5898 the changed region in the buffer. Returns a boolean indicating | |
5899 success or failure. If this function returns a failure then a | |
5900 regenerate_window _must_ be performed next in order to maintain | |
5901 invariants located here. */ | |
5902 | |
5903 static int | |
665 | 5904 regenerate_window_incrementally (struct window *w, Charbpos startp, |
5905 Charbpos pointm) | |
428 | 5906 { |
5907 struct buffer *b = XBUFFER (w->buffer); | |
5908 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5909 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5910 Charcount beg_unchanged, end_unchanged; | |
5911 Charcount extent_beg_unchanged, extent_end_unchanged; | |
5912 | |
5913 int dla_start = 0; | |
5914 int dla_end, line; | |
665 | 5915 Charbpos start_pos; |
428 | 5916 |
5917 /* If this function is called, the current and desired structures | |
5918 had better be identical. If they are not, then that is a bug. */ | |
5919 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
5920 | |
5921 /* We don't handle minibuffer windows yet. The minibuffer prompt | |
5922 screws us up. */ | |
5923 if (MINI_WINDOW_P (w)) | |
5924 return 0; | |
5925 | |
5926 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b); | |
5927 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1 | |
5928 ? -1 | |
5929 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b)); | |
5930 | |
5931 /* If nothing has changed in the buffer, then make sure point is ok | |
5932 and succeed. */ | |
5933 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1) | |
5934 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5935 extent_beg_unchanged, | |
5936 extent_end_unchanged); | |
5937 | |
5938 /* We can't deal with deleted newlines. */ | |
5939 if (BUF_NEWLINE_WAS_DELETED (b)) | |
5940 return 0; | |
5941 | |
5942 beg_unchanged = BUF_BEGIN_UNCHANGED (b); | |
5943 end_unchanged = (BUF_END_UNCHANGED (b) == -1 | |
5944 ? -1 | |
5945 : BUF_Z (b) - BUF_END_UNCHANGED (b)); | |
5946 | |
5947 REGEN_INC_FIND_START_END; | |
5948 | |
5949 /* If the changed area starts before the visible area, give up. */ | |
5950 if (beg_unchanged < startp) | |
5951 return 0; | |
5952 | |
5953 /* Find what display line the buffer changes first affect. */ | |
5954 line = dla_start; | |
5955 while (line <= dla_end) | |
5956 { | |
5957 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5958 Charbpos lstart = dl->charpos + dl->offset; |
5959 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5960 |
5961 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5962 break; | |
5963 | |
5964 line++; | |
5965 } | |
5966 | |
5967 /* If the changes are below the visible area then if point hasn't | |
5968 moved return success otherwise fail in order to be safe. */ | |
5969 if (line > dla_end) | |
5970 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5971 extent_beg_unchanged, | |
5972 extent_end_unchanged); | |
5973 else | |
5974 /* At this point we know what line the changes first affect. We | |
5975 now redraw that line. If the changes are contained within it | |
5976 we are going to succeed and can update just that one line. | |
5977 Otherwise we fail. If we fail we will have altered the desired | |
5978 structs which could lead to an assertion failure. However, if | |
5979 we fail the next thing that is going to happen is a full regen | |
5980 so we will actually end up being safe. */ | |
5981 { | |
5982 prop_block_dynarr *prop = NULL; | |
5983 struct display_line *cdl = Dynarr_atp (cdla, line); | |
5984 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5985 | |
826 | 5986 assert (cdl->charpos == ddl->charpos); |
5987 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5988 assert (cdl->offset == ddl->offset); |
5989 | |
442 | 5990 /* If the line continues to next display line, fail. */ |
5991 if (ddl->line_continuation) | |
5992 return 0; | |
428 | 5993 |
5994 /* If the line was generated using propagation data, fail. */ | |
5995 if (ddl->used_prop_data) | |
5996 return 0; | |
5997 | |
2286 | 5998 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
5999 &prop, DESIRED_DISP); | |
428 | 6000 ddl->offset = 0; |
6001 | |
6002 /* If there is propagated stuff then it is pretty much a | |
4187 | 6003 guarantee that more than just the one line is affected. */ |
428 | 6004 if (prop) |
6005 { | |
6006 Dynarr_free (prop); | |
6007 return 0; | |
6008 } | |
6009 | |
442 | 6010 /* If the line continues to next display line, fail. */ |
6011 if (ddl->line_continuation) | |
6012 return 0; | |
428 | 6013 |
6014 /* If any line position parameters have changed or a | |
4187 | 6015 cursor has disappeared or disappeared, fail. */ |
428 | 6016 if (cdl->ypos != ddl->ypos |
6017 || cdl->ascent != ddl->ascent | |
6018 || cdl->descent != ddl->descent | |
6019 || cdl->top_clip != ddl->top_clip | |
6020 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
6021 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) | |
6022 { | |
6023 return 0; | |
6024 } | |
6025 | |
6026 /* If the changed area also ends on this line, then we may be in | |
4187 | 6027 business. Update everything and return success. */ |
826 | 6028 if (end_unchanged >= ddl->charpos && end_unchanged <= ddl->end_charpos) |
428 | 6029 { |
6030 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
6031 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
6032 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), | |
6033 w->buffer); | |
6034 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), | |
6035 w->buffer); | |
6036 | |
6037 if (ddl->cursor_elt != -1) | |
6038 { | |
6039 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
6040 w->last_point_y[DESIRED_DISP] = line; | |
6041 } | |
6042 | |
6043 redisplay_update_line (w, line, line, 1); | |
6044 regenerate_modeline (w); | |
6045 | |
6046 /* #### For now we just flush the cache until this has been | |
4187 | 6047 tested. After that is done, this should correct the |
6048 cache directly. */ | |
428 | 6049 Dynarr_reset (w->line_start_cache); |
6050 | |
6051 /* Adjust the extent changed boundaries to remove any | |
4187 | 6052 overlap with the buffer changes since we've just |
6053 successfully updated that area. */ | |
428 | 6054 if (extent_beg_unchanged != -1 |
6055 && extent_beg_unchanged >= beg_unchanged | |
6056 && extent_beg_unchanged < end_unchanged) | |
6057 extent_beg_unchanged = end_unchanged; | |
6058 | |
6059 if (extent_end_unchanged != -1 | |
6060 && extent_end_unchanged >= beg_unchanged | |
6061 && extent_end_unchanged < end_unchanged) | |
6062 extent_end_unchanged = beg_unchanged - 1; | |
6063 | |
6064 if (extent_end_unchanged <= extent_beg_unchanged) | |
6065 extent_beg_unchanged = extent_end_unchanged = -1; | |
6066 | |
6067 /* This could lead to odd results if it fails, but since the | |
4187 | 6068 buffer changes update succeeded this probably will to. |
6069 We already know that the extent changes start at or after | |
6070 the line because we checked before entering the loop. */ | |
428 | 6071 if (extent_beg_unchanged != -1 |
6072 && extent_end_unchanged != -1 | |
826 | 6073 && ((extent_beg_unchanged < ddl->charpos) |
6074 || (extent_end_unchanged > ddl->end_charpos))) | |
428 | 6075 return regenerate_window_extents_only_changed (w, startp, pointm, |
6076 extent_beg_unchanged, | |
6077 extent_end_unchanged); | |
6078 else | |
6079 return 1; | |
6080 } | |
6081 } | |
6082 | |
6083 /* Oh, well. */ | |
6084 return 0; | |
6085 } | |
6086 | |
6087 /* Given a window and a point, update the given display lines such | |
6088 that point is displayed in the middle of the window. | |
6089 Return the window's new start position. */ | |
6090 | |
665 | 6091 static Charbpos |
6092 regenerate_window_point_center (struct window *w, Charbpos point, int type) | |
428 | 6093 { |
665 | 6094 Charbpos startp; |
428 | 6095 |
6096 /* We need to make sure that the modeline is generated so that the | |
6097 window height can be calculated correctly. */ | |
6098 ensure_modeline_generated (w, type); | |
6099 | |
6100 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w)); | |
6101 regenerate_window (w, startp, point, type); | |
6102 Fset_marker (w->start[type], make_int (startp), w->buffer); | |
6103 | |
6104 return startp; | |
6105 } | |
6106 | |
6107 /* Given a window and a set of display lines, return a boolean | |
6108 indicating whether the given point is contained within. */ | |
6109 | |
6110 static int | |
665 | 6111 point_visible (struct window *w, Charbpos point, int type) |
428 | 6112 { |
6113 struct buffer *b = XBUFFER (w->buffer); | |
6114 display_line_dynarr *dla = window_display_lines (w, type); | |
6115 int first_line; | |
6116 | |
4967 | 6117 if (Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
428 | 6118 first_line = 1; |
6119 else | |
6120 first_line = 0; | |
6121 | |
6122 if (Dynarr_length (dla) > first_line) | |
6123 { | |
665 | 6124 Charbpos start, end; |
428 | 6125 struct display_line *dl = Dynarr_atp (dla, first_line); |
6126 | |
826 | 6127 start = dl->charpos; |
428 | 6128 end = BUF_Z (b) - w->window_end_pos[type] - 1; |
6129 | |
6130 if (point >= start && point <= end) | |
6131 { | |
6132 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines) | |
6133 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
6134 dl = Dynarr_lastp (dla); |
428 | 6135 |
826 | 6136 if (point >= (dl->charpos + dl->offset) |
6137 && point <= (dl->end_charpos + dl->offset)) | |
428 | 6138 return !dl->clip; |
6139 else | |
6140 return 1; | |
6141 } | |
6142 else | |
6143 return 1; | |
6144 } | |
6145 else | |
6146 return 0; | |
6147 } | |
6148 else | |
6149 return 0; | |
6150 } | |
6151 | |
6152 /* Return pixel position the middle of the window, not including the | |
6153 modeline and any potential horizontal scrollbar. */ | |
6154 | |
6155 int | |
6156 window_half_pixpos (struct window *w) | |
6157 { | |
6158 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1); | |
6159 } | |
6160 | |
6161 /* Return the display line which is currently in the middle of the | |
6162 window W for display lines TYPE. */ | |
6163 | |
6164 int | |
665 | 6165 line_at_center (struct window *w, int type, Charbpos start, Charbpos point) |
428 | 6166 { |
6167 display_line_dynarr *dla; | |
6168 int half; | |
6169 int elt; | |
6170 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1); | |
6171 | |
6172 if (type == CMOTION_DISP) | |
6173 regenerate_window (w, start, point, type); | |
6174 | |
6175 dla = window_display_lines (w, type); | |
6176 half = window_half_pixpos (w); | |
6177 | |
6178 for (elt = first_elt; elt < Dynarr_length (dla); elt++) | |
6179 { | |
6180 struct display_line *dl = Dynarr_atp (dla, elt); | |
6181 int line_bot = dl->ypos + dl->descent; | |
6182 | |
6183 if (line_bot > half) | |
6184 return elt; | |
6185 } | |
6186 | |
6187 /* We may not have a line at the middle if the end of the buffer is | |
6188 being displayed. */ | |
6189 return -1; | |
6190 } | |
6191 | |
6192 /* Return a value for point that would place it at the beginning of | |
6193 the line which is in the middle of the window. */ | |
6194 | |
665 | 6195 Charbpos |
6196 point_at_center (struct window *w, int type, Charbpos start, Charbpos point) | |
428 | 6197 { |
6198 /* line_at_center will regenerate the display structures, if necessary. */ | |
6199 int line = line_at_center (w, type, start, point); | |
6200 | |
6201 if (line == -1) | |
6202 return BUF_ZV (XBUFFER (w->buffer)); | |
6203 else | |
6204 { | |
6205 display_line_dynarr *dla = window_display_lines (w, type); | |
6206 struct display_line *dl = Dynarr_atp (dla, line); | |
6207 | |
826 | 6208 return dl->charpos; |
428 | 6209 } |
6210 } | |
6211 | |
6212 /* For a given window, ensure that the current visual representation | |
6213 is accurate. */ | |
6214 | |
6215 static void | |
6216 redisplay_window (Lisp_Object window, int skip_selected) | |
6217 { | |
6218 struct window *w = XWINDOW (window); | |
6219 struct frame *f = XFRAME (w->frame); | |
6220 struct device *d = XDEVICE (f->device); | |
6221 Lisp_Object old_buffer = w->buffer; | |
6222 Lisp_Object the_buffer = w->buffer; | |
6223 struct buffer *b; | |
6224 int echo_active = 0; | |
6225 int startp = 1; | |
6226 int pointm; | |
6227 int old_startp = 1; | |
6228 int old_pointm = 1; | |
6229 int selected_in_its_frame; | |
6230 int selected_globally; | |
6231 int skip_output = 0; | |
6232 int truncation_changed; | |
6233 int inactive_minibuffer = | |
6234 (MINI_WINDOW_P (w) && | |
6235 (f != device_selected_frame (d)) && | |
6236 !is_surrogate_for_selected_frame (f)); | |
6237 | |
6238 /* #### In the new world this function actually does a bunch of | |
6239 optimizations such as buffer-based scrolling, but none of that is | |
6240 implemented yet. */ | |
6241 | |
6242 /* If this is a combination window, do its children; that's all. | |
6243 The selected window is always a leaf so we don't check for | |
6244 skip_selected here. */ | |
6245 if (!NILP (w->vchild)) | |
6246 { | |
6247 redisplay_windows (w->vchild, skip_selected); | |
6248 return; | |
6249 } | |
6250 if (!NILP (w->hchild)) | |
6251 { | |
6252 redisplay_windows (w->hchild, skip_selected); | |
6253 return; | |
6254 } | |
6255 | |
6256 /* Is this window the selected window on its frame? */ | |
6257 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f))); | |
6258 selected_globally = | |
6259 selected_in_its_frame && | |
6260 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
6261 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d && | |
6262 XFRAME(DEVICE_SELECTED_FRAME(d)) == f; | |
6263 if (skip_selected && selected_in_its_frame) | |
6264 return; | |
6265 | |
6266 /* It is possible that the window is not fully initialized yet. */ | |
6267 if (NILP (w->buffer)) | |
6268 return; | |
6269 | |
6270 if (MINI_WINDOW_P (w) && echo_area_active (f)) | |
6271 { | |
6272 w->buffer = the_buffer = Vecho_area_buffer; | |
6273 echo_active = 1; | |
6274 } | |
6275 | |
6276 b = XBUFFER (w->buffer); | |
6277 | |
6278 if (echo_active) | |
6279 { | |
6280 old_pointm = selected_globally | |
4187 | 6281 ? BUF_PT (b) |
6282 : marker_position (w->pointm[CURRENT_DISP]); | |
428 | 6283 pointm = 1; |
6284 } | |
6285 else | |
6286 { | |
6287 if (selected_globally) | |
6288 { | |
6289 pointm = BUF_PT (b); | |
6290 } | |
6291 else | |
6292 { | |
6293 pointm = marker_position (w->pointm[CURRENT_DISP]); | |
6294 | |
6295 if (pointm < BUF_BEGV (b)) | |
6296 pointm = BUF_BEGV (b); | |
6297 else if (pointm > BUF_ZV (b)) | |
6298 pointm = BUF_ZV (b); | |
6299 } | |
6300 } | |
6301 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); | |
6302 | |
4968 | 6303 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
6304 because we initialized them at startup and the only way to reduce | |
6305 their number is through calling reset_face_cachels() or | |
6306 reset_glyph_cachels(), which as a side effect sets up a number of | |
6307 standard entries */ | |
6308 assert (Dynarr_length (w->face_cachels)); | |
6309 assert (Dynarr_length (w->glyph_cachels)); | |
6310 | |
428 | 6311 /* If the buffer has changed we have to invalidate all of our face |
6312 cache elements. */ | |
6313 if ((!echo_active && b != window_display_buffer (w)) | |
4968 | 6314 #if 0 |
6315 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
6316 not needed */ | |
428 | 6317 || !Dynarr_length (w->face_cachels) |
4968 | 6318 #endif |
428 | 6319 || f->faces_changed) |
6320 reset_face_cachels (w); | |
6321 else | |
6322 mark_face_cachels_as_not_updated (w); | |
6323 | |
6324 /* Ditto the glyph cache elements, although we do *not* invalidate | |
6325 the cache purely because glyphs have changed - this is now | |
6326 handled by the dirty flag.*/ | |
6327 if ((!echo_active && b != window_display_buffer (w)) | |
4968 | 6328 #if 0 |
6329 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
6330 not needed */ | |
6331 || !Dynarr_length (w->glyph_cachels) | |
6332 #endif | |
6333 || f->faces_changed) | |
428 | 6334 reset_glyph_cachels (w); |
6335 else | |
6336 mark_glyph_cachels_as_not_updated (w); | |
6337 | |
6338 /* If the marker's buffer is not the window's buffer, then we need | |
6339 to find a new starting position. */ | |
6340 if (!MINI_WINDOW_P (w) | |
6341 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer)) | |
6342 { | |
6343 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6344 | |
6345 goto regeneration_done; | |
6346 } | |
6347 | |
6348 if (echo_active) | |
6349 { | |
6350 old_startp = marker_position (w->start[CURRENT_DISP]); | |
6351 startp = 1; | |
6352 } | |
6353 else | |
6354 { | |
6355 startp = marker_position (w->start[CURRENT_DISP]); | |
6356 if (startp < BUF_BEGV (b)) | |
6357 startp = BUF_BEGV (b); | |
6358 else if (startp > BUF_ZV (b)) | |
6359 startp = BUF_ZV (b); | |
6360 } | |
6361 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer); | |
6362 | |
6363 truncation_changed = (find_window_mirror (w)->truncate_win != | |
647 | 6364 (unsigned int) window_truncation_on (w)); |
428 | 6365 |
6366 /* If w->force_start is set, then some function set w->start and we | |
6367 should display from there and change point, if necessary, to | |
6368 ensure that it is visible. */ | |
6369 if (w->force_start || inactive_minibuffer) | |
6370 { | |
6371 w->force_start = 0; | |
6372 w->last_modified[DESIRED_DISP] = Qzero; | |
6373 w->last_facechange[DESIRED_DISP] = Qzero; | |
6374 | |
6375 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6376 | |
6377 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer) | |
6378 { | |
6379 pointm = point_at_center (w, DESIRED_DISP, 0, 0); | |
6380 | |
6381 if (selected_globally) | |
6382 BUF_SET_PT (b, pointm); | |
6383 | |
6384 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), | |
6385 the_buffer); | |
6386 | |
6387 /* #### BUFU amounts of overkill just to get the cursor | |
4187 | 6388 location marked properly. FIX ME FIX ME FIX ME */ |
428 | 6389 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6390 } | |
6391 | |
6392 goto regeneration_done; | |
6393 } | |
6394 | |
6395 /* If nothing has changed since the last redisplay, then we just | |
6396 need to make sure that point is still visible. */ | |
6397 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) | |
6398 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b) | |
6399 && pointm >= startp | |
6400 /* This check is to make sure we restore the minibuffer after a | |
4187 | 6401 temporary change to the echo area. */ |
428 | 6402 && !(MINI_WINDOW_P (w) && f->buffers_changed) |
6403 && !f->frame_changed | |
6404 && !truncation_changed | |
442 | 6405 /* check whether start is really at the beginning of a line GE */ |
428 | 6406 && (!w->start_at_line_beg || beginning_of_line_p (b, startp)) |
6407 ) | |
6408 { | |
6409 /* Check if the cursor has actually moved. */ | |
6410 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
6411 && pointm == marker_position (w->last_point[CURRENT_DISP]) | |
6412 && selected_globally | |
6413 && !w->windows_changed | |
6414 && !f->clip_changed | |
6415 && !f->extents_changed | |
6416 && !f->faces_changed | |
6417 && !f->glyphs_changed | |
6418 && !f->subwindows_changed | |
442 | 6419 /* && !f->subwindows_state_changed*/ |
428 | 6420 && !f->point_changed |
6421 && !f->windows_structure_changed) | |
6422 { | |
6423 /* If not, we're done. */ | |
6424 if (f->modeline_changed) | |
6425 regenerate_modeline (w); | |
6426 | |
6427 skip_output = 1; | |
6428 goto regeneration_done; | |
6429 } | |
6430 else | |
6431 { | |
6432 /* If the new point is visible in the redisplay structures, | |
4187 | 6433 then let the output update routines handle it, otherwise |
6434 do things the hard way. */ | |
428 | 6435 if (!w->windows_changed |
6436 && !f->clip_changed | |
6437 && !f->extents_changed | |
6438 && !f->faces_changed | |
6439 && !f->glyphs_changed | |
6440 && !f->subwindows_changed | |
442 | 6441 /* && !f->subwindows_state_changed*/ |
428 | 6442 && !f->windows_structure_changed) |
6443 { | |
6444 if (point_visible (w, pointm, CURRENT_DISP) | |
6445 && w->last_point_x[CURRENT_DISP] != -1 | |
6446 && w->last_point_y[CURRENT_DISP] != -1) | |
6447 { | |
6448 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f))) | |
6449 { | |
6450 /* Always regenerate in case it is displaying | |
4187 | 6451 the current line or column. */ |
428 | 6452 regenerate_modeline (w); |
6453 | |
6454 skip_output = 1; | |
6455 goto regeneration_done; | |
6456 } | |
6457 } | |
6458 else if (!selected_in_its_frame && !f->point_changed) | |
6459 { | |
6460 if (f->modeline_changed) | |
6461 regenerate_modeline (w); | |
6462 | |
6463 skip_output = 1; | |
6464 goto regeneration_done; | |
6465 } | |
6466 } | |
6467 | |
6468 /* If we weren't able to take the shortcut method, then use | |
4187 | 6469 the brute force method. */ |
428 | 6470 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6471 | |
6472 if (point_visible (w, pointm, DESIRED_DISP)) | |
6473 goto regeneration_done; | |
6474 } | |
6475 } | |
6476 | |
6477 /* Check if the starting point is no longer at the beginning of a | |
6478 line, in which case find a new starting point. We also recenter | |
6479 if our start position is equal to point-max. Otherwise we'll end | |
6480 up with a blank window. */ | |
6481 else if (((w->start_at_line_beg || MINI_WINDOW_P (w)) | |
6482 && !(startp == BUF_BEGV (b) | |
6483 || BUF_FETCH_CHAR (b, startp - 1) == '\n')) | |
6484 || (pointm == startp && | |
6485 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) && | |
6486 startp < marker_position (w->last_start[CURRENT_DISP])) | |
6487 || (startp == BUF_ZV (b))) | |
6488 { | |
6489 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6490 | |
6491 goto regeneration_done; | |
6492 } | |
6493 /* See if we can update the data structures locally based on | |
6494 knowledge of what changed in the buffer. */ | |
6495 else if (!w->windows_changed | |
6496 && !f->clip_changed | |
6497 && !f->faces_changed | |
6498 && !f->glyphs_changed | |
6499 && !f->subwindows_changed | |
442 | 6500 /* && !f->subwindows_state_changed*/ |
428 | 6501 && !f->windows_structure_changed |
6502 && !f->frame_changed | |
6503 && !truncation_changed | |
6504 && pointm >= startp | |
6505 && regenerate_window_incrementally (w, startp, pointm)) | |
6506 { | |
6507 if (f->modeline_changed | |
6508 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b) | |
6509 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b)) | |
6510 regenerate_modeline (w); | |
6511 | |
6512 skip_output = 1; | |
6513 goto regeneration_done; | |
6514 } | |
6515 /* #### This is where a check for structure based scrolling would go. */ | |
6516 /* If all else fails, try just regenerating and see what happens. */ | |
6517 else | |
6518 { | |
6519 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6520 | |
6521 if (point_visible (w, pointm, DESIRED_DISP)) | |
6522 goto regeneration_done; | |
6523 } | |
6524 | |
6525 /* We still haven't gotten the window regenerated with point | |
6526 visible. Next we try scrolling a little and see if point comes | |
6527 back onto the screen. */ | |
6528 if (scroll_step > 0) | |
6529 { | |
6530 int scrolled = scroll_conservatively; | |
6531 for (; scrolled >= 0; scrolled -= scroll_step) | |
6532 { | |
6533 startp = vmotion (w, startp, | |
6534 (pointm < startp) ? -scroll_step : scroll_step, 0); | |
6535 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6536 | |
6537 if (point_visible (w, pointm, DESIRED_DISP)) | |
6538 goto regeneration_done; | |
6539 } | |
6540 } | |
6541 | |
6542 /* We still haven't managed to get the screen drawn with point on | |
6543 the screen, so just center it and be done with it. */ | |
6544 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6545 | |
6546 | |
6547 regeneration_done: | |
6548 | |
6549 /* If the window's frame is changed then reset the current display | |
6550 lines in order to force a full repaint. */ | |
6551 if (f->frame_changed) | |
6552 { | |
6553 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
6554 | |
6555 Dynarr_reset (cla); | |
6556 } | |
6557 | |
6558 /* Must do this before calling redisplay_output_window because it | |
6559 sets some markers on the window. */ | |
6560 if (echo_active) | |
6561 { | |
6562 w->buffer = old_buffer; | |
6563 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer); | |
6564 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer); | |
6565 } | |
6566 | |
6567 /* These also have to be set before calling redisplay_output_window | |
6568 since it sets the CURRENT_DISP values based on them. */ | |
6569 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
6570 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
6571 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
6572 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
6573 | |
6574 if (!skip_output) | |
6575 { | |
665 | 6576 Charbpos start = marker_position (w->start[DESIRED_DISP]); |
6577 Charbpos end = (w->window_end_pos[DESIRED_DISP] == -1 | |
428 | 6578 ? BUF_ZV (b) |
6579 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1); | |
6580 /* Don't pollute the cache if not sure if we are correct */ | |
6581 if (w->start_at_line_beg) | |
6582 update_line_start_cache (w, start, end, pointm, 1); | |
6583 redisplay_output_window (w); | |
6584 /* | |
6585 * If we just displayed the echo area, the line start cache is | |
6586 * no longer valid, because the minibuffer window is associated | |
6587 * with the window now. | |
6588 */ | |
6589 if (echo_active) | |
6590 w->line_cache_last_updated = make_int (-1); | |
6591 } | |
6592 | |
6593 /* #### This should be dependent on face changes and will need to be | |
6594 somewhere else once tty updates occur on a per-frame basis. */ | |
6595 mark_face_cachels_as_clean (w); | |
6596 | |
438 | 6597 /* The glyph cachels only get dirty if someone changed something. |
6598 Since redisplay has now effectively ended we can reset the dirty | |
6599 flag since everything must be up-to-date. */ | |
428 | 6600 if (glyphs_changed) |
6601 mark_glyph_cachels_as_clean (w); | |
6602 | |
6603 w->windows_changed = 0; | |
6604 } | |
6605 | |
6606 /* Call buffer_reset_changes for all buffers present in any window | |
6607 currently visible in all frames on all devices. #### There has to | |
6608 be a better way to do this. */ | |
6609 | |
6610 static int | |
2286 | 6611 reset_buffer_changes_mapfun (struct window *w, void *UNUSED (closure)) |
428 | 6612 { |
6613 buffer_reset_changes (XBUFFER (w->buffer)); | |
6614 return 0; | |
6615 } | |
6616 | |
6617 static void | |
6618 reset_buffer_changes (void) | |
6619 { | |
6620 Lisp_Object frmcons, devcons, concons; | |
6621 | |
6622 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
6623 { | |
6624 struct frame *f = XFRAME (XCAR (frmcons)); | |
6625 | |
6626 if (FRAME_REPAINT_P (f)) | |
6627 map_windows (f, reset_buffer_changes_mapfun, 0); | |
6628 } | |
6629 } | |
6630 | |
6631 /* Ensure that all windows underneath the given window in the window | |
6632 hierarchy are correctly displayed. */ | |
6633 | |
6634 static void | |
6635 redisplay_windows (Lisp_Object window, int skip_selected) | |
6636 { | |
6637 for (; !NILP (window) ; window = XWINDOW (window)->next) | |
6638 { | |
6639 redisplay_window (window, skip_selected); | |
6640 } | |
6641 } | |
6642 | |
1318 | 6643 /* Register an action to be called at the end of redisplay. |
6644 in_display is 0 when this is called. | |
6645 This is used when it is discovered that an action needs to be taken, | |
6646 but it's during redisplay, so it's not safe. (Typically, it's an action | |
6647 that needs to enter redisplay, which can't happen reentrantly.) | |
6648 | |
6649 NEVER signal an error in these functions. | |
6650 */ | |
6651 | |
6652 void | |
6653 register_post_redisplay_action (void (*fun) (Lisp_Object), Lisp_Object arg) | |
6654 { | |
6655 Vpost_redisplay_actions = nconc2 (Vpost_redisplay_actions, | |
6656 list1 (Fcons (make_opaque_ptr | |
6657 ((void *) fun), arg))); | |
6658 } | |
6659 | |
1320 | 6660 static int running_post_redisplay_actions; |
6661 | |
1318 | 6662 static void |
6663 run_post_redisplay_actions (void) | |
6664 { | |
1320 | 6665 int depth; |
6666 | |
6667 if (running_post_redisplay_actions) | |
6668 return; | |
6669 | |
6670 depth = internal_bind_int (&running_post_redisplay_actions, 1); | |
6671 /* If the function pushes further actions, they will be tacked onto | |
6672 the end of the list, and we'll run them when we're done with the | |
6673 current ones. */ | |
1318 | 6674 while (!NILP (Vpost_redisplay_actions)) |
6675 { | |
6676 Lisp_Object car = XCAR (Vpost_redisplay_actions); | |
6677 void (*fun) (Lisp_Object) = | |
6678 (void (*)(Lisp_Object)) get_opaque_ptr (XCAR (car)); | |
6679 (*fun) (XCDR (car)); | |
6680 free_opaque_ptr (XCAR (car)); | |
6681 free_cons (car); | |
6682 Vpost_redisplay_actions = XCDR (Vpost_redisplay_actions); | |
6683 } | |
1320 | 6684 unbind_to (depth); |
1318 | 6685 } |
6686 | |
6687 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
6688 | |
6689 static Lisp_Object | |
2286 | 6690 commit_ritual_suicide (Lisp_Object UNUSED (ceci_nest_pas_une_pipe)) |
1318 | 6691 { |
6692 assert (!in_display); | |
6693 return Qnil; | |
6694 } | |
6695 | |
6696 #endif | |
6697 | |
6698 /* Within the guts of redisplay, we are defenseless and cannot allow any of | |
6699 the following to happen: | |
6700 | |
6701 1) garbage collection | |
6702 2) QUIT | |
6703 3) any non-local exits | |
6704 4) frame size changes | |
6705 5) deletion of any buffers, windows, frames, etc. | |
6706 6) modification of buffer text | |
6707 7) reentrant entry of redisplay (see the stack trace above | |
6708 generate_displayable_area()) | |
6709 | |
6710 The general reason is that the redisplay code is written to assume that | |
6711 it is the only code running, and thus (a) cannot tolerate structures | |
6712 changed out from under it (hence 1, 4, 5, 6, 7) and (b) at various points | |
6713 within redisplay the redisplay structures may be in an inconsistent | |
6714 state and there are no unwind-protects to clean the structures up in | |
6715 case of non-local exit (hence 2, 3). Fixing redisplay to address these | |
6716 issues is hard and perhaps not worth it (and might slow things down a | |
6717 fair amount). We address 1, 4, 5 and 6 ourselves inside of | |
6718 enter_redisplay_critical_section() by simply inhibiting them, but we | |
6719 cannot handle 2 and 3, which must be handled at the actual point where | |
6720 they may occur (especially, internal_equal() or any place that may call | |
6721 Lisp), by wrapping the code in call_trapping_problems() or | |
6722 call_with_suspended_errors(). [[ NOTE: We could address QUIT by inhibiting | |
6723 it but this would be anti-social because it would prevent the user from | |
6724 interrupting any Lisp code called within the critical section. With the | |
6725 call_*() wrapping, C-g will interrupt the Lisp code and throw back to | |
6726 the innermost wrapping. ]] In fact we do turn off QUIT handling, since | |
6727 it's just too dangerous otherwise. See below. | |
6728 | |
6729 Code calling enter_redisplay_critical_section() must check for reentrancy | |
6730 (#7) and take appropriate corrective action. | |
6731 | |
6732 To help debug potential problems, we arrange (when | |
6733 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every time | |
6734 we execute QUIT or call Lisp code unless proper wrapping is in place, as | |
6735 well as further checks when we actually Fsignal(), Fthrow(), | |
6736 garbage_collect_1(). | |
6737 | |
6738 #### If a frame-size change does occur we should probably actually be | |
6739 preempting redisplay. */ | |
6740 | |
6741 /* Count of number of recursive times we call | |
6742 enter_redisplay_critical_section() or | |
6743 enter_redisplay_critical_section_maybe(). | |
6744 enter_redisplay_critical_section() cannot occur reentrantly but we have | |
6745 to know in the *maybe() version whether to exit the section when we're | |
6746 done. */ | |
6747 static int in_display_nesting; | |
6748 | |
6749 static Lisp_Object | |
2286 | 6750 end_hold_frame_size_changes (Lisp_Object UNUSED (obj)) |
1318 | 6751 { |
6752 if (!hold_frame_size_changes) | |
6753 { | |
6754 /* we used to have a function to do this for only one frame, and | |
6755 it was typical to call it at the end of a critical section | |
6756 (which occurs once per frame); but what then happens if multiple | |
6757 frames have frame changes held up? | |
4187 | 6758 |
1318 | 6759 This means we are O(N^2) over frames. I seriously doubt it matters. |
6760 --ben */ | |
6761 Lisp_Object frmcons, devcons, concons; | |
4187 | 6762 |
1318 | 6763 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
6764 { | |
6765 struct frame *f = XFRAME (XCAR (frmcons)); | |
6766 if (f->size_change_pending) | |
6767 change_frame_size (f, f->new_height, f->new_width, 0); | |
6768 } | |
6769 } | |
6770 return Qnil; | |
6771 } | |
6772 | |
6773 /* Call this to temporarily prevent frame-size changes from being processed. | |
6774 To undo, use unbind_to(), passing it the value returned by this function. | |
6775 */ | |
6776 | |
6777 int | |
6778 begin_hold_frame_size_changes (void) | |
6779 { | |
6780 int depth = specpdl_depth (); | |
6781 record_unwind_protect (end_hold_frame_size_changes, Qnil); | |
6782 internal_bind_int (&hold_frame_size_changes, 1 + hold_frame_size_changes); | |
6783 return depth; | |
6784 } | |
6785 | |
6786 int | |
6787 enter_redisplay_critical_section (void) | |
6788 { | |
6789 int depth = specpdl_depth (); | |
6790 | |
6791 /* Reentrant entry is deadly. The calling function must check for this. */ | |
6792 assert (!in_display); | |
6793 begin_hold_frame_size_changes (); | |
6794 /* Make sure in_display gets reset, but don't set it yet so that | |
6795 commit_ritual_suicide() can be used. */ | |
6796 internal_bind_int (&in_display, 0); | |
6797 internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6798 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
6799 /* Force every call to QUIT to check for in_displayness. This will | |
6800 verify proper wrapping, as in the previous comment, aborting if not. */ | |
6801 something_happened++; | |
6802 /* Verify that no nonlocal exits blow past us. */ | |
6803 record_unwind_protect (commit_ritual_suicide, Qnil); | |
6804 #endif | |
6805 in_display++; | |
6806 | |
6807 set_trapping_problems_flags (INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY); | |
6808 /* Even checking for QUIT can cause arbitrary Lisp code to be executed, | |
6809 e.g. through a menu handler. We really don't want that happening | |
6810 inside of redisplay. Code that we `eval' is at least written with the | |
6811 expectation that it's inside of redisplay, and shouldn't try anything | |
6812 weird; but that's not the case for menu code (e.g. custom loads huge | |
6813 amounts of LISP FILES from a menu handler! FMH!). Safest just to turn | |
6814 this off. We could turn it on using UNINHIBIT_QUIT or | |
6815 begin_do_check_for_quit() in certain places if we want, if we know | |
6816 it's not in an especially tricky place. */ | |
6817 begin_dont_check_for_quit (); | |
6818 return depth; | |
6819 } | |
6820 | |
6821 void | |
6822 exit_redisplay_critical_section (int depth) | |
6823 { | |
6824 in_display--; | |
6825 assert (!in_display); | |
6826 unbind_to (depth); | |
6827 | |
6828 run_post_redisplay_actions (); | |
6829 } | |
6830 | |
6831 /* Enter the redisplay critical section if we're not already in it. This | |
6832 is for code that needs frame changes held up and other protections from | |
6833 being inside, but doesn't modify the redisplay structures, and doesn't | |
6834 look at them in a way that they will be confused by inconsistencies. */ | |
6835 | |
6836 int | |
6837 enter_redisplay_critical_section_maybe (void) | |
6838 { | |
6839 if (!in_display) | |
6840 return enter_redisplay_critical_section (); | |
6841 else | |
6842 return internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6843 } | |
6844 | |
6845 void | |
6846 exit_redisplay_critical_section_maybe (int depth) | |
6847 { | |
6848 if (in_display_nesting == 1) | |
6849 exit_redisplay_critical_section (depth); | |
6850 else | |
6851 unbind_to (depth); | |
6852 } | |
6853 | |
1279 | 6854 /* Ensure that all windows on the given frame are correctly displayed. |
6855 Return non-zero if pre-empted. */ | |
428 | 6856 |
442 | 6857 int |
428 | 6858 redisplay_frame (struct frame *f, int preemption_check) |
6859 { | |
6860 struct device *d = XDEVICE (f->device); | |
853 | 6861 int depth; |
428 | 6862 |
1279 | 6863 assert (f->init_finished); |
6864 | |
1318 | 6865 /* NOTE: Without sufficient checks for stream frames, we got weird |
6866 crashes in pdump. These came and went very easily -- adding the | |
6867 critical-section code for redisplay was enough to trigger them. | |
6868 Perhaps I should have debugged them but there didn't seem to be any | |
6869 point. --ben */ | |
1279 | 6870 if (FRAME_STREAM_P (f)) /* nothing to do */ |
6871 return 0; | |
6872 | |
1318 | 6873 /* Reentrancy into redisplay can be deadly. See stack trace above |
6874 generate_displayable_area(). */ | |
6875 if (in_display) | |
6876 return 1; | |
6877 | |
545 | 6878 if (preemption_check |
6879 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) | |
428 | 6880 { |
6881 /* The preemption check itself takes a lot of time, | |
6882 so normally don't do it here. We do it if called | |
6883 from Lisp, though (`redisplay-frame'). */ | |
6884 int preempted; | |
6885 | |
6886 REDISPLAY_PREEMPTION_CHECK; | |
6887 if (preempted) | |
6888 return 1; | |
6889 } | |
6890 | |
442 | 6891 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) |
6892 { | |
6893 Lisp_Object frame; | |
6894 | |
6895 f->old_buffer_alist = Freplace_list (f->old_buffer_alist, | |
6896 f->buffer_alist); | |
793 | 6897 frame = wrap_frame (f); |
442 | 6898 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); |
6899 } | |
6900 | |
428 | 6901 /* Before we put a hold on frame size changes, attempt to process |
6902 any which are already pending. */ | |
6903 if (f->size_change_pending) | |
6904 change_frame_size (f, f->new_height, f->new_width, 0); | |
6905 | |
6906 /* If frame size might need to be changed, due to changed size | |
6907 of toolbars, scrollbars etc, change it now */ | |
6908 if (f->size_slipped) | |
6909 { | |
6910 adjust_frame_size (f); | |
6911 assert (!f->size_slipped); | |
6912 } | |
6913 | |
1318 | 6914 /* The menubar, toolbar, and icon updates should be done before |
853 | 6915 enter_redisplay_critical_section is called and we are officially |
3025 | 6916 `in_display'. They is because they tend to eval Lisp code, which |
1318 | 6917 needs to be carefully wrapped within the critical section (and hence |
6918 is difficult to debug). */ | |
428 | 6919 |
6920 #ifdef HAVE_MENUBARS | |
6921 /* Update the menubar. It is done first since it could change | |
6922 the menubar's visibility. This way we avoid having flashing | |
6923 caused by an Expose event generated by the visibility change | |
6924 being handled. */ | |
6925 update_frame_menubars (f); | |
6926 #endif /* HAVE_MENUBARS */ | |
6927 #ifdef HAVE_TOOLBARS | |
905 | 6928 /* Update the toolbars geometry. We don't update the toolbars |
6929 themselves at this point since the space they are trying to | |
6930 occupy may currently by occupied by gutter elements. Instead we | |
6931 update the geometry, then update the gutter geometry, then update | |
6932 the gutters - which will cause mapped windows to be repositioned | |
6933 - and finally update the toolbars. */ | |
6934 update_frame_toolbars_geometry (f); | |
428 | 6935 #endif /* HAVE_TOOLBARS */ |
442 | 6936 /* Gutter update proper has to be done inside display when no frame |
6937 size changes can occur, thus we separately update the gutter | |
6938 geometry here if it needs it. */ | |
6939 update_frame_gutter_geometry (f); | |
428 | 6940 |
6941 /* If we clear the frame we have to force its contents to be redrawn. */ | |
6942 if (f->clear) | |
6943 f->frame_changed = 1; | |
6944 | |
442 | 6945 /* Invalidate the subwindow caches. We use subwindows_changed here |
6946 to cause subwindows to get instantiated. This is because | |
428 | 6947 subwindows_state_changed is less strict - dealing with things |
6948 like the clicked state of button. We have to do this before | |
6949 redisplaying the gutters as subwindows get unmapped in the | |
6950 process.*/ | |
442 | 6951 if (f->frame_changed) |
6952 reset_frame_subwindow_instance_cache (f); | |
6953 | |
6954 if (f->frame_changed || f->subwindows_changed) | |
6955 { | |
428 | 6956 /* we have to do this so the gutter gets regenerated. */ |
6957 reset_gutter_display_lines (f); | |
6958 } | |
6959 | |
853 | 6960 depth = enter_redisplay_critical_section (); |
428 | 6961 |
6962 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ | |
1318 | 6963 |
6964 /* See comments in enter_redisplay_critical_section() */ | |
428 | 6965 |
442 | 6966 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
6967 | |
6968 /* We can now update the gutters, safe in the knowledge that our | |
6969 efforts won't get undone. */ | |
6970 | |
6971 /* This can call lisp, but redisplay is protected by binding | |
6972 inhibit_quit. More importantly the code involving display lines | |
6973 *assumes* that GC will not happen and so does not GCPRO | |
6974 anything. Since we use this code the whole time with the gutters | |
1318 | 6975 we cannot allow GC to happen when manipulating the gutters. |
6976 | |
6977 This must be inside of the critical section for various reasons. | |
6978 For example, it messes with display structures, which be left in | |
6979 an inconsistent state. */ | |
442 | 6980 update_frame_gutters (f); |
6981 | |
428 | 6982 /* Erase the frame before outputting its contents. */ |
6983 if (f->clear) | |
6984 { | |
442 | 6985 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 6986 } |
6987 | |
6988 /* Do the selected window first. */ | |
6989 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); | |
6990 | |
6991 /* Then do the rest. */ | |
6992 redisplay_windows (f->root_window, 1); | |
6993 | |
442 | 6994 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 6995 |
6996 update_frame_title (f); | |
6997 | |
905 | 6998 #ifdef HAVE_TOOLBARS |
6999 /* Finally update the toolbars. It seems its possible to get in a | |
7000 cycle between updating the gutter and the toolbars. Basically we | |
7001 want to end up with both being up-to-date and this doesn't seem | |
7002 possible in a single pass. */ | |
7003 update_frame_toolbars (f); | |
7004 #endif /* HAVE_TOOLBARS */ | |
7005 | |
428 | 7006 CLASS_RESET_CHANGED_FLAGS (f); |
7007 f->window_face_cache_reset = 0; | |
7008 f->echo_area_garbaged = 0; | |
7009 f->clear = 0; | |
7010 | |
7011 if (!f->size_change_pending) | |
7012 f->size_changed = 0; | |
7013 | |
7014 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */ | |
7015 | |
853 | 7016 /* Allow frame size changes to occur again. */ |
7017 exit_redisplay_critical_section (depth); | |
428 | 7018 |
7019 return 0; | |
7020 } | |
7021 | |
440 | 7022 /* Ensure that all frames on the given device are correctly displayed. |
7023 If AUTOMATIC is non-zero, and the device implementation indicates | |
7024 no automatic redisplay, as printers do, then the device is not | |
7025 redisplayed. AUTOMATIC is set to zero when called from lisp | |
7026 functions (redraw-device) and (redisplay-device), and to non-zero | |
7027 when called from "lazy" redisplay(); | |
7028 */ | |
428 | 7029 |
7030 static int | |
440 | 7031 redisplay_device (struct device *d, int automatic) |
428 | 7032 { |
7033 Lisp_Object frame, frmcons; | |
7034 int size_change_failed = 0; | |
7035 struct frame *f; | |
7036 | |
545 | 7037 if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) |
440 | 7038 return 0; |
7039 | |
428 | 7040 if (DEVICE_STREAM_P (d)) /* nothing to do */ |
7041 return 0; | |
7042 | |
7043 /* It is possible that redisplay has been called before the | |
545 | 7044 device is fully initialized, or that the console implementation |
7045 allows frameless devices. If so then continue with the next | |
7046 device. */ | |
428 | 7047 if (NILP (DEVICE_SELECTED_FRAME (d))) |
7048 return 0; | |
7049 | |
545 | 7050 if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) |
7051 { | |
7052 int preempted; | |
7053 REDISPLAY_PREEMPTION_CHECK; | |
7054 if (preempted) | |
7055 return 1; | |
7056 } | |
428 | 7057 |
7058 /* Always do the selected frame first. */ | |
7059 frame = DEVICE_SELECTED_FRAME (d); | |
7060 | |
7061 f = XFRAME (frame); | |
7062 | |
7063 if (f->icon_changed || f->windows_changed) | |
7064 update_frame_icon (f); | |
7065 | |
7066 if (FRAME_REPAINT_P (f)) | |
7067 { | |
7068 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) | |
7069 { | |
588 | 7070 int preempted = redisplay_frame (f, 1); |
545 | 7071 if (preempted) |
7072 return 1; | |
7073 } | |
428 | 7074 |
7075 /* If the frame redisplay did not get preempted, then this flag | |
4187 | 7076 should have gotten set to 0. It might be possible for that |
7077 not to happen if a size change event were to occur at an odd | |
7078 time. To make sure we don't miss anything we simply don't | |
7079 reset the top level flags until the condition ends up being | |
7080 in the right state. */ | |
428 | 7081 if (f->size_changed) |
7082 size_change_failed = 1; | |
7083 } | |
7084 | |
7085 DEVICE_FRAME_LOOP (frmcons, d) | |
7086 { | |
7087 f = XFRAME (XCAR (frmcons)); | |
7088 | |
7089 if (f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
7090 continue; | |
7091 | |
7092 if (f->icon_changed || f->windows_changed) | |
7093 update_frame_icon (f); | |
7094 | |
7095 if (FRAME_REPAINT_P (f)) | |
7096 { | |
430 | 7097 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
428 | 7098 { |
588 | 7099 int preempted = redisplay_frame (f, 1); |
545 | 7100 if (preempted) |
7101 return 1; | |
428 | 7102 } |
7103 | |
7104 if (f->size_change_pending) | |
7105 size_change_failed = 1; | |
7106 } | |
7107 } | |
7108 | |
7109 /* If we get here then we redisplayed all of our frames without | |
7110 getting preempted so mark ourselves as clean. */ | |
7111 CLASS_RESET_CHANGED_FLAGS (d); | |
7112 | |
7113 if (!size_change_failed) | |
7114 d->size_changed = 0; | |
7115 | |
7116 return 0; | |
7117 } | |
7118 | |
7119 /* Ensure that all windows on all frames on all devices are displaying | |
7120 the current contents of their respective buffers. */ | |
7121 | |
7122 static void | |
7123 redisplay_without_hooks (void) | |
7124 { | |
7125 Lisp_Object devcons, concons; | |
7126 int size_change_failed = 0; | |
1292 | 7127 PROFILE_DECLARE (); |
7128 | |
7129 PROFILE_RECORD_ENTERING_SECTION (QSin_redisplay); | |
428 | 7130 |
7131 if (asynch_device_change_pending) | |
7132 handle_asynch_device_change (); | |
7133 | |
7134 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && | |
430 | 7135 !disable_preemption && preemption_count < max_preempts) |
428 | 7136 goto done; |
7137 | |
7138 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
7139 { | |
7140 struct device *d = XDEVICE (XCAR (devcons)); | |
7141 int preempted; | |
7142 | |
430 | 7143 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) |
428 | 7144 { |
440 | 7145 preempted = redisplay_device (d, 1); |
428 | 7146 |
7147 if (preempted) | |
7148 { | |
7149 preemption_count++; | |
7150 RESET_CHANGED_SET_FLAGS; | |
7151 goto done; | |
7152 } | |
7153 | |
7154 /* See comment in redisplay_device. */ | |
7155 if (d->size_changed) | |
7156 size_change_failed = 1; | |
7157 } | |
7158 } | |
7159 preemption_count = 0; | |
7160 | |
7161 /* Mark redisplay as accurate */ | |
7162 GLOBAL_RESET_CHANGED_FLAGS; | |
7163 RESET_CHANGED_SET_FLAGS; | |
7164 | |
7165 if (faces_changed) | |
7166 { | |
7167 mark_all_faces_as_clean (); | |
7168 faces_changed = 0; | |
7169 } | |
7170 | |
7171 if (!size_change_failed) | |
7172 size_changed = 0; | |
7173 | |
7174 reset_buffer_changes (); | |
7175 | |
7176 done: | |
800 | 7177 #ifdef ERROR_CHECK_DISPLAY |
7178 sledgehammer_check_redisplay_structs (); | |
7179 #endif /* ERROR_CHECK_DISPLAY */ | |
1292 | 7180 |
7181 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay); | |
428 | 7182 } |
7183 | |
1318 | 7184 /* Note: All places in the C code that call redisplay() are prepared to |
7185 handle GCing, which can happen from run_pre_idle_hook(). However, we | |
7186 can't currently handle GC inside the guts of redisplay; see | |
7187 enter_redisplay_critical_section(). | |
853 | 7188 |
7189 (#### What about other external entry points to the redisplay code? | |
7190 Someone should go through and make sure that all callers can handle | |
7191 GC there, too.) | |
7192 */ | |
7193 | |
428 | 7194 void |
7195 redisplay (void) | |
7196 { | |
853 | 7197 run_pre_idle_hook (); |
7198 redisplay_no_pre_idle_hook (); | |
7199 } | |
7200 | |
7201 void | |
7202 redisplay_no_pre_idle_hook (void) | |
7203 { | |
428 | 7204 if (last_display_warning_tick != display_warning_tick && |
7205 !inhibit_warning_display) | |
7206 { | |
7207 /* If an error occurs during this function, oh well. | |
4187 | 7208 If we report another warning, we could get stuck in an |
428 | 7209 infinite loop reporting warnings. */ |
853 | 7210 call0_trapping_problems |
7211 (0, Qdisplay_warning_buffer, | |
7212 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 7213 last_display_warning_tick = display_warning_tick; |
7214 } | |
7215 | |
7216 redisplay_without_hooks (); | |
7217 } | |
7218 | |
853 | 7219 Lisp_Object |
7220 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker) | |
7221 { | |
7222 return | |
7223 eval_in_buffer_trapping_problems | |
7224 ("Error calling function within redisplay", current_buffer, | |
1318 | 7225 dont_trust_this_damn_sucker, 0); |
853 | 7226 } |
428 | 7227 |
7228 /* Efficiently determine the window line number, and return a pointer | |
7229 to its printed representation. Do this regardless of whether | |
7230 line-number-mode is on. The first line in the buffer is counted as | |
7231 1. If narrowing is in effect, the lines are counted from the | |
7232 beginning of the visible portion of the buffer. */ | |
4970 | 7233 static Ascbyte * |
428 | 7234 window_line_number (struct window *w, int type) |
7235 { | |
7236 struct device *d = XDEVICE (XFRAME (w->frame)->device); | |
7237 struct buffer *b = XBUFFER (w->buffer); | |
7238 /* Be careful in the order of these tests. The first clause will | |
7239 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be). | |
7240 This can occur when the frame title is computed really early */ | |
665 | 7241 Charbpos pos = |
428 | 7242 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) && |
7243 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) && | |
7244 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
7245 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d ) | |
7246 ? BUF_PT (b) | |
7247 : marker_position (w->pointm[type])); | |
7248 EMACS_INT line; | |
7249 | |
7250 line = buffer_line_number (b, pos, 1); | |
7251 | |
603 | 7252 { |
4970 | 7253 static Ascbyte window_line_number_buf[DECIMAL_PRINT_SIZE (long)]; |
603 | 7254 |
7255 long_to_string (window_line_number_buf, line + 1); | |
7256 | |
7257 return window_line_number_buf; | |
7258 } | |
428 | 7259 } |
7260 | |
7261 | |
7262 /* Given a character representing an object in a modeline | |
7263 specification, return a string (stored into the global array | |
867 | 7264 `mode_spec_ibyte_string') with the information that object |
428 | 7265 represents. |
7266 | |
7267 This function is largely unchanged from previous versions of the | |
7268 redisplay engine. | |
7269 | |
7270 Warning! This code is also used for frame titles and can be called | |
7271 very early in the device/frame update process! JV | |
7272 */ | |
7273 | |
7274 static void | |
867 | 7275 decode_mode_spec (struct window *w, Ichar spec, int type) |
428 | 7276 { |
7277 Lisp_Object obj = Qnil; | |
4970 | 7278 const Ascbyte *str = NULL; |
428 | 7279 struct buffer *b = XBUFFER (w->buffer); |
7280 | |
867 | 7281 Dynarr_reset (mode_spec_ibyte_string); |
428 | 7282 |
7283 switch (spec) | |
7284 { | |
7285 /* print buffer name */ | |
7286 case 'b': | |
7287 obj = b->name; | |
7288 break; | |
7289 | |
7290 /* print visited file name */ | |
7291 case 'f': | |
7292 obj = b->filename; | |
7293 break; | |
7294 | |
7295 /* print the current column */ | |
7296 case 'c': | |
7297 { | |
4187 | 7298 Charbpos pt = (w == XWINDOW (Fselected_window (Qnil))) |
7299 ? BUF_PT (b) | |
7300 : marker_position (w->pointm[type]); | |
428 | 7301 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one; |
4970 | 7302 Ascbyte buf[DECIMAL_PRINT_SIZE (long)]; |
428 | 7303 |
7304 long_to_string (buf, col); | |
7305 | |
867 | 7306 Dynarr_add_many (mode_spec_ibyte_string, |
7307 (const Ibyte *) buf, strlen (buf)); | |
428 | 7308 |
7309 goto decode_mode_spec_done; | |
7310 } | |
7311 /* print the file coding system */ | |
7312 case 'C': | |
7313 { | |
4187 | 7314 Lisp_Object codesys = b->buffer_file_coding_system; |
7315 /* Be very careful here not to get an error. */ | |
428 | 7316 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys)) |
4187 | 7317 { |
7318 codesys = find_coding_system_for_text_file (codesys, 0); | |
428 | 7319 if (CODING_SYSTEMP (codesys)) |
4187 | 7320 obj = XCODING_SYSTEM_MNEMONIC (codesys); |
7321 } | |
428 | 7322 } |
7323 break; | |
7324 | |
7325 /* print the current line number */ | |
7326 case 'l': | |
7327 str = window_line_number (w, type); | |
7328 break; | |
7329 | |
7330 /* print value of mode-name (obsolete) */ | |
7331 case 'm': | |
7332 obj = b->mode_name; | |
7333 break; | |
7334 | |
7335 /* print hyphen and frame number, if != 1 */ | |
7336 case 'N': | |
7337 #ifdef HAVE_TTY | |
7338 { | |
7339 struct frame *f = XFRAME (w->frame); | |
7340 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999) | |
7341 { | |
7342 /* Naughty, naughty */ | |
4970 | 7343 Ascbyte *writable_str = alloca_array (Ascbyte, 10); |
428 | 7344 sprintf (writable_str, "-%d", f->order_count); |
7345 str = writable_str; | |
7346 } | |
7347 } | |
7348 #endif /* HAVE_TTY */ | |
7349 break; | |
7350 | |
7351 /* print Narrow if appropriate */ | |
7352 case 'n': | |
7353 if (BUF_BEGV (b) > BUF_BEG (b) | |
7354 || BUF_ZV (b) < BUF_Z (b)) | |
7355 str = " Narrow"; | |
7356 break; | |
7357 | |
7358 /* print %, * or hyphen, if buffer is read-only, modified or neither */ | |
7359 case '*': | |
7360 str = (!NILP (b->read_only) | |
7361 ? "%" | |
7362 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7363 ? "*" | |
7364 : "-")); | |
7365 break; | |
7366 | |
7367 /* print * or hyphen -- XEmacs change to allow a buffer to be | |
4187 | 7368 read-only but still indicate whether it is modified. */ |
428 | 7369 case '+': |
7370 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7371 ? "*" | |
7372 : (!NILP (b->read_only) | |
7373 ? "%" | |
7374 : "-")); | |
7375 break; | |
7376 | |
7377 /* #### defined in 19.29 decode_mode_spec, but not in | |
4187 | 7378 modeline-format doc string. */ |
428 | 7379 /* This differs from %* in that it ignores read-only-ness. */ |
7380 case '&': | |
7381 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7382 ? "*" | |
7383 : "-"); | |
7384 break; | |
7385 | |
7386 /* print process status */ | |
7387 case 's': | |
7388 obj = Fget_buffer_process (w->buffer); | |
7389 if (NILP (obj)) | |
7390 str = GETTEXT ("no process"); | |
7391 else | |
7392 obj = Fsymbol_name (Fprocess_status (obj)); | |
7393 break; | |
7394 | |
7395 /* Print name of selected frame. */ | |
7396 case 'S': | |
7397 obj = XFRAME (w->frame)->name; | |
7398 break; | |
7399 | |
7400 /* indicate TEXT or BINARY */ | |
7401 case 't': | |
7402 /* #### NT does not use this any more. Now what? */ | |
7403 str = "T"; | |
7404 break; | |
7405 | |
7406 /* print percent of buffer above top of window, or Top, Bot or All */ | |
7407 case 'p': | |
7408 { | |
665 | 7409 Charbpos pos = marker_position (w->start[type]); |
428 | 7410 |
7411 /* This had better be while the desired lines are being done. */ | |
7412 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) | |
7413 { | |
7414 if (pos <= BUF_BEGV (b)) | |
7415 str = "All"; | |
7416 else | |
7417 str = "Bottom"; | |
7418 } | |
7419 else if (pos <= BUF_BEGV (b)) | |
7420 str = "Top"; | |
7421 else | |
7422 { | |
7423 /* This hard limit is ok since the string it will hold has a | |
4187 | 7424 fixed maximum length of 3. But just to be safe... */ |
4970 | 7425 Ascbyte buf[10]; |
428 | 7426 Charcount chars = pos - BUF_BEGV (b); |
7427 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7428 | |
7429 /* Avoid overflow on big buffers */ | |
7430 int percent = total > LONG_MAX/200 ? | |
7431 (chars + total/200) / (total / 100) : | |
7432 (chars * 100 + total/2) / total; | |
7433 | |
7434 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7435 2-digit number that is close. */ |
428 | 7436 if (percent == 100) |
7437 percent = 99; | |
7438 | |
7439 sprintf (buf, "%d%%", percent); | |
867 | 7440 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7441 strlen (buf)); |
7442 | |
7443 goto decode_mode_spec_done; | |
7444 } | |
7445 break; | |
7446 } | |
7447 | |
7448 /* print percent of buffer above bottom of window, perhaps plus | |
7449 Top, or print Bottom or All */ | |
7450 case 'P': | |
7451 { | |
665 | 7452 Charbpos toppos = marker_position (w->start[type]); |
7453 Charbpos botpos = BUF_Z (b) - w->window_end_pos[type]; | |
428 | 7454 |
7455 /* botpos is only accurate as of the last redisplay, so we can | |
4187 | 7456 only treat it as a hint. In particular, after erase-buffer, |
7457 botpos may be negative. */ | |
428 | 7458 if (botpos < toppos) |
7459 botpos = toppos; | |
7460 | |
7461 if (botpos >= BUF_ZV (b)) | |
7462 { | |
7463 if (toppos <= BUF_BEGV (b)) | |
7464 str = "All"; | |
7465 else | |
7466 str = "Bottom"; | |
7467 } | |
7468 else | |
7469 { | |
7470 /* This hard limit is ok since the string it will hold has a | |
4187 | 7471 fixed maximum length of around 6. But just to be safe... */ |
4970 | 7472 Ascbyte buf[10]; |
428 | 7473 Charcount chars = botpos - BUF_BEGV (b); |
7474 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7475 | |
7476 /* Avoid overflow on big buffers */ | |
7477 int percent = total > LONG_MAX/200 ? | |
7478 (chars + total/200) / (total / 100) : | |
7479 (chars * 100 + total/2) / max (total, 1); | |
7480 | |
7481 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7482 2-digit number that is close. */ |
428 | 7483 if (percent == 100) |
7484 percent = 99; | |
7485 | |
7486 if (toppos <= BUF_BEGV (b)) | |
7487 sprintf (buf, "Top%d%%", percent); | |
7488 else | |
7489 sprintf (buf, "%d%%", percent); | |
7490 | |
867 | 7491 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7492 strlen (buf)); |
7493 | |
7494 goto decode_mode_spec_done; | |
7495 } | |
7496 break; | |
7497 } | |
7498 | |
7499 /* print % */ | |
7500 case '%': | |
7501 str = "%"; | |
7502 break; | |
7503 | |
7504 /* print one [ for each recursive editing level. */ | |
7505 case '[': | |
7506 { | |
7507 int i; | |
7508 | |
7509 if (command_loop_level > 5) | |
7510 { | |
7511 str = "[[[... "; | |
7512 break; | |
7513 } | |
7514 | |
7515 for (i = 0; i < command_loop_level; i++) | |
867 | 7516 Dynarr_add (mode_spec_ibyte_string, '['); |
428 | 7517 |
7518 goto decode_mode_spec_done; | |
7519 } | |
7520 | |
7521 /* print one ] for each recursive editing level. */ | |
7522 case ']': | |
7523 { | |
7524 int i; | |
7525 | |
7526 if (command_loop_level > 5) | |
7527 { | |
7528 str = "...]]]"; | |
7529 break; | |
7530 } | |
7531 | |
7532 for (i = 0; i < command_loop_level; i++) | |
867 | 7533 Dynarr_add (mode_spec_ibyte_string, ']'); |
428 | 7534 |
7535 goto decode_mode_spec_done; | |
7536 } | |
7537 | |
7538 /* print infinitely many dashes -- handle at top level now */ | |
7539 case '-': | |
7540 break; | |
7541 | |
7542 } | |
7543 | |
7544 if (STRINGP (obj)) | |
867 | 7545 Dynarr_add_many (mode_spec_ibyte_string, |
428 | 7546 XSTRING_DATA (obj), |
7547 XSTRING_LENGTH (obj)); | |
7548 else if (str) | |
867 | 7549 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) str, strlen (str)); |
428 | 7550 |
7551 decode_mode_spec_done: | |
867 | 7552 Dynarr_add (mode_spec_ibyte_string, '\0'); |
428 | 7553 } |
7554 | |
7555 /* Given a display line, free all of its data structures. */ | |
7556 | |
7557 static void | |
7558 free_display_line (struct display_line *dl) | |
7559 { | |
7560 int block; | |
7561 | |
7562 if (dl->display_blocks) | |
7563 { | |
7564 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
4187 | 7565 { |
428 | 7566 struct display_block *db = Dynarr_atp (dl->display_blocks, block); |
7567 | |
7568 Dynarr_free (db->runes); | |
7569 } | |
7570 | |
7571 Dynarr_free (dl->display_blocks); | |
7572 dl->display_blocks = NULL; | |
7573 } | |
7574 | |
7575 if (dl->left_glyphs) | |
7576 { | |
7577 Dynarr_free (dl->left_glyphs); | |
7578 dl->left_glyphs = NULL; | |
7579 } | |
7580 | |
7581 if (dl->right_glyphs) | |
7582 { | |
7583 Dynarr_free (dl->right_glyphs); | |
7584 dl->right_glyphs = NULL; | |
7585 } | |
7586 } | |
7587 | |
7588 | |
7589 /* Given an array of display lines, free them and all data structures | |
7590 contained within them. */ | |
7591 | |
7592 void | |
7593 free_display_lines (display_line_dynarr *dla) | |
7594 { | |
7595 int line; | |
7596 | |
7597 for (line = 0; line < Dynarr_largest (dla); line++) | |
7598 { | |
7599 free_display_line (Dynarr_atp (dla, line)); | |
7600 } | |
7601 | |
7602 Dynarr_free (dla); | |
7603 } | |
7604 | |
7605 /* Call internal free routine for each set of display lines. */ | |
7606 | |
7607 void | |
7608 free_display_structs (struct window_mirror *mir) | |
7609 { | |
7610 if (mir->current_display_lines) | |
7611 { | |
7612 free_display_lines (mir->current_display_lines); | |
7613 mir->current_display_lines = 0; | |
7614 } | |
7615 | |
7616 if (mir->desired_display_lines) | |
7617 { | |
7618 free_display_lines (mir->desired_display_lines); | |
7619 mir->desired_display_lines = 0; | |
7620 } | |
7621 } | |
7622 | |
7623 | |
7624 static void | |
7625 mark_glyph_block_dynarr (glyph_block_dynarr *gba) | |
7626 { | |
7627 if (gba) | |
7628 { | |
4967 | 7629 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
|
7630 glyph_block *gb_last = Dynarr_past_lastp (gba); |
428 | 7631 |
7632 for (; gb < gb_last; gb++) | |
7633 { | |
7634 if (!NILP (gb->glyph)) | |
7635 mark_object (gb->glyph); | |
7636 if (!NILP (gb->extent)) | |
7637 mark_object (gb->extent); | |
7638 } | |
7639 } | |
7640 } | |
7641 | |
442 | 7642 /* See the comment in image_instantiate_cache_result as to why marking |
7643 the glyph will also mark the image_instance. */ | |
7644 void | |
428 | 7645 mark_redisplay_structs (display_line_dynarr *dla) |
7646 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7647 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
|
7648 display_line *dl_last = Dynarr_past_lastp (dla); |
428 | 7649 |
7650 for (; dl < dl_last; dl++) | |
7651 { | |
7652 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
|
7653 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
|
7654 display_block *db_last = Dynarr_past_lastp (dba); |
428 | 7655 |
7656 for (; db < db_last; db++) | |
7657 { | |
7658 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
|
7659 rune *r = Dynarr_begin (ra); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7660 rune *r_last = Dynarr_past_lastp (ra); |
428 | 7661 |
7662 for (; r < r_last; r++) | |
7663 { | |
7664 if (r->type == RUNE_DGLYPH) | |
7665 { | |
7666 if (!NILP (r->object.dglyph.glyph)) | |
7667 mark_object (r->object.dglyph.glyph); | |
7668 if (!NILP (r->object.dglyph.extent)) | |
7669 mark_object (r->object.dglyph.extent); | |
7670 } | |
7671 } | |
7672 } | |
7673 | |
7674 mark_glyph_block_dynarr (dl->left_glyphs); | |
7675 mark_glyph_block_dynarr (dl->right_glyphs); | |
7676 } | |
7677 } | |
7678 | |
7679 | |
2367 | 7680 |
7681 /* | |
7682 | |
7683 Info on line-start cache: | |
7684 | |
7685 (Info-goto-node "(internals)Line Start Cache") | |
7686 */ | |
428 | 7687 |
7688 /* This will get used quite a bit so we don't want to be constantly | |
7689 allocating and freeing it. */ | |
7690 static line_start_cache_dynarr *internal_cache; | |
7691 | |
7692 /* Makes internal_cache represent the TYPE display structs and only | |
7693 the TYPE display structs. */ | |
7694 | |
7695 static void | |
7696 update_internal_cache_list (struct window *w, int type) | |
7697 { | |
7698 int line; | |
7699 display_line_dynarr *dla = window_display_lines (w, type); | |
7700 | |
7701 Dynarr_reset (internal_cache); | |
7702 for (line = 0; line < Dynarr_length (dla); line++) | |
7703 { | |
7704 struct display_line *dl = Dynarr_atp (dla, line); | |
7705 | |
7706 if (dl->modeline) | |
7707 continue; | |
7708 else | |
7709 { | |
7710 struct line_start_cache lsc; | |
434 | 7711 |
826 | 7712 lsc.start = dl->charpos; |
7713 lsc.end = dl->end_charpos; | |
428 | 7714 lsc.height = dl->ascent + dl->descent; |
7715 | |
7716 Dynarr_add (internal_cache, lsc); | |
7717 } | |
7718 } | |
7719 } | |
7720 | |
7721 /* Reset the line cache if necessary. This should be run at the | |
7722 beginning of any function which access the cache. */ | |
7723 | |
7724 static void | |
7725 validate_line_start_cache (struct window *w) | |
7726 { | |
7727 struct buffer *b = XBUFFER (w->buffer); | |
7728 struct frame *f = XFRAME (w->frame); | |
7729 | |
7730 if (!w->line_cache_validation_override) | |
7731 { | |
7732 /* f->extents_changed used to be in here because extent face and | |
4187 | 7733 size changes can cause text shifting. However, the extent |
7734 covering the region is constantly having its face set and | |
7735 priority altered by the mouse code. This means that the line | |
7736 start cache is constantly being invalidated. This is bad | |
7737 since the mouse code also triggers heavy usage of the cache. | |
7738 Since it is an unlikely that f->extents being changed | |
7739 indicates that the cache really needs to be updated and if it | |
7740 does redisplay will catch it pretty quickly we no longer | |
7741 invalidate the cache if it is set. This greatly speeds up | |
7742 dragging out regions with the mouse. */ | |
428 | 7743 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b) |
7744 || f->faces_changed | |
7745 || f->clip_changed) | |
7746 { | |
7747 Dynarr_reset (w->line_start_cache); | |
7748 } | |
7749 } | |
7750 } | |
7751 | |
7752 /* Return the very first buffer position contained in the given | |
7753 window's cache, or -1 if the cache is empty. Assumes that the | |
7754 cache is valid. */ | |
7755 | |
665 | 7756 static Charbpos |
428 | 7757 line_start_cache_start (struct window *w) |
7758 { | |
7759 line_start_cache_dynarr *cache = w->line_start_cache; | |
7760 | |
7761 if (!Dynarr_length (cache)) | |
7762 return -1; | |
7763 else | |
4967 | 7764 return Dynarr_begin (cache)->start; |
428 | 7765 } |
7766 | |
7767 /* Return the very last buffer position contained in the given | |
7768 window's cache, or -1 if the cache is empty. Assumes that the | |
7769 cache is valid. */ | |
7770 | |
665 | 7771 static Charbpos |
428 | 7772 line_start_cache_end (struct window *w) |
7773 { | |
7774 line_start_cache_dynarr *cache = w->line_start_cache; | |
7775 | |
7776 if (!Dynarr_length (cache)) | |
7777 return -1; | |
7778 else | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7779 return Dynarr_lastp (cache)->end; |
428 | 7780 } |
7781 | |
7782 /* Return the index of the line POINT is contained within in window | |
7783 W's line start cache. It will enlarge the cache or move the cache | |
7784 window in order to have POINT be present in the cache. MIN_PAST is | |
7785 a guarantee of the number of entries in the cache present on either | |
7786 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1 | |
7787 then it will be treated as 0, but the cache window will not be | |
7788 allowed to shift. Returns -1 if POINT cannot be found in the cache | |
7789 for any reason. */ | |
7790 | |
7791 int | |
665 | 7792 point_in_line_start_cache (struct window *w, Charbpos point, int min_past) |
428 | 7793 { |
7794 struct buffer *b = XBUFFER (w->buffer); | |
7795 line_start_cache_dynarr *cache = w->line_start_cache; | |
647 | 7796 int top, bottom, pos; |
428 | 7797 |
7798 validate_line_start_cache (w); | |
7799 w->line_cache_validation_override++; | |
7800 | |
7801 /* Let functions pass in negative values, but we still treat -1 | |
7802 specially. */ | |
7803 /* #### bogosity alert */ | |
7804 if (min_past < 0 && min_past != -1) | |
7805 min_past = -min_past; | |
7806 | |
7807 if (!Dynarr_length (cache) || line_start_cache_start (w) > point | |
7808 || line_start_cache_end (w) < point) | |
7809 { | |
7810 int loop; | |
7811 int win_char_height = window_char_height (w, 1); | |
7812 | |
7813 /* Occasionally we get here with a 0 height | |
4187 | 7814 window. find_next_newline_no_quit will abort if we pass it a |
7815 count of 0 so handle that case. */ | |
428 | 7816 if (!win_char_height) |
7817 win_char_height = 1; | |
7818 | |
7819 if (!Dynarr_length (cache)) | |
7820 { | |
665 | 7821 Charbpos from = find_next_newline_no_quit (b, point, -1); |
7822 Charbpos to = find_next_newline_no_quit (b, from, win_char_height); | |
428 | 7823 |
7824 update_line_start_cache (w, from, to, point, 0); | |
7825 | |
7826 if (!Dynarr_length (cache)) | |
7827 { | |
7828 w->line_cache_validation_override--; | |
7829 return -1; | |
7830 } | |
7831 } | |
7832 | |
7833 assert (Dynarr_length (cache)); | |
7834 | |
7835 loop = 0; | |
7836 while (line_start_cache_start (w) > point | |
7837 && (loop < cache_adjustment || min_past == -1)) | |
7838 { | |
665 | 7839 Charbpos from, to; |
428 | 7840 |
7841 from = line_start_cache_start (w); | |
7842 if (from <= BUF_BEGV (b)) | |
7843 break; | |
7844 | |
7845 from = find_next_newline_no_quit (b, from, -win_char_height); | |
7846 to = line_start_cache_end (w); | |
7847 | |
7848 update_line_start_cache (w, from, to, point, 0); | |
7849 loop++; | |
7850 } | |
7851 | |
7852 if (line_start_cache_start (w) > point) | |
7853 { | |
665 | 7854 Charbpos from, to; |
428 | 7855 |
7856 from = find_next_newline_no_quit (b, point, -1); | |
7857 if (from >= BUF_ZV (b)) | |
7858 { | |
7859 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7860 from = to; | |
7861 to = BUF_ZV (b); | |
7862 } | |
7863 else | |
7864 to = find_next_newline_no_quit (b, from, win_char_height); | |
7865 | |
7866 update_line_start_cache (w, from, to, point, 0); | |
7867 } | |
7868 | |
7869 loop = 0; | |
7870 while (line_start_cache_end (w) < point | |
7871 && (loop < cache_adjustment || min_past == -1)) | |
7872 { | |
665 | 7873 Charbpos from, to; |
428 | 7874 |
7875 to = line_start_cache_end (w); | |
7876 if (to >= BUF_ZV (b)) | |
7877 break; | |
7878 | |
7879 from = line_start_cache_end (w); | |
7880 to = find_next_newline_no_quit (b, from, win_char_height); | |
7881 | |
7882 update_line_start_cache (w, from, to, point, 0); | |
7883 loop++; | |
7884 } | |
7885 | |
7886 if (line_start_cache_end (w) < point) | |
7887 { | |
665 | 7888 Charbpos from, to; |
428 | 7889 |
7890 from = find_next_newline_no_quit (b, point, -1); | |
7891 if (from >= BUF_ZV (b)) | |
7892 { | |
7893 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7894 from = to; | |
7895 to = BUF_ZV (b); | |
7896 } | |
7897 else | |
7898 to = find_next_newline_no_quit (b, from, win_char_height); | |
7899 | |
7900 update_line_start_cache (w, from, to, point, 0); | |
7901 } | |
7902 } | |
7903 | |
7904 assert (Dynarr_length (cache)); | |
7905 | |
7906 if (min_past == -1) | |
7907 min_past = 0; | |
7908 | |
7909 /* This could happen if the buffer is narrowed. */ | |
7910 if (line_start_cache_start (w) > point | |
7911 || line_start_cache_end (w) < point) | |
7912 { | |
7913 w->line_cache_validation_override--; | |
7914 return -1; | |
7915 } | |
7916 | |
7917 find_point_loop: | |
7918 | |
7919 top = Dynarr_length (cache) - 1; | |
7920 bottom = 0; | |
7921 | |
7922 while (1) | |
7923 { | |
647 | 7924 int new_pos; |
665 | 7925 Charbpos start, end; |
428 | 7926 |
7927 pos = (bottom + top + 1) >> 1; | |
7928 start = Dynarr_atp (cache, pos)->start; | |
7929 end = Dynarr_atp (cache, pos)->end; | |
7930 | |
7931 if (point >= start && point <= end) | |
7932 { | |
7933 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b)) | |
7934 { | |
665 | 7935 Charbpos from = |
428 | 7936 find_next_newline_no_quit (b, line_start_cache_start (w), |
7937 -min_past - 1); | |
665 | 7938 Charbpos to = line_start_cache_end (w); |
428 | 7939 |
7940 update_line_start_cache (w, from, to, point, 0); | |
7941 goto find_point_loop; | |
7942 } | |
7943 else if ((Dynarr_length (cache) - pos - 1) < min_past | |
7944 && line_start_cache_end (w) < BUF_ZV (b)) | |
7945 { | |
665 | 7946 Charbpos from = line_start_cache_end (w); |
7947 Charbpos to = find_next_newline_no_quit (b, from, | |
428 | 7948 (min_past |
7949 ? min_past | |
7950 : 1)); | |
7951 | |
7952 update_line_start_cache (w, from, to, point, 0); | |
7953 goto find_point_loop; | |
7954 } | |
7955 else | |
7956 { | |
7957 w->line_cache_validation_override--; | |
7958 return pos; | |
7959 } | |
7960 } | |
7961 else if (point > end) | |
7962 bottom = pos + 1; | |
7963 else if (point < start) | |
7964 top = pos - 1; | |
7965 else | |
2500 | 7966 ABORT (); |
428 | 7967 |
7968 new_pos = (bottom + top + 1) >> 1; | |
7969 if (pos == new_pos) | |
7970 { | |
7971 w->line_cache_validation_override--; | |
7972 return -1; | |
7973 } | |
7974 } | |
7975 } | |
7976 | |
7977 /* Return a boolean indicating if POINT would be visible in window W | |
1708 | 7978 if display of the window was to begin at STARTP. If PARTIALLY is |
7979 zero, then if POINT has fewer visible pixels than the window clip, | |
7980 0 is returned; otherwise, 1 is returned if POINT has any visible | |
7981 pixels. */ | |
428 | 7982 int |
1708 | 7983 point_would_be_visible (struct window *w, Charbpos startp, Charbpos point, |
7984 int partially) | |
428 | 7985 { |
7986 struct buffer *b = XBUFFER (w->buffer); | |
430 | 7987 int pixpos = -WINDOW_TEXT_TOP_CLIP(w); |
428 | 7988 int bottom = WINDOW_TEXT_HEIGHT (w); |
7989 int start_elt; | |
7990 | |
7991 /* If point is before the intended start it obviously can't be visible. */ | |
7992 if (point < startp) | |
7993 return 0; | |
7994 | |
7995 /* If point or start are not in the accessible buffer range, then | |
7996 fail. */ | |
7997 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b) | |
7998 || point < BUF_BEGV (b) || point > BUF_ZV (b)) | |
7999 return 0; | |
8000 | |
8001 validate_line_start_cache (w); | |
8002 w->line_cache_validation_override++; | |
8003 | |
8004 start_elt = point_in_line_start_cache (w, startp, 0); | |
8005 if (start_elt == -1) | |
8006 { | |
8007 w->line_cache_validation_override--; | |
8008 return 0; | |
8009 } | |
8010 | |
8011 assert (line_start_cache_start (w) <= startp | |
8012 && line_start_cache_end (w) >= startp); | |
8013 | |
8014 while (1) | |
8015 { | |
8016 int height; | |
8017 | |
8018 /* Expand the cache if necessary. */ | |
8019 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8020 { | |
665 | 8021 Charbpos old_startp = |
428 | 8022 Dynarr_atp (w->line_start_cache, start_elt - 1)->start; |
8023 | |
8024 start_elt = point_in_line_start_cache (w, old_startp, | |
8025 window_char_height (w, 0)); | |
8026 | |
8027 /* We've already actually processed old_startp, so increment | |
4187 | 8028 immediately. */ |
428 | 8029 start_elt++; |
8030 | |
8031 /* If this happens we didn't add any extra elements. Bummer. */ | |
8032 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8033 { | |
8034 w->line_cache_validation_override--; | |
8035 return 0; | |
8036 } | |
8037 } | |
8038 | |
8039 height = Dynarr_atp (w->line_start_cache, start_elt)->height; | |
8040 | |
8041 if (pixpos + height > bottom) | |
8042 { | |
1708 | 8043 if (bottom - pixpos < (partially ? 0 : VERTICAL_CLIP (w, 0))) |
428 | 8044 { |
8045 w->line_cache_validation_override--; | |
8046 return 0; | |
8047 } | |
8048 } | |
8049 | |
8050 pixpos += height; | |
8051 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end) | |
8052 { | |
8053 w->line_cache_validation_override--; | |
8054 return 1; | |
8055 } | |
8056 | |
8057 start_elt++; | |
8058 } | |
8059 } | |
8060 | |
8061 /* For the given window W, if display starts at STARTP, what will be | |
8062 the buffer position at the beginning or end of the last line | |
8063 displayed. The end of the last line is also know as the window end | |
8064 position. | |
8065 | |
442 | 8066 WARNING: It is possible that redisplay failed to layout any lines for the |
8067 windows. Under normal circumstances this is rare. However it seems that it | |
8068 does occur in the following situation: A mouse event has come in and we | |
8069 need to compute its location in a window. That code (in | |
8070 pixel_to_glyph_translation) already can handle 0 as an error return value. | |
8071 | |
428 | 8072 #### With a little work this could probably be reworked as just a |
8073 call to start_with_line_at_pixpos. */ | |
8074 | |
665 | 8075 static Charbpos |
8076 start_end_of_last_line (struct window *w, Charbpos startp, int end, | |
4187 | 8077 int may_error) |
428 | 8078 { |
8079 struct buffer *b = XBUFFER (w->buffer); | |
8080 line_start_cache_dynarr *cache = w->line_start_cache; | |
8081 int pixpos = 0; | |
8082 int bottom = WINDOW_TEXT_HEIGHT (w); | |
665 | 8083 Charbpos cur_start; |
428 | 8084 int start_elt; |
8085 | |
8086 validate_line_start_cache (w); | |
8087 w->line_cache_validation_override++; | |
8088 | |
8089 if (startp < BUF_BEGV (b)) | |
8090 startp = BUF_BEGV (b); | |
8091 else if (startp > BUF_ZV (b)) | |
8092 startp = BUF_ZV (b); | |
8093 cur_start = startp; | |
8094 | |
8095 start_elt = point_in_line_start_cache (w, cur_start, 0); | |
8096 if (start_elt == -1) | |
442 | 8097 return may_error ? 0 : startp; |
428 | 8098 |
8099 while (1) | |
8100 { | |
8101 int height = Dynarr_atp (cache, start_elt)->height; | |
8102 | |
8103 cur_start = Dynarr_atp (cache, start_elt)->start; | |
8104 | |
8105 if (pixpos + height > bottom) | |
8106 { | |
8107 /* Adjust for any possible clip. */ | |
8108 if (bottom - pixpos < VERTICAL_CLIP (w, 0)) | |
8109 start_elt--; | |
8110 | |
8111 if (start_elt < 0) | |
8112 { | |
8113 w->line_cache_validation_override--; | |
8114 if (end) | |
8115 return BUF_ZV (b); | |
8116 else | |
8117 return BUF_BEGV (b); | |
8118 } | |
8119 else | |
8120 { | |
8121 w->line_cache_validation_override--; | |
8122 if (end) | |
8123 return Dynarr_atp (cache, start_elt)->end; | |
8124 else | |
8125 return Dynarr_atp (cache, start_elt)->start; | |
8126 } | |
8127 } | |
8128 | |
8129 pixpos += height; | |
8130 start_elt++; | |
8131 if (start_elt == Dynarr_length (cache)) | |
8132 { | |
665 | 8133 Charbpos from = line_start_cache_end (w); |
428 | 8134 int win_char_height = window_char_height (w, 0); |
665 | 8135 Charbpos to = find_next_newline_no_quit (b, from, |
428 | 8136 (win_char_height |
8137 ? win_char_height | |
8138 : 1)); | |
8139 | |
8140 /* We've hit the end of the bottom so that's what it is. */ | |
8141 if (from >= BUF_ZV (b)) | |
8142 { | |
8143 w->line_cache_validation_override--; | |
8144 return BUF_ZV (b); | |
8145 } | |
8146 | |
8147 update_line_start_cache (w, from, to, BUF_PT (b), 0); | |
8148 | |
8149 /* Updating the cache invalidates any current indexes. */ | |
8150 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1; | |
8151 } | |
8152 } | |
8153 } | |
8154 | |
8155 /* For the given window W, if display starts at STARTP, what will be | |
8156 the buffer position at the beginning of the last line displayed. */ | |
8157 | |
665 | 8158 Charbpos |
8159 start_of_last_line (struct window *w, Charbpos startp) | |
428 | 8160 { |
442 | 8161 return start_end_of_last_line (w, startp, 0 , 0); |
428 | 8162 } |
8163 | |
8164 /* For the given window W, if display starts at STARTP, what will be | |
8165 the buffer position at the end of the last line displayed. This is | |
8166 also know as the window end position. */ | |
8167 | |
665 | 8168 Charbpos |
8169 end_of_last_line (struct window *w, Charbpos startp) | |
428 | 8170 { |
442 | 8171 return start_end_of_last_line (w, startp, 1, 0); |
428 | 8172 } |
8173 | |
665 | 8174 static Charbpos |
8175 end_of_last_line_may_error (struct window *w, Charbpos startp) | |
442 | 8176 { |
8177 return start_end_of_last_line (w, startp, 1, 1); | |
8178 } | |
8179 | |
8180 | |
428 | 8181 /* For window W, what does the starting position have to be so that |
8182 the line containing POINT will cover pixel position PIXPOS. */ | |
8183 | |
665 | 8184 Charbpos |
8185 start_with_line_at_pixpos (struct window *w, Charbpos point, int pixpos) | |
428 | 8186 { |
8187 struct buffer *b = XBUFFER (w->buffer); | |
8188 int cur_elt; | |
665 | 8189 Charbpos cur_pos, prev_pos = point; |
428 | 8190 int point_line_height; |
8191 int pixheight = pixpos - WINDOW_TEXT_TOP (w); | |
8192 | |
8193 validate_line_start_cache (w); | |
8194 w->line_cache_validation_override++; | |
8195 | |
8196 cur_elt = point_in_line_start_cache (w, point, 0); | |
8197 /* #### See comment in update_line_start_cache about big minibuffers. */ | |
8198 if (cur_elt < 0) | |
8199 { | |
8200 w->line_cache_validation_override--; | |
8201 return point; | |
8202 } | |
8203 | |
8204 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8205 | |
8206 while (1) | |
8207 { | |
8208 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8209 | |
8210 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8211 | |
8212 /* Do not take into account the value of vertical_clip here. | |
4187 | 8213 That is the responsibility of the calling functions. */ |
428 | 8214 if (pixheight < 0) |
8215 { | |
8216 w->line_cache_validation_override--; | |
8217 if (-pixheight > point_line_height) | |
8218 /* We can't make the target line cover pixpos, so put it | |
8219 above pixpos. That way it will at least be visible. */ | |
8220 return prev_pos; | |
8221 else | |
8222 return cur_pos; | |
8223 } | |
8224 | |
8225 cur_elt--; | |
8226 while (cur_elt < 0) | |
8227 { | |
665 | 8228 Charbpos from, to; |
428 | 8229 int win_char_height; |
8230 | |
8231 if (cur_pos <= BUF_BEGV (b)) | |
8232 { | |
8233 w->line_cache_validation_override--; | |
8234 return BUF_BEGV (b); | |
8235 } | |
8236 | |
8237 win_char_height = window_char_height (w, 0); | |
8238 if (!win_char_height) | |
8239 win_char_height = 1; | |
8240 | |
8241 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); | |
8242 to = line_start_cache_end (w); | |
8243 update_line_start_cache (w, from, to, point, 0); | |
8244 | |
8245 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; | |
8246 assert (cur_elt >= -1); | |
8247 /* This used to be cur_elt>=0 under the assumption that if | |
8248 point is in the top line and not at BUF_BEGV, then | |
434 | 8249 setting the window_start to a newline before the start of |
428 | 8250 the first line will always cause scrolling. |
8251 | |
8252 However in my (jv) opinion this is wrong. That new line | |
8253 can be hidden in various ways: invisible extents, an | |
8254 explicit window-start not at a newline character etc. | |
8255 The existence of those are indeed known to create crashes | |
8256 on that assert. So we have no option but to continue the | |
8257 search if we found point at the top of the line_start_cache | |
8258 again. */ | |
4967 | 8259 cur_pos = Dynarr_begin (w->line_start_cache)->start; |
428 | 8260 } |
8261 prev_pos = cur_pos; | |
8262 } | |
8263 } | |
8264 | |
8265 /* For window W, what does the starting position have to be so that | |
8266 the line containing point is on display line LINE. If LINE is | |
8267 positive it is considered to be the number of lines from the top of | |
8268 the window (0 is the top line). If it is negative the number is | |
8269 considered to be the number of lines from the bottom (-1 is the | |
8270 bottom line). */ | |
8271 | |
665 | 8272 Charbpos |
8273 start_with_point_on_display_line (struct window *w, Charbpos point, int line) | |
428 | 8274 { |
8275 validate_line_start_cache (w); | |
8276 w->line_cache_validation_override++; | |
8277 | |
8278 if (line >= 0) | |
8279 { | |
8280 int cur_elt = point_in_line_start_cache (w, point, line); | |
8281 | |
8282 if (cur_elt - line < 0) | |
8283 cur_elt = 0; /* Hit the top */ | |
8284 else | |
8285 cur_elt -= line; | |
8286 | |
8287 w->line_cache_validation_override--; | |
8288 return Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8289 } | |
8290 else | |
8291 { | |
8292 /* The calculated value of pixpos is correct for the bottom line | |
4187 | 8293 or what we want when line is -1. Therefore we subtract one |
8294 because we have already handled one line. */ | |
428 | 8295 int new_line = -line - 1; |
8296 int cur_elt = point_in_line_start_cache (w, point, new_line); | |
8297 int pixpos = WINDOW_TEXT_BOTTOM (w); | |
665 | 8298 Charbpos retval, search_point; |
428 | 8299 |
8300 /* If scroll_on_clipped_lines is false, the last "visible" line of | |
4187 | 8301 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1. |
8302 If s_o_c_l is true, then we don't want to count a clipped | |
8303 line, so back up from the bottom by the height of the line | |
8304 containing point. */ | |
428 | 8305 if (scroll_on_clipped_lines) |
8306 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8307 else | |
8308 pixpos -= 1; | |
8309 | |
8310 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache)) | |
8311 { | |
8312 /* Hit the bottom of the buffer. */ | |
8313 int adjustment = | |
8314 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1; | |
8315 Lisp_Object window; | |
8316 int defheight; | |
8317 | |
793 | 8318 window = wrap_window (w); |
428 | 8319 default_face_height_and_width (window, &defheight, 0); |
8320 | |
8321 cur_elt = Dynarr_length (w->line_start_cache) - 1; | |
8322 | |
8323 pixpos -= (adjustment * defheight); | |
8324 if (pixpos < WINDOW_TEXT_TOP (w)) | |
8325 pixpos = WINDOW_TEXT_TOP (w); | |
8326 } | |
8327 else | |
8328 cur_elt = cur_elt + new_line; | |
8329 | |
8330 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8331 | |
8332 retval = start_with_line_at_pixpos (w, search_point, pixpos); | |
8333 w->line_cache_validation_override--; | |
8334 return retval; | |
8335 } | |
8336 } | |
8337 | |
8338 /* This is used to speed up vertical scrolling by caching the known | |
8339 buffer starting positions for display lines. This allows the | |
8340 scrolling routines to avoid costly calls to regenerate_window. If | |
8341 NO_REGEN is true then it will only add the values in the DESIRED | |
8342 display structs which are in the given range. | |
8343 | |
8344 Note also that the FROM/TO values are minimums. It is possible | |
8345 that this function will actually add information outside of the | |
8346 lines containing those positions. This can't hurt but it could | |
8347 possibly help. | |
8348 | |
8349 #### We currently force the cache to have only 1 contiguous region. | |
8350 It might help to make the cache a dynarr of caches so that we can | |
8351 cover more areas. This might, however, turn out to be a lot of | |
8352 overhead for too little gain. */ | |
8353 | |
8354 static void | |
665 | 8355 update_line_start_cache (struct window *w, Charbpos from, Charbpos to, |
8356 Charbpos point, int no_regen) | |
428 | 8357 { |
8358 struct buffer *b = XBUFFER (w->buffer); | |
8359 line_start_cache_dynarr *cache = w->line_start_cache; | |
665 | 8360 Charbpos low_bound, high_bound; |
428 | 8361 |
8362 validate_line_start_cache (w); | |
8363 w->line_cache_validation_override++; | |
8364 | |
8365 if (from < BUF_BEGV (b)) | |
8366 from = BUF_BEGV (b); | |
8367 if (to > BUF_ZV (b)) | |
8368 to = BUF_ZV (b); | |
8369 | |
8370 if (from > to) | |
8371 { | |
8372 w->line_cache_validation_override--; | |
8373 return; | |
8374 } | |
8375 | |
8376 if (Dynarr_length (cache)) | |
8377 { | |
8378 low_bound = line_start_cache_start (w); | |
8379 high_bound = line_start_cache_end (w); | |
8380 | |
8381 /* Check to see if the desired range is already in the cache. */ | |
8382 if (from >= low_bound && to <= high_bound) | |
8383 { | |
8384 w->line_cache_validation_override--; | |
8385 return; | |
8386 } | |
8387 | |
8388 /* Check to make sure that the desired range is adjacent to the | |
8389 current cache. If not, invalidate the cache. */ | |
8390 if (to < low_bound || from > high_bound) | |
8391 { | |
8392 Dynarr_reset (cache); | |
8393 low_bound = high_bound = -1; | |
8394 } | |
8395 } | |
8396 else | |
8397 { | |
8398 low_bound = high_bound = -1; | |
8399 } | |
8400 | |
8401 w->line_cache_last_updated = make_int (BUF_MODIFF (b)); | |
8402 | |
8403 /* This could be integrated into the next two sections, but it is easier | |
8404 to follow what's going on by having it separate. */ | |
8405 if (no_regen) | |
8406 { | |
665 | 8407 Charbpos start, end; |
428 | 8408 |
8409 update_internal_cache_list (w, DESIRED_DISP); | |
8410 if (!Dynarr_length (internal_cache)) | |
8411 { | |
8412 w->line_cache_validation_override--; | |
8413 return; | |
8414 } | |
8415 | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8416 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
|
8417 end = Dynarr_lastp (internal_cache)->end; |
428 | 8418 |
8419 /* We aren't allowed to generate additional information to fill in | |
4187 | 8420 gaps, so if the DESIRED structs don't overlap the cache, reset the |
8421 cache. */ | |
428 | 8422 if (Dynarr_length (cache)) |
8423 { | |
8424 if (end < low_bound || start > high_bound) | |
8425 Dynarr_reset (cache); | |
8426 | |
8427 /* #### What should really happen if what we are doing is | |
4187 | 8428 extending a line (the last line)? */ |
428 | 8429 if (Dynarr_length (cache) == 1 |
8430 && Dynarr_length (internal_cache) == 1) | |
8431 Dynarr_reset (cache); | |
8432 } | |
8433 | |
8434 if (!Dynarr_length (cache)) | |
8435 { | |
4967 | 8436 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8437 Dynarr_length (internal_cache)); |
8438 w->line_cache_validation_override--; | |
8439 return; | |
8440 } | |
8441 | |
8442 /* An extra check just in case the calling function didn't pass in | |
4187 | 8443 the bounds of the DESIRED structs in the first place. */ |
428 | 8444 if (start >= low_bound && end <= high_bound) |
8445 { | |
8446 w->line_cache_validation_override--; | |
8447 return; | |
8448 } | |
8449 | |
8450 /* At this point we know that the internal cache partially overlaps | |
4187 | 8451 the main cache. */ |
428 | 8452 if (start < low_bound) |
8453 { | |
8454 int ic_elt = Dynarr_length (internal_cache) - 1; | |
8455 while (ic_elt >= 0) | |
8456 { | |
8457 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound) | |
8458 break; | |
8459 else | |
8460 ic_elt--; | |
8461 } | |
8462 | |
8463 if (!(ic_elt >= 0)) | |
8464 { | |
8465 Dynarr_reset (cache); | |
4967 | 8466 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8467 Dynarr_length (internal_cache)); |
8468 w->line_cache_validation_override--; | |
8469 return; | |
8470 } | |
8471 | |
4967 | 8472 Dynarr_insert_many_at_start (cache, Dynarr_begin (internal_cache), |
428 | 8473 ic_elt + 1); |
8474 } | |
8475 | |
8476 if (end > high_bound) | |
8477 { | |
8478 int ic_elt = 0; | |
8479 | |
8480 while (ic_elt < Dynarr_length (internal_cache)) | |
8481 { | |
8482 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound) | |
8483 break; | |
8484 else | |
8485 ic_elt++; | |
8486 } | |
8487 | |
8488 if (!(ic_elt < Dynarr_length (internal_cache))) | |
8489 { | |
8490 Dynarr_reset (cache); | |
4967 | 8491 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8492 Dynarr_length (internal_cache)); |
8493 w->line_cache_validation_override--; | |
8494 return; | |
8495 } | |
8496 | |
8497 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), | |
8498 Dynarr_length (internal_cache) - ic_elt); | |
8499 } | |
8500 | |
8501 w->line_cache_validation_override--; | |
8502 return; | |
8503 } | |
8504 | |
8505 if (!Dynarr_length (cache) || from < low_bound) | |
8506 { | |
665 | 8507 Charbpos startp = find_next_newline_no_quit (b, from, -1); |
428 | 8508 int marker = 0; |
8509 int old_lb = low_bound; | |
8510 | |
8511 while (startp < old_lb || low_bound == -1) | |
8512 { | |
8513 int ic_elt; | |
4187 | 8514 Charbpos new_startp; |
428 | 8515 |
8516 regenerate_window (w, startp, point, CMOTION_DISP); | |
8517 update_internal_cache_list (w, CMOTION_DISP); | |
8518 | |
8519 /* If this assert is triggered then regenerate_window failed | |
4187 | 8520 to layout a single line. This is not possible since we |
442 | 8521 force at least a single line to be layout for CMOTION_DISP */ |
8522 assert (Dynarr_length (internal_cache)); | |
4967 | 8523 assert (startp == Dynarr_begin (internal_cache)->start); |
428 | 8524 |
8525 ic_elt = Dynarr_length (internal_cache) - 1; | |
8526 if (low_bound != -1) | |
8527 { | |
8528 while (ic_elt >= 0) | |
8529 { | |
8530 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb) | |
8531 break; | |
8532 else | |
8533 ic_elt--; | |
8534 } | |
8535 } | |
8536 assert (ic_elt >= 0); | |
8537 | |
8538 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1; | |
8539 | |
4187 | 8540 /* |
8541 * Handle invisible text properly: | |
8542 * If the last line we're inserting has the same end as the | |
8543 * line before which it will be added, merge the two lines. | |
8544 */ | |
8545 if (Dynarr_length (cache) && | |
8546 Dynarr_atp (internal_cache, ic_elt)->end == | |
8547 Dynarr_atp (cache, marker)->end) | |
8548 { | |
8549 Dynarr_atp (cache, marker)->start | |
8550 = Dynarr_atp (internal_cache, ic_elt)->start; | |
8551 Dynarr_atp (cache, marker)->height | |
8552 = Dynarr_atp (internal_cache, ic_elt)->height; | |
8553 ic_elt--; | |
8554 } | |
8555 | |
8556 if (ic_elt >= 0) /* we still have lines to add.. */ | |
8557 { | |
4967 | 8558 Dynarr_insert_many (cache, Dynarr_begin (internal_cache), |
4187 | 8559 ic_elt + 1, marker); |
8560 marker += (ic_elt + 1); | |
8561 } | |
428 | 8562 |
8563 if (startp < low_bound || low_bound == -1) | |
8564 low_bound = startp; | |
8565 startp = new_startp; | |
8566 if (startp > BUF_ZV (b)) | |
8567 { | |
8568 w->line_cache_validation_override--; | |
8569 return; | |
8570 } | |
8571 } | |
8572 } | |
8573 | |
8574 assert (Dynarr_length (cache)); | |
8575 assert (from >= low_bound); | |
8576 | |
8577 /* Readjust the high_bound to account for any changes made while | |
8578 correcting the low_bound. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8579 high_bound = Dynarr_lastp (cache)->end; |
428 | 8580 |
8581 if (to > high_bound) | |
8582 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8583 Charbpos startp = Dynarr_lastp (cache)->end + 1; |
428 | 8584 |
8585 do | |
8586 { | |
8587 regenerate_window (w, startp, point, CMOTION_DISP); | |
8588 update_internal_cache_list (w, CMOTION_DISP); | |
8589 | |
8590 /* See comment above about regenerate_window failing. */ | |
8591 assert (Dynarr_length (internal_cache)); | |
8592 | |
4967 | 8593 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8594 Dynarr_length (internal_cache)); |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8595 high_bound = Dynarr_lastp (cache)->end; |
428 | 8596 startp = high_bound + 1; |
8597 } | |
8598 while (to > high_bound); | |
8599 } | |
8600 | |
8601 w->line_cache_validation_override--; | |
8602 assert (to <= high_bound); | |
8603 } | |
8604 | |
8605 | |
8606 /* Given x and y coordinates in characters, relative to a window, | |
8607 return the pixel location corresponding to those coordinates. The | |
8608 pixel location returned is the center of the given character | |
8609 position. The pixel values are generated relative to the window, | |
8610 not the frame. | |
8611 | |
8612 The modeline is considered to be part of the window. */ | |
8613 | |
8614 void | |
8615 glyph_to_pixel_translation (struct window *w, int char_x, int char_y, | |
8616 int *pix_x, int *pix_y) | |
8617 { | |
8618 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
8619 int num_disp_lines, modeline; | |
8620 Lisp_Object window; | |
8621 int defheight, defwidth; | |
8622 | |
793 | 8623 window = wrap_window (w); |
428 | 8624 default_face_height_and_width (window, &defheight, &defwidth); |
8625 | |
8626 /* If we get a bogus value indicating somewhere above or to the left of | |
8627 the window, use the first window line or character position | |
8628 instead. */ | |
8629 if (char_y < 0) | |
8630 char_y = 0; | |
8631 if (char_x < 0) | |
8632 char_x = 0; | |
8633 | |
8634 num_disp_lines = Dynarr_length (dla); | |
8635 modeline = 0; | |
8636 if (num_disp_lines) | |
8637 { | |
4967 | 8638 if (Dynarr_begin (dla)->modeline) |
428 | 8639 { |
8640 num_disp_lines--; | |
8641 modeline = 1; | |
8642 } | |
8643 } | |
8644 | |
8645 /* First check if the y position intersects the display lines. */ | |
8646 if (char_y < num_disp_lines) | |
8647 { | |
8648 struct display_line *dl = Dynarr_atp (dla, char_y + modeline); | |
8649 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
8650 | |
8651 *pix_y = (dl->ypos - dl->ascent + | |
647 | 8652 ((dl->ascent + dl->descent - dl->clip) >> 1)); |
428 | 8653 |
8654 if (char_x < Dynarr_length (db->runes)) | |
8655 { | |
8656 struct rune *rb = Dynarr_atp (db->runes, char_x); | |
8657 | |
8658 *pix_x = rb->xpos + (rb->width >> 1); | |
8659 } | |
8660 else | |
8661 { | |
8662 int last_rune = Dynarr_length (db->runes) - 1; | |
8663 struct rune *rb = Dynarr_atp (db->runes, last_rune); | |
8664 | |
8665 char_x -= last_rune; | |
8666 | |
8667 *pix_x = rb->xpos + rb->width; | |
8668 *pix_x += ((char_x - 1) * defwidth); | |
8669 *pix_x += (defwidth >> 1); | |
8670 } | |
8671 } | |
8672 else | |
8673 { | |
8674 /* It didn't intersect, so extrapolate. #### For now, we include the | |
8675 modeline in this since we don't have true character positions in | |
8676 it. */ | |
8677 | |
8678 if (!Dynarr_length (w->face_cachels)) | |
8679 reset_face_cachels (w); | |
8680 | |
8681 char_y -= num_disp_lines; | |
8682 | |
8683 if (Dynarr_length (dla)) | |
8684 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8685 struct display_line *dl = Dynarr_lastp (dla); |
428 | 8686 *pix_y = dl->ypos + dl->descent - dl->clip; |
8687 } | |
8688 else | |
8689 *pix_y = WINDOW_TEXT_TOP (w); | |
8690 | |
8691 *pix_y += (char_y * defheight); | |
8692 *pix_y += (defheight >> 1); | |
8693 | |
8694 *pix_x = WINDOW_TEXT_LEFT (w); | |
8695 /* Don't adjust by one because this is still the unadjusted value. */ | |
8696 *pix_x += (char_x * defwidth); | |
8697 *pix_x += (defwidth >> 1); | |
8698 } | |
8699 | |
8700 if (*pix_x > w->pixel_left + w->pixel_width) | |
8701 *pix_x = w->pixel_left + w->pixel_width; | |
8702 if (*pix_y > w->pixel_top + w->pixel_height) | |
8703 *pix_y = w->pixel_top + w->pixel_height; | |
8704 | |
8705 *pix_x -= w->pixel_left; | |
8706 *pix_y -= w->pixel_top; | |
8707 } | |
8708 | |
8709 /* Given a display line and a position, determine if there is a glyph | |
8710 there and return information about it if there is. */ | |
8711 | |
8712 static void | |
8713 get_position_object (struct display_line *dl, Lisp_Object *obj1, | |
8714 Lisp_Object *obj2, int x_coord, int *low_x_coord, | |
8715 int *high_x_coord) | |
8716 { | |
8717 struct display_block *db; | |
8718 int elt; | |
8719 int block = | |
8720 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0); | |
8721 | |
8722 /* We use get_next_display_block to get the actual display block | |
8723 that would be displayed at x_coord. */ | |
8724 | |
8725 if (block == NO_BLOCK) | |
8726 return; | |
8727 else | |
8728 db = Dynarr_atp (dl->display_blocks, block); | |
8729 | |
8730 for (elt = 0; elt < Dynarr_length (db->runes); elt++) | |
8731 { | |
8732 struct rune *rb = Dynarr_atp (db->runes, elt); | |
8733 | |
8734 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) | |
8735 { | |
8736 if (rb->type == RUNE_DGLYPH) | |
8737 { | |
8738 *obj1 = rb->object.dglyph.glyph; | |
8739 *obj2 = rb->object.dglyph.extent; | |
8740 } | |
8741 else | |
8742 { | |
8743 *obj1 = Qnil; | |
8744 *obj2 = Qnil; | |
8745 } | |
8746 | |
8747 if (low_x_coord) | |
8748 *low_x_coord = rb->xpos; | |
8749 if (high_x_coord) | |
8750 *high_x_coord = rb->xpos + rb->width; | |
8751 | |
8752 return; | |
8753 } | |
8754 } | |
8755 } | |
8756 | |
8757 #define UPDATE_CACHE_RETURN \ | |
8758 do { \ | |
8759 d->pixel_to_glyph_cache.valid = 1; \ | |
8760 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \ | |
8761 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \ | |
8762 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \ | |
8763 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \ | |
8764 d->pixel_to_glyph_cache.frame = f; \ | |
8765 d->pixel_to_glyph_cache.col = *col; \ | |
8766 d->pixel_to_glyph_cache.row = *row; \ | |
8767 d->pixel_to_glyph_cache.obj_x = *obj_x; \ | |
8768 d->pixel_to_glyph_cache.obj_y = *obj_y; \ | |
8769 d->pixel_to_glyph_cache.w = *w; \ | |
826 | 8770 d->pixel_to_glyph_cache.charpos = *charpos; \ |
428 | 8771 d->pixel_to_glyph_cache.closest = *closest; \ |
8772 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \ | |
8773 d->pixel_to_glyph_cache.obj1 = *obj1; \ | |
8774 d->pixel_to_glyph_cache.obj2 = *obj2; \ | |
8775 d->pixel_to_glyph_cache.retval = position; \ | |
8776 RETURN_SANS_WARNINGS position; \ | |
8777 } while (0) | |
8778 | |
8779 /* Given x and y coordinates in pixels relative to a frame, return | |
8780 information about what is located under those coordinates. | |
8781 | |
8782 The return value will be one of: | |
8783 | |
8784 OVER_TOOLBAR: over one of the 4 frame toolbars | |
8785 OVER_MODELINE: over a modeline | |
8786 OVER_BORDER: over an internal border | |
8787 OVER_NOTHING: over the text area, but not over text | |
8788 OVER_OUTSIDE: outside of the frame border | |
8789 OVER_TEXT: over text in the text area | |
8790 | |
8791 OBJ1 is one of | |
8792 | |
8793 -- a toolbar button | |
8794 -- a glyph | |
8795 -- nil if the coordinates are not over a glyph or a toolbar button. | |
8796 | |
8797 OBJ2 is one of | |
8798 | |
8799 -- an extent, if the coordinates are over a glyph in the text area | |
8800 -- nil otherwise. | |
8801 | |
8802 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the | |
8803 equivalent coordinates relative to the upper-left corner of the glyph. | |
8804 | |
8805 If the coordinates are over a character, OBJ_X and OBJ_Y give the | |
8806 equivalent coordinates relative to the upper-left corner of the character. | |
8807 | |
8808 Otherwise, OBJ_X and OBJ_Y are undefined. | |
8809 */ | |
8810 | |
8811 int | |
8812 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, | |
8813 int *col, int *row, int *obj_x, int *obj_y, | |
826 | 8814 struct window **w, Charbpos *charpos, |
665 | 8815 Charbpos *closest, Charcount *modeline_closest, |
428 | 8816 Lisp_Object *obj1, Lisp_Object *obj2) |
8817 { | |
8818 struct device *d; | |
8819 struct pixel_to_glyph_translation_cache *cache; | |
8820 Lisp_Object window; | |
8821 int frm_left, frm_right, frm_top, frm_bottom; | |
8822 int low_x_coord, high_x_coord, low_y_coord, high_y_coord; | |
8823 int position = OVER_NOTHING; | |
8824 int device_check_failed = 0; | |
8825 display_line_dynarr *dla; | |
8826 | |
8827 /* This is a safety valve in case this got called with a frame in | |
8828 the middle of being deleted. */ | |
8829 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device))) | |
8830 { | |
8831 device_check_failed = 1; | |
8832 d = NULL, cache = NULL; /* Warning suppression */ | |
8833 } | |
8834 else | |
8835 { | |
8836 d = XDEVICE (f->device); | |
8837 cache = &d->pixel_to_glyph_cache; | |
8838 } | |
8839 | |
8840 if (!device_check_failed | |
8841 && cache->valid | |
8842 && cache->frame == f | |
8843 && cache->low_x_coord <= x_coord | |
8844 && cache->high_x_coord > x_coord | |
8845 && cache->low_y_coord <= y_coord | |
8846 && cache->high_y_coord > y_coord) | |
8847 { | |
8848 *col = cache->col; | |
8849 *row = cache->row; | |
8850 *obj_x = cache->obj_x; | |
8851 *obj_y = cache->obj_y; | |
8852 *w = cache->w; | |
826 | 8853 *charpos = cache->charpos; |
428 | 8854 *closest = cache->closest; |
8855 *modeline_closest = cache->modeline_closest; | |
8856 *obj1 = cache->obj1; | |
8857 *obj2 = cache->obj2; | |
8858 | |
8859 return cache->retval; | |
8860 } | |
8861 else | |
8862 { | |
8863 *col = 0; | |
8864 *row = 0; | |
8865 *obj_x = 0; | |
8866 *obj_y = 0; | |
8867 *w = 0; | |
826 | 8868 *charpos = 0; |
428 | 8869 *closest = 0; |
8870 *modeline_closest = -1; | |
8871 *obj1 = Qnil; | |
8872 *obj2 = Qnil; | |
8873 | |
8874 low_x_coord = x_coord; | |
8875 high_x_coord = x_coord + 1; | |
8876 low_y_coord = y_coord; | |
8877 high_y_coord = y_coord + 1; | |
8878 } | |
8879 | |
8880 if (device_check_failed) | |
8881 return OVER_NOTHING; | |
8882 | |
8883 frm_left = FRAME_LEFT_BORDER_END (f); | |
8884 frm_right = FRAME_RIGHT_BORDER_START (f); | |
8885 frm_top = FRAME_TOP_BORDER_END (f); | |
8886 frm_bottom = FRAME_BOTTOM_BORDER_START (f); | |
8887 | |
8888 /* Check if the mouse is outside of the text area actually used by | |
8889 redisplay. */ | |
8890 if (y_coord < frm_top) | |
8891 { | |
8892 if (y_coord >= FRAME_TOP_BORDER_START (f)) | |
8893 { | |
8894 low_y_coord = FRAME_TOP_BORDER_START (f); | |
8895 high_y_coord = frm_top; | |
8896 position = OVER_BORDER; | |
8897 } | |
8898 else if (y_coord >= 0) | |
8899 { | |
8900 low_y_coord = 0; | |
8901 high_y_coord = FRAME_TOP_BORDER_START (f); | |
8902 position = OVER_TOOLBAR; | |
8903 } | |
8904 else | |
8905 { | |
8906 low_y_coord = y_coord; | |
8907 high_y_coord = 0; | |
8908 position = OVER_OUTSIDE; | |
8909 } | |
8910 } | |
8911 else if (y_coord >= frm_bottom) | |
8912 { | |
8913 if (y_coord < FRAME_BOTTOM_BORDER_END (f)) | |
8914 { | |
8915 low_y_coord = frm_bottom; | |
8916 high_y_coord = FRAME_BOTTOM_BORDER_END (f); | |
8917 position = OVER_BORDER; | |
8918 } | |
8919 else if (y_coord < FRAME_PIXHEIGHT (f)) | |
8920 { | |
8921 low_y_coord = FRAME_BOTTOM_BORDER_END (f); | |
8922 high_y_coord = FRAME_PIXHEIGHT (f); | |
8923 position = OVER_TOOLBAR; | |
8924 } | |
8925 else | |
8926 { | |
8927 low_y_coord = FRAME_PIXHEIGHT (f); | |
8928 high_y_coord = y_coord; | |
8929 position = OVER_OUTSIDE; | |
8930 } | |
8931 } | |
8932 | |
8933 if (position != OVER_TOOLBAR && position != OVER_BORDER) | |
8934 { | |
8935 if (x_coord < frm_left) | |
8936 { | |
8937 if (x_coord >= FRAME_LEFT_BORDER_START (f)) | |
8938 { | |
8939 low_x_coord = FRAME_LEFT_BORDER_START (f); | |
8940 high_x_coord = frm_left; | |
8941 position = OVER_BORDER; | |
8942 } | |
8943 else if (x_coord >= 0) | |
8944 { | |
8945 low_x_coord = 0; | |
8946 high_x_coord = FRAME_LEFT_BORDER_START (f); | |
8947 position = OVER_TOOLBAR; | |
8948 } | |
8949 else | |
8950 { | |
8951 low_x_coord = x_coord; | |
8952 high_x_coord = 0; | |
8953 position = OVER_OUTSIDE; | |
8954 } | |
8955 } | |
8956 else if (x_coord >= frm_right) | |
8957 { | |
8958 if (x_coord < FRAME_RIGHT_BORDER_END (f)) | |
8959 { | |
8960 low_x_coord = frm_right; | |
8961 high_x_coord = FRAME_RIGHT_BORDER_END (f); | |
8962 position = OVER_BORDER; | |
8963 } | |
8964 else if (x_coord < FRAME_PIXWIDTH (f)) | |
8965 { | |
8966 low_x_coord = FRAME_RIGHT_BORDER_END (f); | |
8967 high_x_coord = FRAME_PIXWIDTH (f); | |
8968 position = OVER_TOOLBAR; | |
8969 } | |
8970 else | |
8971 { | |
8972 low_x_coord = FRAME_PIXWIDTH (f); | |
8973 high_x_coord = x_coord; | |
8974 position = OVER_OUTSIDE; | |
8975 } | |
8976 } | |
8977 } | |
8978 | |
8979 #ifdef HAVE_TOOLBARS | |
8980 if (position == OVER_TOOLBAR) | |
8981 { | |
8982 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord); | |
8983 *obj2 = Qnil; | |
8984 *w = 0; | |
8985 UPDATE_CACHE_RETURN; | |
8986 } | |
8987 #endif /* HAVE_TOOLBARS */ | |
8988 | |
8989 /* We still have to return the window the pointer is next to and its | |
8990 relative y position even if it is outside the x boundary. */ | |
8991 if (x_coord < frm_left) | |
8992 x_coord = frm_left; | |
8993 else if (x_coord > frm_right) | |
8994 x_coord = frm_right; | |
8995 | |
8996 /* Same in reverse. */ | |
8997 if (y_coord < frm_top) | |
8998 y_coord = frm_top; | |
8999 else if (y_coord > frm_bottom) | |
9000 y_coord = frm_bottom; | |
9001 | |
9002 /* Find what window the given coordinates are actually in. */ | |
9003 window = f->root_window; | |
9004 *w = find_window_by_pixel_pos (x_coord, y_coord, window); | |
9005 | |
9006 /* If we didn't find a window, we're done. */ | |
9007 if (!*w) | |
9008 { | |
9009 UPDATE_CACHE_RETURN; | |
9010 } | |
9011 else if (position != OVER_NOTHING) | |
9012 { | |
9013 *closest = 0; | |
9014 *modeline_closest = -1; | |
9015 | |
9016 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) | |
9017 { | |
9018 *w = 0; | |
9019 UPDATE_CACHE_RETURN; | |
9020 } | |
9021 } | |
9022 | |
9023 /* Check if the window is a minibuffer but isn't active. */ | |
9024 if (MINI_WINDOW_P (*w) && !minibuf_level) | |
9025 { | |
9026 /* Must reset the window value since some callers will ignore | |
4187 | 9027 the return value if it is set. */ |
428 | 9028 *w = 0; |
9029 UPDATE_CACHE_RETURN; | |
9030 } | |
9031 | |
9032 /* See if the point is over window vertical divider */ | |
9033 if (window_needs_vertical_divider (*w)) | |
9034 { | |
9035 int div_x_high = WINDOW_RIGHT (*w); | |
9036 int div_x_low = div_x_high - window_divider_width (*w); | |
9037 int div_y_high = WINDOW_BOTTOM (*w); | |
9038 int div_y_low = WINDOW_TOP (*w); | |
9039 | |
9040 if (div_x_low < x_coord && x_coord <= div_x_high && | |
9041 div_y_low < y_coord && y_coord <= div_y_high) | |
9042 { | |
9043 low_x_coord = div_x_low; | |
9044 high_x_coord = div_x_high; | |
9045 low_y_coord = div_y_low; | |
9046 high_y_coord = div_y_high; | |
9047 position = OVER_V_DIVIDER; | |
9048 UPDATE_CACHE_RETURN; | |
9049 } | |
9050 } | |
9051 | |
9052 dla = window_display_lines (*w, CURRENT_DISP); | |
9053 | |
9054 for (*row = 0; *row < Dynarr_length (dla); (*row)++) | |
9055 { | |
9056 int really_over_nothing = 0; | |
9057 struct display_line *dl = Dynarr_atp (dla, *row); | |
9058 | |
9059 if ((int) (dl->ypos - dl->ascent) <= y_coord | |
9060 && y_coord <= (int) (dl->ypos + dl->descent)) | |
9061 { | |
9062 int check_margin_glyphs = 0; | |
9063 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
9064 struct rune *rb = 0; | |
9065 | |
9066 if (x_coord < dl->bounds.left_white | |
9067 || x_coord >= dl->bounds.right_white) | |
9068 check_margin_glyphs = 1; | |
9069 | |
9070 low_y_coord = dl->ypos - dl->ascent; | |
9071 high_y_coord = dl->ypos + dl->descent + 1; | |
9072 | |
9073 if (position == OVER_BORDER | |
9074 || position == OVER_OUTSIDE | |
9075 || check_margin_glyphs) | |
9076 { | |
9077 int x_check, left_bound; | |
9078 | |
9079 if (check_margin_glyphs) | |
9080 { | |
9081 x_check = x_coord; | |
9082 left_bound = dl->bounds.left_white; | |
9083 } | |
9084 else | |
9085 { | |
9086 x_check = high_x_coord; | |
9087 left_bound = frm_left; | |
9088 } | |
9089 | |
9090 if (Dynarr_length (db->runes)) | |
9091 { | |
9092 if (x_check <= left_bound) | |
9093 { | |
9094 if (dl->modeline) | |
4967 | 9095 *modeline_closest = Dynarr_begin (db->runes)->charpos; |
428 | 9096 else |
4967 | 9097 *closest = Dynarr_begin (db->runes)->charpos; |
428 | 9098 } |
9099 else | |
9100 { | |
9101 if (dl->modeline) | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9102 *modeline_closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9103 else |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9104 *closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9105 } |
9106 | |
9107 if (dl->modeline) | |
9108 *modeline_closest += dl->offset; | |
9109 else | |
9110 *closest += dl->offset; | |
9111 } | |
9112 else | |
9113 { | |
9114 /* #### What should be here. */ | |
9115 if (dl->modeline) | |
9116 *modeline_closest = 0; | |
9117 else | |
9118 *closest = 0; | |
9119 } | |
9120 | |
9121 if (check_margin_glyphs) | |
9122 { | |
9123 if (x_coord < dl->bounds.left_in | |
9124 || x_coord >= dl->bounds.right_in) | |
9125 { | |
9126 /* If we are over the outside margins then we | |
4187 | 9127 know the loop over the text block isn't going |
9128 to accomplish anything. So we go ahead and | |
9129 set what information we can right here and | |
9130 return. */ | |
428 | 9131 (*row)--; |
9132 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9133 get_position_object (dl, obj1, obj2, x_coord, | |
9134 &low_x_coord, &high_x_coord); | |
9135 | |
9136 UPDATE_CACHE_RETURN; | |
9137 } | |
9138 } | |
9139 else | |
9140 UPDATE_CACHE_RETURN; | |
9141 } | |
9142 | |
9143 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++) | |
9144 { | |
9145 int past_end = (*col == Dynarr_length (db->runes)); | |
9146 | |
9147 if (!past_end) | |
9148 rb = Dynarr_atp (db->runes, *col); | |
9149 | |
9150 if (past_end || | |
9151 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width)) | |
9152 { | |
9153 if (past_end) | |
9154 { | |
9155 (*col)--; | |
9156 rb = Dynarr_atp (db->runes, *col); | |
9157 } | |
9158 | |
826 | 9159 *charpos = rb->charpos + dl->offset; |
428 | 9160 low_x_coord = rb->xpos; |
9161 high_x_coord = rb->xpos + rb->width; | |
9162 | |
9163 if (rb->type == RUNE_DGLYPH) | |
9164 { | |
9165 int elt = *col + 1; | |
9166 | |
9167 /* Find the first character after the glyph. */ | |
9168 while (elt < Dynarr_length (db->runes)) | |
9169 { | |
9170 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH) | |
9171 { | |
9172 if (dl->modeline) | |
9173 *modeline_closest = | |
826 | 9174 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9175 dl->offset); |
9176 else | |
9177 *closest = | |
826 | 9178 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9179 dl->offset); |
9180 break; | |
9181 } | |
9182 | |
9183 elt++; | |
9184 } | |
9185 | |
9186 /* In this case we failed to find a non-glyph | |
4187 | 9187 character so we return the last position |
9188 displayed on the line. */ | |
428 | 9189 if (elt == Dynarr_length (db->runes)) |
9190 { | |
9191 if (dl->modeline) | |
826 | 9192 *modeline_closest = dl->end_charpos + dl->offset; |
428 | 9193 else |
826 | 9194 *closest = dl->end_charpos + dl->offset; |
428 | 9195 really_over_nothing = 1; |
9196 } | |
9197 } | |
9198 else | |
9199 { | |
9200 if (dl->modeline) | |
826 | 9201 *modeline_closest = rb->charpos + dl->offset; |
428 | 9202 else |
826 | 9203 *closest = rb->charpos + dl->offset; |
428 | 9204 } |
9205 | |
9206 if (dl->modeline) | |
9207 { | |
9208 *row = window_displayed_height (*w); | |
9209 | |
9210 if (position == OVER_NOTHING) | |
9211 position = OVER_MODELINE; | |
9212 | |
9213 if (rb->type == RUNE_DGLYPH) | |
9214 { | |
9215 *obj1 = rb->object.dglyph.glyph; | |
9216 *obj2 = rb->object.dglyph.extent; | |
9217 } | |
9218 else if (rb->type == RUNE_CHAR) | |
9219 { | |
9220 *obj1 = Qnil; | |
9221 *obj2 = Qnil; | |
9222 } | |
9223 else | |
9224 { | |
9225 *obj1 = Qnil; | |
9226 *obj2 = Qnil; | |
9227 } | |
9228 | |
9229 UPDATE_CACHE_RETURN; | |
9230 } | |
9231 else if (past_end | |
9232 || (rb->type == RUNE_CHAR | |
9233 && rb->object.chr.ch == '\n')) | |
9234 { | |
9235 (*row)--; | |
9236 /* At this point we may have glyphs in the right | |
4187 | 9237 inside margin. */ |
428 | 9238 if (check_margin_glyphs) |
9239 get_position_object (dl, obj1, obj2, x_coord, | |
9240 &low_x_coord, &high_x_coord); | |
9241 UPDATE_CACHE_RETURN; | |
9242 } | |
9243 else | |
9244 { | |
9245 (*row)--; | |
9246 if (rb->type == RUNE_DGLYPH) | |
9247 { | |
9248 *obj1 = rb->object.dglyph.glyph; | |
9249 *obj2 = rb->object.dglyph.extent; | |
9250 } | |
9251 else if (rb->type == RUNE_CHAR) | |
9252 { | |
9253 *obj1 = Qnil; | |
9254 *obj2 = Qnil; | |
9255 } | |
9256 else | |
9257 { | |
9258 *obj1 = Qnil; | |
9259 *obj2 = Qnil; | |
9260 } | |
9261 | |
9262 *obj_x = x_coord - rb->xpos; | |
9263 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9264 | |
9265 /* At this point we may have glyphs in the left | |
4187 | 9266 inside margin. */ |
428 | 9267 if (check_margin_glyphs) |
9268 get_position_object (dl, obj1, obj2, x_coord, 0, 0); | |
9269 | |
9270 if (position == OVER_NOTHING && !really_over_nothing) | |
9271 position = OVER_TEXT; | |
9272 | |
9273 UPDATE_CACHE_RETURN; | |
9274 } | |
9275 } | |
9276 } | |
9277 } | |
9278 } | |
9279 | |
9280 *row = Dynarr_length (dla) - 1; | |
9281 if (FRAME_WIN_P (f)) | |
9282 { | |
9283 int bot_elt = Dynarr_length (dla) - 1; | |
9284 | |
9285 if (bot_elt >= 0) | |
9286 { | |
9287 struct display_line *dl = Dynarr_atp (dla, bot_elt); | |
9288 int adj_area = y_coord - (dl->ypos + dl->descent); | |
9289 Lisp_Object lwin; | |
9290 int defheight; | |
9291 | |
793 | 9292 lwin = wrap_window (*w); |
428 | 9293 default_face_height_and_width (lwin, 0, &defheight); |
9294 | |
9295 *row += (adj_area / defheight); | |
9296 } | |
9297 } | |
9298 | |
9299 /* #### This should be checked out some more to determine what | |
9300 should really be going on. */ | |
9301 if (!MARKERP ((*w)->start[CURRENT_DISP])) | |
9302 *closest = 0; | |
9303 else | |
442 | 9304 *closest = end_of_last_line_may_error (*w, |
428 | 9305 marker_position ((*w)->start[CURRENT_DISP])); |
9306 *col = 0; | |
9307 UPDATE_CACHE_RETURN; | |
9308 } | |
9309 #undef UPDATE_CACHE_RETURN | |
9310 | |
9311 | |
9312 /***************************************************************************/ | |
9313 /* */ | |
9314 /* Lisp functions */ | |
9315 /* */ | |
9316 /***************************************************************************/ | |
9317 | |
9318 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /* | |
9319 Ensure that all minibuffers are correctly showing the echo area. | |
9320 */ | |
9321 ()) | |
9322 { | |
9323 Lisp_Object devcons, concons; | |
9324 | |
1318 | 9325 if (in_display) |
9326 return Qnil; | |
9327 | |
428 | 9328 DEVICE_LOOP_NO_BREAK (devcons, concons) |
9329 { | |
9330 struct device *d = XDEVICE (XCAR (devcons)); | |
9331 Lisp_Object frmcons; | |
9332 | |
1279 | 9333 if (DEVICE_STREAM_P (d)) |
9334 continue; | |
9335 | |
428 | 9336 DEVICE_FRAME_LOOP (frmcons, d) |
9337 { | |
9338 struct frame *f = XFRAME (XCAR (frmcons)); | |
853 | 9339 int depth; |
428 | 9340 |
9341 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) | |
9342 { | |
9343 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); | |
442 | 9344 |
9345 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
9346 | |
428 | 9347 /* |
9348 * If the frame size has changed, there may be random | |
9349 * chud on the screen left from previous messages | |
9350 * because redisplay_frame hasn't been called yet. | |
9351 * Clear the screen to get rid of the potential mess. | |
9352 */ | |
9353 if (f->echo_area_garbaged) | |
9354 { | |
442 | 9355 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 9356 f->echo_area_garbaged = 0; |
9357 } | |
853 | 9358 depth = enter_redisplay_critical_section (); |
428 | 9359 redisplay_window (window, 0); |
853 | 9360 exit_redisplay_critical_section (depth); |
442 | 9361 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 9362 } |
9363 } | |
9364 } | |
9365 | |
9366 return Qnil; | |
9367 } | |
9368 | |
9369 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /* | |
9370 Clear frame FRAME and output again what is supposed to appear on it. | |
9371 FRAME defaults to the selected frame if omitted. | |
9372 Normally, redisplay is preempted as normal if input arrives. However, | |
9373 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9374 input and is guaranteed to proceed to completion. | |
9375 */ | |
9376 (frame, no_preempt)) | |
9377 { | |
9378 struct frame *f = decode_frame (frame); | |
9379 int count = specpdl_depth (); | |
9380 | |
9381 if (!NILP (no_preempt)) | |
853 | 9382 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9383 |
9384 f->clear = 1; | |
9385 redisplay_frame (f, 1); | |
9386 | |
442 | 9387 /* See the comment in Fredisplay_frame. */ |
9388 RESET_CHANGED_SET_FLAGS; | |
9389 | |
771 | 9390 return unbind_to (count); |
428 | 9391 } |
9392 | |
9393 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* | |
9394 Ensure that FRAME's contents are correctly displayed. | |
9395 This differs from `redraw-frame' in that it only redraws what needs to | |
9396 be updated, as opposed to unconditionally clearing and redrawing | |
9397 the frame. | |
9398 FRAME defaults to the selected frame 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 (frame, no_preempt)) | |
9404 { | |
9405 struct frame *f = decode_frame (frame); | |
9406 int count = specpdl_depth (); | |
9407 | |
9408 if (!NILP (no_preempt)) | |
853 | 9409 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9410 |
9411 redisplay_frame (f, 1); | |
9412 | |
442 | 9413 /* If we don't reset the global redisplay flags here, subsequent |
9414 changes to the display will not get registered by redisplay | |
9415 because it thinks it already has registered changes. If you | |
9416 really knew what you were doing you could confuse redisplay by | |
9417 calling Fredisplay_frame while updating another frame. We assume | |
9418 that if you know what you are doing you will not be that | |
9419 stupid. */ | |
9420 RESET_CHANGED_SET_FLAGS; | |
9421 | |
771 | 9422 return unbind_to (count); |
428 | 9423 } |
9424 | |
9425 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* | |
9426 Clear device DEVICE and output again what is supposed to appear on it. | |
9427 DEVICE defaults to the selected device if omitted. | |
9428 Normally, redisplay is preempted as normal if input arrives. However, | |
9429 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9430 input and is guaranteed to proceed to completion. | |
9431 */ | |
9432 (device, no_preempt)) | |
9433 { | |
9434 struct device *d = decode_device (device); | |
9435 Lisp_Object frmcons; | |
9436 int count = specpdl_depth (); | |
9437 | |
9438 if (!NILP (no_preempt)) | |
853 | 9439 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9440 |
9441 DEVICE_FRAME_LOOP (frmcons, d) | |
9442 { | |
9443 XFRAME (XCAR (frmcons))->clear = 1; | |
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 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* | |
9454 Ensure that DEVICE's contents are correctly displayed. | |
9455 This differs from `redraw-device' in that it only redraws what needs to | |
9456 be updated, as opposed to unconditionally clearing and redrawing | |
9457 the device. | |
9458 DEVICE defaults to the selected device if omitted. | |
9459 Normally, redisplay is preempted as normal if input arrives. However, | |
9460 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9461 input and is guaranteed to proceed to completion. | |
853 | 9462 |
9463 Note: If you simply want everything redisplayed, the current idiom is | |
9464 `(sit-for 0)'. | |
428 | 9465 */ |
9466 (device, no_preempt)) | |
9467 { | |
9468 struct device *d = decode_device (device); | |
9469 int count = specpdl_depth (); | |
9470 | |
9471 if (!NILP (no_preempt)) | |
853 | 9472 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9473 |
440 | 9474 redisplay_device (d, 0); |
428 | 9475 |
442 | 9476 /* See the comment in Fredisplay_frame. */ |
9477 RESET_CHANGED_SET_FLAGS; | |
9478 | |
771 | 9479 return unbind_to (count); |
428 | 9480 } |
9481 | |
9482 /* Big lie. Big lie. This will force all modelines to be updated | |
9483 regardless if the all flag is set or not. It remains in existence | |
9484 solely for backwards compatibility. */ | |
9485 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /* | |
9486 Force the modeline of the current buffer to be redisplayed. | |
9487 With optional non-nil ALL, force redisplay of all modelines. | |
9488 */ | |
2286 | 9489 (UNUSED (all))) |
428 | 9490 { |
9491 MARK_MODELINE_CHANGED; | |
9492 return Qnil; | |
9493 } | |
9494 | |
9495 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /* | |
9496 Force an immediate update of the cursor on FRAME. | |
9497 FRAME defaults to the selected frame if omitted. | |
9498 */ | |
9499 (frame)) | |
9500 { | |
1279 | 9501 struct frame *f = decode_frame (frame); |
9502 | |
9503 if (!FRAME_STREAM_P (f)) | |
9504 redisplay_redraw_cursor (f, 1); | |
428 | 9505 return Qnil; |
9506 } | |
9507 | |
9508 | |
9509 /***************************************************************************/ | |
9510 /* */ | |
872 | 9511 /* Change flags */ |
428 | 9512 /* */ |
9513 /***************************************************************************/ | |
9514 | |
9515 static void | |
2286 | 9516 margin_width_changed_in_frame (Lisp_Object UNUSED (specifier), |
9517 struct frame *UNUSED (f), | |
9518 Lisp_Object UNUSED (oldval)) | |
428 | 9519 { |
9520 /* Nothing to be done? */ | |
9521 } | |
9522 | |
9523 int | |
2286 | 9524 redisplay_variable_changed (Lisp_Object UNUSED (sym), |
9525 Lisp_Object *UNUSED (val), | |
9526 Lisp_Object UNUSED (in_object), | |
9527 int UNUSED (flags)) | |
428 | 9528 { |
9529 /* #### clip_changed should really be renamed something like | |
9530 global_redisplay_change. */ | |
9531 MARK_CLIP_CHANGED; | |
9532 return 0; | |
9533 } | |
9534 | |
9535 /* This is called if the built-in glyphs have their properties | |
9536 changed. */ | |
9537 void | |
2286 | 9538 redisplay_glyph_changed (Lisp_Object UNUSED (glyph), |
9539 Lisp_Object UNUSED (property), Lisp_Object locale) | |
428 | 9540 { |
9541 if (WINDOWP (locale)) | |
9542 { | |
9543 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale)))); | |
9544 } | |
9545 else if (FRAMEP (locale)) | |
9546 { | |
9547 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale)); | |
9548 } | |
9549 else if (DEVICEP (locale)) | |
9550 { | |
9551 Lisp_Object frmcons; | |
9552 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale)) | |
9553 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9554 } | |
9555 else if (CONSOLEP (locale)) | |
9556 { | |
9557 Lisp_Object frmcons, devcons; | |
9558 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale)) | |
9559 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9560 } | |
9561 else /* global or buffer */ | |
9562 { | |
9563 Lisp_Object frmcons, devcons, concons; | |
9564 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
9565 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9566 } | |
9567 } | |
9568 | |
9569 static void | |
2286 | 9570 text_cursor_visible_p_changed (Lisp_Object UNUSED (specifier), |
9571 struct window *w, Lisp_Object UNUSED (oldval)) | |
428 | 9572 { |
9573 if (XFRAME (w->frame)->init_finished) | |
9574 Fforce_cursor_redisplay (w->frame); | |
9575 } | |
9576 | |
872 | 9577 void |
9578 mark_buffers_changed (void) | |
9579 { | |
9580 MARK_TYPE_CHANGED (buffers); | |
9581 } | |
9582 | |
9583 void | |
9584 mark_clip_changed (void) | |
9585 { | |
9586 MARK_TYPE_CHANGED (clip); | |
9587 } | |
9588 | |
9589 void | |
9590 mark_extents_changed (void) | |
9591 { | |
9592 MARK_TYPE_CHANGED (extents); | |
9593 } | |
9594 | |
9595 void | |
9596 mark_icon_changed (void) | |
9597 { | |
9598 MARK_TYPE_CHANGED (icon); | |
9599 } | |
9600 | |
9601 void | |
9602 mark_menubar_changed (void) | |
9603 { | |
9604 MARK_TYPE_CHANGED (menubar); | |
9605 } | |
9606 | |
9607 void | |
9608 mark_modeline_changed (void) | |
9609 { | |
9610 MARK_TYPE_CHANGED (modeline); | |
9611 } | |
9612 | |
9613 void | |
9614 mark_point_changed (void) | |
9615 { | |
9616 MARK_TYPE_CHANGED (point); | |
9617 } | |
9618 | |
9619 void | |
9620 mark_toolbar_changed (void) | |
9621 { | |
9622 MARK_TYPE_CHANGED (toolbar); | |
9623 } | |
9624 | |
9625 void | |
9626 mark_gutter_changed (void) | |
9627 { | |
9628 MARK_TYPE_CHANGED (gutter); | |
9629 } | |
9630 | |
9631 void | |
9632 mark_glyphs_changed (void) | |
9633 { | |
9634 MARK_TYPE_CHANGED (glyphs); | |
9635 } | |
9636 | |
9637 void | |
9638 mark_subwindows_changed (void) | |
9639 { | |
9640 MARK_TYPE_CHANGED (subwindows); | |
9641 } | |
9642 | |
9643 void | |
9644 mark_subwindows_state_changed (void) | |
9645 { | |
9646 MARK_TYPE_CHANGED (subwindows_state); | |
9647 } | |
9648 | |
428 | 9649 #ifdef MEMORY_USAGE_STATS |
9650 | |
9651 | |
9652 /***************************************************************************/ | |
9653 /* */ | |
9654 /* memory usage computation */ | |
9655 /* */ | |
9656 /***************************************************************************/ | |
9657 | |
9658 static int | |
9659 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats) | |
9660 { | |
9661 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
9662 } | |
9663 | |
9664 static int | |
9665 compute_display_block_dynarr_usage (display_block_dynarr *dyn, | |
9666 struct overhead_stats *ovstats) | |
9667 { | |
9668 int total, i; | |
9669 | |
9670 if (!dyn) | |
9671 return 0; | |
9672 | |
9673 total = Dynarr_memory_usage (dyn, ovstats); | |
9674 for (i = 0; i < Dynarr_largest (dyn); i++) | |
9675 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats); | |
9676 | |
9677 return total; | |
9678 } | |
9679 | |
9680 static int | |
9681 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn, | |
9682 struct overhead_stats *ovstats) | |
9683 { | |
9684 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
9685 } | |
9686 | |
9687 int | |
9688 compute_display_line_dynarr_usage (display_line_dynarr *dyn, | |
9689 struct overhead_stats *ovstats) | |
9690 { | |
9691 int total, i; | |
9692 | |
9693 if (!dyn) | |
9694 return 0; | |
9695 | |
9696 total = Dynarr_memory_usage (dyn, ovstats); | |
9697 for (i = 0; i < Dynarr_largest (dyn); i++) | |
9698 { | |
9699 struct display_line *dl = &Dynarr_at (dyn, i); | |
9700 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats); | |
9701 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats); | |
9702 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats); | |
9703 } | |
9704 | |
9705 return total; | |
9706 } | |
9707 | |
9708 int | |
9709 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn, | |
9710 struct overhead_stats *ovstats) | |
9711 { | |
9712 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
9713 } | |
9714 | |
9715 #endif /* MEMORY_USAGE_STATS */ | |
9716 | |
1204 | 9717 #ifdef ERROR_CHECK_DISPLAY |
9718 | |
800 | 9719 static int |
2286 | 9720 sledgehammer_check_redisplay_structs_1 (struct window *w, |
9721 void *UNUSED (closure)) | |
800 | 9722 { |
9723 int i, j; | |
9724 display_line_dynarr *dl; | |
9725 | |
9726 dl = window_display_lines (w, CURRENT_DISP); | |
4187 | 9727 |
800 | 9728 for (i = 0; i < Dynarr_largest (dl); i++) |
9729 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9730 assert (Dynarr_atp (dl, i)->display_blocks != | |
9731 Dynarr_atp (dl, j)->display_blocks); | |
9732 | |
9733 dl = window_display_lines (w, DESIRED_DISP); | |
9734 | |
9735 for (i = 0; i < Dynarr_largest (dl); i++) | |
9736 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9737 assert (Dynarr_atp (dl, i)->display_blocks != | |
9738 Dynarr_atp (dl, j)->display_blocks); | |
9739 | |
9740 return 0; | |
9741 } | |
9742 | |
9743 static void | |
9744 sledgehammer_check_redisplay_structs (void) | |
9745 { | |
9746 map_windows (0, sledgehammer_check_redisplay_structs_1, NULL); | |
9747 } | |
9748 | |
1204 | 9749 #endif /* ERROR_CHECK_DISPLAY */ |
9750 | |
428 | 9751 |
9752 /***************************************************************************/ | |
9753 /* */ | |
9754 /* initialization */ | |
9755 /* */ | |
9756 /***************************************************************************/ | |
9757 | |
9758 void | |
9759 init_redisplay (void) | |
9760 { | |
9761 disable_preemption = 0; | |
9762 preemption_count = 0; | |
9763 | |
9764 #ifndef PDUMP | |
9765 if (!initialized) | |
9766 #endif | |
9767 { | |
440 | 9768 if (!cmotion_display_lines) |
9769 cmotion_display_lines = Dynarr_new (display_line); | |
867 | 9770 if (!mode_spec_ibyte_string) |
9771 mode_spec_ibyte_string = Dynarr_new (Ibyte); | |
440 | 9772 if (!formatted_string_extent_dynarr) |
9773 formatted_string_extent_dynarr = Dynarr_new (EXTENT); | |
9774 if (!formatted_string_extent_start_dynarr) | |
9775 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); | |
9776 if (!formatted_string_extent_end_dynarr) | |
9777 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); | |
9778 if (!internal_cache) | |
9779 internal_cache = Dynarr_new (line_start_cache); | |
428 | 9780 } |
9781 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9782 if (!initialized) |
428 | 9783 return; |
9784 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9785 if (noninteractive) |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9786 { |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9787 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
|
9788 return; |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9789 } |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9790 |
428 | 9791 /* If the user wants to use a window system, we shouldn't bother |
9792 initializing the terminal. This is especially important when the | |
9793 terminal is so dumb that emacs gives up before and doesn't bother | |
9794 using the window system. | |
9795 | |
9796 If the DISPLAY environment variable is set, try to use X, and die | |
9797 with an error message if that doesn't work. */ | |
9798 | |
9799 #ifdef HAVE_X_WINDOWS | |
9800 if (!strcmp (display_use, "x")) | |
9801 { | |
9802 /* Some stuff checks this way early. */ | |
9803 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
|
9804 Vinitial_device_type = Qx; |
428 | 9805 return; |
9806 } | |
9807 #endif /* HAVE_X_WINDOWS */ | |
9808 | |
462 | 9809 #ifdef HAVE_GTK |
9810 if (!strcmp (display_use, "gtk")) | |
9811 { | |
9812 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
|
9813 Vinitial_device_type = Qgtk; |
462 | 9814 return; |
9815 } | |
9816 #endif | |
9817 | |
428 | 9818 #ifdef HAVE_MS_WINDOWS |
9819 if (!strcmp (display_use, "mswindows")) | |
9820 { | |
9821 /* Some stuff checks this way early. */ | |
9822 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
|
9823 Vinitial_device_type = Qmswindows; |
428 | 9824 return; |
9825 } | |
9826 #endif /* HAVE_MS_WINDOWS */ | |
9827 | |
9828 #ifdef HAVE_TTY | |
9829 /* If no window system has been specified, try to use the terminal. */ | |
9830 if (!isatty (0)) | |
9831 { | |
9832 stderr_out ("XEmacs: standard input is not a tty\n"); | |
9833 exit (1); | |
9834 } | |
9835 | |
9836 /* Look at the TERM variable */ | |
771 | 9837 if (!egetenv ("TERM")) |
428 | 9838 { |
9839 stderr_out ("Please set the environment variable TERM; see tset(1).\n"); | |
9840 exit (1); | |
9841 } | |
9842 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9843 Vinitial_device_type = Qtty; |
428 | 9844 return; |
9845 #else /* not HAVE_TTY */ | |
9846 /* No DISPLAY specified, and no TTY support. */ | |
9847 stderr_out ("XEmacs: Cannot open display.\n\ | |
9848 Please set the environmental variable DISPLAY to an appropriate value.\n"); | |
9849 exit (1); | |
9850 #endif | |
9851 /* Unreached. */ | |
9852 } | |
9853 | |
9854 void | |
9855 syms_of_redisplay (void) | |
9856 { | |
563 | 9857 DEFSYMBOL (Qcursor_in_echo_area); |
9858 DEFSYMBOL (Qdisplay_warning_buffer); | |
9859 DEFSYMBOL (Qbar_cursor); | |
9860 DEFSYMBOL (Qtop_bottom); | |
9861 DEFSYMBOL (Qbuffer_list_changed_hook); | |
428 | 9862 |
9863 DEFSUBR (Fredisplay_echo_area); | |
9864 DEFSUBR (Fredraw_frame); | |
9865 DEFSUBR (Fredisplay_frame); | |
9866 DEFSUBR (Fredraw_device); | |
9867 DEFSUBR (Fredisplay_device); | |
9868 DEFSUBR (Fredraw_modeline); | |
9869 DEFSUBR (Fforce_cursor_redisplay); | |
9870 } | |
9871 | |
9872 void | |
9873 vars_of_redisplay (void) | |
9874 { | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
9875 QSin_redisplay = build_defer_string ("(in redisplay)"); |
1292 | 9876 staticpro (&QSin_redisplay); |
428 | 9877 |
1318 | 9878 Vpost_redisplay_actions = Qnil; |
9879 staticpro (&Vpost_redisplay_actions); | |
9880 | |
428 | 9881 #if 0 |
9882 staticpro (&last_arrow_position); | |
9883 staticpro (&last_arrow_string); | |
9884 last_arrow_position = Qnil; | |
9885 last_arrow_string = Qnil; | |
9886 #endif /* 0 */ | |
9887 | |
9888 /* #### Probably temporary */ | |
9889 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* | |
9890 \(Temporary) Setting this will impact the performance of the internal | |
9891 line start cache. | |
9892 */ ); | |
9893 cache_adjustment = 2; | |
9894 | |
1268 | 9895 DEFVAR_INT ("maximum-preempts", &max_preempts /* |
9896 Maximum number of times redisplay can be preempted by user input. | |
9897 */ ); | |
9898 max_preempts = INIT_MAX_PREEMPTS; | |
9899 | |
428 | 9900 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /* |
9901 Minimum pixel height for clipped bottom display line. | |
9902 A clipped line shorter than this won't be displayed. | |
9903 */ , | |
9904 redisplay_variable_changed); | |
9905 vertical_clip = 5; | |
9906 | |
9907 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /* | |
9908 Minimum visible area for clipped glyphs at right boundary. | |
9909 Clipped glyphs shorter than this won't be displayed. | |
9910 Only pixmap glyph instances are currently allowed to be clipped. | |
9911 */ , | |
9912 redisplay_variable_changed); | |
9913 horizontal_clip = 5; | |
9914 | |
9915 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /* | |
9916 String displayed by modeline-format's "%m" specification. | |
9917 */ ); | |
9918 Vglobal_mode_string = Qnil; | |
9919 | |
9920 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /* | |
9921 Marker for where to display an arrow on top of the buffer text. | |
9922 This must be the beginning of a line in order to work. | |
9923 See also `overlay-arrow-string'. | |
9924 */ , | |
9925 redisplay_variable_changed); | |
9926 Voverlay_arrow_position = Qnil; | |
9927 | |
9928 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* | |
442 | 9929 String or glyph to display as an arrow. See also `overlay-arrow-position'. |
444 | 9930 \(Note that despite the name of this variable, it can be set to a glyph as |
442 | 9931 well as a string.) |
428 | 9932 */ , |
9933 redisplay_variable_changed); | |
9934 Voverlay_arrow_string = Qnil; | |
9935 | |
9936 DEFVAR_INT ("scroll-step", &scroll_step /* | |
9937 *The number of lines to try scrolling a window by when point moves out. | |
9938 If that fails to bring point back on frame, point is centered instead. | |
9939 If this is zero, point is always centered after it moves off screen. | |
9940 */ ); | |
9941 scroll_step = 0; | |
9942 | |
9943 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /* | |
9944 *Scroll up to this many lines, to bring point back on screen. | |
9945 */ ); | |
9946 scroll_conservatively = 0; | |
9947 | |
9948 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows", | |
9949 &truncate_partial_width_windows /* | |
9950 *Non-nil means truncate lines in all windows less than full frame wide. | |
9951 */ , | |
9952 redisplay_variable_changed); | |
9953 truncate_partial_width_windows = 1; | |
9954 | |
442 | 9955 DEFVAR_LISP ("visible-bell", &Vvisible_bell /* |
9956 *Non-nil substitutes a visual signal for the audible bell. | |
9957 | |
9958 Default behavior is to flash the whole screen. On some platforms, | |
9959 special effects are available using the following values: | |
9960 | |
3025 | 9961 `display' Flash the whole screen (ie, the default behavior). |
9962 `top-bottom' Flash only the top and bottom lines of the selected frame. | |
442 | 9963 |
9964 When effects are unavailable on a platform, the visual bell is the | |
9965 default, whole screen. (Currently only X supports any special effects.) | |
428 | 9966 */ ); |
442 | 9967 Vvisible_bell = Qnil; |
428 | 9968 |
9969 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* | |
9970 *Non-nil means no need to redraw entire frame after suspending. | |
9971 A non-nil value is useful if the terminal can automatically preserve | |
9972 Emacs's frame display when you reenter Emacs. | |
9973 It is up to you to set this variable if your terminal can do that. | |
9974 */ ); | |
9975 no_redraw_on_reenter = 0; | |
9976 | |
9977 DEFVAR_LISP ("window-system", &Vwindow_system /* | |
9978 A symbol naming the window-system under which Emacs is running, | |
9979 such as `x', or nil if emacs is running on an ordinary terminal. | |
9980 | |
9981 Do not use this variable, except for GNU Emacs compatibility, as it | |
9982 gives wrong values in a multi-device environment. Use `console-type' | |
9983 instead. | |
9984 */ ); | |
9985 Vwindow_system = Qnil; | |
9986 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9987 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
|
9988 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
|
9989 |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9990 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
|
9991 to Lisp what type the initial device to be created should be. |
428 | 9992 */ ); |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9993 Vinitial_device_type = Qnil; |
428 | 9994 |
9995 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* | |
9996 Non-nil means put cursor in minibuffer, at end of any message there. | |
9997 */ ); | |
9998 cursor_in_echo_area = 0; | |
9999 | |
10000 /* #### Shouldn't this be generalized as follows: | |
10001 | |
10002 if nil, use block cursor. | |
10003 if a number, use a bar cursor of that width. | |
10004 Otherwise, use a 1-pixel bar cursor. | |
10005 | |
10006 #### Or better yet, this variable should be trashed entirely | |
10007 (use a Lisp-magic variable to maintain compatibility) | |
10008 and a specifier `cursor-shape' added, which allows a block | |
10009 cursor, a bar cursor, a flashing block or bar cursor, | |
10010 maybe a caret cursor, etc. */ | |
10011 | |
10012 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /* | |
448 | 10013 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. |
428 | 10014 */ ); |
10015 Vbar_cursor = Qnil; | |
10016 | |
442 | 10017 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* |
10018 Function or functions to call when a frame's buffer list has changed. | |
10019 This is called during redisplay, before redisplaying each frame. | |
10020 Functions on this hook are called with one argument, the frame. | |
10021 */ ); | |
10022 Vbuffer_list_changed_hook = Qnil; | |
10023 | |
428 | 10024 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* |
10025 Bump this to tell the C code to call `display-warning-buffer' | |
10026 at next redisplay. You should not normally change this; the function | |
10027 `display-warning' automatically does this at appropriate times. | |
10028 */ ); | |
10029 display_warning_tick = 0; | |
10030 | |
10031 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /* | |
10032 Non-nil means inhibit display of warning messages. | |
10033 You should *bind* this, not set it. Any pending warning messages | |
10034 will be displayed when the binding no longer applies. | |
10035 */ ); | |
10036 /* reset to 0 by startup.el after the splash screen has displayed. | |
10037 This way, the warnings don't obliterate the splash screen. */ | |
10038 inhibit_warning_display = 1; | |
10039 | |
10040 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /* | |
10041 *Non-nil means column display number starts at 1. | |
10042 */ ); | |
10043 column_number_start_at_one = 0; | |
10044 } | |
10045 | |
10046 void | |
10047 specifier_vars_of_redisplay (void) | |
10048 { | |
10049 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /* | |
10050 *Width of left margin. | |
10051 This is a specifier; use `set-specifier' to change it. | |
10052 */ ); | |
10053 Vleft_margin_width = Fmake_specifier (Qnatnum); | |
10054 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10055 set_specifier_caching (Vleft_margin_width, | |
438 | 10056 offsetof (struct window, left_margin_width), |
428 | 10057 some_window_value_changed, |
438 | 10058 offsetof (struct frame, left_margin_width), |
444 | 10059 margin_width_changed_in_frame, 0); |
428 | 10060 |
10061 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* | |
10062 *Width of right margin. | |
10063 This is a specifier; use `set-specifier' to change it. | |
10064 */ ); | |
10065 Vright_margin_width = Fmake_specifier (Qnatnum); | |
10066 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10067 set_specifier_caching (Vright_margin_width, | |
438 | 10068 offsetof (struct window, right_margin_width), |
428 | 10069 some_window_value_changed, |
438 | 10070 offsetof (struct frame, right_margin_width), |
444 | 10071 margin_width_changed_in_frame, 0); |
428 | 10072 |
10073 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* | |
10074 *Minimum ascent height of lines. | |
10075 This is a specifier; use `set-specifier' to change it. | |
10076 */ ); | |
10077 Vminimum_line_ascent = Fmake_specifier (Qnatnum); | |
10078 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); | |
10079 set_specifier_caching (Vminimum_line_ascent, | |
438 | 10080 offsetof (struct window, minimum_line_ascent), |
428 | 10081 some_window_value_changed, |
444 | 10082 0, 0, 0); |
428 | 10083 |
10084 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* | |
10085 *Minimum descent height of lines. | |
10086 This is a specifier; use `set-specifier' to change it. | |
10087 */ ); | |
10088 Vminimum_line_descent = Fmake_specifier (Qnatnum); | |
10089 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); | |
10090 set_specifier_caching (Vminimum_line_descent, | |
438 | 10091 offsetof (struct window, minimum_line_descent), |
428 | 10092 some_window_value_changed, |
444 | 10093 0, 0, 0); |
428 | 10094 |
10095 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* | |
10096 *Non-nil means use the left outside margin as extra whitespace when | |
3025 | 10097 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10098 This is a specifier; use `set-specifier' to change it. |
10099 */ ); | |
10100 Vuse_left_overflow = Fmake_specifier (Qboolean); | |
10101 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); | |
10102 set_specifier_caching (Vuse_left_overflow, | |
438 | 10103 offsetof (struct window, use_left_overflow), |
428 | 10104 some_window_value_changed, |
444 | 10105 0, 0, 0); |
428 | 10106 |
10107 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* | |
10108 *Non-nil means use the right outside margin as extra whitespace when | |
3025 | 10109 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10110 This is a specifier; use `set-specifier' to change it. |
10111 */ ); | |
10112 Vuse_right_overflow = Fmake_specifier (Qboolean); | |
10113 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); | |
10114 set_specifier_caching (Vuse_right_overflow, | |
438 | 10115 offsetof (struct window, use_right_overflow), |
428 | 10116 some_window_value_changed, |
444 | 10117 0, 0, 0); |
428 | 10118 |
10119 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* | |
10120 *Non-nil means the text cursor is visible (this is usually the case). | |
10121 This is a specifier; use `set-specifier' to change it. | |
10122 */ ); | |
10123 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); | |
10124 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); | |
10125 set_specifier_caching (Vtext_cursor_visible_p, | |
438 | 10126 offsetof (struct window, text_cursor_visible_p), |
428 | 10127 text_cursor_visible_p_changed, |
444 | 10128 0, 0, 0); |
428 | 10129 |
10130 } |