Mercurial > hg > xemacs-beta
annotate src/redisplay.c @ 5834:7984e732829e
Fix file descriptor leak in pop.c.
See <CAHCOHQkUhtC7netdxqCkDy3vqtctbLBwxWC7ucmvLhRaPkAsDw@mail.gmail.com>
in xemacs-patches.
author | Jerry James <james@xemacs.org> |
---|---|
date | Fri, 05 Dec 2014 16:22:57 -0700 |
parents | cfc6a8c144f1 |
children | bd4d2c8ef9cc |
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; | |
5688
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
262 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
263 struct |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
264 { |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
265 Lisp_Object preprompt; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
266 Lisp_Object prompt; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
267 } p_minibuf_prompt; |
819 | 268 |
428 | 269 } data; |
270 }; | |
271 | |
272 typedef struct | |
273 { | |
274 Dynarr_declare (prop_block); | |
275 } prop_block_dynarr; | |
276 | |
277 | |
278 static Charcount generate_fstring_runes (struct window *w, pos_data *data, | |
279 Charcount pos, Charcount min_pos, | |
280 Charcount max_pos, Lisp_Object elt, | |
281 int depth, int max_pixsize, | |
438 | 282 face_index findex, int type, |
283 Charcount *offset, | |
284 Lisp_Object cur_ext); | |
428 | 285 static prop_block_dynarr *add_glyph_rune (pos_data *data, |
286 struct glyph_block *gb, | |
287 int pos_type, int allow_cursor, | |
288 struct glyph_cachel *cachel); | |
665 | 289 static Bytebpos create_text_block (struct window *w, struct display_line *dl, |
826 | 290 Bytebpos byte_start_pos, |
291 prop_block_dynarr **prop, | |
292 int type); | |
428 | 293 static int create_overlay_glyph_block (struct window *w, |
294 struct display_line *dl); | |
295 static void create_left_glyph_block (struct window *w, | |
296 struct display_line *dl, | |
297 int overlay_width); | |
298 static void create_right_glyph_block (struct window *w, | |
299 struct display_line *dl); | |
300 static void redisplay_windows (Lisp_Object window, int skip_selected); | |
867 | 301 static void decode_mode_spec (struct window *w, Ichar spec, int type); |
428 | 302 static void free_display_line (struct display_line *dl); |
826 | 303 static void update_line_start_cache (struct window *w, Charbpos from, |
304 Charbpos to, Charbpos point, | |
305 int no_regen); | |
665 | 306 static int point_visible (struct window *w, Charbpos point, int type); |
819 | 307 static void calculate_yoffset (struct display_line *dl, |
4187 | 308 struct display_block *fixup); |
819 | 309 static void calculate_baseline (pos_data *data); |
428 | 310 |
1204 | 311 #ifdef ERROR_CHECK_DISPLAY |
800 | 312 static void sledgehammer_check_redisplay_structs (void); |
1204 | 313 #endif /* ERROR_CHECK_DISPLAY */ |
800 | 314 |
428 | 315 /* This used to be 10 but 30 seems to give much better performance. */ |
316 #define INIT_MAX_PREEMPTS 30 | |
1268 | 317 static Fixnum max_preempts; |
318 | |
319 #define QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION 4 | |
428 | 320 |
1318 | 321 /* Note that doing this can call Lisp. */ |
428 | 322 #define REDISPLAY_PREEMPTION_CHECK \ |
323 ((void) \ | |
324 (preempted = \ | |
325 (!disable_preemption && \ | |
326 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \ | |
4187 | 327 (!INTERACTIVE || \ |
1268 | 328 detect_input_pending (QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION))))) |
428 | 329 |
330 /* | |
331 * Redisplay global variables. | |
332 */ | |
333 | |
334 /* We need a third set of display structures for the cursor motion | |
335 routines. We used to just give each window a third set. However, | |
336 we always fully regenerate the structures when needed so there | |
337 isn't any reason we need more than a single set. */ | |
338 display_line_dynarr *cmotion_display_lines; | |
339 | |
340 /* We store the extents that we need to generate in a Dynarr and then | |
341 frob them all on at the end of generating the string. We do it | |
342 this way rather than adding them as we generate the string because | |
343 we don't store the text into the resulting string until we're done | |
344 (to avoid having to resize the string multiple times), and we don't | |
345 want to go around adding extents to a string when the extents might | |
346 stretch off the end of the string. */ | |
347 static EXTENT_dynarr *formatted_string_extent_dynarr; | |
348 static Bytecount_dynarr *formatted_string_extent_start_dynarr; | |
349 static Bytecount_dynarr *formatted_string_extent_end_dynarr; | |
350 | |
351 | |
352 /* #### probably temporary */ | |
458 | 353 Fixnum cache_adjustment; |
428 | 354 |
355 /* This holds a string representing the text corresponding to a single | |
356 modeline % spec. */ | |
867 | 357 static Ibyte_dynarr *mode_spec_ibyte_string; |
428 | 358 |
359 int in_display; /* 1 if in redisplay. */ | |
360 | |
1318 | 361 /* Whether we should delay size changes. Broken out of |
362 enter_redisplay_critical_section(). */ | |
363 int hold_frame_size_changes; | |
364 | |
428 | 365 int disable_preemption; /* Used for debugging redisplay and for |
366 force-redisplay. */ | |
367 | |
368 /* We only allow max_preempts preemptions before we force a redisplay. */ | |
369 static int preemption_count; | |
370 | |
371 /* Minimum pixel height of clipped bottom display line. */ | |
458 | 372 Fixnum vertical_clip; |
428 | 373 |
374 /* Minimum visible pixel width of clipped glyphs at right margin. */ | |
458 | 375 Fixnum horizontal_clip; |
428 | 376 |
377 /* Nonzero means reading single-character input with prompt | |
378 so put cursor on minibuffer after the prompt. */ | |
379 int cursor_in_echo_area; | |
380 Lisp_Object Qcursor_in_echo_area; | |
381 | |
382 /* Nonzero means truncate lines in all windows less wide than the frame */ | |
383 int truncate_partial_width_windows; | |
384 | |
385 /* non-nil if a buffer has changed since the last time redisplay completed */ | |
386 int buffers_changed; | |
387 int buffers_changed_set; | |
388 | |
389 /* non-nil if hscroll has changed somewhere or a buffer has been | |
390 narrowed or widened */ | |
391 int clip_changed; | |
392 int clip_changed_set; | |
393 | |
394 /* non-nil if any extent has changed since the last time redisplay completed */ | |
395 int extents_changed; | |
396 int extents_changed_set; | |
397 | |
398 /* non-nil if any face has changed since the last time redisplay completed */ | |
399 int faces_changed; | |
400 | |
401 /* Nonzero means some frames have been marked as garbaged */ | |
402 int frame_changed; | |
403 | |
404 /* non-zero if any of the builtin display glyphs (continuation, | |
405 hscroll, control-arrow, etc) is in need of updating | |
406 somewhere. */ | |
407 int glyphs_changed; | |
408 int glyphs_changed_set; | |
409 | |
442 | 410 /* non-zero if any subwindow has been deleted. */ |
428 | 411 int subwindows_changed; |
412 int subwindows_changed_set; | |
413 | |
414 /* non-zero if any displayed subwindow is in need of updating | |
415 somewhere. */ | |
416 int subwindows_state_changed; | |
417 int subwindows_state_changed_set; | |
418 | |
419 /* This variable is 1 if the icon has to be updated. | |
420 It is set to 1 when `frame-icon-glyph' changes. */ | |
421 int icon_changed; | |
422 int icon_changed_set; | |
423 | |
424 /* This variable is 1 if the menubar widget has to be updated. | |
425 It is set to 1 by set-menubar-dirty-flag and cleared when the widget | |
426 has been updated. */ | |
427 int menubar_changed; | |
428 int menubar_changed_set; | |
429 | |
430 /* true iff we should redraw the modelines on the next redisplay */ | |
431 int modeline_changed; | |
432 int modeline_changed_set; | |
433 | |
434 /* non-nil if point has changed in some buffer since the last time | |
435 redisplay completed */ | |
436 int point_changed; | |
437 int point_changed_set; | |
438 | |
439 /* non-nil if some frame has changed its size */ | |
440 int size_changed; | |
441 | |
442 /* non-nil if some device has signaled that it wants to change size */ | |
443 int asynch_device_change_pending; | |
444 | |
445 /* non-nil if any toolbar has changed */ | |
446 int toolbar_changed; | |
447 int toolbar_changed_set; | |
448 | |
905 | 449 /* Nonzero if some frame has changed the layout of internal elements |
450 (gutters or toolbars). */ | |
451 int frame_layout_changed; | |
452 | |
428 | 453 /* non-nil if any gutter has changed */ |
454 int gutter_changed; | |
455 int gutter_changed_set; | |
456 | |
457 /* non-nil if any window has changed since the last time redisplay completed */ | |
458 int windows_changed; | |
459 | |
460 /* non-nil if any frame's window structure has changed since the last | |
461 time redisplay completed */ | |
462 int windows_structure_changed; | |
463 | |
464 /* If non-nil, use vertical bar cursor. */ | |
465 Lisp_Object Vbar_cursor; | |
466 Lisp_Object Qbar_cursor; | |
467 | |
442 | 468 Lisp_Object Vvisible_bell; /* If true and the terminal will support it |
469 then the frame will flash instead of | |
470 beeping when an error occurs */ | |
428 | 471 |
472 /* Nonzero means no need to redraw the entire frame on resuming | |
473 a suspended Emacs. This is useful on terminals with multiple pages, | |
474 where one page is used for Emacs and another for all else. */ | |
475 int no_redraw_on_reenter; | |
476 | |
3360 | 477 Lisp_Object Vwindow_system; /* #### this variable is deprecated |
478 nil or a symbol naming the window system | |
428 | 479 under which emacs is running |
3360 | 480 (`x', `gtk', `mswindows', and `tty' are |
481 supported -- yes, TTYs are window systems | |
482 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
|
483 Lisp_Object Vinitial_device_type; |
428 | 484 |
485 Lisp_Object Vglobal_mode_string; | |
486 | |
487 /* The number of lines scroll a window by when point leaves the window; if | |
488 it is <=0 then point is centered in the window */ | |
458 | 489 Fixnum scroll_step; |
428 | 490 |
491 /* Scroll up to this many lines, to bring point back on screen. */ | |
458 | 492 Fixnum scroll_conservatively; |
428 | 493 |
494 /* Marker for where to display an arrow on top of the buffer text. */ | |
495 Lisp_Object Voverlay_arrow_position; | |
496 /* String to display for the arrow. */ | |
497 Lisp_Object Voverlay_arrow_string; | |
498 | |
442 | 499 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook; |
500 | |
458 | 501 static Fixnum last_display_warning_tick; |
502 static Fixnum display_warning_tick; | |
428 | 503 Lisp_Object Qdisplay_warning_buffer; |
504 int inhibit_warning_display; | |
505 | |
506 Lisp_Object Vleft_margin_width, Vright_margin_width; | |
507 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; | |
508 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; | |
509 Lisp_Object Vtext_cursor_visible_p; | |
510 | |
1292 | 511 static Lisp_Object QSin_redisplay; |
512 | |
1318 | 513 static Lisp_Object Vpost_redisplay_actions; |
514 | |
428 | 515 int column_number_start_at_one; |
516 | |
442 | 517 Lisp_Object Qtop_bottom; |
518 | |
444 | 519 #define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset) |
428 | 520 |
1204 | 521 static const struct memory_description rune_dglyph_description_1[] = { |
522 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, glyph) }, | |
523 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, extent) }, | |
524 { XD_END } | |
525 }; | |
526 | |
527 static const struct sized_memory_description rune_dglyph_description = { | |
528 sizeof (struct rune_dglyph), rune_dglyph_description_1 | |
529 }; | |
530 | |
531 static const struct memory_description rune_object_description_1[] = { | |
2551 | 532 { XD_BLOCK_ARRAY, RUNE_DGLYPH, 1, { &rune_dglyph_description } }, |
1204 | 533 { XD_END } |
534 }; | |
535 | |
536 static const struct sized_memory_description rune_object_description = { | |
537 0, rune_object_description_1 | |
538 }; | |
539 | |
540 static const struct memory_description rune_description_1[] = { | |
541 { XD_INT, offsetof (rune, type) }, | |
542 { XD_UNION, offsetof (rune, object), | |
2551 | 543 XD_INDIRECT (0, 0), { &rune_object_description } }, |
1204 | 544 { XD_END } |
545 }; | |
546 | |
547 static const struct sized_memory_description rune_description = { | |
548 sizeof (rune), | |
549 rune_description_1 | |
550 }; | |
551 | |
552 static const struct memory_description rune_dynarr_description_1[] = { | |
553 XD_DYNARR_DESC (rune_dynarr, &rune_description), | |
554 { XD_END } | |
555 }; | |
556 | |
557 static const struct sized_memory_description rune_dynarr_description = { | |
558 sizeof (rune_dynarr), | |
559 rune_dynarr_description_1 | |
560 }; | |
561 | |
562 static const struct memory_description display_block_description_1[] = { | |
2367 | 563 { XD_BLOCK_PTR, offsetof (display_block, runes), |
2551 | 564 1, { &rune_dynarr_description } }, |
1204 | 565 { XD_END } |
566 }; | |
567 | |
568 static const struct sized_memory_description display_block_description = { | |
569 sizeof (display_block), | |
570 display_block_description_1 | |
571 }; | |
572 | |
573 static const struct memory_description display_block_dynarr_description_1[] = { | |
574 XD_DYNARR_DESC (display_block_dynarr, &display_block_description), | |
575 { XD_END } | |
576 }; | |
577 | |
578 static const struct sized_memory_description display_block_dynarr_description = { | |
579 sizeof (display_block_dynarr), | |
580 display_block_dynarr_description_1 | |
581 }; | |
582 | |
583 static const struct memory_description glyph_block_description_1[] = { | |
584 { XD_LISP_OBJECT, offsetof (glyph_block, glyph) }, | |
585 { XD_LISP_OBJECT, offsetof (glyph_block, extent) }, | |
586 { XD_END } | |
587 }; | |
588 | |
589 static const struct sized_memory_description glyph_block_description = { | |
590 sizeof (glyph_block), | |
591 glyph_block_description_1 | |
592 }; | |
593 | |
594 static const struct memory_description glyph_block_dynarr_description_1[] = { | |
595 XD_DYNARR_DESC (glyph_block_dynarr, &glyph_block_description), | |
596 { XD_END } | |
597 }; | |
598 | |
599 static const struct sized_memory_description glyph_block_dynarr_description = { | |
600 sizeof (glyph_block_dynarr), | |
601 glyph_block_dynarr_description_1 | |
602 }; | |
603 | |
604 static const struct memory_description display_line_description_1[] = { | |
2367 | 605 { XD_BLOCK_PTR, offsetof (display_line, display_blocks), |
2551 | 606 1, { &display_block_dynarr_description } }, |
2367 | 607 { XD_BLOCK_PTR, offsetof (display_line, left_glyphs), |
2551 | 608 1, { &glyph_block_dynarr_description } }, |
2367 | 609 { XD_BLOCK_PTR, offsetof (display_line, right_glyphs), |
2551 | 610 1, { &glyph_block_dynarr_description } }, |
1204 | 611 { XD_END } |
612 }; | |
613 | |
614 static const struct sized_memory_description display_line_description = { | |
615 sizeof (display_line), | |
616 display_line_description_1 | |
617 }; | |
618 | |
619 static const struct memory_description display_line_dynarr_description_1[] = { | |
620 XD_DYNARR_DESC (display_line_dynarr, &display_line_description), | |
621 { XD_END } | |
622 }; | |
623 | |
624 const struct sized_memory_description display_line_dynarr_description = { | |
625 sizeof (display_line_dynarr), | |
626 display_line_dynarr_description_1 | |
627 }; | |
628 | |
428 | 629 |
630 /***************************************************************************/ | |
631 /* */ | |
632 /* low-level interfaces onto device routines */ | |
633 /* */ | |
634 /***************************************************************************/ | |
635 | |
636 static int | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
637 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
|
638 Ichar *str, Charcount len) |
428 | 639 { |
640 unsigned char charsets[NUM_LEADING_BYTES]; | |
641 Lisp_Object window; | |
642 | |
867 | 643 find_charsets_in_ichar_string (charsets, str, len); |
793 | 644 window = wrap_window (w); |
428 | 645 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window, |
646 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
|
647 return DEVMETH (WINDOW_XDEVICE (w), |
5628
81fee4aee9b6
text_width methods interface cleanup.
Didier Verna <didier@xemacs.org>
parents:
5619
diff
changeset
|
648 text_width, (WINDOW_XFRAME (w), |
81fee4aee9b6
text_width methods interface cleanup.
Didier Verna <didier@xemacs.org>
parents:
5619
diff
changeset
|
649 WINDOW_FACE_CACHEL (w, findex), str, |
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
|
650 len)); |
428 | 651 } |
652 | |
867 | 653 static Ichar_dynarr *rtw_ichar_dynarr; |
428 | 654 |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
655 static int |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
656 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
|
657 Ibyte *nonreloc, Lisp_Object reloc, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
658 Bytecount offset, Bytecount len) |
428 | 659 { |
867 | 660 if (!rtw_ichar_dynarr) |
661 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
662 Dynarr_reset (rtw_ichar_dynarr); | |
428 | 663 |
664 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
665 if (STRINGP (reloc)) | |
666 nonreloc = XSTRING_DATA (reloc); | |
867 | 667 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
|
668 return redisplay_window_text_width_ichar_string |
4967 | 669 (w, findex, Dynarr_begin (rtw_ichar_dynarr), |
867 | 670 Dynarr_length (rtw_ichar_dynarr)); |
428 | 671 } |
672 | |
673 int | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
674 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
|
675 Ibyte *nonreloc, Lisp_Object reloc, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
676 Bytecount offset, Bytecount len) |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
677 { |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
678 Lisp_Object window = DOMAIN_WINDOW (domain); |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
679 Lisp_Object frame = DOMAIN_FRAME (domain); |
428 | 680 unsigned char charsets[NUM_LEADING_BYTES]; |
681 struct face_cachel cachel; | |
682 | |
867 | 683 if (!rtw_ichar_dynarr) |
684 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
685 Dynarr_reset (rtw_ichar_dynarr); | |
428 | 686 |
687 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
688 if (STRINGP (reloc)) | |
689 nonreloc = XSTRING_DATA (reloc); | |
867 | 690 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
691 find_charsets_in_ibyte_string (charsets, nonreloc, len); | |
428 | 692 reset_face_cachel (&cachel); |
693 cachel.face = face; | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
694 ensure_face_cachel_complete (&cachel, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
695 NILP (window) ? frame : window, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
696 charsets); |
5628
81fee4aee9b6
text_width methods interface cleanup.
Didier Verna <didier@xemacs.org>
parents:
5619
diff
changeset
|
697 return DEVMETH (FRAME_XDEVICE (XFRAME (frame)), |
81fee4aee9b6
text_width methods interface cleanup.
Didier Verna <didier@xemacs.org>
parents:
5619
diff
changeset
|
698 text_width, (XFRAME (frame), |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
699 &cachel, |
4967 | 700 Dynarr_begin (rtw_ichar_dynarr), |
867 | 701 Dynarr_length (rtw_ichar_dynarr))); |
428 | 702 } |
703 | |
704 /* Return the display block from DL of the given TYPE. A display line | |
705 can have only one display block of each possible type. If DL does | |
706 not have a block of type TYPE, one will be created and added to DL. */ | |
707 | |
708 struct display_block * | |
709 get_display_block_from_line (struct display_line *dl, enum display_type type) | |
710 { | |
711 int elt; | |
712 struct display_block db; | |
713 | |
714 /* Check if this display line already has a block of the desired type and | |
715 if so, return it. */ | |
716 if (dl->display_blocks) | |
717 { | |
718 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++) | |
719 { | |
720 if (Dynarr_at (dl->display_blocks, elt).type == type) | |
721 return Dynarr_atp (dl->display_blocks, elt); | |
722 } | |
723 | |
724 /* There isn't an active block of the desired type, but there | |
4187 | 725 might still be allocated blocks we need to reuse. */ |
428 | 726 if (elt < Dynarr_largest (dl->display_blocks)) |
727 { | |
728 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt); | |
729 | |
3025 | 730 /* "add" the block to the list */ |
5038 | 731 Dynarr_incrementr (dl->display_blocks); |
428 | 732 |
733 /* initialize and return */ | |
734 dbp->type = type; | |
735 return dbp; | |
736 } | |
737 } | |
738 else | |
739 { | |
740 /* This line doesn't have any display blocks, so initialize the display | |
4187 | 741 bock array. */ |
428 | 742 dl->display_blocks = Dynarr_new (display_block); |
743 } | |
744 | |
745 /* The line doesn't have a block of the desired type so go ahead and create | |
746 one and add it to the line. */ | |
747 xzero (db); | |
748 db.type = type; | |
749 db.runes = Dynarr_new (rune); | |
750 Dynarr_add (dl->display_blocks, db); | |
751 | |
752 /* Return the newly added display block. */ | |
753 elt = Dynarr_length (dl->display_blocks) - 1; | |
754 | |
755 return Dynarr_atp (dl->display_blocks, elt); | |
756 } | |
757 | |
758 static int | |
759 tab_char_width (struct window *w) | |
760 { | |
761 struct buffer *b = XBUFFER (w->buffer); | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
762 int char_tab_width = XFIXNUM (b->tab_width); |
428 | 763 |
764 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8; | |
765 | |
766 return char_tab_width; | |
767 } | |
768 | |
769 static int | |
770 space_width (struct window *w) | |
771 { | |
3659 | 772 /* While tabs are traditionally composed of spaces, for variable-width |
428 | 773 fonts the space character tends to give too narrow a value. So |
774 we use 'n' instead. Except that we don't. We use the default | |
775 character width for the default face. If this is actually | |
776 defined by the font then it is probably the best thing to | |
777 actually use. If it isn't, we have assumed it is 'n' and have | |
778 already calculated its width. Thus we can avoid a call to | |
779 XTextWidth on X frames by just querying the default width. */ | |
780 return XFONT_INSTANCE | |
781 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width; | |
782 } | |
783 | |
784 static int | |
785 tab_pix_width (struct window *w) | |
786 { | |
787 return space_width (w) * tab_char_width (w); | |
788 } | |
789 | |
790 /* Given a pixel position in a window, return the pixel location of | |
791 the next tabstop. Tabs are calculated from the left window edge in | |
792 terms of spaces displayed in the default face. Formerly the space | |
793 width was determined using the currently active face. That method | |
794 leads to tabstops which do not line up. */ | |
795 | |
796 static int | |
797 next_tab_position (struct window *w, int start_pixpos, int left_pixpos) | |
798 { | |
799 int n_pos = left_pixpos; | |
800 int pix_tab_width = tab_pix_width (w); | |
801 | |
802 /* Adjust n_pos for any hscrolling which has happened. */ | |
803 if (WINDOW_SCROLLED (w)) | |
804 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset; | |
805 | |
806 while (n_pos <= start_pixpos) | |
807 n_pos += pix_tab_width; | |
808 | |
809 return n_pos; | |
810 } | |
811 | |
812 /* For the given window, calculate the outside and margin boundaries for a | |
813 display line. The whitespace boundaries must be calculated by the text | |
814 layout routines. */ | |
815 | |
816 layout_bounds | |
817 calculate_display_line_boundaries (struct window *w, int modeline) | |
818 { | |
819 layout_bounds bounds; | |
820 | |
821 /* Set the outermost boundaries which are the boundaries of the | |
822 window itself minus the gutters (and minus the scrollbars if this | |
823 is for the modeline). */ | |
824 if (!modeline) | |
825 { | |
826 bounds.left_out = WINDOW_TEXT_LEFT (w); | |
827 bounds.right_out = WINDOW_TEXT_RIGHT (w); | |
828 } | |
829 else | |
830 { | |
831 bounds.left_out = WINDOW_MODELINE_LEFT (w); | |
832 bounds.right_out = WINDOW_MODELINE_RIGHT (w); | |
833 } | |
834 | |
835 /* The inner boundaries mark where the glyph margins are located. */ | |
836 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
837 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
838 | |
839 /* We cannot fully calculate the whitespace boundaries as they | |
840 depend on the contents of the line being displayed. */ | |
841 bounds.left_white = bounds.left_in; | |
842 bounds.right_white = bounds.right_in; | |
843 | |
844 return bounds; | |
845 } | |
846 | |
819 | 847 /* This takes a display_block and its containing line and corrects the yoffset |
848 of each glyph in the block to cater for the ascent of the line as a | |
849 whole. Must be called *after* the line-ascent is known! */ | |
850 | |
851 static void | |
852 calculate_yoffset (struct display_line *dl, struct display_block *fixup) | |
853 { | |
854 int i; | |
855 for (i=0; i<Dynarr_length (fixup->runes); i++) | |
856 { | |
857 struct rune *r = Dynarr_atp (fixup->runes,i); | |
858 if (r->type == RUNE_DGLYPH) | |
4187 | 859 { |
860 if (r->object.dglyph.ascent < dl->ascent) | |
861 r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent + | |
819 | 862 r->object.dglyph.descent; |
4187 | 863 } |
819 | 864 } |
865 } | |
866 | |
867 /* Calculate the textual baseline (the ascent and descent values for the | |
868 display_line as a whole). | |
869 | |
870 If the baseline is completely blank, or contains no manually positioned | |
871 glyphs, then the textual baseline is simply the baseline of the default font. | |
872 (The `contains no manually positioned glyphs' part is actually done for | |
867 | 873 us by `add_ichar_rune'.) |
819 | 874 |
875 If the baseline contains pixmaps, and they're all manually positioned, then | |
876 the textual baseline location is constrained that way, and we need do no | |
877 work. | |
878 | |
879 If the baseline contains pixmaps, and at least one is automatically | |
880 positioned, then the textual ascent is the largest ascent on the line, and | |
881 the textual descent is the largest descent (which is how things are set up at | |
882 entry to this function anyway): except that if the max_ascent + max_descent | |
883 is too small for the height of the line (say you've adjusted the baseline of | |
884 a short glyph, and there's a tall one next to it), then take the ascent and | |
885 descent for the line individually from the largest of the explicitly set | |
886 ascent/descent, and the rescaled ascent/descent of the default font, scaled | |
887 such that the largest glyph will fit. | |
888 | |
889 This means that if you have a short glyph (but taller than the default | |
890 font's descent) forced right under the baseline, and a really tall | |
891 automatically positioned glyph, that the descent for the line is just big | |
892 enough for the manually positioned short glyph, and the tall one uses as | |
893 much of that space as the default font would were it as tall as the tall | |
894 glyph; but that the ascent is big enough for the tall glyph to fit. | |
895 | |
896 This behaviour means that under no circumstances will changing the baseline | |
897 of a short glyph cause a tall glyph to move around; nor will it move the | |
898 textual baseline more than necessary. (Changing a tall glyph's baseline | |
899 might move the text's baseline arbitrarily, of course.) */ | |
900 | |
901 static void | |
902 calculate_baseline (pos_data *data) | |
903 { | |
904 /* Blank line: baseline is default font's baseline. */ | |
905 | |
906 if (!data->new_ascent && !data->new_descent) | |
907 { | |
908 /* We've got a blank line so initialize these values from the default | |
4187 | 909 face. */ |
819 | 910 default_face_font_info (data->window, &data->new_ascent, |
911 &data->new_descent, 0, 0, 0); | |
912 } | |
4187 | 913 |
819 | 914 /* No automatically positioned glyphs? Return at once. */ |
915 if (!data->need_baseline_computation) | |
916 return; | |
917 | |
918 /* Is the tallest glyph on the line automatically positioned? | |
919 If it's manually positioned, or it's automatically positioned | |
920 and there's enough room for it anyway, we need do no more work. */ | |
921 if (data->max_pixmap_height > data->new_ascent + data->new_descent) | |
922 { | |
923 int default_font_ascent, default_font_descent, default_font_height; | |
924 int scaled_default_font_ascent, scaled_default_font_descent; | |
4187 | 925 |
819 | 926 default_face_font_info (data->window, &default_font_ascent, |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
927 &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
|
928 0); |
819 | 929 |
930 scaled_default_font_ascent = data->max_pixmap_height * | |
931 default_font_ascent / default_font_height; | |
932 | |
933 data->new_ascent = max (data->new_ascent, scaled_default_font_ascent); | |
934 | |
935 /* The ascent may have expanded now. Do we still need to grow the descent, | |
4187 | 936 or are things big enough? |
937 | |
938 The +1 caters for the baseline row itself. */ | |
819 | 939 if (data->max_pixmap_height > data->new_ascent + data->new_descent) |
4187 | 940 { |
941 scaled_default_font_descent = (data->max_pixmap_height * | |
819 | 942 default_font_descent / default_font_height) + 1; |
943 | |
4187 | 944 data->new_descent = max (data->new_descent, scaled_default_font_descent); |
945 } | |
819 | 946 } |
947 } | |
948 | |
428 | 949 /* Given a display line and a starting position, ensure that the |
950 contents of the display line accurately represent the visual | |
951 representation of the buffer contents starting from the given | |
952 position when displayed in the given window. The display line ends | |
953 when the contents of the line reach the right boundary of the given | |
954 window. */ | |
955 | |
665 | 956 static Charbpos |
428 | 957 generate_display_line (struct window *w, struct display_line *dl, int bounds, |
665 | 958 Charbpos start_pos, prop_block_dynarr **prop, |
428 | 959 int type) |
960 { | |
826 | 961 Charbpos ret_charpos; |
428 | 962 int overlay_width; |
963 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); | |
964 | |
965 /* If our caller hasn't already set the boundaries, then do so now. */ | |
966 if (!bounds) | |
967 dl->bounds = calculate_display_line_boundaries (w, 0); | |
968 | |
969 /* Reset what this line is using. */ | |
970 if (dl->display_blocks) | |
971 Dynarr_reset (dl->display_blocks); | |
972 if (dl->left_glyphs) | |
973 { | |
974 Dynarr_free (dl->left_glyphs); | |
975 dl->left_glyphs = 0; | |
976 } | |
977 if (dl->right_glyphs) | |
978 { | |
979 Dynarr_free (dl->right_glyphs); | |
980 dl->right_glyphs = 0; | |
981 } | |
982 | |
983 /* We aren't generating a modeline at the moment. */ | |
984 dl->modeline = 0; | |
985 | |
986 /* Create a display block for the text region of the line. */ | |
987 { | |
988 /* #### urk urk urk!!! Chuck fix this shit! */ | |
665 | 989 Bytebpos hacked_up_bytebpos = |
990 create_text_block (w, dl, charbpos_to_bytebpos (b, start_pos), | |
428 | 991 prop, type); |
826 | 992 if (hacked_up_bytebpos > BYTE_BUF_ZV (b)) |
993 ret_charpos = BUF_ZV (b) + 1; | |
428 | 994 else |
826 | 995 ret_charpos = bytebpos_to_charbpos (b, hacked_up_bytebpos); |
428 | 996 } |
826 | 997 dl->charpos = start_pos; |
998 if (dl->end_charpos < dl->charpos) | |
999 dl->end_charpos = dl->charpos; | |
428 | 1000 |
1001 if (MARKERP (Voverlay_arrow_position) | |
1002 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position)) | |
1003 && start_pos == marker_position (Voverlay_arrow_position) | |
1004 && (STRINGP (Voverlay_arrow_string) | |
1005 || GLYPHP (Voverlay_arrow_string))) | |
1006 { | |
1007 overlay_width = create_overlay_glyph_block (w, dl); | |
1008 } | |
1009 else | |
1010 overlay_width = 0; | |
1011 | |
1012 /* If there are left glyphs associated with any character in the | |
1013 text block, then create a display block to handle them. */ | |
1014 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
1015 create_left_glyph_block (w, dl, overlay_width); | |
1016 | |
1017 /* If there are right glyphs associated with any character in the | |
1018 text block, then create a display block to handle them. */ | |
1019 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
1020 create_right_glyph_block (w, dl); | |
1021 | |
1022 /* In the future additional types of display blocks may be generated | |
1023 here. */ | |
1024 | |
826 | 1025 w->last_redisplay_pos = ret_charpos; |
1026 | |
1027 return ret_charpos; | |
428 | 1028 } |
1029 | |
1030 /* Adds an hscroll glyph to a display block. If this is called, then | |
1031 the block had better be empty. | |
1032 | |
1033 Yes, there are multiple places where this function is called but | |
1034 that is the way it has to be. Each calling function has to deal | |
826 | 1035 with byte_start_col_enabled a little differently depending on the |
428 | 1036 object being worked with. */ |
1037 | |
1038 static prop_block_dynarr * | |
1039 add_hscroll_rune (pos_data *data) | |
1040 { | |
1041 struct glyph_block gb; | |
1042 prop_block_dynarr *retval; | |
826 | 1043 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
647 | 1044 int old_cursor_type = data->cursor_type; |
826 | 1045 Bytebpos byte_old_charpos = data->byte_charpos; |
428 | 1046 |
1047 if (data->cursor_type == CURSOR_ON | |
826 | 1048 && data->byte_cursor_charpos >= data->byte_start_col_enabled |
1049 && data->byte_cursor_charpos <= data->byte_charpos) | |
1050 { | |
1051 data->byte_cursor_charpos = data->byte_start_col_enabled; | |
428 | 1052 } |
1053 else | |
1054 { | |
1055 data->cursor_type = NO_CURSOR; | |
1056 } | |
1057 | |
826 | 1058 data->byte_endpos = data->byte_charpos; |
1059 data->byte_charpos = data->byte_start_col_enabled; | |
428 | 1060 |
1061 gb.extent = Qnil; | |
1062 gb.glyph = Vhscroll_glyph; | |
1063 { | |
1064 int oldpixpos = data->pixpos; | |
442 | 1065 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, |
428 | 1066 GLYPH_CACHEL (XWINDOW (data->window), |
1067 HSCROLL_GLYPH_INDEX)); | |
1068 data->hscroll_glyph_width_adjust = | |
1069 data->pixpos - oldpixpos - space_width (XWINDOW (data->window)); | |
1070 } | |
826 | 1071 data->byte_endpos = 0; |
1072 data->byte_cursor_charpos = byte_old_cursor_charpos; | |
428 | 1073 data->cursor_type = old_cursor_type; |
826 | 1074 data->byte_charpos = byte_old_charpos; |
1075 | |
1076 data->byte_start_col_enabled = 0; | |
428 | 1077 return retval; |
1078 } | |
1079 | |
793 | 1080 /* Adds a character rune to a display block. If there is not enough room |
1081 to fit the rune on the display block (as determined by the MAX_PIXPOS) | |
1082 then it adds nothing and returns ADD_FAILED. If | |
1083 NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't allow the char's height | |
867 | 1084 to affect the total line height. (See add_ibyte_string_runes()). */ |
428 | 1085 |
1086 static prop_block_dynarr * | |
867 | 1087 add_ichar_rune_1 (pos_data *data, int no_contribute_to_line_height) |
428 | 1088 { |
1089 struct rune rb, *crb; | |
1090 int width, local; | |
1091 | |
1092 if (data->start_col) | |
1093 { | |
1094 data->start_col--; | |
1095 | |
1096 if (data->start_col) | |
1097 return NULL; | |
1098 } | |
1099 | |
826 | 1100 if (data->byte_start_col_enabled) |
428 | 1101 { |
1102 return add_hscroll_rune (data); | |
1103 } | |
1104 | |
1105 if (data->ch == '\n') | |
1106 { | |
1107 data->font_is_bogus = 0; | |
1108 /* Cheesy end-of-line pseudo-character. */ | |
1109 width = data->blank_width; | |
1110 } | |
1111 else | |
1112 { | |
867 | 1113 Lisp_Object charset = ichar_charset (data->ch); |
428 | 1114 if (!EQ (charset, data->last_charset) || |
1115 data->findex != data->last_findex) | |
1116 { | |
1117 /* OK, we need to do things the hard way. */ | |
1118 struct window *w = XWINDOW (data->window); | |
1119 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex); | |
1120 Lisp_Object font_instance = | |
1121 ensure_face_cachel_contains_charset (cachel, data->window, | |
1122 charset); | |
440 | 1123 Lisp_Font_Instance *fi; |
428 | 1124 |
1125 if (EQ (font_instance, Vthe_null_font_instance)) | |
1126 { | |
1127 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); | |
1128 data->font_is_bogus = 1; | |
1129 } | |
1130 else | |
1131 data->font_is_bogus = 0; | |
1132 | |
1133 fi = XFONT_INSTANCE (font_instance); | |
771 | 1134 if (!fi->proportional_p || data->font_is_bogus) |
1135 { | |
867 | 1136 Ichar ch = data->font_is_bogus ? '~' : data->ch; |
771 | 1137 |
1138 data->last_char_width = | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1139 redisplay_window_text_width_ichar_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1140 (XWINDOW (data->window), data->findex, &ch, 1); |
771 | 1141 } |
428 | 1142 else |
1143 data->last_char_width = -1; | |
819 | 1144 |
793 | 1145 if (!no_contribute_to_line_height) |
1146 { | |
1147 data->new_ascent = max (data->new_ascent, (int) fi->ascent); | |
1148 data->new_descent = max (data->new_descent, (int) fi->descent); | |
1149 } | |
819 | 1150 |
428 | 1151 data->last_charset = charset; |
1152 data->last_findex = data->findex; | |
1153 } | |
1154 | |
1155 width = data->last_char_width; | |
771 | 1156 if (width < 0) /* proportional fonts */ |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1157 width = redisplay_window_text_width_ichar_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1158 (XWINDOW (data->window), data->findex, &data->ch, 1); |
428 | 1159 } |
1160 | |
1161 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos)) | |
1162 { | |
1163 return ADD_FAILED; | |
1164 } | |
1165 | |
1166 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes)) | |
1167 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
1168 crb = Dynarr_past_lastp (data->db->runes); |
428 | 1169 local = 0; |
1170 } | |
1171 else | |
1172 { | |
1173 crb = &rb; | |
1174 local = 1; | |
1175 } | |
1176 | |
1177 crb->findex = data->findex; | |
1178 crb->xpos = data->pixpos; | |
1179 crb->width = width; | |
826 | 1180 if (data->byte_charpos) |
428 | 1181 { |
1182 if (NILP (data->string)) | |
826 | 1183 crb->charpos = |
793 | 1184 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER |
1185 (XWINDOW (data->window))), | |
826 | 1186 data->byte_charpos); |
428 | 1187 else |
826 | 1188 crb->charpos = |
1189 string_index_byte_to_char (data->string, data->byte_charpos); | |
428 | 1190 } |
1191 else if (data->is_modeline) | |
826 | 1192 crb->charpos = data->modeline_charpos; |
428 | 1193 else |
442 | 1194 /* Text but not in buffer */ |
826 | 1195 crb->charpos = 0; |
428 | 1196 crb->type = RUNE_CHAR; |
1197 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch; | |
1198 crb->endpos = 0; | |
1199 | |
1200 if (data->cursor_type == CURSOR_ON) | |
1201 { | |
826 | 1202 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 1203 { |
1204 crb->cursor_type = CURSOR_ON; | |
1205 data->cursor_x = Dynarr_length (data->db->runes); | |
1206 } | |
1207 else | |
1208 crb->cursor_type = CURSOR_OFF; | |
1209 } | |
1210 else if (data->cursor_type == NEXT_CURSOR) | |
1211 { | |
1212 crb->cursor_type = CURSOR_ON; | |
1213 data->cursor_x = Dynarr_length (data->db->runes); | |
1214 data->cursor_type = NO_CURSOR; | |
1215 } | |
1216 else if (data->cursor_type == IGNORE_CURSOR) | |
1217 crb->cursor_type = IGNORE_CURSOR; | |
1218 else | |
1219 crb->cursor_type = CURSOR_OFF; | |
1220 | |
1221 if (local) | |
1222 Dynarr_add (data->db->runes, *crb); | |
1223 else | |
5038 | 1224 Dynarr_incrementr (data->db->runes); |
428 | 1225 |
1226 data->pixpos += width; | |
1227 | |
1228 return NULL; | |
1229 } | |
1230 | |
793 | 1231 static prop_block_dynarr * |
867 | 1232 add_ichar_rune (pos_data *data) |
1233 { | |
1234 return add_ichar_rune_1 (data, 0); | |
1235 } | |
1236 | |
1237 /* Given a string C_STRING of length C_LENGTH, call add_ichar_rune for | |
793 | 1238 each character in the string. Propagate any left-over data unless |
1239 NO_PROP is non-zero. If NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't | |
1240 allow this character to increase the total height of the line. (This is | |
1241 used when the character is part of a text glyph. In that case, the | |
1242 glyph code itself adjusts the line height as necessary, depending on | |
1243 whether glyph-contrib-p is true.) */ | |
428 | 1244 |
1245 static prop_block_dynarr * | |
867 | 1246 add_ibyte_string_runes (pos_data *data, Ibyte *c_string, |
793 | 1247 Bytecount c_length, int no_prop, |
1248 int no_contribute_to_line_height) | |
428 | 1249 { |
867 | 1250 Ibyte *pos, *end = c_string + c_length; |
428 | 1251 prop_block_dynarr *prop; |
1252 | |
1253 /* #### This function is too simplistic. It needs to do the same | |
1254 sort of character interpretation (display-table lookup, | |
1255 ctl-arrow checking), etc. that create_text_block() does. | |
1256 The functionality to do this in that routine needs to be | |
1257 modularized. */ | |
1258 | |
1259 for (pos = c_string; pos < end;) | |
1260 { | |
867 | 1261 Ibyte *old_pos = pos; |
1262 | |
1263 data->ch = itext_ichar (pos); | |
1264 | |
1265 prop = add_ichar_rune_1 (data, no_contribute_to_line_height); | |
428 | 1266 |
1267 if (prop) | |
1268 { | |
1269 if (no_prop) | |
1270 return ADD_FAILED; | |
1271 else | |
1272 { | |
1273 struct prop_block pb; | |
1274 Bytecount len = end - pos; | |
1275 prop = Dynarr_new (prop_block); | |
1276 | |
1277 pb.type = PROP_STRING; | |
867 | 1278 pb.data.p_string.str = xnew_array (Ibyte, len); |
4970 | 1279 qxestrncpy (pb.data.p_string.str, pos, len); |
428 | 1280 pb.data.p_string.len = len; |
1281 | |
1282 Dynarr_add (prop, pb); | |
1283 return prop; | |
1284 } | |
1285 } | |
867 | 1286 INC_IBYTEPTR (pos); |
428 | 1287 assert (pos <= end); |
464 | 1288 /* #### Duplicate code from add_string_to_fstring_db_runes |
1289 should we do more?*/ | |
1290 data->bytepos += pos - old_pos; | |
428 | 1291 } |
1292 | |
1293 return NULL; | |
1294 } | |
1295 | |
1296 /* Add a single rune of the specified width. The area covered by this | |
1297 rune will be displayed in the foreground color of the associated | |
1298 face. */ | |
1299 | |
1300 static prop_block_dynarr * | |
1301 add_blank_rune (pos_data *data, struct window *w, int char_tab_width) | |
1302 { | |
1303 struct rune rb; | |
1304 | |
1305 /* If data->start_col is not 0 then this call to add_blank_rune must have | |
1306 been to add it as a tab. */ | |
1307 if (data->start_col) | |
1308 { | |
1309 /* assert (w != NULL) */ | |
1310 prop_block_dynarr *retval; | |
1311 | |
1312 /* If we have still not fully scrolled horizontally, subtract | |
4187 | 1313 the width of this tab and return. */ |
428 | 1314 if (char_tab_width < data->start_col) |
1315 { | |
1316 data->start_col -= char_tab_width; | |
1317 return NULL; | |
1318 } | |
1319 else if (char_tab_width == data->start_col) | |
1320 data->blank_width = 0; | |
1321 else | |
1322 { | |
1323 int spcwid = space_width (w); | |
1324 | |
1325 if (spcwid >= data->blank_width) | |
1326 data->blank_width = 0; | |
1327 else | |
1328 data->blank_width -= spcwid; | |
1329 } | |
1330 | |
1331 data->start_col = 0; | |
1332 retval = add_hscroll_rune (data); | |
1333 | |
1334 /* Could be caused by the handling of the hscroll rune. */ | |
1335 if (retval != NULL || !data->blank_width) | |
1336 return retval; | |
1337 } | |
1338 | |
1339 /* Blank runes are always calculated to fit. */ | |
1340 assert (data->pixpos + data->blank_width <= data->max_pixpos); | |
1341 | |
1342 rb.findex = data->findex; | |
1343 rb.xpos = data->pixpos; | |
1344 rb.width = data->blank_width; | |
826 | 1345 if (data->byte_charpos) |
1346 rb.charpos = | |
665 | 1347 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))), |
826 | 1348 data->byte_charpos); |
428 | 1349 else |
1350 /* #### and this is really correct too? */ | |
826 | 1351 rb.charpos = 0; |
428 | 1352 rb.endpos = 0; |
1353 rb.type = RUNE_BLANK; | |
1354 | |
1355 if (data->cursor_type == CURSOR_ON) | |
1356 { | |
826 | 1357 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 1358 { |
1359 rb.cursor_type = CURSOR_ON; | |
1360 data->cursor_x = Dynarr_length (data->db->runes); | |
1361 } | |
1362 else | |
1363 rb.cursor_type = CURSOR_OFF; | |
1364 } | |
1365 else if (data->cursor_type == NEXT_CURSOR) | |
1366 { | |
1367 rb.cursor_type = CURSOR_ON; | |
1368 data->cursor_x = Dynarr_length (data->db->runes); | |
1369 data->cursor_type = NO_CURSOR; | |
1370 } | |
1371 else | |
1372 rb.cursor_type = CURSOR_OFF; | |
1373 | |
1374 Dynarr_add (data->db->runes, rb); | |
1375 data->pixpos += data->blank_width; | |
1376 | |
1377 return NULL; | |
1378 } | |
1379 | |
1380 /* Add runes representing a character in octal. */ | |
1381 | |
1382 #define ADD_NEXT_OCTAL_RUNE_CHAR do \ | |
1383 { \ | |
867 | 1384 if (add_failed || (add_failed = add_ichar_rune (data))) \ |
428 | 1385 { \ |
1386 struct prop_block pb; \ | |
1387 if (!prop) \ | |
1388 prop = Dynarr_new (prop_block); \ | |
1389 \ | |
1390 pb.type = PROP_CHAR; \ | |
1391 pb.data.p_char.ch = data->ch; \ | |
1392 pb.data.p_char.cursor_type = data->cursor_type; \ | |
1393 Dynarr_add (prop, pb); \ | |
1394 } \ | |
1395 } while (0) | |
1396 | |
1397 static prop_block_dynarr * | |
1398 add_octal_runes (pos_data *data) | |
1399 { | |
819 | 1400 prop_block_dynarr *add_failed, *prop = 0; |
867 | 1401 Ichar orig_char = data->ch; |
647 | 1402 int orig_cursor_type = data->cursor_type; |
428 | 1403 |
1404 /* Initialize */ | |
1405 add_failed = NULL; | |
1406 | |
1407 if (data->start_col) | |
1408 data->start_col--; | |
1409 | |
1410 if (!data->start_col) | |
1411 { | |
826 | 1412 if (data->byte_start_col_enabled) |
428 | 1413 { |
1414 add_failed = add_hscroll_rune (data); | |
1415 } | |
1416 else | |
1417 { | |
1418 struct glyph_block gb; | |
1419 struct window *w = XWINDOW (data->window); | |
1420 | |
1421 gb.extent = Qnil; | |
1422 gb.glyph = Voctal_escape_glyph; | |
1423 add_failed = | |
1424 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
1425 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX)); | |
1426 } | |
1427 } | |
1428 | |
1429 /* We only propagate information if the glyph was partially | |
1430 added. */ | |
1431 if (add_failed) | |
1432 return add_failed; | |
1433 | |
1434 data->cursor_type = IGNORE_CURSOR; | |
1435 | |
1436 if (data->ch >= 0x100) | |
1437 { | |
1438 /* If the character is an extended Mule character, it could have | |
3498 | 1439 up to 21 bits. For the moment, we treat it as a seven-digit |
428 | 1440 octal number. This is not that pretty, but whatever. */ |
1441 data->ch = (7 & (orig_char >> 18)) + '0'; | |
1442 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1443 | |
1444 data->ch = (7 & (orig_char >> 15)) + '0'; | |
1445 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1446 | |
1447 data->ch = (7 & (orig_char >> 12)) + '0'; | |
1448 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1449 | |
1450 data->ch = (7 & (orig_char >> 9)) + '0'; | |
1451 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1452 } | |
1453 | |
1454 data->ch = (7 & (orig_char >> 6)) + '0'; | |
1455 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1456 | |
1457 data->ch = (7 & (orig_char >> 3)) + '0'; | |
1458 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1459 | |
1460 data->ch = (7 & orig_char) + '0'; | |
1461 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1462 | |
1463 data->cursor_type = orig_cursor_type; | |
819 | 1464 return NULL; |
428 | 1465 } |
1466 | |
1467 #undef ADD_NEXT_OCTAL_RUNE_CHAR | |
1468 | |
1469 /* Add runes representing a control character to a display block. */ | |
1470 | |
1471 static prop_block_dynarr * | |
1472 add_control_char_runes (pos_data *data, struct buffer *b) | |
1473 { | |
1474 if (!NILP (b->ctl_arrow)) | |
1475 { | |
1476 prop_block_dynarr *prop; | |
867 | 1477 Ichar orig_char = data->ch; |
647 | 1478 int old_cursor_type = data->cursor_type; |
428 | 1479 |
1480 /* Initialize */ | |
1481 prop = NULL; | |
1482 | |
1483 if (data->start_col) | |
1484 data->start_col--; | |
1485 | |
1486 if (!data->start_col) | |
1487 { | |
826 | 1488 if (data->byte_start_col_enabled) |
428 | 1489 { |
1490 prop_block_dynarr *retval; | |
1491 | |
1492 retval = add_hscroll_rune (data); | |
1493 if (retval) | |
1494 return retval; | |
1495 } | |
1496 else | |
1497 { | |
1498 struct glyph_block gb; | |
1499 struct window *w = XWINDOW (data->window); | |
1500 | |
1501 gb.extent = Qnil; | |
1502 gb.glyph = Vcontrol_arrow_glyph; | |
1503 | |
1504 /* We only propagate information if the glyph was partially | |
1505 added. */ | |
1506 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
1507 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX))) | |
1508 return ADD_FAILED; | |
1509 } | |
1510 } | |
1511 | |
1512 if (orig_char == 0177) | |
1513 data->ch = '?'; | |
1514 else | |
1515 data->ch = orig_char ^ 0100; | |
1516 data->cursor_type = IGNORE_CURSOR; | |
1517 | |
867 | 1518 if (add_ichar_rune (data)) |
428 | 1519 { |
1520 struct prop_block pb; | |
1521 if (!prop) | |
1522 prop = Dynarr_new (prop_block); | |
1523 | |
1524 pb.type = PROP_CHAR; | |
1525 pb.data.p_char.ch = data->ch; | |
1526 pb.data.p_char.cursor_type = data->cursor_type; | |
1527 Dynarr_add (prop, pb); | |
1528 } | |
1529 | |
1530 data->cursor_type = old_cursor_type; | |
1531 return prop; | |
1532 } | |
1533 else | |
1534 { | |
1535 return add_octal_runes (data); | |
1536 } | |
1537 } | |
1538 | |
1539 static prop_block_dynarr * | |
1540 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) | |
1541 { | |
1542 prop_block_dynarr *prop = NULL; | |
1543 | |
1544 if (STRINGP (entry)) | |
1545 { | |
867 | 1546 prop = add_ibyte_string_runes (data, |
428 | 1547 XSTRING_DATA (entry), |
1548 XSTRING_LENGTH (entry), | |
793 | 1549 0, 0); |
428 | 1550 } |
1551 else if (GLYPHP (entry)) | |
1552 { | |
1553 if (data->start_col) | |
1554 data->start_col--; | |
1555 | |
826 | 1556 if (!data->start_col && data->byte_start_col_enabled) |
428 | 1557 { |
1558 prop = add_hscroll_rune (data); | |
1559 } | |
1560 else | |
1561 { | |
1562 struct glyph_block gb; | |
1563 | |
1564 gb.glyph = entry; | |
1565 gb.extent = Qnil; | |
1566 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); | |
1567 } | |
1568 } | |
1569 else if (CHAR_OR_CHAR_INTP (entry)) | |
1570 { | |
1571 data->ch = XCHAR_OR_CHAR_INT (entry); | |
867 | 1572 prop = add_ichar_rune (data); |
428 | 1573 } |
1574 else if (CONSP (entry)) | |
1575 { | |
1576 if (EQ (XCAR (entry), Qformat) | |
1577 && CONSP (XCDR (entry)) | |
1578 && STRINGP (XCAR (XCDR (entry)))) | |
1579 { | |
1580 Lisp_Object format = XCAR (XCDR (entry)); | |
665 | 1581 Bytebpos len = XSTRING_LENGTH (format); |
867 | 1582 Ibyte *src = XSTRING_DATA (format), *end = src + len; |
2367 | 1583 Ibyte *result = alloca_ibytes (len); |
867 | 1584 Ibyte *dst = result; |
428 | 1585 |
1586 while (src < end) | |
1587 { | |
867 | 1588 Ichar c = itext_ichar (src); |
1589 INC_IBYTEPTR (src); | |
428 | 1590 if (c != '%' || src == end) |
867 | 1591 dst += set_itext_ichar (dst, c); |
428 | 1592 else |
1593 { | |
867 | 1594 c = itext_ichar (src); |
1595 INC_IBYTEPTR (src); | |
428 | 1596 switch (c) |
1597 { | |
1598 /*case 'x': | |
1599 dst += long_to_string_base ((char *)dst, data->ch, 16); | |
1600 break;*/ | |
1601 case '%': | |
867 | 1602 dst += set_itext_ichar (dst, '%'); |
428 | 1603 break; |
442 | 1604 /* #### unimplemented */ |
428 | 1605 } |
1606 } | |
1607 } | |
867 | 1608 prop = add_ibyte_string_runes (data, result, dst - result, 0, 0); |
428 | 1609 } |
1610 } | |
1611 | |
1612 /* Else blow it off because someone added a bad entry and we don't | |
1613 have any safe way of signaling an error. */ | |
1614 return prop; | |
1615 } | |
1616 | |
1617 /* Given a display table entry, call the appropriate functions to | |
1618 display each element of the entry. */ | |
1619 | |
1620 static prop_block_dynarr * | |
1621 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) | |
1622 { | |
1623 prop_block_dynarr *prop = NULL; | |
1624 if (VECTORP (entry)) | |
1625 { | |
440 | 1626 Lisp_Vector *de = XVECTOR (entry); |
428 | 1627 EMACS_INT len = vector_length (de); |
1628 int elt; | |
1629 | |
1630 for (elt = 0; elt < len; elt++) | |
1631 { | |
1632 if (NILP (vector_data (de)[elt])) | |
1633 continue; | |
1634 else | |
1635 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]); | |
1636 /* Else blow it off because someone added a bad entry and we | |
1637 don't have any safe way of signaling an error. Hey, this | |
1638 comment sounds familiar. */ | |
1639 | |
1640 /* #### Still need to add any remaining elements to the | |
4187 | 1641 propagation information. */ |
428 | 1642 if (prop) |
1643 return prop; | |
1644 } | |
1645 } | |
1646 else | |
1647 prop = add_disp_table_entry_runes_1 (data, entry); | |
1648 return prop; | |
1649 } | |
1650 | |
1651 /* Add runes which were propagated from the previous line. */ | |
1652 | |
1653 static prop_block_dynarr * | |
1654 add_propagation_runes (prop_block_dynarr **prop, pos_data *data) | |
1655 { | |
1656 /* #### Remember to handle start_col parameter of data when the rest of | |
1657 this is finished. */ | |
1658 /* #### Chuck -- I've redone this function a bit. It looked like the | |
1659 case of not all the propagation blocks being added was not handled | |
1660 well. */ | |
1661 /* #### Chuck -- I also think the double indirection of PROP is kind | |
1662 of bogus. A cleaner solution is just to check for | |
1663 Dynarr_length (prop) > 0. */ | |
1664 /* #### This function also doesn't even pay attention to ADD_FAILED! | |
1665 This is seriously fucked! Seven ####'s in 130 lines -- is that a | |
1666 record? */ | |
1667 int elt; | |
1668 prop_block_dynarr *add_failed; | |
826 | 1669 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
647 | 1670 int old_cursor_type = data->cursor_type; |
428 | 1671 |
1672 for (elt = 0; elt < Dynarr_length (*prop); elt++) | |
1673 { | |
1674 struct prop_block *pb = Dynarr_atp (*prop, elt); | |
1675 | |
1676 switch (pb->type) | |
1677 { | |
1678 case PROP_CHAR: | |
1679 data->ch = pb->data.p_char.ch; | |
826 | 1680 data->byte_cursor_charpos = pb->data.p_char.byte_cursor_charpos; |
428 | 1681 data->cursor_type = pb->data.p_char.cursor_type; |
867 | 1682 add_failed = add_ichar_rune (data); |
428 | 1683 |
1684 if (add_failed) | |
1685 goto oops_no_more_space; | |
1686 break; | |
1687 case PROP_STRING: | |
1688 if (pb->data.p_string.str) | |
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
|
1689 { |
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 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
|
1691 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
|
1692 } |
428 | 1693 /* #### bogus bogus -- this doesn't do anything! |
867 | 1694 Should probably call add_ibyte_string_runes(), |
428 | 1695 once that function is fixed. */ |
1696 break; | |
1697 case PROP_MINIBUF_PROMPT: | |
1698 { | |
1699 face_index old_findex = data->findex; | |
826 | 1700 Bytebpos byte_old_charpos = data->byte_charpos; |
5688
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1701 Boolint stop_after = NILP (pb->data.p_minibuf_prompt.preprompt); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1702 Lisp_Object str = stop_after ? pb->data.p_minibuf_prompt.prompt |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1703 : pb->data.p_minibuf_prompt.preprompt; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1704 struct window *w = XWINDOW (data->window); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1705 |
826 | 1706 data->byte_charpos = 0; |
428 | 1707 data->cursor_type = NO_CURSOR; |
1708 | |
5688
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1709 /* This doesn't handle begin-glyphs and end-glyphs and so on. It |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1710 may be reasonable not to, given that we're a "propagation |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1711 glyph", but it's not intuitively clear either way. It is |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1712 clear that it should handle the face and the display |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1713 table. */ |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1714 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1715 while (STRINGP (str)) |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1716 { |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1717 Ibyte *pstart = XSTRING_DATA (str), *pp = pstart, |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1718 *pend = pstart + XSTRING_LENGTH (str); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1719 struct extent_fragment *ef |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1720 = extent_fragment_new (str, XFRAME (w->frame)); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1721 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1722 while (pp < pend) |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1723 { |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1724 Lisp_Object face_dt, window_dt, entry = Qnil; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1725 face_index new_findex |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1726 = data->findex = extent_fragment_update (w, ef, |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1727 pp - pstart, |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1728 Qnil); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1729 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1730 data->ch = itext_ichar (pp); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1731 get_display_tables (w, new_findex, &face_dt, &window_dt); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1732 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1733 if (!NILP (face_dt) || !NILP (window_dt)) |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1734 { |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1735 entry = display_table_entry (data->ch, face_dt, |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1736 window_dt); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1737 } |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1738 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1739 /* If there is a display table entry for it, hand it off |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1740 to add_disp_table_entry_runes and let it worry about |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1741 it. */ |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1742 if (!NILP (entry) && !EQ (entry, make_char (data->ch))) |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1743 { |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1744 add_failed = add_disp_table_entry_runes (data, entry); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1745 } |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1746 else |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1747 { |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1748 add_failed = add_ichar_rune (data); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1749 } |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1750 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1751 if (add_failed) |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1752 { |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1753 data->findex = old_findex; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1754 data->byte_charpos = byte_old_charpos; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1755 extent_fragment_delete (ef); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1756 goto oops_no_more_space; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1757 } |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1758 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1759 INC_IBYTEPTR (pp); |
428 | 1760 } |
5688
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1761 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1762 extent_fragment_delete (ef); |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1763 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1764 if (stop_after) |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1765 { |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1766 break; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1767 } |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1768 |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1769 str = pb->data.p_minibuf_prompt.prompt; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1770 stop_after = 1; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
1771 } |
428 | 1772 |
1773 data->findex = old_findex; | |
1774 /* ##### FIXME FIXME FIXME -- Upon successful return from | |
826 | 1775 this function, data->byte_charpos is automatically incremented. |
428 | 1776 However, we don't want that to happen if we were adding |
1777 the minibuffer prompt. */ | |
1778 { | |
1779 struct buffer *buf = | |
1780 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))); | |
1781 /* #### Chuck fix this shit or I'm gonna scream! */ | |
826 | 1782 if (byte_old_charpos > BYTE_BUF_BEGV (buf)) |
4187 | 1783 data->byte_charpos = prev_bytebpos (buf, byte_old_charpos); |
1784 else | |
428 | 1785 /* #### is this correct? Does anyone know? |
1786 Does anyone care? Is this a cheesy hack or what? */ | |
4187 | 1787 data->byte_charpos = BYTE_BUF_BEGV (buf) - 1; |
428 | 1788 } |
1789 } | |
1790 break; | |
1791 case PROP_BLANK: | |
1792 { | |
1793 /* #### I think it's unnecessary and misleading to preserve | |
1794 the blank_width, as it implies that the value carries | |
1795 over from one rune to the next, which is wrong. */ | |
1796 int old_width = data->blank_width; | |
1797 face_index old_findex = data->findex; | |
1798 | |
1799 data->findex = pb->data.p_blank.findex; | |
1800 data->blank_width = pb->data.p_blank.width; | |
826 | 1801 data->byte_cursor_charpos = 0; |
428 | 1802 data->cursor_type = IGNORE_CURSOR; |
1803 | |
1804 if (data->pixpos + data->blank_width > data->max_pixpos) | |
1805 data->blank_width = data->max_pixpos - data->pixpos; | |
1806 | |
1807 /* We pass a bogus value of char_tab_width. It shouldn't | |
4187 | 1808 matter because unless something is really screwed up |
1809 this call won't cause that arg to be used. */ | |
428 | 1810 add_failed = add_blank_rune (data, XWINDOW (data->window), 0); |
1811 | |
1812 /* This can happen in the case where we have a tab which | |
4187 | 1813 is wider than the window. */ |
428 | 1814 if (data->blank_width != pb->data.p_blank.width) |
1815 { | |
1816 pb->data.p_blank.width -= data->blank_width; | |
1817 add_failed = ADD_FAILED; | |
1818 } | |
1819 | |
1820 data->findex = old_findex; | |
1821 data->blank_width = old_width; | |
1822 | |
1823 if (add_failed) | |
1824 goto oops_no_more_space; | |
1825 } | |
1826 break; | |
1827 default: | |
2500 | 1828 ABORT (); |
428 | 1829 } |
1830 } | |
1831 | |
1832 oops_no_more_space: | |
1833 | |
826 | 1834 data->byte_cursor_charpos = byte_old_cursor_charpos; |
428 | 1835 data->cursor_type = old_cursor_type; |
1836 if (elt < Dynarr_length (*prop)) | |
1837 { | |
1838 Dynarr_delete_many (*prop, 0, elt); | |
1839 return *prop; | |
1840 } | |
1841 else | |
1842 { | |
1843 Dynarr_free (*prop); | |
1844 return NULL; | |
1845 } | |
1846 } | |
1847 | |
3025 | 1848 /* Add `text' layout glyphs at position POS_TYPE that are contained to |
428 | 1849 the display block, but add all other types to the appropriate list |
1850 of the display line. They will be added later by different | |
1851 routines. */ | |
1852 | |
1853 static prop_block_dynarr * | |
1854 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, | |
1855 int allow_cursor, struct glyph_cachel *cachel) | |
1856 { | |
1857 struct window *w = XWINDOW (data->window); | |
1858 | |
440 | 1859 /* If window faces changed, and glyph instance is text, then |
1860 glyph sizes might have changed too */ | |
1861 invalidate_glyph_geometry_maybe (gb->glyph, w); | |
1862 | |
442 | 1863 /* This makes sure the glyph is in the cachels. |
1864 | |
1865 #### We do this to make sure the glyph is in the glyph cachels, | |
1866 so that the dirty flag can be reset after redisplay has | |
1867 finished. We should do this some other way, maybe by iterating | |
1868 over the window cache of subwindows. */ | |
1869 get_glyph_cachel_index (w, gb->glyph); | |
1870 | |
428 | 1871 /* A nil extent indicates a special glyph (ex. truncator). */ |
1872 if (NILP (gb->extent) | |
1873 || (pos_type == BEGIN_GLYPHS && | |
1874 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) | |
1875 || (pos_type == END_GLYPHS && | |
442 | 1876 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) |
1877 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) | |
428 | 1878 { |
1879 struct rune rb; | |
1880 int width; | |
1881 int xoffset = 0; | |
1882 int ascent, descent; | |
1883 Lisp_Object baseline; | |
1884 Lisp_Object face; | |
442 | 1885 Lisp_Object instance; |
1886 face_index findex; | |
819 | 1887 prop_block_dynarr *retval = 0; |
428 | 1888 |
1889 if (cachel) | |
1890 width = cachel->width; | |
1891 else | |
438 | 1892 width = glyph_width (gb->glyph, data->window); |
428 | 1893 |
1894 if (!width) | |
1895 return NULL; | |
1896 | |
1897 if (data->start_col || data->start_col_xoffset) | |
1898 { | |
1899 int glyph_char_width = width / space_width (w); | |
1900 | |
1901 /* If we still have not fully scrolled horizontally after | |
4187 | 1902 taking into account the width of the glyph, subtract its |
1903 width and return. */ | |
428 | 1904 if (glyph_char_width < data->start_col) |
1905 { | |
1906 data->start_col -= glyph_char_width; | |
1907 return NULL; | |
1908 } | |
1909 else if (glyph_char_width == data->start_col) | |
1910 width = 0; | |
1911 else | |
1912 { | |
1913 xoffset = space_width (w) * data->start_col; | |
1914 width -= xoffset; | |
1915 | |
1916 /* #### Can this happen? */ | |
1917 if (width < 0) | |
1918 width = 0; | |
1919 } | |
1920 | |
1921 data->start_col = 0; | |
1922 retval = add_hscroll_rune (data); | |
1923 | |
1924 /* Could be caused by the handling of the hscroll rune. */ | |
1925 if (retval != NULL || !width) | |
1926 return retval; | |
1927 } | |
1928 else | |
1929 xoffset = 0; | |
1930 | |
1931 if (data->pixpos + width > data->max_pixpos) | |
1932 { | |
1933 /* If this is the first object we are attempting to add to | |
819 | 1934 the line then we ignore the horizontal_clip threshold. |
1935 Otherwise we will loop until the bottom of the window | |
1936 continually failing to add this glyph because it is wider | |
1937 than the window. We could alternatively just completely | |
1938 ignore the glyph and proceed from there but I think that | |
1939 this is a better solution. | |
4187 | 1940 |
819 | 1941 This does, however, create a different problem in that we |
1942 can end up adding the object to every single line, never | |
1943 getting any further - for instance an extent with a long | |
1944 start-glyph that covers multitple following | |
1945 characters. */ | |
428 | 1946 if (Dynarr_length (data->db->runes) |
1947 && data->max_pixpos - data->pixpos < horizontal_clip) | |
1948 return ADD_FAILED; | |
819 | 1949 else { |
1950 struct prop_block pb; | |
1951 | |
1952 /* We need to account for the width of the end-of-line | |
1953 glyph if there is nothing more in the line to display, | |
1954 since we will not display it in this instance. It seems | |
1955 kind of gross doing it here, but otherwise we have to | |
1956 search the runes in create_text_block(). */ | |
1957 if (data->ch == '\n') | |
1958 data->max_pixpos += data->end_glyph_width; | |
428 | 1959 width = data->max_pixpos - data->pixpos; |
819 | 1960 /* Add the glyph we are displaying, but clipping, to the |
1961 propagation data so that we don't try and do it | |
4187 | 1962 again. */ |
819 | 1963 retval = Dynarr_new (prop_block); |
1964 pb.type = PROP_GLYPH; | |
1965 pb.data.p_glyph.glyph = gb->glyph; | |
1966 pb.data.p_glyph.width = width; | |
1967 Dynarr_add (retval, pb); | |
1968 } | |
428 | 1969 } |
1970 | |
1971 if (cachel) | |
1972 { | |
1973 ascent = cachel->ascent; | |
1974 descent = cachel->descent; | |
1975 } | |
1976 else | |
1977 { | |
438 | 1978 ascent = glyph_ascent (gb->glyph, data->window); |
1979 descent = glyph_descent (gb->glyph, data->window); | |
428 | 1980 } |
1981 | |
1982 baseline = glyph_baseline (gb->glyph, data->window); | |
1983 | |
819 | 1984 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ |
1985 | |
428 | 1986 if (glyph_contrib_p (gb->glyph, data->window)) |
1987 { | |
1988 /* A pixmap that has not had a baseline explicitly set. Its | |
1989 contribution will be determined later. */ | |
1990 if (NILP (baseline)) | |
1991 { | |
1992 int height = ascent + descent; | |
819 | 1993 data->need_baseline_computation = 1; |
428 | 1994 data->max_pixmap_height = max (data->max_pixmap_height, height); |
1995 } | |
1996 | |
1997 /* A string so determine contribution normally. */ | |
1998 else if (EQ (baseline, Qt)) | |
1999 { | |
2000 data->new_ascent = max (data->new_ascent, ascent); | |
2001 data->new_descent = max (data->new_descent, descent); | |
2002 } | |
2003 | |
2004 /* A pixmap with an explicitly set baseline. We determine the | |
2005 contribution here. */ | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
2006 else if (FIXNUMP (baseline)) |
428 | 2007 { |
2008 int height = ascent + descent; | |
2009 int pix_ascent, pix_descent; | |
2010 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
2011 pix_ascent = height * XFIXNUM (baseline) / 100; |
428 | 2012 pix_descent = height - pix_ascent; |
2013 | |
2014 data->new_ascent = max (data->new_ascent, pix_ascent); | |
2015 data->new_descent = max (data->new_descent, pix_descent); | |
819 | 2016 data->max_pixmap_height = max (data->max_pixmap_height, height); |
4187 | 2017 |
819 | 2018 rb.object.dglyph.descent = pix_descent; |
428 | 2019 } |
2020 | |
2021 /* Otherwise something is screwed up. */ | |
2022 else | |
2500 | 2023 ABORT (); |
428 | 2024 } |
2025 | |
2026 face = glyph_face (gb->glyph, data->window); | |
2027 if (NILP (face)) | |
442 | 2028 findex = data->findex; |
428 | 2029 else |
442 | 2030 findex = get_builtin_face_cache_index (w, face); |
2031 | |
2032 instance = glyph_image_instance (gb->glyph, data->window, | |
793 | 2033 ERROR_ME_DEBUG_WARN, 1); |
442 | 2034 if (TEXT_IMAGE_INSTANCEP (instance)) |
2035 { | |
2036 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); | |
2037 face_index orig_findex = data->findex; | |
826 | 2038 Bytebpos orig_charpos = data->byte_charpos; |
2039 Bytebpos orig_start_col_enabled = data->byte_start_col_enabled; | |
442 | 2040 |
2041 data->findex = findex; | |
826 | 2042 data->byte_start_col_enabled = 0; |
442 | 2043 if (!allow_cursor) |
826 | 2044 data->byte_charpos = 0; |
867 | 2045 add_ibyte_string_runes (data, XSTRING_DATA (string), |
793 | 2046 XSTRING_LENGTH (string), 0, 1); |
442 | 2047 data->findex = orig_findex; |
826 | 2048 data->byte_charpos = orig_charpos; |
2049 data->byte_start_col_enabled = orig_start_col_enabled; | |
819 | 2050 return retval; |
442 | 2051 } |
2052 | |
2053 rb.findex = findex; | |
428 | 2054 rb.xpos = data->pixpos; |
2055 rb.width = width; | |
826 | 2056 rb.charpos = 0; /* glyphs are never "at" anywhere */ |
2057 if (data->byte_endpos) | |
428 | 2058 /* #### is this necessary at all? */ |
665 | 2059 rb.endpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
826 | 2060 data->byte_endpos); |
428 | 2061 else |
4187 | 2062 rb.endpos = 0; |
428 | 2063 rb.type = RUNE_DGLYPH; |
2064 rb.object.dglyph.glyph = gb->glyph; | |
2065 rb.object.dglyph.extent = gb->extent; | |
2066 rb.object.dglyph.xoffset = xoffset; | |
819 | 2067 rb.object.dglyph.ascent = ascent; |
2068 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has | |
2069 a normal (textual) baseline. */ | |
428 | 2070 |
2071 if (allow_cursor) | |
2072 { | |
826 | 2073 rb.charpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
2074 data->byte_charpos); | |
428 | 2075 |
2076 if (data->cursor_type == CURSOR_ON) | |
2077 { | |
826 | 2078 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 2079 { |
2080 rb.cursor_type = CURSOR_ON; | |
2081 data->cursor_x = Dynarr_length (data->db->runes); | |
2082 } | |
2083 else | |
2084 rb.cursor_type = CURSOR_OFF; | |
2085 } | |
2086 else if (data->cursor_type == NEXT_CURSOR) | |
2087 { | |
2088 rb.cursor_type = CURSOR_ON; | |
2089 data->cursor_x = Dynarr_length (data->db->runes); | |
2090 data->cursor_type = NO_CURSOR; | |
2091 } | |
2092 else if (data->cursor_type == IGNORE_CURSOR) | |
2093 rb.cursor_type = IGNORE_CURSOR; | |
2094 else if (data->cursor_type == NO_CURSOR) | |
2095 rb.cursor_type = NO_CURSOR; | |
2096 else | |
2097 rb.cursor_type = CURSOR_OFF; | |
2098 } | |
2099 else | |
2100 rb.cursor_type = CURSOR_OFF; | |
2101 | |
2102 Dynarr_add (data->db->runes, rb); | |
2103 data->pixpos += width; | |
2104 | |
819 | 2105 return retval; |
428 | 2106 } |
2107 else | |
2108 { | |
2109 if (!NILP (glyph_face (gb->glyph, data->window))) | |
2110 gb->findex = | |
2111 get_builtin_face_cache_index (w, glyph_face (gb->glyph, | |
2112 data->window)); | |
2113 else | |
2114 gb->findex = data->findex; | |
2115 | |
2116 if (pos_type == BEGIN_GLYPHS) | |
2117 { | |
2118 if (!data->dl->left_glyphs) | |
2119 data->dl->left_glyphs = Dynarr_new (glyph_block); | |
2120 Dynarr_add (data->dl->left_glyphs, *gb); | |
2121 return NULL; | |
2122 } | |
2123 else if (pos_type == END_GLYPHS) | |
2124 { | |
2125 if (!data->dl->right_glyphs) | |
2126 data->dl->right_glyphs = Dynarr_new (glyph_block); | |
2127 Dynarr_add (data->dl->right_glyphs, *gb); | |
2128 return NULL; | |
2129 } | |
2130 else | |
2500 | 2131 ABORT (); /* there are no unknown types */ |
428 | 2132 } |
2133 | |
819 | 2134 return NULL; |
428 | 2135 } |
2136 | |
2137 /* Add all glyphs at position POS_TYPE that are contained in the given | |
2138 data. */ | |
2139 | |
2140 static prop_block_dynarr * | |
2141 add_glyph_runes (pos_data *data, int pos_type) | |
2142 { | |
2143 /* #### This still needs to handle the start_col parameter. Duh, Chuck, | |
2144 why didn't you just modify add_glyph_rune in the first place? */ | |
2145 int elt; | |
2146 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS | |
2147 ? data->ef->begin_glyphs | |
2148 : data->ef->end_glyphs); | |
2149 prop_block_dynarr *prop; | |
2150 | |
2151 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++) | |
2152 { | |
2153 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0, | |
2154 0); | |
2155 | |
2156 if (prop) | |
2157 { | |
2158 /* #### Add some propagation information. */ | |
2159 return prop; | |
2160 } | |
2161 } | |
2162 | |
2163 Dynarr_reset (glyph_arr); | |
2164 | |
2165 return NULL; | |
2166 } | |
2167 | |
2168 /* Given a position for a buffer in a window, ensure that the given | |
2169 display line DL accurately represents the text on a line starting | |
2170 at the given position. | |
2171 | |
826 | 2172 NOTE NOTE NOTE NOTE: This function works with and returns Bytebpos's. |
428 | 2173 You must do appropriate conversion. */ |
2174 | |
665 | 2175 static Bytebpos |
428 | 2176 create_text_block (struct window *w, struct display_line *dl, |
826 | 2177 Bytebpos byte_start_pos, prop_block_dynarr **prop, |
428 | 2178 int type) |
2179 { | |
2180 struct frame *f = XFRAME (w->frame); | |
2181 struct buffer *b = XBUFFER (w->buffer); | |
2182 struct device *d = XDEVICE (f->device); | |
2183 | |
2184 pos_data data; | |
2185 | |
2186 /* Don't display anything in the minibuffer if this window is not on | |
2187 a selected frame. We consider all other windows to be active | |
2188 minibuffers as it simplifies the coding. */ | |
2189 int active_minibuffer = (!MINI_WINDOW_P (w) || | |
2190 (f == device_selected_frame (d)) || | |
2191 is_surrogate_for_selected_frame (f)); | |
2192 | |
2193 int truncate_win = window_truncation_on (w); | |
2194 | |
2195 /* If the buffer's value of selective_display is an integer then | |
2196 only lines that start with less than selective_display columns of | |
2197 space will be displayed. If selective_display is t then all text | |
2198 after a ^M is invisible. */ | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
2199 int selective = (FIXNUMP (b->selective_display) |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
2200 ? XFIXNUM (b->selective_display) |
434 | 2201 : (!NILP (b->selective_display) ? -1 : 0)); |
428 | 2202 |
2203 /* The variable ctl-arrow allows the user to specify what characters | |
2204 can actually be displayed and which octal should be used for. | |
2205 #### This variable should probably have some rethought done to | |
2206 it. | |
2207 | |
2367 | 2208 See also |
2209 | |
2210 (Info-goto-node "(internals)Future Work -- Display Tables") | |
2211 | |
2212 */ | |
867 | 2213 Ichar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
428 | 2214 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
2215 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
2216 ? 255 : 160)); | |
2217 | |
2218 Lisp_Object face_dt, window_dt; | |
2219 | |
2220 /* The text display block for this display line. */ | |
2221 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
2222 | |
2223 /* The first time through the main loop we need to force the glyph | |
2224 data to be updated. */ | |
2225 int initial = 1; | |
2226 | |
2227 /* Apparently the new extent_fragment_update returns an end position | |
2228 equal to the position passed in if there are no more runs to be | |
2229 displayed. */ | |
2230 int no_more_frags = 0; | |
2231 | |
2232 Lisp_Object synch_minibuffers_value = | |
2233 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer); | |
2234 | |
2235 dl->used_prop_data = 0; | |
2236 dl->num_chars = 0; | |
442 | 2237 dl->line_continuation = 0; |
5617
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
2238 dl->clear_findex = DEFAULT_INDEX; |
428 | 2239 |
2240 xzero (data); | |
2241 data.ef = extent_fragment_new (w->buffer, f); | |
2242 | |
2243 /* These values are used by all of the rune addition routines. We add | |
2244 them to this structure for ease of passing. */ | |
2245 data.d = d; | |
793 | 2246 data.window = wrap_window (w); |
428 | 2247 data.string = Qnil; |
2248 data.db = db; | |
2249 data.dl = dl; | |
2250 | |
826 | 2251 data.byte_charpos = byte_start_pos; |
428 | 2252 data.pixpos = dl->bounds.left_in; |
2253 data.last_charset = Qunbound; | |
2254 data.last_findex = DEFAULT_INDEX; | |
2255 data.result_str = Qnil; | |
2256 | |
2257 /* Set the right boundary adjusting it to take into account any end | |
2258 glyph. Save the width of the end glyph for later use. */ | |
2259 data.max_pixpos = dl->bounds.right_in; | |
2260 if (truncate_win) | |
819 | 2261 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); |
428 | 2262 else |
819 | 2263 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); |
2264 data.max_pixpos -= data.end_glyph_width; | |
428 | 2265 |
2266 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f)) | |
2267 { | |
826 | 2268 data.byte_cursor_charpos = BYTE_BUF_ZV (b); |
428 | 2269 data.cursor_type = CURSOR_ON; |
2270 } | |
2271 else if (MINI_WINDOW_P (w) && !active_minibuffer) | |
2272 data.cursor_type = NO_CURSOR; | |
2273 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) && | |
5198 | 2274 EQ (DEVICE_CONSOLE (d), Vselected_console) && |
2275 d == XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d))))&& | |
2276 f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
428 | 2277 { |
826 | 2278 data.byte_cursor_charpos = BYTE_BUF_PT (b); |
428 | 2279 data.cursor_type = CURSOR_ON; |
2280 } | |
2281 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | |
2282 { | |
826 | 2283 data.byte_cursor_charpos = byte_marker_position (w->pointm[type]); |
428 | 2284 data.cursor_type = CURSOR_ON; |
2285 } | |
2286 else | |
2287 data.cursor_type = NO_CURSOR; | |
2288 data.cursor_x = -1; | |
2289 | |
2290 data.start_col = w->hscroll; | |
2291 data.start_col_xoffset = w->left_xoffset; | |
826 | 2292 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
428 | 2293 data.hscroll_glyph_width_adjust = 0; |
2294 | |
2295 /* We regenerate the line from the very beginning. */ | |
2296 Dynarr_reset (db->runes); | |
2297 | |
2298 /* Why is this less than or equal and not just less than? If the | |
2299 starting position is already equal to the maximum we can't add | |
2300 anything else, right? Wrong. We might still have a newline to | |
2301 add. A newline can use the room allocated for an end glyph since | |
2302 if we add it we know we aren't going to be adding any end | |
2303 glyph. */ | |
2304 | |
2305 /* #### Chuck -- I think this condition should be while (1). | |
2306 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
2307 and the begin-glyph ends exactly at the end of the window, the | |
2308 end-glyph and text might not be displayed. while (1) ensures | |
2309 that the loop terminates only when either (a) there is | |
2310 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
2311 | |
2312 #### Also I think you need to ensure that the operation | |
2313 "add begin glyphs; add end glyphs; add text" is atomic and | |
2314 can't get interrupted in the middle. If you run off the end | |
2315 of the line during that operation, then you keep accumulating | |
2316 propagation data until you're done. Otherwise, if the (e.g.) | |
2317 there's a begin glyph at a particular position and attempting | |
2318 to display that glyph results in window-end being hit and | |
2319 propagation data being generated, then the character at that | |
2320 position won't be displayed. | |
2321 | |
2322 #### See also the comment after the end of this loop, below. | |
2323 */ | |
2324 while (data.pixpos <= data.max_pixpos | |
2325 && (active_minibuffer || !NILP (synch_minibuffers_value))) | |
2326 { | |
2327 /* #### This check probably should not be necessary. */ | |
826 | 2328 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
428 | 2329 { |
2330 /* #### urk! More of this lossage! */ | |
826 | 2331 data.byte_charpos--; |
428 | 2332 goto done; |
2333 } | |
2334 | |
2335 /* If selective display was an integer and we aren't working on | |
4187 | 2336 a continuation line then find the next line we are actually |
2337 supposed to display. */ | |
428 | 2338 if (selective > 0 |
826 | 2339 && (data.byte_charpos == BYTE_BUF_BEGV (b) |
2340 || BUF_FETCH_CHAR (b, prev_bytebpos (b, data.byte_charpos)) == '\n')) | |
2341 { | |
2342 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
428 | 2343 { |
826 | 2344 data.byte_charpos = |
2345 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2346 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
428 | 2347 { |
826 | 2348 data.byte_charpos = BYTE_BUF_ZV (b); |
428 | 2349 goto done; |
2350 } | |
2351 } | |
2352 } | |
2353 | |
2354 /* Check for face changes. */ | |
826 | 2355 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
428 | 2356 { |
819 | 2357 Lisp_Object last_glyph = Qnil; |
2358 | |
2359 /* Deal with glyphs that we have already displayed. The | |
2360 theory is that if we end up with a PROP_GLYPH in the | |
2361 propagation data then we are clipping the glyph and there | |
2362 can be no propagation data before that point. The theory | |
2363 works because we always recalculate the extent-fragments | |
2364 for propagated data, we never actually propagate the | |
2365 fragments that still need to be displayed. */ | |
4967 | 2366 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
2367 { | |
2368 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
819 | 2369 Dynarr_free (*prop); |
2370 *prop = 0; | |
2371 } | |
428 | 2372 /* Now compute the face and begin/end-glyph information. */ |
2373 data.findex = | |
665 | 2374 /* Remember that the extent-fragment routines deal in Bytebpos's. */ |
826 | 2375 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
428 | 2376 |
2377 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
2378 | |
826 | 2379 if (data.byte_charpos == data.ef->end) |
428 | 2380 no_more_frags = 1; |
2381 } | |
2382 initial = 0; | |
2383 | |
2384 /* Determine what is next to be displayed. We first handle any | |
4187 | 2385 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
2386 display then we determine what to do based on the character at the | |
2387 current buffer position. */ | |
428 | 2388 |
2389 /* If the current position is covered by an invisible extent, do | |
4187 | 2390 nothing (except maybe add some ellipses). |
428 | 2391 |
2392 #### The behavior of begin and end-glyphs at the edge of an | |
2393 invisible extent should be investigated further. This is | |
2394 fairly low priority though. */ | |
2395 if (data.ef->invisible) | |
2396 { | |
2397 /* #### Chuck, perhaps you could look at this code? I don't | |
2398 really know what I'm doing. */ | |
2399 if (*prop) | |
2400 { | |
2401 Dynarr_free (*prop); | |
2402 *prop = 0; | |
2403 } | |
2404 | |
2405 /* The extent fragment code only sets this when we should | |
2406 really display the ellipses. It makes sure the ellipses | |
2407 don't get displayed more than once in a row. */ | |
2408 if (data.ef->invisible_ellipses) | |
2409 { | |
2410 struct glyph_block gb; | |
2411 | |
2412 data.ef->invisible_ellipses_already_displayed = 1; | |
2413 data.ef->invisible_ellipses = 0; | |
2414 gb.extent = Qnil; | |
2415 gb.glyph = Vinvisible_text_glyph; | |
2416 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2417 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2418 /* Perhaps they shouldn't propagate if the very next thing | |
2419 is to display a newline (for compatibility with | |
2420 selective-display-ellipses)? Maybe that's too | |
2421 abstruse. */ | |
2422 if (*prop) | |
2423 goto done; | |
2424 } | |
2425 | |
2426 /* If point is in an invisible region we place it on the | |
4187 | 2427 next visible character. */ |
428 | 2428 if (data.cursor_type == CURSOR_ON |
826 | 2429 && data.byte_charpos == data.byte_cursor_charpos) |
428 | 2430 { |
2431 data.cursor_type = NEXT_CURSOR; | |
2432 } | |
2433 | |
2434 /* #### What if we we're dealing with a display table? */ | |
2435 if (data.start_col) | |
2436 data.start_col--; | |
2437 | |
826 | 2438 if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2439 goto done; |
2440 else | |
826 | 2441 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2442 } |
2443 | |
2444 /* If there is propagation data, then it represents the current | |
819 | 2445 buffer position being displayed. Add them and advance the |
2446 position counter. This might also add the minibuffer | |
2447 prompt. */ | |
428 | 2448 else if (*prop) |
2449 { | |
2450 dl->used_prop_data = 1; | |
2451 *prop = add_propagation_runes (prop, &data); | |
2452 | |
2453 if (*prop) | |
2454 goto done; /* gee, a really narrow window */ | |
826 | 2455 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2456 goto done; |
826 | 2457 else if (data.byte_charpos < BYTE_BUF_BEGV (b)) |
428 | 2458 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
826 | 2459 data.byte_charpos = BYTE_BUF_BEGV (b); |
428 | 2460 else |
826 | 2461 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2462 } |
2463 | |
2464 /* If there are end glyphs, add them to the line. These are | |
2465 the end glyphs for the previous run of text. We add them | |
2466 here rather than doing them at the end of handling the | |
2467 previous run so that glyphs at the beginning and end of | |
2468 a line are handled correctly. */ | |
819 | 2469 else if (Dynarr_length (data.ef->end_glyphs) > 0 |
2470 || Dynarr_length (data.ef->begin_glyphs) > 0) | |
2471 { | |
2472 glyph_block_dynarr* tmpglyphs = 0; | |
2473 /* #### I think this is safe, but could be wrong. */ | |
826 | 2474 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
819 | 2475 |
4187 | 2476 if (Dynarr_length (data.ef->end_glyphs) > 0) |
819 | 2477 { |
2478 *prop = add_glyph_runes (&data, END_GLYPHS); | |
2479 tmpglyphs = data.ef->end_glyphs; | |
2480 } | |
2481 | |
2482 /* If there are begin glyphs, add them to the line. */ | |
4187 | 2483 if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0) |
819 | 2484 { |
2485 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); | |
2486 tmpglyphs = data.ef->begin_glyphs; | |
2487 } | |
2488 | |
4187 | 2489 if (*prop) |
819 | 2490 { |
2491 /* If we just clipped a glyph and we are at the end of a | |
2492 line and there are more glyphs to display then do | |
2493 appropriate processing to not get a continuation | |
2494 glyph. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2495 if (*prop != ADD_FAILED |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2496 && Dynarr_begin (*prop)->type == PROP_GLYPH |
819 | 2497 && data.ch == '\n') |
4187 | 2498 { |
819 | 2499 /* If there are no more glyphs then do the normal |
4187 | 2500 processing. |
819 | 2501 |
2502 #### This doesn't actually work if the same glyph is | |
2503 present more than once in the block. To solve | |
2504 this we would have to carry the index around | |
2505 which might be problematic since the fragment is | |
2506 recalculated for each line. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2507 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
|
2508 Dynarr_begin (*prop)->data.p_glyph.glyph)) |
819 | 2509 { |
2510 Dynarr_free (*prop); | |
2511 *prop = 0; | |
2512 } | |
2513 else { | |
2514 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2515 add_ichar_rune (&data); /* discard prop data. */ |
819 | 2516 goto done; |
2517 } | |
2518 } | |
2519 else | |
2520 goto done; | |
2521 } | |
428 | 2522 } |
2523 | |
2524 /* If at end-of-buffer, we've already processed begin and | |
2525 end-glyphs at this point and there's no text to process, | |
2526 so we're done. */ | |
826 | 2527 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2528 goto done; |
2529 | |
2530 else | |
2531 { | |
2532 Lisp_Object entry = Qnil; | |
2533 /* Get the character at the current buffer position. */ | |
826 | 2534 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
428 | 2535 if (!NILP (face_dt) || !NILP (window_dt)) |
2536 entry = display_table_entry (data.ch, face_dt, window_dt); | |
2537 | |
2538 /* If there is a display table entry for it, hand it off to | |
4187 | 2539 add_disp_table_entry_runes and let it worry about it. */ |
428 | 2540 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
2541 { | |
2542 *prop = add_disp_table_entry_runes (&data, entry); | |
2543 | |
2544 if (*prop) | |
2545 goto done; | |
2546 } | |
2547 | |
2548 /* Check if we have hit a newline character. If so, add a marker | |
4187 | 2549 to the line and end this loop. */ |
428 | 2550 else if (data.ch == '\n') |
2551 { | |
5619
75ad4969a16d
Replace the 'flush face property with the opposite 'shrink one.
Didier Verna <didier@xemacs.org>
parents:
5617
diff
changeset
|
2552 /* Update the clearing face index unless the shrink property is |
5617
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
2553 set. -- dvl */ |
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
2554 if ((data.findex > DEFAULT_INDEX) |
5619
75ad4969a16d
Replace the 'flush face property with the opposite 'shrink one.
Didier Verna <didier@xemacs.org>
parents:
5617
diff
changeset
|
2555 && ! WINDOW_FACE_CACHEL_SHRINK_P (w, data.findex)) |
5617
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
2556 dl->clear_findex = data.findex; |
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
2557 |
428 | 2558 /* We aren't going to be adding an end glyph so give its |
4187 | 2559 space back in order to make sure that the cursor can |
2560 fit. */ | |
819 | 2561 data.max_pixpos += data.end_glyph_width; |
428 | 2562 |
2563 if (selective > 0 | |
826 | 2564 && (byte_spaces_at_point |
2565 (b, next_bytebpos (b, data.byte_charpos)) | |
428 | 2566 >= selective)) |
2567 { | |
2568 if (!NILP (b->selective_display_ellipses)) | |
2569 { | |
2570 struct glyph_block gb; | |
2571 | |
2572 gb.extent = Qnil; | |
2573 gb.glyph = Vinvisible_text_glyph; | |
2574 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2575 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2576 } | |
2577 else | |
2578 { | |
2579 /* Cheesy, cheesy, cheesy. We mark the end of the | |
2580 line with a special "character rune" whose width | |
2581 is the EOL cursor width and whose character is | |
2582 the non-printing character '\n'. */ | |
2583 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2584 *prop = add_ichar_rune (&data); |
428 | 2585 } |
2586 | |
826 | 2587 /* We need to set data.byte_charpos to the start of the |
4187 | 2588 next visible region in order to make this line |
2589 appear to contain all of the invisible area. | |
2590 Otherwise, the line cache won't work | |
2591 correctly. */ | |
826 | 2592 INC_BYTEBPOS (b, data.byte_charpos); |
2593 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
428 | 2594 { |
826 | 2595 data.byte_charpos = |
2596 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2597 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
428 | 2598 { |
826 | 2599 data.byte_charpos = BYTE_BUF_ZV (b); |
428 | 2600 break; |
2601 } | |
2602 } | |
826 | 2603 if (BYTE_BUF_FETCH_CHAR |
2604 (b, prev_bytebpos (b, data.byte_charpos)) == '\n') | |
2605 DEC_BYTEBPOS (b, data.byte_charpos); | |
428 | 2606 } |
2607 else | |
2608 { | |
2609 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2610 *prop = add_ichar_rune (&data); |
428 | 2611 } |
2612 | |
2613 goto done; | |
2614 } | |
2615 | |
2616 /* If the current character is ^M, and selective display is | |
4187 | 2617 enabled, then add the invisible-text-glyph if |
2618 selective-display-ellipses is set. In any case, this | |
2619 line is done. */ | |
428 | 2620 else if (data.ch == (('M' & 037)) && selective == -1) |
2621 { | |
826 | 2622 Bytebpos byte_next_charpos; |
428 | 2623 |
2624 /* Find the buffer position at the end of the line. */ | |
826 | 2625 byte_next_charpos = |
2626 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2627 if (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_next_charpos)) | |
428 | 2628 == '\n') |
826 | 2629 DEC_BYTEBPOS (b, byte_next_charpos); |
428 | 2630 |
2631 /* If the cursor is somewhere in the elided text make | |
4187 | 2632 sure that the cursor gets drawn appropriately. */ |
428 | 2633 if (data.cursor_type == CURSOR_ON |
826 | 2634 && (data.byte_cursor_charpos >= data.byte_charpos && |
2635 data.byte_cursor_charpos < byte_next_charpos)) | |
428 | 2636 { |
2637 data.cursor_type = NEXT_CURSOR; | |
2638 } | |
2639 | |
2640 /* We won't be adding a truncation or continuation glyph | |
4187 | 2641 so give up the room allocated for them. */ |
819 | 2642 data.max_pixpos += data.end_glyph_width; |
428 | 2643 |
2644 if (!NILP (b->selective_display_ellipses)) | |
2645 { | |
2646 /* We don't propagate anything from the invisible | |
4187 | 2647 text glyph if it fails to fit. This is |
2648 intentional. */ | |
428 | 2649 struct glyph_block gb; |
2650 | |
2651 gb.extent = Qnil; | |
2652 gb.glyph = Vinvisible_text_glyph; | |
2653 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, | |
2654 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2655 } | |
2656 | |
2657 /* Set the buffer position to the end of the line. We | |
4187 | 2658 need to do this before potentially adding a newline |
2659 so that the cursor flag will get set correctly (if | |
2660 needed). */ | |
826 | 2661 data.byte_charpos = byte_next_charpos; |
428 | 2662 |
2663 if (NILP (b->selective_display_ellipses) | |
826 | 2664 || data.byte_cursor_charpos == byte_next_charpos) |
428 | 2665 { |
2666 /* We have to at least add a newline character so | |
4187 | 2667 that the cursor shows up properly. */ |
428 | 2668 data.ch = '\n'; |
2669 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2670 data.findex = DEFAULT_INDEX; | |
2671 data.start_col = 0; | |
2672 data.start_col_xoffset = 0; | |
826 | 2673 data.byte_start_col_enabled = 0; |
428 | 2674 |
867 | 2675 add_ichar_rune (&data); |
428 | 2676 } |
2677 | |
2678 /* This had better be a newline but doing it this way | |
4187 | 2679 we'll see obvious incorrect results if it isn't. No |
2680 need to abort here. */ | |
826 | 2681 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
428 | 2682 |
2683 goto done; | |
2684 } | |
2685 | |
2686 /* If the current character is considered to be printable, then | |
4187 | 2687 just add it. */ |
428 | 2688 else if (data.ch >= printable_min) |
2689 { | |
867 | 2690 *prop = add_ichar_rune (&data); |
428 | 2691 if (*prop) |
2692 goto done; | |
2693 } | |
2694 | |
2695 /* If the current character is a tab, determine the next tab | |
4187 | 2696 starting position and add a blank rune which extends from the |
2697 current pixel position to that starting position. */ | |
428 | 2698 else if (data.ch == '\t') |
2699 { | |
2700 int tab_start_pixpos = data.pixpos; | |
2701 int next_tab_start; | |
2702 int char_tab_width; | |
2703 int prop_width = 0; | |
2704 | |
2705 if (data.start_col > 1) | |
434 | 2706 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)) |
428 | 2707 + data.start_col_xoffset; |
2708 | |
2709 next_tab_start = | |
2710 next_tab_position (w, tab_start_pixpos, | |
2711 dl->bounds.left_in + | |
2712 data.hscroll_glyph_width_adjust); | |
2713 if (next_tab_start > data.max_pixpos) | |
2714 { | |
2715 prop_width = next_tab_start - data.max_pixpos; | |
2716 next_tab_start = data.max_pixpos; | |
2717 } | |
2718 data.blank_width = next_tab_start - data.pixpos; | |
2719 char_tab_width = | |
2720 (next_tab_start - tab_start_pixpos) / space_width (w); | |
2721 | |
2722 *prop = add_blank_rune (&data, w, char_tab_width); | |
2723 | |
2724 /* add_blank_rune is only supposed to be called with | |
4187 | 2725 sizes guaranteed to fit in the available space. */ |
428 | 2726 assert (!(*prop)); |
2727 | |
2728 if (prop_width) | |
2729 { | |
2730 struct prop_block pb; | |
2731 *prop = Dynarr_new (prop_block); | |
2732 | |
2733 pb.type = PROP_BLANK; | |
2734 pb.data.p_blank.width = prop_width; | |
2735 pb.data.p_blank.findex = data.findex; | |
2736 Dynarr_add (*prop, pb); | |
2737 | |
2738 goto done; | |
2739 } | |
2740 } | |
2741 | |
2742 /* If character is a control character, pass it off to | |
4187 | 2743 add_control_char_runes. |
428 | 2744 |
2745 The is_*() routines have undefined results on | |
2746 arguments outside of the range [-1, 255]. (This | |
2747 often bites people who carelessly use `char' instead | |
2748 of `unsigned char'.) | |
2749 */ | |
867 | 2750 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
428 | 2751 { |
2752 *prop = add_control_char_runes (&data, b); | |
2753 | |
2754 if (*prop) | |
2755 goto done; | |
2756 } | |
2757 | |
2758 /* If the character is above the ASCII range and we have not | |
4187 | 2759 already handled it, then print it as an octal number. */ |
428 | 2760 else if (data.ch >= 0200) |
2761 { | |
2762 *prop = add_octal_runes (&data); | |
2763 | |
2764 if (*prop) | |
2765 goto done; | |
2766 } | |
2767 | |
2768 /* Assume the current character is considered to be printable, | |
4187 | 2769 then just add it. */ |
428 | 2770 else |
2771 { | |
867 | 2772 *prop = add_ichar_rune (&data); |
428 | 2773 if (*prop) |
2774 goto done; | |
2775 } | |
2776 | |
826 | 2777 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2778 } |
2779 } | |
2780 | |
2781 done: | |
2782 | |
2783 /* Determine the starting point of the next line if we did not hit the | |
2784 end of the buffer. */ | |
826 | 2785 if (data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 2786 && (active_minibuffer || !NILP (synch_minibuffers_value))) |
2787 { | |
2788 /* #### This check is not correct. If the line terminated | |
2789 due to a begin-glyph or end-glyph hitting window-end, then | |
826 | 2790 data.ch will not point to the character at data.byte_charpos. If |
428 | 2791 you make the two changes mentioned at the top of this loop, |
2792 you should be able to say '(if (*prop))'. That should also | |
826 | 2793 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 2794 check. */ |
2795 | |
2796 /* The common case is that the line ended because we hit a newline. | |
4187 | 2797 In that case, the next character is just the next buffer |
2798 position. */ | |
428 | 2799 if (data.ch == '\n') |
2800 { | |
2801 /* If data.start_col_enabled is still true, then the window is | |
4187 | 2802 scrolled far enough so that nothing on this line is visible. |
2803 We need to stick a truncation glyph at the beginning of the | |
2804 line in that case unless the line is completely blank. */ | |
826 | 2805 if (data.byte_start_col_enabled) |
428 | 2806 { |
2807 if (data.cursor_type == CURSOR_ON) | |
2808 { | |
826 | 2809 if (data.byte_cursor_charpos >= byte_start_pos |
2810 && data.byte_cursor_charpos <= data.byte_charpos) | |
2811 data.byte_cursor_charpos = data.byte_charpos; | |
428 | 2812 } |
2813 data.findex = DEFAULT_INDEX; | |
2814 data.start_col = 0; | |
826 | 2815 data.byte_start_col_enabled = 0; |
2816 | |
2817 if (data.byte_charpos != byte_start_pos) | |
428 | 2818 { |
2819 struct glyph_block gb; | |
2820 | |
2821 gb.extent = Qnil; | |
2822 gb.glyph = Vhscroll_glyph; | |
2823 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2824 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX)); | |
2825 } | |
2826 else | |
2827 { | |
2828 /* This duplicates code down below to add a newline to | |
4187 | 2829 the end of an otherwise empty line.*/ |
428 | 2830 data.ch = '\n'; |
2831 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2832 | |
867 | 2833 add_ichar_rune (&data); |
428 | 2834 } |
2835 } | |
2836 | |
826 | 2837 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2838 } |
2839 | |
2840 /* Otherwise we have a buffer line which cannot fit on one display | |
4187 | 2841 line. */ |
428 | 2842 else |
2843 { | |
2844 struct glyph_block gb; | |
2845 struct glyph_cachel *cachel; | |
2846 | |
2847 /* If the line is to be truncated then we actually have to look | |
4187 | 2848 for the next newline. We also add the end-of-line glyph which |
2849 we know will fit because we adjusted the right border before | |
2850 we starting laying out the line. */ | |
819 | 2851 data.max_pixpos += data.end_glyph_width; |
428 | 2852 data.findex = DEFAULT_INDEX; |
2853 gb.extent = Qnil; | |
2854 | |
2855 if (truncate_win) | |
2856 { | |
826 | 2857 Bytebpos byte_pos; |
428 | 2858 |
2859 /* Now find the start of the next line. */ | |
826 | 2860 byte_pos = byte_find_next_newline_no_quit (b, data.byte_charpos, 1); |
428 | 2861 |
2862 /* If the cursor is past the truncation line then we | |
4187 | 2863 make it appear on the truncation glyph. If we've hit |
2864 the end of the buffer then we also make the cursor | |
2865 appear unless eob is immediately preceded by a | |
2866 newline. In that case the cursor should actually | |
2867 appear on the next line. */ | |
428 | 2868 if (data.cursor_type == CURSOR_ON |
826 | 2869 && data.byte_cursor_charpos >= data.byte_charpos |
2870 && (data.byte_cursor_charpos < byte_pos || | |
2871 (byte_pos == BYTE_BUF_ZV (b) | |
2872 && (byte_pos == BYTE_BUF_BEGV (b) | |
2873 || (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_pos)) | |
428 | 2874 != '\n'))))) |
826 | 2875 data.byte_cursor_charpos = byte_pos; |
428 | 2876 else |
2877 data.cursor_type = NO_CURSOR; | |
2878 | |
826 | 2879 data.byte_charpos = byte_pos; |
428 | 2880 gb.glyph = Vtruncation_glyph; |
2881 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
2882 } | |
2883 else | |
2884 { | |
2885 /* The cursor can never be on the continuation glyph. */ | |
2886 data.cursor_type = NO_CURSOR; | |
2887 | |
826 | 2888 /* data.byte_charpos is already at the start of the next line. */ |
428 | 2889 |
442 | 2890 dl->line_continuation = 1; |
428 | 2891 gb.glyph = Vcontinuation_glyph; |
2892 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
2893 } | |
2894 | |
442 | 2895 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
428 | 2896 |
826 | 2897 if (truncate_win && data.byte_charpos == BYTE_BUF_ZV (b) |
2898 && BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, BYTE_BUF_ZV (b))) != '\n') | |
428 | 2899 /* #### Damn this losing shit. */ |
826 | 2900 data.byte_charpos++; |
428 | 2901 } |
2902 } | |
2903 else if ((active_minibuffer || !NILP (synch_minibuffers_value)) | |
826 | 2904 && (!echo_area_active (f) || data.byte_charpos == BYTE_BUF_ZV (b))) |
428 | 2905 { |
2906 /* We need to add a marker to the end of the line since there is no | |
4187 | 2907 newline character in order for the cursor to get drawn. We label |
2908 it as a newline so that it gets handled correctly by the | |
2909 whitespace routines below. */ | |
428 | 2910 |
2911 data.ch = '\n'; | |
2912 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2913 data.findex = DEFAULT_INDEX; | |
2914 data.start_col = 0; | |
2915 data.start_col_xoffset = 0; | |
826 | 2916 data.byte_start_col_enabled = 0; |
428 | 2917 |
2918 data.max_pixpos += data.blank_width; | |
867 | 2919 add_ichar_rune (&data); |
428 | 2920 data.max_pixpos -= data.blank_width; |
2921 | |
2922 /* #### urk! Chuck, this shit is bad news. Going around | |
2923 manipulating invalid positions is guaranteed to result in | |
2924 trouble sooner or later. */ | |
826 | 2925 data.byte_charpos = BYTE_BUF_ZV (b) + 1; |
428 | 2926 } |
2927 | |
2928 /* Calculate left whitespace boundary. */ | |
2929 { | |
2930 int elt = 0; | |
2931 | |
2932 /* Whitespace past a newline is considered right whitespace. */ | |
2933 while (elt < Dynarr_length (db->runes)) | |
2934 { | |
2935 struct rune *rb = Dynarr_atp (db->runes, elt); | |
2936 | |
2937 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
2938 || rb->type == RUNE_BLANK) | |
2939 { | |
2940 dl->bounds.left_white += rb->width; | |
2941 elt++; | |
2942 } | |
2943 else | |
2944 elt = Dynarr_length (db->runes); | |
2945 } | |
2946 } | |
2947 | |
2948 /* Calculate right whitespace boundary. */ | |
2949 { | |
2950 int elt = Dynarr_length (db->runes) - 1; | |
2951 int done = 0; | |
2952 | |
2953 while (!done && elt >= 0) | |
2954 { | |
2955 struct rune *rb = Dynarr_atp (db->runes, elt); | |
2956 | |
2957 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
2958 && isspace (rb->object.chr.ch)) | |
2959 && !rb->type == RUNE_BLANK) | |
2960 { | |
2961 dl->bounds.right_white = rb->xpos + rb->width; | |
2962 done = 1; | |
2963 } | |
2964 | |
2965 elt--; | |
2966 | |
2967 } | |
2968 | |
2969 /* The line is blank so everything is considered to be right | |
2970 whitespace. */ | |
2971 if (!done) | |
2972 dl->bounds.right_white = dl->bounds.left_in; | |
2973 } | |
2974 | |
2975 /* Set the display blocks bounds. */ | |
2976 db->start_pos = dl->bounds.left_in; | |
2977 if (Dynarr_length (db->runes)) | |
2978 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2979 struct rune *rb = Dynarr_lastp (db->runes); |
428 | 2980 |
2981 db->end_pos = rb->xpos + rb->width; | |
2982 } | |
2983 else | |
2984 db->end_pos = dl->bounds.right_white; | |
2985 | |
819 | 2986 calculate_baseline (&data); |
428 | 2987 |
2988 dl->ascent = data.new_ascent; | |
2989 dl->descent = data.new_descent; | |
2990 | |
2991 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
2992 unsigned short ascent = (unsigned short) XFIXNUM (w->minimum_line_ascent); |
428 | 2993 |
2994 if (dl->ascent < ascent) | |
2995 dl->ascent = ascent; | |
2996 } | |
2997 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
2998 unsigned short descent = (unsigned short) XFIXNUM (w->minimum_line_descent); |
428 | 2999 |
3000 if (dl->descent < descent) | |
3001 dl->descent = descent; | |
3002 } | |
3003 | |
819 | 3004 calculate_yoffset (dl, db); |
3005 | |
428 | 3006 dl->cursor_elt = data.cursor_x; |
3007 /* #### lossage lossage lossage! Fix this shit! */ | |
826 | 3008 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
3009 dl->end_charpos = BUF_ZV (b); | |
428 | 3010 else |
826 | 3011 dl->end_charpos = bytebpos_to_charbpos (b, data.byte_charpos) - 1; |
428 | 3012 if (truncate_win) |
826 | 3013 data.dl->num_chars = column_at_point (b, dl->end_charpos, 0); |
428 | 3014 else |
3015 /* This doesn't correctly take into account tabs and control | |
3016 characters but if the window isn't being truncated then this | |
3017 value isn't going to end up being used anyhow. */ | |
826 | 3018 data.dl->num_chars = dl->end_charpos - dl->charpos; |
428 | 3019 |
3020 /* #### handle horizontally scrolled line with text none of which | |
3021 was actually laid out. */ | |
3022 | |
3023 /* #### handle any remainder of overlay arrow */ | |
3024 | |
3025 if (*prop == ADD_FAILED) | |
3026 *prop = NULL; | |
3027 | |
3028 if (truncate_win && *prop) | |
3029 { | |
3030 Dynarr_free (*prop); | |
3031 *prop = NULL; | |
3032 } | |
3033 | |
3034 extent_fragment_delete (data.ef); | |
3035 | |
3036 /* #### If we started at EOB, then make sure we return a value past | |
3037 it so that regenerate_window will exit properly. This is bogus. | |
3038 The main loop should get fixed so that it isn't necessary to call | |
3039 this function if we are already at EOB. */ | |
3040 | |
826 | 3041 if (data.byte_charpos == BYTE_BUF_ZV (b) && byte_start_pos == BYTE_BUF_ZV (b)) |
3042 return data.byte_charpos + 1; /* Yuck! */ | |
428 | 3043 else |
826 | 3044 return data.byte_charpos; |
428 | 3045 } |
3046 | |
3047 /* Display the overlay arrow at the beginning of the given line. */ | |
3048 | |
3049 static int | |
3050 create_overlay_glyph_block (struct window *w, struct display_line *dl) | |
3051 { | |
3052 struct frame *f = XFRAME (w->frame); | |
3053 struct device *d = XDEVICE (f->device); | |
3054 pos_data data; | |
3055 | |
3056 /* If Voverlay_arrow_string isn't valid then just fail silently. */ | |
3057 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string)) | |
3058 return 0; | |
3059 | |
3060 xzero (data); | |
3061 data.ef = NULL; | |
3062 data.d = d; | |
793 | 3063 data.window = wrap_window (w); |
428 | 3064 data.db = get_display_block_from_line (dl, OVERWRITE); |
3065 data.dl = dl; | |
3066 data.pixpos = dl->bounds.left_in; | |
3067 data.max_pixpos = dl->bounds.right_in; | |
3068 data.cursor_type = NO_CURSOR; | |
3069 data.cursor_x = -1; | |
3070 data.findex = DEFAULT_INDEX; | |
3071 data.last_charset = Qunbound; | |
3072 data.last_findex = DEFAULT_INDEX; | |
3073 data.result_str = Qnil; | |
3074 data.string = Qnil; | |
3075 | |
3076 Dynarr_reset (data.db->runes); | |
3077 | |
3078 if (STRINGP (Voverlay_arrow_string)) | |
3079 { | |
867 | 3080 add_ibyte_string_runes |
428 | 3081 (&data, |
3082 XSTRING_DATA (Voverlay_arrow_string), | |
3083 XSTRING_LENGTH (Voverlay_arrow_string), | |
793 | 3084 1, 0); |
428 | 3085 } |
3086 else if (GLYPHP (Voverlay_arrow_string)) | |
3087 { | |
3088 struct glyph_block gb; | |
3089 | |
3090 gb.glyph = Voverlay_arrow_string; | |
3091 gb.extent = Qnil; | |
3092 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0); | |
3093 } | |
4187 | 3094 |
428 | 3095 if (data.max_pixmap_height) |
3096 { | |
3097 int height = data.new_ascent + data.new_descent; | |
3098 int pix_ascent, pix_descent; | |
4187 | 3099 |
428 | 3100 pix_descent = data.max_pixmap_height * data.new_descent / height; |
3101 pix_ascent = data.max_pixmap_height - pix_descent; | |
819 | 3102 calculate_baseline (&data); |
428 | 3103 |
3104 data.new_ascent = max (data.new_ascent, pix_ascent); | |
3105 data.new_descent = max (data.new_descent, pix_descent); | |
3106 } | |
3107 | |
3108 dl->ascent = data.new_ascent; | |
3109 dl->descent = data.new_descent; | |
3110 | |
3111 data.db->start_pos = dl->bounds.left_in; | |
3112 data.db->end_pos = data.pixpos; | |
3113 | |
819 | 3114 calculate_yoffset (dl, data.db); |
3115 | |
428 | 3116 return data.pixpos - dl->bounds.left_in; |
3117 } | |
3118 | |
3119 /* Add a type of glyph to a margin display block. */ | |
3120 | |
3121 static int | |
3122 add_margin_runes (struct display_line *dl, struct display_block *db, int start, | |
3123 int count, enum glyph_layout layout, int side, Lisp_Object window) | |
3124 { | |
3125 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS | |
3126 ? dl->left_glyphs | |
3127 : dl->right_glyphs); | |
3128 int elt, end; | |
3129 int reverse; | |
442 | 3130 struct window *w = XWINDOW (window); |
3131 struct frame *f = XFRAME (w->frame); | |
3132 struct device *d = XDEVICE (f->device); | |
3133 pos_data data; | |
3134 | |
3135 xzero (data); | |
3136 data.d = d; | |
3137 data.window = window; | |
3138 data.db = db; | |
3139 data.dl = dl; | |
3140 data.pixpos = start; | |
3141 data.cursor_type = NO_CURSOR; | |
3142 data.cursor_x = -1; | |
3143 data.last_charset = Qunbound; | |
3144 data.last_findex = DEFAULT_INDEX; | |
3145 data.result_str = Qnil; | |
3146 data.string = Qnil; | |
3147 data.new_ascent = dl->ascent; | |
3148 data.new_descent = dl->descent; | |
428 | 3149 |
3150 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) | |
3151 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) | |
3152 { | |
3153 reverse = 1; | |
3154 elt = Dynarr_length (gbd) - 1; | |
3155 end = 0; | |
3156 } | |
3157 else | |
3158 { | |
3159 reverse = 0; | |
3160 elt = 0; | |
3161 end = Dynarr_length (gbd); | |
3162 } | |
3163 | |
3164 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) | |
3165 { | |
3166 struct glyph_block *gb = Dynarr_atp (gbd, elt); | |
3167 | |
3168 if (NILP (gb->extent)) | |
2500 | 3169 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3170 |
3171 if (gb->active && | |
3172 ((side == LEFT_GLYPHS && | |
3173 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout) | |
3174 || (side == RIGHT_GLYPHS && | |
3175 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) | |
3176 { | |
442 | 3177 data.findex = gb->findex; |
3178 data.max_pixpos = data.pixpos + gb->width; | |
3179 add_glyph_rune (&data, gb, side, 0, NULL); | |
428 | 3180 count--; |
3181 gb->active = 0; | |
3182 } | |
3183 | |
3184 (reverse ? elt-- : elt++); | |
3185 } | |
3186 | |
819 | 3187 calculate_baseline (&data); |
442 | 3188 |
3189 dl->ascent = data.new_ascent; | |
3190 dl->descent = data.new_descent; | |
3191 | |
819 | 3192 calculate_yoffset (dl, data.db); |
3193 | |
442 | 3194 return data.pixpos; |
428 | 3195 } |
3196 | |
3197 /* Add a blank to a margin display block. */ | |
3198 | |
3199 static void | |
2286 | 3200 add_margin_blank (struct display_line *UNUSED (dl), struct display_block *db, |
428 | 3201 struct window *w, int xpos, int width, int side) |
3202 { | |
3203 struct rune rb; | |
3204 | |
3205 rb.findex = (side == LEFT_GLYPHS | |
3206 ? get_builtin_face_cache_index (w, Vleft_margin_face) | |
3207 : get_builtin_face_cache_index (w, Vright_margin_face)); | |
3208 rb.xpos = xpos; | |
3209 rb.width = width; | |
826 | 3210 rb.charpos = -1; |
428 | 3211 rb.endpos = 0; |
3212 rb.type = RUNE_BLANK; | |
3213 rb.cursor_type = CURSOR_OFF; | |
3214 | |
3215 Dynarr_add (db->runes, rb); | |
3216 } | |
3217 | |
3218 /* Display glyphs in the left outside margin, left inside margin and | |
3219 left whitespace area. */ | |
3220 | |
3221 static void | |
3222 create_left_glyph_block (struct window *w, struct display_line *dl, | |
3223 int overlay_width) | |
3224 { | |
3225 Lisp_Object window; | |
3226 | |
3227 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1); | |
3228 int elt, end_xpos; | |
3229 int out_end, in_out_start, in_in_end, white_out_start, white_in_start; | |
3230 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
3231 int left_in_start = dl->bounds.left_in; | |
3232 int left_in_end = dl->bounds.left_in + overlay_width; | |
3233 | |
3234 struct display_block *odb, *idb; | |
3235 | |
793 | 3236 window = wrap_window (w); |
428 | 3237 |
3238 /* We have to add the glyphs to the line in the order outside, | |
3239 inside, whitespace. However the precedence dictates that we | |
3240 determine how many will fit in the reverse order. */ | |
3241 | |
3242 /* Determine how many whitespace glyphs we can display and where | |
3243 they should start. */ | |
3244 white_in_start = dl->bounds.left_white; | |
3245 white_out_start = left_in_start; | |
3246 white_out_cnt = white_in_cnt = 0; | |
3247 elt = 0; | |
3248 | |
3249 while (elt < Dynarr_length (dl->left_glyphs)) | |
3250 { | |
3251 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3252 | |
3253 if (NILP (gb->extent)) | |
2500 | 3254 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3255 |
3256 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
3257 { | |
3258 int width; | |
3259 | |
438 | 3260 width = glyph_width (gb->glyph, window); |
428 | 3261 |
3262 if (white_in_start - width >= left_in_end) | |
3263 { | |
3264 white_in_cnt++; | |
3265 white_in_start -= width; | |
3266 gb->width = width; | |
3267 gb->active = 1; | |
3268 } | |
3269 else if (use_overflow | |
3270 && (white_out_start - width > dl->bounds.left_out)) | |
3271 { | |
3272 white_out_cnt++; | |
3273 white_out_start -= width; | |
3274 gb->width = width; | |
3275 gb->active = 1; | |
3276 } | |
3277 else | |
3278 gb->active = 0; | |
3279 } | |
3280 | |
3281 elt++; | |
3282 } | |
3283 | |
3284 /* Determine how many inside margin glyphs we can display and where | |
3285 they should start. The inside margin glyphs get whatever space | |
3286 is left after the whitespace glyphs have been displayed. These | |
3287 are tricky to calculate since if we decide to use the overflow | |
3288 area we basically have to start over. So for these we build up a | |
3289 list of just the inside margin glyphs and manipulate it to | |
3290 determine the needed info. */ | |
3291 { | |
3292 glyph_block_dynarr *ib; | |
3293 int avail_in, avail_out; | |
3294 int done = 0; | |
3295 int marker = 0; | |
3296 int used_in, used_out; | |
3297 | |
3298 elt = 0; | |
3299 used_in = used_out = 0; | |
3300 ib = Dynarr_new (glyph_block); | |
3301 while (elt < Dynarr_length (dl->left_glyphs)) | |
3302 { | |
3303 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3304 | |
3305 if (NILP (gb->extent)) | |
2500 | 3306 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3307 |
3308 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3309 GL_INSIDE_MARGIN) | |
3310 { | |
438 | 3311 gb->width = glyph_width (gb->glyph, window); |
428 | 3312 used_in += gb->width; |
3313 Dynarr_add (ib, *gb); | |
3314 } | |
3315 | |
3316 elt++; | |
3317 } | |
3318 | |
3319 if (white_out_cnt) | |
3320 avail_in = 0; | |
3321 else | |
3322 { | |
3323 avail_in = white_in_start - left_in_end; | |
3324 if (avail_in < 0) | |
3325 avail_in = 0; | |
3326 } | |
3327 | |
3328 if (!use_overflow) | |
3329 avail_out = 0; | |
3330 else | |
3331 avail_out = white_out_start - dl->bounds.left_out; | |
3332 | |
3333 marker = 0; | |
3334 while (!done && marker < Dynarr_length (ib)) | |
3335 { | |
3336 int width = Dynarr_atp (ib, marker)->width; | |
3337 | |
3338 /* If everything now fits in the available inside margin | |
4187 | 3339 space, we're done. */ |
428 | 3340 if (used_in <= avail_in) |
3341 done = 1; | |
3342 else | |
3343 { | |
3344 /* Otherwise see if we have room to move a glyph to the | |
4187 | 3345 outside. */ |
428 | 3346 if (used_out + width <= avail_out) |
3347 { | |
3348 used_out += width; | |
3349 used_in -= width; | |
3350 } | |
3351 else | |
3352 done = 1; | |
3353 } | |
3354 | |
3355 if (!done) | |
3356 marker++; | |
3357 } | |
3358 | |
3359 /* At this point we now know that everything from marker on goes in | |
3360 the inside margin and everything before it goes in the outside | |
3361 margin. The stuff going into the outside margin is guaranteed | |
3362 to fit, but we may have to trim some stuff from the inside. */ | |
3363 | |
3364 in_in_end = left_in_end; | |
3365 in_out_start = white_out_start; | |
3366 in_out_cnt = in_in_cnt = 0; | |
3367 | |
3368 Dynarr_free (ib); | |
3369 elt = 0; | |
3370 while (elt < Dynarr_length (dl->left_glyphs)) | |
3371 { | |
3372 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3373 | |
3374 if (NILP (gb->extent)) | |
2500 | 3375 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3376 |
3377 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3378 GL_INSIDE_MARGIN) | |
3379 { | |
438 | 3380 int width = glyph_width (gb->glyph, window); |
428 | 3381 |
3382 if (used_out) | |
3383 { | |
3384 in_out_cnt++; | |
3385 in_out_start -= width; | |
3386 gb->width = width; | |
3387 gb->active = 1; | |
3388 used_out -= width; | |
3389 } | |
3390 else if (in_in_end + width < white_in_start) | |
3391 { | |
3392 in_in_cnt++; | |
3393 in_in_end += width; | |
3394 gb->width = width; | |
3395 gb->active = 1; | |
3396 } | |
3397 else | |
3398 gb->active = 0; | |
3399 } | |
3400 | |
3401 elt++; | |
3402 } | |
3403 } | |
3404 | |
3405 /* Determine how many outside margin glyphs we can display. They | |
3406 always start at the left outside margin and can only use the | |
3407 outside margin space. */ | |
3408 out_end = dl->bounds.left_out; | |
3409 out_cnt = 0; | |
3410 elt = 0; | |
3411 | |
3412 while (elt < Dynarr_length (dl->left_glyphs)) | |
3413 { | |
3414 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3415 | |
3416 if (NILP (gb->extent)) | |
2500 | 3417 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3418 |
3419 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3420 GL_OUTSIDE_MARGIN) | |
3421 { | |
438 | 3422 int width = glyph_width (gb->glyph, window); |
428 | 3423 |
3424 if (out_end + width <= in_out_start) | |
3425 { | |
3426 out_cnt++; | |
3427 out_end += width; | |
3428 gb->width = width; | |
3429 gb->active = 1; | |
3430 } | |
3431 else | |
3432 gb->active = 0; | |
3433 } | |
3434 | |
3435 elt++; | |
3436 } | |
3437 | |
3438 /* Now that we know where everything goes, we add the glyphs as | |
3439 runes to the appropriate display blocks. */ | |
3440 if (out_cnt || in_out_cnt || white_out_cnt) | |
3441 { | |
3442 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN); | |
3443 odb->start_pos = dl->bounds.left_out; | |
3444 /* #### We should stop adding a blank to account for the space | |
4187 | 3445 between the end of the glyphs and the margin and instead set |
3446 this accordingly. */ | |
428 | 3447 odb->end_pos = dl->bounds.left_in; |
3448 Dynarr_reset (odb->runes); | |
3449 } | |
3450 else | |
3451 odb = 0; | |
3452 | |
3453 if (in_in_cnt || white_in_cnt) | |
3454 { | |
3455 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN); | |
3456 idb->start_pos = dl->bounds.left_in; | |
3457 /* #### See above comment for odb->end_pos */ | |
3458 idb->end_pos = dl->bounds.left_white; | |
3459 Dynarr_reset (idb->runes); | |
3460 } | |
3461 else | |
3462 idb = 0; | |
3463 | |
3464 /* First add the outside margin glyphs. */ | |
3465 if (out_cnt) | |
3466 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt, | |
3467 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window); | |
3468 else | |
3469 end_xpos = dl->bounds.left_out; | |
3470 | |
3471 /* There may be blank space between the outside margin glyphs and | |
3472 the inside margin glyphs. If so, add a blank. */ | |
3473 if (in_out_cnt && (in_out_start - end_xpos)) | |
3474 { | |
3475 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos, | |
3476 LEFT_GLYPHS); | |
3477 } | |
3478 | |
3479 /* Next add the inside margin glyphs which are actually in the | |
3480 outside margin. */ | |
3481 if (in_out_cnt) | |
3482 { | |
3483 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt, | |
3484 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
3485 } | |
3486 | |
3487 /* If we didn't add any inside margin glyphs to the outside margin, | |
3488 but are adding whitespace glyphs, then we need to add a blank | |
3489 here. */ | |
3490 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) | |
3491 { | |
3492 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos, | |
3493 LEFT_GLYPHS); | |
3494 } | |
3495 | |
3496 /* Next add the whitespace margin glyphs which are actually in the | |
3497 outside margin. */ | |
3498 if (white_out_cnt) | |
3499 { | |
3500 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt, | |
3501 GL_WHITESPACE, LEFT_GLYPHS, window); | |
3502 } | |
3503 | |
3504 /* We take care of clearing between the end of the glyphs and the | |
3505 start of the inside margin for lines which have glyphs. */ | |
3506 if (odb && (left_in_start - end_xpos)) | |
3507 { | |
3508 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos, | |
3509 LEFT_GLYPHS); | |
3510 } | |
3511 | |
3512 /* Next add the inside margin glyphs which are actually in the | |
3513 inside margin. */ | |
3514 if (in_in_cnt) | |
3515 { | |
3516 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt, | |
3517 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
3518 } | |
3519 else | |
3520 end_xpos = left_in_end; | |
3521 | |
3522 /* Make sure that the area between the end of the inside margin | |
3523 glyphs and the whitespace glyphs is cleared. */ | |
3524 if (idb && (white_in_start - end_xpos > 0)) | |
3525 { | |
3526 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos, | |
3527 LEFT_GLYPHS); | |
3528 } | |
3529 | |
3530 /* Next add the whitespace margin glyphs which are actually in the | |
3531 inside margin. */ | |
3532 if (white_in_cnt) | |
3533 { | |
3534 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE, | |
3535 LEFT_GLYPHS, window); | |
3536 } | |
3537 | |
3538 /* Whitespace glyphs always end right next to the text block so | |
3539 there is nothing we have to make sure is cleared after them. */ | |
3540 } | |
3541 | |
3542 /* Display glyphs in the right outside margin, right inside margin and | |
3543 right whitespace area. */ | |
3544 | |
3545 static void | |
3546 create_right_glyph_block (struct window *w, struct display_line *dl) | |
3547 { | |
3548 Lisp_Object window; | |
3549 | |
3550 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1); | |
3551 int elt, end_xpos; | |
3552 int out_start, in_out_end, in_in_start, white_out_end, white_in_end; | |
3553 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
3554 | |
3555 struct display_block *odb, *idb; | |
3556 | |
793 | 3557 window = wrap_window (w); |
428 | 3558 |
3559 /* We have to add the glyphs to the line in the order outside, | |
3560 inside, whitespace. However the precedence dictates that we | |
3561 determine how many will fit in the reverse order. */ | |
3562 | |
3563 /* Determine how many whitespace glyphs we can display and where | |
3564 they should start. */ | |
3565 white_in_end = dl->bounds.right_white; | |
3566 white_out_end = dl->bounds.right_in; | |
3567 white_out_cnt = white_in_cnt = 0; | |
3568 elt = 0; | |
3569 | |
3570 while (elt < Dynarr_length (dl->right_glyphs)) | |
3571 { | |
3572 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3573 | |
3574 if (NILP (gb->extent)) | |
2500 | 3575 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3576 |
3577 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
3578 { | |
438 | 3579 int width = glyph_width (gb->glyph, window); |
428 | 3580 |
3581 if (white_in_end + width <= dl->bounds.right_in) | |
3582 { | |
3583 white_in_cnt++; | |
3584 white_in_end += width; | |
3585 gb->width = width; | |
3586 gb->active = 1; | |
3587 } | |
3588 else if (use_overflow | |
3589 && (white_out_end + width <= dl->bounds.right_out)) | |
3590 { | |
3591 white_out_cnt++; | |
3592 white_out_end += width; | |
3593 gb->width = width; | |
3594 gb->active = 1; | |
3595 } | |
3596 else | |
3597 gb->active = 0; | |
3598 } | |
3599 | |
3600 elt++; | |
3601 } | |
3602 | |
3603 /* Determine how many inside margin glyphs we can display and where | |
3604 they should start. The inside margin glyphs get whatever space | |
3605 is left after the whitespace glyphs have been displayed. These | |
3606 are tricky to calculate since if we decide to use the overflow | |
3607 area we basically have to start over. So for these we build up a | |
3608 list of just the inside margin glyphs and manipulate it to | |
3609 determine the needed info. */ | |
3610 { | |
3611 glyph_block_dynarr *ib; | |
3612 int avail_in, avail_out; | |
3613 int done = 0; | |
3614 int marker = 0; | |
3615 int used_in, used_out; | |
3616 | |
3617 elt = 0; | |
3618 used_in = used_out = 0; | |
3619 ib = Dynarr_new (glyph_block); | |
3620 while (elt < Dynarr_length (dl->right_glyphs)) | |
3621 { | |
3622 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3623 | |
3624 if (NILP (gb->extent)) | |
2500 | 3625 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3626 |
3627 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
3628 { | |
438 | 3629 gb->width = glyph_width (gb->glyph, window); |
428 | 3630 used_in += gb->width; |
3631 Dynarr_add (ib, *gb); | |
3632 } | |
3633 | |
3634 elt++; | |
3635 } | |
3636 | |
3637 if (white_out_cnt) | |
3638 avail_in = 0; | |
3639 else | |
3640 avail_in = dl->bounds.right_in - white_in_end; | |
3641 | |
3642 if (!use_overflow) | |
3643 avail_out = 0; | |
3644 else | |
3645 avail_out = dl->bounds.right_out - white_out_end; | |
3646 | |
3647 marker = 0; | |
3648 while (!done && marker < Dynarr_length (ib)) | |
3649 { | |
3650 int width = Dynarr_atp (ib, marker)->width; | |
3651 | |
3652 /* If everything now fits in the available inside margin | |
4187 | 3653 space, we're done. */ |
428 | 3654 if (used_in <= avail_in) |
3655 done = 1; | |
3656 else | |
3657 { | |
3658 /* Otherwise see if we have room to move a glyph to the | |
4187 | 3659 outside. */ |
428 | 3660 if (used_out + width <= avail_out) |
3661 { | |
3662 used_out += width; | |
3663 used_in -= width; | |
3664 } | |
3665 else | |
3666 done = 1; | |
3667 } | |
3668 | |
3669 if (!done) | |
3670 marker++; | |
3671 } | |
3672 | |
3673 /* At this point we now know that everything from marker on goes in | |
3674 the inside margin and everything before it goes in the outside | |
3675 margin. The stuff going into the outside margin is guaranteed | |
3676 to fit, but we may have to trim some stuff from the inside. */ | |
3677 | |
3678 in_in_start = dl->bounds.right_in; | |
3679 in_out_end = dl->bounds.right_in; | |
3680 in_out_cnt = in_in_cnt = 0; | |
3681 | |
3682 Dynarr_free (ib); | |
3683 elt = 0; | |
3684 while (elt < Dynarr_length (dl->right_glyphs)) | |
3685 { | |
3686 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3687 | |
3688 if (NILP (gb->extent)) | |
2500 | 3689 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3690 |
3691 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
3692 { | |
438 | 3693 int width = glyph_width (gb->glyph, window); |
428 | 3694 |
3695 if (used_out) | |
3696 { | |
3697 in_out_cnt++; | |
3698 in_out_end += width; | |
3699 gb->width = width; | |
3700 gb->active = 1; | |
3701 used_out -= width; | |
3702 } | |
3703 else if (in_in_start - width >= white_in_end) | |
3704 { | |
3705 in_in_cnt++; | |
3706 in_in_start -= width; | |
3707 gb->width = width; | |
3708 gb->active = 1; | |
3709 } | |
3710 else | |
3711 gb->active = 0; | |
3712 } | |
3713 | |
3714 elt++; | |
3715 } | |
3716 } | |
3717 | |
3718 /* Determine how many outside margin glyphs we can display. They | |
3719 always start at the right outside margin and can only use the | |
3720 outside margin space. */ | |
3721 out_start = dl->bounds.right_out; | |
3722 out_cnt = 0; | |
3723 elt = 0; | |
3724 | |
3725 while (elt < Dynarr_length (dl->right_glyphs)) | |
3726 { | |
3727 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3728 | |
3729 if (NILP (gb->extent)) | |
2500 | 3730 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3731 |
3732 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) | |
3733 { | |
438 | 3734 int width = glyph_width (gb->glyph, window); |
428 | 3735 |
3736 if (out_start - width >= in_out_end) | |
3737 { | |
3738 out_cnt++; | |
3739 out_start -= width; | |
3740 gb->width = width; | |
3741 gb->active = 1; | |
3742 } | |
3743 else | |
3744 gb->active = 0; | |
3745 } | |
3746 | |
3747 elt++; | |
3748 } | |
3749 | |
3750 /* Now that we now where everything goes, we add the glyphs as runes | |
3751 to the appropriate display blocks. */ | |
3752 if (out_cnt || in_out_cnt || white_out_cnt) | |
3753 { | |
3754 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN); | |
3755 /* #### See comments before odb->start_pos init in | |
4187 | 3756 create_left_glyph_block */ |
428 | 3757 odb->start_pos = dl->bounds.right_in; |
3758 odb->end_pos = dl->bounds.right_out; | |
3759 Dynarr_reset (odb->runes); | |
3760 } | |
3761 else | |
3762 odb = 0; | |
3763 | |
3764 if (in_in_cnt || white_in_cnt) | |
3765 { | |
3766 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN); | |
3767 idb->start_pos = dl->bounds.right_white; | |
3768 /* #### See comments before odb->start_pos init in | |
4187 | 3769 create_left_glyph_block */ |
428 | 3770 idb->end_pos = dl->bounds.right_in; |
3771 Dynarr_reset (idb->runes); | |
3772 } | |
3773 else | |
3774 idb = 0; | |
3775 | |
3776 /* First add the whitespace margin glyphs which are actually in the | |
3777 inside margin. */ | |
3778 if (white_in_cnt) | |
3779 { | |
3780 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white, | |
3781 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS, | |
3782 window); | |
3783 } | |
3784 else | |
3785 end_xpos = dl->bounds.right_white; | |
3786 | |
3787 /* Make sure that the area between the end of the whitespace glyphs | |
3788 and the inside margin glyphs is cleared. */ | |
3789 if (in_in_cnt && (in_in_start - end_xpos)) | |
3790 { | |
3791 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos, | |
3792 RIGHT_GLYPHS); | |
3793 } | |
3794 | |
3795 /* Next add the inside margin glyphs which are actually in the | |
3796 inside margin. */ | |
3797 if (in_in_cnt) | |
3798 { | |
3799 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt, | |
3800 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
3801 } | |
3802 | |
3803 /* If we didn't add any inside margin glyphs then make sure the rest | |
3804 of the inside margin area gets cleared. */ | |
3805 if (idb && (dl->bounds.right_in - end_xpos)) | |
3806 { | |
3807 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos, | |
3808 RIGHT_GLYPHS); | |
3809 } | |
3810 | |
3811 /* Next add any whitespace glyphs in the outside margin. */ | |
3812 if (white_out_cnt) | |
3813 { | |
3814 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt, | |
3815 GL_WHITESPACE, RIGHT_GLYPHS, window); | |
3816 } | |
3817 else | |
3818 end_xpos = dl->bounds.right_in; | |
3819 | |
3820 /* Next add any inside margin glyphs in the outside margin. */ | |
3821 if (in_out_cnt) | |
3822 { | |
3823 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt, | |
3824 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
3825 } | |
3826 | |
3827 /* There may be space between any whitespace or inside margin glyphs | |
3828 in the outside margin and the actual outside margin glyphs. */ | |
3829 if (odb && (out_start - end_xpos)) | |
3830 { | |
3831 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos, | |
3832 RIGHT_GLYPHS); | |
3833 } | |
3834 | |
3835 /* Finally, add the outside margin glyphs. */ | |
3836 if (out_cnt) | |
3837 { | |
3838 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN, | |
3839 RIGHT_GLYPHS, window); | |
3840 } | |
3841 } | |
3842 | |
3843 | |
3844 /***************************************************************************/ | |
3845 /* */ | |
3846 /* modeline routines */ | |
3847 /* */ | |
3848 /***************************************************************************/ | |
3849 | |
438 | 3850 /* This function is also used in frame.c by `generate_title_string' */ |
3851 void | |
3852 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, | |
4187 | 3853 struct window *w, struct display_line *dl, |
3854 struct display_block *db, face_index findex, | |
3855 int min_pixpos, int max_pixpos, int type) | |
438 | 3856 { |
3857 struct frame *f = XFRAME (w->frame); | |
3858 struct device *d = XDEVICE (f->device); | |
3859 | |
3860 pos_data data; | |
3861 int c_pixpos; | |
3862 Charcount offset = 0; | |
3863 | |
3864 xzero (data); | |
3865 data.d = d; | |
3866 data.db = db; | |
3867 data.dl = dl; | |
3868 data.findex = findex; | |
3869 data.pixpos = min_pixpos; | |
3870 data.max_pixpos = max_pixpos; | |
3871 data.cursor_type = NO_CURSOR; | |
3872 data.last_charset = Qunbound; | |
3873 data.last_findex = DEFAULT_INDEX; | |
3874 data.result_str = result_str; | |
3875 data.is_modeline = 1; | |
3876 data.string = Qnil; | |
793 | 3877 data.window = wrap_window (w); |
438 | 3878 |
3879 Dynarr_reset (formatted_string_extent_dynarr); | |
3880 Dynarr_reset (formatted_string_extent_start_dynarr); | |
3881 Dynarr_reset (formatted_string_extent_end_dynarr); | |
3882 | |
3883 /* result_str is nil when we're building a frame or icon title. Otherwise, | |
3884 we're building a modeline, so the offset starts at the modeline | |
442 | 3885 horizontal scrolling amount */ |
438 | 3886 if (! NILP (result_str)) |
3887 offset = w->modeline_hscroll; | |
3888 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, | |
4187 | 3889 max_pixpos - min_pixpos, findex, type, &offset, |
438 | 3890 Qnil); |
3891 | |
3892 if (Dynarr_length (db->runes)) | |
3893 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3894 struct rune *rb = Dynarr_lastp (db->runes); |
438 | 3895 c_pixpos = rb->xpos + rb->width; |
3896 } | |
3897 else | |
3898 c_pixpos = min_pixpos; | |
3899 | |
3900 /* If we don't reach the right side of the window, add a blank rune | |
3901 to make up the difference. This usually only occurs if the | |
3902 modeline face is using a proportional width font or a fixed width | |
3903 font of a different size from the default face font. */ | |
3904 | |
3905 if (c_pixpos < max_pixpos) | |
3906 { | |
3907 data.pixpos = c_pixpos; | |
3908 data.blank_width = max_pixpos - data.pixpos; | |
3909 | |
3910 add_blank_rune (&data, NULL, 0); | |
3911 } | |
3912 | |
3913 /* Now create the result string and frob the extents into it. */ | |
3914 if (!NILP (result_str)) | |
3915 { | |
3916 int elt; | |
3917 Bytecount len; | |
867 | 3918 Ibyte *strdata; |
438 | 3919 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); |
3920 | |
442 | 3921 in_modeline_generation = 1; |
3922 | |
771 | 3923 sledgehammer_check_ascii_begin (result_str); |
438 | 3924 detach_all_extents (result_str); |
793 | 3925 resize_string (result_str, -1, |
4187 | 3926 data.bytepos - XSTRING_LENGTH (result_str)); |
438 | 3927 |
3928 strdata = XSTRING_DATA (result_str); | |
3929 | |
3930 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
|
3931 { |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3932 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
|
3933 { |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3934 len += (set_itext_ichar |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3935 (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
|
3936 elt)->object.chr.ch)); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3937 } |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3938 } |
438 | 3939 |
771 | 3940 init_string_ascii_begin (result_str); |
3941 bump_string_modiff (result_str); | |
3942 sledgehammer_check_ascii_begin (result_str); | |
3943 | |
438 | 3944 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr); |
4187 | 3945 elt++) |
3946 { | |
3947 Lisp_Object extent = Qnil; | |
3948 Lisp_Object child; | |
3949 | |
3950 extent = wrap_extent (Dynarr_at (formatted_string_extent_dynarr, elt)); | |
3951 child = Fgethash (extent, buf->modeline_extent_table, Qnil); | |
3952 if (NILP (child)) | |
3953 { | |
3954 child = Fmake_extent (Qnil, Qnil, result_str); | |
3955 Fputhash (extent, child, buf->modeline_extent_table); | |
3956 } | |
3957 Fset_extent_parent (child, extent); | |
3958 set_extent_endpoints | |
3959 (XEXTENT (child), | |
3960 Dynarr_at (formatted_string_extent_start_dynarr, elt), | |
3961 Dynarr_at (formatted_string_extent_end_dynarr, elt), | |
3962 result_str); | |
3963 } | |
442 | 3964 |
3965 in_modeline_generation = 0; | |
438 | 3966 } |
3967 } | |
3968 | |
428 | 3969 /* Ensure that the given display line DL accurately represents the |
3970 modeline for the given window. */ | |
3971 static void | |
3972 generate_modeline (struct window *w, struct display_line *dl, int type) | |
3973 { | |
3974 struct buffer *b = XBUFFER (w->buffer); | |
3975 struct frame *f = XFRAME (w->frame); | |
3976 struct device *d = XDEVICE (f->device); | |
3977 | |
3978 /* Unlike display line and rune pointers, this one can't change underneath | |
3979 our feet. */ | |
3980 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
3981 int max_pixpos, min_pixpos, ypos_adj; | |
3982 Lisp_Object font_inst; | |
3983 | |
3984 /* This will actually determine incorrect inside boundaries for the | |
3985 modeline since it ignores the margins. However being aware of this fact | |
3986 we never use those values anywhere so it doesn't matter. */ | |
3987 dl->bounds = calculate_display_line_boundaries (w, 1); | |
3988 | |
3989 /* We are generating a modeline. */ | |
3990 dl->modeline = 1; | |
3991 dl->cursor_elt = -1; | |
3992 | |
3993 /* Reset the runes on the modeline. */ | |
3994 Dynarr_reset (db->runes); | |
3995 | |
3996 if (!WINDOW_HAS_MODELINE_P (w)) | |
3997 { | |
3998 struct rune rb; | |
3999 | |
4000 /* If there is a horizontal scrollbar, don't add anything. */ | |
4001 if (window_scrollbar_height (w)) | |
4002 return; | |
4003 | |
4004 dl->ascent = DEVMETH (d, divider_height, ()); | |
4005 dl->descent = 0; | |
4006 /* The modeline is at the bottom of the gutters. */ | |
4007 dl->ypos = WINDOW_BOTTOM (w); | |
4008 | |
4009 rb.findex = MODELINE_INDEX; | |
4010 rb.xpos = dl->bounds.left_out; | |
4011 rb.width = dl->bounds.right_out - dl->bounds.left_out; | |
826 | 4012 rb.charpos = 0; |
428 | 4013 rb.endpos = 0; |
4014 rb.type = RUNE_HLINE; | |
4015 rb.object.hline.thickness = 1; | |
4016 rb.object.hline.yoffset = 0; | |
4017 rb.cursor_type = NO_CURSOR; | |
4018 | |
4019 if (!EQ (Qzero, w->modeline_shadow_thickness) | |
4020 && FRAME_WIN_P (f)) | |
4021 { | |
4022 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
4023 | |
4024 dl->ypos -= shadow_thickness; | |
4025 rb.xpos += shadow_thickness; | |
4026 rb.width -= 2 * shadow_thickness; | |
4027 } | |
4028 | |
4029 Dynarr_add (db->runes, rb); | |
4030 return; | |
4031 } | |
4032 | |
4033 /* !!#### not right; needs to compute the max height of | |
4034 all the charsets */ | |
4035 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); | |
4036 | |
4037 dl->ascent = XFONT_INSTANCE (font_inst)->ascent; | |
4038 dl->descent = XFONT_INSTANCE (font_inst)->descent; | |
4039 | |
4040 min_pixpos = dl->bounds.left_out; | |
4041 max_pixpos = dl->bounds.right_out; | |
4042 | |
4043 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
4044 { | |
4045 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
4046 | |
4047 ypos_adj = shadow_thickness; | |
4048 min_pixpos += shadow_thickness; | |
4049 max_pixpos -= shadow_thickness; | |
4050 } | |
4051 else | |
4052 ypos_adj = 0; | |
4053 | |
4054 generate_formatted_string_db (b->modeline_format, | |
4055 b->generated_modeline_string, w, dl, db, | |
4056 MODELINE_INDEX, min_pixpos, max_pixpos, type); | |
4057 | |
4058 /* The modeline is at the bottom of the gutters. We have to wait to | |
4059 set this until we've generated the modeline in order to account | |
4060 for any embedded faces. */ | |
4061 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj; | |
4062 } | |
4063 | |
4064 static Charcount | |
867 | 4065 add_string_to_fstring_db_runes (pos_data *data, const Ibyte *str, |
4187 | 4066 Charcount pos, Charcount min_pos, |
771 | 4067 Charcount max_pos) |
428 | 4068 { |
4069 /* This function has been Mule-ized. */ | |
4070 Charcount end; | |
867 | 4071 const Ibyte *cur_pos = str; |
428 | 4072 struct display_block *db = data->db; |
4073 | |
4074 data->blank_width = space_width (XWINDOW (data->window)); | |
4075 while (Dynarr_length (db->runes) < pos) | |
4076 add_blank_rune (data, NULL, 0); | |
4077 | |
4078 end = (Dynarr_length (db->runes) + | |
4970 | 4079 bytecount_to_charcount (str, qxestrlen (str))); |
428 | 4080 if (max_pos != -1) |
4081 end = min (max_pos, end); | |
4082 | |
4083 while (pos < end && *cur_pos) | |
4084 { | |
867 | 4085 const Ibyte *old_cur_pos = cur_pos; |
428 | 4086 int succeeded; |
4087 | |
867 | 4088 data->ch = itext_ichar (cur_pos); |
4089 succeeded = (add_ichar_rune (data) != ADD_FAILED); | |
4090 INC_IBYTEPTR (cur_pos); | |
428 | 4091 if (succeeded) |
4187 | 4092 { |
4093 pos++; | |
4094 data->modeline_charpos++; | |
4095 data->bytepos += cur_pos - old_cur_pos; | |
4096 } | |
428 | 4097 } |
4098 | |
4099 while (Dynarr_length (db->runes) < min_pos && | |
4187 | 4100 (data->pixpos + data->blank_width <= data->max_pixpos)) |
428 | 4101 add_blank_rune (data, NULL, 0); |
4102 | |
4103 return Dynarr_length (db->runes); | |
4104 } | |
4105 | |
4106 /* #### Urk! Should also handle begin-glyphs and end-glyphs in | |
4107 modeline extents. */ | |
4108 static Charcount | |
4109 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, | |
4187 | 4110 Charcount pos, Charcount UNUSED (min_pos), |
438 | 4111 Charcount max_pos, Lisp_Object extent) |
428 | 4112 { |
4113 /* This function has been Mule-ized. */ | |
4114 Charcount end; | |
4115 struct display_block *db = data->db; | |
4116 struct glyph_block gb; | |
4117 | |
4118 data->blank_width = space_width (XWINDOW (data->window)); | |
4119 while (Dynarr_length (db->runes) < pos) | |
4120 add_blank_rune (data, NULL, 0); | |
4121 | |
4122 end = Dynarr_length (db->runes) + 1; | |
4123 if (max_pos != -1) | |
4124 end = min (max_pos, end); | |
4125 | |
4126 gb.glyph = glyph; | |
438 | 4127 gb.extent = extent; |
428 | 4128 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); |
4129 pos++; | |
4130 | |
4131 while (Dynarr_length (db->runes) < pos && | |
4187 | 4132 (data->pixpos + data->blank_width <= data->max_pixpos)) |
428 | 4133 add_blank_rune (data, NULL, 0); |
4134 | |
4135 return Dynarr_length (db->runes); | |
4136 } | |
4137 | |
4138 /* If max_pos is == -1, it is considered to be infinite. The same is | |
4139 true of max_pixsize. */ | |
4140 #define SET_CURRENT_MODE_CHARS_PIXSIZE \ | |
4141 if (Dynarr_length (data->db->runes)) \ | |
4967 | 4142 cur_pixsize = data->pixpos - Dynarr_begin (data->db->runes)->xpos; \ |
428 | 4143 else \ |
4144 cur_pixsize = 0; | |
4145 | |
4146 /* Note that this function does "positions" in terms of characters and | |
4147 not in terms of columns. This is necessary to make the formatting | |
4148 work correctly when proportional width fonts are used in the | |
4149 modeline. */ | |
4150 static Charcount | |
4151 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, | |
4187 | 4152 Charcount min_pos, Charcount max_pos, |
4153 Lisp_Object elt, int depth, int max_pixsize, | |
4154 face_index findex, int type, Charcount *offset, | |
438 | 4155 Lisp_Object cur_ext) |
428 | 4156 { |
4157 /* This function has been Mule-ized. */ | |
4158 /* #### The other losing things in this function are: | |
4159 | |
4160 -- C zero-terminated-string lossage. | |
4161 -- Non-printable characters should be converted into something | |
4187 | 4162 appropriate (e.g. ^F) instead of blindly being printed anyway. |
428 | 4163 */ |
4164 | |
4165 tail_recurse: | |
4166 if (depth > 10) | |
4167 goto invalid; | |
4168 | |
4169 depth++; | |
4170 | |
4171 if (STRINGP (elt)) | |
4172 { | |
4173 /* A string. Add to the display line and check for %-constructs | |
4187 | 4174 within it. */ |
428 | 4175 |
2552 | 4176 Ibyte *this_str = XSTRING_DATA (elt); |
4177 | |
4178 while ((pos < max_pos || max_pos == -1) && *this_str) | |
4187 | 4179 { |
4180 Ibyte *last = this_str; | |
4181 | |
4182 while (*this_str && *this_str != '%') | |
4183 this_str++; | |
4184 | |
4185 if (this_str != last) | |
4186 { | |
4187 /* No %-construct */ | |
4188 Charcount size = | |
2552 | 4189 bytecount_to_charcount (last, this_str - last); |
438 | 4190 |
4191 if (size <= *offset) | |
4192 *offset -= size; | |
4193 else | |
4194 { | |
4195 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset : | |
4196 min (pos + size - *offset, max_pos)); | |
867 | 4197 const Ibyte *tmp_last = itext_n_addr (last, *offset); |
438 | 4198 |
4199 pos = add_string_to_fstring_db_runes (data, tmp_last, | |
4200 pos, pos, tmp_max); | |
4201 *offset = 0; | |
4202 } | |
4187 | 4203 } |
4204 else /* *this_str == '%' */ | |
4205 { | |
4206 Charcount spec_width = 0; | |
4207 | |
4208 this_str++; /* skip over '%' */ | |
4209 | |
4210 /* We can't allow -ve args due to the "%-" construct. | |
4211 * Argument specifies minwidth but not maxwidth | |
4212 * (maxwidth can be specified by | |
4213 * (<negative-number> . <stuff>) modeline elements) | |
4214 */ | |
4215 while (isdigit (*this_str)) | |
4216 { | |
4217 spec_width = spec_width * 10 + (*this_str - '0'); | |
4218 this_str++; | |
4219 } | |
4220 spec_width += pos; | |
4221 | |
4222 if (*this_str == 'M') | |
4223 { | |
4224 pos = generate_fstring_runes (w, data, pos, spec_width, | |
4225 max_pos, Vglobal_mode_string, | |
4226 depth, max_pixsize, findex, | |
4227 type, offset, cur_ext); | |
4228 } | |
4229 else if (*this_str == '-') | |
4230 { | |
4231 Charcount num_to_add; | |
4232 | |
4233 if (max_pixsize < 0) | |
4234 num_to_add = 0; | |
4235 else if (max_pos != -1) | |
4236 num_to_add = max_pos - pos; | |
4237 else | |
4238 { | |
4239 int cur_pixsize; | |
4240 int dash_pixsize; | |
4241 Ibyte ch = '-'; | |
4242 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
4243 | |
4244 dash_pixsize = | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4245 redisplay_window_text_width_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4246 (w, findex, &ch, Qnil, 0, 1); |
4187 | 4247 |
4248 if (dash_pixsize == 0) | |
3094 | 4249 num_to_add = 0; |
4250 else { | |
4251 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize; | |
4252 num_to_add++; | |
4253 } | |
4187 | 4254 } |
4255 | |
4256 while (num_to_add--) | |
4257 pos = add_string_to_fstring_db_runes | |
4258 (data, (const Ibyte *) "-", pos, pos, max_pos); | |
4259 } | |
4260 else if (*this_str != 0) | |
4261 { | |
4262 Ichar ch = itext_ichar (this_str); | |
4263 Ibyte *str; | |
438 | 4264 Charcount size; |
4265 | |
4187 | 4266 decode_mode_spec (w, ch, type); |
4267 | |
4967 | 4268 str = Dynarr_begin (mode_spec_ibyte_string); |
438 | 4269 size = bytecount_to_charcount |
4270 /* Skip the null character added by `decode_mode_spec' */ | |
867 | 4271 (str, Dynarr_length (mode_spec_ibyte_string)) - 1; |
438 | 4272 |
4273 if (size <= *offset) | |
4274 *offset -= size; | |
4275 else | |
4276 { | |
867 | 4277 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
438 | 4278 |
440 | 4279 /* #### NOTE: I don't understand why a tmp_max is not |
438 | 4280 computed and used here as in the plain string case |
4281 above. -- dv */ | |
4282 pos = add_string_to_fstring_db_runes (data, tmp_str, | |
4283 pos, pos, | |
4284 max_pos); | |
4285 *offset = 0; | |
4286 } | |
4187 | 4287 } |
4288 | |
4289 /* NOT this_str++. There could be any sort of character at | |
4290 the current position. */ | |
4291 INC_IBYTEPTR (this_str); | |
4292 } | |
4293 | |
4294 if (max_pixsize > 0) | |
4295 { | |
4296 int cur_pixsize; | |
4297 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
4298 | |
4299 if (cur_pixsize >= max_pixsize) | |
4300 break; | |
4301 } | |
4302 } | |
428 | 4303 } |
4304 else if (SYMBOLP (elt)) | |
4305 { | |
4306 /* A symbol: process the value of the symbol recursively | |
4187 | 4307 as if it appeared here directly. */ |
428 | 4308 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); |
4309 | |
4310 if (!UNBOUNDP (tem)) | |
4187 | 4311 { |
438 | 4312 /* If value is a string, output that string literally: |
4187 | 4313 don't check for % within it. */ |
4314 if (STRINGP (tem)) | |
4315 { | |
867 | 4316 Ibyte *str = XSTRING_DATA (tem); |
826 | 4317 Charcount size = string_char_length (tem); |
438 | 4318 |
4319 if (size <= *offset) | |
4320 *offset -= size; | |
4321 else | |
4322 { | |
867 | 4323 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
438 | 4324 |
440 | 4325 /* #### NOTE: I don't understand why a tmp_max is not |
438 | 4326 computed and used here as in the plain string case |
4327 above. -- dv */ | |
4328 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4329 min_pos, max_pos); | |
4330 *offset = 0; | |
4331 } | |
4187 | 4332 } |
4333 /* Give up right away for nil or t. */ | |
4334 else if (!EQ (tem, elt)) | |
4335 { | |
4336 elt = tem; | |
4337 goto tail_recurse; | |
4338 } | |
4339 } | |
428 | 4340 } |
4341 else if (GENERIC_SPECIFIERP (elt)) | |
4342 { | |
4343 Lisp_Object window, tem; | |
793 | 4344 window = wrap_window (w); |
428 | 4345 tem = specifier_instance_no_quit (elt, Qunbound, window, |
793 | 4346 ERROR_ME_DEBUG_WARN, 0, Qzero); |
428 | 4347 if (!UNBOUNDP (tem)) |
4348 { | |
4349 elt = tem; | |
4350 goto tail_recurse; | |
4351 } | |
4352 } | |
4353 else if (CONSP (elt)) | |
4354 { | |
4355 /* A cons cell: four distinct cases. | |
438 | 4356 * - If first element is a string or a cons, process all the elements |
4357 * and effectively concatenate them. | |
4358 * - If first element is a negative number, truncate displaying cdr to | |
4359 * at most that many characters. If positive, pad (with spaces) | |
4360 * to at least that many characters. | |
771 | 4361 * - If first element is another symbol or a boolean specifier, process |
4362 * the cadr or caddr recursively according to whether the symbol's | |
4363 * value or specifier's instance is non-nil or nil. | |
4364 * - If first element is , process the cadr or caddr | |
4365 * recursively according to whether the instance of the specifier in | |
4366 * the modeline's window is non-nil or nil. | |
442 | 4367 * - If first element is an extent, process the cdr recursively |
4368 * and handle the extent's face. | |
428 | 4369 */ |
438 | 4370 |
428 | 4371 Lisp_Object car, tem; |
4372 | |
4373 car = XCAR (elt); | |
771 | 4374 if (SYMBOLP (car) || BOOLEAN_SPECIFIERP (car)) |
438 | 4375 { |
4376 elt = XCDR (elt); | |
4377 if (!CONSP (elt)) | |
4378 goto invalid; | |
4379 | |
771 | 4380 if (SYMBOLP (car)) |
4381 tem = symbol_value_in_buffer (car, w->buffer); | |
4382 else | |
4383 tem = specifier_instance_no_quit (car, Qunbound, wrap_window (w), | |
793 | 4384 ERROR_ME_DEBUG_WARN, 0, Qzero); |
438 | 4385 /* elt is now the cdr, and we know it is a cons cell. |
4386 Use its car if CAR has a non-nil value. */ | |
771 | 4387 if (!UNBOUNDP (tem) && !NILP (tem)) |
438 | 4388 { |
771 | 4389 elt = XCAR (elt); |
4390 goto tail_recurse; | |
438 | 4391 } |
771 | 4392 /* Symbol's value or specifier's instance is nil or unbound |
438 | 4393 * Get the cddr of the original list |
4394 * and if possible find the caddr and use that. | |
4395 */ | |
4396 elt = XCDR (elt); | |
4397 if (NILP (elt)) | |
4398 ; | |
4399 else if (!CONSP (elt)) | |
4400 goto invalid; | |
4401 else | |
4402 { | |
4403 elt = XCAR (elt); | |
4404 goto tail_recurse; | |
4405 } | |
4406 } | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
4407 else if (FIXNUMP (car)) |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
4408 { |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
4409 Charcount lim = XFIXNUM (car); |
4187 | 4410 |
4411 elt = XCDR (elt); | |
4412 | |
4413 if (lim < 0) | |
4414 { | |
4415 /* Negative int means reduce maximum width. | |
4416 * DO NOT change MIN_PIXPOS here! | |
4417 * (20 -10 . foo) should truncate foo to 10 col | |
4418 * and then pad to 20. | |
4419 */ | |
4420 if (max_pos == -1) | |
4421 max_pos = pos - lim; | |
4422 else | |
4423 max_pos = min (max_pos, pos - lim); | |
4424 } | |
4425 else if (lim > 0) | |
4426 { | |
4427 /* Padding specified. Don't let it be more than | |
4428 * current maximum. | |
4429 */ | |
4430 lim += pos; | |
4431 if (max_pos != -1 && lim > max_pos) | |
4432 lim = max_pos; | |
4433 /* If that's more padding than already wanted, queue it. | |
4434 * But don't reduce padding already specified even if | |
4435 * that is beyond the current truncation point. | |
4436 */ | |
4437 if (lim > min_pos) | |
4438 min_pos = lim; | |
4439 } | |
4440 goto tail_recurse; | |
4441 } | |
428 | 4442 else if (STRINGP (car) || CONSP (car)) |
4187 | 4443 { |
4444 int limit = 50; | |
4445 | |
4446 /* LIMIT is to protect against circular lists. */ | |
4447 while (CONSP (elt) && --limit > 0 | |
4448 && (pos < max_pos || max_pos == -1)) | |
4449 { | |
4450 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
4451 XCAR (elt), depth, max_pixsize, | |
438 | 4452 findex, type, offset, cur_ext); |
4187 | 4453 elt = XCDR (elt); |
4454 } | |
4455 } | |
428 | 4456 else if (EXTENTP (car)) |
4187 | 4457 { |
4458 struct extent *ext = XEXTENT (car); | |
4459 | |
4460 if (EXTENT_LIVE_P (ext)) | |
4461 { | |
4462 face_index old_findex = data->findex; | |
4463 Lisp_Object face; | |
4464 Lisp_Object font_inst; | |
4465 face_index new_findex; | |
4466 Bytecount start = data->bytepos; | |
4467 | |
4468 face = extent_face (ext); | |
4469 if (FACEP (face)) | |
4470 { | |
4471 /* #### needs to merge faces, sigh */ | |
4472 /* #### needs to handle list of faces */ | |
4473 new_findex = get_builtin_face_cache_index (w, face); | |
4474 /* !!#### not right; needs to compute the max height of | |
4475 all the charsets */ | |
4476 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex, | |
4477 Vcharset_ascii); | |
4478 | |
4479 data->dl->ascent = max (data->dl->ascent, | |
4480 XFONT_INSTANCE (font_inst)->ascent); | |
4481 data->dl->descent = max (data->dl->descent, | |
4482 XFONT_INSTANCE (font_inst)-> | |
4483 descent); | |
4484 } | |
4485 else | |
4486 new_findex = old_findex; | |
4487 | |
4488 data->findex = new_findex; | |
4489 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
4490 XCDR (elt), depth - 1, | |
438 | 4491 max_pixsize, new_findex, type, |
4492 offset, car); | |
4187 | 4493 data->findex = old_findex; |
4494 Dynarr_add (formatted_string_extent_dynarr, ext); | |
4495 Dynarr_add (formatted_string_extent_start_dynarr, start); | |
4496 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); | |
4497 } | |
4498 } | |
428 | 4499 } |
4500 else if (GLYPHP (elt)) | |
4501 { | |
438 | 4502 /* Glyphs are considered as one character with respect to the modeline |
4503 horizontal scrolling facility. -- dv */ | |
4504 if (*offset > 0) | |
4505 *offset -= 1; | |
4506 else | |
4507 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos, | |
4508 cur_ext); | |
428 | 4509 } |
4510 else | |
4511 { | |
4512 invalid: | |
438 | 4513 { |
4970 | 4514 const Ascbyte *str = GETTEXT ("*invalid*"); |
438 | 4515 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */ |
4516 | |
4517 if (size <= *offset) | |
4518 *offset -= size; | |
4519 else | |
4520 { | |
867 | 4521 const Ibyte *tmp_str = |
4522 itext_n_addr ((const Ibyte *) str, *offset); | |
438 | 4523 |
440 | 4524 /* #### NOTE: I don't understand why a tmp_max is not computed and |
438 | 4525 used here as in the plain string case above. -- dv */ |
4526 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4527 min_pos, max_pos); | |
4528 *offset = 0; | |
4529 } | |
4530 } | |
428 | 4531 } |
4532 | |
4533 if (min_pos > pos) | |
4534 { | |
867 | 4535 add_string_to_fstring_db_runes (data, (const Ibyte *) "", pos, |
438 | 4536 min_pos, -1); |
428 | 4537 } |
4538 | |
4539 return pos; | |
4540 } | |
4541 | |
4542 /* Update just the modeline. Assumes the desired display structs. If | |
4543 they do not have a modeline block, it does nothing. */ | |
4544 static void | |
4545 regenerate_modeline (struct window *w) | |
4546 { | |
4547 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP); | |
4548 | |
4967 | 4549 if (!Dynarr_length (dla) || !Dynarr_begin (dla)->modeline) |
428 | 4550 return; |
4551 else | |
4552 { | |
4967 | 4553 generate_modeline (w, Dynarr_begin (dla), DESIRED_DISP); |
428 | 4554 redisplay_update_line (w, 0, 0, 0); |
4555 } | |
4556 } | |
4557 | |
4558 /* Make sure that modeline display line is present in the given | |
4559 display structs if the window has a modeline and update that | |
4560 line. Returns true if a modeline was needed. */ | |
4561 static int | |
4562 ensure_modeline_generated (struct window *w, int type) | |
4563 { | |
4564 int need_modeline; | |
4565 | |
4566 /* minibuffer windows don't have modelines */ | |
4567 if (MINI_WINDOW_P (w)) | |
4568 need_modeline = 0; | |
4569 /* windows which haven't had it turned off do */ | |
4570 else if (WINDOW_HAS_MODELINE_P (w)) | |
4571 need_modeline = 1; | |
4572 /* windows which have it turned off don't have a divider if there is | |
4573 a horizontal scrollbar */ | |
4574 else if (window_scrollbar_height (w)) | |
4575 need_modeline = 0; | |
4576 /* and in this case there is none */ | |
4577 else | |
4578 need_modeline = 1; | |
4579 | |
4580 if (need_modeline) | |
4581 { | |
4582 display_line_dynarr *dla; | |
4583 | |
4584 dla = window_display_lines (w, type); | |
4585 | |
4586 /* We don't care if there is a display line which is not | |
4187 | 4587 currently a modeline because it is definitely going to become |
4588 one if we have gotten to this point. */ | |
428 | 4589 if (Dynarr_length (dla) == 0) |
4590 { | |
4591 if (Dynarr_largest (dla) > 0) | |
5038 | 4592 Dynarr_incrementr (dla); |
428 | 4593 else |
4594 { | |
4595 struct display_line modeline; | |
4207 | 4596 |
4597 DISPLAY_LINE_INIT (modeline); | |
428 | 4598 Dynarr_add (dla, modeline); |
4599 } | |
4600 } | |
4601 | |
4602 /* If we're adding a new place marker go ahead and generate the | |
4187 | 4603 modeline so that it is available for use by |
4604 window_modeline_height. */ | |
4967 | 4605 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 4606 } |
4607 | |
4608 return need_modeline; | |
4609 } | |
4610 | |
4611 /* #### Kludge or not a kludge. I tend towards the former. */ | |
4612 int | |
4613 real_current_modeline_height (struct window *w) | |
4614 { | |
4615 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer); | |
4616 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer); | |
4617 | |
4618 if (ensure_modeline_generated (w, CMOTION_DISP)) | |
4619 { | |
4620 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP); | |
4621 | |
4622 if (Dynarr_length (dla)) | |
4623 { | |
4967 | 4624 if (Dynarr_begin (dla)->modeline) |
4625 return (Dynarr_begin (dla)->ascent + | |
4626 Dynarr_begin (dla)->descent); | |
428 | 4627 } |
4628 } | |
4629 return 0; | |
4630 } | |
4631 | |
4632 | |
4633 /***************************************************************************/ | |
819 | 4634 /* */ |
826 | 4635 /* displayable string routines */ |
819 | 4636 /* */ |
428 | 4637 /***************************************************************************/ |
4638 | |
4639 /* Given a position for a string in a window, ensure that the given | |
4640 display line DL accurately represents the text on a line starting | |
4641 at the given position. | |
4642 | |
4643 Yes, this is duplicating the code of create_text_block, but it | |
4644 looked just too hard to change create_text_block to handle strings | |
4645 *and* buffers. We already make a distinction between the two | |
4646 elsewhere in the code so I think unifying them would require a | |
4647 complete MULE rewrite. Besides, the other distinction is that these | |
4648 functions cover text that the user *cannot edit* so we can remove | |
4649 everything to do with cursors, minibuffers etc. Eventually the | |
4650 modeline routines should be modified to use this code as it copes | |
4651 with many more types of display situation. */ | |
4652 | |
665 | 4653 static Charbpos |
428 | 4654 create_string_text_block (struct window *w, Lisp_Object disp_string, |
4655 struct display_line *dl, | |
826 | 4656 Charcount start_pos, |
428 | 4657 prop_block_dynarr **prop, |
4658 face_index default_face) | |
4659 { | |
4660 struct frame *f = XFRAME (w->frame); | |
4661 /* Note that a lot of the buffer controlled stuff has been left in | |
4662 because you might well want to make use of it (selective display | |
4663 etc), its just the buffer text that we do not use. However, it | |
4664 seems to be possible for buffer to be nil sometimes so protect | |
4665 against this case. */ | |
4666 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; | |
4667 struct device *d = XDEVICE (f->device); | |
4668 | |
4669 /* we're working with these a lot so precalculate them */ | |
4670 Bytecount slen = XSTRING_LENGTH (disp_string); | |
826 | 4671 Bytecount byte_string_zv = slen; |
4672 Bytecount byte_start_pos = string_index_char_to_byte (disp_string, start_pos); | |
428 | 4673 |
4674 pos_data data; | |
4675 | |
4676 int truncate_win = b ? window_truncation_on (w) : 0; | |
4677 | |
442 | 4678 /* We're going to ditch selective display for static text, it's an |
4679 FSF thing and invisible extents are the way to go here. | |
4680 Implementing it also relies on a number of buffer-specific | |
428 | 4681 functions that we don't have the luxury of being able to use |
4682 here. */ | |
4683 | |
4684 /* The variable ctl-arrow allows the user to specify what characters | |
4685 can actually be displayed and which octal should be used for. | |
4686 #### This variable should probably have some rethought done to | |
4687 it. | |
4688 | |
4689 #### It would also be really nice if you could specify that | |
4690 the characters come out in hex instead of in octal. Mule | |
4691 does that by adding a ctl-hexa variable similar to ctl-arrow, | |
4692 but that's bogus -- we need a more general solution. I | |
4693 think you need to extend the concept of display tables | |
4694 into a more general conversion mechanism. Ideally you | |
4695 could specify a Lisp function that converts characters, | |
4696 but this violates the Second Golden Rule and besides would | |
4697 make things way way way way slow. | |
4698 | |
4699 So instead, we extend the display-table concept, which was | |
4700 historically limited to 256-byte vectors, to one of the | |
4701 following: | |
4702 | |
4703 a) A 256-entry vector, for backward compatibility; | |
4704 b) char-table, mapping characters to values; | |
4705 c) range-table, mapping ranges of characters to values; | |
4706 d) a list of the above. | |
4707 | |
4708 The (d) option allows you to specify multiple display tables | |
4709 instead of just one. Each display table can specify conversions | |
4710 for some characters and leave others unchanged. The way the | |
4711 character gets displayed is determined by the first display table | |
4712 with a binding for that character. This way, you could call a | |
4713 function `enable-hex-display' that adds a hex display-table to | |
4714 the list of display tables for the current buffer. | |
4715 | |
4716 #### ...not yet implemented... Also, we extend the concept of | |
4717 "mapping" to include a printf-like spec. Thus you can make all | |
4718 extended characters show up as hex with a display table like | |
4719 this: | |
4720 | |
4187 | 4721 #s(range-table data ((256 524288) (format "%x"))) |
428 | 4722 |
4723 Since more than one display table is possible, you have | |
4724 great flexibility in mapping ranges of characters. */ | |
867 | 4725 Ichar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
428 | 4726 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
4727 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
4728 ? 255 : 160)) : 255; | |
4729 | |
4730 Lisp_Object face_dt, window_dt; | |
4731 | |
4732 /* The text display block for this display line. */ | |
4733 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
4734 | |
4735 /* The first time through the main loop we need to force the glyph | |
4736 data to be updated. */ | |
4737 int initial = 1; | |
4738 | |
4739 /* Apparently the new extent_fragment_update returns an end position | |
4740 equal to the position passed in if there are no more runs to be | |
4741 displayed. */ | |
4742 int no_more_frags = 0; | |
4743 | |
4744 dl->used_prop_data = 0; | |
4745 dl->num_chars = 0; | |
442 | 4746 dl->line_continuation = 0; |
428 | 4747 |
4187 | 4748 /* Set up faces to use for clearing areas, used by output_display_line. */ |
5617
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
4749 dl->clear_findex = default_face; |
4187 | 4750 if (default_face > DEFAULT_INDEX) |
428 | 4751 { |
4752 dl->left_margin_findex = default_face; | |
4753 dl->right_margin_findex = default_face; | |
4754 } | |
4755 else | |
4756 { | |
434 | 4757 dl->left_margin_findex = |
428 | 4758 get_builtin_face_cache_index (w, Vleft_margin_face); |
434 | 4759 dl->right_margin_findex = |
428 | 4760 get_builtin_face_cache_index (w, Vright_margin_face); |
4761 } | |
4762 | |
4763 xzero (data); | |
4764 data.ef = extent_fragment_new (disp_string, f); | |
4765 | |
4766 /* These values are used by all of the rune addition routines. We add | |
4767 them to this structure for ease of passing. */ | |
4768 data.d = d; | |
793 | 4769 data.window = wrap_window (w); |
428 | 4770 data.db = db; |
4771 data.dl = dl; | |
4772 | |
826 | 4773 data.byte_charpos = byte_start_pos; |
428 | 4774 data.pixpos = dl->bounds.left_in; |
4775 data.last_charset = Qunbound; | |
4776 data.last_findex = default_face; | |
4777 data.result_str = Qnil; | |
4778 data.string = disp_string; | |
4779 | |
4780 /* Set the right boundary adjusting it to take into account any end | |
4781 glyph. Save the width of the end glyph for later use. */ | |
4782 data.max_pixpos = dl->bounds.right_in; | |
819 | 4783 data.max_pixpos -= data.end_glyph_width; |
428 | 4784 |
4785 data.cursor_type = NO_CURSOR; | |
4786 data.cursor_x = -1; | |
4787 | |
4788 data.start_col = 0; | |
4789 /* I don't think we want this, string areas should not scroll with | |
434 | 4790 the window |
428 | 4791 data.start_col = w->hscroll; |
826 | 4792 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
428 | 4793 */ |
826 | 4794 data.byte_start_col_enabled = 0; |
428 | 4795 data.hscroll_glyph_width_adjust = 0; |
4796 | |
4797 /* We regenerate the line from the very beginning. */ | |
4798 Dynarr_reset (db->runes); | |
4799 | |
4800 /* Why is this less than or equal and not just less than? If the | |
4801 starting position is already equal to the maximum we can't add | |
4802 anything else, right? Wrong. We might still have a newline to | |
4803 add. A newline can use the room allocated for an end glyph since | |
4804 if we add it we know we aren't going to be adding any end | |
4805 glyph. */ | |
4806 | |
4807 /* #### Chuck -- I think this condition should be while (1). | |
4808 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
4809 and the begin-glyph ends exactly at the end of the window, the | |
4810 end-glyph and text might not be displayed. while (1) ensures | |
4811 that the loop terminates only when either (a) there is | |
4812 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
4813 | |
4814 #### Also I think you need to ensure that the operation | |
4815 "add begin glyphs; add end glyphs; add text" is atomic and | |
4816 can't get interrupted in the middle. If you run off the end | |
4817 of the line during that operation, then you keep accumulating | |
4818 propagation data until you're done. Otherwise, if the (e.g.) | |
4819 there's a begin glyph at a particular position and attempting | |
4820 to display that glyph results in window-end being hit and | |
4821 propagation data being generated, then the character at that | |
4822 position won't be displayed. | |
4823 | |
4824 #### See also the comment after the end of this loop, below. | |
4825 */ | |
4826 while (data.pixpos <= data.max_pixpos) | |
4827 { | |
4828 /* #### This check probably should not be necessary. */ | |
826 | 4829 if (data.byte_charpos > byte_string_zv) |
428 | 4830 { |
4831 /* #### urk! More of this lossage! */ | |
826 | 4832 data.byte_charpos--; |
428 | 4833 goto done; |
4834 } | |
4835 | |
4836 /* Check for face changes. */ | |
826 | 4837 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
428 | 4838 { |
819 | 4839 Lisp_Object last_glyph = Qnil; |
4840 /* Deal with clipped glyphs that we have already displayed. */ | |
4967 | 4841 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
4842 { | |
4843 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
819 | 4844 Dynarr_free (*prop); |
4845 *prop = 0; | |
4846 } | |
428 | 4847 /* Now compute the face and begin/end-glyph information. */ |
4848 data.findex = | |
793 | 4849 /* Remember that the extent-fragment routines deal in |
4187 | 4850 Bytexpos's. */ |
826 | 4851 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
428 | 4852 /* This is somewhat cheesy but the alternative is to |
4187 | 4853 propagate default_face into extent_fragment_update. */ |
428 | 4854 if (data.findex == DEFAULT_INDEX) |
4855 data.findex = default_face; | |
4856 | |
4857 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
4858 | |
826 | 4859 if (data.byte_charpos == data.ef->end) |
428 | 4860 no_more_frags = 1; |
4861 } | |
4862 initial = 0; | |
4863 | |
4864 /* Determine what is next to be displayed. We first handle any | |
4187 | 4865 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
4866 display then we determine what to do based on the character at the | |
4867 current buffer position. */ | |
428 | 4868 |
4869 /* If the current position is covered by an invisible extent, do | |
4187 | 4870 nothing (except maybe add some ellipses). |
428 | 4871 |
4872 #### The behavior of begin and end-glyphs at the edge of an | |
4873 invisible extent should be investigated further. This is | |
4874 fairly low priority though. */ | |
4875 if (data.ef->invisible) | |
4876 { | |
4877 /* #### Chuck, perhaps you could look at this code? I don't | |
4878 really know what I'm doing. */ | |
4879 if (*prop) | |
4880 { | |
4881 Dynarr_free (*prop); | |
4882 *prop = 0; | |
4883 } | |
4884 | |
4885 /* The extent fragment code only sets this when we should | |
4886 really display the ellipses. It makes sure the ellipses | |
4887 don't get displayed more than once in a row. */ | |
4888 if (data.ef->invisible_ellipses) | |
4889 { | |
4890 struct glyph_block gb; | |
4891 | |
4892 data.ef->invisible_ellipses_already_displayed = 1; | |
4893 data.ef->invisible_ellipses = 0; | |
4894 gb.extent = Qnil; | |
4895 gb.glyph = Vinvisible_text_glyph; | |
4896 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
4897 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
4898 /* Perhaps they shouldn't propagate if the very next thing | |
4899 is to display a newline (for compatibility with | |
4900 selective-display-ellipses)? Maybe that's too | |
4901 abstruse. */ | |
4902 if (*prop) | |
4903 goto done; | |
4904 } | |
4905 | |
638 | 4906 /* #### What if we're dealing with a display table? */ |
428 | 4907 if (data.start_col) |
4908 data.start_col--; | |
4909 | |
826 | 4910 if (data.byte_charpos == byte_string_zv) |
428 | 4911 goto done; |
4912 else | |
826 | 4913 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 4914 } |
4915 | |
4916 /* If there is propagation data, then it represents the current | |
4187 | 4917 buffer position being displayed. Add them and advance the |
4918 position counter. This might also add the minibuffer | |
4919 prompt. */ | |
428 | 4920 else if (*prop) |
4921 { | |
4922 dl->used_prop_data = 1; | |
4923 *prop = add_propagation_runes (prop, &data); | |
4924 | |
4925 if (*prop) | |
4926 goto done; /* gee, a really narrow window */ | |
826 | 4927 else if (data.byte_charpos == byte_string_zv) |
428 | 4928 goto done; |
826 | 4929 else if (data.byte_charpos < 0) |
428 | 4930 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
826 | 4931 data.byte_charpos = 0; |
428 | 4932 else |
826 | 4933 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 4934 } |
4935 | |
4936 /* If there are end glyphs, add them to the line. These are | |
4937 the end glyphs for the previous run of text. We add them | |
4938 here rather than doing them at the end of handling the | |
4939 previous run so that glyphs at the beginning and end of | |
4940 a line are handled correctly. */ | |
4941 else if (Dynarr_length (data.ef->end_glyphs) > 0) | |
4942 { | |
867 | 4943 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4944 *prop = add_glyph_runes (&data, END_GLYPHS); |
819 | 4945 |
4946 if (*prop) { | |
428 | 4947 goto done; |
819 | 4948 } |
428 | 4949 } |
4950 | |
4951 /* If there are begin glyphs, add them to the line. */ | |
4952 else if (Dynarr_length (data.ef->begin_glyphs) > 0) | |
4953 { | |
867 | 4954 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4955 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); |
819 | 4956 |
4957 if (*prop) { | |
428 | 4958 goto done; |
819 | 4959 } |
428 | 4960 } |
4961 | |
4962 /* If at end-of-buffer, we've already processed begin and | |
4963 end-glyphs at this point and there's no text to process, | |
4964 so we're done. */ | |
826 | 4965 else if (data.byte_charpos == byte_string_zv) |
428 | 4966 goto done; |
4967 | |
4968 else | |
4969 { | |
4970 Lisp_Object entry = Qnil; | |
4971 /* Get the character at the current buffer position. */ | |
867 | 4972 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4973 if (!NILP (face_dt) || !NILP (window_dt)) |
4974 entry = display_table_entry (data.ch, face_dt, window_dt); | |
4975 | |
4976 /* If there is a display table entry for it, hand it off to | |
4187 | 4977 add_disp_table_entry_runes and let it worry about it. */ |
428 | 4978 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
4979 { | |
4980 *prop = add_disp_table_entry_runes (&data, entry); | |
4981 | |
4982 if (*prop) | |
4983 goto done; | |
4984 } | |
4985 | |
4986 /* Check if we have hit a newline character. If so, add a marker | |
4187 | 4987 to the line and end this loop. */ |
428 | 4988 else if (data.ch == '\n') |
4989 { | |
5619
75ad4969a16d
Replace the 'flush face property with the opposite 'shrink one.
Didier Verna <didier@xemacs.org>
parents:
5617
diff
changeset
|
4990 /* Update the clearing face index unless the shrink property is |
5617
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
4991 set. -- dvl */ |
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
4992 if ((data.findex > DEFAULT_INDEX) |
5619
75ad4969a16d
Replace the 'flush face property with the opposite 'shrink one.
Didier Verna <didier@xemacs.org>
parents:
5617
diff
changeset
|
4993 && ! WINDOW_FACE_CACHEL_SHRINK_P (w, data.findex)) |
5617
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
4994 dl->clear_findex = data.findex; |
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
4995 |
428 | 4996 /* We aren't going to be adding an end glyph so give its |
4187 | 4997 space back in order to make sure that the cursor can |
4998 fit. */ | |
819 | 4999 data.max_pixpos += data.end_glyph_width; |
428 | 5000 goto done; |
5001 } | |
5002 | |
5003 /* If the current character is considered to be printable, then | |
4187 | 5004 just add it. */ |
428 | 5005 else if (data.ch >= printable_min) |
5006 { | |
867 | 5007 *prop = add_ichar_rune (&data); |
428 | 5008 if (*prop) |
5009 goto done; | |
5010 } | |
5011 | |
5012 /* If the current character is a tab, determine the next tab | |
4187 | 5013 starting position and add a blank rune which extends from the |
5014 current pixel position to that starting position. */ | |
428 | 5015 else if (data.ch == '\t') |
5016 { | |
5017 int tab_start_pixpos = data.pixpos; | |
5018 int next_tab_start; | |
5019 int char_tab_width; | |
5020 int prop_width = 0; | |
5021 | |
5022 if (data.start_col > 1) | |
5023 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); | |
5024 | |
5025 next_tab_start = | |
5026 next_tab_position (w, tab_start_pixpos, | |
5027 dl->bounds.left_in + | |
5028 data.hscroll_glyph_width_adjust); | |
5029 if (next_tab_start > data.max_pixpos) | |
5030 { | |
5031 prop_width = next_tab_start - data.max_pixpos; | |
5032 next_tab_start = data.max_pixpos; | |
5033 } | |
5034 data.blank_width = next_tab_start - data.pixpos; | |
5035 char_tab_width = | |
5036 (next_tab_start - tab_start_pixpos) / space_width (w); | |
5037 | |
5038 *prop = add_blank_rune (&data, w, char_tab_width); | |
5039 | |
5040 /* add_blank_rune is only supposed to be called with | |
819 | 5041 sizes guaranteed to fit in the available space. */ |
428 | 5042 assert (!(*prop)); |
5043 | |
5044 if (prop_width) | |
5045 { | |
5046 struct prop_block pb; | |
5047 *prop = Dynarr_new (prop_block); | |
5048 | |
5049 pb.type = PROP_BLANK; | |
5050 pb.data.p_blank.width = prop_width; | |
5051 pb.data.p_blank.findex = data.findex; | |
5052 Dynarr_add (*prop, pb); | |
5053 | |
5054 goto done; | |
5055 } | |
5056 } | |
5057 | |
5058 /* If character is a control character, pass it off to | |
4187 | 5059 add_control_char_runes. |
428 | 5060 |
5061 The is_*() routines have undefined results on | |
5062 arguments outside of the range [-1, 255]. (This | |
5063 often bites people who carelessly use `char' instead | |
5064 of `unsigned char'.) | |
5065 */ | |
867 | 5066 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
428 | 5067 { |
5068 *prop = add_control_char_runes (&data, b); | |
5069 | |
5070 if (*prop) | |
5071 goto done; | |
5072 } | |
5073 | |
5074 /* If the character is above the ASCII range and we have not | |
4187 | 5075 already handled it, then print it as an octal number. */ |
428 | 5076 else if (data.ch >= 0200) |
5077 { | |
5078 *prop = add_octal_runes (&data); | |
5079 | |
5080 if (*prop) | |
5081 goto done; | |
5082 } | |
5083 | |
5084 /* Assume the current character is considered to be printable, | |
4187 | 5085 then just add it. */ |
428 | 5086 else |
5087 { | |
867 | 5088 *prop = add_ichar_rune (&data); |
428 | 5089 if (*prop) |
5090 goto done; | |
5091 } | |
5092 | |
826 | 5093 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 5094 } |
5095 } | |
5096 | |
819 | 5097 done: |
428 | 5098 |
5099 /* Determine the starting point of the next line if we did not hit the | |
5100 end of the buffer. */ | |
826 | 5101 if (data.byte_charpos < byte_string_zv) |
428 | 5102 { |
5103 /* #### This check is not correct. If the line terminated | |
5104 due to a begin-glyph or end-glyph hitting window-end, then | |
826 | 5105 data.ch will not point to the character at data.byte_charpos. If |
428 | 5106 you make the two changes mentioned at the top of this loop, |
5107 you should be able to say '(if (*prop))'. That should also | |
826 | 5108 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 5109 check. */ |
5110 | |
5111 /* The common case is that the line ended because we hit a newline. | |
4187 | 5112 In that case, the next character is just the next buffer |
5113 position. */ | |
428 | 5114 if (data.ch == '\n') |
5115 { | |
826 | 5116 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 5117 } |
5118 | |
5119 /* Otherwise we have a buffer line which cannot fit on one display | |
4187 | 5120 line. */ |
428 | 5121 else |
5122 { | |
5123 struct glyph_block gb; | |
5124 struct glyph_cachel *cachel; | |
5125 | |
5126 /* If the line is to be truncated then we actually have to look | |
4187 | 5127 for the next newline. We also add the end-of-line glyph which |
5128 we know will fit because we adjusted the right border before | |
5129 we starting laying out the line. */ | |
819 | 5130 data.max_pixpos += data.end_glyph_width; |
428 | 5131 data.findex = default_face; |
5132 gb.extent = Qnil; | |
5133 | |
5134 if (truncate_win) | |
5135 { | |
826 | 5136 Bytecount byte_pos; |
428 | 5137 |
5138 /* Now find the start of the next line. */ | |
867 | 5139 byte_pos = byte_find_next_ichar_in_string (disp_string, '\n', |
826 | 5140 data.byte_charpos, 1); |
428 | 5141 |
5142 data.cursor_type = NO_CURSOR; | |
826 | 5143 data.byte_charpos = byte_pos; |
428 | 5144 gb.glyph = Vtruncation_glyph; |
5145 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
5146 } | |
5147 else | |
5148 { | |
5149 /* The cursor can never be on the continuation glyph. */ | |
5150 data.cursor_type = NO_CURSOR; | |
5151 | |
826 | 5152 /* data.byte_charpos is already at the start of the next line. */ |
428 | 5153 |
442 | 5154 dl->line_continuation = 1; |
428 | 5155 gb.glyph = Vcontinuation_glyph; |
5156 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
5157 } | |
5158 | |
819 | 5159 if (data.end_glyph_width) |
428 | 5160 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
5161 | |
826 | 5162 if (truncate_win && data.byte_charpos == byte_string_zv) |
428 | 5163 { |
867 | 5164 const Ibyte *endb = itext_n_addr (XSTRING_DATA (disp_string), |
826 | 5165 byte_string_zv); |
867 | 5166 DEC_IBYTEPTR (endb); |
5167 if (itext_ichar (endb) != '\n') | |
428 | 5168 { |
5169 /* #### Damn this losing shit. */ | |
826 | 5170 data.byte_charpos++; |
428 | 5171 } |
5172 } | |
5173 } | |
5174 } | |
826 | 5175 else if (data.byte_charpos == byte_string_zv) |
428 | 5176 { |
5177 /* create_text_block () adds a bogus \n marker here which screws | |
5178 up subwindow display. Since we never have a cursor in the | |
5179 gutter we can safely ignore it. */ | |
5180 } | |
5181 /* Calculate left whitespace boundary. */ | |
5182 { | |
5183 int elt = 0; | |
5184 | |
5185 /* Whitespace past a newline is considered right whitespace. */ | |
5186 while (elt < Dynarr_length (db->runes)) | |
5187 { | |
5188 struct rune *rb = Dynarr_atp (db->runes, elt); | |
5189 | |
5190 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
5191 || rb->type == RUNE_BLANK) | |
5192 { | |
5193 dl->bounds.left_white += rb->width; | |
5194 elt++; | |
5195 } | |
5196 else | |
5197 elt = Dynarr_length (db->runes); | |
5198 } | |
5199 } | |
5200 | |
5201 /* Calculate right whitespace boundary. */ | |
5202 { | |
5203 int elt = Dynarr_length (db->runes) - 1; | |
5204 int done = 0; | |
5205 | |
5206 while (!done && elt >= 0) | |
5207 { | |
5208 struct rune *rb = Dynarr_atp (db->runes, elt); | |
5209 | |
5210 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
5211 && isspace (rb->object.chr.ch)) | |
5212 && !rb->type == RUNE_BLANK) | |
5213 { | |
5214 dl->bounds.right_white = rb->xpos + rb->width; | |
5215 done = 1; | |
5216 } | |
5217 | |
5218 elt--; | |
5219 | |
5220 } | |
5221 | |
5222 /* The line is blank so everything is considered to be right | |
5223 whitespace. */ | |
5224 if (!done) | |
5225 dl->bounds.right_white = dl->bounds.left_in; | |
5226 } | |
5227 | |
5228 /* Set the display blocks bounds. */ | |
5229 db->start_pos = dl->bounds.left_in; | |
5230 if (Dynarr_length (db->runes)) | |
5231 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
5232 struct rune *rb = Dynarr_lastp (db->runes); |
428 | 5233 |
5234 db->end_pos = rb->xpos + rb->width; | |
5235 } | |
5236 else | |
5237 db->end_pos = dl->bounds.right_white; | |
5238 | |
819 | 5239 calculate_baseline (&data); |
428 | 5240 |
5241 dl->ascent = data.new_ascent; | |
5242 dl->descent = data.new_descent; | |
5243 | |
5244 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5245 unsigned short ascent = (unsigned short) XFIXNUM (w->minimum_line_ascent); |
428 | 5246 |
5247 if (dl->ascent < ascent) | |
5248 dl->ascent = ascent; | |
5249 } | |
5250 { | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5251 unsigned short descent = (unsigned short) XFIXNUM (w->minimum_line_descent); |
428 | 5252 |
5253 if (dl->descent < descent) | |
5254 dl->descent = descent; | |
5255 } | |
5256 | |
819 | 5257 calculate_yoffset (dl, db); |
5258 | |
428 | 5259 dl->cursor_elt = data.cursor_x; |
5260 /* #### lossage lossage lossage! Fix this shit! */ | |
826 | 5261 if (data.byte_charpos > byte_string_zv) |
5262 dl->end_charpos = buffer_or_string_bytexpos_to_charxpos (disp_string, | |
5263 byte_string_zv); | |
428 | 5264 else |
826 | 5265 dl->end_charpos = |
5266 buffer_or_string_bytexpos_to_charxpos (disp_string, | |
5267 data.byte_charpos) - 1; | |
428 | 5268 if (truncate_win) |
434 | 5269 data.dl->num_chars = |
826 | 5270 string_column_at_point (disp_string, dl->end_charpos, |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5271 b ? XFIXNUM (b->tab_width) : 8); |
428 | 5272 else |
5273 /* This doesn't correctly take into account tabs and control | |
5274 characters but if the window isn't being truncated then this | |
5275 value isn't going to end up being used anyhow. */ | |
826 | 5276 data.dl->num_chars = dl->end_charpos - dl->charpos; |
428 | 5277 |
5278 /* #### handle horizontally scrolled line with text none of which | |
5279 was actually laid out. */ | |
5280 | |
5281 /* #### handle any remainder of overlay arrow */ | |
5282 | |
5283 if (*prop == ADD_FAILED) | |
5284 *prop = NULL; | |
5285 | |
5286 if (truncate_win && *prop) | |
5287 { | |
5288 Dynarr_free (*prop); | |
5289 *prop = NULL; | |
5290 } | |
5291 | |
5292 extent_fragment_delete (data.ef); | |
5293 | |
5294 /* #### If we started at EOB, then make sure we return a value past | |
5295 it so that regenerate_window will exit properly. This is bogus. | |
5296 The main loop should get fixed so that it isn't necessary to call | |
5297 this function if we are already at EOB. */ | |
5298 | |
826 | 5299 if (data.byte_charpos == byte_string_zv && byte_start_pos == byte_string_zv) |
793 | 5300 return string_index_byte_to_char (disp_string, |
826 | 5301 data.byte_charpos) + 1; /* Yuck! */ |
428 | 5302 else |
826 | 5303 return string_index_byte_to_char (disp_string, data.byte_charpos); |
428 | 5304 } |
5305 | |
5306 /* Given a display line and a starting position, ensure that the | |
5307 contents of the display line accurately represent the visual | |
5308 representation of the buffer contents starting from the given | |
5309 position when displayed in the given window. The display line ends | |
5310 when the contents of the line reach the right boundary of the given | |
434 | 5311 window. |
5312 | |
428 | 5313 This is very similar to generate_display_line but with the same |
5314 limitations as create_string_text_block. I have taken the liberty | |
665 | 5315 of fixing the bytebpos stuff though.*/ |
5316 | |
5317 static Charbpos | |
428 | 5318 generate_string_display_line (struct window *w, Lisp_Object disp_string, |
5319 struct display_line *dl, | |
826 | 5320 Charcount start_pos, |
428 | 5321 prop_block_dynarr **prop, |
5322 face_index default_face) | |
5323 { | |
826 | 5324 Charcount ret_charcount; |
428 | 5325 |
5326 /* you must set bounds before calling this. */ | |
434 | 5327 |
428 | 5328 /* Reset what this line is using. */ |
5329 if (dl->display_blocks) | |
5330 Dynarr_reset (dl->display_blocks); | |
5331 if (dl->left_glyphs) | |
5332 { | |
5333 Dynarr_free (dl->left_glyphs); | |
5334 dl->left_glyphs = 0; | |
5335 } | |
5336 if (dl->right_glyphs) | |
5337 { | |
5338 Dynarr_free (dl->right_glyphs); | |
5339 dl->right_glyphs = 0; | |
5340 } | |
5341 | |
5342 /* We aren't generating a modeline at the moment. */ | |
5343 dl->modeline = 0; | |
5344 | |
5345 /* Create a display block for the text region of the line. */ | |
826 | 5346 ret_charcount = create_string_text_block (w, disp_string, dl, start_pos, |
5347 prop, default_face); | |
5348 dl->charpos = start_pos; | |
5349 if (dl->end_charpos < dl->charpos) | |
5350 dl->end_charpos = dl->charpos; | |
428 | 5351 |
5352 /* If there are left glyphs associated with any character in the | |
5353 text block, then create a display block to handle them. */ | |
5354 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
5355 create_left_glyph_block (w, dl, 0); | |
5356 | |
5357 /* If there are right glyphs associated with any character in the | |
5358 text block, then create a display block to handle them. */ | |
5359 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
5360 create_right_glyph_block (w, dl); | |
5361 | |
826 | 5362 return ret_charcount; |
428 | 5363 } |
5364 | |
2518 | 5365 /* |
5366 | |
5038 | 5367 Info on reentrancy crashes, with backtraces given: |
5368 | |
5369 (Info-goto-node "(internals)Critical Redisplay Sections") | |
5370 | |
1318 | 5371 */ |
5372 | |
5373 | |
428 | 5374 /* This is ripped off from regenerate_window. All we want to do is |
5375 loop through elements in the string creating display lines until we | |
5376 have covered the provided area. Simple really. */ | |
5377 void | |
5378 generate_displayable_area (struct window *w, Lisp_Object disp_string, | |
5379 int xpos, int ypos, int width, int height, | |
5380 display_line_dynarr* dla, | |
826 | 5381 Charcount start_pos, |
428 | 5382 face_index default_face) |
5383 { | |
5384 int yend = ypos + height; | |
5385 Charcount s_zv; | |
5386 prop_block_dynarr *prop = 0; | |
5387 layout_bounds bounds; | |
2518 | 5388 int depth = -1; |
5389 | |
428 | 5390 /* if there's nothing to do then do nothing. code after this assumes |
5391 there is something to do. */ | |
5392 if (NILP (disp_string)) | |
5393 return; | |
5394 | |
2518 | 5395 /* See comment in regenerate_window() */ |
5396 if (!in_display) | |
5397 depth = enter_redisplay_critical_section (); | |
5398 | |
5399 assert (dla); | |
5400 Dynarr_reset (dla); | |
5401 | |
826 | 5402 s_zv = string_char_length (disp_string); |
428 | 5403 |
5404 bounds.left_out = xpos; | |
5405 bounds.right_out = xpos + width; | |
5406 /* The inner boundaries mark where the glyph margins are located. */ | |
5407 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
5408 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
5409 /* We cannot fully calculate the whitespace boundaries as they | |
5410 depend on the contents of the line being displayed. */ | |
5411 bounds.left_white = bounds.left_in; | |
5412 bounds.right_white = bounds.right_in; | |
5413 | |
5414 while (ypos < yend) | |
5415 { | |
5416 struct display_line dl; | |
5417 struct display_line *dlp; | |
826 | 5418 Charcount next_pos; |
428 | 5419 int local; |
851 | 5420 int pos_of_dlp = -1; |
428 | 5421 |
5422 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5423 { | |
851 | 5424 pos_of_dlp = Dynarr_length (dla); |
5425 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5426 local = 0; |
5427 } | |
5428 else | |
5429 { | |
4207 | 5430 DISPLAY_LINE_INIT (dl); |
428 | 5431 dlp = &dl; |
5432 local = 1; | |
5433 } | |
5434 | |
5435 dlp->bounds = bounds; | |
5436 dlp->offset = 0; | |
1318 | 5437 Dynarr_lock (dla); |
428 | 5438 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos, |
5439 &prop, default_face); | |
1318 | 5440 Dynarr_unlock (dla); |
428 | 5441 /* we need to make sure that we continue along the line if there |
4187 | 5442 is more left to display otherwise we just end up redisplaying |
5443 the same chunk over and over again. */ | |
428 | 5444 if (next_pos == start_pos && next_pos < s_zv) |
5445 start_pos++; | |
5446 else | |
5447 start_pos = next_pos; | |
5448 | |
5449 dlp->ypos = ypos + dlp->ascent; | |
5450 ypos = dlp->ypos + dlp->descent; | |
5451 | |
5452 if (ypos > yend) | |
5453 { | |
5454 int visible_height = dlp->ascent + dlp->descent; | |
5455 | |
5456 dlp->clip = (ypos - yend); | |
5457 visible_height -= dlp->clip; | |
5458 | |
5459 if (visible_height < VERTICAL_CLIP (w, 1)) | |
5460 { | |
5461 if (local) | |
5462 free_display_line (dlp); | |
5463 break; | |
5464 } | |
5465 } | |
5466 else | |
5467 dlp->clip = 0; | |
5468 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5469 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
|
5470 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
|
5471 else if (pos_of_dlp == Dynarr_length (dla)) |
5038 | 5472 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
|
5473 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5474 ABORT (); |
428 | 5475 |
5476 /* #### This type of check needs to be done down in the | |
5477 generate_display_line call. */ | |
5478 if (start_pos >= s_zv) | |
5479 break; | |
5480 } | |
5481 | |
5482 if (prop) | |
5483 Dynarr_free (prop); | |
2518 | 5484 |
5485 if (depth >= 0) | |
5486 exit_redisplay_critical_section (depth); | |
428 | 5487 } |
5488 | |
5489 | |
5490 /***************************************************************************/ | |
5491 /* */ | |
5492 /* window-regeneration routines */ | |
5493 /* */ | |
5494 /***************************************************************************/ | |
5495 | |
5496 /* For a given window and starting position in the buffer it contains, | |
5497 ensure that the TYPE display lines accurately represent the | |
5498 presentation of the window. We pass the buffer instead of getting | |
5499 it from the window since redisplay_window may have temporarily | |
5500 changed it to the echo area buffer. */ | |
5501 | |
5502 static void | |
2518 | 5503 regenerate_window (struct window *w, Charbpos start_pos, Charbpos point, |
5504 int type) | |
428 | 5505 { |
5506 struct frame *f = XFRAME (w->frame); | |
5507 struct buffer *b = XBUFFER (w->buffer); | |
5508 int ypos = WINDOW_TEXT_TOP (w); | |
5509 int yend; /* set farther down */ | |
5510 int yclip = WINDOW_TEXT_TOP_CLIP (w); | |
442 | 5511 int force; |
2518 | 5512 int depth = -1; |
428 | 5513 |
5514 prop_block_dynarr *prop; | |
5515 layout_bounds bounds; | |
5516 display_line_dynarr *dla; | |
5517 int need_modeline; | |
5518 | |
5519 /* The lines had better exist by this point. */ | |
5520 if (!(dla = window_display_lines (w, type))) | |
2500 | 5521 ABORT (); |
2518 | 5522 |
5523 if (!in_display) | |
5524 depth = enter_redisplay_critical_section (); | |
5525 | |
5038 | 5526 /* This is one spot where a reentrancy crash will occur, due to a check |
2518 | 5527 in the dynarr to make sure it isn't "locked" */ |
5528 /* | |
5529 | |
5038 | 5530 Info on reentrancy crashes, with backtraces given: |
5531 | |
5532 (Info-goto-node "(internals)Critical Redisplay Sections") | |
2518 | 5533 */ |
5534 | |
428 | 5535 Dynarr_reset (dla); |
5536 w->max_line_len = 0; | |
5537 | |
4968 | 5538 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
5539 because we initialized them at startup and the only way to reduce | |
5540 their number is through calling reset_face_cachels() or | |
5541 reset_glyph_cachels(), which as a side effect sets up a number of | |
5542 standard entries */ | |
5543 assert (Dynarr_length (w->face_cachels)); | |
5544 assert (Dynarr_length (w->glyph_cachels)); | |
5545 | |
5546 #if 0 | |
5547 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
5548 not needed */ | |
428 | 5549 /* Normally these get updated in redisplay_window but it is possible |
5550 for this function to get called from some other points where that | |
5551 update may not have occurred. This acts as a safety check. */ | |
5552 if (!Dynarr_length (w->face_cachels)) | |
5553 reset_face_cachels (w); | |
5554 if (!Dynarr_length (w->glyph_cachels)) | |
5555 reset_glyph_cachels (w); | |
4968 | 5556 #endif |
428 | 5557 |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5558 Fset_marker (w->start[type], make_fixnum (start_pos), w->buffer); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5559 Fset_marker (w->pointm[type], make_fixnum (point), w->buffer); |
428 | 5560 w->last_point_x[type] = -1; |
5561 w->last_point_y[type] = -1; | |
5562 | |
5563 /* Make sure a modeline is in the structs if needed. */ | |
5564 need_modeline = ensure_modeline_generated (w, type); | |
5565 | |
5566 /* Wait until here to set this so that the structs have a modeline | |
5567 generated in the case where one didn't exist. */ | |
5568 yend = WINDOW_TEXT_BOTTOM (w); | |
5569 | |
5570 bounds = calculate_display_line_boundaries (w, 0); | |
5571 | |
5572 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */ | |
5573 if (MINI_WINDOW_P (w) | |
5574 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt)) | |
5575 && !echo_area_active (f) | |
5576 && start_pos == BUF_BEGV (b)) | |
5577 { | |
5578 struct prop_block pb; | |
5579 prop = Dynarr_new (prop_block); | |
5580 | |
5581 pb.type = PROP_MINIBUF_PROMPT; | |
5688
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
5582 pb.data.p_minibuf_prompt.preprompt = Vminibuf_preprompt; |
b6c506c30f93
Respect face and display table information for the minibuffer prompt.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5628
diff
changeset
|
5583 pb.data.p_minibuf_prompt.prompt = Vminibuf_prompt; |
428 | 5584 Dynarr_add (prop, pb); |
5585 } | |
5586 else | |
5587 prop = 0; | |
5588 | |
442 | 5589 /* When we are computing things for scrolling purposes, make |
5590 sure at least one line is always generated */ | |
5591 force = (type == CMOTION_DISP); | |
5592 | |
5593 /* Make sure this is set always */ | |
5594 /* Note the conversion at end */ | |
5595 w->window_end_pos[type] = start_pos; | |
5596 while (ypos < yend || force) | |
428 | 5597 { |
5598 struct display_line dl; | |
5599 struct display_line *dlp; | |
5600 int local; | |
851 | 5601 int pos_of_dlp = -1; |
428 | 5602 |
5603 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5604 { | |
851 | 5605 pos_of_dlp = Dynarr_length (dla); |
5606 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5607 local = 0; |
5608 } | |
5609 else | |
5610 { | |
4207 | 5611 DISPLAY_LINE_INIT (dl); |
428 | 5612 dlp = &dl; |
5613 local = 1; | |
5614 } | |
5615 | |
5616 dlp->bounds = bounds; | |
5617 dlp->offset = 0; | |
1318 | 5618 Dynarr_lock (dla); |
428 | 5619 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); |
1318 | 5620 Dynarr_unlock (dla); |
428 | 5621 |
5622 if (yclip > dlp->ascent) | |
5623 { | |
5624 /* this should never happen, but if it does just display the | |
5625 whole line */ | |
5626 yclip = 0; | |
5627 } | |
5628 | |
5629 dlp->ypos = (ypos + dlp->ascent) - yclip; | |
5630 ypos = dlp->ypos + dlp->descent; | |
5631 | |
5632 /* See if we've been asked to start midway through a line, for | |
4187 | 5633 partial display line scrolling. */ |
434 | 5634 if (yclip) |
428 | 5635 { |
5636 dlp->top_clip = yclip; | |
5637 yclip = 0; | |
5638 } | |
5639 else | |
5640 dlp->top_clip = 0; | |
5641 | |
5642 if (ypos > yend) | |
5643 { | |
5644 int visible_height = dlp->ascent + dlp->descent; | |
5645 | |
5646 dlp->clip = (ypos - yend); | |
5647 /* Although this seems strange we could have a single very | |
5648 tall line visible for which we need to account for both | |
5649 the top clip and the bottom clip. */ | |
5650 visible_height -= (dlp->clip + dlp->top_clip); | |
5651 | |
442 | 5652 if (visible_height < VERTICAL_CLIP (w, 1) && !force) |
428 | 5653 { |
5654 if (local) | |
5655 free_display_line (dlp); | |
5656 break; | |
5657 } | |
5658 } | |
5659 else | |
5660 dlp->clip = 0; | |
5661 | |
5662 if (dlp->cursor_elt != -1) | |
5663 { | |
5664 /* #### This check is steaming crap. Have to get things | |
4187 | 5665 fixed so when create_text_block hits EOB, we're done, |
5666 period. */ | |
428 | 5667 if (w->last_point_x[type] == -1) |
5668 { | |
5669 w->last_point_x[type] = dlp->cursor_elt; | |
5670 w->last_point_y[type] = Dynarr_length (dla); | |
5671 } | |
5672 else | |
5673 { | |
5674 /* #### This means that we've added a cursor at EOB | |
4187 | 5675 twice. Yuck oh yuck. */ |
1318 | 5676 struct display_block *db; |
5677 | |
5678 Dynarr_lock (dla); | |
5679 db = get_display_block_from_line (dlp, TEXT); | |
5680 Dynarr_unlock (dla); | |
428 | 5681 |
5682 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR; | |
5683 dlp->cursor_elt = -1; | |
5684 } | |
5685 } | |
5686 | |
5687 if (dlp->num_chars > w->max_line_len) | |
5688 w->max_line_len = dlp->num_chars; | |
5689 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5690 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
|
5691 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
|
5692 else if (pos_of_dlp == Dynarr_length (dla)) |
5038 | 5693 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
|
5694 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5695 ABORT (); |
428 | 5696 |
5697 /* #### This isn't right, but it is close enough for now. */ | |
5698 w->window_end_pos[type] = start_pos; | |
5699 | |
5700 /* #### This type of check needs to be done down in the | |
5701 generate_display_line call. */ | |
5702 if (start_pos > BUF_ZV (b)) | |
5703 break; | |
442 | 5704 |
5705 force = 0; | |
428 | 5706 } |
5707 | |
5708 if (prop) | |
5709 Dynarr_free (prop); | |
5710 | |
5711 /* #### More not quite right, but close enough. */ | |
442 | 5712 /* Ben sez: apparently window_end_pos[] is measured |
428 | 5713 as the number of characters between the window end and the |
5714 end of the buffer? This seems rather weirdo. What's | |
442 | 5715 the justification for this? |
5716 | |
5717 JV sez: Because BUF_Z (b) would be a good initial value, however | |
5718 that can change. This representation allows initalizing with 0. | |
5719 */ | |
428 | 5720 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; |
5721 | |
5722 if (need_modeline) | |
5723 { | |
5724 /* We know that this is the right thing to use because we put it | |
4187 | 5725 there when we first started working in this function. */ |
4967 | 5726 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 5727 } |
2518 | 5728 |
5729 if (depth >= 0) | |
5730 exit_redisplay_critical_section (depth); | |
428 | 5731 } |
5732 | |
826 | 5733 #define REGEN_INC_FIND_START_END \ |
5734 do { \ | |
5735 /* Determine start and end of lines. */ \ | |
5736 if (!Dynarr_length (cdla)) \ | |
5737 return 0; \ | |
5738 else \ | |
5739 { \ | |
4967 | 5740 if (Dynarr_begin (cdla)->modeline && Dynarr_begin (ddla)->modeline) \ |
826 | 5741 { \ |
5742 dla_start = 1; \ | |
5743 } \ | |
4967 | 5744 else if (!Dynarr_begin (cdla)->modeline \ |
5745 && !Dynarr_begin (ddla)->modeline) \ | |
826 | 5746 { \ |
5747 dla_start = 0; \ | |
5748 } \ | |
5749 else \ | |
2500 | 5750 ABORT (); /* structs differ */ \ |
826 | 5751 \ |
5752 dla_end = Dynarr_length (cdla) - 1; \ | |
5753 } \ | |
5754 \ | |
5755 start_pos = (Dynarr_atp (cdla, dla_start)->charpos \ | |
5756 + Dynarr_atp (cdla, dla_start)->offset); \ | |
5757 /* If this isn't true, then startp has changed and we need to do a \ | |
5758 full regen. */ \ | |
5759 if (startp != start_pos) \ | |
5760 return 0; \ | |
5761 \ | |
5762 /* Point is outside the visible region so give up. */ \ | |
5763 if (pointm < start_pos) \ | |
5764 return 0; \ | |
5765 \ | |
428 | 5766 } while (0) |
5767 | |
5768 /* This attempts to incrementally update the display structures. It | |
5769 returns a boolean indicating success or failure. This function is | |
5770 very similar to regenerate_window_incrementally and is in fact only | |
5771 called from that function. However, because of the nature of the | |
5772 changes it deals with it sometimes makes different assumptions | |
5773 which can lead to success which are much more difficult to make | |
5774 when dealing with buffer changes. */ | |
5775 | |
5776 static int | |
665 | 5777 regenerate_window_extents_only_changed (struct window *w, Charbpos startp, |
5778 Charbpos pointm, | |
428 | 5779 Charcount beg_unchanged, |
5780 Charcount end_unchanged) | |
5781 { | |
5782 struct buffer *b = XBUFFER (w->buffer); | |
5783 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5784 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5785 | |
5786 int dla_start = 0; | |
5787 int dla_end, line; | |
5788 int first_line, last_line; | |
665 | 5789 Charbpos start_pos; |
428 | 5790 /* Don't define this in the loop where it is used because we |
5791 definitely want its value to survive between passes. */ | |
5792 prop_block_dynarr *prop = NULL; | |
5793 | |
5794 /* If we don't have any buffer change recorded but the modiff flag has | |
5795 been incremented, then fail. I'm not sure of the exact circumstances | |
5796 under which this can happen, but I believe that it is probably a | |
5797 reasonable happening. */ | |
5798 if (!point_visible (w, pointm, CURRENT_DISP) | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5799 || XFIXNUM (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)) |
428 | 5800 return 0; |
5801 | |
5802 /* If the cursor is moved we attempt to update it. If we succeed we | |
5803 go ahead and proceed with the optimization attempt. */ | |
5804 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5805 || pointm != marker_position (w->last_point[CURRENT_DISP])) | |
5806 { | |
5807 struct frame *f = XFRAME (w->frame); | |
5808 struct device *d = XDEVICE (f->device); | |
5809 struct frame *sel_f = device_selected_frame (d); | |
5810 int success = 0; | |
5811 | |
5812 if (w->last_point_x[CURRENT_DISP] != -1 | |
5813 && w->last_point_y[CURRENT_DISP] != -1) | |
5814 { | |
5815 | |
5816 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w))) | |
5817 { | |
5818 /* Always regenerate the modeline in case it is | |
4187 | 5819 displaying the current line or column. */ |
428 | 5820 regenerate_modeline (w); |
5821 success = 1; | |
5822 } | |
5823 } | |
5824 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f))) | |
5825 { | |
5826 if (f->modeline_changed) | |
5827 regenerate_modeline (w); | |
5828 success = 1; | |
5829 } | |
5830 | |
5831 if (!success) | |
5832 return 0; | |
5833 } | |
5834 | |
5835 if (beg_unchanged == -1 && end_unchanged == -1) | |
5836 return 1; | |
5837 | |
5838 /* assert: There are no buffer modifications or they are all below the | |
5839 visible region. We assume that regenerate_window_incrementally has | |
5840 not called us unless this is true. */ | |
5841 | |
5842 REGEN_INC_FIND_START_END; | |
5843 | |
5844 /* If the changed are starts before the visible area, give up. */ | |
5845 if (beg_unchanged < startp) | |
5846 return 0; | |
5847 | |
5848 /* Find what display line the extent changes first affect. */ | |
5849 line = dla_start; | |
5850 while (line <= dla_end) | |
5851 { | |
5852 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5853 Charbpos lstart = dl->charpos + dl->offset; |
5854 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5855 |
5856 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5857 break; | |
5858 | |
5859 line++; | |
5860 } | |
5861 | |
5862 /* If the changes are below the visible area then if point hasn't | |
5863 moved return success otherwise fail in order to be safe. */ | |
5864 if (line > dla_end) | |
5865 { | |
5866 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5867 && pointm == marker_position (w->last_point[CURRENT_DISP])) | |
5868 return 1; | |
5869 else | |
5870 return 0; | |
5871 } | |
5872 | |
5873 /* At this point we know what line the changes first affect. We now | |
5874 begin redrawing lines as long as we are still in the affected | |
5875 region and the line's size and positioning don't change. | |
5876 Otherwise we fail. If we fail we will have altered the desired | |
5877 structs which could lead to an assertion failure. However, if we | |
5878 fail the next thing that is going to happen is a full regen so we | |
5879 will actually end up being safe. */ | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5880 w->last_modified[DESIRED_DISP] = make_fixnum (BUF_MODIFF (b)); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5881 w->last_facechange[DESIRED_DISP] = make_fixnum (BUF_FACECHANGE (b)); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5882 Fset_marker (w->last_start[DESIRED_DISP], make_fixnum (startp), w->buffer); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
5883 Fset_marker (w->last_point[DESIRED_DISP], make_fixnum (pointm), w->buffer); |
428 | 5884 |
5885 first_line = last_line = line; | |
5886 while (line <= dla_end) | |
5887 { | |
2286 | 5888 Charbpos old_start, old_end; |
428 | 5889 struct display_line *cdl = Dynarr_atp (cdla, line); |
5890 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5891 struct display_block *db; | |
5892 int initial_size; | |
5893 | |
826 | 5894 assert (cdl->charpos == ddl->charpos); |
5895 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5896 assert (cdl->offset == ddl->offset); |
5897 | |
5898 db = get_display_block_from_line (ddl, TEXT); | |
5899 initial_size = Dynarr_length (db->runes); | |
826 | 5900 old_start = ddl->charpos + ddl->offset; |
5901 old_end = ddl->end_charpos + ddl->offset; | |
428 | 5902 |
5903 /* If this is the first line being updated and it used | |
4187 | 5904 propagation data, fail. Otherwise we'll be okay because |
5905 we'll have the necessary propagation data. */ | |
428 | 5906 if (line == first_line && ddl->used_prop_data) |
5907 return 0; | |
5908 | |
2286 | 5909 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
5910 &prop, DESIRED_DISP); | |
428 | 5911 ddl->offset = 0; |
5912 | |
5913 /* #### If there is propagated stuff the fail. We could | |
4187 | 5914 probably actually deal with this if the line had propagated |
5915 information when originally created by a full | |
5916 regeneration. */ | |
428 | 5917 if (prop) |
5918 { | |
5919 Dynarr_free (prop); | |
5920 return 0; | |
5921 } | |
5922 | |
5923 /* If any line position parameters have changed or a | |
4187 | 5924 cursor has disappeared or disappeared, fail. */ |
428 | 5925 db = get_display_block_from_line (ddl, TEXT); |
5926 if (cdl->ypos != ddl->ypos | |
5927 || cdl->ascent != ddl->ascent | |
5928 || cdl->descent != ddl->descent | |
5929 || cdl->top_clip != ddl->top_clip | |
5930 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
5931 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
826 | 5932 || old_start != ddl->charpos |
5933 || old_end != ddl->end_charpos | |
5617
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
5934 || initial_size != Dynarr_length (db->runes) |
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
5935 || cdl->clear_findex != ddl->clear_findex) |
428 | 5936 { |
5937 return 0; | |
5938 } | |
5939 | |
5940 if (ddl->cursor_elt != -1) | |
5941 { | |
5942 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
5943 w->last_point_y[DESIRED_DISP] = line; | |
5944 } | |
5945 | |
5946 last_line = line; | |
5947 | |
5948 /* If the extent changes end on the line we just updated then | |
4187 | 5949 we're done. Otherwise go on to the next line. */ |
826 | 5950 if (end_unchanged <= ddl->end_charpos) |
428 | 5951 break; |
5952 else | |
5953 line++; | |
5954 } | |
5955 | |
5956 redisplay_update_line (w, first_line, last_line, 1); | |
5957 return 1; | |
5958 } | |
5959 | |
5960 /* Attempt to update the display data structures based on knowledge of | |
5961 the changed region in the buffer. Returns a boolean indicating | |
5962 success or failure. If this function returns a failure then a | |
5963 regenerate_window _must_ be performed next in order to maintain | |
5964 invariants located here. */ | |
5965 | |
5966 static int | |
665 | 5967 regenerate_window_incrementally (struct window *w, Charbpos startp, |
5968 Charbpos pointm) | |
428 | 5969 { |
5970 struct buffer *b = XBUFFER (w->buffer); | |
5971 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5972 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5973 Charcount beg_unchanged, end_unchanged; | |
5974 Charcount extent_beg_unchanged, extent_end_unchanged; | |
5975 | |
5976 int dla_start = 0; | |
5977 int dla_end, line; | |
665 | 5978 Charbpos start_pos; |
428 | 5979 |
5980 /* If this function is called, the current and desired structures | |
5981 had better be identical. If they are not, then that is a bug. */ | |
5982 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
5983 | |
5984 /* We don't handle minibuffer windows yet. The minibuffer prompt | |
5985 screws us up. */ | |
5986 if (MINI_WINDOW_P (w)) | |
5987 return 0; | |
5988 | |
5989 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b); | |
5990 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1 | |
5991 ? -1 | |
5992 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b)); | |
5993 | |
5994 /* If nothing has changed in the buffer, then make sure point is ok | |
5995 and succeed. */ | |
5996 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1) | |
5997 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5998 extent_beg_unchanged, | |
5999 extent_end_unchanged); | |
6000 | |
6001 /* We can't deal with deleted newlines. */ | |
6002 if (BUF_NEWLINE_WAS_DELETED (b)) | |
6003 return 0; | |
6004 | |
6005 beg_unchanged = BUF_BEGIN_UNCHANGED (b); | |
6006 end_unchanged = (BUF_END_UNCHANGED (b) == -1 | |
6007 ? -1 | |
6008 : BUF_Z (b) - BUF_END_UNCHANGED (b)); | |
6009 | |
6010 REGEN_INC_FIND_START_END; | |
6011 | |
6012 /* If the changed area starts before the visible area, give up. */ | |
6013 if (beg_unchanged < startp) | |
6014 return 0; | |
6015 | |
6016 /* Find what display line the buffer changes first affect. */ | |
6017 line = dla_start; | |
6018 while (line <= dla_end) | |
6019 { | |
6020 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 6021 Charbpos lstart = dl->charpos + dl->offset; |
6022 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 6023 |
6024 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
6025 break; | |
6026 | |
6027 line++; | |
6028 } | |
6029 | |
6030 /* If the changes are below the visible area then if point hasn't | |
6031 moved return success otherwise fail in order to be safe. */ | |
6032 if (line > dla_end) | |
6033 return regenerate_window_extents_only_changed (w, startp, pointm, | |
6034 extent_beg_unchanged, | |
6035 extent_end_unchanged); | |
6036 else | |
6037 /* At this point we know what line the changes first affect. We | |
6038 now redraw that line. If the changes are contained within it | |
6039 we are going to succeed and can update just that one line. | |
6040 Otherwise we fail. If we fail we will have altered the desired | |
6041 structs which could lead to an assertion failure. However, if | |
6042 we fail the next thing that is going to happen is a full regen | |
6043 so we will actually end up being safe. */ | |
6044 { | |
6045 prop_block_dynarr *prop = NULL; | |
6046 struct display_line *cdl = Dynarr_atp (cdla, line); | |
6047 struct display_line *ddl = Dynarr_atp (ddla, line); | |
6048 | |
826 | 6049 assert (cdl->charpos == ddl->charpos); |
6050 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 6051 assert (cdl->offset == ddl->offset); |
6052 | |
442 | 6053 /* If the line continues to next display line, fail. */ |
6054 if (ddl->line_continuation) | |
6055 return 0; | |
428 | 6056 |
6057 /* If the line was generated using propagation data, fail. */ | |
6058 if (ddl->used_prop_data) | |
6059 return 0; | |
6060 | |
2286 | 6061 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
6062 &prop, DESIRED_DISP); | |
428 | 6063 ddl->offset = 0; |
6064 | |
6065 /* If there is propagated stuff then it is pretty much a | |
4187 | 6066 guarantee that more than just the one line is affected. */ |
428 | 6067 if (prop) |
6068 { | |
6069 Dynarr_free (prop); | |
6070 return 0; | |
6071 } | |
6072 | |
442 | 6073 /* If the line continues to next display line, fail. */ |
6074 if (ddl->line_continuation) | |
6075 return 0; | |
428 | 6076 |
6077 /* If any line position parameters have changed or a | |
4187 | 6078 cursor has disappeared or disappeared, fail. */ |
428 | 6079 if (cdl->ypos != ddl->ypos |
6080 || cdl->ascent != ddl->ascent | |
6081 || cdl->descent != ddl->descent | |
6082 || cdl->top_clip != ddl->top_clip | |
6083 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
5617
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
6084 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) |
b0d712bbc2a6
The "flush" face property.
Didier Verna <didier@xemacs.org>
parents:
5587
diff
changeset
|
6085 || cdl->clear_findex != ddl->clear_findex) |
428 | 6086 { |
6087 return 0; | |
6088 } | |
6089 | |
6090 /* If the changed area also ends on this line, then we may be in | |
4187 | 6091 business. Update everything and return success. */ |
826 | 6092 if (end_unchanged >= ddl->charpos && end_unchanged <= ddl->end_charpos) |
428 | 6093 { |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6094 w->last_modified[DESIRED_DISP] = make_fixnum (BUF_MODIFF (b)); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6095 w->last_facechange[DESIRED_DISP] = make_fixnum (BUF_FACECHANGE (b)); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6096 Fset_marker (w->last_start[DESIRED_DISP], make_fixnum (startp), |
428 | 6097 w->buffer); |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6098 Fset_marker (w->last_point[DESIRED_DISP], make_fixnum (pointm), |
428 | 6099 w->buffer); |
6100 | |
6101 if (ddl->cursor_elt != -1) | |
6102 { | |
6103 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
6104 w->last_point_y[DESIRED_DISP] = line; | |
6105 } | |
6106 | |
6107 redisplay_update_line (w, line, line, 1); | |
6108 regenerate_modeline (w); | |
6109 | |
6110 /* #### For now we just flush the cache until this has been | |
4187 | 6111 tested. After that is done, this should correct the |
6112 cache directly. */ | |
428 | 6113 Dynarr_reset (w->line_start_cache); |
6114 | |
6115 /* Adjust the extent changed boundaries to remove any | |
4187 | 6116 overlap with the buffer changes since we've just |
6117 successfully updated that area. */ | |
428 | 6118 if (extent_beg_unchanged != -1 |
6119 && extent_beg_unchanged >= beg_unchanged | |
6120 && extent_beg_unchanged < end_unchanged) | |
6121 extent_beg_unchanged = end_unchanged; | |
6122 | |
6123 if (extent_end_unchanged != -1 | |
6124 && extent_end_unchanged >= beg_unchanged | |
6125 && extent_end_unchanged < end_unchanged) | |
6126 extent_end_unchanged = beg_unchanged - 1; | |
6127 | |
6128 if (extent_end_unchanged <= extent_beg_unchanged) | |
6129 extent_beg_unchanged = extent_end_unchanged = -1; | |
6130 | |
6131 /* This could lead to odd results if it fails, but since the | |
4187 | 6132 buffer changes update succeeded this probably will to. |
6133 We already know that the extent changes start at or after | |
6134 the line because we checked before entering the loop. */ | |
428 | 6135 if (extent_beg_unchanged != -1 |
6136 && extent_end_unchanged != -1 | |
826 | 6137 && ((extent_beg_unchanged < ddl->charpos) |
6138 || (extent_end_unchanged > ddl->end_charpos))) | |
428 | 6139 return regenerate_window_extents_only_changed (w, startp, pointm, |
6140 extent_beg_unchanged, | |
6141 extent_end_unchanged); | |
6142 else | |
6143 return 1; | |
6144 } | |
6145 } | |
6146 | |
6147 /* Oh, well. */ | |
6148 return 0; | |
6149 } | |
6150 | |
6151 /* Given a window and a point, update the given display lines such | |
6152 that point is displayed in the middle of the window. | |
6153 Return the window's new start position. */ | |
6154 | |
665 | 6155 static Charbpos |
6156 regenerate_window_point_center (struct window *w, Charbpos point, int type) | |
428 | 6157 { |
665 | 6158 Charbpos startp; |
428 | 6159 |
6160 /* We need to make sure that the modeline is generated so that the | |
6161 window height can be calculated correctly. */ | |
6162 ensure_modeline_generated (w, type); | |
6163 | |
6164 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w)); | |
6165 regenerate_window (w, startp, point, type); | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6166 Fset_marker (w->start[type], make_fixnum (startp), w->buffer); |
428 | 6167 |
6168 return startp; | |
6169 } | |
6170 | |
6171 /* Given a window and a set of display lines, return a boolean | |
6172 indicating whether the given point is contained within. */ | |
6173 | |
6174 static int | |
665 | 6175 point_visible (struct window *w, Charbpos point, int type) |
428 | 6176 { |
6177 struct buffer *b = XBUFFER (w->buffer); | |
6178 display_line_dynarr *dla = window_display_lines (w, type); | |
6179 int first_line; | |
6180 | |
4967 | 6181 if (Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
428 | 6182 first_line = 1; |
6183 else | |
6184 first_line = 0; | |
6185 | |
6186 if (Dynarr_length (dla) > first_line) | |
6187 { | |
665 | 6188 Charbpos start, end; |
428 | 6189 struct display_line *dl = Dynarr_atp (dla, first_line); |
6190 | |
826 | 6191 start = dl->charpos; |
428 | 6192 end = BUF_Z (b) - w->window_end_pos[type] - 1; |
6193 | |
6194 if (point >= start && point <= end) | |
6195 { | |
6196 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines) | |
6197 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
6198 dl = Dynarr_lastp (dla); |
428 | 6199 |
826 | 6200 if (point >= (dl->charpos + dl->offset) |
6201 && point <= (dl->end_charpos + dl->offset)) | |
428 | 6202 return !dl->clip; |
6203 else | |
6204 return 1; | |
6205 } | |
6206 else | |
6207 return 1; | |
6208 } | |
6209 else | |
6210 return 0; | |
6211 } | |
6212 else | |
6213 return 0; | |
6214 } | |
6215 | |
6216 /* Return pixel position the middle of the window, not including the | |
6217 modeline and any potential horizontal scrollbar. */ | |
6218 | |
6219 int | |
6220 window_half_pixpos (struct window *w) | |
6221 { | |
6222 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1); | |
6223 } | |
6224 | |
6225 /* Return the display line which is currently in the middle of the | |
6226 window W for display lines TYPE. */ | |
6227 | |
6228 int | |
665 | 6229 line_at_center (struct window *w, int type, Charbpos start, Charbpos point) |
428 | 6230 { |
6231 display_line_dynarr *dla; | |
6232 int half; | |
6233 int elt; | |
6234 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1); | |
6235 | |
6236 if (type == CMOTION_DISP) | |
6237 regenerate_window (w, start, point, type); | |
6238 | |
6239 dla = window_display_lines (w, type); | |
6240 half = window_half_pixpos (w); | |
6241 | |
6242 for (elt = first_elt; elt < Dynarr_length (dla); elt++) | |
6243 { | |
6244 struct display_line *dl = Dynarr_atp (dla, elt); | |
6245 int line_bot = dl->ypos + dl->descent; | |
6246 | |
6247 if (line_bot > half) | |
6248 return elt; | |
6249 } | |
6250 | |
6251 /* We may not have a line at the middle if the end of the buffer is | |
6252 being displayed. */ | |
6253 return -1; | |
6254 } | |
6255 | |
6256 /* Return a value for point that would place it at the beginning of | |
6257 the line which is in the middle of the window. */ | |
6258 | |
665 | 6259 Charbpos |
6260 point_at_center (struct window *w, int type, Charbpos start, Charbpos point) | |
428 | 6261 { |
6262 /* line_at_center will regenerate the display structures, if necessary. */ | |
6263 int line = line_at_center (w, type, start, point); | |
6264 | |
6265 if (line == -1) | |
6266 return BUF_ZV (XBUFFER (w->buffer)); | |
6267 else | |
6268 { | |
6269 display_line_dynarr *dla = window_display_lines (w, type); | |
6270 struct display_line *dl = Dynarr_atp (dla, line); | |
6271 | |
826 | 6272 return dl->charpos; |
428 | 6273 } |
6274 } | |
6275 | |
6276 /* For a given window, ensure that the current visual representation | |
6277 is accurate. */ | |
6278 | |
6279 static void | |
6280 redisplay_window (Lisp_Object window, int skip_selected) | |
6281 { | |
6282 struct window *w = XWINDOW (window); | |
6283 struct frame *f = XFRAME (w->frame); | |
6284 struct device *d = XDEVICE (f->device); | |
6285 Lisp_Object old_buffer = w->buffer; | |
6286 Lisp_Object the_buffer = w->buffer; | |
6287 struct buffer *b; | |
6288 int echo_active = 0; | |
6289 int startp = 1; | |
6290 int pointm; | |
6291 int old_startp = 1; | |
6292 int old_pointm = 1; | |
6293 int selected_in_its_frame; | |
6294 int selected_globally; | |
6295 int skip_output = 0; | |
6296 int truncation_changed; | |
6297 int inactive_minibuffer = | |
6298 (MINI_WINDOW_P (w) && | |
6299 (f != device_selected_frame (d)) && | |
6300 !is_surrogate_for_selected_frame (f)); | |
6301 | |
6302 /* #### In the new world this function actually does a bunch of | |
6303 optimizations such as buffer-based scrolling, but none of that is | |
6304 implemented yet. */ | |
6305 | |
6306 /* If this is a combination window, do its children; that's all. | |
6307 The selected window is always a leaf so we don't check for | |
6308 skip_selected here. */ | |
6309 if (!NILP (w->vchild)) | |
6310 { | |
6311 redisplay_windows (w->vchild, skip_selected); | |
6312 return; | |
6313 } | |
6314 if (!NILP (w->hchild)) | |
6315 { | |
6316 redisplay_windows (w->hchild, skip_selected); | |
6317 return; | |
6318 } | |
6319 | |
6320 /* Is this window the selected window on its frame? */ | |
6321 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f))); | |
6322 selected_globally = | |
6323 selected_in_its_frame && | |
5198 | 6324 EQ (DEVICE_CONSOLE (d), Vselected_console) && |
6325 XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d)))) == d && | |
6326 XFRAME (DEVICE_SELECTED_FRAME (d)) == f; | |
428 | 6327 if (skip_selected && selected_in_its_frame) |
6328 return; | |
6329 | |
6330 /* It is possible that the window is not fully initialized yet. */ | |
6331 if (NILP (w->buffer)) | |
6332 return; | |
6333 | |
6334 if (MINI_WINDOW_P (w) && echo_area_active (f)) | |
6335 { | |
6336 w->buffer = the_buffer = Vecho_area_buffer; | |
6337 echo_active = 1; | |
6338 } | |
6339 | |
6340 b = XBUFFER (w->buffer); | |
6341 | |
6342 if (echo_active) | |
6343 { | |
6344 old_pointm = selected_globally | |
4187 | 6345 ? BUF_PT (b) |
6346 : marker_position (w->pointm[CURRENT_DISP]); | |
428 | 6347 pointm = 1; |
6348 } | |
6349 else | |
6350 { | |
6351 if (selected_globally) | |
6352 { | |
6353 pointm = BUF_PT (b); | |
6354 } | |
6355 else | |
6356 { | |
6357 pointm = marker_position (w->pointm[CURRENT_DISP]); | |
6358 | |
6359 if (pointm < BUF_BEGV (b)) | |
6360 pointm = BUF_BEGV (b); | |
6361 else if (pointm > BUF_ZV (b)) | |
6362 pointm = BUF_ZV (b); | |
6363 } | |
6364 } | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6365 Fset_marker (w->pointm[DESIRED_DISP], make_fixnum (pointm), the_buffer); |
428 | 6366 |
4968 | 6367 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
6368 because we initialized them at startup and the only way to reduce | |
6369 their number is through calling reset_face_cachels() or | |
6370 reset_glyph_cachels(), which as a side effect sets up a number of | |
5587
3fde0e346ad7
Prevent assert at frame.c, l. 6311 by initializing glyph cachels.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
5581
diff
changeset
|
6371 standard entries |
3fde0e346ad7
Prevent assert at frame.c, l. 6311 by initializing glyph cachels.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
5581
diff
changeset
|
6372 2011-10-29 -- We were managing to hit the glyph_cachels assert in certain |
3fde0e346ad7
Prevent assert at frame.c, l. 6311 by initializing glyph cachels.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
5581
diff
changeset
|
6373 contexts where VM was creating a lot of frames. I don't have a full |
3fde0e346ad7
Prevent assert at frame.c, l. 6311 by initializing glyph cachels.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
5581
diff
changeset
|
6374 analysis, but I suspect that we were failing to setup the glyph_cachels |
3fde0e346ad7
Prevent assert at frame.c, l. 6311 by initializing glyph cachels.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
5581
diff
changeset
|
6375 at about l. 961 of frame.c, and a message was being sent to the echo area |
3fde0e346ad7
Prevent assert at frame.c, l. 6311 by initializing glyph cachels.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
5581
diff
changeset
|
6376 before the initialization was complete. This triggered a redisplay of |
3fde0e346ad7
Prevent assert at frame.c, l. 6311 by initializing glyph cachels.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
5581
diff
changeset
|
6377 the minibuffer window (this part is confirmed), and thus this assert. */ |
4968 | 6378 assert (Dynarr_length (w->face_cachels)); |
6379 assert (Dynarr_length (w->glyph_cachels)); | |
6380 | |
428 | 6381 /* If the buffer has changed we have to invalidate all of our face |
6382 cache elements. */ | |
6383 if ((!echo_active && b != window_display_buffer (w)) | |
6384 || f->faces_changed) | |
6385 reset_face_cachels (w); | |
6386 else | |
6387 mark_face_cachels_as_not_updated (w); | |
6388 | |
6389 /* Ditto the glyph cache elements, although we do *not* invalidate | |
6390 the cache purely because glyphs have changed - this is now | |
6391 handled by the dirty flag.*/ | |
6392 if ((!echo_active && b != window_display_buffer (w)) | |
4968 | 6393 || f->faces_changed) |
428 | 6394 reset_glyph_cachels (w); |
6395 else | |
6396 mark_glyph_cachels_as_not_updated (w); | |
6397 | |
6398 /* If the marker's buffer is not the window's buffer, then we need | |
6399 to find a new starting position. */ | |
6400 if (!MINI_WINDOW_P (w) | |
6401 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer)) | |
6402 { | |
6403 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6404 | |
6405 goto regeneration_done; | |
6406 } | |
6407 | |
6408 if (echo_active) | |
6409 { | |
6410 old_startp = marker_position (w->start[CURRENT_DISP]); | |
6411 startp = 1; | |
6412 } | |
6413 else | |
6414 { | |
6415 startp = marker_position (w->start[CURRENT_DISP]); | |
6416 if (startp < BUF_BEGV (b)) | |
6417 startp = BUF_BEGV (b); | |
6418 else if (startp > BUF_ZV (b)) | |
6419 startp = BUF_ZV (b); | |
6420 } | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6421 Fset_marker (w->start[DESIRED_DISP], make_fixnum (startp), the_buffer); |
428 | 6422 |
6423 truncation_changed = (find_window_mirror (w)->truncate_win != | |
647 | 6424 (unsigned int) window_truncation_on (w)); |
428 | 6425 |
6426 /* If w->force_start is set, then some function set w->start and we | |
6427 should display from there and change point, if necessary, to | |
6428 ensure that it is visible. */ | |
6429 if (w->force_start || inactive_minibuffer) | |
6430 { | |
6431 w->force_start = 0; | |
6432 w->last_modified[DESIRED_DISP] = Qzero; | |
6433 w->last_facechange[DESIRED_DISP] = Qzero; | |
6434 | |
6435 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6436 | |
6437 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer) | |
6438 { | |
6439 pointm = point_at_center (w, DESIRED_DISP, 0, 0); | |
6440 | |
6441 if (selected_globally) | |
6442 BUF_SET_PT (b, pointm); | |
6443 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6444 Fset_marker (w->pointm[DESIRED_DISP], make_fixnum (pointm), |
428 | 6445 the_buffer); |
6446 | |
6447 /* #### BUFU amounts of overkill just to get the cursor | |
4187 | 6448 location marked properly. FIX ME FIX ME FIX ME */ |
428 | 6449 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6450 } | |
6451 | |
6452 goto regeneration_done; | |
6453 } | |
6454 | |
6455 /* If nothing has changed since the last redisplay, then we just | |
6456 need to make sure that point is still visible. */ | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6457 if (XFIXNUM (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6458 && XFIXNUM (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b) |
428 | 6459 && pointm >= startp |
6460 /* This check is to make sure we restore the minibuffer after a | |
4187 | 6461 temporary change to the echo area. */ |
428 | 6462 && !(MINI_WINDOW_P (w) && f->buffers_changed) |
6463 && !f->frame_changed | |
6464 && !truncation_changed | |
442 | 6465 /* check whether start is really at the beginning of a line GE */ |
428 | 6466 && (!w->start_at_line_beg || beginning_of_line_p (b, startp)) |
6467 ) | |
6468 { | |
6469 /* Check if the cursor has actually moved. */ | |
6470 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
6471 && pointm == marker_position (w->last_point[CURRENT_DISP]) | |
6472 && selected_globally | |
6473 && !w->windows_changed | |
6474 && !f->clip_changed | |
6475 && !f->extents_changed | |
6476 && !f->faces_changed | |
6477 && !f->glyphs_changed | |
6478 && !f->subwindows_changed | |
442 | 6479 /* && !f->subwindows_state_changed*/ |
428 | 6480 && !f->point_changed |
6481 && !f->windows_structure_changed) | |
6482 { | |
6483 /* If not, we're done. */ | |
6484 if (f->modeline_changed) | |
6485 regenerate_modeline (w); | |
6486 | |
6487 skip_output = 1; | |
6488 goto regeneration_done; | |
6489 } | |
6490 else | |
6491 { | |
6492 /* If the new point is visible in the redisplay structures, | |
4187 | 6493 then let the output update routines handle it, otherwise |
6494 do things the hard way. */ | |
428 | 6495 if (!w->windows_changed |
6496 && !f->clip_changed | |
6497 && !f->extents_changed | |
6498 && !f->faces_changed | |
6499 && !f->glyphs_changed | |
6500 && !f->subwindows_changed | |
442 | 6501 /* && !f->subwindows_state_changed*/ |
428 | 6502 && !f->windows_structure_changed) |
6503 { | |
6504 if (point_visible (w, pointm, CURRENT_DISP) | |
6505 && w->last_point_x[CURRENT_DISP] != -1 | |
6506 && w->last_point_y[CURRENT_DISP] != -1) | |
6507 { | |
6508 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f))) | |
6509 { | |
6510 /* Always regenerate in case it is displaying | |
4187 | 6511 the current line or column. */ |
428 | 6512 regenerate_modeline (w); |
6513 | |
6514 skip_output = 1; | |
6515 goto regeneration_done; | |
6516 } | |
6517 } | |
6518 else if (!selected_in_its_frame && !f->point_changed) | |
6519 { | |
6520 if (f->modeline_changed) | |
6521 regenerate_modeline (w); | |
6522 | |
6523 skip_output = 1; | |
6524 goto regeneration_done; | |
6525 } | |
6526 } | |
6527 | |
6528 /* If we weren't able to take the shortcut method, then use | |
4187 | 6529 the brute force method. */ |
428 | 6530 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6531 | |
6532 if (point_visible (w, pointm, DESIRED_DISP)) | |
6533 goto regeneration_done; | |
6534 } | |
6535 } | |
6536 | |
6537 /* Check if the starting point is no longer at the beginning of a | |
6538 line, in which case find a new starting point. We also recenter | |
6539 if our start position is equal to point-max. Otherwise we'll end | |
6540 up with a blank window. */ | |
6541 else if (((w->start_at_line_beg || MINI_WINDOW_P (w)) | |
6542 && !(startp == BUF_BEGV (b) | |
6543 || BUF_FETCH_CHAR (b, startp - 1) == '\n')) | |
6544 || (pointm == startp && | |
6545 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) && | |
6546 startp < marker_position (w->last_start[CURRENT_DISP])) | |
6547 || (startp == BUF_ZV (b))) | |
6548 { | |
6549 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6550 | |
6551 goto regeneration_done; | |
6552 } | |
6553 /* See if we can update the data structures locally based on | |
6554 knowledge of what changed in the buffer. */ | |
6555 else if (!w->windows_changed | |
6556 && !f->clip_changed | |
6557 && !f->faces_changed | |
6558 && !f->glyphs_changed | |
6559 && !f->subwindows_changed | |
442 | 6560 /* && !f->subwindows_state_changed*/ |
428 | 6561 && !f->windows_structure_changed |
6562 && !f->frame_changed | |
6563 && !truncation_changed | |
6564 && pointm >= startp | |
6565 && regenerate_window_incrementally (w, startp, pointm)) | |
6566 { | |
6567 if (f->modeline_changed | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6568 || XFIXNUM (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b) |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6569 || XFIXNUM (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b)) |
428 | 6570 regenerate_modeline (w); |
6571 | |
6572 skip_output = 1; | |
6573 goto regeneration_done; | |
6574 } | |
6575 /* #### This is where a check for structure based scrolling would go. */ | |
6576 /* If all else fails, try just regenerating and see what happens. */ | |
6577 else | |
6578 { | |
6579 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6580 | |
6581 if (point_visible (w, pointm, DESIRED_DISP)) | |
6582 goto regeneration_done; | |
6583 } | |
6584 | |
6585 /* We still haven't gotten the window regenerated with point | |
6586 visible. Next we try scrolling a little and see if point comes | |
6587 back onto the screen. */ | |
6588 if (scroll_step > 0) | |
6589 { | |
6590 int scrolled = scroll_conservatively; | |
6591 for (; scrolled >= 0; scrolled -= scroll_step) | |
6592 { | |
6593 startp = vmotion (w, startp, | |
6594 (pointm < startp) ? -scroll_step : scroll_step, 0); | |
6595 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6596 | |
6597 if (point_visible (w, pointm, DESIRED_DISP)) | |
6598 goto regeneration_done; | |
6599 } | |
6600 } | |
6601 | |
6602 /* We still haven't managed to get the screen drawn with point on | |
6603 the screen, so just center it and be done with it. */ | |
6604 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6605 | |
6606 | |
6607 regeneration_done: | |
6608 | |
6609 /* If the window's frame is changed then reset the current display | |
6610 lines in order to force a full repaint. */ | |
6611 if (f->frame_changed) | |
6612 { | |
6613 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
6614 | |
6615 Dynarr_reset (cla); | |
6616 } | |
6617 | |
6618 /* Must do this before calling redisplay_output_window because it | |
6619 sets some markers on the window. */ | |
6620 if (echo_active) | |
6621 { | |
6622 w->buffer = old_buffer; | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6623 Fset_marker (w->pointm[DESIRED_DISP], make_fixnum (old_pointm), old_buffer); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6624 Fset_marker (w->start[DESIRED_DISP], make_fixnum (old_startp), old_buffer); |
428 | 6625 } |
6626 | |
6627 /* These also have to be set before calling redisplay_output_window | |
6628 since it sets the CURRENT_DISP values based on them. */ | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6629 w->last_modified[DESIRED_DISP] = make_fixnum (BUF_MODIFF (b)); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6630 w->last_facechange[DESIRED_DISP] = make_fixnum (BUF_FACECHANGE (b)); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6631 Fset_marker (w->last_start[DESIRED_DISP], make_fixnum (startp), w->buffer); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6632 Fset_marker (w->last_point[DESIRED_DISP], make_fixnum (pointm), w->buffer); |
428 | 6633 |
6634 if (!skip_output) | |
6635 { | |
665 | 6636 Charbpos start = marker_position (w->start[DESIRED_DISP]); |
6637 Charbpos end = (w->window_end_pos[DESIRED_DISP] == -1 | |
428 | 6638 ? BUF_ZV (b) |
6639 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1); | |
6640 /* Don't pollute the cache if not sure if we are correct */ | |
6641 if (w->start_at_line_beg) | |
6642 update_line_start_cache (w, start, end, pointm, 1); | |
6643 redisplay_output_window (w); | |
6644 /* | |
6645 * If we just displayed the echo area, the line start cache is | |
6646 * no longer valid, because the minibuffer window is associated | |
6647 * with the window now. | |
6648 */ | |
6649 if (echo_active) | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
6650 w->line_cache_last_updated = make_fixnum (-1); |
428 | 6651 } |
6652 | |
6653 /* #### This should be dependent on face changes and will need to be | |
6654 somewhere else once tty updates occur on a per-frame basis. */ | |
6655 mark_face_cachels_as_clean (w); | |
6656 | |
438 | 6657 /* The glyph cachels only get dirty if someone changed something. |
6658 Since redisplay has now effectively ended we can reset the dirty | |
6659 flag since everything must be up-to-date. */ | |
428 | 6660 if (glyphs_changed) |
6661 mark_glyph_cachels_as_clean (w); | |
6662 | |
6663 w->windows_changed = 0; | |
6664 } | |
6665 | |
6666 /* Call buffer_reset_changes for all buffers present in any window | |
6667 currently visible in all frames on all devices. #### There has to | |
6668 be a better way to do this. */ | |
6669 | |
6670 static int | |
2286 | 6671 reset_buffer_changes_mapfun (struct window *w, void *UNUSED (closure)) |
428 | 6672 { |
6673 buffer_reset_changes (XBUFFER (w->buffer)); | |
6674 return 0; | |
6675 } | |
6676 | |
6677 static void | |
6678 reset_buffer_changes (void) | |
6679 { | |
6680 Lisp_Object frmcons, devcons, concons; | |
6681 | |
6682 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
6683 { | |
6684 struct frame *f = XFRAME (XCAR (frmcons)); | |
6685 | |
6686 if (FRAME_REPAINT_P (f)) | |
6687 map_windows (f, reset_buffer_changes_mapfun, 0); | |
6688 } | |
6689 } | |
6690 | |
6691 /* Ensure that all windows underneath the given window in the window | |
6692 hierarchy are correctly displayed. */ | |
6693 | |
6694 static void | |
6695 redisplay_windows (Lisp_Object window, int skip_selected) | |
6696 { | |
6697 for (; !NILP (window) ; window = XWINDOW (window)->next) | |
6698 { | |
6699 redisplay_window (window, skip_selected); | |
6700 } | |
6701 } | |
6702 | |
1318 | 6703 /* Register an action to be called at the end of redisplay. |
6704 in_display is 0 when this is called. | |
6705 This is used when it is discovered that an action needs to be taken, | |
6706 but it's during redisplay, so it's not safe. (Typically, it's an action | |
6707 that needs to enter redisplay, which can't happen reentrantly.) | |
6708 | |
6709 NEVER signal an error in these functions. | |
6710 */ | |
6711 | |
6712 void | |
6713 register_post_redisplay_action (void (*fun) (Lisp_Object), Lisp_Object arg) | |
6714 { | |
6715 Vpost_redisplay_actions = nconc2 (Vpost_redisplay_actions, | |
6716 list1 (Fcons (make_opaque_ptr | |
6717 ((void *) fun), arg))); | |
6718 } | |
6719 | |
1320 | 6720 static int running_post_redisplay_actions; |
6721 | |
1318 | 6722 static void |
6723 run_post_redisplay_actions (void) | |
6724 { | |
1320 | 6725 int depth; |
6726 | |
6727 if (running_post_redisplay_actions) | |
6728 return; | |
6729 | |
6730 depth = internal_bind_int (&running_post_redisplay_actions, 1); | |
6731 /* If the function pushes further actions, they will be tacked onto | |
6732 the end of the list, and we'll run them when we're done with the | |
6733 current ones. */ | |
1318 | 6734 while (!NILP (Vpost_redisplay_actions)) |
6735 { | |
6736 Lisp_Object car = XCAR (Vpost_redisplay_actions); | |
6737 void (*fun) (Lisp_Object) = | |
6738 (void (*)(Lisp_Object)) get_opaque_ptr (XCAR (car)); | |
6739 (*fun) (XCDR (car)); | |
6740 free_opaque_ptr (XCAR (car)); | |
6741 free_cons (car); | |
6742 Vpost_redisplay_actions = XCDR (Vpost_redisplay_actions); | |
6743 } | |
1320 | 6744 unbind_to (depth); |
1318 | 6745 } |
6746 | |
5348
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6747 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
|
6748 |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6749 void |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6750 redisplay_cancel_ritual_suicide(void) |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6751 { |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6752 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
|
6753 } |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6754 |
1318 | 6755 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS |
6756 | |
6757 static Lisp_Object | |
2286 | 6758 commit_ritual_suicide (Lisp_Object UNUSED (ceci_nest_pas_une_pipe)) |
1318 | 6759 { |
5348
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6760 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
|
6761 { |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6762 assert (!in_display); |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6763 } |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6764 else |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6765 the_ritual_suicide_has_been_cancelled = 0; |
1318 | 6766 return Qnil; |
6767 } | |
6768 | |
6769 #endif | |
6770 | |
6771 /* Within the guts of redisplay, we are defenseless and cannot allow any of | |
6772 the following to happen: | |
6773 | |
6774 1) garbage collection | |
6775 2) QUIT | |
6776 3) any non-local exits | |
6777 4) frame size changes | |
6778 5) deletion of any buffers, windows, frames, etc. | |
6779 6) modification of buffer text | |
6780 7) reentrant entry of redisplay (see the stack trace above | |
6781 generate_displayable_area()) | |
6782 | |
6783 The general reason is that the redisplay code is written to assume that | |
6784 it is the only code running, and thus (a) cannot tolerate structures | |
6785 changed out from under it (hence 1, 4, 5, 6, 7) and (b) at various points | |
6786 within redisplay the redisplay structures may be in an inconsistent | |
6787 state and there are no unwind-protects to clean the structures up in | |
6788 case of non-local exit (hence 2, 3). Fixing redisplay to address these | |
6789 issues is hard and perhaps not worth it (and might slow things down a | |
6790 fair amount). We address 1, 4, 5 and 6 ourselves inside of | |
6791 enter_redisplay_critical_section() by simply inhibiting them, but we | |
6792 cannot handle 2 and 3, which must be handled at the actual point where | |
6793 they may occur (especially, internal_equal() or any place that may call | |
6794 Lisp), by wrapping the code in call_trapping_problems() or | |
6795 call_with_suspended_errors(). [[ NOTE: We could address QUIT by inhibiting | |
6796 it but this would be anti-social because it would prevent the user from | |
6797 interrupting any Lisp code called within the critical section. With the | |
6798 call_*() wrapping, C-g will interrupt the Lisp code and throw back to | |
6799 the innermost wrapping. ]] In fact we do turn off QUIT handling, since | |
6800 it's just too dangerous otherwise. See below. | |
6801 | |
6802 Code calling enter_redisplay_critical_section() must check for reentrancy | |
6803 (#7) and take appropriate corrective action. | |
6804 | |
6805 To help debug potential problems, we arrange (when | |
6806 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every time | |
6807 we execute QUIT or call Lisp code unless proper wrapping is in place, as | |
6808 well as further checks when we actually Fsignal(), Fthrow(), | |
6809 garbage_collect_1(). | |
6810 | |
6811 #### If a frame-size change does occur we should probably actually be | |
6812 preempting redisplay. */ | |
6813 | |
6814 /* Count of number of recursive times we call | |
6815 enter_redisplay_critical_section() or | |
6816 enter_redisplay_critical_section_maybe(). | |
6817 enter_redisplay_critical_section() cannot occur reentrantly but we have | |
6818 to know in the *maybe() version whether to exit the section when we're | |
6819 done. */ | |
6820 static int in_display_nesting; | |
6821 | |
6822 static Lisp_Object | |
2286 | 6823 end_hold_frame_size_changes (Lisp_Object UNUSED (obj)) |
1318 | 6824 { |
6825 if (!hold_frame_size_changes) | |
6826 { | |
6827 /* we used to have a function to do this for only one frame, and | |
6828 it was typical to call it at the end of a critical section | |
6829 (which occurs once per frame); but what then happens if multiple | |
6830 frames have frame changes held up? | |
4187 | 6831 |
1318 | 6832 This means we are O(N^2) over frames. I seriously doubt it matters. |
6833 --ben */ | |
6834 Lisp_Object frmcons, devcons, concons; | |
4187 | 6835 |
1318 | 6836 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
6837 { | |
6838 struct frame *f = XFRAME (XCAR (frmcons)); | |
6839 if (f->size_change_pending) | |
5043 | 6840 change_frame_size (f, f->new_width, f->new_height, 0); |
1318 | 6841 } |
6842 } | |
6843 return Qnil; | |
6844 } | |
6845 | |
6846 /* Call this to temporarily prevent frame-size changes from being processed. | |
6847 To undo, use unbind_to(), passing it the value returned by this function. | |
6848 */ | |
6849 | |
6850 int | |
6851 begin_hold_frame_size_changes (void) | |
6852 { | |
6853 int depth = specpdl_depth (); | |
6854 record_unwind_protect (end_hold_frame_size_changes, Qnil); | |
6855 internal_bind_int (&hold_frame_size_changes, 1 + hold_frame_size_changes); | |
6856 return depth; | |
6857 } | |
6858 | |
6859 int | |
6860 enter_redisplay_critical_section (void) | |
6861 { | |
6862 int depth = specpdl_depth (); | |
6863 | |
6864 /* Reentrant entry is deadly. The calling function must check for this. */ | |
6865 assert (!in_display); | |
6866 begin_hold_frame_size_changes (); | |
6867 /* Make sure in_display gets reset, but don't set it yet so that | |
6868 commit_ritual_suicide() can be used. */ | |
6869 internal_bind_int (&in_display, 0); | |
6870 internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6871 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
6872 /* Force every call to QUIT to check for in_displayness. This will | |
6873 verify proper wrapping, as in the previous comment, aborting if not. */ | |
6874 something_happened++; | |
6875 /* Verify that no nonlocal exits blow past us. */ | |
6876 record_unwind_protect (commit_ritual_suicide, Qnil); | |
6877 #endif | |
6878 in_display++; | |
6879 | |
6880 set_trapping_problems_flags (INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY); | |
6881 /* Even checking for QUIT can cause arbitrary Lisp code to be executed, | |
6882 e.g. through a menu handler. We really don't want that happening | |
6883 inside of redisplay. Code that we `eval' is at least written with the | |
6884 expectation that it's inside of redisplay, and shouldn't try anything | |
6885 weird; but that's not the case for menu code (e.g. custom loads huge | |
6886 amounts of LISP FILES from a menu handler! FMH!). Safest just to turn | |
6887 this off. We could turn it on using UNINHIBIT_QUIT or | |
6888 begin_do_check_for_quit() in certain places if we want, if we know | |
6889 it's not in an especially tricky place. */ | |
6890 begin_dont_check_for_quit (); | |
6891 return depth; | |
6892 } | |
6893 | |
6894 void | |
6895 exit_redisplay_critical_section (int depth) | |
6896 { | |
6897 in_display--; | |
6898 assert (!in_display); | |
6899 unbind_to (depth); | |
6900 | |
6901 run_post_redisplay_actions (); | |
6902 } | |
6903 | |
6904 /* Enter the redisplay critical section if we're not already in it. This | |
6905 is for code that needs frame changes held up and other protections from | |
6906 being inside, but doesn't modify the redisplay structures, and doesn't | |
6907 look at them in a way that they will be confused by inconsistencies. */ | |
6908 | |
6909 int | |
6910 enter_redisplay_critical_section_maybe (void) | |
6911 { | |
6912 if (!in_display) | |
6913 return enter_redisplay_critical_section (); | |
6914 else | |
6915 return internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6916 } | |
6917 | |
6918 void | |
6919 exit_redisplay_critical_section_maybe (int depth) | |
6920 { | |
6921 if (in_display_nesting == 1) | |
6922 exit_redisplay_critical_section (depth); | |
6923 else | |
6924 unbind_to (depth); | |
6925 } | |
6926 | |
1279 | 6927 /* Ensure that all windows on the given frame are correctly displayed. |
6928 Return non-zero if pre-empted. */ | |
428 | 6929 |
442 | 6930 int |
428 | 6931 redisplay_frame (struct frame *f, int preemption_check) |
6932 { | |
6933 struct device *d = XDEVICE (f->device); | |
853 | 6934 int depth; |
428 | 6935 |
1279 | 6936 assert (f->init_finished); |
6937 | |
1318 | 6938 /* NOTE: Without sufficient checks for stream frames, we got weird |
6939 crashes in pdump. These came and went very easily -- adding the | |
6940 critical-section code for redisplay was enough to trigger them. | |
6941 Perhaps I should have debugged them but there didn't seem to be any | |
6942 point. --ben */ | |
1279 | 6943 if (FRAME_STREAM_P (f)) /* nothing to do */ |
6944 return 0; | |
6945 | |
1318 | 6946 /* Reentrancy into redisplay can be deadly. See stack trace above |
6947 generate_displayable_area(). */ | |
6948 if (in_display) | |
6949 return 1; | |
6950 | |
545 | 6951 if (preemption_check |
6952 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) | |
428 | 6953 { |
6954 /* The preemption check itself takes a lot of time, | |
6955 so normally don't do it here. We do it if called | |
6956 from Lisp, though (`redisplay-frame'). */ | |
6957 int preempted; | |
6958 | |
6959 REDISPLAY_PREEMPTION_CHECK; | |
6960 if (preempted) | |
6961 return 1; | |
6962 } | |
6963 | |
442 | 6964 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) |
6965 { | |
6966 Lisp_Object frame; | |
6967 | |
6968 f->old_buffer_alist = Freplace_list (f->old_buffer_alist, | |
6969 f->buffer_alist); | |
793 | 6970 frame = wrap_frame (f); |
442 | 6971 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); |
6972 } | |
6973 | |
428 | 6974 /* Before we put a hold on frame size changes, attempt to process |
6975 any which are already pending. */ | |
6976 if (f->size_change_pending) | |
5043 | 6977 change_frame_size (f, f->new_width, f->new_height, 0); |
428 | 6978 |
6979 /* If frame size might need to be changed, due to changed size | |
6980 of toolbars, scrollbars etc, change it now */ | |
6981 if (f->size_slipped) | |
6982 { | |
6983 adjust_frame_size (f); | |
6984 assert (!f->size_slipped); | |
6985 } | |
6986 | |
1318 | 6987 /* The menubar, toolbar, and icon updates should be done before |
853 | 6988 enter_redisplay_critical_section is called and we are officially |
3025 | 6989 `in_display'. They is because they tend to eval Lisp code, which |
1318 | 6990 needs to be carefully wrapped within the critical section (and hence |
6991 is difficult to debug). */ | |
428 | 6992 |
6993 #ifdef HAVE_MENUBARS | |
6994 /* Update the menubar. It is done first since it could change | |
6995 the menubar's visibility. This way we avoid having flashing | |
6996 caused by an Expose event generated by the visibility change | |
6997 being handled. */ | |
6998 update_frame_menubars (f); | |
6999 #endif /* HAVE_MENUBARS */ | |
7000 #ifdef HAVE_TOOLBARS | |
905 | 7001 /* Update the toolbars geometry. We don't update the toolbars |
7002 themselves at this point since the space they are trying to | |
7003 occupy may currently by occupied by gutter elements. Instead we | |
7004 update the geometry, then update the gutter geometry, then update | |
7005 the gutters - which will cause mapped windows to be repositioned | |
7006 - and finally update the toolbars. */ | |
7007 update_frame_toolbars_geometry (f); | |
428 | 7008 #endif /* HAVE_TOOLBARS */ |
442 | 7009 /* Gutter update proper has to be done inside display when no frame |
7010 size changes can occur, thus we separately update the gutter | |
7011 geometry here if it needs it. */ | |
7012 update_frame_gutter_geometry (f); | |
428 | 7013 |
7014 /* If we clear the frame we have to force its contents to be redrawn. */ | |
7015 if (f->clear) | |
7016 f->frame_changed = 1; | |
7017 | |
442 | 7018 /* Invalidate the subwindow caches. We use subwindows_changed here |
7019 to cause subwindows to get instantiated. This is because | |
428 | 7020 subwindows_state_changed is less strict - dealing with things |
7021 like the clicked state of button. We have to do this before | |
7022 redisplaying the gutters as subwindows get unmapped in the | |
7023 process.*/ | |
442 | 7024 if (f->frame_changed) |
7025 reset_frame_subwindow_instance_cache (f); | |
7026 | |
7027 if (f->frame_changed || f->subwindows_changed) | |
7028 { | |
428 | 7029 /* we have to do this so the gutter gets regenerated. */ |
7030 reset_gutter_display_lines (f); | |
7031 } | |
7032 | |
853 | 7033 depth = enter_redisplay_critical_section (); |
428 | 7034 |
7035 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ | |
1318 | 7036 |
7037 /* See comments in enter_redisplay_critical_section() */ | |
428 | 7038 |
442 | 7039 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
7040 | |
7041 /* We can now update the gutters, safe in the knowledge that our | |
7042 efforts won't get undone. */ | |
7043 | |
7044 /* This can call lisp, but redisplay is protected by binding | |
7045 inhibit_quit. More importantly the code involving display lines | |
7046 *assumes* that GC will not happen and so does not GCPRO | |
7047 anything. Since we use this code the whole time with the gutters | |
1318 | 7048 we cannot allow GC to happen when manipulating the gutters. |
7049 | |
7050 This must be inside of the critical section for various reasons. | |
7051 For example, it messes with display structures, which be left in | |
7052 an inconsistent state. */ | |
442 | 7053 update_frame_gutters (f); |
7054 | |
428 | 7055 /* Erase the frame before outputting its contents. */ |
7056 if (f->clear) | |
7057 { | |
442 | 7058 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 7059 } |
7060 | |
7061 /* Do the selected window first. */ | |
7062 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); | |
7063 | |
7064 /* Then do the rest. */ | |
7065 redisplay_windows (f->root_window, 1); | |
7066 | |
442 | 7067 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 7068 |
7069 update_frame_title (f); | |
7070 | |
905 | 7071 #ifdef HAVE_TOOLBARS |
7072 /* Finally update the toolbars. It seems its possible to get in a | |
7073 cycle between updating the gutter and the toolbars. Basically we | |
7074 want to end up with both being up-to-date and this doesn't seem | |
7075 possible in a single pass. */ | |
7076 update_frame_toolbars (f); | |
7077 #endif /* HAVE_TOOLBARS */ | |
7078 | |
428 | 7079 CLASS_RESET_CHANGED_FLAGS (f); |
7080 f->window_face_cache_reset = 0; | |
7081 f->echo_area_garbaged = 0; | |
7082 f->clear = 0; | |
7083 | |
7084 if (!f->size_change_pending) | |
7085 f->size_changed = 0; | |
7086 | |
7087 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */ | |
7088 | |
853 | 7089 /* Allow frame size changes to occur again. */ |
7090 exit_redisplay_critical_section (depth); | |
428 | 7091 |
7092 return 0; | |
7093 } | |
7094 | |
440 | 7095 /* Ensure that all frames on the given device are correctly displayed. |
7096 If AUTOMATIC is non-zero, and the device implementation indicates | |
7097 no automatic redisplay, as printers do, then the device is not | |
7098 redisplayed. AUTOMATIC is set to zero when called from lisp | |
7099 functions (redraw-device) and (redisplay-device), and to non-zero | |
7100 when called from "lazy" redisplay(); | |
7101 */ | |
428 | 7102 |
7103 static int | |
440 | 7104 redisplay_device (struct device *d, int automatic) |
428 | 7105 { |
7106 Lisp_Object frame, frmcons; | |
7107 int size_change_failed = 0; | |
7108 struct frame *f; | |
7109 | |
545 | 7110 if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) |
440 | 7111 return 0; |
7112 | |
428 | 7113 if (DEVICE_STREAM_P (d)) /* nothing to do */ |
7114 return 0; | |
7115 | |
7116 /* It is possible that redisplay has been called before the | |
545 | 7117 device is fully initialized, or that the console implementation |
7118 allows frameless devices. If so then continue with the next | |
7119 device. */ | |
428 | 7120 if (NILP (DEVICE_SELECTED_FRAME (d))) |
7121 return 0; | |
7122 | |
545 | 7123 if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) |
7124 { | |
7125 int preempted; | |
7126 REDISPLAY_PREEMPTION_CHECK; | |
7127 if (preempted) | |
7128 return 1; | |
7129 } | |
428 | 7130 |
7131 /* Always do the selected frame first. */ | |
7132 frame = DEVICE_SELECTED_FRAME (d); | |
7133 | |
7134 f = XFRAME (frame); | |
7135 | |
7136 if (f->icon_changed || f->windows_changed) | |
7137 update_frame_icon (f); | |
7138 | |
7139 if (FRAME_REPAINT_P (f)) | |
7140 { | |
5198 | 7141 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
428 | 7142 { |
588 | 7143 int preempted = redisplay_frame (f, 1); |
545 | 7144 if (preempted) |
7145 return 1; | |
7146 } | |
428 | 7147 |
7148 /* If the frame redisplay did not get preempted, then this flag | |
4187 | 7149 should have gotten set to 0. It might be possible for that |
7150 not to happen if a size change event were to occur at an odd | |
7151 time. To make sure we don't miss anything we simply don't | |
7152 reset the top level flags until the condition ends up being | |
7153 in the right state. */ | |
428 | 7154 if (f->size_changed) |
7155 size_change_failed = 1; | |
7156 } | |
7157 | |
7158 DEVICE_FRAME_LOOP (frmcons, d) | |
7159 { | |
7160 f = XFRAME (XCAR (frmcons)); | |
7161 | |
7162 if (f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
7163 continue; | |
7164 | |
7165 if (f->icon_changed || f->windows_changed) | |
7166 update_frame_icon (f); | |
7167 | |
7168 if (FRAME_REPAINT_P (f)) | |
7169 { | |
430 | 7170 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
428 | 7171 { |
588 | 7172 int preempted = redisplay_frame (f, 1); |
545 | 7173 if (preempted) |
7174 return 1; | |
428 | 7175 } |
7176 | |
7177 if (f->size_change_pending) | |
7178 size_change_failed = 1; | |
7179 } | |
7180 } | |
7181 | |
7182 /* If we get here then we redisplayed all of our frames without | |
7183 getting preempted so mark ourselves as clean. */ | |
7184 CLASS_RESET_CHANGED_FLAGS (d); | |
7185 | |
7186 if (!size_change_failed) | |
7187 d->size_changed = 0; | |
7188 | |
7189 return 0; | |
7190 } | |
7191 | |
7192 /* Ensure that all windows on all frames on all devices are displaying | |
7193 the current contents of their respective buffers. */ | |
7194 | |
7195 static void | |
7196 redisplay_without_hooks (void) | |
7197 { | |
7198 Lisp_Object devcons, concons; | |
7199 int size_change_failed = 0; | |
1292 | 7200 PROFILE_DECLARE (); |
7201 | |
7202 PROFILE_RECORD_ENTERING_SECTION (QSin_redisplay); | |
428 | 7203 |
7204 if (asynch_device_change_pending) | |
7205 handle_asynch_device_change (); | |
7206 | |
7207 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && | |
430 | 7208 !disable_preemption && preemption_count < max_preempts) |
428 | 7209 goto done; |
7210 | |
7211 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
7212 { | |
7213 struct device *d = XDEVICE (XCAR (devcons)); | |
7214 int preempted; | |
7215 | |
430 | 7216 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) |
428 | 7217 { |
440 | 7218 preempted = redisplay_device (d, 1); |
428 | 7219 |
7220 if (preempted) | |
7221 { | |
7222 preemption_count++; | |
7223 RESET_CHANGED_SET_FLAGS; | |
7224 goto done; | |
7225 } | |
7226 | |
7227 /* See comment in redisplay_device. */ | |
7228 if (d->size_changed) | |
7229 size_change_failed = 1; | |
7230 } | |
7231 } | |
7232 preemption_count = 0; | |
7233 | |
7234 /* Mark redisplay as accurate */ | |
7235 GLOBAL_RESET_CHANGED_FLAGS; | |
7236 RESET_CHANGED_SET_FLAGS; | |
7237 | |
7238 if (faces_changed) | |
7239 { | |
7240 mark_all_faces_as_clean (); | |
7241 faces_changed = 0; | |
7242 } | |
7243 | |
7244 if (!size_change_failed) | |
7245 size_changed = 0; | |
7246 | |
7247 reset_buffer_changes (); | |
7248 | |
7249 done: | |
800 | 7250 #ifdef ERROR_CHECK_DISPLAY |
7251 sledgehammer_check_redisplay_structs (); | |
7252 #endif /* ERROR_CHECK_DISPLAY */ | |
1292 | 7253 |
7254 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay); | |
428 | 7255 } |
7256 | |
1318 | 7257 /* Note: All places in the C code that call redisplay() are prepared to |
7258 handle GCing, which can happen from run_pre_idle_hook(). However, we | |
7259 can't currently handle GC inside the guts of redisplay; see | |
7260 enter_redisplay_critical_section(). | |
853 | 7261 |
7262 (#### What about other external entry points to the redisplay code? | |
7263 Someone should go through and make sure that all callers can handle | |
7264 GC there, too.) | |
7265 */ | |
7266 | |
428 | 7267 void |
7268 redisplay (void) | |
7269 { | |
853 | 7270 run_pre_idle_hook (); |
7271 redisplay_no_pre_idle_hook (); | |
7272 } | |
7273 | |
7274 void | |
7275 redisplay_no_pre_idle_hook (void) | |
7276 { | |
428 | 7277 if (last_display_warning_tick != display_warning_tick && |
7278 !inhibit_warning_display) | |
7279 { | |
7280 /* If an error occurs during this function, oh well. | |
4187 | 7281 If we report another warning, we could get stuck in an |
428 | 7282 infinite loop reporting warnings. */ |
853 | 7283 call0_trapping_problems |
7284 (0, Qdisplay_warning_buffer, | |
7285 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 7286 last_display_warning_tick = display_warning_tick; |
7287 } | |
7288 | |
7289 redisplay_without_hooks (); | |
7290 } | |
7291 | |
853 | 7292 Lisp_Object |
7293 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker) | |
7294 { | |
7295 return | |
7296 eval_in_buffer_trapping_problems | |
7297 ("Error calling function within redisplay", current_buffer, | |
1318 | 7298 dont_trust_this_damn_sucker, 0); |
853 | 7299 } |
428 | 7300 |
7301 /* Efficiently determine the window line number, and return a pointer | |
7302 to its printed representation. Do this regardless of whether | |
7303 line-number-mode is on. The first line in the buffer is counted as | |
7304 1. If narrowing is in effect, the lines are counted from the | |
7305 beginning of the visible portion of the buffer. */ | |
4970 | 7306 static Ascbyte * |
428 | 7307 window_line_number (struct window *w, int type) |
7308 { | |
7309 struct device *d = XDEVICE (XFRAME (w->frame)->device); | |
7310 struct buffer *b = XBUFFER (w->buffer); | |
7311 /* Be careful in the order of these tests. The first clause will | |
7312 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be). | |
7313 This can occur when the frame title is computed really early */ | |
665 | 7314 Charbpos pos = |
5198 | 7315 ((EQ (DEVICE_SELECTED_FRAME (d), w->frame) && |
7316 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d)))) && | |
7317 EQ (DEVICE_CONSOLE (d), Vselected_console) && | |
7318 XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d)))) == d ) | |
428 | 7319 ? BUF_PT (b) |
7320 : marker_position (w->pointm[type])); | |
7321 EMACS_INT line; | |
7322 | |
7323 line = buffer_line_number (b, pos, 1); | |
7324 | |
603 | 7325 { |
4970 | 7326 static Ascbyte window_line_number_buf[DECIMAL_PRINT_SIZE (long)]; |
603 | 7327 |
7328 long_to_string (window_line_number_buf, line + 1); | |
7329 | |
7330 return window_line_number_buf; | |
7331 } | |
428 | 7332 } |
7333 | |
7334 | |
7335 /* Given a character representing an object in a modeline | |
7336 specification, return a string (stored into the global array | |
867 | 7337 `mode_spec_ibyte_string') with the information that object |
428 | 7338 represents. |
7339 | |
7340 This function is largely unchanged from previous versions of the | |
7341 redisplay engine. | |
7342 | |
7343 Warning! This code is also used for frame titles and can be called | |
7344 very early in the device/frame update process! JV | |
7345 */ | |
7346 | |
7347 static void | |
867 | 7348 decode_mode_spec (struct window *w, Ichar spec, int type) |
428 | 7349 { |
7350 Lisp_Object obj = Qnil; | |
4970 | 7351 const Ascbyte *str = NULL; |
428 | 7352 struct buffer *b = XBUFFER (w->buffer); |
7353 | |
867 | 7354 Dynarr_reset (mode_spec_ibyte_string); |
428 | 7355 |
7356 switch (spec) | |
7357 { | |
7358 /* print buffer name */ | |
7359 case 'b': | |
7360 obj = b->name; | |
7361 break; | |
7362 | |
7363 /* print visited file name */ | |
7364 case 'f': | |
7365 obj = b->filename; | |
7366 break; | |
7367 | |
7368 /* print the current column */ | |
7369 case 'c': | |
7370 { | |
4187 | 7371 Charbpos pt = (w == XWINDOW (Fselected_window (Qnil))) |
7372 ? BUF_PT (b) | |
7373 : marker_position (w->pointm[type]); | |
428 | 7374 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one; |
4970 | 7375 Ascbyte buf[DECIMAL_PRINT_SIZE (long)]; |
428 | 7376 |
7377 long_to_string (buf, col); | |
7378 | |
867 | 7379 Dynarr_add_many (mode_spec_ibyte_string, |
7380 (const Ibyte *) buf, strlen (buf)); | |
428 | 7381 |
7382 goto decode_mode_spec_done; | |
7383 } | |
7384 /* print the file coding system */ | |
7385 case 'C': | |
7386 { | |
4187 | 7387 Lisp_Object codesys = b->buffer_file_coding_system; |
7388 /* Be very careful here not to get an error. */ | |
428 | 7389 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys)) |
4187 | 7390 { |
7391 codesys = find_coding_system_for_text_file (codesys, 0); | |
428 | 7392 if (CODING_SYSTEMP (codesys)) |
4187 | 7393 obj = XCODING_SYSTEM_MNEMONIC (codesys); |
7394 } | |
428 | 7395 } |
7396 break; | |
7397 | |
7398 /* print the current line number */ | |
7399 case 'l': | |
7400 str = window_line_number (w, type); | |
7401 break; | |
7402 | |
7403 /* print value of mode-name (obsolete) */ | |
7404 case 'm': | |
7405 obj = b->mode_name; | |
7406 break; | |
7407 | |
7408 /* print hyphen and frame number, if != 1 */ | |
7409 case 'N': | |
7410 #ifdef HAVE_TTY | |
7411 { | |
7412 struct frame *f = XFRAME (w->frame); | |
7413 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999) | |
7414 { | |
7415 /* Naughty, naughty */ | |
4970 | 7416 Ascbyte *writable_str = alloca_array (Ascbyte, 10); |
428 | 7417 sprintf (writable_str, "-%d", f->order_count); |
7418 str = writable_str; | |
7419 } | |
7420 } | |
7421 #endif /* HAVE_TTY */ | |
7422 break; | |
7423 | |
7424 /* print Narrow if appropriate */ | |
7425 case 'n': | |
7426 if (BUF_BEGV (b) > BUF_BEG (b) | |
7427 || BUF_ZV (b) < BUF_Z (b)) | |
7428 str = " Narrow"; | |
7429 break; | |
7430 | |
7431 /* print %, * or hyphen, if buffer is read-only, modified or neither */ | |
7432 case '*': | |
7433 str = (!NILP (b->read_only) | |
7434 ? "%" | |
7435 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7436 ? "*" | |
7437 : "-")); | |
7438 break; | |
7439 | |
7440 /* print * or hyphen -- XEmacs change to allow a buffer to be | |
4187 | 7441 read-only but still indicate whether it is modified. */ |
428 | 7442 case '+': |
7443 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7444 ? "*" | |
7445 : (!NILP (b->read_only) | |
7446 ? "%" | |
7447 : "-")); | |
7448 break; | |
7449 | |
7450 /* #### defined in 19.29 decode_mode_spec, but not in | |
4187 | 7451 modeline-format doc string. */ |
428 | 7452 /* This differs from %* in that it ignores read-only-ness. */ |
7453 case '&': | |
7454 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7455 ? "*" | |
7456 : "-"); | |
7457 break; | |
7458 | |
7459 /* print process status */ | |
7460 case 's': | |
7461 obj = Fget_buffer_process (w->buffer); | |
7462 if (NILP (obj)) | |
7463 str = GETTEXT ("no process"); | |
7464 else | |
7465 obj = Fsymbol_name (Fprocess_status (obj)); | |
7466 break; | |
7467 | |
7468 /* Print name of selected frame. */ | |
7469 case 'S': | |
7470 obj = XFRAME (w->frame)->name; | |
7471 break; | |
7472 | |
7473 /* indicate TEXT or BINARY */ | |
7474 case 't': | |
7475 /* #### NT does not use this any more. Now what? */ | |
7476 str = "T"; | |
7477 break; | |
7478 | |
7479 /* print percent of buffer above top of window, or Top, Bot or All */ | |
7480 case 'p': | |
7481 { | |
665 | 7482 Charbpos pos = marker_position (w->start[type]); |
428 | 7483 |
7484 /* This had better be while the desired lines are being done. */ | |
7485 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) | |
7486 { | |
7487 if (pos <= BUF_BEGV (b)) | |
7488 str = "All"; | |
7489 else | |
7490 str = "Bottom"; | |
7491 } | |
7492 else if (pos <= BUF_BEGV (b)) | |
7493 str = "Top"; | |
7494 else | |
7495 { | |
7496 /* This hard limit is ok since the string it will hold has a | |
4187 | 7497 fixed maximum length of 3. But just to be safe... */ |
4970 | 7498 Ascbyte buf[10]; |
428 | 7499 Charcount chars = pos - BUF_BEGV (b); |
7500 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7501 | |
7502 /* Avoid overflow on big buffers */ | |
7503 int percent = total > LONG_MAX/200 ? | |
7504 (chars + total/200) / (total / 100) : | |
7505 (chars * 100 + total/2) / total; | |
7506 | |
7507 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7508 2-digit number that is close. */ |
428 | 7509 if (percent == 100) |
7510 percent = 99; | |
7511 | |
7512 sprintf (buf, "%d%%", percent); | |
867 | 7513 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7514 strlen (buf)); |
7515 | |
7516 goto decode_mode_spec_done; | |
7517 } | |
7518 break; | |
7519 } | |
7520 | |
7521 /* print percent of buffer above bottom of window, perhaps plus | |
7522 Top, or print Bottom or All */ | |
7523 case 'P': | |
7524 { | |
665 | 7525 Charbpos toppos = marker_position (w->start[type]); |
7526 Charbpos botpos = BUF_Z (b) - w->window_end_pos[type]; | |
428 | 7527 |
7528 /* botpos is only accurate as of the last redisplay, so we can | |
4187 | 7529 only treat it as a hint. In particular, after erase-buffer, |
7530 botpos may be negative. */ | |
428 | 7531 if (botpos < toppos) |
7532 botpos = toppos; | |
7533 | |
7534 if (botpos >= BUF_ZV (b)) | |
7535 { | |
7536 if (toppos <= BUF_BEGV (b)) | |
7537 str = "All"; | |
7538 else | |
7539 str = "Bottom"; | |
7540 } | |
7541 else | |
7542 { | |
7543 /* This hard limit is ok since the string it will hold has a | |
4187 | 7544 fixed maximum length of around 6. But just to be safe... */ |
4970 | 7545 Ascbyte buf[10]; |
428 | 7546 Charcount chars = botpos - BUF_BEGV (b); |
7547 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7548 | |
7549 /* Avoid overflow on big buffers */ | |
7550 int percent = total > LONG_MAX/200 ? | |
7551 (chars + total/200) / (total / 100) : | |
7552 (chars * 100 + total/2) / max (total, 1); | |
7553 | |
7554 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7555 2-digit number that is close. */ |
428 | 7556 if (percent == 100) |
7557 percent = 99; | |
7558 | |
7559 if (toppos <= BUF_BEGV (b)) | |
7560 sprintf (buf, "Top%d%%", percent); | |
7561 else | |
7562 sprintf (buf, "%d%%", percent); | |
7563 | |
867 | 7564 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7565 strlen (buf)); |
7566 | |
7567 goto decode_mode_spec_done; | |
7568 } | |
7569 break; | |
7570 } | |
7571 | |
7572 /* print % */ | |
7573 case '%': | |
7574 str = "%"; | |
7575 break; | |
7576 | |
7577 /* print one [ for each recursive editing level. */ | |
7578 case '[': | |
7579 { | |
7580 int i; | |
7581 | |
7582 if (command_loop_level > 5) | |
7583 { | |
7584 str = "[[[... "; | |
7585 break; | |
7586 } | |
7587 | |
7588 for (i = 0; i < command_loop_level; i++) | |
867 | 7589 Dynarr_add (mode_spec_ibyte_string, '['); |
428 | 7590 |
7591 goto decode_mode_spec_done; | |
7592 } | |
7593 | |
7594 /* print one ] for each recursive editing level. */ | |
7595 case ']': | |
7596 { | |
7597 int i; | |
7598 | |
7599 if (command_loop_level > 5) | |
7600 { | |
7601 str = "...]]]"; | |
7602 break; | |
7603 } | |
7604 | |
7605 for (i = 0; i < command_loop_level; i++) | |
867 | 7606 Dynarr_add (mode_spec_ibyte_string, ']'); |
428 | 7607 |
7608 goto decode_mode_spec_done; | |
7609 } | |
7610 | |
7611 /* print infinitely many dashes -- handle at top level now */ | |
7612 case '-': | |
7613 break; | |
7614 | |
7615 } | |
7616 | |
7617 if (STRINGP (obj)) | |
867 | 7618 Dynarr_add_many (mode_spec_ibyte_string, |
428 | 7619 XSTRING_DATA (obj), |
7620 XSTRING_LENGTH (obj)); | |
7621 else if (str) | |
867 | 7622 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) str, strlen (str)); |
428 | 7623 |
7624 decode_mode_spec_done: | |
867 | 7625 Dynarr_add (mode_spec_ibyte_string, '\0'); |
428 | 7626 } |
7627 | |
7628 /* Given a display line, free all of its data structures. */ | |
7629 | |
7630 static void | |
7631 free_display_line (struct display_line *dl) | |
7632 { | |
7633 int block; | |
7634 | |
7635 if (dl->display_blocks) | |
7636 { | |
7637 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
4187 | 7638 { |
428 | 7639 struct display_block *db = Dynarr_atp (dl->display_blocks, block); |
7640 | |
7641 Dynarr_free (db->runes); | |
7642 } | |
7643 | |
7644 Dynarr_free (dl->display_blocks); | |
7645 dl->display_blocks = NULL; | |
7646 } | |
7647 | |
7648 if (dl->left_glyphs) | |
7649 { | |
7650 Dynarr_free (dl->left_glyphs); | |
7651 dl->left_glyphs = NULL; | |
7652 } | |
7653 | |
7654 if (dl->right_glyphs) | |
7655 { | |
7656 Dynarr_free (dl->right_glyphs); | |
7657 dl->right_glyphs = NULL; | |
7658 } | |
7659 } | |
7660 | |
7661 | |
7662 /* Given an array of display lines, free them and all data structures | |
7663 contained within them. */ | |
7664 | |
7665 void | |
7666 free_display_lines (display_line_dynarr *dla) | |
7667 { | |
7668 int line; | |
7669 | |
7670 for (line = 0; line < Dynarr_largest (dla); line++) | |
7671 { | |
7672 free_display_line (Dynarr_atp (dla, line)); | |
7673 } | |
7674 | |
7675 Dynarr_free (dla); | |
7676 } | |
7677 | |
7678 /* Call internal free routine for each set of display lines. */ | |
7679 | |
7680 void | |
7681 free_display_structs (struct window_mirror *mir) | |
7682 { | |
7683 if (mir->current_display_lines) | |
7684 { | |
7685 free_display_lines (mir->current_display_lines); | |
7686 mir->current_display_lines = 0; | |
7687 } | |
7688 | |
7689 if (mir->desired_display_lines) | |
7690 { | |
7691 free_display_lines (mir->desired_display_lines); | |
7692 mir->desired_display_lines = 0; | |
7693 } | |
7694 } | |
7695 | |
7696 | |
7697 static void | |
7698 mark_glyph_block_dynarr (glyph_block_dynarr *gba) | |
7699 { | |
7700 if (gba) | |
7701 { | |
4967 | 7702 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
|
7703 glyph_block *gb_last = Dynarr_past_lastp (gba); |
428 | 7704 |
7705 for (; gb < gb_last; gb++) | |
7706 { | |
7707 if (!NILP (gb->glyph)) | |
7708 mark_object (gb->glyph); | |
7709 if (!NILP (gb->extent)) | |
7710 mark_object (gb->extent); | |
7711 } | |
7712 } | |
7713 } | |
7714 | |
442 | 7715 /* See the comment in image_instantiate_cache_result as to why marking |
7716 the glyph will also mark the image_instance. */ | |
7717 void | |
428 | 7718 mark_redisplay_structs (display_line_dynarr *dla) |
7719 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7720 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
|
7721 display_line *dl_last = Dynarr_past_lastp (dla); |
428 | 7722 |
7723 for (; dl < dl_last; dl++) | |
7724 { | |
7725 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
|
7726 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
|
7727 display_block *db_last = Dynarr_past_lastp (dba); |
428 | 7728 |
7729 for (; db < db_last; db++) | |
7730 { | |
7731 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
|
7732 rune *r = Dynarr_begin (ra); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7733 rune *r_last = Dynarr_past_lastp (ra); |
428 | 7734 |
7735 for (; r < r_last; r++) | |
7736 { | |
7737 if (r->type == RUNE_DGLYPH) | |
7738 { | |
7739 if (!NILP (r->object.dglyph.glyph)) | |
7740 mark_object (r->object.dglyph.glyph); | |
7741 if (!NILP (r->object.dglyph.extent)) | |
7742 mark_object (r->object.dglyph.extent); | |
7743 } | |
7744 } | |
7745 } | |
7746 | |
7747 mark_glyph_block_dynarr (dl->left_glyphs); | |
7748 mark_glyph_block_dynarr (dl->right_glyphs); | |
7749 } | |
7750 } | |
7751 | |
7752 | |
2367 | 7753 |
7754 /* | |
7755 | |
7756 Info on line-start cache: | |
7757 | |
7758 (Info-goto-node "(internals)Line Start Cache") | |
7759 */ | |
428 | 7760 |
7761 /* This will get used quite a bit so we don't want to be constantly | |
7762 allocating and freeing it. */ | |
7763 static line_start_cache_dynarr *internal_cache; | |
7764 | |
7765 /* Makes internal_cache represent the TYPE display structs and only | |
7766 the TYPE display structs. */ | |
7767 | |
7768 static void | |
7769 update_internal_cache_list (struct window *w, int type) | |
7770 { | |
7771 int line; | |
7772 display_line_dynarr *dla = window_display_lines (w, type); | |
7773 | |
7774 Dynarr_reset (internal_cache); | |
7775 for (line = 0; line < Dynarr_length (dla); line++) | |
7776 { | |
7777 struct display_line *dl = Dynarr_atp (dla, line); | |
7778 | |
7779 if (dl->modeline) | |
7780 continue; | |
7781 else | |
7782 { | |
7783 struct line_start_cache lsc; | |
434 | 7784 |
826 | 7785 lsc.start = dl->charpos; |
7786 lsc.end = dl->end_charpos; | |
428 | 7787 lsc.height = dl->ascent + dl->descent; |
7788 | |
7789 Dynarr_add (internal_cache, lsc); | |
7790 } | |
7791 } | |
7792 } | |
7793 | |
7794 /* Reset the line cache if necessary. This should be run at the | |
7795 beginning of any function which access the cache. */ | |
7796 | |
7797 static void | |
7798 validate_line_start_cache (struct window *w) | |
7799 { | |
7800 struct buffer *b = XBUFFER (w->buffer); | |
7801 struct frame *f = XFRAME (w->frame); | |
7802 | |
7803 if (!w->line_cache_validation_override) | |
7804 { | |
7805 /* f->extents_changed used to be in here because extent face and | |
4187 | 7806 size changes can cause text shifting. However, the extent |
7807 covering the region is constantly having its face set and | |
7808 priority altered by the mouse code. This means that the line | |
7809 start cache is constantly being invalidated. This is bad | |
7810 since the mouse code also triggers heavy usage of the cache. | |
7811 Since it is an unlikely that f->extents being changed | |
7812 indicates that the cache really needs to be updated and if it | |
7813 does redisplay will catch it pretty quickly we no longer | |
7814 invalidate the cache if it is set. This greatly speeds up | |
7815 dragging out regions with the mouse. */ | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
7816 if (XFIXNUM (w->line_cache_last_updated) < BUF_MODIFF (b) |
428 | 7817 || f->faces_changed |
7818 || f->clip_changed) | |
7819 { | |
7820 Dynarr_reset (w->line_start_cache); | |
7821 } | |
7822 } | |
7823 } | |
7824 | |
7825 /* Return the very first buffer position contained in the given | |
7826 window's cache, or -1 if the cache is empty. Assumes that the | |
7827 cache is valid. */ | |
7828 | |
665 | 7829 static Charbpos |
428 | 7830 line_start_cache_start (struct window *w) |
7831 { | |
7832 line_start_cache_dynarr *cache = w->line_start_cache; | |
7833 | |
7834 if (!Dynarr_length (cache)) | |
7835 return -1; | |
7836 else | |
4967 | 7837 return Dynarr_begin (cache)->start; |
428 | 7838 } |
7839 | |
7840 /* Return the very last buffer position contained in the given | |
7841 window's cache, or -1 if the cache is empty. Assumes that the | |
7842 cache is valid. */ | |
7843 | |
665 | 7844 static Charbpos |
428 | 7845 line_start_cache_end (struct window *w) |
7846 { | |
7847 line_start_cache_dynarr *cache = w->line_start_cache; | |
7848 | |
7849 if (!Dynarr_length (cache)) | |
7850 return -1; | |
7851 else | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7852 return Dynarr_lastp (cache)->end; |
428 | 7853 } |
7854 | |
7855 /* Return the index of the line POINT is contained within in window | |
7856 W's line start cache. It will enlarge the cache or move the cache | |
7857 window in order to have POINT be present in the cache. MIN_PAST is | |
7858 a guarantee of the number of entries in the cache present on either | |
7859 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1 | |
7860 then it will be treated as 0, but the cache window will not be | |
7861 allowed to shift. Returns -1 if POINT cannot be found in the cache | |
7862 for any reason. */ | |
7863 | |
7864 int | |
665 | 7865 point_in_line_start_cache (struct window *w, Charbpos point, int min_past) |
428 | 7866 { |
7867 struct buffer *b = XBUFFER (w->buffer); | |
7868 line_start_cache_dynarr *cache = w->line_start_cache; | |
647 | 7869 int top, bottom, pos; |
428 | 7870 |
7871 validate_line_start_cache (w); | |
7872 w->line_cache_validation_override++; | |
7873 | |
7874 /* Let functions pass in negative values, but we still treat -1 | |
7875 specially. */ | |
7876 /* #### bogosity alert */ | |
7877 if (min_past < 0 && min_past != -1) | |
7878 min_past = -min_past; | |
7879 | |
7880 if (!Dynarr_length (cache) || line_start_cache_start (w) > point | |
7881 || line_start_cache_end (w) < point) | |
7882 { | |
7883 int loop; | |
7884 int win_char_height = window_char_height (w, 1); | |
7885 | |
7886 /* Occasionally we get here with a 0 height | |
4187 | 7887 window. find_next_newline_no_quit will abort if we pass it a |
7888 count of 0 so handle that case. */ | |
428 | 7889 if (!win_char_height) |
7890 win_char_height = 1; | |
7891 | |
7892 if (!Dynarr_length (cache)) | |
7893 { | |
665 | 7894 Charbpos from = find_next_newline_no_quit (b, point, -1); |
7895 Charbpos to = find_next_newline_no_quit (b, from, win_char_height); | |
428 | 7896 |
7897 update_line_start_cache (w, from, to, point, 0); | |
7898 | |
7899 if (!Dynarr_length (cache)) | |
7900 { | |
7901 w->line_cache_validation_override--; | |
7902 return -1; | |
7903 } | |
7904 } | |
7905 | |
7906 assert (Dynarr_length (cache)); | |
7907 | |
7908 loop = 0; | |
7909 while (line_start_cache_start (w) > point | |
7910 && (loop < cache_adjustment || min_past == -1)) | |
7911 { | |
665 | 7912 Charbpos from, to; |
428 | 7913 |
7914 from = line_start_cache_start (w); | |
7915 if (from <= BUF_BEGV (b)) | |
7916 break; | |
7917 | |
7918 from = find_next_newline_no_quit (b, from, -win_char_height); | |
7919 to = line_start_cache_end (w); | |
7920 | |
7921 update_line_start_cache (w, from, to, point, 0); | |
7922 loop++; | |
7923 } | |
7924 | |
7925 if (line_start_cache_start (w) > point) | |
7926 { | |
665 | 7927 Charbpos from, to; |
428 | 7928 |
7929 from = find_next_newline_no_quit (b, point, -1); | |
7930 if (from >= BUF_ZV (b)) | |
7931 { | |
7932 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7933 from = to; | |
7934 to = BUF_ZV (b); | |
7935 } | |
7936 else | |
7937 to = find_next_newline_no_quit (b, from, win_char_height); | |
7938 | |
7939 update_line_start_cache (w, from, to, point, 0); | |
7940 } | |
7941 | |
7942 loop = 0; | |
7943 while (line_start_cache_end (w) < point | |
7944 && (loop < cache_adjustment || min_past == -1)) | |
7945 { | |
665 | 7946 Charbpos from, to; |
428 | 7947 |
7948 to = line_start_cache_end (w); | |
7949 if (to >= BUF_ZV (b)) | |
7950 break; | |
7951 | |
7952 from = line_start_cache_end (w); | |
7953 to = find_next_newline_no_quit (b, from, win_char_height); | |
7954 | |
7955 update_line_start_cache (w, from, to, point, 0); | |
7956 loop++; | |
7957 } | |
7958 | |
7959 if (line_start_cache_end (w) < point) | |
7960 { | |
665 | 7961 Charbpos from, to; |
428 | 7962 |
7963 from = find_next_newline_no_quit (b, point, -1); | |
7964 if (from >= BUF_ZV (b)) | |
7965 { | |
7966 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7967 from = to; | |
7968 to = BUF_ZV (b); | |
7969 } | |
7970 else | |
7971 to = find_next_newline_no_quit (b, from, win_char_height); | |
7972 | |
7973 update_line_start_cache (w, from, to, point, 0); | |
7974 } | |
7975 } | |
7976 | |
7977 assert (Dynarr_length (cache)); | |
7978 | |
7979 if (min_past == -1) | |
7980 min_past = 0; | |
7981 | |
7982 /* This could happen if the buffer is narrowed. */ | |
7983 if (line_start_cache_start (w) > point | |
7984 || line_start_cache_end (w) < point) | |
7985 { | |
7986 w->line_cache_validation_override--; | |
7987 return -1; | |
7988 } | |
7989 | |
7990 find_point_loop: | |
7991 | |
7992 top = Dynarr_length (cache) - 1; | |
7993 bottom = 0; | |
7994 | |
7995 while (1) | |
7996 { | |
647 | 7997 int new_pos; |
665 | 7998 Charbpos start, end; |
428 | 7999 |
8000 pos = (bottom + top + 1) >> 1; | |
8001 start = Dynarr_atp (cache, pos)->start; | |
8002 end = Dynarr_atp (cache, pos)->end; | |
8003 | |
8004 if (point >= start && point <= end) | |
8005 { | |
8006 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b)) | |
8007 { | |
665 | 8008 Charbpos from = |
428 | 8009 find_next_newline_no_quit (b, line_start_cache_start (w), |
8010 -min_past - 1); | |
665 | 8011 Charbpos to = line_start_cache_end (w); |
428 | 8012 |
8013 update_line_start_cache (w, from, to, point, 0); | |
8014 goto find_point_loop; | |
8015 } | |
8016 else if ((Dynarr_length (cache) - pos - 1) < min_past | |
8017 && line_start_cache_end (w) < BUF_ZV (b)) | |
8018 { | |
665 | 8019 Charbpos from = line_start_cache_end (w); |
8020 Charbpos to = find_next_newline_no_quit (b, from, | |
428 | 8021 (min_past |
8022 ? min_past | |
8023 : 1)); | |
8024 | |
8025 update_line_start_cache (w, from, to, point, 0); | |
8026 goto find_point_loop; | |
8027 } | |
8028 else | |
8029 { | |
8030 w->line_cache_validation_override--; | |
8031 return pos; | |
8032 } | |
8033 } | |
8034 else if (point > end) | |
8035 bottom = pos + 1; | |
8036 else if (point < start) | |
8037 top = pos - 1; | |
8038 else | |
2500 | 8039 ABORT (); |
428 | 8040 |
8041 new_pos = (bottom + top + 1) >> 1; | |
8042 if (pos == new_pos) | |
8043 { | |
8044 w->line_cache_validation_override--; | |
8045 return -1; | |
8046 } | |
8047 } | |
8048 } | |
8049 | |
8050 /* Return a boolean indicating if POINT would be visible in window W | |
1708 | 8051 if display of the window was to begin at STARTP. If PARTIALLY is |
8052 zero, then if POINT has fewer visible pixels than the window clip, | |
8053 0 is returned; otherwise, 1 is returned if POINT has any visible | |
8054 pixels. */ | |
428 | 8055 int |
1708 | 8056 point_would_be_visible (struct window *w, Charbpos startp, Charbpos point, |
8057 int partially) | |
428 | 8058 { |
8059 struct buffer *b = XBUFFER (w->buffer); | |
5198 | 8060 int pixpos = -WINDOW_TEXT_TOP_CLIP (w); |
428 | 8061 int bottom = WINDOW_TEXT_HEIGHT (w); |
8062 int start_elt; | |
8063 | |
8064 /* If point is before the intended start it obviously can't be visible. */ | |
8065 if (point < startp) | |
8066 return 0; | |
8067 | |
8068 /* If point or start are not in the accessible buffer range, then | |
8069 fail. */ | |
8070 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b) | |
8071 || point < BUF_BEGV (b) || point > BUF_ZV (b)) | |
8072 return 0; | |
8073 | |
8074 validate_line_start_cache (w); | |
8075 w->line_cache_validation_override++; | |
8076 | |
8077 start_elt = point_in_line_start_cache (w, startp, 0); | |
8078 if (start_elt == -1) | |
8079 { | |
8080 w->line_cache_validation_override--; | |
8081 return 0; | |
8082 } | |
8083 | |
8084 assert (line_start_cache_start (w) <= startp | |
8085 && line_start_cache_end (w) >= startp); | |
8086 | |
8087 while (1) | |
8088 { | |
8089 int height; | |
8090 | |
8091 /* Expand the cache if necessary. */ | |
8092 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8093 { | |
665 | 8094 Charbpos old_startp = |
428 | 8095 Dynarr_atp (w->line_start_cache, start_elt - 1)->start; |
8096 | |
8097 start_elt = point_in_line_start_cache (w, old_startp, | |
8098 window_char_height (w, 0)); | |
8099 | |
8100 /* We've already actually processed old_startp, so increment | |
4187 | 8101 immediately. */ |
428 | 8102 start_elt++; |
8103 | |
8104 /* If this happens we didn't add any extra elements. Bummer. */ | |
8105 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8106 { | |
8107 w->line_cache_validation_override--; | |
8108 return 0; | |
8109 } | |
8110 } | |
8111 | |
8112 height = Dynarr_atp (w->line_start_cache, start_elt)->height; | |
8113 | |
8114 if (pixpos + height > bottom) | |
8115 { | |
1708 | 8116 if (bottom - pixpos < (partially ? 0 : VERTICAL_CLIP (w, 0))) |
428 | 8117 { |
8118 w->line_cache_validation_override--; | |
8119 return 0; | |
8120 } | |
8121 } | |
8122 | |
8123 pixpos += height; | |
8124 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end) | |
8125 { | |
8126 w->line_cache_validation_override--; | |
8127 return 1; | |
8128 } | |
8129 | |
8130 start_elt++; | |
8131 } | |
8132 } | |
8133 | |
8134 /* For the given window W, if display starts at STARTP, what will be | |
8135 the buffer position at the beginning or end of the last line | |
8136 displayed. The end of the last line is also know as the window end | |
8137 position. | |
8138 | |
442 | 8139 WARNING: It is possible that redisplay failed to layout any lines for the |
8140 windows. Under normal circumstances this is rare. However it seems that it | |
8141 does occur in the following situation: A mouse event has come in and we | |
8142 need to compute its location in a window. That code (in | |
8143 pixel_to_glyph_translation) already can handle 0 as an error return value. | |
8144 | |
428 | 8145 #### With a little work this could probably be reworked as just a |
8146 call to start_with_line_at_pixpos. */ | |
8147 | |
665 | 8148 static Charbpos |
8149 start_end_of_last_line (struct window *w, Charbpos startp, int end, | |
4187 | 8150 int may_error) |
428 | 8151 { |
8152 struct buffer *b = XBUFFER (w->buffer); | |
8153 line_start_cache_dynarr *cache = w->line_start_cache; | |
8154 int pixpos = 0; | |
8155 int bottom = WINDOW_TEXT_HEIGHT (w); | |
665 | 8156 Charbpos cur_start; |
428 | 8157 int start_elt; |
8158 | |
8159 validate_line_start_cache (w); | |
8160 w->line_cache_validation_override++; | |
8161 | |
8162 if (startp < BUF_BEGV (b)) | |
8163 startp = BUF_BEGV (b); | |
8164 else if (startp > BUF_ZV (b)) | |
8165 startp = BUF_ZV (b); | |
8166 cur_start = startp; | |
8167 | |
8168 start_elt = point_in_line_start_cache (w, cur_start, 0); | |
8169 if (start_elt == -1) | |
442 | 8170 return may_error ? 0 : startp; |
428 | 8171 |
8172 while (1) | |
8173 { | |
8174 int height = Dynarr_atp (cache, start_elt)->height; | |
8175 | |
8176 cur_start = Dynarr_atp (cache, start_elt)->start; | |
8177 | |
8178 if (pixpos + height > bottom) | |
8179 { | |
8180 /* Adjust for any possible clip. */ | |
8181 if (bottom - pixpos < VERTICAL_CLIP (w, 0)) | |
8182 start_elt--; | |
8183 | |
8184 if (start_elt < 0) | |
8185 { | |
8186 w->line_cache_validation_override--; | |
8187 if (end) | |
8188 return BUF_ZV (b); | |
8189 else | |
8190 return BUF_BEGV (b); | |
8191 } | |
8192 else | |
8193 { | |
8194 w->line_cache_validation_override--; | |
8195 if (end) | |
8196 return Dynarr_atp (cache, start_elt)->end; | |
8197 else | |
8198 return Dynarr_atp (cache, start_elt)->start; | |
8199 } | |
8200 } | |
8201 | |
8202 pixpos += height; | |
8203 start_elt++; | |
8204 if (start_elt == Dynarr_length (cache)) | |
8205 { | |
665 | 8206 Charbpos from = line_start_cache_end (w); |
428 | 8207 int win_char_height = window_char_height (w, 0); |
665 | 8208 Charbpos to = find_next_newline_no_quit (b, from, |
428 | 8209 (win_char_height |
8210 ? win_char_height | |
8211 : 1)); | |
8212 | |
8213 /* We've hit the end of the bottom so that's what it is. */ | |
8214 if (from >= BUF_ZV (b)) | |
8215 { | |
8216 w->line_cache_validation_override--; | |
8217 return BUF_ZV (b); | |
8218 } | |
8219 | |
8220 update_line_start_cache (w, from, to, BUF_PT (b), 0); | |
8221 | |
8222 /* Updating the cache invalidates any current indexes. */ | |
8223 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1; | |
8224 } | |
8225 } | |
8226 } | |
8227 | |
8228 /* For the given window W, if display starts at STARTP, what will be | |
8229 the buffer position at the beginning of the last line displayed. */ | |
8230 | |
665 | 8231 Charbpos |
8232 start_of_last_line (struct window *w, Charbpos startp) | |
428 | 8233 { |
442 | 8234 return start_end_of_last_line (w, startp, 0 , 0); |
428 | 8235 } |
8236 | |
8237 /* For the given window W, if display starts at STARTP, what will be | |
8238 the buffer position at the end of the last line displayed. This is | |
8239 also know as the window end position. */ | |
8240 | |
665 | 8241 Charbpos |
8242 end_of_last_line (struct window *w, Charbpos startp) | |
428 | 8243 { |
442 | 8244 return start_end_of_last_line (w, startp, 1, 0); |
428 | 8245 } |
8246 | |
665 | 8247 static Charbpos |
8248 end_of_last_line_may_error (struct window *w, Charbpos startp) | |
442 | 8249 { |
8250 return start_end_of_last_line (w, startp, 1, 1); | |
8251 } | |
8252 | |
8253 | |
428 | 8254 /* For window W, what does the starting position have to be so that |
8255 the line containing POINT will cover pixel position PIXPOS. */ | |
8256 | |
665 | 8257 Charbpos |
8258 start_with_line_at_pixpos (struct window *w, Charbpos point, int pixpos) | |
428 | 8259 { |
8260 struct buffer *b = XBUFFER (w->buffer); | |
8261 int cur_elt; | |
665 | 8262 Charbpos cur_pos, prev_pos = point; |
428 | 8263 int point_line_height; |
8264 int pixheight = pixpos - WINDOW_TEXT_TOP (w); | |
8265 | |
8266 validate_line_start_cache (w); | |
8267 w->line_cache_validation_override++; | |
8268 | |
8269 cur_elt = point_in_line_start_cache (w, point, 0); | |
8270 /* #### See comment in update_line_start_cache about big minibuffers. */ | |
8271 if (cur_elt < 0) | |
8272 { | |
8273 w->line_cache_validation_override--; | |
8274 return point; | |
8275 } | |
8276 | |
8277 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8278 | |
8279 while (1) | |
8280 { | |
8281 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8282 | |
8283 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8284 | |
8285 /* Do not take into account the value of vertical_clip here. | |
4187 | 8286 That is the responsibility of the calling functions. */ |
428 | 8287 if (pixheight < 0) |
8288 { | |
8289 w->line_cache_validation_override--; | |
5783
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8290 /* I see no reason why cur_pos can't be before BEGV |
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8291 here, so check for it. It's not clear to me whether |
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8292 prev_pos could be before BEGV, so check that as well. */ |
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8293 if (-pixheight > point_line_height) |
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8294 /* We can't make the target line cover pixpos, so put it |
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8295 above pixpos. That way it will at least be visible. */ |
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8296 return (prev_pos <= BUF_BEGV (b)) ? BUF_BEGV (b) : prev_pos; |
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8297 else |
cfc6a8c144f1
Don't return a Charbpos before visible region, start_with_line_at_pixpos()
Aidan Kehoe <kehoea@parhasard.net>
parents:
5688
diff
changeset
|
8298 return (cur_pos <= BUF_BEGV (b)) ? BUF_BEGV (b) : cur_pos; |
428 | 8299 } |
8300 | |
8301 cur_elt--; | |
8302 while (cur_elt < 0) | |
8303 { | |
665 | 8304 Charbpos from, to; |
428 | 8305 int win_char_height; |
8306 | |
8307 if (cur_pos <= BUF_BEGV (b)) | |
8308 { | |
8309 w->line_cache_validation_override--; | |
8310 return BUF_BEGV (b); | |
8311 } | |
8312 | |
8313 win_char_height = window_char_height (w, 0); | |
8314 if (!win_char_height) | |
8315 win_char_height = 1; | |
8316 | |
8317 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); | |
8318 to = line_start_cache_end (w); | |
8319 update_line_start_cache (w, from, to, point, 0); | |
8320 | |
8321 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; | |
8322 assert (cur_elt >= -1); | |
8323 /* This used to be cur_elt>=0 under the assumption that if | |
8324 point is in the top line and not at BUF_BEGV, then | |
434 | 8325 setting the window_start to a newline before the start of |
428 | 8326 the first line will always cause scrolling. |
8327 | |
8328 However in my (jv) opinion this is wrong. That new line | |
8329 can be hidden in various ways: invisible extents, an | |
8330 explicit window-start not at a newline character etc. | |
8331 The existence of those are indeed known to create crashes | |
8332 on that assert. So we have no option but to continue the | |
8333 search if we found point at the top of the line_start_cache | |
8334 again. */ | |
4967 | 8335 cur_pos = Dynarr_begin (w->line_start_cache)->start; |
428 | 8336 } |
8337 prev_pos = cur_pos; | |
8338 } | |
8339 } | |
8340 | |
8341 /* For window W, what does the starting position have to be so that | |
8342 the line containing point is on display line LINE. If LINE is | |
8343 positive it is considered to be the number of lines from the top of | |
8344 the window (0 is the top line). If it is negative the number is | |
8345 considered to be the number of lines from the bottom (-1 is the | |
8346 bottom line). */ | |
8347 | |
665 | 8348 Charbpos |
8349 start_with_point_on_display_line (struct window *w, Charbpos point, int line) | |
428 | 8350 { |
8351 validate_line_start_cache (w); | |
8352 w->line_cache_validation_override++; | |
8353 | |
8354 if (line >= 0) | |
8355 { | |
8356 int cur_elt = point_in_line_start_cache (w, point, line); | |
8357 | |
8358 if (cur_elt - line < 0) | |
8359 cur_elt = 0; /* Hit the top */ | |
8360 else | |
8361 cur_elt -= line; | |
8362 | |
8363 w->line_cache_validation_override--; | |
8364 return Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8365 } | |
8366 else | |
8367 { | |
8368 /* The calculated value of pixpos is correct for the bottom line | |
4187 | 8369 or what we want when line is -1. Therefore we subtract one |
8370 because we have already handled one line. */ | |
428 | 8371 int new_line = -line - 1; |
8372 int cur_elt = point_in_line_start_cache (w, point, new_line); | |
8373 int pixpos = WINDOW_TEXT_BOTTOM (w); | |
665 | 8374 Charbpos retval, search_point; |
428 | 8375 |
8376 /* If scroll_on_clipped_lines is false, the last "visible" line of | |
4187 | 8377 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1. |
8378 If s_o_c_l is true, then we don't want to count a clipped | |
8379 line, so back up from the bottom by the height of the line | |
8380 containing point. */ | |
428 | 8381 if (scroll_on_clipped_lines) |
8382 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8383 else | |
8384 pixpos -= 1; | |
8385 | |
8386 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache)) | |
8387 { | |
8388 /* Hit the bottom of the buffer. */ | |
8389 int adjustment = | |
8390 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1; | |
8391 Lisp_Object window; | |
8392 int defheight; | |
8393 | |
793 | 8394 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
|
8395 default_face_width_and_height (window, 0, &defheight); |
428 | 8396 |
8397 cur_elt = Dynarr_length (w->line_start_cache) - 1; | |
8398 | |
8399 pixpos -= (adjustment * defheight); | |
8400 if (pixpos < WINDOW_TEXT_TOP (w)) | |
8401 pixpos = WINDOW_TEXT_TOP (w); | |
8402 } | |
8403 else | |
8404 cur_elt = cur_elt + new_line; | |
8405 | |
8406 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8407 | |
8408 retval = start_with_line_at_pixpos (w, search_point, pixpos); | |
8409 w->line_cache_validation_override--; | |
8410 return retval; | |
8411 } | |
8412 } | |
8413 | |
8414 /* This is used to speed up vertical scrolling by caching the known | |
8415 buffer starting positions for display lines. This allows the | |
8416 scrolling routines to avoid costly calls to regenerate_window. If | |
8417 NO_REGEN is true then it will only add the values in the DESIRED | |
8418 display structs which are in the given range. | |
8419 | |
8420 Note also that the FROM/TO values are minimums. It is possible | |
8421 that this function will actually add information outside of the | |
8422 lines containing those positions. This can't hurt but it could | |
8423 possibly help. | |
8424 | |
8425 #### We currently force the cache to have only 1 contiguous region. | |
8426 It might help to make the cache a dynarr of caches so that we can | |
8427 cover more areas. This might, however, turn out to be a lot of | |
8428 overhead for too little gain. */ | |
8429 | |
8430 static void | |
665 | 8431 update_line_start_cache (struct window *w, Charbpos from, Charbpos to, |
8432 Charbpos point, int no_regen) | |
428 | 8433 { |
8434 struct buffer *b = XBUFFER (w->buffer); | |
8435 line_start_cache_dynarr *cache = w->line_start_cache; | |
665 | 8436 Charbpos low_bound, high_bound; |
428 | 8437 |
8438 validate_line_start_cache (w); | |
8439 w->line_cache_validation_override++; | |
8440 | |
8441 if (from < BUF_BEGV (b)) | |
8442 from = BUF_BEGV (b); | |
8443 if (to > BUF_ZV (b)) | |
8444 to = BUF_ZV (b); | |
8445 | |
8446 if (from > to) | |
8447 { | |
8448 w->line_cache_validation_override--; | |
8449 return; | |
8450 } | |
8451 | |
8452 if (Dynarr_length (cache)) | |
8453 { | |
8454 low_bound = line_start_cache_start (w); | |
8455 high_bound = line_start_cache_end (w); | |
8456 | |
8457 /* Check to see if the desired range is already in the cache. */ | |
8458 if (from >= low_bound && to <= high_bound) | |
8459 { | |
8460 w->line_cache_validation_override--; | |
8461 return; | |
8462 } | |
8463 | |
8464 /* Check to make sure that the desired range is adjacent to the | |
8465 current cache. If not, invalidate the cache. */ | |
8466 if (to < low_bound || from > high_bound) | |
8467 { | |
8468 Dynarr_reset (cache); | |
8469 low_bound = high_bound = -1; | |
8470 } | |
8471 } | |
8472 else | |
8473 { | |
8474 low_bound = high_bound = -1; | |
8475 } | |
8476 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5486
diff
changeset
|
8477 w->line_cache_last_updated = make_fixnum (BUF_MODIFF (b)); |
428 | 8478 |
8479 /* This could be integrated into the next two sections, but it is easier | |
8480 to follow what's going on by having it separate. */ | |
8481 if (no_regen) | |
8482 { | |
665 | 8483 Charbpos start, end; |
428 | 8484 |
8485 update_internal_cache_list (w, DESIRED_DISP); | |
8486 if (!Dynarr_length (internal_cache)) | |
8487 { | |
8488 w->line_cache_validation_override--; | |
8489 return; | |
8490 } | |
8491 | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8492 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
|
8493 end = Dynarr_lastp (internal_cache)->end; |
428 | 8494 |
8495 /* We aren't allowed to generate additional information to fill in | |
4187 | 8496 gaps, so if the DESIRED structs don't overlap the cache, reset the |
8497 cache. */ | |
428 | 8498 if (Dynarr_length (cache)) |
8499 { | |
8500 if (end < low_bound || start > high_bound) | |
8501 Dynarr_reset (cache); | |
8502 | |
8503 /* #### What should really happen if what we are doing is | |
4187 | 8504 extending a line (the last line)? */ |
428 | 8505 if (Dynarr_length (cache) == 1 |
8506 && Dynarr_length (internal_cache) == 1) | |
8507 Dynarr_reset (cache); | |
8508 } | |
8509 | |
8510 if (!Dynarr_length (cache)) | |
8511 { | |
4967 | 8512 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8513 Dynarr_length (internal_cache)); |
8514 w->line_cache_validation_override--; | |
8515 return; | |
8516 } | |
8517 | |
8518 /* An extra check just in case the calling function didn't pass in | |
4187 | 8519 the bounds of the DESIRED structs in the first place. */ |
428 | 8520 if (start >= low_bound && end <= high_bound) |
8521 { | |
8522 w->line_cache_validation_override--; | |
8523 return; | |
8524 } | |
8525 | |
8526 /* At this point we know that the internal cache partially overlaps | |
4187 | 8527 the main cache. */ |
428 | 8528 if (start < low_bound) |
8529 { | |
8530 int ic_elt = Dynarr_length (internal_cache) - 1; | |
8531 while (ic_elt >= 0) | |
8532 { | |
8533 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound) | |
8534 break; | |
8535 else | |
8536 ic_elt--; | |
8537 } | |
8538 | |
8539 if (!(ic_elt >= 0)) | |
8540 { | |
8541 Dynarr_reset (cache); | |
4967 | 8542 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8543 Dynarr_length (internal_cache)); |
8544 w->line_cache_validation_override--; | |
8545 return; | |
8546 } | |
8547 | |
5038 | 8548 Dynarr_prepend_many (cache, Dynarr_begin (internal_cache), |
428 | 8549 ic_elt + 1); |
8550 } | |
8551 | |
8552 if (end > high_bound) | |
8553 { | |
8554 int ic_elt = 0; | |
8555 | |
8556 while (ic_elt < Dynarr_length (internal_cache)) | |
8557 { | |
8558 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound) | |
8559 break; | |
8560 else | |
8561 ic_elt++; | |
8562 } | |
8563 | |
8564 if (!(ic_elt < Dynarr_length (internal_cache))) | |
8565 { | |
8566 Dynarr_reset (cache); | |
4967 | 8567 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8568 Dynarr_length (internal_cache)); |
8569 w->line_cache_validation_override--; | |
8570 return; | |
8571 } | |
8572 | |
8573 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), | |
8574 Dynarr_length (internal_cache) - ic_elt); | |
8575 } | |
8576 | |
8577 w->line_cache_validation_override--; | |
8578 return; | |
8579 } | |
8580 | |
8581 if (!Dynarr_length (cache) || from < low_bound) | |
8582 { | |
665 | 8583 Charbpos startp = find_next_newline_no_quit (b, from, -1); |
428 | 8584 int marker = 0; |
8585 int old_lb = low_bound; | |
8586 | |
8587 while (startp < old_lb || low_bound == -1) | |
8588 { | |
8589 int ic_elt; | |
4187 | 8590 Charbpos new_startp; |
428 | 8591 |
8592 regenerate_window (w, startp, point, CMOTION_DISP); | |
8593 update_internal_cache_list (w, CMOTION_DISP); | |
8594 | |
8595 /* If this assert is triggered then regenerate_window failed | |
4187 | 8596 to layout a single line. This is not possible since we |
442 | 8597 force at least a single line to be layout for CMOTION_DISP */ |
8598 assert (Dynarr_length (internal_cache)); | |
4967 | 8599 assert (startp == Dynarr_begin (internal_cache)->start); |
428 | 8600 |
8601 ic_elt = Dynarr_length (internal_cache) - 1; | |
8602 if (low_bound != -1) | |
8603 { | |
8604 while (ic_elt >= 0) | |
8605 { | |
8606 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb) | |
8607 break; | |
8608 else | |
8609 ic_elt--; | |
8610 } | |
8611 } | |
8612 assert (ic_elt >= 0); | |
8613 | |
8614 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1; | |
8615 | |
4187 | 8616 /* |
8617 * Handle invisible text properly: | |
8618 * If the last line we're inserting has the same end as the | |
8619 * line before which it will be added, merge the two lines. | |
8620 */ | |
8621 if (Dynarr_length (cache) && | |
8622 Dynarr_atp (internal_cache, ic_elt)->end == | |
8623 Dynarr_atp (cache, marker)->end) | |
8624 { | |
8625 Dynarr_atp (cache, marker)->start | |
8626 = Dynarr_atp (internal_cache, ic_elt)->start; | |
8627 Dynarr_atp (cache, marker)->height | |
8628 = Dynarr_atp (internal_cache, ic_elt)->height; | |
8629 ic_elt--; | |
8630 } | |
8631 | |
8632 if (ic_elt >= 0) /* we still have lines to add.. */ | |
8633 { | |
4967 | 8634 Dynarr_insert_many (cache, Dynarr_begin (internal_cache), |
4187 | 8635 ic_elt + 1, marker); |
8636 marker += (ic_elt + 1); | |
8637 } | |
428 | 8638 |
8639 if (startp < low_bound || low_bound == -1) | |
8640 low_bound = startp; | |
8641 startp = new_startp; | |
8642 if (startp > BUF_ZV (b)) | |
8643 { | |
8644 w->line_cache_validation_override--; | |
8645 return; | |
8646 } | |
8647 } | |
8648 } | |
8649 | |
8650 assert (Dynarr_length (cache)); | |
8651 assert (from >= low_bound); | |
8652 | |
8653 /* Readjust the high_bound to account for any changes made while | |
8654 correcting the low_bound. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8655 high_bound = Dynarr_lastp (cache)->end; |
428 | 8656 |
8657 if (to > high_bound) | |
8658 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8659 Charbpos startp = Dynarr_lastp (cache)->end + 1; |
428 | 8660 |
8661 do | |
8662 { | |
8663 regenerate_window (w, startp, point, CMOTION_DISP); | |
8664 update_internal_cache_list (w, CMOTION_DISP); | |
8665 | |
8666 /* See comment above about regenerate_window failing. */ | |
8667 assert (Dynarr_length (internal_cache)); | |
8668 | |
4967 | 8669 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8670 Dynarr_length (internal_cache)); |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8671 high_bound = Dynarr_lastp (cache)->end; |
428 | 8672 startp = high_bound + 1; |
8673 } | |
8674 while (to > high_bound); | |
8675 } | |
8676 | |
8677 w->line_cache_validation_override--; | |
8678 assert (to <= high_bound); | |
8679 } | |
8680 | |
8681 | |
8682 /* Given x and y coordinates in characters, relative to a window, | |
8683 return the pixel location corresponding to those coordinates. The | |
8684 pixel location returned is the center of the given character | |
8685 position. The pixel values are generated relative to the window, | |
8686 not the frame. | |
8687 | |
8688 The modeline is considered to be part of the window. */ | |
8689 | |
8690 void | |
8691 glyph_to_pixel_translation (struct window *w, int char_x, int char_y, | |
8692 int *pix_x, int *pix_y) | |
8693 { | |
8694 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
8695 int num_disp_lines, modeline; | |
8696 Lisp_Object window; | |
8697 int defheight, defwidth; | |
8698 | |
793 | 8699 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
|
8700 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 8701 |
8702 /* If we get a bogus value indicating somewhere above or to the left of | |
8703 the window, use the first window line or character position | |
8704 instead. */ | |
8705 if (char_y < 0) | |
8706 char_y = 0; | |
8707 if (char_x < 0) | |
8708 char_x = 0; | |
8709 | |
8710 num_disp_lines = Dynarr_length (dla); | |
8711 modeline = 0; | |
8712 if (num_disp_lines) | |
8713 { | |
4967 | 8714 if (Dynarr_begin (dla)->modeline) |
428 | 8715 { |
8716 num_disp_lines--; | |
8717 modeline = 1; | |
8718 } | |
8719 } | |
8720 | |
8721 /* First check if the y position intersects the display lines. */ | |
8722 if (char_y < num_disp_lines) | |
8723 { | |
8724 struct display_line *dl = Dynarr_atp (dla, char_y + modeline); | |
8725 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
8726 | |
8727 *pix_y = (dl->ypos - dl->ascent + | |
647 | 8728 ((dl->ascent + dl->descent - dl->clip) >> 1)); |
428 | 8729 |
8730 if (char_x < Dynarr_length (db->runes)) | |
8731 { | |
8732 struct rune *rb = Dynarr_atp (db->runes, char_x); | |
8733 | |
8734 *pix_x = rb->xpos + (rb->width >> 1); | |
8735 } | |
8736 else | |
8737 { | |
8738 int last_rune = Dynarr_length (db->runes) - 1; | |
8739 struct rune *rb = Dynarr_atp (db->runes, last_rune); | |
8740 | |
8741 char_x -= last_rune; | |
8742 | |
8743 *pix_x = rb->xpos + rb->width; | |
8744 *pix_x += ((char_x - 1) * defwidth); | |
8745 *pix_x += (defwidth >> 1); | |
8746 } | |
8747 } | |
8748 else | |
8749 { | |
8750 /* It didn't intersect, so extrapolate. #### For now, we include the | |
8751 modeline in this since we don't have true character positions in | |
8752 it. */ | |
8753 | |
8754 if (!Dynarr_length (w->face_cachels)) | |
8755 reset_face_cachels (w); | |
8756 | |
8757 char_y -= num_disp_lines; | |
8758 | |
8759 if (Dynarr_length (dla)) | |
8760 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8761 struct display_line *dl = Dynarr_lastp (dla); |
428 | 8762 *pix_y = dl->ypos + dl->descent - dl->clip; |
8763 } | |
8764 else | |
8765 *pix_y = WINDOW_TEXT_TOP (w); | |
8766 | |
8767 *pix_y += (char_y * defheight); | |
8768 *pix_y += (defheight >> 1); | |
8769 | |
8770 *pix_x = WINDOW_TEXT_LEFT (w); | |
8771 /* Don't adjust by one because this is still the unadjusted value. */ | |
8772 *pix_x += (char_x * defwidth); | |
8773 *pix_x += (defwidth >> 1); | |
8774 } | |
8775 | |
8776 if (*pix_x > w->pixel_left + w->pixel_width) | |
8777 *pix_x = w->pixel_left + w->pixel_width; | |
8778 if (*pix_y > w->pixel_top + w->pixel_height) | |
8779 *pix_y = w->pixel_top + w->pixel_height; | |
8780 | |
8781 *pix_x -= w->pixel_left; | |
8782 *pix_y -= w->pixel_top; | |
8783 } | |
8784 | |
8785 /* Given a display line and a position, determine if there is a glyph | |
8786 there and return information about it if there is. */ | |
8787 | |
8788 static void | |
8789 get_position_object (struct display_line *dl, Lisp_Object *obj1, | |
8790 Lisp_Object *obj2, int x_coord, int *low_x_coord, | |
8791 int *high_x_coord) | |
8792 { | |
8793 struct display_block *db; | |
8794 int elt; | |
8795 int block = | |
8796 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0); | |
8797 | |
8798 /* We use get_next_display_block to get the actual display block | |
8799 that would be displayed at x_coord. */ | |
8800 | |
8801 if (block == NO_BLOCK) | |
8802 return; | |
8803 else | |
8804 db = Dynarr_atp (dl->display_blocks, block); | |
8805 | |
8806 for (elt = 0; elt < Dynarr_length (db->runes); elt++) | |
8807 { | |
8808 struct rune *rb = Dynarr_atp (db->runes, elt); | |
8809 | |
8810 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) | |
8811 { | |
8812 if (rb->type == RUNE_DGLYPH) | |
8813 { | |
8814 *obj1 = rb->object.dglyph.glyph; | |
8815 *obj2 = rb->object.dglyph.extent; | |
8816 } | |
8817 else | |
8818 { | |
8819 *obj1 = Qnil; | |
8820 *obj2 = Qnil; | |
8821 } | |
8822 | |
8823 if (low_x_coord) | |
8824 *low_x_coord = rb->xpos; | |
8825 if (high_x_coord) | |
8826 *high_x_coord = rb->xpos + rb->width; | |
8827 | |
8828 return; | |
8829 } | |
8830 } | |
8831 } | |
8832 | |
8833 #define UPDATE_CACHE_RETURN \ | |
8834 do { \ | |
8835 d->pixel_to_glyph_cache.valid = 1; \ | |
8836 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \ | |
8837 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \ | |
8838 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \ | |
8839 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \ | |
8840 d->pixel_to_glyph_cache.frame = f; \ | |
8841 d->pixel_to_glyph_cache.col = *col; \ | |
8842 d->pixel_to_glyph_cache.row = *row; \ | |
8843 d->pixel_to_glyph_cache.obj_x = *obj_x; \ | |
8844 d->pixel_to_glyph_cache.obj_y = *obj_y; \ | |
8845 d->pixel_to_glyph_cache.w = *w; \ | |
5090 | 8846 d->pixel_to_glyph_cache.charpos = *charpos; \ |
428 | 8847 d->pixel_to_glyph_cache.closest = *closest; \ |
8848 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \ | |
8849 d->pixel_to_glyph_cache.obj1 = *obj1; \ | |
8850 d->pixel_to_glyph_cache.obj2 = *obj2; \ | |
8851 d->pixel_to_glyph_cache.retval = position; \ | |
8852 RETURN_SANS_WARNINGS position; \ | |
8853 } while (0) | |
8854 | |
8855 /* Given x and y coordinates in pixels relative to a frame, return | |
8856 information about what is located under those coordinates. | |
8857 | |
8858 The return value will be one of: | |
8859 | |
8860 OVER_TOOLBAR: over one of the 4 frame toolbars | |
8861 OVER_MODELINE: over a modeline | |
8862 OVER_BORDER: over an internal border | |
5090 | 8863 OVER_V_DIVIDER: over a vertical divider between windows (used as a |
8864 grab bar for resizing) | |
428 | 8865 OVER_NOTHING: over the text area, but not over text |
8866 OVER_OUTSIDE: outside of the frame border | |
8867 OVER_TEXT: over text in the text area | |
8868 | |
5090 | 8869 #### GEOM! We need to also have an OVER_GUTTER, OVER_SCROLLBAR and |
8870 OVER_DEAD_BOX. | |
8871 | |
428 | 8872 OBJ1 is one of |
8873 | |
8874 -- a toolbar button | |
8875 -- a glyph | |
8876 -- nil if the coordinates are not over a glyph or a toolbar button. | |
8877 | |
8878 OBJ2 is one of | |
8879 | |
8880 -- an extent, if the coordinates are over a glyph in the text area | |
8881 -- nil otherwise. | |
8882 | |
8883 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the | |
8884 equivalent coordinates relative to the upper-left corner of the glyph. | |
8885 | |
8886 If the coordinates are over a character, OBJ_X and OBJ_Y give the | |
8887 equivalent coordinates relative to the upper-left corner of the character. | |
8888 | |
8889 Otherwise, OBJ_X and OBJ_Y are undefined. | |
8890 */ | |
8891 | |
8892 int | |
8893 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, | |
8894 int *col, int *row, int *obj_x, int *obj_y, | |
826 | 8895 struct window **w, Charbpos *charpos, |
665 | 8896 Charbpos *closest, Charcount *modeline_closest, |
428 | 8897 Lisp_Object *obj1, Lisp_Object *obj2) |
8898 { | |
8899 struct device *d; | |
8900 struct pixel_to_glyph_translation_cache *cache; | |
8901 Lisp_Object window; | |
8902 int frm_left, frm_right, frm_top, frm_bottom; | |
8903 int low_x_coord, high_x_coord, low_y_coord, high_y_coord; | |
8904 int position = OVER_NOTHING; | |
8905 int device_check_failed = 0; | |
8906 display_line_dynarr *dla; | |
8907 | |
8908 /* This is a safety valve in case this got called with a frame in | |
8909 the middle of being deleted. */ | |
8910 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device))) | |
8911 { | |
8912 device_check_failed = 1; | |
8913 d = NULL, cache = NULL; /* Warning suppression */ | |
8914 } | |
8915 else | |
8916 { | |
8917 d = XDEVICE (f->device); | |
8918 cache = &d->pixel_to_glyph_cache; | |
8919 } | |
8920 | |
8921 if (!device_check_failed | |
8922 && cache->valid | |
8923 && cache->frame == f | |
8924 && cache->low_x_coord <= x_coord | |
8925 && cache->high_x_coord > x_coord | |
8926 && cache->low_y_coord <= y_coord | |
8927 && cache->high_y_coord > y_coord) | |
8928 { | |
8929 *col = cache->col; | |
8930 *row = cache->row; | |
8931 *obj_x = cache->obj_x; | |
8932 *obj_y = cache->obj_y; | |
8933 *w = cache->w; | |
826 | 8934 *charpos = cache->charpos; |
428 | 8935 *closest = cache->closest; |
8936 *modeline_closest = cache->modeline_closest; | |
8937 *obj1 = cache->obj1; | |
8938 *obj2 = cache->obj2; | |
8939 | |
8940 return cache->retval; | |
8941 } | |
8942 else | |
8943 { | |
8944 *col = 0; | |
8945 *row = 0; | |
8946 *obj_x = 0; | |
8947 *obj_y = 0; | |
8948 *w = 0; | |
826 | 8949 *charpos = 0; |
428 | 8950 *closest = 0; |
8951 *modeline_closest = -1; | |
8952 *obj1 = Qnil; | |
8953 *obj2 = Qnil; | |
8954 | |
8955 low_x_coord = x_coord; | |
8956 high_x_coord = x_coord + 1; | |
8957 low_y_coord = y_coord; | |
8958 high_y_coord = y_coord + 1; | |
8959 } | |
8960 | |
8961 if (device_check_failed) | |
8962 return OVER_NOTHING; | |
8963 | |
5090 | 8964 /* #### GEOM! The gutter is just inside of this. We should also have an |
8965 OVER_GUTTER return value to indicate that we're over a gutter. See | |
8966 above. */ | |
8967 frm_left = FRAME_LEFT_INTERNAL_BORDER_END (f); | |
8968 frm_right = FRAME_RIGHT_INTERNAL_BORDER_START (f); | |
8969 frm_top = FRAME_TOP_INTERNAL_BORDER_END (f); | |
8970 frm_bottom = FRAME_BOTTOM_INTERNAL_BORDER_START (f); | |
428 | 8971 |
8972 /* Check if the mouse is outside of the text area actually used by | |
8973 redisplay. */ | |
8974 if (y_coord < frm_top) | |
8975 { | |
5090 | 8976 if (y_coord >= FRAME_TOP_INTERNAL_BORDER_START (f)) |
8977 { | |
8978 low_y_coord = FRAME_TOP_INTERNAL_BORDER_START (f); | |
428 | 8979 high_y_coord = frm_top; |
8980 position = OVER_BORDER; | |
8981 } | |
8982 else if (y_coord >= 0) | |
8983 { | |
8984 low_y_coord = 0; | |
5090 | 8985 high_y_coord = FRAME_TOP_INTERNAL_BORDER_START (f); |
428 | 8986 position = OVER_TOOLBAR; |
8987 } | |
8988 else | |
8989 { | |
8990 low_y_coord = y_coord; | |
8991 high_y_coord = 0; | |
8992 position = OVER_OUTSIDE; | |
8993 } | |
8994 } | |
8995 else if (y_coord >= frm_bottom) | |
8996 { | |
5090 | 8997 if (y_coord < FRAME_BOTTOM_INTERNAL_BORDER_END (f)) |
428 | 8998 { |
8999 low_y_coord = frm_bottom; | |
5090 | 9000 high_y_coord = FRAME_BOTTOM_INTERNAL_BORDER_END (f); |
428 | 9001 position = OVER_BORDER; |
9002 } | |
9003 else if (y_coord < FRAME_PIXHEIGHT (f)) | |
9004 { | |
5090 | 9005 low_y_coord = FRAME_BOTTOM_INTERNAL_BORDER_END (f); |
428 | 9006 high_y_coord = FRAME_PIXHEIGHT (f); |
9007 position = OVER_TOOLBAR; | |
9008 } | |
9009 else | |
9010 { | |
9011 low_y_coord = FRAME_PIXHEIGHT (f); | |
9012 high_y_coord = y_coord; | |
9013 position = OVER_OUTSIDE; | |
9014 } | |
9015 } | |
9016 | |
9017 if (position != OVER_TOOLBAR && position != OVER_BORDER) | |
9018 { | |
9019 if (x_coord < frm_left) | |
9020 { | |
5090 | 9021 if (x_coord >= FRAME_LEFT_INTERNAL_BORDER_START (f)) |
9022 { | |
9023 low_x_coord = FRAME_LEFT_INTERNAL_BORDER_START (f); | |
428 | 9024 high_x_coord = frm_left; |
9025 position = OVER_BORDER; | |
9026 } | |
9027 else if (x_coord >= 0) | |
9028 { | |
9029 low_x_coord = 0; | |
5090 | 9030 high_x_coord = FRAME_LEFT_INTERNAL_BORDER_START (f); |
428 | 9031 position = OVER_TOOLBAR; |
9032 } | |
9033 else | |
9034 { | |
9035 low_x_coord = x_coord; | |
9036 high_x_coord = 0; | |
9037 position = OVER_OUTSIDE; | |
9038 } | |
9039 } | |
9040 else if (x_coord >= frm_right) | |
9041 { | |
5090 | 9042 if (x_coord < FRAME_RIGHT_INTERNAL_BORDER_END (f)) |
428 | 9043 { |
9044 low_x_coord = frm_right; | |
5090 | 9045 high_x_coord = FRAME_RIGHT_INTERNAL_BORDER_END (f); |
428 | 9046 position = OVER_BORDER; |
9047 } | |
9048 else if (x_coord < FRAME_PIXWIDTH (f)) | |
9049 { | |
5090 | 9050 low_x_coord = FRAME_RIGHT_INTERNAL_BORDER_END (f); |
428 | 9051 high_x_coord = FRAME_PIXWIDTH (f); |
9052 position = OVER_TOOLBAR; | |
9053 } | |
9054 else | |
9055 { | |
9056 low_x_coord = FRAME_PIXWIDTH (f); | |
9057 high_x_coord = x_coord; | |
9058 position = OVER_OUTSIDE; | |
9059 } | |
9060 } | |
9061 } | |
9062 | |
9063 #ifdef HAVE_TOOLBARS | |
9064 if (position == OVER_TOOLBAR) | |
9065 { | |
9066 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord); | |
9067 *obj2 = Qnil; | |
9068 *w = 0; | |
9069 UPDATE_CACHE_RETURN; | |
9070 } | |
9071 #endif /* HAVE_TOOLBARS */ | |
9072 | |
9073 /* We still have to return the window the pointer is next to and its | |
9074 relative y position even if it is outside the x boundary. */ | |
9075 if (x_coord < frm_left) | |
9076 x_coord = frm_left; | |
9077 else if (x_coord > frm_right) | |
9078 x_coord = frm_right; | |
9079 | |
9080 /* Same in reverse. */ | |
9081 if (y_coord < frm_top) | |
9082 y_coord = frm_top; | |
9083 else if (y_coord > frm_bottom) | |
9084 y_coord = frm_bottom; | |
9085 | |
9086 /* Find what window the given coordinates are actually in. */ | |
9087 window = f->root_window; | |
9088 *w = find_window_by_pixel_pos (x_coord, y_coord, window); | |
9089 | |
9090 /* If we didn't find a window, we're done. */ | |
9091 if (!*w) | |
9092 { | |
9093 UPDATE_CACHE_RETURN; | |
9094 } | |
9095 else if (position != OVER_NOTHING) | |
9096 { | |
9097 *closest = 0; | |
9098 *modeline_closest = -1; | |
9099 | |
9100 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) | |
9101 { | |
9102 *w = 0; | |
9103 UPDATE_CACHE_RETURN; | |
9104 } | |
9105 } | |
9106 | |
9107 /* Check if the window is a minibuffer but isn't active. */ | |
9108 if (MINI_WINDOW_P (*w) && !minibuf_level) | |
9109 { | |
9110 /* Must reset the window value since some callers will ignore | |
4187 | 9111 the return value if it is set. */ |
428 | 9112 *w = 0; |
9113 UPDATE_CACHE_RETURN; | |
9114 } | |
9115 | |
9116 /* See if the point is over window vertical divider */ | |
9117 if (window_needs_vertical_divider (*w)) | |
9118 { | |
9119 int div_x_high = WINDOW_RIGHT (*w); | |
9120 int div_x_low = div_x_high - window_divider_width (*w); | |
9121 int div_y_high = WINDOW_BOTTOM (*w); | |
9122 int div_y_low = WINDOW_TOP (*w); | |
9123 | |
9124 if (div_x_low < x_coord && x_coord <= div_x_high && | |
9125 div_y_low < y_coord && y_coord <= div_y_high) | |
9126 { | |
9127 low_x_coord = div_x_low; | |
9128 high_x_coord = div_x_high; | |
9129 low_y_coord = div_y_low; | |
9130 high_y_coord = div_y_high; | |
9131 position = OVER_V_DIVIDER; | |
9132 UPDATE_CACHE_RETURN; | |
9133 } | |
9134 } | |
9135 | |
9136 dla = window_display_lines (*w, CURRENT_DISP); | |
9137 | |
9138 for (*row = 0; *row < Dynarr_length (dla); (*row)++) | |
9139 { | |
9140 int really_over_nothing = 0; | |
9141 struct display_line *dl = Dynarr_atp (dla, *row); | |
9142 | |
9143 if ((int) (dl->ypos - dl->ascent) <= y_coord | |
9144 && y_coord <= (int) (dl->ypos + dl->descent)) | |
9145 { | |
9146 int check_margin_glyphs = 0; | |
9147 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
9148 struct rune *rb = 0; | |
9149 | |
9150 if (x_coord < dl->bounds.left_white | |
9151 || x_coord >= dl->bounds.right_white) | |
9152 check_margin_glyphs = 1; | |
9153 | |
9154 low_y_coord = dl->ypos - dl->ascent; | |
9155 high_y_coord = dl->ypos + dl->descent + 1; | |
9156 | |
9157 if (position == OVER_BORDER | |
9158 || position == OVER_OUTSIDE | |
9159 || check_margin_glyphs) | |
9160 { | |
9161 int x_check, left_bound; | |
9162 | |
9163 if (check_margin_glyphs) | |
9164 { | |
9165 x_check = x_coord; | |
9166 left_bound = dl->bounds.left_white; | |
9167 } | |
9168 else | |
9169 { | |
9170 x_check = high_x_coord; | |
9171 left_bound = frm_left; | |
9172 } | |
9173 | |
9174 if (Dynarr_length (db->runes)) | |
9175 { | |
9176 if (x_check <= left_bound) | |
9177 { | |
9178 if (dl->modeline) | |
4967 | 9179 *modeline_closest = Dynarr_begin (db->runes)->charpos; |
428 | 9180 else |
4967 | 9181 *closest = Dynarr_begin (db->runes)->charpos; |
428 | 9182 } |
9183 else | |
9184 { | |
9185 if (dl->modeline) | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9186 *modeline_closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9187 else |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9188 *closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9189 } |
9190 | |
9191 if (dl->modeline) | |
9192 *modeline_closest += dl->offset; | |
9193 else | |
9194 *closest += dl->offset; | |
9195 } | |
9196 else | |
9197 { | |
9198 /* #### What should be here. */ | |
9199 if (dl->modeline) | |
9200 *modeline_closest = 0; | |
9201 else | |
9202 *closest = 0; | |
9203 } | |
9204 | |
9205 if (check_margin_glyphs) | |
9206 { | |
9207 if (x_coord < dl->bounds.left_in | |
9208 || x_coord >= dl->bounds.right_in) | |
9209 { | |
9210 /* If we are over the outside margins then we | |
4187 | 9211 know the loop over the text block isn't going |
9212 to accomplish anything. So we go ahead and | |
9213 set what information we can right here and | |
9214 return. */ | |
428 | 9215 (*row)--; |
9216 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9217 get_position_object (dl, obj1, obj2, x_coord, | |
9218 &low_x_coord, &high_x_coord); | |
9219 | |
9220 UPDATE_CACHE_RETURN; | |
9221 } | |
9222 } | |
9223 else | |
9224 UPDATE_CACHE_RETURN; | |
9225 } | |
9226 | |
9227 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++) | |
9228 { | |
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9229 if (*col == Dynarr_length (db->runes)) |
428 | 9230 { |
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9231 /* 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
|
9232 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
|
9233 character. */ |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9234 if (dl->modeline) |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9235 *modeline_closest = dl->end_charpos + dl->offset; |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9236 else |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9237 *closest = dl->end_charpos + dl->offset; |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9238 |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9239 if (check_margin_glyphs) |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9240 get_position_object (dl, obj1, obj2, x_coord, |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9241 &low_x_coord, &high_x_coord); |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9242 |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9243 UPDATE_CACHE_RETURN; |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9244 } |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9245 |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9246 rb = Dynarr_atp (db->runes, *col); |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9247 |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9248 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
|
9249 { |
428 | 9250 |
826 | 9251 *charpos = rb->charpos + dl->offset; |
428 | 9252 low_x_coord = rb->xpos; |
9253 high_x_coord = rb->xpos + rb->width; | |
9254 | |
9255 if (rb->type == RUNE_DGLYPH) | |
9256 { | |
9257 int elt = *col + 1; | |
9258 | |
9259 /* Find the first character after the glyph. */ | |
9260 while (elt < Dynarr_length (db->runes)) | |
9261 { | |
9262 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH) | |
9263 { | |
9264 if (dl->modeline) | |
9265 *modeline_closest = | |
826 | 9266 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9267 dl->offset); |
9268 else | |
9269 *closest = | |
826 | 9270 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9271 dl->offset); |
9272 break; | |
9273 } | |
9274 | |
9275 elt++; | |
9276 } | |
9277 | |
9278 /* In this case we failed to find a non-glyph | |
4187 | 9279 character so we return the last position |
9280 displayed on the line. */ | |
428 | 9281 if (elt == Dynarr_length (db->runes)) |
9282 { | |
9283 if (dl->modeline) | |
826 | 9284 *modeline_closest = dl->end_charpos + dl->offset; |
428 | 9285 else |
826 | 9286 *closest = dl->end_charpos + dl->offset; |
428 | 9287 really_over_nothing = 1; |
9288 } | |
9289 } | |
9290 else | |
9291 { | |
9292 if (dl->modeline) | |
826 | 9293 *modeline_closest = rb->charpos + dl->offset; |
428 | 9294 else |
826 | 9295 *closest = rb->charpos + dl->offset; |
428 | 9296 } |
9297 | |
9298 if (dl->modeline) | |
9299 { | |
9300 *row = window_displayed_height (*w); | |
9301 | |
9302 if (position == OVER_NOTHING) | |
9303 position = OVER_MODELINE; | |
9304 | |
9305 if (rb->type == RUNE_DGLYPH) | |
9306 { | |
9307 *obj1 = rb->object.dglyph.glyph; | |
9308 *obj2 = rb->object.dglyph.extent; | |
9309 } | |
9310 else if (rb->type == RUNE_CHAR) | |
9311 { | |
9312 *obj1 = Qnil; | |
9313 *obj2 = Qnil; | |
9314 } | |
9315 else | |
9316 { | |
9317 *obj1 = Qnil; | |
9318 *obj2 = Qnil; | |
9319 } | |
9320 | |
9321 UPDATE_CACHE_RETURN; | |
9322 } | |
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9323 else if (rb->type == RUNE_CHAR |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9324 && rb->object.chr.ch == '\n') |
428 | 9325 { |
9326 (*row)--; | |
9327 /* At this point we may have glyphs in the right | |
4187 | 9328 inside margin. */ |
428 | 9329 if (check_margin_glyphs) |
9330 get_position_object (dl, obj1, obj2, x_coord, | |
9331 &low_x_coord, &high_x_coord); | |
9332 UPDATE_CACHE_RETURN; | |
9333 } | |
9334 else | |
9335 { | |
9336 (*row)--; | |
9337 if (rb->type == RUNE_DGLYPH) | |
9338 { | |
9339 *obj1 = rb->object.dglyph.glyph; | |
9340 *obj2 = rb->object.dglyph.extent; | |
9341 } | |
9342 else if (rb->type == RUNE_CHAR) | |
9343 { | |
9344 *obj1 = Qnil; | |
9345 *obj2 = Qnil; | |
9346 } | |
9347 else | |
9348 { | |
9349 *obj1 = Qnil; | |
9350 *obj2 = Qnil; | |
9351 } | |
9352 | |
9353 *obj_x = x_coord - rb->xpos; | |
9354 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9355 | |
9356 /* At this point we may have glyphs in the left | |
4187 | 9357 inside margin. */ |
428 | 9358 if (check_margin_glyphs) |
9359 get_position_object (dl, obj1, obj2, x_coord, 0, 0); | |
9360 | |
9361 if (position == OVER_NOTHING && !really_over_nothing) | |
9362 position = OVER_TEXT; | |
9363 | |
9364 UPDATE_CACHE_RETURN; | |
9365 } | |
9366 } | |
9367 } | |
9368 } | |
9369 } | |
9370 | |
9371 *row = Dynarr_length (dla) - 1; | |
9372 if (FRAME_WIN_P (f)) | |
9373 { | |
9374 int bot_elt = Dynarr_length (dla) - 1; | |
9375 | |
9376 if (bot_elt >= 0) | |
9377 { | |
9378 struct display_line *dl = Dynarr_atp (dla, bot_elt); | |
9379 int adj_area = y_coord - (dl->ypos + dl->descent); | |
9380 Lisp_Object lwin; | |
9381 int defheight; | |
9382 | |
793 | 9383 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
|
9384 default_face_width_and_height (lwin, 0, &defheight); |
428 | 9385 |
9386 *row += (adj_area / defheight); | |
9387 } | |
9388 } | |
9389 | |
9390 /* #### This should be checked out some more to determine what | |
9391 should really be going on. */ | |
9392 if (!MARKERP ((*w)->start[CURRENT_DISP])) | |
9393 *closest = 0; | |
9394 else | |
442 | 9395 *closest = end_of_last_line_may_error (*w, |
428 | 9396 marker_position ((*w)->start[CURRENT_DISP])); |
9397 *col = 0; | |
9398 UPDATE_CACHE_RETURN; | |
9399 } | |
9400 #undef UPDATE_CACHE_RETURN | |
9401 | |
9402 | |
9403 /***************************************************************************/ | |
9404 /* */ | |
9405 /* Lisp functions */ | |
9406 /* */ | |
9407 /***************************************************************************/ | |
9408 | |
9409 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /* | |
9410 Ensure that all minibuffers are correctly showing the echo area. | |
9411 */ | |
9412 ()) | |
9413 { | |
9414 Lisp_Object devcons, concons; | |
9415 | |
1318 | 9416 if (in_display) |
9417 return Qnil; | |
9418 | |
428 | 9419 DEVICE_LOOP_NO_BREAK (devcons, concons) |
9420 { | |
9421 struct device *d = XDEVICE (XCAR (devcons)); | |
9422 Lisp_Object frmcons; | |
9423 | |
1279 | 9424 if (DEVICE_STREAM_P (d)) |
9425 continue; | |
9426 | |
428 | 9427 DEVICE_FRAME_LOOP (frmcons, d) |
9428 { | |
9429 struct frame *f = XFRAME (XCAR (frmcons)); | |
853 | 9430 int depth; |
428 | 9431 |
9432 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) | |
9433 { | |
9434 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); | |
442 | 9435 |
9436 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
9437 | |
428 | 9438 /* |
9439 * If the frame size has changed, there may be random | |
9440 * chud on the screen left from previous messages | |
9441 * because redisplay_frame hasn't been called yet. | |
9442 * Clear the screen to get rid of the potential mess. | |
9443 */ | |
9444 if (f->echo_area_garbaged) | |
9445 { | |
442 | 9446 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 9447 f->echo_area_garbaged = 0; |
9448 } | |
853 | 9449 depth = enter_redisplay_critical_section (); |
428 | 9450 redisplay_window (window, 0); |
853 | 9451 exit_redisplay_critical_section (depth); |
442 | 9452 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 9453 } |
9454 } | |
9455 } | |
9456 | |
9457 return Qnil; | |
9458 } | |
9459 | |
9460 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /* | |
9461 Clear frame FRAME and output again what is supposed to appear on it. | |
9462 FRAME defaults to the selected frame if omitted. | |
9463 Normally, redisplay is preempted as normal if input arrives. However, | |
9464 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9465 input and is guaranteed to proceed to completion. | |
9466 */ | |
9467 (frame, no_preempt)) | |
9468 { | |
9469 struct frame *f = decode_frame (frame); | |
9470 int count = specpdl_depth (); | |
9471 | |
9472 if (!NILP (no_preempt)) | |
853 | 9473 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9474 |
9475 f->clear = 1; | |
9476 redisplay_frame (f, 1); | |
9477 | |
442 | 9478 /* See the comment in Fredisplay_frame. */ |
9479 RESET_CHANGED_SET_FLAGS; | |
9480 | |
771 | 9481 return unbind_to (count); |
428 | 9482 } |
9483 | |
9484 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* | |
9485 Ensure that FRAME's contents are correctly displayed. | |
9486 This differs from `redraw-frame' in that it only redraws what needs to | |
9487 be updated, as opposed to unconditionally clearing and redrawing | |
9488 the frame. | |
9489 FRAME defaults to the selected frame if omitted. | |
9490 Normally, redisplay is preempted as normal if input arrives. However, | |
9491 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9492 input and is guaranteed to proceed to completion. | |
9493 */ | |
9494 (frame, no_preempt)) | |
9495 { | |
9496 struct frame *f = decode_frame (frame); | |
9497 int count = specpdl_depth (); | |
9498 | |
9499 if (!NILP (no_preempt)) | |
853 | 9500 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9501 |
9502 redisplay_frame (f, 1); | |
9503 | |
442 | 9504 /* If we don't reset the global redisplay flags here, subsequent |
9505 changes to the display will not get registered by redisplay | |
9506 because it thinks it already has registered changes. If you | |
9507 really knew what you were doing you could confuse redisplay by | |
9508 calling Fredisplay_frame while updating another frame. We assume | |
9509 that if you know what you are doing you will not be that | |
9510 stupid. */ | |
9511 RESET_CHANGED_SET_FLAGS; | |
9512 | |
771 | 9513 return unbind_to (count); |
428 | 9514 } |
9515 | |
9516 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* | |
9517 Clear device DEVICE and output again what is supposed to appear on it. | |
9518 DEVICE defaults to the selected device if omitted. | |
9519 Normally, redisplay is preempted as normal if input arrives. However, | |
9520 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9521 input and is guaranteed to proceed to completion. | |
9522 */ | |
9523 (device, no_preempt)) | |
9524 { | |
9525 struct device *d = decode_device (device); | |
9526 Lisp_Object frmcons; | |
9527 int count = specpdl_depth (); | |
9528 | |
9529 if (!NILP (no_preempt)) | |
853 | 9530 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9531 |
9532 DEVICE_FRAME_LOOP (frmcons, d) | |
9533 { | |
9534 XFRAME (XCAR (frmcons))->clear = 1; | |
9535 } | |
440 | 9536 redisplay_device (d, 0); |
428 | 9537 |
442 | 9538 /* See the comment in Fredisplay_frame. */ |
9539 RESET_CHANGED_SET_FLAGS; | |
9540 | |
771 | 9541 return unbind_to (count); |
428 | 9542 } |
9543 | |
9544 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* | |
9545 Ensure that DEVICE's contents are correctly displayed. | |
9546 This differs from `redraw-device' in that it only redraws what needs to | |
9547 be updated, as opposed to unconditionally clearing and redrawing | |
9548 the device. | |
9549 DEVICE defaults to the selected device if omitted. | |
9550 Normally, redisplay is preempted as normal if input arrives. However, | |
9551 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9552 input and is guaranteed to proceed to completion. | |
853 | 9553 |
9554 Note: If you simply want everything redisplayed, the current idiom is | |
9555 `(sit-for 0)'. | |
428 | 9556 */ |
9557 (device, no_preempt)) | |
9558 { | |
9559 struct device *d = decode_device (device); | |
9560 int count = specpdl_depth (); | |
9561 | |
9562 if (!NILP (no_preempt)) | |
853 | 9563 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9564 |
440 | 9565 redisplay_device (d, 0); |
428 | 9566 |
442 | 9567 /* See the comment in Fredisplay_frame. */ |
9568 RESET_CHANGED_SET_FLAGS; | |
9569 | |
771 | 9570 return unbind_to (count); |
428 | 9571 } |
9572 | |
9573 /* Big lie. Big lie. This will force all modelines to be updated | |
9574 regardless if the all flag is set or not. It remains in existence | |
9575 solely for backwards compatibility. */ | |
9576 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /* | |
9577 Force the modeline of the current buffer to be redisplayed. | |
9578 With optional non-nil ALL, force redisplay of all modelines. | |
9579 */ | |
2286 | 9580 (UNUSED (all))) |
428 | 9581 { |
9582 MARK_MODELINE_CHANGED; | |
9583 return Qnil; | |
9584 } | |
9585 | |
9586 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /* | |
9587 Force an immediate update of the cursor on FRAME. | |
9588 FRAME defaults to the selected frame if omitted. | |
9589 */ | |
9590 (frame)) | |
9591 { | |
1279 | 9592 struct frame *f = decode_frame (frame); |
9593 | |
9594 if (!FRAME_STREAM_P (f)) | |
9595 redisplay_redraw_cursor (f, 1); | |
428 | 9596 return Qnil; |
9597 } | |
9598 | |
9599 | |
9600 /***************************************************************************/ | |
9601 /* */ | |
872 | 9602 /* Change flags */ |
428 | 9603 /* */ |
9604 /***************************************************************************/ | |
9605 | |
9606 static void | |
2286 | 9607 margin_width_changed_in_frame (Lisp_Object UNUSED (specifier), |
9608 struct frame *UNUSED (f), | |
9609 Lisp_Object UNUSED (oldval)) | |
428 | 9610 { |
9611 /* Nothing to be done? */ | |
9612 } | |
9613 | |
9614 int | |
2286 | 9615 redisplay_variable_changed (Lisp_Object UNUSED (sym), |
9616 Lisp_Object *UNUSED (val), | |
9617 Lisp_Object UNUSED (in_object), | |
9618 int UNUSED (flags)) | |
428 | 9619 { |
9620 /* #### clip_changed should really be renamed something like | |
9621 global_redisplay_change. */ | |
9622 MARK_CLIP_CHANGED; | |
9623 return 0; | |
9624 } | |
9625 | |
9626 /* This is called if the built-in glyphs have their properties | |
9627 changed. */ | |
9628 void | |
2286 | 9629 redisplay_glyph_changed (Lisp_Object UNUSED (glyph), |
9630 Lisp_Object UNUSED (property), Lisp_Object locale) | |
428 | 9631 { |
9632 if (WINDOWP (locale)) | |
9633 { | |
9634 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale)))); | |
9635 } | |
9636 else if (FRAMEP (locale)) | |
9637 { | |
9638 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale)); | |
9639 } | |
9640 else if (DEVICEP (locale)) | |
9641 { | |
9642 Lisp_Object frmcons; | |
9643 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale)) | |
9644 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9645 } | |
9646 else if (CONSOLEP (locale)) | |
9647 { | |
9648 Lisp_Object frmcons, devcons; | |
9649 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale)) | |
9650 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9651 } | |
9652 else /* global or buffer */ | |
9653 { | |
9654 Lisp_Object frmcons, devcons, concons; | |
9655 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
9656 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9657 } | |
9658 } | |
9659 | |
9660 static void | |
2286 | 9661 text_cursor_visible_p_changed (Lisp_Object UNUSED (specifier), |
9662 struct window *w, Lisp_Object UNUSED (oldval)) | |
428 | 9663 { |
9664 if (XFRAME (w->frame)->init_finished) | |
9665 Fforce_cursor_redisplay (w->frame); | |
9666 } | |
9667 | |
872 | 9668 void |
9669 mark_buffers_changed (void) | |
9670 { | |
9671 MARK_TYPE_CHANGED (buffers); | |
9672 } | |
9673 | |
9674 void | |
9675 mark_clip_changed (void) | |
9676 { | |
9677 MARK_TYPE_CHANGED (clip); | |
9678 } | |
9679 | |
9680 void | |
9681 mark_extents_changed (void) | |
9682 { | |
9683 MARK_TYPE_CHANGED (extents); | |
9684 } | |
9685 | |
9686 void | |
9687 mark_icon_changed (void) | |
9688 { | |
9689 MARK_TYPE_CHANGED (icon); | |
9690 } | |
9691 | |
9692 void | |
9693 mark_menubar_changed (void) | |
9694 { | |
9695 MARK_TYPE_CHANGED (menubar); | |
9696 } | |
9697 | |
9698 void | |
9699 mark_modeline_changed (void) | |
9700 { | |
9701 MARK_TYPE_CHANGED (modeline); | |
9702 } | |
9703 | |
9704 void | |
9705 mark_point_changed (void) | |
9706 { | |
9707 MARK_TYPE_CHANGED (point); | |
9708 } | |
9709 | |
9710 void | |
9711 mark_toolbar_changed (void) | |
9712 { | |
9713 MARK_TYPE_CHANGED (toolbar); | |
9714 } | |
9715 | |
9716 void | |
9717 mark_gutter_changed (void) | |
9718 { | |
9719 MARK_TYPE_CHANGED (gutter); | |
9720 } | |
9721 | |
9722 void | |
9723 mark_glyphs_changed (void) | |
9724 { | |
9725 MARK_TYPE_CHANGED (glyphs); | |
9726 } | |
9727 | |
9728 void | |
9729 mark_subwindows_changed (void) | |
9730 { | |
9731 MARK_TYPE_CHANGED (subwindows); | |
9732 } | |
9733 | |
9734 void | |
9735 mark_subwindows_state_changed (void) | |
9736 { | |
9737 MARK_TYPE_CHANGED (subwindows_state); | |
9738 } | |
9739 | |
428 | 9740 #ifdef MEMORY_USAGE_STATS |
9741 | |
9742 | |
9743 /***************************************************************************/ | |
9744 /* */ | |
9745 /* memory usage computation */ | |
9746 /* */ | |
9747 /***************************************************************************/ | |
9748 | |
9749 static int | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9750 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
|
9751 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9752 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9753 } |
9754 | |
9755 static int | |
9756 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
|
9757 struct usage_stats *ustats) |
428 | 9758 { |
9759 int total, i; | |
9760 | |
9761 if (!dyn) | |
9762 return 0; | |
9763 | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9764 total = Dynarr_memory_usage (dyn, ustats); |
428 | 9765 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
|
9766 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ustats); |
428 | 9767 |
9768 return total; | |
9769 } | |
9770 | |
9771 static int | |
9772 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
|
9773 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
|
9774 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9775 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9776 } |
9777 | |
9778 int | |
9779 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
|
9780 struct usage_stats *ustats) |
428 | 9781 { |
9782 int total, i; | |
9783 | |
9784 if (!dyn) | |
9785 return 0; | |
9786 | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9787 total = Dynarr_memory_usage (dyn, ustats); |
428 | 9788 for (i = 0; i < Dynarr_largest (dyn); i++) |
9789 { | |
9790 struct display_line *dl = &Dynarr_at (dyn, i); | |
5198 | 9791 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
|
9792 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
|
9793 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ustats); |
428 | 9794 } |
9795 | |
9796 return total; | |
9797 } | |
9798 | |
9799 int | |
9800 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
|
9801 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
|
9802 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9803 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9804 } |
9805 | |
9806 #endif /* MEMORY_USAGE_STATS */ | |
9807 | |
1204 | 9808 #ifdef ERROR_CHECK_DISPLAY |
9809 | |
800 | 9810 static int |
2286 | 9811 sledgehammer_check_redisplay_structs_1 (struct window *w, |
9812 void *UNUSED (closure)) | |
800 | 9813 { |
9814 int i, j; | |
9815 display_line_dynarr *dl; | |
9816 | |
9817 dl = window_display_lines (w, CURRENT_DISP); | |
4187 | 9818 |
800 | 9819 for (i = 0; i < Dynarr_largest (dl); i++) |
9820 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9821 assert (Dynarr_atp (dl, i)->display_blocks != | |
9822 Dynarr_atp (dl, j)->display_blocks); | |
9823 | |
9824 dl = window_display_lines (w, DESIRED_DISP); | |
9825 | |
9826 for (i = 0; i < Dynarr_largest (dl); i++) | |
9827 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9828 assert (Dynarr_atp (dl, i)->display_blocks != | |
9829 Dynarr_atp (dl, j)->display_blocks); | |
9830 | |
9831 return 0; | |
9832 } | |
9833 | |
9834 static void | |
9835 sledgehammer_check_redisplay_structs (void) | |
9836 { | |
9837 map_windows (0, sledgehammer_check_redisplay_structs_1, NULL); | |
9838 } | |
9839 | |
1204 | 9840 #endif /* ERROR_CHECK_DISPLAY */ |
9841 | |
428 | 9842 |
9843 /***************************************************************************/ | |
9844 /* */ | |
9845 /* initialization */ | |
9846 /* */ | |
9847 /***************************************************************************/ | |
9848 | |
9849 void | |
9850 init_redisplay (void) | |
9851 { | |
9852 disable_preemption = 0; | |
9853 preemption_count = 0; | |
9854 | |
9855 #ifndef PDUMP | |
9856 if (!initialized) | |
9857 #endif | |
9858 { | |
440 | 9859 if (!cmotion_display_lines) |
9860 cmotion_display_lines = Dynarr_new (display_line); | |
867 | 9861 if (!mode_spec_ibyte_string) |
9862 mode_spec_ibyte_string = Dynarr_new (Ibyte); | |
440 | 9863 if (!formatted_string_extent_dynarr) |
9864 formatted_string_extent_dynarr = Dynarr_new (EXTENT); | |
9865 if (!formatted_string_extent_start_dynarr) | |
9866 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); | |
9867 if (!formatted_string_extent_end_dynarr) | |
9868 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); | |
9869 if (!internal_cache) | |
9870 internal_cache = Dynarr_new (line_start_cache); | |
428 | 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 if (!initialized) |
428 | 9874 return; |
9875 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9876 if (noninteractive) |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9877 { |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9878 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
|
9879 return; |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9880 } |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9881 |
428 | 9882 /* If the user wants to use a window system, we shouldn't bother |
9883 initializing the terminal. This is especially important when the | |
9884 terminal is so dumb that emacs gives up before and doesn't bother | |
9885 using the window system. | |
9886 | |
9887 If the DISPLAY environment variable is set, try to use X, and die | |
9888 with an error message if that doesn't work. */ | |
9889 | |
9890 #ifdef HAVE_X_WINDOWS | |
9891 if (!strcmp (display_use, "x")) | |
9892 { | |
9893 /* Some stuff checks this way early. */ | |
9894 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
|
9895 Vinitial_device_type = Qx; |
428 | 9896 return; |
9897 } | |
9898 #endif /* HAVE_X_WINDOWS */ | |
9899 | |
462 | 9900 #ifdef HAVE_GTK |
9901 if (!strcmp (display_use, "gtk")) | |
9902 { | |
9903 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
|
9904 Vinitial_device_type = Qgtk; |
462 | 9905 return; |
9906 } | |
9907 #endif | |
9908 | |
428 | 9909 #ifdef HAVE_MS_WINDOWS |
9910 if (!strcmp (display_use, "mswindows")) | |
9911 { | |
9912 /* Some stuff checks this way early. */ | |
9913 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
|
9914 Vinitial_device_type = Qmswindows; |
428 | 9915 return; |
9916 } | |
9917 #endif /* HAVE_MS_WINDOWS */ | |
9918 | |
9919 #ifdef HAVE_TTY | |
9920 /* If no window system has been specified, try to use the terminal. */ | |
9921 if (!isatty (0)) | |
9922 { | |
9923 stderr_out ("XEmacs: standard input is not a tty\n"); | |
9924 exit (1); | |
9925 } | |
9926 | |
9927 /* Look at the TERM variable */ | |
771 | 9928 if (!egetenv ("TERM")) |
428 | 9929 { |
9930 stderr_out ("Please set the environment variable TERM; see tset(1).\n"); | |
9931 exit (1); | |
9932 } | |
9933 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9934 Vinitial_device_type = Qtty; |
428 | 9935 return; |
9936 #else /* not HAVE_TTY */ | |
9937 /* No DISPLAY specified, and no TTY support. */ | |
9938 stderr_out ("XEmacs: Cannot open display.\n\ | |
9939 Please set the environmental variable DISPLAY to an appropriate value.\n"); | |
9940 exit (1); | |
9941 #endif | |
9942 /* Unreached. */ | |
9943 } | |
9944 | |
9945 void | |
9946 syms_of_redisplay (void) | |
9947 { | |
563 | 9948 DEFSYMBOL (Qcursor_in_echo_area); |
9949 DEFSYMBOL (Qdisplay_warning_buffer); | |
9950 DEFSYMBOL (Qbar_cursor); | |
9951 DEFSYMBOL (Qtop_bottom); | |
9952 DEFSYMBOL (Qbuffer_list_changed_hook); | |
428 | 9953 |
9954 DEFSUBR (Fredisplay_echo_area); | |
9955 DEFSUBR (Fredraw_frame); | |
9956 DEFSUBR (Fredisplay_frame); | |
9957 DEFSUBR (Fredraw_device); | |
9958 DEFSUBR (Fredisplay_device); | |
9959 DEFSUBR (Fredraw_modeline); | |
9960 DEFSUBR (Fforce_cursor_redisplay); | |
9961 } | |
9962 | |
9963 void | |
9964 vars_of_redisplay (void) | |
9965 { | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
9966 QSin_redisplay = build_defer_string ("(in redisplay)"); |
1292 | 9967 staticpro (&QSin_redisplay); |
428 | 9968 |
1318 | 9969 Vpost_redisplay_actions = Qnil; |
9970 staticpro (&Vpost_redisplay_actions); | |
9971 | |
428 | 9972 #if 0 |
9973 staticpro (&last_arrow_position); | |
9974 staticpro (&last_arrow_string); | |
9975 last_arrow_position = Qnil; | |
9976 last_arrow_string = Qnil; | |
9977 #endif /* 0 */ | |
9978 | |
9979 /* #### Probably temporary */ | |
9980 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* | |
9981 \(Temporary) Setting this will impact the performance of the internal | |
9982 line start cache. | |
9983 */ ); | |
9984 cache_adjustment = 2; | |
9985 | |
1268 | 9986 DEFVAR_INT ("maximum-preempts", &max_preempts /* |
9987 Maximum number of times redisplay can be preempted by user input. | |
9988 */ ); | |
9989 max_preempts = INIT_MAX_PREEMPTS; | |
9990 | |
428 | 9991 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /* |
9992 Minimum pixel height for clipped bottom display line. | |
9993 A clipped line shorter than this won't be displayed. | |
9994 */ , | |
9995 redisplay_variable_changed); | |
9996 vertical_clip = 5; | |
9997 | |
9998 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /* | |
9999 Minimum visible area for clipped glyphs at right boundary. | |
10000 Clipped glyphs shorter than this won't be displayed. | |
10001 Only pixmap glyph instances are currently allowed to be clipped. | |
10002 */ , | |
10003 redisplay_variable_changed); | |
10004 horizontal_clip = 5; | |
10005 | |
10006 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /* | |
10007 String displayed by modeline-format's "%m" specification. | |
10008 */ ); | |
10009 Vglobal_mode_string = Qnil; | |
10010 | |
10011 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /* | |
10012 Marker for where to display an arrow on top of the buffer text. | |
10013 This must be the beginning of a line in order to work. | |
10014 See also `overlay-arrow-string'. | |
10015 */ , | |
10016 redisplay_variable_changed); | |
10017 Voverlay_arrow_position = Qnil; | |
10018 | |
10019 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* | |
442 | 10020 String or glyph to display as an arrow. See also `overlay-arrow-position'. |
444 | 10021 \(Note that despite the name of this variable, it can be set to a glyph as |
442 | 10022 well as a string.) |
428 | 10023 */ , |
10024 redisplay_variable_changed); | |
10025 Voverlay_arrow_string = Qnil; | |
10026 | |
10027 DEFVAR_INT ("scroll-step", &scroll_step /* | |
10028 *The number of lines to try scrolling a window by when point moves out. | |
10029 If that fails to bring point back on frame, point is centered instead. | |
10030 If this is zero, point is always centered after it moves off screen. | |
10031 */ ); | |
10032 scroll_step = 0; | |
10033 | |
10034 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /* | |
10035 *Scroll up to this many lines, to bring point back on screen. | |
10036 */ ); | |
10037 scroll_conservatively = 0; | |
10038 | |
10039 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows", | |
10040 &truncate_partial_width_windows /* | |
10041 *Non-nil means truncate lines in all windows less than full frame wide. | |
10042 */ , | |
10043 redisplay_variable_changed); | |
10044 truncate_partial_width_windows = 1; | |
10045 | |
442 | 10046 DEFVAR_LISP ("visible-bell", &Vvisible_bell /* |
10047 *Non-nil substitutes a visual signal for the audible bell. | |
10048 | |
10049 Default behavior is to flash the whole screen. On some platforms, | |
10050 special effects are available using the following values: | |
10051 | |
3025 | 10052 `display' Flash the whole screen (ie, the default behavior). |
10053 `top-bottom' Flash only the top and bottom lines of the selected frame. | |
442 | 10054 |
10055 When effects are unavailable on a platform, the visual bell is the | |
10056 default, whole screen. (Currently only X supports any special effects.) | |
428 | 10057 */ ); |
442 | 10058 Vvisible_bell = Qnil; |
428 | 10059 |
10060 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* | |
10061 *Non-nil means no need to redraw entire frame after suspending. | |
10062 A non-nil value is useful if the terminal can automatically preserve | |
10063 Emacs's frame display when you reenter Emacs. | |
10064 It is up to you to set this variable if your terminal can do that. | |
10065 */ ); | |
10066 no_redraw_on_reenter = 0; | |
10067 | |
10068 DEFVAR_LISP ("window-system", &Vwindow_system /* | |
10069 A symbol naming the window-system under which Emacs is running, | |
10070 such as `x', or nil if emacs is running on an ordinary terminal. | |
10071 | |
10072 Do not use this variable, except for GNU Emacs compatibility, as it | |
10073 gives wrong values in a multi-device environment. Use `console-type' | |
10074 instead. | |
10075 */ ); | |
10076 Vwindow_system = Qnil; | |
10077 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10078 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
|
10079 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
|
10080 |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10081 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
|
10082 to Lisp what type the initial device to be created should be. |
428 | 10083 */ ); |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10084 Vinitial_device_type = Qnil; |
428 | 10085 |
10086 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* | |
10087 Non-nil means put cursor in minibuffer, at end of any message there. | |
10088 */ ); | |
10089 cursor_in_echo_area = 0; | |
10090 | |
10091 /* #### Shouldn't this be generalized as follows: | |
10092 | |
10093 if nil, use block cursor. | |
10094 if a number, use a bar cursor of that width. | |
10095 Otherwise, use a 1-pixel bar cursor. | |
10096 | |
10097 #### Or better yet, this variable should be trashed entirely | |
10098 (use a Lisp-magic variable to maintain compatibility) | |
10099 and a specifier `cursor-shape' added, which allows a block | |
10100 cursor, a bar cursor, a flashing block or bar cursor, | |
10101 maybe a caret cursor, etc. */ | |
10102 | |
10103 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /* | |
448 | 10104 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. |
428 | 10105 */ ); |
10106 Vbar_cursor = Qnil; | |
10107 | |
442 | 10108 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* |
10109 Function or functions to call when a frame's buffer list has changed. | |
10110 This is called during redisplay, before redisplaying each frame. | |
10111 Functions on this hook are called with one argument, the frame. | |
10112 */ ); | |
10113 Vbuffer_list_changed_hook = Qnil; | |
10114 | |
428 | 10115 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* |
10116 Bump this to tell the C code to call `display-warning-buffer' | |
10117 at next redisplay. You should not normally change this; the function | |
10118 `display-warning' automatically does this at appropriate times. | |
10119 */ ); | |
10120 display_warning_tick = 0; | |
10121 | |
10122 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /* | |
10123 Non-nil means inhibit display of warning messages. | |
10124 You should *bind* this, not set it. Any pending warning messages | |
10125 will be displayed when the binding no longer applies. | |
10126 */ ); | |
10127 /* reset to 0 by startup.el after the splash screen has displayed. | |
10128 This way, the warnings don't obliterate the splash screen. */ | |
10129 inhibit_warning_display = 1; | |
10130 | |
10131 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /* | |
10132 *Non-nil means column display number starts at 1. | |
10133 */ ); | |
10134 column_number_start_at_one = 0; | |
10135 } | |
10136 | |
10137 void | |
10138 specifier_vars_of_redisplay (void) | |
10139 { | |
10140 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /* | |
10141 *Width of left margin. | |
10142 This is a specifier; use `set-specifier' to change it. | |
10143 */ ); | |
10144 Vleft_margin_width = Fmake_specifier (Qnatnum); | |
10145 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10146 set_specifier_caching (Vleft_margin_width, | |
438 | 10147 offsetof (struct window, left_margin_width), |
428 | 10148 some_window_value_changed, |
438 | 10149 offsetof (struct frame, left_margin_width), |
444 | 10150 margin_width_changed_in_frame, 0); |
428 | 10151 |
10152 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* | |
10153 *Width of right margin. | |
10154 This is a specifier; use `set-specifier' to change it. | |
10155 */ ); | |
10156 Vright_margin_width = Fmake_specifier (Qnatnum); | |
10157 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10158 set_specifier_caching (Vright_margin_width, | |
438 | 10159 offsetof (struct window, right_margin_width), |
428 | 10160 some_window_value_changed, |
438 | 10161 offsetof (struct frame, right_margin_width), |
444 | 10162 margin_width_changed_in_frame, 0); |
428 | 10163 |
10164 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* | |
10165 *Minimum ascent height of lines. | |
10166 This is a specifier; use `set-specifier' to change it. | |
10167 */ ); | |
10168 Vminimum_line_ascent = Fmake_specifier (Qnatnum); | |
10169 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); | |
10170 set_specifier_caching (Vminimum_line_ascent, | |
438 | 10171 offsetof (struct window, minimum_line_ascent), |
428 | 10172 some_window_value_changed, |
444 | 10173 0, 0, 0); |
428 | 10174 |
10175 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* | |
10176 *Minimum descent height of lines. | |
10177 This is a specifier; use `set-specifier' to change it. | |
10178 */ ); | |
10179 Vminimum_line_descent = Fmake_specifier (Qnatnum); | |
10180 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); | |
10181 set_specifier_caching (Vminimum_line_descent, | |
438 | 10182 offsetof (struct window, minimum_line_descent), |
428 | 10183 some_window_value_changed, |
444 | 10184 0, 0, 0); |
428 | 10185 |
10186 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* | |
10187 *Non-nil means use the left outside margin as extra whitespace when | |
3025 | 10188 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10189 This is a specifier; use `set-specifier' to change it. |
10190 */ ); | |
10191 Vuse_left_overflow = Fmake_specifier (Qboolean); | |
10192 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); | |
10193 set_specifier_caching (Vuse_left_overflow, | |
438 | 10194 offsetof (struct window, use_left_overflow), |
428 | 10195 some_window_value_changed, |
444 | 10196 0, 0, 0); |
428 | 10197 |
10198 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* | |
10199 *Non-nil means use the right outside margin as extra whitespace when | |
3025 | 10200 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10201 This is a specifier; use `set-specifier' to change it. |
10202 */ ); | |
10203 Vuse_right_overflow = Fmake_specifier (Qboolean); | |
10204 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); | |
10205 set_specifier_caching (Vuse_right_overflow, | |
438 | 10206 offsetof (struct window, use_right_overflow), |
428 | 10207 some_window_value_changed, |
444 | 10208 0, 0, 0); |
428 | 10209 |
10210 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* | |
10211 *Non-nil means the text cursor is visible (this is usually the case). | |
10212 This is a specifier; use `set-specifier' to change it. | |
10213 */ ); | |
10214 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); | |
10215 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); | |
10216 set_specifier_caching (Vtext_cursor_visible_p, | |
438 | 10217 offsetof (struct window, text_cursor_visible_p), |
428 | 10218 text_cursor_visible_p_changed, |
444 | 10219 0, 0, 0); |
428 | 10220 |
10221 } |