Mercurial > hg > xemacs-beta
annotate src/redisplay.c @ 5554:a42e686a01bf
Automated merge with file:///Sources/xemacs-21.5-checked-out
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Wed, 24 Aug 2011 11:07:26 +0100 |
| parents | 58e320bde005 |
| children | 56144c8593a8 |
| rev | line source |
|---|---|
| 428 | 1 /* Display generation from window structure and buffer text. |
| 2 Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois. | |
| 3 Copyright (C) 1995 Free Software Foundation, Inc. | |
|
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
4 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2005, 2010 Ben Wing. |
| 428 | 5 Copyright (C) 1995 Sun Microsystems, Inc. |
| 6 Copyright (C) 1996 Chuck Thompson. | |
| 7 | |
| 8 This file is part of XEmacs. | |
| 9 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5198
diff
changeset
|
10 XEmacs is free software: you can redistribute it and/or modify it |
| 428 | 11 under the terms of the GNU General Public License as published by the |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5198
diff
changeset
|
12 Free Software Foundation, either version 3 of the License, or (at your |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5198
diff
changeset
|
13 option) any later version. |
| 428 | 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 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5198
diff
changeset
|
21 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
| 428 | 22 |
| 23 /* Synched up with: Not in FSF. */ | |
| 24 | |
| 25 /* Author: Chuck Thompson */ | |
| 26 | |
| 27 /* Fixed up by Ben Wing for Mule */ | |
| 28 | |
| 29 /* This file has been Mule-ized. */ | |
| 30 | |
| 31 /***************************************************************************** | |
| 32 The Golden Rules of Redisplay | |
| 33 | |
| 853 | 34 First: It Is Better To Be Correct Than Fast |
| 35 Second: Thou Shalt Use Due Caution When Running Elisp From Within Redisplay | |
| 36 Third: It Is Better To Be Fast Than Not To Be | |
| 428 | 37 ****************************************************************************/ |
| 38 | |
| 1318 | 39 /* Note: The second rule used to prohibit running Elisp from within |
| 40 redisplay, but that's not correct any more -- use | |
| 41 call*_trapping_problems() or call_with_suspended_errors() instead. | |
| 853 | 42 |
| 43 --ben | |
| 44 */ | |
| 45 | |
| 428 | 46 #include <config.h> |
| 47 #include "lisp.h" | |
| 48 | |
| 49 #include "buffer.h" | |
| 50 #include "commands.h" | |
| 51 #include "debug.h" | |
| 872 | 52 #include "device-impl.h" |
| 428 | 53 #include "elhash.h" |
| 853 | 54 #include "events.h" |
| 872 | 55 #include "extents-impl.h" |
| 428 | 56 #include "faces.h" |
| 872 | 57 #include "frame-impl.h" |
| 428 | 58 #include "glyphs.h" |
| 59 #include "gutter.h" | |
| 60 #include "insdel.h" | |
| 61 #include "menubar.h" | |
|
5176
8b2f75cecb89
rename objects* (.c, .h and .el files) to fontcolor*
Ben Wing <ben@xemacs.org>
parents:
5049
diff
changeset
|
62 #include "fontcolor-impl.h" |
| 1318 | 63 #include "opaque.h" |
| 428 | 64 #include "process.h" |
| 1292 | 65 #include "profile.h" |
| 428 | 66 #include "redisplay.h" |
| 67 #include "toolbar.h" | |
| 872 | 68 #include "window-impl.h" |
| 428 | 69 #include "line-number.h" |
| 70 #include "file-coding.h" | |
| 71 | |
| 442 | 72 #include "sysfile.h" |
| 73 | |
| 428 | 74 #ifdef HAVE_TTY |
| 75 #include "console-tty.h" | |
| 76 #endif /* HAVE_TTY */ | |
| 77 | |
| 78 /* Note: We have to be careful throughout this code to properly handle | |
| 867 | 79 and differentiate between Ibytes and Ichars. |
| 80 | |
| 81 Since strings are generally composed of Ibytes, I've taken the tack | |
| 82 that any contiguous set of Ibytes is called a "string", while | |
| 83 any contiguous set of Ichars is called an "array". */ | |
| 428 | 84 |
| 85 /* Return value to indicate a failure by an add_*_rune routine to add | |
| 86 a rune, but no propagation information needs to be returned. */ | |
| 87 #define ADD_FAILED (prop_block_dynarr *) 1 | |
| 88 | |
| 89 #define BEGIN_GLYPHS 0 | |
| 90 #define END_GLYPHS 1 | |
| 91 #define LEFT_GLYPHS 2 | |
| 92 #define RIGHT_GLYPHS 3 | |
| 93 | |
| 94 #define VERTICAL_CLIP(w, display) \ | |
| 442 | 95 ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \ |
| 428 | 96 ? INT_MAX \ |
| 442 | 97 : vertical_clip) |
| 428 | 98 |
| 99 /* The following structures are completely private to redisplay.c so | |
| 100 we put them here instead of in a header file, for modularity. */ | |
| 101 | |
| 826 | 102 /* NOTE: Bytexpos's not Charxpos's in this structure. */ |
| 428 | 103 |
| 104 typedef struct position_redisplay_data_type | |
| 105 { | |
| 106 /* This information is normally filled in by the create_*_block | |
| 107 routines and is used by the add_*_rune routines. */ | |
| 108 Lisp_Object window; | |
| 109 /* if we are working with strings rather than buffers we need a | |
| 110 handle to the string */ | |
| 111 Lisp_Object string; | |
| 112 struct device *d; | |
| 113 struct display_block *db; | |
| 114 struct display_line *dl; | |
| 867 | 115 Ichar ch; /* Character that is to be added. This is |
| 428 | 116 used to communicate this information to |
| 867 | 117 add_ichar_rune(). */ |
| 428 | 118 Lisp_Object last_charset; /* The charset of the previous character. |
| 119 Used to optimize some lookups -- we | |
| 120 only have to do some things when | |
| 121 the charset changes. */ | |
| 122 face_index last_findex; /* The face index of the previous character. | |
| 123 Needed to ensure the validity of the | |
| 124 last_charset optimization. */ | |
| 125 | |
| 126 int last_char_width; /* The width of the previous character. */ | |
| 127 int font_is_bogus; /* If true, it means we couldn't instantiate | |
| 128 the font for this charset, so we substitute | |
| 129 ~'s from the ASCII charset. */ | |
| 826 | 130 Bytexpos byte_charpos; /* Position of character we are processing. This |
| 131 is a Bytexpos, meaning it refers to bytes (not | |
| 132 chars) and can refer to either buffers (1-based) | |
| 133 or strings (0-based). We need to be careful | |
| 134 when doing anything that references the text in | |
| 135 the buffer or string. */ | |
| 136 Bytexpos byte_endpos; /* ????? Unknown, under-used. */ | |
| 428 | 137 int pixpos; |
| 138 int max_pixpos; | |
| 139 int blank_width; /* Width of the blank that is to be added. | |
| 140 This is used to communicate this information | |
| 141 to add_blank_rune(). | |
| 142 | |
| 143 This is also used rather cheesily to | |
| 144 communicate the width of the eol-cursor-size | |
| 145 blank that exists at the end of the line. | |
| 867 | 146 add_ichar_rune() is called cheesily with |
| 428 | 147 the non-printing char '\n', which is stuck |
| 148 in the output routines with its width being | |
| 149 BLANK_WIDTH. */ | |
| 826 | 150 Bytexpos byte_cursor_charpos; /* This stores the buffer position of the |
| 151 cursor. */ | |
| 428 | 152 unsigned int cursor_type :3; |
| 153 int cursor_x; /* rune block cursor is at */ | |
| 154 int start_col; /* Number of character columns (each column has | |
| 155 a width of the default char width) that still | |
| 156 need to be skipped. This is used for horizontal | |
| 157 scrolling, where a certain number of columns | |
| 158 (those off the left side of the screen) need | |
| 159 to be skipped before anything is displayed. */ | |
| 826 | 160 Bytexpos byte_start_col_enabled; |
| 428 | 161 int start_col_xoffset; /* Number of pixels that still need to |
| 4187 | 162 be skipped. This is used for |
| 163 horizontal scrolling of glyphs, where we want | |
| 164 to be able to scroll over part of the glyph. */ | |
| 428 | 165 |
| 166 int hscroll_glyph_width_adjust; /* how much the width of the hscroll | |
| 167 glyph differs from space_width (w). | |
| 168 0 if no hscroll glyph was used, | |
| 169 i.e. the window is not scrolled | |
| 170 horizontally. Used in tab | |
| 171 calculations. */ | |
| 172 | |
| 173 /* Information about the face the text should be displayed in and | |
| 174 any begin-glyphs and end-glyphs. */ | |
| 175 struct extent_fragment *ef; | |
| 176 face_index findex; | |
| 177 | |
| 819 | 178 /* The height of a pixmap may either be predetermined if the user has set a |
| 179 baseline value, or it may be dependent on whatever the line ascent and | |
| 180 descent values end up being, based just on font and pixmap-ascent | |
| 181 information. In the first case we can immediately update the values, thus | |
| 182 their inclusion here. In the last case we cannot determine the actual | |
| 183 contribution to the line height until we have finished laying out all text | |
| 184 on the line. Thus we propagate the max height of such pixmaps and do a | |
| 185 final calculation (in calculate_baseline()) after all text has been added | |
| 186 to the line. */ | |
| 428 | 187 int new_ascent; |
| 188 int new_descent; | |
| 189 int max_pixmap_height; | |
| 819 | 190 int need_baseline_computation; |
| 191 int end_glyph_width; /* Well, it is the kitchen sink after all ... */ | |
| 428 | 192 |
| 193 Lisp_Object result_str; /* String where we put the result of | |
| 194 generating a formatted string in the modeline. */ | |
| 195 int is_modeline; /* Non-zero if we're generating the modeline. */ | |
| 196 Charcount modeline_charpos; /* Number of chars used in result_str so far; | |
| 197 corresponds to bytepos. */ | |
| 198 Bytecount bytepos; /* Number of bytes used in result_str so far. | |
| 4187 | 199 We don't actually copy the bytes into result_str |
| 428 | 200 until the end because we don't know how big the |
| 201 string is going to be until then. */ | |
| 202 } pos_data; | |
| 203 | |
| 204 enum prop_type | |
| 205 { | |
| 206 PROP_STRING, | |
| 207 PROP_CHAR, | |
| 208 PROP_MINIBUF_PROMPT, | |
| 819 | 209 PROP_BLANK, |
| 210 PROP_GLYPH | |
| 428 | 211 }; |
| 212 | |
| 213 /* Data that should be propagated to the next line. Either a single | |
| 867 | 214 Ichar, a string of Ibyte's or a glyph. |
| 428 | 215 |
| 216 The actual data that is propagated ends up as a Dynarr of these | |
| 217 blocks. | |
| 218 | |
| 819 | 219 prop_blocks are used to indicate that data that was supposed to go |
| 220 on the previous line couldn't actually be displayed. Generally this | |
| 221 shouldn't happen if we are clipping the end of lines. If we are | |
| 222 wrapping then we need to display the propagation data before moving | |
| 223 on. Its questionable whether we should wrap or clip glyphs in this | |
| 224 instance. Most e-lisp relies on clipping so we preserve this | |
| 225 behavior. | |
| 226 | |
| 867 | 227 #### It's unclean that both Ichars and Ibytes are here. |
| 428 | 228 */ |
| 229 | |
| 230 typedef struct prop_block prop_block; | |
| 231 struct prop_block | |
| 232 { | |
| 233 enum prop_type type; | |
| 234 | |
| 235 union data | |
| 236 { | |
| 237 struct | |
| 238 { | |
| 867 | 239 Ibyte *str; |
| 428 | 240 Bytecount len; /* length of the string. */ |
| 241 } p_string; | |
| 242 | |
| 243 struct | |
| 244 { | |
| 867 | 245 Ichar ch; |
| 826 | 246 Bytebpos byte_cursor_charpos; /* NOTE: is in Bytebpos's */ |
| 428 | 247 unsigned int cursor_type :3; |
| 248 } p_char; | |
| 249 | |
| 250 struct | |
| 251 { | |
| 252 int width; | |
| 253 face_index findex; | |
| 254 } p_blank; | |
| 819 | 255 |
| 256 struct | |
| 257 { | |
| 258 /* Not used as yet, but could be used to wrap rather than clip glyphs. */ | |
| 4187 | 259 int width; |
| 819 | 260 Lisp_Object glyph; |
| 261 } p_glyph; | |
| 262 | |
| 428 | 263 } data; |
| 264 }; | |
| 265 | |
| 266 typedef struct | |
| 267 { | |
| 268 Dynarr_declare (prop_block); | |
| 269 } prop_block_dynarr; | |
| 270 | |
| 271 | |
| 272 static Charcount generate_fstring_runes (struct window *w, pos_data *data, | |
| 273 Charcount pos, Charcount min_pos, | |
| 274 Charcount max_pos, Lisp_Object elt, | |
| 275 int depth, int max_pixsize, | |
| 438 | 276 face_index findex, int type, |
| 277 Charcount *offset, | |
| 278 Lisp_Object cur_ext); | |
| 428 | 279 static prop_block_dynarr *add_glyph_rune (pos_data *data, |
| 280 struct glyph_block *gb, | |
| 281 int pos_type, int allow_cursor, | |
| 282 struct glyph_cachel *cachel); | |
| 665 | 283 static Bytebpos create_text_block (struct window *w, struct display_line *dl, |
| 826 | 284 Bytebpos byte_start_pos, |
| 285 prop_block_dynarr **prop, | |
| 286 int type); | |
| 428 | 287 static int create_overlay_glyph_block (struct window *w, |
| 288 struct display_line *dl); | |
| 289 static void create_left_glyph_block (struct window *w, | |
| 290 struct display_line *dl, | |
| 291 int overlay_width); | |
| 292 static void create_right_glyph_block (struct window *w, | |
| 293 struct display_line *dl); | |
| 294 static void redisplay_windows (Lisp_Object window, int skip_selected); | |
| 867 | 295 static void decode_mode_spec (struct window *w, Ichar spec, int type); |
| 428 | 296 static void free_display_line (struct display_line *dl); |
| 826 | 297 static void update_line_start_cache (struct window *w, Charbpos from, |
| 298 Charbpos to, Charbpos point, | |
| 299 int no_regen); | |
| 665 | 300 static int point_visible (struct window *w, Charbpos point, int type); |
| 819 | 301 static void calculate_yoffset (struct display_line *dl, |
| 4187 | 302 struct display_block *fixup); |
| 819 | 303 static void calculate_baseline (pos_data *data); |
| 428 | 304 |
| 1204 | 305 #ifdef ERROR_CHECK_DISPLAY |
| 800 | 306 static void sledgehammer_check_redisplay_structs (void); |
| 1204 | 307 #endif /* ERROR_CHECK_DISPLAY */ |
| 800 | 308 |
| 428 | 309 /* This used to be 10 but 30 seems to give much better performance. */ |
| 310 #define INIT_MAX_PREEMPTS 30 | |
| 1268 | 311 static Fixnum max_preempts; |
| 312 | |
| 313 #define QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION 4 | |
| 428 | 314 |
| 1318 | 315 /* Note that doing this can call Lisp. */ |
| 428 | 316 #define REDISPLAY_PREEMPTION_CHECK \ |
| 317 ((void) \ | |
| 318 (preempted = \ | |
| 319 (!disable_preemption && \ | |
| 320 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \ | |
| 4187 | 321 (!INTERACTIVE || \ |
| 1268 | 322 detect_input_pending (QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION))))) |
| 428 | 323 |
| 324 /* | |
| 325 * Redisplay global variables. | |
| 326 */ | |
| 327 | |
| 328 /* We need a third set of display structures for the cursor motion | |
| 329 routines. We used to just give each window a third set. However, | |
| 330 we always fully regenerate the structures when needed so there | |
| 331 isn't any reason we need more than a single set. */ | |
| 332 display_line_dynarr *cmotion_display_lines; | |
| 333 | |
| 334 /* We store the extents that we need to generate in a Dynarr and then | |
| 335 frob them all on at the end of generating the string. We do it | |
| 336 this way rather than adding them as we generate the string because | |
| 337 we don't store the text into the resulting string until we're done | |
| 338 (to avoid having to resize the string multiple times), and we don't | |
| 339 want to go around adding extents to a string when the extents might | |
| 340 stretch off the end of the string. */ | |
| 341 static EXTENT_dynarr *formatted_string_extent_dynarr; | |
| 342 static Bytecount_dynarr *formatted_string_extent_start_dynarr; | |
| 343 static Bytecount_dynarr *formatted_string_extent_end_dynarr; | |
| 344 | |
| 345 | |
| 346 /* #### probably temporary */ | |
| 458 | 347 Fixnum cache_adjustment; |
| 428 | 348 |
| 349 /* This holds a string representing the text corresponding to a single | |
| 350 modeline % spec. */ | |
| 867 | 351 static Ibyte_dynarr *mode_spec_ibyte_string; |
| 428 | 352 |
| 353 int in_display; /* 1 if in redisplay. */ | |
| 354 | |
| 1318 | 355 /* Whether we should delay size changes. Broken out of |
| 356 enter_redisplay_critical_section(). */ | |
| 357 int hold_frame_size_changes; | |
| 358 | |
| 428 | 359 int disable_preemption; /* Used for debugging redisplay and for |
| 360 force-redisplay. */ | |
| 361 | |
| 362 /* We only allow max_preempts preemptions before we force a redisplay. */ | |
| 363 static int preemption_count; | |
| 364 | |
| 365 /* Minimum pixel height of clipped bottom display line. */ | |
| 458 | 366 Fixnum vertical_clip; |
| 428 | 367 |
| 368 /* Minimum visible pixel width of clipped glyphs at right margin. */ | |
| 458 | 369 Fixnum horizontal_clip; |
| 428 | 370 |
| 371 /* Nonzero means reading single-character input with prompt | |
| 372 so put cursor on minibuffer after the prompt. */ | |
| 373 int cursor_in_echo_area; | |
| 374 Lisp_Object Qcursor_in_echo_area; | |
| 375 | |
| 376 /* Nonzero means truncate lines in all windows less wide than the frame */ | |
| 377 int truncate_partial_width_windows; | |
| 378 | |
| 379 /* non-nil if a buffer has changed since the last time redisplay completed */ | |
| 380 int buffers_changed; | |
| 381 int buffers_changed_set; | |
| 382 | |
| 383 /* non-nil if hscroll has changed somewhere or a buffer has been | |
| 384 narrowed or widened */ | |
| 385 int clip_changed; | |
| 386 int clip_changed_set; | |
| 387 | |
| 388 /* non-nil if any extent has changed since the last time redisplay completed */ | |
| 389 int extents_changed; | |
| 390 int extents_changed_set; | |
| 391 | |
| 392 /* non-nil if any face has changed since the last time redisplay completed */ | |
| 393 int faces_changed; | |
| 394 | |
| 395 /* Nonzero means some frames have been marked as garbaged */ | |
| 396 int frame_changed; | |
| 397 | |
| 398 /* non-zero if any of the builtin display glyphs (continuation, | |
| 399 hscroll, control-arrow, etc) is in need of updating | |
| 400 somewhere. */ | |
| 401 int glyphs_changed; | |
| 402 int glyphs_changed_set; | |
| 403 | |
| 442 | 404 /* non-zero if any subwindow has been deleted. */ |
| 428 | 405 int subwindows_changed; |
| 406 int subwindows_changed_set; | |
| 407 | |
| 408 /* non-zero if any displayed subwindow is in need of updating | |
| 409 somewhere. */ | |
| 410 int subwindows_state_changed; | |
| 411 int subwindows_state_changed_set; | |
| 412 | |
| 413 /* This variable is 1 if the icon has to be updated. | |
| 414 It is set to 1 when `frame-icon-glyph' changes. */ | |
| 415 int icon_changed; | |
| 416 int icon_changed_set; | |
| 417 | |
| 418 /* This variable is 1 if the menubar widget has to be updated. | |
| 419 It is set to 1 by set-menubar-dirty-flag and cleared when the widget | |
| 420 has been updated. */ | |
| 421 int menubar_changed; | |
| 422 int menubar_changed_set; | |
| 423 | |
| 424 /* true iff we should redraw the modelines on the next redisplay */ | |
| 425 int modeline_changed; | |
| 426 int modeline_changed_set; | |
| 427 | |
| 428 /* non-nil if point has changed in some buffer since the last time | |
| 429 redisplay completed */ | |
| 430 int point_changed; | |
| 431 int point_changed_set; | |
| 432 | |
| 433 /* non-nil if some frame has changed its size */ | |
| 434 int size_changed; | |
| 435 | |
| 436 /* non-nil if some device has signaled that it wants to change size */ | |
| 437 int asynch_device_change_pending; | |
| 438 | |
| 439 /* non-nil if any toolbar has changed */ | |
| 440 int toolbar_changed; | |
| 441 int toolbar_changed_set; | |
| 442 | |
| 905 | 443 /* Nonzero if some frame has changed the layout of internal elements |
| 444 (gutters or toolbars). */ | |
| 445 int frame_layout_changed; | |
| 446 | |
| 428 | 447 /* non-nil if any gutter has changed */ |
| 448 int gutter_changed; | |
| 449 int gutter_changed_set; | |
| 450 | |
| 451 /* non-nil if any window has changed since the last time redisplay completed */ | |
| 452 int windows_changed; | |
| 453 | |
| 454 /* non-nil if any frame's window structure has changed since the last | |
| 455 time redisplay completed */ | |
| 456 int windows_structure_changed; | |
| 457 | |
| 458 /* If non-nil, use vertical bar cursor. */ | |
| 459 Lisp_Object Vbar_cursor; | |
| 460 Lisp_Object Qbar_cursor; | |
| 461 | |
| 442 | 462 Lisp_Object Vvisible_bell; /* If true and the terminal will support it |
| 463 then the frame will flash instead of | |
| 464 beeping when an error occurs */ | |
| 428 | 465 |
| 466 /* Nonzero means no need to redraw the entire frame on resuming | |
| 467 a suspended Emacs. This is useful on terminals with multiple pages, | |
| 468 where one page is used for Emacs and another for all else. */ | |
| 469 int no_redraw_on_reenter; | |
| 470 | |
| 3360 | 471 Lisp_Object Vwindow_system; /* #### this variable is deprecated |
| 472 nil or a symbol naming the window system | |
| 428 | 473 under which emacs is running |
| 3360 | 474 (`x', `gtk', `mswindows', and `tty' are |
| 475 supported -- yes, TTYs are window systems | |
| 476 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
|
477 Lisp_Object Vinitial_device_type; |
| 428 | 478 |
| 479 Lisp_Object Vglobal_mode_string; | |
| 480 | |
| 481 /* The number of lines scroll a window by when point leaves the window; if | |
| 482 it is <=0 then point is centered in the window */ | |
| 458 | 483 Fixnum scroll_step; |
| 428 | 484 |
| 485 /* Scroll up to this many lines, to bring point back on screen. */ | |
| 458 | 486 Fixnum scroll_conservatively; |
| 428 | 487 |
| 488 /* Marker for where to display an arrow on top of the buffer text. */ | |
| 489 Lisp_Object Voverlay_arrow_position; | |
| 490 /* String to display for the arrow. */ | |
| 491 Lisp_Object Voverlay_arrow_string; | |
| 492 | |
| 442 | 493 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook; |
| 494 | |
| 458 | 495 static Fixnum last_display_warning_tick; |
| 496 static Fixnum display_warning_tick; | |
| 428 | 497 Lisp_Object Qdisplay_warning_buffer; |
| 498 int inhibit_warning_display; | |
| 499 | |
| 500 Lisp_Object Vleft_margin_width, Vright_margin_width; | |
| 501 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; | |
| 502 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; | |
| 503 Lisp_Object Vtext_cursor_visible_p; | |
| 504 | |
| 1292 | 505 static Lisp_Object QSin_redisplay; |
| 506 | |
| 1318 | 507 static Lisp_Object Vpost_redisplay_actions; |
| 508 | |
| 428 | 509 int column_number_start_at_one; |
| 510 | |
| 442 | 511 Lisp_Object Qtop_bottom; |
| 512 | |
| 444 | 513 #define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset) |
| 428 | 514 |
| 1204 | 515 static const struct memory_description rune_dglyph_description_1[] = { |
| 516 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, glyph) }, | |
| 517 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, extent) }, | |
| 518 { XD_END } | |
| 519 }; | |
| 520 | |
| 521 static const struct sized_memory_description rune_dglyph_description = { | |
| 522 sizeof (struct rune_dglyph), rune_dglyph_description_1 | |
| 523 }; | |
| 524 | |
| 525 static const struct memory_description rune_object_description_1[] = { | |
| 2551 | 526 { XD_BLOCK_ARRAY, RUNE_DGLYPH, 1, { &rune_dglyph_description } }, |
| 1204 | 527 { XD_END } |
| 528 }; | |
| 529 | |
| 530 static const struct sized_memory_description rune_object_description = { | |
| 531 0, rune_object_description_1 | |
| 532 }; | |
| 533 | |
| 534 static const struct memory_description rune_description_1[] = { | |
| 535 { XD_INT, offsetof (rune, type) }, | |
| 536 { XD_UNION, offsetof (rune, object), | |
| 2551 | 537 XD_INDIRECT (0, 0), { &rune_object_description } }, |
| 1204 | 538 { XD_END } |
| 539 }; | |
| 540 | |
| 541 static const struct sized_memory_description rune_description = { | |
| 542 sizeof (rune), | |
| 543 rune_description_1 | |
| 544 }; | |
| 545 | |
| 546 static const struct memory_description rune_dynarr_description_1[] = { | |
| 547 XD_DYNARR_DESC (rune_dynarr, &rune_description), | |
| 548 { XD_END } | |
| 549 }; | |
| 550 | |
| 551 static const struct sized_memory_description rune_dynarr_description = { | |
| 552 sizeof (rune_dynarr), | |
| 553 rune_dynarr_description_1 | |
| 554 }; | |
| 555 | |
| 556 static const struct memory_description display_block_description_1[] = { | |
| 2367 | 557 { XD_BLOCK_PTR, offsetof (display_block, runes), |
| 2551 | 558 1, { &rune_dynarr_description } }, |
| 1204 | 559 { XD_END } |
| 560 }; | |
| 561 | |
| 562 static const struct sized_memory_description display_block_description = { | |
| 563 sizeof (display_block), | |
| 564 display_block_description_1 | |
| 565 }; | |
| 566 | |
| 567 static const struct memory_description display_block_dynarr_description_1[] = { | |
| 568 XD_DYNARR_DESC (display_block_dynarr, &display_block_description), | |
| 569 { XD_END } | |
| 570 }; | |
| 571 | |
| 572 static const struct sized_memory_description display_block_dynarr_description = { | |
| 573 sizeof (display_block_dynarr), | |
| 574 display_block_dynarr_description_1 | |
| 575 }; | |
| 576 | |
| 577 static const struct memory_description glyph_block_description_1[] = { | |
| 578 { XD_LISP_OBJECT, offsetof (glyph_block, glyph) }, | |
| 579 { XD_LISP_OBJECT, offsetof (glyph_block, extent) }, | |
| 580 { XD_END } | |
| 581 }; | |
| 582 | |
| 583 static const struct sized_memory_description glyph_block_description = { | |
| 584 sizeof (glyph_block), | |
| 585 glyph_block_description_1 | |
| 586 }; | |
| 587 | |
| 588 static const struct memory_description glyph_block_dynarr_description_1[] = { | |
| 589 XD_DYNARR_DESC (glyph_block_dynarr, &glyph_block_description), | |
| 590 { XD_END } | |
| 591 }; | |
| 592 | |
| 593 static const struct sized_memory_description glyph_block_dynarr_description = { | |
| 594 sizeof (glyph_block_dynarr), | |
| 595 glyph_block_dynarr_description_1 | |
| 596 }; | |
| 597 | |
| 598 static const struct memory_description display_line_description_1[] = { | |
| 2367 | 599 { XD_BLOCK_PTR, offsetof (display_line, display_blocks), |
| 2551 | 600 1, { &display_block_dynarr_description } }, |
| 2367 | 601 { XD_BLOCK_PTR, offsetof (display_line, left_glyphs), |
| 2551 | 602 1, { &glyph_block_dynarr_description } }, |
| 2367 | 603 { XD_BLOCK_PTR, offsetof (display_line, right_glyphs), |
| 2551 | 604 1, { &glyph_block_dynarr_description } }, |
| 1204 | 605 { XD_END } |
| 606 }; | |
| 607 | |
| 608 static const struct sized_memory_description display_line_description = { | |
| 609 sizeof (display_line), | |
| 610 display_line_description_1 | |
| 611 }; | |
| 612 | |
| 613 static const struct memory_description display_line_dynarr_description_1[] = { | |
| 614 XD_DYNARR_DESC (display_line_dynarr, &display_line_description), | |
| 615 { XD_END } | |
| 616 }; | |
| 617 | |
| 618 const struct sized_memory_description display_line_dynarr_description = { | |
| 619 sizeof (display_line_dynarr), | |
| 620 display_line_dynarr_description_1 | |
| 621 }; | |
| 622 | |
| 428 | 623 |
| 624 /***************************************************************************/ | |
| 625 /* */ | |
| 626 /* low-level interfaces onto device routines */ | |
| 627 /* */ | |
| 628 /***************************************************************************/ | |
| 629 | |
| 630 static int | |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
631 redisplay_window_text_width_ichar_string (struct window *w, int findex, |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
632 Ichar *str, Charcount len) |
| 428 | 633 { |
| 634 unsigned char charsets[NUM_LEADING_BYTES]; | |
| 635 Lisp_Object window; | |
| 636 | |
| 867 | 637 find_charsets_in_ichar_string (charsets, str, len); |
| 793 | 638 window = wrap_window (w); |
| 428 | 639 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window, |
| 640 charsets); | |
|
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
641 return DEVMETH (WINDOW_XDEVICE (w), |
|
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
642 text_width, (w, WINDOW_FACE_CACHEL (w, findex), str, |
|
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
643 len)); |
| 428 | 644 } |
| 645 | |
| 867 | 646 static Ichar_dynarr *rtw_ichar_dynarr; |
| 428 | 647 |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
648 static int |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
649 redisplay_window_text_width_string (struct window *w, int findex, |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
650 Ibyte *nonreloc, Lisp_Object reloc, |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
651 Bytecount offset, Bytecount len) |
| 428 | 652 { |
| 867 | 653 if (!rtw_ichar_dynarr) |
| 654 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
| 655 Dynarr_reset (rtw_ichar_dynarr); | |
| 428 | 656 |
| 657 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
| 658 if (STRINGP (reloc)) | |
| 659 nonreloc = XSTRING_DATA (reloc); | |
| 867 | 660 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
661 return redisplay_window_text_width_ichar_string |
| 4967 | 662 (w, findex, Dynarr_begin (rtw_ichar_dynarr), |
| 867 | 663 Dynarr_length (rtw_ichar_dynarr)); |
| 428 | 664 } |
| 665 | |
| 666 int | |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
667 redisplay_text_width_string (Lisp_Object domain, Lisp_Object face, |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
668 Ibyte *nonreloc, Lisp_Object reloc, |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
669 Bytecount offset, Bytecount len) |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
670 { |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
671 Lisp_Object window = DOMAIN_WINDOW (domain); |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
672 Lisp_Object frame = DOMAIN_FRAME (domain); |
| 428 | 673 unsigned char charsets[NUM_LEADING_BYTES]; |
| 674 struct face_cachel cachel; | |
| 675 | |
| 867 | 676 if (!rtw_ichar_dynarr) |
| 677 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
| 678 Dynarr_reset (rtw_ichar_dynarr); | |
| 428 | 679 |
| 680 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
| 681 if (STRINGP (reloc)) | |
| 682 nonreloc = XSTRING_DATA (reloc); | |
| 867 | 683 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
| 684 find_charsets_in_ibyte_string (charsets, nonreloc, len); | |
| 428 | 685 reset_face_cachel (&cachel); |
| 686 cachel.face = face; | |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
687 ensure_face_cachel_complete (&cachel, |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
688 NILP (window) ? frame : window, |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
689 charsets); |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
690 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (frame))), |
|
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
691 /* #### Not clear if we're always passed a window, but |
|
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
692 I think so. If not, we will get an abort here, |
|
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
693 and then we need to either fix the callers to pass in |
|
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
694 a window, or change *text_width() to take a domain |
|
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
695 argument. */ |
|
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
696 text_width, (XWINDOW (window), |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
697 &cachel, |
| 4967 | 698 Dynarr_begin (rtw_ichar_dynarr), |
| 867 | 699 Dynarr_length (rtw_ichar_dynarr))); |
| 428 | 700 } |
| 701 | |
| 702 /* Return the display block from DL of the given TYPE. A display line | |
| 703 can have only one display block of each possible type. If DL does | |
| 704 not have a block of type TYPE, one will be created and added to DL. */ | |
| 705 | |
| 706 struct display_block * | |
| 707 get_display_block_from_line (struct display_line *dl, enum display_type type) | |
| 708 { | |
| 709 int elt; | |
| 710 struct display_block db; | |
| 711 | |
| 712 /* Check if this display line already has a block of the desired type and | |
| 713 if so, return it. */ | |
| 714 if (dl->display_blocks) | |
| 715 { | |
| 716 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++) | |
| 717 { | |
| 718 if (Dynarr_at (dl->display_blocks, elt).type == type) | |
| 719 return Dynarr_atp (dl->display_blocks, elt); | |
| 720 } | |
| 721 | |
| 722 /* There isn't an active block of the desired type, but there | |
| 4187 | 723 might still be allocated blocks we need to reuse. */ |
| 428 | 724 if (elt < Dynarr_largest (dl->display_blocks)) |
| 725 { | |
| 726 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt); | |
| 727 | |
| 3025 | 728 /* "add" the block to the list */ |
| 5038 | 729 Dynarr_incrementr (dl->display_blocks); |
| 428 | 730 |
| 731 /* initialize and return */ | |
| 732 dbp->type = type; | |
| 733 return dbp; | |
| 734 } | |
| 735 } | |
| 736 else | |
| 737 { | |
| 738 /* This line doesn't have any display blocks, so initialize the display | |
| 4187 | 739 bock array. */ |
| 428 | 740 dl->display_blocks = Dynarr_new (display_block); |
| 741 } | |
| 742 | |
| 743 /* The line doesn't have a block of the desired type so go ahead and create | |
| 744 one and add it to the line. */ | |
| 745 xzero (db); | |
| 746 db.type = type; | |
| 747 db.runes = Dynarr_new (rune); | |
| 748 Dynarr_add (dl->display_blocks, db); | |
| 749 | |
| 750 /* Return the newly added display block. */ | |
| 751 elt = Dynarr_length (dl->display_blocks) - 1; | |
| 752 | |
| 753 return Dynarr_atp (dl->display_blocks, elt); | |
| 754 } | |
| 755 | |
| 756 static int | |
| 757 tab_char_width (struct window *w) | |
| 758 { | |
| 759 struct buffer *b = XBUFFER (w->buffer); | |
| 760 int char_tab_width = XINT (b->tab_width); | |
| 761 | |
| 762 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8; | |
| 763 | |
| 764 return char_tab_width; | |
| 765 } | |
| 766 | |
| 767 static int | |
| 768 space_width (struct window *w) | |
| 769 { | |
| 3659 | 770 /* While tabs are traditionally composed of spaces, for variable-width |
| 428 | 771 fonts the space character tends to give too narrow a value. So |
| 772 we use 'n' instead. Except that we don't. We use the default | |
| 773 character width for the default face. If this is actually | |
| 774 defined by the font then it is probably the best thing to | |
| 775 actually use. If it isn't, we have assumed it is 'n' and have | |
| 776 already calculated its width. Thus we can avoid a call to | |
| 777 XTextWidth on X frames by just querying the default width. */ | |
| 778 return XFONT_INSTANCE | |
| 779 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width; | |
| 780 } | |
| 781 | |
| 782 static int | |
| 783 tab_pix_width (struct window *w) | |
| 784 { | |
| 785 return space_width (w) * tab_char_width (w); | |
| 786 } | |
| 787 | |
| 788 /* Given a pixel position in a window, return the pixel location of | |
| 789 the next tabstop. Tabs are calculated from the left window edge in | |
| 790 terms of spaces displayed in the default face. Formerly the space | |
| 791 width was determined using the currently active face. That method | |
| 792 leads to tabstops which do not line up. */ | |
| 793 | |
| 794 static int | |
| 795 next_tab_position (struct window *w, int start_pixpos, int left_pixpos) | |
| 796 { | |
| 797 int n_pos = left_pixpos; | |
| 798 int pix_tab_width = tab_pix_width (w); | |
| 799 | |
| 800 /* Adjust n_pos for any hscrolling which has happened. */ | |
| 801 if (WINDOW_SCROLLED (w)) | |
| 802 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset; | |
| 803 | |
| 804 while (n_pos <= start_pixpos) | |
| 805 n_pos += pix_tab_width; | |
| 806 | |
| 807 return n_pos; | |
| 808 } | |
| 809 | |
| 810 /* For the given window, calculate the outside and margin boundaries for a | |
| 811 display line. The whitespace boundaries must be calculated by the text | |
| 812 layout routines. */ | |
| 813 | |
| 814 layout_bounds | |
| 815 calculate_display_line_boundaries (struct window *w, int modeline) | |
| 816 { | |
| 817 layout_bounds bounds; | |
| 818 | |
| 819 /* Set the outermost boundaries which are the boundaries of the | |
| 820 window itself minus the gutters (and minus the scrollbars if this | |
| 821 is for the modeline). */ | |
| 822 if (!modeline) | |
| 823 { | |
| 824 bounds.left_out = WINDOW_TEXT_LEFT (w); | |
| 825 bounds.right_out = WINDOW_TEXT_RIGHT (w); | |
| 826 } | |
| 827 else | |
| 828 { | |
| 829 bounds.left_out = WINDOW_MODELINE_LEFT (w); | |
| 830 bounds.right_out = WINDOW_MODELINE_RIGHT (w); | |
| 831 } | |
| 832 | |
| 833 /* The inner boundaries mark where the glyph margins are located. */ | |
| 834 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
| 835 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
| 836 | |
| 837 /* We cannot fully calculate the whitespace boundaries as they | |
| 838 depend on the contents of the line being displayed. */ | |
| 839 bounds.left_white = bounds.left_in; | |
| 840 bounds.right_white = bounds.right_in; | |
| 841 | |
| 842 return bounds; | |
| 843 } | |
| 844 | |
| 819 | 845 /* This takes a display_block and its containing line and corrects the yoffset |
| 846 of each glyph in the block to cater for the ascent of the line as a | |
| 847 whole. Must be called *after* the line-ascent is known! */ | |
| 848 | |
| 849 static void | |
| 850 calculate_yoffset (struct display_line *dl, struct display_block *fixup) | |
| 851 { | |
| 852 int i; | |
| 853 for (i=0; i<Dynarr_length (fixup->runes); i++) | |
| 854 { | |
| 855 struct rune *r = Dynarr_atp (fixup->runes,i); | |
| 856 if (r->type == RUNE_DGLYPH) | |
| 4187 | 857 { |
| 858 if (r->object.dglyph.ascent < dl->ascent) | |
| 859 r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent + | |
| 819 | 860 r->object.dglyph.descent; |
| 4187 | 861 } |
| 819 | 862 } |
| 863 } | |
| 864 | |
| 865 /* Calculate the textual baseline (the ascent and descent values for the | |
| 866 display_line as a whole). | |
| 867 | |
| 868 If the baseline is completely blank, or contains no manually positioned | |
| 869 glyphs, then the textual baseline is simply the baseline of the default font. | |
| 870 (The `contains no manually positioned glyphs' part is actually done for | |
| 867 | 871 us by `add_ichar_rune'.) |
| 819 | 872 |
| 873 If the baseline contains pixmaps, and they're all manually positioned, then | |
| 874 the textual baseline location is constrained that way, and we need do no | |
| 875 work. | |
| 876 | |
| 877 If the baseline contains pixmaps, and at least one is automatically | |
| 878 positioned, then the textual ascent is the largest ascent on the line, and | |
| 879 the textual descent is the largest descent (which is how things are set up at | |
| 880 entry to this function anyway): except that if the max_ascent + max_descent | |
| 881 is too small for the height of the line (say you've adjusted the baseline of | |
| 882 a short glyph, and there's a tall one next to it), then take the ascent and | |
| 883 descent for the line individually from the largest of the explicitly set | |
| 884 ascent/descent, and the rescaled ascent/descent of the default font, scaled | |
| 885 such that the largest glyph will fit. | |
| 886 | |
| 887 This means that if you have a short glyph (but taller than the default | |
| 888 font's descent) forced right under the baseline, and a really tall | |
| 889 automatically positioned glyph, that the descent for the line is just big | |
| 890 enough for the manually positioned short glyph, and the tall one uses as | |
| 891 much of that space as the default font would were it as tall as the tall | |
| 892 glyph; but that the ascent is big enough for the tall glyph to fit. | |
| 893 | |
| 894 This behaviour means that under no circumstances will changing the baseline | |
| 895 of a short glyph cause a tall glyph to move around; nor will it move the | |
| 896 textual baseline more than necessary. (Changing a tall glyph's baseline | |
| 897 might move the text's baseline arbitrarily, of course.) */ | |
| 898 | |
| 899 static void | |
| 900 calculate_baseline (pos_data *data) | |
| 901 { | |
| 902 /* Blank line: baseline is default font's baseline. */ | |
| 903 | |
| 904 if (!data->new_ascent && !data->new_descent) | |
| 905 { | |
| 906 /* We've got a blank line so initialize these values from the default | |
| 4187 | 907 face. */ |
| 819 | 908 default_face_font_info (data->window, &data->new_ascent, |
| 909 &data->new_descent, 0, 0, 0); | |
| 910 } | |
| 4187 | 911 |
| 819 | 912 /* No automatically positioned glyphs? Return at once. */ |
| 913 if (!data->need_baseline_computation) | |
| 914 return; | |
| 915 | |
| 916 /* Is the tallest glyph on the line automatically positioned? | |
| 917 If it's manually positioned, or it's automatically positioned | |
| 918 and there's enough room for it anyway, we need do no more work. */ | |
| 919 if (data->max_pixmap_height > data->new_ascent + data->new_descent) | |
| 920 { | |
| 921 int default_font_ascent, default_font_descent, default_font_height; | |
| 922 int scaled_default_font_ascent, scaled_default_font_descent; | |
| 4187 | 923 |
| 819 | 924 default_face_font_info (data->window, &default_font_ascent, |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
925 &default_font_descent, 0, &default_font_height, |
|
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
926 0); |
| 819 | 927 |
| 928 scaled_default_font_ascent = data->max_pixmap_height * | |
| 929 default_font_ascent / default_font_height; | |
| 930 | |
| 931 data->new_ascent = max (data->new_ascent, scaled_default_font_ascent); | |
| 932 | |
| 933 /* The ascent may have expanded now. Do we still need to grow the descent, | |
| 4187 | 934 or are things big enough? |
| 935 | |
| 936 The +1 caters for the baseline row itself. */ | |
| 819 | 937 if (data->max_pixmap_height > data->new_ascent + data->new_descent) |
| 4187 | 938 { |
| 939 scaled_default_font_descent = (data->max_pixmap_height * | |
| 819 | 940 default_font_descent / default_font_height) + 1; |
| 941 | |
| 4187 | 942 data->new_descent = max (data->new_descent, scaled_default_font_descent); |
| 943 } | |
| 819 | 944 } |
| 945 } | |
| 946 | |
| 428 | 947 /* Given a display line and a starting position, ensure that the |
| 948 contents of the display line accurately represent the visual | |
| 949 representation of the buffer contents starting from the given | |
| 950 position when displayed in the given window. The display line ends | |
| 951 when the contents of the line reach the right boundary of the given | |
| 952 window. */ | |
| 953 | |
| 665 | 954 static Charbpos |
| 428 | 955 generate_display_line (struct window *w, struct display_line *dl, int bounds, |
| 665 | 956 Charbpos start_pos, prop_block_dynarr **prop, |
| 428 | 957 int type) |
| 958 { | |
| 826 | 959 Charbpos ret_charpos; |
| 428 | 960 int overlay_width; |
| 961 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); | |
| 962 | |
| 963 /* If our caller hasn't already set the boundaries, then do so now. */ | |
| 964 if (!bounds) | |
| 965 dl->bounds = calculate_display_line_boundaries (w, 0); | |
| 966 | |
| 967 /* Reset what this line is using. */ | |
| 968 if (dl->display_blocks) | |
| 969 Dynarr_reset (dl->display_blocks); | |
| 970 if (dl->left_glyphs) | |
| 971 { | |
| 972 Dynarr_free (dl->left_glyphs); | |
| 973 dl->left_glyphs = 0; | |
| 974 } | |
| 975 if (dl->right_glyphs) | |
| 976 { | |
| 977 Dynarr_free (dl->right_glyphs); | |
| 978 dl->right_glyphs = 0; | |
| 979 } | |
| 980 | |
| 981 /* We aren't generating a modeline at the moment. */ | |
| 982 dl->modeline = 0; | |
| 983 | |
| 984 /* Create a display block for the text region of the line. */ | |
| 985 { | |
| 986 /* #### urk urk urk!!! Chuck fix this shit! */ | |
| 665 | 987 Bytebpos hacked_up_bytebpos = |
| 988 create_text_block (w, dl, charbpos_to_bytebpos (b, start_pos), | |
| 428 | 989 prop, type); |
| 826 | 990 if (hacked_up_bytebpos > BYTE_BUF_ZV (b)) |
| 991 ret_charpos = BUF_ZV (b) + 1; | |
| 428 | 992 else |
| 826 | 993 ret_charpos = bytebpos_to_charbpos (b, hacked_up_bytebpos); |
| 428 | 994 } |
| 826 | 995 dl->charpos = start_pos; |
| 996 if (dl->end_charpos < dl->charpos) | |
| 997 dl->end_charpos = dl->charpos; | |
| 428 | 998 |
| 999 if (MARKERP (Voverlay_arrow_position) | |
| 1000 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position)) | |
| 1001 && start_pos == marker_position (Voverlay_arrow_position) | |
| 1002 && (STRINGP (Voverlay_arrow_string) | |
| 1003 || GLYPHP (Voverlay_arrow_string))) | |
| 1004 { | |
| 1005 overlay_width = create_overlay_glyph_block (w, dl); | |
| 1006 } | |
| 1007 else | |
| 1008 overlay_width = 0; | |
| 1009 | |
| 1010 /* If there are left glyphs associated with any character in the | |
| 1011 text block, then create a display block to handle them. */ | |
| 1012 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
| 1013 create_left_glyph_block (w, dl, overlay_width); | |
| 1014 | |
| 1015 /* If there are right glyphs associated with any character in the | |
| 1016 text block, then create a display block to handle them. */ | |
| 1017 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
| 1018 create_right_glyph_block (w, dl); | |
| 1019 | |
| 1020 /* In the future additional types of display blocks may be generated | |
| 1021 here. */ | |
| 1022 | |
| 826 | 1023 w->last_redisplay_pos = ret_charpos; |
| 1024 | |
| 1025 return ret_charpos; | |
| 428 | 1026 } |
| 1027 | |
| 1028 /* Adds an hscroll glyph to a display block. If this is called, then | |
| 1029 the block had better be empty. | |
| 1030 | |
| 1031 Yes, there are multiple places where this function is called but | |
| 1032 that is the way it has to be. Each calling function has to deal | |
| 826 | 1033 with byte_start_col_enabled a little differently depending on the |
| 428 | 1034 object being worked with. */ |
| 1035 | |
| 1036 static prop_block_dynarr * | |
| 1037 add_hscroll_rune (pos_data *data) | |
| 1038 { | |
| 1039 struct glyph_block gb; | |
| 1040 prop_block_dynarr *retval; | |
| 826 | 1041 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
| 647 | 1042 int old_cursor_type = data->cursor_type; |
| 826 | 1043 Bytebpos byte_old_charpos = data->byte_charpos; |
| 428 | 1044 |
| 1045 if (data->cursor_type == CURSOR_ON | |
| 826 | 1046 && data->byte_cursor_charpos >= data->byte_start_col_enabled |
| 1047 && data->byte_cursor_charpos <= data->byte_charpos) | |
| 1048 { | |
| 1049 data->byte_cursor_charpos = data->byte_start_col_enabled; | |
| 428 | 1050 } |
| 1051 else | |
| 1052 { | |
| 1053 data->cursor_type = NO_CURSOR; | |
| 1054 } | |
| 1055 | |
| 826 | 1056 data->byte_endpos = data->byte_charpos; |
| 1057 data->byte_charpos = data->byte_start_col_enabled; | |
| 428 | 1058 |
| 1059 gb.extent = Qnil; | |
| 1060 gb.glyph = Vhscroll_glyph; | |
| 1061 { | |
| 1062 int oldpixpos = data->pixpos; | |
| 442 | 1063 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, |
| 428 | 1064 GLYPH_CACHEL (XWINDOW (data->window), |
| 1065 HSCROLL_GLYPH_INDEX)); | |
| 1066 data->hscroll_glyph_width_adjust = | |
| 1067 data->pixpos - oldpixpos - space_width (XWINDOW (data->window)); | |
| 1068 } | |
| 826 | 1069 data->byte_endpos = 0; |
| 1070 data->byte_cursor_charpos = byte_old_cursor_charpos; | |
| 428 | 1071 data->cursor_type = old_cursor_type; |
| 826 | 1072 data->byte_charpos = byte_old_charpos; |
| 1073 | |
| 1074 data->byte_start_col_enabled = 0; | |
| 428 | 1075 return retval; |
| 1076 } | |
| 1077 | |
| 793 | 1078 /* Adds a character rune to a display block. If there is not enough room |
| 1079 to fit the rune on the display block (as determined by the MAX_PIXPOS) | |
| 1080 then it adds nothing and returns ADD_FAILED. If | |
| 1081 NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't allow the char's height | |
| 867 | 1082 to affect the total line height. (See add_ibyte_string_runes()). */ |
| 428 | 1083 |
| 1084 static prop_block_dynarr * | |
| 867 | 1085 add_ichar_rune_1 (pos_data *data, int no_contribute_to_line_height) |
| 428 | 1086 { |
| 1087 struct rune rb, *crb; | |
| 1088 int width, local; | |
| 1089 | |
| 1090 if (data->start_col) | |
| 1091 { | |
| 1092 data->start_col--; | |
| 1093 | |
| 1094 if (data->start_col) | |
| 1095 return NULL; | |
| 1096 } | |
| 1097 | |
| 826 | 1098 if (data->byte_start_col_enabled) |
| 428 | 1099 { |
| 1100 return add_hscroll_rune (data); | |
| 1101 } | |
| 1102 | |
| 1103 if (data->ch == '\n') | |
| 1104 { | |
| 1105 data->font_is_bogus = 0; | |
| 1106 /* Cheesy end-of-line pseudo-character. */ | |
| 1107 width = data->blank_width; | |
| 1108 } | |
| 1109 else | |
| 1110 { | |
| 867 | 1111 Lisp_Object charset = ichar_charset (data->ch); |
| 428 | 1112 if (!EQ (charset, data->last_charset) || |
| 1113 data->findex != data->last_findex) | |
| 1114 { | |
| 1115 /* OK, we need to do things the hard way. */ | |
| 1116 struct window *w = XWINDOW (data->window); | |
| 1117 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex); | |
| 1118 Lisp_Object font_instance = | |
| 1119 ensure_face_cachel_contains_charset (cachel, data->window, | |
| 1120 charset); | |
| 440 | 1121 Lisp_Font_Instance *fi; |
| 428 | 1122 |
| 1123 if (EQ (font_instance, Vthe_null_font_instance)) | |
| 1124 { | |
| 1125 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); | |
| 1126 data->font_is_bogus = 1; | |
| 1127 } | |
| 1128 else | |
| 1129 data->font_is_bogus = 0; | |
| 1130 | |
| 1131 fi = XFONT_INSTANCE (font_instance); | |
| 771 | 1132 if (!fi->proportional_p || data->font_is_bogus) |
| 1133 { | |
| 867 | 1134 Ichar ch = data->font_is_bogus ? '~' : data->ch; |
| 771 | 1135 |
| 1136 data->last_char_width = | |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1137 redisplay_window_text_width_ichar_string |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1138 (XWINDOW (data->window), data->findex, &ch, 1); |
| 771 | 1139 } |
| 428 | 1140 else |
| 1141 data->last_char_width = -1; | |
| 819 | 1142 |
| 793 | 1143 if (!no_contribute_to_line_height) |
| 1144 { | |
| 1145 data->new_ascent = max (data->new_ascent, (int) fi->ascent); | |
| 1146 data->new_descent = max (data->new_descent, (int) fi->descent); | |
| 1147 } | |
| 819 | 1148 |
| 428 | 1149 data->last_charset = charset; |
| 1150 data->last_findex = data->findex; | |
| 1151 } | |
| 1152 | |
| 1153 width = data->last_char_width; | |
| 771 | 1154 if (width < 0) /* proportional fonts */ |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1155 width = redisplay_window_text_width_ichar_string |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1156 (XWINDOW (data->window), data->findex, &data->ch, 1); |
| 428 | 1157 } |
| 1158 | |
| 1159 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos)) | |
| 1160 { | |
| 1161 return ADD_FAILED; | |
| 1162 } | |
| 1163 | |
| 1164 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes)) | |
| 1165 { | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
1166 crb = Dynarr_past_lastp (data->db->runes); |
| 428 | 1167 local = 0; |
| 1168 } | |
| 1169 else | |
| 1170 { | |
| 1171 crb = &rb; | |
| 1172 local = 1; | |
| 1173 } | |
| 1174 | |
| 1175 crb->findex = data->findex; | |
| 1176 crb->xpos = data->pixpos; | |
| 1177 crb->width = width; | |
| 826 | 1178 if (data->byte_charpos) |
| 428 | 1179 { |
| 1180 if (NILP (data->string)) | |
| 826 | 1181 crb->charpos = |
| 793 | 1182 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER |
| 1183 (XWINDOW (data->window))), | |
| 826 | 1184 data->byte_charpos); |
| 428 | 1185 else |
| 826 | 1186 crb->charpos = |
| 1187 string_index_byte_to_char (data->string, data->byte_charpos); | |
| 428 | 1188 } |
| 1189 else if (data->is_modeline) | |
| 826 | 1190 crb->charpos = data->modeline_charpos; |
| 428 | 1191 else |
| 442 | 1192 /* Text but not in buffer */ |
| 826 | 1193 crb->charpos = 0; |
| 428 | 1194 crb->type = RUNE_CHAR; |
| 1195 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch; | |
| 1196 crb->endpos = 0; | |
| 1197 | |
| 1198 if (data->cursor_type == CURSOR_ON) | |
| 1199 { | |
| 826 | 1200 if (data->byte_charpos == data->byte_cursor_charpos) |
| 428 | 1201 { |
| 1202 crb->cursor_type = CURSOR_ON; | |
| 1203 data->cursor_x = Dynarr_length (data->db->runes); | |
| 1204 } | |
| 1205 else | |
| 1206 crb->cursor_type = CURSOR_OFF; | |
| 1207 } | |
| 1208 else if (data->cursor_type == NEXT_CURSOR) | |
| 1209 { | |
| 1210 crb->cursor_type = CURSOR_ON; | |
| 1211 data->cursor_x = Dynarr_length (data->db->runes); | |
| 1212 data->cursor_type = NO_CURSOR; | |
| 1213 } | |
| 1214 else if (data->cursor_type == IGNORE_CURSOR) | |
| 1215 crb->cursor_type = IGNORE_CURSOR; | |
| 1216 else | |
| 1217 crb->cursor_type = CURSOR_OFF; | |
| 1218 | |
| 1219 if (local) | |
| 1220 Dynarr_add (data->db->runes, *crb); | |
| 1221 else | |
| 5038 | 1222 Dynarr_incrementr (data->db->runes); |
| 428 | 1223 |
| 1224 data->pixpos += width; | |
| 1225 | |
| 1226 return NULL; | |
| 1227 } | |
| 1228 | |
| 793 | 1229 static prop_block_dynarr * |
| 867 | 1230 add_ichar_rune (pos_data *data) |
| 1231 { | |
| 1232 return add_ichar_rune_1 (data, 0); | |
| 1233 } | |
| 1234 | |
| 1235 /* Given a string C_STRING of length C_LENGTH, call add_ichar_rune for | |
| 793 | 1236 each character in the string. Propagate any left-over data unless |
| 1237 NO_PROP is non-zero. If NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't | |
| 1238 allow this character to increase the total height of the line. (This is | |
| 1239 used when the character is part of a text glyph. In that case, the | |
| 1240 glyph code itself adjusts the line height as necessary, depending on | |
| 1241 whether glyph-contrib-p is true.) */ | |
| 428 | 1242 |
| 1243 static prop_block_dynarr * | |
| 867 | 1244 add_ibyte_string_runes (pos_data *data, Ibyte *c_string, |
| 793 | 1245 Bytecount c_length, int no_prop, |
| 1246 int no_contribute_to_line_height) | |
| 428 | 1247 { |
| 867 | 1248 Ibyte *pos, *end = c_string + c_length; |
| 428 | 1249 prop_block_dynarr *prop; |
| 1250 | |
| 1251 /* #### This function is too simplistic. It needs to do the same | |
| 1252 sort of character interpretation (display-table lookup, | |
| 1253 ctl-arrow checking), etc. that create_text_block() does. | |
| 1254 The functionality to do this in that routine needs to be | |
| 1255 modularized. */ | |
| 1256 | |
| 1257 for (pos = c_string; pos < end;) | |
| 1258 { | |
| 867 | 1259 Ibyte *old_pos = pos; |
| 1260 | |
| 1261 data->ch = itext_ichar (pos); | |
| 1262 | |
| 1263 prop = add_ichar_rune_1 (data, no_contribute_to_line_height); | |
| 428 | 1264 |
| 1265 if (prop) | |
| 1266 { | |
| 1267 if (no_prop) | |
| 1268 return ADD_FAILED; | |
| 1269 else | |
| 1270 { | |
| 1271 struct prop_block pb; | |
| 1272 Bytecount len = end - pos; | |
| 1273 prop = Dynarr_new (prop_block); | |
| 1274 | |
| 1275 pb.type = PROP_STRING; | |
| 867 | 1276 pb.data.p_string.str = xnew_array (Ibyte, len); |
| 4970 | 1277 qxestrncpy (pb.data.p_string.str, pos, len); |
| 428 | 1278 pb.data.p_string.len = len; |
| 1279 | |
| 1280 Dynarr_add (prop, pb); | |
| 1281 return prop; | |
| 1282 } | |
| 1283 } | |
| 867 | 1284 INC_IBYTEPTR (pos); |
| 428 | 1285 assert (pos <= end); |
| 464 | 1286 /* #### Duplicate code from add_string_to_fstring_db_runes |
| 1287 should we do more?*/ | |
| 1288 data->bytepos += pos - old_pos; | |
| 428 | 1289 } |
| 1290 | |
| 1291 return NULL; | |
| 1292 } | |
| 1293 | |
| 1294 /* Add a single rune of the specified width. The area covered by this | |
| 1295 rune will be displayed in the foreground color of the associated | |
| 1296 face. */ | |
| 1297 | |
| 1298 static prop_block_dynarr * | |
| 1299 add_blank_rune (pos_data *data, struct window *w, int char_tab_width) | |
| 1300 { | |
| 1301 struct rune rb; | |
| 1302 | |
| 1303 /* If data->start_col is not 0 then this call to add_blank_rune must have | |
| 1304 been to add it as a tab. */ | |
| 1305 if (data->start_col) | |
| 1306 { | |
| 1307 /* assert (w != NULL) */ | |
| 1308 prop_block_dynarr *retval; | |
| 1309 | |
| 1310 /* If we have still not fully scrolled horizontally, subtract | |
| 4187 | 1311 the width of this tab and return. */ |
| 428 | 1312 if (char_tab_width < data->start_col) |
| 1313 { | |
| 1314 data->start_col -= char_tab_width; | |
| 1315 return NULL; | |
| 1316 } | |
| 1317 else if (char_tab_width == data->start_col) | |
| 1318 data->blank_width = 0; | |
| 1319 else | |
| 1320 { | |
| 1321 int spcwid = space_width (w); | |
| 1322 | |
| 1323 if (spcwid >= data->blank_width) | |
| 1324 data->blank_width = 0; | |
| 1325 else | |
| 1326 data->blank_width -= spcwid; | |
| 1327 } | |
| 1328 | |
| 1329 data->start_col = 0; | |
| 1330 retval = add_hscroll_rune (data); | |
| 1331 | |
| 1332 /* Could be caused by the handling of the hscroll rune. */ | |
| 1333 if (retval != NULL || !data->blank_width) | |
| 1334 return retval; | |
| 1335 } | |
| 1336 | |
| 1337 /* Blank runes are always calculated to fit. */ | |
| 1338 assert (data->pixpos + data->blank_width <= data->max_pixpos); | |
| 1339 | |
| 1340 rb.findex = data->findex; | |
| 1341 rb.xpos = data->pixpos; | |
| 1342 rb.width = data->blank_width; | |
| 826 | 1343 if (data->byte_charpos) |
| 1344 rb.charpos = | |
| 665 | 1345 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))), |
| 826 | 1346 data->byte_charpos); |
| 428 | 1347 else |
| 1348 /* #### and this is really correct too? */ | |
| 826 | 1349 rb.charpos = 0; |
| 428 | 1350 rb.endpos = 0; |
| 1351 rb.type = RUNE_BLANK; | |
| 1352 | |
| 1353 if (data->cursor_type == CURSOR_ON) | |
| 1354 { | |
| 826 | 1355 if (data->byte_charpos == data->byte_cursor_charpos) |
| 428 | 1356 { |
| 1357 rb.cursor_type = CURSOR_ON; | |
| 1358 data->cursor_x = Dynarr_length (data->db->runes); | |
| 1359 } | |
| 1360 else | |
| 1361 rb.cursor_type = CURSOR_OFF; | |
| 1362 } | |
| 1363 else if (data->cursor_type == NEXT_CURSOR) | |
| 1364 { | |
| 1365 rb.cursor_type = CURSOR_ON; | |
| 1366 data->cursor_x = Dynarr_length (data->db->runes); | |
| 1367 data->cursor_type = NO_CURSOR; | |
| 1368 } | |
| 1369 else | |
| 1370 rb.cursor_type = CURSOR_OFF; | |
| 1371 | |
| 1372 Dynarr_add (data->db->runes, rb); | |
| 1373 data->pixpos += data->blank_width; | |
| 1374 | |
| 1375 return NULL; | |
| 1376 } | |
| 1377 | |
| 1378 /* Add runes representing a character in octal. */ | |
| 1379 | |
| 1380 #define ADD_NEXT_OCTAL_RUNE_CHAR do \ | |
| 1381 { \ | |
| 867 | 1382 if (add_failed || (add_failed = add_ichar_rune (data))) \ |
| 428 | 1383 { \ |
| 1384 struct prop_block pb; \ | |
| 1385 if (!prop) \ | |
| 1386 prop = Dynarr_new (prop_block); \ | |
| 1387 \ | |
| 1388 pb.type = PROP_CHAR; \ | |
| 1389 pb.data.p_char.ch = data->ch; \ | |
| 1390 pb.data.p_char.cursor_type = data->cursor_type; \ | |
| 1391 Dynarr_add (prop, pb); \ | |
| 1392 } \ | |
| 1393 } while (0) | |
| 1394 | |
| 1395 static prop_block_dynarr * | |
| 1396 add_octal_runes (pos_data *data) | |
| 1397 { | |
| 819 | 1398 prop_block_dynarr *add_failed, *prop = 0; |
| 867 | 1399 Ichar orig_char = data->ch; |
| 647 | 1400 int orig_cursor_type = data->cursor_type; |
| 428 | 1401 |
| 1402 /* Initialize */ | |
| 1403 add_failed = NULL; | |
| 1404 | |
| 1405 if (data->start_col) | |
| 1406 data->start_col--; | |
| 1407 | |
| 1408 if (!data->start_col) | |
| 1409 { | |
| 826 | 1410 if (data->byte_start_col_enabled) |
| 428 | 1411 { |
| 1412 add_failed = add_hscroll_rune (data); | |
| 1413 } | |
| 1414 else | |
| 1415 { | |
| 1416 struct glyph_block gb; | |
| 1417 struct window *w = XWINDOW (data->window); | |
| 1418 | |
| 1419 gb.extent = Qnil; | |
| 1420 gb.glyph = Voctal_escape_glyph; | |
| 1421 add_failed = | |
| 1422 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
| 1423 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX)); | |
| 1424 } | |
| 1425 } | |
| 1426 | |
| 1427 /* We only propagate information if the glyph was partially | |
| 1428 added. */ | |
| 1429 if (add_failed) | |
| 1430 return add_failed; | |
| 1431 | |
| 1432 data->cursor_type = IGNORE_CURSOR; | |
| 1433 | |
| 1434 if (data->ch >= 0x100) | |
| 1435 { | |
| 1436 /* If the character is an extended Mule character, it could have | |
| 3498 | 1437 up to 21 bits. For the moment, we treat it as a seven-digit |
| 428 | 1438 octal number. This is not that pretty, but whatever. */ |
| 1439 data->ch = (7 & (orig_char >> 18)) + '0'; | |
| 1440 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1441 | |
| 1442 data->ch = (7 & (orig_char >> 15)) + '0'; | |
| 1443 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1444 | |
| 1445 data->ch = (7 & (orig_char >> 12)) + '0'; | |
| 1446 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1447 | |
| 1448 data->ch = (7 & (orig_char >> 9)) + '0'; | |
| 1449 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1450 } | |
| 1451 | |
| 1452 data->ch = (7 & (orig_char >> 6)) + '0'; | |
| 1453 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1454 | |
| 1455 data->ch = (7 & (orig_char >> 3)) + '0'; | |
| 1456 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1457 | |
| 1458 data->ch = (7 & orig_char) + '0'; | |
| 1459 ADD_NEXT_OCTAL_RUNE_CHAR; | |
| 1460 | |
| 1461 data->cursor_type = orig_cursor_type; | |
| 819 | 1462 return NULL; |
| 428 | 1463 } |
| 1464 | |
| 1465 #undef ADD_NEXT_OCTAL_RUNE_CHAR | |
| 1466 | |
| 1467 /* Add runes representing a control character to a display block. */ | |
| 1468 | |
| 1469 static prop_block_dynarr * | |
| 1470 add_control_char_runes (pos_data *data, struct buffer *b) | |
| 1471 { | |
| 1472 if (!NILP (b->ctl_arrow)) | |
| 1473 { | |
| 1474 prop_block_dynarr *prop; | |
| 867 | 1475 Ichar orig_char = data->ch; |
| 647 | 1476 int old_cursor_type = data->cursor_type; |
| 428 | 1477 |
| 1478 /* Initialize */ | |
| 1479 prop = NULL; | |
| 1480 | |
| 1481 if (data->start_col) | |
| 1482 data->start_col--; | |
| 1483 | |
| 1484 if (!data->start_col) | |
| 1485 { | |
| 826 | 1486 if (data->byte_start_col_enabled) |
| 428 | 1487 { |
| 1488 prop_block_dynarr *retval; | |
| 1489 | |
| 1490 retval = add_hscroll_rune (data); | |
| 1491 if (retval) | |
| 1492 return retval; | |
| 1493 } | |
| 1494 else | |
| 1495 { | |
| 1496 struct glyph_block gb; | |
| 1497 struct window *w = XWINDOW (data->window); | |
| 1498 | |
| 1499 gb.extent = Qnil; | |
| 1500 gb.glyph = Vcontrol_arrow_glyph; | |
| 1501 | |
| 1502 /* We only propagate information if the glyph was partially | |
| 1503 added. */ | |
| 1504 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
| 1505 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX))) | |
| 1506 return ADD_FAILED; | |
| 1507 } | |
| 1508 } | |
| 1509 | |
| 1510 if (orig_char == 0177) | |
| 1511 data->ch = '?'; | |
| 1512 else | |
| 1513 data->ch = orig_char ^ 0100; | |
| 1514 data->cursor_type = IGNORE_CURSOR; | |
| 1515 | |
| 867 | 1516 if (add_ichar_rune (data)) |
| 428 | 1517 { |
| 1518 struct prop_block pb; | |
| 1519 if (!prop) | |
| 1520 prop = Dynarr_new (prop_block); | |
| 1521 | |
| 1522 pb.type = PROP_CHAR; | |
| 1523 pb.data.p_char.ch = data->ch; | |
| 1524 pb.data.p_char.cursor_type = data->cursor_type; | |
| 1525 Dynarr_add (prop, pb); | |
| 1526 } | |
| 1527 | |
| 1528 data->cursor_type = old_cursor_type; | |
| 1529 return prop; | |
| 1530 } | |
| 1531 else | |
| 1532 { | |
| 1533 return add_octal_runes (data); | |
| 1534 } | |
| 1535 } | |
| 1536 | |
| 1537 static prop_block_dynarr * | |
| 1538 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) | |
| 1539 { | |
| 1540 prop_block_dynarr *prop = NULL; | |
| 1541 | |
| 1542 if (STRINGP (entry)) | |
| 1543 { | |
| 867 | 1544 prop = add_ibyte_string_runes (data, |
| 428 | 1545 XSTRING_DATA (entry), |
| 1546 XSTRING_LENGTH (entry), | |
| 793 | 1547 0, 0); |
| 428 | 1548 } |
| 1549 else if (GLYPHP (entry)) | |
| 1550 { | |
| 1551 if (data->start_col) | |
| 1552 data->start_col--; | |
| 1553 | |
| 826 | 1554 if (!data->start_col && data->byte_start_col_enabled) |
| 428 | 1555 { |
| 1556 prop = add_hscroll_rune (data); | |
| 1557 } | |
| 1558 else | |
| 1559 { | |
| 1560 struct glyph_block gb; | |
| 1561 | |
| 1562 gb.glyph = entry; | |
| 1563 gb.extent = Qnil; | |
| 1564 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); | |
| 1565 } | |
| 1566 } | |
| 1567 else if (CHAR_OR_CHAR_INTP (entry)) | |
| 1568 { | |
| 1569 data->ch = XCHAR_OR_CHAR_INT (entry); | |
| 867 | 1570 prop = add_ichar_rune (data); |
| 428 | 1571 } |
| 1572 else if (CONSP (entry)) | |
| 1573 { | |
| 1574 if (EQ (XCAR (entry), Qformat) | |
| 1575 && CONSP (XCDR (entry)) | |
| 1576 && STRINGP (XCAR (XCDR (entry)))) | |
| 1577 { | |
| 1578 Lisp_Object format = XCAR (XCDR (entry)); | |
| 665 | 1579 Bytebpos len = XSTRING_LENGTH (format); |
| 867 | 1580 Ibyte *src = XSTRING_DATA (format), *end = src + len; |
| 2367 | 1581 Ibyte *result = alloca_ibytes (len); |
| 867 | 1582 Ibyte *dst = result; |
| 428 | 1583 |
| 1584 while (src < end) | |
| 1585 { | |
| 867 | 1586 Ichar c = itext_ichar (src); |
| 1587 INC_IBYTEPTR (src); | |
| 428 | 1588 if (c != '%' || src == end) |
| 867 | 1589 dst += set_itext_ichar (dst, c); |
| 428 | 1590 else |
| 1591 { | |
| 867 | 1592 c = itext_ichar (src); |
| 1593 INC_IBYTEPTR (src); | |
| 428 | 1594 switch (c) |
| 1595 { | |
| 1596 /*case 'x': | |
| 1597 dst += long_to_string_base ((char *)dst, data->ch, 16); | |
| 1598 break;*/ | |
| 1599 case '%': | |
| 867 | 1600 dst += set_itext_ichar (dst, '%'); |
| 428 | 1601 break; |
| 442 | 1602 /* #### unimplemented */ |
| 428 | 1603 } |
| 1604 } | |
| 1605 } | |
| 867 | 1606 prop = add_ibyte_string_runes (data, result, dst - result, 0, 0); |
| 428 | 1607 } |
| 1608 } | |
| 1609 | |
| 1610 /* Else blow it off because someone added a bad entry and we don't | |
| 1611 have any safe way of signaling an error. */ | |
| 1612 return prop; | |
| 1613 } | |
| 1614 | |
| 1615 /* Given a display table entry, call the appropriate functions to | |
| 1616 display each element of the entry. */ | |
| 1617 | |
| 1618 static prop_block_dynarr * | |
| 1619 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) | |
| 1620 { | |
| 1621 prop_block_dynarr *prop = NULL; | |
| 1622 if (VECTORP (entry)) | |
| 1623 { | |
| 440 | 1624 Lisp_Vector *de = XVECTOR (entry); |
| 428 | 1625 EMACS_INT len = vector_length (de); |
| 1626 int elt; | |
| 1627 | |
| 1628 for (elt = 0; elt < len; elt++) | |
| 1629 { | |
| 1630 if (NILP (vector_data (de)[elt])) | |
| 1631 continue; | |
| 1632 else | |
| 1633 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]); | |
| 1634 /* Else blow it off because someone added a bad entry and we | |
| 1635 don't have any safe way of signaling an error. Hey, this | |
| 1636 comment sounds familiar. */ | |
| 1637 | |
| 1638 /* #### Still need to add any remaining elements to the | |
| 4187 | 1639 propagation information. */ |
| 428 | 1640 if (prop) |
| 1641 return prop; | |
| 1642 } | |
| 1643 } | |
| 1644 else | |
| 1645 prop = add_disp_table_entry_runes_1 (data, entry); | |
| 1646 return prop; | |
| 1647 } | |
| 1648 | |
| 1649 /* Add runes which were propagated from the previous line. */ | |
| 1650 | |
| 1651 static prop_block_dynarr * | |
| 1652 add_propagation_runes (prop_block_dynarr **prop, pos_data *data) | |
| 1653 { | |
| 1654 /* #### Remember to handle start_col parameter of data when the rest of | |
| 1655 this is finished. */ | |
| 1656 /* #### Chuck -- I've redone this function a bit. It looked like the | |
| 1657 case of not all the propagation blocks being added was not handled | |
| 1658 well. */ | |
| 1659 /* #### Chuck -- I also think the double indirection of PROP is kind | |
| 1660 of bogus. A cleaner solution is just to check for | |
| 1661 Dynarr_length (prop) > 0. */ | |
| 1662 /* #### This function also doesn't even pay attention to ADD_FAILED! | |
| 1663 This is seriously fucked! Seven ####'s in 130 lines -- is that a | |
| 1664 record? */ | |
| 1665 int elt; | |
| 1666 prop_block_dynarr *add_failed; | |
| 826 | 1667 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
| 647 | 1668 int old_cursor_type = data->cursor_type; |
| 428 | 1669 |
| 1670 for (elt = 0; elt < Dynarr_length (*prop); elt++) | |
| 1671 { | |
| 1672 struct prop_block *pb = Dynarr_atp (*prop, elt); | |
| 1673 | |
| 1674 switch (pb->type) | |
| 1675 { | |
| 1676 case PROP_CHAR: | |
| 1677 data->ch = pb->data.p_char.ch; | |
| 826 | 1678 data->byte_cursor_charpos = pb->data.p_char.byte_cursor_charpos; |
| 428 | 1679 data->cursor_type = pb->data.p_char.cursor_type; |
| 867 | 1680 add_failed = add_ichar_rune (data); |
| 428 | 1681 |
| 1682 if (add_failed) | |
| 1683 goto oops_no_more_space; | |
| 1684 break; | |
| 1685 case PROP_STRING: | |
| 1686 if (pb->data.p_string.str) | |
|
5169
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
1687 { |
|
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
1688 xfree (pb->data.p_string.str); |
|
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
1689 pb->data.p_string.str = 0; |
|
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
1690 } |
| 428 | 1691 /* #### bogus bogus -- this doesn't do anything! |
| 867 | 1692 Should probably call add_ibyte_string_runes(), |
| 428 | 1693 once that function is fixed. */ |
| 1694 break; | |
| 1695 case PROP_MINIBUF_PROMPT: | |
| 1696 { | |
| 1697 face_index old_findex = data->findex; | |
| 826 | 1698 Bytebpos byte_old_charpos = data->byte_charpos; |
| 428 | 1699 |
| 1700 data->findex = DEFAULT_INDEX; | |
| 826 | 1701 data->byte_charpos = 0; |
| 428 | 1702 data->cursor_type = NO_CURSOR; |
| 1703 | |
| 1704 while (pb->data.p_string.len > 0) | |
| 1705 { | |
| 867 | 1706 data->ch = itext_ichar (pb->data.p_string.str); |
| 1707 add_failed = add_ichar_rune (data); | |
| 428 | 1708 |
| 1709 if (add_failed) | |
| 1710 { | |
| 1711 data->findex = old_findex; | |
| 826 | 1712 data->byte_charpos = byte_old_charpos; |
| 428 | 1713 goto oops_no_more_space; |
| 1714 } | |
| 1715 else | |
| 1716 { | |
| 1717 /* Complicated equivalent of ptr++, len-- */ | |
| 867 | 1718 Ibyte *oldpos = pb->data.p_string.str; |
| 1719 INC_IBYTEPTR (pb->data.p_string.str); | |
| 428 | 1720 pb->data.p_string.len -= pb->data.p_string.str - oldpos; |
| 1721 } | |
| 1722 } | |
| 1723 | |
| 1724 data->findex = old_findex; | |
| 1725 /* ##### FIXME FIXME FIXME -- Upon successful return from | |
| 826 | 1726 this function, data->byte_charpos is automatically incremented. |
| 428 | 1727 However, we don't want that to happen if we were adding |
| 1728 the minibuffer prompt. */ | |
| 1729 { | |
| 1730 struct buffer *buf = | |
| 1731 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))); | |
| 1732 /* #### Chuck fix this shit or I'm gonna scream! */ | |
| 826 | 1733 if (byte_old_charpos > BYTE_BUF_BEGV (buf)) |
| 4187 | 1734 data->byte_charpos = prev_bytebpos (buf, byte_old_charpos); |
| 1735 else | |
| 428 | 1736 /* #### is this correct? Does anyone know? |
| 1737 Does anyone care? Is this a cheesy hack or what? */ | |
| 4187 | 1738 data->byte_charpos = BYTE_BUF_BEGV (buf) - 1; |
| 428 | 1739 } |
| 1740 } | |
| 1741 break; | |
| 1742 case PROP_BLANK: | |
| 1743 { | |
| 1744 /* #### I think it's unnecessary and misleading to preserve | |
| 1745 the blank_width, as it implies that the value carries | |
| 1746 over from one rune to the next, which is wrong. */ | |
| 1747 int old_width = data->blank_width; | |
| 1748 face_index old_findex = data->findex; | |
| 1749 | |
| 1750 data->findex = pb->data.p_blank.findex; | |
| 1751 data->blank_width = pb->data.p_blank.width; | |
| 826 | 1752 data->byte_cursor_charpos = 0; |
| 428 | 1753 data->cursor_type = IGNORE_CURSOR; |
| 1754 | |
| 1755 if (data->pixpos + data->blank_width > data->max_pixpos) | |
| 1756 data->blank_width = data->max_pixpos - data->pixpos; | |
| 1757 | |
| 1758 /* We pass a bogus value of char_tab_width. It shouldn't | |
| 4187 | 1759 matter because unless something is really screwed up |
| 1760 this call won't cause that arg to be used. */ | |
| 428 | 1761 add_failed = add_blank_rune (data, XWINDOW (data->window), 0); |
| 1762 | |
| 1763 /* This can happen in the case where we have a tab which | |
| 4187 | 1764 is wider than the window. */ |
| 428 | 1765 if (data->blank_width != pb->data.p_blank.width) |
| 1766 { | |
| 1767 pb->data.p_blank.width -= data->blank_width; | |
| 1768 add_failed = ADD_FAILED; | |
| 1769 } | |
| 1770 | |
| 1771 data->findex = old_findex; | |
| 1772 data->blank_width = old_width; | |
| 1773 | |
| 1774 if (add_failed) | |
| 1775 goto oops_no_more_space; | |
| 1776 } | |
| 1777 break; | |
| 1778 default: | |
| 2500 | 1779 ABORT (); |
| 428 | 1780 } |
| 1781 } | |
| 1782 | |
| 1783 oops_no_more_space: | |
| 1784 | |
| 826 | 1785 data->byte_cursor_charpos = byte_old_cursor_charpos; |
| 428 | 1786 data->cursor_type = old_cursor_type; |
| 1787 if (elt < Dynarr_length (*prop)) | |
| 1788 { | |
| 1789 Dynarr_delete_many (*prop, 0, elt); | |
| 1790 return *prop; | |
| 1791 } | |
| 1792 else | |
| 1793 { | |
| 1794 Dynarr_free (*prop); | |
| 1795 return NULL; | |
| 1796 } | |
| 1797 } | |
| 1798 | |
| 3025 | 1799 /* Add `text' layout glyphs at position POS_TYPE that are contained to |
| 428 | 1800 the display block, but add all other types to the appropriate list |
| 1801 of the display line. They will be added later by different | |
| 1802 routines. */ | |
| 1803 | |
| 1804 static prop_block_dynarr * | |
| 1805 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, | |
| 1806 int allow_cursor, struct glyph_cachel *cachel) | |
| 1807 { | |
| 1808 struct window *w = XWINDOW (data->window); | |
| 1809 | |
| 440 | 1810 /* If window faces changed, and glyph instance is text, then |
| 1811 glyph sizes might have changed too */ | |
| 1812 invalidate_glyph_geometry_maybe (gb->glyph, w); | |
| 1813 | |
| 442 | 1814 /* This makes sure the glyph is in the cachels. |
| 1815 | |
| 1816 #### We do this to make sure the glyph is in the glyph cachels, | |
| 1817 so that the dirty flag can be reset after redisplay has | |
| 1818 finished. We should do this some other way, maybe by iterating | |
| 1819 over the window cache of subwindows. */ | |
| 1820 get_glyph_cachel_index (w, gb->glyph); | |
| 1821 | |
| 428 | 1822 /* A nil extent indicates a special glyph (ex. truncator). */ |
| 1823 if (NILP (gb->extent) | |
| 1824 || (pos_type == BEGIN_GLYPHS && | |
| 1825 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) | |
| 1826 || (pos_type == END_GLYPHS && | |
| 442 | 1827 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) |
| 1828 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) | |
| 428 | 1829 { |
| 1830 struct rune rb; | |
| 1831 int width; | |
| 1832 int xoffset = 0; | |
| 1833 int ascent, descent; | |
| 1834 Lisp_Object baseline; | |
| 1835 Lisp_Object face; | |
| 442 | 1836 Lisp_Object instance; |
| 1837 face_index findex; | |
| 819 | 1838 prop_block_dynarr *retval = 0; |
| 428 | 1839 |
| 1840 if (cachel) | |
| 1841 width = cachel->width; | |
| 1842 else | |
| 438 | 1843 width = glyph_width (gb->glyph, data->window); |
| 428 | 1844 |
| 1845 if (!width) | |
| 1846 return NULL; | |
| 1847 | |
| 1848 if (data->start_col || data->start_col_xoffset) | |
| 1849 { | |
| 1850 int glyph_char_width = width / space_width (w); | |
| 1851 | |
| 1852 /* If we still have not fully scrolled horizontally after | |
| 4187 | 1853 taking into account the width of the glyph, subtract its |
| 1854 width and return. */ | |
| 428 | 1855 if (glyph_char_width < data->start_col) |
| 1856 { | |
| 1857 data->start_col -= glyph_char_width; | |
| 1858 return NULL; | |
| 1859 } | |
| 1860 else if (glyph_char_width == data->start_col) | |
| 1861 width = 0; | |
| 1862 else | |
| 1863 { | |
| 1864 xoffset = space_width (w) * data->start_col; | |
| 1865 width -= xoffset; | |
| 1866 | |
| 1867 /* #### Can this happen? */ | |
| 1868 if (width < 0) | |
| 1869 width = 0; | |
| 1870 } | |
| 1871 | |
| 1872 data->start_col = 0; | |
| 1873 retval = add_hscroll_rune (data); | |
| 1874 | |
| 1875 /* Could be caused by the handling of the hscroll rune. */ | |
| 1876 if (retval != NULL || !width) | |
| 1877 return retval; | |
| 1878 } | |
| 1879 else | |
| 1880 xoffset = 0; | |
| 1881 | |
| 1882 if (data->pixpos + width > data->max_pixpos) | |
| 1883 { | |
| 1884 /* If this is the first object we are attempting to add to | |
| 819 | 1885 the line then we ignore the horizontal_clip threshold. |
| 1886 Otherwise we will loop until the bottom of the window | |
| 1887 continually failing to add this glyph because it is wider | |
| 1888 than the window. We could alternatively just completely | |
| 1889 ignore the glyph and proceed from there but I think that | |
| 1890 this is a better solution. | |
| 4187 | 1891 |
| 819 | 1892 This does, however, create a different problem in that we |
| 1893 can end up adding the object to every single line, never | |
| 1894 getting any further - for instance an extent with a long | |
| 1895 start-glyph that covers multitple following | |
| 1896 characters. */ | |
| 428 | 1897 if (Dynarr_length (data->db->runes) |
| 1898 && data->max_pixpos - data->pixpos < horizontal_clip) | |
| 1899 return ADD_FAILED; | |
| 819 | 1900 else { |
| 1901 struct prop_block pb; | |
| 1902 | |
| 1903 /* We need to account for the width of the end-of-line | |
| 1904 glyph if there is nothing more in the line to display, | |
| 1905 since we will not display it in this instance. It seems | |
| 1906 kind of gross doing it here, but otherwise we have to | |
| 1907 search the runes in create_text_block(). */ | |
| 1908 if (data->ch == '\n') | |
| 1909 data->max_pixpos += data->end_glyph_width; | |
| 428 | 1910 width = data->max_pixpos - data->pixpos; |
| 819 | 1911 /* Add the glyph we are displaying, but clipping, to the |
| 1912 propagation data so that we don't try and do it | |
| 4187 | 1913 again. */ |
| 819 | 1914 retval = Dynarr_new (prop_block); |
| 1915 pb.type = PROP_GLYPH; | |
| 1916 pb.data.p_glyph.glyph = gb->glyph; | |
| 1917 pb.data.p_glyph.width = width; | |
| 1918 Dynarr_add (retval, pb); | |
| 1919 } | |
| 428 | 1920 } |
| 1921 | |
| 1922 if (cachel) | |
| 1923 { | |
| 1924 ascent = cachel->ascent; | |
| 1925 descent = cachel->descent; | |
| 1926 } | |
| 1927 else | |
| 1928 { | |
| 438 | 1929 ascent = glyph_ascent (gb->glyph, data->window); |
| 1930 descent = glyph_descent (gb->glyph, data->window); | |
| 428 | 1931 } |
| 1932 | |
| 1933 baseline = glyph_baseline (gb->glyph, data->window); | |
| 1934 | |
| 819 | 1935 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ |
| 1936 | |
| 428 | 1937 if (glyph_contrib_p (gb->glyph, data->window)) |
| 1938 { | |
| 1939 /* A pixmap that has not had a baseline explicitly set. Its | |
| 1940 contribution will be determined later. */ | |
| 1941 if (NILP (baseline)) | |
| 1942 { | |
| 1943 int height = ascent + descent; | |
| 819 | 1944 data->need_baseline_computation = 1; |
| 428 | 1945 data->max_pixmap_height = max (data->max_pixmap_height, height); |
| 1946 } | |
| 1947 | |
| 1948 /* A string so determine contribution normally. */ | |
| 1949 else if (EQ (baseline, Qt)) | |
| 1950 { | |
| 1951 data->new_ascent = max (data->new_ascent, ascent); | |
| 1952 data->new_descent = max (data->new_descent, descent); | |
| 1953 } | |
| 1954 | |
| 1955 /* A pixmap with an explicitly set baseline. We determine the | |
| 1956 contribution here. */ | |
| 1957 else if (INTP (baseline)) | |
| 1958 { | |
| 1959 int height = ascent + descent; | |
| 1960 int pix_ascent, pix_descent; | |
| 1961 | |
| 1962 pix_ascent = height * XINT (baseline) / 100; | |
| 1963 pix_descent = height - pix_ascent; | |
| 1964 | |
| 1965 data->new_ascent = max (data->new_ascent, pix_ascent); | |
| 1966 data->new_descent = max (data->new_descent, pix_descent); | |
| 819 | 1967 data->max_pixmap_height = max (data->max_pixmap_height, height); |
| 4187 | 1968 |
| 819 | 1969 rb.object.dglyph.descent = pix_descent; |
| 428 | 1970 } |
| 1971 | |
| 1972 /* Otherwise something is screwed up. */ | |
| 1973 else | |
| 2500 | 1974 ABORT (); |
| 428 | 1975 } |
| 1976 | |
| 1977 face = glyph_face (gb->glyph, data->window); | |
| 1978 if (NILP (face)) | |
| 442 | 1979 findex = data->findex; |
| 428 | 1980 else |
| 442 | 1981 findex = get_builtin_face_cache_index (w, face); |
| 1982 | |
| 1983 instance = glyph_image_instance (gb->glyph, data->window, | |
| 793 | 1984 ERROR_ME_DEBUG_WARN, 1); |
| 442 | 1985 if (TEXT_IMAGE_INSTANCEP (instance)) |
| 1986 { | |
| 1987 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); | |
| 1988 face_index orig_findex = data->findex; | |
| 826 | 1989 Bytebpos orig_charpos = data->byte_charpos; |
| 1990 Bytebpos orig_start_col_enabled = data->byte_start_col_enabled; | |
| 442 | 1991 |
| 1992 data->findex = findex; | |
| 826 | 1993 data->byte_start_col_enabled = 0; |
| 442 | 1994 if (!allow_cursor) |
| 826 | 1995 data->byte_charpos = 0; |
| 867 | 1996 add_ibyte_string_runes (data, XSTRING_DATA (string), |
| 793 | 1997 XSTRING_LENGTH (string), 0, 1); |
| 442 | 1998 data->findex = orig_findex; |
| 826 | 1999 data->byte_charpos = orig_charpos; |
| 2000 data->byte_start_col_enabled = orig_start_col_enabled; | |
| 819 | 2001 return retval; |
| 442 | 2002 } |
| 2003 | |
| 2004 rb.findex = findex; | |
| 428 | 2005 rb.xpos = data->pixpos; |
| 2006 rb.width = width; | |
| 826 | 2007 rb.charpos = 0; /* glyphs are never "at" anywhere */ |
| 2008 if (data->byte_endpos) | |
| 428 | 2009 /* #### is this necessary at all? */ |
| 665 | 2010 rb.endpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
| 826 | 2011 data->byte_endpos); |
| 428 | 2012 else |
| 4187 | 2013 rb.endpos = 0; |
| 428 | 2014 rb.type = RUNE_DGLYPH; |
| 2015 rb.object.dglyph.glyph = gb->glyph; | |
| 2016 rb.object.dglyph.extent = gb->extent; | |
| 2017 rb.object.dglyph.xoffset = xoffset; | |
| 819 | 2018 rb.object.dglyph.ascent = ascent; |
| 2019 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has | |
| 2020 a normal (textual) baseline. */ | |
| 428 | 2021 |
| 2022 if (allow_cursor) | |
| 2023 { | |
| 826 | 2024 rb.charpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
| 2025 data->byte_charpos); | |
| 428 | 2026 |
| 2027 if (data->cursor_type == CURSOR_ON) | |
| 2028 { | |
| 826 | 2029 if (data->byte_charpos == data->byte_cursor_charpos) |
| 428 | 2030 { |
| 2031 rb.cursor_type = CURSOR_ON; | |
| 2032 data->cursor_x = Dynarr_length (data->db->runes); | |
| 2033 } | |
| 2034 else | |
| 2035 rb.cursor_type = CURSOR_OFF; | |
| 2036 } | |
| 2037 else if (data->cursor_type == NEXT_CURSOR) | |
| 2038 { | |
| 2039 rb.cursor_type = CURSOR_ON; | |
| 2040 data->cursor_x = Dynarr_length (data->db->runes); | |
| 2041 data->cursor_type = NO_CURSOR; | |
| 2042 } | |
| 2043 else if (data->cursor_type == IGNORE_CURSOR) | |
| 2044 rb.cursor_type = IGNORE_CURSOR; | |
| 2045 else if (data->cursor_type == NO_CURSOR) | |
| 2046 rb.cursor_type = NO_CURSOR; | |
| 2047 else | |
| 2048 rb.cursor_type = CURSOR_OFF; | |
| 2049 } | |
| 2050 else | |
| 2051 rb.cursor_type = CURSOR_OFF; | |
| 2052 | |
| 2053 Dynarr_add (data->db->runes, rb); | |
| 2054 data->pixpos += width; | |
| 2055 | |
| 819 | 2056 return retval; |
| 428 | 2057 } |
| 2058 else | |
| 2059 { | |
| 2060 if (!NILP (glyph_face (gb->glyph, data->window))) | |
| 2061 gb->findex = | |
| 2062 get_builtin_face_cache_index (w, glyph_face (gb->glyph, | |
| 2063 data->window)); | |
| 2064 else | |
| 2065 gb->findex = data->findex; | |
| 2066 | |
| 2067 if (pos_type == BEGIN_GLYPHS) | |
| 2068 { | |
| 2069 if (!data->dl->left_glyphs) | |
| 2070 data->dl->left_glyphs = Dynarr_new (glyph_block); | |
| 2071 Dynarr_add (data->dl->left_glyphs, *gb); | |
| 2072 return NULL; | |
| 2073 } | |
| 2074 else if (pos_type == END_GLYPHS) | |
| 2075 { | |
| 2076 if (!data->dl->right_glyphs) | |
| 2077 data->dl->right_glyphs = Dynarr_new (glyph_block); | |
| 2078 Dynarr_add (data->dl->right_glyphs, *gb); | |
| 2079 return NULL; | |
| 2080 } | |
| 2081 else | |
| 2500 | 2082 ABORT (); /* there are no unknown types */ |
| 428 | 2083 } |
| 2084 | |
| 819 | 2085 return NULL; |
| 428 | 2086 } |
| 2087 | |
| 2088 /* Add all glyphs at position POS_TYPE that are contained in the given | |
| 2089 data. */ | |
| 2090 | |
| 2091 static prop_block_dynarr * | |
| 2092 add_glyph_runes (pos_data *data, int pos_type) | |
| 2093 { | |
| 2094 /* #### This still needs to handle the start_col parameter. Duh, Chuck, | |
| 2095 why didn't you just modify add_glyph_rune in the first place? */ | |
| 2096 int elt; | |
| 2097 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS | |
| 2098 ? data->ef->begin_glyphs | |
| 2099 : data->ef->end_glyphs); | |
| 2100 prop_block_dynarr *prop; | |
| 2101 | |
| 2102 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++) | |
| 2103 { | |
| 2104 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0, | |
| 2105 0); | |
| 2106 | |
| 2107 if (prop) | |
| 2108 { | |
| 2109 /* #### Add some propagation information. */ | |
| 2110 return prop; | |
| 2111 } | |
| 2112 } | |
| 2113 | |
| 2114 Dynarr_reset (glyph_arr); | |
| 2115 | |
| 2116 return NULL; | |
| 2117 } | |
| 2118 | |
| 2119 /* Given a position for a buffer in a window, ensure that the given | |
| 2120 display line DL accurately represents the text on a line starting | |
| 2121 at the given position. | |
| 2122 | |
| 826 | 2123 NOTE NOTE NOTE NOTE: This function works with and returns Bytebpos's. |
| 428 | 2124 You must do appropriate conversion. */ |
| 2125 | |
| 665 | 2126 static Bytebpos |
| 428 | 2127 create_text_block (struct window *w, struct display_line *dl, |
| 826 | 2128 Bytebpos byte_start_pos, prop_block_dynarr **prop, |
| 428 | 2129 int type) |
| 2130 { | |
| 2131 struct frame *f = XFRAME (w->frame); | |
| 2132 struct buffer *b = XBUFFER (w->buffer); | |
| 2133 struct device *d = XDEVICE (f->device); | |
| 2134 | |
| 2135 pos_data data; | |
| 2136 | |
| 2137 /* Don't display anything in the minibuffer if this window is not on | |
| 2138 a selected frame. We consider all other windows to be active | |
| 2139 minibuffers as it simplifies the coding. */ | |
| 2140 int active_minibuffer = (!MINI_WINDOW_P (w) || | |
| 2141 (f == device_selected_frame (d)) || | |
| 2142 is_surrogate_for_selected_frame (f)); | |
| 2143 | |
| 2144 int truncate_win = window_truncation_on (w); | |
| 2145 | |
| 2146 /* If the buffer's value of selective_display is an integer then | |
| 2147 only lines that start with less than selective_display columns of | |
| 2148 space will be displayed. If selective_display is t then all text | |
| 2149 after a ^M is invisible. */ | |
| 2150 int selective = (INTP (b->selective_display) | |
| 2151 ? XINT (b->selective_display) | |
| 434 | 2152 : (!NILP (b->selective_display) ? -1 : 0)); |
| 428 | 2153 |
| 2154 /* The variable ctl-arrow allows the user to specify what characters | |
| 2155 can actually be displayed and which octal should be used for. | |
| 2156 #### This variable should probably have some rethought done to | |
| 2157 it. | |
| 2158 | |
| 2367 | 2159 See also |
| 2160 | |
| 2161 (Info-goto-node "(internals)Future Work -- Display Tables") | |
| 2162 | |
| 2163 */ | |
| 867 | 2164 Ichar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
| 428 | 2165 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
| 2166 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
| 2167 ? 255 : 160)); | |
| 2168 | |
| 2169 Lisp_Object face_dt, window_dt; | |
| 2170 | |
| 2171 /* The text display block for this display line. */ | |
| 2172 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 2173 | |
| 2174 /* The first time through the main loop we need to force the glyph | |
| 2175 data to be updated. */ | |
| 2176 int initial = 1; | |
| 2177 | |
| 2178 /* Apparently the new extent_fragment_update returns an end position | |
| 2179 equal to the position passed in if there are no more runs to be | |
| 2180 displayed. */ | |
| 2181 int no_more_frags = 0; | |
| 2182 | |
| 2183 Lisp_Object synch_minibuffers_value = | |
| 2184 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer); | |
| 2185 | |
| 2186 dl->used_prop_data = 0; | |
| 2187 dl->num_chars = 0; | |
| 442 | 2188 dl->line_continuation = 0; |
| 428 | 2189 |
| 2190 xzero (data); | |
| 2191 data.ef = extent_fragment_new (w->buffer, f); | |
| 2192 | |
| 2193 /* These values are used by all of the rune addition routines. We add | |
| 2194 them to this structure for ease of passing. */ | |
| 2195 data.d = d; | |
| 793 | 2196 data.window = wrap_window (w); |
| 428 | 2197 data.string = Qnil; |
| 2198 data.db = db; | |
| 2199 data.dl = dl; | |
| 2200 | |
| 826 | 2201 data.byte_charpos = byte_start_pos; |
| 428 | 2202 data.pixpos = dl->bounds.left_in; |
| 2203 data.last_charset = Qunbound; | |
| 2204 data.last_findex = DEFAULT_INDEX; | |
| 2205 data.result_str = Qnil; | |
| 2206 | |
| 2207 /* Set the right boundary adjusting it to take into account any end | |
| 2208 glyph. Save the width of the end glyph for later use. */ | |
| 2209 data.max_pixpos = dl->bounds.right_in; | |
| 2210 if (truncate_win) | |
| 819 | 2211 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); |
| 428 | 2212 else |
| 819 | 2213 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); |
| 2214 data.max_pixpos -= data.end_glyph_width; | |
| 428 | 2215 |
| 2216 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f)) | |
| 2217 { | |
| 826 | 2218 data.byte_cursor_charpos = BYTE_BUF_ZV (b); |
| 428 | 2219 data.cursor_type = CURSOR_ON; |
| 2220 } | |
| 2221 else if (MINI_WINDOW_P (w) && !active_minibuffer) | |
| 2222 data.cursor_type = NO_CURSOR; | |
| 2223 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) && | |
| 5198 | 2224 EQ (DEVICE_CONSOLE (d), Vselected_console) && |
| 2225 d == XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d))))&& | |
| 2226 f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
| 428 | 2227 { |
| 826 | 2228 data.byte_cursor_charpos = BYTE_BUF_PT (b); |
| 428 | 2229 data.cursor_type = CURSOR_ON; |
| 2230 } | |
| 2231 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | |
| 2232 { | |
| 826 | 2233 data.byte_cursor_charpos = byte_marker_position (w->pointm[type]); |
| 428 | 2234 data.cursor_type = CURSOR_ON; |
| 2235 } | |
| 2236 else | |
| 2237 data.cursor_type = NO_CURSOR; | |
| 2238 data.cursor_x = -1; | |
| 2239 | |
| 2240 data.start_col = w->hscroll; | |
| 2241 data.start_col_xoffset = w->left_xoffset; | |
| 826 | 2242 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
| 428 | 2243 data.hscroll_glyph_width_adjust = 0; |
| 2244 | |
| 2245 /* We regenerate the line from the very beginning. */ | |
| 2246 Dynarr_reset (db->runes); | |
| 2247 | |
| 2248 /* Why is this less than or equal and not just less than? If the | |
| 2249 starting position is already equal to the maximum we can't add | |
| 2250 anything else, right? Wrong. We might still have a newline to | |
| 2251 add. A newline can use the room allocated for an end glyph since | |
| 2252 if we add it we know we aren't going to be adding any end | |
| 2253 glyph. */ | |
| 2254 | |
| 2255 /* #### Chuck -- I think this condition should be while (1). | |
| 2256 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
| 2257 and the begin-glyph ends exactly at the end of the window, the | |
| 2258 end-glyph and text might not be displayed. while (1) ensures | |
| 2259 that the loop terminates only when either (a) there is | |
| 2260 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
| 2261 | |
| 2262 #### Also I think you need to ensure that the operation | |
| 2263 "add begin glyphs; add end glyphs; add text" is atomic and | |
| 2264 can't get interrupted in the middle. If you run off the end | |
| 2265 of the line during that operation, then you keep accumulating | |
| 2266 propagation data until you're done. Otherwise, if the (e.g.) | |
| 2267 there's a begin glyph at a particular position and attempting | |
| 2268 to display that glyph results in window-end being hit and | |
| 2269 propagation data being generated, then the character at that | |
| 2270 position won't be displayed. | |
| 2271 | |
| 2272 #### See also the comment after the end of this loop, below. | |
| 2273 */ | |
| 2274 while (data.pixpos <= data.max_pixpos | |
| 2275 && (active_minibuffer || !NILP (synch_minibuffers_value))) | |
| 2276 { | |
| 2277 /* #### This check probably should not be necessary. */ | |
| 826 | 2278 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
| 428 | 2279 { |
| 2280 /* #### urk! More of this lossage! */ | |
| 826 | 2281 data.byte_charpos--; |
| 428 | 2282 goto done; |
| 2283 } | |
| 2284 | |
| 2285 /* If selective display was an integer and we aren't working on | |
| 4187 | 2286 a continuation line then find the next line we are actually |
| 2287 supposed to display. */ | |
| 428 | 2288 if (selective > 0 |
| 826 | 2289 && (data.byte_charpos == BYTE_BUF_BEGV (b) |
| 2290 || BUF_FETCH_CHAR (b, prev_bytebpos (b, data.byte_charpos)) == '\n')) | |
| 2291 { | |
| 2292 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
| 428 | 2293 { |
| 826 | 2294 data.byte_charpos = |
| 2295 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
| 2296 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
| 428 | 2297 { |
| 826 | 2298 data.byte_charpos = BYTE_BUF_ZV (b); |
| 428 | 2299 goto done; |
| 2300 } | |
| 2301 } | |
| 2302 } | |
| 2303 | |
| 2304 /* Check for face changes. */ | |
| 826 | 2305 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
| 428 | 2306 { |
| 819 | 2307 Lisp_Object last_glyph = Qnil; |
| 2308 | |
| 2309 /* Deal with glyphs that we have already displayed. The | |
| 2310 theory is that if we end up with a PROP_GLYPH in the | |
| 2311 propagation data then we are clipping the glyph and there | |
| 2312 can be no propagation data before that point. The theory | |
| 2313 works because we always recalculate the extent-fragments | |
| 2314 for propagated data, we never actually propagate the | |
| 2315 fragments that still need to be displayed. */ | |
| 4967 | 2316 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
| 2317 { | |
| 2318 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
| 819 | 2319 Dynarr_free (*prop); |
| 2320 *prop = 0; | |
| 2321 } | |
| 428 | 2322 /* Now compute the face and begin/end-glyph information. */ |
| 2323 data.findex = | |
| 665 | 2324 /* Remember that the extent-fragment routines deal in Bytebpos's. */ |
| 826 | 2325 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
| 428 | 2326 |
| 2327 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
| 2328 | |
| 826 | 2329 if (data.byte_charpos == data.ef->end) |
| 428 | 2330 no_more_frags = 1; |
| 2331 } | |
| 2332 initial = 0; | |
| 2333 | |
| 2334 /* Determine what is next to be displayed. We first handle any | |
| 4187 | 2335 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
| 2336 display then we determine what to do based on the character at the | |
| 2337 current buffer position. */ | |
| 428 | 2338 |
| 2339 /* If the current position is covered by an invisible extent, do | |
| 4187 | 2340 nothing (except maybe add some ellipses). |
| 428 | 2341 |
| 2342 #### The behavior of begin and end-glyphs at the edge of an | |
| 2343 invisible extent should be investigated further. This is | |
| 2344 fairly low priority though. */ | |
| 2345 if (data.ef->invisible) | |
| 2346 { | |
| 2347 /* #### Chuck, perhaps you could look at this code? I don't | |
| 2348 really know what I'm doing. */ | |
| 2349 if (*prop) | |
| 2350 { | |
| 2351 Dynarr_free (*prop); | |
| 2352 *prop = 0; | |
| 2353 } | |
| 2354 | |
| 2355 /* The extent fragment code only sets this when we should | |
| 2356 really display the ellipses. It makes sure the ellipses | |
| 2357 don't get displayed more than once in a row. */ | |
| 2358 if (data.ef->invisible_ellipses) | |
| 2359 { | |
| 2360 struct glyph_block gb; | |
| 2361 | |
| 2362 data.ef->invisible_ellipses_already_displayed = 1; | |
| 2363 data.ef->invisible_ellipses = 0; | |
| 2364 gb.extent = Qnil; | |
| 2365 gb.glyph = Vinvisible_text_glyph; | |
| 2366 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
| 2367 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
| 2368 /* Perhaps they shouldn't propagate if the very next thing | |
| 2369 is to display a newline (for compatibility with | |
| 2370 selective-display-ellipses)? Maybe that's too | |
| 2371 abstruse. */ | |
| 2372 if (*prop) | |
| 2373 goto done; | |
| 2374 } | |
| 2375 | |
| 2376 /* If point is in an invisible region we place it on the | |
| 4187 | 2377 next visible character. */ |
| 428 | 2378 if (data.cursor_type == CURSOR_ON |
| 826 | 2379 && data.byte_charpos == data.byte_cursor_charpos) |
| 428 | 2380 { |
| 2381 data.cursor_type = NEXT_CURSOR; | |
| 2382 } | |
| 2383 | |
| 2384 /* #### What if we we're dealing with a display table? */ | |
| 2385 if (data.start_col) | |
| 2386 data.start_col--; | |
| 2387 | |
| 826 | 2388 if (data.byte_charpos == BYTE_BUF_ZV (b)) |
| 428 | 2389 goto done; |
| 2390 else | |
| 826 | 2391 INC_BYTEBPOS (b, data.byte_charpos); |
| 428 | 2392 } |
| 2393 | |
| 2394 /* If there is propagation data, then it represents the current | |
| 819 | 2395 buffer position being displayed. Add them and advance the |
| 2396 position counter. This might also add the minibuffer | |
| 2397 prompt. */ | |
| 428 | 2398 else if (*prop) |
| 2399 { | |
| 2400 dl->used_prop_data = 1; | |
| 2401 *prop = add_propagation_runes (prop, &data); | |
| 2402 | |
| 2403 if (*prop) | |
| 2404 goto done; /* gee, a really narrow window */ | |
| 826 | 2405 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
| 428 | 2406 goto done; |
| 826 | 2407 else if (data.byte_charpos < BYTE_BUF_BEGV (b)) |
| 428 | 2408 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
| 826 | 2409 data.byte_charpos = BYTE_BUF_BEGV (b); |
| 428 | 2410 else |
| 826 | 2411 INC_BYTEBPOS (b, data.byte_charpos); |
| 428 | 2412 } |
| 2413 | |
| 2414 /* If there are end glyphs, add them to the line. These are | |
| 2415 the end glyphs for the previous run of text. We add them | |
| 2416 here rather than doing them at the end of handling the | |
| 2417 previous run so that glyphs at the beginning and end of | |
| 2418 a line are handled correctly. */ | |
| 819 | 2419 else if (Dynarr_length (data.ef->end_glyphs) > 0 |
| 2420 || Dynarr_length (data.ef->begin_glyphs) > 0) | |
| 2421 { | |
| 2422 glyph_block_dynarr* tmpglyphs = 0; | |
| 2423 /* #### I think this is safe, but could be wrong. */ | |
| 826 | 2424 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
| 819 | 2425 |
| 4187 | 2426 if (Dynarr_length (data.ef->end_glyphs) > 0) |
| 819 | 2427 { |
| 2428 *prop = add_glyph_runes (&data, END_GLYPHS); | |
| 2429 tmpglyphs = data.ef->end_glyphs; | |
| 2430 } | |
| 2431 | |
| 2432 /* If there are begin glyphs, add them to the line. */ | |
| 4187 | 2433 if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0) |
| 819 | 2434 { |
| 2435 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); | |
| 2436 tmpglyphs = data.ef->begin_glyphs; | |
| 2437 } | |
| 2438 | |
| 4187 | 2439 if (*prop) |
| 819 | 2440 { |
| 2441 /* If we just clipped a glyph and we are at the end of a | |
| 2442 line and there are more glyphs to display then do | |
| 2443 appropriate processing to not get a continuation | |
| 2444 glyph. */ | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2445 if (*prop != ADD_FAILED |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2446 && Dynarr_begin (*prop)->type == PROP_GLYPH |
| 819 | 2447 && data.ch == '\n') |
| 4187 | 2448 { |
| 819 | 2449 /* If there are no more glyphs then do the normal |
| 4187 | 2450 processing. |
| 819 | 2451 |
| 2452 #### This doesn't actually work if the same glyph is | |
| 2453 present more than once in the block. To solve | |
| 2454 this we would have to carry the index around | |
| 2455 which might be problematic since the fragment is | |
| 2456 recalculated for each line. */ | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2457 if (EQ (Dynarr_lastp (tmpglyphs)->glyph, |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2458 Dynarr_begin (*prop)->data.p_glyph.glyph)) |
| 819 | 2459 { |
| 2460 Dynarr_free (*prop); | |
| 2461 *prop = 0; | |
| 2462 } | |
| 2463 else { | |
| 2464 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 867 | 2465 add_ichar_rune (&data); /* discard prop data. */ |
| 819 | 2466 goto done; |
| 2467 } | |
| 2468 } | |
| 2469 else | |
| 2470 goto done; | |
| 2471 } | |
| 428 | 2472 } |
| 2473 | |
| 2474 /* If at end-of-buffer, we've already processed begin and | |
| 2475 end-glyphs at this point and there's no text to process, | |
| 2476 so we're done. */ | |
| 826 | 2477 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
| 428 | 2478 goto done; |
| 2479 | |
| 2480 else | |
| 2481 { | |
| 2482 Lisp_Object entry = Qnil; | |
| 2483 /* Get the character at the current buffer position. */ | |
| 826 | 2484 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
| 428 | 2485 if (!NILP (face_dt) || !NILP (window_dt)) |
| 2486 entry = display_table_entry (data.ch, face_dt, window_dt); | |
| 2487 | |
| 2488 /* If there is a display table entry for it, hand it off to | |
| 4187 | 2489 add_disp_table_entry_runes and let it worry about it. */ |
| 428 | 2490 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
| 2491 { | |
| 2492 *prop = add_disp_table_entry_runes (&data, entry); | |
| 2493 | |
| 2494 if (*prop) | |
| 2495 goto done; | |
| 2496 } | |
| 2497 | |
| 2498 /* Check if we have hit a newline character. If so, add a marker | |
| 4187 | 2499 to the line and end this loop. */ |
| 428 | 2500 else if (data.ch == '\n') |
| 2501 { | |
| 2502 /* We aren't going to be adding an end glyph so give its | |
| 4187 | 2503 space back in order to make sure that the cursor can |
| 2504 fit. */ | |
| 819 | 2505 data.max_pixpos += data.end_glyph_width; |
| 428 | 2506 |
| 2507 if (selective > 0 | |
| 826 | 2508 && (byte_spaces_at_point |
| 2509 (b, next_bytebpos (b, data.byte_charpos)) | |
| 428 | 2510 >= selective)) |
| 2511 { | |
| 2512 if (!NILP (b->selective_display_ellipses)) | |
| 2513 { | |
| 2514 struct glyph_block gb; | |
| 2515 | |
| 2516 gb.extent = Qnil; | |
| 2517 gb.glyph = Vinvisible_text_glyph; | |
| 2518 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
| 2519 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
| 2520 } | |
| 2521 else | |
| 2522 { | |
| 2523 /* Cheesy, cheesy, cheesy. We mark the end of the | |
| 2524 line with a special "character rune" whose width | |
| 2525 is the EOL cursor width and whose character is | |
| 2526 the non-printing character '\n'. */ | |
| 2527 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 867 | 2528 *prop = add_ichar_rune (&data); |
| 428 | 2529 } |
| 2530 | |
| 826 | 2531 /* We need to set data.byte_charpos to the start of the |
| 4187 | 2532 next visible region in order to make this line |
| 2533 appear to contain all of the invisible area. | |
| 2534 Otherwise, the line cache won't work | |
| 2535 correctly. */ | |
| 826 | 2536 INC_BYTEBPOS (b, data.byte_charpos); |
| 2537 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
| 428 | 2538 { |
| 826 | 2539 data.byte_charpos = |
| 2540 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
| 2541 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
| 428 | 2542 { |
| 826 | 2543 data.byte_charpos = BYTE_BUF_ZV (b); |
| 428 | 2544 break; |
| 2545 } | |
| 2546 } | |
| 826 | 2547 if (BYTE_BUF_FETCH_CHAR |
| 2548 (b, prev_bytebpos (b, data.byte_charpos)) == '\n') | |
| 2549 DEC_BYTEBPOS (b, data.byte_charpos); | |
| 428 | 2550 } |
| 2551 else | |
| 2552 { | |
| 2553 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 867 | 2554 *prop = add_ichar_rune (&data); |
| 428 | 2555 } |
| 2556 | |
| 2557 goto done; | |
| 2558 } | |
| 2559 | |
| 2560 /* If the current character is ^M, and selective display is | |
| 4187 | 2561 enabled, then add the invisible-text-glyph if |
| 2562 selective-display-ellipses is set. In any case, this | |
| 2563 line is done. */ | |
| 428 | 2564 else if (data.ch == (('M' & 037)) && selective == -1) |
| 2565 { | |
| 826 | 2566 Bytebpos byte_next_charpos; |
| 428 | 2567 |
| 2568 /* Find the buffer position at the end of the line. */ | |
| 826 | 2569 byte_next_charpos = |
| 2570 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
| 2571 if (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_next_charpos)) | |
| 428 | 2572 == '\n') |
| 826 | 2573 DEC_BYTEBPOS (b, byte_next_charpos); |
| 428 | 2574 |
| 2575 /* If the cursor is somewhere in the elided text make | |
| 4187 | 2576 sure that the cursor gets drawn appropriately. */ |
| 428 | 2577 if (data.cursor_type == CURSOR_ON |
| 826 | 2578 && (data.byte_cursor_charpos >= data.byte_charpos && |
| 2579 data.byte_cursor_charpos < byte_next_charpos)) | |
| 428 | 2580 { |
| 2581 data.cursor_type = NEXT_CURSOR; | |
| 2582 } | |
| 2583 | |
| 2584 /* We won't be adding a truncation or continuation glyph | |
| 4187 | 2585 so give up the room allocated for them. */ |
| 819 | 2586 data.max_pixpos += data.end_glyph_width; |
| 428 | 2587 |
| 2588 if (!NILP (b->selective_display_ellipses)) | |
| 2589 { | |
| 2590 /* We don't propagate anything from the invisible | |
| 4187 | 2591 text glyph if it fails to fit. This is |
| 2592 intentional. */ | |
| 428 | 2593 struct glyph_block gb; |
| 2594 | |
| 2595 gb.extent = Qnil; | |
| 2596 gb.glyph = Vinvisible_text_glyph; | |
| 2597 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, | |
| 2598 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
| 2599 } | |
| 2600 | |
| 2601 /* Set the buffer position to the end of the line. We | |
| 4187 | 2602 need to do this before potentially adding a newline |
| 2603 so that the cursor flag will get set correctly (if | |
| 2604 needed). */ | |
| 826 | 2605 data.byte_charpos = byte_next_charpos; |
| 428 | 2606 |
| 2607 if (NILP (b->selective_display_ellipses) | |
| 826 | 2608 || data.byte_cursor_charpos == byte_next_charpos) |
| 428 | 2609 { |
| 2610 /* We have to at least add a newline character so | |
| 4187 | 2611 that the cursor shows up properly. */ |
| 428 | 2612 data.ch = '\n'; |
| 2613 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 2614 data.findex = DEFAULT_INDEX; | |
| 2615 data.start_col = 0; | |
| 2616 data.start_col_xoffset = 0; | |
| 826 | 2617 data.byte_start_col_enabled = 0; |
| 428 | 2618 |
| 867 | 2619 add_ichar_rune (&data); |
| 428 | 2620 } |
| 2621 | |
| 2622 /* This had better be a newline but doing it this way | |
| 4187 | 2623 we'll see obvious incorrect results if it isn't. No |
| 2624 need to abort here. */ | |
| 826 | 2625 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
| 428 | 2626 |
| 2627 goto done; | |
| 2628 } | |
| 2629 | |
| 2630 /* If the current character is considered to be printable, then | |
| 4187 | 2631 just add it. */ |
| 428 | 2632 else if (data.ch >= printable_min) |
| 2633 { | |
| 867 | 2634 *prop = add_ichar_rune (&data); |
| 428 | 2635 if (*prop) |
| 2636 goto done; | |
| 2637 } | |
| 2638 | |
| 2639 /* If the current character is a tab, determine the next tab | |
| 4187 | 2640 starting position and add a blank rune which extends from the |
| 2641 current pixel position to that starting position. */ | |
| 428 | 2642 else if (data.ch == '\t') |
| 2643 { | |
| 2644 int tab_start_pixpos = data.pixpos; | |
| 2645 int next_tab_start; | |
| 2646 int char_tab_width; | |
| 2647 int prop_width = 0; | |
| 2648 | |
| 2649 if (data.start_col > 1) | |
| 434 | 2650 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)) |
| 428 | 2651 + data.start_col_xoffset; |
| 2652 | |
| 2653 next_tab_start = | |
| 2654 next_tab_position (w, tab_start_pixpos, | |
| 2655 dl->bounds.left_in + | |
| 2656 data.hscroll_glyph_width_adjust); | |
| 2657 if (next_tab_start > data.max_pixpos) | |
| 2658 { | |
| 2659 prop_width = next_tab_start - data.max_pixpos; | |
| 2660 next_tab_start = data.max_pixpos; | |
| 2661 } | |
| 2662 data.blank_width = next_tab_start - data.pixpos; | |
| 2663 char_tab_width = | |
| 2664 (next_tab_start - tab_start_pixpos) / space_width (w); | |
| 2665 | |
| 2666 *prop = add_blank_rune (&data, w, char_tab_width); | |
| 2667 | |
| 2668 /* add_blank_rune is only supposed to be called with | |
| 4187 | 2669 sizes guaranteed to fit in the available space. */ |
| 428 | 2670 assert (!(*prop)); |
| 2671 | |
| 2672 if (prop_width) | |
| 2673 { | |
| 2674 struct prop_block pb; | |
| 2675 *prop = Dynarr_new (prop_block); | |
| 2676 | |
| 2677 pb.type = PROP_BLANK; | |
| 2678 pb.data.p_blank.width = prop_width; | |
| 2679 pb.data.p_blank.findex = data.findex; | |
| 2680 Dynarr_add (*prop, pb); | |
| 2681 | |
| 2682 goto done; | |
| 2683 } | |
| 2684 } | |
| 2685 | |
| 2686 /* If character is a control character, pass it off to | |
| 4187 | 2687 add_control_char_runes. |
| 428 | 2688 |
| 2689 The is_*() routines have undefined results on | |
| 2690 arguments outside of the range [-1, 255]. (This | |
| 2691 often bites people who carelessly use `char' instead | |
| 2692 of `unsigned char'.) | |
| 2693 */ | |
| 867 | 2694 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
| 428 | 2695 { |
| 2696 *prop = add_control_char_runes (&data, b); | |
| 2697 | |
| 2698 if (*prop) | |
| 2699 goto done; | |
| 2700 } | |
| 2701 | |
| 2702 /* If the character is above the ASCII range and we have not | |
| 4187 | 2703 already handled it, then print it as an octal number. */ |
| 428 | 2704 else if (data.ch >= 0200) |
| 2705 { | |
| 2706 *prop = add_octal_runes (&data); | |
| 2707 | |
| 2708 if (*prop) | |
| 2709 goto done; | |
| 2710 } | |
| 2711 | |
| 2712 /* Assume the current character is considered to be printable, | |
| 4187 | 2713 then just add it. */ |
| 428 | 2714 else |
| 2715 { | |
| 867 | 2716 *prop = add_ichar_rune (&data); |
| 428 | 2717 if (*prop) |
| 2718 goto done; | |
| 2719 } | |
| 2720 | |
| 826 | 2721 INC_BYTEBPOS (b, data.byte_charpos); |
| 428 | 2722 } |
| 2723 } | |
| 2724 | |
| 2725 done: | |
| 2726 | |
| 2727 /* Determine the starting point of the next line if we did not hit the | |
| 2728 end of the buffer. */ | |
| 826 | 2729 if (data.byte_charpos < BYTE_BUF_ZV (b) |
| 428 | 2730 && (active_minibuffer || !NILP (synch_minibuffers_value))) |
| 2731 { | |
| 2732 /* #### This check is not correct. If the line terminated | |
| 2733 due to a begin-glyph or end-glyph hitting window-end, then | |
| 826 | 2734 data.ch will not point to the character at data.byte_charpos. If |
| 428 | 2735 you make the two changes mentioned at the top of this loop, |
| 2736 you should be able to say '(if (*prop))'. That should also | |
| 826 | 2737 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
| 428 | 2738 check. */ |
| 2739 | |
| 2740 /* The common case is that the line ended because we hit a newline. | |
| 4187 | 2741 In that case, the next character is just the next buffer |
| 2742 position. */ | |
| 428 | 2743 if (data.ch == '\n') |
| 2744 { | |
| 2745 /* If data.start_col_enabled is still true, then the window is | |
| 4187 | 2746 scrolled far enough so that nothing on this line is visible. |
| 2747 We need to stick a truncation glyph at the beginning of the | |
| 2748 line in that case unless the line is completely blank. */ | |
| 826 | 2749 if (data.byte_start_col_enabled) |
| 428 | 2750 { |
| 2751 if (data.cursor_type == CURSOR_ON) | |
| 2752 { | |
| 826 | 2753 if (data.byte_cursor_charpos >= byte_start_pos |
| 2754 && data.byte_cursor_charpos <= data.byte_charpos) | |
| 2755 data.byte_cursor_charpos = data.byte_charpos; | |
| 428 | 2756 } |
| 2757 data.findex = DEFAULT_INDEX; | |
| 2758 data.start_col = 0; | |
| 826 | 2759 data.byte_start_col_enabled = 0; |
| 2760 | |
| 2761 if (data.byte_charpos != byte_start_pos) | |
| 428 | 2762 { |
| 2763 struct glyph_block gb; | |
| 2764 | |
| 2765 gb.extent = Qnil; | |
| 2766 gb.glyph = Vhscroll_glyph; | |
| 2767 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
| 2768 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX)); | |
| 2769 } | |
| 2770 else | |
| 2771 { | |
| 2772 /* This duplicates code down below to add a newline to | |
| 4187 | 2773 the end of an otherwise empty line.*/ |
| 428 | 2774 data.ch = '\n'; |
| 2775 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 2776 | |
| 867 | 2777 add_ichar_rune (&data); |
| 428 | 2778 } |
| 2779 } | |
| 2780 | |
| 826 | 2781 INC_BYTEBPOS (b, data.byte_charpos); |
| 428 | 2782 } |
| 2783 | |
| 2784 /* Otherwise we have a buffer line which cannot fit on one display | |
| 4187 | 2785 line. */ |
| 428 | 2786 else |
| 2787 { | |
| 2788 struct glyph_block gb; | |
| 2789 struct glyph_cachel *cachel; | |
| 2790 | |
| 2791 /* If the line is to be truncated then we actually have to look | |
| 4187 | 2792 for the next newline. We also add the end-of-line glyph which |
| 2793 we know will fit because we adjusted the right border before | |
| 2794 we starting laying out the line. */ | |
| 819 | 2795 data.max_pixpos += data.end_glyph_width; |
| 428 | 2796 data.findex = DEFAULT_INDEX; |
| 2797 gb.extent = Qnil; | |
| 2798 | |
| 2799 if (truncate_win) | |
| 2800 { | |
| 826 | 2801 Bytebpos byte_pos; |
| 428 | 2802 |
| 2803 /* Now find the start of the next line. */ | |
| 826 | 2804 byte_pos = byte_find_next_newline_no_quit (b, data.byte_charpos, 1); |
| 428 | 2805 |
| 2806 /* If the cursor is past the truncation line then we | |
| 4187 | 2807 make it appear on the truncation glyph. If we've hit |
| 2808 the end of the buffer then we also make the cursor | |
| 2809 appear unless eob is immediately preceded by a | |
| 2810 newline. In that case the cursor should actually | |
| 2811 appear on the next line. */ | |
| 428 | 2812 if (data.cursor_type == CURSOR_ON |
| 826 | 2813 && data.byte_cursor_charpos >= data.byte_charpos |
| 2814 && (data.byte_cursor_charpos < byte_pos || | |
| 2815 (byte_pos == BYTE_BUF_ZV (b) | |
| 2816 && (byte_pos == BYTE_BUF_BEGV (b) | |
| 2817 || (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_pos)) | |
| 428 | 2818 != '\n'))))) |
| 826 | 2819 data.byte_cursor_charpos = byte_pos; |
| 428 | 2820 else |
| 2821 data.cursor_type = NO_CURSOR; | |
| 2822 | |
| 826 | 2823 data.byte_charpos = byte_pos; |
| 428 | 2824 gb.glyph = Vtruncation_glyph; |
| 2825 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
| 2826 } | |
| 2827 else | |
| 2828 { | |
| 2829 /* The cursor can never be on the continuation glyph. */ | |
| 2830 data.cursor_type = NO_CURSOR; | |
| 2831 | |
| 826 | 2832 /* data.byte_charpos is already at the start of the next line. */ |
| 428 | 2833 |
| 442 | 2834 dl->line_continuation = 1; |
| 428 | 2835 gb.glyph = Vcontinuation_glyph; |
| 2836 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
| 2837 } | |
| 2838 | |
| 442 | 2839 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
| 428 | 2840 |
| 826 | 2841 if (truncate_win && data.byte_charpos == BYTE_BUF_ZV (b) |
| 2842 && BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, BYTE_BUF_ZV (b))) != '\n') | |
| 428 | 2843 /* #### Damn this losing shit. */ |
| 826 | 2844 data.byte_charpos++; |
| 428 | 2845 } |
| 2846 } | |
| 2847 else if ((active_minibuffer || !NILP (synch_minibuffers_value)) | |
| 826 | 2848 && (!echo_area_active (f) || data.byte_charpos == BYTE_BUF_ZV (b))) |
| 428 | 2849 { |
| 2850 /* We need to add a marker to the end of the line since there is no | |
| 4187 | 2851 newline character in order for the cursor to get drawn. We label |
| 2852 it as a newline so that it gets handled correctly by the | |
| 2853 whitespace routines below. */ | |
| 428 | 2854 |
| 2855 data.ch = '\n'; | |
| 2856 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
| 2857 data.findex = DEFAULT_INDEX; | |
| 2858 data.start_col = 0; | |
| 2859 data.start_col_xoffset = 0; | |
| 826 | 2860 data.byte_start_col_enabled = 0; |
| 428 | 2861 |
| 2862 data.max_pixpos += data.blank_width; | |
| 867 | 2863 add_ichar_rune (&data); |
| 428 | 2864 data.max_pixpos -= data.blank_width; |
| 2865 | |
| 2866 /* #### urk! Chuck, this shit is bad news. Going around | |
| 2867 manipulating invalid positions is guaranteed to result in | |
| 2868 trouble sooner or later. */ | |
| 826 | 2869 data.byte_charpos = BYTE_BUF_ZV (b) + 1; |
| 428 | 2870 } |
| 2871 | |
| 2872 /* Calculate left whitespace boundary. */ | |
| 2873 { | |
| 2874 int elt = 0; | |
| 2875 | |
| 2876 /* Whitespace past a newline is considered right whitespace. */ | |
| 2877 while (elt < Dynarr_length (db->runes)) | |
| 2878 { | |
| 2879 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 2880 | |
| 2881 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
| 2882 || rb->type == RUNE_BLANK) | |
| 2883 { | |
| 2884 dl->bounds.left_white += rb->width; | |
| 2885 elt++; | |
| 2886 } | |
| 2887 else | |
| 2888 elt = Dynarr_length (db->runes); | |
| 2889 } | |
| 2890 } | |
| 2891 | |
| 2892 /* Calculate right whitespace boundary. */ | |
| 2893 { | |
| 2894 int elt = Dynarr_length (db->runes) - 1; | |
| 2895 int done = 0; | |
| 2896 | |
| 2897 while (!done && elt >= 0) | |
| 2898 { | |
| 2899 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 2900 | |
| 2901 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
| 2902 && isspace (rb->object.chr.ch)) | |
| 2903 && !rb->type == RUNE_BLANK) | |
| 2904 { | |
| 2905 dl->bounds.right_white = rb->xpos + rb->width; | |
| 2906 done = 1; | |
| 2907 } | |
| 2908 | |
| 2909 elt--; | |
| 2910 | |
| 2911 } | |
| 2912 | |
| 2913 /* The line is blank so everything is considered to be right | |
| 2914 whitespace. */ | |
| 2915 if (!done) | |
| 2916 dl->bounds.right_white = dl->bounds.left_in; | |
| 2917 } | |
| 2918 | |
| 2919 /* Set the display blocks bounds. */ | |
| 2920 db->start_pos = dl->bounds.left_in; | |
| 2921 if (Dynarr_length (db->runes)) | |
| 2922 { | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2923 struct rune *rb = Dynarr_lastp (db->runes); |
| 428 | 2924 |
| 2925 db->end_pos = rb->xpos + rb->width; | |
| 2926 } | |
| 2927 else | |
| 2928 db->end_pos = dl->bounds.right_white; | |
| 2929 | |
| 819 | 2930 calculate_baseline (&data); |
| 428 | 2931 |
| 2932 dl->ascent = data.new_ascent; | |
| 2933 dl->descent = data.new_descent; | |
| 2934 | |
| 2935 { | |
| 2936 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
| 2937 | |
| 2938 if (dl->ascent < ascent) | |
| 2939 dl->ascent = ascent; | |
| 2940 } | |
| 2941 { | |
| 2942 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
| 2943 | |
| 2944 if (dl->descent < descent) | |
| 2945 dl->descent = descent; | |
| 2946 } | |
| 2947 | |
| 819 | 2948 calculate_yoffset (dl, db); |
| 2949 | |
| 428 | 2950 dl->cursor_elt = data.cursor_x; |
| 2951 /* #### lossage lossage lossage! Fix this shit! */ | |
| 826 | 2952 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
| 2953 dl->end_charpos = BUF_ZV (b); | |
| 428 | 2954 else |
| 826 | 2955 dl->end_charpos = bytebpos_to_charbpos (b, data.byte_charpos) - 1; |
| 428 | 2956 if (truncate_win) |
| 826 | 2957 data.dl->num_chars = column_at_point (b, dl->end_charpos, 0); |
| 428 | 2958 else |
| 2959 /* This doesn't correctly take into account tabs and control | |
| 2960 characters but if the window isn't being truncated then this | |
| 2961 value isn't going to end up being used anyhow. */ | |
| 826 | 2962 data.dl->num_chars = dl->end_charpos - dl->charpos; |
| 428 | 2963 |
| 2964 /* #### handle horizontally scrolled line with text none of which | |
| 2965 was actually laid out. */ | |
| 2966 | |
| 2967 /* #### handle any remainder of overlay arrow */ | |
| 2968 | |
| 2969 if (*prop == ADD_FAILED) | |
| 2970 *prop = NULL; | |
| 2971 | |
| 2972 if (truncate_win && *prop) | |
| 2973 { | |
| 2974 Dynarr_free (*prop); | |
| 2975 *prop = NULL; | |
| 2976 } | |
| 2977 | |
| 2978 extent_fragment_delete (data.ef); | |
| 2979 | |
| 2980 /* #### If we started at EOB, then make sure we return a value past | |
| 2981 it so that regenerate_window will exit properly. This is bogus. | |
| 2982 The main loop should get fixed so that it isn't necessary to call | |
| 2983 this function if we are already at EOB. */ | |
| 2984 | |
| 826 | 2985 if (data.byte_charpos == BYTE_BUF_ZV (b) && byte_start_pos == BYTE_BUF_ZV (b)) |
| 2986 return data.byte_charpos + 1; /* Yuck! */ | |
| 428 | 2987 else |
| 826 | 2988 return data.byte_charpos; |
| 428 | 2989 } |
| 2990 | |
| 2991 /* Display the overlay arrow at the beginning of the given line. */ | |
| 2992 | |
| 2993 static int | |
| 2994 create_overlay_glyph_block (struct window *w, struct display_line *dl) | |
| 2995 { | |
| 2996 struct frame *f = XFRAME (w->frame); | |
| 2997 struct device *d = XDEVICE (f->device); | |
| 2998 pos_data data; | |
| 2999 | |
| 3000 /* If Voverlay_arrow_string isn't valid then just fail silently. */ | |
| 3001 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string)) | |
| 3002 return 0; | |
| 3003 | |
| 3004 xzero (data); | |
| 3005 data.ef = NULL; | |
| 3006 data.d = d; | |
| 793 | 3007 data.window = wrap_window (w); |
| 428 | 3008 data.db = get_display_block_from_line (dl, OVERWRITE); |
| 3009 data.dl = dl; | |
| 3010 data.pixpos = dl->bounds.left_in; | |
| 3011 data.max_pixpos = dl->bounds.right_in; | |
| 3012 data.cursor_type = NO_CURSOR; | |
| 3013 data.cursor_x = -1; | |
| 3014 data.findex = DEFAULT_INDEX; | |
| 3015 data.last_charset = Qunbound; | |
| 3016 data.last_findex = DEFAULT_INDEX; | |
| 3017 data.result_str = Qnil; | |
| 3018 data.string = Qnil; | |
| 3019 | |
| 3020 Dynarr_reset (data.db->runes); | |
| 3021 | |
| 3022 if (STRINGP (Voverlay_arrow_string)) | |
| 3023 { | |
| 867 | 3024 add_ibyte_string_runes |
| 428 | 3025 (&data, |
| 3026 XSTRING_DATA (Voverlay_arrow_string), | |
| 3027 XSTRING_LENGTH (Voverlay_arrow_string), | |
| 793 | 3028 1, 0); |
| 428 | 3029 } |
| 3030 else if (GLYPHP (Voverlay_arrow_string)) | |
| 3031 { | |
| 3032 struct glyph_block gb; | |
| 3033 | |
| 3034 gb.glyph = Voverlay_arrow_string; | |
| 3035 gb.extent = Qnil; | |
| 3036 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0); | |
| 3037 } | |
| 4187 | 3038 |
| 428 | 3039 if (data.max_pixmap_height) |
| 3040 { | |
| 3041 int height = data.new_ascent + data.new_descent; | |
| 3042 int pix_ascent, pix_descent; | |
| 4187 | 3043 |
| 428 | 3044 pix_descent = data.max_pixmap_height * data.new_descent / height; |
| 3045 pix_ascent = data.max_pixmap_height - pix_descent; | |
| 819 | 3046 calculate_baseline (&data); |
| 428 | 3047 |
| 3048 data.new_ascent = max (data.new_ascent, pix_ascent); | |
| 3049 data.new_descent = max (data.new_descent, pix_descent); | |
| 3050 } | |
| 3051 | |
| 3052 dl->ascent = data.new_ascent; | |
| 3053 dl->descent = data.new_descent; | |
| 3054 | |
| 3055 data.db->start_pos = dl->bounds.left_in; | |
| 3056 data.db->end_pos = data.pixpos; | |
| 3057 | |
| 819 | 3058 calculate_yoffset (dl, data.db); |
| 3059 | |
| 428 | 3060 return data.pixpos - dl->bounds.left_in; |
| 3061 } | |
| 3062 | |
| 3063 /* Add a type of glyph to a margin display block. */ | |
| 3064 | |
| 3065 static int | |
| 3066 add_margin_runes (struct display_line *dl, struct display_block *db, int start, | |
| 3067 int count, enum glyph_layout layout, int side, Lisp_Object window) | |
| 3068 { | |
| 3069 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS | |
| 3070 ? dl->left_glyphs | |
| 3071 : dl->right_glyphs); | |
| 3072 int elt, end; | |
| 3073 int reverse; | |
| 442 | 3074 struct window *w = XWINDOW (window); |
| 3075 struct frame *f = XFRAME (w->frame); | |
| 3076 struct device *d = XDEVICE (f->device); | |
| 3077 pos_data data; | |
| 3078 | |
| 3079 xzero (data); | |
| 3080 data.d = d; | |
| 3081 data.window = window; | |
| 3082 data.db = db; | |
| 3083 data.dl = dl; | |
| 3084 data.pixpos = start; | |
| 3085 data.cursor_type = NO_CURSOR; | |
| 3086 data.cursor_x = -1; | |
| 3087 data.last_charset = Qunbound; | |
| 3088 data.last_findex = DEFAULT_INDEX; | |
| 3089 data.result_str = Qnil; | |
| 3090 data.string = Qnil; | |
| 3091 data.new_ascent = dl->ascent; | |
| 3092 data.new_descent = dl->descent; | |
| 428 | 3093 |
| 3094 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) | |
| 3095 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) | |
| 3096 { | |
| 3097 reverse = 1; | |
| 3098 elt = Dynarr_length (gbd) - 1; | |
| 3099 end = 0; | |
| 3100 } | |
| 3101 else | |
| 3102 { | |
| 3103 reverse = 0; | |
| 3104 elt = 0; | |
| 3105 end = Dynarr_length (gbd); | |
| 3106 } | |
| 3107 | |
| 3108 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) | |
| 3109 { | |
| 3110 struct glyph_block *gb = Dynarr_atp (gbd, elt); | |
| 3111 | |
| 3112 if (NILP (gb->extent)) | |
| 2500 | 3113 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3114 |
| 3115 if (gb->active && | |
| 3116 ((side == LEFT_GLYPHS && | |
| 3117 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout) | |
| 3118 || (side == RIGHT_GLYPHS && | |
| 3119 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) | |
| 3120 { | |
| 442 | 3121 data.findex = gb->findex; |
| 3122 data.max_pixpos = data.pixpos + gb->width; | |
| 3123 add_glyph_rune (&data, gb, side, 0, NULL); | |
| 428 | 3124 count--; |
| 3125 gb->active = 0; | |
| 3126 } | |
| 3127 | |
| 3128 (reverse ? elt-- : elt++); | |
| 3129 } | |
| 3130 | |
| 819 | 3131 calculate_baseline (&data); |
| 442 | 3132 |
| 3133 dl->ascent = data.new_ascent; | |
| 3134 dl->descent = data.new_descent; | |
| 3135 | |
| 819 | 3136 calculate_yoffset (dl, data.db); |
| 3137 | |
| 442 | 3138 return data.pixpos; |
| 428 | 3139 } |
| 3140 | |
| 3141 /* Add a blank to a margin display block. */ | |
| 3142 | |
| 3143 static void | |
| 2286 | 3144 add_margin_blank (struct display_line *UNUSED (dl), struct display_block *db, |
| 428 | 3145 struct window *w, int xpos, int width, int side) |
| 3146 { | |
| 3147 struct rune rb; | |
| 3148 | |
| 3149 rb.findex = (side == LEFT_GLYPHS | |
| 3150 ? get_builtin_face_cache_index (w, Vleft_margin_face) | |
| 3151 : get_builtin_face_cache_index (w, Vright_margin_face)); | |
| 3152 rb.xpos = xpos; | |
| 3153 rb.width = width; | |
| 826 | 3154 rb.charpos = -1; |
| 428 | 3155 rb.endpos = 0; |
| 3156 rb.type = RUNE_BLANK; | |
| 3157 rb.cursor_type = CURSOR_OFF; | |
| 3158 | |
| 3159 Dynarr_add (db->runes, rb); | |
| 3160 } | |
| 3161 | |
| 3162 /* Display glyphs in the left outside margin, left inside margin and | |
| 3163 left whitespace area. */ | |
| 3164 | |
| 3165 static void | |
| 3166 create_left_glyph_block (struct window *w, struct display_line *dl, | |
| 3167 int overlay_width) | |
| 3168 { | |
| 3169 Lisp_Object window; | |
| 3170 | |
| 3171 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1); | |
| 3172 int elt, end_xpos; | |
| 3173 int out_end, in_out_start, in_in_end, white_out_start, white_in_start; | |
| 3174 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
| 3175 int left_in_start = dl->bounds.left_in; | |
| 3176 int left_in_end = dl->bounds.left_in + overlay_width; | |
| 3177 | |
| 3178 struct display_block *odb, *idb; | |
| 3179 | |
| 793 | 3180 window = wrap_window (w); |
| 428 | 3181 |
| 3182 /* We have to add the glyphs to the line in the order outside, | |
| 3183 inside, whitespace. However the precedence dictates that we | |
| 3184 determine how many will fit in the reverse order. */ | |
| 3185 | |
| 3186 /* Determine how many whitespace glyphs we can display and where | |
| 3187 they should start. */ | |
| 3188 white_in_start = dl->bounds.left_white; | |
| 3189 white_out_start = left_in_start; | |
| 3190 white_out_cnt = white_in_cnt = 0; | |
| 3191 elt = 0; | |
| 3192 | |
| 3193 while (elt < Dynarr_length (dl->left_glyphs)) | |
| 3194 { | |
| 3195 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
| 3196 | |
| 3197 if (NILP (gb->extent)) | |
| 2500 | 3198 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3199 |
| 3200 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
| 3201 { | |
| 3202 int width; | |
| 3203 | |
| 438 | 3204 width = glyph_width (gb->glyph, window); |
| 428 | 3205 |
| 3206 if (white_in_start - width >= left_in_end) | |
| 3207 { | |
| 3208 white_in_cnt++; | |
| 3209 white_in_start -= width; | |
| 3210 gb->width = width; | |
| 3211 gb->active = 1; | |
| 3212 } | |
| 3213 else if (use_overflow | |
| 3214 && (white_out_start - width > dl->bounds.left_out)) | |
| 3215 { | |
| 3216 white_out_cnt++; | |
| 3217 white_out_start -= width; | |
| 3218 gb->width = width; | |
| 3219 gb->active = 1; | |
| 3220 } | |
| 3221 else | |
| 3222 gb->active = 0; | |
| 3223 } | |
| 3224 | |
| 3225 elt++; | |
| 3226 } | |
| 3227 | |
| 3228 /* Determine how many inside margin glyphs we can display and where | |
| 3229 they should start. The inside margin glyphs get whatever space | |
| 3230 is left after the whitespace glyphs have been displayed. These | |
| 3231 are tricky to calculate since if we decide to use the overflow | |
| 3232 area we basically have to start over. So for these we build up a | |
| 3233 list of just the inside margin glyphs and manipulate it to | |
| 3234 determine the needed info. */ | |
| 3235 { | |
| 3236 glyph_block_dynarr *ib; | |
| 3237 int avail_in, avail_out; | |
| 3238 int done = 0; | |
| 3239 int marker = 0; | |
| 3240 int used_in, used_out; | |
| 3241 | |
| 3242 elt = 0; | |
| 3243 used_in = used_out = 0; | |
| 3244 ib = Dynarr_new (glyph_block); | |
| 3245 while (elt < Dynarr_length (dl->left_glyphs)) | |
| 3246 { | |
| 3247 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
| 3248 | |
| 3249 if (NILP (gb->extent)) | |
| 2500 | 3250 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3251 |
| 3252 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
| 3253 GL_INSIDE_MARGIN) | |
| 3254 { | |
| 438 | 3255 gb->width = glyph_width (gb->glyph, window); |
| 428 | 3256 used_in += gb->width; |
| 3257 Dynarr_add (ib, *gb); | |
| 3258 } | |
| 3259 | |
| 3260 elt++; | |
| 3261 } | |
| 3262 | |
| 3263 if (white_out_cnt) | |
| 3264 avail_in = 0; | |
| 3265 else | |
| 3266 { | |
| 3267 avail_in = white_in_start - left_in_end; | |
| 3268 if (avail_in < 0) | |
| 3269 avail_in = 0; | |
| 3270 } | |
| 3271 | |
| 3272 if (!use_overflow) | |
| 3273 avail_out = 0; | |
| 3274 else | |
| 3275 avail_out = white_out_start - dl->bounds.left_out; | |
| 3276 | |
| 3277 marker = 0; | |
| 3278 while (!done && marker < Dynarr_length (ib)) | |
| 3279 { | |
| 3280 int width = Dynarr_atp (ib, marker)->width; | |
| 3281 | |
| 3282 /* If everything now fits in the available inside margin | |
| 4187 | 3283 space, we're done. */ |
| 428 | 3284 if (used_in <= avail_in) |
| 3285 done = 1; | |
| 3286 else | |
| 3287 { | |
| 3288 /* Otherwise see if we have room to move a glyph to the | |
| 4187 | 3289 outside. */ |
| 428 | 3290 if (used_out + width <= avail_out) |
| 3291 { | |
| 3292 used_out += width; | |
| 3293 used_in -= width; | |
| 3294 } | |
| 3295 else | |
| 3296 done = 1; | |
| 3297 } | |
| 3298 | |
| 3299 if (!done) | |
| 3300 marker++; | |
| 3301 } | |
| 3302 | |
| 3303 /* At this point we now know that everything from marker on goes in | |
| 3304 the inside margin and everything before it goes in the outside | |
| 3305 margin. The stuff going into the outside margin is guaranteed | |
| 3306 to fit, but we may have to trim some stuff from the inside. */ | |
| 3307 | |
| 3308 in_in_end = left_in_end; | |
| 3309 in_out_start = white_out_start; | |
| 3310 in_out_cnt = in_in_cnt = 0; | |
| 3311 | |
| 3312 Dynarr_free (ib); | |
| 3313 elt = 0; | |
| 3314 while (elt < Dynarr_length (dl->left_glyphs)) | |
| 3315 { | |
| 3316 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
| 3317 | |
| 3318 if (NILP (gb->extent)) | |
| 2500 | 3319 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3320 |
| 3321 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
| 3322 GL_INSIDE_MARGIN) | |
| 3323 { | |
| 438 | 3324 int width = glyph_width (gb->glyph, window); |
| 428 | 3325 |
| 3326 if (used_out) | |
| 3327 { | |
| 3328 in_out_cnt++; | |
| 3329 in_out_start -= width; | |
| 3330 gb->width = width; | |
| 3331 gb->active = 1; | |
| 3332 used_out -= width; | |
| 3333 } | |
| 3334 else if (in_in_end + width < white_in_start) | |
| 3335 { | |
| 3336 in_in_cnt++; | |
| 3337 in_in_end += width; | |
| 3338 gb->width = width; | |
| 3339 gb->active = 1; | |
| 3340 } | |
| 3341 else | |
| 3342 gb->active = 0; | |
| 3343 } | |
| 3344 | |
| 3345 elt++; | |
| 3346 } | |
| 3347 } | |
| 3348 | |
| 3349 /* Determine how many outside margin glyphs we can display. They | |
| 3350 always start at the left outside margin and can only use the | |
| 3351 outside margin space. */ | |
| 3352 out_end = dl->bounds.left_out; | |
| 3353 out_cnt = 0; | |
| 3354 elt = 0; | |
| 3355 | |
| 3356 while (elt < Dynarr_length (dl->left_glyphs)) | |
| 3357 { | |
| 3358 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
| 3359 | |
| 3360 if (NILP (gb->extent)) | |
| 2500 | 3361 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3362 |
| 3363 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
| 3364 GL_OUTSIDE_MARGIN) | |
| 3365 { | |
| 438 | 3366 int width = glyph_width (gb->glyph, window); |
| 428 | 3367 |
| 3368 if (out_end + width <= in_out_start) | |
| 3369 { | |
| 3370 out_cnt++; | |
| 3371 out_end += width; | |
| 3372 gb->width = width; | |
| 3373 gb->active = 1; | |
| 3374 } | |
| 3375 else | |
| 3376 gb->active = 0; | |
| 3377 } | |
| 3378 | |
| 3379 elt++; | |
| 3380 } | |
| 3381 | |
| 3382 /* Now that we know where everything goes, we add the glyphs as | |
| 3383 runes to the appropriate display blocks. */ | |
| 3384 if (out_cnt || in_out_cnt || white_out_cnt) | |
| 3385 { | |
| 3386 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN); | |
| 3387 odb->start_pos = dl->bounds.left_out; | |
| 3388 /* #### We should stop adding a blank to account for the space | |
| 4187 | 3389 between the end of the glyphs and the margin and instead set |
| 3390 this accordingly. */ | |
| 428 | 3391 odb->end_pos = dl->bounds.left_in; |
| 3392 Dynarr_reset (odb->runes); | |
| 3393 } | |
| 3394 else | |
| 3395 odb = 0; | |
| 3396 | |
| 3397 if (in_in_cnt || white_in_cnt) | |
| 3398 { | |
| 3399 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN); | |
| 3400 idb->start_pos = dl->bounds.left_in; | |
| 3401 /* #### See above comment for odb->end_pos */ | |
| 3402 idb->end_pos = dl->bounds.left_white; | |
| 3403 Dynarr_reset (idb->runes); | |
| 3404 } | |
| 3405 else | |
| 3406 idb = 0; | |
| 3407 | |
| 3408 /* First add the outside margin glyphs. */ | |
| 3409 if (out_cnt) | |
| 3410 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt, | |
| 3411 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window); | |
| 3412 else | |
| 3413 end_xpos = dl->bounds.left_out; | |
| 3414 | |
| 3415 /* There may be blank space between the outside margin glyphs and | |
| 3416 the inside margin glyphs. If so, add a blank. */ | |
| 3417 if (in_out_cnt && (in_out_start - end_xpos)) | |
| 3418 { | |
| 3419 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos, | |
| 3420 LEFT_GLYPHS); | |
| 3421 } | |
| 3422 | |
| 3423 /* Next add the inside margin glyphs which are actually in the | |
| 3424 outside margin. */ | |
| 3425 if (in_out_cnt) | |
| 3426 { | |
| 3427 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt, | |
| 3428 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
| 3429 } | |
| 3430 | |
| 3431 /* If we didn't add any inside margin glyphs to the outside margin, | |
| 3432 but are adding whitespace glyphs, then we need to add a blank | |
| 3433 here. */ | |
| 3434 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) | |
| 3435 { | |
| 3436 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos, | |
| 3437 LEFT_GLYPHS); | |
| 3438 } | |
| 3439 | |
| 3440 /* Next add the whitespace margin glyphs which are actually in the | |
| 3441 outside margin. */ | |
| 3442 if (white_out_cnt) | |
| 3443 { | |
| 3444 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt, | |
| 3445 GL_WHITESPACE, LEFT_GLYPHS, window); | |
| 3446 } | |
| 3447 | |
| 3448 /* We take care of clearing between the end of the glyphs and the | |
| 3449 start of the inside margin for lines which have glyphs. */ | |
| 3450 if (odb && (left_in_start - end_xpos)) | |
| 3451 { | |
| 3452 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos, | |
| 3453 LEFT_GLYPHS); | |
| 3454 } | |
| 3455 | |
| 3456 /* Next add the inside margin glyphs which are actually in the | |
| 3457 inside margin. */ | |
| 3458 if (in_in_cnt) | |
| 3459 { | |
| 3460 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt, | |
| 3461 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
| 3462 } | |
| 3463 else | |
| 3464 end_xpos = left_in_end; | |
| 3465 | |
| 3466 /* Make sure that the area between the end of the inside margin | |
| 3467 glyphs and the whitespace glyphs is cleared. */ | |
| 3468 if (idb && (white_in_start - end_xpos > 0)) | |
| 3469 { | |
| 3470 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos, | |
| 3471 LEFT_GLYPHS); | |
| 3472 } | |
| 3473 | |
| 3474 /* Next add the whitespace margin glyphs which are actually in the | |
| 3475 inside margin. */ | |
| 3476 if (white_in_cnt) | |
| 3477 { | |
| 3478 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE, | |
| 3479 LEFT_GLYPHS, window); | |
| 3480 } | |
| 3481 | |
| 3482 /* Whitespace glyphs always end right next to the text block so | |
| 3483 there is nothing we have to make sure is cleared after them. */ | |
| 3484 } | |
| 3485 | |
| 3486 /* Display glyphs in the right outside margin, right inside margin and | |
| 3487 right whitespace area. */ | |
| 3488 | |
| 3489 static void | |
| 3490 create_right_glyph_block (struct window *w, struct display_line *dl) | |
| 3491 { | |
| 3492 Lisp_Object window; | |
| 3493 | |
| 3494 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1); | |
| 3495 int elt, end_xpos; | |
| 3496 int out_start, in_out_end, in_in_start, white_out_end, white_in_end; | |
| 3497 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
| 3498 | |
| 3499 struct display_block *odb, *idb; | |
| 3500 | |
| 793 | 3501 window = wrap_window (w); |
| 428 | 3502 |
| 3503 /* We have to add the glyphs to the line in the order outside, | |
| 3504 inside, whitespace. However the precedence dictates that we | |
| 3505 determine how many will fit in the reverse order. */ | |
| 3506 | |
| 3507 /* Determine how many whitespace glyphs we can display and where | |
| 3508 they should start. */ | |
| 3509 white_in_end = dl->bounds.right_white; | |
| 3510 white_out_end = dl->bounds.right_in; | |
| 3511 white_out_cnt = white_in_cnt = 0; | |
| 3512 elt = 0; | |
| 3513 | |
| 3514 while (elt < Dynarr_length (dl->right_glyphs)) | |
| 3515 { | |
| 3516 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
| 3517 | |
| 3518 if (NILP (gb->extent)) | |
| 2500 | 3519 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3520 |
| 3521 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
| 3522 { | |
| 438 | 3523 int width = glyph_width (gb->glyph, window); |
| 428 | 3524 |
| 3525 if (white_in_end + width <= dl->bounds.right_in) | |
| 3526 { | |
| 3527 white_in_cnt++; | |
| 3528 white_in_end += width; | |
| 3529 gb->width = width; | |
| 3530 gb->active = 1; | |
| 3531 } | |
| 3532 else if (use_overflow | |
| 3533 && (white_out_end + width <= dl->bounds.right_out)) | |
| 3534 { | |
| 3535 white_out_cnt++; | |
| 3536 white_out_end += width; | |
| 3537 gb->width = width; | |
| 3538 gb->active = 1; | |
| 3539 } | |
| 3540 else | |
| 3541 gb->active = 0; | |
| 3542 } | |
| 3543 | |
| 3544 elt++; | |
| 3545 } | |
| 3546 | |
| 3547 /* Determine how many inside margin glyphs we can display and where | |
| 3548 they should start. The inside margin glyphs get whatever space | |
| 3549 is left after the whitespace glyphs have been displayed. These | |
| 3550 are tricky to calculate since if we decide to use the overflow | |
| 3551 area we basically have to start over. So for these we build up a | |
| 3552 list of just the inside margin glyphs and manipulate it to | |
| 3553 determine the needed info. */ | |
| 3554 { | |
| 3555 glyph_block_dynarr *ib; | |
| 3556 int avail_in, avail_out; | |
| 3557 int done = 0; | |
| 3558 int marker = 0; | |
| 3559 int used_in, used_out; | |
| 3560 | |
| 3561 elt = 0; | |
| 3562 used_in = used_out = 0; | |
| 3563 ib = Dynarr_new (glyph_block); | |
| 3564 while (elt < Dynarr_length (dl->right_glyphs)) | |
| 3565 { | |
| 3566 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
| 3567 | |
| 3568 if (NILP (gb->extent)) | |
| 2500 | 3569 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3570 |
| 3571 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
| 3572 { | |
| 438 | 3573 gb->width = glyph_width (gb->glyph, window); |
| 428 | 3574 used_in += gb->width; |
| 3575 Dynarr_add (ib, *gb); | |
| 3576 } | |
| 3577 | |
| 3578 elt++; | |
| 3579 } | |
| 3580 | |
| 3581 if (white_out_cnt) | |
| 3582 avail_in = 0; | |
| 3583 else | |
| 3584 avail_in = dl->bounds.right_in - white_in_end; | |
| 3585 | |
| 3586 if (!use_overflow) | |
| 3587 avail_out = 0; | |
| 3588 else | |
| 3589 avail_out = dl->bounds.right_out - white_out_end; | |
| 3590 | |
| 3591 marker = 0; | |
| 3592 while (!done && marker < Dynarr_length (ib)) | |
| 3593 { | |
| 3594 int width = Dynarr_atp (ib, marker)->width; | |
| 3595 | |
| 3596 /* If everything now fits in the available inside margin | |
| 4187 | 3597 space, we're done. */ |
| 428 | 3598 if (used_in <= avail_in) |
| 3599 done = 1; | |
| 3600 else | |
| 3601 { | |
| 3602 /* Otherwise see if we have room to move a glyph to the | |
| 4187 | 3603 outside. */ |
| 428 | 3604 if (used_out + width <= avail_out) |
| 3605 { | |
| 3606 used_out += width; | |
| 3607 used_in -= width; | |
| 3608 } | |
| 3609 else | |
| 3610 done = 1; | |
| 3611 } | |
| 3612 | |
| 3613 if (!done) | |
| 3614 marker++; | |
| 3615 } | |
| 3616 | |
| 3617 /* At this point we now know that everything from marker on goes in | |
| 3618 the inside margin and everything before it goes in the outside | |
| 3619 margin. The stuff going into the outside margin is guaranteed | |
| 3620 to fit, but we may have to trim some stuff from the inside. */ | |
| 3621 | |
| 3622 in_in_start = dl->bounds.right_in; | |
| 3623 in_out_end = dl->bounds.right_in; | |
| 3624 in_out_cnt = in_in_cnt = 0; | |
| 3625 | |
| 3626 Dynarr_free (ib); | |
| 3627 elt = 0; | |
| 3628 while (elt < Dynarr_length (dl->right_glyphs)) | |
| 3629 { | |
| 3630 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
| 3631 | |
| 3632 if (NILP (gb->extent)) | |
| 2500 | 3633 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3634 |
| 3635 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
| 3636 { | |
| 438 | 3637 int width = glyph_width (gb->glyph, window); |
| 428 | 3638 |
| 3639 if (used_out) | |
| 3640 { | |
| 3641 in_out_cnt++; | |
| 3642 in_out_end += width; | |
| 3643 gb->width = width; | |
| 3644 gb->active = 1; | |
| 3645 used_out -= width; | |
| 3646 } | |
| 3647 else if (in_in_start - width >= white_in_end) | |
| 3648 { | |
| 3649 in_in_cnt++; | |
| 3650 in_in_start -= width; | |
| 3651 gb->width = width; | |
| 3652 gb->active = 1; | |
| 3653 } | |
| 3654 else | |
| 3655 gb->active = 0; | |
| 3656 } | |
| 3657 | |
| 3658 elt++; | |
| 3659 } | |
| 3660 } | |
| 3661 | |
| 3662 /* Determine how many outside margin glyphs we can display. They | |
| 3663 always start at the right outside margin and can only use the | |
| 3664 outside margin space. */ | |
| 3665 out_start = dl->bounds.right_out; | |
| 3666 out_cnt = 0; | |
| 3667 elt = 0; | |
| 3668 | |
| 3669 while (elt < Dynarr_length (dl->right_glyphs)) | |
| 3670 { | |
| 3671 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
| 3672 | |
| 3673 if (NILP (gb->extent)) | |
| 2500 | 3674 ABORT (); /* these should have been handled in add_glyph_rune */ |
| 428 | 3675 |
| 3676 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) | |
| 3677 { | |
| 438 | 3678 int width = glyph_width (gb->glyph, window); |
| 428 | 3679 |
| 3680 if (out_start - width >= in_out_end) | |
| 3681 { | |
| 3682 out_cnt++; | |
| 3683 out_start -= width; | |
| 3684 gb->width = width; | |
| 3685 gb->active = 1; | |
| 3686 } | |
| 3687 else | |
| 3688 gb->active = 0; | |
| 3689 } | |
| 3690 | |
| 3691 elt++; | |
| 3692 } | |
| 3693 | |
| 3694 /* Now that we now where everything goes, we add the glyphs as runes | |
| 3695 to the appropriate display blocks. */ | |
| 3696 if (out_cnt || in_out_cnt || white_out_cnt) | |
| 3697 { | |
| 3698 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN); | |
| 3699 /* #### See comments before odb->start_pos init in | |
| 4187 | 3700 create_left_glyph_block */ |
| 428 | 3701 odb->start_pos = dl->bounds.right_in; |
| 3702 odb->end_pos = dl->bounds.right_out; | |
| 3703 Dynarr_reset (odb->runes); | |
| 3704 } | |
| 3705 else | |
| 3706 odb = 0; | |
| 3707 | |
| 3708 if (in_in_cnt || white_in_cnt) | |
| 3709 { | |
| 3710 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN); | |
| 3711 idb->start_pos = dl->bounds.right_white; | |
| 3712 /* #### See comments before odb->start_pos init in | |
| 4187 | 3713 create_left_glyph_block */ |
| 428 | 3714 idb->end_pos = dl->bounds.right_in; |
| 3715 Dynarr_reset (idb->runes); | |
| 3716 } | |
| 3717 else | |
| 3718 idb = 0; | |
| 3719 | |
| 3720 /* First add the whitespace margin glyphs which are actually in the | |
| 3721 inside margin. */ | |
| 3722 if (white_in_cnt) | |
| 3723 { | |
| 3724 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white, | |
| 3725 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS, | |
| 3726 window); | |
| 3727 } | |
| 3728 else | |
| 3729 end_xpos = dl->bounds.right_white; | |
| 3730 | |
| 3731 /* Make sure that the area between the end of the whitespace glyphs | |
| 3732 and the inside margin glyphs is cleared. */ | |
| 3733 if (in_in_cnt && (in_in_start - end_xpos)) | |
| 3734 { | |
| 3735 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos, | |
| 3736 RIGHT_GLYPHS); | |
| 3737 } | |
| 3738 | |
| 3739 /* Next add the inside margin glyphs which are actually in the | |
| 3740 inside margin. */ | |
| 3741 if (in_in_cnt) | |
| 3742 { | |
| 3743 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt, | |
| 3744 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
| 3745 } | |
| 3746 | |
| 3747 /* If we didn't add any inside margin glyphs then make sure the rest | |
| 3748 of the inside margin area gets cleared. */ | |
| 3749 if (idb && (dl->bounds.right_in - end_xpos)) | |
| 3750 { | |
| 3751 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos, | |
| 3752 RIGHT_GLYPHS); | |
| 3753 } | |
| 3754 | |
| 3755 /* Next add any whitespace glyphs in the outside margin. */ | |
| 3756 if (white_out_cnt) | |
| 3757 { | |
| 3758 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt, | |
| 3759 GL_WHITESPACE, RIGHT_GLYPHS, window); | |
| 3760 } | |
| 3761 else | |
| 3762 end_xpos = dl->bounds.right_in; | |
| 3763 | |
| 3764 /* Next add any inside margin glyphs in the outside margin. */ | |
| 3765 if (in_out_cnt) | |
| 3766 { | |
| 3767 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt, | |
| 3768 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
| 3769 } | |
| 3770 | |
| 3771 /* There may be space between any whitespace or inside margin glyphs | |
| 3772 in the outside margin and the actual outside margin glyphs. */ | |
| 3773 if (odb && (out_start - end_xpos)) | |
| 3774 { | |
| 3775 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos, | |
| 3776 RIGHT_GLYPHS); | |
| 3777 } | |
| 3778 | |
| 3779 /* Finally, add the outside margin glyphs. */ | |
| 3780 if (out_cnt) | |
| 3781 { | |
| 3782 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN, | |
| 3783 RIGHT_GLYPHS, window); | |
| 3784 } | |
| 3785 } | |
| 3786 | |
| 3787 | |
| 3788 /***************************************************************************/ | |
| 3789 /* */ | |
| 3790 /* modeline routines */ | |
| 3791 /* */ | |
| 3792 /***************************************************************************/ | |
| 3793 | |
| 438 | 3794 /* This function is also used in frame.c by `generate_title_string' */ |
| 3795 void | |
| 3796 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, | |
| 4187 | 3797 struct window *w, struct display_line *dl, |
| 3798 struct display_block *db, face_index findex, | |
| 3799 int min_pixpos, int max_pixpos, int type) | |
| 438 | 3800 { |
| 3801 struct frame *f = XFRAME (w->frame); | |
| 3802 struct device *d = XDEVICE (f->device); | |
| 3803 | |
| 3804 pos_data data; | |
| 3805 int c_pixpos; | |
| 3806 Charcount offset = 0; | |
| 3807 | |
| 3808 xzero (data); | |
| 3809 data.d = d; | |
| 3810 data.db = db; | |
| 3811 data.dl = dl; | |
| 3812 data.findex = findex; | |
| 3813 data.pixpos = min_pixpos; | |
| 3814 data.max_pixpos = max_pixpos; | |
| 3815 data.cursor_type = NO_CURSOR; | |
| 3816 data.last_charset = Qunbound; | |
| 3817 data.last_findex = DEFAULT_INDEX; | |
| 3818 data.result_str = result_str; | |
| 3819 data.is_modeline = 1; | |
| 3820 data.string = Qnil; | |
| 793 | 3821 data.window = wrap_window (w); |
| 438 | 3822 |
| 3823 Dynarr_reset (formatted_string_extent_dynarr); | |
| 3824 Dynarr_reset (formatted_string_extent_start_dynarr); | |
| 3825 Dynarr_reset (formatted_string_extent_end_dynarr); | |
| 3826 | |
| 3827 /* result_str is nil when we're building a frame or icon title. Otherwise, | |
| 3828 we're building a modeline, so the offset starts at the modeline | |
| 442 | 3829 horizontal scrolling amount */ |
| 438 | 3830 if (! NILP (result_str)) |
| 3831 offset = w->modeline_hscroll; | |
| 3832 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, | |
| 4187 | 3833 max_pixpos - min_pixpos, findex, type, &offset, |
| 438 | 3834 Qnil); |
| 3835 | |
| 3836 if (Dynarr_length (db->runes)) | |
| 3837 { | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3838 struct rune *rb = Dynarr_lastp (db->runes); |
| 438 | 3839 c_pixpos = rb->xpos + rb->width; |
| 3840 } | |
| 3841 else | |
| 3842 c_pixpos = min_pixpos; | |
| 3843 | |
| 3844 /* If we don't reach the right side of the window, add a blank rune | |
| 3845 to make up the difference. This usually only occurs if the | |
| 3846 modeline face is using a proportional width font or a fixed width | |
| 3847 font of a different size from the default face font. */ | |
| 3848 | |
| 3849 if (c_pixpos < max_pixpos) | |
| 3850 { | |
| 3851 data.pixpos = c_pixpos; | |
| 3852 data.blank_width = max_pixpos - data.pixpos; | |
| 3853 | |
| 3854 add_blank_rune (&data, NULL, 0); | |
| 3855 } | |
| 3856 | |
| 3857 /* Now create the result string and frob the extents into it. */ | |
| 3858 if (!NILP (result_str)) | |
| 3859 { | |
| 3860 int elt; | |
| 3861 Bytecount len; | |
| 867 | 3862 Ibyte *strdata; |
| 438 | 3863 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); |
| 3864 | |
| 442 | 3865 in_modeline_generation = 1; |
| 3866 | |
| 771 | 3867 sledgehammer_check_ascii_begin (result_str); |
| 438 | 3868 detach_all_extents (result_str); |
| 793 | 3869 resize_string (result_str, -1, |
| 4187 | 3870 data.bytepos - XSTRING_LENGTH (result_str)); |
| 438 | 3871 |
| 3872 strdata = XSTRING_DATA (result_str); | |
| 3873 | |
| 3874 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++) | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3875 { |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3876 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3877 { |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3878 len += (set_itext_ichar |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3879 (strdata + len, Dynarr_atp (db->runes, |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3880 elt)->object.chr.ch)); |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3881 } |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3882 } |
| 438 | 3883 |
| 771 | 3884 init_string_ascii_begin (result_str); |
| 3885 bump_string_modiff (result_str); | |
| 3886 sledgehammer_check_ascii_begin (result_str); | |
| 3887 | |
| 438 | 3888 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr); |
| 4187 | 3889 elt++) |
| 3890 { | |
| 3891 Lisp_Object extent = Qnil; | |
| 3892 Lisp_Object child; | |
| 3893 | |
| 3894 extent = wrap_extent (Dynarr_at (formatted_string_extent_dynarr, elt)); | |
| 3895 child = Fgethash (extent, buf->modeline_extent_table, Qnil); | |
| 3896 if (NILP (child)) | |
| 3897 { | |
| 3898 child = Fmake_extent (Qnil, Qnil, result_str); | |
| 3899 Fputhash (extent, child, buf->modeline_extent_table); | |
| 3900 } | |
| 3901 Fset_extent_parent (child, extent); | |
| 3902 set_extent_endpoints | |
| 3903 (XEXTENT (child), | |
| 3904 Dynarr_at (formatted_string_extent_start_dynarr, elt), | |
| 3905 Dynarr_at (formatted_string_extent_end_dynarr, elt), | |
| 3906 result_str); | |
| 3907 } | |
| 442 | 3908 |
| 3909 in_modeline_generation = 0; | |
| 438 | 3910 } |
| 3911 } | |
| 3912 | |
| 428 | 3913 /* Ensure that the given display line DL accurately represents the |
| 3914 modeline for the given window. */ | |
| 3915 static void | |
| 3916 generate_modeline (struct window *w, struct display_line *dl, int type) | |
| 3917 { | |
| 3918 struct buffer *b = XBUFFER (w->buffer); | |
| 3919 struct frame *f = XFRAME (w->frame); | |
| 3920 struct device *d = XDEVICE (f->device); | |
| 3921 | |
| 3922 /* Unlike display line and rune pointers, this one can't change underneath | |
| 3923 our feet. */ | |
| 3924 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 3925 int max_pixpos, min_pixpos, ypos_adj; | |
| 3926 Lisp_Object font_inst; | |
| 3927 | |
| 3928 /* This will actually determine incorrect inside boundaries for the | |
| 3929 modeline since it ignores the margins. However being aware of this fact | |
| 3930 we never use those values anywhere so it doesn't matter. */ | |
| 3931 dl->bounds = calculate_display_line_boundaries (w, 1); | |
| 3932 | |
| 3933 /* We are generating a modeline. */ | |
| 3934 dl->modeline = 1; | |
| 3935 dl->cursor_elt = -1; | |
| 3936 | |
| 3937 /* Reset the runes on the modeline. */ | |
| 3938 Dynarr_reset (db->runes); | |
| 3939 | |
| 3940 if (!WINDOW_HAS_MODELINE_P (w)) | |
| 3941 { | |
| 3942 struct rune rb; | |
| 3943 | |
| 3944 /* If there is a horizontal scrollbar, don't add anything. */ | |
| 3945 if (window_scrollbar_height (w)) | |
| 3946 return; | |
| 3947 | |
| 3948 dl->ascent = DEVMETH (d, divider_height, ()); | |
| 3949 dl->descent = 0; | |
| 3950 /* The modeline is at the bottom of the gutters. */ | |
| 3951 dl->ypos = WINDOW_BOTTOM (w); | |
| 3952 | |
| 3953 rb.findex = MODELINE_INDEX; | |
| 3954 rb.xpos = dl->bounds.left_out; | |
| 3955 rb.width = dl->bounds.right_out - dl->bounds.left_out; | |
| 826 | 3956 rb.charpos = 0; |
| 428 | 3957 rb.endpos = 0; |
| 3958 rb.type = RUNE_HLINE; | |
| 3959 rb.object.hline.thickness = 1; | |
| 3960 rb.object.hline.yoffset = 0; | |
| 3961 rb.cursor_type = NO_CURSOR; | |
| 3962 | |
| 3963 if (!EQ (Qzero, w->modeline_shadow_thickness) | |
| 3964 && FRAME_WIN_P (f)) | |
| 3965 { | |
| 3966 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
| 3967 | |
| 3968 dl->ypos -= shadow_thickness; | |
| 3969 rb.xpos += shadow_thickness; | |
| 3970 rb.width -= 2 * shadow_thickness; | |
| 3971 } | |
| 3972 | |
| 3973 Dynarr_add (db->runes, rb); | |
| 3974 return; | |
| 3975 } | |
| 3976 | |
| 3977 /* !!#### not right; needs to compute the max height of | |
| 3978 all the charsets */ | |
| 3979 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); | |
| 3980 | |
| 3981 dl->ascent = XFONT_INSTANCE (font_inst)->ascent; | |
| 3982 dl->descent = XFONT_INSTANCE (font_inst)->descent; | |
| 3983 | |
| 3984 min_pixpos = dl->bounds.left_out; | |
| 3985 max_pixpos = dl->bounds.right_out; | |
| 3986 | |
| 3987 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
| 3988 { | |
| 3989 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
| 3990 | |
| 3991 ypos_adj = shadow_thickness; | |
| 3992 min_pixpos += shadow_thickness; | |
| 3993 max_pixpos -= shadow_thickness; | |
| 3994 } | |
| 3995 else | |
| 3996 ypos_adj = 0; | |
| 3997 | |
| 3998 generate_formatted_string_db (b->modeline_format, | |
| 3999 b->generated_modeline_string, w, dl, db, | |
| 4000 MODELINE_INDEX, min_pixpos, max_pixpos, type); | |
| 4001 | |
| 4002 /* The modeline is at the bottom of the gutters. We have to wait to | |
| 4003 set this until we've generated the modeline in order to account | |
| 4004 for any embedded faces. */ | |
| 4005 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj; | |
| 4006 } | |
| 4007 | |
| 4008 static Charcount | |
| 867 | 4009 add_string_to_fstring_db_runes (pos_data *data, const Ibyte *str, |
| 4187 | 4010 Charcount pos, Charcount min_pos, |
| 771 | 4011 Charcount max_pos) |
| 428 | 4012 { |
| 4013 /* This function has been Mule-ized. */ | |
| 4014 Charcount end; | |
| 867 | 4015 const Ibyte *cur_pos = str; |
| 428 | 4016 struct display_block *db = data->db; |
| 4017 | |
| 4018 data->blank_width = space_width (XWINDOW (data->window)); | |
| 4019 while (Dynarr_length (db->runes) < pos) | |
| 4020 add_blank_rune (data, NULL, 0); | |
| 4021 | |
| 4022 end = (Dynarr_length (db->runes) + | |
| 4970 | 4023 bytecount_to_charcount (str, qxestrlen (str))); |
| 428 | 4024 if (max_pos != -1) |
| 4025 end = min (max_pos, end); | |
| 4026 | |
| 4027 while (pos < end && *cur_pos) | |
| 4028 { | |
| 867 | 4029 const Ibyte *old_cur_pos = cur_pos; |
| 428 | 4030 int succeeded; |
| 4031 | |
| 867 | 4032 data->ch = itext_ichar (cur_pos); |
| 4033 succeeded = (add_ichar_rune (data) != ADD_FAILED); | |
| 4034 INC_IBYTEPTR (cur_pos); | |
| 428 | 4035 if (succeeded) |
| 4187 | 4036 { |
| 4037 pos++; | |
| 4038 data->modeline_charpos++; | |
| 4039 data->bytepos += cur_pos - old_cur_pos; | |
| 4040 } | |
| 428 | 4041 } |
| 4042 | |
| 4043 while (Dynarr_length (db->runes) < min_pos && | |
| 4187 | 4044 (data->pixpos + data->blank_width <= data->max_pixpos)) |
| 428 | 4045 add_blank_rune (data, NULL, 0); |
| 4046 | |
| 4047 return Dynarr_length (db->runes); | |
| 4048 } | |
| 4049 | |
| 4050 /* #### Urk! Should also handle begin-glyphs and end-glyphs in | |
| 4051 modeline extents. */ | |
| 4052 static Charcount | |
| 4053 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, | |
| 4187 | 4054 Charcount pos, Charcount UNUSED (min_pos), |
| 438 | 4055 Charcount max_pos, Lisp_Object extent) |
| 428 | 4056 { |
| 4057 /* This function has been Mule-ized. */ | |
| 4058 Charcount end; | |
| 4059 struct display_block *db = data->db; | |
| 4060 struct glyph_block gb; | |
| 4061 | |
| 4062 data->blank_width = space_width (XWINDOW (data->window)); | |
| 4063 while (Dynarr_length (db->runes) < pos) | |
| 4064 add_blank_rune (data, NULL, 0); | |
| 4065 | |
| 4066 end = Dynarr_length (db->runes) + 1; | |
| 4067 if (max_pos != -1) | |
| 4068 end = min (max_pos, end); | |
| 4069 | |
| 4070 gb.glyph = glyph; | |
| 438 | 4071 gb.extent = extent; |
| 428 | 4072 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); |
| 4073 pos++; | |
| 4074 | |
| 4075 while (Dynarr_length (db->runes) < pos && | |
| 4187 | 4076 (data->pixpos + data->blank_width <= data->max_pixpos)) |
| 428 | 4077 add_blank_rune (data, NULL, 0); |
| 4078 | |
| 4079 return Dynarr_length (db->runes); | |
| 4080 } | |
| 4081 | |
| 4082 /* If max_pos is == -1, it is considered to be infinite. The same is | |
| 4083 true of max_pixsize. */ | |
| 4084 #define SET_CURRENT_MODE_CHARS_PIXSIZE \ | |
| 4085 if (Dynarr_length (data->db->runes)) \ | |
| 4967 | 4086 cur_pixsize = data->pixpos - Dynarr_begin (data->db->runes)->xpos; \ |
| 428 | 4087 else \ |
| 4088 cur_pixsize = 0; | |
| 4089 | |
| 4090 /* Note that this function does "positions" in terms of characters and | |
| 4091 not in terms of columns. This is necessary to make the formatting | |
| 4092 work correctly when proportional width fonts are used in the | |
| 4093 modeline. */ | |
| 4094 static Charcount | |
| 4095 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, | |
| 4187 | 4096 Charcount min_pos, Charcount max_pos, |
| 4097 Lisp_Object elt, int depth, int max_pixsize, | |
| 4098 face_index findex, int type, Charcount *offset, | |
| 438 | 4099 Lisp_Object cur_ext) |
| 428 | 4100 { |
| 4101 /* This function has been Mule-ized. */ | |
| 4102 /* #### The other losing things in this function are: | |
| 4103 | |
| 4104 -- C zero-terminated-string lossage. | |
| 4105 -- Non-printable characters should be converted into something | |
| 4187 | 4106 appropriate (e.g. ^F) instead of blindly being printed anyway. |
| 428 | 4107 */ |
| 4108 | |
| 4109 tail_recurse: | |
| 4110 if (depth > 10) | |
| 4111 goto invalid; | |
| 4112 | |
| 4113 depth++; | |
| 4114 | |
| 4115 if (STRINGP (elt)) | |
| 4116 { | |
| 4117 /* A string. Add to the display line and check for %-constructs | |
| 4187 | 4118 within it. */ |
| 428 | 4119 |
| 2552 | 4120 Ibyte *this_str = XSTRING_DATA (elt); |
| 4121 | |
| 4122 while ((pos < max_pos || max_pos == -1) && *this_str) | |
| 4187 | 4123 { |
| 4124 Ibyte *last = this_str; | |
| 4125 | |
| 4126 while (*this_str && *this_str != '%') | |
| 4127 this_str++; | |
| 4128 | |
| 4129 if (this_str != last) | |
| 4130 { | |
| 4131 /* No %-construct */ | |
| 4132 Charcount size = | |
| 2552 | 4133 bytecount_to_charcount (last, this_str - last); |
| 438 | 4134 |
| 4135 if (size <= *offset) | |
| 4136 *offset -= size; | |
| 4137 else | |
| 4138 { | |
| 4139 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset : | |
| 4140 min (pos + size - *offset, max_pos)); | |
| 867 | 4141 const Ibyte *tmp_last = itext_n_addr (last, *offset); |
| 438 | 4142 |
| 4143 pos = add_string_to_fstring_db_runes (data, tmp_last, | |
| 4144 pos, pos, tmp_max); | |
| 4145 *offset = 0; | |
| 4146 } | |
| 4187 | 4147 } |
| 4148 else /* *this_str == '%' */ | |
| 4149 { | |
| 4150 Charcount spec_width = 0; | |
| 4151 | |
| 4152 this_str++; /* skip over '%' */ | |
| 4153 | |
| 4154 /* We can't allow -ve args due to the "%-" construct. | |
| 4155 * Argument specifies minwidth but not maxwidth | |
| 4156 * (maxwidth can be specified by | |
| 4157 * (<negative-number> . <stuff>) modeline elements) | |
| 4158 */ | |
| 4159 while (isdigit (*this_str)) | |
| 4160 { | |
| 4161 spec_width = spec_width * 10 + (*this_str - '0'); | |
| 4162 this_str++; | |
| 4163 } | |
| 4164 spec_width += pos; | |
| 4165 | |
| 4166 if (*this_str == 'M') | |
| 4167 { | |
| 4168 pos = generate_fstring_runes (w, data, pos, spec_width, | |
| 4169 max_pos, Vglobal_mode_string, | |
| 4170 depth, max_pixsize, findex, | |
| 4171 type, offset, cur_ext); | |
| 4172 } | |
| 4173 else if (*this_str == '-') | |
| 4174 { | |
| 4175 Charcount num_to_add; | |
| 4176 | |
| 4177 if (max_pixsize < 0) | |
| 4178 num_to_add = 0; | |
| 4179 else if (max_pos != -1) | |
| 4180 num_to_add = max_pos - pos; | |
| 4181 else | |
| 4182 { | |
| 4183 int cur_pixsize; | |
| 4184 int dash_pixsize; | |
| 4185 Ibyte ch = '-'; | |
| 4186 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
| 4187 | |
| 4188 dash_pixsize = | |
|
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4189 redisplay_window_text_width_string |
|
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4190 (w, findex, &ch, Qnil, 0, 1); |
| 4187 | 4191 |
| 4192 if (dash_pixsize == 0) | |
| 3094 | 4193 num_to_add = 0; |
| 4194 else { | |
| 4195 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize; | |
| 4196 num_to_add++; | |
| 4197 } | |
| 4187 | 4198 } |
| 4199 | |
| 4200 while (num_to_add--) | |
| 4201 pos = add_string_to_fstring_db_runes | |
| 4202 (data, (const Ibyte *) "-", pos, pos, max_pos); | |
| 4203 } | |
| 4204 else if (*this_str != 0) | |
| 4205 { | |
| 4206 Ichar ch = itext_ichar (this_str); | |
| 4207 Ibyte *str; | |
| 438 | 4208 Charcount size; |
| 4209 | |
| 4187 | 4210 decode_mode_spec (w, ch, type); |
| 4211 | |
| 4967 | 4212 str = Dynarr_begin (mode_spec_ibyte_string); |
| 438 | 4213 size = bytecount_to_charcount |
| 4214 /* Skip the null character added by `decode_mode_spec' */ | |
| 867 | 4215 (str, Dynarr_length (mode_spec_ibyte_string)) - 1; |
| 438 | 4216 |
| 4217 if (size <= *offset) | |
| 4218 *offset -= size; | |
| 4219 else | |
| 4220 { | |
| 867 | 4221 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
| 438 | 4222 |
| 440 | 4223 /* #### NOTE: I don't understand why a tmp_max is not |
| 438 | 4224 computed and used here as in the plain string case |
| 4225 above. -- dv */ | |
| 4226 pos = add_string_to_fstring_db_runes (data, tmp_str, | |
| 4227 pos, pos, | |
| 4228 max_pos); | |
| 4229 *offset = 0; | |
| 4230 } | |
| 4187 | 4231 } |
| 4232 | |
| 4233 /* NOT this_str++. There could be any sort of character at | |
| 4234 the current position. */ | |
| 4235 INC_IBYTEPTR (this_str); | |
| 4236 } | |
| 4237 | |
| 4238 if (max_pixsize > 0) | |
| 4239 { | |
| 4240 int cur_pixsize; | |
| 4241 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
| 4242 | |
| 4243 if (cur_pixsize >= max_pixsize) | |
| 4244 break; | |
| 4245 } | |
| 4246 } | |
| 428 | 4247 } |
| 4248 else if (SYMBOLP (elt)) | |
| 4249 { | |
| 4250 /* A symbol: process the value of the symbol recursively | |
| 4187 | 4251 as if it appeared here directly. */ |
| 428 | 4252 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); |
| 4253 | |
| 4254 if (!UNBOUNDP (tem)) | |
| 4187 | 4255 { |
| 438 | 4256 /* If value is a string, output that string literally: |
| 4187 | 4257 don't check for % within it. */ |
| 4258 if (STRINGP (tem)) | |
| 4259 { | |
| 867 | 4260 Ibyte *str = XSTRING_DATA (tem); |
| 826 | 4261 Charcount size = string_char_length (tem); |
| 438 | 4262 |
| 4263 if (size <= *offset) | |
| 4264 *offset -= size; | |
| 4265 else | |
| 4266 { | |
| 867 | 4267 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
| 438 | 4268 |
| 440 | 4269 /* #### NOTE: I don't understand why a tmp_max is not |
| 438 | 4270 computed and used here as in the plain string case |
| 4271 above. -- dv */ | |
| 4272 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
| 4273 min_pos, max_pos); | |
| 4274 *offset = 0; | |
| 4275 } | |
| 4187 | 4276 } |
| 4277 /* Give up right away for nil or t. */ | |
| 4278 else if (!EQ (tem, elt)) | |
| 4279 { | |
| 4280 elt = tem; | |
| 4281 goto tail_recurse; | |
| 4282 } | |
| 4283 } | |
| 428 | 4284 } |
| 4285 else if (GENERIC_SPECIFIERP (elt)) | |
| 4286 { | |
| 4287 Lisp_Object window, tem; | |
| 793 | 4288 window = wrap_window (w); |
| 428 | 4289 tem = specifier_instance_no_quit (elt, Qunbound, window, |
| 793 | 4290 ERROR_ME_DEBUG_WARN, 0, Qzero); |
| 428 | 4291 if (!UNBOUNDP (tem)) |
| 4292 { | |
| 4293 elt = tem; | |
| 4294 goto tail_recurse; | |
| 4295 } | |
| 4296 } | |
| 4297 else if (CONSP (elt)) | |
| 4298 { | |
| 4299 /* A cons cell: four distinct cases. | |
| 438 | 4300 * - If first element is a string or a cons, process all the elements |
| 4301 * and effectively concatenate them. | |
| 4302 * - If first element is a negative number, truncate displaying cdr to | |
| 4303 * at most that many characters. If positive, pad (with spaces) | |
| 4304 * to at least that many characters. | |
| 771 | 4305 * - If first element is another symbol or a boolean specifier, process |
| 4306 * the cadr or caddr recursively according to whether the symbol's | |
| 4307 * value or specifier's instance is non-nil or nil. | |
| 4308 * - If first element is , process the cadr or caddr | |
| 4309 * recursively according to whether the instance of the specifier in | |
| 4310 * the modeline's window is non-nil or nil. | |
| 442 | 4311 * - If first element is an extent, process the cdr recursively |
| 4312 * and handle the extent's face. | |
| 428 | 4313 */ |
| 438 | 4314 |
| 428 | 4315 Lisp_Object car, tem; |
| 4316 | |
| 4317 car = XCAR (elt); | |
| 771 | 4318 if (SYMBOLP (car) || BOOLEAN_SPECIFIERP (car)) |
| 438 | 4319 { |
| 4320 elt = XCDR (elt); | |
| 4321 if (!CONSP (elt)) | |
| 4322 goto invalid; | |
| 4323 | |
| 771 | 4324 if (SYMBOLP (car)) |
| 4325 tem = symbol_value_in_buffer (car, w->buffer); | |
| 4326 else | |
| 4327 tem = specifier_instance_no_quit (car, Qunbound, wrap_window (w), | |
| 793 | 4328 ERROR_ME_DEBUG_WARN, 0, Qzero); |
| 438 | 4329 /* elt is now the cdr, and we know it is a cons cell. |
| 4330 Use its car if CAR has a non-nil value. */ | |
| 771 | 4331 if (!UNBOUNDP (tem) && !NILP (tem)) |
| 438 | 4332 { |
| 771 | 4333 elt = XCAR (elt); |
| 4334 goto tail_recurse; | |
| 438 | 4335 } |
| 771 | 4336 /* Symbol's value or specifier's instance is nil or unbound |
| 438 | 4337 * Get the cddr of the original list |
| 4338 * and if possible find the caddr and use that. | |
| 4339 */ | |
| 4340 elt = XCDR (elt); | |
| 4341 if (NILP (elt)) | |
| 4342 ; | |
| 4343 else if (!CONSP (elt)) | |
| 4344 goto invalid; | |
| 4345 else | |
| 4346 { | |
| 4347 elt = XCAR (elt); | |
| 4348 goto tail_recurse; | |
| 4349 } | |
| 4350 } | |
| 428 | 4351 else if (INTP (car)) |
| 4187 | 4352 { |
| 4353 Charcount lim = XINT (car); | |
| 4354 | |
| 4355 elt = XCDR (elt); | |
| 4356 | |
| 4357 if (lim < 0) | |
| 4358 { | |
| 4359 /* Negative int means reduce maximum width. | |
| 4360 * DO NOT change MIN_PIXPOS here! | |
| 4361 * (20 -10 . foo) should truncate foo to 10 col | |
| 4362 * and then pad to 20. | |
| 4363 */ | |
| 4364 if (max_pos == -1) | |
| 4365 max_pos = pos - lim; | |
| 4366 else | |
| 4367 max_pos = min (max_pos, pos - lim); | |
| 4368 } | |
| 4369 else if (lim > 0) | |
| 4370 { | |
| 4371 /* Padding specified. Don't let it be more than | |
| 4372 * current maximum. | |
| 4373 */ | |
| 4374 lim += pos; | |
| 4375 if (max_pos != -1 && lim > max_pos) | |
| 4376 lim = max_pos; | |
| 4377 /* If that's more padding than already wanted, queue it. | |
| 4378 * But don't reduce padding already specified even if | |
| 4379 * that is beyond the current truncation point. | |
| 4380 */ | |
| 4381 if (lim > min_pos) | |
| 4382 min_pos = lim; | |
| 4383 } | |
| 4384 goto tail_recurse; | |
| 4385 } | |
| 428 | 4386 else if (STRINGP (car) || CONSP (car)) |
| 4187 | 4387 { |
| 4388 int limit = 50; | |
| 4389 | |
| 4390 /* LIMIT is to protect against circular lists. */ | |
| 4391 while (CONSP (elt) && --limit > 0 | |
| 4392 && (pos < max_pos || max_pos == -1)) | |
| 4393 { | |
| 4394 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
| 4395 XCAR (elt), depth, max_pixsize, | |
| 438 | 4396 findex, type, offset, cur_ext); |
| 4187 | 4397 elt = XCDR (elt); |
| 4398 } | |
| 4399 } | |
| 428 | 4400 else if (EXTENTP (car)) |
| 4187 | 4401 { |
| 4402 struct extent *ext = XEXTENT (car); | |
| 4403 | |
| 4404 if (EXTENT_LIVE_P (ext)) | |
| 4405 { | |
| 4406 face_index old_findex = data->findex; | |
| 4407 Lisp_Object face; | |
| 4408 Lisp_Object font_inst; | |
| 4409 face_index new_findex; | |
| 4410 Bytecount start = data->bytepos; | |
| 4411 | |
| 4412 face = extent_face (ext); | |
| 4413 if (FACEP (face)) | |
| 4414 { | |
| 4415 /* #### needs to merge faces, sigh */ | |
| 4416 /* #### needs to handle list of faces */ | |
| 4417 new_findex = get_builtin_face_cache_index (w, face); | |
| 4418 /* !!#### not right; needs to compute the max height of | |
| 4419 all the charsets */ | |
| 4420 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex, | |
| 4421 Vcharset_ascii); | |
| 4422 | |
| 4423 data->dl->ascent = max (data->dl->ascent, | |
| 4424 XFONT_INSTANCE (font_inst)->ascent); | |
| 4425 data->dl->descent = max (data->dl->descent, | |
| 4426 XFONT_INSTANCE (font_inst)-> | |
| 4427 descent); | |
| 4428 } | |
| 4429 else | |
| 4430 new_findex = old_findex; | |
| 4431 | |
| 4432 data->findex = new_findex; | |
| 4433 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
| 4434 XCDR (elt), depth - 1, | |
| 438 | 4435 max_pixsize, new_findex, type, |
| 4436 offset, car); | |
| 4187 | 4437 data->findex = old_findex; |
| 4438 Dynarr_add (formatted_string_extent_dynarr, ext); | |
| 4439 Dynarr_add (formatted_string_extent_start_dynarr, start); | |
| 4440 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); | |
| 4441 } | |
| 4442 } | |
| 428 | 4443 } |
| 4444 else if (GLYPHP (elt)) | |
| 4445 { | |
| 438 | 4446 /* Glyphs are considered as one character with respect to the modeline |
| 4447 horizontal scrolling facility. -- dv */ | |
| 4448 if (*offset > 0) | |
| 4449 *offset -= 1; | |
| 4450 else | |
| 4451 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos, | |
| 4452 cur_ext); | |
| 428 | 4453 } |
| 4454 else | |
| 4455 { | |
| 4456 invalid: | |
| 438 | 4457 { |
| 4970 | 4458 const Ascbyte *str = GETTEXT ("*invalid*"); |
| 438 | 4459 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */ |
| 4460 | |
| 4461 if (size <= *offset) | |
| 4462 *offset -= size; | |
| 4463 else | |
| 4464 { | |
| 867 | 4465 const Ibyte *tmp_str = |
| 4466 itext_n_addr ((const Ibyte *) str, *offset); | |
| 438 | 4467 |
| 440 | 4468 /* #### NOTE: I don't understand why a tmp_max is not computed and |
| 438 | 4469 used here as in the plain string case above. -- dv */ |
| 4470 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
| 4471 min_pos, max_pos); | |
| 4472 *offset = 0; | |
| 4473 } | |
| 4474 } | |
| 428 | 4475 } |
| 4476 | |
| 4477 if (min_pos > pos) | |
| 4478 { | |
| 867 | 4479 add_string_to_fstring_db_runes (data, (const Ibyte *) "", pos, |
| 438 | 4480 min_pos, -1); |
| 428 | 4481 } |
| 4482 | |
| 4483 return pos; | |
| 4484 } | |
| 4485 | |
| 4486 /* Update just the modeline. Assumes the desired display structs. If | |
| 4487 they do not have a modeline block, it does nothing. */ | |
| 4488 static void | |
| 4489 regenerate_modeline (struct window *w) | |
| 4490 { | |
| 4491 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP); | |
| 4492 | |
| 4967 | 4493 if (!Dynarr_length (dla) || !Dynarr_begin (dla)->modeline) |
| 428 | 4494 return; |
| 4495 else | |
| 4496 { | |
| 4967 | 4497 generate_modeline (w, Dynarr_begin (dla), DESIRED_DISP); |
| 428 | 4498 redisplay_update_line (w, 0, 0, 0); |
| 4499 } | |
| 4500 } | |
| 4501 | |
| 4502 /* Make sure that modeline display line is present in the given | |
| 4503 display structs if the window has a modeline and update that | |
| 4504 line. Returns true if a modeline was needed. */ | |
| 4505 static int | |
| 4506 ensure_modeline_generated (struct window *w, int type) | |
| 4507 { | |
| 4508 int need_modeline; | |
| 4509 | |
| 4510 /* minibuffer windows don't have modelines */ | |
| 4511 if (MINI_WINDOW_P (w)) | |
| 4512 need_modeline = 0; | |
| 4513 /* windows which haven't had it turned off do */ | |
| 4514 else if (WINDOW_HAS_MODELINE_P (w)) | |
| 4515 need_modeline = 1; | |
| 4516 /* windows which have it turned off don't have a divider if there is | |
| 4517 a horizontal scrollbar */ | |
| 4518 else if (window_scrollbar_height (w)) | |
| 4519 need_modeline = 0; | |
| 4520 /* and in this case there is none */ | |
| 4521 else | |
| 4522 need_modeline = 1; | |
| 4523 | |
| 4524 if (need_modeline) | |
| 4525 { | |
| 4526 display_line_dynarr *dla; | |
| 4527 | |
| 4528 dla = window_display_lines (w, type); | |
| 4529 | |
| 4530 /* We don't care if there is a display line which is not | |
| 4187 | 4531 currently a modeline because it is definitely going to become |
| 4532 one if we have gotten to this point. */ | |
| 428 | 4533 if (Dynarr_length (dla) == 0) |
| 4534 { | |
| 4535 if (Dynarr_largest (dla) > 0) | |
| 5038 | 4536 Dynarr_incrementr (dla); |
| 428 | 4537 else |
| 4538 { | |
| 4539 struct display_line modeline; | |
| 4207 | 4540 |
| 4541 DISPLAY_LINE_INIT (modeline); | |
| 428 | 4542 Dynarr_add (dla, modeline); |
| 4543 } | |
| 4544 } | |
| 4545 | |
| 4546 /* If we're adding a new place marker go ahead and generate the | |
| 4187 | 4547 modeline so that it is available for use by |
| 4548 window_modeline_height. */ | |
| 4967 | 4549 generate_modeline (w, Dynarr_begin (dla), type); |
| 428 | 4550 } |
| 4551 | |
| 4552 return need_modeline; | |
| 4553 } | |
| 4554 | |
| 4555 /* #### Kludge or not a kludge. I tend towards the former. */ | |
| 4556 int | |
| 4557 real_current_modeline_height (struct window *w) | |
| 4558 { | |
| 4559 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer); | |
| 4560 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer); | |
| 4561 | |
| 4562 if (ensure_modeline_generated (w, CMOTION_DISP)) | |
| 4563 { | |
| 4564 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP); | |
| 4565 | |
| 4566 if (Dynarr_length (dla)) | |
| 4567 { | |
| 4967 | 4568 if (Dynarr_begin (dla)->modeline) |
| 4569 return (Dynarr_begin (dla)->ascent + | |
| 4570 Dynarr_begin (dla)->descent); | |
| 428 | 4571 } |
| 4572 } | |
| 4573 return 0; | |
| 4574 } | |
| 4575 | |
| 4576 | |
| 4577 /***************************************************************************/ | |
| 819 | 4578 /* */ |
| 826 | 4579 /* displayable string routines */ |
| 819 | 4580 /* */ |
| 428 | 4581 /***************************************************************************/ |
| 4582 | |
| 4583 /* Given a position for a string in a window, ensure that the given | |
| 4584 display line DL accurately represents the text on a line starting | |
| 4585 at the given position. | |
| 4586 | |
| 4587 Yes, this is duplicating the code of create_text_block, but it | |
| 4588 looked just too hard to change create_text_block to handle strings | |
| 4589 *and* buffers. We already make a distinction between the two | |
| 4590 elsewhere in the code so I think unifying them would require a | |
| 4591 complete MULE rewrite. Besides, the other distinction is that these | |
| 4592 functions cover text that the user *cannot edit* so we can remove | |
| 4593 everything to do with cursors, minibuffers etc. Eventually the | |
| 4594 modeline routines should be modified to use this code as it copes | |
| 4595 with many more types of display situation. */ | |
| 4596 | |
| 665 | 4597 static Charbpos |
| 428 | 4598 create_string_text_block (struct window *w, Lisp_Object disp_string, |
| 4599 struct display_line *dl, | |
| 826 | 4600 Charcount start_pos, |
| 428 | 4601 prop_block_dynarr **prop, |
| 4602 face_index default_face) | |
| 4603 { | |
| 4604 struct frame *f = XFRAME (w->frame); | |
| 4605 /* Note that a lot of the buffer controlled stuff has been left in | |
| 4606 because you might well want to make use of it (selective display | |
| 4607 etc), its just the buffer text that we do not use. However, it | |
| 4608 seems to be possible for buffer to be nil sometimes so protect | |
| 4609 against this case. */ | |
| 4610 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; | |
| 4611 struct device *d = XDEVICE (f->device); | |
| 4612 | |
| 4613 /* we're working with these a lot so precalculate them */ | |
| 4614 Bytecount slen = XSTRING_LENGTH (disp_string); | |
| 826 | 4615 Bytecount byte_string_zv = slen; |
| 4616 Bytecount byte_start_pos = string_index_char_to_byte (disp_string, start_pos); | |
| 428 | 4617 |
| 4618 pos_data data; | |
| 4619 | |
| 4620 int truncate_win = b ? window_truncation_on (w) : 0; | |
| 4621 | |
| 442 | 4622 /* We're going to ditch selective display for static text, it's an |
| 4623 FSF thing and invisible extents are the way to go here. | |
| 4624 Implementing it also relies on a number of buffer-specific | |
| 428 | 4625 functions that we don't have the luxury of being able to use |
| 4626 here. */ | |
| 4627 | |
| 4628 /* The variable ctl-arrow allows the user to specify what characters | |
| 4629 can actually be displayed and which octal should be used for. | |
| 4630 #### This variable should probably have some rethought done to | |
| 4631 it. | |
| 4632 | |
| 4633 #### It would also be really nice if you could specify that | |
| 4634 the characters come out in hex instead of in octal. Mule | |
| 4635 does that by adding a ctl-hexa variable similar to ctl-arrow, | |
| 4636 but that's bogus -- we need a more general solution. I | |
| 4637 think you need to extend the concept of display tables | |
| 4638 into a more general conversion mechanism. Ideally you | |
| 4639 could specify a Lisp function that converts characters, | |
| 4640 but this violates the Second Golden Rule and besides would | |
| 4641 make things way way way way slow. | |
| 4642 | |
| 4643 So instead, we extend the display-table concept, which was | |
| 4644 historically limited to 256-byte vectors, to one of the | |
| 4645 following: | |
| 4646 | |
| 4647 a) A 256-entry vector, for backward compatibility; | |
| 4648 b) char-table, mapping characters to values; | |
| 4649 c) range-table, mapping ranges of characters to values; | |
| 4650 d) a list of the above. | |
| 4651 | |
| 4652 The (d) option allows you to specify multiple display tables | |
| 4653 instead of just one. Each display table can specify conversions | |
| 4654 for some characters and leave others unchanged. The way the | |
| 4655 character gets displayed is determined by the first display table | |
| 4656 with a binding for that character. This way, you could call a | |
| 4657 function `enable-hex-display' that adds a hex display-table to | |
| 4658 the list of display tables for the current buffer. | |
| 4659 | |
| 4660 #### ...not yet implemented... Also, we extend the concept of | |
| 4661 "mapping" to include a printf-like spec. Thus you can make all | |
| 4662 extended characters show up as hex with a display table like | |
| 4663 this: | |
| 4664 | |
| 4187 | 4665 #s(range-table data ((256 524288) (format "%x"))) |
| 428 | 4666 |
| 4667 Since more than one display table is possible, you have | |
| 4668 great flexibility in mapping ranges of characters. */ | |
| 867 | 4669 Ichar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
| 428 | 4670 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
| 4671 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
| 4672 ? 255 : 160)) : 255; | |
| 4673 | |
| 4674 Lisp_Object face_dt, window_dt; | |
| 4675 | |
| 4676 /* The text display block for this display line. */ | |
| 4677 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 4678 | |
| 4679 /* The first time through the main loop we need to force the glyph | |
| 4680 data to be updated. */ | |
| 4681 int initial = 1; | |
| 4682 | |
| 4683 /* Apparently the new extent_fragment_update returns an end position | |
| 4684 equal to the position passed in if there are no more runs to be | |
| 4685 displayed. */ | |
| 4686 int no_more_frags = 0; | |
| 4687 | |
| 4688 dl->used_prop_data = 0; | |
| 4689 dl->num_chars = 0; | |
| 442 | 4690 dl->line_continuation = 0; |
| 428 | 4691 |
| 4187 | 4692 /* Set up faces to use for clearing areas, used by output_display_line. */ |
| 428 | 4693 dl->default_findex = default_face; |
| 4187 | 4694 if (default_face > DEFAULT_INDEX) |
| 428 | 4695 { |
| 4696 dl->left_margin_findex = default_face; | |
| 4697 dl->right_margin_findex = default_face; | |
| 4698 } | |
| 4699 else | |
| 4700 { | |
| 434 | 4701 dl->left_margin_findex = |
| 428 | 4702 get_builtin_face_cache_index (w, Vleft_margin_face); |
| 434 | 4703 dl->right_margin_findex = |
| 428 | 4704 get_builtin_face_cache_index (w, Vright_margin_face); |
| 4705 } | |
| 4706 | |
| 4707 xzero (data); | |
| 4708 data.ef = extent_fragment_new (disp_string, f); | |
| 4709 | |
| 4710 /* These values are used by all of the rune addition routines. We add | |
| 4711 them to this structure for ease of passing. */ | |
| 4712 data.d = d; | |
| 793 | 4713 data.window = wrap_window (w); |
| 428 | 4714 data.db = db; |
| 4715 data.dl = dl; | |
| 4716 | |
| 826 | 4717 data.byte_charpos = byte_start_pos; |
| 428 | 4718 data.pixpos = dl->bounds.left_in; |
| 4719 data.last_charset = Qunbound; | |
| 4720 data.last_findex = default_face; | |
| 4721 data.result_str = Qnil; | |
| 4722 data.string = disp_string; | |
| 4723 | |
| 4724 /* Set the right boundary adjusting it to take into account any end | |
| 4725 glyph. Save the width of the end glyph for later use. */ | |
| 4726 data.max_pixpos = dl->bounds.right_in; | |
| 819 | 4727 data.max_pixpos -= data.end_glyph_width; |
| 428 | 4728 |
| 4729 data.cursor_type = NO_CURSOR; | |
| 4730 data.cursor_x = -1; | |
| 4731 | |
| 4732 data.start_col = 0; | |
| 4733 /* I don't think we want this, string areas should not scroll with | |
| 434 | 4734 the window |
| 428 | 4735 data.start_col = w->hscroll; |
| 826 | 4736 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
| 428 | 4737 */ |
| 826 | 4738 data.byte_start_col_enabled = 0; |
| 428 | 4739 data.hscroll_glyph_width_adjust = 0; |
| 4740 | |
| 4741 /* We regenerate the line from the very beginning. */ | |
| 4742 Dynarr_reset (db->runes); | |
| 4743 | |
| 4744 /* Why is this less than or equal and not just less than? If the | |
| 4745 starting position is already equal to the maximum we can't add | |
| 4746 anything else, right? Wrong. We might still have a newline to | |
| 4747 add. A newline can use the room allocated for an end glyph since | |
| 4748 if we add it we know we aren't going to be adding any end | |
| 4749 glyph. */ | |
| 4750 | |
| 4751 /* #### Chuck -- I think this condition should be while (1). | |
| 4752 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
| 4753 and the begin-glyph ends exactly at the end of the window, the | |
| 4754 end-glyph and text might not be displayed. while (1) ensures | |
| 4755 that the loop terminates only when either (a) there is | |
| 4756 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
| 4757 | |
| 4758 #### Also I think you need to ensure that the operation | |
| 4759 "add begin glyphs; add end glyphs; add text" is atomic and | |
| 4760 can't get interrupted in the middle. If you run off the end | |
| 4761 of the line during that operation, then you keep accumulating | |
| 4762 propagation data until you're done. Otherwise, if the (e.g.) | |
| 4763 there's a begin glyph at a particular position and attempting | |
| 4764 to display that glyph results in window-end being hit and | |
| 4765 propagation data being generated, then the character at that | |
| 4766 position won't be displayed. | |
| 4767 | |
| 4768 #### See also the comment after the end of this loop, below. | |
| 4769 */ | |
| 4770 while (data.pixpos <= data.max_pixpos) | |
| 4771 { | |
| 4772 /* #### This check probably should not be necessary. */ | |
| 826 | 4773 if (data.byte_charpos > byte_string_zv) |
| 428 | 4774 { |
| 4775 /* #### urk! More of this lossage! */ | |
| 826 | 4776 data.byte_charpos--; |
| 428 | 4777 goto done; |
| 4778 } | |
| 4779 | |
| 4780 /* Check for face changes. */ | |
| 826 | 4781 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
| 428 | 4782 { |
| 819 | 4783 Lisp_Object last_glyph = Qnil; |
| 4784 /* Deal with clipped glyphs that we have already displayed. */ | |
| 4967 | 4785 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
| 4786 { | |
| 4787 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
| 819 | 4788 Dynarr_free (*prop); |
| 4789 *prop = 0; | |
| 4790 } | |
| 428 | 4791 /* Now compute the face and begin/end-glyph information. */ |
| 4792 data.findex = | |
| 793 | 4793 /* Remember that the extent-fragment routines deal in |
| 4187 | 4794 Bytexpos's. */ |
| 826 | 4795 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
| 428 | 4796 /* This is somewhat cheesy but the alternative is to |
| 4187 | 4797 propagate default_face into extent_fragment_update. */ |
| 428 | 4798 if (data.findex == DEFAULT_INDEX) |
| 4799 data.findex = default_face; | |
| 4800 | |
| 4801 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
| 4802 | |
| 826 | 4803 if (data.byte_charpos == data.ef->end) |
| 428 | 4804 no_more_frags = 1; |
| 4805 } | |
| 4806 initial = 0; | |
| 4807 | |
| 4808 /* Determine what is next to be displayed. We first handle any | |
| 4187 | 4809 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
| 4810 display then we determine what to do based on the character at the | |
| 4811 current buffer position. */ | |
| 428 | 4812 |
| 4813 /* If the current position is covered by an invisible extent, do | |
| 4187 | 4814 nothing (except maybe add some ellipses). |
| 428 | 4815 |
| 4816 #### The behavior of begin and end-glyphs at the edge of an | |
| 4817 invisible extent should be investigated further. This is | |
| 4818 fairly low priority though. */ | |
| 4819 if (data.ef->invisible) | |
| 4820 { | |
| 4821 /* #### Chuck, perhaps you could look at this code? I don't | |
| 4822 really know what I'm doing. */ | |
| 4823 if (*prop) | |
| 4824 { | |
| 4825 Dynarr_free (*prop); | |
| 4826 *prop = 0; | |
| 4827 } | |
| 4828 | |
| 4829 /* The extent fragment code only sets this when we should | |
| 4830 really display the ellipses. It makes sure the ellipses | |
| 4831 don't get displayed more than once in a row. */ | |
| 4832 if (data.ef->invisible_ellipses) | |
| 4833 { | |
| 4834 struct glyph_block gb; | |
| 4835 | |
| 4836 data.ef->invisible_ellipses_already_displayed = 1; | |
| 4837 data.ef->invisible_ellipses = 0; | |
| 4838 gb.extent = Qnil; | |
| 4839 gb.glyph = Vinvisible_text_glyph; | |
| 4840 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
| 4841 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
| 4842 /* Perhaps they shouldn't propagate if the very next thing | |
| 4843 is to display a newline (for compatibility with | |
| 4844 selective-display-ellipses)? Maybe that's too | |
| 4845 abstruse. */ | |
| 4846 if (*prop) | |
| 4847 goto done; | |
| 4848 } | |
| 4849 | |
| 638 | 4850 /* #### What if we're dealing with a display table? */ |
| 428 | 4851 if (data.start_col) |
| 4852 data.start_col--; | |
| 4853 | |
| 826 | 4854 if (data.byte_charpos == byte_string_zv) |
| 428 | 4855 goto done; |
| 4856 else | |
| 826 | 4857 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
| 428 | 4858 } |
| 4859 | |
| 4860 /* If there is propagation data, then it represents the current | |
| 4187 | 4861 buffer position being displayed. Add them and advance the |
| 4862 position counter. This might also add the minibuffer | |
| 4863 prompt. */ | |
| 428 | 4864 else if (*prop) |
| 4865 { | |
| 4866 dl->used_prop_data = 1; | |
| 4867 *prop = add_propagation_runes (prop, &data); | |
| 4868 | |
| 4869 if (*prop) | |
| 4870 goto done; /* gee, a really narrow window */ | |
| 826 | 4871 else if (data.byte_charpos == byte_string_zv) |
| 428 | 4872 goto done; |
| 826 | 4873 else if (data.byte_charpos < 0) |
| 428 | 4874 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
| 826 | 4875 data.byte_charpos = 0; |
| 428 | 4876 else |
| 826 | 4877 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
| 428 | 4878 } |
| 4879 | |
| 4880 /* If there are end glyphs, add them to the line. These are | |
| 4881 the end glyphs for the previous run of text. We add them | |
| 4882 here rather than doing them at the end of handling the | |
| 4883 previous run so that glyphs at the beginning and end of | |
| 4884 a line are handled correctly. */ | |
| 4885 else if (Dynarr_length (data.ef->end_glyphs) > 0) | |
| 4886 { | |
| 867 | 4887 data.ch = string_ichar (disp_string, data.byte_charpos); |
| 428 | 4888 *prop = add_glyph_runes (&data, END_GLYPHS); |
| 819 | 4889 |
| 4890 if (*prop) { | |
| 428 | 4891 goto done; |
| 819 | 4892 } |
| 428 | 4893 } |
| 4894 | |
| 4895 /* If there are begin glyphs, add them to the line. */ | |
| 4896 else if (Dynarr_length (data.ef->begin_glyphs) > 0) | |
| 4897 { | |
| 867 | 4898 data.ch = string_ichar (disp_string, data.byte_charpos); |
| 428 | 4899 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); |
| 819 | 4900 |
| 4901 if (*prop) { | |
| 428 | 4902 goto done; |
| 819 | 4903 } |
| 428 | 4904 } |
| 4905 | |
| 4906 /* If at end-of-buffer, we've already processed begin and | |
| 4907 end-glyphs at this point and there's no text to process, | |
| 4908 so we're done. */ | |
| 826 | 4909 else if (data.byte_charpos == byte_string_zv) |
| 428 | 4910 goto done; |
| 4911 | |
| 4912 else | |
| 4913 { | |
| 4914 Lisp_Object entry = Qnil; | |
| 4915 /* Get the character at the current buffer position. */ | |
| 867 | 4916 data.ch = string_ichar (disp_string, data.byte_charpos); |
| 428 | 4917 if (!NILP (face_dt) || !NILP (window_dt)) |
| 4918 entry = display_table_entry (data.ch, face_dt, window_dt); | |
| 4919 | |
| 4920 /* If there is a display table entry for it, hand it off to | |
| 4187 | 4921 add_disp_table_entry_runes and let it worry about it. */ |
| 428 | 4922 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
| 4923 { | |
| 4924 *prop = add_disp_table_entry_runes (&data, entry); | |
| 4925 | |
| 4926 if (*prop) | |
| 4927 goto done; | |
| 4928 } | |
| 4929 | |
| 4930 /* Check if we have hit a newline character. If so, add a marker | |
| 4187 | 4931 to the line and end this loop. */ |
| 428 | 4932 else if (data.ch == '\n') |
| 4933 { | |
| 4934 /* We aren't going to be adding an end glyph so give its | |
| 4187 | 4935 space back in order to make sure that the cursor can |
| 4936 fit. */ | |
| 819 | 4937 data.max_pixpos += data.end_glyph_width; |
| 428 | 4938 goto done; |
| 4939 } | |
| 4940 | |
| 4941 /* If the current character is considered to be printable, then | |
| 4187 | 4942 just add it. */ |
| 428 | 4943 else if (data.ch >= printable_min) |
| 4944 { | |
| 867 | 4945 *prop = add_ichar_rune (&data); |
| 428 | 4946 if (*prop) |
| 4947 goto done; | |
| 4948 } | |
| 4949 | |
| 4950 /* If the current character is a tab, determine the next tab | |
| 4187 | 4951 starting position and add a blank rune which extends from the |
| 4952 current pixel position to that starting position. */ | |
| 428 | 4953 else if (data.ch == '\t') |
| 4954 { | |
| 4955 int tab_start_pixpos = data.pixpos; | |
| 4956 int next_tab_start; | |
| 4957 int char_tab_width; | |
| 4958 int prop_width = 0; | |
| 4959 | |
| 4960 if (data.start_col > 1) | |
| 4961 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); | |
| 4962 | |
| 4963 next_tab_start = | |
| 4964 next_tab_position (w, tab_start_pixpos, | |
| 4965 dl->bounds.left_in + | |
| 4966 data.hscroll_glyph_width_adjust); | |
| 4967 if (next_tab_start > data.max_pixpos) | |
| 4968 { | |
| 4969 prop_width = next_tab_start - data.max_pixpos; | |
| 4970 next_tab_start = data.max_pixpos; | |
| 4971 } | |
| 4972 data.blank_width = next_tab_start - data.pixpos; | |
| 4973 char_tab_width = | |
| 4974 (next_tab_start - tab_start_pixpos) / space_width (w); | |
| 4975 | |
| 4976 *prop = add_blank_rune (&data, w, char_tab_width); | |
| 4977 | |
| 4978 /* add_blank_rune is only supposed to be called with | |
| 819 | 4979 sizes guaranteed to fit in the available space. */ |
| 428 | 4980 assert (!(*prop)); |
| 4981 | |
| 4982 if (prop_width) | |
| 4983 { | |
| 4984 struct prop_block pb; | |
| 4985 *prop = Dynarr_new (prop_block); | |
| 4986 | |
| 4987 pb.type = PROP_BLANK; | |
| 4988 pb.data.p_blank.width = prop_width; | |
| 4989 pb.data.p_blank.findex = data.findex; | |
| 4990 Dynarr_add (*prop, pb); | |
| 4991 | |
| 4992 goto done; | |
| 4993 } | |
| 4994 } | |
| 4995 | |
| 4996 /* If character is a control character, pass it off to | |
| 4187 | 4997 add_control_char_runes. |
| 428 | 4998 |
| 4999 The is_*() routines have undefined results on | |
| 5000 arguments outside of the range [-1, 255]. (This | |
| 5001 often bites people who carelessly use `char' instead | |
| 5002 of `unsigned char'.) | |
| 5003 */ | |
| 867 | 5004 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
| 428 | 5005 { |
| 5006 *prop = add_control_char_runes (&data, b); | |
| 5007 | |
| 5008 if (*prop) | |
| 5009 goto done; | |
| 5010 } | |
| 5011 | |
| 5012 /* If the character is above the ASCII range and we have not | |
| 4187 | 5013 already handled it, then print it as an octal number. */ |
| 428 | 5014 else if (data.ch >= 0200) |
| 5015 { | |
| 5016 *prop = add_octal_runes (&data); | |
| 5017 | |
| 5018 if (*prop) | |
| 5019 goto done; | |
| 5020 } | |
| 5021 | |
| 5022 /* Assume the current character is considered to be printable, | |
| 4187 | 5023 then just add it. */ |
| 428 | 5024 else |
| 5025 { | |
| 867 | 5026 *prop = add_ichar_rune (&data); |
| 428 | 5027 if (*prop) |
| 5028 goto done; | |
| 5029 } | |
| 5030 | |
| 826 | 5031 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
| 428 | 5032 } |
| 5033 } | |
| 5034 | |
| 819 | 5035 done: |
| 428 | 5036 |
| 5037 /* Determine the starting point of the next line if we did not hit the | |
| 5038 end of the buffer. */ | |
| 826 | 5039 if (data.byte_charpos < byte_string_zv) |
| 428 | 5040 { |
| 5041 /* #### This check is not correct. If the line terminated | |
| 5042 due to a begin-glyph or end-glyph hitting window-end, then | |
| 826 | 5043 data.ch will not point to the character at data.byte_charpos. If |
| 428 | 5044 you make the two changes mentioned at the top of this loop, |
| 5045 you should be able to say '(if (*prop))'. That should also | |
| 826 | 5046 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
| 428 | 5047 check. */ |
| 5048 | |
| 5049 /* The common case is that the line ended because we hit a newline. | |
| 4187 | 5050 In that case, the next character is just the next buffer |
| 5051 position. */ | |
| 428 | 5052 if (data.ch == '\n') |
| 5053 { | |
| 826 | 5054 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
| 428 | 5055 } |
| 5056 | |
| 5057 /* Otherwise we have a buffer line which cannot fit on one display | |
| 4187 | 5058 line. */ |
| 428 | 5059 else |
| 5060 { | |
| 5061 struct glyph_block gb; | |
| 5062 struct glyph_cachel *cachel; | |
| 5063 | |
| 5064 /* If the line is to be truncated then we actually have to look | |
| 4187 | 5065 for the next newline. We also add the end-of-line glyph which |
| 5066 we know will fit because we adjusted the right border before | |
| 5067 we starting laying out the line. */ | |
| 819 | 5068 data.max_pixpos += data.end_glyph_width; |
| 428 | 5069 data.findex = default_face; |
| 5070 gb.extent = Qnil; | |
| 5071 | |
| 5072 if (truncate_win) | |
| 5073 { | |
| 826 | 5074 Bytecount byte_pos; |
| 428 | 5075 |
| 5076 /* Now find the start of the next line. */ | |
| 867 | 5077 byte_pos = byte_find_next_ichar_in_string (disp_string, '\n', |
| 826 | 5078 data.byte_charpos, 1); |
| 428 | 5079 |
| 5080 data.cursor_type = NO_CURSOR; | |
| 826 | 5081 data.byte_charpos = byte_pos; |
| 428 | 5082 gb.glyph = Vtruncation_glyph; |
| 5083 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
| 5084 } | |
| 5085 else | |
| 5086 { | |
| 5087 /* The cursor can never be on the continuation glyph. */ | |
| 5088 data.cursor_type = NO_CURSOR; | |
| 5089 | |
| 826 | 5090 /* data.byte_charpos is already at the start of the next line. */ |
| 428 | 5091 |
| 442 | 5092 dl->line_continuation = 1; |
| 428 | 5093 gb.glyph = Vcontinuation_glyph; |
| 5094 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
| 5095 } | |
| 5096 | |
| 819 | 5097 if (data.end_glyph_width) |
| 428 | 5098 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
| 5099 | |
| 826 | 5100 if (truncate_win && data.byte_charpos == byte_string_zv) |
| 428 | 5101 { |
| 867 | 5102 const Ibyte *endb = itext_n_addr (XSTRING_DATA (disp_string), |
| 826 | 5103 byte_string_zv); |
| 867 | 5104 DEC_IBYTEPTR (endb); |
| 5105 if (itext_ichar (endb) != '\n') | |
| 428 | 5106 { |
| 5107 /* #### Damn this losing shit. */ | |
| 826 | 5108 data.byte_charpos++; |
| 428 | 5109 } |
| 5110 } | |
| 5111 } | |
| 5112 } | |
| 826 | 5113 else if (data.byte_charpos == byte_string_zv) |
| 428 | 5114 { |
| 5115 /* create_text_block () adds a bogus \n marker here which screws | |
| 5116 up subwindow display. Since we never have a cursor in the | |
| 5117 gutter we can safely ignore it. */ | |
| 5118 } | |
| 5119 /* Calculate left whitespace boundary. */ | |
| 5120 { | |
| 5121 int elt = 0; | |
| 5122 | |
| 5123 /* Whitespace past a newline is considered right whitespace. */ | |
| 5124 while (elt < Dynarr_length (db->runes)) | |
| 5125 { | |
| 5126 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 5127 | |
| 5128 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
| 5129 || rb->type == RUNE_BLANK) | |
| 5130 { | |
| 5131 dl->bounds.left_white += rb->width; | |
| 5132 elt++; | |
| 5133 } | |
| 5134 else | |
| 5135 elt = Dynarr_length (db->runes); | |
| 5136 } | |
| 5137 } | |
| 5138 | |
| 5139 /* Calculate right whitespace boundary. */ | |
| 5140 { | |
| 5141 int elt = Dynarr_length (db->runes) - 1; | |
| 5142 int done = 0; | |
| 5143 | |
| 5144 while (!done && elt >= 0) | |
| 5145 { | |
| 5146 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 5147 | |
| 5148 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
| 5149 && isspace (rb->object.chr.ch)) | |
| 5150 && !rb->type == RUNE_BLANK) | |
| 5151 { | |
| 5152 dl->bounds.right_white = rb->xpos + rb->width; | |
| 5153 done = 1; | |
| 5154 } | |
| 5155 | |
| 5156 elt--; | |
| 5157 | |
| 5158 } | |
| 5159 | |
| 5160 /* The line is blank so everything is considered to be right | |
| 5161 whitespace. */ | |
| 5162 if (!done) | |
| 5163 dl->bounds.right_white = dl->bounds.left_in; | |
| 5164 } | |
| 5165 | |
| 5166 /* Set the display blocks bounds. */ | |
| 5167 db->start_pos = dl->bounds.left_in; | |
| 5168 if (Dynarr_length (db->runes)) | |
| 5169 { | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
5170 struct rune *rb = Dynarr_lastp (db->runes); |
| 428 | 5171 |
| 5172 db->end_pos = rb->xpos + rb->width; | |
| 5173 } | |
| 5174 else | |
| 5175 db->end_pos = dl->bounds.right_white; | |
| 5176 | |
| 819 | 5177 calculate_baseline (&data); |
| 428 | 5178 |
| 5179 dl->ascent = data.new_ascent; | |
| 5180 dl->descent = data.new_descent; | |
| 5181 | |
| 5182 { | |
| 5183 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
| 5184 | |
| 5185 if (dl->ascent < ascent) | |
| 5186 dl->ascent = ascent; | |
| 5187 } | |
| 5188 { | |
| 5189 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
| 5190 | |
| 5191 if (dl->descent < descent) | |
| 5192 dl->descent = descent; | |
| 5193 } | |
| 5194 | |
| 819 | 5195 calculate_yoffset (dl, db); |
| 5196 | |
| 428 | 5197 dl->cursor_elt = data.cursor_x; |
| 5198 /* #### lossage lossage lossage! Fix this shit! */ | |
| 826 | 5199 if (data.byte_charpos > byte_string_zv) |
| 5200 dl->end_charpos = buffer_or_string_bytexpos_to_charxpos (disp_string, | |
| 5201 byte_string_zv); | |
| 428 | 5202 else |
| 826 | 5203 dl->end_charpos = |
| 5204 buffer_or_string_bytexpos_to_charxpos (disp_string, | |
| 5205 data.byte_charpos) - 1; | |
| 428 | 5206 if (truncate_win) |
| 434 | 5207 data.dl->num_chars = |
| 826 | 5208 string_column_at_point (disp_string, dl->end_charpos, |
| 793 | 5209 b ? XINT (b->tab_width) : 8); |
| 428 | 5210 else |
| 5211 /* This doesn't correctly take into account tabs and control | |
| 5212 characters but if the window isn't being truncated then this | |
| 5213 value isn't going to end up being used anyhow. */ | |
| 826 | 5214 data.dl->num_chars = dl->end_charpos - dl->charpos; |
| 428 | 5215 |
| 5216 /* #### handle horizontally scrolled line with text none of which | |
| 5217 was actually laid out. */ | |
| 5218 | |
| 5219 /* #### handle any remainder of overlay arrow */ | |
| 5220 | |
| 5221 if (*prop == ADD_FAILED) | |
| 5222 *prop = NULL; | |
| 5223 | |
| 5224 if (truncate_win && *prop) | |
| 5225 { | |
| 5226 Dynarr_free (*prop); | |
| 5227 *prop = NULL; | |
| 5228 } | |
| 5229 | |
| 5230 extent_fragment_delete (data.ef); | |
| 5231 | |
| 5232 /* #### If we started at EOB, then make sure we return a value past | |
| 5233 it so that regenerate_window will exit properly. This is bogus. | |
| 5234 The main loop should get fixed so that it isn't necessary to call | |
| 5235 this function if we are already at EOB. */ | |
| 5236 | |
| 826 | 5237 if (data.byte_charpos == byte_string_zv && byte_start_pos == byte_string_zv) |
| 793 | 5238 return string_index_byte_to_char (disp_string, |
| 826 | 5239 data.byte_charpos) + 1; /* Yuck! */ |
| 428 | 5240 else |
| 826 | 5241 return string_index_byte_to_char (disp_string, data.byte_charpos); |
| 428 | 5242 } |
| 5243 | |
| 5244 /* Given a display line and a starting position, ensure that the | |
| 5245 contents of the display line accurately represent the visual | |
| 5246 representation of the buffer contents starting from the given | |
| 5247 position when displayed in the given window. The display line ends | |
| 5248 when the contents of the line reach the right boundary of the given | |
| 434 | 5249 window. |
| 5250 | |
| 428 | 5251 This is very similar to generate_display_line but with the same |
| 5252 limitations as create_string_text_block. I have taken the liberty | |
| 665 | 5253 of fixing the bytebpos stuff though.*/ |
| 5254 | |
| 5255 static Charbpos | |
| 428 | 5256 generate_string_display_line (struct window *w, Lisp_Object disp_string, |
| 5257 struct display_line *dl, | |
| 826 | 5258 Charcount start_pos, |
| 428 | 5259 prop_block_dynarr **prop, |
| 5260 face_index default_face) | |
| 5261 { | |
| 826 | 5262 Charcount ret_charcount; |
| 428 | 5263 |
| 5264 /* you must set bounds before calling this. */ | |
| 434 | 5265 |
| 428 | 5266 /* Reset what this line is using. */ |
| 5267 if (dl->display_blocks) | |
| 5268 Dynarr_reset (dl->display_blocks); | |
| 5269 if (dl->left_glyphs) | |
| 5270 { | |
| 5271 Dynarr_free (dl->left_glyphs); | |
| 5272 dl->left_glyphs = 0; | |
| 5273 } | |
| 5274 if (dl->right_glyphs) | |
| 5275 { | |
| 5276 Dynarr_free (dl->right_glyphs); | |
| 5277 dl->right_glyphs = 0; | |
| 5278 } | |
| 5279 | |
| 5280 /* We aren't generating a modeline at the moment. */ | |
| 5281 dl->modeline = 0; | |
| 5282 | |
| 5283 /* Create a display block for the text region of the line. */ | |
| 826 | 5284 ret_charcount = create_string_text_block (w, disp_string, dl, start_pos, |
| 5285 prop, default_face); | |
| 5286 dl->charpos = start_pos; | |
| 5287 if (dl->end_charpos < dl->charpos) | |
| 5288 dl->end_charpos = dl->charpos; | |
| 428 | 5289 |
| 5290 /* If there are left glyphs associated with any character in the | |
| 5291 text block, then create a display block to handle them. */ | |
| 5292 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
| 5293 create_left_glyph_block (w, dl, 0); | |
| 5294 | |
| 5295 /* If there are right glyphs associated with any character in the | |
| 5296 text block, then create a display block to handle them. */ | |
| 5297 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
| 5298 create_right_glyph_block (w, dl); | |
| 5299 | |
| 826 | 5300 return ret_charcount; |
| 428 | 5301 } |
| 5302 | |
| 2518 | 5303 /* |
| 5304 | |
| 5038 | 5305 Info on reentrancy crashes, with backtraces given: |
| 5306 | |
| 5307 (Info-goto-node "(internals)Critical Redisplay Sections") | |
| 5308 | |
| 1318 | 5309 */ |
| 5310 | |
| 5311 | |
| 428 | 5312 /* This is ripped off from regenerate_window. All we want to do is |
| 5313 loop through elements in the string creating display lines until we | |
| 5314 have covered the provided area. Simple really. */ | |
| 5315 void | |
| 5316 generate_displayable_area (struct window *w, Lisp_Object disp_string, | |
| 5317 int xpos, int ypos, int width, int height, | |
| 5318 display_line_dynarr* dla, | |
| 826 | 5319 Charcount start_pos, |
| 428 | 5320 face_index default_face) |
| 5321 { | |
| 5322 int yend = ypos + height; | |
| 5323 Charcount s_zv; | |
| 5324 prop_block_dynarr *prop = 0; | |
| 5325 layout_bounds bounds; | |
| 2518 | 5326 int depth = -1; |
| 5327 | |
| 428 | 5328 /* if there's nothing to do then do nothing. code after this assumes |
| 5329 there is something to do. */ | |
| 5330 if (NILP (disp_string)) | |
| 5331 return; | |
| 5332 | |
| 2518 | 5333 /* See comment in regenerate_window() */ |
| 5334 if (!in_display) | |
| 5335 depth = enter_redisplay_critical_section (); | |
| 5336 | |
| 5337 assert (dla); | |
| 5338 Dynarr_reset (dla); | |
| 5339 | |
| 826 | 5340 s_zv = string_char_length (disp_string); |
| 428 | 5341 |
| 5342 bounds.left_out = xpos; | |
| 5343 bounds.right_out = xpos + width; | |
| 5344 /* The inner boundaries mark where the glyph margins are located. */ | |
| 5345 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
| 5346 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
| 5347 /* We cannot fully calculate the whitespace boundaries as they | |
| 5348 depend on the contents of the line being displayed. */ | |
| 5349 bounds.left_white = bounds.left_in; | |
| 5350 bounds.right_white = bounds.right_in; | |
| 5351 | |
| 5352 while (ypos < yend) | |
| 5353 { | |
| 5354 struct display_line dl; | |
| 5355 struct display_line *dlp; | |
| 826 | 5356 Charcount next_pos; |
| 428 | 5357 int local; |
| 851 | 5358 int pos_of_dlp = -1; |
| 428 | 5359 |
| 5360 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
| 5361 { | |
| 851 | 5362 pos_of_dlp = Dynarr_length (dla); |
| 5363 dlp = Dynarr_atp (dla, pos_of_dlp); | |
| 428 | 5364 local = 0; |
| 5365 } | |
| 5366 else | |
| 5367 { | |
| 4207 | 5368 DISPLAY_LINE_INIT (dl); |
| 428 | 5369 dlp = &dl; |
| 5370 local = 1; | |
| 5371 } | |
| 5372 | |
| 5373 dlp->bounds = bounds; | |
| 5374 dlp->offset = 0; | |
| 1318 | 5375 Dynarr_lock (dla); |
| 428 | 5376 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos, |
| 5377 &prop, default_face); | |
| 1318 | 5378 Dynarr_unlock (dla); |
| 428 | 5379 /* we need to make sure that we continue along the line if there |
| 4187 | 5380 is more left to display otherwise we just end up redisplaying |
| 5381 the same chunk over and over again. */ | |
| 428 | 5382 if (next_pos == start_pos && next_pos < s_zv) |
| 5383 start_pos++; | |
| 5384 else | |
| 5385 start_pos = next_pos; | |
| 5386 | |
| 5387 dlp->ypos = ypos + dlp->ascent; | |
| 5388 ypos = dlp->ypos + dlp->descent; | |
| 5389 | |
| 5390 if (ypos > yend) | |
| 5391 { | |
| 5392 int visible_height = dlp->ascent + dlp->descent; | |
| 5393 | |
| 5394 dlp->clip = (ypos - yend); | |
| 5395 visible_height -= dlp->clip; | |
| 5396 | |
| 5397 if (visible_height < VERTICAL_CLIP (w, 1)) | |
| 5398 { | |
| 5399 if (local) | |
| 5400 free_display_line (dlp); | |
| 5401 break; | |
| 5402 } | |
| 5403 } | |
| 5404 else | |
| 5405 dlp->clip = 0; | |
| 5406 | |
|
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5407 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
|
5408 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
|
5409 else if (pos_of_dlp == Dynarr_length (dla)) |
| 5038 | 5410 Dynarr_incrementr (dla); |
|
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5411 else |
|
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5412 ABORT (); |
| 428 | 5413 |
| 5414 /* #### This type of check needs to be done down in the | |
| 5415 generate_display_line call. */ | |
| 5416 if (start_pos >= s_zv) | |
| 5417 break; | |
| 5418 } | |
| 5419 | |
| 5420 if (prop) | |
| 5421 Dynarr_free (prop); | |
| 2518 | 5422 |
| 5423 if (depth >= 0) | |
| 5424 exit_redisplay_critical_section (depth); | |
| 428 | 5425 } |
| 5426 | |
| 5427 | |
| 5428 /***************************************************************************/ | |
| 5429 /* */ | |
| 5430 /* window-regeneration routines */ | |
| 5431 /* */ | |
| 5432 /***************************************************************************/ | |
| 5433 | |
| 5434 /* For a given window and starting position in the buffer it contains, | |
| 5435 ensure that the TYPE display lines accurately represent the | |
| 5436 presentation of the window. We pass the buffer instead of getting | |
| 5437 it from the window since redisplay_window may have temporarily | |
| 5438 changed it to the echo area buffer. */ | |
| 5439 | |
| 5440 static void | |
| 2518 | 5441 regenerate_window (struct window *w, Charbpos start_pos, Charbpos point, |
| 5442 int type) | |
| 428 | 5443 { |
| 5444 struct frame *f = XFRAME (w->frame); | |
| 5445 struct buffer *b = XBUFFER (w->buffer); | |
| 5446 int ypos = WINDOW_TEXT_TOP (w); | |
| 5447 int yend; /* set farther down */ | |
| 5448 int yclip = WINDOW_TEXT_TOP_CLIP (w); | |
| 442 | 5449 int force; |
| 2518 | 5450 int depth = -1; |
| 428 | 5451 |
| 5452 prop_block_dynarr *prop; | |
| 5453 layout_bounds bounds; | |
| 5454 display_line_dynarr *dla; | |
| 5455 int need_modeline; | |
| 5456 | |
| 5457 /* The lines had better exist by this point. */ | |
| 5458 if (!(dla = window_display_lines (w, type))) | |
| 2500 | 5459 ABORT (); |
| 2518 | 5460 |
| 5461 if (!in_display) | |
| 5462 depth = enter_redisplay_critical_section (); | |
| 5463 | |
| 5038 | 5464 /* This is one spot where a reentrancy crash will occur, due to a check |
| 2518 | 5465 in the dynarr to make sure it isn't "locked" */ |
| 5466 /* | |
| 5467 | |
| 5038 | 5468 Info on reentrancy crashes, with backtraces given: |
| 5469 | |
| 5470 (Info-goto-node "(internals)Critical Redisplay Sections") | |
| 2518 | 5471 */ |
| 5472 | |
| 428 | 5473 Dynarr_reset (dla); |
| 5474 w->max_line_len = 0; | |
| 5475 | |
| 4968 | 5476 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
| 5477 because we initialized them at startup and the only way to reduce | |
| 5478 their number is through calling reset_face_cachels() or | |
| 5479 reset_glyph_cachels(), which as a side effect sets up a number of | |
| 5480 standard entries */ | |
| 5481 assert (Dynarr_length (w->face_cachels)); | |
| 5482 assert (Dynarr_length (w->glyph_cachels)); | |
| 5483 | |
| 5484 #if 0 | |
| 5485 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
| 5486 not needed */ | |
| 428 | 5487 /* Normally these get updated in redisplay_window but it is possible |
| 5488 for this function to get called from some other points where that | |
| 5489 update may not have occurred. This acts as a safety check. */ | |
| 5490 if (!Dynarr_length (w->face_cachels)) | |
| 5491 reset_face_cachels (w); | |
| 5492 if (!Dynarr_length (w->glyph_cachels)) | |
| 5493 reset_glyph_cachels (w); | |
| 4968 | 5494 #endif |
| 428 | 5495 |
| 5496 Fset_marker (w->start[type], make_int (start_pos), w->buffer); | |
| 5497 Fset_marker (w->pointm[type], make_int (point), w->buffer); | |
| 5498 w->last_point_x[type] = -1; | |
| 5499 w->last_point_y[type] = -1; | |
| 5500 | |
| 5501 /* Make sure a modeline is in the structs if needed. */ | |
| 5502 need_modeline = ensure_modeline_generated (w, type); | |
| 5503 | |
| 5504 /* Wait until here to set this so that the structs have a modeline | |
| 5505 generated in the case where one didn't exist. */ | |
| 5506 yend = WINDOW_TEXT_BOTTOM (w); | |
| 5507 | |
| 5508 bounds = calculate_display_line_boundaries (w, 0); | |
| 5509 | |
| 5510 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */ | |
| 5511 if (MINI_WINDOW_P (w) | |
| 5512 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt)) | |
| 5513 && !echo_area_active (f) | |
| 5514 && start_pos == BUF_BEGV (b)) | |
| 5515 { | |
| 5516 struct prop_block pb; | |
| 5517 Lisp_Object string; | |
| 5518 prop = Dynarr_new (prop_block); | |
| 5519 | |
| 5198 | 5520 string = concat2 (Vminibuf_preprompt, Vminibuf_prompt); |
| 428 | 5521 pb.type = PROP_MINIBUF_PROMPT; |
| 5198 | 5522 pb.data.p_string.str = XSTRING_DATA (string); |
| 5523 pb.data.p_string.len = XSTRING_LENGTH (string); | |
| 428 | 5524 Dynarr_add (prop, pb); |
| 5525 } | |
| 5526 else | |
| 5527 prop = 0; | |
| 5528 | |
| 442 | 5529 /* When we are computing things for scrolling purposes, make |
| 5530 sure at least one line is always generated */ | |
| 5531 force = (type == CMOTION_DISP); | |
| 5532 | |
| 5533 /* Make sure this is set always */ | |
| 5534 /* Note the conversion at end */ | |
| 5535 w->window_end_pos[type] = start_pos; | |
| 5536 while (ypos < yend || force) | |
| 428 | 5537 { |
| 5538 struct display_line dl; | |
| 5539 struct display_line *dlp; | |
| 5540 int local; | |
| 851 | 5541 int pos_of_dlp = -1; |
| 428 | 5542 |
| 5543 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
| 5544 { | |
| 851 | 5545 pos_of_dlp = Dynarr_length (dla); |
| 5546 dlp = Dynarr_atp (dla, pos_of_dlp); | |
| 428 | 5547 local = 0; |
| 5548 } | |
| 5549 else | |
| 5550 { | |
| 4207 | 5551 DISPLAY_LINE_INIT (dl); |
| 428 | 5552 dlp = &dl; |
| 5553 local = 1; | |
| 5554 } | |
| 5555 | |
| 5556 dlp->bounds = bounds; | |
| 5557 dlp->offset = 0; | |
| 1318 | 5558 Dynarr_lock (dla); |
| 428 | 5559 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); |
| 1318 | 5560 Dynarr_unlock (dla); |
| 428 | 5561 |
| 5562 if (yclip > dlp->ascent) | |
| 5563 { | |
| 5564 /* this should never happen, but if it does just display the | |
| 5565 whole line */ | |
| 5566 yclip = 0; | |
| 5567 } | |
| 5568 | |
| 5569 dlp->ypos = (ypos + dlp->ascent) - yclip; | |
| 5570 ypos = dlp->ypos + dlp->descent; | |
| 5571 | |
| 5572 /* See if we've been asked to start midway through a line, for | |
| 4187 | 5573 partial display line scrolling. */ |
| 434 | 5574 if (yclip) |
| 428 | 5575 { |
| 5576 dlp->top_clip = yclip; | |
| 5577 yclip = 0; | |
| 5578 } | |
| 5579 else | |
| 5580 dlp->top_clip = 0; | |
| 5581 | |
| 5582 if (ypos > yend) | |
| 5583 { | |
| 5584 int visible_height = dlp->ascent + dlp->descent; | |
| 5585 | |
| 5586 dlp->clip = (ypos - yend); | |
| 5587 /* Although this seems strange we could have a single very | |
| 5588 tall line visible for which we need to account for both | |
| 5589 the top clip and the bottom clip. */ | |
| 5590 visible_height -= (dlp->clip + dlp->top_clip); | |
| 5591 | |
| 442 | 5592 if (visible_height < VERTICAL_CLIP (w, 1) && !force) |
| 428 | 5593 { |
| 5594 if (local) | |
| 5595 free_display_line (dlp); | |
| 5596 break; | |
| 5597 } | |
| 5598 } | |
| 5599 else | |
| 5600 dlp->clip = 0; | |
| 5601 | |
| 5602 if (dlp->cursor_elt != -1) | |
| 5603 { | |
| 5604 /* #### This check is steaming crap. Have to get things | |
| 4187 | 5605 fixed so when create_text_block hits EOB, we're done, |
| 5606 period. */ | |
| 428 | 5607 if (w->last_point_x[type] == -1) |
| 5608 { | |
| 5609 w->last_point_x[type] = dlp->cursor_elt; | |
| 5610 w->last_point_y[type] = Dynarr_length (dla); | |
| 5611 } | |
| 5612 else | |
| 5613 { | |
| 5614 /* #### This means that we've added a cursor at EOB | |
| 4187 | 5615 twice. Yuck oh yuck. */ |
| 1318 | 5616 struct display_block *db; |
| 5617 | |
| 5618 Dynarr_lock (dla); | |
| 5619 db = get_display_block_from_line (dlp, TEXT); | |
| 5620 Dynarr_unlock (dla); | |
| 428 | 5621 |
| 5622 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR; | |
| 5623 dlp->cursor_elt = -1; | |
| 5624 } | |
| 5625 } | |
| 5626 | |
| 5627 if (dlp->num_chars > w->max_line_len) | |
| 5628 w->max_line_len = dlp->num_chars; | |
| 5629 | |
|
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5630 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
|
5631 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
|
5632 else if (pos_of_dlp == Dynarr_length (dla)) |
| 5038 | 5633 Dynarr_incrementr (dla); |
|
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5634 else |
|
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5635 ABORT (); |
| 428 | 5636 |
| 5637 /* #### This isn't right, but it is close enough for now. */ | |
| 5638 w->window_end_pos[type] = start_pos; | |
| 5639 | |
| 5640 /* #### This type of check needs to be done down in the | |
| 5641 generate_display_line call. */ | |
| 5642 if (start_pos > BUF_ZV (b)) | |
| 5643 break; | |
| 442 | 5644 |
| 5645 force = 0; | |
| 428 | 5646 } |
| 5647 | |
| 5648 if (prop) | |
| 5649 Dynarr_free (prop); | |
| 5650 | |
| 5651 /* #### More not quite right, but close enough. */ | |
| 442 | 5652 /* Ben sez: apparently window_end_pos[] is measured |
| 428 | 5653 as the number of characters between the window end and the |
| 5654 end of the buffer? This seems rather weirdo. What's | |
| 442 | 5655 the justification for this? |
| 5656 | |
| 5657 JV sez: Because BUF_Z (b) would be a good initial value, however | |
| 5658 that can change. This representation allows initalizing with 0. | |
| 5659 */ | |
| 428 | 5660 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; |
| 5661 | |
| 5662 if (need_modeline) | |
| 5663 { | |
| 5664 /* We know that this is the right thing to use because we put it | |
| 4187 | 5665 there when we first started working in this function. */ |
| 4967 | 5666 generate_modeline (w, Dynarr_begin (dla), type); |
| 428 | 5667 } |
| 2518 | 5668 |
| 5669 if (depth >= 0) | |
| 5670 exit_redisplay_critical_section (depth); | |
| 428 | 5671 } |
| 5672 | |
| 826 | 5673 #define REGEN_INC_FIND_START_END \ |
| 5674 do { \ | |
| 5675 /* Determine start and end of lines. */ \ | |
| 5676 if (!Dynarr_length (cdla)) \ | |
| 5677 return 0; \ | |
| 5678 else \ | |
| 5679 { \ | |
| 4967 | 5680 if (Dynarr_begin (cdla)->modeline && Dynarr_begin (ddla)->modeline) \ |
| 826 | 5681 { \ |
| 5682 dla_start = 1; \ | |
| 5683 } \ | |
| 4967 | 5684 else if (!Dynarr_begin (cdla)->modeline \ |
| 5685 && !Dynarr_begin (ddla)->modeline) \ | |
| 826 | 5686 { \ |
| 5687 dla_start = 0; \ | |
| 5688 } \ | |
| 5689 else \ | |
| 2500 | 5690 ABORT (); /* structs differ */ \ |
| 826 | 5691 \ |
| 5692 dla_end = Dynarr_length (cdla) - 1; \ | |
| 5693 } \ | |
| 5694 \ | |
| 5695 start_pos = (Dynarr_atp (cdla, dla_start)->charpos \ | |
| 5696 + Dynarr_atp (cdla, dla_start)->offset); \ | |
| 5697 /* If this isn't true, then startp has changed and we need to do a \ | |
| 5698 full regen. */ \ | |
| 5699 if (startp != start_pos) \ | |
| 5700 return 0; \ | |
| 5701 \ | |
| 5702 /* Point is outside the visible region so give up. */ \ | |
| 5703 if (pointm < start_pos) \ | |
| 5704 return 0; \ | |
| 5705 \ | |
| 428 | 5706 } while (0) |
| 5707 | |
| 5708 /* This attempts to incrementally update the display structures. It | |
| 5709 returns a boolean indicating success or failure. This function is | |
| 5710 very similar to regenerate_window_incrementally and is in fact only | |
| 5711 called from that function. However, because of the nature of the | |
| 5712 changes it deals with it sometimes makes different assumptions | |
| 5713 which can lead to success which are much more difficult to make | |
| 5714 when dealing with buffer changes. */ | |
| 5715 | |
| 5716 static int | |
| 665 | 5717 regenerate_window_extents_only_changed (struct window *w, Charbpos startp, |
| 5718 Charbpos pointm, | |
| 428 | 5719 Charcount beg_unchanged, |
| 5720 Charcount end_unchanged) | |
| 5721 { | |
| 5722 struct buffer *b = XBUFFER (w->buffer); | |
| 5723 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
| 5724 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
| 5725 | |
| 5726 int dla_start = 0; | |
| 5727 int dla_end, line; | |
| 5728 int first_line, last_line; | |
| 665 | 5729 Charbpos start_pos; |
| 428 | 5730 /* Don't define this in the loop where it is used because we |
| 5731 definitely want its value to survive between passes. */ | |
| 5732 prop_block_dynarr *prop = NULL; | |
| 5733 | |
| 5734 /* If we don't have any buffer change recorded but the modiff flag has | |
| 5735 been incremented, then fail. I'm not sure of the exact circumstances | |
| 5736 under which this can happen, but I believe that it is probably a | |
| 5737 reasonable happening. */ | |
| 5738 if (!point_visible (w, pointm, CURRENT_DISP) | |
| 5739 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)) | |
| 5740 return 0; | |
| 5741 | |
| 5742 /* If the cursor is moved we attempt to update it. If we succeed we | |
| 5743 go ahead and proceed with the optimization attempt. */ | |
| 5744 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
| 5745 || pointm != marker_position (w->last_point[CURRENT_DISP])) | |
| 5746 { | |
| 5747 struct frame *f = XFRAME (w->frame); | |
| 5748 struct device *d = XDEVICE (f->device); | |
| 5749 struct frame *sel_f = device_selected_frame (d); | |
| 5750 int success = 0; | |
| 5751 | |
| 5752 if (w->last_point_x[CURRENT_DISP] != -1 | |
| 5753 && w->last_point_y[CURRENT_DISP] != -1) | |
| 5754 { | |
| 5755 | |
| 5756 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w))) | |
| 5757 { | |
| 5758 /* Always regenerate the modeline in case it is | |
| 4187 | 5759 displaying the current line or column. */ |
| 428 | 5760 regenerate_modeline (w); |
| 5761 success = 1; | |
| 5762 } | |
| 5763 } | |
| 5764 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f))) | |
| 5765 { | |
| 5766 if (f->modeline_changed) | |
| 5767 regenerate_modeline (w); | |
| 5768 success = 1; | |
| 5769 } | |
| 5770 | |
| 5771 if (!success) | |
| 5772 return 0; | |
| 5773 } | |
| 5774 | |
| 5775 if (beg_unchanged == -1 && end_unchanged == -1) | |
| 5776 return 1; | |
| 5777 | |
| 5778 /* assert: There are no buffer modifications or they are all below the | |
| 5779 visible region. We assume that regenerate_window_incrementally has | |
| 5780 not called us unless this is true. */ | |
| 5781 | |
| 5782 REGEN_INC_FIND_START_END; | |
| 5783 | |
| 5784 /* If the changed are starts before the visible area, give up. */ | |
| 5785 if (beg_unchanged < startp) | |
| 5786 return 0; | |
| 5787 | |
| 5788 /* Find what display line the extent changes first affect. */ | |
| 5789 line = dla_start; | |
| 5790 while (line <= dla_end) | |
| 5791 { | |
| 5792 struct display_line *dl = Dynarr_atp (cdla, line); | |
| 826 | 5793 Charbpos lstart = dl->charpos + dl->offset; |
| 5794 Charbpos lend = dl->end_charpos + dl->offset; | |
| 428 | 5795 |
| 5796 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
| 5797 break; | |
| 5798 | |
| 5799 line++; | |
| 5800 } | |
| 5801 | |
| 5802 /* If the changes are below the visible area then if point hasn't | |
| 5803 moved return success otherwise fail in order to be safe. */ | |
| 5804 if (line > dla_end) | |
| 5805 { | |
| 5806 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
| 5807 && pointm == marker_position (w->last_point[CURRENT_DISP])) | |
| 5808 return 1; | |
| 5809 else | |
| 5810 return 0; | |
| 5811 } | |
| 5812 | |
| 5813 /* At this point we know what line the changes first affect. We now | |
| 5814 begin redrawing lines as long as we are still in the affected | |
| 5815 region and the line's size and positioning don't change. | |
| 5816 Otherwise we fail. If we fail we will have altered the desired | |
| 5817 structs which could lead to an assertion failure. However, if we | |
| 5818 fail the next thing that is going to happen is a full regen so we | |
| 5819 will actually end up being safe. */ | |
| 5820 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
| 5821 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
| 5822 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
| 5823 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
| 5824 | |
| 5825 first_line = last_line = line; | |
| 5826 while (line <= dla_end) | |
| 5827 { | |
| 2286 | 5828 Charbpos old_start, old_end; |
| 428 | 5829 struct display_line *cdl = Dynarr_atp (cdla, line); |
| 5830 struct display_line *ddl = Dynarr_atp (ddla, line); | |
| 5831 struct display_block *db; | |
| 5832 int initial_size; | |
| 5833 | |
| 826 | 5834 assert (cdl->charpos == ddl->charpos); |
| 5835 assert (cdl->end_charpos == ddl->end_charpos); | |
| 428 | 5836 assert (cdl->offset == ddl->offset); |
| 5837 | |
| 5838 db = get_display_block_from_line (ddl, TEXT); | |
| 5839 initial_size = Dynarr_length (db->runes); | |
| 826 | 5840 old_start = ddl->charpos + ddl->offset; |
| 5841 old_end = ddl->end_charpos + ddl->offset; | |
| 428 | 5842 |
| 5843 /* If this is the first line being updated and it used | |
| 4187 | 5844 propagation data, fail. Otherwise we'll be okay because |
| 5845 we'll have the necessary propagation data. */ | |
| 428 | 5846 if (line == first_line && ddl->used_prop_data) |
| 5847 return 0; | |
| 5848 | |
| 2286 | 5849 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
| 5850 &prop, DESIRED_DISP); | |
| 428 | 5851 ddl->offset = 0; |
| 5852 | |
| 5853 /* #### If there is propagated stuff the fail. We could | |
| 4187 | 5854 probably actually deal with this if the line had propagated |
| 5855 information when originally created by a full | |
| 5856 regeneration. */ | |
| 428 | 5857 if (prop) |
| 5858 { | |
| 5859 Dynarr_free (prop); | |
| 5860 return 0; | |
| 5861 } | |
| 5862 | |
| 5863 /* If any line position parameters have changed or a | |
| 4187 | 5864 cursor has disappeared or disappeared, fail. */ |
| 428 | 5865 db = get_display_block_from_line (ddl, TEXT); |
| 5866 if (cdl->ypos != ddl->ypos | |
| 5867 || cdl->ascent != ddl->ascent | |
| 5868 || cdl->descent != ddl->descent | |
| 5869 || cdl->top_clip != ddl->top_clip | |
| 5870 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
| 5871 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
| 826 | 5872 || old_start != ddl->charpos |
| 5873 || old_end != ddl->end_charpos | |
| 428 | 5874 || initial_size != Dynarr_length (db->runes)) |
| 5875 { | |
| 5876 return 0; | |
| 5877 } | |
| 5878 | |
| 5879 if (ddl->cursor_elt != -1) | |
| 5880 { | |
| 5881 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
| 5882 w->last_point_y[DESIRED_DISP] = line; | |
| 5883 } | |
| 5884 | |
| 5885 last_line = line; | |
| 5886 | |
| 5887 /* If the extent changes end on the line we just updated then | |
| 4187 | 5888 we're done. Otherwise go on to the next line. */ |
| 826 | 5889 if (end_unchanged <= ddl->end_charpos) |
| 428 | 5890 break; |
| 5891 else | |
| 5892 line++; | |
| 5893 } | |
| 5894 | |
| 5895 redisplay_update_line (w, first_line, last_line, 1); | |
| 5896 return 1; | |
| 5897 } | |
| 5898 | |
| 5899 /* Attempt to update the display data structures based on knowledge of | |
| 5900 the changed region in the buffer. Returns a boolean indicating | |
| 5901 success or failure. If this function returns a failure then a | |
| 5902 regenerate_window _must_ be performed next in order to maintain | |
| 5903 invariants located here. */ | |
| 5904 | |
| 5905 static int | |
| 665 | 5906 regenerate_window_incrementally (struct window *w, Charbpos startp, |
| 5907 Charbpos pointm) | |
| 428 | 5908 { |
| 5909 struct buffer *b = XBUFFER (w->buffer); | |
| 5910 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
| 5911 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
| 5912 Charcount beg_unchanged, end_unchanged; | |
| 5913 Charcount extent_beg_unchanged, extent_end_unchanged; | |
| 5914 | |
| 5915 int dla_start = 0; | |
| 5916 int dla_end, line; | |
| 665 | 5917 Charbpos start_pos; |
| 428 | 5918 |
| 5919 /* If this function is called, the current and desired structures | |
| 5920 had better be identical. If they are not, then that is a bug. */ | |
| 5921 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
| 5922 | |
| 5923 /* We don't handle minibuffer windows yet. The minibuffer prompt | |
| 5924 screws us up. */ | |
| 5925 if (MINI_WINDOW_P (w)) | |
| 5926 return 0; | |
| 5927 | |
| 5928 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b); | |
| 5929 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1 | |
| 5930 ? -1 | |
| 5931 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b)); | |
| 5932 | |
| 5933 /* If nothing has changed in the buffer, then make sure point is ok | |
| 5934 and succeed. */ | |
| 5935 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1) | |
| 5936 return regenerate_window_extents_only_changed (w, startp, pointm, | |
| 5937 extent_beg_unchanged, | |
| 5938 extent_end_unchanged); | |
| 5939 | |
| 5940 /* We can't deal with deleted newlines. */ | |
| 5941 if (BUF_NEWLINE_WAS_DELETED (b)) | |
| 5942 return 0; | |
| 5943 | |
| 5944 beg_unchanged = BUF_BEGIN_UNCHANGED (b); | |
| 5945 end_unchanged = (BUF_END_UNCHANGED (b) == -1 | |
| 5946 ? -1 | |
| 5947 : BUF_Z (b) - BUF_END_UNCHANGED (b)); | |
| 5948 | |
| 5949 REGEN_INC_FIND_START_END; | |
| 5950 | |
| 5951 /* If the changed area starts before the visible area, give up. */ | |
| 5952 if (beg_unchanged < startp) | |
| 5953 return 0; | |
| 5954 | |
| 5955 /* Find what display line the buffer changes first affect. */ | |
| 5956 line = dla_start; | |
| 5957 while (line <= dla_end) | |
| 5958 { | |
| 5959 struct display_line *dl = Dynarr_atp (cdla, line); | |
| 826 | 5960 Charbpos lstart = dl->charpos + dl->offset; |
| 5961 Charbpos lend = dl->end_charpos + dl->offset; | |
| 428 | 5962 |
| 5963 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
| 5964 break; | |
| 5965 | |
| 5966 line++; | |
| 5967 } | |
| 5968 | |
| 5969 /* If the changes are below the visible area then if point hasn't | |
| 5970 moved return success otherwise fail in order to be safe. */ | |
| 5971 if (line > dla_end) | |
| 5972 return regenerate_window_extents_only_changed (w, startp, pointm, | |
| 5973 extent_beg_unchanged, | |
| 5974 extent_end_unchanged); | |
| 5975 else | |
| 5976 /* At this point we know what line the changes first affect. We | |
| 5977 now redraw that line. If the changes are contained within it | |
| 5978 we are going to succeed and can update just that one line. | |
| 5979 Otherwise we fail. If we fail we will have altered the desired | |
| 5980 structs which could lead to an assertion failure. However, if | |
| 5981 we fail the next thing that is going to happen is a full regen | |
| 5982 so we will actually end up being safe. */ | |
| 5983 { | |
| 5984 prop_block_dynarr *prop = NULL; | |
| 5985 struct display_line *cdl = Dynarr_atp (cdla, line); | |
| 5986 struct display_line *ddl = Dynarr_atp (ddla, line); | |
| 5987 | |
| 826 | 5988 assert (cdl->charpos == ddl->charpos); |
| 5989 assert (cdl->end_charpos == ddl->end_charpos); | |
| 428 | 5990 assert (cdl->offset == ddl->offset); |
| 5991 | |
| 442 | 5992 /* If the line continues to next display line, fail. */ |
| 5993 if (ddl->line_continuation) | |
| 5994 return 0; | |
| 428 | 5995 |
| 5996 /* If the line was generated using propagation data, fail. */ | |
| 5997 if (ddl->used_prop_data) | |
| 5998 return 0; | |
| 5999 | |
| 2286 | 6000 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
| 6001 &prop, DESIRED_DISP); | |
| 428 | 6002 ddl->offset = 0; |
| 6003 | |
| 6004 /* If there is propagated stuff then it is pretty much a | |
| 4187 | 6005 guarantee that more than just the one line is affected. */ |
| 428 | 6006 if (prop) |
| 6007 { | |
| 6008 Dynarr_free (prop); | |
| 6009 return 0; | |
| 6010 } | |
| 6011 | |
| 442 | 6012 /* If the line continues to next display line, fail. */ |
| 6013 if (ddl->line_continuation) | |
| 6014 return 0; | |
| 428 | 6015 |
| 6016 /* If any line position parameters have changed or a | |
| 4187 | 6017 cursor has disappeared or disappeared, fail. */ |
| 428 | 6018 if (cdl->ypos != ddl->ypos |
| 6019 || cdl->ascent != ddl->ascent | |
| 6020 || cdl->descent != ddl->descent | |
| 6021 || cdl->top_clip != ddl->top_clip | |
| 6022 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
| 6023 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) | |
| 6024 { | |
| 6025 return 0; | |
| 6026 } | |
| 6027 | |
| 6028 /* If the changed area also ends on this line, then we may be in | |
| 4187 | 6029 business. Update everything and return success. */ |
| 826 | 6030 if (end_unchanged >= ddl->charpos && end_unchanged <= ddl->end_charpos) |
| 428 | 6031 { |
| 6032 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
| 6033 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
| 6034 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), | |
| 6035 w->buffer); | |
| 6036 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), | |
| 6037 w->buffer); | |
| 6038 | |
| 6039 if (ddl->cursor_elt != -1) | |
| 6040 { | |
| 6041 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
| 6042 w->last_point_y[DESIRED_DISP] = line; | |
| 6043 } | |
| 6044 | |
| 6045 redisplay_update_line (w, line, line, 1); | |
| 6046 regenerate_modeline (w); | |
| 6047 | |
| 6048 /* #### For now we just flush the cache until this has been | |
| 4187 | 6049 tested. After that is done, this should correct the |
| 6050 cache directly. */ | |
| 428 | 6051 Dynarr_reset (w->line_start_cache); |
| 6052 | |
| 6053 /* Adjust the extent changed boundaries to remove any | |
| 4187 | 6054 overlap with the buffer changes since we've just |
| 6055 successfully updated that area. */ | |
| 428 | 6056 if (extent_beg_unchanged != -1 |
| 6057 && extent_beg_unchanged >= beg_unchanged | |
| 6058 && extent_beg_unchanged < end_unchanged) | |
| 6059 extent_beg_unchanged = end_unchanged; | |
| 6060 | |
| 6061 if (extent_end_unchanged != -1 | |
| 6062 && extent_end_unchanged >= beg_unchanged | |
| 6063 && extent_end_unchanged < end_unchanged) | |
| 6064 extent_end_unchanged = beg_unchanged - 1; | |
| 6065 | |
| 6066 if (extent_end_unchanged <= extent_beg_unchanged) | |
| 6067 extent_beg_unchanged = extent_end_unchanged = -1; | |
| 6068 | |
| 6069 /* This could lead to odd results if it fails, but since the | |
| 4187 | 6070 buffer changes update succeeded this probably will to. |
| 6071 We already know that the extent changes start at or after | |
| 6072 the line because we checked before entering the loop. */ | |
| 428 | 6073 if (extent_beg_unchanged != -1 |
| 6074 && extent_end_unchanged != -1 | |
| 826 | 6075 && ((extent_beg_unchanged < ddl->charpos) |
| 6076 || (extent_end_unchanged > ddl->end_charpos))) | |
| 428 | 6077 return regenerate_window_extents_only_changed (w, startp, pointm, |
| 6078 extent_beg_unchanged, | |
| 6079 extent_end_unchanged); | |
| 6080 else | |
| 6081 return 1; | |
| 6082 } | |
| 6083 } | |
| 6084 | |
| 6085 /* Oh, well. */ | |
| 6086 return 0; | |
| 6087 } | |
| 6088 | |
| 6089 /* Given a window and a point, update the given display lines such | |
| 6090 that point is displayed in the middle of the window. | |
| 6091 Return the window's new start position. */ | |
| 6092 | |
| 665 | 6093 static Charbpos |
| 6094 regenerate_window_point_center (struct window *w, Charbpos point, int type) | |
| 428 | 6095 { |
| 665 | 6096 Charbpos startp; |
| 428 | 6097 |
| 6098 /* We need to make sure that the modeline is generated so that the | |
| 6099 window height can be calculated correctly. */ | |
| 6100 ensure_modeline_generated (w, type); | |
| 6101 | |
| 6102 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w)); | |
| 6103 regenerate_window (w, startp, point, type); | |
| 6104 Fset_marker (w->start[type], make_int (startp), w->buffer); | |
| 6105 | |
| 6106 return startp; | |
| 6107 } | |
| 6108 | |
| 6109 /* Given a window and a set of display lines, return a boolean | |
| 6110 indicating whether the given point is contained within. */ | |
| 6111 | |
| 6112 static int | |
| 665 | 6113 point_visible (struct window *w, Charbpos point, int type) |
| 428 | 6114 { |
| 6115 struct buffer *b = XBUFFER (w->buffer); | |
| 6116 display_line_dynarr *dla = window_display_lines (w, type); | |
| 6117 int first_line; | |
| 6118 | |
| 4967 | 6119 if (Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
| 428 | 6120 first_line = 1; |
| 6121 else | |
| 6122 first_line = 0; | |
| 6123 | |
| 6124 if (Dynarr_length (dla) > first_line) | |
| 6125 { | |
| 665 | 6126 Charbpos start, end; |
| 428 | 6127 struct display_line *dl = Dynarr_atp (dla, first_line); |
| 6128 | |
| 826 | 6129 start = dl->charpos; |
| 428 | 6130 end = BUF_Z (b) - w->window_end_pos[type] - 1; |
| 6131 | |
| 6132 if (point >= start && point <= end) | |
| 6133 { | |
| 6134 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines) | |
| 6135 { | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
6136 dl = Dynarr_lastp (dla); |
| 428 | 6137 |
| 826 | 6138 if (point >= (dl->charpos + dl->offset) |
| 6139 && point <= (dl->end_charpos + dl->offset)) | |
| 428 | 6140 return !dl->clip; |
| 6141 else | |
| 6142 return 1; | |
| 6143 } | |
| 6144 else | |
| 6145 return 1; | |
| 6146 } | |
| 6147 else | |
| 6148 return 0; | |
| 6149 } | |
| 6150 else | |
| 6151 return 0; | |
| 6152 } | |
| 6153 | |
| 6154 /* Return pixel position the middle of the window, not including the | |
| 6155 modeline and any potential horizontal scrollbar. */ | |
| 6156 | |
| 6157 int | |
| 6158 window_half_pixpos (struct window *w) | |
| 6159 { | |
| 6160 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1); | |
| 6161 } | |
| 6162 | |
| 6163 /* Return the display line which is currently in the middle of the | |
| 6164 window W for display lines TYPE. */ | |
| 6165 | |
| 6166 int | |
| 665 | 6167 line_at_center (struct window *w, int type, Charbpos start, Charbpos point) |
| 428 | 6168 { |
| 6169 display_line_dynarr *dla; | |
| 6170 int half; | |
| 6171 int elt; | |
| 6172 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1); | |
| 6173 | |
| 6174 if (type == CMOTION_DISP) | |
| 6175 regenerate_window (w, start, point, type); | |
| 6176 | |
| 6177 dla = window_display_lines (w, type); | |
| 6178 half = window_half_pixpos (w); | |
| 6179 | |
| 6180 for (elt = first_elt; elt < Dynarr_length (dla); elt++) | |
| 6181 { | |
| 6182 struct display_line *dl = Dynarr_atp (dla, elt); | |
| 6183 int line_bot = dl->ypos + dl->descent; | |
| 6184 | |
| 6185 if (line_bot > half) | |
| 6186 return elt; | |
| 6187 } | |
| 6188 | |
| 6189 /* We may not have a line at the middle if the end of the buffer is | |
| 6190 being displayed. */ | |
| 6191 return -1; | |
| 6192 } | |
| 6193 | |
| 6194 /* Return a value for point that would place it at the beginning of | |
| 6195 the line which is in the middle of the window. */ | |
| 6196 | |
| 665 | 6197 Charbpos |
| 6198 point_at_center (struct window *w, int type, Charbpos start, Charbpos point) | |
| 428 | 6199 { |
| 6200 /* line_at_center will regenerate the display structures, if necessary. */ | |
| 6201 int line = line_at_center (w, type, start, point); | |
| 6202 | |
| 6203 if (line == -1) | |
| 6204 return BUF_ZV (XBUFFER (w->buffer)); | |
| 6205 else | |
| 6206 { | |
| 6207 display_line_dynarr *dla = window_display_lines (w, type); | |
| 6208 struct display_line *dl = Dynarr_atp (dla, line); | |
| 6209 | |
| 826 | 6210 return dl->charpos; |
| 428 | 6211 } |
| 6212 } | |
| 6213 | |
| 6214 /* For a given window, ensure that the current visual representation | |
| 6215 is accurate. */ | |
| 6216 | |
| 6217 static void | |
| 6218 redisplay_window (Lisp_Object window, int skip_selected) | |
| 6219 { | |
| 6220 struct window *w = XWINDOW (window); | |
| 6221 struct frame *f = XFRAME (w->frame); | |
| 6222 struct device *d = XDEVICE (f->device); | |
| 6223 Lisp_Object old_buffer = w->buffer; | |
| 6224 Lisp_Object the_buffer = w->buffer; | |
| 6225 struct buffer *b; | |
| 6226 int echo_active = 0; | |
| 6227 int startp = 1; | |
| 6228 int pointm; | |
| 6229 int old_startp = 1; | |
| 6230 int old_pointm = 1; | |
| 6231 int selected_in_its_frame; | |
| 6232 int selected_globally; | |
| 6233 int skip_output = 0; | |
| 6234 int truncation_changed; | |
| 6235 int inactive_minibuffer = | |
| 6236 (MINI_WINDOW_P (w) && | |
| 6237 (f != device_selected_frame (d)) && | |
| 6238 !is_surrogate_for_selected_frame (f)); | |
| 6239 | |
| 6240 /* #### In the new world this function actually does a bunch of | |
| 6241 optimizations such as buffer-based scrolling, but none of that is | |
| 6242 implemented yet. */ | |
| 6243 | |
| 6244 /* If this is a combination window, do its children; that's all. | |
| 6245 The selected window is always a leaf so we don't check for | |
| 6246 skip_selected here. */ | |
| 6247 if (!NILP (w->vchild)) | |
| 6248 { | |
| 6249 redisplay_windows (w->vchild, skip_selected); | |
| 6250 return; | |
| 6251 } | |
| 6252 if (!NILP (w->hchild)) | |
| 6253 { | |
| 6254 redisplay_windows (w->hchild, skip_selected); | |
| 6255 return; | |
| 6256 } | |
| 6257 | |
| 6258 /* Is this window the selected window on its frame? */ | |
| 6259 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f))); | |
| 6260 selected_globally = | |
| 6261 selected_in_its_frame && | |
| 5198 | 6262 EQ (DEVICE_CONSOLE (d), Vselected_console) && |
| 6263 XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d)))) == d && | |
| 6264 XFRAME (DEVICE_SELECTED_FRAME (d)) == f; | |
| 428 | 6265 if (skip_selected && selected_in_its_frame) |
| 6266 return; | |
| 6267 | |
| 6268 /* It is possible that the window is not fully initialized yet. */ | |
| 6269 if (NILP (w->buffer)) | |
| 6270 return; | |
| 6271 | |
| 6272 if (MINI_WINDOW_P (w) && echo_area_active (f)) | |
| 6273 { | |
| 6274 w->buffer = the_buffer = Vecho_area_buffer; | |
| 6275 echo_active = 1; | |
| 6276 } | |
| 6277 | |
| 6278 b = XBUFFER (w->buffer); | |
| 6279 | |
| 6280 if (echo_active) | |
| 6281 { | |
| 6282 old_pointm = selected_globally | |
| 4187 | 6283 ? BUF_PT (b) |
| 6284 : marker_position (w->pointm[CURRENT_DISP]); | |
| 428 | 6285 pointm = 1; |
| 6286 } | |
| 6287 else | |
| 6288 { | |
| 6289 if (selected_globally) | |
| 6290 { | |
| 6291 pointm = BUF_PT (b); | |
| 6292 } | |
| 6293 else | |
| 6294 { | |
| 6295 pointm = marker_position (w->pointm[CURRENT_DISP]); | |
| 6296 | |
| 6297 if (pointm < BUF_BEGV (b)) | |
| 6298 pointm = BUF_BEGV (b); | |
| 6299 else if (pointm > BUF_ZV (b)) | |
| 6300 pointm = BUF_ZV (b); | |
| 6301 } | |
| 6302 } | |
| 6303 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); | |
| 6304 | |
| 4968 | 6305 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
| 6306 because we initialized them at startup and the only way to reduce | |
| 6307 their number is through calling reset_face_cachels() or | |
| 6308 reset_glyph_cachels(), which as a side effect sets up a number of | |
| 6309 standard entries */ | |
| 6310 assert (Dynarr_length (w->face_cachels)); | |
| 6311 assert (Dynarr_length (w->glyph_cachels)); | |
| 6312 | |
| 428 | 6313 /* If the buffer has changed we have to invalidate all of our face |
| 6314 cache elements. */ | |
| 6315 if ((!echo_active && b != window_display_buffer (w)) | |
| 4968 | 6316 #if 0 |
| 6317 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
| 6318 not needed */ | |
| 428 | 6319 || !Dynarr_length (w->face_cachels) |
| 4968 | 6320 #endif |
| 428 | 6321 || f->faces_changed) |
| 6322 reset_face_cachels (w); | |
| 6323 else | |
| 6324 mark_face_cachels_as_not_updated (w); | |
| 6325 | |
| 6326 /* Ditto the glyph cache elements, although we do *not* invalidate | |
| 6327 the cache purely because glyphs have changed - this is now | |
| 6328 handled by the dirty flag.*/ | |
| 6329 if ((!echo_active && b != window_display_buffer (w)) | |
| 4968 | 6330 #if 0 |
| 6331 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
| 6332 not needed */ | |
| 6333 || !Dynarr_length (w->glyph_cachels) | |
| 6334 #endif | |
| 6335 || f->faces_changed) | |
| 428 | 6336 reset_glyph_cachels (w); |
| 6337 else | |
| 6338 mark_glyph_cachels_as_not_updated (w); | |
| 6339 | |
| 6340 /* If the marker's buffer is not the window's buffer, then we need | |
| 6341 to find a new starting position. */ | |
| 6342 if (!MINI_WINDOW_P (w) | |
| 6343 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer)) | |
| 6344 { | |
| 6345 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
| 6346 | |
| 6347 goto regeneration_done; | |
| 6348 } | |
| 6349 | |
| 6350 if (echo_active) | |
| 6351 { | |
| 6352 old_startp = marker_position (w->start[CURRENT_DISP]); | |
| 6353 startp = 1; | |
| 6354 } | |
| 6355 else | |
| 6356 { | |
| 6357 startp = marker_position (w->start[CURRENT_DISP]); | |
| 6358 if (startp < BUF_BEGV (b)) | |
| 6359 startp = BUF_BEGV (b); | |
| 6360 else if (startp > BUF_ZV (b)) | |
| 6361 startp = BUF_ZV (b); | |
| 6362 } | |
| 6363 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer); | |
| 6364 | |
| 6365 truncation_changed = (find_window_mirror (w)->truncate_win != | |
| 647 | 6366 (unsigned int) window_truncation_on (w)); |
| 428 | 6367 |
| 6368 /* If w->force_start is set, then some function set w->start and we | |
| 6369 should display from there and change point, if necessary, to | |
| 6370 ensure that it is visible. */ | |
| 6371 if (w->force_start || inactive_minibuffer) | |
| 6372 { | |
| 6373 w->force_start = 0; | |
| 6374 w->last_modified[DESIRED_DISP] = Qzero; | |
| 6375 w->last_facechange[DESIRED_DISP] = Qzero; | |
| 6376 | |
| 6377 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
| 6378 | |
| 6379 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer) | |
| 6380 { | |
| 6381 pointm = point_at_center (w, DESIRED_DISP, 0, 0); | |
| 6382 | |
| 6383 if (selected_globally) | |
| 6384 BUF_SET_PT (b, pointm); | |
| 6385 | |
| 6386 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), | |
| 6387 the_buffer); | |
| 6388 | |
| 6389 /* #### BUFU amounts of overkill just to get the cursor | |
| 4187 | 6390 location marked properly. FIX ME FIX ME FIX ME */ |
| 428 | 6391 regenerate_window (w, startp, pointm, DESIRED_DISP); |
| 6392 } | |
| 6393 | |
| 6394 goto regeneration_done; | |
| 6395 } | |
| 6396 | |
| 6397 /* If nothing has changed since the last redisplay, then we just | |
| 6398 need to make sure that point is still visible. */ | |
| 6399 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) | |
| 6400 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b) | |
| 6401 && pointm >= startp | |
| 6402 /* This check is to make sure we restore the minibuffer after a | |
| 4187 | 6403 temporary change to the echo area. */ |
| 428 | 6404 && !(MINI_WINDOW_P (w) && f->buffers_changed) |
| 6405 && !f->frame_changed | |
| 6406 && !truncation_changed | |
| 442 | 6407 /* check whether start is really at the beginning of a line GE */ |
| 428 | 6408 && (!w->start_at_line_beg || beginning_of_line_p (b, startp)) |
| 6409 ) | |
| 6410 { | |
| 6411 /* Check if the cursor has actually moved. */ | |
| 6412 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
| 6413 && pointm == marker_position (w->last_point[CURRENT_DISP]) | |
| 6414 && selected_globally | |
| 6415 && !w->windows_changed | |
| 6416 && !f->clip_changed | |
| 6417 && !f->extents_changed | |
| 6418 && !f->faces_changed | |
| 6419 && !f->glyphs_changed | |
| 6420 && !f->subwindows_changed | |
| 442 | 6421 /* && !f->subwindows_state_changed*/ |
| 428 | 6422 && !f->point_changed |
| 6423 && !f->windows_structure_changed) | |
| 6424 { | |
| 6425 /* If not, we're done. */ | |
| 6426 if (f->modeline_changed) | |
| 6427 regenerate_modeline (w); | |
| 6428 | |
| 6429 skip_output = 1; | |
| 6430 goto regeneration_done; | |
| 6431 } | |
| 6432 else | |
| 6433 { | |
| 6434 /* If the new point is visible in the redisplay structures, | |
| 4187 | 6435 then let the output update routines handle it, otherwise |
| 6436 do things the hard way. */ | |
| 428 | 6437 if (!w->windows_changed |
| 6438 && !f->clip_changed | |
| 6439 && !f->extents_changed | |
| 6440 && !f->faces_changed | |
| 6441 && !f->glyphs_changed | |
| 6442 && !f->subwindows_changed | |
| 442 | 6443 /* && !f->subwindows_state_changed*/ |
| 428 | 6444 && !f->windows_structure_changed) |
| 6445 { | |
| 6446 if (point_visible (w, pointm, CURRENT_DISP) | |
| 6447 && w->last_point_x[CURRENT_DISP] != -1 | |
| 6448 && w->last_point_y[CURRENT_DISP] != -1) | |
| 6449 { | |
| 6450 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f))) | |
| 6451 { | |
| 6452 /* Always regenerate in case it is displaying | |
| 4187 | 6453 the current line or column. */ |
| 428 | 6454 regenerate_modeline (w); |
| 6455 | |
| 6456 skip_output = 1; | |
| 6457 goto regeneration_done; | |
| 6458 } | |
| 6459 } | |
| 6460 else if (!selected_in_its_frame && !f->point_changed) | |
| 6461 { | |
| 6462 if (f->modeline_changed) | |
| 6463 regenerate_modeline (w); | |
| 6464 | |
| 6465 skip_output = 1; | |
| 6466 goto regeneration_done; | |
| 6467 } | |
| 6468 } | |
| 6469 | |
| 6470 /* If we weren't able to take the shortcut method, then use | |
| 4187 | 6471 the brute force method. */ |
| 428 | 6472 regenerate_window (w, startp, pointm, DESIRED_DISP); |
| 6473 | |
| 6474 if (point_visible (w, pointm, DESIRED_DISP)) | |
| 6475 goto regeneration_done; | |
| 6476 } | |
| 6477 } | |
| 6478 | |
| 6479 /* Check if the starting point is no longer at the beginning of a | |
| 6480 line, in which case find a new starting point. We also recenter | |
| 6481 if our start position is equal to point-max. Otherwise we'll end | |
| 6482 up with a blank window. */ | |
| 6483 else if (((w->start_at_line_beg || MINI_WINDOW_P (w)) | |
| 6484 && !(startp == BUF_BEGV (b) | |
| 6485 || BUF_FETCH_CHAR (b, startp - 1) == '\n')) | |
| 6486 || (pointm == startp && | |
| 6487 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) && | |
| 6488 startp < marker_position (w->last_start[CURRENT_DISP])) | |
| 6489 || (startp == BUF_ZV (b))) | |
| 6490 { | |
| 6491 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
| 6492 | |
| 6493 goto regeneration_done; | |
| 6494 } | |
| 6495 /* See if we can update the data structures locally based on | |
| 6496 knowledge of what changed in the buffer. */ | |
| 6497 else if (!w->windows_changed | |
| 6498 && !f->clip_changed | |
| 6499 && !f->faces_changed | |
| 6500 && !f->glyphs_changed | |
| 6501 && !f->subwindows_changed | |
| 442 | 6502 /* && !f->subwindows_state_changed*/ |
| 428 | 6503 && !f->windows_structure_changed |
| 6504 && !f->frame_changed | |
| 6505 && !truncation_changed | |
| 6506 && pointm >= startp | |
| 6507 && regenerate_window_incrementally (w, startp, pointm)) | |
| 6508 { | |
| 6509 if (f->modeline_changed | |
| 6510 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b) | |
| 6511 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b)) | |
| 6512 regenerate_modeline (w); | |
| 6513 | |
| 6514 skip_output = 1; | |
| 6515 goto regeneration_done; | |
| 6516 } | |
| 6517 /* #### This is where a check for structure based scrolling would go. */ | |
| 6518 /* If all else fails, try just regenerating and see what happens. */ | |
| 6519 else | |
| 6520 { | |
| 6521 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
| 6522 | |
| 6523 if (point_visible (w, pointm, DESIRED_DISP)) | |
| 6524 goto regeneration_done; | |
| 6525 } | |
| 6526 | |
| 6527 /* We still haven't gotten the window regenerated with point | |
| 6528 visible. Next we try scrolling a little and see if point comes | |
| 6529 back onto the screen. */ | |
| 6530 if (scroll_step > 0) | |
| 6531 { | |
| 6532 int scrolled = scroll_conservatively; | |
| 6533 for (; scrolled >= 0; scrolled -= scroll_step) | |
| 6534 { | |
| 6535 startp = vmotion (w, startp, | |
| 6536 (pointm < startp) ? -scroll_step : scroll_step, 0); | |
| 6537 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
| 6538 | |
| 6539 if (point_visible (w, pointm, DESIRED_DISP)) | |
| 6540 goto regeneration_done; | |
| 6541 } | |
| 6542 } | |
| 6543 | |
| 6544 /* We still haven't managed to get the screen drawn with point on | |
| 6545 the screen, so just center it and be done with it. */ | |
| 6546 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
| 6547 | |
| 6548 | |
| 6549 regeneration_done: | |
| 6550 | |
| 6551 /* If the window's frame is changed then reset the current display | |
| 6552 lines in order to force a full repaint. */ | |
| 6553 if (f->frame_changed) | |
| 6554 { | |
| 6555 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
| 6556 | |
| 6557 Dynarr_reset (cla); | |
| 6558 } | |
| 6559 | |
| 6560 /* Must do this before calling redisplay_output_window because it | |
| 6561 sets some markers on the window. */ | |
| 6562 if (echo_active) | |
| 6563 { | |
| 6564 w->buffer = old_buffer; | |
| 6565 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer); | |
| 6566 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer); | |
| 6567 } | |
| 6568 | |
| 6569 /* These also have to be set before calling redisplay_output_window | |
| 6570 since it sets the CURRENT_DISP values based on them. */ | |
| 6571 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
| 6572 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
| 6573 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
| 6574 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
| 6575 | |
| 6576 if (!skip_output) | |
| 6577 { | |
| 665 | 6578 Charbpos start = marker_position (w->start[DESIRED_DISP]); |
| 6579 Charbpos end = (w->window_end_pos[DESIRED_DISP] == -1 | |
| 428 | 6580 ? BUF_ZV (b) |
| 6581 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1); | |
| 6582 /* Don't pollute the cache if not sure if we are correct */ | |
| 6583 if (w->start_at_line_beg) | |
| 6584 update_line_start_cache (w, start, end, pointm, 1); | |
| 6585 redisplay_output_window (w); | |
| 6586 /* | |
| 6587 * If we just displayed the echo area, the line start cache is | |
| 6588 * no longer valid, because the minibuffer window is associated | |
| 6589 * with the window now. | |
| 6590 */ | |
| 6591 if (echo_active) | |
| 6592 w->line_cache_last_updated = make_int (-1); | |
| 6593 } | |
| 6594 | |
| 6595 /* #### This should be dependent on face changes and will need to be | |
| 6596 somewhere else once tty updates occur on a per-frame basis. */ | |
| 6597 mark_face_cachels_as_clean (w); | |
| 6598 | |
| 438 | 6599 /* The glyph cachels only get dirty if someone changed something. |
| 6600 Since redisplay has now effectively ended we can reset the dirty | |
| 6601 flag since everything must be up-to-date. */ | |
| 428 | 6602 if (glyphs_changed) |
| 6603 mark_glyph_cachels_as_clean (w); | |
| 6604 | |
| 6605 w->windows_changed = 0; | |
| 6606 } | |
| 6607 | |
| 6608 /* Call buffer_reset_changes for all buffers present in any window | |
| 6609 currently visible in all frames on all devices. #### There has to | |
| 6610 be a better way to do this. */ | |
| 6611 | |
| 6612 static int | |
| 2286 | 6613 reset_buffer_changes_mapfun (struct window *w, void *UNUSED (closure)) |
| 428 | 6614 { |
| 6615 buffer_reset_changes (XBUFFER (w->buffer)); | |
| 6616 return 0; | |
| 6617 } | |
| 6618 | |
| 6619 static void | |
| 6620 reset_buffer_changes (void) | |
| 6621 { | |
| 6622 Lisp_Object frmcons, devcons, concons; | |
| 6623 | |
| 6624 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
| 6625 { | |
| 6626 struct frame *f = XFRAME (XCAR (frmcons)); | |
| 6627 | |
| 6628 if (FRAME_REPAINT_P (f)) | |
| 6629 map_windows (f, reset_buffer_changes_mapfun, 0); | |
| 6630 } | |
| 6631 } | |
| 6632 | |
| 6633 /* Ensure that all windows underneath the given window in the window | |
| 6634 hierarchy are correctly displayed. */ | |
| 6635 | |
| 6636 static void | |
| 6637 redisplay_windows (Lisp_Object window, int skip_selected) | |
| 6638 { | |
| 6639 for (; !NILP (window) ; window = XWINDOW (window)->next) | |
| 6640 { | |
| 6641 redisplay_window (window, skip_selected); | |
| 6642 } | |
| 6643 } | |
| 6644 | |
| 1318 | 6645 /* Register an action to be called at the end of redisplay. |
| 6646 in_display is 0 when this is called. | |
| 6647 This is used when it is discovered that an action needs to be taken, | |
| 6648 but it's during redisplay, so it's not safe. (Typically, it's an action | |
| 6649 that needs to enter redisplay, which can't happen reentrantly.) | |
| 6650 | |
| 6651 NEVER signal an error in these functions. | |
| 6652 */ | |
| 6653 | |
| 6654 void | |
| 6655 register_post_redisplay_action (void (*fun) (Lisp_Object), Lisp_Object arg) | |
| 6656 { | |
| 6657 Vpost_redisplay_actions = nconc2 (Vpost_redisplay_actions, | |
| 6658 list1 (Fcons (make_opaque_ptr | |
| 6659 ((void *) fun), arg))); | |
| 6660 } | |
| 6661 | |
| 1320 | 6662 static int running_post_redisplay_actions; |
| 6663 | |
| 1318 | 6664 static void |
| 6665 run_post_redisplay_actions (void) | |
| 6666 { | |
| 1320 | 6667 int depth; |
| 6668 | |
| 6669 if (running_post_redisplay_actions) | |
| 6670 return; | |
| 6671 | |
| 6672 depth = internal_bind_int (&running_post_redisplay_actions, 1); | |
| 6673 /* If the function pushes further actions, they will be tacked onto | |
| 6674 the end of the list, and we'll run them when we're done with the | |
| 6675 current ones. */ | |
| 1318 | 6676 while (!NILP (Vpost_redisplay_actions)) |
| 6677 { | |
| 6678 Lisp_Object car = XCAR (Vpost_redisplay_actions); | |
| 6679 void (*fun) (Lisp_Object) = | |
| 6680 (void (*)(Lisp_Object)) get_opaque_ptr (XCAR (car)); | |
| 6681 (*fun) (XCDR (car)); | |
| 6682 free_opaque_ptr (XCAR (car)); | |
| 6683 free_cons (car); | |
| 6684 Vpost_redisplay_actions = XCDR (Vpost_redisplay_actions); | |
| 6685 } | |
| 1320 | 6686 unbind_to (depth); |
| 1318 | 6687 } |
| 6688 | |
|
5348
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6689 static int the_ritual_suicide_has_been_cancelled = 0; |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6690 |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6691 void |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6692 redisplay_cancel_ritual_suicide(void) |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6693 { |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6694 the_ritual_suicide_has_been_cancelled = 1; |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6695 } |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6696 |
| 1318 | 6697 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS |
| 6698 | |
| 6699 static Lisp_Object | |
| 2286 | 6700 commit_ritual_suicide (Lisp_Object UNUSED (ceci_nest_pas_une_pipe)) |
| 1318 | 6701 { |
|
5348
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6702 if (!the_ritual_suicide_has_been_cancelled) |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6703 { |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6704 assert (!in_display); |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6705 } |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6706 else |
|
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6707 the_ritual_suicide_has_been_cancelled = 0; |
| 1318 | 6708 return Qnil; |
| 6709 } | |
| 6710 | |
| 6711 #endif | |
| 6712 | |
| 6713 /* Within the guts of redisplay, we are defenseless and cannot allow any of | |
| 6714 the following to happen: | |
| 6715 | |
| 6716 1) garbage collection | |
| 6717 2) QUIT | |
| 6718 3) any non-local exits | |
| 6719 4) frame size changes | |
| 6720 5) deletion of any buffers, windows, frames, etc. | |
| 6721 6) modification of buffer text | |
| 6722 7) reentrant entry of redisplay (see the stack trace above | |
| 6723 generate_displayable_area()) | |
| 6724 | |
| 6725 The general reason is that the redisplay code is written to assume that | |
| 6726 it is the only code running, and thus (a) cannot tolerate structures | |
| 6727 changed out from under it (hence 1, 4, 5, 6, 7) and (b) at various points | |
| 6728 within redisplay the redisplay structures may be in an inconsistent | |
| 6729 state and there are no unwind-protects to clean the structures up in | |
| 6730 case of non-local exit (hence 2, 3). Fixing redisplay to address these | |
| 6731 issues is hard and perhaps not worth it (and might slow things down a | |
| 6732 fair amount). We address 1, 4, 5 and 6 ourselves inside of | |
| 6733 enter_redisplay_critical_section() by simply inhibiting them, but we | |
| 6734 cannot handle 2 and 3, which must be handled at the actual point where | |
| 6735 they may occur (especially, internal_equal() or any place that may call | |
| 6736 Lisp), by wrapping the code in call_trapping_problems() or | |
| 6737 call_with_suspended_errors(). [[ NOTE: We could address QUIT by inhibiting | |
| 6738 it but this would be anti-social because it would prevent the user from | |
| 6739 interrupting any Lisp code called within the critical section. With the | |
| 6740 call_*() wrapping, C-g will interrupt the Lisp code and throw back to | |
| 6741 the innermost wrapping. ]] In fact we do turn off QUIT handling, since | |
| 6742 it's just too dangerous otherwise. See below. | |
| 6743 | |
| 6744 Code calling enter_redisplay_critical_section() must check for reentrancy | |
| 6745 (#7) and take appropriate corrective action. | |
| 6746 | |
| 6747 To help debug potential problems, we arrange (when | |
| 6748 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every time | |
| 6749 we execute QUIT or call Lisp code unless proper wrapping is in place, as | |
| 6750 well as further checks when we actually Fsignal(), Fthrow(), | |
| 6751 garbage_collect_1(). | |
| 6752 | |
| 6753 #### If a frame-size change does occur we should probably actually be | |
| 6754 preempting redisplay. */ | |
| 6755 | |
| 6756 /* Count of number of recursive times we call | |
| 6757 enter_redisplay_critical_section() or | |
| 6758 enter_redisplay_critical_section_maybe(). | |
| 6759 enter_redisplay_critical_section() cannot occur reentrantly but we have | |
| 6760 to know in the *maybe() version whether to exit the section when we're | |
| 6761 done. */ | |
| 6762 static int in_display_nesting; | |
| 6763 | |
| 6764 static Lisp_Object | |
| 2286 | 6765 end_hold_frame_size_changes (Lisp_Object UNUSED (obj)) |
| 1318 | 6766 { |
| 6767 if (!hold_frame_size_changes) | |
| 6768 { | |
| 6769 /* we used to have a function to do this for only one frame, and | |
| 6770 it was typical to call it at the end of a critical section | |
| 6771 (which occurs once per frame); but what then happens if multiple | |
| 6772 frames have frame changes held up? | |
| 4187 | 6773 |
| 1318 | 6774 This means we are O(N^2) over frames. I seriously doubt it matters. |
| 6775 --ben */ | |
| 6776 Lisp_Object frmcons, devcons, concons; | |
| 4187 | 6777 |
| 1318 | 6778 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
| 6779 { | |
| 6780 struct frame *f = XFRAME (XCAR (frmcons)); | |
| 6781 if (f->size_change_pending) | |
| 5043 | 6782 change_frame_size (f, f->new_width, f->new_height, 0); |
| 1318 | 6783 } |
| 6784 } | |
| 6785 return Qnil; | |
| 6786 } | |
| 6787 | |
| 6788 /* Call this to temporarily prevent frame-size changes from being processed. | |
| 6789 To undo, use unbind_to(), passing it the value returned by this function. | |
| 6790 */ | |
| 6791 | |
| 6792 int | |
| 6793 begin_hold_frame_size_changes (void) | |
| 6794 { | |
| 6795 int depth = specpdl_depth (); | |
| 6796 record_unwind_protect (end_hold_frame_size_changes, Qnil); | |
| 6797 internal_bind_int (&hold_frame_size_changes, 1 + hold_frame_size_changes); | |
| 6798 return depth; | |
| 6799 } | |
| 6800 | |
| 6801 int | |
| 6802 enter_redisplay_critical_section (void) | |
| 6803 { | |
| 6804 int depth = specpdl_depth (); | |
| 6805 | |
| 6806 /* Reentrant entry is deadly. The calling function must check for this. */ | |
| 6807 assert (!in_display); | |
| 6808 begin_hold_frame_size_changes (); | |
| 6809 /* Make sure in_display gets reset, but don't set it yet so that | |
| 6810 commit_ritual_suicide() can be used. */ | |
| 6811 internal_bind_int (&in_display, 0); | |
| 6812 internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
| 6813 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
| 6814 /* Force every call to QUIT to check for in_displayness. This will | |
| 6815 verify proper wrapping, as in the previous comment, aborting if not. */ | |
| 6816 something_happened++; | |
| 6817 /* Verify that no nonlocal exits blow past us. */ | |
| 6818 record_unwind_protect (commit_ritual_suicide, Qnil); | |
| 6819 #endif | |
| 6820 in_display++; | |
| 6821 | |
| 6822 set_trapping_problems_flags (INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY); | |
| 6823 /* Even checking for QUIT can cause arbitrary Lisp code to be executed, | |
| 6824 e.g. through a menu handler. We really don't want that happening | |
| 6825 inside of redisplay. Code that we `eval' is at least written with the | |
| 6826 expectation that it's inside of redisplay, and shouldn't try anything | |
| 6827 weird; but that's not the case for menu code (e.g. custom loads huge | |
| 6828 amounts of LISP FILES from a menu handler! FMH!). Safest just to turn | |
| 6829 this off. We could turn it on using UNINHIBIT_QUIT or | |
| 6830 begin_do_check_for_quit() in certain places if we want, if we know | |
| 6831 it's not in an especially tricky place. */ | |
| 6832 begin_dont_check_for_quit (); | |
| 6833 return depth; | |
| 6834 } | |
| 6835 | |
| 6836 void | |
| 6837 exit_redisplay_critical_section (int depth) | |
| 6838 { | |
| 6839 in_display--; | |
| 6840 assert (!in_display); | |
| 6841 unbind_to (depth); | |
| 6842 | |
| 6843 run_post_redisplay_actions (); | |
| 6844 } | |
| 6845 | |
| 6846 /* Enter the redisplay critical section if we're not already in it. This | |
| 6847 is for code that needs frame changes held up and other protections from | |
| 6848 being inside, but doesn't modify the redisplay structures, and doesn't | |
| 6849 look at them in a way that they will be confused by inconsistencies. */ | |
| 6850 | |
| 6851 int | |
| 6852 enter_redisplay_critical_section_maybe (void) | |
| 6853 { | |
| 6854 if (!in_display) | |
| 6855 return enter_redisplay_critical_section (); | |
| 6856 else | |
| 6857 return internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
| 6858 } | |
| 6859 | |
| 6860 void | |
| 6861 exit_redisplay_critical_section_maybe (int depth) | |
| 6862 { | |
| 6863 if (in_display_nesting == 1) | |
| 6864 exit_redisplay_critical_section (depth); | |
| 6865 else | |
| 6866 unbind_to (depth); | |
| 6867 } | |
| 6868 | |
| 1279 | 6869 /* Ensure that all windows on the given frame are correctly displayed. |
| 6870 Return non-zero if pre-empted. */ | |
| 428 | 6871 |
| 442 | 6872 int |
| 428 | 6873 redisplay_frame (struct frame *f, int preemption_check) |
| 6874 { | |
| 6875 struct device *d = XDEVICE (f->device); | |
| 853 | 6876 int depth; |
| 428 | 6877 |
| 1279 | 6878 assert (f->init_finished); |
| 6879 | |
| 1318 | 6880 /* NOTE: Without sufficient checks for stream frames, we got weird |
| 6881 crashes in pdump. These came and went very easily -- adding the | |
| 6882 critical-section code for redisplay was enough to trigger them. | |
| 6883 Perhaps I should have debugged them but there didn't seem to be any | |
| 6884 point. --ben */ | |
| 1279 | 6885 if (FRAME_STREAM_P (f)) /* nothing to do */ |
| 6886 return 0; | |
| 6887 | |
| 1318 | 6888 /* Reentrancy into redisplay can be deadly. See stack trace above |
| 6889 generate_displayable_area(). */ | |
| 6890 if (in_display) | |
| 6891 return 1; | |
| 6892 | |
| 545 | 6893 if (preemption_check |
| 6894 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) | |
| 428 | 6895 { |
| 6896 /* The preemption check itself takes a lot of time, | |
| 6897 so normally don't do it here. We do it if called | |
| 6898 from Lisp, though (`redisplay-frame'). */ | |
| 6899 int preempted; | |
| 6900 | |
| 6901 REDISPLAY_PREEMPTION_CHECK; | |
| 6902 if (preempted) | |
| 6903 return 1; | |
| 6904 } | |
| 6905 | |
| 442 | 6906 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) |
| 6907 { | |
| 6908 Lisp_Object frame; | |
| 6909 | |
| 6910 f->old_buffer_alist = Freplace_list (f->old_buffer_alist, | |
| 6911 f->buffer_alist); | |
| 793 | 6912 frame = wrap_frame (f); |
| 442 | 6913 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); |
| 6914 } | |
| 6915 | |
| 428 | 6916 /* Before we put a hold on frame size changes, attempt to process |
| 6917 any which are already pending. */ | |
| 6918 if (f->size_change_pending) | |
| 5043 | 6919 change_frame_size (f, f->new_width, f->new_height, 0); |
| 428 | 6920 |
| 6921 /* If frame size might need to be changed, due to changed size | |
| 6922 of toolbars, scrollbars etc, change it now */ | |
| 6923 if (f->size_slipped) | |
| 6924 { | |
| 6925 adjust_frame_size (f); | |
| 6926 assert (!f->size_slipped); | |
| 6927 } | |
| 6928 | |
| 1318 | 6929 /* The menubar, toolbar, and icon updates should be done before |
| 853 | 6930 enter_redisplay_critical_section is called and we are officially |
| 3025 | 6931 `in_display'. They is because they tend to eval Lisp code, which |
| 1318 | 6932 needs to be carefully wrapped within the critical section (and hence |
| 6933 is difficult to debug). */ | |
| 428 | 6934 |
| 6935 #ifdef HAVE_MENUBARS | |
| 6936 /* Update the menubar. It is done first since it could change | |
| 6937 the menubar's visibility. This way we avoid having flashing | |
| 6938 caused by an Expose event generated by the visibility change | |
| 6939 being handled. */ | |
| 6940 update_frame_menubars (f); | |
| 6941 #endif /* HAVE_MENUBARS */ | |
| 6942 #ifdef HAVE_TOOLBARS | |
| 905 | 6943 /* Update the toolbars geometry. We don't update the toolbars |
| 6944 themselves at this point since the space they are trying to | |
| 6945 occupy may currently by occupied by gutter elements. Instead we | |
| 6946 update the geometry, then update the gutter geometry, then update | |
| 6947 the gutters - which will cause mapped windows to be repositioned | |
| 6948 - and finally update the toolbars. */ | |
| 6949 update_frame_toolbars_geometry (f); | |
| 428 | 6950 #endif /* HAVE_TOOLBARS */ |
| 442 | 6951 /* Gutter update proper has to be done inside display when no frame |
| 6952 size changes can occur, thus we separately update the gutter | |
| 6953 geometry here if it needs it. */ | |
| 6954 update_frame_gutter_geometry (f); | |
| 428 | 6955 |
| 6956 /* If we clear the frame we have to force its contents to be redrawn. */ | |
| 6957 if (f->clear) | |
| 6958 f->frame_changed = 1; | |
| 6959 | |
| 442 | 6960 /* Invalidate the subwindow caches. We use subwindows_changed here |
| 6961 to cause subwindows to get instantiated. This is because | |
| 428 | 6962 subwindows_state_changed is less strict - dealing with things |
| 6963 like the clicked state of button. We have to do this before | |
| 6964 redisplaying the gutters as subwindows get unmapped in the | |
| 6965 process.*/ | |
| 442 | 6966 if (f->frame_changed) |
| 6967 reset_frame_subwindow_instance_cache (f); | |
| 6968 | |
| 6969 if (f->frame_changed || f->subwindows_changed) | |
| 6970 { | |
| 428 | 6971 /* we have to do this so the gutter gets regenerated. */ |
| 6972 reset_gutter_display_lines (f); | |
| 6973 } | |
| 6974 | |
| 853 | 6975 depth = enter_redisplay_critical_section (); |
| 428 | 6976 |
| 6977 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ | |
| 1318 | 6978 |
| 6979 /* See comments in enter_redisplay_critical_section() */ | |
| 428 | 6980 |
| 442 | 6981 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
| 6982 | |
| 6983 /* We can now update the gutters, safe in the knowledge that our | |
| 6984 efforts won't get undone. */ | |
| 6985 | |
| 6986 /* This can call lisp, but redisplay is protected by binding | |
| 6987 inhibit_quit. More importantly the code involving display lines | |
| 6988 *assumes* that GC will not happen and so does not GCPRO | |
| 6989 anything. Since we use this code the whole time with the gutters | |
| 1318 | 6990 we cannot allow GC to happen when manipulating the gutters. |
| 6991 | |
| 6992 This must be inside of the critical section for various reasons. | |
| 6993 For example, it messes with display structures, which be left in | |
| 6994 an inconsistent state. */ | |
| 442 | 6995 update_frame_gutters (f); |
| 6996 | |
| 428 | 6997 /* Erase the frame before outputting its contents. */ |
| 6998 if (f->clear) | |
| 6999 { | |
| 442 | 7000 MAYBE_DEVMETH (d, clear_frame, (f)); |
| 428 | 7001 } |
| 7002 | |
| 7003 /* Do the selected window first. */ | |
| 7004 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); | |
| 7005 | |
| 7006 /* Then do the rest. */ | |
| 7007 redisplay_windows (f->root_window, 1); | |
| 7008 | |
| 442 | 7009 MAYBE_DEVMETH (d, frame_output_end, (f)); |
| 428 | 7010 |
| 7011 update_frame_title (f); | |
| 7012 | |
| 905 | 7013 #ifdef HAVE_TOOLBARS |
| 7014 /* Finally update the toolbars. It seems its possible to get in a | |
| 7015 cycle between updating the gutter and the toolbars. Basically we | |
| 7016 want to end up with both being up-to-date and this doesn't seem | |
| 7017 possible in a single pass. */ | |
| 7018 update_frame_toolbars (f); | |
| 7019 #endif /* HAVE_TOOLBARS */ | |
| 7020 | |
| 428 | 7021 CLASS_RESET_CHANGED_FLAGS (f); |
| 7022 f->window_face_cache_reset = 0; | |
| 7023 f->echo_area_garbaged = 0; | |
| 7024 f->clear = 0; | |
| 7025 | |
| 7026 if (!f->size_change_pending) | |
| 7027 f->size_changed = 0; | |
| 7028 | |
| 7029 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */ | |
| 7030 | |
| 853 | 7031 /* Allow frame size changes to occur again. */ |
| 7032 exit_redisplay_critical_section (depth); | |
| 428 | 7033 |
| 7034 return 0; | |
| 7035 } | |
| 7036 | |
| 440 | 7037 /* Ensure that all frames on the given device are correctly displayed. |
| 7038 If AUTOMATIC is non-zero, and the device implementation indicates | |
| 7039 no automatic redisplay, as printers do, then the device is not | |
| 7040 redisplayed. AUTOMATIC is set to zero when called from lisp | |
| 7041 functions (redraw-device) and (redisplay-device), and to non-zero | |
| 7042 when called from "lazy" redisplay(); | |
| 7043 */ | |
| 428 | 7044 |
| 7045 static int | |
| 440 | 7046 redisplay_device (struct device *d, int automatic) |
| 428 | 7047 { |
| 7048 Lisp_Object frame, frmcons; | |
| 7049 int size_change_failed = 0; | |
| 7050 struct frame *f; | |
| 7051 | |
| 545 | 7052 if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) |
| 440 | 7053 return 0; |
| 7054 | |
| 428 | 7055 if (DEVICE_STREAM_P (d)) /* nothing to do */ |
| 7056 return 0; | |
| 7057 | |
| 7058 /* It is possible that redisplay has been called before the | |
| 545 | 7059 device is fully initialized, or that the console implementation |
| 7060 allows frameless devices. If so then continue with the next | |
| 7061 device. */ | |
| 428 | 7062 if (NILP (DEVICE_SELECTED_FRAME (d))) |
| 7063 return 0; | |
| 7064 | |
| 545 | 7065 if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) |
| 7066 { | |
| 7067 int preempted; | |
| 7068 REDISPLAY_PREEMPTION_CHECK; | |
| 7069 if (preempted) | |
| 7070 return 1; | |
| 7071 } | |
| 428 | 7072 |
| 7073 /* Always do the selected frame first. */ | |
| 7074 frame = DEVICE_SELECTED_FRAME (d); | |
| 7075 | |
| 7076 f = XFRAME (frame); | |
| 7077 | |
| 7078 if (f->icon_changed || f->windows_changed) | |
| 7079 update_frame_icon (f); | |
| 7080 | |
| 7081 if (FRAME_REPAINT_P (f)) | |
| 7082 { | |
| 5198 | 7083 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
| 428 | 7084 { |
| 588 | 7085 int preempted = redisplay_frame (f, 1); |
| 545 | 7086 if (preempted) |
| 7087 return 1; | |
| 7088 } | |
| 428 | 7089 |
| 7090 /* If the frame redisplay did not get preempted, then this flag | |
| 4187 | 7091 should have gotten set to 0. It might be possible for that |
| 7092 not to happen if a size change event were to occur at an odd | |
| 7093 time. To make sure we don't miss anything we simply don't | |
| 7094 reset the top level flags until the condition ends up being | |
| 7095 in the right state. */ | |
| 428 | 7096 if (f->size_changed) |
| 7097 size_change_failed = 1; | |
| 7098 } | |
| 7099 | |
| 7100 DEVICE_FRAME_LOOP (frmcons, d) | |
| 7101 { | |
| 7102 f = XFRAME (XCAR (frmcons)); | |
| 7103 | |
| 7104 if (f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
| 7105 continue; | |
| 7106 | |
| 7107 if (f->icon_changed || f->windows_changed) | |
| 7108 update_frame_icon (f); | |
| 7109 | |
| 7110 if (FRAME_REPAINT_P (f)) | |
| 7111 { | |
| 430 | 7112 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
| 428 | 7113 { |
| 588 | 7114 int preempted = redisplay_frame (f, 1); |
| 545 | 7115 if (preempted) |
| 7116 return 1; | |
| 428 | 7117 } |
| 7118 | |
| 7119 if (f->size_change_pending) | |
| 7120 size_change_failed = 1; | |
| 7121 } | |
| 7122 } | |
| 7123 | |
| 7124 /* If we get here then we redisplayed all of our frames without | |
| 7125 getting preempted so mark ourselves as clean. */ | |
| 7126 CLASS_RESET_CHANGED_FLAGS (d); | |
| 7127 | |
| 7128 if (!size_change_failed) | |
| 7129 d->size_changed = 0; | |
| 7130 | |
| 7131 return 0; | |
| 7132 } | |
| 7133 | |
| 7134 /* Ensure that all windows on all frames on all devices are displaying | |
| 7135 the current contents of their respective buffers. */ | |
| 7136 | |
| 7137 static void | |
| 7138 redisplay_without_hooks (void) | |
| 7139 { | |
| 7140 Lisp_Object devcons, concons; | |
| 7141 int size_change_failed = 0; | |
| 1292 | 7142 PROFILE_DECLARE (); |
| 7143 | |
| 7144 PROFILE_RECORD_ENTERING_SECTION (QSin_redisplay); | |
| 428 | 7145 |
| 7146 if (asynch_device_change_pending) | |
| 7147 handle_asynch_device_change (); | |
| 7148 | |
| 7149 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && | |
| 430 | 7150 !disable_preemption && preemption_count < max_preempts) |
| 428 | 7151 goto done; |
| 7152 | |
| 7153 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
| 7154 { | |
| 7155 struct device *d = XDEVICE (XCAR (devcons)); | |
| 7156 int preempted; | |
| 7157 | |
| 430 | 7158 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) |
| 428 | 7159 { |
| 440 | 7160 preempted = redisplay_device (d, 1); |
| 428 | 7161 |
| 7162 if (preempted) | |
| 7163 { | |
| 7164 preemption_count++; | |
| 7165 RESET_CHANGED_SET_FLAGS; | |
| 7166 goto done; | |
| 7167 } | |
| 7168 | |
| 7169 /* See comment in redisplay_device. */ | |
| 7170 if (d->size_changed) | |
| 7171 size_change_failed = 1; | |
| 7172 } | |
| 7173 } | |
| 7174 preemption_count = 0; | |
| 7175 | |
| 7176 /* Mark redisplay as accurate */ | |
| 7177 GLOBAL_RESET_CHANGED_FLAGS; | |
| 7178 RESET_CHANGED_SET_FLAGS; | |
| 7179 | |
| 7180 if (faces_changed) | |
| 7181 { | |
| 7182 mark_all_faces_as_clean (); | |
| 7183 faces_changed = 0; | |
| 7184 } | |
| 7185 | |
| 7186 if (!size_change_failed) | |
| 7187 size_changed = 0; | |
| 7188 | |
| 7189 reset_buffer_changes (); | |
| 7190 | |
| 7191 done: | |
| 800 | 7192 #ifdef ERROR_CHECK_DISPLAY |
| 7193 sledgehammer_check_redisplay_structs (); | |
| 7194 #endif /* ERROR_CHECK_DISPLAY */ | |
| 1292 | 7195 |
| 7196 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay); | |
| 428 | 7197 } |
| 7198 | |
| 1318 | 7199 /* Note: All places in the C code that call redisplay() are prepared to |
| 7200 handle GCing, which can happen from run_pre_idle_hook(). However, we | |
| 7201 can't currently handle GC inside the guts of redisplay; see | |
| 7202 enter_redisplay_critical_section(). | |
| 853 | 7203 |
| 7204 (#### What about other external entry points to the redisplay code? | |
| 7205 Someone should go through and make sure that all callers can handle | |
| 7206 GC there, too.) | |
| 7207 */ | |
| 7208 | |
| 428 | 7209 void |
| 7210 redisplay (void) | |
| 7211 { | |
| 853 | 7212 run_pre_idle_hook (); |
| 7213 redisplay_no_pre_idle_hook (); | |
| 7214 } | |
| 7215 | |
| 7216 void | |
| 7217 redisplay_no_pre_idle_hook (void) | |
| 7218 { | |
| 428 | 7219 if (last_display_warning_tick != display_warning_tick && |
| 7220 !inhibit_warning_display) | |
| 7221 { | |
| 7222 /* If an error occurs during this function, oh well. | |
| 4187 | 7223 If we report another warning, we could get stuck in an |
| 428 | 7224 infinite loop reporting warnings. */ |
| 853 | 7225 call0_trapping_problems |
| 7226 (0, Qdisplay_warning_buffer, | |
| 7227 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
| 428 | 7228 last_display_warning_tick = display_warning_tick; |
| 7229 } | |
| 7230 | |
| 7231 redisplay_without_hooks (); | |
| 7232 } | |
| 7233 | |
| 853 | 7234 Lisp_Object |
| 7235 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker) | |
| 7236 { | |
| 7237 return | |
| 7238 eval_in_buffer_trapping_problems | |
| 7239 ("Error calling function within redisplay", current_buffer, | |
| 1318 | 7240 dont_trust_this_damn_sucker, 0); |
| 853 | 7241 } |
| 428 | 7242 |
| 7243 /* Efficiently determine the window line number, and return a pointer | |
| 7244 to its printed representation. Do this regardless of whether | |
| 7245 line-number-mode is on. The first line in the buffer is counted as | |
| 7246 1. If narrowing is in effect, the lines are counted from the | |
| 7247 beginning of the visible portion of the buffer. */ | |
| 4970 | 7248 static Ascbyte * |
| 428 | 7249 window_line_number (struct window *w, int type) |
| 7250 { | |
| 7251 struct device *d = XDEVICE (XFRAME (w->frame)->device); | |
| 7252 struct buffer *b = XBUFFER (w->buffer); | |
| 7253 /* Be careful in the order of these tests. The first clause will | |
| 7254 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be). | |
| 7255 This can occur when the frame title is computed really early */ | |
| 665 | 7256 Charbpos pos = |
| 5198 | 7257 ((EQ (DEVICE_SELECTED_FRAME (d), w->frame) && |
| 7258 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d)))) && | |
| 7259 EQ (DEVICE_CONSOLE (d), Vselected_console) && | |
| 7260 XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d)))) == d ) | |
| 428 | 7261 ? BUF_PT (b) |
| 7262 : marker_position (w->pointm[type])); | |
| 7263 EMACS_INT line; | |
| 7264 | |
| 7265 line = buffer_line_number (b, pos, 1); | |
| 7266 | |
| 603 | 7267 { |
| 4970 | 7268 static Ascbyte window_line_number_buf[DECIMAL_PRINT_SIZE (long)]; |
| 603 | 7269 |
| 7270 long_to_string (window_line_number_buf, line + 1); | |
| 7271 | |
| 7272 return window_line_number_buf; | |
| 7273 } | |
| 428 | 7274 } |
| 7275 | |
| 7276 | |
| 7277 /* Given a character representing an object in a modeline | |
| 7278 specification, return a string (stored into the global array | |
| 867 | 7279 `mode_spec_ibyte_string') with the information that object |
| 428 | 7280 represents. |
| 7281 | |
| 7282 This function is largely unchanged from previous versions of the | |
| 7283 redisplay engine. | |
| 7284 | |
| 7285 Warning! This code is also used for frame titles and can be called | |
| 7286 very early in the device/frame update process! JV | |
| 7287 */ | |
| 7288 | |
| 7289 static void | |
| 867 | 7290 decode_mode_spec (struct window *w, Ichar spec, int type) |
| 428 | 7291 { |
| 7292 Lisp_Object obj = Qnil; | |
| 4970 | 7293 const Ascbyte *str = NULL; |
| 428 | 7294 struct buffer *b = XBUFFER (w->buffer); |
| 7295 | |
| 867 | 7296 Dynarr_reset (mode_spec_ibyte_string); |
| 428 | 7297 |
| 7298 switch (spec) | |
| 7299 { | |
| 7300 /* print buffer name */ | |
| 7301 case 'b': | |
| 7302 obj = b->name; | |
| 7303 break; | |
| 7304 | |
| 7305 /* print visited file name */ | |
| 7306 case 'f': | |
| 7307 obj = b->filename; | |
| 7308 break; | |
| 7309 | |
| 7310 /* print the current column */ | |
| 7311 case 'c': | |
| 7312 { | |
| 4187 | 7313 Charbpos pt = (w == XWINDOW (Fselected_window (Qnil))) |
| 7314 ? BUF_PT (b) | |
| 7315 : marker_position (w->pointm[type]); | |
| 428 | 7316 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one; |
| 4970 | 7317 Ascbyte buf[DECIMAL_PRINT_SIZE (long)]; |
| 428 | 7318 |
| 7319 long_to_string (buf, col); | |
| 7320 | |
| 867 | 7321 Dynarr_add_many (mode_spec_ibyte_string, |
| 7322 (const Ibyte *) buf, strlen (buf)); | |
| 428 | 7323 |
| 7324 goto decode_mode_spec_done; | |
| 7325 } | |
| 7326 /* print the file coding system */ | |
| 7327 case 'C': | |
| 7328 { | |
| 4187 | 7329 Lisp_Object codesys = b->buffer_file_coding_system; |
| 7330 /* Be very careful here not to get an error. */ | |
| 428 | 7331 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys)) |
| 4187 | 7332 { |
| 7333 codesys = find_coding_system_for_text_file (codesys, 0); | |
| 428 | 7334 if (CODING_SYSTEMP (codesys)) |
| 4187 | 7335 obj = XCODING_SYSTEM_MNEMONIC (codesys); |
| 7336 } | |
| 428 | 7337 } |
| 7338 break; | |
| 7339 | |
| 7340 /* print the current line number */ | |
| 7341 case 'l': | |
| 7342 str = window_line_number (w, type); | |
| 7343 break; | |
| 7344 | |
| 7345 /* print value of mode-name (obsolete) */ | |
| 7346 case 'm': | |
| 7347 obj = b->mode_name; | |
| 7348 break; | |
| 7349 | |
| 7350 /* print hyphen and frame number, if != 1 */ | |
| 7351 case 'N': | |
| 7352 #ifdef HAVE_TTY | |
| 7353 { | |
| 7354 struct frame *f = XFRAME (w->frame); | |
| 7355 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999) | |
| 7356 { | |
| 7357 /* Naughty, naughty */ | |
| 4970 | 7358 Ascbyte *writable_str = alloca_array (Ascbyte, 10); |
| 428 | 7359 sprintf (writable_str, "-%d", f->order_count); |
| 7360 str = writable_str; | |
| 7361 } | |
| 7362 } | |
| 7363 #endif /* HAVE_TTY */ | |
| 7364 break; | |
| 7365 | |
| 7366 /* print Narrow if appropriate */ | |
| 7367 case 'n': | |
| 7368 if (BUF_BEGV (b) > BUF_BEG (b) | |
| 7369 || BUF_ZV (b) < BUF_Z (b)) | |
| 7370 str = " Narrow"; | |
| 7371 break; | |
| 7372 | |
| 7373 /* print %, * or hyphen, if buffer is read-only, modified or neither */ | |
| 7374 case '*': | |
| 7375 str = (!NILP (b->read_only) | |
| 7376 ? "%" | |
| 7377 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
| 7378 ? "*" | |
| 7379 : "-")); | |
| 7380 break; | |
| 7381 | |
| 7382 /* print * or hyphen -- XEmacs change to allow a buffer to be | |
| 4187 | 7383 read-only but still indicate whether it is modified. */ |
| 428 | 7384 case '+': |
| 7385 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
| 7386 ? "*" | |
| 7387 : (!NILP (b->read_only) | |
| 7388 ? "%" | |
| 7389 : "-")); | |
| 7390 break; | |
| 7391 | |
| 7392 /* #### defined in 19.29 decode_mode_spec, but not in | |
| 4187 | 7393 modeline-format doc string. */ |
| 428 | 7394 /* This differs from %* in that it ignores read-only-ness. */ |
| 7395 case '&': | |
| 7396 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
| 7397 ? "*" | |
| 7398 : "-"); | |
| 7399 break; | |
| 7400 | |
| 7401 /* print process status */ | |
| 7402 case 's': | |
| 7403 obj = Fget_buffer_process (w->buffer); | |
| 7404 if (NILP (obj)) | |
| 7405 str = GETTEXT ("no process"); | |
| 7406 else | |
| 7407 obj = Fsymbol_name (Fprocess_status (obj)); | |
| 7408 break; | |
| 7409 | |
| 7410 /* Print name of selected frame. */ | |
| 7411 case 'S': | |
| 7412 obj = XFRAME (w->frame)->name; | |
| 7413 break; | |
| 7414 | |
| 7415 /* indicate TEXT or BINARY */ | |
| 7416 case 't': | |
| 7417 /* #### NT does not use this any more. Now what? */ | |
| 7418 str = "T"; | |
| 7419 break; | |
| 7420 | |
| 7421 /* print percent of buffer above top of window, or Top, Bot or All */ | |
| 7422 case 'p': | |
| 7423 { | |
| 665 | 7424 Charbpos pos = marker_position (w->start[type]); |
| 428 | 7425 |
| 7426 /* This had better be while the desired lines are being done. */ | |
| 7427 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) | |
| 7428 { | |
| 7429 if (pos <= BUF_BEGV (b)) | |
| 7430 str = "All"; | |
| 7431 else | |
| 7432 str = "Bottom"; | |
| 7433 } | |
| 7434 else if (pos <= BUF_BEGV (b)) | |
| 7435 str = "Top"; | |
| 7436 else | |
| 7437 { | |
| 7438 /* This hard limit is ok since the string it will hold has a | |
| 4187 | 7439 fixed maximum length of 3. But just to be safe... */ |
| 4970 | 7440 Ascbyte buf[10]; |
| 428 | 7441 Charcount chars = pos - BUF_BEGV (b); |
| 7442 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
| 7443 | |
| 7444 /* Avoid overflow on big buffers */ | |
| 7445 int percent = total > LONG_MAX/200 ? | |
| 7446 (chars + total/200) / (total / 100) : | |
| 7447 (chars * 100 + total/2) / total; | |
| 7448 | |
| 7449 /* We can't normally display a 3-digit number, so get us a | |
| 4187 | 7450 2-digit number that is close. */ |
| 428 | 7451 if (percent == 100) |
| 7452 percent = 99; | |
| 7453 | |
| 7454 sprintf (buf, "%d%%", percent); | |
| 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 percent of buffer above bottom of window, perhaps plus | |
| 7464 Top, or print Bottom or All */ | |
| 7465 case 'P': | |
| 7466 { | |
| 665 | 7467 Charbpos toppos = marker_position (w->start[type]); |
| 7468 Charbpos botpos = BUF_Z (b) - w->window_end_pos[type]; | |
| 428 | 7469 |
| 7470 /* botpos is only accurate as of the last redisplay, so we can | |
| 4187 | 7471 only treat it as a hint. In particular, after erase-buffer, |
| 7472 botpos may be negative. */ | |
| 428 | 7473 if (botpos < toppos) |
| 7474 botpos = toppos; | |
| 7475 | |
| 7476 if (botpos >= BUF_ZV (b)) | |
| 7477 { | |
| 7478 if (toppos <= BUF_BEGV (b)) | |
| 7479 str = "All"; | |
| 7480 else | |
| 7481 str = "Bottom"; | |
| 7482 } | |
| 7483 else | |
| 7484 { | |
| 7485 /* This hard limit is ok since the string it will hold has a | |
| 4187 | 7486 fixed maximum length of around 6. But just to be safe... */ |
| 4970 | 7487 Ascbyte buf[10]; |
| 428 | 7488 Charcount chars = botpos - BUF_BEGV (b); |
| 7489 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
| 7490 | |
| 7491 /* Avoid overflow on big buffers */ | |
| 7492 int percent = total > LONG_MAX/200 ? | |
| 7493 (chars + total/200) / (total / 100) : | |
| 7494 (chars * 100 + total/2) / max (total, 1); | |
| 7495 | |
| 7496 /* We can't normally display a 3-digit number, so get us a | |
| 4187 | 7497 2-digit number that is close. */ |
| 428 | 7498 if (percent == 100) |
| 7499 percent = 99; | |
| 7500 | |
| 7501 if (toppos <= BUF_BEGV (b)) | |
| 7502 sprintf (buf, "Top%d%%", percent); | |
| 7503 else | |
| 7504 sprintf (buf, "%d%%", percent); | |
| 7505 | |
| 867 | 7506 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
| 428 | 7507 strlen (buf)); |
| 7508 | |
| 7509 goto decode_mode_spec_done; | |
| 7510 } | |
| 7511 break; | |
| 7512 } | |
| 7513 | |
| 7514 /* print % */ | |
| 7515 case '%': | |
| 7516 str = "%"; | |
| 7517 break; | |
| 7518 | |
| 7519 /* print one [ for each recursive editing level. */ | |
| 7520 case '[': | |
| 7521 { | |
| 7522 int i; | |
| 7523 | |
| 7524 if (command_loop_level > 5) | |
| 7525 { | |
| 7526 str = "[[[... "; | |
| 7527 break; | |
| 7528 } | |
| 7529 | |
| 7530 for (i = 0; i < command_loop_level; i++) | |
| 867 | 7531 Dynarr_add (mode_spec_ibyte_string, '['); |
| 428 | 7532 |
| 7533 goto decode_mode_spec_done; | |
| 7534 } | |
| 7535 | |
| 7536 /* print one ] for each recursive editing level. */ | |
| 7537 case ']': | |
| 7538 { | |
| 7539 int i; | |
| 7540 | |
| 7541 if (command_loop_level > 5) | |
| 7542 { | |
| 7543 str = "...]]]"; | |
| 7544 break; | |
| 7545 } | |
| 7546 | |
| 7547 for (i = 0; i < command_loop_level; i++) | |
| 867 | 7548 Dynarr_add (mode_spec_ibyte_string, ']'); |
| 428 | 7549 |
| 7550 goto decode_mode_spec_done; | |
| 7551 } | |
| 7552 | |
| 7553 /* print infinitely many dashes -- handle at top level now */ | |
| 7554 case '-': | |
| 7555 break; | |
| 7556 | |
| 7557 } | |
| 7558 | |
| 7559 if (STRINGP (obj)) | |
| 867 | 7560 Dynarr_add_many (mode_spec_ibyte_string, |
| 428 | 7561 XSTRING_DATA (obj), |
| 7562 XSTRING_LENGTH (obj)); | |
| 7563 else if (str) | |
| 867 | 7564 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) str, strlen (str)); |
| 428 | 7565 |
| 7566 decode_mode_spec_done: | |
| 867 | 7567 Dynarr_add (mode_spec_ibyte_string, '\0'); |
| 428 | 7568 } |
| 7569 | |
| 7570 /* Given a display line, free all of its data structures. */ | |
| 7571 | |
| 7572 static void | |
| 7573 free_display_line (struct display_line *dl) | |
| 7574 { | |
| 7575 int block; | |
| 7576 | |
| 7577 if (dl->display_blocks) | |
| 7578 { | |
| 7579 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
| 4187 | 7580 { |
| 428 | 7581 struct display_block *db = Dynarr_atp (dl->display_blocks, block); |
| 7582 | |
| 7583 Dynarr_free (db->runes); | |
| 7584 } | |
| 7585 | |
| 7586 Dynarr_free (dl->display_blocks); | |
| 7587 dl->display_blocks = NULL; | |
| 7588 } | |
| 7589 | |
| 7590 if (dl->left_glyphs) | |
| 7591 { | |
| 7592 Dynarr_free (dl->left_glyphs); | |
| 7593 dl->left_glyphs = NULL; | |
| 7594 } | |
| 7595 | |
| 7596 if (dl->right_glyphs) | |
| 7597 { | |
| 7598 Dynarr_free (dl->right_glyphs); | |
| 7599 dl->right_glyphs = NULL; | |
| 7600 } | |
| 7601 } | |
| 7602 | |
| 7603 | |
| 7604 /* Given an array of display lines, free them and all data structures | |
| 7605 contained within them. */ | |
| 7606 | |
| 7607 void | |
| 7608 free_display_lines (display_line_dynarr *dla) | |
| 7609 { | |
| 7610 int line; | |
| 7611 | |
| 7612 for (line = 0; line < Dynarr_largest (dla); line++) | |
| 7613 { | |
| 7614 free_display_line (Dynarr_atp (dla, line)); | |
| 7615 } | |
| 7616 | |
| 7617 Dynarr_free (dla); | |
| 7618 } | |
| 7619 | |
| 7620 /* Call internal free routine for each set of display lines. */ | |
| 7621 | |
| 7622 void | |
| 7623 free_display_structs (struct window_mirror *mir) | |
| 7624 { | |
| 7625 if (mir->current_display_lines) | |
| 7626 { | |
| 7627 free_display_lines (mir->current_display_lines); | |
| 7628 mir->current_display_lines = 0; | |
| 7629 } | |
| 7630 | |
| 7631 if (mir->desired_display_lines) | |
| 7632 { | |
| 7633 free_display_lines (mir->desired_display_lines); | |
| 7634 mir->desired_display_lines = 0; | |
| 7635 } | |
| 7636 } | |
| 7637 | |
| 7638 | |
| 7639 static void | |
| 7640 mark_glyph_block_dynarr (glyph_block_dynarr *gba) | |
| 7641 { | |
| 7642 if (gba) | |
| 7643 { | |
| 4967 | 7644 glyph_block *gb = Dynarr_begin (gba); |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7645 glyph_block *gb_last = Dynarr_past_lastp (gba); |
| 428 | 7646 |
| 7647 for (; gb < gb_last; gb++) | |
| 7648 { | |
| 7649 if (!NILP (gb->glyph)) | |
| 7650 mark_object (gb->glyph); | |
| 7651 if (!NILP (gb->extent)) | |
| 7652 mark_object (gb->extent); | |
| 7653 } | |
| 7654 } | |
| 7655 } | |
| 7656 | |
| 442 | 7657 /* See the comment in image_instantiate_cache_result as to why marking |
| 7658 the glyph will also mark the image_instance. */ | |
| 7659 void | |
| 428 | 7660 mark_redisplay_structs (display_line_dynarr *dla) |
| 7661 { | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7662 display_line *dl = Dynarr_begin (dla); |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7663 display_line *dl_last = Dynarr_past_lastp (dla); |
| 428 | 7664 |
| 7665 for (; dl < dl_last; dl++) | |
| 7666 { | |
| 7667 display_block_dynarr *dba = dl->display_blocks; | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7668 display_block *db = Dynarr_begin (dba); |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7669 display_block *db_last = Dynarr_past_lastp (dba); |
| 428 | 7670 |
| 7671 for (; db < db_last; db++) | |
| 7672 { | |
| 7673 rune_dynarr *ra = db->runes; | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7674 rune *r = Dynarr_begin (ra); |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7675 rune *r_last = Dynarr_past_lastp (ra); |
| 428 | 7676 |
| 7677 for (; r < r_last; r++) | |
| 7678 { | |
| 7679 if (r->type == RUNE_DGLYPH) | |
| 7680 { | |
| 7681 if (!NILP (r->object.dglyph.glyph)) | |
| 7682 mark_object (r->object.dglyph.glyph); | |
| 7683 if (!NILP (r->object.dglyph.extent)) | |
| 7684 mark_object (r->object.dglyph.extent); | |
| 7685 } | |
| 7686 } | |
| 7687 } | |
| 7688 | |
| 7689 mark_glyph_block_dynarr (dl->left_glyphs); | |
| 7690 mark_glyph_block_dynarr (dl->right_glyphs); | |
| 7691 } | |
| 7692 } | |
| 7693 | |
| 7694 | |
| 2367 | 7695 |
| 7696 /* | |
| 7697 | |
| 7698 Info on line-start cache: | |
| 7699 | |
| 7700 (Info-goto-node "(internals)Line Start Cache") | |
| 7701 */ | |
| 428 | 7702 |
| 7703 /* This will get used quite a bit so we don't want to be constantly | |
| 7704 allocating and freeing it. */ | |
| 7705 static line_start_cache_dynarr *internal_cache; | |
| 7706 | |
| 7707 /* Makes internal_cache represent the TYPE display structs and only | |
| 7708 the TYPE display structs. */ | |
| 7709 | |
| 7710 static void | |
| 7711 update_internal_cache_list (struct window *w, int type) | |
| 7712 { | |
| 7713 int line; | |
| 7714 display_line_dynarr *dla = window_display_lines (w, type); | |
| 7715 | |
| 7716 Dynarr_reset (internal_cache); | |
| 7717 for (line = 0; line < Dynarr_length (dla); line++) | |
| 7718 { | |
| 7719 struct display_line *dl = Dynarr_atp (dla, line); | |
| 7720 | |
| 7721 if (dl->modeline) | |
| 7722 continue; | |
| 7723 else | |
| 7724 { | |
| 7725 struct line_start_cache lsc; | |
| 434 | 7726 |
| 826 | 7727 lsc.start = dl->charpos; |
| 7728 lsc.end = dl->end_charpos; | |
| 428 | 7729 lsc.height = dl->ascent + dl->descent; |
| 7730 | |
| 7731 Dynarr_add (internal_cache, lsc); | |
| 7732 } | |
| 7733 } | |
| 7734 } | |
| 7735 | |
| 7736 /* Reset the line cache if necessary. This should be run at the | |
| 7737 beginning of any function which access the cache. */ | |
| 7738 | |
| 7739 static void | |
| 7740 validate_line_start_cache (struct window *w) | |
| 7741 { | |
| 7742 struct buffer *b = XBUFFER (w->buffer); | |
| 7743 struct frame *f = XFRAME (w->frame); | |
| 7744 | |
| 7745 if (!w->line_cache_validation_override) | |
| 7746 { | |
| 7747 /* f->extents_changed used to be in here because extent face and | |
| 4187 | 7748 size changes can cause text shifting. However, the extent |
| 7749 covering the region is constantly having its face set and | |
| 7750 priority altered by the mouse code. This means that the line | |
| 7751 start cache is constantly being invalidated. This is bad | |
| 7752 since the mouse code also triggers heavy usage of the cache. | |
| 7753 Since it is an unlikely that f->extents being changed | |
| 7754 indicates that the cache really needs to be updated and if it | |
| 7755 does redisplay will catch it pretty quickly we no longer | |
| 7756 invalidate the cache if it is set. This greatly speeds up | |
| 7757 dragging out regions with the mouse. */ | |
| 428 | 7758 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b) |
| 7759 || f->faces_changed | |
| 7760 || f->clip_changed) | |
| 7761 { | |
| 7762 Dynarr_reset (w->line_start_cache); | |
| 7763 } | |
| 7764 } | |
| 7765 } | |
| 7766 | |
| 7767 /* Return the very first buffer position contained in the given | |
| 7768 window's cache, or -1 if the cache is empty. Assumes that the | |
| 7769 cache is valid. */ | |
| 7770 | |
| 665 | 7771 static Charbpos |
| 428 | 7772 line_start_cache_start (struct window *w) |
| 7773 { | |
| 7774 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 7775 | |
| 7776 if (!Dynarr_length (cache)) | |
| 7777 return -1; | |
| 7778 else | |
| 4967 | 7779 return Dynarr_begin (cache)->start; |
| 428 | 7780 } |
| 7781 | |
| 7782 /* Return the very last buffer position contained in the given | |
| 7783 window's cache, or -1 if the cache is empty. Assumes that the | |
| 7784 cache is valid. */ | |
| 7785 | |
| 665 | 7786 static Charbpos |
| 428 | 7787 line_start_cache_end (struct window *w) |
| 7788 { | |
| 7789 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 7790 | |
| 7791 if (!Dynarr_length (cache)) | |
| 7792 return -1; | |
| 7793 else | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7794 return Dynarr_lastp (cache)->end; |
| 428 | 7795 } |
| 7796 | |
| 7797 /* Return the index of the line POINT is contained within in window | |
| 7798 W's line start cache. It will enlarge the cache or move the cache | |
| 7799 window in order to have POINT be present in the cache. MIN_PAST is | |
| 7800 a guarantee of the number of entries in the cache present on either | |
| 7801 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1 | |
| 7802 then it will be treated as 0, but the cache window will not be | |
| 7803 allowed to shift. Returns -1 if POINT cannot be found in the cache | |
| 7804 for any reason. */ | |
| 7805 | |
| 7806 int | |
| 665 | 7807 point_in_line_start_cache (struct window *w, Charbpos point, int min_past) |
| 428 | 7808 { |
| 7809 struct buffer *b = XBUFFER (w->buffer); | |
| 7810 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 647 | 7811 int top, bottom, pos; |
| 428 | 7812 |
| 7813 validate_line_start_cache (w); | |
| 7814 w->line_cache_validation_override++; | |
| 7815 | |
| 7816 /* Let functions pass in negative values, but we still treat -1 | |
| 7817 specially. */ | |
| 7818 /* #### bogosity alert */ | |
| 7819 if (min_past < 0 && min_past != -1) | |
| 7820 min_past = -min_past; | |
| 7821 | |
| 7822 if (!Dynarr_length (cache) || line_start_cache_start (w) > point | |
| 7823 || line_start_cache_end (w) < point) | |
| 7824 { | |
| 7825 int loop; | |
| 7826 int win_char_height = window_char_height (w, 1); | |
| 7827 | |
| 7828 /* Occasionally we get here with a 0 height | |
| 4187 | 7829 window. find_next_newline_no_quit will abort if we pass it a |
| 7830 count of 0 so handle that case. */ | |
| 428 | 7831 if (!win_char_height) |
| 7832 win_char_height = 1; | |
| 7833 | |
| 7834 if (!Dynarr_length (cache)) | |
| 7835 { | |
| 665 | 7836 Charbpos from = find_next_newline_no_quit (b, point, -1); |
| 7837 Charbpos to = find_next_newline_no_quit (b, from, win_char_height); | |
| 428 | 7838 |
| 7839 update_line_start_cache (w, from, to, point, 0); | |
| 7840 | |
| 7841 if (!Dynarr_length (cache)) | |
| 7842 { | |
| 7843 w->line_cache_validation_override--; | |
| 7844 return -1; | |
| 7845 } | |
| 7846 } | |
| 7847 | |
| 7848 assert (Dynarr_length (cache)); | |
| 7849 | |
| 7850 loop = 0; | |
| 7851 while (line_start_cache_start (w) > point | |
| 7852 && (loop < cache_adjustment || min_past == -1)) | |
| 7853 { | |
| 665 | 7854 Charbpos from, to; |
| 428 | 7855 |
| 7856 from = line_start_cache_start (w); | |
| 7857 if (from <= BUF_BEGV (b)) | |
| 7858 break; | |
| 7859 | |
| 7860 from = find_next_newline_no_quit (b, from, -win_char_height); | |
| 7861 to = line_start_cache_end (w); | |
| 7862 | |
| 7863 update_line_start_cache (w, from, to, point, 0); | |
| 7864 loop++; | |
| 7865 } | |
| 7866 | |
| 7867 if (line_start_cache_start (w) > point) | |
| 7868 { | |
| 665 | 7869 Charbpos from, to; |
| 428 | 7870 |
| 7871 from = find_next_newline_no_quit (b, point, -1); | |
| 7872 if (from >= BUF_ZV (b)) | |
| 7873 { | |
| 7874 to = find_next_newline_no_quit (b, from, -win_char_height); | |
| 7875 from = to; | |
| 7876 to = BUF_ZV (b); | |
| 7877 } | |
| 7878 else | |
| 7879 to = find_next_newline_no_quit (b, from, win_char_height); | |
| 7880 | |
| 7881 update_line_start_cache (w, from, to, point, 0); | |
| 7882 } | |
| 7883 | |
| 7884 loop = 0; | |
| 7885 while (line_start_cache_end (w) < point | |
| 7886 && (loop < cache_adjustment || min_past == -1)) | |
| 7887 { | |
| 665 | 7888 Charbpos from, to; |
| 428 | 7889 |
| 7890 to = line_start_cache_end (w); | |
| 7891 if (to >= BUF_ZV (b)) | |
| 7892 break; | |
| 7893 | |
| 7894 from = line_start_cache_end (w); | |
| 7895 to = find_next_newline_no_quit (b, from, win_char_height); | |
| 7896 | |
| 7897 update_line_start_cache (w, from, to, point, 0); | |
| 7898 loop++; | |
| 7899 } | |
| 7900 | |
| 7901 if (line_start_cache_end (w) < point) | |
| 7902 { | |
| 665 | 7903 Charbpos from, to; |
| 428 | 7904 |
| 7905 from = find_next_newline_no_quit (b, point, -1); | |
| 7906 if (from >= BUF_ZV (b)) | |
| 7907 { | |
| 7908 to = find_next_newline_no_quit (b, from, -win_char_height); | |
| 7909 from = to; | |
| 7910 to = BUF_ZV (b); | |
| 7911 } | |
| 7912 else | |
| 7913 to = find_next_newline_no_quit (b, from, win_char_height); | |
| 7914 | |
| 7915 update_line_start_cache (w, from, to, point, 0); | |
| 7916 } | |
| 7917 } | |
| 7918 | |
| 7919 assert (Dynarr_length (cache)); | |
| 7920 | |
| 7921 if (min_past == -1) | |
| 7922 min_past = 0; | |
| 7923 | |
| 7924 /* This could happen if the buffer is narrowed. */ | |
| 7925 if (line_start_cache_start (w) > point | |
| 7926 || line_start_cache_end (w) < point) | |
| 7927 { | |
| 7928 w->line_cache_validation_override--; | |
| 7929 return -1; | |
| 7930 } | |
| 7931 | |
| 7932 find_point_loop: | |
| 7933 | |
| 7934 top = Dynarr_length (cache) - 1; | |
| 7935 bottom = 0; | |
| 7936 | |
| 7937 while (1) | |
| 7938 { | |
| 647 | 7939 int new_pos; |
| 665 | 7940 Charbpos start, end; |
| 428 | 7941 |
| 7942 pos = (bottom + top + 1) >> 1; | |
| 7943 start = Dynarr_atp (cache, pos)->start; | |
| 7944 end = Dynarr_atp (cache, pos)->end; | |
| 7945 | |
| 7946 if (point >= start && point <= end) | |
| 7947 { | |
| 7948 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b)) | |
| 7949 { | |
| 665 | 7950 Charbpos from = |
| 428 | 7951 find_next_newline_no_quit (b, line_start_cache_start (w), |
| 7952 -min_past - 1); | |
| 665 | 7953 Charbpos to = line_start_cache_end (w); |
| 428 | 7954 |
| 7955 update_line_start_cache (w, from, to, point, 0); | |
| 7956 goto find_point_loop; | |
| 7957 } | |
| 7958 else if ((Dynarr_length (cache) - pos - 1) < min_past | |
| 7959 && line_start_cache_end (w) < BUF_ZV (b)) | |
| 7960 { | |
| 665 | 7961 Charbpos from = line_start_cache_end (w); |
| 7962 Charbpos to = find_next_newline_no_quit (b, from, | |
| 428 | 7963 (min_past |
| 7964 ? min_past | |
| 7965 : 1)); | |
| 7966 | |
| 7967 update_line_start_cache (w, from, to, point, 0); | |
| 7968 goto find_point_loop; | |
| 7969 } | |
| 7970 else | |
| 7971 { | |
| 7972 w->line_cache_validation_override--; | |
| 7973 return pos; | |
| 7974 } | |
| 7975 } | |
| 7976 else if (point > end) | |
| 7977 bottom = pos + 1; | |
| 7978 else if (point < start) | |
| 7979 top = pos - 1; | |
| 7980 else | |
| 2500 | 7981 ABORT (); |
| 428 | 7982 |
| 7983 new_pos = (bottom + top + 1) >> 1; | |
| 7984 if (pos == new_pos) | |
| 7985 { | |
| 7986 w->line_cache_validation_override--; | |
| 7987 return -1; | |
| 7988 } | |
| 7989 } | |
| 7990 } | |
| 7991 | |
| 7992 /* Return a boolean indicating if POINT would be visible in window W | |
| 1708 | 7993 if display of the window was to begin at STARTP. If PARTIALLY is |
| 7994 zero, then if POINT has fewer visible pixels than the window clip, | |
| 7995 0 is returned; otherwise, 1 is returned if POINT has any visible | |
| 7996 pixels. */ | |
| 428 | 7997 int |
| 1708 | 7998 point_would_be_visible (struct window *w, Charbpos startp, Charbpos point, |
| 7999 int partially) | |
| 428 | 8000 { |
| 8001 struct buffer *b = XBUFFER (w->buffer); | |
| 5198 | 8002 int pixpos = -WINDOW_TEXT_TOP_CLIP (w); |
| 428 | 8003 int bottom = WINDOW_TEXT_HEIGHT (w); |
| 8004 int start_elt; | |
| 8005 | |
| 8006 /* If point is before the intended start it obviously can't be visible. */ | |
| 8007 if (point < startp) | |
| 8008 return 0; | |
| 8009 | |
| 8010 /* If point or start are not in the accessible buffer range, then | |
| 8011 fail. */ | |
| 8012 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b) | |
| 8013 || point < BUF_BEGV (b) || point > BUF_ZV (b)) | |
| 8014 return 0; | |
| 8015 | |
| 8016 validate_line_start_cache (w); | |
| 8017 w->line_cache_validation_override++; | |
| 8018 | |
| 8019 start_elt = point_in_line_start_cache (w, startp, 0); | |
| 8020 if (start_elt == -1) | |
| 8021 { | |
| 8022 w->line_cache_validation_override--; | |
| 8023 return 0; | |
| 8024 } | |
| 8025 | |
| 8026 assert (line_start_cache_start (w) <= startp | |
| 8027 && line_start_cache_end (w) >= startp); | |
| 8028 | |
| 8029 while (1) | |
| 8030 { | |
| 8031 int height; | |
| 8032 | |
| 8033 /* Expand the cache if necessary. */ | |
| 8034 if (start_elt == Dynarr_length (w->line_start_cache)) | |
| 8035 { | |
| 665 | 8036 Charbpos old_startp = |
| 428 | 8037 Dynarr_atp (w->line_start_cache, start_elt - 1)->start; |
| 8038 | |
| 8039 start_elt = point_in_line_start_cache (w, old_startp, | |
| 8040 window_char_height (w, 0)); | |
| 8041 | |
| 8042 /* We've already actually processed old_startp, so increment | |
| 4187 | 8043 immediately. */ |
| 428 | 8044 start_elt++; |
| 8045 | |
| 8046 /* If this happens we didn't add any extra elements. Bummer. */ | |
| 8047 if (start_elt == Dynarr_length (w->line_start_cache)) | |
| 8048 { | |
| 8049 w->line_cache_validation_override--; | |
| 8050 return 0; | |
| 8051 } | |
| 8052 } | |
| 8053 | |
| 8054 height = Dynarr_atp (w->line_start_cache, start_elt)->height; | |
| 8055 | |
| 8056 if (pixpos + height > bottom) | |
| 8057 { | |
| 1708 | 8058 if (bottom - pixpos < (partially ? 0 : VERTICAL_CLIP (w, 0))) |
| 428 | 8059 { |
| 8060 w->line_cache_validation_override--; | |
| 8061 return 0; | |
| 8062 } | |
| 8063 } | |
| 8064 | |
| 8065 pixpos += height; | |
| 8066 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end) | |
| 8067 { | |
| 8068 w->line_cache_validation_override--; | |
| 8069 return 1; | |
| 8070 } | |
| 8071 | |
| 8072 start_elt++; | |
| 8073 } | |
| 8074 } | |
| 8075 | |
| 8076 /* For the given window W, if display starts at STARTP, what will be | |
| 8077 the buffer position at the beginning or end of the last line | |
| 8078 displayed. The end of the last line is also know as the window end | |
| 8079 position. | |
| 8080 | |
| 442 | 8081 WARNING: It is possible that redisplay failed to layout any lines for the |
| 8082 windows. Under normal circumstances this is rare. However it seems that it | |
| 8083 does occur in the following situation: A mouse event has come in and we | |
| 8084 need to compute its location in a window. That code (in | |
| 8085 pixel_to_glyph_translation) already can handle 0 as an error return value. | |
| 8086 | |
| 428 | 8087 #### With a little work this could probably be reworked as just a |
| 8088 call to start_with_line_at_pixpos. */ | |
| 8089 | |
| 665 | 8090 static Charbpos |
| 8091 start_end_of_last_line (struct window *w, Charbpos startp, int end, | |
| 4187 | 8092 int may_error) |
| 428 | 8093 { |
| 8094 struct buffer *b = XBUFFER (w->buffer); | |
| 8095 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 8096 int pixpos = 0; | |
| 8097 int bottom = WINDOW_TEXT_HEIGHT (w); | |
| 665 | 8098 Charbpos cur_start; |
| 428 | 8099 int start_elt; |
| 8100 | |
| 8101 validate_line_start_cache (w); | |
| 8102 w->line_cache_validation_override++; | |
| 8103 | |
| 8104 if (startp < BUF_BEGV (b)) | |
| 8105 startp = BUF_BEGV (b); | |
| 8106 else if (startp > BUF_ZV (b)) | |
| 8107 startp = BUF_ZV (b); | |
| 8108 cur_start = startp; | |
| 8109 | |
| 8110 start_elt = point_in_line_start_cache (w, cur_start, 0); | |
| 8111 if (start_elt == -1) | |
| 442 | 8112 return may_error ? 0 : startp; |
| 428 | 8113 |
| 8114 while (1) | |
| 8115 { | |
| 8116 int height = Dynarr_atp (cache, start_elt)->height; | |
| 8117 | |
| 8118 cur_start = Dynarr_atp (cache, start_elt)->start; | |
| 8119 | |
| 8120 if (pixpos + height > bottom) | |
| 8121 { | |
| 8122 /* Adjust for any possible clip. */ | |
| 8123 if (bottom - pixpos < VERTICAL_CLIP (w, 0)) | |
| 8124 start_elt--; | |
| 8125 | |
| 8126 if (start_elt < 0) | |
| 8127 { | |
| 8128 w->line_cache_validation_override--; | |
| 8129 if (end) | |
| 8130 return BUF_ZV (b); | |
| 8131 else | |
| 8132 return BUF_BEGV (b); | |
| 8133 } | |
| 8134 else | |
| 8135 { | |
| 8136 w->line_cache_validation_override--; | |
| 8137 if (end) | |
| 8138 return Dynarr_atp (cache, start_elt)->end; | |
| 8139 else | |
| 8140 return Dynarr_atp (cache, start_elt)->start; | |
| 8141 } | |
| 8142 } | |
| 8143 | |
| 8144 pixpos += height; | |
| 8145 start_elt++; | |
| 8146 if (start_elt == Dynarr_length (cache)) | |
| 8147 { | |
| 665 | 8148 Charbpos from = line_start_cache_end (w); |
| 428 | 8149 int win_char_height = window_char_height (w, 0); |
| 665 | 8150 Charbpos to = find_next_newline_no_quit (b, from, |
| 428 | 8151 (win_char_height |
| 8152 ? win_char_height | |
| 8153 : 1)); | |
| 8154 | |
| 8155 /* We've hit the end of the bottom so that's what it is. */ | |
| 8156 if (from >= BUF_ZV (b)) | |
| 8157 { | |
| 8158 w->line_cache_validation_override--; | |
| 8159 return BUF_ZV (b); | |
| 8160 } | |
| 8161 | |
| 8162 update_line_start_cache (w, from, to, BUF_PT (b), 0); | |
| 8163 | |
| 8164 /* Updating the cache invalidates any current indexes. */ | |
| 8165 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1; | |
| 8166 } | |
| 8167 } | |
| 8168 } | |
| 8169 | |
| 8170 /* For the given window W, if display starts at STARTP, what will be | |
| 8171 the buffer position at the beginning of the last line displayed. */ | |
| 8172 | |
| 665 | 8173 Charbpos |
| 8174 start_of_last_line (struct window *w, Charbpos startp) | |
| 428 | 8175 { |
| 442 | 8176 return start_end_of_last_line (w, startp, 0 , 0); |
| 428 | 8177 } |
| 8178 | |
| 8179 /* For the given window W, if display starts at STARTP, what will be | |
| 8180 the buffer position at the end of the last line displayed. This is | |
| 8181 also know as the window end position. */ | |
| 8182 | |
| 665 | 8183 Charbpos |
| 8184 end_of_last_line (struct window *w, Charbpos startp) | |
| 428 | 8185 { |
| 442 | 8186 return start_end_of_last_line (w, startp, 1, 0); |
| 428 | 8187 } |
| 8188 | |
| 665 | 8189 static Charbpos |
| 8190 end_of_last_line_may_error (struct window *w, Charbpos startp) | |
| 442 | 8191 { |
| 8192 return start_end_of_last_line (w, startp, 1, 1); | |
| 8193 } | |
| 8194 | |
| 8195 | |
| 428 | 8196 /* For window W, what does the starting position have to be so that |
| 8197 the line containing POINT will cover pixel position PIXPOS. */ | |
| 8198 | |
| 665 | 8199 Charbpos |
| 8200 start_with_line_at_pixpos (struct window *w, Charbpos point, int pixpos) | |
| 428 | 8201 { |
| 8202 struct buffer *b = XBUFFER (w->buffer); | |
| 8203 int cur_elt; | |
| 665 | 8204 Charbpos cur_pos, prev_pos = point; |
| 428 | 8205 int point_line_height; |
| 8206 int pixheight = pixpos - WINDOW_TEXT_TOP (w); | |
| 8207 | |
| 8208 validate_line_start_cache (w); | |
| 8209 w->line_cache_validation_override++; | |
| 8210 | |
| 8211 cur_elt = point_in_line_start_cache (w, point, 0); | |
| 8212 /* #### See comment in update_line_start_cache about big minibuffers. */ | |
| 8213 if (cur_elt < 0) | |
| 8214 { | |
| 8215 w->line_cache_validation_override--; | |
| 8216 return point; | |
| 8217 } | |
| 8218 | |
| 8219 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
| 8220 | |
| 8221 while (1) | |
| 8222 { | |
| 8223 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
| 8224 | |
| 8225 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
| 8226 | |
| 8227 /* Do not take into account the value of vertical_clip here. | |
| 4187 | 8228 That is the responsibility of the calling functions. */ |
| 428 | 8229 if (pixheight < 0) |
| 8230 { | |
| 8231 w->line_cache_validation_override--; | |
| 8232 if (-pixheight > point_line_height) | |
| 8233 /* We can't make the target line cover pixpos, so put it | |
| 8234 above pixpos. That way it will at least be visible. */ | |
| 8235 return prev_pos; | |
| 8236 else | |
| 8237 return cur_pos; | |
| 8238 } | |
| 8239 | |
| 8240 cur_elt--; | |
| 8241 while (cur_elt < 0) | |
| 8242 { | |
| 665 | 8243 Charbpos from, to; |
| 428 | 8244 int win_char_height; |
| 8245 | |
| 8246 if (cur_pos <= BUF_BEGV (b)) | |
| 8247 { | |
| 8248 w->line_cache_validation_override--; | |
| 8249 return BUF_BEGV (b); | |
| 8250 } | |
| 8251 | |
| 8252 win_char_height = window_char_height (w, 0); | |
| 8253 if (!win_char_height) | |
| 8254 win_char_height = 1; | |
| 8255 | |
| 8256 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); | |
| 8257 to = line_start_cache_end (w); | |
| 8258 update_line_start_cache (w, from, to, point, 0); | |
| 8259 | |
| 8260 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; | |
| 8261 assert (cur_elt >= -1); | |
| 8262 /* This used to be cur_elt>=0 under the assumption that if | |
| 8263 point is in the top line and not at BUF_BEGV, then | |
| 434 | 8264 setting the window_start to a newline before the start of |
| 428 | 8265 the first line will always cause scrolling. |
| 8266 | |
| 8267 However in my (jv) opinion this is wrong. That new line | |
| 8268 can be hidden in various ways: invisible extents, an | |
| 8269 explicit window-start not at a newline character etc. | |
| 8270 The existence of those are indeed known to create crashes | |
| 8271 on that assert. So we have no option but to continue the | |
| 8272 search if we found point at the top of the line_start_cache | |
| 8273 again. */ | |
| 4967 | 8274 cur_pos = Dynarr_begin (w->line_start_cache)->start; |
| 428 | 8275 } |
| 8276 prev_pos = cur_pos; | |
| 8277 } | |
| 8278 } | |
| 8279 | |
| 8280 /* For window W, what does the starting position have to be so that | |
| 8281 the line containing point is on display line LINE. If LINE is | |
| 8282 positive it is considered to be the number of lines from the top of | |
| 8283 the window (0 is the top line). If it is negative the number is | |
| 8284 considered to be the number of lines from the bottom (-1 is the | |
| 8285 bottom line). */ | |
| 8286 | |
| 665 | 8287 Charbpos |
| 8288 start_with_point_on_display_line (struct window *w, Charbpos point, int line) | |
| 428 | 8289 { |
| 8290 validate_line_start_cache (w); | |
| 8291 w->line_cache_validation_override++; | |
| 8292 | |
| 8293 if (line >= 0) | |
| 8294 { | |
| 8295 int cur_elt = point_in_line_start_cache (w, point, line); | |
| 8296 | |
| 8297 if (cur_elt - line < 0) | |
| 8298 cur_elt = 0; /* Hit the top */ | |
| 8299 else | |
| 8300 cur_elt -= line; | |
| 8301 | |
| 8302 w->line_cache_validation_override--; | |
| 8303 return Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
| 8304 } | |
| 8305 else | |
| 8306 { | |
| 8307 /* The calculated value of pixpos is correct for the bottom line | |
| 4187 | 8308 or what we want when line is -1. Therefore we subtract one |
| 8309 because we have already handled one line. */ | |
| 428 | 8310 int new_line = -line - 1; |
| 8311 int cur_elt = point_in_line_start_cache (w, point, new_line); | |
| 8312 int pixpos = WINDOW_TEXT_BOTTOM (w); | |
| 665 | 8313 Charbpos retval, search_point; |
| 428 | 8314 |
| 8315 /* If scroll_on_clipped_lines is false, the last "visible" line of | |
| 4187 | 8316 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1. |
| 8317 If s_o_c_l is true, then we don't want to count a clipped | |
| 8318 line, so back up from the bottom by the height of the line | |
| 8319 containing point. */ | |
| 428 | 8320 if (scroll_on_clipped_lines) |
| 8321 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
| 8322 else | |
| 8323 pixpos -= 1; | |
| 8324 | |
| 8325 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache)) | |
| 8326 { | |
| 8327 /* Hit the bottom of the buffer. */ | |
| 8328 int adjustment = | |
| 8329 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1; | |
| 8330 Lisp_Object window; | |
| 8331 int defheight; | |
| 8332 | |
| 793 | 8333 window = wrap_window (w); |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
8334 default_face_width_and_height (window, 0, &defheight); |
| 428 | 8335 |
| 8336 cur_elt = Dynarr_length (w->line_start_cache) - 1; | |
| 8337 | |
| 8338 pixpos -= (adjustment * defheight); | |
| 8339 if (pixpos < WINDOW_TEXT_TOP (w)) | |
| 8340 pixpos = WINDOW_TEXT_TOP (w); | |
| 8341 } | |
| 8342 else | |
| 8343 cur_elt = cur_elt + new_line; | |
| 8344 | |
| 8345 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
| 8346 | |
| 8347 retval = start_with_line_at_pixpos (w, search_point, pixpos); | |
| 8348 w->line_cache_validation_override--; | |
| 8349 return retval; | |
| 8350 } | |
| 8351 } | |
| 8352 | |
| 8353 /* This is used to speed up vertical scrolling by caching the known | |
| 8354 buffer starting positions for display lines. This allows the | |
| 8355 scrolling routines to avoid costly calls to regenerate_window. If | |
| 8356 NO_REGEN is true then it will only add the values in the DESIRED | |
| 8357 display structs which are in the given range. | |
| 8358 | |
| 8359 Note also that the FROM/TO values are minimums. It is possible | |
| 8360 that this function will actually add information outside of the | |
| 8361 lines containing those positions. This can't hurt but it could | |
| 8362 possibly help. | |
| 8363 | |
| 8364 #### We currently force the cache to have only 1 contiguous region. | |
| 8365 It might help to make the cache a dynarr of caches so that we can | |
| 8366 cover more areas. This might, however, turn out to be a lot of | |
| 8367 overhead for too little gain. */ | |
| 8368 | |
| 8369 static void | |
| 665 | 8370 update_line_start_cache (struct window *w, Charbpos from, Charbpos to, |
| 8371 Charbpos point, int no_regen) | |
| 428 | 8372 { |
| 8373 struct buffer *b = XBUFFER (w->buffer); | |
| 8374 line_start_cache_dynarr *cache = w->line_start_cache; | |
| 665 | 8375 Charbpos low_bound, high_bound; |
| 428 | 8376 |
| 8377 validate_line_start_cache (w); | |
| 8378 w->line_cache_validation_override++; | |
| 8379 | |
| 8380 if (from < BUF_BEGV (b)) | |
| 8381 from = BUF_BEGV (b); | |
| 8382 if (to > BUF_ZV (b)) | |
| 8383 to = BUF_ZV (b); | |
| 8384 | |
| 8385 if (from > to) | |
| 8386 { | |
| 8387 w->line_cache_validation_override--; | |
| 8388 return; | |
| 8389 } | |
| 8390 | |
| 8391 if (Dynarr_length (cache)) | |
| 8392 { | |
| 8393 low_bound = line_start_cache_start (w); | |
| 8394 high_bound = line_start_cache_end (w); | |
| 8395 | |
| 8396 /* Check to see if the desired range is already in the cache. */ | |
| 8397 if (from >= low_bound && to <= high_bound) | |
| 8398 { | |
| 8399 w->line_cache_validation_override--; | |
| 8400 return; | |
| 8401 } | |
| 8402 | |
| 8403 /* Check to make sure that the desired range is adjacent to the | |
| 8404 current cache. If not, invalidate the cache. */ | |
| 8405 if (to < low_bound || from > high_bound) | |
| 8406 { | |
| 8407 Dynarr_reset (cache); | |
| 8408 low_bound = high_bound = -1; | |
| 8409 } | |
| 8410 } | |
| 8411 else | |
| 8412 { | |
| 8413 low_bound = high_bound = -1; | |
| 8414 } | |
| 8415 | |
| 8416 w->line_cache_last_updated = make_int (BUF_MODIFF (b)); | |
| 8417 | |
| 8418 /* This could be integrated into the next two sections, but it is easier | |
| 8419 to follow what's going on by having it separate. */ | |
| 8420 if (no_regen) | |
| 8421 { | |
| 665 | 8422 Charbpos start, end; |
| 428 | 8423 |
| 8424 update_internal_cache_list (w, DESIRED_DISP); | |
| 8425 if (!Dynarr_length (internal_cache)) | |
| 8426 { | |
| 8427 w->line_cache_validation_override--; | |
| 8428 return; | |
| 8429 } | |
| 8430 | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8431 start = Dynarr_begin (internal_cache)->start; |
|
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8432 end = Dynarr_lastp (internal_cache)->end; |
| 428 | 8433 |
| 8434 /* We aren't allowed to generate additional information to fill in | |
| 4187 | 8435 gaps, so if the DESIRED structs don't overlap the cache, reset the |
| 8436 cache. */ | |
| 428 | 8437 if (Dynarr_length (cache)) |
| 8438 { | |
| 8439 if (end < low_bound || start > high_bound) | |
| 8440 Dynarr_reset (cache); | |
| 8441 | |
| 8442 /* #### What should really happen if what we are doing is | |
| 4187 | 8443 extending a line (the last line)? */ |
| 428 | 8444 if (Dynarr_length (cache) == 1 |
| 8445 && Dynarr_length (internal_cache) == 1) | |
| 8446 Dynarr_reset (cache); | |
| 8447 } | |
| 8448 | |
| 8449 if (!Dynarr_length (cache)) | |
| 8450 { | |
| 4967 | 8451 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
| 428 | 8452 Dynarr_length (internal_cache)); |
| 8453 w->line_cache_validation_override--; | |
| 8454 return; | |
| 8455 } | |
| 8456 | |
| 8457 /* An extra check just in case the calling function didn't pass in | |
| 4187 | 8458 the bounds of the DESIRED structs in the first place. */ |
| 428 | 8459 if (start >= low_bound && end <= high_bound) |
| 8460 { | |
| 8461 w->line_cache_validation_override--; | |
| 8462 return; | |
| 8463 } | |
| 8464 | |
| 8465 /* At this point we know that the internal cache partially overlaps | |
| 4187 | 8466 the main cache. */ |
| 428 | 8467 if (start < low_bound) |
| 8468 { | |
| 8469 int ic_elt = Dynarr_length (internal_cache) - 1; | |
| 8470 while (ic_elt >= 0) | |
| 8471 { | |
| 8472 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound) | |
| 8473 break; | |
| 8474 else | |
| 8475 ic_elt--; | |
| 8476 } | |
| 8477 | |
| 8478 if (!(ic_elt >= 0)) | |
| 8479 { | |
| 8480 Dynarr_reset (cache); | |
| 4967 | 8481 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
| 428 | 8482 Dynarr_length (internal_cache)); |
| 8483 w->line_cache_validation_override--; | |
| 8484 return; | |
| 8485 } | |
| 8486 | |
| 5038 | 8487 Dynarr_prepend_many (cache, Dynarr_begin (internal_cache), |
| 428 | 8488 ic_elt + 1); |
| 8489 } | |
| 8490 | |
| 8491 if (end > high_bound) | |
| 8492 { | |
| 8493 int ic_elt = 0; | |
| 8494 | |
| 8495 while (ic_elt < Dynarr_length (internal_cache)) | |
| 8496 { | |
| 8497 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound) | |
| 8498 break; | |
| 8499 else | |
| 8500 ic_elt++; | |
| 8501 } | |
| 8502 | |
| 8503 if (!(ic_elt < Dynarr_length (internal_cache))) | |
| 8504 { | |
| 8505 Dynarr_reset (cache); | |
| 4967 | 8506 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
| 428 | 8507 Dynarr_length (internal_cache)); |
| 8508 w->line_cache_validation_override--; | |
| 8509 return; | |
| 8510 } | |
| 8511 | |
| 8512 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), | |
| 8513 Dynarr_length (internal_cache) - ic_elt); | |
| 8514 } | |
| 8515 | |
| 8516 w->line_cache_validation_override--; | |
| 8517 return; | |
| 8518 } | |
| 8519 | |
| 8520 if (!Dynarr_length (cache) || from < low_bound) | |
| 8521 { | |
| 665 | 8522 Charbpos startp = find_next_newline_no_quit (b, from, -1); |
| 428 | 8523 int marker = 0; |
| 8524 int old_lb = low_bound; | |
| 8525 | |
| 8526 while (startp < old_lb || low_bound == -1) | |
| 8527 { | |
| 8528 int ic_elt; | |
| 4187 | 8529 Charbpos new_startp; |
| 428 | 8530 |
| 8531 regenerate_window (w, startp, point, CMOTION_DISP); | |
| 8532 update_internal_cache_list (w, CMOTION_DISP); | |
| 8533 | |
| 8534 /* If this assert is triggered then regenerate_window failed | |
| 4187 | 8535 to layout a single line. This is not possible since we |
| 442 | 8536 force at least a single line to be layout for CMOTION_DISP */ |
| 8537 assert (Dynarr_length (internal_cache)); | |
| 4967 | 8538 assert (startp == Dynarr_begin (internal_cache)->start); |
| 428 | 8539 |
| 8540 ic_elt = Dynarr_length (internal_cache) - 1; | |
| 8541 if (low_bound != -1) | |
| 8542 { | |
| 8543 while (ic_elt >= 0) | |
| 8544 { | |
| 8545 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb) | |
| 8546 break; | |
| 8547 else | |
| 8548 ic_elt--; | |
| 8549 } | |
| 8550 } | |
| 8551 assert (ic_elt >= 0); | |
| 8552 | |
| 8553 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1; | |
| 8554 | |
| 4187 | 8555 /* |
| 8556 * Handle invisible text properly: | |
| 8557 * If the last line we're inserting has the same end as the | |
| 8558 * line before which it will be added, merge the two lines. | |
| 8559 */ | |
| 8560 if (Dynarr_length (cache) && | |
| 8561 Dynarr_atp (internal_cache, ic_elt)->end == | |
| 8562 Dynarr_atp (cache, marker)->end) | |
| 8563 { | |
| 8564 Dynarr_atp (cache, marker)->start | |
| 8565 = Dynarr_atp (internal_cache, ic_elt)->start; | |
| 8566 Dynarr_atp (cache, marker)->height | |
| 8567 = Dynarr_atp (internal_cache, ic_elt)->height; | |
| 8568 ic_elt--; | |
| 8569 } | |
| 8570 | |
| 8571 if (ic_elt >= 0) /* we still have lines to add.. */ | |
| 8572 { | |
| 4967 | 8573 Dynarr_insert_many (cache, Dynarr_begin (internal_cache), |
| 4187 | 8574 ic_elt + 1, marker); |
| 8575 marker += (ic_elt + 1); | |
| 8576 } | |
| 428 | 8577 |
| 8578 if (startp < low_bound || low_bound == -1) | |
| 8579 low_bound = startp; | |
| 8580 startp = new_startp; | |
| 8581 if (startp > BUF_ZV (b)) | |
| 8582 { | |
| 8583 w->line_cache_validation_override--; | |
| 8584 return; | |
| 8585 } | |
| 8586 } | |
| 8587 } | |
| 8588 | |
| 8589 assert (Dynarr_length (cache)); | |
| 8590 assert (from >= low_bound); | |
| 8591 | |
| 8592 /* Readjust the high_bound to account for any changes made while | |
| 8593 correcting the low_bound. */ | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8594 high_bound = Dynarr_lastp (cache)->end; |
| 428 | 8595 |
| 8596 if (to > high_bound) | |
| 8597 { | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8598 Charbpos startp = Dynarr_lastp (cache)->end + 1; |
| 428 | 8599 |
| 8600 do | |
| 8601 { | |
| 8602 regenerate_window (w, startp, point, CMOTION_DISP); | |
| 8603 update_internal_cache_list (w, CMOTION_DISP); | |
| 8604 | |
| 8605 /* See comment above about regenerate_window failing. */ | |
| 8606 assert (Dynarr_length (internal_cache)); | |
| 8607 | |
| 4967 | 8608 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
| 428 | 8609 Dynarr_length (internal_cache)); |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8610 high_bound = Dynarr_lastp (cache)->end; |
| 428 | 8611 startp = high_bound + 1; |
| 8612 } | |
| 8613 while (to > high_bound); | |
| 8614 } | |
| 8615 | |
| 8616 w->line_cache_validation_override--; | |
| 8617 assert (to <= high_bound); | |
| 8618 } | |
| 8619 | |
| 8620 | |
| 8621 /* Given x and y coordinates in characters, relative to a window, | |
| 8622 return the pixel location corresponding to those coordinates. The | |
| 8623 pixel location returned is the center of the given character | |
| 8624 position. The pixel values are generated relative to the window, | |
| 8625 not the frame. | |
| 8626 | |
| 8627 The modeline is considered to be part of the window. */ | |
| 8628 | |
| 8629 void | |
| 8630 glyph_to_pixel_translation (struct window *w, int char_x, int char_y, | |
| 8631 int *pix_x, int *pix_y) | |
| 8632 { | |
| 8633 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
| 8634 int num_disp_lines, modeline; | |
| 8635 Lisp_Object window; | |
| 8636 int defheight, defwidth; | |
| 8637 | |
| 793 | 8638 window = wrap_window (w); |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
8639 default_face_width_and_height (window, &defwidth, &defheight); |
| 428 | 8640 |
| 8641 /* If we get a bogus value indicating somewhere above or to the left of | |
| 8642 the window, use the first window line or character position | |
| 8643 instead. */ | |
| 8644 if (char_y < 0) | |
| 8645 char_y = 0; | |
| 8646 if (char_x < 0) | |
| 8647 char_x = 0; | |
| 8648 | |
| 8649 num_disp_lines = Dynarr_length (dla); | |
| 8650 modeline = 0; | |
| 8651 if (num_disp_lines) | |
| 8652 { | |
| 4967 | 8653 if (Dynarr_begin (dla)->modeline) |
| 428 | 8654 { |
| 8655 num_disp_lines--; | |
| 8656 modeline = 1; | |
| 8657 } | |
| 8658 } | |
| 8659 | |
| 8660 /* First check if the y position intersects the display lines. */ | |
| 8661 if (char_y < num_disp_lines) | |
| 8662 { | |
| 8663 struct display_line *dl = Dynarr_atp (dla, char_y + modeline); | |
| 8664 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 8665 | |
| 8666 *pix_y = (dl->ypos - dl->ascent + | |
| 647 | 8667 ((dl->ascent + dl->descent - dl->clip) >> 1)); |
| 428 | 8668 |
| 8669 if (char_x < Dynarr_length (db->runes)) | |
| 8670 { | |
| 8671 struct rune *rb = Dynarr_atp (db->runes, char_x); | |
| 8672 | |
| 8673 *pix_x = rb->xpos + (rb->width >> 1); | |
| 8674 } | |
| 8675 else | |
| 8676 { | |
| 8677 int last_rune = Dynarr_length (db->runes) - 1; | |
| 8678 struct rune *rb = Dynarr_atp (db->runes, last_rune); | |
| 8679 | |
| 8680 char_x -= last_rune; | |
| 8681 | |
| 8682 *pix_x = rb->xpos + rb->width; | |
| 8683 *pix_x += ((char_x - 1) * defwidth); | |
| 8684 *pix_x += (defwidth >> 1); | |
| 8685 } | |
| 8686 } | |
| 8687 else | |
| 8688 { | |
| 8689 /* It didn't intersect, so extrapolate. #### For now, we include the | |
| 8690 modeline in this since we don't have true character positions in | |
| 8691 it. */ | |
| 8692 | |
| 8693 if (!Dynarr_length (w->face_cachels)) | |
| 8694 reset_face_cachels (w); | |
| 8695 | |
| 8696 char_y -= num_disp_lines; | |
| 8697 | |
| 8698 if (Dynarr_length (dla)) | |
| 8699 { | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8700 struct display_line *dl = Dynarr_lastp (dla); |
| 428 | 8701 *pix_y = dl->ypos + dl->descent - dl->clip; |
| 8702 } | |
| 8703 else | |
| 8704 *pix_y = WINDOW_TEXT_TOP (w); | |
| 8705 | |
| 8706 *pix_y += (char_y * defheight); | |
| 8707 *pix_y += (defheight >> 1); | |
| 8708 | |
| 8709 *pix_x = WINDOW_TEXT_LEFT (w); | |
| 8710 /* Don't adjust by one because this is still the unadjusted value. */ | |
| 8711 *pix_x += (char_x * defwidth); | |
| 8712 *pix_x += (defwidth >> 1); | |
| 8713 } | |
| 8714 | |
| 8715 if (*pix_x > w->pixel_left + w->pixel_width) | |
| 8716 *pix_x = w->pixel_left + w->pixel_width; | |
| 8717 if (*pix_y > w->pixel_top + w->pixel_height) | |
| 8718 *pix_y = w->pixel_top + w->pixel_height; | |
| 8719 | |
| 8720 *pix_x -= w->pixel_left; | |
| 8721 *pix_y -= w->pixel_top; | |
| 8722 } | |
| 8723 | |
| 8724 /* Given a display line and a position, determine if there is a glyph | |
| 8725 there and return information about it if there is. */ | |
| 8726 | |
| 8727 static void | |
| 8728 get_position_object (struct display_line *dl, Lisp_Object *obj1, | |
| 8729 Lisp_Object *obj2, int x_coord, int *low_x_coord, | |
| 8730 int *high_x_coord) | |
| 8731 { | |
| 8732 struct display_block *db; | |
| 8733 int elt; | |
| 8734 int block = | |
| 8735 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0); | |
| 8736 | |
| 8737 /* We use get_next_display_block to get the actual display block | |
| 8738 that would be displayed at x_coord. */ | |
| 8739 | |
| 8740 if (block == NO_BLOCK) | |
| 8741 return; | |
| 8742 else | |
| 8743 db = Dynarr_atp (dl->display_blocks, block); | |
| 8744 | |
| 8745 for (elt = 0; elt < Dynarr_length (db->runes); elt++) | |
| 8746 { | |
| 8747 struct rune *rb = Dynarr_atp (db->runes, elt); | |
| 8748 | |
| 8749 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) | |
| 8750 { | |
| 8751 if (rb->type == RUNE_DGLYPH) | |
| 8752 { | |
| 8753 *obj1 = rb->object.dglyph.glyph; | |
| 8754 *obj2 = rb->object.dglyph.extent; | |
| 8755 } | |
| 8756 else | |
| 8757 { | |
| 8758 *obj1 = Qnil; | |
| 8759 *obj2 = Qnil; | |
| 8760 } | |
| 8761 | |
| 8762 if (low_x_coord) | |
| 8763 *low_x_coord = rb->xpos; | |
| 8764 if (high_x_coord) | |
| 8765 *high_x_coord = rb->xpos + rb->width; | |
| 8766 | |
| 8767 return; | |
| 8768 } | |
| 8769 } | |
| 8770 } | |
| 8771 | |
| 8772 #define UPDATE_CACHE_RETURN \ | |
| 8773 do { \ | |
| 8774 d->pixel_to_glyph_cache.valid = 1; \ | |
| 8775 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \ | |
| 8776 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \ | |
| 8777 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \ | |
| 8778 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \ | |
| 8779 d->pixel_to_glyph_cache.frame = f; \ | |
| 8780 d->pixel_to_glyph_cache.col = *col; \ | |
| 8781 d->pixel_to_glyph_cache.row = *row; \ | |
| 8782 d->pixel_to_glyph_cache.obj_x = *obj_x; \ | |
| 8783 d->pixel_to_glyph_cache.obj_y = *obj_y; \ | |
| 8784 d->pixel_to_glyph_cache.w = *w; \ | |
| 5090 | 8785 d->pixel_to_glyph_cache.charpos = *charpos; \ |
| 428 | 8786 d->pixel_to_glyph_cache.closest = *closest; \ |
| 8787 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \ | |
| 8788 d->pixel_to_glyph_cache.obj1 = *obj1; \ | |
| 8789 d->pixel_to_glyph_cache.obj2 = *obj2; \ | |
| 8790 d->pixel_to_glyph_cache.retval = position; \ | |
| 8791 RETURN_SANS_WARNINGS position; \ | |
| 8792 } while (0) | |
| 8793 | |
| 8794 /* Given x and y coordinates in pixels relative to a frame, return | |
| 8795 information about what is located under those coordinates. | |
| 8796 | |
| 8797 The return value will be one of: | |
| 8798 | |
| 8799 OVER_TOOLBAR: over one of the 4 frame toolbars | |
| 8800 OVER_MODELINE: over a modeline | |
| 8801 OVER_BORDER: over an internal border | |
| 5090 | 8802 OVER_V_DIVIDER: over a vertical divider between windows (used as a |
| 8803 grab bar for resizing) | |
| 428 | 8804 OVER_NOTHING: over the text area, but not over text |
| 8805 OVER_OUTSIDE: outside of the frame border | |
| 8806 OVER_TEXT: over text in the text area | |
| 8807 | |
| 5090 | 8808 #### GEOM! We need to also have an OVER_GUTTER, OVER_SCROLLBAR and |
| 8809 OVER_DEAD_BOX. | |
| 8810 | |
| 428 | 8811 OBJ1 is one of |
| 8812 | |
| 8813 -- a toolbar button | |
| 8814 -- a glyph | |
| 8815 -- nil if the coordinates are not over a glyph or a toolbar button. | |
| 8816 | |
| 8817 OBJ2 is one of | |
| 8818 | |
| 8819 -- an extent, if the coordinates are over a glyph in the text area | |
| 8820 -- nil otherwise. | |
| 8821 | |
| 8822 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the | |
| 8823 equivalent coordinates relative to the upper-left corner of the glyph. | |
| 8824 | |
| 8825 If the coordinates are over a character, OBJ_X and OBJ_Y give the | |
| 8826 equivalent coordinates relative to the upper-left corner of the character. | |
| 8827 | |
| 8828 Otherwise, OBJ_X and OBJ_Y are undefined. | |
| 8829 */ | |
| 8830 | |
| 8831 int | |
| 8832 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, | |
| 8833 int *col, int *row, int *obj_x, int *obj_y, | |
| 826 | 8834 struct window **w, Charbpos *charpos, |
| 665 | 8835 Charbpos *closest, Charcount *modeline_closest, |
| 428 | 8836 Lisp_Object *obj1, Lisp_Object *obj2) |
| 8837 { | |
| 8838 struct device *d; | |
| 8839 struct pixel_to_glyph_translation_cache *cache; | |
| 8840 Lisp_Object window; | |
| 8841 int frm_left, frm_right, frm_top, frm_bottom; | |
| 8842 int low_x_coord, high_x_coord, low_y_coord, high_y_coord; | |
| 8843 int position = OVER_NOTHING; | |
| 8844 int device_check_failed = 0; | |
| 8845 display_line_dynarr *dla; | |
| 8846 | |
| 8847 /* This is a safety valve in case this got called with a frame in | |
| 8848 the middle of being deleted. */ | |
| 8849 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device))) | |
| 8850 { | |
| 8851 device_check_failed = 1; | |
| 8852 d = NULL, cache = NULL; /* Warning suppression */ | |
| 8853 } | |
| 8854 else | |
| 8855 { | |
| 8856 d = XDEVICE (f->device); | |
| 8857 cache = &d->pixel_to_glyph_cache; | |
| 8858 } | |
| 8859 | |
| 8860 if (!device_check_failed | |
| 8861 && cache->valid | |
| 8862 && cache->frame == f | |
| 8863 && cache->low_x_coord <= x_coord | |
| 8864 && cache->high_x_coord > x_coord | |
| 8865 && cache->low_y_coord <= y_coord | |
| 8866 && cache->high_y_coord > y_coord) | |
| 8867 { | |
| 8868 *col = cache->col; | |
| 8869 *row = cache->row; | |
| 8870 *obj_x = cache->obj_x; | |
| 8871 *obj_y = cache->obj_y; | |
| 8872 *w = cache->w; | |
| 826 | 8873 *charpos = cache->charpos; |
| 428 | 8874 *closest = cache->closest; |
| 8875 *modeline_closest = cache->modeline_closest; | |
| 8876 *obj1 = cache->obj1; | |
| 8877 *obj2 = cache->obj2; | |
| 8878 | |
| 8879 return cache->retval; | |
| 8880 } | |
| 8881 else | |
| 8882 { | |
| 8883 *col = 0; | |
| 8884 *row = 0; | |
| 8885 *obj_x = 0; | |
| 8886 *obj_y = 0; | |
| 8887 *w = 0; | |
| 826 | 8888 *charpos = 0; |
| 428 | 8889 *closest = 0; |
| 8890 *modeline_closest = -1; | |
| 8891 *obj1 = Qnil; | |
| 8892 *obj2 = Qnil; | |
| 8893 | |
| 8894 low_x_coord = x_coord; | |
| 8895 high_x_coord = x_coord + 1; | |
| 8896 low_y_coord = y_coord; | |
| 8897 high_y_coord = y_coord + 1; | |
| 8898 } | |
| 8899 | |
| 8900 if (device_check_failed) | |
| 8901 return OVER_NOTHING; | |
| 8902 | |
| 5090 | 8903 /* #### GEOM! The gutter is just inside of this. We should also have an |
| 8904 OVER_GUTTER return value to indicate that we're over a gutter. See | |
| 8905 above. */ | |
| 8906 frm_left = FRAME_LEFT_INTERNAL_BORDER_END (f); | |
| 8907 frm_right = FRAME_RIGHT_INTERNAL_BORDER_START (f); | |
| 8908 frm_top = FRAME_TOP_INTERNAL_BORDER_END (f); | |
| 8909 frm_bottom = FRAME_BOTTOM_INTERNAL_BORDER_START (f); | |
| 428 | 8910 |
| 8911 /* Check if the mouse is outside of the text area actually used by | |
| 8912 redisplay. */ | |
| 8913 if (y_coord < frm_top) | |
| 8914 { | |
| 5090 | 8915 if (y_coord >= FRAME_TOP_INTERNAL_BORDER_START (f)) |
| 8916 { | |
| 8917 low_y_coord = FRAME_TOP_INTERNAL_BORDER_START (f); | |
| 428 | 8918 high_y_coord = frm_top; |
| 8919 position = OVER_BORDER; | |
| 8920 } | |
| 8921 else if (y_coord >= 0) | |
| 8922 { | |
| 8923 low_y_coord = 0; | |
| 5090 | 8924 high_y_coord = FRAME_TOP_INTERNAL_BORDER_START (f); |
| 428 | 8925 position = OVER_TOOLBAR; |
| 8926 } | |
| 8927 else | |
| 8928 { | |
| 8929 low_y_coord = y_coord; | |
| 8930 high_y_coord = 0; | |
| 8931 position = OVER_OUTSIDE; | |
| 8932 } | |
| 8933 } | |
| 8934 else if (y_coord >= frm_bottom) | |
| 8935 { | |
| 5090 | 8936 if (y_coord < FRAME_BOTTOM_INTERNAL_BORDER_END (f)) |
| 428 | 8937 { |
| 8938 low_y_coord = frm_bottom; | |
| 5090 | 8939 high_y_coord = FRAME_BOTTOM_INTERNAL_BORDER_END (f); |
| 428 | 8940 position = OVER_BORDER; |
| 8941 } | |
| 8942 else if (y_coord < FRAME_PIXHEIGHT (f)) | |
| 8943 { | |
| 5090 | 8944 low_y_coord = FRAME_BOTTOM_INTERNAL_BORDER_END (f); |
| 428 | 8945 high_y_coord = FRAME_PIXHEIGHT (f); |
| 8946 position = OVER_TOOLBAR; | |
| 8947 } | |
| 8948 else | |
| 8949 { | |
| 8950 low_y_coord = FRAME_PIXHEIGHT (f); | |
| 8951 high_y_coord = y_coord; | |
| 8952 position = OVER_OUTSIDE; | |
| 8953 } | |
| 8954 } | |
| 8955 | |
| 8956 if (position != OVER_TOOLBAR && position != OVER_BORDER) | |
| 8957 { | |
| 8958 if (x_coord < frm_left) | |
| 8959 { | |
| 5090 | 8960 if (x_coord >= FRAME_LEFT_INTERNAL_BORDER_START (f)) |
| 8961 { | |
| 8962 low_x_coord = FRAME_LEFT_INTERNAL_BORDER_START (f); | |
| 428 | 8963 high_x_coord = frm_left; |
| 8964 position = OVER_BORDER; | |
| 8965 } | |
| 8966 else if (x_coord >= 0) | |
| 8967 { | |
| 8968 low_x_coord = 0; | |
| 5090 | 8969 high_x_coord = FRAME_LEFT_INTERNAL_BORDER_START (f); |
| 428 | 8970 position = OVER_TOOLBAR; |
| 8971 } | |
| 8972 else | |
| 8973 { | |
| 8974 low_x_coord = x_coord; | |
| 8975 high_x_coord = 0; | |
| 8976 position = OVER_OUTSIDE; | |
| 8977 } | |
| 8978 } | |
| 8979 else if (x_coord >= frm_right) | |
| 8980 { | |
| 5090 | 8981 if (x_coord < FRAME_RIGHT_INTERNAL_BORDER_END (f)) |
| 428 | 8982 { |
| 8983 low_x_coord = frm_right; | |
| 5090 | 8984 high_x_coord = FRAME_RIGHT_INTERNAL_BORDER_END (f); |
| 428 | 8985 position = OVER_BORDER; |
| 8986 } | |
| 8987 else if (x_coord < FRAME_PIXWIDTH (f)) | |
| 8988 { | |
| 5090 | 8989 low_x_coord = FRAME_RIGHT_INTERNAL_BORDER_END (f); |
| 428 | 8990 high_x_coord = FRAME_PIXWIDTH (f); |
| 8991 position = OVER_TOOLBAR; | |
| 8992 } | |
| 8993 else | |
| 8994 { | |
| 8995 low_x_coord = FRAME_PIXWIDTH (f); | |
| 8996 high_x_coord = x_coord; | |
| 8997 position = OVER_OUTSIDE; | |
| 8998 } | |
| 8999 } | |
| 9000 } | |
| 9001 | |
| 9002 #ifdef HAVE_TOOLBARS | |
| 9003 if (position == OVER_TOOLBAR) | |
| 9004 { | |
| 9005 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord); | |
| 9006 *obj2 = Qnil; | |
| 9007 *w = 0; | |
| 9008 UPDATE_CACHE_RETURN; | |
| 9009 } | |
| 9010 #endif /* HAVE_TOOLBARS */ | |
| 9011 | |
| 9012 /* We still have to return the window the pointer is next to and its | |
| 9013 relative y position even if it is outside the x boundary. */ | |
| 9014 if (x_coord < frm_left) | |
| 9015 x_coord = frm_left; | |
| 9016 else if (x_coord > frm_right) | |
| 9017 x_coord = frm_right; | |
| 9018 | |
| 9019 /* Same in reverse. */ | |
| 9020 if (y_coord < frm_top) | |
| 9021 y_coord = frm_top; | |
| 9022 else if (y_coord > frm_bottom) | |
| 9023 y_coord = frm_bottom; | |
| 9024 | |
| 9025 /* Find what window the given coordinates are actually in. */ | |
| 9026 window = f->root_window; | |
| 9027 *w = find_window_by_pixel_pos (x_coord, y_coord, window); | |
| 9028 | |
| 9029 /* If we didn't find a window, we're done. */ | |
| 9030 if (!*w) | |
| 9031 { | |
| 9032 UPDATE_CACHE_RETURN; | |
| 9033 } | |
| 9034 else if (position != OVER_NOTHING) | |
| 9035 { | |
| 9036 *closest = 0; | |
| 9037 *modeline_closest = -1; | |
| 9038 | |
| 9039 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) | |
| 9040 { | |
| 9041 *w = 0; | |
| 9042 UPDATE_CACHE_RETURN; | |
| 9043 } | |
| 9044 } | |
| 9045 | |
| 9046 /* Check if the window is a minibuffer but isn't active. */ | |
| 9047 if (MINI_WINDOW_P (*w) && !minibuf_level) | |
| 9048 { | |
| 9049 /* Must reset the window value since some callers will ignore | |
| 4187 | 9050 the return value if it is set. */ |
| 428 | 9051 *w = 0; |
| 9052 UPDATE_CACHE_RETURN; | |
| 9053 } | |
| 9054 | |
| 9055 /* See if the point is over window vertical divider */ | |
| 9056 if (window_needs_vertical_divider (*w)) | |
| 9057 { | |
| 9058 int div_x_high = WINDOW_RIGHT (*w); | |
| 9059 int div_x_low = div_x_high - window_divider_width (*w); | |
| 9060 int div_y_high = WINDOW_BOTTOM (*w); | |
| 9061 int div_y_low = WINDOW_TOP (*w); | |
| 9062 | |
| 9063 if (div_x_low < x_coord && x_coord <= div_x_high && | |
| 9064 div_y_low < y_coord && y_coord <= div_y_high) | |
| 9065 { | |
| 9066 low_x_coord = div_x_low; | |
| 9067 high_x_coord = div_x_high; | |
| 9068 low_y_coord = div_y_low; | |
| 9069 high_y_coord = div_y_high; | |
| 9070 position = OVER_V_DIVIDER; | |
| 9071 UPDATE_CACHE_RETURN; | |
| 9072 } | |
| 9073 } | |
| 9074 | |
| 9075 dla = window_display_lines (*w, CURRENT_DISP); | |
| 9076 | |
| 9077 for (*row = 0; *row < Dynarr_length (dla); (*row)++) | |
| 9078 { | |
| 9079 int really_over_nothing = 0; | |
| 9080 struct display_line *dl = Dynarr_atp (dla, *row); | |
| 9081 | |
| 9082 if ((int) (dl->ypos - dl->ascent) <= y_coord | |
| 9083 && y_coord <= (int) (dl->ypos + dl->descent)) | |
| 9084 { | |
| 9085 int check_margin_glyphs = 0; | |
| 9086 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
| 9087 struct rune *rb = 0; | |
| 9088 | |
| 9089 if (x_coord < dl->bounds.left_white | |
| 9090 || x_coord >= dl->bounds.right_white) | |
| 9091 check_margin_glyphs = 1; | |
| 9092 | |
| 9093 low_y_coord = dl->ypos - dl->ascent; | |
| 9094 high_y_coord = dl->ypos + dl->descent + 1; | |
| 9095 | |
| 9096 if (position == OVER_BORDER | |
| 9097 || position == OVER_OUTSIDE | |
| 9098 || check_margin_glyphs) | |
| 9099 { | |
| 9100 int x_check, left_bound; | |
| 9101 | |
| 9102 if (check_margin_glyphs) | |
| 9103 { | |
| 9104 x_check = x_coord; | |
| 9105 left_bound = dl->bounds.left_white; | |
| 9106 } | |
| 9107 else | |
| 9108 { | |
| 9109 x_check = high_x_coord; | |
| 9110 left_bound = frm_left; | |
| 9111 } | |
| 9112 | |
| 9113 if (Dynarr_length (db->runes)) | |
| 9114 { | |
| 9115 if (x_check <= left_bound) | |
| 9116 { | |
| 9117 if (dl->modeline) | |
| 4967 | 9118 *modeline_closest = Dynarr_begin (db->runes)->charpos; |
| 428 | 9119 else |
| 4967 | 9120 *closest = Dynarr_begin (db->runes)->charpos; |
| 428 | 9121 } |
| 9122 else | |
| 9123 { | |
| 9124 if (dl->modeline) | |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9125 *modeline_closest = Dynarr_lastp (db->runes)->charpos; |
| 428 | 9126 else |
|
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9127 *closest = Dynarr_lastp (db->runes)->charpos; |
| 428 | 9128 } |
| 9129 | |
| 9130 if (dl->modeline) | |
| 9131 *modeline_closest += dl->offset; | |
| 9132 else | |
| 9133 *closest += dl->offset; | |
| 9134 } | |
| 9135 else | |
| 9136 { | |
| 9137 /* #### What should be here. */ | |
| 9138 if (dl->modeline) | |
| 9139 *modeline_closest = 0; | |
| 9140 else | |
| 9141 *closest = 0; | |
| 9142 } | |
| 9143 | |
| 9144 if (check_margin_glyphs) | |
| 9145 { | |
| 9146 if (x_coord < dl->bounds.left_in | |
| 9147 || x_coord >= dl->bounds.right_in) | |
| 9148 { | |
| 9149 /* If we are over the outside margins then we | |
| 4187 | 9150 know the loop over the text block isn't going |
| 9151 to accomplish anything. So we go ahead and | |
| 9152 set what information we can right here and | |
| 9153 return. */ | |
| 428 | 9154 (*row)--; |
| 9155 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
| 9156 get_position_object (dl, obj1, obj2, x_coord, | |
| 9157 &low_x_coord, &high_x_coord); | |
| 9158 | |
| 9159 UPDATE_CACHE_RETURN; | |
| 9160 } | |
| 9161 } | |
| 9162 else | |
| 9163 UPDATE_CACHE_RETURN; | |
| 9164 } | |
| 9165 | |
| 9166 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++) | |
| 9167 { | |
|
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9168 if (*col == Dynarr_length (db->runes)) |
| 428 | 9169 { |
|
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9170 /* We've run out of runes to look at. Treat the same as |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9171 the case below where we failed to find a non-glyph |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9172 character. */ |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9173 if (dl->modeline) |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9174 *modeline_closest = dl->end_charpos + dl->offset; |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9175 else |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9176 *closest = dl->end_charpos + dl->offset; |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9177 |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9178 if (check_margin_glyphs) |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9179 get_position_object (dl, obj1, obj2, x_coord, |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9180 &low_x_coord, &high_x_coord); |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9181 |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9182 UPDATE_CACHE_RETURN; |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9183 } |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9184 |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9185 rb = Dynarr_atp (db->runes, *col); |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9186 |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9187 if (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width) |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9188 { |
| 428 | 9189 |
| 826 | 9190 *charpos = rb->charpos + dl->offset; |
| 428 | 9191 low_x_coord = rb->xpos; |
| 9192 high_x_coord = rb->xpos + rb->width; | |
| 9193 | |
| 9194 if (rb->type == RUNE_DGLYPH) | |
| 9195 { | |
| 9196 int elt = *col + 1; | |
| 9197 | |
| 9198 /* Find the first character after the glyph. */ | |
| 9199 while (elt < Dynarr_length (db->runes)) | |
| 9200 { | |
| 9201 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH) | |
| 9202 { | |
| 9203 if (dl->modeline) | |
| 9204 *modeline_closest = | |
| 826 | 9205 (Dynarr_atp (db->runes, elt)->charpos + |
| 428 | 9206 dl->offset); |
| 9207 else | |
| 9208 *closest = | |
| 826 | 9209 (Dynarr_atp (db->runes, elt)->charpos + |
| 428 | 9210 dl->offset); |
| 9211 break; | |
| 9212 } | |
| 9213 | |
| 9214 elt++; | |
| 9215 } | |
| 9216 | |
| 9217 /* In this case we failed to find a non-glyph | |
| 4187 | 9218 character so we return the last position |
| 9219 displayed on the line. */ | |
| 428 | 9220 if (elt == Dynarr_length (db->runes)) |
| 9221 { | |
| 9222 if (dl->modeline) | |
| 826 | 9223 *modeline_closest = dl->end_charpos + dl->offset; |
| 428 | 9224 else |
| 826 | 9225 *closest = dl->end_charpos + dl->offset; |
| 428 | 9226 really_over_nothing = 1; |
| 9227 } | |
| 9228 } | |
| 9229 else | |
| 9230 { | |
| 9231 if (dl->modeline) | |
| 826 | 9232 *modeline_closest = rb->charpos + dl->offset; |
| 428 | 9233 else |
| 826 | 9234 *closest = rb->charpos + dl->offset; |
| 428 | 9235 } |
| 9236 | |
| 9237 if (dl->modeline) | |
| 9238 { | |
| 9239 *row = window_displayed_height (*w); | |
| 9240 | |
| 9241 if (position == OVER_NOTHING) | |
| 9242 position = OVER_MODELINE; | |
| 9243 | |
| 9244 if (rb->type == RUNE_DGLYPH) | |
| 9245 { | |
| 9246 *obj1 = rb->object.dglyph.glyph; | |
| 9247 *obj2 = rb->object.dglyph.extent; | |
| 9248 } | |
| 9249 else if (rb->type == RUNE_CHAR) | |
| 9250 { | |
| 9251 *obj1 = Qnil; | |
| 9252 *obj2 = Qnil; | |
| 9253 } | |
| 9254 else | |
| 9255 { | |
| 9256 *obj1 = Qnil; | |
| 9257 *obj2 = Qnil; | |
| 9258 } | |
| 9259 | |
| 9260 UPDATE_CACHE_RETURN; | |
| 9261 } | |
|
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9262 else if (rb->type == RUNE_CHAR |
|
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9263 && rb->object.chr.ch == '\n') |
| 428 | 9264 { |
| 9265 (*row)--; | |
| 9266 /* At this point we may have glyphs in the right | |
| 4187 | 9267 inside margin. */ |
| 428 | 9268 if (check_margin_glyphs) |
| 9269 get_position_object (dl, obj1, obj2, x_coord, | |
| 9270 &low_x_coord, &high_x_coord); | |
| 9271 UPDATE_CACHE_RETURN; | |
| 9272 } | |
| 9273 else | |
| 9274 { | |
| 9275 (*row)--; | |
| 9276 if (rb->type == RUNE_DGLYPH) | |
| 9277 { | |
| 9278 *obj1 = rb->object.dglyph.glyph; | |
| 9279 *obj2 = rb->object.dglyph.extent; | |
| 9280 } | |
| 9281 else if (rb->type == RUNE_CHAR) | |
| 9282 { | |
| 9283 *obj1 = Qnil; | |
| 9284 *obj2 = Qnil; | |
| 9285 } | |
| 9286 else | |
| 9287 { | |
| 9288 *obj1 = Qnil; | |
| 9289 *obj2 = Qnil; | |
| 9290 } | |
| 9291 | |
| 9292 *obj_x = x_coord - rb->xpos; | |
| 9293 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
| 9294 | |
| 9295 /* At this point we may have glyphs in the left | |
| 4187 | 9296 inside margin. */ |
| 428 | 9297 if (check_margin_glyphs) |
| 9298 get_position_object (dl, obj1, obj2, x_coord, 0, 0); | |
| 9299 | |
| 9300 if (position == OVER_NOTHING && !really_over_nothing) | |
| 9301 position = OVER_TEXT; | |
| 9302 | |
| 9303 UPDATE_CACHE_RETURN; | |
| 9304 } | |
| 9305 } | |
| 9306 } | |
| 9307 } | |
| 9308 } | |
| 9309 | |
| 9310 *row = Dynarr_length (dla) - 1; | |
| 9311 if (FRAME_WIN_P (f)) | |
| 9312 { | |
| 9313 int bot_elt = Dynarr_length (dla) - 1; | |
| 9314 | |
| 9315 if (bot_elt >= 0) | |
| 9316 { | |
| 9317 struct display_line *dl = Dynarr_atp (dla, bot_elt); | |
| 9318 int adj_area = y_coord - (dl->ypos + dl->descent); | |
| 9319 Lisp_Object lwin; | |
| 9320 int defheight; | |
| 9321 | |
| 793 | 9322 lwin = wrap_window (*w); |
|
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
9323 default_face_width_and_height (lwin, 0, &defheight); |
| 428 | 9324 |
| 9325 *row += (adj_area / defheight); | |
| 9326 } | |
| 9327 } | |
| 9328 | |
| 9329 /* #### This should be checked out some more to determine what | |
| 9330 should really be going on. */ | |
| 9331 if (!MARKERP ((*w)->start[CURRENT_DISP])) | |
| 9332 *closest = 0; | |
| 9333 else | |
| 442 | 9334 *closest = end_of_last_line_may_error (*w, |
| 428 | 9335 marker_position ((*w)->start[CURRENT_DISP])); |
| 9336 *col = 0; | |
| 9337 UPDATE_CACHE_RETURN; | |
| 9338 } | |
| 9339 #undef UPDATE_CACHE_RETURN | |
| 9340 | |
| 9341 | |
| 9342 /***************************************************************************/ | |
| 9343 /* */ | |
| 9344 /* Lisp functions */ | |
| 9345 /* */ | |
| 9346 /***************************************************************************/ | |
| 9347 | |
| 9348 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /* | |
| 9349 Ensure that all minibuffers are correctly showing the echo area. | |
| 9350 */ | |
| 9351 ()) | |
| 9352 { | |
| 9353 Lisp_Object devcons, concons; | |
| 9354 | |
| 1318 | 9355 if (in_display) |
| 9356 return Qnil; | |
| 9357 | |
| 428 | 9358 DEVICE_LOOP_NO_BREAK (devcons, concons) |
| 9359 { | |
| 9360 struct device *d = XDEVICE (XCAR (devcons)); | |
| 9361 Lisp_Object frmcons; | |
| 9362 | |
| 1279 | 9363 if (DEVICE_STREAM_P (d)) |
| 9364 continue; | |
| 9365 | |
| 428 | 9366 DEVICE_FRAME_LOOP (frmcons, d) |
| 9367 { | |
| 9368 struct frame *f = XFRAME (XCAR (frmcons)); | |
| 853 | 9369 int depth; |
| 428 | 9370 |
| 9371 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) | |
| 9372 { | |
| 9373 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); | |
| 442 | 9374 |
| 9375 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
| 9376 | |
| 428 | 9377 /* |
| 9378 * If the frame size has changed, there may be random | |
| 9379 * chud on the screen left from previous messages | |
| 9380 * because redisplay_frame hasn't been called yet. | |
| 9381 * Clear the screen to get rid of the potential mess. | |
| 9382 */ | |
| 9383 if (f->echo_area_garbaged) | |
| 9384 { | |
| 442 | 9385 MAYBE_DEVMETH (d, clear_frame, (f)); |
| 428 | 9386 f->echo_area_garbaged = 0; |
| 9387 } | |
| 853 | 9388 depth = enter_redisplay_critical_section (); |
| 428 | 9389 redisplay_window (window, 0); |
| 853 | 9390 exit_redisplay_critical_section (depth); |
| 442 | 9391 MAYBE_DEVMETH (d, frame_output_end, (f)); |
| 428 | 9392 } |
| 9393 } | |
| 9394 } | |
| 9395 | |
| 9396 return Qnil; | |
| 9397 } | |
| 9398 | |
| 9399 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /* | |
| 9400 Clear frame FRAME and output again what is supposed to appear on it. | |
| 9401 FRAME defaults to the selected frame if omitted. | |
| 9402 Normally, redisplay is preempted as normal if input arrives. However, | |
| 9403 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
| 9404 input and is guaranteed to proceed to completion. | |
| 9405 */ | |
| 9406 (frame, no_preempt)) | |
| 9407 { | |
| 9408 struct frame *f = decode_frame (frame); | |
| 9409 int count = specpdl_depth (); | |
| 9410 | |
| 9411 if (!NILP (no_preempt)) | |
| 853 | 9412 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
| 428 | 9413 |
| 9414 f->clear = 1; | |
| 9415 redisplay_frame (f, 1); | |
| 9416 | |
| 442 | 9417 /* See the comment in Fredisplay_frame. */ |
| 9418 RESET_CHANGED_SET_FLAGS; | |
| 9419 | |
| 771 | 9420 return unbind_to (count); |
| 428 | 9421 } |
| 9422 | |
| 9423 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* | |
| 9424 Ensure that FRAME's contents are correctly displayed. | |
| 9425 This differs from `redraw-frame' in that it only redraws what needs to | |
| 9426 be updated, as opposed to unconditionally clearing and redrawing | |
| 9427 the frame. | |
| 9428 FRAME defaults to the selected frame if omitted. | |
| 9429 Normally, redisplay is preempted as normal if input arrives. However, | |
| 9430 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
| 9431 input and is guaranteed to proceed to completion. | |
| 9432 */ | |
| 9433 (frame, no_preempt)) | |
| 9434 { | |
| 9435 struct frame *f = decode_frame (frame); | |
| 9436 int count = specpdl_depth (); | |
| 9437 | |
| 9438 if (!NILP (no_preempt)) | |
| 853 | 9439 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
| 428 | 9440 |
| 9441 redisplay_frame (f, 1); | |
| 9442 | |
| 442 | 9443 /* If we don't reset the global redisplay flags here, subsequent |
| 9444 changes to the display will not get registered by redisplay | |
| 9445 because it thinks it already has registered changes. If you | |
| 9446 really knew what you were doing you could confuse redisplay by | |
| 9447 calling Fredisplay_frame while updating another frame. We assume | |
| 9448 that if you know what you are doing you will not be that | |
| 9449 stupid. */ | |
| 9450 RESET_CHANGED_SET_FLAGS; | |
| 9451 | |
| 771 | 9452 return unbind_to (count); |
| 428 | 9453 } |
| 9454 | |
| 9455 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* | |
| 9456 Clear device DEVICE and output again what is supposed to appear on it. | |
| 9457 DEVICE defaults to the selected device if omitted. | |
| 9458 Normally, redisplay is preempted as normal if input arrives. However, | |
| 9459 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
| 9460 input and is guaranteed to proceed to completion. | |
| 9461 */ | |
| 9462 (device, no_preempt)) | |
| 9463 { | |
| 9464 struct device *d = decode_device (device); | |
| 9465 Lisp_Object frmcons; | |
| 9466 int count = specpdl_depth (); | |
| 9467 | |
| 9468 if (!NILP (no_preempt)) | |
| 853 | 9469 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
| 428 | 9470 |
| 9471 DEVICE_FRAME_LOOP (frmcons, d) | |
| 9472 { | |
| 9473 XFRAME (XCAR (frmcons))->clear = 1; | |
| 9474 } | |
| 440 | 9475 redisplay_device (d, 0); |
| 428 | 9476 |
| 442 | 9477 /* See the comment in Fredisplay_frame. */ |
| 9478 RESET_CHANGED_SET_FLAGS; | |
| 9479 | |
| 771 | 9480 return unbind_to (count); |
| 428 | 9481 } |
| 9482 | |
| 9483 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* | |
| 9484 Ensure that DEVICE's contents are correctly displayed. | |
| 9485 This differs from `redraw-device' in that it only redraws what needs to | |
| 9486 be updated, as opposed to unconditionally clearing and redrawing | |
| 9487 the device. | |
| 9488 DEVICE defaults to the selected device if omitted. | |
| 9489 Normally, redisplay is preempted as normal if input arrives. However, | |
| 9490 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
| 9491 input and is guaranteed to proceed to completion. | |
| 853 | 9492 |
| 9493 Note: If you simply want everything redisplayed, the current idiom is | |
| 9494 `(sit-for 0)'. | |
| 428 | 9495 */ |
| 9496 (device, no_preempt)) | |
| 9497 { | |
| 9498 struct device *d = decode_device (device); | |
| 9499 int count = specpdl_depth (); | |
| 9500 | |
| 9501 if (!NILP (no_preempt)) | |
| 853 | 9502 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
| 428 | 9503 |
| 440 | 9504 redisplay_device (d, 0); |
| 428 | 9505 |
| 442 | 9506 /* See the comment in Fredisplay_frame. */ |
| 9507 RESET_CHANGED_SET_FLAGS; | |
| 9508 | |
| 771 | 9509 return unbind_to (count); |
| 428 | 9510 } |
| 9511 | |
| 9512 /* Big lie. Big lie. This will force all modelines to be updated | |
| 9513 regardless if the all flag is set or not. It remains in existence | |
| 9514 solely for backwards compatibility. */ | |
| 9515 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /* | |
| 9516 Force the modeline of the current buffer to be redisplayed. | |
| 9517 With optional non-nil ALL, force redisplay of all modelines. | |
| 9518 */ | |
| 2286 | 9519 (UNUSED (all))) |
| 428 | 9520 { |
| 9521 MARK_MODELINE_CHANGED; | |
| 9522 return Qnil; | |
| 9523 } | |
| 9524 | |
| 9525 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /* | |
| 9526 Force an immediate update of the cursor on FRAME. | |
| 9527 FRAME defaults to the selected frame if omitted. | |
| 9528 */ | |
| 9529 (frame)) | |
| 9530 { | |
| 1279 | 9531 struct frame *f = decode_frame (frame); |
| 9532 | |
| 9533 if (!FRAME_STREAM_P (f)) | |
| 9534 redisplay_redraw_cursor (f, 1); | |
| 428 | 9535 return Qnil; |
| 9536 } | |
| 9537 | |
| 9538 | |
| 9539 /***************************************************************************/ | |
| 9540 /* */ | |
| 872 | 9541 /* Change flags */ |
| 428 | 9542 /* */ |
| 9543 /***************************************************************************/ | |
| 9544 | |
| 9545 static void | |
| 2286 | 9546 margin_width_changed_in_frame (Lisp_Object UNUSED (specifier), |
| 9547 struct frame *UNUSED (f), | |
| 9548 Lisp_Object UNUSED (oldval)) | |
| 428 | 9549 { |
| 9550 /* Nothing to be done? */ | |
| 9551 } | |
| 9552 | |
| 9553 int | |
| 2286 | 9554 redisplay_variable_changed (Lisp_Object UNUSED (sym), |
| 9555 Lisp_Object *UNUSED (val), | |
| 9556 Lisp_Object UNUSED (in_object), | |
| 9557 int UNUSED (flags)) | |
| 428 | 9558 { |
| 9559 /* #### clip_changed should really be renamed something like | |
| 9560 global_redisplay_change. */ | |
| 9561 MARK_CLIP_CHANGED; | |
| 9562 return 0; | |
| 9563 } | |
| 9564 | |
| 9565 /* This is called if the built-in glyphs have their properties | |
| 9566 changed. */ | |
| 9567 void | |
| 2286 | 9568 redisplay_glyph_changed (Lisp_Object UNUSED (glyph), |
| 9569 Lisp_Object UNUSED (property), Lisp_Object locale) | |
| 428 | 9570 { |
| 9571 if (WINDOWP (locale)) | |
| 9572 { | |
| 9573 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale)))); | |
| 9574 } | |
| 9575 else if (FRAMEP (locale)) | |
| 9576 { | |
| 9577 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale)); | |
| 9578 } | |
| 9579 else if (DEVICEP (locale)) | |
| 9580 { | |
| 9581 Lisp_Object frmcons; | |
| 9582 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale)) | |
| 9583 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
| 9584 } | |
| 9585 else if (CONSOLEP (locale)) | |
| 9586 { | |
| 9587 Lisp_Object frmcons, devcons; | |
| 9588 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale)) | |
| 9589 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
| 9590 } | |
| 9591 else /* global or buffer */ | |
| 9592 { | |
| 9593 Lisp_Object frmcons, devcons, concons; | |
| 9594 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
| 9595 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
| 9596 } | |
| 9597 } | |
| 9598 | |
| 9599 static void | |
| 2286 | 9600 text_cursor_visible_p_changed (Lisp_Object UNUSED (specifier), |
| 9601 struct window *w, Lisp_Object UNUSED (oldval)) | |
| 428 | 9602 { |
| 9603 if (XFRAME (w->frame)->init_finished) | |
| 9604 Fforce_cursor_redisplay (w->frame); | |
| 9605 } | |
| 9606 | |
| 872 | 9607 void |
| 9608 mark_buffers_changed (void) | |
| 9609 { | |
| 9610 MARK_TYPE_CHANGED (buffers); | |
| 9611 } | |
| 9612 | |
| 9613 void | |
| 9614 mark_clip_changed (void) | |
| 9615 { | |
| 9616 MARK_TYPE_CHANGED (clip); | |
| 9617 } | |
| 9618 | |
| 9619 void | |
| 9620 mark_extents_changed (void) | |
| 9621 { | |
| 9622 MARK_TYPE_CHANGED (extents); | |
| 9623 } | |
| 9624 | |
| 9625 void | |
| 9626 mark_icon_changed (void) | |
| 9627 { | |
| 9628 MARK_TYPE_CHANGED (icon); | |
| 9629 } | |
| 9630 | |
| 9631 void | |
| 9632 mark_menubar_changed (void) | |
| 9633 { | |
| 9634 MARK_TYPE_CHANGED (menubar); | |
| 9635 } | |
| 9636 | |
| 9637 void | |
| 9638 mark_modeline_changed (void) | |
| 9639 { | |
| 9640 MARK_TYPE_CHANGED (modeline); | |
| 9641 } | |
| 9642 | |
| 9643 void | |
| 9644 mark_point_changed (void) | |
| 9645 { | |
| 9646 MARK_TYPE_CHANGED (point); | |
| 9647 } | |
| 9648 | |
| 9649 void | |
| 9650 mark_toolbar_changed (void) | |
| 9651 { | |
| 9652 MARK_TYPE_CHANGED (toolbar); | |
| 9653 } | |
| 9654 | |
| 9655 void | |
| 9656 mark_gutter_changed (void) | |
| 9657 { | |
| 9658 MARK_TYPE_CHANGED (gutter); | |
| 9659 } | |
| 9660 | |
| 9661 void | |
| 9662 mark_glyphs_changed (void) | |
| 9663 { | |
| 9664 MARK_TYPE_CHANGED (glyphs); | |
| 9665 } | |
| 9666 | |
| 9667 void | |
| 9668 mark_subwindows_changed (void) | |
| 9669 { | |
| 9670 MARK_TYPE_CHANGED (subwindows); | |
| 9671 } | |
| 9672 | |
| 9673 void | |
| 9674 mark_subwindows_state_changed (void) | |
| 9675 { | |
| 9676 MARK_TYPE_CHANGED (subwindows_state); | |
| 9677 } | |
| 9678 | |
| 428 | 9679 #ifdef MEMORY_USAGE_STATS |
| 9680 | |
| 9681 | |
| 9682 /***************************************************************************/ | |
| 9683 /* */ | |
| 9684 /* memory usage computation */ | |
| 9685 /* */ | |
| 9686 /***************************************************************************/ | |
| 9687 | |
| 9688 static int | |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9689 compute_rune_dynarr_usage (rune_dynarr *dyn, struct usage_stats *ustats) |
|
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9690 { |
|
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9691 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
| 428 | 9692 } |
| 9693 | |
| 9694 static int | |
| 9695 compute_display_block_dynarr_usage (display_block_dynarr *dyn, | |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9696 struct usage_stats *ustats) |
| 428 | 9697 { |
| 9698 int total, i; | |
| 9699 | |
| 9700 if (!dyn) | |
| 9701 return 0; | |
| 9702 | |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9703 total = Dynarr_memory_usage (dyn, ustats); |
| 428 | 9704 for (i = 0; i < Dynarr_largest (dyn); i++) |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9705 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ustats); |
| 428 | 9706 |
| 9707 return total; | |
| 9708 } | |
| 9709 | |
| 9710 static int | |
| 9711 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn, | |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9712 struct usage_stats *ustats) |
|
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9713 { |
|
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9714 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
| 428 | 9715 } |
| 9716 | |
| 9717 int | |
| 9718 compute_display_line_dynarr_usage (display_line_dynarr *dyn, | |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9719 struct usage_stats *ustats) |
| 428 | 9720 { |
| 9721 int total, i; | |
| 9722 | |
| 9723 if (!dyn) | |
| 9724 return 0; | |
| 9725 | |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9726 total = Dynarr_memory_usage (dyn, ustats); |
| 428 | 9727 for (i = 0; i < Dynarr_largest (dyn); i++) |
| 9728 { | |
| 9729 struct display_line *dl = &Dynarr_at (dyn, i); | |
| 5198 | 9730 total += compute_display_block_dynarr_usage (dl->display_blocks, ustats); |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9731 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ustats); |
|
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9732 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ustats); |
| 428 | 9733 } |
| 9734 | |
| 9735 return total; | |
| 9736 } | |
| 9737 | |
| 9738 int | |
| 9739 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn, | |
|
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9740 struct usage_stats *ustats) |
|
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9741 { |
|
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9742 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
| 428 | 9743 } |
| 9744 | |
| 9745 #endif /* MEMORY_USAGE_STATS */ | |
| 9746 | |
| 1204 | 9747 #ifdef ERROR_CHECK_DISPLAY |
| 9748 | |
| 800 | 9749 static int |
| 2286 | 9750 sledgehammer_check_redisplay_structs_1 (struct window *w, |
| 9751 void *UNUSED (closure)) | |
| 800 | 9752 { |
| 9753 int i, j; | |
| 9754 display_line_dynarr *dl; | |
| 9755 | |
| 9756 dl = window_display_lines (w, CURRENT_DISP); | |
| 4187 | 9757 |
| 800 | 9758 for (i = 0; i < Dynarr_largest (dl); i++) |
| 9759 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
| 9760 assert (Dynarr_atp (dl, i)->display_blocks != | |
| 9761 Dynarr_atp (dl, j)->display_blocks); | |
| 9762 | |
| 9763 dl = window_display_lines (w, DESIRED_DISP); | |
| 9764 | |
| 9765 for (i = 0; i < Dynarr_largest (dl); i++) | |
| 9766 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
| 9767 assert (Dynarr_atp (dl, i)->display_blocks != | |
| 9768 Dynarr_atp (dl, j)->display_blocks); | |
| 9769 | |
| 9770 return 0; | |
| 9771 } | |
| 9772 | |
| 9773 static void | |
| 9774 sledgehammer_check_redisplay_structs (void) | |
| 9775 { | |
| 9776 map_windows (0, sledgehammer_check_redisplay_structs_1, NULL); | |
| 9777 } | |
| 9778 | |
| 1204 | 9779 #endif /* ERROR_CHECK_DISPLAY */ |
| 9780 | |
| 428 | 9781 |
| 9782 /***************************************************************************/ | |
| 9783 /* */ | |
| 9784 /* initialization */ | |
| 9785 /* */ | |
| 9786 /***************************************************************************/ | |
| 9787 | |
| 9788 void | |
| 9789 init_redisplay (void) | |
| 9790 { | |
| 9791 disable_preemption = 0; | |
| 9792 preemption_count = 0; | |
| 9793 | |
| 9794 #ifndef PDUMP | |
| 9795 if (!initialized) | |
| 9796 #endif | |
| 9797 { | |
| 440 | 9798 if (!cmotion_display_lines) |
| 9799 cmotion_display_lines = Dynarr_new (display_line); | |
| 867 | 9800 if (!mode_spec_ibyte_string) |
| 9801 mode_spec_ibyte_string = Dynarr_new (Ibyte); | |
| 440 | 9802 if (!formatted_string_extent_dynarr) |
| 9803 formatted_string_extent_dynarr = Dynarr_new (EXTENT); | |
| 9804 if (!formatted_string_extent_start_dynarr) | |
| 9805 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); | |
| 9806 if (!formatted_string_extent_end_dynarr) | |
| 9807 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); | |
| 9808 if (!internal_cache) | |
| 9809 internal_cache = Dynarr_new (line_start_cache); | |
| 428 | 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 if (!initialized) |
| 428 | 9813 return; |
| 9814 | |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9815 if (noninteractive) |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9816 { |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9817 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
|
9818 return; |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9819 } |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9820 |
| 428 | 9821 /* If the user wants to use a window system, we shouldn't bother |
| 9822 initializing the terminal. This is especially important when the | |
| 9823 terminal is so dumb that emacs gives up before and doesn't bother | |
| 9824 using the window system. | |
| 9825 | |
| 9826 If the DISPLAY environment variable is set, try to use X, and die | |
| 9827 with an error message if that doesn't work. */ | |
| 9828 | |
| 9829 #ifdef HAVE_X_WINDOWS | |
| 9830 if (!strcmp (display_use, "x")) | |
| 9831 { | |
| 9832 /* Some stuff checks this way early. */ | |
| 9833 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
|
9834 Vinitial_device_type = Qx; |
| 428 | 9835 return; |
| 9836 } | |
| 9837 #endif /* HAVE_X_WINDOWS */ | |
| 9838 | |
| 462 | 9839 #ifdef HAVE_GTK |
| 9840 if (!strcmp (display_use, "gtk")) | |
| 9841 { | |
| 9842 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
|
9843 Vinitial_device_type = Qgtk; |
| 462 | 9844 return; |
| 9845 } | |
| 9846 #endif | |
| 9847 | |
| 428 | 9848 #ifdef HAVE_MS_WINDOWS |
| 9849 if (!strcmp (display_use, "mswindows")) | |
| 9850 { | |
| 9851 /* Some stuff checks this way early. */ | |
| 9852 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
|
9853 Vinitial_device_type = Qmswindows; |
| 428 | 9854 return; |
| 9855 } | |
| 9856 #endif /* HAVE_MS_WINDOWS */ | |
| 9857 | |
| 9858 #ifdef HAVE_TTY | |
| 9859 /* If no window system has been specified, try to use the terminal. */ | |
| 9860 if (!isatty (0)) | |
| 9861 { | |
| 9862 stderr_out ("XEmacs: standard input is not a tty\n"); | |
| 9863 exit (1); | |
| 9864 } | |
| 9865 | |
| 9866 /* Look at the TERM variable */ | |
| 771 | 9867 if (!egetenv ("TERM")) |
| 428 | 9868 { |
| 9869 stderr_out ("Please set the environment variable TERM; see tset(1).\n"); | |
| 9870 exit (1); | |
| 9871 } | |
| 9872 | |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9873 Vinitial_device_type = Qtty; |
| 428 | 9874 return; |
| 9875 #else /* not HAVE_TTY */ | |
| 9876 /* No DISPLAY specified, and no TTY support. */ | |
| 9877 stderr_out ("XEmacs: Cannot open display.\n\ | |
| 9878 Please set the environmental variable DISPLAY to an appropriate value.\n"); | |
| 9879 exit (1); | |
| 9880 #endif | |
| 9881 /* Unreached. */ | |
| 9882 } | |
| 9883 | |
| 9884 void | |
| 9885 syms_of_redisplay (void) | |
| 9886 { | |
| 563 | 9887 DEFSYMBOL (Qcursor_in_echo_area); |
| 9888 DEFSYMBOL (Qdisplay_warning_buffer); | |
| 9889 DEFSYMBOL (Qbar_cursor); | |
| 9890 DEFSYMBOL (Qtop_bottom); | |
| 9891 DEFSYMBOL (Qbuffer_list_changed_hook); | |
| 428 | 9892 |
| 9893 DEFSUBR (Fredisplay_echo_area); | |
| 9894 DEFSUBR (Fredraw_frame); | |
| 9895 DEFSUBR (Fredisplay_frame); | |
| 9896 DEFSUBR (Fredraw_device); | |
| 9897 DEFSUBR (Fredisplay_device); | |
| 9898 DEFSUBR (Fredraw_modeline); | |
| 9899 DEFSUBR (Fforce_cursor_redisplay); | |
| 9900 } | |
| 9901 | |
| 9902 void | |
| 9903 vars_of_redisplay (void) | |
| 9904 { | |
|
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
9905 QSin_redisplay = build_defer_string ("(in redisplay)"); |
| 1292 | 9906 staticpro (&QSin_redisplay); |
| 428 | 9907 |
| 1318 | 9908 Vpost_redisplay_actions = Qnil; |
| 9909 staticpro (&Vpost_redisplay_actions); | |
| 9910 | |
| 428 | 9911 #if 0 |
| 9912 staticpro (&last_arrow_position); | |
| 9913 staticpro (&last_arrow_string); | |
| 9914 last_arrow_position = Qnil; | |
| 9915 last_arrow_string = Qnil; | |
| 9916 #endif /* 0 */ | |
| 9917 | |
| 9918 /* #### Probably temporary */ | |
| 9919 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* | |
| 9920 \(Temporary) Setting this will impact the performance of the internal | |
| 9921 line start cache. | |
| 9922 */ ); | |
| 9923 cache_adjustment = 2; | |
| 9924 | |
| 1268 | 9925 DEFVAR_INT ("maximum-preempts", &max_preempts /* |
| 9926 Maximum number of times redisplay can be preempted by user input. | |
| 9927 */ ); | |
| 9928 max_preempts = INIT_MAX_PREEMPTS; | |
| 9929 | |
| 428 | 9930 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /* |
| 9931 Minimum pixel height for clipped bottom display line. | |
| 9932 A clipped line shorter than this won't be displayed. | |
| 9933 */ , | |
| 9934 redisplay_variable_changed); | |
| 9935 vertical_clip = 5; | |
| 9936 | |
| 9937 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /* | |
| 9938 Minimum visible area for clipped glyphs at right boundary. | |
| 9939 Clipped glyphs shorter than this won't be displayed. | |
| 9940 Only pixmap glyph instances are currently allowed to be clipped. | |
| 9941 */ , | |
| 9942 redisplay_variable_changed); | |
| 9943 horizontal_clip = 5; | |
| 9944 | |
| 9945 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /* | |
| 9946 String displayed by modeline-format's "%m" specification. | |
| 9947 */ ); | |
| 9948 Vglobal_mode_string = Qnil; | |
| 9949 | |
| 9950 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /* | |
| 9951 Marker for where to display an arrow on top of the buffer text. | |
| 9952 This must be the beginning of a line in order to work. | |
| 9953 See also `overlay-arrow-string'. | |
| 9954 */ , | |
| 9955 redisplay_variable_changed); | |
| 9956 Voverlay_arrow_position = Qnil; | |
| 9957 | |
| 9958 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* | |
| 442 | 9959 String or glyph to display as an arrow. See also `overlay-arrow-position'. |
| 444 | 9960 \(Note that despite the name of this variable, it can be set to a glyph as |
| 442 | 9961 well as a string.) |
| 428 | 9962 */ , |
| 9963 redisplay_variable_changed); | |
| 9964 Voverlay_arrow_string = Qnil; | |
| 9965 | |
| 9966 DEFVAR_INT ("scroll-step", &scroll_step /* | |
| 9967 *The number of lines to try scrolling a window by when point moves out. | |
| 9968 If that fails to bring point back on frame, point is centered instead. | |
| 9969 If this is zero, point is always centered after it moves off screen. | |
| 9970 */ ); | |
| 9971 scroll_step = 0; | |
| 9972 | |
| 9973 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /* | |
| 9974 *Scroll up to this many lines, to bring point back on screen. | |
| 9975 */ ); | |
| 9976 scroll_conservatively = 0; | |
| 9977 | |
| 9978 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows", | |
| 9979 &truncate_partial_width_windows /* | |
| 9980 *Non-nil means truncate lines in all windows less than full frame wide. | |
| 9981 */ , | |
| 9982 redisplay_variable_changed); | |
| 9983 truncate_partial_width_windows = 1; | |
| 9984 | |
| 442 | 9985 DEFVAR_LISP ("visible-bell", &Vvisible_bell /* |
| 9986 *Non-nil substitutes a visual signal for the audible bell. | |
| 9987 | |
| 9988 Default behavior is to flash the whole screen. On some platforms, | |
| 9989 special effects are available using the following values: | |
| 9990 | |
| 3025 | 9991 `display' Flash the whole screen (ie, the default behavior). |
| 9992 `top-bottom' Flash only the top and bottom lines of the selected frame. | |
| 442 | 9993 |
| 9994 When effects are unavailable on a platform, the visual bell is the | |
| 9995 default, whole screen. (Currently only X supports any special effects.) | |
| 428 | 9996 */ ); |
| 442 | 9997 Vvisible_bell = Qnil; |
| 428 | 9998 |
| 9999 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* | |
| 10000 *Non-nil means no need to redraw entire frame after suspending. | |
| 10001 A non-nil value is useful if the terminal can automatically preserve | |
| 10002 Emacs's frame display when you reenter Emacs. | |
| 10003 It is up to you to set this variable if your terminal can do that. | |
| 10004 */ ); | |
| 10005 no_redraw_on_reenter = 0; | |
| 10006 | |
| 10007 DEFVAR_LISP ("window-system", &Vwindow_system /* | |
| 10008 A symbol naming the window-system under which Emacs is running, | |
| 10009 such as `x', or nil if emacs is running on an ordinary terminal. | |
| 10010 | |
| 10011 Do not use this variable, except for GNU Emacs compatibility, as it | |
| 10012 gives wrong values in a multi-device environment. Use `console-type' | |
| 10013 instead. | |
| 10014 */ ); | |
| 10015 Vwindow_system = Qnil; | |
| 10016 | |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10017 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
|
10018 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
|
10019 |
|
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10020 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
|
10021 to Lisp what type the initial device to be created should be. |
| 428 | 10022 */ ); |
|
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10023 Vinitial_device_type = Qnil; |
| 428 | 10024 |
| 10025 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* | |
| 10026 Non-nil means put cursor in minibuffer, at end of any message there. | |
| 10027 */ ); | |
| 10028 cursor_in_echo_area = 0; | |
| 10029 | |
| 10030 /* #### Shouldn't this be generalized as follows: | |
| 10031 | |
| 10032 if nil, use block cursor. | |
| 10033 if a number, use a bar cursor of that width. | |
| 10034 Otherwise, use a 1-pixel bar cursor. | |
| 10035 | |
| 10036 #### Or better yet, this variable should be trashed entirely | |
| 10037 (use a Lisp-magic variable to maintain compatibility) | |
| 10038 and a specifier `cursor-shape' added, which allows a block | |
| 10039 cursor, a bar cursor, a flashing block or bar cursor, | |
| 10040 maybe a caret cursor, etc. */ | |
| 10041 | |
| 10042 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /* | |
| 448 | 10043 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. |
| 428 | 10044 */ ); |
| 10045 Vbar_cursor = Qnil; | |
| 10046 | |
| 442 | 10047 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* |
| 10048 Function or functions to call when a frame's buffer list has changed. | |
| 10049 This is called during redisplay, before redisplaying each frame. | |
| 10050 Functions on this hook are called with one argument, the frame. | |
| 10051 */ ); | |
| 10052 Vbuffer_list_changed_hook = Qnil; | |
| 10053 | |
| 428 | 10054 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* |
| 10055 Bump this to tell the C code to call `display-warning-buffer' | |
| 10056 at next redisplay. You should not normally change this; the function | |
| 10057 `display-warning' automatically does this at appropriate times. | |
| 10058 */ ); | |
| 10059 display_warning_tick = 0; | |
| 10060 | |
| 10061 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /* | |
| 10062 Non-nil means inhibit display of warning messages. | |
| 10063 You should *bind* this, not set it. Any pending warning messages | |
| 10064 will be displayed when the binding no longer applies. | |
| 10065 */ ); | |
| 10066 /* reset to 0 by startup.el after the splash screen has displayed. | |
| 10067 This way, the warnings don't obliterate the splash screen. */ | |
| 10068 inhibit_warning_display = 1; | |
| 10069 | |
| 10070 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /* | |
| 10071 *Non-nil means column display number starts at 1. | |
| 10072 */ ); | |
| 10073 column_number_start_at_one = 0; | |
| 10074 } | |
| 10075 | |
| 10076 void | |
| 10077 specifier_vars_of_redisplay (void) | |
| 10078 { | |
| 10079 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /* | |
| 10080 *Width of left margin. | |
| 10081 This is a specifier; use `set-specifier' to change it. | |
| 10082 */ ); | |
| 10083 Vleft_margin_width = Fmake_specifier (Qnatnum); | |
| 10084 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); | |
| 10085 set_specifier_caching (Vleft_margin_width, | |
| 438 | 10086 offsetof (struct window, left_margin_width), |
| 428 | 10087 some_window_value_changed, |
| 438 | 10088 offsetof (struct frame, left_margin_width), |
| 444 | 10089 margin_width_changed_in_frame, 0); |
| 428 | 10090 |
| 10091 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* | |
| 10092 *Width of right margin. | |
| 10093 This is a specifier; use `set-specifier' to change it. | |
| 10094 */ ); | |
| 10095 Vright_margin_width = Fmake_specifier (Qnatnum); | |
| 10096 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); | |
| 10097 set_specifier_caching (Vright_margin_width, | |
| 438 | 10098 offsetof (struct window, right_margin_width), |
| 428 | 10099 some_window_value_changed, |
| 438 | 10100 offsetof (struct frame, right_margin_width), |
| 444 | 10101 margin_width_changed_in_frame, 0); |
| 428 | 10102 |
| 10103 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* | |
| 10104 *Minimum ascent height of lines. | |
| 10105 This is a specifier; use `set-specifier' to change it. | |
| 10106 */ ); | |
| 10107 Vminimum_line_ascent = Fmake_specifier (Qnatnum); | |
| 10108 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); | |
| 10109 set_specifier_caching (Vminimum_line_ascent, | |
| 438 | 10110 offsetof (struct window, minimum_line_ascent), |
| 428 | 10111 some_window_value_changed, |
| 444 | 10112 0, 0, 0); |
| 428 | 10113 |
| 10114 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* | |
| 10115 *Minimum descent height of lines. | |
| 10116 This is a specifier; use `set-specifier' to change it. | |
| 10117 */ ); | |
| 10118 Vminimum_line_descent = Fmake_specifier (Qnatnum); | |
| 10119 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); | |
| 10120 set_specifier_caching (Vminimum_line_descent, | |
| 438 | 10121 offsetof (struct window, minimum_line_descent), |
| 428 | 10122 some_window_value_changed, |
| 444 | 10123 0, 0, 0); |
| 428 | 10124 |
| 10125 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* | |
| 10126 *Non-nil means use the left outside margin as extra whitespace when | |
| 3025 | 10127 displaying `whitespace' or `inside-margin' glyphs. |
| 428 | 10128 This is a specifier; use `set-specifier' to change it. |
| 10129 */ ); | |
| 10130 Vuse_left_overflow = Fmake_specifier (Qboolean); | |
| 10131 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); | |
| 10132 set_specifier_caching (Vuse_left_overflow, | |
| 438 | 10133 offsetof (struct window, use_left_overflow), |
| 428 | 10134 some_window_value_changed, |
| 444 | 10135 0, 0, 0); |
| 428 | 10136 |
| 10137 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* | |
| 10138 *Non-nil means use the right outside margin as extra whitespace when | |
| 3025 | 10139 displaying `whitespace' or `inside-margin' glyphs. |
| 428 | 10140 This is a specifier; use `set-specifier' to change it. |
| 10141 */ ); | |
| 10142 Vuse_right_overflow = Fmake_specifier (Qboolean); | |
| 10143 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); | |
| 10144 set_specifier_caching (Vuse_right_overflow, | |
| 438 | 10145 offsetof (struct window, use_right_overflow), |
| 428 | 10146 some_window_value_changed, |
| 444 | 10147 0, 0, 0); |
| 428 | 10148 |
| 10149 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* | |
| 10150 *Non-nil means the text cursor is visible (this is usually the case). | |
| 10151 This is a specifier; use `set-specifier' to change it. | |
| 10152 */ ); | |
| 10153 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); | |
| 10154 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); | |
| 10155 set_specifier_caching (Vtext_cursor_visible_p, | |
| 438 | 10156 offsetof (struct window, text_cursor_visible_p), |
| 428 | 10157 text_cursor_visible_p_changed, |
| 444 | 10158 0, 0, 0); |
| 428 | 10159 |
| 10160 } |
