Mercurial > hg > xemacs-beta
annotate src/redisplay.c @ 4742:4cf435fcebbc
Make #'letf not error if handed a #'values form.
lisp/ChangeLog addition:
2009-11-14 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (letf):
Check whether arguments to #'values are bound, and make them
unbound after evaluating BODY; document the limitations of this
macro.
tests/ChangeLog addition:
2009-11-14 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Don't call Known-Bug-Expect-Failure now that the particular letf
bug it tickled is fixed.
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Sat, 14 Nov 2009 11:43:09 +0000 |
| 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 } |
