Mercurial > hg > xemacs-beta
annotate src/redisplay.c @ 4614:afbfad080ddd
The URLs in our current config.guess and config.sub files are obsolete.
Update to the latest upstream release to get correct URLs, as well as fixes
and enhancements to those scripts.
| author | Jerry James <james@xemacs.org> |
|---|---|
| date | Wed, 11 Feb 2009 11:09:35 -0700 |
| parents | 726060ee587c |
| children | 6540302eedf5 |
| 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. | |
| 3025 | 4 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2005 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 | |
| 867 | 633 redisplay_text_width_ichar_string (struct window *w, int findex, |
| 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); | |
| 643 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))), | |
| 644 text_width, (XFRAME (WINDOW_FRAME (w)), | |
| 645 WINDOW_FACE_CACHEL (w, findex), str, len)); | |
| 646 } | |
| 647 | |
| 867 | 648 static Ichar_dynarr *rtw_ichar_dynarr; |
| 428 | 649 |
| 650 int | |
| 651 redisplay_text_width_string (struct window *w, int findex, | |
| 867 | 652 Ibyte *nonreloc, Lisp_Object reloc, |
| 428 | 653 Bytecount offset, Bytecount len) |
| 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); |
| 663 return redisplay_text_width_ichar_string | |
| 664 (w, findex, Dynarr_atp (rtw_ichar_dynarr, 0), | |
| 665 Dynarr_length (rtw_ichar_dynarr)); | |
| 428 | 666 } |
| 667 | |
| 668 int | |
| 669 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face, | |
| 867 | 670 Ibyte *nonreloc, Lisp_Object reloc, |
| 428 | 671 Bytecount offset, Bytecount len) |
| 672 { | |
| 673 unsigned char charsets[NUM_LEADING_BYTES]; | |
| 674 Lisp_Object frame; | |
| 675 struct face_cachel cachel; | |
| 676 | |
| 867 | 677 if (!rtw_ichar_dynarr) |
| 678 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
| 679 Dynarr_reset (rtw_ichar_dynarr); | |
| 428 | 680 |
| 681 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
| 682 if (STRINGP (reloc)) | |
| 683 nonreloc = XSTRING_DATA (reloc); | |
| 867 | 684 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
| 685 find_charsets_in_ibyte_string (charsets, nonreloc, len); | |
| 428 | 686 reset_face_cachel (&cachel); |
| 687 cachel.face = face; | |
| 793 | 688 frame = wrap_frame (f); |
| 428 | 689 ensure_face_cachel_complete (&cachel, frame, charsets); |
| 690 return DEVMETH (XDEVICE (FRAME_DEVICE (f)), | |
| 867 | 691 text_width, (f, &cachel, Dynarr_atp (rtw_ichar_dynarr, 0), |
| 692 Dynarr_length (rtw_ichar_dynarr))); | |
| 428 | 693 } |
| 694 | |
| 695 /* Return the display block from DL of the given TYPE. A display line | |
| 696 can have only one display block of each possible type. If DL does | |
| 697 not have a block of type TYPE, one will be created and added to DL. */ | |
| 698 | |
| 699 struct display_block * | |
| 700 get_display_block_from_line (struct display_line *dl, enum display_type type) | |
| 701 { | |
| 702 int elt; | |
| 703 struct display_block db; | |
| 704 | |
| 705 /* Check if this display line already has a block of the desired type and | |
| 706 if so, return it. */ | |
| 707 if (dl->display_blocks) | |
| 708 { | |
| 709 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++) | |
| 710 { | |
| 711 if (Dynarr_at (dl->display_blocks, elt).type == type) | |
| 712 return Dynarr_atp (dl->display_blocks, elt); | |
| 713 } | |
| 714 | |
| 715 /* There isn't an active block of the desired type, but there | |
| 4187 | 716 might still be allocated blocks we need to reuse. */ |
| 428 | 717 if (elt < Dynarr_largest (dl->display_blocks)) |
| 718 { | |
| 719 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt); | |
| 720 | |
| 3025 | 721 /* "add" the block to the list */ |
| 428 | 722 Dynarr_increment (dl->display_blocks); |
| 723 | |
| 724 /* initialize and return */ | |
| 725 dbp->type = type; | |
| 726 return dbp; | |
| 727 } | |
| 728 } | |
| 729 else | |
| 730 { | |
| 731 /* This line doesn't have any display blocks, so initialize the display | |
| 4187 | 732 bock array. */ |
| 428 | 733 dl->display_blocks = Dynarr_new (display_block); |
| 734 } | |
| 735 | |
| 736 /* The line doesn't have a block of the desired type so go ahead and create | |
| 737 one and add it to the line. */ | |
| 738 xzero (db); | |
| 739 db.type = type; | |
| 740 db.runes = Dynarr_new (rune); | |
| 741 Dynarr_add (dl->display_blocks, db); | |
| 742 | |
| 743 /* Return the newly added display block. */ | |
| 744 elt = Dynarr_length (dl->display_blocks) - 1; | |
| 745 | |
| 746 return Dynarr_atp (dl->display_blocks, elt); | |
| 747 } | |
| 748 | |
| 749 static int | |
| 750 tab_char_width (struct window *w) | |
| 751 { | |
| 752 struct buffer *b = XBUFFER (w->buffer); | |
| 753 int char_tab_width = XINT (b->tab_width); | |
| 754 | |
| 755 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8; | |
| 756 | |
| 757 return char_tab_width; | |
| 758 } | |
| 759 | |
| 760 static int | |
| 761 space_width (struct window *w) | |
| 762 { | |
| 3659 | 763 /* While tabs are traditionally composed of spaces, for variable-width |
| 428 | 764 fonts the space character tends to give too narrow a value. So |
| 765 we use 'n' instead. Except that we don't. We use the default | |
| 766 character width for the default face. If this is actually | |
| 767 defined by the font then it is probably the best thing to | |
| 768 actually use. If it isn't, we have assumed it is 'n' and have | |
| 769 already calculated its width. Thus we can avoid a call to | |
| 770 XTextWidth on X frames by just querying the default width. */ | |
| 771 return XFONT_INSTANCE | |
| 772 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width; | |
| 773 } | |
| 774 | |
| 775 static int | |
| 776 tab_pix_width (struct window *w) | |
| 777 { | |
| 778 return space_width (w) * tab_char_width (w); | |
| 779 } | |
| 780 | |
| 781 /* Given a pixel position in a window, return the pixel location of | |
| 782 the next tabstop. Tabs are calculated from the left window edge in | |
| 783 terms of spaces displayed in the default face. Formerly the space | |
| 784 width was determined using the currently active face. That method | |
| 785 leads to tabstops which do not line up. */ | |
| 786 | |
| 787 static int | |
| 788 next_tab_position (struct window *w, int start_pixpos, int left_pixpos) | |
| 789 { | |
| 790 int n_pos = left_pixpos; | |
| 791 int pix_tab_width = tab_pix_width (w); | |
| 792 | |
| 793 /* Adjust n_pos for any hscrolling which has happened. */ | |
| 794 if (WINDOW_SCROLLED (w)) | |
| 795 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset; | |
| 796 | |
| 797 while (n_pos <= start_pixpos) | |
| 798 n_pos += pix_tab_width; | |
| 799 | |
| 800 return n_pos; | |
| 801 } | |
| 802 | |
| 803 /* For the given window, calculate the outside and margin boundaries for a | |
| 804 display line. The whitespace boundaries must be calculated by the text | |
| 805 layout routines. */ | |
| 806 | |
| 807 layout_bounds | |
| 808 calculate_display_line_boundaries (struct window *w, int modeline) | |
| 809 { | |
| 810 layout_bounds bounds; | |
| 811 | |
| 812 /* Set the outermost boundaries which are the boundaries of the | |
| 813 window itself minus the gutters (and minus the scrollbars if this | |
| 814 is for the modeline). */ | |
| 815 if (!modeline) | |
| 816 { | |
| 817 bounds.left_out = WINDOW_TEXT_LEFT (w); | |
| 818 bounds.right_out = WINDOW_TEXT_RIGHT (w); | |
| 819 } | |
| 820 else | |
| 821 { | |
| 822 bounds.left_out = WINDOW_MODELINE_LEFT (w); | |
| 823 bounds.right_out = WINDOW_MODELINE_RIGHT (w); | |
| 824 } | |
| 825 | |
| 826 /* The inner boundaries mark where the glyph margins are located. */ | |
| 827 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
| 828 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
| 829 | |
| 830 /* We cannot fully calculate the whitespace boundaries as they | |
| 831 depend on the contents of the line being displayed. */ | |
| 832 bounds.left_white = bounds.left_in; | |
| 833 bounds.right_white = bounds.right_in; | |
| 834 | |
| 835 return bounds; | |
| 836 } | |
| 837 | |
| 819 | 838 /* This takes a display_block and its containing line and corrects the yoffset |
| 839 of each glyph in the block to cater for the ascent of the line as a | |
| 840 whole. Must be called *after* the line-ascent is known! */ | |
| 841 | |
| 842 static void | |
| 843 calculate_yoffset (struct display_line *dl, struct display_block *fixup) | |
| 844 { | |
| 845 int i; | |
| 846 for (i=0; i<Dynarr_length (fixup->runes); i++) | |
| 847 { | |
| 848 struct rune *r = Dynarr_atp (fixup->runes,i); | |
| 849 if (r->type == RUNE_DGLYPH) | |
| 4187 | 850 { |
| 851 if (r->object.dglyph.ascent < dl->ascent) | |
| 852 r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent + | |
| 819 | 853 r->object.dglyph.descent; |
| 4187 | 854 } |
| 819 | 855 } |
| 856 } | |
| 857 | |
| 858 /* Calculate the textual baseline (the ascent and descent values for the | |
| 859 display_line as a whole). | |
| 860 | |
| 861 If the baseline is completely blank, or contains no manually positioned | |
| 862 glyphs, then the textual baseline is simply the baseline of the default font. | |
| 863 (The `contains no manually positioned glyphs' part is actually done for | |
| 867 | 864 us by `add_ichar_rune'.) |
| 819 | 865 |
| 866 If the baseline contains pixmaps, and they're all manually positioned, then | |
| 867 the textual baseline location is constrained that way, and we need do no | |
| 868 work. | |
| 869 | |
| 870 If the baseline contains pixmaps, and at least one is automatically | |
| 871 positioned, then the textual ascent is the largest ascent on the line, and | |
| 872 the textual descent is the largest descent (which is how things are set up at | |
| 873 entry to this function anyway): except that if the max_ascent + max_descent | |
| 874 is too small for the height of the line (say you've adjusted the baseline of | |
| 875 a short glyph, and there's a tall one next to it), then take the ascent and | |
| 876 descent for the line individually from the largest of the explicitly set | |
| 877 ascent/descent, and the rescaled ascent/descent of the default font, scaled | |
| 878 such that the largest glyph will fit. | |
| 879 | |
| 880 This means that if you have a short glyph (but taller than the default | |
| 881 font's descent) forced right under the baseline, and a really tall | |
| 882 automatically positioned glyph, that the descent for the line is just big | |
| 883 enough for the manually positioned short glyph, and the tall one uses as | |
| 884 much of that space as the default font would were it as tall as the tall | |
| 885 glyph; but that the ascent is big enough for the tall glyph to fit. | |
| 886 | |
| 887 This behaviour means that under no circumstances will changing the baseline | |
| 888 of a short glyph cause a tall glyph to move around; nor will it move the | |
| 889 textual baseline more than necessary. (Changing a tall glyph's baseline | |
| 890 might move the text's baseline arbitrarily, of course.) */ | |
| 891 | |
| 892 static void | |
| 893 calculate_baseline (pos_data *data) | |
| 894 { | |
| 895 /* Blank line: baseline is default font's baseline. */ | |
| 896 | |
| 897 if (!data->new_ascent && !data->new_descent) | |
| 898 { | |
| 899 /* We've got a blank line so initialize these values from the default | |
| 4187 | 900 face. */ |
| 819 | 901 default_face_font_info (data->window, &data->new_ascent, |
| 902 &data->new_descent, 0, 0, 0); | |
| 903 } | |
| 4187 | 904 |
| 819 | 905 /* No automatically positioned glyphs? Return at once. */ |
| 906 if (!data->need_baseline_computation) | |
| 907 return; | |
| 908 | |
| 909 /* Is the tallest glyph on the line automatically positioned? | |
| 910 If it's manually positioned, or it's automatically positioned | |
| 911 and there's enough room for it anyway, we need do no more work. */ | |
| 912 if (data->max_pixmap_height > data->new_ascent + data->new_descent) | |
| 913 { | |
| 914 int default_font_ascent, default_font_descent, default_font_height; | |
| 915 int scaled_default_font_ascent, scaled_default_font_descent; | |
| 4187 | 916 |
| 819 | 917 default_face_font_info (data->window, &default_font_ascent, |
| 918 &default_font_descent, &default_font_height, | |
| 919 0, 0); | |
| 920 | |
| 921 scaled_default_font_ascent = data->max_pixmap_height * | |
| 922 default_font_ascent / default_font_height; | |
| 923 | |
| 924 data->new_ascent = max (data->new_ascent, scaled_default_font_ascent); | |
| 925 | |
| 926 /* The ascent may have expanded now. Do we still need to grow the descent, | |
| 4187 | 927 or are things big enough? |
| 928 | |
| 929 The +1 caters for the baseline row itself. */ | |
| 819 | 930 if (data->max_pixmap_height > data->new_ascent + data->new_descent) |
| 4187 | 931 { |
| 932 scaled_default_font_descent = (data->max_pixmap_height * | |
| 819 | 933 default_font_descent / default_font_height) + 1; |
| 934 | |
| 4187 | 935 data->new_descent = max (data->new_descent, scaled_default_font_descent); |
| 936 } | |
| 819 | 937 } |
| 938 } | |
| 939 | |
| 428 | 940 /* Given a display line and a starting position, ensure that the |
| 941 contents of the display line accurately represent the visual | |
| 942 representation of the buffer contents starting from the given | |
| 943 position when displayed in the given window. The display line ends | |
| 944 when the contents of the line reach the right boundary of the given | |
| 945 window. */ | |
| 946 | |
| 665 | 947 static Charbpos |
| 428 | 948 generate_display_line (struct window *w, struct display_line *dl, int bounds, |
| 665 | 949 Charbpos start_pos, prop_block_dynarr **prop, |
| 428 | 950 int type) |
| 951 { | |
| 826 | 952 Charbpos ret_charpos; |
| 428 | 953 int overlay_width; |
| 954 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); | |
| 955 | |
| 956 /* If our caller hasn't already set the boundaries, then do so now. */ | |
| 957 if (!bounds) | |
| 958 dl->bounds = calculate_display_line_boundaries (w, 0); | |
| 959 | |
| 960 /* Reset what this line is using. */ | |
| 961 if (dl->display_blocks) | |
| 962 Dynarr_reset (dl->display_blocks); | |
| 963 if (dl->left_glyphs) | |
| 964 { | |
| 965 Dynarr_free (dl->left_glyphs); | |
| 966 dl->left_glyphs = 0; | |
| 967 } | |
| 968 if (dl->right_glyphs) | |
| 969 { | |
| 970 Dynarr_free (dl->right_glyphs); | |
| 971 dl->right_glyphs = 0; | |
| 972 } | |
| 973 | |
| 974 /* We aren't generating a modeline at the moment. */ | |
| 975 dl->modeline = 0; | |
| 976 | |
| 977 /* Create a display block for the text region of the line. */ | |
| 978 { | |
| 979 /* #### urk urk urk!!! Chuck fix this shit! */ | |
| 665 | 980 Bytebpos hacked_up_bytebpos = |
| 981 create_text_block (w, dl, charbpos_to_bytebpos (b, start_pos), | |
| 428 | 982 prop, type); |
| 826 | 983 if (hacked_up_bytebpos > BYTE_BUF_ZV (b)) |
| 984 ret_charpos = BUF_ZV (b) + 1; | |
| 428 | 985 else |
| 826 | 986 ret_charpos = bytebpos_to_charbpos (b, hacked_up_bytebpos); |
| 428 | 987 } |
| 826 | 988 dl->charpos = start_pos; |
| 989 if (dl->end_charpos < dl->charpos) | |
| 990 dl->end_charpos = dl->charpos; | |
| 428 | 991 |
| 992 if (MARKERP (Voverlay_arrow_position) | |
| 993 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position)) | |
| 994 && start_pos == marker_position (Voverlay_arrow_position) | |
| 995 && (STRINGP (Voverlay_arrow_string) | |
| 996 || GLYPHP (Voverlay_arrow_string))) | |
| 997 { | |
| 998 overlay_width = create_overlay_glyph_block (w, dl); | |
| 999 } | |
| 1000 else | |
| 1001 overlay_width = 0; | |
| 1002 | |
| 1003 /* If there are left glyphs associated with any character in the | |
| 1004 text block, then create a display block to handle them. */ | |
| 1005 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
| 1006 create_left_glyph_block (w, dl, overlay_width); | |
| 1007 | |
| 1008 /* If there are right glyphs associated with any character in the | |
| 1009 text block, then create a display block to handle them. */ | |
| 1010 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
| 1011 create_right_glyph_block (w, dl); | |
| 1012 | |
| 1013 /* In the future additional types of display blocks may be generated | |
| 1014 here. */ | |
| 1015 | |
| 826 | 1016 w->last_redisplay_pos = ret_charpos; |
| 1017 | |
| 1018 return ret_charpos; | |
| 428 | 1019 } |
| 1020 | |
| 1021 /* Adds an hscroll glyph to a display block. If this is called, then | |
| 1022 the block had better be empty. | |
| 1023 | |
| 1024 Yes, there are multiple places where this function is called but | |
| 1025 that is the way it has to be. Each calling function has to deal | |
| 826 | 1026 with byte_start_col_enabled a little differently depending on the |
| 428 | 1027 object being worked with. */ |
| 1028 | |
| 1029 static prop_block_dynarr * | |
| 1030 add_hscroll_rune (pos_data *data) | |
| 1031 { | |
| 1032 struct glyph_block gb; | |
| 1033 prop_block_dynarr *retval; | |
| 826 | 1034 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
| 647 | 1035 int old_cursor_type = data->cursor_type; |
| 826 | 1036 Bytebpos byte_old_charpos = data->byte_charpos; |
| 428 | 1037 |
| 1038 if (data->cursor_type == CURSOR_ON | |
| 826 | 1039 && data->byte_cursor_charpos >= data->byte_start_col_enabled |
| 1040 && data->byte_cursor_charpos <= data->byte_charpos) | |
| 1041 { | |
| 1042 data->byte_cursor_charpos = data->byte_start_col_enabled; | |
| 428 | 1043 } |
| 1044 else | |
| 1045 { | |
| 1046 data->cursor_type = NO_CURSOR; | |
| 1047 } | |
| 1048 | |
| 826 | 1049 data->byte_endpos = data->byte_charpos; |
| 1050 data->byte_charpos = data->byte_start_col_enabled; | |
| 428 | 1051 |
| 1052 gb.extent = Qnil; | |
| 1053 gb.glyph = Vhscroll_glyph; | |
| 1054 { | |
| 1055 int oldpixpos = data->pixpos; | |
| 442 | 1056 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, |
| 428 | 1057 GLYPH_CACHEL (XWINDOW (data->window), |
| 1058 HSCROLL_GLYPH_INDEX)); | |
| 1059 data->hscroll_glyph_width_adjust = | |
| 1060 data->pixpos - oldpixpos - space_width (XWINDOW (data->window)); | |
| 1061 } | |
| 826 | 1062 data->byte_endpos = 0; |
| 1063 data->byte_cursor_charpos = byte_old_cursor_charpos; | |
| 428 | 1064 data->cursor_type = old_cursor_type; |
| 826 | 1065 data->byte_charpos = byte_old_charpos; |
| 1066 | |
| 1067 data->byte_start_col_enabled = 0; | |
| 428 | 1068 return retval; |
| 1069 } | |
| 1070 | |
| 793 | 1071 /* Adds a character rune to a display block. If there is not enough room |
| 1072 to fit the rune on the display block (as determined by the MAX_PIXPOS) | |
| 1073 then it adds nothing and returns ADD_FAILED. If | |
| 1074 NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't allow the char's height | |
| 867 | 1075 to affect the total line height. (See add_ibyte_string_runes()). */ |
| 428 | 1076 |
| 1077 static prop_block_dynarr * | |
| 867 | 1078 add_ichar_rune_1 (pos_data *data, int no_contribute_to_line_height) |
| 428 | 1079 { |
| 1080 struct rune rb, *crb; | |
| 1081 int width, local; | |
| 1082 | |
| 1083 if (data->start_col) | |
| 1084 { | |
| 1085 data->start_col--; | |
| 1086 | |
| 1087 if (data->start_col) | |
| 1088 return NULL; | |
| 1089 } | |
| 1090 | |
| 826 | 1091 if (data->byte_start_col_enabled) |
| 428 | 1092 { |
| 1093 return add_hscroll_rune (data); | |
| 1094 } | |
| 1095 | |
| 1096 if (data->ch == '\n') | |
| 1097 { | |
| 1098 data->font_is_bogus = 0; | |
| 1099 /* Cheesy end-of-line pseudo-character. */ | |
| 1100 width = data->blank_width; | |
| 1101 } | |
| 1102 else | |
| 1103 { | |
| 867 | 1104 Lisp_Object charset = ichar_charset (data->ch); |
| 428 | 1105 if (!EQ (charset, data->last_charset) || |
| 1106 data->findex != data->last_findex) | |
| 1107 { | |
| 1108 /* OK, we need to do things the hard way. */ | |
| 1109 struct window *w = XWINDOW (data->window); | |
| 1110 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex); | |
| 1111 Lisp_Object font_instance = | |
| 1112 ensure_face_cachel_contains_charset (cachel, data->window, | |
| 1113 charset); | |
| 440 | 1114 Lisp_Font_Instance *fi; |
| 428 | 1115 |
| 1116 if (EQ (font_instance, Vthe_null_font_instance)) | |
| 1117 { | |
| 1118 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); | |
| 1119 data->font_is_bogus = 1; | |
| 1120 } | |
| 1121 else | |
| 1122 data->font_is_bogus = 0; | |
| 1123 | |
| 1124 fi = XFONT_INSTANCE (font_instance); | |
| 771 | 1125 if (!fi->proportional_p || data->font_is_bogus) |
| 1126 { | |
| 867 | 1127 Ichar ch = data->font_is_bogus ? '~' : data->ch; |
| 771 | 1128 |
| 1129 data->last_char_width = | |
| 4187 | 1130 redisplay_text_width_ichar_string (XWINDOW (data->window), |
| 771 | 1131 data->findex, &ch, 1); |
| 1132 } | |
| 428 | 1133 else |
| 1134 data->last_char_width = -1; | |
| 819 | 1135 |
| 793 | 1136 if (!no_contribute_to_line_height) |
| 1137 { | |
| 1138 data->new_ascent = max (data->new_ascent, (int) fi->ascent); | |
| 1139 data->new_descent = max (data->new_descent, (int) fi->descent); | |
| 1140 } | |
| 819 | 1141 |
| 428 | 1142 data->last_charset = charset; |
| 1143 data->last_findex = data->findex; | |
| 1144 } | |
| 1145 | |
| 1146 width = data->last_char_width; | |
| 771 | 1147 if (width < 0) /* proportional fonts */ |
| 867 | 1148 width = redisplay_text_width_ichar_string (XWINDOW (data->window), |
| 771 | 1149 data->findex, |
| 1150 &data->ch, 1); | |
| 428 | 1151 } |
| 1152 | |
| 1153 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos)) | |
| 1154 { | |
| 1155 return ADD_FAILED; | |
| 1156 } | |
| 1157 | |
| 1158 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes)) | |
| 1159 { | |
| 1160 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes)); | |
| 1161 local = 0; | |
| 1162 } | |
| 1163 else | |
| 1164 { | |
| 1165 crb = &rb; | |
| 1166 local = 1; | |
| 1167 } | |
| 1168 | |
| 1169 crb->findex = data->findex; | |
| 1170 crb->xpos = data->pixpos; | |
| 1171 crb->width = width; | |
| 826 | 1172 if (data->byte_charpos) |
| 428 | 1173 { |
| 1174 if (NILP (data->string)) | |
| 826 | 1175 crb->charpos = |
| 793 | 1176 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER |
| 1177 (XWINDOW (data->window))), | |
| 826 | 1178 data->byte_charpos); |
| 428 | 1179 else |
| 826 | 1180 crb->charpos = |
| 1181 string_index_byte_to_char (data->string, data->byte_charpos); | |
| 428 | 1182 } |
| 1183 else if (data->is_modeline) | |
| 826 | 1184 crb->charpos = data->modeline_charpos; |
| 428 | 1185 else |
| 442 | 1186 /* Text but not in buffer */ |
| 826 | 1187 crb->charpos = 0; |
| 428 | 1188 crb->type = RUNE_CHAR; |
| 1189 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch; | |
| 1190 crb->endpos = 0; | |
| 1191 | |
| 1192 if (data->cursor_type == CURSOR_ON) | |
| 1193 { | |
| 826 | 1194 if (data->byte_charpos == data->byte_cursor_charpos) |
| 428 | 1195 { |
| 1196 crb->cursor_type = CURSOR_ON; | |
| 1197 data->cursor_x = Dynarr_length (data->db->runes); | |
| 1198 } | |
| 1199 else | |
| 1200 crb->cursor_type = CURSOR_OFF; | |
| 1201 } | |
| 1202 else if (data->cursor_type == NEXT_CURSOR) | |
| 1203 { | |
| 1204 crb->cursor_type = CURSOR_ON; | |
| 1205 data->cursor_x = Dynarr_length (data->db->runes); | |
| 1206 data->cursor_type = NO_CURSOR; | |
| 1207 } | |
| 1208 else if (data->cursor_type == IGNORE_CURSOR) | |
| 1209 crb->cursor_type = IGNORE_CURSOR; | |
| 1210 else | |
| 1211 crb->cursor_type = CURSOR_OFF; | |
| 1212 | |
| 1213 if (local) | |
| 1214 Dynarr_add (data->db->runes, *crb); | |
| 1215 else | |
| 1216 Dynarr_increment (data->db->runes); | |
| 1217 | |
| 1218 data->pixpos += width; | |
| 1219 | |
| 1220 return NULL; | |
| 1221 } | |
| 1222 | |
| 793 | 1223 static prop_block_dynarr * |
| 867 | 1224 add_ichar_rune (pos_data *data) |
| 1225 { | |
| 1226 return add_ichar_rune_1 (data, 0); | |
| 1227 } | |
| 1228 | |
| 1229 /* Given a string C_STRING of length C_LENGTH, call add_ichar_rune for | |
| 793 | 1230 each character in the string. Propagate any left-over data unless |
| 1231 NO_PROP is non-zero. If NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't | |
| 1232 allow this character to increase the total height of the line. (This is | |
| 1233 used when the character is part of a text glyph. In that case, the | |
| 1234 glyph code itself adjusts the line height as necessary, depending on | |
| 1235 whether glyph-contrib-p is true.) */ | |
| 428 | 1236 |
| 1237 static prop_block_dynarr * | |
| 867 | 1238 add_ibyte_string_runes (pos_data *data, Ibyte *c_string, |
| 793 | 1239 Bytecount c_length, int no_prop, |
| 1240 int no_contribute_to_line_height) | |
| 428 | 1241 { |
| 867 | 1242 Ibyte *pos, *end = c_string + c_length; |
| 428 | 1243 prop_block_dynarr *prop; |
| 1244 | |
| 1245 /* #### This function is too simplistic. It needs to do the same | |
| 1246 sort of character interpretation (display-table lookup, | |
| 1247 ctl-arrow checking), etc. that create_text_block() does. | |
| 1248 The functionality to do this in that routine needs to be | |
| 1249 modularized. */ | |
| 1250 | |
| 1251 for (pos = c_string; pos < end;) | |
| 1252 { | |
| 867 | 1253 Ibyte *old_pos = pos; |
| 1254 | |
| 1255 data->ch = itext_ichar (pos); | |
| 1256 | |
| 1257 prop = add_ichar_rune_1 (data, no_contribute_to_line_height); | |
| 428 | 1258 |
| 1259 if (prop) | |
| 1260 { | |
| 1261 if (no_prop) | |
| 1262 return ADD_FAILED; | |
| 1263 else | |
| 1264 { | |
| 1265 struct prop_block pb; | |
| 1266 Bytecount len = end - pos; | |
| 1267 prop = Dynarr_new (prop_block); | |
| 1268 | |
| 1269 pb.type = PROP_STRING; | |
| 867 | 1270 pb.data.p_string.str = xnew_array (Ibyte, len); |
| 428 | 1271 strncpy ((char *) pb.data.p_string.str, (char *) pos, len); |
| 1272 pb.data.p_string.len = len; | |
| 1273 | |
| 1274 Dynarr_add (prop, pb); | |
| 1275 return prop; | |
| 1276 } | |
| 1277 } | |
| 867 | 1278 INC_IBYTEPTR (pos); |
| 428 | 1279 assert (pos <= end); |
| 464 | 1280 /* #### Duplicate code from add_string_to_fstring_db_runes |
| 1281 should we do more?*/ | |
| 1282 data->bytepos += pos - old_pos; | |
| 428 | 1283 } |
| 1284 | |
| 1285 return NULL; | |
| 1286 } | |
| 1287 | |
| 1288 /* Add a single rune of the specified width. The area covered by this | |
| 1289 rune will be displayed in the foreground color of the associated | |
| 1290 face. */ | |
| 1291 | |
| 1292 static prop_block_dynarr * | |
| 1293 add_blank_rune (pos_data *data, struct window *w, int char_tab_width) | |
| 1294 { | |
| 1295 struct rune rb; | |
| 1296 | |
| 1297 /* If data->start_col is not 0 then this call to add_blank_rune must have | |
| 1298 been to add it as a tab. */ | |
| 1299 if (data->start_col) | |
| 1300 { | |
| 1301 /* assert (w != NULL) */ | |
| 1302 prop_block_dynarr *retval; | |
| 1303 | |
| 1304 /* If we have still not fully scrolled horizontally, subtract | |
| 4187 | 1305 the width of this tab and return. */ |
| 428 | 1306 if (char_tab_width < data->start_col) |
| 1307 { | |
| 1308 data->start_col -= char_tab_width; | |
| 1309 return NULL; | |
| 1310 } | |
| 1311 else if (char_tab_width == data->start_col) | |
| 1312 data->blank_width = 0; | |
| 1313 else | |
| 1314 { | |
| 1315 int spcwid = space_width (w); | |
| 1316 | |
| 1317 if (spcwid >= data->blank_width) | |
| 1318 data->blank_width = 0; | |
| 1319 else | |
| 1320 data->blank_width -= spcwid; | |
| 1321 } | |
| 1322 | |
| 1323 data->start_col = 0; | |
| 1324 retval = add_hscroll_rune (data); | |
| 1325 | |
| 1326 /* Could be caused by the handling of the hscroll rune. */ | |
| 1327 if (retval != NULL || !data->blank_width) | |
| 1328 return retval; | |
| 1329 } | |
| 1330 | |
| 1331 /* Blank runes are always calculated to fit. */ | |
| 1332 assert (data->pixpos + data->blank_width <= data->max_pixpos); | |
| 1333 | |
| 1334 rb.findex = data->findex; | |
| 1335 rb.xpos = data->pixpos; | |
| 1336 rb.width = data->blank_width; | |
| 826 | 1337 if (data->byte_charpos) |
| 1338 rb.charpos = | |
| 665 | 1339 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))), |
| 826 | 1340 data->byte_charpos); |
| 428 | 1341 else |
| 1342 /* #### and this is really correct too? */ | |
| 826 | 1343 rb.charpos = 0; |
| 428 | 1344 rb.endpos = 0; |
| 1345 rb.type = RUNE_BLANK; | |
| 1346 | |
| 1347 if (data->cursor_type == CURSOR_ON) | |
| 1348 { | |
| 826 | 1349 if (data->byte_charpos == data->byte_cursor_charpos) |
| 428 | 1350 { |
| 1351 rb.cursor_type = CURSOR_ON; | |
| 1352 data->cursor_x = Dynarr_length (data->db->runes); | |
| 1353 } | |
| 1354 else | |
| 1355 rb.cursor_type = CURSOR_OFF; | |
| 1356 } | |
| 1357 else if (data->cursor_type == NEXT_CURSOR) | |
| 1358 { | |
| 1359 rb.cursor_type = CURSOR_ON; | |
| 1360 data->cursor_x = Dynarr_length (data->db->runes); | |
| 1361 data->cursor_type = NO_CURSOR; | |
| 1362 } | |
| 1363 else | |
| 1364 rb.cursor_type = CURSOR_OFF; | |
| 1365 | |
| 1366 Dynarr_add (data->db->runes, rb); | |
| 1367 data->pixpos += data->blank_width; | |
| 1368 | |
| 1369 return NULL; | |
| 1370 } | |
| 1371 | |
| 1372 /* Add runes representing a character in octal. */ | |
| 1373 | |
| 1374 #define ADD_NEXT_OCTAL_RUNE_CHAR do \ | |
| 1375 { \ | |
| 867 | 1376 if (add_failed || (add_failed = add_ichar_rune (data))) \ |
| 428 | 1377 { \ |
| 1378 struct prop_block pb; \ | |
| 1379 if (!prop) \ | |
| 1380 prop = Dynarr_new (prop_block); \ | |
| 1381 \ | |
| 1382 pb.type = PROP_CHAR; \ | |
| 1383 pb.data.p_char.ch = data->ch; \ | |
| 1384 pb.data.p_char.cursor_type = data->cursor_type; \ | |
| 1385 Dynarr_add (prop, pb); \ | |
| 1386 } \ | |
| 1387 } while (0) | |
| 1388 | |
| 1389 static prop_block_dynarr * | |
| 1390 add_octal_runes (pos_data *data) | |
| 1391 { | |
| 819 | 1392 prop_block_dynarr *add_failed, *prop = 0; |
| 867 | 1393 Ichar orig_char = data->ch; |
| 647 | 1394 int orig_cursor_type = data->cursor_type; |
| 428 | 1395 |
| 1396 /* Initialize */ | |
| 1397 add_failed = NULL; | |
| 1398 | |
| 1399 if (data->start_col) | |
| 1400 data->start_col--; | |
| 1401 | |
| 1402 if (!data->start_col) | |
| 1403 { | |
| 826 | 1404 if (data->byte_start_col_enabled) |
| 428 | 1405 { |
| 1406 add_failed = add_hscroll_rune (data); | |
| 1407 } | |
| 1408 else | |
| 1409 { | |
| 1410 struct glyph_block gb; | |
| 1411 struct window *w = XWINDOW (data->window); | |
| 1412 | |
| 1413 gb.extent = Qnil; | |
| 1414 gb.glyph = Voctal_escape_glyph; | |
| 1415 add_failed = | |
| 1416 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
| 1417 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX)); | |
| 1418 } | |
| 1419 } | |
| 1420 | |
| 1421 /* We only propagate information if the glyph was partially | |
| 1422 added. */ | |
| 1423 if (add_failed) | |
| 1424 return add_failed; | |
| 1425 | |
| 1426 data->cursor_type = IGNORE_CURSOR; | |
| 1427 | |
| 1428 if (data->ch >= 0x100) | |
| 1429 { | |
| 1430 /* If the character is an extended Mule character, it could have | |
| 3498 | 1431 up to 21 bits. For the moment, we treat it as a seven-digit |
| 428 | 1432 octal number. This is not that pretty, but whatever. */ |
| 1433 data->ch = (7 & (orig_char >> 18)) + '0'; | |
| 1434 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1435 | |
| 1436 data->ch = (7 & (orig_char >> 15)) + '0'; | |
| 1437 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1438 | |
| 1439 data->ch = (7 & (orig_char >> 12)) + '0'; | |
| 1440 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1441 | |
| 1442 data->ch = (7 & (orig_char >> 9)) + '0'; | |
| 1443 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1444 } | |
| 1445 | |
| 1446 data->ch = (7 & (orig_char >> 6)) + '0'; | |
| 1447 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1448 | |
| 1449 data->ch = (7 & (orig_char >> 3)) + '0'; | |
| 1450 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1451 | |
| 1452 data->ch = (7 & orig_char) + '0'; | |
| 1453 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1454 | |
| 1455 data->cursor_type = orig_cursor_type; | |
| 819 | 1456 return NULL; |
| 428 | 1457 } |
| 1458 | |
| 1459 #undef ADD_NEXT_OCTAL_RUNE_CHAR | |
| 1460 | |
| 1461 /* Add runes representing a control character to a display block. */ | |
| 1462 | |
| 1463 static prop_block_dynarr * | |
| 1464 add_control_char_runes (pos_data *data, struct buffer *b) | |
| 1465 { | |
| 1466 if (!NILP (b->ctl_arrow)) | |
| 1467 { | |
| 1468 prop_block_dynarr *prop; | |
| 867 | 1469 Ichar orig_char = data->ch; |
| 647 | 1470 int old_cursor_type = data->cursor_type; |
| 428 | 1471 |
| 1472 /* Initialize */ | |
| 1473 prop = NULL; | |
| 1474 | |
| 1475 if (data->start_col) | |
| 1476 data->start_col--; | |
| 1477 | |
| 1478 if (!data->start_col) | |
| 1479 { | |
| 826 | 1480 if (data->byte_start_col_enabled) |
| 428 | 1481 { |
| 1482 prop_block_dynarr *retval; | |
| 1483 | |
| 1484 retval = add_hscroll_rune (data); | |
| 1485 if (retval) | |
| 1486 return retval; | |
| 1487 } | |
| 1488 else | |
| 1489 { | |
| 1490 struct glyph_block gb; | |
| 1491 struct window *w = XWINDOW (data->window); | |
| 1492 | |
| 1493 gb.extent = Qnil; | |
| 1494 gb.glyph = Vcontrol_arrow_glyph; | |
| 1495 | |
| 1496 /* We only propagate information if the glyph was partially | |
| 1497 added. */ | |
| 1498 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
| 1499 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX))) | |
| 1500 return ADD_FAILED; | |
| 1501 } | |
| 1502 } | |
| 1503 | |
| 1504 if (orig_char == 0177) | |
| 1505 data->ch = '?'; | |
| 1506 else | |
| 1507 data->ch = orig_char ^ 0100; | |
| 1508 data->cursor_type = IGNORE_CURSOR; | |
| 1509 | |
| 867 | 1510 if (add_ichar_rune (data)) |
| 428 | 1511 { |
| 1512 struct prop_block pb; | |
| 1513 if (!prop) | |
| 1514 prop = Dynarr_new (prop_block); | |
| 1515 | |
| 1516 pb.type = PROP_CHAR; | |
| 1517 pb.data.p_char.ch = data->ch; | |
| 1518 pb.data.p_char.cursor_type = data->cursor_type; | |
| 1519 Dynarr_add (prop, pb); | |
| 1520 } | |
| 1521 | |
| 1522 data->cursor_type = old_cursor_type; | |
| 1523 return prop; | |
| 1524 } | |
| 1525 else | |
| 1526 { | |
| 1527 return add_octal_runes (data); | |
| 1528 } | |
| 1529 } | |
| 1530 | |
| 1531 static prop_block_dynarr * | |
| 1532 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) | |
| 1533 { | |
| 1534 prop_block_dynarr *prop = NULL; | |
| 1535 | |
| 1536 if (STRINGP (entry)) | |
| 1537 { | |
| 867 | 1538 prop = add_ibyte_string_runes (data, |
| 428 | 1539 XSTRING_DATA (entry), |
| 1540 XSTRING_LENGTH (entry), | |
| 793 | 1541 0, 0); |
| 428 | 1542 } |
| 1543 else if (GLYPHP (entry)) | |
| 1544 { | |
| 1545 if (data->start_col) | |
| 1546 data->start_col--; | |
| 1547 | |
| 826 | 1548 if (!data->start_col && data->byte_start_col_enabled) |
| 428 | 1549 { |
| 1550 prop = add_hscroll_rune (data); | |
| 1551 } | |
| 1552 else | |
| 1553 { | |
| 1554 struct glyph_block gb; | |
| 1555 | |
| 1556 gb.glyph = entry; | |
| 1557 gb.extent = Qnil; | |
| 1558 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); | |
| 1559 } | |
| 1560 } | |
| 1561 else if (CHAR_OR_CHAR_INTP (entry)) | |
| 1562 { | |
| 1563 data->ch = XCHAR_OR_CHAR_INT (entry); | |
| 867 | 1564 prop = add_ichar_rune (data); |
| 428 | 1565 } |
| 1566 else if (CONSP (entry)) | |
| 1567 { | |
| 1568 if (EQ (XCAR (entry), Qformat) | |
| 1569 && CONSP (XCDR (entry)) | |
| 1570 && STRINGP (XCAR (XCDR (entry)))) | |
| 1571 { | |
| 1572 Lisp_Object format = XCAR (XCDR (entry)); | |
| 665 | 1573 Bytebpos len = XSTRING_LENGTH (format); |
| 867 | 1574 Ibyte *src = XSTRING_DATA (format), *end = src + len; |
| 2367 | 1575 Ibyte *result = alloca_ibytes (len); |
| 867 | 1576 Ibyte *dst = result; |
| 428 | 1577 |
| 1578 while (src < end) | |
| 1579 { | |
| 867 | 1580 Ichar c = itext_ichar (src); |
| 1581 INC_IBYTEPTR (src); | |
| 428 | 1582 if (c != '%' || src == end) |
| 867 | 1583 dst += set_itext_ichar (dst, c); |
| 428 | 1584 else |
| 1585 { | |
| 867 | 1586 c = itext_ichar (src); |
| 1587 INC_IBYTEPTR (src); | |
| 428 | 1588 switch (c) |
| 1589 { | |
| 1590 /*case 'x': | |
| 1591 dst += long_to_string_base ((char *)dst, data->ch, 16); | |
| 1592 break;*/ | |
| 1593 case '%': | |
| 867 | 1594 dst += set_itext_ichar (dst, '%'); |
| 428 | 1595 break; |
| 442 | 1596 /* #### unimplemented */ |
| 428 | 1597 } |
| 1598 } | |
| 1599 } | |
| 867 | 1600 prop = add_ibyte_string_runes (data, result, dst - result, 0, 0); |
| 428 | 1601 } |
| 1602 } | |
| 1603 | |
| 1604 /* Else blow it off because someone added a bad entry and we don't | |
| 1605 have any safe way of signaling an error. */ | |
| 1606 return prop; | |
| 1607 } | |
| 1608 | |
| 1609 /* Given a display table entry, call the appropriate functions to | |
| 1610 display each element of the entry. */ | |
| 1611 | |
| 1612 static prop_block_dynarr * | |
| 1613 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) | |
| 1614 { | |
| 1615 prop_block_dynarr *prop = NULL; | |
| 1616 if (VECTORP (entry)) | |
| 1617 { | |
| 440 | 1618 Lisp_Vector *de = XVECTOR (entry); |
| 428 | 1619 EMACS_INT len = vector_length (de); |
| 1620 int elt; | |
| 1621 | |
| 1622 for (elt = 0; elt < len; elt++) | |
| 1623 { | |
| 1624 if (NILP (vector_data (de)[elt])) | |
| 1625 continue; | |
| 1626 else | |
| 1627 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]); | |
| 1628 /* Else blow it off because someone added a bad entry and we | |
| 1629 don't have any safe way of signaling an error. Hey, this | |
| 1630 comment sounds familiar. */ | |
| 1631 | |
| 1632 /* #### Still need to add any remaining elements to the | |
| 4187 | 1633 propagation information. */ |
| 428 | 1634 if (prop) |
| 1635 return prop; | |
| 1636 } | |
| 1637 } | |
| 1638 else | |
| 1639 prop = add_disp_table_entry_runes_1 (data, entry); | |
| 1640 return prop; | |
| 1641 } | |
| 1642 | |
| 1643 /* Add runes which were propagated from the previous line. */ | |
| 1644 | |
| 1645 static prop_block_dynarr * | |
| 1646 add_propagation_runes (prop_block_dynarr **prop, pos_data *data) | |
| 1647 { | |
| 1648 /* #### Remember to handle start_col parameter of data when the rest of | |
| 1649 this is finished. */ | |
| 1650 /* #### Chuck -- I've redone this function a bit. It looked like the | |
| 1651 case of not all the propagation blocks being added was not handled | |
| 1652 well. */ | |
| 1653 /* #### Chuck -- I also think the double indirection of PROP is kind | |
| 1654 of bogus. A cleaner solution is just to check for | |
| 1655 Dynarr_length (prop) > 0. */ | |
| 1656 /* #### This function also doesn't even pay attention to ADD_FAILED! | |
| 1657 This is seriously fucked! Seven ####'s in 130 lines -- is that a | |
| 1658 record? */ | |
| 1659 int elt; | |
| 1660 prop_block_dynarr *add_failed; | |
| 826 | 1661 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
| 647 | 1662 int old_cursor_type = data->cursor_type; |
| 428 | 1663 |
| 1664 for (elt = 0; elt < Dynarr_length (*prop); elt++) | |
| 1665 { | |
| 1666 struct prop_block *pb = Dynarr_atp (*prop, elt); | |
| 1667 | |
| 1668 switch (pb->type) | |
| 1669 { | |
| 1670 case PROP_CHAR: | |
| 1671 data->ch = pb->data.p_char.ch; | |
| 826 | 1672 data->byte_cursor_charpos = pb->data.p_char.byte_cursor_charpos; |
| 428 | 1673 data->cursor_type = pb->data.p_char.cursor_type; |
| 867 | 1674 add_failed = add_ichar_rune (data); |
| 428 | 1675 |
| 1676 if (add_failed) | |
| 1677 goto oops_no_more_space; | |
| 1678 break; | |
| 1679 case PROP_STRING: | |
| 1680 if (pb->data.p_string.str) | |
| 1726 | 1681 xfree (pb->data.p_string.str, Ibyte *); |
| 428 | 1682 /* #### bogus bogus -- this doesn't do anything! |
| 867 | 1683 Should probably call add_ibyte_string_runes(), |
| 428 | 1684 once that function is fixed. */ |
| 1685 break; | |
| 1686 case PROP_MINIBUF_PROMPT: | |
| 1687 { | |
| 1688 face_index old_findex = data->findex; | |
| 826 | 1689 Bytebpos byte_old_charpos = data->byte_charpos; |
| 428 | 1690 |
| 1691 data->findex = DEFAULT_INDEX; | |
| 826 | 1692 data->byte_charpos = 0; |
| 428 | 1693 data->cursor_type = NO_CURSOR; |
| 1694 | |
| 1695 while (pb->data.p_string.len > 0) | |
| 1696 { | |
| 867 | 1697 data->ch = itext_ichar (pb->data.p_string.str); |
| 1698 add_failed = add_ichar_rune (data); | |
| 428 | 1699 |
| 1700 if (add_failed) | |
| 1701 { | |
| 1702 data->findex = old_findex; | |
| 826 | 1703 data->byte_charpos = byte_old_charpos; |
| 428 | 1704 goto oops_no_more_space; |
| 1705 } | |
| 1706 else | |
| 1707 { | |
| 1708 /* Complicated equivalent of ptr++, len-- */ | |
| 867 | 1709 Ibyte *oldpos = pb->data.p_string.str; |
| 1710 INC_IBYTEPTR (pb->data.p_string.str); | |
| 428 | 1711 pb->data.p_string.len -= pb->data.p_string.str - oldpos; |
| 1712 } | |
| 1713 } | |
| 1714 | |
| 1715 data->findex = old_findex; | |
| 1716 /* ##### FIXME FIXME FIXME -- Upon successful return from | |
| 826 | 1717 this function, data->byte_charpos is automatically incremented. |
| 428 | 1718 However, we don't want that to happen if we were adding |
| 1719 the minibuffer prompt. */ | |
| 1720 { | |
| 1721 struct buffer *buf = | |
| 1722 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))); | |
| 1723 /* #### Chuck fix this shit or I'm gonna scream! */ | |
| 826 | 1724 if (byte_old_charpos > BYTE_BUF_BEGV (buf)) |
| 4187 | 1725 data->byte_charpos = prev_bytebpos (buf, byte_old_charpos); |
| 1726 else | |
| 428 | 1727 /* #### is this correct? Does anyone know? |
| 1728 Does anyone care? Is this a cheesy hack or what? */ | |
| 4187 | 1729 data->byte_charpos = BYTE_BUF_BEGV (buf) - 1; |
| 428 | 1730 } |
| 1731 } | |
| 1732 break; | |
| 1733 case PROP_BLANK: | |
| 1734 { | |
| 1735 /* #### I think it's unnecessary and misleading to preserve | |
| 1736 the blank_width, as it implies that the value carries | |
| 1737 over from one rune to the next, which is wrong. */ | |
| 1738 int old_width = data->blank_width; | |
| 1739 face_index old_findex = data->findex; | |
| 1740 | |
| 1741 data->findex = pb->data.p_blank.findex; | |
| 1742 data->blank_width = pb->data.p_blank.width; | |
| 826 | 1743 data->byte_cursor_charpos = 0; |
| 428 | 1744 data->cursor_type = IGNORE_CURSOR; |
| 1745 | |
| 1746 if (data->pixpos + data->blank_width > data->max_pixpos) | |
| 1747 data->blank_width = data->max_pixpos - data->pixpos; | |
| 1748 | |
| 1749 /* We pass a bogus value of char_tab_width. It shouldn't | |
| 4187 | 1750 matter because unless something is really screwed up |
| 1751 this call won't cause that arg to be used. */ | |
| 428 | 1752 add_failed = add_blank_rune (data, XWINDOW (data->window), 0); |
| 1753 | |
| 1754 /* This can happen in the case where we have a tab which | |
| 4187 | 1755 is wider than the window. */ |
| 428 | 1756 if (data->blank_width != pb->data.p_blank.width) |
| 1757 { | |
| 1758 pb->data.p_blank.width -= data->blank_width; | |
| 1759 add_failed = ADD_FAILED; | |
| 1760 } | |
| 1761 | |
| 1762 data->findex = old_findex; | |
| 1763 data->blank_width = old_width; | |
| 1764 | |
| 1765 if (add_failed) | |
| 1766 goto oops_no_more_space; | |
| 1767 } | |
| 1768 break; | |
| 1769 default: | |
| 2500 | 1770 ABORT (); |
| 428 | 1771 } |
| 1772 } | |
| 1773 | |
| 1774 oops_no_more_space: | |
| 1775 | |
| 826 | 1776 data->byte_cursor_charpos = byte_old_cursor_charpos; |
| 428 | 1777 data->cursor_type = old_cursor_type; |
| 1778 if (elt < Dynarr_length (*prop)) | |
| 1779 { | |
| 1780 Dynarr_delete_many (*prop, 0, elt); | |
| 1781 return *prop; | |
| 1782 } | |
| 1783 else | |
| 1784 { | |
| 1785 Dynarr_free (*prop); | |
| 1786 return NULL; | |
| 1787 } | |
| 1788 } | |
| 1789 | |
| 3025 | 1790 /* Add `text' layout glyphs at position POS_TYPE that are contained to |
| 428 | 1791 the display block, but add all other types to the appropriate list |
| 1792 of the display line. They will be added later by different | |
| 1793 routines. */ | |
| 1794 | |
| 1795 static prop_block_dynarr * | |
| 1796 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, | |
| 1797 int allow_cursor, struct glyph_cachel *cachel) | |
| 1798 { | |
| 1799 struct window *w = XWINDOW (data->window); | |
| 1800 | |
| 440 | 1801 /* If window faces changed, and glyph instance is text, then |
| 1802 glyph sizes might have changed too */ | |
| 1803 invalidate_glyph_geometry_maybe (gb->glyph, w); | |
| 1804 | |
| 442 | 1805 /* This makes sure the glyph is in the cachels. |
| 1806 | |
| 1807 #### We do this to make sure the glyph is in the glyph cachels, | |
| 1808 so that the dirty flag can be reset after redisplay has | |
| 1809 finished. We should do this some other way, maybe by iterating | |
| 1810 over the window cache of subwindows. */ | |
| 1811 get_glyph_cachel_index (w, gb->glyph); | |
| 1812 | |
| 428 | 1813 /* A nil extent indicates a special glyph (ex. truncator). */ |
| 1814 if (NILP (gb->extent) | |
| 1815 || (pos_type == BEGIN_GLYPHS && | |
| 1816 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) | |
| 1817 || (pos_type == END_GLYPHS && | |
| 442 | 1818 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) |
| 1819 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) | |
| 428 | 1820 { |
| 1821 struct rune rb; | |
| 1822 int width; | |
| 1823 int xoffset = 0; | |
| 1824 int ascent, descent; | |
| 1825 Lisp_Object baseline; | |
| 1826 Lisp_Object face; | |
| 442 | 1827 Lisp_Object instance; |
| 1828 face_index findex; | |
| 819 | 1829 prop_block_dynarr *retval = 0; |
| 428 | 1830 |
| 1831 if (cachel) | |
| 1832 width = cachel->width; | |
| 1833 else | |
| 438 | 1834 width = glyph_width (gb->glyph, data->window); |
| 428 | 1835 |
| 1836 if (!width) | |
| 1837 return NULL; | |
| 1838 | |
| 1839 if (data->start_col || data->start_col_xoffset) | |
| 1840 { | |
| 1841 int glyph_char_width = width / space_width (w); | |
| 1842 | |
| 1843 /* If we still have not fully scrolled horizontally after | |
| 4187 | 1844 taking into account the width of the glyph, subtract its |
| 1845 width and return. */ | |
| 428 | 1846 if (glyph_char_width < data->start_col) |
| 1847 { | |
| 1848 data->start_col -= glyph_char_width; | |
| 1849 return NULL; | |
| 1850 } | |
| 1851 else if (glyph_char_width == data->start_col) | |
| 1852 width = 0; | |
| 1853 else | |
| 1854 { | |
| 1855 xoffset = space_width (w) * data->start_col; | |
| 1856 width -= xoffset; | |
| 1857 | |
| 1858 /* #### Can this happen? */ | |
| 1859 if (width < 0) | |
| 1860 width = 0; | |
| 1861 } | |
| 1862 | |
| 1863 data->start_col = 0; | |
| 1864 retval = add_hscroll_rune (data); | |
| 1865 | |
| 1866 /* Could be caused by the handling of the hscroll rune. */ | |
| 1867 if (retval != NULL || !width) | |
| 1868 return retval; | |
| 1869 } | |
| 1870 else | |
| 1871 xoffset = 0; | |
| 1872 | |
| 1873 if (data->pixpos + width > data->max_pixpos) | |
| 1874 { | |
| 1875 /* If this is the first object we are attempting to add to | |
| 819 | 1876 the line then we ignore the horizontal_clip threshold. |
| 1877 Otherwise we will loop until the bottom of the window | |
| 1878 continually failing to add this glyph because it is wider | |
| 1879 than the window. We could alternatively just completely | |
| 1880 ignore the glyph and proceed from there but I think that | |
| 1881 this is a better solution. | |
| 4187 | 1882 |
| 819 | 1883 This does, however, create a different problem in that we |
| 1884 can end up adding the object to every single line, never | |
| 1885 getting any further - for instance an extent with a long | |
| 1886 start-glyph that covers multitple following | |
| 1887 characters. */ | |
| 428 | 1888 if (Dynarr_length (data->db->runes) |
| 1889 && data->max_pixpos - data->pixpos < horizontal_clip) | |
| 1890 return ADD_FAILED; | |
| 819 | 1891 else { |
| 1892 struct prop_block pb; | |
| 1893 | |
| 1894 /* We need to account for the width of the end-of-line | |
| 1895 glyph if there is nothing more in the line to display, | |
| 1896 since we will not display it in this instance. It seems | |
| 1897 kind of gross doing it here, but otherwise we have to | |
| 1898 search the runes in create_text_block(). */ | |
| 1899 if (data->ch == '\n') | |
| 1900 data->max_pixpos += data->end_glyph_width; | |
| 428 | 1901 width = data->max_pixpos - data->pixpos; |
| 819 | 1902 /* Add the glyph we are displaying, but clipping, to the |
| 1903 propagation data so that we don't try and do it | |
| 4187 | 1904 again. */ |
| 819 | 1905 retval = Dynarr_new (prop_block); |
| 1906 pb.type = PROP_GLYPH; | |
| 1907 pb.data.p_glyph.glyph = gb->glyph; | |
| 1908 pb.data.p_glyph.width = width; | |
| 1909 Dynarr_add (retval, pb); | |
| 1910 } | |
| 428 | 1911 } |
| 1912 | |
| 1913 if (cachel) | |
| 1914 { | |
| 1915 ascent = cachel->ascent; | |
| 1916 descent = cachel->descent; | |
| 1917 } | |
| 1918 else | |
| 1919 { | |
| 438 | 1920 ascent = glyph_ascent (gb->glyph, data->window); |
| 1921 descent = glyph_descent (gb->glyph, data->window); | |
| 428 | 1922 } |
| 1923 | |
| 1924 baseline = glyph_baseline (gb->glyph, data->window); | |
| 1925 | |
| 819 | 1926 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ |
| 1927 | |
| 428 | 1928 if (glyph_contrib_p (gb->glyph, data->window)) |
| 1929 { | |
| 1930 /* A pixmap that has not had a baseline explicitly set. Its | |
| 1931 contribution will be determined later. */ | |
| 1932 if (NILP (baseline)) | |
| 1933 { | |
| 1934 int height = ascent + descent; | |
| 819 | 1935 data->need_baseline_computation = 1; |
| 428 | 1936 data->max_pixmap_height = max (data->max_pixmap_height, height); |
| 1937 } | |
| 1938 | |
| 1939 /* A string so determine contribution normally. */ | |
| 1940 else if (EQ (baseline, Qt)) | |
| 1941 { | |
| 1942 data->new_ascent = max (data->new_ascent, ascent); | |
| 1943 data->new_descent = max (data->new_descent, descent); | |
| 1944 } | |
| 1945 | |
| 1946 /* A pixmap with an explicitly set baseline. We determine the | |
| 1947 contribution here. */ | |
| 1948 else if (INTP (baseline)) | |
| 1949 { | |
| 1950 int height = ascent + descent; | |
| 1951 int pix_ascent, pix_descent; | |
| 1952 | |
| 1953 pix_ascent = height * XINT (baseline) / 100; | |
| 1954 pix_descent = height - pix_ascent; | |
| 1955 | |
| 1956 data->new_ascent = max (data->new_ascent, pix_ascent); | |
| 1957 data->new_descent = max (data->new_descent, pix_descent); | |
| 819 | 1958 data->max_pixmap_height = max (data->max_pixmap_height, height); |
| 4187 | 1959 |
| 819 | 1960 rb.object.dglyph.descent = pix_descent; |
| 428 | 1961 } |
| 1962 | |
| 1963 /* Otherwise something is screwed up. */ | |
| 1964 else | |
| 2500 | 1965 ABORT (); |
| 428 | 1966 } |
| 1967 | |
| 1968 face = glyph_face (gb->glyph, data->window); | |
| 1969 if (NILP (face)) | |
| 442 | 1970 findex = data->findex; |
| 428 | 1971 else |
| 442 | 1972 findex = get_builtin_face_cache_index (w, face); |
| 1973 | |
| 1974 instance = glyph_image_instance (gb->glyph, data->window, | |
| 793 | 1975 ERROR_ME_DEBUG_WARN, 1); |
| 442 | 1976 if (TEXT_IMAGE_INSTANCEP (instance)) |
| 1977 { | |
| 1978 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); | |
| 1979 face_index orig_findex = data->findex; | |
| 826 | 1980 Bytebpos orig_charpos = data->byte_charpos; |
| 1981 Bytebpos orig_start_col_enabled = data->byte_start_col_enabled; | |
| 442 | 1982 |
| 1983 data->findex = findex; | |
| 826 | 1984 data->byte_start_col_enabled = 0; |
| 442 | 1985 if (!allow_cursor) |
| 826 | 1986 data->byte_charpos = 0; |
| 867 | 1987 add_ibyte_string_runes (data, XSTRING_DATA (string), |
| 793 | 1988 XSTRING_LENGTH (string), 0, 1); |
| 442 | 1989 data->findex = orig_findex; |
| 826 | 1990 data->byte_charpos = orig_charpos; |
| 1991 data->byte_start_col_enabled = orig_start_col_enabled; | |
| 819 | 1992 return retval; |
| 442 | 1993 } |
| 1994 | |
| 1995 rb.findex = findex; | |
| 428 | 1996 rb.xpos = data->pixpos; |
| 1997 rb.width = width; | |
| 826 | 1998 rb.charpos = 0; /* glyphs are never "at" anywhere */ |
| 1999 if (data->byte_endpos) | |
| 428 | 2000 /* #### is this necessary at all? */ |
| 665 | 2001 rb.endpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
| 826 | 2002 data->byte_endpos); |
| 428 | 2003 else |
| 4187 | 2004 rb.endpos = 0; |
| 428 | 2005 rb.type = RUNE_DGLYPH; |
| 2006 rb.object.dglyph.glyph = gb->glyph; | |
| 2007 rb.object.dglyph.extent = gb->extent; | |
| 2008 rb.object.dglyph.xoffset = xoffset; | |
| 819 | 2009 rb.object.dglyph.ascent = ascent; |
| 2010 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has | |
| 2011 a normal (textual) baseline. */ | |
| 428 | 2012 |
| 2013 if (allow_cursor) | |
| 2014 { | |
| 826 | 2015 rb.charpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
| 2016 data->byte_charpos); | |
| 428 | 2017 |
| 2018 if (data->cursor_type == CURSOR_ON) | |
| 2019 { | |
| 826 | 2020 if (data->byte_charpos == data->byte_cursor_charpos) |
| 428 | 2021 { |
| 2022 rb.cursor_type = CURSOR_ON; | |
| 2023 data->cursor_x = Dynarr_length (data->db->runes); | |
| 2024 } | |
| 2025 else | |
| 2026 rb.cursor_type = CURSOR_OFF; | |
| 2027 } | |
| 2028 else if (data->cursor_type == NEXT_CURSOR) | |
| 2029 { | |
| 2030 rb.cursor_type = CURSOR_ON; | |
| 2031 data->cursor_x = Dynarr_length (data->db->runes); | |
| 2032 data->cursor_type = NO_CURSOR; | |
| 2033 } | |
| 2034 else if (data->cursor_type == IGNORE_CURSOR) | |
| 2035 rb.cursor_type = IGNORE_CURSOR; | |
| 2036 else if (data->cursor_type == NO_CURSOR) | |
| 2037 rb.cursor_type = NO_CURSOR; | |
| 2038 else | |
| 2039 rb.cursor_type = CURSOR_OFF; | |
| 2040 } | |
| 2041 else | |
| 2042 rb.cursor_type = CURSOR_OFF; | |
| 2043 | |
| 2044 Dynarr_add (data->db->runes, rb); | |
| 2045 data->pixpos += width; | |
| 2046 | |
| 819 | 2047 return retval; |
| 428 | 2048 } |
| 2049 else | |
| 2050 { | |
| 2051 if (!NILP (glyph_face (gb->glyph, data->window))) | |
| 2052 gb->findex = | |
| 2053 get_builtin_face_cache_index (w, glyph_face (gb->glyph, | |
| 2054 data->window)); | |
| 2055 else | |
| 2056 gb->findex = data->findex; | |
| 2057 | |
| 2058 if (pos_type == BEGIN_GLYPHS) | |
| 2059 { | |
| 2060 if (!data->dl->left_glyphs) | |
| 2061 data->dl->left_glyphs = Dynarr_new (glyph_block); | |
| 2062 Dynarr_add (data->dl->left_glyphs, *gb); | |
| 2063 return NULL; | |
| 2064 } | |
| 2065 else if (pos_type == END_GLYPHS) | |
| 2066 { | |
| 2067 if (!data->dl->right_glyphs) | |
| 2068 data->dl->right_glyphs = Dynarr_new (glyph_block); | |
| 2069 Dynarr_add (data->dl->right_glyphs, *gb); | |
| 2070 return NULL; | |
| 2071 } | |
| 2072 else | |
| 2500 | 2073 ABORT (); /* there are no unknown types */ |
| 428 | 2074 } |
| 2075 | |
| 819 | 2076 return NULL; |
| 428 | 2077 } |
| 2078 | |
| 2079 /* Add all glyphs at position POS_TYPE that are contained in the given | |
| 2080 data. */ | |
| 2081 | |
| 2082 static prop_block_dynarr * | |
| 2083 add_glyph_runes (pos_data *data, int pos_type) | |
| 2084 { | |
| 2085 /* #### This still needs to handle the start_col parameter. Duh, Chuck, | |
| 2086 why didn't you just modify add_glyph_rune in the first place? */ | |
| 2087 int elt; | |
| 2088 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS | |
| 2089 ? data->ef->begin_glyphs | |
| 2090 : data->ef->end_glyphs); | |
| 2091 prop_block_dynarr *prop; | |
| 2092 | |
| 2093 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++) | |
| 2094 { | |
| 2095 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0, | |
| 2096 0); | |
| 2097 | |
| 2098 if (prop) | |
| 2099 { | |
| 2100 /* #### Add some propagation information. */ | |
| 2101 return prop; | |
| 2102 } | |
| 2103 } | |
| 2104 | |
| 2105 Dynarr_reset (glyph_arr); | |
| 2106 | |
| 2107 return NULL; | |
| 2108 } | |
| 2109 | |
| 2110 /* Given a position for a buffer in a window, ensure that the given | |
| 2111 display line DL accurately represents the text on a line starting | |
| 2112 at the given position. | |
| 2113 | |
| 826 | 2114 NOTE NOTE NOTE NOTE: This function works with and returns Bytebpos's. |
| 428 | 2115 You must do appropriate conversion. */ |
| 2116 | |
| 665 | 2117 static Bytebpos |
| 428 | 2118 create_text_block (struct window *w, struct display_line *dl, |
| 826 | 2119 Bytebpos byte_start_pos, prop_block_dynarr **prop, |
| 428 | 2120 int type) |
| 2121 { | |
| 2122 struct frame *f = XFRAME (w->frame); | |
| 2123 struct buffer *b = XBUFFER (w->buffer); | |
| 2124 struct device *d = XDEVICE (f->device); | |
| 2125 | |
| 2126 pos_data data; | |
| 2127 | |
| 2128 /* Don't display anything in the minibuffer if this window is not on | |
| 2129 a selected frame. We consider all other windows to be active | |
| 2130 minibuffers as it simplifies the coding. */ | |
| 2131 int active_minibuffer = (!MINI_WINDOW_P (w) || | |
| 2132 (f == device_selected_frame (d)) || | |
| 2133 is_surrogate_for_selected_frame (f)); | |
| 2134 | |
| 2135 int truncate_win = window_truncation_on (w); | |
| 2136 | |
| 2137 /* If the buffer's value of selective_display is an integer then | |
| 2138 only lines that start with less than selective_display columns of | |
| 2139 space will be displayed. If selective_display is t then all text | |
| 2140 after a ^M is invisible. */ | |
| 2141 int selective = (INTP (b->selective_display) | |
| 2142 ? XINT (b->selective_display) | |
| 434 | 2143 : (!NILP (b->selective_display) ? -1 : 0)); |
| 428 | 2144 |
| 2145 /* The variable ctl-arrow allows the user to specify what characters | |
| 2146 can actually be displayed and which octal should be used for. | |
| 2147 #### This variable should probably have some rethought done to | |
| 2148 it. | |
| 2149 | |
| 2367 | 2150 See also |
| 2151 | |
| 2152 (Info-goto-node "(internals)Future Work -- Display Tables") | |
| 2153 | |
| 2154 */ | |
| 867 | 2155 Ichar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
| 428 | 2156 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
| 2157 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
| 2158 ? 255 : 160)); | |
| 2159 | |
| 2160 Lisp_Object face_dt, window_dt; | |
| 2161 | |
| 2162 /* The text display block for this display line. */ | |
| 2163 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 2164 | |
| 2165 /* The first time through the main loop we need to force the glyph | |
| 2166 data to be updated. */ | |
| 2167 int initial = 1; | |
| 2168 | |
| 2169 /* Apparently the new extent_fragment_update returns an end position | |
| 2170 equal to the position passed in if there are no more runs to be | |
| 2171 displayed. */ | |
| 2172 int no_more_frags = 0; | |
| 2173 | |
| 2174 Lisp_Object synch_minibuffers_value = | |
| 2175 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer); | |
| 2176 | |
| 2177 dl->used_prop_data = 0; | |
| 2178 dl->num_chars = 0; | |
| 442 | 2179 dl->line_continuation = 0; |
| 428 | 2180 |
| 2181 xzero (data); | |
| 2182 data.ef = extent_fragment_new (w->buffer, f); | |
| 2183 | |
| 2184 /* These values are used by all of the rune addition routines. We add | |
| 2185 them to this structure for ease of passing. */ | |
| 2186 data.d = d; | |
| 793 | 2187 data.window = wrap_window (w); |
| 428 | 2188 data.string = Qnil; |
| 2189 data.db = db; | |
| 2190 data.dl = dl; | |
| 2191 | |
| 826 | 2192 data.byte_charpos = byte_start_pos; |
| 428 | 2193 data.pixpos = dl->bounds.left_in; |
| 2194 data.last_charset = Qunbound; | |
| 2195 data.last_findex = DEFAULT_INDEX; | |
| 2196 data.result_str = Qnil; | |
| 2197 | |
| 2198 /* Set the right boundary adjusting it to take into account any end | |
| 2199 glyph. Save the width of the end glyph for later use. */ | |
| 2200 data.max_pixpos = dl->bounds.right_in; | |
| 2201 if (truncate_win) | |
| 819 | 2202 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); |
| 428 | 2203 else |
| 819 | 2204 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); |
| 2205 data.max_pixpos -= data.end_glyph_width; | |
| 428 | 2206 |
| 2207 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f)) | |
| 2208 { | |
| 826 | 2209 data.byte_cursor_charpos = BYTE_BUF_ZV (b); |
| 428 | 2210 data.cursor_type = CURSOR_ON; |
| 2211 } | |
| 2212 else if (MINI_WINDOW_P (w) && !active_minibuffer) | |
| 2213 data.cursor_type = NO_CURSOR; | |
| 2214 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) && | |
| 2215 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
| 2216 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&& | |
| 2217 f == XFRAME(DEVICE_SELECTED_FRAME(d))) | |
| 2218 { | |
| 826 | 2219 data.byte_cursor_charpos = BYTE_BUF_PT (b); |
| 428 | 2220 data.cursor_type = CURSOR_ON; |
| 2221 } | |
| 2222 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | |
| 2223 { | |
| 826 | 2224 data.byte_cursor_charpos = byte_marker_position (w->pointm[type]); |
| 428 | 2225 data.cursor_type = CURSOR_ON; |
| 2226 } | |
| 2227 else | |
| 2228 data.cursor_type = NO_CURSOR; | |
| 2229 data.cursor_x = -1; | |
| 2230 | |
| 2231 data.start_col = w->hscroll; | |
| 2232 data.start_col_xoffset = w->left_xoffset; | |
| 826 | 2233 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
| 428 | 2234 data.hscroll_glyph_width_adjust = 0; |
| 2235 | |
| 2236 /* We regenerate the line from the very beginning. */ | |
| 2237 Dynarr_reset (db->runes); | |
| 2238 | |
| 2239 /* Why is this less than or equal and not just less than? If the | |
| 2240 starting position is already equal to the maximum we can't add | |
| 2241 anything else, right? Wrong. We might still have a newline to | |
| 2242 add. A newline can use the room allocated for an end glyph since | |
| 2243 if we add it we know we aren't going to be adding any end | |
| 2244 glyph. */ | |
| 2245 | |
| 2246 /* #### Chuck -- I think this condition should be while (1). | |
| 2247 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
| 2248 and the begin-glyph ends exactly at the end of the window, the | |
| 2249 end-glyph and text might not be displayed. while (1) ensures | |
| 2250 that the loop terminates only when either (a) there is | |
| 2251 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
| 2252 | |
| 2253 #### Also I think you need to ensure that the operation | |
| 2254 "add begin glyphs; add end glyphs; add text" is atomic and | |
| 2255 can't get interrupted in the middle. If you run off the end | |
| 2256 of the line during that operation, then you keep accumulating | |
| 2257 propagation data until you're done. Otherwise, if the (e.g.) | |
| 2258 there's a begin glyph at a particular position and attempting | |
| 2259 to display that glyph results in window-end being hit and | |
| 2260 propagation data being generated, then the character at that | |
| 2261 position won't be displayed. | |
| 2262 | |
| 2263 #### See also the comment after the end of this loop, below. | |
| 2264 */ | |
| 2265 while (data.pixpos <= data.max_pixpos | |
| 2266 && (active_minibuffer || !NILP (synch_minibuffers_value))) | |
| 2267 { | |
| 2268 /* #### This check probably should not be necessary. */ | |
| 826 | 2269 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
| 428 | 2270 { |
| 2271 /* #### urk! More of this lossage! */ | |
| 826 | 2272 data.byte_charpos--; |
| 428 | 2273 goto done; |
| 2274 } | |
| 2275 | |
| 2276 /* If selective display was an integer and we aren't working on | |
| 4187 | 2277 a continuation line then find the next line we are actually |
| 2278 supposed to display. */ | |
| 428 | 2279 if (selective > 0 |
| 826 | 2280 && (data.byte_charpos == BYTE_BUF_BEGV (b) |
| 2281 || BUF_FETCH_CHAR (b, prev_bytebpos (b, data.byte_charpos)) == '\n')) | |
| 2282 { | |
| 2283 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
| 428 | 2284 { |
| 826 | 2285 data.byte_charpos = |
| 2286 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
| 2287 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
| 428 | 2288 { |
| 826 | 2289 data.byte_charpos = BYTE_BUF_ZV (b); |
| 428 | 2290 goto done; |
| 2291 } | |
| 2292 } | |
| 2293 } | |
| 2294 | |
| 2295 /* Check for face changes. */ | |
| 826 | 2296 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
| 428 | 2297 { |
| 819 | 2298 Lisp_Object last_glyph = Qnil; |
| 2299 | |
| 2300 /* Deal with glyphs that we have already displayed. The | |
| 2301 theory is that if we end up with a PROP_GLYPH in the | |
| 2302 propagation data then we are clipping the glyph and there | |
| 2303 can be no propagation data before that point. The theory | |
| 2304 works because we always recalculate the extent-fragments | |
| 2305 for propagated data, we never actually propagate the | |
| 2306 fragments that still need to be displayed. */ | |
| 4187 | 2307 if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH) |
| 819 | 2308 { |
| 2309 last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph; | |
| 2310 Dynarr_free (*prop); | |
| 2311 *prop = 0; | |
| 2312 } | |
| 428 | 2313 /* Now compute the face and begin/end-glyph information. */ |
| 2314 data.findex = | |
| 665 | 2315 /* Remember that the extent-fragment routines deal in Bytebpos's. */ |
| 826 | 2316 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
| 428 | 2317 |
| 2318 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
| 2319 | |
| 826 | 2320 if (data.byte_charpos == data.ef->end) |
| 428 | 2321 no_more_frags = 1; |
| 2322 } | |
| 2323 initial = 0; | |
| 2324 | |
| 2325 /* Determine what is next to be displayed. We first handle any | |
| 4187 | 2326 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
| 2327 display then we determine what to do based on the character at the | |
| 2328 current buffer position. */ | |
| 428 | 2329 |
| 2330 /* If the current position is covered by an invisible extent, do | |
| 4187 | 2331 nothing (except maybe add some ellipses). |
| 428 | 2332 |
| 2333 #### The behavior of begin and end-glyphs at the edge of an | |
| 2334 invisible extent should be investigated further. This is | |
| 2335 fairly low priority though. */ | |
| 2336 if (data.ef->invisible) | |
| 2337 { | |
| 2338 /* #### Chuck, perhaps you could look at this code? I don't | |
| 2339 really know what I'm doing. */ | |
| 2340 if (*prop) | |
| 2341 { | |
| 2342 Dynarr_free (*prop); | |
| 2343 *prop = 0; | |
| 2344 } | |
| 2345 | |
| 2346 /* The extent fragment code only sets this when we should | |
| 2347 really display the ellipses. It makes sure the ellipses | |
| 2348 don't get displayed more than once in a row. */ | |
| 2349 if (data.ef->invisible_ellipses) | |
| 2350 { | |
| 2351 struct glyph_block gb; | |
| 2352 | |
| 2353 data.ef->invisible_ellipses_already_displayed = 1; | |
| 2354 data.ef->invisible_ellipses = 0; | |
| 2355 gb.extent = Qnil; | |
| 2356 gb.glyph = Vinvisible_text_glyph; | |
| 2357 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
| 2358 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
| 2359 /* Perhaps they shouldn't propagate if the very next thing | |
| 2360 is to display a newline (for compatibility with | |
| 2361 selective-display-ellipses)? Maybe that's too | |
| 2362 abstruse. */ | |
| 2363 if (*prop) | |
| 2364 goto done; | |
| 2365 } | |
| 2366 | |
| 2367 /* If point is in an invisible region we place it on the | |
| 4187 | 2368 next visible character. */ |
| 428 | 2369 if (data.cursor_type == CURSOR_ON |
| 826 | 2370 && data.byte_charpos == data.byte_cursor_charpos) |
| 428 | 2371 { |
| 2372 data.cursor_type = NEXT_CURSOR; | |
| 2373 } | |
| 2374 | |
| 2375 /* #### What if we we're dealing with a display table? */ | |
| 2376 if (data.start_col) | |
| 2377 data.start_col--; | |
| 2378 | |
| 826 | 2379 if (data.byte_charpos == BYTE_BUF_ZV (b)) |
| 428 | 2380 goto done; |
| 2381 else | |
| 826 | 2382 INC_BYTEBPOS (b, data.byte_charpos); |
| 428 | 2383 } |
| 2384 | |
| 2385 /* If there is propagation data, then it represents the current | |
| 819 | 2386 buffer position being displayed. Add them and advance the |
| 2387 position counter. This might also add the minibuffer | |
| 2388 prompt. */ | |
| 428 | 2389 else if (*prop) |
| 2390 { | |
| 2391 dl->used_prop_data = 1; | |
| 2392 *prop = add_propagation_runes (prop, &data); | |
| 2393 | |
| 2394 if (*prop) | |
| 2395 goto done; /* gee, a really narrow window */ | |
| 826 | 2396 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
| 428 | 2397 goto done; |
| 826 | 2398 else if (data.byte_charpos < BYTE_BUF_BEGV (b)) |
| 428 | 2399 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
| 826 | 2400 data.byte_charpos = BYTE_BUF_BEGV (b); |
| 428 | 2401 else |
| 826 | 2402 INC_BYTEBPOS (b, data.byte_charpos); |
| 428 | 2403 } |
| 2404 | |
| 2405 /* If there are end glyphs, add them to the line. These are | |
| 2406 the end glyphs for the previous run of text. We add them | |
| 2407 here rather than doing them at the end of handling the | |
| 2408 previous run so that glyphs at the beginning and end of | |
| 2409 a line are handled correctly. */ | |
| 819 | 2410 else if (Dynarr_length (data.ef->end_glyphs) > 0 |
| 2411 || Dynarr_length (data.ef->begin_glyphs) > 0) | |
| 2412 { | |
| 2413 glyph_block_dynarr* tmpglyphs = 0; | |
| 2414 /* #### I think this is safe, but could be wrong. */ | |
| 826 | 2415 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
| 819 | 2416 |
| 4187 | 2417 if (Dynarr_length (data.ef->end_glyphs) > 0) |
| 819 | 2418 { |
| 2419 *prop = add_glyph_runes (&data, END_GLYPHS); | |
| 2420 tmpglyphs = data.ef->end_glyphs; | |
| 2421 } | |
| 2422 | |
| 2423 /* If there are begin glyphs, add them to the line. */ | |
| 4187 | 2424 if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0) |
| 819 | 2425 { |
| 2426 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); | |
| 2427 tmpglyphs = data.ef->begin_glyphs; | |
| 2428 } | |
| 2429 | |
| 4187 | 2430 if (*prop) |
| 819 | 2431 { |
| 2432 /* If we just clipped a glyph and we are at the end of a | |
| 2433 line and there are more glyphs to display then do | |
| 2434 appropriate processing to not get a continuation | |
| 2435 glyph. */ | |
| 4187 | 2436 if (*prop != ADD_FAILED |
| 819 | 2437 && Dynarr_atp (*prop, 0)->type == PROP_GLYPH |
| 2438 && data.ch == '\n') | |
| 4187 | 2439 { |
| 819 | 2440 /* If there are no more glyphs then do the normal |
| 4187 | 2441 processing. |
| 819 | 2442 |
| 2443 #### This doesn't actually work if the same glyph is | |
| 2444 present more than once in the block. To solve | |
| 2445 this we would have to carry the index around | |
| 2446 which might be problematic since the fragment is | |
| 2447 recalculated for each line. */ | |
| 2448 if (EQ (Dynarr_end (tmpglyphs)->glyph, | |
| 2449 Dynarr_atp (*prop, 0)->data.p_glyph.glyph)) | |
| 2450 { | |
| 2451 Dynarr_free (*prop); | |
| 2452 *prop = 0; | |
| 2453 } | |
| 2454 else { | |
| 2455 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 867 | 2456 add_ichar_rune (&data); /* discard prop data. */ |
| 819 | 2457 goto done; |
| 2458 } | |
| 2459 } | |
| 2460 else | |
| 2461 goto done; | |
| 2462 } | |
| 428 | 2463 } |
| 2464 | |
| 2465 /* If at end-of-buffer, we've already processed begin and | |
| 2466 end-glyphs at this point and there's no text to process, | |
| 2467 so we're done. */ | |
| 826 | 2468 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
| 428 | 2469 goto done; |
| 2470 | |
| 2471 else | |
| 2472 { | |
| 2473 Lisp_Object entry = Qnil; | |
| 2474 /* Get the character at the current buffer position. */ | |
| 826 | 2475 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
| 428 | 2476 if (!NILP (face_dt) || !NILP (window_dt)) |
| 2477 entry = display_table_entry (data.ch, face_dt, window_dt); | |
| 2478 | |
| 2479 /* If there is a display table entry for it, hand it off to | |
| 4187 | 2480 add_disp_table_entry_runes and let it worry about it. */ |
| 428 | 2481 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
| 2482 { | |
| 2483 *prop = add_disp_table_entry_runes (&data, entry); | |
| 2484 | |
| 2485 if (*prop) | |
| 2486 goto done; | |
| 2487 } | |
| 2488 | |
| 2489 /* Check if we have hit a newline character. If so, add a marker | |
| 4187 | 2490 to the line and end this loop. */ |
| 428 | 2491 else if (data.ch == '\n') |
| 2492 { | |
| 2493 /* We aren't going to be adding an end glyph so give its | |
| 4187 | 2494 space back in order to make sure that the cursor can |
| 2495 fit. */ | |
| 819 | 2496 data.max_pixpos += data.end_glyph_width; |
| 428 | 2497 |
| 2498 if (selective > 0 | |
| 826 | 2499 && (byte_spaces_at_point |
| 2500 (b, next_bytebpos (b, data.byte_charpos)) | |
| 428 | 2501 >= selective)) |
| 2502 { | |
| 2503 if (!NILP (b->selective_display_ellipses)) | |
| 2504 { | |
| 2505 struct glyph_block gb; | |
| 2506 | |
| 2507 gb.extent = Qnil; | |
| 2508 gb.glyph = Vinvisible_text_glyph; | |
| 2509 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
| 2510 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
| 2511 } | |
| 2512 else | |
| 2513 { | |
| 2514 /* Cheesy, cheesy, cheesy. We mark the end of the | |
| 2515 line with a special "character rune" whose width | |
| 2516 is the EOL cursor width and whose character is | |
| 2517 the non-printing character '\n'. */ | |
| 2518 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 867 | 2519 *prop = add_ichar_rune (&data); |
| 428 | 2520 } |
| 2521 | |
| 826 | 2522 /* We need to set data.byte_charpos to the start of the |
| 4187 | 2523 next visible region in order to make this line |
| 2524 appear to contain all of the invisible area. | |
| 2525 Otherwise, the line cache won't work | |
| 2526 correctly. */ | |
| 826 | 2527 INC_BYTEBPOS (b, data.byte_charpos); |
| 2528 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
| 428 | 2529 { |
| 826 | 2530 data.byte_charpos = |
| 2531 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
| 2532 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
| 428 | 2533 { |
| 826 | 2534 data.byte_charpos = BYTE_BUF_ZV (b); |
| 428 | 2535 break; |
| 2536 } | |
| 2537 } | |
| 826 | 2538 if (BYTE_BUF_FETCH_CHAR |
| 2539 (b, prev_bytebpos (b, data.byte_charpos)) == '\n') | |
| 2540 DEC_BYTEBPOS (b, data.byte_charpos); | |
| 428 | 2541 } |
| 2542 else | |
| 2543 { | |
| 2544 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 867 | 2545 *prop = add_ichar_rune (&data); |
| 428 | 2546 } |
| 2547 | |
| 2548 goto done; | |
| 2549 } | |
| 2550 | |
| 2551 /* If the current character is ^M, and selective display is | |
| 4187 | 2552 enabled, then add the invisible-text-glyph if |
| 2553 selective-display-ellipses is set. In any case, this | |
| 2554 line is done. */ | |
| 428 | 2555 else if (data.ch == (('M' & 037)) && selective == -1) |
| 2556 { | |
| 826 | 2557 Bytebpos byte_next_charpos; |
| 428 | 2558 |
| 2559 /* Find the buffer position at the end of the line. */ | |
| 826 | 2560 byte_next_charpos = |
| 2561 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
| 2562 if (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_next_charpos)) | |
| 428 | 2563 == '\n') |
| 826 | 2564 DEC_BYTEBPOS (b, byte_next_charpos); |
| 428 | 2565 |
| 2566 /* If the cursor is somewhere in the elided text make | |
| 4187 | 2567 sure that the cursor gets drawn appropriately. */ |
| 428 | 2568 if (data.cursor_type == CURSOR_ON |
| 826 | 2569 && (data.byte_cursor_charpos >= data.byte_charpos && |
| 2570 data.byte_cursor_charpos < byte_next_charpos)) | |
| 428 | 2571 { |
| 2572 data.cursor_type = NEXT_CURSOR; | |
| 2573 } | |
| 2574 | |
| 2575 /* We won't be adding a truncation or continuation glyph | |
| 4187 | 2576 so give up the room allocated for them. */ |
| 819 | 2577 data.max_pixpos += data.end_glyph_width; |
| 428 | 2578 |
| 2579 if (!NILP (b->selective_display_ellipses)) | |
| 2580 { | |
| 2581 /* We don't propagate anything from the invisible | |
| 4187 | 2582 text glyph if it fails to fit. This is |
| 2583 intentional. */ | |
| 428 | 2584 struct glyph_block gb; |
| 2585 | |
| 2586 gb.extent = Qnil; | |
| 2587 gb.glyph = Vinvisible_text_glyph; | |
| 2588 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, | |
| 2589 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
| 2590 } | |
| 2591 | |
| 2592 /* Set the buffer position to the end of the line. We | |
| 4187 | 2593 need to do this before potentially adding a newline |
| 2594 so that the cursor flag will get set correctly (if | |
| 2595 needed). */ | |
| 826 | 2596 data.byte_charpos = byte_next_charpos; |
| 428 | 2597 |
| 2598 if (NILP (b->selective_display_ellipses) | |
| 826 | 2599 || data.byte_cursor_charpos == byte_next_charpos) |
| 428 | 2600 { |
| 2601 /* We have to at least add a newline character so | |
| 4187 | 2602 that the cursor shows up properly. */ |
| 428 | 2603 data.ch = '\n'; |
| 2604 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 2605 data.findex = DEFAULT_INDEX; | |
| 2606 data.start_col = 0; | |
| 2607 data.start_col_xoffset = 0; | |
| 826 | 2608 data.byte_start_col_enabled = 0; |
| 428 | 2609 |
| 867 | 2610 add_ichar_rune (&data); |
| 428 | 2611 } |
| 2612 | |
| 2613 /* This had better be a newline but doing it this way | |
| 4187 | 2614 we'll see obvious incorrect results if it isn't. No |
| 2615 need to abort here. */ | |
| 826 | 2616 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
| 428 | 2617 |
| 2618 goto done; | |
| 2619 } | |
| 2620 | |
| 2621 /* If the current character is considered to be printable, then | |
| 4187 | 2622 just add it. */ |
| 428 | 2623 else if (data.ch >= printable_min) |
| 2624 { | |
| 867 | 2625 *prop = add_ichar_rune (&data); |
| 428 | 2626 if (*prop) |
| 2627 goto done; | |
| 2628 } | |
| 2629 | |
| 2630 /* If the current character is a tab, determine the next tab | |
| 4187 | 2631 starting position and add a blank rune which extends from the |
| 2632 current pixel position to that starting position. */ | |
| 428 | 2633 else if (data.ch == '\t') |
| 2634 { | |
| 2635 int tab_start_pixpos = data.pixpos; | |
| 2636 int next_tab_start; | |
| 2637 int char_tab_width; | |
| 2638 int prop_width = 0; | |
| 2639 | |
| 2640 if (data.start_col > 1) | |
| 434 | 2641 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)) |
| 428 | 2642 + data.start_col_xoffset; |
| 2643 | |
| 2644 next_tab_start = | |
| 2645 next_tab_position (w, tab_start_pixpos, | |
| 2646 dl->bounds.left_in + | |
| 2647 data.hscroll_glyph_width_adjust); | |
| 2648 if (next_tab_start > data.max_pixpos) | |
| 2649 { | |
| 2650 prop_width = next_tab_start - data.max_pixpos; | |
| 2651 next_tab_start = data.max_pixpos; | |
| 2652 } | |
| 2653 data.blank_width = next_tab_start - data.pixpos; | |
| 2654 char_tab_width = | |
| 2655 (next_tab_start - tab_start_pixpos) / space_width (w); | |
| 2656 | |
| 2657 *prop = add_blank_rune (&data, w, char_tab_width); | |
| 2658 | |
| 2659 /* add_blank_rune is only supposed to be called with | |
| 4187 | 2660 sizes guaranteed to fit in the available space. */ |
| 428 | 2661 assert (!(*prop)); |
| 2662 | |
| 2663 if (prop_width) | |
| 2664 { | |
| 2665 struct prop_block pb; | |
| 2666 *prop = Dynarr_new (prop_block); | |
| 2667 | |
| 2668 pb.type = PROP_BLANK; | |
| 2669 pb.data.p_blank.width = prop_width; | |
| 2670 pb.data.p_blank.findex = data.findex; | |
| 2671 Dynarr_add (*prop, pb); | |
| 2672 | |
| 2673 goto done; | |
| 2674 } | |
| 2675 } | |
| 2676 | |
| 2677 /* If character is a control character, pass it off to | |
| 4187 | 2678 add_control_char_runes. |
| 428 | 2679 |
| 2680 The is_*() routines have undefined results on | |
| 2681 arguments outside of the range [-1, 255]. (This | |
| 2682 often bites people who carelessly use `char' instead | |
| 2683 of `unsigned char'.) | |
| 2684 */ | |
| 867 | 2685 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
| 428 | 2686 { |
| 2687 *prop = add_control_char_runes (&data, b); | |
| 2688 | |
| 2689 if (*prop) | |
| 2690 goto done; | |
| 2691 } | |
| 2692 | |
| 2693 /* If the character is above the ASCII range and we have not | |
| 4187 | 2694 already handled it, then print it as an octal number. */ |
| 428 | 2695 else if (data.ch >= 0200) |
| 2696 { | |
| 2697 *prop = add_octal_runes (&data); | |
| 2698 | |
| 2699 if (*prop) | |
| 2700 goto done; | |
| 2701 } | |
| 2702 | |
| 2703 /* Assume the current character is considered to be printable, | |
| 4187 | 2704 then just add it. */ |
| 428 | 2705 else |
| 2706 { | |
| 867 | 2707 *prop = add_ichar_rune (&data); |
| 428 | 2708 if (*prop) |
| 2709 goto done; | |
| 2710 } | |
| 2711 | |
| 826 | 2712 INC_BYTEBPOS (b, data.byte_charpos); |
| 428 | 2713 } |
| 2714 } | |
| 2715 | |
| 2716 done: | |
| 2717 | |
| 2718 /* Determine the starting point of the next line if we did not hit the | |
| 2719 end of the buffer. */ | |
| 826 | 2720 if (data.byte_charpos < BYTE_BUF_ZV (b) |
| 428 | 2721 && (active_minibuffer || !NILP (synch_minibuffers_value))) |
| 2722 { | |
| 2723 /* #### This check is not correct. If the line terminated | |
| 2724 due to a begin-glyph or end-glyph hitting window-end, then | |
| 826 | 2725 data.ch will not point to the character at data.byte_charpos. If |
| 428 | 2726 you make the two changes mentioned at the top of this loop, |
| 2727 you should be able to say '(if (*prop))'. That should also | |
| 826 | 2728 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
| 428 | 2729 check. */ |
| 2730 | |
| 2731 /* The common case is that the line ended because we hit a newline. | |
| 4187 | 2732 In that case, the next character is just the next buffer |
| 2733 position. */ | |
| 428 | 2734 if (data.ch == '\n') |
| 2735 { | |
| 2736 /* If data.start_col_enabled is still true, then the window is | |
| 4187 | 2737 scrolled far enough so that nothing on this line is visible. |
| 2738 We need to stick a truncation glyph at the beginning of the | |
| 2739 line in that case unless the line is completely blank. */ | |
| 826 | 2740 if (data.byte_start_col_enabled) |
| 428 | 2741 { |
| 2742 if (data.cursor_type == CURSOR_ON) | |
| 2743 { | |
| 826 | 2744 if (data.byte_cursor_charpos >= byte_start_pos |
| 2745 && data.byte_cursor_charpos <= data.byte_charpos) | |
| 2746 data.byte_cursor_charpos = data.byte_charpos; | |
| 428 | 2747 } |
| 2748 data.findex = DEFAULT_INDEX; | |
| 2749 data.start_col = 0; | |
| 826 | 2750 data.byte_start_col_enabled = 0; |
| 2751 | |
| 2752 if (data.byte_charpos != byte_start_pos) | |
| 428 | 2753 { |
| 2754 struct glyph_block gb; | |
| 2755 | |
| 2756 gb.extent = Qnil; | |
| 2757 gb.glyph = Vhscroll_glyph; | |
| 2758 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
| 2759 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX)); | |
| 2760 } | |
| 2761 else | |
| 2762 { | |
| 2763 /* This duplicates code down below to add a newline to | |
| 4187 | 2764 the end of an otherwise empty line.*/ |
| 428 | 2765 data.ch = '\n'; |
| 2766 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 2767 | |
| 867 | 2768 add_ichar_rune (&data); |
| 428 | 2769 } |
| 2770 } | |
| 2771 | |
| 826 | 2772 INC_BYTEBPOS (b, data.byte_charpos); |
| 428 | 2773 } |
| 2774 | |
| 2775 /* Otherwise we have a buffer line which cannot fit on one display | |
| 4187 | 2776 line. */ |
| 428 | 2777 else |
| 2778 { | |
| 2779 struct glyph_block gb; | |
| 2780 struct glyph_cachel *cachel; | |
| 2781 | |
| 2782 /* If the line is to be truncated then we actually have to look | |
| 4187 | 2783 for the next newline. We also add the end-of-line glyph which |
| 2784 we know will fit because we adjusted the right border before | |
| 2785 we starting laying out the line. */ | |
| 819 | 2786 data.max_pixpos += data.end_glyph_width; |
| 428 | 2787 data.findex = DEFAULT_INDEX; |
| 2788 gb.extent = Qnil; | |
| 2789 | |
| 2790 if (truncate_win) | |
| 2791 { | |
| 826 | 2792 Bytebpos byte_pos; |
| 428 | 2793 |
| 2794 /* Now find the start of the next line. */ | |
| 826 | 2795 byte_pos = byte_find_next_newline_no_quit (b, data.byte_charpos, 1); |
| 428 | 2796 |
| 2797 /* If the cursor is past the truncation line then we | |
| 4187 | 2798 make it appear on the truncation glyph. If we've hit |
| 2799 the end of the buffer then we also make the cursor | |
| 2800 appear unless eob is immediately preceded by a | |
| 2801 newline. In that case the cursor should actually | |
| 2802 appear on the next line. */ | |
| 428 | 2803 if (data.cursor_type == CURSOR_ON |
| 826 | 2804 && data.byte_cursor_charpos >= data.byte_charpos |
| 2805 && (data.byte_cursor_charpos < byte_pos || | |
| 2806 (byte_pos == BYTE_BUF_ZV (b) | |
| 2807 && (byte_pos == BYTE_BUF_BEGV (b) | |
| 2808 || (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_pos)) | |
| 428 | 2809 != '\n'))))) |
| 826 | 2810 data.byte_cursor_charpos = byte_pos; |
| 428 | 2811 else |
| 2812 data.cursor_type = NO_CURSOR; | |
| 2813 | |
| 826 | 2814 data.byte_charpos = byte_pos; |
| 428 | 2815 gb.glyph = Vtruncation_glyph; |
| 2816 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
| 2817 } | |
| 2818 else | |
| 2819 { | |
| 2820 /* The cursor can never be on the continuation glyph. */ | |
| 2821 data.cursor_type = NO_CURSOR; | |
| 2822 | |
| 826 | 2823 /* data.byte_charpos is already at the start of the next line. */ |
| 428 | 2824 |
| 442 | 2825 dl->line_continuation = 1; |
| 428 | 2826 gb.glyph = Vcontinuation_glyph; |
| 2827 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
| 2828 } | |
| 2829 | |
| 442 | 2830 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
| 428 | 2831 |
| 826 | 2832 if (truncate_win && data.byte_charpos == BYTE_BUF_ZV (b) |
| 2833 && BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, BYTE_BUF_ZV (b))) != '\n') | |
| 428 | 2834 /* #### Damn this losing shit. */ |
| 826 | 2835 data.byte_charpos++; |
| 428 | 2836 } |
| 2837 } | |
| 2838 else if ((active_minibuffer || !NILP (synch_minibuffers_value)) | |
| 826 | 2839 && (!echo_area_active (f) || data.byte_charpos == BYTE_BUF_ZV (b))) |
| 428 | 2840 { |
| 2841 /* We need to add a marker to the end of the line since there is no | |
| 4187 | 2842 newline character in order for the cursor to get drawn. We label |
| 2843 it as a newline so that it gets handled correctly by the | |
| 2844 whitespace routines below. */ | |
| 428 | 2845 |
| 2846 data.ch = '\n'; | |
| 2847 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 2848 data.findex = DEFAULT_INDEX; | |
| 2849 data.start_col = 0; | |
| 2850 data.start_col_xoffset = 0; | |
| 826 | 2851 data.byte_start_col_enabled = 0; |
| 428 | 2852 |
| 2853 data.max_pixpos += data.blank_width; | |
| 867 | 2854 add_ichar_rune (&data); |
| 428 | 2855 data.max_pixpos -= data.blank_width; |
| 2856 | |
| 2857 /* #### urk! Chuck, this shit is bad news. Going around | |
| 2858 manipulating invalid positions is guaranteed to result in | |
| 2859 trouble sooner or later. */ | |
| 826 | 2860 data.byte_charpos = BYTE_BUF_ZV (b) + 1; |
| 428 | 2861 } |
| 2862 | |
| 2863 /* Calculate left whitespace boundary. */ | |
| 2864 { | |
| 2865 int elt = 0; | |
| 2866 | |
| 2867 /* Whitespace past a newline is considered right whitespace. */ | |
| 2868 while (elt < Dynarr_length (db->runes)) | |
| 2869 { | |
| 2870 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 2871 | |
| 2872 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
| 2873 || rb->type == RUNE_BLANK) | |
| 2874 { | |
| 2875 dl->bounds.left_white += rb->width; | |
| 2876 elt++; | |
| 2877 } | |
| 2878 else | |
| 2879 elt = Dynarr_length (db->runes); | |
| 2880 } | |
| 2881 } | |
| 2882 | |
| 2883 /* Calculate right whitespace boundary. */ | |
| 2884 { | |
| 2885 int elt = Dynarr_length (db->runes) - 1; | |
| 2886 int done = 0; | |
| 2887 | |
| 2888 while (!done && elt >= 0) | |
| 2889 { | |
| 2890 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 2891 | |
| 2892 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
| 2893 && isspace (rb->object.chr.ch)) | |
| 2894 && !rb->type == RUNE_BLANK) | |
| 2895 { | |
| 2896 dl->bounds.right_white = rb->xpos + rb->width; | |
| 2897 done = 1; | |
| 2898 } | |
| 2899 | |
| 2900 elt--; | |
| 2901 | |
| 2902 } | |
| 2903 | |
| 2904 /* The line is blank so everything is considered to be right | |
| 2905 whitespace. */ | |
| 2906 if (!done) | |
| 2907 dl->bounds.right_white = dl->bounds.left_in; | |
| 2908 } | |
| 2909 | |
| 2910 /* Set the display blocks bounds. */ | |
| 2911 db->start_pos = dl->bounds.left_in; | |
| 2912 if (Dynarr_length (db->runes)) | |
| 2913 { | |
| 2914 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); | |
| 2915 | |
| 2916 db->end_pos = rb->xpos + rb->width; | |
| 2917 } | |
| 2918 else | |
| 2919 db->end_pos = dl->bounds.right_white; | |
| 2920 | |
| 819 | 2921 calculate_baseline (&data); |
| 428 | 2922 |
| 2923 dl->ascent = data.new_ascent; | |
| 2924 dl->descent = data.new_descent; | |
| 2925 | |
| 2926 { | |
| 2927 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
| 2928 | |
| 2929 if (dl->ascent < ascent) | |
| 2930 dl->ascent = ascent; | |
| 2931 } | |
| 2932 { | |
| 2933 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
| 2934 | |
| 2935 if (dl->descent < descent) | |
| 2936 dl->descent = descent; | |
| 2937 } | |
| 2938 | |
| 819 | 2939 calculate_yoffset (dl, db); |
| 2940 | |
| 428 | 2941 dl->cursor_elt = data.cursor_x; |
| 2942 /* #### lossage lossage lossage! Fix this shit! */ | |
| 826 | 2943 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
| 2944 dl->end_charpos = BUF_ZV (b); | |
| 428 | 2945 else |
| 826 | 2946 dl->end_charpos = bytebpos_to_charbpos (b, data.byte_charpos) - 1; |
| 428 | 2947 if (truncate_win) |
| 826 | 2948 data.dl->num_chars = column_at_point (b, dl->end_charpos, 0); |
| 428 | 2949 else |
| 2950 /* This doesn't correctly take into account tabs and control | |
| 2951 characters but if the window isn't being truncated then this | |
| 2952 value isn't going to end up being used anyhow. */ | |
| 826 | 2953 data.dl->num_chars = dl->end_charpos - dl->charpos; |
| 428 | 2954 |
| 2955 /* #### handle horizontally scrolled line with text none of which | |
| 2956 was actually laid out. */ | |
| 2957 | |
| 2958 /* #### handle any remainder of overlay arrow */ | |
| 2959 | |
| 2960 if (*prop == ADD_FAILED) | |
| 2961 *prop = NULL; | |
| 2962 | |
| 2963 if (truncate_win && *prop) | |
| 2964 { | |
| 2965 Dynarr_free (*prop); | |
| 2966 *prop = NULL; | |
| 2967 } | |
| 2968 | |
| 2969 extent_fragment_delete (data.ef); | |
| 2970 | |
| 2971 /* #### If we started at EOB, then make sure we return a value past | |
| 2972 it so that regenerate_window will exit properly. This is bogus. | |
| 2973 The main loop should get fixed so that it isn't necessary to call | |
| 2974 this function if we are already at EOB. */ | |
| 2975 | |
| 826 | 2976 if (data.byte_charpos == BYTE_BUF_ZV (b) && byte_start_pos == BYTE_BUF_ZV (b)) |
| 2977 return data.byte_charpos + 1; /* Yuck! */ | |
| 428 | 2978 else |
| 826 | 2979 return data.byte_charpos; |
| 428 | 2980 } |
| 2981 | |
| 2982 /* Display the overlay arrow at the beginning of the given line. */ | |
| 2983 | |
| 2984 static int | |
| 2985 create_overlay_glyph_block (struct window *w, struct display_line *dl) | |
| 2986 { | |
| 2987 struct frame *f = XFRAME (w->frame); | |
| 2988 struct device *d = XDEVICE (f->device); | |
| 2989 pos_data data; | |
| 2990 | |
| 2991 /* If Voverlay_arrow_string isn't valid then just fail silently. */ | |
| 2992 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string)) | |
| 2993 return 0; | |
| 2994 | |
| 2995 xzero (data); | |
| 2996 data.ef = NULL; | |
| 2997 data.d = d; | |
| 793 | 2998 data.window = wrap_window (w); |
| 428 | 2999 data.db = get_display_block_from_line (dl, OVERWRITE); |
| 3000 data.dl = dl; | |
| 3001 data.pixpos = dl->bounds.left_in; | |
| 3002 data.max_pixpos = dl->bounds.right_in; | |
| 3003 data.cursor_type = NO_CURSOR; | |
| 3004 data.cursor_x = -1; | |
| 3005 data.findex = DEFAULT_INDEX; | |
| 3006 data.last_charset = Qunbound; | |
| 3007 data.last_findex = DEFAULT_INDEX; | |
| 3008 data.result_str = Qnil; | |
| 3009 data.string = Qnil; | |
| 3010 | |
| 3011 Dynarr_reset (data.db->runes); | |
| 3012 | |
| 3013 if (STRINGP (Voverlay_arrow_string)) | |
| 3014 { | |
| 867 | 3015 add_ibyte_string_runes |
| 428 | 3016 (&data, |
| 3017 XSTRING_DATA (Voverlay_arrow_string), | |
| 3018 XSTRING_LENGTH (Voverlay_arrow_string), | |
| 793 | 3019 1, 0); |
| 428 | 3020 } |
| 3021 else if (GLYPHP (Voverlay_arrow_string)) | |
| 3022 { | |
| 3023 struct glyph_block gb; | |
| 3024 | |
| 3025 gb.glyph = Voverlay_arrow_string; | |
| 3026 gb.extent = Qnil; | |
| 3027 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0); | |
| 3028 } | |
| 4187 | 3029 |
| 428 | 3030 if (data.max_pixmap_height) |
| 3031 { | |
| 3032 int height = data.new_ascent + data.new_descent; | |
| 3033 int pix_ascent, pix_descent; | |
| 4187 | 3034 |
| 428 | 3035 pix_descent = data.max_pixmap_height * data.new_descent / height; |
| 3036 pix_ascent = data.max_pixmap_height - pix_descent; | |
| 819 | 3037 calculate_baseline (&data); |
| 428 | 3038 |
| 3039 data.new_ascent = max (data.new_ascent, pix_ascent); | |
| 3040 data.new_descent = max (data.new_descent, pix_descent); | |
| 3041 } | |
| 3042 | |
| 3043 dl->ascent = data.new_ascent; | |
| 3044 dl->descent = data.new_descent; | |
| 3045 | |
| 3046 data.db->start_pos = dl->bounds.left_in; | |
| 3047 data.db->end_pos = data.pixpos; | |
| 3048 | |
| 819 | 3049 calculate_yoffset (dl, data.db); |
| 3050 | |
| 428 | 3051 return data.pixpos - dl->bounds.left_in; |
| 3052 } | |
| 3053 | |
| 3054 /* Add a type of glyph to a margin display block. */ | |
| 3055 | |
| 3056 static int | |
| 3057 add_margin_runes (struct display_line *dl, struct display_block *db, int start, | |
| 3058 int count, enum glyph_layout layout, int side, Lisp_Object window) | |
| 3059 { | |
| 3060 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS | |
| 3061 ? dl->left_glyphs | |
| 3062 : dl->right_glyphs); | |
| 3063 int elt, end; | |
| 3064 int reverse; | |
| 442 | 3065 struct window *w = XWINDOW (window); |
| 3066 struct frame *f = XFRAME (w->frame); | |
| 3067 struct device *d = XDEVICE (f->device); | |
| 3068 pos_data data; | |
| 3069 | |
| 3070 xzero (data); | |
| 3071 data.d = d; | |
| 3072 data.window = window; | |
| 3073 data.db = db; | |
| 3074 data.dl = dl; | |
| 3075 data.pixpos = start; | |
| 3076 data.cursor_type = NO_CURSOR; | |
| 3077 data.cursor_x = -1; | |
| 3078 data.last_charset = Qunbound; | |
| 3079 data.last_findex = DEFAULT_INDEX; | |
| 3080 data.result_str = Qnil; | |
| 3081 data.string = Qnil; | |
| 3082 data.new_ascent = dl->ascent; | |
| 3083 data.new_descent = dl->descent; | |
| 428 | 3084 |
| 3085 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) | |
| 3086 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) | |
| 3087 { | |
| 3088 reverse = 1; | |
| 3089 elt = Dynarr_length (gbd) - 1; | |
| 3090 end = 0; | |
| 3091 } | |
| 3092 else | |
| 3093 { | |
| 3094 reverse = 0; | |
| 3095 elt = 0; | |
| 3096 end = Dynarr_length (gbd); | |
| 3097 } | |
| 3098 | |
| 3099 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) | |
| 3100 { | |
| 3101 struct glyph_block *gb = Dynarr_atp (gbd, elt); | |
| 3102 | |
| 3103 if (NILP (gb->extent)) | |
| 2500 | 3104 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3105 |
| 3106 if (gb->active && | |
| 3107 ((side == LEFT_GLYPHS && | |
| 3108 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout) | |
| 3109 || (side == RIGHT_GLYPHS && | |
| 3110 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) | |
| 3111 { | |
| 442 | 3112 data.findex = gb->findex; |
| 3113 data.max_pixpos = data.pixpos + gb->width; | |
| 3114 add_glyph_rune (&data, gb, side, 0, NULL); | |
| 428 | 3115 count--; |
| 3116 gb->active = 0; | |
| 3117 } | |
| 3118 | |
| 3119 (reverse ? elt-- : elt++); | |
| 3120 } | |
| 3121 | |
| 819 | 3122 calculate_baseline (&data); |
| 442 | 3123 |
| 3124 dl->ascent = data.new_ascent; | |
| 3125 dl->descent = data.new_descent; | |
| 3126 | |
| 819 | 3127 calculate_yoffset (dl, data.db); |
| 3128 | |
| 442 | 3129 return data.pixpos; |
| 428 | 3130 } |
| 3131 | |
| 3132 /* Add a blank to a margin display block. */ | |
| 3133 | |
| 3134 static void | |
| 2286 | 3135 add_margin_blank (struct display_line *UNUSED (dl), struct display_block *db, |
| 428 | 3136 struct window *w, int xpos, int width, int side) |
| 3137 { | |
| 3138 struct rune rb; | |
| 3139 | |
| 3140 rb.findex = (side == LEFT_GLYPHS | |
| 3141 ? get_builtin_face_cache_index (w, Vleft_margin_face) | |
| 3142 : get_builtin_face_cache_index (w, Vright_margin_face)); | |
| 3143 rb.xpos = xpos; | |
| 3144 rb.width = width; | |
| 826 | 3145 rb.charpos = -1; |
| 428 | 3146 rb.endpos = 0; |
| 3147 rb.type = RUNE_BLANK; | |
| 3148 rb.cursor_type = CURSOR_OFF; | |
| 3149 | |
| 3150 Dynarr_add (db->runes, rb); | |
| 3151 } | |
| 3152 | |
| 3153 /* Display glyphs in the left outside margin, left inside margin and | |
| 3154 left whitespace area. */ | |
| 3155 | |
| 3156 static void | |
| 3157 create_left_glyph_block (struct window *w, struct display_line *dl, | |
| 3158 int overlay_width) | |
| 3159 { | |
| 3160 Lisp_Object window; | |
| 3161 | |
| 3162 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1); | |
| 3163 int elt, end_xpos; | |
| 3164 int out_end, in_out_start, in_in_end, white_out_start, white_in_start; | |
| 3165 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
| 3166 int left_in_start = dl->bounds.left_in; | |
| 3167 int left_in_end = dl->bounds.left_in + overlay_width; | |
| 3168 | |
| 3169 struct display_block *odb, *idb; | |
| 3170 | |
| 793 | 3171 window = wrap_window (w); |
| 428 | 3172 |
| 3173 /* We have to add the glyphs to the line in the order outside, | |
| 3174 inside, whitespace. However the precedence dictates that we | |
| 3175 determine how many will fit in the reverse order. */ | |
| 3176 | |
| 3177 /* Determine how many whitespace glyphs we can display and where | |
| 3178 they should start. */ | |
| 3179 white_in_start = dl->bounds.left_white; | |
| 3180 white_out_start = left_in_start; | |
| 3181 white_out_cnt = white_in_cnt = 0; | |
| 3182 elt = 0; | |
| 3183 | |
| 3184 while (elt < Dynarr_length (dl->left_glyphs)) | |
| 3185 { | |
| 3186 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
| 3187 | |
| 3188 if (NILP (gb->extent)) | |
| 2500 | 3189 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3190 |
| 3191 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
| 3192 { | |
| 3193 int width; | |
| 3194 | |
| 438 | 3195 width = glyph_width (gb->glyph, window); |
| 428 | 3196 |
| 3197 if (white_in_start - width >= left_in_end) | |
| 3198 { | |
| 3199 white_in_cnt++; | |
| 3200 white_in_start -= width; | |
| 3201 gb->width = width; | |
| 3202 gb->active = 1; | |
| 3203 } | |
| 3204 else if (use_overflow | |
| 3205 && (white_out_start - width > dl->bounds.left_out)) | |
| 3206 { | |
| 3207 white_out_cnt++; | |
| 3208 white_out_start -= width; | |
| 3209 gb->width = width; | |
| 3210 gb->active = 1; | |
| 3211 } | |
| 3212 else | |
| 3213 gb->active = 0; | |
| 3214 } | |
| 3215 | |
| 3216 elt++; | |
| 3217 } | |
| 3218 | |
| 3219 /* Determine how many inside margin glyphs we can display and where | |
| 3220 they should start. The inside margin glyphs get whatever space | |
| 3221 is left after the whitespace glyphs have been displayed. These | |
| 3222 are tricky to calculate since if we decide to use the overflow | |
| 3223 area we basically have to start over. So for these we build up a | |
| 3224 list of just the inside margin glyphs and manipulate it to | |
| 3225 determine the needed info. */ | |
| 3226 { | |
| 3227 glyph_block_dynarr *ib; | |
| 3228 int avail_in, avail_out; | |
| 3229 int done = 0; | |
| 3230 int marker = 0; | |
| 3231 int used_in, used_out; | |
| 3232 | |
| 3233 elt = 0; | |
| 3234 used_in = used_out = 0; | |
| 3235 ib = Dynarr_new (glyph_block); | |
| 3236 while (elt < Dynarr_length (dl->left_glyphs)) | |
| 3237 { | |
| 3238 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
| 3239 | |
| 3240 if (NILP (gb->extent)) | |
| 2500 | 3241 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3242 |
| 3243 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
| 3244 GL_INSIDE_MARGIN) | |
| 3245 { | |
| 438 | 3246 gb->width = glyph_width (gb->glyph, window); |
| 428 | 3247 used_in += gb->width; |
| 3248 Dynarr_add (ib, *gb); | |
| 3249 } | |
| 3250 | |
| 3251 elt++; | |
| 3252 } | |
| 3253 | |
| 3254 if (white_out_cnt) | |
| 3255 avail_in = 0; | |
| 3256 else | |
| 3257 { | |
| 3258 avail_in = white_in_start - left_in_end; | |
| 3259 if (avail_in < 0) | |
| 3260 avail_in = 0; | |
| 3261 } | |
| 3262 | |
| 3263 if (!use_overflow) | |
| 3264 avail_out = 0; | |
| 3265 else | |
| 3266 avail_out = white_out_start - dl->bounds.left_out; | |
| 3267 | |
| 3268 marker = 0; | |
| 3269 while (!done && marker < Dynarr_length (ib)) | |
| 3270 { | |
| 3271 int width = Dynarr_atp (ib, marker)->width; | |
| 3272 | |
| 3273 /* If everything now fits in the available inside margin | |
| 4187 | 3274 space, we're done. */ |
| 428 | 3275 if (used_in <= avail_in) |
| 3276 done = 1; | |
| 3277 else | |
| 3278 { | |
| 3279 /* Otherwise see if we have room to move a glyph to the | |
| 4187 | 3280 outside. */ |
| 428 | 3281 if (used_out + width <= avail_out) |
| 3282 { | |
| 3283 used_out += width; | |
| 3284 used_in -= width; | |
| 3285 } | |
| 3286 else | |
| 3287 done = 1; | |
| 3288 } | |
| 3289 | |
| 3290 if (!done) | |
| 3291 marker++; | |
| 3292 } | |
| 3293 | |
| 3294 /* At this point we now know that everything from marker on goes in | |
| 3295 the inside margin and everything before it goes in the outside | |
| 3296 margin. The stuff going into the outside margin is guaranteed | |
| 3297 to fit, but we may have to trim some stuff from the inside. */ | |
| 3298 | |
| 3299 in_in_end = left_in_end; | |
| 3300 in_out_start = white_out_start; | |
| 3301 in_out_cnt = in_in_cnt = 0; | |
| 3302 | |
| 3303 Dynarr_free (ib); | |
| 3304 elt = 0; | |
| 3305 while (elt < Dynarr_length (dl->left_glyphs)) | |
| 3306 { | |
| 3307 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
| 3308 | |
| 3309 if (NILP (gb->extent)) | |
| 2500 | 3310 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3311 |
| 3312 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
| 3313 GL_INSIDE_MARGIN) | |
| 3314 { | |
| 438 | 3315 int width = glyph_width (gb->glyph, window); |
| 428 | 3316 |
| 3317 if (used_out) | |
| 3318 { | |
| 3319 in_out_cnt++; | |
| 3320 in_out_start -= width; | |
| 3321 gb->width = width; | |
| 3322 gb->active = 1; | |
| 3323 used_out -= width; | |
| 3324 } | |
| 3325 else if (in_in_end + width < white_in_start) | |
| 3326 { | |
| 3327 in_in_cnt++; | |
| 3328 in_in_end += width; | |
| 3329 gb->width = width; | |
| 3330 gb->active = 1; | |
| 3331 } | |
| 3332 else | |
| 3333 gb->active = 0; | |
| 3334 } | |
| 3335 | |
| 3336 elt++; | |
| 3337 } | |
| 3338 } | |
| 3339 | |
| 3340 /* Determine how many outside margin glyphs we can display. They | |
| 3341 always start at the left outside margin and can only use the | |
| 3342 outside margin space. */ | |
| 3343 out_end = dl->bounds.left_out; | |
| 3344 out_cnt = 0; | |
| 3345 elt = 0; | |
| 3346 | |
| 3347 while (elt < Dynarr_length (dl->left_glyphs)) | |
| 3348 { | |
| 3349 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
| 3350 | |
| 3351 if (NILP (gb->extent)) | |
| 2500 | 3352 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3353 |
| 3354 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
| 3355 GL_OUTSIDE_MARGIN) | |
| 3356 { | |
| 438 | 3357 int width = glyph_width (gb->glyph, window); |
| 428 | 3358 |
| 3359 if (out_end + width <= in_out_start) | |
| 3360 { | |
| 3361 out_cnt++; | |
| 3362 out_end += width; | |
| 3363 gb->width = width; | |
| 3364 gb->active = 1; | |
| 3365 } | |
| 3366 else | |
| 3367 gb->active = 0; | |
| 3368 } | |
| 3369 | |
| 3370 elt++; | |
| 3371 } | |
| 3372 | |
| 3373 /* Now that we know where everything goes, we add the glyphs as | |
| 3374 runes to the appropriate display blocks. */ | |
| 3375 if (out_cnt || in_out_cnt || white_out_cnt) | |
| 3376 { | |
| 3377 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN); | |
| 3378 odb->start_pos = dl->bounds.left_out; | |
| 3379 /* #### We should stop adding a blank to account for the space | |
| 4187 | 3380 between the end of the glyphs and the margin and instead set |
| 3381 this accordingly. */ | |
| 428 | 3382 odb->end_pos = dl->bounds.left_in; |
| 3383 Dynarr_reset (odb->runes); | |
| 3384 } | |
| 3385 else | |
| 3386 odb = 0; | |
| 3387 | |
| 3388 if (in_in_cnt || white_in_cnt) | |
| 3389 { | |
| 3390 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN); | |
| 3391 idb->start_pos = dl->bounds.left_in; | |
| 3392 /* #### See above comment for odb->end_pos */ | |
| 3393 idb->end_pos = dl->bounds.left_white; | |
| 3394 Dynarr_reset (idb->runes); | |
| 3395 } | |
| 3396 else | |
| 3397 idb = 0; | |
| 3398 | |
| 3399 /* First add the outside margin glyphs. */ | |
| 3400 if (out_cnt) | |
| 3401 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt, | |
| 3402 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window); | |
| 3403 else | |
| 3404 end_xpos = dl->bounds.left_out; | |
| 3405 | |
| 3406 /* There may be blank space between the outside margin glyphs and | |
| 3407 the inside margin glyphs. If so, add a blank. */ | |
| 3408 if (in_out_cnt && (in_out_start - end_xpos)) | |
| 3409 { | |
| 3410 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos, | |
| 3411 LEFT_GLYPHS); | |
| 3412 } | |
| 3413 | |
| 3414 /* Next add the inside margin glyphs which are actually in the | |
| 3415 outside margin. */ | |
| 3416 if (in_out_cnt) | |
| 3417 { | |
| 3418 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt, | |
| 3419 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
| 3420 } | |
| 3421 | |
| 3422 /* If we didn't add any inside margin glyphs to the outside margin, | |
| 3423 but are adding whitespace glyphs, then we need to add a blank | |
| 3424 here. */ | |
| 3425 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) | |
| 3426 { | |
| 3427 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos, | |
| 3428 LEFT_GLYPHS); | |
| 3429 } | |
| 3430 | |
| 3431 /* Next add the whitespace margin glyphs which are actually in the | |
| 3432 outside margin. */ | |
| 3433 if (white_out_cnt) | |
| 3434 { | |
| 3435 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt, | |
| 3436 GL_WHITESPACE, LEFT_GLYPHS, window); | |
| 3437 } | |
| 3438 | |
| 3439 /* We take care of clearing between the end of the glyphs and the | |
| 3440 start of the inside margin for lines which have glyphs. */ | |
| 3441 if (odb && (left_in_start - end_xpos)) | |
| 3442 { | |
| 3443 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos, | |
| 3444 LEFT_GLYPHS); | |
| 3445 } | |
| 3446 | |
| 3447 /* Next add the inside margin glyphs which are actually in the | |
| 3448 inside margin. */ | |
| 3449 if (in_in_cnt) | |
| 3450 { | |
| 3451 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt, | |
| 3452 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
| 3453 } | |
| 3454 else | |
| 3455 end_xpos = left_in_end; | |
| 3456 | |
| 3457 /* Make sure that the area between the end of the inside margin | |
| 3458 glyphs and the whitespace glyphs is cleared. */ | |
| 3459 if (idb && (white_in_start - end_xpos > 0)) | |
| 3460 { | |
| 3461 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos, | |
| 3462 LEFT_GLYPHS); | |
| 3463 } | |
| 3464 | |
| 3465 /* Next add the whitespace margin glyphs which are actually in the | |
| 3466 inside margin. */ | |
| 3467 if (white_in_cnt) | |
| 3468 { | |
| 3469 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE, | |
| 3470 LEFT_GLYPHS, window); | |
| 3471 } | |
| 3472 | |
| 3473 /* Whitespace glyphs always end right next to the text block so | |
| 3474 there is nothing we have to make sure is cleared after them. */ | |
| 3475 } | |
| 3476 | |
| 3477 /* Display glyphs in the right outside margin, right inside margin and | |
| 3478 right whitespace area. */ | |
| 3479 | |
| 3480 static void | |
| 3481 create_right_glyph_block (struct window *w, struct display_line *dl) | |
| 3482 { | |
| 3483 Lisp_Object window; | |
| 3484 | |
| 3485 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1); | |
| 3486 int elt, end_xpos; | |
| 3487 int out_start, in_out_end, in_in_start, white_out_end, white_in_end; | |
| 3488 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
| 3489 | |
| 3490 struct display_block *odb, *idb; | |
| 3491 | |
| 793 | 3492 window = wrap_window (w); |
| 428 | 3493 |
| 3494 /* We have to add the glyphs to the line in the order outside, | |
| 3495 inside, whitespace. However the precedence dictates that we | |
| 3496 determine how many will fit in the reverse order. */ | |
| 3497 | |
| 3498 /* Determine how many whitespace glyphs we can display and where | |
| 3499 they should start. */ | |
| 3500 white_in_end = dl->bounds.right_white; | |
| 3501 white_out_end = dl->bounds.right_in; | |
| 3502 white_out_cnt = white_in_cnt = 0; | |
| 3503 elt = 0; | |
| 3504 | |
| 3505 while (elt < Dynarr_length (dl->right_glyphs)) | |
| 3506 { | |
| 3507 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
| 3508 | |
| 3509 if (NILP (gb->extent)) | |
| 2500 | 3510 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3511 |
| 3512 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
| 3513 { | |
| 438 | 3514 int width = glyph_width (gb->glyph, window); |
| 428 | 3515 |
| 3516 if (white_in_end + width <= dl->bounds.right_in) | |
| 3517 { | |
| 3518 white_in_cnt++; | |
| 3519 white_in_end += width; | |
| 3520 gb->width = width; | |
| 3521 gb->active = 1; | |
| 3522 } | |
| 3523 else if (use_overflow | |
| 3524 && (white_out_end + width <= dl->bounds.right_out)) | |
| 3525 { | |
| 3526 white_out_cnt++; | |
| 3527 white_out_end += width; | |
| 3528 gb->width = width; | |
| 3529 gb->active = 1; | |
| 3530 } | |
| 3531 else | |
| 3532 gb->active = 0; | |
| 3533 } | |
| 3534 | |
| 3535 elt++; | |
| 3536 } | |
| 3537 | |
| 3538 /* Determine how many inside margin glyphs we can display and where | |
| 3539 they should start. The inside margin glyphs get whatever space | |
| 3540 is left after the whitespace glyphs have been displayed. These | |
| 3541 are tricky to calculate since if we decide to use the overflow | |
| 3542 area we basically have to start over. So for these we build up a | |
| 3543 list of just the inside margin glyphs and manipulate it to | |
| 3544 determine the needed info. */ | |
| 3545 { | |
| 3546 glyph_block_dynarr *ib; | |
| 3547 int avail_in, avail_out; | |
| 3548 int done = 0; | |
| 3549 int marker = 0; | |
| 3550 int used_in, used_out; | |
| 3551 | |
| 3552 elt = 0; | |
| 3553 used_in = used_out = 0; | |
| 3554 ib = Dynarr_new (glyph_block); | |
| 3555 while (elt < Dynarr_length (dl->right_glyphs)) | |
| 3556 { | |
| 3557 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
| 3558 | |
| 3559 if (NILP (gb->extent)) | |
| 2500 | 3560 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3561 |
| 3562 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
| 3563 { | |
| 438 | 3564 gb->width = glyph_width (gb->glyph, window); |
| 428 | 3565 used_in += gb->width; |
| 3566 Dynarr_add (ib, *gb); | |
| 3567 } | |
| 3568 | |
| 3569 elt++; | |
| 3570 } | |
| 3571 | |
| 3572 if (white_out_cnt) | |
| 3573 avail_in = 0; | |
| 3574 else | |
| 3575 avail_in = dl->bounds.right_in - white_in_end; | |
| 3576 | |
| 3577 if (!use_overflow) | |
| 3578 avail_out = 0; | |
| 3579 else | |
| 3580 avail_out = dl->bounds.right_out - white_out_end; | |
| 3581 | |
| 3582 marker = 0; | |
| 3583 while (!done && marker < Dynarr_length (ib)) | |
| 3584 { | |
| 3585 int width = Dynarr_atp (ib, marker)->width; | |
| 3586 | |
| 3587 /* If everything now fits in the available inside margin | |
| 4187 | 3588 space, we're done. */ |
| 428 | 3589 if (used_in <= avail_in) |
| 3590 done = 1; | |
| 3591 else | |
| 3592 { | |
| 3593 /* Otherwise see if we have room to move a glyph to the | |
| 4187 | 3594 outside. */ |
| 428 | 3595 if (used_out + width <= avail_out) |
| 3596 { | |
| 3597 used_out += width; | |
| 3598 used_in -= width; | |
| 3599 } | |
| 3600 else | |
| 3601 done = 1; | |
| 3602 } | |
| 3603 | |
| 3604 if (!done) | |
| 3605 marker++; | |
| 3606 } | |
| 3607 | |
| 3608 /* At this point we now know that everything from marker on goes in | |
| 3609 the inside margin and everything before it goes in the outside | |
| 3610 margin. The stuff going into the outside margin is guaranteed | |
| 3611 to fit, but we may have to trim some stuff from the inside. */ | |
| 3612 | |
| 3613 in_in_start = dl->bounds.right_in; | |
| 3614 in_out_end = dl->bounds.right_in; | |
| 3615 in_out_cnt = in_in_cnt = 0; | |
| 3616 | |
| 3617 Dynarr_free (ib); | |
| 3618 elt = 0; | |
| 3619 while (elt < Dynarr_length (dl->right_glyphs)) | |
| 3620 { | |
| 3621 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
| 3622 | |
| 3623 if (NILP (gb->extent)) | |
| 2500 | 3624 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3625 |
| 3626 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
| 3627 { | |
| 438 | 3628 int width = glyph_width (gb->glyph, window); |
| 428 | 3629 |
| 3630 if (used_out) | |
| 3631 { | |
| 3632 in_out_cnt++; | |
| 3633 in_out_end += width; | |
| 3634 gb->width = width; | |
| 3635 gb->active = 1; | |
| 3636 used_out -= width; | |
| 3637 } | |
| 3638 else if (in_in_start - width >= white_in_end) | |
| 3639 { | |
| 3640 in_in_cnt++; | |
| 3641 in_in_start -= width; | |
| 3642 gb->width = width; | |
| 3643 gb->active = 1; | |
| 3644 } | |
| 3645 else | |
| 3646 gb->active = 0; | |
| 3647 } | |
| 3648 | |
| 3649 elt++; | |
| 3650 } | |
| 3651 } | |
| 3652 | |
| 3653 /* Determine how many outside margin glyphs we can display. They | |
| 3654 always start at the right outside margin and can only use the | |
| 3655 outside margin space. */ | |
| 3656 out_start = dl->bounds.right_out; | |
| 3657 out_cnt = 0; | |
| 3658 elt = 0; | |
| 3659 | |
| 3660 while (elt < Dynarr_length (dl->right_glyphs)) | |
| 3661 { | |
| 3662 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
| 3663 | |
| 3664 if (NILP (gb->extent)) | |
| 2500 | 3665 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3666 |
| 3667 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) | |
| 3668 { | |
| 438 | 3669 int width = glyph_width (gb->glyph, window); |
| 428 | 3670 |
| 3671 if (out_start - width >= in_out_end) | |
| 3672 { | |
| 3673 out_cnt++; | |
| 3674 out_start -= width; | |
| 3675 gb->width = width; | |
| 3676 gb->active = 1; | |
| 3677 } | |
| 3678 else | |
| 3679 gb->active = 0; | |
| 3680 } | |
| 3681 | |
| 3682 elt++; | |
| 3683 } | |
| 3684 | |
| 3685 /* Now that we now where everything goes, we add the glyphs as runes | |
| 3686 to the appropriate display blocks. */ | |
| 3687 if (out_cnt || in_out_cnt || white_out_cnt) | |
| 3688 { | |
| 3689 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN); | |
| 3690 /* #### See comments before odb->start_pos init in | |
| 4187 | 3691 create_left_glyph_block */ |
| 428 | 3692 odb->start_pos = dl->bounds.right_in; |
| 3693 odb->end_pos = dl->bounds.right_out; | |
| 3694 Dynarr_reset (odb->runes); | |
| 3695 } | |
| 3696 else | |
| 3697 odb = 0; | |
| 3698 | |
| 3699 if (in_in_cnt || white_in_cnt) | |
| 3700 { | |
| 3701 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN); | |
| 3702 idb->start_pos = dl->bounds.right_white; | |
| 3703 /* #### See comments before odb->start_pos init in | |
| 4187 | 3704 create_left_glyph_block */ |
| 428 | 3705 idb->end_pos = dl->bounds.right_in; |
| 3706 Dynarr_reset (idb->runes); | |
| 3707 } | |
| 3708 else | |
| 3709 idb = 0; | |
| 3710 | |
| 3711 /* First add the whitespace margin glyphs which are actually in the | |
| 3712 inside margin. */ | |
| 3713 if (white_in_cnt) | |
| 3714 { | |
| 3715 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white, | |
| 3716 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS, | |
| 3717 window); | |
| 3718 } | |
| 3719 else | |
| 3720 end_xpos = dl->bounds.right_white; | |
| 3721 | |
| 3722 /* Make sure that the area between the end of the whitespace glyphs | |
| 3723 and the inside margin glyphs is cleared. */ | |
| 3724 if (in_in_cnt && (in_in_start - end_xpos)) | |
| 3725 { | |
| 3726 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos, | |
| 3727 RIGHT_GLYPHS); | |
| 3728 } | |
| 3729 | |
| 3730 /* Next add the inside margin glyphs which are actually in the | |
| 3731 inside margin. */ | |
| 3732 if (in_in_cnt) | |
| 3733 { | |
| 3734 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt, | |
| 3735 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
| 3736 } | |
| 3737 | |
| 3738 /* If we didn't add any inside margin glyphs then make sure the rest | |
| 3739 of the inside margin area gets cleared. */ | |
| 3740 if (idb && (dl->bounds.right_in - end_xpos)) | |
| 3741 { | |
| 3742 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos, | |
| 3743 RIGHT_GLYPHS); | |
| 3744 } | |
| 3745 | |
| 3746 /* Next add any whitespace glyphs in the outside margin. */ | |
| 3747 if (white_out_cnt) | |
| 3748 { | |
| 3749 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt, | |
| 3750 GL_WHITESPACE, RIGHT_GLYPHS, window); | |
| 3751 } | |
| 3752 else | |
| 3753 end_xpos = dl->bounds.right_in; | |
| 3754 | |
| 3755 /* Next add any inside margin glyphs in the outside margin. */ | |
| 3756 if (in_out_cnt) | |
| 3757 { | |
| 3758 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt, | |
| 3759 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
| 3760 } | |
| 3761 | |
| 3762 /* There may be space between any whitespace or inside margin glyphs | |
| 3763 in the outside margin and the actual outside margin glyphs. */ | |
| 3764 if (odb && (out_start - end_xpos)) | |
| 3765 { | |
| 3766 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos, | |
| 3767 RIGHT_GLYPHS); | |
| 3768 } | |
| 3769 | |
| 3770 /* Finally, add the outside margin glyphs. */ | |
| 3771 if (out_cnt) | |
| 3772 { | |
| 3773 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN, | |
| 3774 RIGHT_GLYPHS, window); | |
| 3775 } | |
| 3776 } | |
| 3777 | |
| 3778 | |
| 3779 /***************************************************************************/ | |
| 3780 /* */ | |
| 3781 /* modeline routines */ | |
| 3782 /* */ | |
| 3783 /***************************************************************************/ | |
| 3784 | |
| 438 | 3785 /* This function is also used in frame.c by `generate_title_string' */ |
| 3786 void | |
| 3787 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, | |
| 4187 | 3788 struct window *w, struct display_line *dl, |
| 3789 struct display_block *db, face_index findex, | |
| 3790 int min_pixpos, int max_pixpos, int type) | |
| 438 | 3791 { |
| 3792 struct frame *f = XFRAME (w->frame); | |
| 3793 struct device *d = XDEVICE (f->device); | |
| 3794 | |
| 3795 pos_data data; | |
| 3796 int c_pixpos; | |
| 3797 Charcount offset = 0; | |
| 3798 | |
| 3799 xzero (data); | |
| 3800 data.d = d; | |
| 3801 data.db = db; | |
| 3802 data.dl = dl; | |
| 3803 data.findex = findex; | |
| 3804 data.pixpos = min_pixpos; | |
| 3805 data.max_pixpos = max_pixpos; | |
| 3806 data.cursor_type = NO_CURSOR; | |
| 3807 data.last_charset = Qunbound; | |
| 3808 data.last_findex = DEFAULT_INDEX; | |
| 3809 data.result_str = result_str; | |
| 3810 data.is_modeline = 1; | |
| 3811 data.string = Qnil; | |
| 793 | 3812 data.window = wrap_window (w); |
| 438 | 3813 |
| 3814 Dynarr_reset (formatted_string_extent_dynarr); | |
| 3815 Dynarr_reset (formatted_string_extent_start_dynarr); | |
| 3816 Dynarr_reset (formatted_string_extent_end_dynarr); | |
| 3817 | |
| 3818 /* result_str is nil when we're building a frame or icon title. Otherwise, | |
| 3819 we're building a modeline, so the offset starts at the modeline | |
| 442 | 3820 horizontal scrolling amount */ |
| 438 | 3821 if (! NILP (result_str)) |
| 3822 offset = w->modeline_hscroll; | |
| 3823 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, | |
| 4187 | 3824 max_pixpos - min_pixpos, findex, type, &offset, |
| 438 | 3825 Qnil); |
| 3826 | |
| 3827 if (Dynarr_length (db->runes)) | |
| 3828 { | |
| 3829 struct rune *rb = | |
| 4187 | 3830 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); |
| 438 | 3831 c_pixpos = rb->xpos + rb->width; |
| 3832 } | |
| 3833 else | |
| 3834 c_pixpos = min_pixpos; | |
| 3835 | |
| 3836 /* If we don't reach the right side of the window, add a blank rune | |
| 3837 to make up the difference. This usually only occurs if the | |
| 3838 modeline face is using a proportional width font or a fixed width | |
| 3839 font of a different size from the default face font. */ | |
| 3840 | |
| 3841 if (c_pixpos < max_pixpos) | |
| 3842 { | |
| 3843 data.pixpos = c_pixpos; | |
| 3844 data.blank_width = max_pixpos - data.pixpos; | |
| 3845 | |
| 3846 add_blank_rune (&data, NULL, 0); | |
| 3847 } | |
| 3848 | |
| 3849 /* Now create the result string and frob the extents into it. */ | |
| 3850 if (!NILP (result_str)) | |
| 3851 { | |
| 3852 int elt; | |
| 3853 Bytecount len; | |
| 867 | 3854 Ibyte *strdata; |
| 438 | 3855 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); |
| 3856 | |
| 442 | 3857 in_modeline_generation = 1; |
| 3858 | |
| 771 | 3859 sledgehammer_check_ascii_begin (result_str); |
| 438 | 3860 detach_all_extents (result_str); |
| 793 | 3861 resize_string (result_str, -1, |
| 4187 | 3862 data.bytepos - XSTRING_LENGTH (result_str)); |
| 438 | 3863 |
| 3864 strdata = XSTRING_DATA (result_str); | |
| 3865 | |
| 3866 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++) | |
| 4187 | 3867 { |
| 3868 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) | |
| 3869 { | |
| 3870 len += (set_itext_ichar | |
| 3871 (strdata + len, Dynarr_atp (db->runes, | |
| 3872 elt)->object.chr.ch)); | |
| 3873 } | |
| 3874 } | |
| 438 | 3875 |
| 771 | 3876 init_string_ascii_begin (result_str); |
| 3877 bump_string_modiff (result_str); | |
| 3878 sledgehammer_check_ascii_begin (result_str); | |
| 3879 | |
| 438 | 3880 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr); |
| 4187 | 3881 elt++) |
| 3882 { | |
| 3883 Lisp_Object extent = Qnil; | |
| 3884 Lisp_Object child; | |
| 3885 | |
| 3886 extent = wrap_extent (Dynarr_at (formatted_string_extent_dynarr, elt)); | |
| 3887 child = Fgethash (extent, buf->modeline_extent_table, Qnil); | |
| 3888 if (NILP (child)) | |
| 3889 { | |
| 3890 child = Fmake_extent (Qnil, Qnil, result_str); | |
| 3891 Fputhash (extent, child, buf->modeline_extent_table); | |
| 3892 } | |
| 3893 Fset_extent_parent (child, extent); | |
| 3894 set_extent_endpoints | |
| 3895 (XEXTENT (child), | |
| 3896 Dynarr_at (formatted_string_extent_start_dynarr, elt), | |
| 3897 Dynarr_at (formatted_string_extent_end_dynarr, elt), | |
| 3898 result_str); | |
| 3899 } | |
| 442 | 3900 |
| 3901 in_modeline_generation = 0; | |
| 438 | 3902 } |
| 3903 } | |
| 3904 | |
| 428 | 3905 /* Ensure that the given display line DL accurately represents the |
| 3906 modeline for the given window. */ | |
| 3907 static void | |
| 3908 generate_modeline (struct window *w, struct display_line *dl, int type) | |
| 3909 { | |
| 3910 struct buffer *b = XBUFFER (w->buffer); | |
| 3911 struct frame *f = XFRAME (w->frame); | |
| 3912 struct device *d = XDEVICE (f->device); | |
| 3913 | |
| 3914 /* Unlike display line and rune pointers, this one can't change underneath | |
| 3915 our feet. */ | |
| 3916 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 3917 int max_pixpos, min_pixpos, ypos_adj; | |
| 3918 Lisp_Object font_inst; | |
| 3919 | |
| 3920 /* This will actually determine incorrect inside boundaries for the | |
| 3921 modeline since it ignores the margins. However being aware of this fact | |
| 3922 we never use those values anywhere so it doesn't matter. */ | |
| 3923 dl->bounds = calculate_display_line_boundaries (w, 1); | |
| 3924 | |
| 3925 /* We are generating a modeline. */ | |
| 3926 dl->modeline = 1; | |
| 3927 dl->cursor_elt = -1; | |
| 3928 | |
| 3929 /* Reset the runes on the modeline. */ | |
| 3930 Dynarr_reset (db->runes); | |
| 3931 | |
| 3932 if (!WINDOW_HAS_MODELINE_P (w)) | |
| 3933 { | |
| 3934 struct rune rb; | |
| 3935 | |
| 3936 /* If there is a horizontal scrollbar, don't add anything. */ | |
| 3937 if (window_scrollbar_height (w)) | |
| 3938 return; | |
| 3939 | |
| 3940 dl->ascent = DEVMETH (d, divider_height, ()); | |
| 3941 dl->descent = 0; | |
| 3942 /* The modeline is at the bottom of the gutters. */ | |
| 3943 dl->ypos = WINDOW_BOTTOM (w); | |
| 3944 | |
| 3945 rb.findex = MODELINE_INDEX; | |
| 3946 rb.xpos = dl->bounds.left_out; | |
| 3947 rb.width = dl->bounds.right_out - dl->bounds.left_out; | |
| 826 | 3948 rb.charpos = 0; |
| 428 | 3949 rb.endpos = 0; |
| 3950 rb.type = RUNE_HLINE; | |
| 3951 rb.object.hline.thickness = 1; | |
| 3952 rb.object.hline.yoffset = 0; | |
| 3953 rb.cursor_type = NO_CURSOR; | |
| 3954 | |
| 3955 if (!EQ (Qzero, w->modeline_shadow_thickness) | |
| 3956 && FRAME_WIN_P (f)) | |
| 3957 { | |
| 3958 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
| 3959 | |
| 3960 dl->ypos -= shadow_thickness; | |
| 3961 rb.xpos += shadow_thickness; | |
| 3962 rb.width -= 2 * shadow_thickness; | |
| 3963 } | |
| 3964 | |
| 3965 Dynarr_add (db->runes, rb); | |
| 3966 return; | |
| 3967 } | |
| 3968 | |
| 3969 /* !!#### not right; needs to compute the max height of | |
| 3970 all the charsets */ | |
| 3971 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); | |
| 3972 | |
| 3973 dl->ascent = XFONT_INSTANCE (font_inst)->ascent; | |
| 3974 dl->descent = XFONT_INSTANCE (font_inst)->descent; | |
| 3975 | |
| 3976 min_pixpos = dl->bounds.left_out; | |
| 3977 max_pixpos = dl->bounds.right_out; | |
| 3978 | |
| 3979 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
| 3980 { | |
| 3981 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
| 3982 | |
| 3983 ypos_adj = shadow_thickness; | |
| 3984 min_pixpos += shadow_thickness; | |
| 3985 max_pixpos -= shadow_thickness; | |
| 3986 } | |
| 3987 else | |
| 3988 ypos_adj = 0; | |
| 3989 | |
| 3990 generate_formatted_string_db (b->modeline_format, | |
| 3991 b->generated_modeline_string, w, dl, db, | |
| 3992 MODELINE_INDEX, min_pixpos, max_pixpos, type); | |
| 3993 | |
| 3994 /* The modeline is at the bottom of the gutters. We have to wait to | |
| 3995 set this until we've generated the modeline in order to account | |
| 3996 for any embedded faces. */ | |
| 3997 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj; | |
| 3998 } | |
| 3999 | |
| 4000 static Charcount | |
| 867 | 4001 add_string_to_fstring_db_runes (pos_data *data, const Ibyte *str, |
| 4187 | 4002 Charcount pos, Charcount min_pos, |
| 771 | 4003 Charcount max_pos) |
| 428 | 4004 { |
| 4005 /* This function has been Mule-ized. */ | |
| 4006 Charcount end; | |
| 867 | 4007 const Ibyte *cur_pos = str; |
| 428 | 4008 struct display_block *db = data->db; |
| 4009 | |
| 4010 data->blank_width = space_width (XWINDOW (data->window)); | |
| 4011 while (Dynarr_length (db->runes) < pos) | |
| 4012 add_blank_rune (data, NULL, 0); | |
| 4013 | |
| 4014 end = (Dynarr_length (db->runes) + | |
| 4187 | 4015 bytecount_to_charcount (str, strlen ((const char *) str))); |
| 428 | 4016 if (max_pos != -1) |
| 4017 end = min (max_pos, end); | |
| 4018 | |
| 4019 while (pos < end && *cur_pos) | |
| 4020 { | |
| 867 | 4021 const Ibyte *old_cur_pos = cur_pos; |
| 428 | 4022 int succeeded; |
| 4023 | |
| 867 | 4024 data->ch = itext_ichar (cur_pos); |
| 4025 succeeded = (add_ichar_rune (data) != ADD_FAILED); | |
| 4026 INC_IBYTEPTR (cur_pos); | |
| 428 | 4027 if (succeeded) |
| 4187 | 4028 { |
| 4029 pos++; | |
| 4030 data->modeline_charpos++; | |
| 4031 data->bytepos += cur_pos - old_cur_pos; | |
| 4032 } | |
| 428 | 4033 } |
| 4034 | |
| 4035 while (Dynarr_length (db->runes) < min_pos && | |
| 4187 | 4036 (data->pixpos + data->blank_width <= data->max_pixpos)) |
| 428 | 4037 add_blank_rune (data, NULL, 0); |
| 4038 | |
| 4039 return Dynarr_length (db->runes); | |
| 4040 } | |
| 4041 | |
| 4042 /* #### Urk! Should also handle begin-glyphs and end-glyphs in | |
| 4043 modeline extents. */ | |
| 4044 static Charcount | |
| 4045 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, | |
| 4187 | 4046 Charcount pos, Charcount UNUSED (min_pos), |
| 438 | 4047 Charcount max_pos, Lisp_Object extent) |
| 428 | 4048 { |
| 4049 /* This function has been Mule-ized. */ | |
| 4050 Charcount end; | |
| 4051 struct display_block *db = data->db; | |
| 4052 struct glyph_block gb; | |
| 4053 | |
| 4054 data->blank_width = space_width (XWINDOW (data->window)); | |
| 4055 while (Dynarr_length (db->runes) < pos) | |
| 4056 add_blank_rune (data, NULL, 0); | |
| 4057 | |
| 4058 end = Dynarr_length (db->runes) + 1; | |
| 4059 if (max_pos != -1) | |
| 4060 end = min (max_pos, end); | |
| 4061 | |
| 4062 gb.glyph = glyph; | |
| 438 | 4063 gb.extent = extent; |
| 428 | 4064 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); |
| 4065 pos++; | |
| 4066 | |
| 4067 while (Dynarr_length (db->runes) < pos && | |
| 4187 | 4068 (data->pixpos + data->blank_width <= data->max_pixpos)) |
| 428 | 4069 add_blank_rune (data, NULL, 0); |
| 4070 | |
| 4071 return Dynarr_length (db->runes); | |
| 4072 } | |
| 4073 | |
| 4074 /* If max_pos is == -1, it is considered to be infinite. The same is | |
| 4075 true of max_pixsize. */ | |
| 4076 #define SET_CURRENT_MODE_CHARS_PIXSIZE \ | |
| 4077 if (Dynarr_length (data->db->runes)) \ | |
| 4078 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \ | |
| 4079 else \ | |
| 4080 cur_pixsize = 0; | |
| 4081 | |
| 4082 /* Note that this function does "positions" in terms of characters and | |
| 4083 not in terms of columns. This is necessary to make the formatting | |
| 4084 work correctly when proportional width fonts are used in the | |
| 4085 modeline. */ | |
| 4086 static Charcount | |
| 4087 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, | |
| 4187 | 4088 Charcount min_pos, Charcount max_pos, |
| 4089 Lisp_Object elt, int depth, int max_pixsize, | |
| 4090 face_index findex, int type, Charcount *offset, | |
| 438 | 4091 Lisp_Object cur_ext) |
| 428 | 4092 { |
| 4093 /* This function has been Mule-ized. */ | |
| 4094 /* #### The other losing things in this function are: | |
| 4095 | |
| 4096 -- C zero-terminated-string lossage. | |
| 4097 -- Non-printable characters should be converted into something | |
| 4187 | 4098 appropriate (e.g. ^F) instead of blindly being printed anyway. |
| 428 | 4099 */ |
| 4100 | |
| 4101 tail_recurse: | |
| 4102 if (depth > 10) | |
| 4103 goto invalid; | |
| 4104 | |
| 4105 depth++; | |
| 4106 | |
| 4107 if (STRINGP (elt)) | |
| 4108 { | |
| 4109 /* A string. Add to the display line and check for %-constructs | |
| 4187 | 4110 within it. */ |
| 428 | 4111 |
| 2552 | 4112 Ibyte *this_str = XSTRING_DATA (elt); |
| 4113 | |
| 4114 while ((pos < max_pos || max_pos == -1) && *this_str) | |
| 4187 | 4115 { |
| 4116 Ibyte *last = this_str; | |
| 4117 | |
| 4118 while (*this_str && *this_str != '%') | |
| 4119 this_str++; | |
| 4120 | |
| 4121 if (this_str != last) | |
| 4122 { | |
| 4123 /* No %-construct */ | |
| 4124 Charcount size = | |
| 2552 | 4125 bytecount_to_charcount (last, this_str - last); |
| 438 | 4126 |
| 4127 if (size <= *offset) | |
| 4128 *offset -= size; | |
| 4129 else | |
| 4130 { | |
| 4131 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset : | |
| 4132 min (pos + size - *offset, max_pos)); | |
| 867 | 4133 const Ibyte *tmp_last = itext_n_addr (last, *offset); |
| 438 | 4134 |
| 4135 pos = add_string_to_fstring_db_runes (data, tmp_last, | |
| 4136 pos, pos, tmp_max); | |
| 4137 *offset = 0; | |
| 4138 } | |
| 4187 | 4139 } |
| 4140 else /* *this_str == '%' */ | |
| 4141 { | |
| 4142 Charcount spec_width = 0; | |
| 4143 | |
| 4144 this_str++; /* skip over '%' */ | |
| 4145 | |
| 4146 /* We can't allow -ve args due to the "%-" construct. | |
| 4147 * Argument specifies minwidth but not maxwidth | |
| 4148 * (maxwidth can be specified by | |
| 4149 * (<negative-number> . <stuff>) modeline elements) | |
| 4150 */ | |
| 4151 while (isdigit (*this_str)) | |
| 4152 { | |
| 4153 spec_width = spec_width * 10 + (*this_str - '0'); | |
| 4154 this_str++; | |
| 4155 } | |
| 4156 spec_width += pos; | |
| 4157 | |
| 4158 if (*this_str == 'M') | |
| 4159 { | |
| 4160 pos = generate_fstring_runes (w, data, pos, spec_width, | |
| 4161 max_pos, Vglobal_mode_string, | |
| 4162 depth, max_pixsize, findex, | |
| 4163 type, offset, cur_ext); | |
| 4164 } | |
| 4165 else if (*this_str == '-') | |
| 4166 { | |
| 4167 Charcount num_to_add; | |
| 4168 | |
| 4169 if (max_pixsize < 0) | |
| 4170 num_to_add = 0; | |
| 4171 else if (max_pos != -1) | |
| 4172 num_to_add = max_pos - pos; | |
| 4173 else | |
| 4174 { | |
| 4175 int cur_pixsize; | |
| 4176 int dash_pixsize; | |
| 4177 Ibyte ch = '-'; | |
| 4178 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
| 4179 | |
| 4180 dash_pixsize = | |
| 4181 redisplay_text_width_string (w, findex, &ch, Qnil, 0, | |
| 4182 1); | |
| 4183 | |
| 4184 if (dash_pixsize == 0) | |
| 3094 | 4185 num_to_add = 0; |
| 4186 else { | |
| 4187 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize; | |
| 4188 num_to_add++; | |
| 4189 } | |
| 4187 | 4190 } |
| 4191 | |
| 4192 while (num_to_add--) | |
| 4193 pos = add_string_to_fstring_db_runes | |
| 4194 (data, (const Ibyte *) "-", pos, pos, max_pos); | |
| 4195 } | |
| 4196 else if (*this_str != 0) | |
| 4197 { | |
| 4198 Ichar ch = itext_ichar (this_str); | |
| 4199 Ibyte *str; | |
| 438 | 4200 Charcount size; |
| 4201 | |
| 4187 | 4202 decode_mode_spec (w, ch, type); |
| 4203 | |
| 4204 str = Dynarr_atp (mode_spec_ibyte_string, 0); | |
| 438 | 4205 size = bytecount_to_charcount |
| 4206 /* Skip the null character added by `decode_mode_spec' */ | |
| 867 | 4207 (str, Dynarr_length (mode_spec_ibyte_string)) - 1; |
| 438 | 4208 |
| 4209 if (size <= *offset) | |
| 4210 *offset -= size; | |
| 4211 else | |
| 4212 { | |
| 867 | 4213 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
| 438 | 4214 |
| 440 | 4215 /* #### NOTE: I don't understand why a tmp_max is not |
| 438 | 4216 computed and used here as in the plain string case |
| 4217 above. -- dv */ | |
| 4218 pos = add_string_to_fstring_db_runes (data, tmp_str, | |
| 4219 pos, pos, | |
| 4220 max_pos); | |
| 4221 *offset = 0; | |
| 4222 } | |
| 4187 | 4223 } |
| 4224 | |
| 4225 /* NOT this_str++. There could be any sort of character at | |
| 4226 the current position. */ | |
| 4227 INC_IBYTEPTR (this_str); | |
| 4228 } | |
| 4229 | |
| 4230 if (max_pixsize > 0) | |
| 4231 { | |
| 4232 int cur_pixsize; | |
| 4233 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
| 4234 | |
| 4235 if (cur_pixsize >= max_pixsize) | |
| 4236 break; | |
| 4237 } | |
| 4238 } | |
| 428 | 4239 } |
| 4240 else if (SYMBOLP (elt)) | |
| 4241 { | |
| 4242 /* A symbol: process the value of the symbol recursively | |
| 4187 | 4243 as if it appeared here directly. */ |
| 428 | 4244 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); |
| 4245 | |
| 4246 if (!UNBOUNDP (tem)) | |
| 4187 | 4247 { |
| 438 | 4248 /* If value is a string, output that string literally: |
| 4187 | 4249 don't check for % within it. */ |
| 4250 if (STRINGP (tem)) | |
| 4251 { | |
| 867 | 4252 Ibyte *str = XSTRING_DATA (tem); |
| 826 | 4253 Charcount size = string_char_length (tem); |
| 438 | 4254 |
| 4255 if (size <= *offset) | |
| 4256 *offset -= size; | |
| 4257 else | |
| 4258 { | |
| 867 | 4259 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
| 438 | 4260 |
| 440 | 4261 /* #### NOTE: I don't understand why a tmp_max is not |
| 438 | 4262 computed and used here as in the plain string case |
| 4263 above. -- dv */ | |
| 4264 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
| 4265 min_pos, max_pos); | |
| 4266 *offset = 0; | |
| 4267 } | |
| 4187 | 4268 } |
| 4269 /* Give up right away for nil or t. */ | |
| 4270 else if (!EQ (tem, elt)) | |
| 4271 { | |
| 4272 elt = tem; | |
| 4273 goto tail_recurse; | |
| 4274 } | |
| 4275 } | |
| 428 | 4276 } |
| 4277 else if (GENERIC_SPECIFIERP (elt)) | |
| 4278 { | |
| 4279 Lisp_Object window, tem; | |
| 793 | 4280 window = wrap_window (w); |
| 428 | 4281 tem = specifier_instance_no_quit (elt, Qunbound, window, |
| 793 | 4282 ERROR_ME_DEBUG_WARN, 0, Qzero); |
| 428 | 4283 if (!UNBOUNDP (tem)) |
| 4284 { | |
| 4285 elt = tem; | |
| 4286 goto tail_recurse; | |
| 4287 } | |
| 4288 } | |
| 4289 else if (CONSP (elt)) | |
| 4290 { | |
| 4291 /* A cons cell: four distinct cases. | |
| 438 | 4292 * - If first element is a string or a cons, process all the elements |
| 4293 * and effectively concatenate them. | |
| 4294 * - If first element is a negative number, truncate displaying cdr to | |
| 4295 * at most that many characters. If positive, pad (with spaces) | |
| 4296 * to at least that many characters. | |
| 771 | 4297 * - If first element is another symbol or a boolean specifier, process |
| 4298 * the cadr or caddr recursively according to whether the symbol's | |
| 4299 * value or specifier's instance is non-nil or nil. | |
| 4300 * - If first element is , process the cadr or caddr | |
| 4301 * recursively according to whether the instance of the specifier in | |
| 4302 * the modeline's window is non-nil or nil. | |
| 442 | 4303 * - If first element is an extent, process the cdr recursively |
| 4304 * and handle the extent's face. | |
| 428 | 4305 */ |
| 438 | 4306 |
| 428 | 4307 Lisp_Object car, tem; |
| 4308 | |
| 4309 car = XCAR (elt); | |
| 771 | 4310 if (SYMBOLP (car) || BOOLEAN_SPECIFIERP (car)) |
| 438 | 4311 { |
| 4312 elt = XCDR (elt); | |
| 4313 if (!CONSP (elt)) | |
| 4314 goto invalid; | |
| 4315 | |
| 771 | 4316 if (SYMBOLP (car)) |
| 4317 tem = symbol_value_in_buffer (car, w->buffer); | |
| 4318 else | |
| 4319 tem = specifier_instance_no_quit (car, Qunbound, wrap_window (w), | |
| 793 | 4320 ERROR_ME_DEBUG_WARN, 0, Qzero); |
| 438 | 4321 /* elt is now the cdr, and we know it is a cons cell. |
| 4322 Use its car if CAR has a non-nil value. */ | |
| 771 | 4323 if (!UNBOUNDP (tem) && !NILP (tem)) |
| 438 | 4324 { |
| 771 | 4325 elt = XCAR (elt); |
| 4326 goto tail_recurse; | |
| 438 | 4327 } |
| 771 | 4328 /* Symbol's value or specifier's instance is nil or unbound |
| 438 | 4329 * Get the cddr of the original list |
| 4330 * and if possible find the caddr and use that. | |
| 4331 */ | |
| 4332 elt = XCDR (elt); | |
| 4333 if (NILP (elt)) | |
| 4334 ; | |
| 4335 else if (!CONSP (elt)) | |
| 4336 goto invalid; | |
| 4337 else | |
| 4338 { | |
| 4339 elt = XCAR (elt); | |
| 4340 goto tail_recurse; | |
| 4341 } | |
| 4342 } | |
| 428 | 4343 else if (INTP (car)) |
| 4187 | 4344 { |
| 4345 Charcount lim = XINT (car); | |
| 4346 | |
| 4347 elt = XCDR (elt); | |
| 4348 | |
| 4349 if (lim < 0) | |
| 4350 { | |
| 4351 /* Negative int means reduce maximum width. | |
| 4352 * DO NOT change MIN_PIXPOS here! | |
| 4353 * (20 -10 . foo) should truncate foo to 10 col | |
| 4354 * and then pad to 20. | |
| 4355 */ | |
| 4356 if (max_pos == -1) | |
| 4357 max_pos = pos - lim; | |
| 4358 else | |
| 4359 max_pos = min (max_pos, pos - lim); | |
| 4360 } | |
| 4361 else if (lim > 0) | |
| 4362 { | |
| 4363 /* Padding specified. Don't let it be more than | |
| 4364 * current maximum. | |
| 4365 */ | |
| 4366 lim += pos; | |
| 4367 if (max_pos != -1 && lim > max_pos) | |
| 4368 lim = max_pos; | |
| 4369 /* If that's more padding than already wanted, queue it. | |
| 4370 * But don't reduce padding already specified even if | |
| 4371 * that is beyond the current truncation point. | |
| 4372 */ | |
| 4373 if (lim > min_pos) | |
| 4374 min_pos = lim; | |
| 4375 } | |
| 4376 goto tail_recurse; | |
| 4377 } | |
| 428 | 4378 else if (STRINGP (car) || CONSP (car)) |
| 4187 | 4379 { |
| 4380 int limit = 50; | |
| 4381 | |
| 4382 /* LIMIT is to protect against circular lists. */ | |
| 4383 while (CONSP (elt) && --limit > 0 | |
| 4384 && (pos < max_pos || max_pos == -1)) | |
| 4385 { | |
| 4386 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
| 4387 XCAR (elt), depth, max_pixsize, | |
| 438 | 4388 findex, type, offset, cur_ext); |
| 4187 | 4389 elt = XCDR (elt); |
| 4390 } | |
| 4391 } | |
| 428 | 4392 else if (EXTENTP (car)) |
| 4187 | 4393 { |
| 4394 struct extent *ext = XEXTENT (car); | |
| 4395 | |
| 4396 if (EXTENT_LIVE_P (ext)) | |
| 4397 { | |
| 4398 face_index old_findex = data->findex; | |
| 4399 Lisp_Object face; | |
| 4400 Lisp_Object font_inst; | |
| 4401 face_index new_findex; | |
| 4402 Bytecount start = data->bytepos; | |
| 4403 | |
| 4404 face = extent_face (ext); | |
| 4405 if (FACEP (face)) | |
| 4406 { | |
| 4407 /* #### needs to merge faces, sigh */ | |
| 4408 /* #### needs to handle list of faces */ | |
| 4409 new_findex = get_builtin_face_cache_index (w, face); | |
| 4410 /* !!#### not right; needs to compute the max height of | |
| 4411 all the charsets */ | |
| 4412 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex, | |
| 4413 Vcharset_ascii); | |
| 4414 | |
| 4415 data->dl->ascent = max (data->dl->ascent, | |
| 4416 XFONT_INSTANCE (font_inst)->ascent); | |
| 4417 data->dl->descent = max (data->dl->descent, | |
| 4418 XFONT_INSTANCE (font_inst)-> | |
| 4419 descent); | |
| 4420 } | |
| 4421 else | |
| 4422 new_findex = old_findex; | |
| 4423 | |
| 4424 data->findex = new_findex; | |
| 4425 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
| 4426 XCDR (elt), depth - 1, | |
| 438 | 4427 max_pixsize, new_findex, type, |
| 4428 offset, car); | |
| 4187 | 4429 data->findex = old_findex; |
| 4430 Dynarr_add (formatted_string_extent_dynarr, ext); | |
| 4431 Dynarr_add (formatted_string_extent_start_dynarr, start); | |
| 4432 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); | |
| 4433 } | |
| 4434 } | |
| 428 | 4435 } |
| 4436 else if (GLYPHP (elt)) | |
| 4437 { | |
| 438 | 4438 /* Glyphs are considered as one character with respect to the modeline |
| 4439 horizontal scrolling facility. -- dv */ | |
| 4440 if (*offset > 0) | |
| 4441 *offset -= 1; | |
| 4442 else | |
| 4443 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos, | |
| 4444 cur_ext); | |
| 428 | 4445 } |
| 4446 else | |
| 4447 { | |
| 4448 invalid: | |
| 438 | 4449 { |
|
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
4450 const char *str = GETTEXT ("*invalid*"); |
| 438 | 4451 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */ |
| 4452 | |
| 4453 if (size <= *offset) | |
| 4454 *offset -= size; | |
| 4455 else | |
| 4456 { | |
| 867 | 4457 const Ibyte *tmp_str = |
| 4458 itext_n_addr ((const Ibyte *) str, *offset); | |
| 438 | 4459 |
| 440 | 4460 /* #### NOTE: I don't understand why a tmp_max is not computed and |
| 438 | 4461 used here as in the plain string case above. -- dv */ |
| 4462 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
| 4463 min_pos, max_pos); | |
| 4464 *offset = 0; | |
| 4465 } | |
| 4466 } | |
| 428 | 4467 } |
| 4468 | |
| 4469 if (min_pos > pos) | |
| 4470 { | |
| 867 | 4471 add_string_to_fstring_db_runes (data, (const Ibyte *) "", pos, |
| 438 | 4472 min_pos, -1); |
| 428 | 4473 } |
| 4474 | |
| 4475 return pos; | |
| 4476 } | |
| 4477 | |
| 4478 /* Update just the modeline. Assumes the desired display structs. If | |
| 4479 they do not have a modeline block, it does nothing. */ | |
| 4480 static void | |
| 4481 regenerate_modeline (struct window *w) | |
| 4482 { | |
| 4483 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP); | |
| 4484 | |
| 4485 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline) | |
| 4486 return; | |
| 4487 else | |
| 4488 { | |
| 4489 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP); | |
| 4490 redisplay_update_line (w, 0, 0, 0); | |
| 4491 } | |
| 4492 } | |
| 4493 | |
| 4494 /* Make sure that modeline display line is present in the given | |
| 4495 display structs if the window has a modeline and update that | |
| 4496 line. Returns true if a modeline was needed. */ | |
| 4497 static int | |
| 4498 ensure_modeline_generated (struct window *w, int type) | |
| 4499 { | |
| 4500 int need_modeline; | |
| 4501 | |
| 4502 /* minibuffer windows don't have modelines */ | |
| 4503 if (MINI_WINDOW_P (w)) | |
| 4504 need_modeline = 0; | |
| 4505 /* windows which haven't had it turned off do */ | |
| 4506 else if (WINDOW_HAS_MODELINE_P (w)) | |
| 4507 need_modeline = 1; | |
| 4508 /* windows which have it turned off don't have a divider if there is | |
| 4509 a horizontal scrollbar */ | |
| 4510 else if (window_scrollbar_height (w)) | |
| 4511 need_modeline = 0; | |
| 4512 /* and in this case there is none */ | |
| 4513 else | |
| 4514 need_modeline = 1; | |
| 4515 | |
| 4516 if (need_modeline) | |
| 4517 { | |
| 4518 display_line_dynarr *dla; | |
| 4519 | |
| 4520 dla = window_display_lines (w, type); | |
| 4521 | |
| 4522 /* We don't care if there is a display line which is not | |
| 4187 | 4523 currently a modeline because it is definitely going to become |
| 4524 one if we have gotten to this point. */ | |
| 428 | 4525 if (Dynarr_length (dla) == 0) |
| 4526 { | |
| 4527 if (Dynarr_largest (dla) > 0) | |
| 800 | 4528 Dynarr_increment (dla); |
| 428 | 4529 else |
| 4530 { | |
| 4531 struct display_line modeline; | |
| 4207 | 4532 |
| 4533 DISPLAY_LINE_INIT (modeline); | |
| 428 | 4534 Dynarr_add (dla, modeline); |
| 4535 } | |
| 4536 } | |
| 4537 | |
| 4538 /* If we're adding a new place marker go ahead and generate the | |
| 4187 | 4539 modeline so that it is available for use by |
| 4540 window_modeline_height. */ | |
| 428 | 4541 generate_modeline (w, Dynarr_atp (dla, 0), type); |
| 4542 } | |
| 4543 | |
| 4544 return need_modeline; | |
| 4545 } | |
| 4546 | |
| 4547 /* #### Kludge or not a kludge. I tend towards the former. */ | |
| 4548 int | |
| 4549 real_current_modeline_height (struct window *w) | |
| 4550 { | |
| 4551 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer); | |
| 4552 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer); | |
| 4553 | |
| 4554 if (ensure_modeline_generated (w, CMOTION_DISP)) | |
| 4555 { | |
| 4556 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP); | |
| 4557 | |
| 4558 if (Dynarr_length (dla)) | |
| 4559 { | |
| 4560 if (Dynarr_atp (dla, 0)->modeline) | |
| 4561 return (Dynarr_atp (dla, 0)->ascent + | |
| 4562 Dynarr_atp (dla, 0)->descent); | |
| 4563 } | |
| 4564 } | |
| 4565 return 0; | |
| 4566 } | |
| 4567 | |
| 4568 | |
| 4569 /***************************************************************************/ | |
| 819 | 4570 /* */ |
| 826 | 4571 /* displayable string routines */ |
| 819 | 4572 /* */ |
| 428 | 4573 /***************************************************************************/ |
| 4574 | |
| 4575 /* Given a position for a string in a window, ensure that the given | |
| 4576 display line DL accurately represents the text on a line starting | |
| 4577 at the given position. | |
| 4578 | |
| 4579 Yes, this is duplicating the code of create_text_block, but it | |
| 4580 looked just too hard to change create_text_block to handle strings | |
| 4581 *and* buffers. We already make a distinction between the two | |
| 4582 elsewhere in the code so I think unifying them would require a | |
| 4583 complete MULE rewrite. Besides, the other distinction is that these | |
| 4584 functions cover text that the user *cannot edit* so we can remove | |
| 4585 everything to do with cursors, minibuffers etc. Eventually the | |
| 4586 modeline routines should be modified to use this code as it copes | |
| 4587 with many more types of display situation. */ | |
| 4588 | |
| 665 | 4589 static Charbpos |
| 428 | 4590 create_string_text_block (struct window *w, Lisp_Object disp_string, |
| 4591 struct display_line *dl, | |
| 826 | 4592 Charcount start_pos, |
| 428 | 4593 prop_block_dynarr **prop, |
| 4594 face_index default_face) | |
| 4595 { | |
| 4596 struct frame *f = XFRAME (w->frame); | |
| 4597 /* Note that a lot of the buffer controlled stuff has been left in | |
| 4598 because you might well want to make use of it (selective display | |
| 4599 etc), its just the buffer text that we do not use. However, it | |
| 4600 seems to be possible for buffer to be nil sometimes so protect | |
| 4601 against this case. */ | |
| 4602 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; | |
| 4603 struct device *d = XDEVICE (f->device); | |
| 4604 | |
| 4605 /* we're working with these a lot so precalculate them */ | |
| 4606 Bytecount slen = XSTRING_LENGTH (disp_string); | |
| 826 | 4607 Bytecount byte_string_zv = slen; |
| 4608 Bytecount byte_start_pos = string_index_char_to_byte (disp_string, start_pos); | |
| 428 | 4609 |
| 4610 pos_data data; | |
| 4611 | |
| 4612 int truncate_win = b ? window_truncation_on (w) : 0; | |
| 4613 | |
| 442 | 4614 /* We're going to ditch selective display for static text, it's an |
| 4615 FSF thing and invisible extents are the way to go here. | |
| 4616 Implementing it also relies on a number of buffer-specific | |
| 428 | 4617 functions that we don't have the luxury of being able to use |
| 4618 here. */ | |
| 4619 | |
| 4620 /* The variable ctl-arrow allows the user to specify what characters | |
| 4621 can actually be displayed and which octal should be used for. | |
| 4622 #### This variable should probably have some rethought done to | |
| 4623 it. | |
| 4624 | |
| 4625 #### It would also be really nice if you could specify that | |
| 4626 the characters come out in hex instead of in octal. Mule | |
| 4627 does that by adding a ctl-hexa variable similar to ctl-arrow, | |
| 4628 but that's bogus -- we need a more general solution. I | |
| 4629 think you need to extend the concept of display tables | |
| 4630 into a more general conversion mechanism. Ideally you | |
| 4631 could specify a Lisp function that converts characters, | |
| 4632 but this violates the Second Golden Rule and besides would | |
| 4633 make things way way way way slow. | |
| 4634 | |
| 4635 So instead, we extend the display-table concept, which was | |
| 4636 historically limited to 256-byte vectors, to one of the | |
| 4637 following: | |
| 4638 | |
| 4639 a) A 256-entry vector, for backward compatibility; | |
| 4640 b) char-table, mapping characters to values; | |
| 4641 c) range-table, mapping ranges of characters to values; | |
| 4642 d) a list of the above. | |
| 4643 | |
| 4644 The (d) option allows you to specify multiple display tables | |
| 4645 instead of just one. Each display table can specify conversions | |
| 4646 for some characters and leave others unchanged. The way the | |
| 4647 character gets displayed is determined by the first display table | |
| 4648 with a binding for that character. This way, you could call a | |
| 4649 function `enable-hex-display' that adds a hex display-table to | |
| 4650 the list of display tables for the current buffer. | |
| 4651 | |
| 4652 #### ...not yet implemented... Also, we extend the concept of | |
| 4653 "mapping" to include a printf-like spec. Thus you can make all | |
| 4654 extended characters show up as hex with a display table like | |
| 4655 this: | |
| 4656 | |
| 4187 | 4657 #s(range-table data ((256 524288) (format "%x"))) |
| 428 | 4658 |
| 4659 Since more than one display table is possible, you have | |
| 4660 great flexibility in mapping ranges of characters. */ | |
| 867 | 4661 Ichar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
| 428 | 4662 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
| 4663 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
| 4664 ? 255 : 160)) : 255; | |
| 4665 | |
| 4666 Lisp_Object face_dt, window_dt; | |
| 4667 | |
| 4668 /* The text display block for this display line. */ | |
| 4669 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 4670 | |
| 4671 /* The first time through the main loop we need to force the glyph | |
| 4672 data to be updated. */ | |
| 4673 int initial = 1; | |
| 4674 | |
| 4675 /* Apparently the new extent_fragment_update returns an end position | |
| 4676 equal to the position passed in if there are no more runs to be | |
| 4677 displayed. */ | |
| 4678 int no_more_frags = 0; | |
| 4679 | |
| 4680 dl->used_prop_data = 0; | |
| 4681 dl->num_chars = 0; | |
| 442 | 4682 dl->line_continuation = 0; |
| 428 | 4683 |
| 4187 | 4684 /* Set up faces to use for clearing areas, used by output_display_line. */ |
| 428 | 4685 dl->default_findex = default_face; |
| 4187 | 4686 if (default_face > DEFAULT_INDEX) |
| 428 | 4687 { |
| 4688 dl->left_margin_findex = default_face; | |
| 4689 dl->right_margin_findex = default_face; | |
| 4690 } | |
| 4691 else | |
| 4692 { | |
| 434 | 4693 dl->left_margin_findex = |
| 428 | 4694 get_builtin_face_cache_index (w, Vleft_margin_face); |
| 434 | 4695 dl->right_margin_findex = |
| 428 | 4696 get_builtin_face_cache_index (w, Vright_margin_face); |
| 4697 } | |
| 4698 | |
| 4699 xzero (data); | |
| 4700 data.ef = extent_fragment_new (disp_string, f); | |
| 4701 | |
| 4702 /* These values are used by all of the rune addition routines. We add | |
| 4703 them to this structure for ease of passing. */ | |
| 4704 data.d = d; | |
| 793 | 4705 data.window = wrap_window (w); |
| 428 | 4706 data.db = db; |
| 4707 data.dl = dl; | |
| 4708 | |
| 826 | 4709 data.byte_charpos = byte_start_pos; |
| 428 | 4710 data.pixpos = dl->bounds.left_in; |
| 4711 data.last_charset = Qunbound; | |
| 4712 data.last_findex = default_face; | |
| 4713 data.result_str = Qnil; | |
| 4714 data.string = disp_string; | |
| 4715 | |
| 4716 /* Set the right boundary adjusting it to take into account any end | |
| 4717 glyph. Save the width of the end glyph for later use. */ | |
| 4718 data.max_pixpos = dl->bounds.right_in; | |
| 819 | 4719 data.max_pixpos -= data.end_glyph_width; |
| 428 | 4720 |
| 4721 data.cursor_type = NO_CURSOR; | |
| 4722 data.cursor_x = -1; | |
| 4723 | |
| 4724 data.start_col = 0; | |
| 4725 /* I don't think we want this, string areas should not scroll with | |
| 434 | 4726 the window |
| 428 | 4727 data.start_col = w->hscroll; |
| 826 | 4728 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
| 428 | 4729 */ |
| 826 | 4730 data.byte_start_col_enabled = 0; |
| 428 | 4731 data.hscroll_glyph_width_adjust = 0; |
| 4732 | |
| 4733 /* We regenerate the line from the very beginning. */ | |
| 4734 Dynarr_reset (db->runes); | |
| 4735 | |
| 4736 /* Why is this less than or equal and not just less than? If the | |
| 4737 starting position is already equal to the maximum we can't add | |
| 4738 anything else, right? Wrong. We might still have a newline to | |
| 4739 add. A newline can use the room allocated for an end glyph since | |
| 4740 if we add it we know we aren't going to be adding any end | |
| 4741 glyph. */ | |
| 4742 | |
| 4743 /* #### Chuck -- I think this condition should be while (1). | |
| 4744 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
| 4745 and the begin-glyph ends exactly at the end of the window, the | |
| 4746 end-glyph and text might not be displayed. while (1) ensures | |
| 4747 that the loop terminates only when either (a) there is | |
| 4748 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
| 4749 | |
| 4750 #### Also I think you need to ensure that the operation | |
| 4751 "add begin glyphs; add end glyphs; add text" is atomic and | |
| 4752 can't get interrupted in the middle. If you run off the end | |
| 4753 of the line during that operation, then you keep accumulating | |
| 4754 propagation data until you're done. Otherwise, if the (e.g.) | |
| 4755 there's a begin glyph at a particular position and attempting | |
| 4756 to display that glyph results in window-end being hit and | |
| 4757 propagation data being generated, then the character at that | |
| 4758 position won't be displayed. | |
| 4759 | |
| 4760 #### See also the comment after the end of this loop, below. | |
| 4761 */ | |
| 4762 while (data.pixpos <= data.max_pixpos) | |
| 4763 { | |
| 4764 /* #### This check probably should not be necessary. */ | |
| 826 | 4765 if (data.byte_charpos > byte_string_zv) |
| 428 | 4766 { |
| 4767 /* #### urk! More of this lossage! */ | |
| 826 | 4768 data.byte_charpos--; |
| 428 | 4769 goto done; |
| 4770 } | |
| 4771 | |
| 4772 /* Check for face changes. */ | |
| 826 | 4773 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
| 428 | 4774 { |
| 819 | 4775 Lisp_Object last_glyph = Qnil; |
| 4776 /* Deal with clipped glyphs that we have already displayed. */ | |
| 4187 | 4777 if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH) |
| 819 | 4778 { |
| 4779 last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph; | |
| 4780 Dynarr_free (*prop); | |
| 4781 *prop = 0; | |
| 4782 } | |
| 428 | 4783 /* Now compute the face and begin/end-glyph information. */ |
| 4784 data.findex = | |
| 793 | 4785 /* Remember that the extent-fragment routines deal in |
| 4187 | 4786 Bytexpos's. */ |
| 826 | 4787 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
| 428 | 4788 /* This is somewhat cheesy but the alternative is to |
| 4187 | 4789 propagate default_face into extent_fragment_update. */ |
| 428 | 4790 if (data.findex == DEFAULT_INDEX) |
| 4791 data.findex = default_face; | |
| 4792 | |
| 4793 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
| 4794 | |
| 826 | 4795 if (data.byte_charpos == data.ef->end) |
| 428 | 4796 no_more_frags = 1; |
| 4797 } | |
| 4798 initial = 0; | |
| 4799 | |
| 4800 /* Determine what is next to be displayed. We first handle any | |
| 4187 | 4801 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
| 4802 display then we determine what to do based on the character at the | |
| 4803 current buffer position. */ | |
| 428 | 4804 |
| 4805 /* If the current position is covered by an invisible extent, do | |
| 4187 | 4806 nothing (except maybe add some ellipses). |
| 428 | 4807 |
| 4808 #### The behavior of begin and end-glyphs at the edge of an | |
| 4809 invisible extent should be investigated further. This is | |
| 4810 fairly low priority though. */ | |
| 4811 if (data.ef->invisible) | |
| 4812 { | |
| 4813 /* #### Chuck, perhaps you could look at this code? I don't | |
| 4814 really know what I'm doing. */ | |
| 4815 if (*prop) | |
| 4816 { | |
| 4817 Dynarr_free (*prop); | |
| 4818 *prop = 0; | |
| 4819 } | |
| 4820 | |
| 4821 /* The extent fragment code only sets this when we should | |
| 4822 really display the ellipses. It makes sure the ellipses | |
| 4823 don't get displayed more than once in a row. */ | |
| 4824 if (data.ef->invisible_ellipses) | |
| 4825 { | |
| 4826 struct glyph_block gb; | |
| 4827 | |
| 4828 data.ef->invisible_ellipses_already_displayed = 1; | |
| 4829 data.ef->invisible_ellipses = 0; | |
| 4830 gb.extent = Qnil; | |
| 4831 gb.glyph = Vinvisible_text_glyph; | |
| 4832 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
| 4833 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
| 4834 /* Perhaps they shouldn't propagate if the very next thing | |
| 4835 is to display a newline (for compatibility with | |
| 4836 selective-display-ellipses)? Maybe that's too | |
| 4837 abstruse. */ | |
| 4838 if (*prop) | |
| 4839 goto done; | |
| 4840 } | |
| 4841 | |
| 638 | 4842 /* #### What if we're dealing with a display table? */ |
| 428 | 4843 if (data.start_col) |
| 4844 data.start_col--; | |
| 4845 | |
| 826 | 4846 if (data.byte_charpos == byte_string_zv) |
| 428 | 4847 goto done; |
| 4848 else | |
| 826 | 4849 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
| 428 | 4850 } |
| 4851 | |
| 4852 /* If there is propagation data, then it represents the current | |
| 4187 | 4853 buffer position being displayed. Add them and advance the |
| 4854 position counter. This might also add the minibuffer | |
| 4855 prompt. */ | |
| 428 | 4856 else if (*prop) |
| 4857 { | |
| 4858 dl->used_prop_data = 1; | |
| 4859 *prop = add_propagation_runes (prop, &data); | |
| 4860 | |
| 4861 if (*prop) | |
| 4862 goto done; /* gee, a really narrow window */ | |
| 826 | 4863 else if (data.byte_charpos == byte_string_zv) |
| 428 | 4864 goto done; |
| 826 | 4865 else if (data.byte_charpos < 0) |
| 428 | 4866 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
| 826 | 4867 data.byte_charpos = 0; |
| 428 | 4868 else |
| 826 | 4869 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
| 428 | 4870 } |
| 4871 | |
| 4872 /* If there are end glyphs, add them to the line. These are | |
| 4873 the end glyphs for the previous run of text. We add them | |
| 4874 here rather than doing them at the end of handling the | |
| 4875 previous run so that glyphs at the beginning and end of | |
| 4876 a line are handled correctly. */ | |
| 4877 else if (Dynarr_length (data.ef->end_glyphs) > 0) | |
| 4878 { | |
| 867 | 4879 data.ch = string_ichar (disp_string, data.byte_charpos); |
| 428 | 4880 *prop = add_glyph_runes (&data, END_GLYPHS); |
| 819 | 4881 |
| 4882 if (*prop) { | |
| 428 | 4883 goto done; |
| 819 | 4884 } |
| 428 | 4885 } |
| 4886 | |
| 4887 /* If there are begin glyphs, add them to the line. */ | |
| 4888 else if (Dynarr_length (data.ef->begin_glyphs) > 0) | |
| 4889 { | |
| 867 | 4890 data.ch = string_ichar (disp_string, data.byte_charpos); |
| 428 | 4891 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); |
| 819 | 4892 |
| 4893 if (*prop) { | |
| 428 | 4894 goto done; |
| 819 | 4895 } |
| 428 | 4896 } |
| 4897 | |
| 4898 /* If at end-of-buffer, we've already processed begin and | |
| 4899 end-glyphs at this point and there's no text to process, | |
| 4900 so we're done. */ | |
| 826 | 4901 else if (data.byte_charpos == byte_string_zv) |
| 428 | 4902 goto done; |
| 4903 | |
| 4904 else | |
| 4905 { | |
| 4906 Lisp_Object entry = Qnil; | |
| 4907 /* Get the character at the current buffer position. */ | |
| 867 | 4908 data.ch = string_ichar (disp_string, data.byte_charpos); |
| 428 | 4909 if (!NILP (face_dt) || !NILP (window_dt)) |
| 4910 entry = display_table_entry (data.ch, face_dt, window_dt); | |
| 4911 | |
| 4912 /* If there is a display table entry for it, hand it off to | |
| 4187 | 4913 add_disp_table_entry_runes and let it worry about it. */ |
| 428 | 4914 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
| 4915 { | |
| 4916 *prop = add_disp_table_entry_runes (&data, entry); | |
| 4917 | |
| 4918 if (*prop) | |
| 4919 goto done; | |
| 4920 } | |
| 4921 | |
| 4922 /* Check if we have hit a newline character. If so, add a marker | |
| 4187 | 4923 to the line and end this loop. */ |
| 428 | 4924 else if (data.ch == '\n') |
| 4925 { | |
| 4926 /* We aren't going to be adding an end glyph so give its | |
| 4187 | 4927 space back in order to make sure that the cursor can |
| 4928 fit. */ | |
| 819 | 4929 data.max_pixpos += data.end_glyph_width; |
| 428 | 4930 goto done; |
| 4931 } | |
| 4932 | |
| 4933 /* If the current character is considered to be printable, then | |
| 4187 | 4934 just add it. */ |
| 428 | 4935 else if (data.ch >= printable_min) |
| 4936 { | |
| 867 | 4937 *prop = add_ichar_rune (&data); |
| 428 | 4938 if (*prop) |
| 4939 goto done; | |
| 4940 } | |
| 4941 | |
| 4942 /* If the current character is a tab, determine the next tab | |
| 4187 | 4943 starting position and add a blank rune which extends from the |
| 4944 current pixel position to that starting position. */ | |
| 428 | 4945 else if (data.ch == '\t') |
| 4946 { | |
| 4947 int tab_start_pixpos = data.pixpos; | |
| 4948 int next_tab_start; | |
| 4949 int char_tab_width; | |
| 4950 int prop_width = 0; | |
| 4951 | |
| 4952 if (data.start_col > 1) | |
| 4953 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); | |
| 4954 | |
| 4955 next_tab_start = | |
| 4956 next_tab_position (w, tab_start_pixpos, | |
| 4957 dl->bounds.left_in + | |
| 4958 data.hscroll_glyph_width_adjust); | |
| 4959 if (next_tab_start > data.max_pixpos) | |
| 4960 { | |
| 4961 prop_width = next_tab_start - data.max_pixpos; | |
| 4962 next_tab_start = data.max_pixpos; | |
| 4963 } | |
| 4964 data.blank_width = next_tab_start - data.pixpos; | |
| 4965 char_tab_width = | |
| 4966 (next_tab_start - tab_start_pixpos) / space_width (w); | |
| 4967 | |
| 4968 *prop = add_blank_rune (&data, w, char_tab_width); | |
| 4969 | |
| 4970 /* add_blank_rune is only supposed to be called with | |
| 819 | 4971 sizes guaranteed to fit in the available space. */ |
| 428 | 4972 assert (!(*prop)); |
| 4973 | |
| 4974 if (prop_width) | |
| 4975 { | |
| 4976 struct prop_block pb; | |
| 4977 *prop = Dynarr_new (prop_block); | |
| 4978 | |
| 4979 pb.type = PROP_BLANK; | |
| 4980 pb.data.p_blank.width = prop_width; | |
| 4981 pb.data.p_blank.findex = data.findex; | |
| 4982 Dynarr_add (*prop, pb); | |
| 4983 | |
| 4984 goto done; | |
| 4985 } | |
| 4986 } | |
| 4987 | |
| 4988 /* If character is a control character, pass it off to | |
| 4187 | 4989 add_control_char_runes. |
| 428 | 4990 |
| 4991 The is_*() routines have undefined results on | |
| 4992 arguments outside of the range [-1, 255]. (This | |
| 4993 often bites people who carelessly use `char' instead | |
| 4994 of `unsigned char'.) | |
| 4995 */ | |
| 867 | 4996 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
| 428 | 4997 { |
| 4998 *prop = add_control_char_runes (&data, b); | |
| 4999 | |
| 5000 if (*prop) | |
| 5001 goto done; | |
| 5002 } | |
| 5003 | |
| 5004 /* If the character is above the ASCII range and we have not | |
| 4187 | 5005 already handled it, then print it as an octal number. */ |
| 428 | 5006 else if (data.ch >= 0200) |
| 5007 { | |
| 5008 *prop = add_octal_runes (&data); | |
| 5009 | |
| 5010 if (*prop) | |
| 5011 goto done; | |
| 5012 } | |
| 5013 | |
| 5014 /* Assume the current character is considered to be printable, | |
| 4187 | 5015 then just add it. */ |
| 428 | 5016 else |
| 5017 { | |
| 867 | 5018 *prop = add_ichar_rune (&data); |
| 428 | 5019 if (*prop) |
| 5020 goto done; | |
| 5021 } | |
| 5022 | |
| 826 | 5023 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
| 428 | 5024 } |
| 5025 } | |
| 5026 | |
| 819 | 5027 done: |
| 428 | 5028 |
| 5029 /* Determine the starting point of the next line if we did not hit the | |
| 5030 end of the buffer. */ | |
| 826 | 5031 if (data.byte_charpos < byte_string_zv) |
| 428 | 5032 { |
| 5033 /* #### This check is not correct. If the line terminated | |
| 5034 due to a begin-glyph or end-glyph hitting window-end, then | |
| 826 | 5035 data.ch will not point to the character at data.byte_charpos. If |
| 428 | 5036 you make the two changes mentioned at the top of this loop, |
| 5037 you should be able to say '(if (*prop))'. That should also | |
| 826 | 5038 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
| 428 | 5039 check. */ |
| 5040 | |
| 5041 /* The common case is that the line ended because we hit a newline. | |
| 4187 | 5042 In that case, the next character is just the next buffer |
| 5043 position. */ | |
| 428 | 5044 if (data.ch == '\n') |
| 5045 { | |
| 826 | 5046 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
| 428 | 5047 } |
| 5048 | |
| 5049 /* Otherwise we have a buffer line which cannot fit on one display | |
| 4187 | 5050 line. */ |
| 428 | 5051 else |
| 5052 { | |
| 5053 struct glyph_block gb; | |
| 5054 struct glyph_cachel *cachel; | |
| 5055 | |
| 5056 /* If the line is to be truncated then we actually have to look | |
| 4187 | 5057 for the next newline. We also add the end-of-line glyph which |
| 5058 we know will fit because we adjusted the right border before | |
| 5059 we starting laying out the line. */ | |
| 819 | 5060 data.max_pixpos += data.end_glyph_width; |
| 428 | 5061 data.findex = default_face; |
| 5062 gb.extent = Qnil; | |
| 5063 | |
| 5064 if (truncate_win) | |
| 5065 { | |
| 826 | 5066 Bytecount byte_pos; |
| 428 | 5067 |
| 5068 /* Now find the start of the next line. */ | |
| 867 | 5069 byte_pos = byte_find_next_ichar_in_string (disp_string, '\n', |
| 826 | 5070 data.byte_charpos, 1); |
| 428 | 5071 |
| 5072 data.cursor_type = NO_CURSOR; | |
| 826 | 5073 data.byte_charpos = byte_pos; |
| 428 | 5074 gb.glyph = Vtruncation_glyph; |
| 5075 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
| 5076 } | |
| 5077 else | |
| 5078 { | |
| 5079 /* The cursor can never be on the continuation glyph. */ | |
| 5080 data.cursor_type = NO_CURSOR; | |
| 5081 | |
| 826 | 5082 /* data.byte_charpos is already at the start of the next line. */ |
| 428 | 5083 |
| 442 | 5084 dl->line_continuation = 1; |
| 428 | 5085 gb.glyph = Vcontinuation_glyph; |
| 5086 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
| 5087 } | |
| 5088 | |
| 819 | 5089 if (data.end_glyph_width) |
| 428 | 5090 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
| 5091 | |
| 826 | 5092 if (truncate_win && data.byte_charpos == byte_string_zv) |
| 428 | 5093 { |
| 867 | 5094 const Ibyte *endb = itext_n_addr (XSTRING_DATA (disp_string), |
| 826 | 5095 byte_string_zv); |
| 867 | 5096 DEC_IBYTEPTR (endb); |
| 5097 if (itext_ichar (endb) != '\n') | |
| 428 | 5098 { |
| 5099 /* #### Damn this losing shit. */ | |
| 826 | 5100 data.byte_charpos++; |
| 428 | 5101 } |
| 5102 } | |
| 5103 } | |
| 5104 } | |
| 826 | 5105 else if (data.byte_charpos == byte_string_zv) |
| 428 | 5106 { |
| 5107 /* create_text_block () adds a bogus \n marker here which screws | |
| 5108 up subwindow display. Since we never have a cursor in the | |
| 5109 gutter we can safely ignore it. */ | |
| 5110 } | |
| 5111 /* Calculate left whitespace boundary. */ | |
| 5112 { | |
| 5113 int elt = 0; | |
| 5114 | |
| 5115 /* Whitespace past a newline is considered right whitespace. */ | |
| 5116 while (elt < Dynarr_length (db->runes)) | |
| 5117 { | |
| 5118 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 5119 | |
| 5120 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
| 5121 || rb->type == RUNE_BLANK) | |
| 5122 { | |
| 5123 dl->bounds.left_white += rb->width; | |
| 5124 elt++; | |
| 5125 } | |
| 5126 else | |
| 5127 elt = Dynarr_length (db->runes); | |
| 5128 } | |
| 5129 } | |
| 5130 | |
| 5131 /* Calculate right whitespace boundary. */ | |
| 5132 { | |
| 5133 int elt = Dynarr_length (db->runes) - 1; | |
| 5134 int done = 0; | |
| 5135 | |
| 5136 while (!done && elt >= 0) | |
| 5137 { | |
| 5138 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 5139 | |
| 5140 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
| 5141 && isspace (rb->object.chr.ch)) | |
| 5142 && !rb->type == RUNE_BLANK) | |
| 5143 { | |
| 5144 dl->bounds.right_white = rb->xpos + rb->width; | |
| 5145 done = 1; | |
| 5146 } | |
| 5147 | |
| 5148 elt--; | |
| 5149 | |
| 5150 } | |
| 5151 | |
| 5152 /* The line is blank so everything is considered to be right | |
| 5153 whitespace. */ | |
| 5154 if (!done) | |
| 5155 dl->bounds.right_white = dl->bounds.left_in; | |
| 5156 } | |
| 5157 | |
| 5158 /* Set the display blocks bounds. */ | |
| 5159 db->start_pos = dl->bounds.left_in; | |
| 5160 if (Dynarr_length (db->runes)) | |
| 5161 { | |
| 5162 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); | |
| 5163 | |
| 5164 db->end_pos = rb->xpos + rb->width; | |
| 5165 } | |
| 5166 else | |
| 5167 db->end_pos = dl->bounds.right_white; | |
| 5168 | |
| 819 | 5169 calculate_baseline (&data); |
| 428 | 5170 |
| 5171 dl->ascent = data.new_ascent; | |
| 5172 dl->descent = data.new_descent; | |
| 5173 | |
| 5174 { | |
| 5175 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
| 5176 | |
| 5177 if (dl->ascent < ascent) | |
| 5178 dl->ascent = ascent; | |
| 5179 } | |
| 5180 { | |
| 5181 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
| 5182 | |
| 5183 if (dl->descent < descent) | |
| 5184 dl->descent = descent; | |
| 5185 } | |
| 5186 | |
| 819 | 5187 calculate_yoffset (dl, db); |
| 5188 | |
| 428 | 5189 dl->cursor_elt = data.cursor_x; |
| 5190 /* #### lossage lossage lossage! Fix this shit! */ | |
| 826 | 5191 if (data.byte_charpos > byte_string_zv) |
| 5192 dl->end_charpos = buffer_or_string_bytexpos_to_charxpos (disp_string, | |
| 5193 byte_string_zv); | |
| 428 | 5194 else |
| 826 | 5195 dl->end_charpos = |
| 5196 buffer_or_string_bytexpos_to_charxpos (disp_string, | |
| 5197 data.byte_charpos) - 1; | |
| 428 | 5198 if (truncate_win) |
| 434 | 5199 data.dl->num_chars = |
| 826 | 5200 string_column_at_point (disp_string, dl->end_charpos, |
| 793 | 5201 b ? XINT (b->tab_width) : 8); |
| 428 | 5202 else |
| 5203 /* This doesn't correctly take into account tabs and control | |
| 5204 characters but if the window isn't being truncated then this | |
| 5205 value isn't going to end up being used anyhow. */ | |
| 826 | 5206 data.dl->num_chars = dl->end_charpos - dl->charpos; |
| 428 | 5207 |
| 5208 /* #### handle horizontally scrolled line with text none of which | |
| 5209 was actually laid out. */ | |
| 5210 | |
| 5211 /* #### handle any remainder of overlay arrow */ | |
| 5212 | |
| 5213 if (*prop == ADD_FAILED) | |
| 5214 *prop = NULL; | |
| 5215 | |
| 5216 if (truncate_win && *prop) | |
| 5217 { | |
| 5218 Dynarr_free (*prop); | |
| 5219 *prop = NULL; | |
| 5220 } | |
| 5221 | |
| 5222 extent_fragment_delete (data.ef); | |
| 5223 | |
| 5224 /* #### If we started at EOB, then make sure we return a value past | |
| 5225 it so that regenerate_window will exit properly. This is bogus. | |
| 5226 The main loop should get fixed so that it isn't necessary to call | |
| 5227 this function if we are already at EOB. */ | |
| 5228 | |
| 826 | 5229 if (data.byte_charpos == byte_string_zv && byte_start_pos == byte_string_zv) |
| 793 | 5230 return string_index_byte_to_char (disp_string, |
| 826 | 5231 data.byte_charpos) + 1; /* Yuck! */ |
| 428 | 5232 else |
| 826 | 5233 return string_index_byte_to_char (disp_string, data.byte_charpos); |
| 428 | 5234 } |
| 5235 | |
| 5236 /* Given a display line and a starting position, ensure that the | |
| 5237 contents of the display line accurately represent the visual | |
| 5238 representation of the buffer contents starting from the given | |
| 5239 position when displayed in the given window. The display line ends | |
| 5240 when the contents of the line reach the right boundary of the given | |
| 434 | 5241 window. |
| 5242 | |
| 428 | 5243 This is very similar to generate_display_line but with the same |
| 5244 limitations as create_string_text_block. I have taken the liberty | |
| 665 | 5245 of fixing the bytebpos stuff though.*/ |
| 5246 | |
| 5247 static Charbpos | |
| 428 | 5248 generate_string_display_line (struct window *w, Lisp_Object disp_string, |
| 5249 struct display_line *dl, | |
| 826 | 5250 Charcount start_pos, |
| 428 | 5251 prop_block_dynarr **prop, |
| 5252 face_index default_face) | |
| 5253 { | |
| 826 | 5254 Charcount ret_charcount; |
| 428 | 5255 |
| 5256 /* you must set bounds before calling this. */ | |
| 434 | 5257 |
| 428 | 5258 /* Reset what this line is using. */ |
| 5259 if (dl->display_blocks) | |
| 5260 Dynarr_reset (dl->display_blocks); | |
| 5261 if (dl->left_glyphs) | |
| 5262 { | |
| 5263 Dynarr_free (dl->left_glyphs); | |
| 5264 dl->left_glyphs = 0; | |
| 5265 } | |
| 5266 if (dl->right_glyphs) | |
| 5267 { | |
| 5268 Dynarr_free (dl->right_glyphs); | |
| 5269 dl->right_glyphs = 0; | |
| 5270 } | |
| 5271 | |
| 5272 /* We aren't generating a modeline at the moment. */ | |
| 5273 dl->modeline = 0; | |
| 5274 | |
| 5275 /* Create a display block for the text region of the line. */ | |
| 826 | 5276 ret_charcount = create_string_text_block (w, disp_string, dl, start_pos, |
| 5277 prop, default_face); | |
| 5278 dl->charpos = start_pos; | |
| 5279 if (dl->end_charpos < dl->charpos) | |
| 5280 dl->end_charpos = dl->charpos; | |
| 428 | 5281 |
| 5282 /* If there are left glyphs associated with any character in the | |
| 5283 text block, then create a display block to handle them. */ | |
| 5284 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
| 5285 create_left_glyph_block (w, dl, 0); | |
| 5286 | |
| 5287 /* If there are right glyphs associated with any character in the | |
| 5288 text block, then create a display block to handle them. */ | |
| 5289 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
| 5290 create_right_glyph_block (w, dl); | |
| 5291 | |
| 826 | 5292 return ret_charcount; |
| 428 | 5293 } |
| 5294 | |
| 2518 | 5295 /* |
| 5296 | |
| 5297 Info on Re-entrancy crashes, with backtraces given: | |
| 5298 | |
| 5299 (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT") | |
| 1318 | 5300 */ |
| 5301 | |
| 5302 | |
| 428 | 5303 /* This is ripped off from regenerate_window. All we want to do is |
| 5304 loop through elements in the string creating display lines until we | |
| 5305 have covered the provided area. Simple really. */ | |
| 5306 void | |
| 5307 generate_displayable_area (struct window *w, Lisp_Object disp_string, | |
| 5308 int xpos, int ypos, int width, int height, | |
| 5309 display_line_dynarr* dla, | |
| 826 | 5310 Charcount start_pos, |
| 428 | 5311 face_index default_face) |
| 5312 { | |
| 5313 int yend = ypos + height; | |
| 5314 Charcount s_zv; | |
| 5315 prop_block_dynarr *prop = 0; | |
| 5316 layout_bounds bounds; | |
| 2518 | 5317 int depth = -1; |
| 5318 | |
| 428 | 5319 /* if there's nothing to do then do nothing. code after this assumes |
| 5320 there is something to do. */ | |
| 5321 if (NILP (disp_string)) | |
| 5322 return; | |
| 5323 | |
| 2518 | 5324 /* See comment in regenerate_window() */ |
| 5325 if (!in_display) | |
| 5326 depth = enter_redisplay_critical_section (); | |
| 5327 | |
| 5328 assert (dla); | |
| 5329 Dynarr_reset (dla); | |
| 5330 | |
| 826 | 5331 s_zv = string_char_length (disp_string); |
| 428 | 5332 |
| 5333 bounds.left_out = xpos; | |
| 5334 bounds.right_out = xpos + width; | |
| 5335 /* The inner boundaries mark where the glyph margins are located. */ | |
| 5336 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
| 5337 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
| 5338 /* We cannot fully calculate the whitespace boundaries as they | |
| 5339 depend on the contents of the line being displayed. */ | |
| 5340 bounds.left_white = bounds.left_in; | |
| 5341 bounds.right_white = bounds.right_in; | |
| 5342 | |
| 5343 while (ypos < yend) | |
| 5344 { | |
| 5345 struct display_line dl; | |
| 5346 struct display_line *dlp; | |
| 826 | 5347 Charcount next_pos; |
| 428 | 5348 int local; |
| 851 | 5349 int pos_of_dlp = -1; |
| 428 | 5350 |
| 5351 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
| 5352 { | |
| 851 | 5353 pos_of_dlp = Dynarr_length (dla); |
| 5354 dlp = Dynarr_atp (dla, pos_of_dlp); | |
| 428 | 5355 local = 0; |
| 5356 } | |
| 5357 else | |
| 5358 { | |
| 4207 | 5359 DISPLAY_LINE_INIT (dl); |
| 428 | 5360 dlp = &dl; |
| 5361 local = 1; | |
| 5362 } | |
| 5363 | |
| 5364 dlp->bounds = bounds; | |
| 5365 dlp->offset = 0; | |
| 1318 | 5366 Dynarr_lock (dla); |
| 428 | 5367 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos, |
| 5368 &prop, default_face); | |
| 1318 | 5369 Dynarr_unlock (dla); |
| 428 | 5370 /* we need to make sure that we continue along the line if there |
| 4187 | 5371 is more left to display otherwise we just end up redisplaying |
| 5372 the same chunk over and over again. */ | |
| 428 | 5373 if (next_pos == start_pos && next_pos < s_zv) |
| 5374 start_pos++; | |
| 5375 else | |
| 5376 start_pos = next_pos; | |
| 5377 | |
| 5378 dlp->ypos = ypos + dlp->ascent; | |
| 5379 ypos = dlp->ypos + dlp->descent; | |
| 5380 | |
| 5381 if (ypos > yend) | |
| 5382 { | |
| 5383 int visible_height = dlp->ascent + dlp->descent; | |
| 5384 | |
| 5385 dlp->clip = (ypos - yend); | |
| 5386 visible_height -= dlp->clip; | |
| 5387 | |
| 5388 if (visible_height < VERTICAL_CLIP (w, 1)) | |
| 5389 { | |
| 5390 if (local) | |
| 5391 free_display_line (dlp); | |
| 5392 break; | |
| 5393 } | |
| 5394 } | |
| 5395 else | |
| 5396 dlp->clip = 0; | |
| 5397 | |
|
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5398 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
|
5399 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
|
5400 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
|
5401 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
|
5402 else |
|
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5403 ABORT (); |
| 428 | 5404 |
| 5405 /* #### This type of check needs to be done down in the | |
| 5406 generate_display_line call. */ | |
| 5407 if (start_pos >= s_zv) | |
| 5408 break; | |
| 5409 } | |
| 5410 | |
| 5411 if (prop) | |
| 5412 Dynarr_free (prop); | |
| 2518 | 5413 |
| 5414 if (depth >= 0) | |
| 5415 exit_redisplay_critical_section (depth); | |
| 428 | 5416 } |
| 5417 | |
| 5418 | |
| 5419 /***************************************************************************/ | |
| 5420 /* */ | |
| 5421 /* window-regeneration routines */ | |
| 5422 /* */ | |
| 5423 /***************************************************************************/ | |
| 5424 | |
| 5425 /* For a given window and starting position in the buffer it contains, | |
| 5426 ensure that the TYPE display lines accurately represent the | |
| 5427 presentation of the window. We pass the buffer instead of getting | |
| 5428 it from the window since redisplay_window may have temporarily | |
| 5429 changed it to the echo area buffer. */ | |
| 5430 | |
| 5431 static void | |
| 2518 | 5432 regenerate_window (struct window *w, Charbpos start_pos, Charbpos point, |
| 5433 int type) | |
| 428 | 5434 { |
| 5435 struct frame *f = XFRAME (w->frame); | |
| 5436 struct buffer *b = XBUFFER (w->buffer); | |
| 5437 int ypos = WINDOW_TEXT_TOP (w); | |
| 5438 int yend; /* set farther down */ | |
| 5439 int yclip = WINDOW_TEXT_TOP_CLIP (w); | |
| 442 | 5440 int force; |
| 2518 | 5441 int depth = -1; |
| 428 | 5442 |
| 5443 prop_block_dynarr *prop; | |
| 5444 layout_bounds bounds; | |
| 5445 display_line_dynarr *dla; | |
| 5446 int need_modeline; | |
| 5447 | |
| 5448 /* The lines had better exist by this point. */ | |
| 5449 if (!(dla = window_display_lines (w, type))) | |
| 2500 | 5450 ABORT (); |
| 2518 | 5451 |
| 5452 if (!in_display) | |
| 5453 depth = enter_redisplay_critical_section (); | |
| 5454 | |
| 5455 /* This is one spot where a re-entrancy crash will occur, due to a check | |
| 5456 in the dynarr to make sure it isn't "locked" */ | |
| 5457 /* | |
| 5458 | |
| 5459 Info on Re-entrancy crashes, with backtraces given: | |
| 5460 | |
| 5461 (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT") | |
| 5462 */ | |
| 5463 | |
| 428 | 5464 Dynarr_reset (dla); |
| 5465 w->max_line_len = 0; | |
| 5466 | |
| 5467 /* Normally these get updated in redisplay_window but it is possible | |
| 5468 for this function to get called from some other points where that | |
| 5469 update may not have occurred. This acts as a safety check. */ | |
| 5470 if (!Dynarr_length (w->face_cachels)) | |
| 5471 reset_face_cachels (w); | |
| 5472 if (!Dynarr_length (w->glyph_cachels)) | |
| 5473 reset_glyph_cachels (w); | |
| 5474 | |
| 5475 Fset_marker (w->start[type], make_int (start_pos), w->buffer); | |
| 5476 Fset_marker (w->pointm[type], make_int (point), w->buffer); | |
| 5477 w->last_point_x[type] = -1; | |
| 5478 w->last_point_y[type] = -1; | |
| 5479 | |
| 5480 /* Make sure a modeline is in the structs if needed. */ | |
| 5481 need_modeline = ensure_modeline_generated (w, type); | |
| 5482 | |
| 5483 /* Wait until here to set this so that the structs have a modeline | |
| 5484 generated in the case where one didn't exist. */ | |
| 5485 yend = WINDOW_TEXT_BOTTOM (w); | |
| 5486 | |
| 5487 bounds = calculate_display_line_boundaries (w, 0); | |
| 5488 | |
| 5489 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */ | |
| 5490 if (MINI_WINDOW_P (w) | |
| 5491 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt)) | |
| 5492 && !echo_area_active (f) | |
| 5493 && start_pos == BUF_BEGV (b)) | |
| 5494 { | |
| 5495 struct prop_block pb; | |
| 5496 Lisp_Object string; | |
| 5497 prop = Dynarr_new (prop_block); | |
| 5498 | |
| 5499 string = concat2(Vminibuf_preprompt, Vminibuf_prompt); | |
| 5500 pb.type = PROP_MINIBUF_PROMPT; | |
| 5501 pb.data.p_string.str = XSTRING_DATA(string); | |
| 5502 pb.data.p_string.len = XSTRING_LENGTH(string); | |
| 5503 Dynarr_add (prop, pb); | |
| 5504 } | |
| 5505 else | |
| 5506 prop = 0; | |
| 5507 | |
| 442 | 5508 /* When we are computing things for scrolling purposes, make |
| 5509 sure at least one line is always generated */ | |
| 5510 force = (type == CMOTION_DISP); | |
| 5511 | |
| 5512 /* Make sure this is set always */ | |
| 5513 /* Note the conversion at end */ | |
| 5514 w->window_end_pos[type] = start_pos; | |
| 5515 while (ypos < yend || force) | |
| 428 | 5516 { |
| 5517 struct display_line dl; | |
| 5518 struct display_line *dlp; | |
| 5519 int local; | |
| 851 | 5520 int pos_of_dlp = -1; |
| 428 | 5521 |
| 5522 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
| 5523 { | |
| 851 | 5524 pos_of_dlp = Dynarr_length (dla); |
| 5525 dlp = Dynarr_atp (dla, pos_of_dlp); | |
| 428 | 5526 local = 0; |
| 5527 } | |
| 5528 else | |
| 5529 { | |
| 4207 | 5530 DISPLAY_LINE_INIT (dl); |
| 428 | 5531 dlp = &dl; |
| 5532 local = 1; | |
| 5533 } | |
| 5534 | |
| 5535 dlp->bounds = bounds; | |
| 5536 dlp->offset = 0; | |
| 1318 | 5537 Dynarr_lock (dla); |
| 428 | 5538 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); |
| 1318 | 5539 Dynarr_unlock (dla); |
| 428 | 5540 |
| 5541 if (yclip > dlp->ascent) | |
| 5542 { | |
| 5543 /* this should never happen, but if it does just display the | |
| 5544 whole line */ | |
| 5545 yclip = 0; | |
| 5546 } | |
| 5547 | |
| 5548 dlp->ypos = (ypos + dlp->ascent) - yclip; | |
| 5549 ypos = dlp->ypos + dlp->descent; | |
| 5550 | |
| 5551 /* See if we've been asked to start midway through a line, for | |
| 4187 | 5552 partial display line scrolling. */ |
| 434 | 5553 if (yclip) |
| 428 | 5554 { |
| 5555 dlp->top_clip = yclip; | |
| 5556 yclip = 0; | |
| 5557 } | |
| 5558 else | |
| 5559 dlp->top_clip = 0; | |
| 5560 | |
| 5561 if (ypos > yend) | |
| 5562 { | |
| 5563 int visible_height = dlp->ascent + dlp->descent; | |
| 5564 | |
| 5565 dlp->clip = (ypos - yend); | |
| 5566 /* Although this seems strange we could have a single very | |
| 5567 tall line visible for which we need to account for both | |
| 5568 the top clip and the bottom clip. */ | |
| 5569 visible_height -= (dlp->clip + dlp->top_clip); | |
| 5570 | |
| 442 | 5571 if (visible_height < VERTICAL_CLIP (w, 1) && !force) |
| 428 | 5572 { |
| 5573 if (local) | |
| 5574 free_display_line (dlp); | |
| 5575 break; | |
| 5576 } | |
| 5577 } | |
| 5578 else | |
| 5579 dlp->clip = 0; | |
| 5580 | |
| 5581 if (dlp->cursor_elt != -1) | |
| 5582 { | |
| 5583 /* #### This check is steaming crap. Have to get things | |
| 4187 | 5584 fixed so when create_text_block hits EOB, we're done, |
| 5585 period. */ | |
| 428 | 5586 if (w->last_point_x[type] == -1) |
| 5587 { | |
| 5588 w->last_point_x[type] = dlp->cursor_elt; | |
| 5589 w->last_point_y[type] = Dynarr_length (dla); | |
| 5590 } | |
| 5591 else | |
| 5592 { | |
| 5593 /* #### This means that we've added a cursor at EOB | |
| 4187 | 5594 twice. Yuck oh yuck. */ |
| 1318 | 5595 struct display_block *db; |
| 5596 | |
| 5597 Dynarr_lock (dla); | |
| 5598 db = get_display_block_from_line (dlp, TEXT); | |
| 5599 Dynarr_unlock (dla); | |
| 428 | 5600 |
| 5601 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR; | |
| 5602 dlp->cursor_elt = -1; | |
| 5603 } | |
| 5604 } | |
| 5605 | |
| 5606 if (dlp->num_chars > w->max_line_len) | |
| 5607 w->max_line_len = dlp->num_chars; | |
| 5608 | |
|
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5609 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
|
5610 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
|
5611 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
|
5612 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
|
5613 else |
|
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5614 ABORT (); |
| 428 | 5615 |
| 5616 /* #### This isn't right, but it is close enough for now. */ | |
| 5617 w->window_end_pos[type] = start_pos; | |
| 5618 | |
| 5619 /* #### This type of check needs to be done down in the | |
| 5620 generate_display_line call. */ | |
| 5621 if (start_pos > BUF_ZV (b)) | |
| 5622 break; | |
| 442 | 5623 |
| 5624 force = 0; | |
| 428 | 5625 } |
| 5626 | |
| 5627 if (prop) | |
| 5628 Dynarr_free (prop); | |
| 5629 | |
| 5630 /* #### More not quite right, but close enough. */ | |
| 442 | 5631 /* Ben sez: apparently window_end_pos[] is measured |
| 428 | 5632 as the number of characters between the window end and the |
| 5633 end of the buffer? This seems rather weirdo. What's | |
| 442 | 5634 the justification for this? |
| 5635 | |
| 5636 JV sez: Because BUF_Z (b) would be a good initial value, however | |
| 5637 that can change. This representation allows initalizing with 0. | |
| 5638 */ | |
| 428 | 5639 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; |
| 5640 | |
| 5641 if (need_modeline) | |
| 5642 { | |
| 5643 /* We know that this is the right thing to use because we put it | |
| 4187 | 5644 there when we first started working in this function. */ |
| 428 | 5645 generate_modeline (w, Dynarr_atp (dla, 0), type); |
| 5646 } | |
| 2518 | 5647 |
| 5648 if (depth >= 0) | |
| 5649 exit_redisplay_critical_section (depth); | |
| 428 | 5650 } |
| 5651 | |
| 826 | 5652 #define REGEN_INC_FIND_START_END \ |
| 5653 do { \ | |
| 5654 /* Determine start and end of lines. */ \ | |
| 5655 if (!Dynarr_length (cdla)) \ | |
| 5656 return 0; \ | |
| 5657 else \ | |
| 5658 { \ | |
| 428 | 5659 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \ |
| 826 | 5660 { \ |
| 5661 dla_start = 1; \ | |
| 5662 } \ | |
| 5663 else if (!Dynarr_atp (cdla, 0)->modeline \ | |
| 5664 && !Dynarr_atp (ddla, 0)->modeline) \ | |
| 5665 { \ | |
| 5666 dla_start = 0; \ | |
| 5667 } \ | |
| 5668 else \ | |
| 2500 | 5669 ABORT (); /* structs differ */ \ |
| 826 | 5670 \ |
| 5671 dla_end = Dynarr_length (cdla) - 1; \ | |
| 5672 } \ | |
| 5673 \ | |
| 5674 start_pos = (Dynarr_atp (cdla, dla_start)->charpos \ | |
| 5675 + Dynarr_atp (cdla, dla_start)->offset); \ | |
| 5676 /* If this isn't true, then startp has changed and we need to do a \ | |
| 5677 full regen. */ \ | |
| 5678 if (startp != start_pos) \ | |
| 5679 return 0; \ | |
| 5680 \ | |
| 5681 /* Point is outside the visible region so give up. */ \ | |
| 5682 if (pointm < start_pos) \ | |
| 5683 return 0; \ | |
| 5684 \ | |
| 428 | 5685 } while (0) |
| 5686 | |
| 5687 /* This attempts to incrementally update the display structures. It | |
| 5688 returns a boolean indicating success or failure. This function is | |
| 5689 very similar to regenerate_window_incrementally and is in fact only | |
| 5690 called from that function. However, because of the nature of the | |
| 5691 changes it deals with it sometimes makes different assumptions | |
| 5692 which can lead to success which are much more difficult to make | |
| 5693 when dealing with buffer changes. */ | |
| 5694 | |
| 5695 static int | |
| 665 | 5696 regenerate_window_extents_only_changed (struct window *w, Charbpos startp, |
| 5697 Charbpos pointm, | |
| 428 | 5698 Charcount beg_unchanged, |
| 5699 Charcount end_unchanged) | |
| 5700 { | |
| 5701 struct buffer *b = XBUFFER (w->buffer); | |
| 5702 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
| 5703 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
| 5704 | |
| 5705 int dla_start = 0; | |
| 5706 int dla_end, line; | |
| 5707 int first_line, last_line; | |
| 665 | 5708 Charbpos start_pos; |
| 428 | 5709 /* Don't define this in the loop where it is used because we |
| 5710 definitely want its value to survive between passes. */ | |
| 5711 prop_block_dynarr *prop = NULL; | |
| 5712 | |
| 5713 /* If we don't have any buffer change recorded but the modiff flag has | |
| 5714 been incremented, then fail. I'm not sure of the exact circumstances | |
| 5715 under which this can happen, but I believe that it is probably a | |
| 5716 reasonable happening. */ | |
| 5717 if (!point_visible (w, pointm, CURRENT_DISP) | |
| 5718 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)) | |
| 5719 return 0; | |
| 5720 | |
| 5721 /* If the cursor is moved we attempt to update it. If we succeed we | |
| 5722 go ahead and proceed with the optimization attempt. */ | |
| 5723 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
| 5724 || pointm != marker_position (w->last_point[CURRENT_DISP])) | |
| 5725 { | |
| 5726 struct frame *f = XFRAME (w->frame); | |
| 5727 struct device *d = XDEVICE (f->device); | |
| 5728 struct frame *sel_f = device_selected_frame (d); | |
| 5729 int success = 0; | |
| 5730 | |
| 5731 if (w->last_point_x[CURRENT_DISP] != -1 | |
| 5732 && w->last_point_y[CURRENT_DISP] != -1) | |
| 5733 { | |
| 5734 | |
| 5735 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w))) | |
| 5736 { | |
| 5737 /* Always regenerate the modeline in case it is | |
| 4187 | 5738 displaying the current line or column. */ |
| 428 | 5739 regenerate_modeline (w); |
| 5740 success = 1; | |
| 5741 } | |
| 5742 } | |
| 5743 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f))) | |
| 5744 { | |
| 5745 if (f->modeline_changed) | |
| 5746 regenerate_modeline (w); | |
| 5747 success = 1; | |
| 5748 } | |
| 5749 | |
| 5750 if (!success) | |
| 5751 return 0; | |
| 5752 } | |
| 5753 | |
| 5754 if (beg_unchanged == -1 && end_unchanged == -1) | |
| 5755 return 1; | |
| 5756 | |
| 5757 /* assert: There are no buffer modifications or they are all below the | |
| 5758 visible region. We assume that regenerate_window_incrementally has | |
| 5759 not called us unless this is true. */ | |
| 5760 | |
| 5761 REGEN_INC_FIND_START_END; | |
| 5762 | |
| 5763 /* If the changed are starts before the visible area, give up. */ | |
| 5764 if (beg_unchanged < startp) | |
| 5765 return 0; | |
| 5766 | |
| 5767 /* Find what display line the extent changes first affect. */ | |
| 5768 line = dla_start; | |
| 5769 while (line <= dla_end) | |
| 5770 { | |
| 5771 struct display_line *dl = Dynarr_atp (cdla, line); | |
| 826 | 5772 Charbpos lstart = dl->charpos + dl->offset; |
| 5773 Charbpos lend = dl->end_charpos + dl->offset; | |
| 428 | 5774 |
| 5775 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
| 5776 break; | |
| 5777 | |
| 5778 line++; | |
| 5779 } | |
| 5780 | |
| 5781 /* If the changes are below the visible area then if point hasn't | |
| 5782 moved return success otherwise fail in order to be safe. */ | |
| 5783 if (line > dla_end) | |
| 5784 { | |
| 5785 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
| 5786 && pointm == marker_position (w->last_point[CURRENT_DISP])) | |
| 5787 return 1; | |
| 5788 else | |
| 5789 return 0; | |
| 5790 } | |
| 5791 | |
| 5792 /* At this point we know what line the changes first affect. We now | |
| 5793 begin redrawing lines as long as we are still in the affected | |
| 5794 region and the line's size and positioning don't change. | |
| 5795 Otherwise we fail. If we fail we will have altered the desired | |
| 5796 structs which could lead to an assertion failure. However, if we | |
| 5797 fail the next thing that is going to happen is a full regen so we | |
| 5798 will actually end up being safe. */ | |
| 5799 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
| 5800 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
| 5801 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
| 5802 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
| 5803 | |
| 5804 first_line = last_line = line; | |
| 5805 while (line <= dla_end) | |
| 5806 { | |
| 2286 | 5807 Charbpos old_start, old_end; |
| 428 | 5808 struct display_line *cdl = Dynarr_atp (cdla, line); |
| 5809 struct display_line *ddl = Dynarr_atp (ddla, line); | |
| 5810 struct display_block *db; | |
| 5811 int initial_size; | |
| 5812 | |
| 826 | 5813 assert (cdl->charpos == ddl->charpos); |
| 5814 assert (cdl->end_charpos == ddl->end_charpos); | |
| 428 | 5815 assert (cdl->offset == ddl->offset); |
| 5816 | |
| 5817 db = get_display_block_from_line (ddl, TEXT); | |
| 5818 initial_size = Dynarr_length (db->runes); | |
| 826 | 5819 old_start = ddl->charpos + ddl->offset; |
| 5820 old_end = ddl->end_charpos + ddl->offset; | |
| 428 | 5821 |
| 5822 /* If this is the first line being updated and it used | |
| 4187 | 5823 propagation data, fail. Otherwise we'll be okay because |
| 5824 we'll have the necessary propagation data. */ | |
| 428 | 5825 if (line == first_line && ddl->used_prop_data) |
| 5826 return 0; | |
| 5827 | |
| 2286 | 5828 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
| 5829 &prop, DESIRED_DISP); | |
| 428 | 5830 ddl->offset = 0; |
| 5831 | |
| 5832 /* #### If there is propagated stuff the fail. We could | |
| 4187 | 5833 probably actually deal with this if the line had propagated |
| 5834 information when originally created by a full | |
| 5835 regeneration. */ | |
| 428 | 5836 if (prop) |
| 5837 { | |
| 5838 Dynarr_free (prop); | |
| 5839 return 0; | |
| 5840 } | |
| 5841 | |
| 5842 /* If any line position parameters have changed or a | |
| 4187 | 5843 cursor has disappeared or disappeared, fail. */ |
| 428 | 5844 db = get_display_block_from_line (ddl, TEXT); |
| 5845 if (cdl->ypos != ddl->ypos | |
| 5846 || cdl->ascent != ddl->ascent | |
| 5847 || cdl->descent != ddl->descent | |
| 5848 || cdl->top_clip != ddl->top_clip | |
| 5849 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
| 5850 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
| 826 | 5851 || old_start != ddl->charpos |
| 5852 || old_end != ddl->end_charpos | |
| 428 | 5853 || initial_size != Dynarr_length (db->runes)) |
| 5854 { | |
| 5855 return 0; | |
| 5856 } | |
| 5857 | |
| 5858 if (ddl->cursor_elt != -1) | |
| 5859 { | |
| 5860 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
| 5861 w->last_point_y[DESIRED_DISP] = line; | |
| 5862 } | |
| 5863 | |
| 5864 last_line = line; | |
| 5865 | |
| 5866 /* If the extent changes end on the line we just updated then | |
| 4187 | 5867 we're done. Otherwise go on to the next line. */ |
| 826 | 5868 if (end_unchanged <= ddl->end_charpos) |
| 428 | 5869 break; |
| 5870 else | |
| 5871 line++; | |
| 5872 } | |
| 5873 | |
| 5874 redisplay_update_line (w, first_line, last_line, 1); | |
| 5875 return 1; | |
| 5876 } | |
| 5877 | |
| 5878 /* Attempt to update the display data structures based on knowledge of | |
| 5879 the changed region in the buffer. Returns a boolean indicating | |
| 5880 success or failure. If this function returns a failure then a | |
| 5881 regenerate_window _must_ be performed next in order to maintain | |
| 5882 invariants located here. */ | |
| 5883 | |
| 5884 static int | |
| 665 | 5885 regenerate_window_incrementally (struct window *w, Charbpos startp, |
| 5886 Charbpos pointm) | |
| 428 | 5887 { |
| 5888 struct buffer *b = XBUFFER (w->buffer); | |
| 5889 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
| 5890 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
| 5891 Charcount beg_unchanged, end_unchanged; | |
| 5892 Charcount extent_beg_unchanged, extent_end_unchanged; | |
| 5893 | |
| 5894 int dla_start = 0; | |
| 5895 int dla_end, line; | |
| 665 | 5896 Charbpos start_pos; |
| 428 | 5897 |
| 5898 /* If this function is called, the current and desired structures | |
| 5899 had better be identical. If they are not, then that is a bug. */ | |
| 5900 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
| 5901 | |
| 5902 /* We don't handle minibuffer windows yet. The minibuffer prompt | |
| 5903 screws us up. */ | |
| 5904 if (MINI_WINDOW_P (w)) | |
| 5905 return 0; | |
| 5906 | |
| 5907 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b); | |
| 5908 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1 | |
| 5909 ? -1 | |
| 5910 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b)); | |
| 5911 | |
| 5912 /* If nothing has changed in the buffer, then make sure point is ok | |
| 5913 and succeed. */ | |
| 5914 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1) | |
| 5915 return regenerate_window_extents_only_changed (w, startp, pointm, | |
| 5916 extent_beg_unchanged, | |
| 5917 extent_end_unchanged); | |
| 5918 | |
| 5919 /* We can't deal with deleted newlines. */ | |
| 5920 if (BUF_NEWLINE_WAS_DELETED (b)) | |
| 5921 return 0; | |
| 5922 | |
| 5923 beg_unchanged = BUF_BEGIN_UNCHANGED (b); | |
| 5924 end_unchanged = (BUF_END_UNCHANGED (b) == -1 | |
| 5925 ? -1 | |
| 5926 : BUF_Z (b) - BUF_END_UNCHANGED (b)); | |
| 5927 | |
| 5928 REGEN_INC_FIND_START_END; | |
| 5929 | |
| 5930 /* If the changed area starts before the visible area, give up. */ | |
| 5931 if (beg_unchanged < startp) | |
| 5932 return 0; | |
| 5933 | |
| 5934 /* Find what display line the buffer changes first affect. */ | |
| 5935 line = dla_start; | |
| 5936 while (line <= dla_end) | |
| 5937 { | |
| 5938 struct display_line *dl = Dynarr_atp (cdla, line); | |
| 826 | 5939 Charbpos lstart = dl->charpos + dl->offset; |
| 5940 Charbpos lend = dl->end_charpos + dl->offset; | |
| 428 | 5941 |
| 5942 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
| 5943 break; | |
| 5944 | |
| 5945 line++; | |
| 5946 } | |
| 5947 | |
| 5948 /* If the changes are below the visible area then if point hasn't | |
| 5949 moved return success otherwise fail in order to be safe. */ | |
| 5950 if (line > dla_end) | |
| 5951 return regenerate_window_extents_only_changed (w, startp, pointm, | |
| 5952 extent_beg_unchanged, | |
| 5953 extent_end_unchanged); | |
| 5954 else | |
| 5955 /* At this point we know what line the changes first affect. We | |
| 5956 now redraw that line. If the changes are contained within it | |
| 5957 we are going to succeed and can update just that one line. | |
| 5958 Otherwise we fail. If we fail we will have altered the desired | |
| 5959 structs which could lead to an assertion failure. However, if | |
| 5960 we fail the next thing that is going to happen is a full regen | |
| 5961 so we will actually end up being safe. */ | |
| 5962 { | |
| 5963 prop_block_dynarr *prop = NULL; | |
| 5964 struct display_line *cdl = Dynarr_atp (cdla, line); | |
| 5965 struct display_line *ddl = Dynarr_atp (ddla, line); | |
| 5966 | |
| 826 | 5967 assert (cdl->charpos == ddl->charpos); |
| 5968 assert (cdl->end_charpos == ddl->end_charpos); | |
| 428 | 5969 assert (cdl->offset == ddl->offset); |
| 5970 | |
| 442 | 5971 /* If the line continues to next display line, fail. */ |
| 5972 if (ddl->line_continuation) | |
| 5973 return 0; | |
| 428 | 5974 |
| 5975 /* If the line was generated using propagation data, fail. */ | |
| 5976 if (ddl->used_prop_data) | |
| 5977 return 0; | |
| 5978 | |
| 2286 | 5979 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
| 5980 &prop, DESIRED_DISP); | |
| 428 | 5981 ddl->offset = 0; |
| 5982 | |
| 5983 /* If there is propagated stuff then it is pretty much a | |
| 4187 | 5984 guarantee that more than just the one line is affected. */ |
| 428 | 5985 if (prop) |
| 5986 { | |
| 5987 Dynarr_free (prop); | |
| 5988 return 0; | |
| 5989 } | |
| 5990 | |
| 442 | 5991 /* If the line continues to next display line, fail. */ |
| 5992 if (ddl->line_continuation) | |
| 5993 return 0; | |
| 428 | 5994 |
| 5995 /* If any line position parameters have changed or a | |
| 4187 | 5996 cursor has disappeared or disappeared, fail. */ |
| 428 | 5997 if (cdl->ypos != ddl->ypos |
| 5998 || cdl->ascent != ddl->ascent | |
| 5999 || cdl->descent != ddl->descent | |
| 6000 || cdl->top_clip != ddl->top_clip | |
| 6001 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
| 6002 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) | |
| 6003 { | |
| 6004 return 0; | |
| 6005 } | |
| 6006 | |
| 6007 /* If the changed area also ends on this line, then we may be in | |
| 4187 | 6008 business. Update everything and return success. */ |
| 826 | 6009 if (end_unchanged >= ddl->charpos && end_unchanged <= ddl->end_charpos) |
| 428 | 6010 { |
| 6011 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
| 6012 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
| 6013 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), | |
| 6014 w->buffer); | |
| 6015 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), | |
| 6016 w->buffer); | |
| 6017 | |
| 6018 if (ddl->cursor_elt != -1) | |
| 6019 { | |
| 6020 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
| 6021 w->last_point_y[DESIRED_DISP] = line; | |
| 6022 } | |
| 6023 | |
| 6024 redisplay_update_line (w, line, line, 1); | |
| 6025 regenerate_modeline (w); | |
| 6026 | |
| 6027 /* #### For now we just flush the cache until this has been | |
| 4187 | 6028 tested. After that is done, this should correct the |
| 6029 cache directly. */ | |
| 428 | 6030 Dynarr_reset (w->line_start_cache); |
| 6031 | |
| 6032 /* Adjust the extent changed boundaries to remove any | |
| 4187 | 6033 overlap with the buffer changes since we've just |
| 6034 successfully updated that area. */ | |
| 428 | 6035 if (extent_beg_unchanged != -1 |
| 6036 && extent_beg_unchanged >= beg_unchanged | |
| 6037 && extent_beg_unchanged < end_unchanged) | |
| 6038 extent_beg_unchanged = end_unchanged; | |
| 6039 | |
| 6040 if (extent_end_unchanged != -1 | |
| 6041 && extent_end_unchanged >= beg_unchanged | |
| 6042 && extent_end_unchanged < end_unchanged) | |
| 6043 extent_end_unchanged = beg_unchanged - 1; | |
| 6044 | |
| 6045 if (extent_end_unchanged <= extent_beg_unchanged) | |
| 6046 extent_beg_unchanged = extent_end_unchanged = -1; | |
| 6047 | |
| 6048 /* This could lead to odd results if it fails, but since the | |
| 4187 | 6049 buffer changes update succeeded this probably will to. |
| 6050 We already know that the extent changes start at or after | |
| 6051 the line because we checked before entering the loop. */ | |
| 428 | 6052 if (extent_beg_unchanged != -1 |
| 6053 && extent_end_unchanged != -1 | |
| 826 | 6054 && ((extent_beg_unchanged < ddl->charpos) |
| 6055 || (extent_end_unchanged > ddl->end_charpos))) | |
| 428 | 6056 return regenerate_window_extents_only_changed (w, startp, pointm, |
| 6057 extent_beg_unchanged, | |
| 6058 extent_end_unchanged); | |
| 6059 else | |
| 6060 return 1; | |
| 6061 } | |
| 6062 } | |
| 6063 | |
| 6064 /* Oh, well. */ | |
| 6065 return 0; | |
| 6066 } | |
| 6067 | |
| 6068 /* Given a window and a point, update the given display lines such | |
| 6069 that point is displayed in the middle of the window. | |
| 6070 Return the window's new start position. */ | |
| 6071 | |
| 665 | 6072 static Charbpos |
| 6073 regenerate_window_point_center (struct window *w, Charbpos point, int type) | |
| 428 | 6074 { |
| 665 | 6075 Charbpos startp; |
| 428 | 6076 |
| 6077 /* We need to make sure that the modeline is generated so that the | |
| 6078 window height can be calculated correctly. */ | |
| 6079 ensure_modeline_generated (w, type); | |
| 6080 | |
| 6081 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w)); | |
| 6082 regenerate_window (w, startp, point, type); | |
| 6083 Fset_marker (w->start[type], make_int (startp), w->buffer); | |
| 6084 | |
| 6085 return startp; | |
| 6086 } | |
| 6087 | |
| 6088 /* Given a window and a set of display lines, return a boolean | |
| 6089 indicating whether the given point is contained within. */ | |
| 6090 | |
| 6091 static int | |
| 665 | 6092 point_visible (struct window *w, Charbpos point, int type) |
| 428 | 6093 { |
| 6094 struct buffer *b = XBUFFER (w->buffer); | |
| 6095 display_line_dynarr *dla = window_display_lines (w, type); | |
| 6096 int first_line; | |
| 6097 | |
| 6098 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline) | |
| 6099 first_line = 1; | |
| 6100 else | |
| 6101 first_line = 0; | |
| 6102 | |
| 6103 if (Dynarr_length (dla) > first_line) | |
| 6104 { | |
| 665 | 6105 Charbpos start, end; |
| 428 | 6106 struct display_line *dl = Dynarr_atp (dla, first_line); |
| 6107 | |
| 826 | 6108 start = dl->charpos; |
| 428 | 6109 end = BUF_Z (b) - w->window_end_pos[type] - 1; |
| 6110 | |
| 6111 if (point >= start && point <= end) | |
| 6112 { | |
| 6113 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines) | |
| 6114 { | |
| 6115 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1); | |
| 6116 | |
| 826 | 6117 if (point >= (dl->charpos + dl->offset) |
| 6118 && point <= (dl->end_charpos + dl->offset)) | |
| 428 | 6119 return !dl->clip; |
| 6120 else | |
| 6121 return 1; | |
| 6122 } | |
| 6123 else | |
| 6124 return 1; | |
| 6125 } | |
| 6126 else | |
| 6127 return 0; | |
| 6128 } | |
| 6129 else | |
| 6130 return 0; | |
| 6131 } | |
| 6132 | |
| 6133 /* Return pixel position the middle of the window, not including the | |
| 6134 modeline and any potential horizontal scrollbar. */ | |
| 6135 | |
| 6136 int | |
| 6137 window_half_pixpos (struct window *w) | |
| 6138 { | |
| 6139 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1); | |
| 6140 } | |
| 6141 | |
| 6142 /* Return the display line which is currently in the middle of the | |
| 6143 window W for display lines TYPE. */ | |
| 6144 | |
| 6145 int | |
| 665 | 6146 line_at_center (struct window *w, int type, Charbpos start, Charbpos point) |
| 428 | 6147 { |
| 6148 display_line_dynarr *dla; | |
| 6149 int half; | |
| 6150 int elt; | |
| 6151 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1); | |
| 6152 | |
| 6153 if (type == CMOTION_DISP) | |
| 6154 regenerate_window (w, start, point, type); | |
| 6155 | |
| 6156 dla = window_display_lines (w, type); | |
| 6157 half = window_half_pixpos (w); | |
| 6158 | |
| 6159 for (elt = first_elt; elt < Dynarr_length (dla); elt++) | |
| 6160 { | |
| 6161 struct display_line *dl = Dynarr_atp (dla, elt); | |
| 6162 int line_bot = dl->ypos + dl->descent; | |
| 6163 | |
| 6164 if (line_bot > half) | |
| 6165 return elt; | |
| 6166 } | |
| 6167 | |
| 6168 /* We may not have a line at the middle if the end of the buffer is | |
| 6169 being displayed. */ | |
| 6170 return -1; | |
| 6171 } | |
| 6172 | |
| 6173 /* Return a value for point that would place it at the beginning of | |
| 6174 the line which is in the middle of the window. */ | |
| 6175 | |
| 665 | 6176 Charbpos |
| 6177 point_at_center (struct window *w, int type, Charbpos start, Charbpos point) | |
| 428 | 6178 { |
| 6179 /* line_at_center will regenerate the display structures, if necessary. */ | |
| 6180 int line = line_at_center (w, type, start, point); | |
| 6181 | |
| 6182 if (line == -1) | |
| 6183 return BUF_ZV (XBUFFER (w->buffer)); | |
| 6184 else | |
| 6185 { | |
| 6186 display_line_dynarr *dla = window_display_lines (w, type); | |
| 6187 struct display_line *dl = Dynarr_atp (dla, line); | |
| 6188 | |
| 826 | 6189 return dl->charpos; |
| 428 | 6190 } |
| 6191 } | |
| 6192 | |
| 6193 /* For a given window, ensure that the current visual representation | |
| 6194 is accurate. */ | |
| 6195 | |
| 6196 static void | |
| 6197 redisplay_window (Lisp_Object window, int skip_selected) | |
| 6198 { | |
| 6199 struct window *w = XWINDOW (window); | |
| 6200 struct frame *f = XFRAME (w->frame); | |
| 6201 struct device *d = XDEVICE (f->device); | |
| 6202 Lisp_Object old_buffer = w->buffer; | |
| 6203 Lisp_Object the_buffer = w->buffer; | |
| 6204 struct buffer *b; | |
| 6205 int echo_active = 0; | |
| 6206 int startp = 1; | |
| 6207 int pointm; | |
| 6208 int old_startp = 1; | |
| 6209 int old_pointm = 1; | |
| 6210 int selected_in_its_frame; | |
| 6211 int selected_globally; | |
| 6212 int skip_output = 0; | |
| 6213 int truncation_changed; | |
| 6214 int inactive_minibuffer = | |
| 6215 (MINI_WINDOW_P (w) && | |
| 6216 (f != device_selected_frame (d)) && | |
| 6217 !is_surrogate_for_selected_frame (f)); | |
| 6218 | |
| 6219 /* #### In the new world this function actually does a bunch of | |
| 6220 optimizations such as buffer-based scrolling, but none of that is | |
| 6221 implemented yet. */ | |
| 6222 | |
| 6223 /* If this is a combination window, do its children; that's all. | |
| 6224 The selected window is always a leaf so we don't check for | |
| 6225 skip_selected here. */ | |
| 6226 if (!NILP (w->vchild)) | |
| 6227 { | |
| 6228 redisplay_windows (w->vchild, skip_selected); | |
| 6229 return; | |
| 6230 } | |
| 6231 if (!NILP (w->hchild)) | |
| 6232 { | |
| 6233 redisplay_windows (w->hchild, skip_selected); | |
| 6234 return; | |
| 6235 } | |
| 6236 | |
| 6237 /* Is this window the selected window on its frame? */ | |
| 6238 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f))); | |
| 6239 selected_globally = | |
| 6240 selected_in_its_frame && | |
| 6241 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
| 6242 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d && | |
| 6243 XFRAME(DEVICE_SELECTED_FRAME(d)) == f; | |
| 6244 if (skip_selected && selected_in_its_frame) | |
| 6245 return; | |
| 6246 | |
| 6247 /* It is possible that the window is not fully initialized yet. */ | |
| 6248 if (NILP (w->buffer)) | |
| 6249 return; | |
| 6250 | |
| 6251 if (MINI_WINDOW_P (w) && echo_area_active (f)) | |
| 6252 { | |
| 6253 w->buffer = the_buffer = Vecho_area_buffer; | |
| 6254 echo_active = 1; | |
| 6255 } | |
| 6256 | |
| 6257 b = XBUFFER (w->buffer); | |
| 6258 | |
| 6259 if (echo_active) | |
| 6260 { | |
| 6261 old_pointm = selected_globally | |
| 4187 | 6262 ? BUF_PT (b) |
| 6263 : marker_position (w->pointm[CURRENT_DISP]); | |
| 428 | 6264 pointm = 1; |
| 6265 } | |
| 6266 else | |
| 6267 { | |
| 6268 if (selected_globally) | |
| 6269 { | |
| 6270 pointm = BUF_PT (b); | |
| 6271 } | |
| 6272 else | |
| 6273 { | |
| 6274 pointm = marker_position (w->pointm[CURRENT_DISP]); | |
| 6275 | |
| 6276 if (pointm < BUF_BEGV (b)) | |
| 6277 pointm = BUF_BEGV (b); | |
| 6278 else if (pointm > BUF_ZV (b)) | |
| 6279 pointm = BUF_ZV (b); | |
| 6280 } | |
| 6281 } | |
| 6282 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); | |
| 6283 | |
| 6284 /* If the buffer has changed we have to invalidate all of our face | |
| 6285 cache elements. */ | |
| 6286 if ((!echo_active && b != window_display_buffer (w)) | |
| 6287 || !Dynarr_length (w->face_cachels) | |
| 6288 || f->faces_changed) | |
| 6289 reset_face_cachels (w); | |
| 6290 else | |
| 6291 mark_face_cachels_as_not_updated (w); | |
| 6292 | |
| 6293 /* Ditto the glyph cache elements, although we do *not* invalidate | |
| 6294 the cache purely because glyphs have changed - this is now | |
| 6295 handled by the dirty flag.*/ | |
| 6296 if ((!echo_active && b != window_display_buffer (w)) | |
| 440 | 6297 || !Dynarr_length (w->glyph_cachels) || f->faces_changed) |
| 428 | 6298 reset_glyph_cachels (w); |
| 6299 else | |
| 6300 mark_glyph_cachels_as_not_updated (w); | |
| 6301 | |
| 6302 /* If the marker's buffer is not the window's buffer, then we need | |
| 6303 to find a new starting position. */ | |
| 6304 if (!MINI_WINDOW_P (w) | |
| 6305 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer)) | |
| 6306 { | |
| 6307 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
| 6308 | |
| 6309 goto regeneration_done; | |
| 6310 } | |
| 6311 | |
| 6312 if (echo_active) | |
| 6313 { | |
| 6314 old_startp = marker_position (w->start[CURRENT_DISP]); | |
| 6315 startp = 1; | |
| 6316 } | |
| 6317 else | |
| 6318 { | |
| 6319 startp = marker_position (w->start[CURRENT_DISP]); | |
| 6320 if (startp < BUF_BEGV (b)) | |
| 6321 startp = BUF_BEGV (b); | |
| 6322 else if (startp > BUF_ZV (b)) | |
| 6323 startp = BUF_ZV (b); | |
| 6324 } | |
| 6325 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer); | |
| 6326 | |
| 6327 truncation_changed = (find_window_mirror (w)->truncate_win != | |
| 647 | 6328 (unsigned int) window_truncation_on (w)); |
| 428 | 6329 |
| 6330 /* If w->force_start is set, then some function set w->start and we | |
| 6331 should display from there and change point, if necessary, to | |
| 6332 ensure that it is visible. */ | |
| 6333 if (w->force_start || inactive_minibuffer) | |
| 6334 { | |
| 6335 w->force_start = 0; | |
| 6336 w->last_modified[DESIRED_DISP] = Qzero; | |
| 6337 w->last_facechange[DESIRED_DISP] = Qzero; | |
| 6338 | |
| 6339 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
| 6340 | |
| 6341 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer) | |
| 6342 { | |
| 6343 pointm = point_at_center (w, DESIRED_DISP, 0, 0); | |
| 6344 | |
| 6345 if (selected_globally) | |
| 6346 BUF_SET_PT (b, pointm); | |
| 6347 | |
| 6348 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), | |
| 6349 the_buffer); | |
| 6350 | |
| 6351 /* #### BUFU amounts of overkill just to get the cursor | |
| 4187 | 6352 location marked properly. FIX ME FIX ME FIX ME */ |
| 428 | 6353 regenerate_window (w, startp, pointm, DESIRED_DISP); |
| 6354 } | |
| 6355 | |
| 6356 goto regeneration_done; | |
| 6357 } | |
| 6358 | |
| 6359 /* If nothing has changed since the last redisplay, then we just | |
| 6360 need to make sure that point is still visible. */ | |
| 6361 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) | |
| 6362 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b) | |
| 6363 && pointm >= startp | |
| 6364 /* This check is to make sure we restore the minibuffer after a | |
| 4187 | 6365 temporary change to the echo area. */ |
| 428 | 6366 && !(MINI_WINDOW_P (w) && f->buffers_changed) |
| 6367 && !f->frame_changed | |
| 6368 && !truncation_changed | |
| 442 | 6369 /* check whether start is really at the beginning of a line GE */ |
| 428 | 6370 && (!w->start_at_line_beg || beginning_of_line_p (b, startp)) |
| 6371 ) | |
| 6372 { | |
| 6373 /* Check if the cursor has actually moved. */ | |
| 6374 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
| 6375 && pointm == marker_position (w->last_point[CURRENT_DISP]) | |
| 6376 && selected_globally | |
| 6377 && !w->windows_changed | |
| 6378 && !f->clip_changed | |
| 6379 && !f->extents_changed | |
| 6380 && !f->faces_changed | |
| 6381 && !f->glyphs_changed | |
| 6382 && !f->subwindows_changed | |
| 442 | 6383 /* && !f->subwindows_state_changed*/ |
| 428 | 6384 && !f->point_changed |
| 6385 && !f->windows_structure_changed) | |
| 6386 { | |
| 6387 /* If not, we're done. */ | |
| 6388 if (f->modeline_changed) | |
| 6389 regenerate_modeline (w); | |
| 6390 | |
| 6391 skip_output = 1; | |
| 6392 goto regeneration_done; | |
| 6393 } | |
| 6394 else | |
| 6395 { | |
| 6396 /* If the new point is visible in the redisplay structures, | |
| 4187 | 6397 then let the output update routines handle it, otherwise |
| 6398 do things the hard way. */ | |
| 428 | 6399 if (!w->windows_changed |
| 6400 && !f->clip_changed | |
| 6401 && !f->extents_changed | |
| 6402 && !f->faces_changed | |
| 6403 && !f->glyphs_changed | |
| 6404 && !f->subwindows_changed | |
| 442 | 6405 /* && !f->subwindows_state_changed*/ |
| 428 | 6406 && !f->windows_structure_changed) |
| 6407 { | |
| 6408 if (point_visible (w, pointm, CURRENT_DISP) | |
| 6409 && w->last_point_x[CURRENT_DISP] != -1 | |
| 6410 && w->last_point_y[CURRENT_DISP] != -1) | |
| 6411 { | |
| 6412 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f))) | |
| 6413 { | |
| 6414 /* Always regenerate in case it is displaying | |
| 4187 | 6415 the current line or column. */ |
| 428 | 6416 regenerate_modeline (w); |
| 6417 | |
| 6418 skip_output = 1; | |
| 6419 goto regeneration_done; | |
| 6420 } | |
| 6421 } | |
| 6422 else if (!selected_in_its_frame && !f->point_changed) | |
| 6423 { | |
| 6424 if (f->modeline_changed) | |
| 6425 regenerate_modeline (w); | |
| 6426 | |
| 6427 skip_output = 1; | |
| 6428 goto regeneration_done; | |
| 6429 } | |
| 6430 } | |
| 6431 | |
| 6432 /* If we weren't able to take the shortcut method, then use | |
| 4187 | 6433 the brute force method. */ |
| 428 | 6434 regenerate_window (w, startp, pointm, DESIRED_DISP); |
| 6435 | |
| 6436 if (point_visible (w, pointm, DESIRED_DISP)) | |
| 6437 goto regeneration_done; | |
| 6438 } | |
| 6439 } | |
| 6440 | |
| 6441 /* Check if the starting point is no longer at the beginning of a | |
| 6442 line, in which case find a new starting point. We also recenter | |
| 6443 if our start position is equal to point-max. Otherwise we'll end | |
| 6444 up with a blank window. */ | |
| 6445 else if (((w->start_at_line_beg || MINI_WINDOW_P (w)) | |
| 6446 && !(startp == BUF_BEGV (b) | |
| 6447 || BUF_FETCH_CHAR (b, startp - 1) == '\n')) | |
| 6448 || (pointm == startp && | |
| 6449 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) && | |
| 6450 startp < marker_position (w->last_start[CURRENT_DISP])) | |
| 6451 || (startp == BUF_ZV (b))) | |
| 6452 { | |
| 6453 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
| 6454 | |
| 6455 goto regeneration_done; | |
| 6456 } | |
| 6457 /* See if we can update the data structures locally based on | |
| 6458 knowledge of what changed in the buffer. */ | |
| 6459 else if (!w->windows_changed | |
| 6460 && !f->clip_changed | |
| 6461 && !f->faces_changed | |
| 6462 && !f->glyphs_changed | |
| 6463 && !f->subwindows_changed | |
| 442 | 6464 /* && !f->subwindows_state_changed*/ |
| 428 | 6465 && !f->windows_structure_changed |
| 6466 && !f->frame_changed | |
| 6467 && !truncation_changed | |
| 6468 && pointm >= startp | |
| 6469 && regenerate_window_incrementally (w, startp, pointm)) | |
| 6470 { | |
| 6471 if (f->modeline_changed | |
| 6472 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b) | |
| 6473 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b)) | |
| 6474 regenerate_modeline (w); | |
| 6475 | |
| 6476 skip_output = 1; | |
| 6477 goto regeneration_done; | |
| 6478 } | |
| 6479 /* #### This is where a check for structure based scrolling would go. */ | |
| 6480 /* If all else fails, try just regenerating and see what happens. */ | |
| 6481 else | |
| 6482 { | |
| 6483 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
| 6484 | |
| 6485 if (point_visible (w, pointm, DESIRED_DISP)) | |
| 6486 goto regeneration_done; | |
| 6487 } | |
| 6488 | |
| 6489 /* We still haven't gotten the window regenerated with point | |
| 6490 visible. Next we try scrolling a little and see if point comes | |
| 6491 back onto the screen. */ | |
| 6492 if (scroll_step > 0) | |
| 6493 { | |
| 6494 int scrolled = scroll_conservatively; | |
| 6495 for (; scrolled >= 0; scrolled -= scroll_step) | |
| 6496 { | |
| 6497 startp = vmotion (w, startp, | |
| 6498 (pointm < startp) ? -scroll_step : scroll_step, 0); | |
| 6499 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
| 6500 | |
| 6501 if (point_visible (w, pointm, DESIRED_DISP)) | |
| 6502 goto regeneration_done; | |
| 6503 } | |
| 6504 } | |
| 6505 | |
| 6506 /* We still haven't managed to get the screen drawn with point on | |
| 6507 the screen, so just center it and be done with it. */ | |
| 6508 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
| 6509 | |
| 6510 | |
| 6511 regeneration_done: | |
| 6512 | |
| 6513 /* If the window's frame is changed then reset the current display | |
| 6514 lines in order to force a full repaint. */ | |
| 6515 if (f->frame_changed) | |
| 6516 { | |
| 6517 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
| 6518 | |
| 6519 Dynarr_reset (cla); | |
| 6520 } | |
| 6521 | |
| 6522 /* Must do this before calling redisplay_output_window because it | |
| 6523 sets some markers on the window. */ | |
| 6524 if (echo_active) | |
| 6525 { | |
| 6526 w->buffer = old_buffer; | |
| 6527 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer); | |
| 6528 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer); | |
| 6529 } | |
| 6530 | |
| 6531 /* These also have to be set before calling redisplay_output_window | |
| 6532 since it sets the CURRENT_DISP values based on them. */ | |
| 6533 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
| 6534 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
| 6535 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
| 6536 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
| 6537 | |
| 6538 if (!skip_output) | |
| 6539 { | |
| 665 | 6540 Charbpos start = marker_position (w->start[DESIRED_DISP]); |
| 6541 Charbpos end = (w->window_end_pos[DESIRED_DISP] == -1 | |
| 428 | 6542 ? BUF_ZV (b) |
| 6543 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1); | |
| 6544 /* Don't pollute the cache if not sure if we are correct */ | |
| 6545 if (w->start_at_line_beg) | |
| 6546 update_line_start_cache (w, start, end, pointm, 1); | |
| 6547 redisplay_output_window (w); | |
| 6548 /* | |
| 6549 * If we just displayed the echo area, the line start cache is | |
| 6550 * no longer valid, because the minibuffer window is associated | |
| 6551 * with the window now. | |
| 6552 */ | |
| 6553 if (echo_active) | |
| 6554 w->line_cache_last_updated = make_int (-1); | |
| 6555 } | |
| 6556 | |
| 6557 /* #### This should be dependent on face changes and will need to be | |
| 6558 somewhere else once tty updates occur on a per-frame basis. */ | |
| 6559 mark_face_cachels_as_clean (w); | |
| 6560 | |
| 438 | 6561 /* The glyph cachels only get dirty if someone changed something. |
| 6562 Since redisplay has now effectively ended we can reset the dirty | |
| 6563 flag since everything must be up-to-date. */ | |
| 428 | 6564 if (glyphs_changed) |
| 6565 mark_glyph_cachels_as_clean (w); | |
| 6566 | |
| 6567 w->windows_changed = 0; | |
| 6568 } | |
| 6569 | |
| 6570 /* Call buffer_reset_changes for all buffers present in any window | |
| 6571 currently visible in all frames on all devices. #### There has to | |
| 6572 be a better way to do this. */ | |
| 6573 | |
| 6574 static int | |
| 2286 | 6575 reset_buffer_changes_mapfun (struct window *w, void *UNUSED (closure)) |
| 428 | 6576 { |
| 6577 buffer_reset_changes (XBUFFER (w->buffer)); | |
| 6578 return 0; | |
| 6579 } | |
| 6580 | |
| 6581 static void | |
| 6582 reset_buffer_changes (void) | |
| 6583 { | |
| 6584 Lisp_Object frmcons, devcons, concons; | |
| 6585 | |
| 6586 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
| 6587 { | |
| 6588 struct frame *f = XFRAME (XCAR (frmcons)); | |
| 6589 | |
| 6590 if (FRAME_REPAINT_P (f)) | |
| 6591 map_windows (f, reset_buffer_changes_mapfun, 0); | |
| 6592 } | |
| 6593 } | |
| 6594 | |
| 6595 /* Ensure that all windows underneath the given window in the window | |
| 6596 hierarchy are correctly displayed. */ | |
| 6597 | |
| 6598 static void | |
| 6599 redisplay_windows (Lisp_Object window, int skip_selected) | |
| 6600 { | |
| 6601 for (; !NILP (window) ; window = XWINDOW (window)->next) | |
| 6602 { | |
| 6603 redisplay_window (window, skip_selected); | |
| 6604 } | |
| 6605 } | |
| 6606 | |
| 1318 | 6607 /* Register an action to be called at the end of redisplay. |
| 6608 in_display is 0 when this is called. | |
| 6609 This is used when it is discovered that an action needs to be taken, | |
| 6610 but it's during redisplay, so it's not safe. (Typically, it's an action | |
| 6611 that needs to enter redisplay, which can't happen reentrantly.) | |
| 6612 | |
| 6613 NEVER signal an error in these functions. | |
| 6614 */ | |
| 6615 | |
| 6616 void | |
| 6617 register_post_redisplay_action (void (*fun) (Lisp_Object), Lisp_Object arg) | |
| 6618 { | |
| 6619 Vpost_redisplay_actions = nconc2 (Vpost_redisplay_actions, | |
| 6620 list1 (Fcons (make_opaque_ptr | |
| 6621 ((void *) fun), arg))); | |
| 6622 } | |
| 6623 | |
| 1320 | 6624 static int running_post_redisplay_actions; |
| 6625 | |
| 1318 | 6626 static void |
| 6627 run_post_redisplay_actions (void) | |
| 6628 { | |
| 1320 | 6629 int depth; |
| 6630 | |
| 6631 if (running_post_redisplay_actions) | |
| 6632 return; | |
| 6633 | |
| 6634 depth = internal_bind_int (&running_post_redisplay_actions, 1); | |
| 6635 /* If the function pushes further actions, they will be tacked onto | |
| 6636 the end of the list, and we'll run them when we're done with the | |
| 6637 current ones. */ | |
| 1318 | 6638 while (!NILP (Vpost_redisplay_actions)) |
| 6639 { | |
| 6640 Lisp_Object car = XCAR (Vpost_redisplay_actions); | |
| 6641 void (*fun) (Lisp_Object) = | |
| 6642 (void (*)(Lisp_Object)) get_opaque_ptr (XCAR (car)); | |
| 6643 (*fun) (XCDR (car)); | |
| 6644 free_opaque_ptr (XCAR (car)); | |
| 6645 free_cons (car); | |
| 6646 Vpost_redisplay_actions = XCDR (Vpost_redisplay_actions); | |
| 6647 } | |
| 1320 | 6648 unbind_to (depth); |
| 1318 | 6649 } |
| 6650 | |
| 6651 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
| 6652 | |
| 6653 static Lisp_Object | |
| 2286 | 6654 commit_ritual_suicide (Lisp_Object UNUSED (ceci_nest_pas_une_pipe)) |
| 1318 | 6655 { |
| 6656 assert (!in_display); | |
| 6657 return Qnil; | |
| 6658 } | |
| 6659 | |
| 6660 #endif | |
| 6661 | |
| 6662 /* Within the guts of redisplay, we are defenseless and cannot allow any of | |
| 6663 the following to happen: | |
| 6664 | |
| 6665 1) garbage collection | |
| 6666 2) QUIT | |
| 6667 3) any non-local exits | |
| 6668 4) frame size changes | |
| 6669 5) deletion of any buffers, windows, frames, etc. | |
| 6670 6) modification of buffer text | |
| 6671 7) reentrant entry of redisplay (see the stack trace above | |
| 6672 generate_displayable_area()) | |
| 6673 | |
| 6674 The general reason is that the redisplay code is written to assume that | |
| 6675 it is the only code running, and thus (a) cannot tolerate structures | |
| 6676 changed out from under it (hence 1, 4, 5, 6, 7) and (b) at various points | |
| 6677 within redisplay the redisplay structures may be in an inconsistent | |
| 6678 state and there are no unwind-protects to clean the structures up in | |
| 6679 case of non-local exit (hence 2, 3). Fixing redisplay to address these | |
| 6680 issues is hard and perhaps not worth it (and might slow things down a | |
| 6681 fair amount). We address 1, 4, 5 and 6 ourselves inside of | |
| 6682 enter_redisplay_critical_section() by simply inhibiting them, but we | |
| 6683 cannot handle 2 and 3, which must be handled at the actual point where | |
| 6684 they may occur (especially, internal_equal() or any place that may call | |
| 6685 Lisp), by wrapping the code in call_trapping_problems() or | |
| 6686 call_with_suspended_errors(). [[ NOTE: We could address QUIT by inhibiting | |
| 6687 it but this would be anti-social because it would prevent the user from | |
| 6688 interrupting any Lisp code called within the critical section. With the | |
| 6689 call_*() wrapping, C-g will interrupt the Lisp code and throw back to | |
| 6690 the innermost wrapping. ]] In fact we do turn off QUIT handling, since | |
| 6691 it's just too dangerous otherwise. See below. | |
| 6692 | |
| 6693 Code calling enter_redisplay_critical_section() must check for reentrancy | |
| 6694 (#7) and take appropriate corrective action. | |
| 6695 | |
| 6696 To help debug potential problems, we arrange (when | |
| 6697 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every time | |
| 6698 we execute QUIT or call Lisp code unless proper wrapping is in place, as | |
| 6699 well as further checks when we actually Fsignal(), Fthrow(), | |
| 6700 garbage_collect_1(). | |
| 6701 | |
| 6702 #### If a frame-size change does occur we should probably actually be | |
| 6703 preempting redisplay. */ | |
| 6704 | |
| 6705 /* Count of number of recursive times we call | |
| 6706 enter_redisplay_critical_section() or | |
| 6707 enter_redisplay_critical_section_maybe(). | |
| 6708 enter_redisplay_critical_section() cannot occur reentrantly but we have | |
| 6709 to know in the *maybe() version whether to exit the section when we're | |
| 6710 done. */ | |
| 6711 static int in_display_nesting; | |
| 6712 | |
| 6713 static Lisp_Object | |
| 2286 | 6714 end_hold_frame_size_changes (Lisp_Object UNUSED (obj)) |
| 1318 | 6715 { |
| 6716 if (!hold_frame_size_changes) | |
| 6717 { | |
| 6718 /* we used to have a function to do this for only one frame, and | |
| 6719 it was typical to call it at the end of a critical section | |
| 6720 (which occurs once per frame); but what then happens if multiple | |
| 6721 frames have frame changes held up? | |
| 4187 | 6722 |
| 1318 | 6723 This means we are O(N^2) over frames. I seriously doubt it matters. |
| 6724 --ben */ | |
| 6725 Lisp_Object frmcons, devcons, concons; | |
| 4187 | 6726 |
| 1318 | 6727 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
| 6728 { | |
| 6729 struct frame *f = XFRAME (XCAR (frmcons)); | |
| 6730 if (f->size_change_pending) | |
| 6731 change_frame_size (f, f->new_height, f->new_width, 0); | |
| 6732 } | |
| 6733 } | |
| 6734 return Qnil; | |
| 6735 } | |
| 6736 | |
| 6737 /* Call this to temporarily prevent frame-size changes from being processed. | |
| 6738 To undo, use unbind_to(), passing it the value returned by this function. | |
| 6739 */ | |
| 6740 | |
| 6741 int | |
| 6742 begin_hold_frame_size_changes (void) | |
| 6743 { | |
| 6744 int depth = specpdl_depth (); | |
| 6745 record_unwind_protect (end_hold_frame_size_changes, Qnil); | |
| 6746 internal_bind_int (&hold_frame_size_changes, 1 + hold_frame_size_changes); | |
| 6747 return depth; | |
| 6748 } | |
| 6749 | |
| 6750 int | |
| 6751 enter_redisplay_critical_section (void) | |
| 6752 { | |
| 6753 int depth = specpdl_depth (); | |
| 6754 | |
| 6755 /* Reentrant entry is deadly. The calling function must check for this. */ | |
| 6756 assert (!in_display); | |
| 6757 begin_hold_frame_size_changes (); | |
| 6758 /* Make sure in_display gets reset, but don't set it yet so that | |
| 6759 commit_ritual_suicide() can be used. */ | |
| 6760 internal_bind_int (&in_display, 0); | |
| 6761 internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
| 6762 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
| 6763 /* Force every call to QUIT to check for in_displayness. This will | |
| 6764 verify proper wrapping, as in the previous comment, aborting if not. */ | |
| 6765 something_happened++; | |
| 6766 /* Verify that no nonlocal exits blow past us. */ | |
| 6767 record_unwind_protect (commit_ritual_suicide, Qnil); | |
| 6768 #endif | |
| 6769 in_display++; | |
| 6770 | |
| 6771 set_trapping_problems_flags (INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY); | |
| 6772 /* Even checking for QUIT can cause arbitrary Lisp code to be executed, | |
| 6773 e.g. through a menu handler. We really don't want that happening | |
| 6774 inside of redisplay. Code that we `eval' is at least written with the | |
| 6775 expectation that it's inside of redisplay, and shouldn't try anything | |
| 6776 weird; but that's not the case for menu code (e.g. custom loads huge | |
| 6777 amounts of LISP FILES from a menu handler! FMH!). Safest just to turn | |
| 6778 this off. We could turn it on using UNINHIBIT_QUIT or | |
| 6779 begin_do_check_for_quit() in certain places if we want, if we know | |
| 6780 it's not in an especially tricky place. */ | |
| 6781 begin_dont_check_for_quit (); | |
| 6782 return depth; | |
| 6783 } | |
| 6784 | |
| 6785 void | |
| 6786 exit_redisplay_critical_section (int depth) | |
| 6787 { | |
| 6788 in_display--; | |
| 6789 assert (!in_display); | |
| 6790 unbind_to (depth); | |
| 6791 | |
| 6792 run_post_redisplay_actions (); | |
| 6793 } | |
| 6794 | |
| 6795 /* Enter the redisplay critical section if we're not already in it. This | |
| 6796 is for code that needs frame changes held up and other protections from | |
| 6797 being inside, but doesn't modify the redisplay structures, and doesn't | |
| 6798 look at them in a way that they will be confused by inconsistencies. */ | |
| 6799 | |
| 6800 int | |
| 6801 enter_redisplay_critical_section_maybe (void) | |
| 6802 { | |
| 6803 if (!in_display) | |
| 6804 return enter_redisplay_critical_section (); | |
| 6805 else | |
| 6806 return internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
| 6807 } | |
| 6808 | |
| 6809 void | |
| 6810 exit_redisplay_critical_section_maybe (int depth) | |
| 6811 { | |
| 6812 if (in_display_nesting == 1) | |
| 6813 exit_redisplay_critical_section (depth); | |
| 6814 else | |
| 6815 unbind_to (depth); | |
| 6816 } | |
| 6817 | |
| 1279 | 6818 /* Ensure that all windows on the given frame are correctly displayed. |
| 6819 Return non-zero if pre-empted. */ | |
| 428 | 6820 |
| 442 | 6821 int |
| 428 | 6822 redisplay_frame (struct frame *f, int preemption_check) |
| 6823 { | |
| 6824 struct device *d = XDEVICE (f->device); | |
| 853 | 6825 int depth; |
| 428 | 6826 |
| 1279 | 6827 assert (f->init_finished); |
| 6828 | |
| 1318 | 6829 /* NOTE: Without sufficient checks for stream frames, we got weird |
| 6830 crashes in pdump. These came and went very easily -- adding the | |
| 6831 critical-section code for redisplay was enough to trigger them. | |
| 6832 Perhaps I should have debugged them but there didn't seem to be any | |
| 6833 point. --ben */ | |
| 1279 | 6834 if (FRAME_STREAM_P (f)) /* nothing to do */ |
| 6835 return 0; | |
| 6836 | |
| 1318 | 6837 /* Reentrancy into redisplay can be deadly. See stack trace above |
| 6838 generate_displayable_area(). */ | |
| 6839 if (in_display) | |
| 6840 return 1; | |
| 6841 | |
| 545 | 6842 if (preemption_check |
| 6843 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) | |
| 428 | 6844 { |
| 6845 /* The preemption check itself takes a lot of time, | |
| 6846 so normally don't do it here. We do it if called | |
| 6847 from Lisp, though (`redisplay-frame'). */ | |
| 6848 int preempted; | |
| 6849 | |
| 6850 REDISPLAY_PREEMPTION_CHECK; | |
| 6851 if (preempted) | |
| 6852 return 1; | |
| 6853 } | |
| 6854 | |
| 442 | 6855 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) |
| 6856 { | |
| 6857 Lisp_Object frame; | |
| 6858 | |
| 6859 f->old_buffer_alist = Freplace_list (f->old_buffer_alist, | |
| 6860 f->buffer_alist); | |
| 793 | 6861 frame = wrap_frame (f); |
| 442 | 6862 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); |
| 6863 } | |
| 6864 | |
| 428 | 6865 /* Before we put a hold on frame size changes, attempt to process |
| 6866 any which are already pending. */ | |
| 6867 if (f->size_change_pending) | |
| 6868 change_frame_size (f, f->new_height, f->new_width, 0); | |
| 6869 | |
| 6870 /* If frame size might need to be changed, due to changed size | |
| 6871 of toolbars, scrollbars etc, change it now */ | |
| 6872 if (f->size_slipped) | |
| 6873 { | |
| 6874 adjust_frame_size (f); | |
| 6875 assert (!f->size_slipped); | |
| 6876 } | |
| 6877 | |
| 1318 | 6878 /* The menubar, toolbar, and icon updates should be done before |
| 853 | 6879 enter_redisplay_critical_section is called and we are officially |
| 3025 | 6880 `in_display'. They is because they tend to eval Lisp code, which |
| 1318 | 6881 needs to be carefully wrapped within the critical section (and hence |
| 6882 is difficult to debug). */ | |
| 428 | 6883 |
| 6884 #ifdef HAVE_MENUBARS | |
| 6885 /* Update the menubar. It is done first since it could change | |
| 6886 the menubar's visibility. This way we avoid having flashing | |
| 6887 caused by an Expose event generated by the visibility change | |
| 6888 being handled. */ | |
| 6889 update_frame_menubars (f); | |
| 6890 #endif /* HAVE_MENUBARS */ | |
| 6891 #ifdef HAVE_TOOLBARS | |
| 905 | 6892 /* Update the toolbars geometry. We don't update the toolbars |
| 6893 themselves at this point since the space they are trying to | |
| 6894 occupy may currently by occupied by gutter elements. Instead we | |
| 6895 update the geometry, then update the gutter geometry, then update | |
| 6896 the gutters - which will cause mapped windows to be repositioned | |
| 6897 - and finally update the toolbars. */ | |
| 6898 update_frame_toolbars_geometry (f); | |
| 428 | 6899 #endif /* HAVE_TOOLBARS */ |
| 442 | 6900 /* Gutter update proper has to be done inside display when no frame |
| 6901 size changes can occur, thus we separately update the gutter | |
| 6902 geometry here if it needs it. */ | |
| 6903 update_frame_gutter_geometry (f); | |
| 428 | 6904 |
| 6905 /* If we clear the frame we have to force its contents to be redrawn. */ | |
| 6906 if (f->clear) | |
| 6907 f->frame_changed = 1; | |
| 6908 | |
| 442 | 6909 /* Invalidate the subwindow caches. We use subwindows_changed here |
| 6910 to cause subwindows to get instantiated. This is because | |
| 428 | 6911 subwindows_state_changed is less strict - dealing with things |
| 6912 like the clicked state of button. We have to do this before | |
| 6913 redisplaying the gutters as subwindows get unmapped in the | |
| 6914 process.*/ | |
| 442 | 6915 if (f->frame_changed) |
| 6916 reset_frame_subwindow_instance_cache (f); | |
| 6917 | |
| 6918 if (f->frame_changed || f->subwindows_changed) | |
| 6919 { | |
| 428 | 6920 /* we have to do this so the gutter gets regenerated. */ |
| 6921 reset_gutter_display_lines (f); | |
| 6922 } | |
| 6923 | |
| 853 | 6924 depth = enter_redisplay_critical_section (); |
| 428 | 6925 |
| 6926 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ | |
| 1318 | 6927 |
| 6928 /* See comments in enter_redisplay_critical_section() */ | |
| 428 | 6929 |
| 442 | 6930 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
| 6931 | |
| 6932 /* We can now update the gutters, safe in the knowledge that our | |
| 6933 efforts won't get undone. */ | |
| 6934 | |
| 6935 /* This can call lisp, but redisplay is protected by binding | |
| 6936 inhibit_quit. More importantly the code involving display lines | |
| 6937 *assumes* that GC will not happen and so does not GCPRO | |
| 6938 anything. Since we use this code the whole time with the gutters | |
| 1318 | 6939 we cannot allow GC to happen when manipulating the gutters. |
| 6940 | |
| 6941 This must be inside of the critical section for various reasons. | |
| 6942 For example, it messes with display structures, which be left in | |
| 6943 an inconsistent state. */ | |
| 442 | 6944 update_frame_gutters (f); |
| 6945 | |
| 428 | 6946 /* Erase the frame before outputting its contents. */ |
| 6947 if (f->clear) | |
| 6948 { | |
| 442 | 6949 MAYBE_DEVMETH (d, clear_frame, (f)); |
| 428 | 6950 } |
| 6951 | |
| 6952 /* Do the selected window first. */ | |
| 6953 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); | |
| 6954 | |
| 6955 /* Then do the rest. */ | |
| 6956 redisplay_windows (f->root_window, 1); | |
| 6957 | |
| 442 | 6958 MAYBE_DEVMETH (d, frame_output_end, (f)); |
| 428 | 6959 |
| 6960 update_frame_title (f); | |
| 6961 | |
| 905 | 6962 #ifdef HAVE_TOOLBARS |
| 6963 /* Finally update the toolbars. It seems its possible to get in a | |
| 6964 cycle between updating the gutter and the toolbars. Basically we | |
| 6965 want to end up with both being up-to-date and this doesn't seem | |
| 6966 possible in a single pass. */ | |
| 6967 update_frame_toolbars (f); | |
| 6968 #endif /* HAVE_TOOLBARS */ | |
| 6969 | |
| 428 | 6970 CLASS_RESET_CHANGED_FLAGS (f); |
| 6971 f->window_face_cache_reset = 0; | |
| 6972 f->echo_area_garbaged = 0; | |
| 6973 f->clear = 0; | |
| 6974 | |
| 6975 if (!f->size_change_pending) | |
| 6976 f->size_changed = 0; | |
| 6977 | |
| 6978 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */ | |
| 6979 | |
| 853 | 6980 /* Allow frame size changes to occur again. */ |
| 6981 exit_redisplay_critical_section (depth); | |
| 428 | 6982 |
| 6983 return 0; | |
| 6984 } | |
| 6985 | |
| 440 | 6986 /* Ensure that all frames on the given device are correctly displayed. |
| 6987 If AUTOMATIC is non-zero, and the device implementation indicates | |
| 6988 no automatic redisplay, as printers do, then the device is not | |
| 6989 redisplayed. AUTOMATIC is set to zero when called from lisp | |
| 6990 functions (redraw-device) and (redisplay-device), and to non-zero | |
| 6991 when called from "lazy" redisplay(); | |
| 6992 */ | |
| 428 | 6993 |
| 6994 static int | |
| 440 | 6995 redisplay_device (struct device *d, int automatic) |
| 428 | 6996 { |
| 6997 Lisp_Object frame, frmcons; | |
| 6998 int size_change_failed = 0; | |
| 6999 struct frame *f; | |
| 7000 | |
| 545 | 7001 if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) |
| 440 | 7002 return 0; |
| 7003 | |
| 428 | 7004 if (DEVICE_STREAM_P (d)) /* nothing to do */ |
| 7005 return 0; | |
| 7006 | |
| 7007 /* It is possible that redisplay has been called before the | |
| 545 | 7008 device is fully initialized, or that the console implementation |
| 7009 allows frameless devices. If so then continue with the next | |
| 7010 device. */ | |
| 428 | 7011 if (NILP (DEVICE_SELECTED_FRAME (d))) |
| 7012 return 0; | |
| 7013 | |
| 545 | 7014 if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) |
| 7015 { | |
| 7016 int preempted; | |
| 7017 REDISPLAY_PREEMPTION_CHECK; | |
| 7018 if (preempted) | |
| 7019 return 1; | |
| 7020 } | |
| 428 | 7021 |
| 7022 /* Always do the selected frame first. */ | |
| 7023 frame = DEVICE_SELECTED_FRAME (d); | |
| 7024 | |
| 7025 f = XFRAME (frame); | |
| 7026 | |
| 7027 if (f->icon_changed || f->windows_changed) | |
| 7028 update_frame_icon (f); | |
| 7029 | |
| 7030 if (FRAME_REPAINT_P (f)) | |
| 7031 { | |
| 7032 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) | |
| 7033 { | |
| 588 | 7034 int preempted = redisplay_frame (f, 1); |
| 545 | 7035 if (preempted) |
| 7036 return 1; | |
| 7037 } | |
| 428 | 7038 |
| 7039 /* If the frame redisplay did not get preempted, then this flag | |
| 4187 | 7040 should have gotten set to 0. It might be possible for that |
| 7041 not to happen if a size change event were to occur at an odd | |
| 7042 time. To make sure we don't miss anything we simply don't | |
| 7043 reset the top level flags until the condition ends up being | |
| 7044 in the right state. */ | |
| 428 | 7045 if (f->size_changed) |
| 7046 size_change_failed = 1; | |
| 7047 } | |
| 7048 | |
| 7049 DEVICE_FRAME_LOOP (frmcons, d) | |
| 7050 { | |
| 7051 f = XFRAME (XCAR (frmcons)); | |
| 7052 | |
| 7053 if (f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
| 7054 continue; | |
| 7055 | |
| 7056 if (f->icon_changed || f->windows_changed) | |
| 7057 update_frame_icon (f); | |
| 7058 | |
| 7059 if (FRAME_REPAINT_P (f)) | |
| 7060 { | |
| 430 | 7061 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
| 428 | 7062 { |
| 588 | 7063 int preempted = redisplay_frame (f, 1); |
| 545 | 7064 if (preempted) |
| 7065 return 1; | |
| 428 | 7066 } |
| 7067 | |
| 7068 if (f->size_change_pending) | |
| 7069 size_change_failed = 1; | |
| 7070 } | |
| 7071 } | |
| 7072 | |
| 7073 /* If we get here then we redisplayed all of our frames without | |
| 7074 getting preempted so mark ourselves as clean. */ | |
| 7075 CLASS_RESET_CHANGED_FLAGS (d); | |
| 7076 | |
| 7077 if (!size_change_failed) | |
| 7078 d->size_changed = 0; | |
| 7079 | |
| 7080 return 0; | |
| 7081 } | |
| 7082 | |
| 7083 /* Ensure that all windows on all frames on all devices are displaying | |
| 7084 the current contents of their respective buffers. */ | |
| 7085 | |
| 7086 static void | |
| 7087 redisplay_without_hooks (void) | |
| 7088 { | |
| 7089 Lisp_Object devcons, concons; | |
| 7090 int size_change_failed = 0; | |
| 1292 | 7091 PROFILE_DECLARE (); |
| 7092 | |
| 7093 PROFILE_RECORD_ENTERING_SECTION (QSin_redisplay); | |
| 428 | 7094 |
| 7095 if (asynch_device_change_pending) | |
| 7096 handle_asynch_device_change (); | |
| 7097 | |
| 7098 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && | |
| 430 | 7099 !disable_preemption && preemption_count < max_preempts) |
| 428 | 7100 goto done; |
| 7101 | |
| 7102 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
| 7103 { | |
| 7104 struct device *d = XDEVICE (XCAR (devcons)); | |
| 7105 int preempted; | |
| 7106 | |
| 430 | 7107 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) |
| 428 | 7108 { |
| 440 | 7109 preempted = redisplay_device (d, 1); |
| 428 | 7110 |
| 7111 if (preempted) | |
| 7112 { | |
| 7113 preemption_count++; | |
| 7114 RESET_CHANGED_SET_FLAGS; | |
| 7115 goto done; | |
| 7116 } | |
| 7117 | |
| 7118 /* See comment in redisplay_device. */ | |
| 7119 if (d->size_changed) | |
| 7120 size_change_failed = 1; | |
| 7121 } | |
| 7122 } | |
| 7123 preemption_count = 0; | |
| 7124 | |
| 7125 /* Mark redisplay as accurate */ | |
| 7126 GLOBAL_RESET_CHANGED_FLAGS; | |
| 7127 RESET_CHANGED_SET_FLAGS; | |
| 7128 | |
| 7129 if (faces_changed) | |
| 7130 { | |
| 7131 mark_all_faces_as_clean (); | |
| 7132 faces_changed = 0; | |
| 7133 } | |
| 7134 | |
| 7135 if (!size_change_failed) | |
| 7136 size_changed = 0; | |
| 7137 | |
| 7138 reset_buffer_changes (); | |
| 7139 | |
| 7140 done: | |
| 800 | 7141 #ifdef ERROR_CHECK_DISPLAY |
| 7142 sledgehammer_check_redisplay_structs (); | |
| 7143 #endif /* ERROR_CHECK_DISPLAY */ | |
| 1292 | 7144 |
| 7145 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay); | |
| 428 | 7146 } |
| 7147 | |
| 1318 | 7148 /* Note: All places in the C code that call redisplay() are prepared to |
| 7149 handle GCing, which can happen from run_pre_idle_hook(). However, we | |
| 7150 can't currently handle GC inside the guts of redisplay; see | |
| 7151 enter_redisplay_critical_section(). | |
| 853 | 7152 |
| 7153 (#### What about other external entry points to the redisplay code? | |
| 7154 Someone should go through and make sure that all callers can handle | |
| 7155 GC there, too.) | |
| 7156 */ | |
| 7157 | |
| 428 | 7158 void |
| 7159 redisplay (void) | |
| 7160 { | |
| 853 | 7161 run_pre_idle_hook (); |
| 7162 redisplay_no_pre_idle_hook (); | |
| 7163 } | |
| 7164 | |
| 7165 void | |
| 7166 redisplay_no_pre_idle_hook (void) | |
| 7167 { | |
| 428 | 7168 if (last_display_warning_tick != display_warning_tick && |
| 7169 !inhibit_warning_display) | |
| 7170 { | |
| 7171 /* If an error occurs during this function, oh well. | |
| 4187 | 7172 If we report another warning, we could get stuck in an |
| 428 | 7173 infinite loop reporting warnings. */ |
| 853 | 7174 call0_trapping_problems |
| 7175 (0, Qdisplay_warning_buffer, | |
| 7176 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
| 428 | 7177 last_display_warning_tick = display_warning_tick; |
| 7178 } | |
| 7179 | |
| 7180 redisplay_without_hooks (); | |
| 7181 } | |
| 7182 | |
| 853 | 7183 Lisp_Object |
| 7184 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker) | |
| 7185 { | |
| 7186 return | |
| 7187 eval_in_buffer_trapping_problems | |
| 7188 ("Error calling function within redisplay", current_buffer, | |
| 1318 | 7189 dont_trust_this_damn_sucker, 0); |
| 853 | 7190 } |
| 428 | 7191 |
| 7192 /* Efficiently determine the window line number, and return a pointer | |
| 7193 to its printed representation. Do this regardless of whether | |
| 7194 line-number-mode is on. The first line in the buffer is counted as | |
| 7195 1. If narrowing is in effect, the lines are counted from the | |
| 7196 beginning of the visible portion of the buffer. */ | |
| 7197 static char * | |
| 7198 window_line_number (struct window *w, int type) | |
| 7199 { | |
| 7200 struct device *d = XDEVICE (XFRAME (w->frame)->device); | |
| 7201 struct buffer *b = XBUFFER (w->buffer); | |
| 7202 /* Be careful in the order of these tests. The first clause will | |
| 7203 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be). | |
| 7204 This can occur when the frame title is computed really early */ | |
| 665 | 7205 Charbpos pos = |
| 428 | 7206 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) && |
| 7207 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) && | |
| 7208 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
| 7209 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d ) | |
| 7210 ? BUF_PT (b) | |
| 7211 : marker_position (w->pointm[type])); | |
| 7212 EMACS_INT line; | |
| 7213 | |
| 7214 line = buffer_line_number (b, pos, 1); | |
| 7215 | |
| 603 | 7216 { |
| 7217 static char window_line_number_buf[DECIMAL_PRINT_SIZE (long)]; | |
| 7218 | |
| 7219 long_to_string (window_line_number_buf, line + 1); | |
| 7220 | |
| 7221 return window_line_number_buf; | |
| 7222 } | |
| 428 | 7223 } |
| 7224 | |
| 7225 | |
| 7226 /* Given a character representing an object in a modeline | |
| 7227 specification, return a string (stored into the global array | |
| 867 | 7228 `mode_spec_ibyte_string') with the information that object |
| 428 | 7229 represents. |
| 7230 | |
| 7231 This function is largely unchanged from previous versions of the | |
| 7232 redisplay engine. | |
| 7233 | |
| 7234 Warning! This code is also used for frame titles and can be called | |
| 7235 very early in the device/frame update process! JV | |
| 7236 */ | |
| 7237 | |
| 7238 static void | |
| 867 | 7239 decode_mode_spec (struct window *w, Ichar spec, int type) |
| 428 | 7240 { |
| 7241 Lisp_Object obj = Qnil; | |
| 442 | 7242 const char *str = NULL; |
| 428 | 7243 struct buffer *b = XBUFFER (w->buffer); |
| 7244 | |
| 867 | 7245 Dynarr_reset (mode_spec_ibyte_string); |
| 428 | 7246 |
| 7247 switch (spec) | |
| 7248 { | |
| 7249 /* print buffer name */ | |
| 7250 case 'b': | |
| 7251 obj = b->name; | |
| 7252 break; | |
| 7253 | |
| 7254 /* print visited file name */ | |
| 7255 case 'f': | |
| 7256 obj = b->filename; | |
| 7257 break; | |
| 7258 | |
| 7259 /* print the current column */ | |
| 7260 case 'c': | |
| 7261 { | |
| 4187 | 7262 Charbpos pt = (w == XWINDOW (Fselected_window (Qnil))) |
| 7263 ? BUF_PT (b) | |
| 7264 : marker_position (w->pointm[type]); | |
| 428 | 7265 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one; |
| 603 | 7266 char buf[DECIMAL_PRINT_SIZE (long)]; |
| 428 | 7267 |
| 7268 long_to_string (buf, col); | |
| 7269 | |
| 867 | 7270 Dynarr_add_many (mode_spec_ibyte_string, |
| 7271 (const Ibyte *) buf, strlen (buf)); | |
| 428 | 7272 |
| 7273 goto decode_mode_spec_done; | |
| 7274 } | |
| 7275 /* print the file coding system */ | |
| 7276 case 'C': | |
| 7277 { | |
| 4187 | 7278 Lisp_Object codesys = b->buffer_file_coding_system; |
| 7279 /* Be very careful here not to get an error. */ | |
| 428 | 7280 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys)) |
| 4187 | 7281 { |
| 7282 codesys = find_coding_system_for_text_file (codesys, 0); | |
| 428 | 7283 if (CODING_SYSTEMP (codesys)) |
| 4187 | 7284 obj = XCODING_SYSTEM_MNEMONIC (codesys); |
| 7285 } | |
| 428 | 7286 } |
| 7287 break; | |
| 7288 | |
| 7289 /* print the current line number */ | |
| 7290 case 'l': | |
| 7291 str = window_line_number (w, type); | |
| 7292 break; | |
| 7293 | |
| 7294 /* print value of mode-name (obsolete) */ | |
| 7295 case 'm': | |
| 7296 obj = b->mode_name; | |
| 7297 break; | |
| 7298 | |
| 7299 /* print hyphen and frame number, if != 1 */ | |
| 7300 case 'N': | |
| 7301 #ifdef HAVE_TTY | |
| 7302 { | |
| 7303 struct frame *f = XFRAME (w->frame); | |
| 7304 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999) | |
| 7305 { | |
| 7306 /* Naughty, naughty */ | |
| 7307 char * writable_str = alloca_array (char, 10); | |
| 7308 sprintf (writable_str, "-%d", f->order_count); | |
| 7309 str = writable_str; | |
| 7310 } | |
| 7311 } | |
| 7312 #endif /* HAVE_TTY */ | |
| 7313 break; | |
| 7314 | |
| 7315 /* print Narrow if appropriate */ | |
| 7316 case 'n': | |
| 7317 if (BUF_BEGV (b) > BUF_BEG (b) | |
| 7318 || BUF_ZV (b) < BUF_Z (b)) | |
| 7319 str = " Narrow"; | |
| 7320 break; | |
| 7321 | |
| 7322 /* print %, * or hyphen, if buffer is read-only, modified or neither */ | |
| 7323 case '*': | |
| 7324 str = (!NILP (b->read_only) | |
| 7325 ? "%" | |
| 7326 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
| 7327 ? "*" | |
| 7328 : "-")); | |
| 7329 break; | |
| 7330 | |
| 7331 /* print * or hyphen -- XEmacs change to allow a buffer to be | |
| 4187 | 7332 read-only but still indicate whether it is modified. */ |
| 428 | 7333 case '+': |
| 7334 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
| 7335 ? "*" | |
| 7336 : (!NILP (b->read_only) | |
| 7337 ? "%" | |
| 7338 : "-")); | |
| 7339 break; | |
| 7340 | |
| 7341 /* #### defined in 19.29 decode_mode_spec, but not in | |
| 4187 | 7342 modeline-format doc string. */ |
| 428 | 7343 /* This differs from %* in that it ignores read-only-ness. */ |
| 7344 case '&': | |
| 7345 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
| 7346 ? "*" | |
| 7347 : "-"); | |
| 7348 break; | |
| 7349 | |
| 7350 /* print process status */ | |
| 7351 case 's': | |
| 7352 obj = Fget_buffer_process (w->buffer); | |
| 7353 if (NILP (obj)) | |
| 7354 str = GETTEXT ("no process"); | |
| 7355 else | |
| 7356 obj = Fsymbol_name (Fprocess_status (obj)); | |
| 7357 break; | |
| 7358 | |
| 7359 /* Print name of selected frame. */ | |
| 7360 case 'S': | |
| 7361 obj = XFRAME (w->frame)->name; | |
| 7362 break; | |
| 7363 | |
| 7364 /* indicate TEXT or BINARY */ | |
| 7365 case 't': | |
| 7366 /* #### NT does not use this any more. Now what? */ | |
| 7367 str = "T"; | |
| 7368 break; | |
| 7369 | |
| 7370 /* print percent of buffer above top of window, or Top, Bot or All */ | |
| 7371 case 'p': | |
| 7372 { | |
| 665 | 7373 Charbpos pos = marker_position (w->start[type]); |
| 428 | 7374 |
| 7375 /* This had better be while the desired lines are being done. */ | |
| 7376 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) | |
| 7377 { | |
| 7378 if (pos <= BUF_BEGV (b)) | |
| 7379 str = "All"; | |
| 7380 else | |
| 7381 str = "Bottom"; | |
| 7382 } | |
| 7383 else if (pos <= BUF_BEGV (b)) | |
| 7384 str = "Top"; | |
| 7385 else | |
| 7386 { | |
| 7387 /* This hard limit is ok since the string it will hold has a | |
| 4187 | 7388 fixed maximum length of 3. But just to be safe... */ |
| 428 | 7389 char buf[10]; |
| 7390 Charcount chars = pos - BUF_BEGV (b); | |
| 7391 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
| 7392 | |
| 7393 /* Avoid overflow on big buffers */ | |
| 7394 int percent = total > LONG_MAX/200 ? | |
| 7395 (chars + total/200) / (total / 100) : | |
| 7396 (chars * 100 + total/2) / total; | |
| 7397 | |
| 7398 /* We can't normally display a 3-digit number, so get us a | |
| 4187 | 7399 2-digit number that is close. */ |
| 428 | 7400 if (percent == 100) |
| 7401 percent = 99; | |
| 7402 | |
| 7403 sprintf (buf, "%d%%", percent); | |
| 867 | 7404 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
| 428 | 7405 strlen (buf)); |
| 7406 | |
| 7407 goto decode_mode_spec_done; | |
| 7408 } | |
| 7409 break; | |
| 7410 } | |
| 7411 | |
| 7412 /* print percent of buffer above bottom of window, perhaps plus | |
| 7413 Top, or print Bottom or All */ | |
| 7414 case 'P': | |
| 7415 { | |
| 665 | 7416 Charbpos toppos = marker_position (w->start[type]); |
| 7417 Charbpos botpos = BUF_Z (b) - w->window_end_pos[type]; | |
| 428 | 7418 |
| 7419 /* botpos is only accurate as of the last redisplay, so we can | |
| 4187 | 7420 only treat it as a hint. In particular, after erase-buffer, |
| 7421 botpos may be negative. */ | |
| 428 | 7422 if (botpos < toppos) |
| 7423 botpos = toppos; | |
| 7424 | |
| 7425 if (botpos >= BUF_ZV (b)) | |
| 7426 { | |
| 7427 if (toppos <= BUF_BEGV (b)) | |
| 7428 str = "All"; | |
| 7429 else | |
| 7430 str = "Bottom"; | |
| 7431 } | |
| 7432 else | |
| 7433 { | |
| 7434 /* This hard limit is ok since the string it will hold has a | |
| 4187 | 7435 fixed maximum length of around 6. But just to be safe... */ |
| 428 | 7436 char buf[10]; |
| 7437 Charcount chars = botpos - BUF_BEGV (b); | |
| 7438 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
| 7439 | |
| 7440 /* Avoid overflow on big buffers */ | |
| 7441 int percent = total > LONG_MAX/200 ? | |
| 7442 (chars + total/200) / (total / 100) : | |
| 7443 (chars * 100 + total/2) / max (total, 1); | |
| 7444 | |
| 7445 /* We can't normally display a 3-digit number, so get us a | |
| 4187 | 7446 2-digit number that is close. */ |
| 428 | 7447 if (percent == 100) |
| 7448 percent = 99; | |
| 7449 | |
| 7450 if (toppos <= BUF_BEGV (b)) | |
| 7451 sprintf (buf, "Top%d%%", percent); | |
| 7452 else | |
| 7453 sprintf (buf, "%d%%", percent); | |
| 7454 | |
| 867 | 7455 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
| 428 | 7456 strlen (buf)); |
| 7457 | |
| 7458 goto decode_mode_spec_done; | |
| 7459 } | |
| 7460 break; | |
| 7461 } | |
| 7462 | |
| 7463 /* print % */ | |
| 7464 case '%': | |
| 7465 str = "%"; | |
| 7466 break; | |
| 7467 | |
| 7468 /* print one [ for each recursive editing level. */ | |
| 7469 case '[': | |
| 7470 { | |
| 7471 int i; | |
| 7472 | |
| 7473 if (command_loop_level > 5) | |
| 7474 { | |
| 7475 str = "[[[... "; | |
| 7476 break; | |
| 7477 } | |
| 7478 | |
| 7479 for (i = 0; i < command_loop_level; i++) | |
| 867 | 7480 Dynarr_add (mode_spec_ibyte_string, '['); |
| 428 | 7481 |
| 7482 goto decode_mode_spec_done; | |
| 7483 } | |
| 7484 | |
| 7485 /* print one ] for each recursive editing level. */ | |
| 7486 case ']': | |
| 7487 { | |
| 7488 int i; | |
| 7489 | |
| 7490 if (command_loop_level > 5) | |
| 7491 { | |
| 7492 str = "...]]]"; | |
| 7493 break; | |
| 7494 } | |
| 7495 | |
| 7496 for (i = 0; i < command_loop_level; i++) | |
| 867 | 7497 Dynarr_add (mode_spec_ibyte_string, ']'); |
| 428 | 7498 |
| 7499 goto decode_mode_spec_done; | |
| 7500 } | |
| 7501 | |
| 7502 /* print infinitely many dashes -- handle at top level now */ | |
| 7503 case '-': | |
| 7504 break; | |
| 7505 | |
| 7506 } | |
| 7507 | |
| 7508 if (STRINGP (obj)) | |
| 867 | 7509 Dynarr_add_many (mode_spec_ibyte_string, |
| 428 | 7510 XSTRING_DATA (obj), |
| 7511 XSTRING_LENGTH (obj)); | |
| 7512 else if (str) | |
| 867 | 7513 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) str, strlen (str)); |
| 428 | 7514 |
| 7515 decode_mode_spec_done: | |
| 867 | 7516 Dynarr_add (mode_spec_ibyte_string, '\0'); |
| 428 | 7517 } |
| 7518 | |
| 7519 /* Given a display line, free all of its data structures. */ | |
| 7520 | |
| 7521 static void | |
| 7522 free_display_line (struct display_line *dl) | |
| 7523 { | |
| 7524 int block; | |
| 7525 | |
| 7526 if (dl->display_blocks) | |
| 7527 { | |
| 7528 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
| 4187 | 7529 { |
| 428 | 7530 struct display_block *db = Dynarr_atp (dl->display_blocks, block); |
| 7531 | |
| 7532 Dynarr_free (db->runes); | |
| 7533 } | |
| 7534 | |
| 7535 Dynarr_free (dl->display_blocks); | |
| 7536 dl->display_blocks = NULL; | |
| 7537 } | |
| 7538 | |
| 7539 if (dl->left_glyphs) | |
| 7540 { | |
| 7541 Dynarr_free (dl->left_glyphs); | |
| 7542 dl->left_glyphs = NULL; | |
| 7543 } | |
| 7544 | |
| 7545 if (dl->right_glyphs) | |
| 7546 { | |
| 7547 Dynarr_free (dl->right_glyphs); | |
| 7548 dl->right_glyphs = NULL; | |
| 7549 } | |
| 7550 } | |
| 7551 | |
| 7552 | |
| 7553 /* Given an array of display lines, free them and all data structures | |
| 7554 contained within them. */ | |
| 7555 | |
| 7556 void | |
| 7557 free_display_lines (display_line_dynarr *dla) | |
| 7558 { | |
| 7559 int line; | |
| 7560 | |
| 7561 for (line = 0; line < Dynarr_largest (dla); line++) | |
| 7562 { | |
| 7563 free_display_line (Dynarr_atp (dla, line)); | |
| 7564 } | |
| 7565 | |
| 7566 Dynarr_free (dla); | |
| 7567 } | |
| 7568 | |
| 7569 /* Call internal free routine for each set of display lines. */ | |
| 7570 | |
| 7571 void | |
| 7572 free_display_structs (struct window_mirror *mir) | |
| 7573 { | |
| 7574 if (mir->current_display_lines) | |
| 7575 { | |
| 7576 free_display_lines (mir->current_display_lines); | |
| 7577 mir->current_display_lines = 0; | |
| 7578 } | |
| 7579 | |
| 7580 if (mir->desired_display_lines) | |
| 7581 { | |
| 7582 free_display_lines (mir->desired_display_lines); | |
| 7583 mir->desired_display_lines = 0; | |
| 7584 } | |
| 7585 } | |
| 7586 | |
| 7587 | |
| 7588 static void | |
| 7589 mark_glyph_block_dynarr (glyph_block_dynarr *gba) | |
| 7590 { | |
| 7591 if (gba) | |
| 7592 { | |
| 7593 glyph_block *gb = Dynarr_atp (gba, 0); | |
| 7594 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba)); | |
| 7595 | |
| 7596 for (; gb < gb_last; gb++) | |
| 7597 { | |
| 7598 if (!NILP (gb->glyph)) | |
| 7599 mark_object (gb->glyph); | |
| 7600 if (!NILP (gb->extent)) | |
| 7601 mark_object (gb->extent); | |
| 7602 } | |
| 7603 } | |
| 7604 } | |
| 7605 | |
| 442 | 7606 /* See the comment in image_instantiate_cache_result as to why marking |
| 7607 the glyph will also mark the image_instance. */ | |
| 7608 void | |
| 428 | 7609 mark_redisplay_structs (display_line_dynarr *dla) |
| 7610 { | |
| 7611 display_line *dl = Dynarr_atp (dla, 0); | |
| 7612 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla)); | |
| 7613 | |
| 7614 for (; dl < dl_last; dl++) | |
| 7615 { | |
| 7616 display_block_dynarr *dba = dl->display_blocks; | |
| 7617 display_block *db = Dynarr_atp (dba, 0); | |
| 7618 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba)); | |
| 7619 | |
| 7620 for (; db < db_last; db++) | |
| 7621 { | |
| 7622 rune_dynarr *ra = db->runes; | |
| 7623 rune *r = Dynarr_atp (ra, 0); | |
| 7624 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra)); | |
| 7625 | |
| 7626 for (; r < r_last; r++) | |
| 7627 { | |
| 7628 if (r->type == RUNE_DGLYPH) | |
| 7629 { | |
| 7630 if (!NILP (r->object.dglyph.glyph)) | |
| 7631 mark_object (r->object.dglyph.glyph); | |
| 7632 if (!NILP (r->object.dglyph.extent)) | |
| 7633 mark_object (r->object.dglyph.extent); | |
| 7634 } | |
| 7635 } | |
| 7636 } | |
| 7637 | |
| 7638 mark_glyph_block_dynarr (dl->left_glyphs); | |
| 7639 mark_glyph_block_dynarr (dl->right_glyphs); | |
| 7640 } | |
| 7641 } | |
| 7642 | |
| 7643 | |
| 2367 | 7644 |
| 7645 /* | |
| 7646 | |
| 7647 Info on line-start cache: | |
| 7648 | |
| 7649 (Info-goto-node "(internals)Line Start Cache") | |
| 7650 */ | |
| 428 | 7651 |
| 7652 /* This will get used quite a bit so we don't want to be constantly | |
| 7653 allocating and freeing it. */ | |
| 7654 static line_start_cache_dynarr *internal_cache; | |
| 7655 | |
| 7656 /* Makes internal_cache represent the TYPE display structs and only | |
| 7657 the TYPE display structs. */ | |
| 7658 | |
| 7659 static void | |
| 7660 update_internal_cache_list (struct window *w, int type) | |
| 7661 { | |
| 7662 int line; | |
| 7663 display_line_dynarr *dla = window_display_lines (w, type); | |
| 7664 | |
| 7665 Dynarr_reset (internal_cache); | |
| 7666 for (line = 0; line < Dynarr_length (dla); line++) | |
| 7667 { | |
| 7668 struct display_line *dl = Dynarr_atp (dla, line); | |
| 7669 | |
| 7670 if (dl->modeline) | |
| 7671 continue; | |
| 7672 else | |
| 7673 { | |
| 7674 struct line_start_cache lsc; | |
| 434 | 7675 |
| 826 | 7676 lsc.start = dl->charpos; |
| 7677 lsc.end = dl->end_charpos; | |
| 428 | 7678 lsc.height = dl->ascent + dl->descent; |
| 7679 | |
| 7680 Dynarr_add (internal_cache, lsc); | |
| 7681 } | |
| 7682 } | |
| 7683 } | |
| 7684 | |
| 7685 /* Reset the line cache if necessary. This should be run at the | |
| 7686 beginning of any function which access the cache. */ | |
| 7687 | |
| 7688 static void | |
| 7689 validate_line_start_cache (struct window *w) | |
| 7690 { | |
| 7691 struct buffer *b = XBUFFER (w->buffer); | |
| 7692 struct frame *f = XFRAME (w->frame); | |
| 7693 | |
| 7694 if (!w->line_cache_validation_override) | |
| 7695 { | |
| 7696 /* f->extents_changed used to be in here because extent face and | |
| 4187 | 7697 size changes can cause text shifting. However, the extent |
| 7698 covering the region is constantly having its face set and | |
| 7699 priority altered by the mouse code. This means that the line | |
| 7700 start cache is constantly being invalidated. This is bad | |
| 7701 since the mouse code also triggers heavy usage of the cache. | |
| 7702 Since it is an unlikely that f->extents being changed | |
| 7703 indicates that the cache really needs to be updated and if it | |
| 7704 does redisplay will catch it pretty quickly we no longer | |
| 7705 invalidate the cache if it is set. This greatly speeds up | |
| 7706 dragging out regions with the mouse. */ | |
| 428 | 7707 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b) |
| 7708 || f->faces_changed | |
| 7709 || f->clip_changed) | |
| 7710 { | |
| 7711 Dynarr_reset (w->line_start_cache); | |
| 7712 } | |
| 7713 } | |
| 7714 } | |
| 7715 | |
| 7716 /* Return the very first buffer position contained in the given | |
| 7717 window's cache, or -1 if the cache is empty. Assumes that the | |
| 7718 cache is valid. */ | |
| 7719 | |
| 665 | 7720 static Charbpos |
| 428 | 7721 line_start_cache_start (struct window *w) |
| 7722 { | |
| 7723 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 7724 | |
| 7725 if (!Dynarr_length (cache)) | |
| 7726 return -1; | |
| 7727 else | |
| 7728 return Dynarr_atp (cache, 0)->start; | |
| 7729 } | |
| 7730 | |
| 7731 /* Return the very last buffer position contained in the given | |
| 7732 window's cache, or -1 if the cache is empty. Assumes that the | |
| 7733 cache is valid. */ | |
| 7734 | |
| 665 | 7735 static Charbpos |
| 428 | 7736 line_start_cache_end (struct window *w) |
| 7737 { | |
| 7738 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 7739 | |
| 7740 if (!Dynarr_length (cache)) | |
| 7741 return -1; | |
| 7742 else | |
| 7743 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end; | |
| 7744 } | |
| 7745 | |
| 7746 /* Return the index of the line POINT is contained within in window | |
| 7747 W's line start cache. It will enlarge the cache or move the cache | |
| 7748 window in order to have POINT be present in the cache. MIN_PAST is | |
| 7749 a guarantee of the number of entries in the cache present on either | |
| 7750 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1 | |
| 7751 then it will be treated as 0, but the cache window will not be | |
| 7752 allowed to shift. Returns -1 if POINT cannot be found in the cache | |
| 7753 for any reason. */ | |
| 7754 | |
| 7755 int | |
| 665 | 7756 point_in_line_start_cache (struct window *w, Charbpos point, int min_past) |
| 428 | 7757 { |
| 7758 struct buffer *b = XBUFFER (w->buffer); | |
| 7759 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 647 | 7760 int top, bottom, pos; |
| 428 | 7761 |
| 7762 validate_line_start_cache (w); | |
| 7763 w->line_cache_validation_override++; | |
| 7764 | |
| 7765 /* Let functions pass in negative values, but we still treat -1 | |
| 7766 specially. */ | |
| 7767 /* #### bogosity alert */ | |
| 7768 if (min_past < 0 && min_past != -1) | |
| 7769 min_past = -min_past; | |
| 7770 | |
| 7771 if (!Dynarr_length (cache) || line_start_cache_start (w) > point | |
| 7772 || line_start_cache_end (w) < point) | |
| 7773 { | |
| 7774 int loop; | |
| 7775 int win_char_height = window_char_height (w, 1); | |
| 7776 | |
| 7777 /* Occasionally we get here with a 0 height | |
| 4187 | 7778 window. find_next_newline_no_quit will abort if we pass it a |
| 7779 count of 0 so handle that case. */ | |
| 428 | 7780 if (!win_char_height) |
| 7781 win_char_height = 1; | |
| 7782 | |
| 7783 if (!Dynarr_length (cache)) | |
| 7784 { | |
| 665 | 7785 Charbpos from = find_next_newline_no_quit (b, point, -1); |
| 7786 Charbpos to = find_next_newline_no_quit (b, from, win_char_height); | |
| 428 | 7787 |
| 7788 update_line_start_cache (w, from, to, point, 0); | |
| 7789 | |
| 7790 if (!Dynarr_length (cache)) | |
| 7791 { | |
| 7792 w->line_cache_validation_override--; | |
| 7793 return -1; | |
| 7794 } | |
| 7795 } | |
| 7796 | |
| 7797 assert (Dynarr_length (cache)); | |
| 7798 | |
| 7799 loop = 0; | |
| 7800 while (line_start_cache_start (w) > point | |
| 7801 && (loop < cache_adjustment || min_past == -1)) | |
| 7802 { | |
| 665 | 7803 Charbpos from, to; |
| 428 | 7804 |
| 7805 from = line_start_cache_start (w); | |
| 7806 if (from <= BUF_BEGV (b)) | |
| 7807 break; | |
| 7808 | |
| 7809 from = find_next_newline_no_quit (b, from, -win_char_height); | |
| 7810 to = line_start_cache_end (w); | |
| 7811 | |
| 7812 update_line_start_cache (w, from, to, point, 0); | |
| 7813 loop++; | |
| 7814 } | |
| 7815 | |
| 7816 if (line_start_cache_start (w) > point) | |
| 7817 { | |
| 665 | 7818 Charbpos from, to; |
| 428 | 7819 |
| 7820 from = find_next_newline_no_quit (b, point, -1); | |
| 7821 if (from >= BUF_ZV (b)) | |
| 7822 { | |
| 7823 to = find_next_newline_no_quit (b, from, -win_char_height); | |
| 7824 from = to; | |
| 7825 to = BUF_ZV (b); | |
| 7826 } | |
| 7827 else | |
| 7828 to = find_next_newline_no_quit (b, from, win_char_height); | |
| 7829 | |
| 7830 update_line_start_cache (w, from, to, point, 0); | |
| 7831 } | |
| 7832 | |
| 7833 loop = 0; | |
| 7834 while (line_start_cache_end (w) < point | |
| 7835 && (loop < cache_adjustment || min_past == -1)) | |
| 7836 { | |
| 665 | 7837 Charbpos from, to; |
| 428 | 7838 |
| 7839 to = line_start_cache_end (w); | |
| 7840 if (to >= BUF_ZV (b)) | |
| 7841 break; | |
| 7842 | |
| 7843 from = line_start_cache_end (w); | |
| 7844 to = find_next_newline_no_quit (b, from, win_char_height); | |
| 7845 | |
| 7846 update_line_start_cache (w, from, to, point, 0); | |
| 7847 loop++; | |
| 7848 } | |
| 7849 | |
| 7850 if (line_start_cache_end (w) < point) | |
| 7851 { | |
| 665 | 7852 Charbpos from, to; |
| 428 | 7853 |
| 7854 from = find_next_newline_no_quit (b, point, -1); | |
| 7855 if (from >= BUF_ZV (b)) | |
| 7856 { | |
| 7857 to = find_next_newline_no_quit (b, from, -win_char_height); | |
| 7858 from = to; | |
| 7859 to = BUF_ZV (b); | |
| 7860 } | |
| 7861 else | |
| 7862 to = find_next_newline_no_quit (b, from, win_char_height); | |
| 7863 | |
| 7864 update_line_start_cache (w, from, to, point, 0); | |
| 7865 } | |
| 7866 } | |
| 7867 | |
| 7868 assert (Dynarr_length (cache)); | |
| 7869 | |
| 7870 if (min_past == -1) | |
| 7871 min_past = 0; | |
| 7872 | |
| 7873 /* This could happen if the buffer is narrowed. */ | |
| 7874 if (line_start_cache_start (w) > point | |
| 7875 || line_start_cache_end (w) < point) | |
| 7876 { | |
| 7877 w->line_cache_validation_override--; | |
| 7878 return -1; | |
| 7879 } | |
| 7880 | |
| 7881 find_point_loop: | |
| 7882 | |
| 7883 top = Dynarr_length (cache) - 1; | |
| 7884 bottom = 0; | |
| 7885 | |
| 7886 while (1) | |
| 7887 { | |
| 647 | 7888 int new_pos; |
| 665 | 7889 Charbpos start, end; |
| 428 | 7890 |
| 7891 pos = (bottom + top + 1) >> 1; | |
| 7892 start = Dynarr_atp (cache, pos)->start; | |
| 7893 end = Dynarr_atp (cache, pos)->end; | |
| 7894 | |
| 7895 if (point >= start && point <= end) | |
| 7896 { | |
| 7897 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b)) | |
| 7898 { | |
| 665 | 7899 Charbpos from = |
| 428 | 7900 find_next_newline_no_quit (b, line_start_cache_start (w), |
| 7901 -min_past - 1); | |
| 665 | 7902 Charbpos to = line_start_cache_end (w); |
| 428 | 7903 |
| 7904 update_line_start_cache (w, from, to, point, 0); | |
| 7905 goto find_point_loop; | |
| 7906 } | |
| 7907 else if ((Dynarr_length (cache) - pos - 1) < min_past | |
| 7908 && line_start_cache_end (w) < BUF_ZV (b)) | |
| 7909 { | |
| 665 | 7910 Charbpos from = line_start_cache_end (w); |
| 7911 Charbpos to = find_next_newline_no_quit (b, from, | |
| 428 | 7912 (min_past |
| 7913 ? min_past | |
| 7914 : 1)); | |
| 7915 | |
| 7916 update_line_start_cache (w, from, to, point, 0); | |
| 7917 goto find_point_loop; | |
| 7918 } | |
| 7919 else | |
| 7920 { | |
| 7921 w->line_cache_validation_override--; | |
| 7922 return pos; | |
| 7923 } | |
| 7924 } | |
| 7925 else if (point > end) | |
| 7926 bottom = pos + 1; | |
| 7927 else if (point < start) | |
| 7928 top = pos - 1; | |
| 7929 else | |
| 2500 | 7930 ABORT (); |
| 428 | 7931 |
| 7932 new_pos = (bottom + top + 1) >> 1; | |
| 7933 if (pos == new_pos) | |
| 7934 { | |
| 7935 w->line_cache_validation_override--; | |
| 7936 return -1; | |
| 7937 } | |
| 7938 } | |
| 7939 } | |
| 7940 | |
| 7941 /* Return a boolean indicating if POINT would be visible in window W | |
| 1708 | 7942 if display of the window was to begin at STARTP. If PARTIALLY is |
| 7943 zero, then if POINT has fewer visible pixels than the window clip, | |
| 7944 0 is returned; otherwise, 1 is returned if POINT has any visible | |
| 7945 pixels. */ | |
| 428 | 7946 int |
| 1708 | 7947 point_would_be_visible (struct window *w, Charbpos startp, Charbpos point, |
| 7948 int partially) | |
| 428 | 7949 { |
| 7950 struct buffer *b = XBUFFER (w->buffer); | |
| 430 | 7951 int pixpos = -WINDOW_TEXT_TOP_CLIP(w); |
| 428 | 7952 int bottom = WINDOW_TEXT_HEIGHT (w); |
| 7953 int start_elt; | |
| 7954 | |
| 7955 /* If point is before the intended start it obviously can't be visible. */ | |
| 7956 if (point < startp) | |
| 7957 return 0; | |
| 7958 | |
| 7959 /* If point or start are not in the accessible buffer range, then | |
| 7960 fail. */ | |
| 7961 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b) | |
| 7962 || point < BUF_BEGV (b) || point > BUF_ZV (b)) | |
| 7963 return 0; | |
| 7964 | |
| 7965 validate_line_start_cache (w); | |
| 7966 w->line_cache_validation_override++; | |
| 7967 | |
| 7968 start_elt = point_in_line_start_cache (w, startp, 0); | |
| 7969 if (start_elt == -1) | |
| 7970 { | |
| 7971 w->line_cache_validation_override--; | |
| 7972 return 0; | |
| 7973 } | |
| 7974 | |
| 7975 assert (line_start_cache_start (w) <= startp | |
| 7976 && line_start_cache_end (w) >= startp); | |
| 7977 | |
| 7978 while (1) | |
| 7979 { | |
| 7980 int height; | |
| 7981 | |
| 7982 /* Expand the cache if necessary. */ | |
| 7983 if (start_elt == Dynarr_length (w->line_start_cache)) | |
| 7984 { | |
| 665 | 7985 Charbpos old_startp = |
| 428 | 7986 Dynarr_atp (w->line_start_cache, start_elt - 1)->start; |
| 7987 | |
| 7988 start_elt = point_in_line_start_cache (w, old_startp, | |
| 7989 window_char_height (w, 0)); | |
| 7990 | |
| 7991 /* We've already actually processed old_startp, so increment | |
| 4187 | 7992 immediately. */ |
| 428 | 7993 start_elt++; |
| 7994 | |
| 7995 /* If this happens we didn't add any extra elements. Bummer. */ | |
| 7996 if (start_elt == Dynarr_length (w->line_start_cache)) | |
| 7997 { | |
| 7998 w->line_cache_validation_override--; | |
| 7999 return 0; | |
| 8000 } | |
| 8001 } | |
| 8002 | |
| 8003 height = Dynarr_atp (w->line_start_cache, start_elt)->height; | |
| 8004 | |
| 8005 if (pixpos + height > bottom) | |
| 8006 { | |
| 1708 | 8007 if (bottom - pixpos < (partially ? 0 : VERTICAL_CLIP (w, 0))) |
| 428 | 8008 { |
| 8009 w->line_cache_validation_override--; | |
| 8010 return 0; | |
| 8011 } | |
| 8012 } | |
| 8013 | |
| 8014 pixpos += height; | |
| 8015 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end) | |
| 8016 { | |
| 8017 w->line_cache_validation_override--; | |
| 8018 return 1; | |
| 8019 } | |
| 8020 | |
| 8021 start_elt++; | |
| 8022 } | |
| 8023 } | |
| 8024 | |
| 8025 /* For the given window W, if display starts at STARTP, what will be | |
| 8026 the buffer position at the beginning or end of the last line | |
| 8027 displayed. The end of the last line is also know as the window end | |
| 8028 position. | |
| 8029 | |
| 442 | 8030 WARNING: It is possible that redisplay failed to layout any lines for the |
| 8031 windows. Under normal circumstances this is rare. However it seems that it | |
| 8032 does occur in the following situation: A mouse event has come in and we | |
| 8033 need to compute its location in a window. That code (in | |
| 8034 pixel_to_glyph_translation) already can handle 0 as an error return value. | |
| 8035 | |
| 428 | 8036 #### With a little work this could probably be reworked as just a |
| 8037 call to start_with_line_at_pixpos. */ | |
| 8038 | |
| 665 | 8039 static Charbpos |
| 8040 start_end_of_last_line (struct window *w, Charbpos startp, int end, | |
| 4187 | 8041 int may_error) |
| 428 | 8042 { |
| 8043 struct buffer *b = XBUFFER (w->buffer); | |
| 8044 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 8045 int pixpos = 0; | |
| 8046 int bottom = WINDOW_TEXT_HEIGHT (w); | |
| 665 | 8047 Charbpos cur_start; |
| 428 | 8048 int start_elt; |
| 8049 | |
| 8050 validate_line_start_cache (w); | |
| 8051 w->line_cache_validation_override++; | |
| 8052 | |
| 8053 if (startp < BUF_BEGV (b)) | |
| 8054 startp = BUF_BEGV (b); | |
| 8055 else if (startp > BUF_ZV (b)) | |
| 8056 startp = BUF_ZV (b); | |
| 8057 cur_start = startp; | |
| 8058 | |
| 8059 start_elt = point_in_line_start_cache (w, cur_start, 0); | |
| 8060 if (start_elt == -1) | |
| 442 | 8061 return may_error ? 0 : startp; |
| 428 | 8062 |
| 8063 while (1) | |
| 8064 { | |
| 8065 int height = Dynarr_atp (cache, start_elt)->height; | |
| 8066 | |
| 8067 cur_start = Dynarr_atp (cache, start_elt)->start; | |
| 8068 | |
| 8069 if (pixpos + height > bottom) | |
| 8070 { | |
| 8071 /* Adjust for any possible clip. */ | |
| 8072 if (bottom - pixpos < VERTICAL_CLIP (w, 0)) | |
| 8073 start_elt--; | |
| 8074 | |
| 8075 if (start_elt < 0) | |
| 8076 { | |
| 8077 w->line_cache_validation_override--; | |
| 8078 if (end) | |
| 8079 return BUF_ZV (b); | |
| 8080 else | |
| 8081 return BUF_BEGV (b); | |
| 8082 } | |
| 8083 else | |
| 8084 { | |
| 8085 w->line_cache_validation_override--; | |
| 8086 if (end) | |
| 8087 return Dynarr_atp (cache, start_elt)->end; | |
| 8088 else | |
| 8089 return Dynarr_atp (cache, start_elt)->start; | |
| 8090 } | |
| 8091 } | |
| 8092 | |
| 8093 pixpos += height; | |
| 8094 start_elt++; | |
| 8095 if (start_elt == Dynarr_length (cache)) | |
| 8096 { | |
| 665 | 8097 Charbpos from = line_start_cache_end (w); |
| 428 | 8098 int win_char_height = window_char_height (w, 0); |
| 665 | 8099 Charbpos to = find_next_newline_no_quit (b, from, |
| 428 | 8100 (win_char_height |
| 8101 ? win_char_height | |
| 8102 : 1)); | |
| 8103 | |
| 8104 /* We've hit the end of the bottom so that's what it is. */ | |
| 8105 if (from >= BUF_ZV (b)) | |
| 8106 { | |
| 8107 w->line_cache_validation_override--; | |
| 8108 return BUF_ZV (b); | |
| 8109 } | |
| 8110 | |
| 8111 update_line_start_cache (w, from, to, BUF_PT (b), 0); | |
| 8112 | |
| 8113 /* Updating the cache invalidates any current indexes. */ | |
| 8114 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1; | |
| 8115 } | |
| 8116 } | |
| 8117 } | |
| 8118 | |
| 8119 /* For the given window W, if display starts at STARTP, what will be | |
| 8120 the buffer position at the beginning of the last line displayed. */ | |
| 8121 | |
| 665 | 8122 Charbpos |
| 8123 start_of_last_line (struct window *w, Charbpos startp) | |
| 428 | 8124 { |
| 442 | 8125 return start_end_of_last_line (w, startp, 0 , 0); |
| 428 | 8126 } |
| 8127 | |
| 8128 /* For the given window W, if display starts at STARTP, what will be | |
| 8129 the buffer position at the end of the last line displayed. This is | |
| 8130 also know as the window end position. */ | |
| 8131 | |
| 665 | 8132 Charbpos |
| 8133 end_of_last_line (struct window *w, Charbpos startp) | |
| 428 | 8134 { |
| 442 | 8135 return start_end_of_last_line (w, startp, 1, 0); |
| 428 | 8136 } |
| 8137 | |
| 665 | 8138 static Charbpos |
| 8139 end_of_last_line_may_error (struct window *w, Charbpos startp) | |
| 442 | 8140 { |
| 8141 return start_end_of_last_line (w, startp, 1, 1); | |
| 8142 } | |
| 8143 | |
| 8144 | |
| 428 | 8145 /* For window W, what does the starting position have to be so that |
| 8146 the line containing POINT will cover pixel position PIXPOS. */ | |
| 8147 | |
| 665 | 8148 Charbpos |
| 8149 start_with_line_at_pixpos (struct window *w, Charbpos point, int pixpos) | |
| 428 | 8150 { |
| 8151 struct buffer *b = XBUFFER (w->buffer); | |
| 8152 int cur_elt; | |
| 665 | 8153 Charbpos cur_pos, prev_pos = point; |
| 428 | 8154 int point_line_height; |
| 8155 int pixheight = pixpos - WINDOW_TEXT_TOP (w); | |
| 8156 | |
| 8157 validate_line_start_cache (w); | |
| 8158 w->line_cache_validation_override++; | |
| 8159 | |
| 8160 cur_elt = point_in_line_start_cache (w, point, 0); | |
| 8161 /* #### See comment in update_line_start_cache about big minibuffers. */ | |
| 8162 if (cur_elt < 0) | |
| 8163 { | |
| 8164 w->line_cache_validation_override--; | |
| 8165 return point; | |
| 8166 } | |
| 8167 | |
| 8168 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
| 8169 | |
| 8170 while (1) | |
| 8171 { | |
| 8172 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
| 8173 | |
| 8174 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
| 8175 | |
| 8176 /* Do not take into account the value of vertical_clip here. | |
| 4187 | 8177 That is the responsibility of the calling functions. */ |
| 428 | 8178 if (pixheight < 0) |
| 8179 { | |
| 8180 w->line_cache_validation_override--; | |
| 8181 if (-pixheight > point_line_height) | |
| 8182 /* We can't make the target line cover pixpos, so put it | |
| 8183 above pixpos. That way it will at least be visible. */ | |
| 8184 return prev_pos; | |
| 8185 else | |
| 8186 return cur_pos; | |
| 8187 } | |
| 8188 | |
| 8189 cur_elt--; | |
| 8190 while (cur_elt < 0) | |
| 8191 { | |
| 665 | 8192 Charbpos from, to; |
| 428 | 8193 int win_char_height; |
| 8194 | |
| 8195 if (cur_pos <= BUF_BEGV (b)) | |
| 8196 { | |
| 8197 w->line_cache_validation_override--; | |
| 8198 return BUF_BEGV (b); | |
| 8199 } | |
| 8200 | |
| 8201 win_char_height = window_char_height (w, 0); | |
| 8202 if (!win_char_height) | |
| 8203 win_char_height = 1; | |
| 8204 | |
| 8205 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); | |
| 8206 to = line_start_cache_end (w); | |
| 8207 update_line_start_cache (w, from, to, point, 0); | |
| 8208 | |
| 8209 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; | |
| 8210 assert (cur_elt >= -1); | |
| 8211 /* This used to be cur_elt>=0 under the assumption that if | |
| 8212 point is in the top line and not at BUF_BEGV, then | |
| 434 | 8213 setting the window_start to a newline before the start of |
| 428 | 8214 the first line will always cause scrolling. |
| 8215 | |
| 8216 However in my (jv) opinion this is wrong. That new line | |
| 8217 can be hidden in various ways: invisible extents, an | |
| 8218 explicit window-start not at a newline character etc. | |
| 8219 The existence of those are indeed known to create crashes | |
| 8220 on that assert. So we have no option but to continue the | |
| 8221 search if we found point at the top of the line_start_cache | |
| 8222 again. */ | |
| 434 | 8223 cur_pos = Dynarr_atp (w->line_start_cache,0)->start; |
| 428 | 8224 } |
| 8225 prev_pos = cur_pos; | |
| 8226 } | |
| 8227 } | |
| 8228 | |
| 8229 /* For window W, what does the starting position have to be so that | |
| 8230 the line containing point is on display line LINE. If LINE is | |
| 8231 positive it is considered to be the number of lines from the top of | |
| 8232 the window (0 is the top line). If it is negative the number is | |
| 8233 considered to be the number of lines from the bottom (-1 is the | |
| 8234 bottom line). */ | |
| 8235 | |
| 665 | 8236 Charbpos |
| 8237 start_with_point_on_display_line (struct window *w, Charbpos point, int line) | |
| 428 | 8238 { |
| 8239 validate_line_start_cache (w); | |
| 8240 w->line_cache_validation_override++; | |
| 8241 | |
| 8242 if (line >= 0) | |
| 8243 { | |
| 8244 int cur_elt = point_in_line_start_cache (w, point, line); | |
| 8245 | |
| 8246 if (cur_elt - line < 0) | |
| 8247 cur_elt = 0; /* Hit the top */ | |
| 8248 else | |
| 8249 cur_elt -= line; | |
| 8250 | |
| 8251 w->line_cache_validation_override--; | |
| 8252 return Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
| 8253 } | |
| 8254 else | |
| 8255 { | |
| 8256 /* The calculated value of pixpos is correct for the bottom line | |
| 4187 | 8257 or what we want when line is -1. Therefore we subtract one |
| 8258 because we have already handled one line. */ | |
| 428 | 8259 int new_line = -line - 1; |
| 8260 int cur_elt = point_in_line_start_cache (w, point, new_line); | |
| 8261 int pixpos = WINDOW_TEXT_BOTTOM (w); | |
| 665 | 8262 Charbpos retval, search_point; |
| 428 | 8263 |
| 8264 /* If scroll_on_clipped_lines is false, the last "visible" line of | |
| 4187 | 8265 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1. |
| 8266 If s_o_c_l is true, then we don't want to count a clipped | |
| 8267 line, so back up from the bottom by the height of the line | |
| 8268 containing point. */ | |
| 428 | 8269 if (scroll_on_clipped_lines) |
| 8270 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
| 8271 else | |
| 8272 pixpos -= 1; | |
| 8273 | |
| 8274 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache)) | |
| 8275 { | |
| 8276 /* Hit the bottom of the buffer. */ | |
| 8277 int adjustment = | |
| 8278 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1; | |
| 8279 Lisp_Object window; | |
| 8280 int defheight; | |
| 8281 | |
| 793 | 8282 window = wrap_window (w); |
| 428 | 8283 default_face_height_and_width (window, &defheight, 0); |
| 8284 | |
| 8285 cur_elt = Dynarr_length (w->line_start_cache) - 1; | |
| 8286 | |
| 8287 pixpos -= (adjustment * defheight); | |
| 8288 if (pixpos < WINDOW_TEXT_TOP (w)) | |
| 8289 pixpos = WINDOW_TEXT_TOP (w); | |
| 8290 } | |
| 8291 else | |
| 8292 cur_elt = cur_elt + new_line; | |
| 8293 | |
| 8294 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
| 8295 | |
| 8296 retval = start_with_line_at_pixpos (w, search_point, pixpos); | |
| 8297 w->line_cache_validation_override--; | |
| 8298 return retval; | |
| 8299 } | |
| 8300 } | |
| 8301 | |
| 8302 /* This is used to speed up vertical scrolling by caching the known | |
| 8303 buffer starting positions for display lines. This allows the | |
| 8304 scrolling routines to avoid costly calls to regenerate_window. If | |
| 8305 NO_REGEN is true then it will only add the values in the DESIRED | |
| 8306 display structs which are in the given range. | |
| 8307 | |
| 8308 Note also that the FROM/TO values are minimums. It is possible | |
| 8309 that this function will actually add information outside of the | |
| 8310 lines containing those positions. This can't hurt but it could | |
| 8311 possibly help. | |
| 8312 | |
| 8313 #### We currently force the cache to have only 1 contiguous region. | |
| 8314 It might help to make the cache a dynarr of caches so that we can | |
| 8315 cover more areas. This might, however, turn out to be a lot of | |
| 8316 overhead for too little gain. */ | |
| 8317 | |
| 8318 static void | |
| 665 | 8319 update_line_start_cache (struct window *w, Charbpos from, Charbpos to, |
| 8320 Charbpos point, int no_regen) | |
| 428 | 8321 { |
| 8322 struct buffer *b = XBUFFER (w->buffer); | |
| 8323 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 665 | 8324 Charbpos low_bound, high_bound; |
| 428 | 8325 |
| 8326 validate_line_start_cache (w); | |
| 8327 w->line_cache_validation_override++; | |
| 8328 | |
| 8329 if (from < BUF_BEGV (b)) | |
| 8330 from = BUF_BEGV (b); | |
| 8331 if (to > BUF_ZV (b)) | |
| 8332 to = BUF_ZV (b); | |
| 8333 | |
| 8334 if (from > to) | |
| 8335 { | |
| 8336 w->line_cache_validation_override--; | |
| 8337 return; | |
| 8338 } | |
| 8339 | |
| 8340 if (Dynarr_length (cache)) | |
| 8341 { | |
| 8342 low_bound = line_start_cache_start (w); | |
| 8343 high_bound = line_start_cache_end (w); | |
| 8344 | |
| 8345 /* Check to see if the desired range is already in the cache. */ | |
| 8346 if (from >= low_bound && to <= high_bound) | |
| 8347 { | |
| 8348 w->line_cache_validation_override--; | |
| 8349 return; | |
| 8350 } | |
| 8351 | |
| 8352 /* Check to make sure that the desired range is adjacent to the | |
| 8353 current cache. If not, invalidate the cache. */ | |
| 8354 if (to < low_bound || from > high_bound) | |
| 8355 { | |
| 8356 Dynarr_reset (cache); | |
| 8357 low_bound = high_bound = -1; | |
| 8358 } | |
| 8359 } | |
| 8360 else | |
| 8361 { | |
| 8362 low_bound = high_bound = -1; | |
| 8363 } | |
| 8364 | |
| 8365 w->line_cache_last_updated = make_int (BUF_MODIFF (b)); | |
| 8366 | |
| 8367 /* This could be integrated into the next two sections, but it is easier | |
| 8368 to follow what's going on by having it separate. */ | |
| 8369 if (no_regen) | |
| 8370 { | |
| 665 | 8371 Charbpos start, end; |
| 428 | 8372 |
| 8373 update_internal_cache_list (w, DESIRED_DISP); | |
| 8374 if (!Dynarr_length (internal_cache)) | |
| 8375 { | |
| 8376 w->line_cache_validation_override--; | |
| 8377 return; | |
| 8378 } | |
| 8379 | |
| 8380 start = Dynarr_atp (internal_cache, 0)->start; | |
| 8381 end = | |
| 8382 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end; | |
| 8383 | |
| 8384 /* We aren't allowed to generate additional information to fill in | |
| 4187 | 8385 gaps, so if the DESIRED structs don't overlap the cache, reset the |
| 8386 cache. */ | |
| 428 | 8387 if (Dynarr_length (cache)) |
| 8388 { | |
| 8389 if (end < low_bound || start > high_bound) | |
| 8390 Dynarr_reset (cache); | |
| 8391 | |
| 8392 /* #### What should really happen if what we are doing is | |
| 4187 | 8393 extending a line (the last line)? */ |
| 428 | 8394 if (Dynarr_length (cache) == 1 |
| 8395 && Dynarr_length (internal_cache) == 1) | |
| 8396 Dynarr_reset (cache); | |
| 8397 } | |
| 8398 | |
| 8399 if (!Dynarr_length (cache)) | |
| 8400 { | |
| 8401 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), | |
| 8402 Dynarr_length (internal_cache)); | |
| 8403 w->line_cache_validation_override--; | |
| 8404 return; | |
| 8405 } | |
| 8406 | |
| 8407 /* An extra check just in case the calling function didn't pass in | |
| 4187 | 8408 the bounds of the DESIRED structs in the first place. */ |
| 428 | 8409 if (start >= low_bound && end <= high_bound) |
| 8410 { | |
| 8411 w->line_cache_validation_override--; | |
| 8412 return; | |
| 8413 } | |
| 8414 | |
| 8415 /* At this point we know that the internal cache partially overlaps | |
| 4187 | 8416 the main cache. */ |
| 428 | 8417 if (start < low_bound) |
| 8418 { | |
| 8419 int ic_elt = Dynarr_length (internal_cache) - 1; | |
| 8420 while (ic_elt >= 0) | |
| 8421 { | |
| 8422 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound) | |
| 8423 break; | |
| 8424 else | |
| 8425 ic_elt--; | |
| 8426 } | |
| 8427 | |
| 8428 if (!(ic_elt >= 0)) | |
| 8429 { | |
| 8430 Dynarr_reset (cache); | |
| 8431 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), | |
| 8432 Dynarr_length (internal_cache)); | |
| 8433 w->line_cache_validation_override--; | |
| 8434 return; | |
| 8435 } | |
| 8436 | |
| 8437 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0), | |
| 8438 ic_elt + 1); | |
| 8439 } | |
| 8440 | |
| 8441 if (end > high_bound) | |
| 8442 { | |
| 8443 int ic_elt = 0; | |
| 8444 | |
| 8445 while (ic_elt < Dynarr_length (internal_cache)) | |
| 8446 { | |
| 8447 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound) | |
| 8448 break; | |
| 8449 else | |
| 8450 ic_elt++; | |
| 8451 } | |
| 8452 | |
| 8453 if (!(ic_elt < Dynarr_length (internal_cache))) | |
| 8454 { | |
| 8455 Dynarr_reset (cache); | |
| 8456 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), | |
| 8457 Dynarr_length (internal_cache)); | |
| 8458 w->line_cache_validation_override--; | |
| 8459 return; | |
| 8460 } | |
| 8461 | |
| 8462 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), | |
| 8463 Dynarr_length (internal_cache) - ic_elt); | |
| 8464 } | |
| 8465 | |
| 8466 w->line_cache_validation_override--; | |
| 8467 return; | |
| 8468 } | |
| 8469 | |
| 8470 if (!Dynarr_length (cache) || from < low_bound) | |
| 8471 { | |
| 665 | 8472 Charbpos startp = find_next_newline_no_quit (b, from, -1); |
| 428 | 8473 int marker = 0; |
| 8474 int old_lb = low_bound; | |
| 8475 | |
| 8476 while (startp < old_lb || low_bound == -1) | |
| 8477 { | |
| 8478 int ic_elt; | |
| 4187 | 8479 Charbpos new_startp; |
| 428 | 8480 |
| 8481 regenerate_window (w, startp, point, CMOTION_DISP); | |
| 8482 update_internal_cache_list (w, CMOTION_DISP); | |
| 8483 | |
| 8484 /* If this assert is triggered then regenerate_window failed | |
| 4187 | 8485 to layout a single line. This is not possible since we |
| 442 | 8486 force at least a single line to be layout for CMOTION_DISP */ |
| 8487 assert (Dynarr_length (internal_cache)); | |
| 428 | 8488 assert (startp == Dynarr_atp (internal_cache, 0)->start); |
| 8489 | |
| 8490 ic_elt = Dynarr_length (internal_cache) - 1; | |
| 8491 if (low_bound != -1) | |
| 8492 { | |
| 8493 while (ic_elt >= 0) | |
| 8494 { | |
| 8495 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb) | |
| 8496 break; | |
| 8497 else | |
| 8498 ic_elt--; | |
| 8499 } | |
| 8500 } | |
| 8501 assert (ic_elt >= 0); | |
| 8502 | |
| 8503 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1; | |
| 8504 | |
| 4187 | 8505 /* |
| 8506 * Handle invisible text properly: | |
| 8507 * If the last line we're inserting has the same end as the | |
| 8508 * line before which it will be added, merge the two lines. | |
| 8509 */ | |
| 8510 if (Dynarr_length (cache) && | |
| 8511 Dynarr_atp (internal_cache, ic_elt)->end == | |
| 8512 Dynarr_atp (cache, marker)->end) | |
| 8513 { | |
| 8514 Dynarr_atp (cache, marker)->start | |
| 8515 = Dynarr_atp (internal_cache, ic_elt)->start; | |
| 8516 Dynarr_atp (cache, marker)->height | |
| 8517 = Dynarr_atp (internal_cache, ic_elt)->height; | |
| 8518 ic_elt--; | |
| 8519 } | |
| 8520 | |
| 8521 if (ic_elt >= 0) /* we still have lines to add.. */ | |
| 8522 { | |
| 8523 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0), | |
| 8524 ic_elt + 1, marker); | |
| 8525 marker += (ic_elt + 1); | |
| 8526 } | |
| 428 | 8527 |
| 8528 if (startp < low_bound || low_bound == -1) | |
| 8529 low_bound = startp; | |
| 8530 startp = new_startp; | |
| 8531 if (startp > BUF_ZV (b)) | |
| 8532 { | |
| 8533 w->line_cache_validation_override--; | |
| 8534 return; | |
| 8535 } | |
| 8536 } | |
| 8537 } | |
| 8538 | |
| 8539 assert (Dynarr_length (cache)); | |
| 8540 assert (from >= low_bound); | |
| 8541 | |
| 8542 /* Readjust the high_bound to account for any changes made while | |
| 8543 correcting the low_bound. */ | |
| 8544 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end; | |
| 8545 | |
| 8546 if (to > high_bound) | |
| 8547 { | |
| 665 | 8548 Charbpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1; |
| 428 | 8549 |
| 8550 do | |
| 8551 { | |
| 8552 regenerate_window (w, startp, point, CMOTION_DISP); | |
| 8553 update_internal_cache_list (w, CMOTION_DISP); | |
| 8554 | |
| 8555 /* See comment above about regenerate_window failing. */ | |
| 8556 assert (Dynarr_length (internal_cache)); | |
| 8557 | |
| 8558 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), | |
| 8559 Dynarr_length (internal_cache)); | |
| 8560 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end; | |
| 8561 startp = high_bound + 1; | |
| 8562 } | |
| 8563 while (to > high_bound); | |
| 8564 } | |
| 8565 | |
| 8566 w->line_cache_validation_override--; | |
| 8567 assert (to <= high_bound); | |
| 8568 } | |
| 8569 | |
| 8570 | |
| 8571 /* Given x and y coordinates in characters, relative to a window, | |
| 8572 return the pixel location corresponding to those coordinates. The | |
| 8573 pixel location returned is the center of the given character | |
| 8574 position. The pixel values are generated relative to the window, | |
| 8575 not the frame. | |
| 8576 | |
| 8577 The modeline is considered to be part of the window. */ | |
| 8578 | |
| 8579 void | |
| 8580 glyph_to_pixel_translation (struct window *w, int char_x, int char_y, | |
| 8581 int *pix_x, int *pix_y) | |
| 8582 { | |
| 8583 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
| 8584 int num_disp_lines, modeline; | |
| 8585 Lisp_Object window; | |
| 8586 int defheight, defwidth; | |
| 8587 | |
| 793 | 8588 window = wrap_window (w); |
| 428 | 8589 default_face_height_and_width (window, &defheight, &defwidth); |
| 8590 | |
| 8591 /* If we get a bogus value indicating somewhere above or to the left of | |
| 8592 the window, use the first window line or character position | |
| 8593 instead. */ | |
| 8594 if (char_y < 0) | |
| 8595 char_y = 0; | |
| 8596 if (char_x < 0) | |
| 8597 char_x = 0; | |
| 8598 | |
| 8599 num_disp_lines = Dynarr_length (dla); | |
| 8600 modeline = 0; | |
| 8601 if (num_disp_lines) | |
| 8602 { | |
| 8603 if (Dynarr_atp (dla, 0)->modeline) | |
| 8604 { | |
| 8605 num_disp_lines--; | |
| 8606 modeline = 1; | |
| 8607 } | |
| 8608 } | |
| 8609 | |
| 8610 /* First check if the y position intersects the display lines. */ | |
| 8611 if (char_y < num_disp_lines) | |
| 8612 { | |
| 8613 struct display_line *dl = Dynarr_atp (dla, char_y + modeline); | |
| 8614 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 8615 | |
| 8616 *pix_y = (dl->ypos - dl->ascent + | |
| 647 | 8617 ((dl->ascent + dl->descent - dl->clip) >> 1)); |
| 428 | 8618 |
| 8619 if (char_x < Dynarr_length (db->runes)) | |
| 8620 { | |
| 8621 struct rune *rb = Dynarr_atp (db->runes, char_x); | |
| 8622 | |
| 8623 *pix_x = rb->xpos + (rb->width >> 1); | |
| 8624 } | |
| 8625 else | |
| 8626 { | |
| 8627 int last_rune = Dynarr_length (db->runes) - 1; | |
| 8628 struct rune *rb = Dynarr_atp (db->runes, last_rune); | |
| 8629 | |
| 8630 char_x -= last_rune; | |
| 8631 | |
| 8632 *pix_x = rb->xpos + rb->width; | |
| 8633 *pix_x += ((char_x - 1) * defwidth); | |
| 8634 *pix_x += (defwidth >> 1); | |
| 8635 } | |
| 8636 } | |
| 8637 else | |
| 8638 { | |
| 8639 /* It didn't intersect, so extrapolate. #### For now, we include the | |
| 8640 modeline in this since we don't have true character positions in | |
| 8641 it. */ | |
| 8642 | |
| 8643 if (!Dynarr_length (w->face_cachels)) | |
| 8644 reset_face_cachels (w); | |
| 8645 | |
| 8646 char_y -= num_disp_lines; | |
| 8647 | |
| 8648 if (Dynarr_length (dla)) | |
| 8649 { | |
| 8650 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1); | |
| 8651 *pix_y = dl->ypos + dl->descent - dl->clip; | |
| 8652 } | |
| 8653 else | |
| 8654 *pix_y = WINDOW_TEXT_TOP (w); | |
| 8655 | |
| 8656 *pix_y += (char_y * defheight); | |
| 8657 *pix_y += (defheight >> 1); | |
| 8658 | |
| 8659 *pix_x = WINDOW_TEXT_LEFT (w); | |
| 8660 /* Don't adjust by one because this is still the unadjusted value. */ | |
| 8661 *pix_x += (char_x * defwidth); | |
| 8662 *pix_x += (defwidth >> 1); | |
| 8663 } | |
| 8664 | |
| 8665 if (*pix_x > w->pixel_left + w->pixel_width) | |
| 8666 *pix_x = w->pixel_left + w->pixel_width; | |
| 8667 if (*pix_y > w->pixel_top + w->pixel_height) | |
| 8668 *pix_y = w->pixel_top + w->pixel_height; | |
| 8669 | |
| 8670 *pix_x -= w->pixel_left; | |
| 8671 *pix_y -= w->pixel_top; | |
| 8672 } | |
| 8673 | |
| 8674 /* Given a display line and a position, determine if there is a glyph | |
| 8675 there and return information about it if there is. */ | |
| 8676 | |
| 8677 static void | |
| 8678 get_position_object (struct display_line *dl, Lisp_Object *obj1, | |
| 8679 Lisp_Object *obj2, int x_coord, int *low_x_coord, | |
| 8680 int *high_x_coord) | |
| 8681 { | |
| 8682 struct display_block *db; | |
| 8683 int elt; | |
| 8684 int block = | |
| 8685 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0); | |
| 8686 | |
| 8687 /* We use get_next_display_block to get the actual display block | |
| 8688 that would be displayed at x_coord. */ | |
| 8689 | |
| 8690 if (block == NO_BLOCK) | |
| 8691 return; | |
| 8692 else | |
| 8693 db = Dynarr_atp (dl->display_blocks, block); | |
| 8694 | |
| 8695 for (elt = 0; elt < Dynarr_length (db->runes); elt++) | |
| 8696 { | |
| 8697 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 8698 | |
| 8699 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) | |
| 8700 { | |
| 8701 if (rb->type == RUNE_DGLYPH) | |
| 8702 { | |
| 8703 *obj1 = rb->object.dglyph.glyph; | |
| 8704 *obj2 = rb->object.dglyph.extent; | |
| 8705 } | |
| 8706 else | |
| 8707 { | |
| 8708 *obj1 = Qnil; | |
| 8709 *obj2 = Qnil; | |
| 8710 } | |
| 8711 | |
| 8712 if (low_x_coord) | |
| 8713 *low_x_coord = rb->xpos; | |
| 8714 if (high_x_coord) | |
| 8715 *high_x_coord = rb->xpos + rb->width; | |
| 8716 | |
| 8717 return; | |
| 8718 } | |
| 8719 } | |
| 8720 } | |
| 8721 | |
| 8722 #define UPDATE_CACHE_RETURN \ | |
| 8723 do { \ | |
| 8724 d->pixel_to_glyph_cache.valid = 1; \ | |
| 8725 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \ | |
| 8726 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \ | |
| 8727 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \ | |
| 8728 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \ | |
| 8729 d->pixel_to_glyph_cache.frame = f; \ | |
| 8730 d->pixel_to_glyph_cache.col = *col; \ | |
| 8731 d->pixel_to_glyph_cache.row = *row; \ | |
| 8732 d->pixel_to_glyph_cache.obj_x = *obj_x; \ | |
| 8733 d->pixel_to_glyph_cache.obj_y = *obj_y; \ | |
| 8734 d->pixel_to_glyph_cache.w = *w; \ | |
| 826 | 8735 d->pixel_to_glyph_cache.charpos = *charpos; \ |
| 428 | 8736 d->pixel_to_glyph_cache.closest = *closest; \ |
| 8737 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \ | |
| 8738 d->pixel_to_glyph_cache.obj1 = *obj1; \ | |
| 8739 d->pixel_to_glyph_cache.obj2 = *obj2; \ | |
| 8740 d->pixel_to_glyph_cache.retval = position; \ | |
| 8741 RETURN_SANS_WARNINGS position; \ | |
| 8742 } while (0) | |
| 8743 | |
| 8744 /* Given x and y coordinates in pixels relative to a frame, return | |
| 8745 information about what is located under those coordinates. | |
| 8746 | |
| 8747 The return value will be one of: | |
| 8748 | |
| 8749 OVER_TOOLBAR: over one of the 4 frame toolbars | |
| 8750 OVER_MODELINE: over a modeline | |
| 8751 OVER_BORDER: over an internal border | |
| 8752 OVER_NOTHING: over the text area, but not over text | |
| 8753 OVER_OUTSIDE: outside of the frame border | |
| 8754 OVER_TEXT: over text in the text area | |
| 8755 | |
| 8756 OBJ1 is one of | |
| 8757 | |
| 8758 -- a toolbar button | |
| 8759 -- a glyph | |
| 8760 -- nil if the coordinates are not over a glyph or a toolbar button. | |
| 8761 | |
| 8762 OBJ2 is one of | |
| 8763 | |
| 8764 -- an extent, if the coordinates are over a glyph in the text area | |
| 8765 -- nil otherwise. | |
| 8766 | |
| 8767 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the | |
| 8768 equivalent coordinates relative to the upper-left corner of the glyph. | |
| 8769 | |
| 8770 If the coordinates are over a character, OBJ_X and OBJ_Y give the | |
| 8771 equivalent coordinates relative to the upper-left corner of the character. | |
| 8772 | |
| 8773 Otherwise, OBJ_X and OBJ_Y are undefined. | |
| 8774 */ | |
| 8775 | |
| 8776 int | |
| 8777 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, | |
| 8778 int *col, int *row, int *obj_x, int *obj_y, | |
| 826 | 8779 struct window **w, Charbpos *charpos, |
| 665 | 8780 Charbpos *closest, Charcount *modeline_closest, |
| 428 | 8781 Lisp_Object *obj1, Lisp_Object *obj2) |
| 8782 { | |
| 8783 struct device *d; | |
| 8784 struct pixel_to_glyph_translation_cache *cache; | |
| 8785 Lisp_Object window; | |
| 8786 int frm_left, frm_right, frm_top, frm_bottom; | |
| 8787 int low_x_coord, high_x_coord, low_y_coord, high_y_coord; | |
| 8788 int position = OVER_NOTHING; | |
| 8789 int device_check_failed = 0; | |
| 8790 display_line_dynarr *dla; | |
| 8791 | |
| 8792 /* This is a safety valve in case this got called with a frame in | |
| 8793 the middle of being deleted. */ | |
| 8794 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device))) | |
| 8795 { | |
| 8796 device_check_failed = 1; | |
| 8797 d = NULL, cache = NULL; /* Warning suppression */ | |
| 8798 } | |
| 8799 else | |
| 8800 { | |
| 8801 d = XDEVICE (f->device); | |
| 8802 cache = &d->pixel_to_glyph_cache; | |
| 8803 } | |
| 8804 | |
| 8805 if (!device_check_failed | |
| 8806 && cache->valid | |
| 8807 && cache->frame == f | |
| 8808 && cache->low_x_coord <= x_coord | |
| 8809 && cache->high_x_coord > x_coord | |
| 8810 && cache->low_y_coord <= y_coord | |
| 8811 && cache->high_y_coord > y_coord) | |
| 8812 { | |
| 8813 *col = cache->col; | |
| 8814 *row = cache->row; | |
| 8815 *obj_x = cache->obj_x; | |
| 8816 *obj_y = cache->obj_y; | |
| 8817 *w = cache->w; | |
| 826 | 8818 *charpos = cache->charpos; |
| 428 | 8819 *closest = cache->closest; |
| 8820 *modeline_closest = cache->modeline_closest; | |
| 8821 *obj1 = cache->obj1; | |
| 8822 *obj2 = cache->obj2; | |
| 8823 | |
| 8824 return cache->retval; | |
| 8825 } | |
| 8826 else | |
| 8827 { | |
| 8828 *col = 0; | |
| 8829 *row = 0; | |
| 8830 *obj_x = 0; | |
| 8831 *obj_y = 0; | |
| 8832 *w = 0; | |
| 826 | 8833 *charpos = 0; |
| 428 | 8834 *closest = 0; |
| 8835 *modeline_closest = -1; | |
| 8836 *obj1 = Qnil; | |
| 8837 *obj2 = Qnil; | |
| 8838 | |
| 8839 low_x_coord = x_coord; | |
| 8840 high_x_coord = x_coord + 1; | |
| 8841 low_y_coord = y_coord; | |
| 8842 high_y_coord = y_coord + 1; | |
| 8843 } | |
| 8844 | |
| 8845 if (device_check_failed) | |
| 8846 return OVER_NOTHING; | |
| 8847 | |
| 8848 frm_left = FRAME_LEFT_BORDER_END (f); | |
| 8849 frm_right = FRAME_RIGHT_BORDER_START (f); | |
| 8850 frm_top = FRAME_TOP_BORDER_END (f); | |
| 8851 frm_bottom = FRAME_BOTTOM_BORDER_START (f); | |
| 8852 | |
| 8853 /* Check if the mouse is outside of the text area actually used by | |
| 8854 redisplay. */ | |
| 8855 if (y_coord < frm_top) | |
| 8856 { | |
| 8857 if (y_coord >= FRAME_TOP_BORDER_START (f)) | |
| 8858 { | |
| 8859 low_y_coord = FRAME_TOP_BORDER_START (f); | |
| 8860 high_y_coord = frm_top; | |
| 8861 position = OVER_BORDER; | |
| 8862 } | |
| 8863 else if (y_coord >= 0) | |
| 8864 { | |
| 8865 low_y_coord = 0; | |
| 8866 high_y_coord = FRAME_TOP_BORDER_START (f); | |
| 8867 position = OVER_TOOLBAR; | |
| 8868 } | |
| 8869 else | |
| 8870 { | |
| 8871 low_y_coord = y_coord; | |
| 8872 high_y_coord = 0; | |
| 8873 position = OVER_OUTSIDE; | |
| 8874 } | |
| 8875 } | |
| 8876 else if (y_coord >= frm_bottom) | |
| 8877 { | |
| 8878 if (y_coord < FRAME_BOTTOM_BORDER_END (f)) | |
| 8879 { | |
| 8880 low_y_coord = frm_bottom; | |
| 8881 high_y_coord = FRAME_BOTTOM_BORDER_END (f); | |
| 8882 position = OVER_BORDER; | |
| 8883 } | |
| 8884 else if (y_coord < FRAME_PIXHEIGHT (f)) | |
| 8885 { | |
| 8886 low_y_coord = FRAME_BOTTOM_BORDER_END (f); | |
| 8887 high_y_coord = FRAME_PIXHEIGHT (f); | |
| 8888 position = OVER_TOOLBAR; | |
| 8889 } | |
| 8890 else | |
| 8891 { | |
| 8892 low_y_coord = FRAME_PIXHEIGHT (f); | |
| 8893 high_y_coord = y_coord; | |
| 8894 position = OVER_OUTSIDE; | |
| 8895 } | |
| 8896 } | |
| 8897 | |
| 8898 if (position != OVER_TOOLBAR && position != OVER_BORDER) | |
| 8899 { | |
| 8900 if (x_coord < frm_left) | |
| 8901 { | |
| 8902 if (x_coord >= FRAME_LEFT_BORDER_START (f)) | |
| 8903 { | |
| 8904 low_x_coord = FRAME_LEFT_BORDER_START (f); | |
| 8905 high_x_coord = frm_left; | |
| 8906 position = OVER_BORDER; | |
| 8907 } | |
| 8908 else if (x_coord >= 0) | |
| 8909 { | |
| 8910 low_x_coord = 0; | |
| 8911 high_x_coord = FRAME_LEFT_BORDER_START (f); | |
| 8912 position = OVER_TOOLBAR; | |
| 8913 } | |
| 8914 else | |
| 8915 { | |
| 8916 low_x_coord = x_coord; | |
| 8917 high_x_coord = 0; | |
| 8918 position = OVER_OUTSIDE; | |
| 8919 } | |
| 8920 } | |
| 8921 else if (x_coord >= frm_right) | |
| 8922 { | |
| 8923 if (x_coord < FRAME_RIGHT_BORDER_END (f)) | |
| 8924 { | |
| 8925 low_x_coord = frm_right; | |
| 8926 high_x_coord = FRAME_RIGHT_BORDER_END (f); | |
| 8927 position = OVER_BORDER; | |
| 8928 } | |
| 8929 else if (x_coord < FRAME_PIXWIDTH (f)) | |
| 8930 { | |
| 8931 low_x_coord = FRAME_RIGHT_BORDER_END (f); | |
| 8932 high_x_coord = FRAME_PIXWIDTH (f); | |
| 8933 position = OVER_TOOLBAR; | |
| 8934 } | |
| 8935 else | |
| 8936 { | |
| 8937 low_x_coord = FRAME_PIXWIDTH (f); | |
| 8938 high_x_coord = x_coord; | |
| 8939 position = OVER_OUTSIDE; | |
| 8940 } | |
| 8941 } | |
| 8942 } | |
| 8943 | |
| 8944 #ifdef HAVE_TOOLBARS | |
| 8945 if (position == OVER_TOOLBAR) | |
| 8946 { | |
| 8947 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord); | |
| 8948 *obj2 = Qnil; | |
| 8949 *w = 0; | |
| 8950 UPDATE_CACHE_RETURN; | |
| 8951 } | |
| 8952 #endif /* HAVE_TOOLBARS */ | |
| 8953 | |
| 8954 /* We still have to return the window the pointer is next to and its | |
| 8955 relative y position even if it is outside the x boundary. */ | |
| 8956 if (x_coord < frm_left) | |
| 8957 x_coord = frm_left; | |
| 8958 else if (x_coord > frm_right) | |
| 8959 x_coord = frm_right; | |
| 8960 | |
| 8961 /* Same in reverse. */ | |
| 8962 if (y_coord < frm_top) | |
| 8963 y_coord = frm_top; | |
| 8964 else if (y_coord > frm_bottom) | |
| 8965 y_coord = frm_bottom; | |
| 8966 | |
| 8967 /* Find what window the given coordinates are actually in. */ | |
| 8968 window = f->root_window; | |
| 8969 *w = find_window_by_pixel_pos (x_coord, y_coord, window); | |
| 8970 | |
| 8971 /* If we didn't find a window, we're done. */ | |
| 8972 if (!*w) | |
| 8973 { | |
| 8974 UPDATE_CACHE_RETURN; | |
| 8975 } | |
| 8976 else if (position != OVER_NOTHING) | |
| 8977 { | |
| 8978 *closest = 0; | |
| 8979 *modeline_closest = -1; | |
| 8980 | |
| 8981 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) | |
| 8982 { | |
| 8983 *w = 0; | |
| 8984 UPDATE_CACHE_RETURN; | |
| 8985 } | |
| 8986 } | |
| 8987 | |
| 8988 /* Check if the window is a minibuffer but isn't active. */ | |
| 8989 if (MINI_WINDOW_P (*w) && !minibuf_level) | |
| 8990 { | |
| 8991 /* Must reset the window value since some callers will ignore | |
| 4187 | 8992 the return value if it is set. */ |
| 428 | 8993 *w = 0; |
| 8994 UPDATE_CACHE_RETURN; | |
| 8995 } | |
| 8996 | |
| 8997 /* See if the point is over window vertical divider */ | |
| 8998 if (window_needs_vertical_divider (*w)) | |
| 8999 { | |
| 9000 int div_x_high = WINDOW_RIGHT (*w); | |
| 9001 int div_x_low = div_x_high - window_divider_width (*w); | |
| 9002 int div_y_high = WINDOW_BOTTOM (*w); | |
| 9003 int div_y_low = WINDOW_TOP (*w); | |
| 9004 | |
| 9005 if (div_x_low < x_coord && x_coord <= div_x_high && | |
| 9006 div_y_low < y_coord && y_coord <= div_y_high) | |
| 9007 { | |
| 9008 low_x_coord = div_x_low; | |
| 9009 high_x_coord = div_x_high; | |
| 9010 low_y_coord = div_y_low; | |
| 9011 high_y_coord = div_y_high; | |
| 9012 position = OVER_V_DIVIDER; | |
| 9013 UPDATE_CACHE_RETURN; | |
| 9014 } | |
| 9015 } | |
| 9016 | |
| 9017 dla = window_display_lines (*w, CURRENT_DISP); | |
| 9018 | |
| 9019 for (*row = 0; *row < Dynarr_length (dla); (*row)++) | |
| 9020 { | |
| 9021 int really_over_nothing = 0; | |
| 9022 struct display_line *dl = Dynarr_atp (dla, *row); | |
| 9023 | |
| 9024 if ((int) (dl->ypos - dl->ascent) <= y_coord | |
| 9025 && y_coord <= (int) (dl->ypos + dl->descent)) | |
| 9026 { | |
| 9027 int check_margin_glyphs = 0; | |
| 9028 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 9029 struct rune *rb = 0; | |
| 9030 | |
| 9031 if (x_coord < dl->bounds.left_white | |
| 9032 || x_coord >= dl->bounds.right_white) | |
| 9033 check_margin_glyphs = 1; | |
| 9034 | |
| 9035 low_y_coord = dl->ypos - dl->ascent; | |
| 9036 high_y_coord = dl->ypos + dl->descent + 1; | |
| 9037 | |
| 9038 if (position == OVER_BORDER | |
| 9039 || position == OVER_OUTSIDE | |
| 9040 || check_margin_glyphs) | |
| 9041 { | |
| 9042 int x_check, left_bound; | |
| 9043 | |
| 9044 if (check_margin_glyphs) | |
| 9045 { | |
| 9046 x_check = x_coord; | |
| 9047 left_bound = dl->bounds.left_white; | |
| 9048 } | |
| 9049 else | |
| 9050 { | |
| 9051 x_check = high_x_coord; | |
| 9052 left_bound = frm_left; | |
| 9053 } | |
| 9054 | |
| 9055 if (Dynarr_length (db->runes)) | |
| 9056 { | |
| 9057 if (x_check <= left_bound) | |
| 9058 { | |
| 9059 if (dl->modeline) | |
| 826 | 9060 *modeline_closest = Dynarr_atp (db->runes, 0)->charpos; |
| 428 | 9061 else |
| 826 | 9062 *closest = Dynarr_atp (db->runes, 0)->charpos; |
| 428 | 9063 } |
| 9064 else | |
| 9065 { | |
| 9066 if (dl->modeline) | |
| 9067 *modeline_closest = | |
| 9068 Dynarr_atp (db->runes, | |
| 826 | 9069 Dynarr_length (db->runes) - 1)->charpos; |
| 428 | 9070 else |
| 9071 *closest = | |
| 9072 Dynarr_atp (db->runes, | |
| 826 | 9073 Dynarr_length (db->runes) - 1)->charpos; |
| 428 | 9074 } |
| 9075 | |
| 9076 if (dl->modeline) | |
| 9077 *modeline_closest += dl->offset; | |
| 9078 else | |
| 9079 *closest += dl->offset; | |
| 9080 } | |
| 9081 else | |
| 9082 { | |
| 9083 /* #### What should be here. */ | |
| 9084 if (dl->modeline) | |
| 9085 *modeline_closest = 0; | |
| 9086 else | |
| 9087 *closest = 0; | |
| 9088 } | |
| 9089 | |
| 9090 if (check_margin_glyphs) | |
| 9091 { | |
| 9092 if (x_coord < dl->bounds.left_in | |
| 9093 || x_coord >= dl->bounds.right_in) | |
| 9094 { | |
| 9095 /* If we are over the outside margins then we | |
| 4187 | 9096 know the loop over the text block isn't going |
| 9097 to accomplish anything. So we go ahead and | |
| 9098 set what information we can right here and | |
| 9099 return. */ | |
| 428 | 9100 (*row)--; |
| 9101 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
| 9102 get_position_object (dl, obj1, obj2, x_coord, | |
| 9103 &low_x_coord, &high_x_coord); | |
| 9104 | |
| 9105 UPDATE_CACHE_RETURN; | |
| 9106 } | |
| 9107 } | |
| 9108 else | |
| 9109 UPDATE_CACHE_RETURN; | |
| 9110 } | |
| 9111 | |
| 9112 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++) | |
| 9113 { | |
| 9114 int past_end = (*col == Dynarr_length (db->runes)); | |
| 9115 | |
| 9116 if (!past_end) | |
| 9117 rb = Dynarr_atp (db->runes, *col); | |
| 9118 | |
| 9119 if (past_end || | |
| 9120 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width)) | |
| 9121 { | |
| 9122 if (past_end) | |
| 9123 { | |
| 9124 (*col)--; | |
| 9125 rb = Dynarr_atp (db->runes, *col); | |
| 9126 } | |
| 9127 | |
| 826 | 9128 *charpos = rb->charpos + dl->offset; |
| 428 | 9129 low_x_coord = rb->xpos; |
| 9130 high_x_coord = rb->xpos + rb->width; | |
| 9131 | |
| 9132 if (rb->type == RUNE_DGLYPH) | |
| 9133 { | |
| 9134 int elt = *col + 1; | |
| 9135 | |
| 9136 /* Find the first character after the glyph. */ | |
| 9137 while (elt < Dynarr_length (db->runes)) | |
| 9138 { | |
| 9139 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH) | |
| 9140 { | |
| 9141 if (dl->modeline) | |
| 9142 *modeline_closest = | |
| 826 | 9143 (Dynarr_atp (db->runes, elt)->charpos + |
| 428 | 9144 dl->offset); |
| 9145 else | |
| 9146 *closest = | |
| 826 | 9147 (Dynarr_atp (db->runes, elt)->charpos + |
| 428 | 9148 dl->offset); |
| 9149 break; | |
| 9150 } | |
| 9151 | |
| 9152 elt++; | |
| 9153 } | |
| 9154 | |
| 9155 /* In this case we failed to find a non-glyph | |
| 4187 | 9156 character so we return the last position |
| 9157 displayed on the line. */ | |
| 428 | 9158 if (elt == Dynarr_length (db->runes)) |
| 9159 { | |
| 9160 if (dl->modeline) | |
| 826 | 9161 *modeline_closest = dl->end_charpos + dl->offset; |
| 428 | 9162 else |
| 826 | 9163 *closest = dl->end_charpos + dl->offset; |
| 428 | 9164 really_over_nothing = 1; |
| 9165 } | |
| 9166 } | |
| 9167 else | |
| 9168 { | |
| 9169 if (dl->modeline) | |
| 826 | 9170 *modeline_closest = rb->charpos + dl->offset; |
| 428 | 9171 else |
| 826 | 9172 *closest = rb->charpos + dl->offset; |
| 428 | 9173 } |
| 9174 | |
| 9175 if (dl->modeline) | |
| 9176 { | |
| 9177 *row = window_displayed_height (*w); | |
| 9178 | |
| 9179 if (position == OVER_NOTHING) | |
| 9180 position = OVER_MODELINE; | |
| 9181 | |
| 9182 if (rb->type == RUNE_DGLYPH) | |
| 9183 { | |
| 9184 *obj1 = rb->object.dglyph.glyph; | |
| 9185 *obj2 = rb->object.dglyph.extent; | |
| 9186 } | |
| 9187 else if (rb->type == RUNE_CHAR) | |
| 9188 { | |
| 9189 *obj1 = Qnil; | |
| 9190 *obj2 = Qnil; | |
| 9191 } | |
| 9192 else | |
| 9193 { | |
| 9194 *obj1 = Qnil; | |
| 9195 *obj2 = Qnil; | |
| 9196 } | |
| 9197 | |
| 9198 UPDATE_CACHE_RETURN; | |
| 9199 } | |
| 9200 else if (past_end | |
| 9201 || (rb->type == RUNE_CHAR | |
| 9202 && rb->object.chr.ch == '\n')) | |
| 9203 { | |
| 9204 (*row)--; | |
| 9205 /* At this point we may have glyphs in the right | |
| 4187 | 9206 inside margin. */ |
| 428 | 9207 if (check_margin_glyphs) |
| 9208 get_position_object (dl, obj1, obj2, x_coord, | |
| 9209 &low_x_coord, &high_x_coord); | |
| 9210 UPDATE_CACHE_RETURN; | |
| 9211 } | |
| 9212 else | |
| 9213 { | |
| 9214 (*row)--; | |
| 9215 if (rb->type == RUNE_DGLYPH) | |
| 9216 { | |
| 9217 *obj1 = rb->object.dglyph.glyph; | |
| 9218 *obj2 = rb->object.dglyph.extent; | |
| 9219 } | |
| 9220 else if (rb->type == RUNE_CHAR) | |
| 9221 { | |
| 9222 *obj1 = Qnil; | |
| 9223 *obj2 = Qnil; | |
| 9224 } | |
| 9225 else | |
| 9226 { | |
| 9227 *obj1 = Qnil; | |
| 9228 *obj2 = Qnil; | |
| 9229 } | |
| 9230 | |
| 9231 *obj_x = x_coord - rb->xpos; | |
| 9232 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
| 9233 | |
| 9234 /* At this point we may have glyphs in the left | |
| 4187 | 9235 inside margin. */ |
| 428 | 9236 if (check_margin_glyphs) |
| 9237 get_position_object (dl, obj1, obj2, x_coord, 0, 0); | |
| 9238 | |
| 9239 if (position == OVER_NOTHING && !really_over_nothing) | |
| 9240 position = OVER_TEXT; | |
| 9241 | |
| 9242 UPDATE_CACHE_RETURN; | |
| 9243 } | |
| 9244 } | |
| 9245 } | |
| 9246 } | |
| 9247 } | |
| 9248 | |
| 9249 *row = Dynarr_length (dla) - 1; | |
| 9250 if (FRAME_WIN_P (f)) | |
| 9251 { | |
| 9252 int bot_elt = Dynarr_length (dla) - 1; | |
| 9253 | |
| 9254 if (bot_elt >= 0) | |
| 9255 { | |
| 9256 struct display_line *dl = Dynarr_atp (dla, bot_elt); | |
| 9257 int adj_area = y_coord - (dl->ypos + dl->descent); | |
| 9258 Lisp_Object lwin; | |
| 9259 int defheight; | |
| 9260 | |
| 793 | 9261 lwin = wrap_window (*w); |
| 428 | 9262 default_face_height_and_width (lwin, 0, &defheight); |
| 9263 | |
| 9264 *row += (adj_area / defheight); | |
| 9265 } | |
| 9266 } | |
| 9267 | |
| 9268 /* #### This should be checked out some more to determine what | |
| 9269 should really be going on. */ | |
| 9270 if (!MARKERP ((*w)->start[CURRENT_DISP])) | |
| 9271 *closest = 0; | |
| 9272 else | |
| 442 | 9273 *closest = end_of_last_line_may_error (*w, |
| 428 | 9274 marker_position ((*w)->start[CURRENT_DISP])); |
| 9275 *col = 0; | |
| 9276 UPDATE_CACHE_RETURN; | |
| 9277 } | |
| 9278 #undef UPDATE_CACHE_RETURN | |
| 9279 | |
| 9280 | |
| 9281 /***************************************************************************/ | |
| 9282 /* */ | |
| 9283 /* Lisp functions */ | |
| 9284 /* */ | |
| 9285 /***************************************************************************/ | |
| 9286 | |
| 9287 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /* | |
| 9288 Ensure that all minibuffers are correctly showing the echo area. | |
| 9289 */ | |
| 9290 ()) | |
| 9291 { | |
| 9292 Lisp_Object devcons, concons; | |
| 9293 | |
| 1318 | 9294 if (in_display) |
| 9295 return Qnil; | |
| 9296 | |
| 428 | 9297 DEVICE_LOOP_NO_BREAK (devcons, concons) |
| 9298 { | |
| 9299 struct device *d = XDEVICE (XCAR (devcons)); | |
| 9300 Lisp_Object frmcons; | |
| 9301 | |
| 1279 | 9302 if (DEVICE_STREAM_P (d)) |
| 9303 continue; | |
| 9304 | |
| 428 | 9305 DEVICE_FRAME_LOOP (frmcons, d) |
| 9306 { | |
| 9307 struct frame *f = XFRAME (XCAR (frmcons)); | |
| 853 | 9308 int depth; |
| 428 | 9309 |
| 9310 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) | |
| 9311 { | |
| 9312 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); | |
| 442 | 9313 |
| 9314 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
| 9315 | |
| 428 | 9316 /* |
| 9317 * If the frame size has changed, there may be random | |
| 9318 * chud on the screen left from previous messages | |
| 9319 * because redisplay_frame hasn't been called yet. | |
| 9320 * Clear the screen to get rid of the potential mess. | |
| 9321 */ | |
| 9322 if (f->echo_area_garbaged) | |
| 9323 { | |
| 442 | 9324 MAYBE_DEVMETH (d, clear_frame, (f)); |
| 428 | 9325 f->echo_area_garbaged = 0; |
| 9326 } | |
| 853 | 9327 depth = enter_redisplay_critical_section (); |
| 428 | 9328 redisplay_window (window, 0); |
| 853 | 9329 exit_redisplay_critical_section (depth); |
| 442 | 9330 MAYBE_DEVMETH (d, frame_output_end, (f)); |
| 428 | 9331 } |
| 9332 } | |
| 9333 } | |
| 9334 | |
| 9335 return Qnil; | |
| 9336 } | |
| 9337 | |
| 9338 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /* | |
| 9339 Clear frame FRAME and output again what is supposed to appear on it. | |
| 9340 FRAME defaults to the selected frame if omitted. | |
| 9341 Normally, redisplay is preempted as normal if input arrives. However, | |
| 9342 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
| 9343 input and is guaranteed to proceed to completion. | |
| 9344 */ | |
| 9345 (frame, no_preempt)) | |
| 9346 { | |
| 9347 struct frame *f = decode_frame (frame); | |
| 9348 int count = specpdl_depth (); | |
| 9349 | |
| 9350 if (!NILP (no_preempt)) | |
| 853 | 9351 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
| 428 | 9352 |
| 9353 f->clear = 1; | |
| 9354 redisplay_frame (f, 1); | |
| 9355 | |
| 442 | 9356 /* See the comment in Fredisplay_frame. */ |
| 9357 RESET_CHANGED_SET_FLAGS; | |
| 9358 | |
| 771 | 9359 return unbind_to (count); |
| 428 | 9360 } |
| 9361 | |
| 9362 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* | |
| 9363 Ensure that FRAME's contents are correctly displayed. | |
| 9364 This differs from `redraw-frame' in that it only redraws what needs to | |
| 9365 be updated, as opposed to unconditionally clearing and redrawing | |
| 9366 the frame. | |
| 9367 FRAME defaults to the selected frame if omitted. | |
| 9368 Normally, redisplay is preempted as normal if input arrives. However, | |
| 9369 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
| 9370 input and is guaranteed to proceed to completion. | |
| 9371 */ | |
| 9372 (frame, no_preempt)) | |
| 9373 { | |
| 9374 struct frame *f = decode_frame (frame); | |
| 9375 int count = specpdl_depth (); | |
| 9376 | |
| 9377 if (!NILP (no_preempt)) | |
| 853 | 9378 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
| 428 | 9379 |
| 9380 redisplay_frame (f, 1); | |
| 9381 | |
| 442 | 9382 /* If we don't reset the global redisplay flags here, subsequent |
| 9383 changes to the display will not get registered by redisplay | |
| 9384 because it thinks it already has registered changes. If you | |
| 9385 really knew what you were doing you could confuse redisplay by | |
| 9386 calling Fredisplay_frame while updating another frame. We assume | |
| 9387 that if you know what you are doing you will not be that | |
| 9388 stupid. */ | |
| 9389 RESET_CHANGED_SET_FLAGS; | |
| 9390 | |
| 771 | 9391 return unbind_to (count); |
| 428 | 9392 } |
| 9393 | |
| 9394 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* | |
| 9395 Clear device DEVICE and output again what is supposed to appear on it. | |
| 9396 DEVICE defaults to the selected device if omitted. | |
| 9397 Normally, redisplay is preempted as normal if input arrives. However, | |
| 9398 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
| 9399 input and is guaranteed to proceed to completion. | |
| 9400 */ | |
| 9401 (device, no_preempt)) | |
| 9402 { | |
| 9403 struct device *d = decode_device (device); | |
| 9404 Lisp_Object frmcons; | |
| 9405 int count = specpdl_depth (); | |
| 9406 | |
| 9407 if (!NILP (no_preempt)) | |
| 853 | 9408 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
| 428 | 9409 |
| 9410 DEVICE_FRAME_LOOP (frmcons, d) | |
| 9411 { | |
| 9412 XFRAME (XCAR (frmcons))->clear = 1; | |
| 9413 } | |
| 440 | 9414 redisplay_device (d, 0); |
| 428 | 9415 |
| 442 | 9416 /* See the comment in Fredisplay_frame. */ |
| 9417 RESET_CHANGED_SET_FLAGS; | |
| 9418 | |
| 771 | 9419 return unbind_to (count); |
| 428 | 9420 } |
| 9421 | |
| 9422 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* | |
| 9423 Ensure that DEVICE's contents are correctly displayed. | |
| 9424 This differs from `redraw-device' in that it only redraws what needs to | |
| 9425 be updated, as opposed to unconditionally clearing and redrawing | |
| 9426 the device. | |
| 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. | |
| 853 | 9431 |
| 9432 Note: If you simply want everything redisplayed, the current idiom is | |
| 9433 `(sit-for 0)'. | |
| 428 | 9434 */ |
| 9435 (device, no_preempt)) | |
| 9436 { | |
| 9437 struct device *d = decode_device (device); | |
| 9438 int count = specpdl_depth (); | |
| 9439 | |
| 9440 if (!NILP (no_preempt)) | |
| 853 | 9441 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
| 428 | 9442 |
| 440 | 9443 redisplay_device (d, 0); |
| 428 | 9444 |
| 442 | 9445 /* See the comment in Fredisplay_frame. */ |
| 9446 RESET_CHANGED_SET_FLAGS; | |
| 9447 | |
| 771 | 9448 return unbind_to (count); |
| 428 | 9449 } |
| 9450 | |
| 9451 /* Big lie. Big lie. This will force all modelines to be updated | |
| 9452 regardless if the all flag is set or not. It remains in existence | |
| 9453 solely for backwards compatibility. */ | |
| 9454 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /* | |
| 9455 Force the modeline of the current buffer to be redisplayed. | |
| 9456 With optional non-nil ALL, force redisplay of all modelines. | |
| 9457 */ | |
| 2286 | 9458 (UNUSED (all))) |
| 428 | 9459 { |
| 9460 MARK_MODELINE_CHANGED; | |
| 9461 return Qnil; | |
| 9462 } | |
| 9463 | |
| 9464 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /* | |
| 9465 Force an immediate update of the cursor on FRAME. | |
| 9466 FRAME defaults to the selected frame if omitted. | |
| 9467 */ | |
| 9468 (frame)) | |
| 9469 { | |
| 1279 | 9470 struct frame *f = decode_frame (frame); |
| 9471 | |
| 9472 if (!FRAME_STREAM_P (f)) | |
| 9473 redisplay_redraw_cursor (f, 1); | |
| 428 | 9474 return Qnil; |
| 9475 } | |
| 9476 | |
| 9477 | |
| 9478 /***************************************************************************/ | |
| 9479 /* */ | |
| 872 | 9480 /* Change flags */ |
| 428 | 9481 /* */ |
| 9482 /***************************************************************************/ | |
| 9483 | |
| 9484 static void | |
| 2286 | 9485 margin_width_changed_in_frame (Lisp_Object UNUSED (specifier), |
| 9486 struct frame *UNUSED (f), | |
| 9487 Lisp_Object UNUSED (oldval)) | |
| 428 | 9488 { |
| 9489 /* Nothing to be done? */ | |
| 9490 } | |
| 9491 | |
| 9492 int | |
| 2286 | 9493 redisplay_variable_changed (Lisp_Object UNUSED (sym), |
| 9494 Lisp_Object *UNUSED (val), | |
| 9495 Lisp_Object UNUSED (in_object), | |
| 9496 int UNUSED (flags)) | |
| 428 | 9497 { |
| 9498 /* #### clip_changed should really be renamed something like | |
| 9499 global_redisplay_change. */ | |
| 9500 MARK_CLIP_CHANGED; | |
| 9501 return 0; | |
| 9502 } | |
| 9503 | |
| 9504 /* This is called if the built-in glyphs have their properties | |
| 9505 changed. */ | |
| 9506 void | |
| 2286 | 9507 redisplay_glyph_changed (Lisp_Object UNUSED (glyph), |
| 9508 Lisp_Object UNUSED (property), Lisp_Object locale) | |
| 428 | 9509 { |
| 9510 if (WINDOWP (locale)) | |
| 9511 { | |
| 9512 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale)))); | |
| 9513 } | |
| 9514 else if (FRAMEP (locale)) | |
| 9515 { | |
| 9516 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale)); | |
| 9517 } | |
| 9518 else if (DEVICEP (locale)) | |
| 9519 { | |
| 9520 Lisp_Object frmcons; | |
| 9521 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale)) | |
| 9522 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
| 9523 } | |
| 9524 else if (CONSOLEP (locale)) | |
| 9525 { | |
| 9526 Lisp_Object frmcons, devcons; | |
| 9527 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale)) | |
| 9528 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
| 9529 } | |
| 9530 else /* global or buffer */ | |
| 9531 { | |
| 9532 Lisp_Object frmcons, devcons, concons; | |
| 9533 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
| 9534 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
| 9535 } | |
| 9536 } | |
| 9537 | |
| 9538 static void | |
| 2286 | 9539 text_cursor_visible_p_changed (Lisp_Object UNUSED (specifier), |
| 9540 struct window *w, Lisp_Object UNUSED (oldval)) | |
| 428 | 9541 { |
| 9542 if (XFRAME (w->frame)->init_finished) | |
| 9543 Fforce_cursor_redisplay (w->frame); | |
| 9544 } | |
| 9545 | |
| 872 | 9546 void |
| 9547 mark_buffers_changed (void) | |
| 9548 { | |
| 9549 MARK_TYPE_CHANGED (buffers); | |
| 9550 } | |
| 9551 | |
| 9552 void | |
| 9553 mark_clip_changed (void) | |
| 9554 { | |
| 9555 MARK_TYPE_CHANGED (clip); | |
| 9556 } | |
| 9557 | |
| 9558 void | |
| 9559 mark_extents_changed (void) | |
| 9560 { | |
| 9561 MARK_TYPE_CHANGED (extents); | |
| 9562 } | |
| 9563 | |
| 9564 void | |
| 9565 mark_icon_changed (void) | |
| 9566 { | |
| 9567 MARK_TYPE_CHANGED (icon); | |
| 9568 } | |
| 9569 | |
| 9570 void | |
| 9571 mark_menubar_changed (void) | |
| 9572 { | |
| 9573 MARK_TYPE_CHANGED (menubar); | |
| 9574 } | |
| 9575 | |
| 9576 void | |
| 9577 mark_modeline_changed (void) | |
| 9578 { | |
| 9579 MARK_TYPE_CHANGED (modeline); | |
| 9580 } | |
| 9581 | |
| 9582 void | |
| 9583 mark_point_changed (void) | |
| 9584 { | |
| 9585 MARK_TYPE_CHANGED (point); | |
| 9586 } | |
| 9587 | |
| 9588 void | |
| 9589 mark_toolbar_changed (void) | |
| 9590 { | |
| 9591 MARK_TYPE_CHANGED (toolbar); | |
| 9592 } | |
| 9593 | |
| 9594 void | |
| 9595 mark_gutter_changed (void) | |
| 9596 { | |
| 9597 MARK_TYPE_CHANGED (gutter); | |
| 9598 } | |
| 9599 | |
| 9600 void | |
| 9601 mark_glyphs_changed (void) | |
| 9602 { | |
| 9603 MARK_TYPE_CHANGED (glyphs); | |
| 9604 } | |
| 9605 | |
| 9606 void | |
| 9607 mark_subwindows_changed (void) | |
| 9608 { | |
| 9609 MARK_TYPE_CHANGED (subwindows); | |
| 9610 } | |
| 9611 | |
| 9612 void | |
| 9613 mark_subwindows_state_changed (void) | |
| 9614 { | |
| 9615 MARK_TYPE_CHANGED (subwindows_state); | |
| 9616 } | |
| 9617 | |
| 428 | 9618 #ifdef MEMORY_USAGE_STATS |
| 9619 | |
| 9620 | |
| 9621 /***************************************************************************/ | |
| 9622 /* */ | |
| 9623 /* memory usage computation */ | |
| 9624 /* */ | |
| 9625 /***************************************************************************/ | |
| 9626 | |
| 9627 static int | |
| 9628 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats) | |
| 9629 { | |
| 9630 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
| 9631 } | |
| 9632 | |
| 9633 static int | |
| 9634 compute_display_block_dynarr_usage (display_block_dynarr *dyn, | |
| 9635 struct overhead_stats *ovstats) | |
| 9636 { | |
| 9637 int total, i; | |
| 9638 | |
| 9639 if (!dyn) | |
| 9640 return 0; | |
| 9641 | |
| 9642 total = Dynarr_memory_usage (dyn, ovstats); | |
| 9643 for (i = 0; i < Dynarr_largest (dyn); i++) | |
| 9644 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats); | |
| 9645 | |
| 9646 return total; | |
| 9647 } | |
| 9648 | |
| 9649 static int | |
| 9650 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn, | |
| 9651 struct overhead_stats *ovstats) | |
| 9652 { | |
| 9653 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
| 9654 } | |
| 9655 | |
| 9656 int | |
| 9657 compute_display_line_dynarr_usage (display_line_dynarr *dyn, | |
| 9658 struct overhead_stats *ovstats) | |
| 9659 { | |
| 9660 int total, i; | |
| 9661 | |
| 9662 if (!dyn) | |
| 9663 return 0; | |
| 9664 | |
| 9665 total = Dynarr_memory_usage (dyn, ovstats); | |
| 9666 for (i = 0; i < Dynarr_largest (dyn); i++) | |
| 9667 { | |
| 9668 struct display_line *dl = &Dynarr_at (dyn, i); | |
| 9669 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats); | |
| 9670 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats); | |
| 9671 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats); | |
| 9672 } | |
| 9673 | |
| 9674 return total; | |
| 9675 } | |
| 9676 | |
| 9677 int | |
| 9678 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn, | |
| 9679 struct overhead_stats *ovstats) | |
| 9680 { | |
| 9681 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0; | |
| 9682 } | |
| 9683 | |
| 9684 #endif /* MEMORY_USAGE_STATS */ | |
| 9685 | |
| 1204 | 9686 #ifdef ERROR_CHECK_DISPLAY |
| 9687 | |
| 800 | 9688 static int |
| 2286 | 9689 sledgehammer_check_redisplay_structs_1 (struct window *w, |
| 9690 void *UNUSED (closure)) | |
| 800 | 9691 { |
| 9692 int i, j; | |
| 9693 display_line_dynarr *dl; | |
| 9694 | |
| 9695 dl = window_display_lines (w, CURRENT_DISP); | |
| 4187 | 9696 |
| 800 | 9697 for (i = 0; i < Dynarr_largest (dl); i++) |
| 9698 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
| 9699 assert (Dynarr_atp (dl, i)->display_blocks != | |
| 9700 Dynarr_atp (dl, j)->display_blocks); | |
| 9701 | |
| 9702 dl = window_display_lines (w, DESIRED_DISP); | |
| 9703 | |
| 9704 for (i = 0; i < Dynarr_largest (dl); i++) | |
| 9705 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
| 9706 assert (Dynarr_atp (dl, i)->display_blocks != | |
| 9707 Dynarr_atp (dl, j)->display_blocks); | |
| 9708 | |
| 9709 return 0; | |
| 9710 } | |
| 9711 | |
| 9712 static void | |
| 9713 sledgehammer_check_redisplay_structs (void) | |
| 9714 { | |
| 9715 map_windows (0, sledgehammer_check_redisplay_structs_1, NULL); | |
| 9716 } | |
| 9717 | |
| 1204 | 9718 #endif /* ERROR_CHECK_DISPLAY */ |
| 9719 | |
| 428 | 9720 |
| 9721 /***************************************************************************/ | |
| 9722 /* */ | |
| 9723 /* initialization */ | |
| 9724 /* */ | |
| 9725 /***************************************************************************/ | |
| 9726 | |
| 9727 void | |
| 9728 init_redisplay (void) | |
| 9729 { | |
| 9730 disable_preemption = 0; | |
| 9731 preemption_count = 0; | |
| 9732 | |
| 9733 #ifndef PDUMP | |
| 9734 if (!initialized) | |
| 9735 #endif | |
| 9736 { | |
| 440 | 9737 if (!cmotion_display_lines) |
| 9738 cmotion_display_lines = Dynarr_new (display_line); | |
| 867 | 9739 if (!mode_spec_ibyte_string) |
| 9740 mode_spec_ibyte_string = Dynarr_new (Ibyte); | |
| 440 | 9741 if (!formatted_string_extent_dynarr) |
| 9742 formatted_string_extent_dynarr = Dynarr_new (EXTENT); | |
| 9743 if (!formatted_string_extent_start_dynarr) | |
| 9744 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); | |
| 9745 if (!formatted_string_extent_end_dynarr) | |
| 9746 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); | |
| 9747 if (!internal_cache) | |
| 9748 internal_cache = Dynarr_new (line_start_cache); | |
| 428 | 9749 } |
| 9750 | |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9751 if (!initialized) |
| 428 | 9752 return; |
| 9753 | |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9754 if (noninteractive) |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9755 { |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9756 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
|
9757 return; |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9758 } |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9759 |
| 428 | 9760 /* If the user wants to use a window system, we shouldn't bother |
| 9761 initializing the terminal. This is especially important when the | |
| 9762 terminal is so dumb that emacs gives up before and doesn't bother | |
| 9763 using the window system. | |
| 9764 | |
| 9765 If the DISPLAY environment variable is set, try to use X, and die | |
| 9766 with an error message if that doesn't work. */ | |
| 9767 | |
| 9768 #ifdef HAVE_X_WINDOWS | |
| 9769 if (!strcmp (display_use, "x")) | |
| 9770 { | |
| 9771 /* Some stuff checks this way early. */ | |
| 9772 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
|
9773 Vinitial_device_type = Qx; |
| 428 | 9774 return; |
| 9775 } | |
| 9776 #endif /* HAVE_X_WINDOWS */ | |
| 9777 | |
| 462 | 9778 #ifdef HAVE_GTK |
| 9779 if (!strcmp (display_use, "gtk")) | |
| 9780 { | |
| 9781 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
|
9782 Vinitial_device_type = Qgtk; |
| 462 | 9783 return; |
| 9784 } | |
| 9785 #endif | |
| 9786 | |
| 428 | 9787 #ifdef HAVE_MS_WINDOWS |
| 9788 if (!strcmp (display_use, "mswindows")) | |
| 9789 { | |
| 9790 /* Some stuff checks this way early. */ | |
| 9791 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
|
9792 Vinitial_device_type = Qmswindows; |
| 428 | 9793 return; |
| 9794 } | |
| 9795 #endif /* HAVE_MS_WINDOWS */ | |
| 9796 | |
| 9797 #ifdef HAVE_TTY | |
| 9798 /* If no window system has been specified, try to use the terminal. */ | |
| 9799 if (!isatty (0)) | |
| 9800 { | |
| 9801 stderr_out ("XEmacs: standard input is not a tty\n"); | |
| 9802 exit (1); | |
| 9803 } | |
| 9804 | |
| 9805 /* Look at the TERM variable */ | |
| 771 | 9806 if (!egetenv ("TERM")) |
| 428 | 9807 { |
| 9808 stderr_out ("Please set the environment variable TERM; see tset(1).\n"); | |
| 9809 exit (1); | |
| 9810 } | |
| 9811 | |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9812 Vinitial_device_type = Qtty; |
| 428 | 9813 return; |
| 9814 #else /* not HAVE_TTY */ | |
| 9815 /* No DISPLAY specified, and no TTY support. */ | |
| 9816 stderr_out ("XEmacs: Cannot open display.\n\ | |
| 9817 Please set the environmental variable DISPLAY to an appropriate value.\n"); | |
| 9818 exit (1); | |
| 9819 #endif | |
| 9820 /* Unreached. */ | |
| 9821 } | |
| 9822 | |
| 9823 void | |
| 9824 syms_of_redisplay (void) | |
| 9825 { | |
| 563 | 9826 DEFSYMBOL (Qcursor_in_echo_area); |
| 9827 DEFSYMBOL (Qdisplay_warning_buffer); | |
| 9828 DEFSYMBOL (Qbar_cursor); | |
| 9829 DEFSYMBOL (Qtop_bottom); | |
| 9830 DEFSYMBOL (Qbuffer_list_changed_hook); | |
| 428 | 9831 |
| 9832 DEFSUBR (Fredisplay_echo_area); | |
| 9833 DEFSUBR (Fredraw_frame); | |
| 9834 DEFSUBR (Fredisplay_frame); | |
| 9835 DEFSUBR (Fredraw_device); | |
| 9836 DEFSUBR (Fredisplay_device); | |
| 9837 DEFSUBR (Fredraw_modeline); | |
| 9838 DEFSUBR (Fforce_cursor_redisplay); | |
| 9839 } | |
| 9840 | |
| 9841 void | |
| 9842 vars_of_redisplay (void) | |
| 9843 { | |
| 1292 | 9844 QSin_redisplay = build_msg_string ("(in redisplay)"); |
| 9845 staticpro (&QSin_redisplay); | |
| 428 | 9846 |
| 1318 | 9847 Vpost_redisplay_actions = Qnil; |
| 9848 staticpro (&Vpost_redisplay_actions); | |
| 9849 | |
| 428 | 9850 #if 0 |
| 9851 staticpro (&last_arrow_position); | |
| 9852 staticpro (&last_arrow_string); | |
| 9853 last_arrow_position = Qnil; | |
| 9854 last_arrow_string = Qnil; | |
| 9855 #endif /* 0 */ | |
| 9856 | |
| 9857 /* #### Probably temporary */ | |
| 9858 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* | |
| 9859 \(Temporary) Setting this will impact the performance of the internal | |
| 9860 line start cache. | |
| 9861 */ ); | |
| 9862 cache_adjustment = 2; | |
| 9863 | |
| 1268 | 9864 DEFVAR_INT ("maximum-preempts", &max_preempts /* |
| 9865 Maximum number of times redisplay can be preempted by user input. | |
| 9866 */ ); | |
| 9867 max_preempts = INIT_MAX_PREEMPTS; | |
| 9868 | |
| 428 | 9869 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /* |
| 9870 Minimum pixel height for clipped bottom display line. | |
| 9871 A clipped line shorter than this won't be displayed. | |
| 9872 */ , | |
| 9873 redisplay_variable_changed); | |
| 9874 vertical_clip = 5; | |
| 9875 | |
| 9876 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /* | |
| 9877 Minimum visible area for clipped glyphs at right boundary. | |
| 9878 Clipped glyphs shorter than this won't be displayed. | |
| 9879 Only pixmap glyph instances are currently allowed to be clipped. | |
| 9880 */ , | |
| 9881 redisplay_variable_changed); | |
| 9882 horizontal_clip = 5; | |
| 9883 | |
| 9884 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /* | |
| 9885 String displayed by modeline-format's "%m" specification. | |
| 9886 */ ); | |
| 9887 Vglobal_mode_string = Qnil; | |
| 9888 | |
| 9889 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /* | |
| 9890 Marker for where to display an arrow on top of the buffer text. | |
| 9891 This must be the beginning of a line in order to work. | |
| 9892 See also `overlay-arrow-string'. | |
| 9893 */ , | |
| 9894 redisplay_variable_changed); | |
| 9895 Voverlay_arrow_position = Qnil; | |
| 9896 | |
| 9897 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* | |
| 442 | 9898 String or glyph to display as an arrow. See also `overlay-arrow-position'. |
| 444 | 9899 \(Note that despite the name of this variable, it can be set to a glyph as |
| 442 | 9900 well as a string.) |
| 428 | 9901 */ , |
| 9902 redisplay_variable_changed); | |
| 9903 Voverlay_arrow_string = Qnil; | |
| 9904 | |
| 9905 DEFVAR_INT ("scroll-step", &scroll_step /* | |
| 9906 *The number of lines to try scrolling a window by when point moves out. | |
| 9907 If that fails to bring point back on frame, point is centered instead. | |
| 9908 If this is zero, point is always centered after it moves off screen. | |
| 9909 */ ); | |
| 9910 scroll_step = 0; | |
| 9911 | |
| 9912 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /* | |
| 9913 *Scroll up to this many lines, to bring point back on screen. | |
| 9914 */ ); | |
| 9915 scroll_conservatively = 0; | |
| 9916 | |
| 9917 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows", | |
| 9918 &truncate_partial_width_windows /* | |
| 9919 *Non-nil means truncate lines in all windows less than full frame wide. | |
| 9920 */ , | |
| 9921 redisplay_variable_changed); | |
| 9922 truncate_partial_width_windows = 1; | |
| 9923 | |
| 442 | 9924 DEFVAR_LISP ("visible-bell", &Vvisible_bell /* |
| 9925 *Non-nil substitutes a visual signal for the audible bell. | |
| 9926 | |
| 9927 Default behavior is to flash the whole screen. On some platforms, | |
| 9928 special effects are available using the following values: | |
| 9929 | |
| 3025 | 9930 `display' Flash the whole screen (ie, the default behavior). |
| 9931 `top-bottom' Flash only the top and bottom lines of the selected frame. | |
| 442 | 9932 |
| 9933 When effects are unavailable on a platform, the visual bell is the | |
| 9934 default, whole screen. (Currently only X supports any special effects.) | |
| 428 | 9935 */ ); |
| 442 | 9936 Vvisible_bell = Qnil; |
| 428 | 9937 |
| 9938 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* | |
| 9939 *Non-nil means no need to redraw entire frame after suspending. | |
| 9940 A non-nil value is useful if the terminal can automatically preserve | |
| 9941 Emacs's frame display when you reenter Emacs. | |
| 9942 It is up to you to set this variable if your terminal can do that. | |
| 9943 */ ); | |
| 9944 no_redraw_on_reenter = 0; | |
| 9945 | |
| 9946 DEFVAR_LISP ("window-system", &Vwindow_system /* | |
| 9947 A symbol naming the window-system under which Emacs is running, | |
| 9948 such as `x', or nil if emacs is running on an ordinary terminal. | |
| 9949 | |
| 9950 Do not use this variable, except for GNU Emacs compatibility, as it | |
| 9951 gives wrong values in a multi-device environment. Use `console-type' | |
| 9952 instead. | |
| 9953 */ ); | |
| 9954 Vwindow_system = Qnil; | |
| 9955 | |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9956 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
|
9957 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
|
9958 |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9959 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
|
9960 to Lisp what type the initial device to be created should be. |
| 428 | 9961 */ ); |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9962 Vinitial_device_type = Qnil; |
| 428 | 9963 |
| 9964 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* | |
| 9965 Non-nil means put cursor in minibuffer, at end of any message there. | |
| 9966 */ ); | |
| 9967 cursor_in_echo_area = 0; | |
| 9968 | |
| 9969 /* #### Shouldn't this be generalized as follows: | |
| 9970 | |
| 9971 if nil, use block cursor. | |
| 9972 if a number, use a bar cursor of that width. | |
| 9973 Otherwise, use a 1-pixel bar cursor. | |
| 9974 | |
| 9975 #### Or better yet, this variable should be trashed entirely | |
| 9976 (use a Lisp-magic variable to maintain compatibility) | |
| 9977 and a specifier `cursor-shape' added, which allows a block | |
| 9978 cursor, a bar cursor, a flashing block or bar cursor, | |
| 9979 maybe a caret cursor, etc. */ | |
| 9980 | |
| 9981 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /* | |
| 448 | 9982 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. |
| 428 | 9983 */ ); |
| 9984 Vbar_cursor = Qnil; | |
| 9985 | |
| 442 | 9986 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* |
| 9987 Function or functions to call when a frame's buffer list has changed. | |
| 9988 This is called during redisplay, before redisplaying each frame. | |
| 9989 Functions on this hook are called with one argument, the frame. | |
| 9990 */ ); | |
| 9991 Vbuffer_list_changed_hook = Qnil; | |
| 9992 | |
| 428 | 9993 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* |
| 9994 Bump this to tell the C code to call `display-warning-buffer' | |
| 9995 at next redisplay. You should not normally change this; the function | |
| 9996 `display-warning' automatically does this at appropriate times. | |
| 9997 */ ); | |
| 9998 display_warning_tick = 0; | |
| 9999 | |
| 10000 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /* | |
| 10001 Non-nil means inhibit display of warning messages. | |
| 10002 You should *bind* this, not set it. Any pending warning messages | |
| 10003 will be displayed when the binding no longer applies. | |
| 10004 */ ); | |
| 10005 /* reset to 0 by startup.el after the splash screen has displayed. | |
| 10006 This way, the warnings don't obliterate the splash screen. */ | |
| 10007 inhibit_warning_display = 1; | |
| 10008 | |
| 10009 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /* | |
| 10010 *Non-nil means column display number starts at 1. | |
| 10011 */ ); | |
| 10012 column_number_start_at_one = 0; | |
| 10013 } | |
| 10014 | |
| 10015 void | |
| 10016 specifier_vars_of_redisplay (void) | |
| 10017 { | |
| 10018 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /* | |
| 10019 *Width of left margin. | |
| 10020 This is a specifier; use `set-specifier' to change it. | |
| 10021 */ ); | |
| 10022 Vleft_margin_width = Fmake_specifier (Qnatnum); | |
| 10023 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); | |
| 10024 set_specifier_caching (Vleft_margin_width, | |
| 438 | 10025 offsetof (struct window, left_margin_width), |
| 428 | 10026 some_window_value_changed, |
| 438 | 10027 offsetof (struct frame, left_margin_width), |
| 444 | 10028 margin_width_changed_in_frame, 0); |
| 428 | 10029 |
| 10030 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* | |
| 10031 *Width of right margin. | |
| 10032 This is a specifier; use `set-specifier' to change it. | |
| 10033 */ ); | |
| 10034 Vright_margin_width = Fmake_specifier (Qnatnum); | |
| 10035 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); | |
| 10036 set_specifier_caching (Vright_margin_width, | |
| 438 | 10037 offsetof (struct window, right_margin_width), |
| 428 | 10038 some_window_value_changed, |
| 438 | 10039 offsetof (struct frame, right_margin_width), |
| 444 | 10040 margin_width_changed_in_frame, 0); |
| 428 | 10041 |
| 10042 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* | |
| 10043 *Minimum ascent height of lines. | |
| 10044 This is a specifier; use `set-specifier' to change it. | |
| 10045 */ ); | |
| 10046 Vminimum_line_ascent = Fmake_specifier (Qnatnum); | |
| 10047 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); | |
| 10048 set_specifier_caching (Vminimum_line_ascent, | |
| 438 | 10049 offsetof (struct window, minimum_line_ascent), |
| 428 | 10050 some_window_value_changed, |
| 444 | 10051 0, 0, 0); |
| 428 | 10052 |
| 10053 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* | |
| 10054 *Minimum descent height of lines. | |
| 10055 This is a specifier; use `set-specifier' to change it. | |
| 10056 */ ); | |
| 10057 Vminimum_line_descent = Fmake_specifier (Qnatnum); | |
| 10058 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); | |
| 10059 set_specifier_caching (Vminimum_line_descent, | |
| 438 | 10060 offsetof (struct window, minimum_line_descent), |
| 428 | 10061 some_window_value_changed, |
| 444 | 10062 0, 0, 0); |
| 428 | 10063 |
| 10064 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* | |
| 10065 *Non-nil means use the left outside margin as extra whitespace when | |
| 3025 | 10066 displaying `whitespace' or `inside-margin' glyphs. |
| 428 | 10067 This is a specifier; use `set-specifier' to change it. |
| 10068 */ ); | |
| 10069 Vuse_left_overflow = Fmake_specifier (Qboolean); | |
| 10070 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); | |
| 10071 set_specifier_caching (Vuse_left_overflow, | |
| 438 | 10072 offsetof (struct window, use_left_overflow), |
| 428 | 10073 some_window_value_changed, |
| 444 | 10074 0, 0, 0); |
| 428 | 10075 |
| 10076 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* | |
| 10077 *Non-nil means use the right outside margin as extra whitespace when | |
| 3025 | 10078 displaying `whitespace' or `inside-margin' glyphs. |
| 428 | 10079 This is a specifier; use `set-specifier' to change it. |
| 10080 */ ); | |
| 10081 Vuse_right_overflow = Fmake_specifier (Qboolean); | |
| 10082 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); | |
| 10083 set_specifier_caching (Vuse_right_overflow, | |
| 438 | 10084 offsetof (struct window, use_right_overflow), |
| 428 | 10085 some_window_value_changed, |
| 444 | 10086 0, 0, 0); |
| 428 | 10087 |
| 10088 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* | |
| 10089 *Non-nil means the text cursor is visible (this is usually the case). | |
| 10090 This is a specifier; use `set-specifier' to change it. | |
| 10091 */ ); | |
| 10092 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); | |
| 10093 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); | |
| 10094 set_specifier_caching (Vtext_cursor_visible_p, | |
| 438 | 10095 offsetof (struct window, text_cursor_visible_p), |
| 428 | 10096 text_cursor_visible_p_changed, |
| 444 | 10097 0, 0, 0); |
| 428 | 10098 |
| 10099 } |
