Mercurial > hg > xemacs-beta
annotate src/redisplay.c @ 5167:e374ea766cc1
clean up, rearrange allocation statistics code
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-03-21 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (assert_proper_sizing):
* alloc.c (c_readonly):
* alloc.c (malloced_storage_size):
* alloc.c (fixed_type_block_overhead):
* alloc.c (lisp_object_storage_size):
* alloc.c (inc_lrecord_stats):
* alloc.c (dec_lrecord_stats):
* alloc.c (pluralize_word):
* alloc.c (object_memory_usage_stats):
* alloc.c (Fobject_memory_usage):
* alloc.c (compute_memusage_stats_length):
* alloc.c (disksave_object_finalization_1):
* alloc.c (Fgarbage_collect):
* mc-alloc.c:
* mc-alloc.c (mc_alloced_storage_size):
* mc-alloc.h:
No functionality change here. Collect the allocations-statistics
code that was scattered throughout alloc.c into one place. Add
remaining section headings so that all sections have headings
clearly identifying the start of the section and its purpose.
Expose mc_alloced_storage_size() even when not MEMORY_USAGE_STATS;
this fixes build problems and is related to the export of
lisp_object_storage_size() and malloced_storage_size() when
non-MEMORY_USAGE_STATS in the previous change set.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Sun, 21 Mar 2010 04:41:49 -0500 |
parents | 1fae11d56ad2 |
children | 6c6d78781d59 |
rev | line source |
---|---|
428 | 1 /* Display generation from window structure and buffer text. |
2 Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1995 Free Software Foundation, Inc. | |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
4 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2005, 2010 Ben Wing. |
428 | 5 Copyright (C) 1995 Sun Microsystems, Inc. |
6 Copyright (C) 1996 Chuck Thompson. | |
7 | |
8 This file is part of XEmacs. | |
9 | |
10 XEmacs is free software; you can redistribute it and/or modify it | |
11 under the terms of the GNU General Public License as published by the | |
12 Free Software Foundation; either version 2, or (at your option) any | |
13 later version. | |
14 | |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
21 along with XEmacs; see the file COPYING. If not, write to | |
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 Boston, MA 02111-1307, USA. */ | |
24 | |
25 /* Synched up with: Not in FSF. */ | |
26 | |
27 /* Author: Chuck Thompson */ | |
28 | |
29 /* Fixed up by Ben Wing for Mule */ | |
30 | |
31 /* This file has been Mule-ized. */ | |
32 | |
33 /***************************************************************************** | |
34 The Golden Rules of Redisplay | |
35 | |
853 | 36 First: It Is Better To Be Correct Than Fast |
37 Second: Thou Shalt Use Due Caution When Running Elisp From Within Redisplay | |
38 Third: It Is Better To Be Fast Than Not To Be | |
428 | 39 ****************************************************************************/ |
40 | |
1318 | 41 /* Note: The second rule used to prohibit running Elisp from within |
42 redisplay, but that's not correct any more -- use | |
43 call*_trapping_problems() or call_with_suspended_errors() instead. | |
853 | 44 |
45 --ben | |
46 */ | |
47 | |
428 | 48 #include <config.h> |
49 #include "lisp.h" | |
50 | |
51 #include "buffer.h" | |
52 #include "commands.h" | |
53 #include "debug.h" | |
872 | 54 #include "device-impl.h" |
428 | 55 #include "elhash.h" |
853 | 56 #include "events.h" |
872 | 57 #include "extents-impl.h" |
428 | 58 #include "faces.h" |
872 | 59 #include "frame-impl.h" |
428 | 60 #include "glyphs.h" |
61 #include "gutter.h" | |
62 #include "insdel.h" | |
63 #include "menubar.h" | |
872 | 64 #include "objects-impl.h" |
1318 | 65 #include "opaque.h" |
428 | 66 #include "process.h" |
1292 | 67 #include "profile.h" |
428 | 68 #include "redisplay.h" |
69 #include "toolbar.h" | |
872 | 70 #include "window-impl.h" |
428 | 71 #include "line-number.h" |
72 #include "file-coding.h" | |
73 | |
442 | 74 #include "sysfile.h" |
75 | |
428 | 76 #ifdef HAVE_TTY |
77 #include "console-tty.h" | |
78 #endif /* HAVE_TTY */ | |
79 | |
80 /* Note: We have to be careful throughout this code to properly handle | |
867 | 81 and differentiate between Ibytes and Ichars. |
82 | |
83 Since strings are generally composed of Ibytes, I've taken the tack | |
84 that any contiguous set of Ibytes is called a "string", while | |
85 any contiguous set of Ichars is called an "array". */ | |
428 | 86 |
87 /* Return value to indicate a failure by an add_*_rune routine to add | |
88 a rune, but no propagation information needs to be returned. */ | |
89 #define ADD_FAILED (prop_block_dynarr *) 1 | |
90 | |
91 #define BEGIN_GLYPHS 0 | |
92 #define END_GLYPHS 1 | |
93 #define LEFT_GLYPHS 2 | |
94 #define RIGHT_GLYPHS 3 | |
95 | |
96 #define VERTICAL_CLIP(w, display) \ | |
442 | 97 ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \ |
428 | 98 ? INT_MAX \ |
442 | 99 : vertical_clip) |
428 | 100 |
101 /* The following structures are completely private to redisplay.c so | |
102 we put them here instead of in a header file, for modularity. */ | |
103 | |
826 | 104 /* NOTE: Bytexpos's not Charxpos's in this structure. */ |
428 | 105 |
106 typedef struct position_redisplay_data_type | |
107 { | |
108 /* This information is normally filled in by the create_*_block | |
109 routines and is used by the add_*_rune routines. */ | |
110 Lisp_Object window; | |
111 /* if we are working with strings rather than buffers we need a | |
112 handle to the string */ | |
113 Lisp_Object string; | |
114 struct device *d; | |
115 struct display_block *db; | |
116 struct display_line *dl; | |
867 | 117 Ichar ch; /* Character that is to be added. This is |
428 | 118 used to communicate this information to |
867 | 119 add_ichar_rune(). */ |
428 | 120 Lisp_Object last_charset; /* The charset of the previous character. |
121 Used to optimize some lookups -- we | |
122 only have to do some things when | |
123 the charset changes. */ | |
124 face_index last_findex; /* The face index of the previous character. | |
125 Needed to ensure the validity of the | |
126 last_charset optimization. */ | |
127 | |
128 int last_char_width; /* The width of the previous character. */ | |
129 int font_is_bogus; /* If true, it means we couldn't instantiate | |
130 the font for this charset, so we substitute | |
131 ~'s from the ASCII charset. */ | |
826 | 132 Bytexpos byte_charpos; /* Position of character we are processing. This |
133 is a Bytexpos, meaning it refers to bytes (not | |
134 chars) and can refer to either buffers (1-based) | |
135 or strings (0-based). We need to be careful | |
136 when doing anything that references the text in | |
137 the buffer or string. */ | |
138 Bytexpos byte_endpos; /* ????? Unknown, under-used. */ | |
428 | 139 int pixpos; |
140 int max_pixpos; | |
141 int blank_width; /* Width of the blank that is to be added. | |
142 This is used to communicate this information | |
143 to add_blank_rune(). | |
144 | |
145 This is also used rather cheesily to | |
146 communicate the width of the eol-cursor-size | |
147 blank that exists at the end of the line. | |
867 | 148 add_ichar_rune() is called cheesily with |
428 | 149 the non-printing char '\n', which is stuck |
150 in the output routines with its width being | |
151 BLANK_WIDTH. */ | |
826 | 152 Bytexpos byte_cursor_charpos; /* This stores the buffer position of the |
153 cursor. */ | |
428 | 154 unsigned int cursor_type :3; |
155 int cursor_x; /* rune block cursor is at */ | |
156 int start_col; /* Number of character columns (each column has | |
157 a width of the default char width) that still | |
158 need to be skipped. This is used for horizontal | |
159 scrolling, where a certain number of columns | |
160 (those off the left side of the screen) need | |
161 to be skipped before anything is displayed. */ | |
826 | 162 Bytexpos byte_start_col_enabled; |
428 | 163 int start_col_xoffset; /* Number of pixels that still need to |
4187 | 164 be skipped. This is used for |
165 horizontal scrolling of glyphs, where we want | |
166 to be able to scroll over part of the glyph. */ | |
428 | 167 |
168 int hscroll_glyph_width_adjust; /* how much the width of the hscroll | |
169 glyph differs from space_width (w). | |
170 0 if no hscroll glyph was used, | |
171 i.e. the window is not scrolled | |
172 horizontally. Used in tab | |
173 calculations. */ | |
174 | |
175 /* Information about the face the text should be displayed in and | |
176 any begin-glyphs and end-glyphs. */ | |
177 struct extent_fragment *ef; | |
178 face_index findex; | |
179 | |
819 | 180 /* The height of a pixmap may either be predetermined if the user has set a |
181 baseline value, or it may be dependent on whatever the line ascent and | |
182 descent values end up being, based just on font and pixmap-ascent | |
183 information. In the first case we can immediately update the values, thus | |
184 their inclusion here. In the last case we cannot determine the actual | |
185 contribution to the line height until we have finished laying out all text | |
186 on the line. Thus we propagate the max height of such pixmaps and do a | |
187 final calculation (in calculate_baseline()) after all text has been added | |
188 to the line. */ | |
428 | 189 int new_ascent; |
190 int new_descent; | |
191 int max_pixmap_height; | |
819 | 192 int need_baseline_computation; |
193 int end_glyph_width; /* Well, it is the kitchen sink after all ... */ | |
428 | 194 |
195 Lisp_Object result_str; /* String where we put the result of | |
196 generating a formatted string in the modeline. */ | |
197 int is_modeline; /* Non-zero if we're generating the modeline. */ | |
198 Charcount modeline_charpos; /* Number of chars used in result_str so far; | |
199 corresponds to bytepos. */ | |
200 Bytecount bytepos; /* Number of bytes used in result_str so far. | |
4187 | 201 We don't actually copy the bytes into result_str |
428 | 202 until the end because we don't know how big the |
203 string is going to be until then. */ | |
204 } pos_data; | |
205 | |
206 enum prop_type | |
207 { | |
208 PROP_STRING, | |
209 PROP_CHAR, | |
210 PROP_MINIBUF_PROMPT, | |
819 | 211 PROP_BLANK, |
212 PROP_GLYPH | |
428 | 213 }; |
214 | |
215 /* Data that should be propagated to the next line. Either a single | |
867 | 216 Ichar, a string of Ibyte's or a glyph. |
428 | 217 |
218 The actual data that is propagated ends up as a Dynarr of these | |
219 blocks. | |
220 | |
819 | 221 prop_blocks are used to indicate that data that was supposed to go |
222 on the previous line couldn't actually be displayed. Generally this | |
223 shouldn't happen if we are clipping the end of lines. If we are | |
224 wrapping then we need to display the propagation data before moving | |
225 on. Its questionable whether we should wrap or clip glyphs in this | |
226 instance. Most e-lisp relies on clipping so we preserve this | |
227 behavior. | |
228 | |
867 | 229 #### It's unclean that both Ichars and Ibytes are here. |
428 | 230 */ |
231 | |
232 typedef struct prop_block prop_block; | |
233 struct prop_block | |
234 { | |
235 enum prop_type type; | |
236 | |
237 union data | |
238 { | |
239 struct | |
240 { | |
867 | 241 Ibyte *str; |
428 | 242 Bytecount len; /* length of the string. */ |
243 } p_string; | |
244 | |
245 struct | |
246 { | |
867 | 247 Ichar ch; |
826 | 248 Bytebpos byte_cursor_charpos; /* NOTE: is in Bytebpos's */ |
428 | 249 unsigned int cursor_type :3; |
250 } p_char; | |
251 | |
252 struct | |
253 { | |
254 int width; | |
255 face_index findex; | |
256 } p_blank; | |
819 | 257 |
258 struct | |
259 { | |
260 /* Not used as yet, but could be used to wrap rather than clip glyphs. */ | |
4187 | 261 int width; |
819 | 262 Lisp_Object glyph; |
263 } p_glyph; | |
264 | |
428 | 265 } data; |
266 }; | |
267 | |
268 typedef struct | |
269 { | |
270 Dynarr_declare (prop_block); | |
271 } prop_block_dynarr; | |
272 | |
273 | |
274 static Charcount generate_fstring_runes (struct window *w, pos_data *data, | |
275 Charcount pos, Charcount min_pos, | |
276 Charcount max_pos, Lisp_Object elt, | |
277 int depth, int max_pixsize, | |
438 | 278 face_index findex, int type, |
279 Charcount *offset, | |
280 Lisp_Object cur_ext); | |
428 | 281 static prop_block_dynarr *add_glyph_rune (pos_data *data, |
282 struct glyph_block *gb, | |
283 int pos_type, int allow_cursor, | |
284 struct glyph_cachel *cachel); | |
665 | 285 static Bytebpos create_text_block (struct window *w, struct display_line *dl, |
826 | 286 Bytebpos byte_start_pos, |
287 prop_block_dynarr **prop, | |
288 int type); | |
428 | 289 static int create_overlay_glyph_block (struct window *w, |
290 struct display_line *dl); | |
291 static void create_left_glyph_block (struct window *w, | |
292 struct display_line *dl, | |
293 int overlay_width); | |
294 static void create_right_glyph_block (struct window *w, | |
295 struct display_line *dl); | |
296 static void redisplay_windows (Lisp_Object window, int skip_selected); | |
867 | 297 static void decode_mode_spec (struct window *w, Ichar spec, int type); |
428 | 298 static void free_display_line (struct display_line *dl); |
826 | 299 static void update_line_start_cache (struct window *w, Charbpos from, |
300 Charbpos to, Charbpos point, | |
301 int no_regen); | |
665 | 302 static int point_visible (struct window *w, Charbpos point, int type); |
819 | 303 static void calculate_yoffset (struct display_line *dl, |
4187 | 304 struct display_block *fixup); |
819 | 305 static void calculate_baseline (pos_data *data); |
428 | 306 |
1204 | 307 #ifdef ERROR_CHECK_DISPLAY |
800 | 308 static void sledgehammer_check_redisplay_structs (void); |
1204 | 309 #endif /* ERROR_CHECK_DISPLAY */ |
800 | 310 |
428 | 311 /* This used to be 10 but 30 seems to give much better performance. */ |
312 #define INIT_MAX_PREEMPTS 30 | |
1268 | 313 static Fixnum max_preempts; |
314 | |
315 #define QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION 4 | |
428 | 316 |
1318 | 317 /* Note that doing this can call Lisp. */ |
428 | 318 #define REDISPLAY_PREEMPTION_CHECK \ |
319 ((void) \ | |
320 (preempted = \ | |
321 (!disable_preemption && \ | |
322 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \ | |
4187 | 323 (!INTERACTIVE || \ |
1268 | 324 detect_input_pending (QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION))))) |
428 | 325 |
326 /* | |
327 * Redisplay global variables. | |
328 */ | |
329 | |
330 /* We need a third set of display structures for the cursor motion | |
331 routines. We used to just give each window a third set. However, | |
332 we always fully regenerate the structures when needed so there | |
333 isn't any reason we need more than a single set. */ | |
334 display_line_dynarr *cmotion_display_lines; | |
335 | |
336 /* We store the extents that we need to generate in a Dynarr and then | |
337 frob them all on at the end of generating the string. We do it | |
338 this way rather than adding them as we generate the string because | |
339 we don't store the text into the resulting string until we're done | |
340 (to avoid having to resize the string multiple times), and we don't | |
341 want to go around adding extents to a string when the extents might | |
342 stretch off the end of the string. */ | |
343 static EXTENT_dynarr *formatted_string_extent_dynarr; | |
344 static Bytecount_dynarr *formatted_string_extent_start_dynarr; | |
345 static Bytecount_dynarr *formatted_string_extent_end_dynarr; | |
346 | |
347 | |
348 /* #### probably temporary */ | |
458 | 349 Fixnum cache_adjustment; |
428 | 350 |
351 /* This holds a string representing the text corresponding to a single | |
352 modeline % spec. */ | |
867 | 353 static Ibyte_dynarr *mode_spec_ibyte_string; |
428 | 354 |
355 int in_display; /* 1 if in redisplay. */ | |
356 | |
1318 | 357 /* Whether we should delay size changes. Broken out of |
358 enter_redisplay_critical_section(). */ | |
359 int hold_frame_size_changes; | |
360 | |
428 | 361 int disable_preemption; /* Used for debugging redisplay and for |
362 force-redisplay. */ | |
363 | |
364 /* We only allow max_preempts preemptions before we force a redisplay. */ | |
365 static int preemption_count; | |
366 | |
367 /* Minimum pixel height of clipped bottom display line. */ | |
458 | 368 Fixnum vertical_clip; |
428 | 369 |
370 /* Minimum visible pixel width of clipped glyphs at right margin. */ | |
458 | 371 Fixnum horizontal_clip; |
428 | 372 |
373 /* Nonzero means reading single-character input with prompt | |
374 so put cursor on minibuffer after the prompt. */ | |
375 int cursor_in_echo_area; | |
376 Lisp_Object Qcursor_in_echo_area; | |
377 | |
378 /* Nonzero means truncate lines in all windows less wide than the frame */ | |
379 int truncate_partial_width_windows; | |
380 | |
381 /* non-nil if a buffer has changed since the last time redisplay completed */ | |
382 int buffers_changed; | |
383 int buffers_changed_set; | |
384 | |
385 /* non-nil if hscroll has changed somewhere or a buffer has been | |
386 narrowed or widened */ | |
387 int clip_changed; | |
388 int clip_changed_set; | |
389 | |
390 /* non-nil if any extent has changed since the last time redisplay completed */ | |
391 int extents_changed; | |
392 int extents_changed_set; | |
393 | |
394 /* non-nil if any face has changed since the last time redisplay completed */ | |
395 int faces_changed; | |
396 | |
397 /* Nonzero means some frames have been marked as garbaged */ | |
398 int frame_changed; | |
399 | |
400 /* non-zero if any of the builtin display glyphs (continuation, | |
401 hscroll, control-arrow, etc) is in need of updating | |
402 somewhere. */ | |
403 int glyphs_changed; | |
404 int glyphs_changed_set; | |
405 | |
442 | 406 /* non-zero if any subwindow has been deleted. */ |
428 | 407 int subwindows_changed; |
408 int subwindows_changed_set; | |
409 | |
410 /* non-zero if any displayed subwindow is in need of updating | |
411 somewhere. */ | |
412 int subwindows_state_changed; | |
413 int subwindows_state_changed_set; | |
414 | |
415 /* This variable is 1 if the icon has to be updated. | |
416 It is set to 1 when `frame-icon-glyph' changes. */ | |
417 int icon_changed; | |
418 int icon_changed_set; | |
419 | |
420 /* This variable is 1 if the menubar widget has to be updated. | |
421 It is set to 1 by set-menubar-dirty-flag and cleared when the widget | |
422 has been updated. */ | |
423 int menubar_changed; | |
424 int menubar_changed_set; | |
425 | |
426 /* true iff we should redraw the modelines on the next redisplay */ | |
427 int modeline_changed; | |
428 int modeline_changed_set; | |
429 | |
430 /* non-nil if point has changed in some buffer since the last time | |
431 redisplay completed */ | |
432 int point_changed; | |
433 int point_changed_set; | |
434 | |
435 /* non-nil if some frame has changed its size */ | |
436 int size_changed; | |
437 | |
438 /* non-nil if some device has signaled that it wants to change size */ | |
439 int asynch_device_change_pending; | |
440 | |
441 /* non-nil if any toolbar has changed */ | |
442 int toolbar_changed; | |
443 int toolbar_changed_set; | |
444 | |
905 | 445 /* Nonzero if some frame has changed the layout of internal elements |
446 (gutters or toolbars). */ | |
447 int frame_layout_changed; | |
448 | |
428 | 449 /* non-nil if any gutter has changed */ |
450 int gutter_changed; | |
451 int gutter_changed_set; | |
452 | |
453 /* non-nil if any window has changed since the last time redisplay completed */ | |
454 int windows_changed; | |
455 | |
456 /* non-nil if any frame's window structure has changed since the last | |
457 time redisplay completed */ | |
458 int windows_structure_changed; | |
459 | |
460 /* If non-nil, use vertical bar cursor. */ | |
461 Lisp_Object Vbar_cursor; | |
462 Lisp_Object Qbar_cursor; | |
463 | |
442 | 464 Lisp_Object Vvisible_bell; /* If true and the terminal will support it |
465 then the frame will flash instead of | |
466 beeping when an error occurs */ | |
428 | 467 |
468 /* Nonzero means no need to redraw the entire frame on resuming | |
469 a suspended Emacs. This is useful on terminals with multiple pages, | |
470 where one page is used for Emacs and another for all else. */ | |
471 int no_redraw_on_reenter; | |
472 | |
3360 | 473 Lisp_Object Vwindow_system; /* #### this variable is deprecated |
474 nil or a symbol naming the window system | |
428 | 475 under which emacs is running |
3360 | 476 (`x', `gtk', `mswindows', and `tty' are |
477 supported -- yes, TTYs are window systems | |
478 for this purpose. */ | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
479 Lisp_Object Vinitial_device_type; |
428 | 480 |
481 Lisp_Object Vglobal_mode_string; | |
482 | |
483 /* The number of lines scroll a window by when point leaves the window; if | |
484 it is <=0 then point is centered in the window */ | |
458 | 485 Fixnum scroll_step; |
428 | 486 |
487 /* Scroll up to this many lines, to bring point back on screen. */ | |
458 | 488 Fixnum scroll_conservatively; |
428 | 489 |
490 /* Marker for where to display an arrow on top of the buffer text. */ | |
491 Lisp_Object Voverlay_arrow_position; | |
492 /* String to display for the arrow. */ | |
493 Lisp_Object Voverlay_arrow_string; | |
494 | |
442 | 495 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook; |
496 | |
458 | 497 static Fixnum last_display_warning_tick; |
498 static Fixnum display_warning_tick; | |
428 | 499 Lisp_Object Qdisplay_warning_buffer; |
500 int inhibit_warning_display; | |
501 | |
502 Lisp_Object Vleft_margin_width, Vright_margin_width; | |
503 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; | |
504 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; | |
505 Lisp_Object Vtext_cursor_visible_p; | |
506 | |
1292 | 507 static Lisp_Object QSin_redisplay; |
508 | |
1318 | 509 static Lisp_Object Vpost_redisplay_actions; |
510 | |
428 | 511 int column_number_start_at_one; |
512 | |
442 | 513 Lisp_Object Qtop_bottom; |
514 | |
444 | 515 #define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset) |
428 | 516 |
1204 | 517 static const struct memory_description rune_dglyph_description_1[] = { |
518 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, glyph) }, | |
519 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, extent) }, | |
520 { XD_END } | |
521 }; | |
522 | |
523 static const struct sized_memory_description rune_dglyph_description = { | |
524 sizeof (struct rune_dglyph), rune_dglyph_description_1 | |
525 }; | |
526 | |
527 static const struct memory_description rune_object_description_1[] = { | |
2551 | 528 { XD_BLOCK_ARRAY, RUNE_DGLYPH, 1, { &rune_dglyph_description } }, |
1204 | 529 { XD_END } |
530 }; | |
531 | |
532 static const struct sized_memory_description rune_object_description = { | |
533 0, rune_object_description_1 | |
534 }; | |
535 | |
536 static const struct memory_description rune_description_1[] = { | |
537 { XD_INT, offsetof (rune, type) }, | |
538 { XD_UNION, offsetof (rune, object), | |
2551 | 539 XD_INDIRECT (0, 0), { &rune_object_description } }, |
1204 | 540 { XD_END } |
541 }; | |
542 | |
543 static const struct sized_memory_description rune_description = { | |
544 sizeof (rune), | |
545 rune_description_1 | |
546 }; | |
547 | |
548 static const struct memory_description rune_dynarr_description_1[] = { | |
549 XD_DYNARR_DESC (rune_dynarr, &rune_description), | |
550 { XD_END } | |
551 }; | |
552 | |
553 static const struct sized_memory_description rune_dynarr_description = { | |
554 sizeof (rune_dynarr), | |
555 rune_dynarr_description_1 | |
556 }; | |
557 | |
558 static const struct memory_description display_block_description_1[] = { | |
2367 | 559 { XD_BLOCK_PTR, offsetof (display_block, runes), |
2551 | 560 1, { &rune_dynarr_description } }, |
1204 | 561 { XD_END } |
562 }; | |
563 | |
564 static const struct sized_memory_description display_block_description = { | |
565 sizeof (display_block), | |
566 display_block_description_1 | |
567 }; | |
568 | |
569 static const struct memory_description display_block_dynarr_description_1[] = { | |
570 XD_DYNARR_DESC (display_block_dynarr, &display_block_description), | |
571 { XD_END } | |
572 }; | |
573 | |
574 static const struct sized_memory_description display_block_dynarr_description = { | |
575 sizeof (display_block_dynarr), | |
576 display_block_dynarr_description_1 | |
577 }; | |
578 | |
579 static const struct memory_description glyph_block_description_1[] = { | |
580 { XD_LISP_OBJECT, offsetof (glyph_block, glyph) }, | |
581 { XD_LISP_OBJECT, offsetof (glyph_block, extent) }, | |
582 { XD_END } | |
583 }; | |
584 | |
585 static const struct sized_memory_description glyph_block_description = { | |
586 sizeof (glyph_block), | |
587 glyph_block_description_1 | |
588 }; | |
589 | |
590 static const struct memory_description glyph_block_dynarr_description_1[] = { | |
591 XD_DYNARR_DESC (glyph_block_dynarr, &glyph_block_description), | |
592 { XD_END } | |
593 }; | |
594 | |
595 static const struct sized_memory_description glyph_block_dynarr_description = { | |
596 sizeof (glyph_block_dynarr), | |
597 glyph_block_dynarr_description_1 | |
598 }; | |
599 | |
600 static const struct memory_description display_line_description_1[] = { | |
2367 | 601 { XD_BLOCK_PTR, offsetof (display_line, display_blocks), |
2551 | 602 1, { &display_block_dynarr_description } }, |
2367 | 603 { XD_BLOCK_PTR, offsetof (display_line, left_glyphs), |
2551 | 604 1, { &glyph_block_dynarr_description } }, |
2367 | 605 { XD_BLOCK_PTR, offsetof (display_line, right_glyphs), |
2551 | 606 1, { &glyph_block_dynarr_description } }, |
1204 | 607 { XD_END } |
608 }; | |
609 | |
610 static const struct sized_memory_description display_line_description = { | |
611 sizeof (display_line), | |
612 display_line_description_1 | |
613 }; | |
614 | |
615 static const struct memory_description display_line_dynarr_description_1[] = { | |
616 XD_DYNARR_DESC (display_line_dynarr, &display_line_description), | |
617 { XD_END } | |
618 }; | |
619 | |
620 const struct sized_memory_description display_line_dynarr_description = { | |
621 sizeof (display_line_dynarr), | |
622 display_line_dynarr_description_1 | |
623 }; | |
624 | |
428 | 625 |
626 /***************************************************************************/ | |
627 /* */ | |
628 /* low-level interfaces onto device routines */ | |
629 /* */ | |
630 /***************************************************************************/ | |
631 | |
632 static int | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
633 redisplay_window_text_width_ichar_string (struct window *w, int findex, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
634 Ichar *str, Charcount len) |
428 | 635 { |
636 unsigned char charsets[NUM_LEADING_BYTES]; | |
637 Lisp_Object window; | |
638 | |
867 | 639 find_charsets_in_ichar_string (charsets, str, len); |
793 | 640 window = wrap_window (w); |
428 | 641 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window, |
642 charsets); | |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
643 return DEVMETH (WINDOW_XDEVICE (w), |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
644 text_width, (w, WINDOW_FACE_CACHEL (w, findex), str, |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
645 len)); |
428 | 646 } |
647 | |
867 | 648 static Ichar_dynarr *rtw_ichar_dynarr; |
428 | 649 |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
650 static int |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
651 redisplay_window_text_width_string (struct window *w, int findex, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
652 Ibyte *nonreloc, Lisp_Object reloc, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
653 Bytecount offset, Bytecount len) |
428 | 654 { |
867 | 655 if (!rtw_ichar_dynarr) |
656 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
657 Dynarr_reset (rtw_ichar_dynarr); | |
428 | 658 |
659 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
660 if (STRINGP (reloc)) | |
661 nonreloc = XSTRING_DATA (reloc); | |
867 | 662 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
663 return redisplay_window_text_width_ichar_string |
4967 | 664 (w, findex, Dynarr_begin (rtw_ichar_dynarr), |
867 | 665 Dynarr_length (rtw_ichar_dynarr)); |
428 | 666 } |
667 | |
668 int | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
669 redisplay_text_width_string (Lisp_Object domain, Lisp_Object face, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
670 Ibyte *nonreloc, Lisp_Object reloc, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
671 Bytecount offset, Bytecount len) |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
672 { |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
673 Lisp_Object window = DOMAIN_WINDOW (domain); |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
674 Lisp_Object frame = DOMAIN_FRAME (domain); |
428 | 675 unsigned char charsets[NUM_LEADING_BYTES]; |
676 struct face_cachel cachel; | |
677 | |
867 | 678 if (!rtw_ichar_dynarr) |
679 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
680 Dynarr_reset (rtw_ichar_dynarr); | |
428 | 681 |
682 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
683 if (STRINGP (reloc)) | |
684 nonreloc = XSTRING_DATA (reloc); | |
867 | 685 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
686 find_charsets_in_ibyte_string (charsets, nonreloc, len); | |
428 | 687 reset_face_cachel (&cachel); |
688 cachel.face = face; | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
689 ensure_face_cachel_complete (&cachel, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
690 NILP (window) ? frame : window, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
691 charsets); |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
692 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (frame))), |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
693 /* #### Not clear if we're always passed a window, but |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
694 I think so. If not, we will get an abort here, |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
695 and then we need to either fix the callers to pass in |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
696 a window, or change *text_width() to take a domain |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
697 argument. */ |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
698 text_width, (XWINDOW (window), |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
699 &cachel, |
4967 | 700 Dynarr_begin (rtw_ichar_dynarr), |
867 | 701 Dynarr_length (rtw_ichar_dynarr))); |
428 | 702 } |
703 | |
704 /* Return the display block from DL of the given TYPE. A display line | |
705 can have only one display block of each possible type. If DL does | |
706 not have a block of type TYPE, one will be created and added to DL. */ | |
707 | |
708 struct display_block * | |
709 get_display_block_from_line (struct display_line *dl, enum display_type type) | |
710 { | |
711 int elt; | |
712 struct display_block db; | |
713 | |
714 /* Check if this display line already has a block of the desired type and | |
715 if so, return it. */ | |
716 if (dl->display_blocks) | |
717 { | |
718 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++) | |
719 { | |
720 if (Dynarr_at (dl->display_blocks, elt).type == type) | |
721 return Dynarr_atp (dl->display_blocks, elt); | |
722 } | |
723 | |
724 /* There isn't an active block of the desired type, but there | |
4187 | 725 might still be allocated blocks we need to reuse. */ |
428 | 726 if (elt < Dynarr_largest (dl->display_blocks)) |
727 { | |
728 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt); | |
729 | |
3025 | 730 /* "add" the block to the list */ |
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); | |
762 int char_tab_width = XINT (b->tab_width); | |
763 | |
764 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8; | |
765 | |
766 return char_tab_width; | |
767 } | |
768 | |
769 static int | |
770 space_width (struct window *w) | |
771 { | |
3659 | 772 /* While tabs are traditionally composed of spaces, for variable-width |
428 | 773 fonts the space character tends to give too narrow a value. So |
774 we use 'n' instead. Except that we don't. We use the default | |
775 character width for the default face. If this is actually | |
776 defined by the font then it is probably the best thing to | |
777 actually use. If it isn't, we have assumed it is 'n' and have | |
778 already calculated its width. Thus we can avoid a call to | |
779 XTextWidth on X frames by just querying the default width. */ | |
780 return XFONT_INSTANCE | |
781 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width; | |
782 } | |
783 | |
784 static int | |
785 tab_pix_width (struct window *w) | |
786 { | |
787 return space_width (w) * tab_char_width (w); | |
788 } | |
789 | |
790 /* Given a pixel position in a window, return the pixel location of | |
791 the next tabstop. Tabs are calculated from the left window edge in | |
792 terms of spaces displayed in the default face. Formerly the space | |
793 width was determined using the currently active face. That method | |
794 leads to tabstops which do not line up. */ | |
795 | |
796 static int | |
797 next_tab_position (struct window *w, int start_pixpos, int left_pixpos) | |
798 { | |
799 int n_pos = left_pixpos; | |
800 int pix_tab_width = tab_pix_width (w); | |
801 | |
802 /* Adjust n_pos for any hscrolling which has happened. */ | |
803 if (WINDOW_SCROLLED (w)) | |
804 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset; | |
805 | |
806 while (n_pos <= start_pixpos) | |
807 n_pos += pix_tab_width; | |
808 | |
809 return n_pos; | |
810 } | |
811 | |
812 /* For the given window, calculate the outside and margin boundaries for a | |
813 display line. The whitespace boundaries must be calculated by the text | |
814 layout routines. */ | |
815 | |
816 layout_bounds | |
817 calculate_display_line_boundaries (struct window *w, int modeline) | |
818 { | |
819 layout_bounds bounds; | |
820 | |
821 /* Set the outermost boundaries which are the boundaries of the | |
822 window itself minus the gutters (and minus the scrollbars if this | |
823 is for the modeline). */ | |
824 if (!modeline) | |
825 { | |
826 bounds.left_out = WINDOW_TEXT_LEFT (w); | |
827 bounds.right_out = WINDOW_TEXT_RIGHT (w); | |
828 } | |
829 else | |
830 { | |
831 bounds.left_out = WINDOW_MODELINE_LEFT (w); | |
832 bounds.right_out = WINDOW_MODELINE_RIGHT (w); | |
833 } | |
834 | |
835 /* The inner boundaries mark where the glyph margins are located. */ | |
836 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
837 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
838 | |
839 /* We cannot fully calculate the whitespace boundaries as they | |
840 depend on the contents of the line being displayed. */ | |
841 bounds.left_white = bounds.left_in; | |
842 bounds.right_white = bounds.right_in; | |
843 | |
844 return bounds; | |
845 } | |
846 | |
819 | 847 /* This takes a display_block and its containing line and corrects the yoffset |
848 of each glyph in the block to cater for the ascent of the line as a | |
849 whole. Must be called *after* the line-ascent is known! */ | |
850 | |
851 static void | |
852 calculate_yoffset (struct display_line *dl, struct display_block *fixup) | |
853 { | |
854 int i; | |
855 for (i=0; i<Dynarr_length (fixup->runes); i++) | |
856 { | |
857 struct rune *r = Dynarr_atp (fixup->runes,i); | |
858 if (r->type == RUNE_DGLYPH) | |
4187 | 859 { |
860 if (r->object.dglyph.ascent < dl->ascent) | |
861 r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent + | |
819 | 862 r->object.dglyph.descent; |
4187 | 863 } |
819 | 864 } |
865 } | |
866 | |
867 /* Calculate the textual baseline (the ascent and descent values for the | |
868 display_line as a whole). | |
869 | |
870 If the baseline is completely blank, or contains no manually positioned | |
871 glyphs, then the textual baseline is simply the baseline of the default font. | |
872 (The `contains no manually positioned glyphs' part is actually done for | |
867 | 873 us by `add_ichar_rune'.) |
819 | 874 |
875 If the baseline contains pixmaps, and they're all manually positioned, then | |
876 the textual baseline location is constrained that way, and we need do no | |
877 work. | |
878 | |
879 If the baseline contains pixmaps, and at least one is automatically | |
880 positioned, then the textual ascent is the largest ascent on the line, and | |
881 the textual descent is the largest descent (which is how things are set up at | |
882 entry to this function anyway): except that if the max_ascent + max_descent | |
883 is too small for the height of the line (say you've adjusted the baseline of | |
884 a short glyph, and there's a tall one next to it), then take the ascent and | |
885 descent for the line individually from the largest of the explicitly set | |
886 ascent/descent, and the rescaled ascent/descent of the default font, scaled | |
887 such that the largest glyph will fit. | |
888 | |
889 This means that if you have a short glyph (but taller than the default | |
890 font's descent) forced right under the baseline, and a really tall | |
891 automatically positioned glyph, that the descent for the line is just big | |
892 enough for the manually positioned short glyph, and the tall one uses as | |
893 much of that space as the default font would were it as tall as the tall | |
894 glyph; but that the ascent is big enough for the tall glyph to fit. | |
895 | |
896 This behaviour means that under no circumstances will changing the baseline | |
897 of a short glyph cause a tall glyph to move around; nor will it move the | |
898 textual baseline more than necessary. (Changing a tall glyph's baseline | |
899 might move the text's baseline arbitrarily, of course.) */ | |
900 | |
901 static void | |
902 calculate_baseline (pos_data *data) | |
903 { | |
904 /* Blank line: baseline is default font's baseline. */ | |
905 | |
906 if (!data->new_ascent && !data->new_descent) | |
907 { | |
908 /* We've got a blank line so initialize these values from the default | |
4187 | 909 face. */ |
819 | 910 default_face_font_info (data->window, &data->new_ascent, |
911 &data->new_descent, 0, 0, 0); | |
912 } | |
4187 | 913 |
819 | 914 /* No automatically positioned glyphs? Return at once. */ |
915 if (!data->need_baseline_computation) | |
916 return; | |
917 | |
918 /* Is the tallest glyph on the line automatically positioned? | |
919 If it's manually positioned, or it's automatically positioned | |
920 and there's enough room for it anyway, we need do no more work. */ | |
921 if (data->max_pixmap_height > data->new_ascent + data->new_descent) | |
922 { | |
923 int default_font_ascent, default_font_descent, default_font_height; | |
924 int scaled_default_font_ascent, scaled_default_font_descent; | |
4187 | 925 |
819 | 926 default_face_font_info (data->window, &default_font_ascent, |
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) | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4970
diff
changeset
|
1689 xfree (pb->data.p_string.str); |
428 | 1690 /* #### bogus bogus -- this doesn't do anything! |
867 | 1691 Should probably call add_ibyte_string_runes(), |
428 | 1692 once that function is fixed. */ |
1693 break; | |
1694 case PROP_MINIBUF_PROMPT: | |
1695 { | |
1696 face_index old_findex = data->findex; | |
826 | 1697 Bytebpos byte_old_charpos = data->byte_charpos; |
428 | 1698 |
1699 data->findex = DEFAULT_INDEX; | |
826 | 1700 data->byte_charpos = 0; |
428 | 1701 data->cursor_type = NO_CURSOR; |
1702 | |
1703 while (pb->data.p_string.len > 0) | |
1704 { | |
867 | 1705 data->ch = itext_ichar (pb->data.p_string.str); |
1706 add_failed = add_ichar_rune (data); | |
428 | 1707 |
1708 if (add_failed) | |
1709 { | |
1710 data->findex = old_findex; | |
826 | 1711 data->byte_charpos = byte_old_charpos; |
428 | 1712 goto oops_no_more_space; |
1713 } | |
1714 else | |
1715 { | |
1716 /* Complicated equivalent of ptr++, len-- */ | |
867 | 1717 Ibyte *oldpos = pb->data.p_string.str; |
1718 INC_IBYTEPTR (pb->data.p_string.str); | |
428 | 1719 pb->data.p_string.len -= pb->data.p_string.str - oldpos; |
1720 } | |
1721 } | |
1722 | |
1723 data->findex = old_findex; | |
1724 /* ##### FIXME FIXME FIXME -- Upon successful return from | |
826 | 1725 this function, data->byte_charpos is automatically incremented. |
428 | 1726 However, we don't want that to happen if we were adding |
1727 the minibuffer prompt. */ | |
1728 { | |
1729 struct buffer *buf = | |
1730 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))); | |
1731 /* #### Chuck fix this shit or I'm gonna scream! */ | |
826 | 1732 if (byte_old_charpos > BYTE_BUF_BEGV (buf)) |
4187 | 1733 data->byte_charpos = prev_bytebpos (buf, byte_old_charpos); |
1734 else | |
428 | 1735 /* #### is this correct? Does anyone know? |
1736 Does anyone care? Is this a cheesy hack or what? */ | |
4187 | 1737 data->byte_charpos = BYTE_BUF_BEGV (buf) - 1; |
428 | 1738 } |
1739 } | |
1740 break; | |
1741 case PROP_BLANK: | |
1742 { | |
1743 /* #### I think it's unnecessary and misleading to preserve | |
1744 the blank_width, as it implies that the value carries | |
1745 over from one rune to the next, which is wrong. */ | |
1746 int old_width = data->blank_width; | |
1747 face_index old_findex = data->findex; | |
1748 | |
1749 data->findex = pb->data.p_blank.findex; | |
1750 data->blank_width = pb->data.p_blank.width; | |
826 | 1751 data->byte_cursor_charpos = 0; |
428 | 1752 data->cursor_type = IGNORE_CURSOR; |
1753 | |
1754 if (data->pixpos + data->blank_width > data->max_pixpos) | |
1755 data->blank_width = data->max_pixpos - data->pixpos; | |
1756 | |
1757 /* We pass a bogus value of char_tab_width. It shouldn't | |
4187 | 1758 matter because unless something is really screwed up |
1759 this call won't cause that arg to be used. */ | |
428 | 1760 add_failed = add_blank_rune (data, XWINDOW (data->window), 0); |
1761 | |
1762 /* This can happen in the case where we have a tab which | |
4187 | 1763 is wider than the window. */ |
428 | 1764 if (data->blank_width != pb->data.p_blank.width) |
1765 { | |
1766 pb->data.p_blank.width -= data->blank_width; | |
1767 add_failed = ADD_FAILED; | |
1768 } | |
1769 | |
1770 data->findex = old_findex; | |
1771 data->blank_width = old_width; | |
1772 | |
1773 if (add_failed) | |
1774 goto oops_no_more_space; | |
1775 } | |
1776 break; | |
1777 default: | |
2500 | 1778 ABORT (); |
428 | 1779 } |
1780 } | |
1781 | |
1782 oops_no_more_space: | |
1783 | |
826 | 1784 data->byte_cursor_charpos = byte_old_cursor_charpos; |
428 | 1785 data->cursor_type = old_cursor_type; |
1786 if (elt < Dynarr_length (*prop)) | |
1787 { | |
1788 Dynarr_delete_many (*prop, 0, elt); | |
1789 return *prop; | |
1790 } | |
1791 else | |
1792 { | |
1793 Dynarr_free (*prop); | |
1794 return NULL; | |
1795 } | |
1796 } | |
1797 | |
3025 | 1798 /* Add `text' layout glyphs at position POS_TYPE that are contained to |
428 | 1799 the display block, but add all other types to the appropriate list |
1800 of the display line. They will be added later by different | |
1801 routines. */ | |
1802 | |
1803 static prop_block_dynarr * | |
1804 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, | |
1805 int allow_cursor, struct glyph_cachel *cachel) | |
1806 { | |
1807 struct window *w = XWINDOW (data->window); | |
1808 | |
440 | 1809 /* If window faces changed, and glyph instance is text, then |
1810 glyph sizes might have changed too */ | |
1811 invalidate_glyph_geometry_maybe (gb->glyph, w); | |
1812 | |
442 | 1813 /* This makes sure the glyph is in the cachels. |
1814 | |
1815 #### We do this to make sure the glyph is in the glyph cachels, | |
1816 so that the dirty flag can be reset after redisplay has | |
1817 finished. We should do this some other way, maybe by iterating | |
1818 over the window cache of subwindows. */ | |
1819 get_glyph_cachel_index (w, gb->glyph); | |
1820 | |
428 | 1821 /* A nil extent indicates a special glyph (ex. truncator). */ |
1822 if (NILP (gb->extent) | |
1823 || (pos_type == BEGIN_GLYPHS && | |
1824 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) | |
1825 || (pos_type == END_GLYPHS && | |
442 | 1826 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) |
1827 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) | |
428 | 1828 { |
1829 struct rune rb; | |
1830 int width; | |
1831 int xoffset = 0; | |
1832 int ascent, descent; | |
1833 Lisp_Object baseline; | |
1834 Lisp_Object face; | |
442 | 1835 Lisp_Object instance; |
1836 face_index findex; | |
819 | 1837 prop_block_dynarr *retval = 0; |
428 | 1838 |
1839 if (cachel) | |
1840 width = cachel->width; | |
1841 else | |
438 | 1842 width = glyph_width (gb->glyph, data->window); |
428 | 1843 |
1844 if (!width) | |
1845 return NULL; | |
1846 | |
1847 if (data->start_col || data->start_col_xoffset) | |
1848 { | |
1849 int glyph_char_width = width / space_width (w); | |
1850 | |
1851 /* If we still have not fully scrolled horizontally after | |
4187 | 1852 taking into account the width of the glyph, subtract its |
1853 width and return. */ | |
428 | 1854 if (glyph_char_width < data->start_col) |
1855 { | |
1856 data->start_col -= glyph_char_width; | |
1857 return NULL; | |
1858 } | |
1859 else if (glyph_char_width == data->start_col) | |
1860 width = 0; | |
1861 else | |
1862 { | |
1863 xoffset = space_width (w) * data->start_col; | |
1864 width -= xoffset; | |
1865 | |
1866 /* #### Can this happen? */ | |
1867 if (width < 0) | |
1868 width = 0; | |
1869 } | |
1870 | |
1871 data->start_col = 0; | |
1872 retval = add_hscroll_rune (data); | |
1873 | |
1874 /* Could be caused by the handling of the hscroll rune. */ | |
1875 if (retval != NULL || !width) | |
1876 return retval; | |
1877 } | |
1878 else | |
1879 xoffset = 0; | |
1880 | |
1881 if (data->pixpos + width > data->max_pixpos) | |
1882 { | |
1883 /* If this is the first object we are attempting to add to | |
819 | 1884 the line then we ignore the horizontal_clip threshold. |
1885 Otherwise we will loop until the bottom of the window | |
1886 continually failing to add this glyph because it is wider | |
1887 than the window. We could alternatively just completely | |
1888 ignore the glyph and proceed from there but I think that | |
1889 this is a better solution. | |
4187 | 1890 |
819 | 1891 This does, however, create a different problem in that we |
1892 can end up adding the object to every single line, never | |
1893 getting any further - for instance an extent with a long | |
1894 start-glyph that covers multitple following | |
1895 characters. */ | |
428 | 1896 if (Dynarr_length (data->db->runes) |
1897 && data->max_pixpos - data->pixpos < horizontal_clip) | |
1898 return ADD_FAILED; | |
819 | 1899 else { |
1900 struct prop_block pb; | |
1901 | |
1902 /* We need to account for the width of the end-of-line | |
1903 glyph if there is nothing more in the line to display, | |
1904 since we will not display it in this instance. It seems | |
1905 kind of gross doing it here, but otherwise we have to | |
1906 search the runes in create_text_block(). */ | |
1907 if (data->ch == '\n') | |
1908 data->max_pixpos += data->end_glyph_width; | |
428 | 1909 width = data->max_pixpos - data->pixpos; |
819 | 1910 /* Add the glyph we are displaying, but clipping, to the |
1911 propagation data so that we don't try and do it | |
4187 | 1912 again. */ |
819 | 1913 retval = Dynarr_new (prop_block); |
1914 pb.type = PROP_GLYPH; | |
1915 pb.data.p_glyph.glyph = gb->glyph; | |
1916 pb.data.p_glyph.width = width; | |
1917 Dynarr_add (retval, pb); | |
1918 } | |
428 | 1919 } |
1920 | |
1921 if (cachel) | |
1922 { | |
1923 ascent = cachel->ascent; | |
1924 descent = cachel->descent; | |
1925 } | |
1926 else | |
1927 { | |
438 | 1928 ascent = glyph_ascent (gb->glyph, data->window); |
1929 descent = glyph_descent (gb->glyph, data->window); | |
428 | 1930 } |
1931 | |
1932 baseline = glyph_baseline (gb->glyph, data->window); | |
1933 | |
819 | 1934 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ |
1935 | |
428 | 1936 if (glyph_contrib_p (gb->glyph, data->window)) |
1937 { | |
1938 /* A pixmap that has not had a baseline explicitly set. Its | |
1939 contribution will be determined later. */ | |
1940 if (NILP (baseline)) | |
1941 { | |
1942 int height = ascent + descent; | |
819 | 1943 data->need_baseline_computation = 1; |
428 | 1944 data->max_pixmap_height = max (data->max_pixmap_height, height); |
1945 } | |
1946 | |
1947 /* A string so determine contribution normally. */ | |
1948 else if (EQ (baseline, Qt)) | |
1949 { | |
1950 data->new_ascent = max (data->new_ascent, ascent); | |
1951 data->new_descent = max (data->new_descent, descent); | |
1952 } | |
1953 | |
1954 /* A pixmap with an explicitly set baseline. We determine the | |
1955 contribution here. */ | |
1956 else if (INTP (baseline)) | |
1957 { | |
1958 int height = ascent + descent; | |
1959 int pix_ascent, pix_descent; | |
1960 | |
1961 pix_ascent = height * XINT (baseline) / 100; | |
1962 pix_descent = height - pix_ascent; | |
1963 | |
1964 data->new_ascent = max (data->new_ascent, pix_ascent); | |
1965 data->new_descent = max (data->new_descent, pix_descent); | |
819 | 1966 data->max_pixmap_height = max (data->max_pixmap_height, height); |
4187 | 1967 |
819 | 1968 rb.object.dglyph.descent = pix_descent; |
428 | 1969 } |
1970 | |
1971 /* Otherwise something is screwed up. */ | |
1972 else | |
2500 | 1973 ABORT (); |
428 | 1974 } |
1975 | |
1976 face = glyph_face (gb->glyph, data->window); | |
1977 if (NILP (face)) | |
442 | 1978 findex = data->findex; |
428 | 1979 else |
442 | 1980 findex = get_builtin_face_cache_index (w, face); |
1981 | |
1982 instance = glyph_image_instance (gb->glyph, data->window, | |
793 | 1983 ERROR_ME_DEBUG_WARN, 1); |
442 | 1984 if (TEXT_IMAGE_INSTANCEP (instance)) |
1985 { | |
1986 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); | |
1987 face_index orig_findex = data->findex; | |
826 | 1988 Bytebpos orig_charpos = data->byte_charpos; |
1989 Bytebpos orig_start_col_enabled = data->byte_start_col_enabled; | |
442 | 1990 |
1991 data->findex = findex; | |
826 | 1992 data->byte_start_col_enabled = 0; |
442 | 1993 if (!allow_cursor) |
826 | 1994 data->byte_charpos = 0; |
867 | 1995 add_ibyte_string_runes (data, XSTRING_DATA (string), |
793 | 1996 XSTRING_LENGTH (string), 0, 1); |
442 | 1997 data->findex = orig_findex; |
826 | 1998 data->byte_charpos = orig_charpos; |
1999 data->byte_start_col_enabled = orig_start_col_enabled; | |
819 | 2000 return retval; |
442 | 2001 } |
2002 | |
2003 rb.findex = findex; | |
428 | 2004 rb.xpos = data->pixpos; |
2005 rb.width = width; | |
826 | 2006 rb.charpos = 0; /* glyphs are never "at" anywhere */ |
2007 if (data->byte_endpos) | |
428 | 2008 /* #### is this necessary at all? */ |
665 | 2009 rb.endpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
826 | 2010 data->byte_endpos); |
428 | 2011 else |
4187 | 2012 rb.endpos = 0; |
428 | 2013 rb.type = RUNE_DGLYPH; |
2014 rb.object.dglyph.glyph = gb->glyph; | |
2015 rb.object.dglyph.extent = gb->extent; | |
2016 rb.object.dglyph.xoffset = xoffset; | |
819 | 2017 rb.object.dglyph.ascent = ascent; |
2018 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has | |
2019 a normal (textual) baseline. */ | |
428 | 2020 |
2021 if (allow_cursor) | |
2022 { | |
826 | 2023 rb.charpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
2024 data->byte_charpos); | |
428 | 2025 |
2026 if (data->cursor_type == CURSOR_ON) | |
2027 { | |
826 | 2028 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 2029 { |
2030 rb.cursor_type = CURSOR_ON; | |
2031 data->cursor_x = Dynarr_length (data->db->runes); | |
2032 } | |
2033 else | |
2034 rb.cursor_type = CURSOR_OFF; | |
2035 } | |
2036 else if (data->cursor_type == NEXT_CURSOR) | |
2037 { | |
2038 rb.cursor_type = CURSOR_ON; | |
2039 data->cursor_x = Dynarr_length (data->db->runes); | |
2040 data->cursor_type = NO_CURSOR; | |
2041 } | |
2042 else if (data->cursor_type == IGNORE_CURSOR) | |
2043 rb.cursor_type = IGNORE_CURSOR; | |
2044 else if (data->cursor_type == NO_CURSOR) | |
2045 rb.cursor_type = NO_CURSOR; | |
2046 else | |
2047 rb.cursor_type = CURSOR_OFF; | |
2048 } | |
2049 else | |
2050 rb.cursor_type = CURSOR_OFF; | |
2051 | |
2052 Dynarr_add (data->db->runes, rb); | |
2053 data->pixpos += width; | |
2054 | |
819 | 2055 return retval; |
428 | 2056 } |
2057 else | |
2058 { | |
2059 if (!NILP (glyph_face (gb->glyph, data->window))) | |
2060 gb->findex = | |
2061 get_builtin_face_cache_index (w, glyph_face (gb->glyph, | |
2062 data->window)); | |
2063 else | |
2064 gb->findex = data->findex; | |
2065 | |
2066 if (pos_type == BEGIN_GLYPHS) | |
2067 { | |
2068 if (!data->dl->left_glyphs) | |
2069 data->dl->left_glyphs = Dynarr_new (glyph_block); | |
2070 Dynarr_add (data->dl->left_glyphs, *gb); | |
2071 return NULL; | |
2072 } | |
2073 else if (pos_type == END_GLYPHS) | |
2074 { | |
2075 if (!data->dl->right_glyphs) | |
2076 data->dl->right_glyphs = Dynarr_new (glyph_block); | |
2077 Dynarr_add (data->dl->right_glyphs, *gb); | |
2078 return NULL; | |
2079 } | |
2080 else | |
2500 | 2081 ABORT (); /* there are no unknown types */ |
428 | 2082 } |
2083 | |
819 | 2084 return NULL; |
428 | 2085 } |
2086 | |
2087 /* Add all glyphs at position POS_TYPE that are contained in the given | |
2088 data. */ | |
2089 | |
2090 static prop_block_dynarr * | |
2091 add_glyph_runes (pos_data *data, int pos_type) | |
2092 { | |
2093 /* #### This still needs to handle the start_col parameter. Duh, Chuck, | |
2094 why didn't you just modify add_glyph_rune in the first place? */ | |
2095 int elt; | |
2096 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS | |
2097 ? data->ef->begin_glyphs | |
2098 : data->ef->end_glyphs); | |
2099 prop_block_dynarr *prop; | |
2100 | |
2101 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++) | |
2102 { | |
2103 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0, | |
2104 0); | |
2105 | |
2106 if (prop) | |
2107 { | |
2108 /* #### Add some propagation information. */ | |
2109 return prop; | |
2110 } | |
2111 } | |
2112 | |
2113 Dynarr_reset (glyph_arr); | |
2114 | |
2115 return NULL; | |
2116 } | |
2117 | |
2118 /* Given a position for a buffer in a window, ensure that the given | |
2119 display line DL accurately represents the text on a line starting | |
2120 at the given position. | |
2121 | |
826 | 2122 NOTE NOTE NOTE NOTE: This function works with and returns Bytebpos's. |
428 | 2123 You must do appropriate conversion. */ |
2124 | |
665 | 2125 static Bytebpos |
428 | 2126 create_text_block (struct window *w, struct display_line *dl, |
826 | 2127 Bytebpos byte_start_pos, prop_block_dynarr **prop, |
428 | 2128 int type) |
2129 { | |
2130 struct frame *f = XFRAME (w->frame); | |
2131 struct buffer *b = XBUFFER (w->buffer); | |
2132 struct device *d = XDEVICE (f->device); | |
2133 | |
2134 pos_data data; | |
2135 | |
2136 /* Don't display anything in the minibuffer if this window is not on | |
2137 a selected frame. We consider all other windows to be active | |
2138 minibuffers as it simplifies the coding. */ | |
2139 int active_minibuffer = (!MINI_WINDOW_P (w) || | |
2140 (f == device_selected_frame (d)) || | |
2141 is_surrogate_for_selected_frame (f)); | |
2142 | |
2143 int truncate_win = window_truncation_on (w); | |
2144 | |
2145 /* If the buffer's value of selective_display is an integer then | |
2146 only lines that start with less than selective_display columns of | |
2147 space will be displayed. If selective_display is t then all text | |
2148 after a ^M is invisible. */ | |
2149 int selective = (INTP (b->selective_display) | |
2150 ? XINT (b->selective_display) | |
434 | 2151 : (!NILP (b->selective_display) ? -1 : 0)); |
428 | 2152 |
2153 /* The variable ctl-arrow allows the user to specify what characters | |
2154 can actually be displayed and which octal should be used for. | |
2155 #### This variable should probably have some rethought done to | |
2156 it. | |
2157 | |
2367 | 2158 See also |
2159 | |
2160 (Info-goto-node "(internals)Future Work -- Display Tables") | |
2161 | |
2162 */ | |
867 | 2163 Ichar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
428 | 2164 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
2165 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
2166 ? 255 : 160)); | |
2167 | |
2168 Lisp_Object face_dt, window_dt; | |
2169 | |
2170 /* The text display block for this display line. */ | |
2171 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
2172 | |
2173 /* The first time through the main loop we need to force the glyph | |
2174 data to be updated. */ | |
2175 int initial = 1; | |
2176 | |
2177 /* Apparently the new extent_fragment_update returns an end position | |
2178 equal to the position passed in if there are no more runs to be | |
2179 displayed. */ | |
2180 int no_more_frags = 0; | |
2181 | |
2182 Lisp_Object synch_minibuffers_value = | |
2183 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer); | |
2184 | |
2185 dl->used_prop_data = 0; | |
2186 dl->num_chars = 0; | |
442 | 2187 dl->line_continuation = 0; |
428 | 2188 |
2189 xzero (data); | |
2190 data.ef = extent_fragment_new (w->buffer, f); | |
2191 | |
2192 /* These values are used by all of the rune addition routines. We add | |
2193 them to this structure for ease of passing. */ | |
2194 data.d = d; | |
793 | 2195 data.window = wrap_window (w); |
428 | 2196 data.string = Qnil; |
2197 data.db = db; | |
2198 data.dl = dl; | |
2199 | |
826 | 2200 data.byte_charpos = byte_start_pos; |
428 | 2201 data.pixpos = dl->bounds.left_in; |
2202 data.last_charset = Qunbound; | |
2203 data.last_findex = DEFAULT_INDEX; | |
2204 data.result_str = Qnil; | |
2205 | |
2206 /* Set the right boundary adjusting it to take into account any end | |
2207 glyph. Save the width of the end glyph for later use. */ | |
2208 data.max_pixpos = dl->bounds.right_in; | |
2209 if (truncate_win) | |
819 | 2210 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); |
428 | 2211 else |
819 | 2212 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); |
2213 data.max_pixpos -= data.end_glyph_width; | |
428 | 2214 |
2215 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f)) | |
2216 { | |
826 | 2217 data.byte_cursor_charpos = BYTE_BUF_ZV (b); |
428 | 2218 data.cursor_type = CURSOR_ON; |
2219 } | |
2220 else if (MINI_WINDOW_P (w) && !active_minibuffer) | |
2221 data.cursor_type = NO_CURSOR; | |
2222 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) && | |
2223 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
2224 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&& | |
2225 f == XFRAME(DEVICE_SELECTED_FRAME(d))) | |
2226 { | |
826 | 2227 data.byte_cursor_charpos = BYTE_BUF_PT (b); |
428 | 2228 data.cursor_type = CURSOR_ON; |
2229 } | |
2230 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | |
2231 { | |
826 | 2232 data.byte_cursor_charpos = byte_marker_position (w->pointm[type]); |
428 | 2233 data.cursor_type = CURSOR_ON; |
2234 } | |
2235 else | |
2236 data.cursor_type = NO_CURSOR; | |
2237 data.cursor_x = -1; | |
2238 | |
2239 data.start_col = w->hscroll; | |
2240 data.start_col_xoffset = w->left_xoffset; | |
826 | 2241 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
428 | 2242 data.hscroll_glyph_width_adjust = 0; |
2243 | |
2244 /* We regenerate the line from the very beginning. */ | |
2245 Dynarr_reset (db->runes); | |
2246 | |
2247 /* Why is this less than or equal and not just less than? If the | |
2248 starting position is already equal to the maximum we can't add | |
2249 anything else, right? Wrong. We might still have a newline to | |
2250 add. A newline can use the room allocated for an end glyph since | |
2251 if we add it we know we aren't going to be adding any end | |
2252 glyph. */ | |
2253 | |
2254 /* #### Chuck -- I think this condition should be while (1). | |
2255 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
2256 and the begin-glyph ends exactly at the end of the window, the | |
2257 end-glyph and text might not be displayed. while (1) ensures | |
2258 that the loop terminates only when either (a) there is | |
2259 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
2260 | |
2261 #### Also I think you need to ensure that the operation | |
2262 "add begin glyphs; add end glyphs; add text" is atomic and | |
2263 can't get interrupted in the middle. If you run off the end | |
2264 of the line during that operation, then you keep accumulating | |
2265 propagation data until you're done. Otherwise, if the (e.g.) | |
2266 there's a begin glyph at a particular position and attempting | |
2267 to display that glyph results in window-end being hit and | |
2268 propagation data being generated, then the character at that | |
2269 position won't be displayed. | |
2270 | |
2271 #### See also the comment after the end of this loop, below. | |
2272 */ | |
2273 while (data.pixpos <= data.max_pixpos | |
2274 && (active_minibuffer || !NILP (synch_minibuffers_value))) | |
2275 { | |
2276 /* #### This check probably should not be necessary. */ | |
826 | 2277 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
428 | 2278 { |
2279 /* #### urk! More of this lossage! */ | |
826 | 2280 data.byte_charpos--; |
428 | 2281 goto done; |
2282 } | |
2283 | |
2284 /* If selective display was an integer and we aren't working on | |
4187 | 2285 a continuation line then find the next line we are actually |
2286 supposed to display. */ | |
428 | 2287 if (selective > 0 |
826 | 2288 && (data.byte_charpos == BYTE_BUF_BEGV (b) |
2289 || BUF_FETCH_CHAR (b, prev_bytebpos (b, data.byte_charpos)) == '\n')) | |
2290 { | |
2291 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
428 | 2292 { |
826 | 2293 data.byte_charpos = |
2294 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2295 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
428 | 2296 { |
826 | 2297 data.byte_charpos = BYTE_BUF_ZV (b); |
428 | 2298 goto done; |
2299 } | |
2300 } | |
2301 } | |
2302 | |
2303 /* Check for face changes. */ | |
826 | 2304 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
428 | 2305 { |
819 | 2306 Lisp_Object last_glyph = Qnil; |
2307 | |
2308 /* Deal with glyphs that we have already displayed. The | |
2309 theory is that if we end up with a PROP_GLYPH in the | |
2310 propagation data then we are clipping the glyph and there | |
2311 can be no propagation data before that point. The theory | |
2312 works because we always recalculate the extent-fragments | |
2313 for propagated data, we never actually propagate the | |
2314 fragments that still need to be displayed. */ | |
4967 | 2315 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
2316 { | |
2317 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
819 | 2318 Dynarr_free (*prop); |
2319 *prop = 0; | |
2320 } | |
428 | 2321 /* Now compute the face and begin/end-glyph information. */ |
2322 data.findex = | |
665 | 2323 /* Remember that the extent-fragment routines deal in Bytebpos's. */ |
826 | 2324 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
428 | 2325 |
2326 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
2327 | |
826 | 2328 if (data.byte_charpos == data.ef->end) |
428 | 2329 no_more_frags = 1; |
2330 } | |
2331 initial = 0; | |
2332 | |
2333 /* Determine what is next to be displayed. We first handle any | |
4187 | 2334 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
2335 display then we determine what to do based on the character at the | |
2336 current buffer position. */ | |
428 | 2337 |
2338 /* If the current position is covered by an invisible extent, do | |
4187 | 2339 nothing (except maybe add some ellipses). |
428 | 2340 |
2341 #### The behavior of begin and end-glyphs at the edge of an | |
2342 invisible extent should be investigated further. This is | |
2343 fairly low priority though. */ | |
2344 if (data.ef->invisible) | |
2345 { | |
2346 /* #### Chuck, perhaps you could look at this code? I don't | |
2347 really know what I'm doing. */ | |
2348 if (*prop) | |
2349 { | |
2350 Dynarr_free (*prop); | |
2351 *prop = 0; | |
2352 } | |
2353 | |
2354 /* The extent fragment code only sets this when we should | |
2355 really display the ellipses. It makes sure the ellipses | |
2356 don't get displayed more than once in a row. */ | |
2357 if (data.ef->invisible_ellipses) | |
2358 { | |
2359 struct glyph_block gb; | |
2360 | |
2361 data.ef->invisible_ellipses_already_displayed = 1; | |
2362 data.ef->invisible_ellipses = 0; | |
2363 gb.extent = Qnil; | |
2364 gb.glyph = Vinvisible_text_glyph; | |
2365 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2366 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2367 /* Perhaps they shouldn't propagate if the very next thing | |
2368 is to display a newline (for compatibility with | |
2369 selective-display-ellipses)? Maybe that's too | |
2370 abstruse. */ | |
2371 if (*prop) | |
2372 goto done; | |
2373 } | |
2374 | |
2375 /* If point is in an invisible region we place it on the | |
4187 | 2376 next visible character. */ |
428 | 2377 if (data.cursor_type == CURSOR_ON |
826 | 2378 && data.byte_charpos == data.byte_cursor_charpos) |
428 | 2379 { |
2380 data.cursor_type = NEXT_CURSOR; | |
2381 } | |
2382 | |
2383 /* #### What if we we're dealing with a display table? */ | |
2384 if (data.start_col) | |
2385 data.start_col--; | |
2386 | |
826 | 2387 if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2388 goto done; |
2389 else | |
826 | 2390 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2391 } |
2392 | |
2393 /* If there is propagation data, then it represents the current | |
819 | 2394 buffer position being displayed. Add them and advance the |
2395 position counter. This might also add the minibuffer | |
2396 prompt. */ | |
428 | 2397 else if (*prop) |
2398 { | |
2399 dl->used_prop_data = 1; | |
2400 *prop = add_propagation_runes (prop, &data); | |
2401 | |
2402 if (*prop) | |
2403 goto done; /* gee, a really narrow window */ | |
826 | 2404 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2405 goto done; |
826 | 2406 else if (data.byte_charpos < BYTE_BUF_BEGV (b)) |
428 | 2407 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
826 | 2408 data.byte_charpos = BYTE_BUF_BEGV (b); |
428 | 2409 else |
826 | 2410 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2411 } |
2412 | |
2413 /* If there are end glyphs, add them to the line. These are | |
2414 the end glyphs for the previous run of text. We add them | |
2415 here rather than doing them at the end of handling the | |
2416 previous run so that glyphs at the beginning and end of | |
2417 a line are handled correctly. */ | |
819 | 2418 else if (Dynarr_length (data.ef->end_glyphs) > 0 |
2419 || Dynarr_length (data.ef->begin_glyphs) > 0) | |
2420 { | |
2421 glyph_block_dynarr* tmpglyphs = 0; | |
2422 /* #### I think this is safe, but could be wrong. */ | |
826 | 2423 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
819 | 2424 |
4187 | 2425 if (Dynarr_length (data.ef->end_glyphs) > 0) |
819 | 2426 { |
2427 *prop = add_glyph_runes (&data, END_GLYPHS); | |
2428 tmpglyphs = data.ef->end_glyphs; | |
2429 } | |
2430 | |
2431 /* If there are begin glyphs, add them to the line. */ | |
4187 | 2432 if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0) |
819 | 2433 { |
2434 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); | |
2435 tmpglyphs = data.ef->begin_glyphs; | |
2436 } | |
2437 | |
4187 | 2438 if (*prop) |
819 | 2439 { |
2440 /* If we just clipped a glyph and we are at the end of a | |
2441 line and there are more glyphs to display then do | |
2442 appropriate processing to not get a continuation | |
2443 glyph. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2444 if (*prop != ADD_FAILED |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2445 && Dynarr_begin (*prop)->type == PROP_GLYPH |
819 | 2446 && data.ch == '\n') |
4187 | 2447 { |
819 | 2448 /* If there are no more glyphs then do the normal |
4187 | 2449 processing. |
819 | 2450 |
2451 #### This doesn't actually work if the same glyph is | |
2452 present more than once in the block. To solve | |
2453 this we would have to carry the index around | |
2454 which might be problematic since the fragment is | |
2455 recalculated for each line. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2456 if (EQ (Dynarr_lastp (tmpglyphs)->glyph, |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2457 Dynarr_begin (*prop)->data.p_glyph.glyph)) |
819 | 2458 { |
2459 Dynarr_free (*prop); | |
2460 *prop = 0; | |
2461 } | |
2462 else { | |
2463 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2464 add_ichar_rune (&data); /* discard prop data. */ |
819 | 2465 goto done; |
2466 } | |
2467 } | |
2468 else | |
2469 goto done; | |
2470 } | |
428 | 2471 } |
2472 | |
2473 /* If at end-of-buffer, we've already processed begin and | |
2474 end-glyphs at this point and there's no text to process, | |
2475 so we're done. */ | |
826 | 2476 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2477 goto done; |
2478 | |
2479 else | |
2480 { | |
2481 Lisp_Object entry = Qnil; | |
2482 /* Get the character at the current buffer position. */ | |
826 | 2483 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
428 | 2484 if (!NILP (face_dt) || !NILP (window_dt)) |
2485 entry = display_table_entry (data.ch, face_dt, window_dt); | |
2486 | |
2487 /* If there is a display table entry for it, hand it off to | |
4187 | 2488 add_disp_table_entry_runes and let it worry about it. */ |
428 | 2489 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
2490 { | |
2491 *prop = add_disp_table_entry_runes (&data, entry); | |
2492 | |
2493 if (*prop) | |
2494 goto done; | |
2495 } | |
2496 | |
2497 /* Check if we have hit a newline character. If so, add a marker | |
4187 | 2498 to the line and end this loop. */ |
428 | 2499 else if (data.ch == '\n') |
2500 { | |
2501 /* We aren't going to be adding an end glyph so give its | |
4187 | 2502 space back in order to make sure that the cursor can |
2503 fit. */ | |
819 | 2504 data.max_pixpos += data.end_glyph_width; |
428 | 2505 |
2506 if (selective > 0 | |
826 | 2507 && (byte_spaces_at_point |
2508 (b, next_bytebpos (b, data.byte_charpos)) | |
428 | 2509 >= selective)) |
2510 { | |
2511 if (!NILP (b->selective_display_ellipses)) | |
2512 { | |
2513 struct glyph_block gb; | |
2514 | |
2515 gb.extent = Qnil; | |
2516 gb.glyph = Vinvisible_text_glyph; | |
2517 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2518 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2519 } | |
2520 else | |
2521 { | |
2522 /* Cheesy, cheesy, cheesy. We mark the end of the | |
2523 line with a special "character rune" whose width | |
2524 is the EOL cursor width and whose character is | |
2525 the non-printing character '\n'. */ | |
2526 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2527 *prop = add_ichar_rune (&data); |
428 | 2528 } |
2529 | |
826 | 2530 /* We need to set data.byte_charpos to the start of the |
4187 | 2531 next visible region in order to make this line |
2532 appear to contain all of the invisible area. | |
2533 Otherwise, the line cache won't work | |
2534 correctly. */ | |
826 | 2535 INC_BYTEBPOS (b, data.byte_charpos); |
2536 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
428 | 2537 { |
826 | 2538 data.byte_charpos = |
2539 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2540 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
428 | 2541 { |
826 | 2542 data.byte_charpos = BYTE_BUF_ZV (b); |
428 | 2543 break; |
2544 } | |
2545 } | |
826 | 2546 if (BYTE_BUF_FETCH_CHAR |
2547 (b, prev_bytebpos (b, data.byte_charpos)) == '\n') | |
2548 DEC_BYTEBPOS (b, data.byte_charpos); | |
428 | 2549 } |
2550 else | |
2551 { | |
2552 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2553 *prop = add_ichar_rune (&data); |
428 | 2554 } |
2555 | |
2556 goto done; | |
2557 } | |
2558 | |
2559 /* If the current character is ^M, and selective display is | |
4187 | 2560 enabled, then add the invisible-text-glyph if |
2561 selective-display-ellipses is set. In any case, this | |
2562 line is done. */ | |
428 | 2563 else if (data.ch == (('M' & 037)) && selective == -1) |
2564 { | |
826 | 2565 Bytebpos byte_next_charpos; |
428 | 2566 |
2567 /* Find the buffer position at the end of the line. */ | |
826 | 2568 byte_next_charpos = |
2569 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2570 if (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_next_charpos)) | |
428 | 2571 == '\n') |
826 | 2572 DEC_BYTEBPOS (b, byte_next_charpos); |
428 | 2573 |
2574 /* If the cursor is somewhere in the elided text make | |
4187 | 2575 sure that the cursor gets drawn appropriately. */ |
428 | 2576 if (data.cursor_type == CURSOR_ON |
826 | 2577 && (data.byte_cursor_charpos >= data.byte_charpos && |
2578 data.byte_cursor_charpos < byte_next_charpos)) | |
428 | 2579 { |
2580 data.cursor_type = NEXT_CURSOR; | |
2581 } | |
2582 | |
2583 /* We won't be adding a truncation or continuation glyph | |
4187 | 2584 so give up the room allocated for them. */ |
819 | 2585 data.max_pixpos += data.end_glyph_width; |
428 | 2586 |
2587 if (!NILP (b->selective_display_ellipses)) | |
2588 { | |
2589 /* We don't propagate anything from the invisible | |
4187 | 2590 text glyph if it fails to fit. This is |
2591 intentional. */ | |
428 | 2592 struct glyph_block gb; |
2593 | |
2594 gb.extent = Qnil; | |
2595 gb.glyph = Vinvisible_text_glyph; | |
2596 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, | |
2597 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2598 } | |
2599 | |
2600 /* Set the buffer position to the end of the line. We | |
4187 | 2601 need to do this before potentially adding a newline |
2602 so that the cursor flag will get set correctly (if | |
2603 needed). */ | |
826 | 2604 data.byte_charpos = byte_next_charpos; |
428 | 2605 |
2606 if (NILP (b->selective_display_ellipses) | |
826 | 2607 || data.byte_cursor_charpos == byte_next_charpos) |
428 | 2608 { |
2609 /* We have to at least add a newline character so | |
4187 | 2610 that the cursor shows up properly. */ |
428 | 2611 data.ch = '\n'; |
2612 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2613 data.findex = DEFAULT_INDEX; | |
2614 data.start_col = 0; | |
2615 data.start_col_xoffset = 0; | |
826 | 2616 data.byte_start_col_enabled = 0; |
428 | 2617 |
867 | 2618 add_ichar_rune (&data); |
428 | 2619 } |
2620 | |
2621 /* This had better be a newline but doing it this way | |
4187 | 2622 we'll see obvious incorrect results if it isn't. No |
2623 need to abort here. */ | |
826 | 2624 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
428 | 2625 |
2626 goto done; | |
2627 } | |
2628 | |
2629 /* If the current character is considered to be printable, then | |
4187 | 2630 just add it. */ |
428 | 2631 else if (data.ch >= printable_min) |
2632 { | |
867 | 2633 *prop = add_ichar_rune (&data); |
428 | 2634 if (*prop) |
2635 goto done; | |
2636 } | |
2637 | |
2638 /* If the current character is a tab, determine the next tab | |
4187 | 2639 starting position and add a blank rune which extends from the |
2640 current pixel position to that starting position. */ | |
428 | 2641 else if (data.ch == '\t') |
2642 { | |
2643 int tab_start_pixpos = data.pixpos; | |
2644 int next_tab_start; | |
2645 int char_tab_width; | |
2646 int prop_width = 0; | |
2647 | |
2648 if (data.start_col > 1) | |
434 | 2649 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)) |
428 | 2650 + data.start_col_xoffset; |
2651 | |
2652 next_tab_start = | |
2653 next_tab_position (w, tab_start_pixpos, | |
2654 dl->bounds.left_in + | |
2655 data.hscroll_glyph_width_adjust); | |
2656 if (next_tab_start > data.max_pixpos) | |
2657 { | |
2658 prop_width = next_tab_start - data.max_pixpos; | |
2659 next_tab_start = data.max_pixpos; | |
2660 } | |
2661 data.blank_width = next_tab_start - data.pixpos; | |
2662 char_tab_width = | |
2663 (next_tab_start - tab_start_pixpos) / space_width (w); | |
2664 | |
2665 *prop = add_blank_rune (&data, w, char_tab_width); | |
2666 | |
2667 /* add_blank_rune is only supposed to be called with | |
4187 | 2668 sizes guaranteed to fit in the available space. */ |
428 | 2669 assert (!(*prop)); |
2670 | |
2671 if (prop_width) | |
2672 { | |
2673 struct prop_block pb; | |
2674 *prop = Dynarr_new (prop_block); | |
2675 | |
2676 pb.type = PROP_BLANK; | |
2677 pb.data.p_blank.width = prop_width; | |
2678 pb.data.p_blank.findex = data.findex; | |
2679 Dynarr_add (*prop, pb); | |
2680 | |
2681 goto done; | |
2682 } | |
2683 } | |
2684 | |
2685 /* If character is a control character, pass it off to | |
4187 | 2686 add_control_char_runes. |
428 | 2687 |
2688 The is_*() routines have undefined results on | |
2689 arguments outside of the range [-1, 255]. (This | |
2690 often bites people who carelessly use `char' instead | |
2691 of `unsigned char'.) | |
2692 */ | |
867 | 2693 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
428 | 2694 { |
2695 *prop = add_control_char_runes (&data, b); | |
2696 | |
2697 if (*prop) | |
2698 goto done; | |
2699 } | |
2700 | |
2701 /* If the character is above the ASCII range and we have not | |
4187 | 2702 already handled it, then print it as an octal number. */ |
428 | 2703 else if (data.ch >= 0200) |
2704 { | |
2705 *prop = add_octal_runes (&data); | |
2706 | |
2707 if (*prop) | |
2708 goto done; | |
2709 } | |
2710 | |
2711 /* Assume the current character is considered to be printable, | |
4187 | 2712 then just add it. */ |
428 | 2713 else |
2714 { | |
867 | 2715 *prop = add_ichar_rune (&data); |
428 | 2716 if (*prop) |
2717 goto done; | |
2718 } | |
2719 | |
826 | 2720 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2721 } |
2722 } | |
2723 | |
2724 done: | |
2725 | |
2726 /* Determine the starting point of the next line if we did not hit the | |
2727 end of the buffer. */ | |
826 | 2728 if (data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 2729 && (active_minibuffer || !NILP (synch_minibuffers_value))) |
2730 { | |
2731 /* #### This check is not correct. If the line terminated | |
2732 due to a begin-glyph or end-glyph hitting window-end, then | |
826 | 2733 data.ch will not point to the character at data.byte_charpos. If |
428 | 2734 you make the two changes mentioned at the top of this loop, |
2735 you should be able to say '(if (*prop))'. That should also | |
826 | 2736 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 2737 check. */ |
2738 | |
2739 /* The common case is that the line ended because we hit a newline. | |
4187 | 2740 In that case, the next character is just the next buffer |
2741 position. */ | |
428 | 2742 if (data.ch == '\n') |
2743 { | |
2744 /* If data.start_col_enabled is still true, then the window is | |
4187 | 2745 scrolled far enough so that nothing on this line is visible. |
2746 We need to stick a truncation glyph at the beginning of the | |
2747 line in that case unless the line is completely blank. */ | |
826 | 2748 if (data.byte_start_col_enabled) |
428 | 2749 { |
2750 if (data.cursor_type == CURSOR_ON) | |
2751 { | |
826 | 2752 if (data.byte_cursor_charpos >= byte_start_pos |
2753 && data.byte_cursor_charpos <= data.byte_charpos) | |
2754 data.byte_cursor_charpos = data.byte_charpos; | |
428 | 2755 } |
2756 data.findex = DEFAULT_INDEX; | |
2757 data.start_col = 0; | |
826 | 2758 data.byte_start_col_enabled = 0; |
2759 | |
2760 if (data.byte_charpos != byte_start_pos) | |
428 | 2761 { |
2762 struct glyph_block gb; | |
2763 | |
2764 gb.extent = Qnil; | |
2765 gb.glyph = Vhscroll_glyph; | |
2766 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2767 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX)); | |
2768 } | |
2769 else | |
2770 { | |
2771 /* This duplicates code down below to add a newline to | |
4187 | 2772 the end of an otherwise empty line.*/ |
428 | 2773 data.ch = '\n'; |
2774 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2775 | |
867 | 2776 add_ichar_rune (&data); |
428 | 2777 } |
2778 } | |
2779 | |
826 | 2780 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2781 } |
2782 | |
2783 /* Otherwise we have a buffer line which cannot fit on one display | |
4187 | 2784 line. */ |
428 | 2785 else |
2786 { | |
2787 struct glyph_block gb; | |
2788 struct glyph_cachel *cachel; | |
2789 | |
2790 /* If the line is to be truncated then we actually have to look | |
4187 | 2791 for the next newline. We also add the end-of-line glyph which |
2792 we know will fit because we adjusted the right border before | |
2793 we starting laying out the line. */ | |
819 | 2794 data.max_pixpos += data.end_glyph_width; |
428 | 2795 data.findex = DEFAULT_INDEX; |
2796 gb.extent = Qnil; | |
2797 | |
2798 if (truncate_win) | |
2799 { | |
826 | 2800 Bytebpos byte_pos; |
428 | 2801 |
2802 /* Now find the start of the next line. */ | |
826 | 2803 byte_pos = byte_find_next_newline_no_quit (b, data.byte_charpos, 1); |
428 | 2804 |
2805 /* If the cursor is past the truncation line then we | |
4187 | 2806 make it appear on the truncation glyph. If we've hit |
2807 the end of the buffer then we also make the cursor | |
2808 appear unless eob is immediately preceded by a | |
2809 newline. In that case the cursor should actually | |
2810 appear on the next line. */ | |
428 | 2811 if (data.cursor_type == CURSOR_ON |
826 | 2812 && data.byte_cursor_charpos >= data.byte_charpos |
2813 && (data.byte_cursor_charpos < byte_pos || | |
2814 (byte_pos == BYTE_BUF_ZV (b) | |
2815 && (byte_pos == BYTE_BUF_BEGV (b) | |
2816 || (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_pos)) | |
428 | 2817 != '\n'))))) |
826 | 2818 data.byte_cursor_charpos = byte_pos; |
428 | 2819 else |
2820 data.cursor_type = NO_CURSOR; | |
2821 | |
826 | 2822 data.byte_charpos = byte_pos; |
428 | 2823 gb.glyph = Vtruncation_glyph; |
2824 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
2825 } | |
2826 else | |
2827 { | |
2828 /* The cursor can never be on the continuation glyph. */ | |
2829 data.cursor_type = NO_CURSOR; | |
2830 | |
826 | 2831 /* data.byte_charpos is already at the start of the next line. */ |
428 | 2832 |
442 | 2833 dl->line_continuation = 1; |
428 | 2834 gb.glyph = Vcontinuation_glyph; |
2835 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
2836 } | |
2837 | |
442 | 2838 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
428 | 2839 |
826 | 2840 if (truncate_win && data.byte_charpos == BYTE_BUF_ZV (b) |
2841 && BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, BYTE_BUF_ZV (b))) != '\n') | |
428 | 2842 /* #### Damn this losing shit. */ |
826 | 2843 data.byte_charpos++; |
428 | 2844 } |
2845 } | |
2846 else if ((active_minibuffer || !NILP (synch_minibuffers_value)) | |
826 | 2847 && (!echo_area_active (f) || data.byte_charpos == BYTE_BUF_ZV (b))) |
428 | 2848 { |
2849 /* We need to add a marker to the end of the line since there is no | |
4187 | 2850 newline character in order for the cursor to get drawn. We label |
2851 it as a newline so that it gets handled correctly by the | |
2852 whitespace routines below. */ | |
428 | 2853 |
2854 data.ch = '\n'; | |
2855 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2856 data.findex = DEFAULT_INDEX; | |
2857 data.start_col = 0; | |
2858 data.start_col_xoffset = 0; | |
826 | 2859 data.byte_start_col_enabled = 0; |
428 | 2860 |
2861 data.max_pixpos += data.blank_width; | |
867 | 2862 add_ichar_rune (&data); |
428 | 2863 data.max_pixpos -= data.blank_width; |
2864 | |
2865 /* #### urk! Chuck, this shit is bad news. Going around | |
2866 manipulating invalid positions is guaranteed to result in | |
2867 trouble sooner or later. */ | |
826 | 2868 data.byte_charpos = BYTE_BUF_ZV (b) + 1; |
428 | 2869 } |
2870 | |
2871 /* Calculate left whitespace boundary. */ | |
2872 { | |
2873 int elt = 0; | |
2874 | |
2875 /* Whitespace past a newline is considered right whitespace. */ | |
2876 while (elt < Dynarr_length (db->runes)) | |
2877 { | |
2878 struct rune *rb = Dynarr_atp (db->runes, elt); | |
2879 | |
2880 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
2881 || rb->type == RUNE_BLANK) | |
2882 { | |
2883 dl->bounds.left_white += rb->width; | |
2884 elt++; | |
2885 } | |
2886 else | |
2887 elt = Dynarr_length (db->runes); | |
2888 } | |
2889 } | |
2890 | |
2891 /* Calculate right whitespace boundary. */ | |
2892 { | |
2893 int elt = Dynarr_length (db->runes) - 1; | |
2894 int done = 0; | |
2895 | |
2896 while (!done && elt >= 0) | |
2897 { | |
2898 struct rune *rb = Dynarr_atp (db->runes, elt); | |
2899 | |
2900 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
2901 && isspace (rb->object.chr.ch)) | |
2902 && !rb->type == RUNE_BLANK) | |
2903 { | |
2904 dl->bounds.right_white = rb->xpos + rb->width; | |
2905 done = 1; | |
2906 } | |
2907 | |
2908 elt--; | |
2909 | |
2910 } | |
2911 | |
2912 /* The line is blank so everything is considered to be right | |
2913 whitespace. */ | |
2914 if (!done) | |
2915 dl->bounds.right_white = dl->bounds.left_in; | |
2916 } | |
2917 | |
2918 /* Set the display blocks bounds. */ | |
2919 db->start_pos = dl->bounds.left_in; | |
2920 if (Dynarr_length (db->runes)) | |
2921 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2922 struct rune *rb = Dynarr_lastp (db->runes); |
428 | 2923 |
2924 db->end_pos = rb->xpos + rb->width; | |
2925 } | |
2926 else | |
2927 db->end_pos = dl->bounds.right_white; | |
2928 | |
819 | 2929 calculate_baseline (&data); |
428 | 2930 |
2931 dl->ascent = data.new_ascent; | |
2932 dl->descent = data.new_descent; | |
2933 | |
2934 { | |
2935 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
2936 | |
2937 if (dl->ascent < ascent) | |
2938 dl->ascent = ascent; | |
2939 } | |
2940 { | |
2941 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
2942 | |
2943 if (dl->descent < descent) | |
2944 dl->descent = descent; | |
2945 } | |
2946 | |
819 | 2947 calculate_yoffset (dl, db); |
2948 | |
428 | 2949 dl->cursor_elt = data.cursor_x; |
2950 /* #### lossage lossage lossage! Fix this shit! */ | |
826 | 2951 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
2952 dl->end_charpos = BUF_ZV (b); | |
428 | 2953 else |
826 | 2954 dl->end_charpos = bytebpos_to_charbpos (b, data.byte_charpos) - 1; |
428 | 2955 if (truncate_win) |
826 | 2956 data.dl->num_chars = column_at_point (b, dl->end_charpos, 0); |
428 | 2957 else |
2958 /* This doesn't correctly take into account tabs and control | |
2959 characters but if the window isn't being truncated then this | |
2960 value isn't going to end up being used anyhow. */ | |
826 | 2961 data.dl->num_chars = dl->end_charpos - dl->charpos; |
428 | 2962 |
2963 /* #### handle horizontally scrolled line with text none of which | |
2964 was actually laid out. */ | |
2965 | |
2966 /* #### handle any remainder of overlay arrow */ | |
2967 | |
2968 if (*prop == ADD_FAILED) | |
2969 *prop = NULL; | |
2970 | |
2971 if (truncate_win && *prop) | |
2972 { | |
2973 Dynarr_free (*prop); | |
2974 *prop = NULL; | |
2975 } | |
2976 | |
2977 extent_fragment_delete (data.ef); | |
2978 | |
2979 /* #### If we started at EOB, then make sure we return a value past | |
2980 it so that regenerate_window will exit properly. This is bogus. | |
2981 The main loop should get fixed so that it isn't necessary to call | |
2982 this function if we are already at EOB. */ | |
2983 | |
826 | 2984 if (data.byte_charpos == BYTE_BUF_ZV (b) && byte_start_pos == BYTE_BUF_ZV (b)) |
2985 return data.byte_charpos + 1; /* Yuck! */ | |
428 | 2986 else |
826 | 2987 return data.byte_charpos; |
428 | 2988 } |
2989 | |
2990 /* Display the overlay arrow at the beginning of the given line. */ | |
2991 | |
2992 static int | |
2993 create_overlay_glyph_block (struct window *w, struct display_line *dl) | |
2994 { | |
2995 struct frame *f = XFRAME (w->frame); | |
2996 struct device *d = XDEVICE (f->device); | |
2997 pos_data data; | |
2998 | |
2999 /* If Voverlay_arrow_string isn't valid then just fail silently. */ | |
3000 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string)) | |
3001 return 0; | |
3002 | |
3003 xzero (data); | |
3004 data.ef = NULL; | |
3005 data.d = d; | |
793 | 3006 data.window = wrap_window (w); |
428 | 3007 data.db = get_display_block_from_line (dl, OVERWRITE); |
3008 data.dl = dl; | |
3009 data.pixpos = dl->bounds.left_in; | |
3010 data.max_pixpos = dl->bounds.right_in; | |
3011 data.cursor_type = NO_CURSOR; | |
3012 data.cursor_x = -1; | |
3013 data.findex = DEFAULT_INDEX; | |
3014 data.last_charset = Qunbound; | |
3015 data.last_findex = DEFAULT_INDEX; | |
3016 data.result_str = Qnil; | |
3017 data.string = Qnil; | |
3018 | |
3019 Dynarr_reset (data.db->runes); | |
3020 | |
3021 if (STRINGP (Voverlay_arrow_string)) | |
3022 { | |
867 | 3023 add_ibyte_string_runes |
428 | 3024 (&data, |
3025 XSTRING_DATA (Voverlay_arrow_string), | |
3026 XSTRING_LENGTH (Voverlay_arrow_string), | |
793 | 3027 1, 0); |
428 | 3028 } |
3029 else if (GLYPHP (Voverlay_arrow_string)) | |
3030 { | |
3031 struct glyph_block gb; | |
3032 | |
3033 gb.glyph = Voverlay_arrow_string; | |
3034 gb.extent = Qnil; | |
3035 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0); | |
3036 } | |
4187 | 3037 |
428 | 3038 if (data.max_pixmap_height) |
3039 { | |
3040 int height = data.new_ascent + data.new_descent; | |
3041 int pix_ascent, pix_descent; | |
4187 | 3042 |
428 | 3043 pix_descent = data.max_pixmap_height * data.new_descent / height; |
3044 pix_ascent = data.max_pixmap_height - pix_descent; | |
819 | 3045 calculate_baseline (&data); |
428 | 3046 |
3047 data.new_ascent = max (data.new_ascent, pix_ascent); | |
3048 data.new_descent = max (data.new_descent, pix_descent); | |
3049 } | |
3050 | |
3051 dl->ascent = data.new_ascent; | |
3052 dl->descent = data.new_descent; | |
3053 | |
3054 data.db->start_pos = dl->bounds.left_in; | |
3055 data.db->end_pos = data.pixpos; | |
3056 | |
819 | 3057 calculate_yoffset (dl, data.db); |
3058 | |
428 | 3059 return data.pixpos - dl->bounds.left_in; |
3060 } | |
3061 | |
3062 /* Add a type of glyph to a margin display block. */ | |
3063 | |
3064 static int | |
3065 add_margin_runes (struct display_line *dl, struct display_block *db, int start, | |
3066 int count, enum glyph_layout layout, int side, Lisp_Object window) | |
3067 { | |
3068 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS | |
3069 ? dl->left_glyphs | |
3070 : dl->right_glyphs); | |
3071 int elt, end; | |
3072 int reverse; | |
442 | 3073 struct window *w = XWINDOW (window); |
3074 struct frame *f = XFRAME (w->frame); | |
3075 struct device *d = XDEVICE (f->device); | |
3076 pos_data data; | |
3077 | |
3078 xzero (data); | |
3079 data.d = d; | |
3080 data.window = window; | |
3081 data.db = db; | |
3082 data.dl = dl; | |
3083 data.pixpos = start; | |
3084 data.cursor_type = NO_CURSOR; | |
3085 data.cursor_x = -1; | |
3086 data.last_charset = Qunbound; | |
3087 data.last_findex = DEFAULT_INDEX; | |
3088 data.result_str = Qnil; | |
3089 data.string = Qnil; | |
3090 data.new_ascent = dl->ascent; | |
3091 data.new_descent = dl->descent; | |
428 | 3092 |
3093 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) | |
3094 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) | |
3095 { | |
3096 reverse = 1; | |
3097 elt = Dynarr_length (gbd) - 1; | |
3098 end = 0; | |
3099 } | |
3100 else | |
3101 { | |
3102 reverse = 0; | |
3103 elt = 0; | |
3104 end = Dynarr_length (gbd); | |
3105 } | |
3106 | |
3107 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) | |
3108 { | |
3109 struct glyph_block *gb = Dynarr_atp (gbd, elt); | |
3110 | |
3111 if (NILP (gb->extent)) | |
2500 | 3112 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3113 |
3114 if (gb->active && | |
3115 ((side == LEFT_GLYPHS && | |
3116 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout) | |
3117 || (side == RIGHT_GLYPHS && | |
3118 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) | |
3119 { | |
442 | 3120 data.findex = gb->findex; |
3121 data.max_pixpos = data.pixpos + gb->width; | |
3122 add_glyph_rune (&data, gb, side, 0, NULL); | |
428 | 3123 count--; |
3124 gb->active = 0; | |
3125 } | |
3126 | |
3127 (reverse ? elt-- : elt++); | |
3128 } | |
3129 | |
819 | 3130 calculate_baseline (&data); |
442 | 3131 |
3132 dl->ascent = data.new_ascent; | |
3133 dl->descent = data.new_descent; | |
3134 | |
819 | 3135 calculate_yoffset (dl, data.db); |
3136 | |
442 | 3137 return data.pixpos; |
428 | 3138 } |
3139 | |
3140 /* Add a blank to a margin display block. */ | |
3141 | |
3142 static void | |
2286 | 3143 add_margin_blank (struct display_line *UNUSED (dl), struct display_block *db, |
428 | 3144 struct window *w, int xpos, int width, int side) |
3145 { | |
3146 struct rune rb; | |
3147 | |
3148 rb.findex = (side == LEFT_GLYPHS | |
3149 ? get_builtin_face_cache_index (w, Vleft_margin_face) | |
3150 : get_builtin_face_cache_index (w, Vright_margin_face)); | |
3151 rb.xpos = xpos; | |
3152 rb.width = width; | |
826 | 3153 rb.charpos = -1; |
428 | 3154 rb.endpos = 0; |
3155 rb.type = RUNE_BLANK; | |
3156 rb.cursor_type = CURSOR_OFF; | |
3157 | |
3158 Dynarr_add (db->runes, rb); | |
3159 } | |
3160 | |
3161 /* Display glyphs in the left outside margin, left inside margin and | |
3162 left whitespace area. */ | |
3163 | |
3164 static void | |
3165 create_left_glyph_block (struct window *w, struct display_line *dl, | |
3166 int overlay_width) | |
3167 { | |
3168 Lisp_Object window; | |
3169 | |
3170 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1); | |
3171 int elt, end_xpos; | |
3172 int out_end, in_out_start, in_in_end, white_out_start, white_in_start; | |
3173 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
3174 int left_in_start = dl->bounds.left_in; | |
3175 int left_in_end = dl->bounds.left_in + overlay_width; | |
3176 | |
3177 struct display_block *odb, *idb; | |
3178 | |
793 | 3179 window = wrap_window (w); |
428 | 3180 |
3181 /* We have to add the glyphs to the line in the order outside, | |
3182 inside, whitespace. However the precedence dictates that we | |
3183 determine how many will fit in the reverse order. */ | |
3184 | |
3185 /* Determine how many whitespace glyphs we can display and where | |
3186 they should start. */ | |
3187 white_in_start = dl->bounds.left_white; | |
3188 white_out_start = left_in_start; | |
3189 white_out_cnt = white_in_cnt = 0; | |
3190 elt = 0; | |
3191 | |
3192 while (elt < Dynarr_length (dl->left_glyphs)) | |
3193 { | |
3194 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3195 | |
3196 if (NILP (gb->extent)) | |
2500 | 3197 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3198 |
3199 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
3200 { | |
3201 int width; | |
3202 | |
438 | 3203 width = glyph_width (gb->glyph, window); |
428 | 3204 |
3205 if (white_in_start - width >= left_in_end) | |
3206 { | |
3207 white_in_cnt++; | |
3208 white_in_start -= width; | |
3209 gb->width = width; | |
3210 gb->active = 1; | |
3211 } | |
3212 else if (use_overflow | |
3213 && (white_out_start - width > dl->bounds.left_out)) | |
3214 { | |
3215 white_out_cnt++; | |
3216 white_out_start -= width; | |
3217 gb->width = width; | |
3218 gb->active = 1; | |
3219 } | |
3220 else | |
3221 gb->active = 0; | |
3222 } | |
3223 | |
3224 elt++; | |
3225 } | |
3226 | |
3227 /* Determine how many inside margin glyphs we can display and where | |
3228 they should start. The inside margin glyphs get whatever space | |
3229 is left after the whitespace glyphs have been displayed. These | |
3230 are tricky to calculate since if we decide to use the overflow | |
3231 area we basically have to start over. So for these we build up a | |
3232 list of just the inside margin glyphs and manipulate it to | |
3233 determine the needed info. */ | |
3234 { | |
3235 glyph_block_dynarr *ib; | |
3236 int avail_in, avail_out; | |
3237 int done = 0; | |
3238 int marker = 0; | |
3239 int used_in, used_out; | |
3240 | |
3241 elt = 0; | |
3242 used_in = used_out = 0; | |
3243 ib = Dynarr_new (glyph_block); | |
3244 while (elt < Dynarr_length (dl->left_glyphs)) | |
3245 { | |
3246 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3247 | |
3248 if (NILP (gb->extent)) | |
2500 | 3249 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3250 |
3251 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3252 GL_INSIDE_MARGIN) | |
3253 { | |
438 | 3254 gb->width = glyph_width (gb->glyph, window); |
428 | 3255 used_in += gb->width; |
3256 Dynarr_add (ib, *gb); | |
3257 } | |
3258 | |
3259 elt++; | |
3260 } | |
3261 | |
3262 if (white_out_cnt) | |
3263 avail_in = 0; | |
3264 else | |
3265 { | |
3266 avail_in = white_in_start - left_in_end; | |
3267 if (avail_in < 0) | |
3268 avail_in = 0; | |
3269 } | |
3270 | |
3271 if (!use_overflow) | |
3272 avail_out = 0; | |
3273 else | |
3274 avail_out = white_out_start - dl->bounds.left_out; | |
3275 | |
3276 marker = 0; | |
3277 while (!done && marker < Dynarr_length (ib)) | |
3278 { | |
3279 int width = Dynarr_atp (ib, marker)->width; | |
3280 | |
3281 /* If everything now fits in the available inside margin | |
4187 | 3282 space, we're done. */ |
428 | 3283 if (used_in <= avail_in) |
3284 done = 1; | |
3285 else | |
3286 { | |
3287 /* Otherwise see if we have room to move a glyph to the | |
4187 | 3288 outside. */ |
428 | 3289 if (used_out + width <= avail_out) |
3290 { | |
3291 used_out += width; | |
3292 used_in -= width; | |
3293 } | |
3294 else | |
3295 done = 1; | |
3296 } | |
3297 | |
3298 if (!done) | |
3299 marker++; | |
3300 } | |
3301 | |
3302 /* At this point we now know that everything from marker on goes in | |
3303 the inside margin and everything before it goes in the outside | |
3304 margin. The stuff going into the outside margin is guaranteed | |
3305 to fit, but we may have to trim some stuff from the inside. */ | |
3306 | |
3307 in_in_end = left_in_end; | |
3308 in_out_start = white_out_start; | |
3309 in_out_cnt = in_in_cnt = 0; | |
3310 | |
3311 Dynarr_free (ib); | |
3312 elt = 0; | |
3313 while (elt < Dynarr_length (dl->left_glyphs)) | |
3314 { | |
3315 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3316 | |
3317 if (NILP (gb->extent)) | |
2500 | 3318 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3319 |
3320 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3321 GL_INSIDE_MARGIN) | |
3322 { | |
438 | 3323 int width = glyph_width (gb->glyph, window); |
428 | 3324 |
3325 if (used_out) | |
3326 { | |
3327 in_out_cnt++; | |
3328 in_out_start -= width; | |
3329 gb->width = width; | |
3330 gb->active = 1; | |
3331 used_out -= width; | |
3332 } | |
3333 else if (in_in_end + width < white_in_start) | |
3334 { | |
3335 in_in_cnt++; | |
3336 in_in_end += width; | |
3337 gb->width = width; | |
3338 gb->active = 1; | |
3339 } | |
3340 else | |
3341 gb->active = 0; | |
3342 } | |
3343 | |
3344 elt++; | |
3345 } | |
3346 } | |
3347 | |
3348 /* Determine how many outside margin glyphs we can display. They | |
3349 always start at the left outside margin and can only use the | |
3350 outside margin space. */ | |
3351 out_end = dl->bounds.left_out; | |
3352 out_cnt = 0; | |
3353 elt = 0; | |
3354 | |
3355 while (elt < Dynarr_length (dl->left_glyphs)) | |
3356 { | |
3357 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3358 | |
3359 if (NILP (gb->extent)) | |
2500 | 3360 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3361 |
3362 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3363 GL_OUTSIDE_MARGIN) | |
3364 { | |
438 | 3365 int width = glyph_width (gb->glyph, window); |
428 | 3366 |
3367 if (out_end + width <= in_out_start) | |
3368 { | |
3369 out_cnt++; | |
3370 out_end += width; | |
3371 gb->width = width; | |
3372 gb->active = 1; | |
3373 } | |
3374 else | |
3375 gb->active = 0; | |
3376 } | |
3377 | |
3378 elt++; | |
3379 } | |
3380 | |
3381 /* Now that we know where everything goes, we add the glyphs as | |
3382 runes to the appropriate display blocks. */ | |
3383 if (out_cnt || in_out_cnt || white_out_cnt) | |
3384 { | |
3385 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN); | |
3386 odb->start_pos = dl->bounds.left_out; | |
3387 /* #### We should stop adding a blank to account for the space | |
4187 | 3388 between the end of the glyphs and the margin and instead set |
3389 this accordingly. */ | |
428 | 3390 odb->end_pos = dl->bounds.left_in; |
3391 Dynarr_reset (odb->runes); | |
3392 } | |
3393 else | |
3394 odb = 0; | |
3395 | |
3396 if (in_in_cnt || white_in_cnt) | |
3397 { | |
3398 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN); | |
3399 idb->start_pos = dl->bounds.left_in; | |
3400 /* #### See above comment for odb->end_pos */ | |
3401 idb->end_pos = dl->bounds.left_white; | |
3402 Dynarr_reset (idb->runes); | |
3403 } | |
3404 else | |
3405 idb = 0; | |
3406 | |
3407 /* First add the outside margin glyphs. */ | |
3408 if (out_cnt) | |
3409 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt, | |
3410 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window); | |
3411 else | |
3412 end_xpos = dl->bounds.left_out; | |
3413 | |
3414 /* There may be blank space between the outside margin glyphs and | |
3415 the inside margin glyphs. If so, add a blank. */ | |
3416 if (in_out_cnt && (in_out_start - end_xpos)) | |
3417 { | |
3418 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos, | |
3419 LEFT_GLYPHS); | |
3420 } | |
3421 | |
3422 /* Next add the inside margin glyphs which are actually in the | |
3423 outside margin. */ | |
3424 if (in_out_cnt) | |
3425 { | |
3426 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt, | |
3427 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
3428 } | |
3429 | |
3430 /* If we didn't add any inside margin glyphs to the outside margin, | |
3431 but are adding whitespace glyphs, then we need to add a blank | |
3432 here. */ | |
3433 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) | |
3434 { | |
3435 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos, | |
3436 LEFT_GLYPHS); | |
3437 } | |
3438 | |
3439 /* Next add the whitespace margin glyphs which are actually in the | |
3440 outside margin. */ | |
3441 if (white_out_cnt) | |
3442 { | |
3443 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt, | |
3444 GL_WHITESPACE, LEFT_GLYPHS, window); | |
3445 } | |
3446 | |
3447 /* We take care of clearing between the end of the glyphs and the | |
3448 start of the inside margin for lines which have glyphs. */ | |
3449 if (odb && (left_in_start - end_xpos)) | |
3450 { | |
3451 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos, | |
3452 LEFT_GLYPHS); | |
3453 } | |
3454 | |
3455 /* Next add the inside margin glyphs which are actually in the | |
3456 inside margin. */ | |
3457 if (in_in_cnt) | |
3458 { | |
3459 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt, | |
3460 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
3461 } | |
3462 else | |
3463 end_xpos = left_in_end; | |
3464 | |
3465 /* Make sure that the area between the end of the inside margin | |
3466 glyphs and the whitespace glyphs is cleared. */ | |
3467 if (idb && (white_in_start - end_xpos > 0)) | |
3468 { | |
3469 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos, | |
3470 LEFT_GLYPHS); | |
3471 } | |
3472 | |
3473 /* Next add the whitespace margin glyphs which are actually in the | |
3474 inside margin. */ | |
3475 if (white_in_cnt) | |
3476 { | |
3477 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE, | |
3478 LEFT_GLYPHS, window); | |
3479 } | |
3480 | |
3481 /* Whitespace glyphs always end right next to the text block so | |
3482 there is nothing we have to make sure is cleared after them. */ | |
3483 } | |
3484 | |
3485 /* Display glyphs in the right outside margin, right inside margin and | |
3486 right whitespace area. */ | |
3487 | |
3488 static void | |
3489 create_right_glyph_block (struct window *w, struct display_line *dl) | |
3490 { | |
3491 Lisp_Object window; | |
3492 | |
3493 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1); | |
3494 int elt, end_xpos; | |
3495 int out_start, in_out_end, in_in_start, white_out_end, white_in_end; | |
3496 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
3497 | |
3498 struct display_block *odb, *idb; | |
3499 | |
793 | 3500 window = wrap_window (w); |
428 | 3501 |
3502 /* We have to add the glyphs to the line in the order outside, | |
3503 inside, whitespace. However the precedence dictates that we | |
3504 determine how many will fit in the reverse order. */ | |
3505 | |
3506 /* Determine how many whitespace glyphs we can display and where | |
3507 they should start. */ | |
3508 white_in_end = dl->bounds.right_white; | |
3509 white_out_end = dl->bounds.right_in; | |
3510 white_out_cnt = white_in_cnt = 0; | |
3511 elt = 0; | |
3512 | |
3513 while (elt < Dynarr_length (dl->right_glyphs)) | |
3514 { | |
3515 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3516 | |
3517 if (NILP (gb->extent)) | |
2500 | 3518 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3519 |
3520 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
3521 { | |
438 | 3522 int width = glyph_width (gb->glyph, window); |
428 | 3523 |
3524 if (white_in_end + width <= dl->bounds.right_in) | |
3525 { | |
3526 white_in_cnt++; | |
3527 white_in_end += width; | |
3528 gb->width = width; | |
3529 gb->active = 1; | |
3530 } | |
3531 else if (use_overflow | |
3532 && (white_out_end + width <= dl->bounds.right_out)) | |
3533 { | |
3534 white_out_cnt++; | |
3535 white_out_end += width; | |
3536 gb->width = width; | |
3537 gb->active = 1; | |
3538 } | |
3539 else | |
3540 gb->active = 0; | |
3541 } | |
3542 | |
3543 elt++; | |
3544 } | |
3545 | |
3546 /* Determine how many inside margin glyphs we can display and where | |
3547 they should start. The inside margin glyphs get whatever space | |
3548 is left after the whitespace glyphs have been displayed. These | |
3549 are tricky to calculate since if we decide to use the overflow | |
3550 area we basically have to start over. So for these we build up a | |
3551 list of just the inside margin glyphs and manipulate it to | |
3552 determine the needed info. */ | |
3553 { | |
3554 glyph_block_dynarr *ib; | |
3555 int avail_in, avail_out; | |
3556 int done = 0; | |
3557 int marker = 0; | |
3558 int used_in, used_out; | |
3559 | |
3560 elt = 0; | |
3561 used_in = used_out = 0; | |
3562 ib = Dynarr_new (glyph_block); | |
3563 while (elt < Dynarr_length (dl->right_glyphs)) | |
3564 { | |
3565 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3566 | |
3567 if (NILP (gb->extent)) | |
2500 | 3568 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3569 |
3570 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
3571 { | |
438 | 3572 gb->width = glyph_width (gb->glyph, window); |
428 | 3573 used_in += gb->width; |
3574 Dynarr_add (ib, *gb); | |
3575 } | |
3576 | |
3577 elt++; | |
3578 } | |
3579 | |
3580 if (white_out_cnt) | |
3581 avail_in = 0; | |
3582 else | |
3583 avail_in = dl->bounds.right_in - white_in_end; | |
3584 | |
3585 if (!use_overflow) | |
3586 avail_out = 0; | |
3587 else | |
3588 avail_out = dl->bounds.right_out - white_out_end; | |
3589 | |
3590 marker = 0; | |
3591 while (!done && marker < Dynarr_length (ib)) | |
3592 { | |
3593 int width = Dynarr_atp (ib, marker)->width; | |
3594 | |
3595 /* If everything now fits in the available inside margin | |
4187 | 3596 space, we're done. */ |
428 | 3597 if (used_in <= avail_in) |
3598 done = 1; | |
3599 else | |
3600 { | |
3601 /* Otherwise see if we have room to move a glyph to the | |
4187 | 3602 outside. */ |
428 | 3603 if (used_out + width <= avail_out) |
3604 { | |
3605 used_out += width; | |
3606 used_in -= width; | |
3607 } | |
3608 else | |
3609 done = 1; | |
3610 } | |
3611 | |
3612 if (!done) | |
3613 marker++; | |
3614 } | |
3615 | |
3616 /* At this point we now know that everything from marker on goes in | |
3617 the inside margin and everything before it goes in the outside | |
3618 margin. The stuff going into the outside margin is guaranteed | |
3619 to fit, but we may have to trim some stuff from the inside. */ | |
3620 | |
3621 in_in_start = dl->bounds.right_in; | |
3622 in_out_end = dl->bounds.right_in; | |
3623 in_out_cnt = in_in_cnt = 0; | |
3624 | |
3625 Dynarr_free (ib); | |
3626 elt = 0; | |
3627 while (elt < Dynarr_length (dl->right_glyphs)) | |
3628 { | |
3629 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3630 | |
3631 if (NILP (gb->extent)) | |
2500 | 3632 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3633 |
3634 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
3635 { | |
438 | 3636 int width = glyph_width (gb->glyph, window); |
428 | 3637 |
3638 if (used_out) | |
3639 { | |
3640 in_out_cnt++; | |
3641 in_out_end += width; | |
3642 gb->width = width; | |
3643 gb->active = 1; | |
3644 used_out -= width; | |
3645 } | |
3646 else if (in_in_start - width >= white_in_end) | |
3647 { | |
3648 in_in_cnt++; | |
3649 in_in_start -= width; | |
3650 gb->width = width; | |
3651 gb->active = 1; | |
3652 } | |
3653 else | |
3654 gb->active = 0; | |
3655 } | |
3656 | |
3657 elt++; | |
3658 } | |
3659 } | |
3660 | |
3661 /* Determine how many outside margin glyphs we can display. They | |
3662 always start at the right outside margin and can only use the | |
3663 outside margin space. */ | |
3664 out_start = dl->bounds.right_out; | |
3665 out_cnt = 0; | |
3666 elt = 0; | |
3667 | |
3668 while (elt < Dynarr_length (dl->right_glyphs)) | |
3669 { | |
3670 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3671 | |
3672 if (NILP (gb->extent)) | |
2500 | 3673 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3674 |
3675 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) | |
3676 { | |
438 | 3677 int width = glyph_width (gb->glyph, window); |
428 | 3678 |
3679 if (out_start - width >= in_out_end) | |
3680 { | |
3681 out_cnt++; | |
3682 out_start -= width; | |
3683 gb->width = width; | |
3684 gb->active = 1; | |
3685 } | |
3686 else | |
3687 gb->active = 0; | |
3688 } | |
3689 | |
3690 elt++; | |
3691 } | |
3692 | |
3693 /* Now that we now where everything goes, we add the glyphs as runes | |
3694 to the appropriate display blocks. */ | |
3695 if (out_cnt || in_out_cnt || white_out_cnt) | |
3696 { | |
3697 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN); | |
3698 /* #### See comments before odb->start_pos init in | |
4187 | 3699 create_left_glyph_block */ |
428 | 3700 odb->start_pos = dl->bounds.right_in; |
3701 odb->end_pos = dl->bounds.right_out; | |
3702 Dynarr_reset (odb->runes); | |
3703 } | |
3704 else | |
3705 odb = 0; | |
3706 | |
3707 if (in_in_cnt || white_in_cnt) | |
3708 { | |
3709 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN); | |
3710 idb->start_pos = dl->bounds.right_white; | |
3711 /* #### See comments before odb->start_pos init in | |
4187 | 3712 create_left_glyph_block */ |
428 | 3713 idb->end_pos = dl->bounds.right_in; |
3714 Dynarr_reset (idb->runes); | |
3715 } | |
3716 else | |
3717 idb = 0; | |
3718 | |
3719 /* First add the whitespace margin glyphs which are actually in the | |
3720 inside margin. */ | |
3721 if (white_in_cnt) | |
3722 { | |
3723 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white, | |
3724 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS, | |
3725 window); | |
3726 } | |
3727 else | |
3728 end_xpos = dl->bounds.right_white; | |
3729 | |
3730 /* Make sure that the area between the end of the whitespace glyphs | |
3731 and the inside margin glyphs is cleared. */ | |
3732 if (in_in_cnt && (in_in_start - end_xpos)) | |
3733 { | |
3734 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos, | |
3735 RIGHT_GLYPHS); | |
3736 } | |
3737 | |
3738 /* Next add the inside margin glyphs which are actually in the | |
3739 inside margin. */ | |
3740 if (in_in_cnt) | |
3741 { | |
3742 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt, | |
3743 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
3744 } | |
3745 | |
3746 /* If we didn't add any inside margin glyphs then make sure the rest | |
3747 of the inside margin area gets cleared. */ | |
3748 if (idb && (dl->bounds.right_in - end_xpos)) | |
3749 { | |
3750 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos, | |
3751 RIGHT_GLYPHS); | |
3752 } | |
3753 | |
3754 /* Next add any whitespace glyphs in the outside margin. */ | |
3755 if (white_out_cnt) | |
3756 { | |
3757 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt, | |
3758 GL_WHITESPACE, RIGHT_GLYPHS, window); | |
3759 } | |
3760 else | |
3761 end_xpos = dl->bounds.right_in; | |
3762 | |
3763 /* Next add any inside margin glyphs in the outside margin. */ | |
3764 if (in_out_cnt) | |
3765 { | |
3766 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt, | |
3767 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
3768 } | |
3769 | |
3770 /* There may be space between any whitespace or inside margin glyphs | |
3771 in the outside margin and the actual outside margin glyphs. */ | |
3772 if (odb && (out_start - end_xpos)) | |
3773 { | |
3774 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos, | |
3775 RIGHT_GLYPHS); | |
3776 } | |
3777 | |
3778 /* Finally, add the outside margin glyphs. */ | |
3779 if (out_cnt) | |
3780 { | |
3781 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN, | |
3782 RIGHT_GLYPHS, window); | |
3783 } | |
3784 } | |
3785 | |
3786 | |
3787 /***************************************************************************/ | |
3788 /* */ | |
3789 /* modeline routines */ | |
3790 /* */ | |
3791 /***************************************************************************/ | |
3792 | |
438 | 3793 /* This function is also used in frame.c by `generate_title_string' */ |
3794 void | |
3795 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, | |
4187 | 3796 struct window *w, struct display_line *dl, |
3797 struct display_block *db, face_index findex, | |
3798 int min_pixpos, int max_pixpos, int type) | |
438 | 3799 { |
3800 struct frame *f = XFRAME (w->frame); | |
3801 struct device *d = XDEVICE (f->device); | |
3802 | |
3803 pos_data data; | |
3804 int c_pixpos; | |
3805 Charcount offset = 0; | |
3806 | |
3807 xzero (data); | |
3808 data.d = d; | |
3809 data.db = db; | |
3810 data.dl = dl; | |
3811 data.findex = findex; | |
3812 data.pixpos = min_pixpos; | |
3813 data.max_pixpos = max_pixpos; | |
3814 data.cursor_type = NO_CURSOR; | |
3815 data.last_charset = Qunbound; | |
3816 data.last_findex = DEFAULT_INDEX; | |
3817 data.result_str = result_str; | |
3818 data.is_modeline = 1; | |
3819 data.string = Qnil; | |
793 | 3820 data.window = wrap_window (w); |
438 | 3821 |
3822 Dynarr_reset (formatted_string_extent_dynarr); | |
3823 Dynarr_reset (formatted_string_extent_start_dynarr); | |
3824 Dynarr_reset (formatted_string_extent_end_dynarr); | |
3825 | |
3826 /* result_str is nil when we're building a frame or icon title. Otherwise, | |
3827 we're building a modeline, so the offset starts at the modeline | |
442 | 3828 horizontal scrolling amount */ |
438 | 3829 if (! NILP (result_str)) |
3830 offset = w->modeline_hscroll; | |
3831 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, | |
4187 | 3832 max_pixpos - min_pixpos, findex, type, &offset, |
438 | 3833 Qnil); |
3834 | |
3835 if (Dynarr_length (db->runes)) | |
3836 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3837 struct rune *rb = Dynarr_lastp (db->runes); |
438 | 3838 c_pixpos = rb->xpos + rb->width; |
3839 } | |
3840 else | |
3841 c_pixpos = min_pixpos; | |
3842 | |
3843 /* If we don't reach the right side of the window, add a blank rune | |
3844 to make up the difference. This usually only occurs if the | |
3845 modeline face is using a proportional width font or a fixed width | |
3846 font of a different size from the default face font. */ | |
3847 | |
3848 if (c_pixpos < max_pixpos) | |
3849 { | |
3850 data.pixpos = c_pixpos; | |
3851 data.blank_width = max_pixpos - data.pixpos; | |
3852 | |
3853 add_blank_rune (&data, NULL, 0); | |
3854 } | |
3855 | |
3856 /* Now create the result string and frob the extents into it. */ | |
3857 if (!NILP (result_str)) | |
3858 { | |
3859 int elt; | |
3860 Bytecount len; | |
867 | 3861 Ibyte *strdata; |
438 | 3862 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); |
3863 | |
442 | 3864 in_modeline_generation = 1; |
3865 | |
771 | 3866 sledgehammer_check_ascii_begin (result_str); |
438 | 3867 detach_all_extents (result_str); |
793 | 3868 resize_string (result_str, -1, |
4187 | 3869 data.bytepos - XSTRING_LENGTH (result_str)); |
438 | 3870 |
3871 strdata = XSTRING_DATA (result_str); | |
3872 | |
3873 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++) | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3874 { |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3875 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3876 { |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3877 len += (set_itext_ichar |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3878 (strdata + len, Dynarr_atp (db->runes, |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3879 elt)->object.chr.ch)); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3880 } |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3881 } |
438 | 3882 |
771 | 3883 init_string_ascii_begin (result_str); |
3884 bump_string_modiff (result_str); | |
3885 sledgehammer_check_ascii_begin (result_str); | |
3886 | |
438 | 3887 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr); |
4187 | 3888 elt++) |
3889 { | |
3890 Lisp_Object extent = Qnil; | |
3891 Lisp_Object child; | |
3892 | |
3893 extent = wrap_extent (Dynarr_at (formatted_string_extent_dynarr, elt)); | |
3894 child = Fgethash (extent, buf->modeline_extent_table, Qnil); | |
3895 if (NILP (child)) | |
3896 { | |
3897 child = Fmake_extent (Qnil, Qnil, result_str); | |
3898 Fputhash (extent, child, buf->modeline_extent_table); | |
3899 } | |
3900 Fset_extent_parent (child, extent); | |
3901 set_extent_endpoints | |
3902 (XEXTENT (child), | |
3903 Dynarr_at (formatted_string_extent_start_dynarr, elt), | |
3904 Dynarr_at (formatted_string_extent_end_dynarr, elt), | |
3905 result_str); | |
3906 } | |
442 | 3907 |
3908 in_modeline_generation = 0; | |
438 | 3909 } |
3910 } | |
3911 | |
428 | 3912 /* Ensure that the given display line DL accurately represents the |
3913 modeline for the given window. */ | |
3914 static void | |
3915 generate_modeline (struct window *w, struct display_line *dl, int type) | |
3916 { | |
3917 struct buffer *b = XBUFFER (w->buffer); | |
3918 struct frame *f = XFRAME (w->frame); | |
3919 struct device *d = XDEVICE (f->device); | |
3920 | |
3921 /* Unlike display line and rune pointers, this one can't change underneath | |
3922 our feet. */ | |
3923 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
3924 int max_pixpos, min_pixpos, ypos_adj; | |
3925 Lisp_Object font_inst; | |
3926 | |
3927 /* This will actually determine incorrect inside boundaries for the | |
3928 modeline since it ignores the margins. However being aware of this fact | |
3929 we never use those values anywhere so it doesn't matter. */ | |
3930 dl->bounds = calculate_display_line_boundaries (w, 1); | |
3931 | |
3932 /* We are generating a modeline. */ | |
3933 dl->modeline = 1; | |
3934 dl->cursor_elt = -1; | |
3935 | |
3936 /* Reset the runes on the modeline. */ | |
3937 Dynarr_reset (db->runes); | |
3938 | |
3939 if (!WINDOW_HAS_MODELINE_P (w)) | |
3940 { | |
3941 struct rune rb; | |
3942 | |
3943 /* If there is a horizontal scrollbar, don't add anything. */ | |
3944 if (window_scrollbar_height (w)) | |
3945 return; | |
3946 | |
3947 dl->ascent = DEVMETH (d, divider_height, ()); | |
3948 dl->descent = 0; | |
3949 /* The modeline is at the bottom of the gutters. */ | |
3950 dl->ypos = WINDOW_BOTTOM (w); | |
3951 | |
3952 rb.findex = MODELINE_INDEX; | |
3953 rb.xpos = dl->bounds.left_out; | |
3954 rb.width = dl->bounds.right_out - dl->bounds.left_out; | |
826 | 3955 rb.charpos = 0; |
428 | 3956 rb.endpos = 0; |
3957 rb.type = RUNE_HLINE; | |
3958 rb.object.hline.thickness = 1; | |
3959 rb.object.hline.yoffset = 0; | |
3960 rb.cursor_type = NO_CURSOR; | |
3961 | |
3962 if (!EQ (Qzero, w->modeline_shadow_thickness) | |
3963 && FRAME_WIN_P (f)) | |
3964 { | |
3965 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
3966 | |
3967 dl->ypos -= shadow_thickness; | |
3968 rb.xpos += shadow_thickness; | |
3969 rb.width -= 2 * shadow_thickness; | |
3970 } | |
3971 | |
3972 Dynarr_add (db->runes, rb); | |
3973 return; | |
3974 } | |
3975 | |
3976 /* !!#### not right; needs to compute the max height of | |
3977 all the charsets */ | |
3978 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); | |
3979 | |
3980 dl->ascent = XFONT_INSTANCE (font_inst)->ascent; | |
3981 dl->descent = XFONT_INSTANCE (font_inst)->descent; | |
3982 | |
3983 min_pixpos = dl->bounds.left_out; | |
3984 max_pixpos = dl->bounds.right_out; | |
3985 | |
3986 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
3987 { | |
3988 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
3989 | |
3990 ypos_adj = shadow_thickness; | |
3991 min_pixpos += shadow_thickness; | |
3992 max_pixpos -= shadow_thickness; | |
3993 } | |
3994 else | |
3995 ypos_adj = 0; | |
3996 | |
3997 generate_formatted_string_db (b->modeline_format, | |
3998 b->generated_modeline_string, w, dl, db, | |
3999 MODELINE_INDEX, min_pixpos, max_pixpos, type); | |
4000 | |
4001 /* The modeline is at the bottom of the gutters. We have to wait to | |
4002 set this until we've generated the modeline in order to account | |
4003 for any embedded faces. */ | |
4004 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj; | |
4005 } | |
4006 | |
4007 static Charcount | |
867 | 4008 add_string_to_fstring_db_runes (pos_data *data, const Ibyte *str, |
4187 | 4009 Charcount pos, Charcount min_pos, |
771 | 4010 Charcount max_pos) |
428 | 4011 { |
4012 /* This function has been Mule-ized. */ | |
4013 Charcount end; | |
867 | 4014 const Ibyte *cur_pos = str; |
428 | 4015 struct display_block *db = data->db; |
4016 | |
4017 data->blank_width = space_width (XWINDOW (data->window)); | |
4018 while (Dynarr_length (db->runes) < pos) | |
4019 add_blank_rune (data, NULL, 0); | |
4020 | |
4021 end = (Dynarr_length (db->runes) + | |
4970 | 4022 bytecount_to_charcount (str, qxestrlen (str))); |
428 | 4023 if (max_pos != -1) |
4024 end = min (max_pos, end); | |
4025 | |
4026 while (pos < end && *cur_pos) | |
4027 { | |
867 | 4028 const Ibyte *old_cur_pos = cur_pos; |
428 | 4029 int succeeded; |
4030 | |
867 | 4031 data->ch = itext_ichar (cur_pos); |
4032 succeeded = (add_ichar_rune (data) != ADD_FAILED); | |
4033 INC_IBYTEPTR (cur_pos); | |
428 | 4034 if (succeeded) |
4187 | 4035 { |
4036 pos++; | |
4037 data->modeline_charpos++; | |
4038 data->bytepos += cur_pos - old_cur_pos; | |
4039 } | |
428 | 4040 } |
4041 | |
4042 while (Dynarr_length (db->runes) < min_pos && | |
4187 | 4043 (data->pixpos + data->blank_width <= data->max_pixpos)) |
428 | 4044 add_blank_rune (data, NULL, 0); |
4045 | |
4046 return Dynarr_length (db->runes); | |
4047 } | |
4048 | |
4049 /* #### Urk! Should also handle begin-glyphs and end-glyphs in | |
4050 modeline extents. */ | |
4051 static Charcount | |
4052 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, | |
4187 | 4053 Charcount pos, Charcount UNUSED (min_pos), |
438 | 4054 Charcount max_pos, Lisp_Object extent) |
428 | 4055 { |
4056 /* This function has been Mule-ized. */ | |
4057 Charcount end; | |
4058 struct display_block *db = data->db; | |
4059 struct glyph_block gb; | |
4060 | |
4061 data->blank_width = space_width (XWINDOW (data->window)); | |
4062 while (Dynarr_length (db->runes) < pos) | |
4063 add_blank_rune (data, NULL, 0); | |
4064 | |
4065 end = Dynarr_length (db->runes) + 1; | |
4066 if (max_pos != -1) | |
4067 end = min (max_pos, end); | |
4068 | |
4069 gb.glyph = glyph; | |
438 | 4070 gb.extent = extent; |
428 | 4071 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); |
4072 pos++; | |
4073 | |
4074 while (Dynarr_length (db->runes) < pos && | |
4187 | 4075 (data->pixpos + data->blank_width <= data->max_pixpos)) |
428 | 4076 add_blank_rune (data, NULL, 0); |
4077 | |
4078 return Dynarr_length (db->runes); | |
4079 } | |
4080 | |
4081 /* If max_pos is == -1, it is considered to be infinite. The same is | |
4082 true of max_pixsize. */ | |
4083 #define SET_CURRENT_MODE_CHARS_PIXSIZE \ | |
4084 if (Dynarr_length (data->db->runes)) \ | |
4967 | 4085 cur_pixsize = data->pixpos - Dynarr_begin (data->db->runes)->xpos; \ |
428 | 4086 else \ |
4087 cur_pixsize = 0; | |
4088 | |
4089 /* Note that this function does "positions" in terms of characters and | |
4090 not in terms of columns. This is necessary to make the formatting | |
4091 work correctly when proportional width fonts are used in the | |
4092 modeline. */ | |
4093 static Charcount | |
4094 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, | |
4187 | 4095 Charcount min_pos, Charcount max_pos, |
4096 Lisp_Object elt, int depth, int max_pixsize, | |
4097 face_index findex, int type, Charcount *offset, | |
438 | 4098 Lisp_Object cur_ext) |
428 | 4099 { |
4100 /* This function has been Mule-ized. */ | |
4101 /* #### The other losing things in this function are: | |
4102 | |
4103 -- C zero-terminated-string lossage. | |
4104 -- Non-printable characters should be converted into something | |
4187 | 4105 appropriate (e.g. ^F) instead of blindly being printed anyway. |
428 | 4106 */ |
4107 | |
4108 tail_recurse: | |
4109 if (depth > 10) | |
4110 goto invalid; | |
4111 | |
4112 depth++; | |
4113 | |
4114 if (STRINGP (elt)) | |
4115 { | |
4116 /* A string. Add to the display line and check for %-constructs | |
4187 | 4117 within it. */ |
428 | 4118 |
2552 | 4119 Ibyte *this_str = XSTRING_DATA (elt); |
4120 | |
4121 while ((pos < max_pos || max_pos == -1) && *this_str) | |
4187 | 4122 { |
4123 Ibyte *last = this_str; | |
4124 | |
4125 while (*this_str && *this_str != '%') | |
4126 this_str++; | |
4127 | |
4128 if (this_str != last) | |
4129 { | |
4130 /* No %-construct */ | |
4131 Charcount size = | |
2552 | 4132 bytecount_to_charcount (last, this_str - last); |
438 | 4133 |
4134 if (size <= *offset) | |
4135 *offset -= size; | |
4136 else | |
4137 { | |
4138 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset : | |
4139 min (pos + size - *offset, max_pos)); | |
867 | 4140 const Ibyte *tmp_last = itext_n_addr (last, *offset); |
438 | 4141 |
4142 pos = add_string_to_fstring_db_runes (data, tmp_last, | |
4143 pos, pos, tmp_max); | |
4144 *offset = 0; | |
4145 } | |
4187 | 4146 } |
4147 else /* *this_str == '%' */ | |
4148 { | |
4149 Charcount spec_width = 0; | |
4150 | |
4151 this_str++; /* skip over '%' */ | |
4152 | |
4153 /* We can't allow -ve args due to the "%-" construct. | |
4154 * Argument specifies minwidth but not maxwidth | |
4155 * (maxwidth can be specified by | |
4156 * (<negative-number> . <stuff>) modeline elements) | |
4157 */ | |
4158 while (isdigit (*this_str)) | |
4159 { | |
4160 spec_width = spec_width * 10 + (*this_str - '0'); | |
4161 this_str++; | |
4162 } | |
4163 spec_width += pos; | |
4164 | |
4165 if (*this_str == 'M') | |
4166 { | |
4167 pos = generate_fstring_runes (w, data, pos, spec_width, | |
4168 max_pos, Vglobal_mode_string, | |
4169 depth, max_pixsize, findex, | |
4170 type, offset, cur_ext); | |
4171 } | |
4172 else if (*this_str == '-') | |
4173 { | |
4174 Charcount num_to_add; | |
4175 | |
4176 if (max_pixsize < 0) | |
4177 num_to_add = 0; | |
4178 else if (max_pos != -1) | |
4179 num_to_add = max_pos - pos; | |
4180 else | |
4181 { | |
4182 int cur_pixsize; | |
4183 int dash_pixsize; | |
4184 Ibyte ch = '-'; | |
4185 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
4186 | |
4187 dash_pixsize = | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4188 redisplay_window_text_width_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4189 (w, findex, &ch, Qnil, 0, 1); |
4187 | 4190 |
4191 if (dash_pixsize == 0) | |
3094 | 4192 num_to_add = 0; |
4193 else { | |
4194 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize; | |
4195 num_to_add++; | |
4196 } | |
4187 | 4197 } |
4198 | |
4199 while (num_to_add--) | |
4200 pos = add_string_to_fstring_db_runes | |
4201 (data, (const Ibyte *) "-", pos, pos, max_pos); | |
4202 } | |
4203 else if (*this_str != 0) | |
4204 { | |
4205 Ichar ch = itext_ichar (this_str); | |
4206 Ibyte *str; | |
438 | 4207 Charcount size; |
4208 | |
4187 | 4209 decode_mode_spec (w, ch, type); |
4210 | |
4967 | 4211 str = Dynarr_begin (mode_spec_ibyte_string); |
438 | 4212 size = bytecount_to_charcount |
4213 /* Skip the null character added by `decode_mode_spec' */ | |
867 | 4214 (str, Dynarr_length (mode_spec_ibyte_string)) - 1; |
438 | 4215 |
4216 if (size <= *offset) | |
4217 *offset -= size; | |
4218 else | |
4219 { | |
867 | 4220 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
438 | 4221 |
440 | 4222 /* #### NOTE: I don't understand why a tmp_max is not |
438 | 4223 computed and used here as in the plain string case |
4224 above. -- dv */ | |
4225 pos = add_string_to_fstring_db_runes (data, tmp_str, | |
4226 pos, pos, | |
4227 max_pos); | |
4228 *offset = 0; | |
4229 } | |
4187 | 4230 } |
4231 | |
4232 /* NOT this_str++. There could be any sort of character at | |
4233 the current position. */ | |
4234 INC_IBYTEPTR (this_str); | |
4235 } | |
4236 | |
4237 if (max_pixsize > 0) | |
4238 { | |
4239 int cur_pixsize; | |
4240 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
4241 | |
4242 if (cur_pixsize >= max_pixsize) | |
4243 break; | |
4244 } | |
4245 } | |
428 | 4246 } |
4247 else if (SYMBOLP (elt)) | |
4248 { | |
4249 /* A symbol: process the value of the symbol recursively | |
4187 | 4250 as if it appeared here directly. */ |
428 | 4251 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); |
4252 | |
4253 if (!UNBOUNDP (tem)) | |
4187 | 4254 { |
438 | 4255 /* If value is a string, output that string literally: |
4187 | 4256 don't check for % within it. */ |
4257 if (STRINGP (tem)) | |
4258 { | |
867 | 4259 Ibyte *str = XSTRING_DATA (tem); |
826 | 4260 Charcount size = string_char_length (tem); |
438 | 4261 |
4262 if (size <= *offset) | |
4263 *offset -= size; | |
4264 else | |
4265 { | |
867 | 4266 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
438 | 4267 |
440 | 4268 /* #### NOTE: I don't understand why a tmp_max is not |
438 | 4269 computed and used here as in the plain string case |
4270 above. -- dv */ | |
4271 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4272 min_pos, max_pos); | |
4273 *offset = 0; | |
4274 } | |
4187 | 4275 } |
4276 /* Give up right away for nil or t. */ | |
4277 else if (!EQ (tem, elt)) | |
4278 { | |
4279 elt = tem; | |
4280 goto tail_recurse; | |
4281 } | |
4282 } | |
428 | 4283 } |
4284 else if (GENERIC_SPECIFIERP (elt)) | |
4285 { | |
4286 Lisp_Object window, tem; | |
793 | 4287 window = wrap_window (w); |
428 | 4288 tem = specifier_instance_no_quit (elt, Qunbound, window, |
793 | 4289 ERROR_ME_DEBUG_WARN, 0, Qzero); |
428 | 4290 if (!UNBOUNDP (tem)) |
4291 { | |
4292 elt = tem; | |
4293 goto tail_recurse; | |
4294 } | |
4295 } | |
4296 else if (CONSP (elt)) | |
4297 { | |
4298 /* A cons cell: four distinct cases. | |
438 | 4299 * - If first element is a string or a cons, process all the elements |
4300 * and effectively concatenate them. | |
4301 * - If first element is a negative number, truncate displaying cdr to | |
4302 * at most that many characters. If positive, pad (with spaces) | |
4303 * to at least that many characters. | |
771 | 4304 * - If first element is another symbol or a boolean specifier, process |
4305 * the cadr or caddr recursively according to whether the symbol's | |
4306 * value or specifier's instance is non-nil or nil. | |
4307 * - If first element is , process the cadr or caddr | |
4308 * recursively according to whether the instance of the specifier in | |
4309 * the modeline's window is non-nil or nil. | |
442 | 4310 * - If first element is an extent, process the cdr recursively |
4311 * and handle the extent's face. | |
428 | 4312 */ |
438 | 4313 |
428 | 4314 Lisp_Object car, tem; |
4315 | |
4316 car = XCAR (elt); | |
771 | 4317 if (SYMBOLP (car) || BOOLEAN_SPECIFIERP (car)) |
438 | 4318 { |
4319 elt = XCDR (elt); | |
4320 if (!CONSP (elt)) | |
4321 goto invalid; | |
4322 | |
771 | 4323 if (SYMBOLP (car)) |
4324 tem = symbol_value_in_buffer (car, w->buffer); | |
4325 else | |
4326 tem = specifier_instance_no_quit (car, Qunbound, wrap_window (w), | |
793 | 4327 ERROR_ME_DEBUG_WARN, 0, Qzero); |
438 | 4328 /* elt is now the cdr, and we know it is a cons cell. |
4329 Use its car if CAR has a non-nil value. */ | |
771 | 4330 if (!UNBOUNDP (tem) && !NILP (tem)) |
438 | 4331 { |
771 | 4332 elt = XCAR (elt); |
4333 goto tail_recurse; | |
438 | 4334 } |
771 | 4335 /* Symbol's value or specifier's instance is nil or unbound |
438 | 4336 * Get the cddr of the original list |
4337 * and if possible find the caddr and use that. | |
4338 */ | |
4339 elt = XCDR (elt); | |
4340 if (NILP (elt)) | |
4341 ; | |
4342 else if (!CONSP (elt)) | |
4343 goto invalid; | |
4344 else | |
4345 { | |
4346 elt = XCAR (elt); | |
4347 goto tail_recurse; | |
4348 } | |
4349 } | |
428 | 4350 else if (INTP (car)) |
4187 | 4351 { |
4352 Charcount lim = XINT (car); | |
4353 | |
4354 elt = XCDR (elt); | |
4355 | |
4356 if (lim < 0) | |
4357 { | |
4358 /* Negative int means reduce maximum width. | |
4359 * DO NOT change MIN_PIXPOS here! | |
4360 * (20 -10 . foo) should truncate foo to 10 col | |
4361 * and then pad to 20. | |
4362 */ | |
4363 if (max_pos == -1) | |
4364 max_pos = pos - lim; | |
4365 else | |
4366 max_pos = min (max_pos, pos - lim); | |
4367 } | |
4368 else if (lim > 0) | |
4369 { | |
4370 /* Padding specified. Don't let it be more than | |
4371 * current maximum. | |
4372 */ | |
4373 lim += pos; | |
4374 if (max_pos != -1 && lim > max_pos) | |
4375 lim = max_pos; | |
4376 /* If that's more padding than already wanted, queue it. | |
4377 * But don't reduce padding already specified even if | |
4378 * that is beyond the current truncation point. | |
4379 */ | |
4380 if (lim > min_pos) | |
4381 min_pos = lim; | |
4382 } | |
4383 goto tail_recurse; | |
4384 } | |
428 | 4385 else if (STRINGP (car) || CONSP (car)) |
4187 | 4386 { |
4387 int limit = 50; | |
4388 | |
4389 /* LIMIT is to protect against circular lists. */ | |
4390 while (CONSP (elt) && --limit > 0 | |
4391 && (pos < max_pos || max_pos == -1)) | |
4392 { | |
4393 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
4394 XCAR (elt), depth, max_pixsize, | |
438 | 4395 findex, type, offset, cur_ext); |
4187 | 4396 elt = XCDR (elt); |
4397 } | |
4398 } | |
428 | 4399 else if (EXTENTP (car)) |
4187 | 4400 { |
4401 struct extent *ext = XEXTENT (car); | |
4402 | |
4403 if (EXTENT_LIVE_P (ext)) | |
4404 { | |
4405 face_index old_findex = data->findex; | |
4406 Lisp_Object face; | |
4407 Lisp_Object font_inst; | |
4408 face_index new_findex; | |
4409 Bytecount start = data->bytepos; | |
4410 | |
4411 face = extent_face (ext); | |
4412 if (FACEP (face)) | |
4413 { | |
4414 /* #### needs to merge faces, sigh */ | |
4415 /* #### needs to handle list of faces */ | |
4416 new_findex = get_builtin_face_cache_index (w, face); | |
4417 /* !!#### not right; needs to compute the max height of | |
4418 all the charsets */ | |
4419 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex, | |
4420 Vcharset_ascii); | |
4421 | |
4422 data->dl->ascent = max (data->dl->ascent, | |
4423 XFONT_INSTANCE (font_inst)->ascent); | |
4424 data->dl->descent = max (data->dl->descent, | |
4425 XFONT_INSTANCE (font_inst)-> | |
4426 descent); | |
4427 } | |
4428 else | |
4429 new_findex = old_findex; | |
4430 | |
4431 data->findex = new_findex; | |
4432 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
4433 XCDR (elt), depth - 1, | |
438 | 4434 max_pixsize, new_findex, type, |
4435 offset, car); | |
4187 | 4436 data->findex = old_findex; |
4437 Dynarr_add (formatted_string_extent_dynarr, ext); | |
4438 Dynarr_add (formatted_string_extent_start_dynarr, start); | |
4439 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); | |
4440 } | |
4441 } | |
428 | 4442 } |
4443 else if (GLYPHP (elt)) | |
4444 { | |
438 | 4445 /* Glyphs are considered as one character with respect to the modeline |
4446 horizontal scrolling facility. -- dv */ | |
4447 if (*offset > 0) | |
4448 *offset -= 1; | |
4449 else | |
4450 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos, | |
4451 cur_ext); | |
428 | 4452 } |
4453 else | |
4454 { | |
4455 invalid: | |
438 | 4456 { |
4970 | 4457 const Ascbyte *str = GETTEXT ("*invalid*"); |
438 | 4458 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */ |
4459 | |
4460 if (size <= *offset) | |
4461 *offset -= size; | |
4462 else | |
4463 { | |
867 | 4464 const Ibyte *tmp_str = |
4465 itext_n_addr ((const Ibyte *) str, *offset); | |
438 | 4466 |
440 | 4467 /* #### NOTE: I don't understand why a tmp_max is not computed and |
438 | 4468 used here as in the plain string case above. -- dv */ |
4469 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4470 min_pos, max_pos); | |
4471 *offset = 0; | |
4472 } | |
4473 } | |
428 | 4474 } |
4475 | |
4476 if (min_pos > pos) | |
4477 { | |
867 | 4478 add_string_to_fstring_db_runes (data, (const Ibyte *) "", pos, |
438 | 4479 min_pos, -1); |
428 | 4480 } |
4481 | |
4482 return pos; | |
4483 } | |
4484 | |
4485 /* Update just the modeline. Assumes the desired display structs. If | |
4486 they do not have a modeline block, it does nothing. */ | |
4487 static void | |
4488 regenerate_modeline (struct window *w) | |
4489 { | |
4490 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP); | |
4491 | |
4967 | 4492 if (!Dynarr_length (dla) || !Dynarr_begin (dla)->modeline) |
428 | 4493 return; |
4494 else | |
4495 { | |
4967 | 4496 generate_modeline (w, Dynarr_begin (dla), DESIRED_DISP); |
428 | 4497 redisplay_update_line (w, 0, 0, 0); |
4498 } | |
4499 } | |
4500 | |
4501 /* Make sure that modeline display line is present in the given | |
4502 display structs if the window has a modeline and update that | |
4503 line. Returns true if a modeline was needed. */ | |
4504 static int | |
4505 ensure_modeline_generated (struct window *w, int type) | |
4506 { | |
4507 int need_modeline; | |
4508 | |
4509 /* minibuffer windows don't have modelines */ | |
4510 if (MINI_WINDOW_P (w)) | |
4511 need_modeline = 0; | |
4512 /* windows which haven't had it turned off do */ | |
4513 else if (WINDOW_HAS_MODELINE_P (w)) | |
4514 need_modeline = 1; | |
4515 /* windows which have it turned off don't have a divider if there is | |
4516 a horizontal scrollbar */ | |
4517 else if (window_scrollbar_height (w)) | |
4518 need_modeline = 0; | |
4519 /* and in this case there is none */ | |
4520 else | |
4521 need_modeline = 1; | |
4522 | |
4523 if (need_modeline) | |
4524 { | |
4525 display_line_dynarr *dla; | |
4526 | |
4527 dla = window_display_lines (w, type); | |
4528 | |
4529 /* We don't care if there is a display line which is not | |
4187 | 4530 currently a modeline because it is definitely going to become |
4531 one if we have gotten to this point. */ | |
428 | 4532 if (Dynarr_length (dla) == 0) |
4533 { | |
4534 if (Dynarr_largest (dla) > 0) | |
5038 | 4535 Dynarr_incrementr (dla); |
428 | 4536 else |
4537 { | |
4538 struct display_line modeline; | |
4207 | 4539 |
4540 DISPLAY_LINE_INIT (modeline); | |
428 | 4541 Dynarr_add (dla, modeline); |
4542 } | |
4543 } | |
4544 | |
4545 /* If we're adding a new place marker go ahead and generate the | |
4187 | 4546 modeline so that it is available for use by |
4547 window_modeline_height. */ | |
4967 | 4548 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 4549 } |
4550 | |
4551 return need_modeline; | |
4552 } | |
4553 | |
4554 /* #### Kludge or not a kludge. I tend towards the former. */ | |
4555 int | |
4556 real_current_modeline_height (struct window *w) | |
4557 { | |
4558 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer); | |
4559 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer); | |
4560 | |
4561 if (ensure_modeline_generated (w, CMOTION_DISP)) | |
4562 { | |
4563 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP); | |
4564 | |
4565 if (Dynarr_length (dla)) | |
4566 { | |
4967 | 4567 if (Dynarr_begin (dla)->modeline) |
4568 return (Dynarr_begin (dla)->ascent + | |
4569 Dynarr_begin (dla)->descent); | |
428 | 4570 } |
4571 } | |
4572 return 0; | |
4573 } | |
4574 | |
4575 | |
4576 /***************************************************************************/ | |
819 | 4577 /* */ |
826 | 4578 /* displayable string routines */ |
819 | 4579 /* */ |
428 | 4580 /***************************************************************************/ |
4581 | |
4582 /* Given a position for a string in a window, ensure that the given | |
4583 display line DL accurately represents the text on a line starting | |
4584 at the given position. | |
4585 | |
4586 Yes, this is duplicating the code of create_text_block, but it | |
4587 looked just too hard to change create_text_block to handle strings | |
4588 *and* buffers. We already make a distinction between the two | |
4589 elsewhere in the code so I think unifying them would require a | |
4590 complete MULE rewrite. Besides, the other distinction is that these | |
4591 functions cover text that the user *cannot edit* so we can remove | |
4592 everything to do with cursors, minibuffers etc. Eventually the | |
4593 modeline routines should be modified to use this code as it copes | |
4594 with many more types of display situation. */ | |
4595 | |
665 | 4596 static Charbpos |
428 | 4597 create_string_text_block (struct window *w, Lisp_Object disp_string, |
4598 struct display_line *dl, | |
826 | 4599 Charcount start_pos, |
428 | 4600 prop_block_dynarr **prop, |
4601 face_index default_face) | |
4602 { | |
4603 struct frame *f = XFRAME (w->frame); | |
4604 /* Note that a lot of the buffer controlled stuff has been left in | |
4605 because you might well want to make use of it (selective display | |
4606 etc), its just the buffer text that we do not use. However, it | |
4607 seems to be possible for buffer to be nil sometimes so protect | |
4608 against this case. */ | |
4609 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; | |
4610 struct device *d = XDEVICE (f->device); | |
4611 | |
4612 /* we're working with these a lot so precalculate them */ | |
4613 Bytecount slen = XSTRING_LENGTH (disp_string); | |
826 | 4614 Bytecount byte_string_zv = slen; |
4615 Bytecount byte_start_pos = string_index_char_to_byte (disp_string, start_pos); | |
428 | 4616 |
4617 pos_data data; | |
4618 | |
4619 int truncate_win = b ? window_truncation_on (w) : 0; | |
4620 | |
442 | 4621 /* We're going to ditch selective display for static text, it's an |
4622 FSF thing and invisible extents are the way to go here. | |
4623 Implementing it also relies on a number of buffer-specific | |
428 | 4624 functions that we don't have the luxury of being able to use |
4625 here. */ | |
4626 | |
4627 /* The variable ctl-arrow allows the user to specify what characters | |
4628 can actually be displayed and which octal should be used for. | |
4629 #### This variable should probably have some rethought done to | |
4630 it. | |
4631 | |
4632 #### It would also be really nice if you could specify that | |
4633 the characters come out in hex instead of in octal. Mule | |
4634 does that by adding a ctl-hexa variable similar to ctl-arrow, | |
4635 but that's bogus -- we need a more general solution. I | |
4636 think you need to extend the concept of display tables | |
4637 into a more general conversion mechanism. Ideally you | |
4638 could specify a Lisp function that converts characters, | |
4639 but this violates the Second Golden Rule and besides would | |
4640 make things way way way way slow. | |
4641 | |
4642 So instead, we extend the display-table concept, which was | |
4643 historically limited to 256-byte vectors, to one of the | |
4644 following: | |
4645 | |
4646 a) A 256-entry vector, for backward compatibility; | |
4647 b) char-table, mapping characters to values; | |
4648 c) range-table, mapping ranges of characters to values; | |
4649 d) a list of the above. | |
4650 | |
4651 The (d) option allows you to specify multiple display tables | |
4652 instead of just one. Each display table can specify conversions | |
4653 for some characters and leave others unchanged. The way the | |
4654 character gets displayed is determined by the first display table | |
4655 with a binding for that character. This way, you could call a | |
4656 function `enable-hex-display' that adds a hex display-table to | |
4657 the list of display tables for the current buffer. | |
4658 | |
4659 #### ...not yet implemented... Also, we extend the concept of | |
4660 "mapping" to include a printf-like spec. Thus you can make all | |
4661 extended characters show up as hex with a display table like | |
4662 this: | |
4663 | |
4187 | 4664 #s(range-table data ((256 524288) (format "%x"))) |
428 | 4665 |
4666 Since more than one display table is possible, you have | |
4667 great flexibility in mapping ranges of characters. */ | |
867 | 4668 Ichar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
428 | 4669 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
4670 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
4671 ? 255 : 160)) : 255; | |
4672 | |
4673 Lisp_Object face_dt, window_dt; | |
4674 | |
4675 /* The text display block for this display line. */ | |
4676 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
4677 | |
4678 /* The first time through the main loop we need to force the glyph | |
4679 data to be updated. */ | |
4680 int initial = 1; | |
4681 | |
4682 /* Apparently the new extent_fragment_update returns an end position | |
4683 equal to the position passed in if there are no more runs to be | |
4684 displayed. */ | |
4685 int no_more_frags = 0; | |
4686 | |
4687 dl->used_prop_data = 0; | |
4688 dl->num_chars = 0; | |
442 | 4689 dl->line_continuation = 0; |
428 | 4690 |
4187 | 4691 /* Set up faces to use for clearing areas, used by output_display_line. */ |
428 | 4692 dl->default_findex = default_face; |
4187 | 4693 if (default_face > DEFAULT_INDEX) |
428 | 4694 { |
4695 dl->left_margin_findex = default_face; | |
4696 dl->right_margin_findex = default_face; | |
4697 } | |
4698 else | |
4699 { | |
434 | 4700 dl->left_margin_findex = |
428 | 4701 get_builtin_face_cache_index (w, Vleft_margin_face); |
434 | 4702 dl->right_margin_findex = |
428 | 4703 get_builtin_face_cache_index (w, Vright_margin_face); |
4704 } | |
4705 | |
4706 xzero (data); | |
4707 data.ef = extent_fragment_new (disp_string, f); | |
4708 | |
4709 /* These values are used by all of the rune addition routines. We add | |
4710 them to this structure for ease of passing. */ | |
4711 data.d = d; | |
793 | 4712 data.window = wrap_window (w); |
428 | 4713 data.db = db; |
4714 data.dl = dl; | |
4715 | |
826 | 4716 data.byte_charpos = byte_start_pos; |
428 | 4717 data.pixpos = dl->bounds.left_in; |
4718 data.last_charset = Qunbound; | |
4719 data.last_findex = default_face; | |
4720 data.result_str = Qnil; | |
4721 data.string = disp_string; | |
4722 | |
4723 /* Set the right boundary adjusting it to take into account any end | |
4724 glyph. Save the width of the end glyph for later use. */ | |
4725 data.max_pixpos = dl->bounds.right_in; | |
819 | 4726 data.max_pixpos -= data.end_glyph_width; |
428 | 4727 |
4728 data.cursor_type = NO_CURSOR; | |
4729 data.cursor_x = -1; | |
4730 | |
4731 data.start_col = 0; | |
4732 /* I don't think we want this, string areas should not scroll with | |
434 | 4733 the window |
428 | 4734 data.start_col = w->hscroll; |
826 | 4735 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
428 | 4736 */ |
826 | 4737 data.byte_start_col_enabled = 0; |
428 | 4738 data.hscroll_glyph_width_adjust = 0; |
4739 | |
4740 /* We regenerate the line from the very beginning. */ | |
4741 Dynarr_reset (db->runes); | |
4742 | |
4743 /* Why is this less than or equal and not just less than? If the | |
4744 starting position is already equal to the maximum we can't add | |
4745 anything else, right? Wrong. We might still have a newline to | |
4746 add. A newline can use the room allocated for an end glyph since | |
4747 if we add it we know we aren't going to be adding any end | |
4748 glyph. */ | |
4749 | |
4750 /* #### Chuck -- I think this condition should be while (1). | |
4751 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
4752 and the begin-glyph ends exactly at the end of the window, the | |
4753 end-glyph and text might not be displayed. while (1) ensures | |
4754 that the loop terminates only when either (a) there is | |
4755 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
4756 | |
4757 #### Also I think you need to ensure that the operation | |
4758 "add begin glyphs; add end glyphs; add text" is atomic and | |
4759 can't get interrupted in the middle. If you run off the end | |
4760 of the line during that operation, then you keep accumulating | |
4761 propagation data until you're done. Otherwise, if the (e.g.) | |
4762 there's a begin glyph at a particular position and attempting | |
4763 to display that glyph results in window-end being hit and | |
4764 propagation data being generated, then the character at that | |
4765 position won't be displayed. | |
4766 | |
4767 #### See also the comment after the end of this loop, below. | |
4768 */ | |
4769 while (data.pixpos <= data.max_pixpos) | |
4770 { | |
4771 /* #### This check probably should not be necessary. */ | |
826 | 4772 if (data.byte_charpos > byte_string_zv) |
428 | 4773 { |
4774 /* #### urk! More of this lossage! */ | |
826 | 4775 data.byte_charpos--; |
428 | 4776 goto done; |
4777 } | |
4778 | |
4779 /* Check for face changes. */ | |
826 | 4780 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
428 | 4781 { |
819 | 4782 Lisp_Object last_glyph = Qnil; |
4783 /* Deal with clipped glyphs that we have already displayed. */ | |
4967 | 4784 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
4785 { | |
4786 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
819 | 4787 Dynarr_free (*prop); |
4788 *prop = 0; | |
4789 } | |
428 | 4790 /* Now compute the face and begin/end-glyph information. */ |
4791 data.findex = | |
793 | 4792 /* Remember that the extent-fragment routines deal in |
4187 | 4793 Bytexpos's. */ |
826 | 4794 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
428 | 4795 /* This is somewhat cheesy but the alternative is to |
4187 | 4796 propagate default_face into extent_fragment_update. */ |
428 | 4797 if (data.findex == DEFAULT_INDEX) |
4798 data.findex = default_face; | |
4799 | |
4800 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
4801 | |
826 | 4802 if (data.byte_charpos == data.ef->end) |
428 | 4803 no_more_frags = 1; |
4804 } | |
4805 initial = 0; | |
4806 | |
4807 /* Determine what is next to be displayed. We first handle any | |
4187 | 4808 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
4809 display then we determine what to do based on the character at the | |
4810 current buffer position. */ | |
428 | 4811 |
4812 /* If the current position is covered by an invisible extent, do | |
4187 | 4813 nothing (except maybe add some ellipses). |
428 | 4814 |
4815 #### The behavior of begin and end-glyphs at the edge of an | |
4816 invisible extent should be investigated further. This is | |
4817 fairly low priority though. */ | |
4818 if (data.ef->invisible) | |
4819 { | |
4820 /* #### Chuck, perhaps you could look at this code? I don't | |
4821 really know what I'm doing. */ | |
4822 if (*prop) | |
4823 { | |
4824 Dynarr_free (*prop); | |
4825 *prop = 0; | |
4826 } | |
4827 | |
4828 /* The extent fragment code only sets this when we should | |
4829 really display the ellipses. It makes sure the ellipses | |
4830 don't get displayed more than once in a row. */ | |
4831 if (data.ef->invisible_ellipses) | |
4832 { | |
4833 struct glyph_block gb; | |
4834 | |
4835 data.ef->invisible_ellipses_already_displayed = 1; | |
4836 data.ef->invisible_ellipses = 0; | |
4837 gb.extent = Qnil; | |
4838 gb.glyph = Vinvisible_text_glyph; | |
4839 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
4840 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
4841 /* Perhaps they shouldn't propagate if the very next thing | |
4842 is to display a newline (for compatibility with | |
4843 selective-display-ellipses)? Maybe that's too | |
4844 abstruse. */ | |
4845 if (*prop) | |
4846 goto done; | |
4847 } | |
4848 | |
638 | 4849 /* #### What if we're dealing with a display table? */ |
428 | 4850 if (data.start_col) |
4851 data.start_col--; | |
4852 | |
826 | 4853 if (data.byte_charpos == byte_string_zv) |
428 | 4854 goto done; |
4855 else | |
826 | 4856 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 4857 } |
4858 | |
4859 /* If there is propagation data, then it represents the current | |
4187 | 4860 buffer position being displayed. Add them and advance the |
4861 position counter. This might also add the minibuffer | |
4862 prompt. */ | |
428 | 4863 else if (*prop) |
4864 { | |
4865 dl->used_prop_data = 1; | |
4866 *prop = add_propagation_runes (prop, &data); | |
4867 | |
4868 if (*prop) | |
4869 goto done; /* gee, a really narrow window */ | |
826 | 4870 else if (data.byte_charpos == byte_string_zv) |
428 | 4871 goto done; |
826 | 4872 else if (data.byte_charpos < 0) |
428 | 4873 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
826 | 4874 data.byte_charpos = 0; |
428 | 4875 else |
826 | 4876 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 4877 } |
4878 | |
4879 /* If there are end glyphs, add them to the line. These are | |
4880 the end glyphs for the previous run of text. We add them | |
4881 here rather than doing them at the end of handling the | |
4882 previous run so that glyphs at the beginning and end of | |
4883 a line are handled correctly. */ | |
4884 else if (Dynarr_length (data.ef->end_glyphs) > 0) | |
4885 { | |
867 | 4886 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4887 *prop = add_glyph_runes (&data, END_GLYPHS); |
819 | 4888 |
4889 if (*prop) { | |
428 | 4890 goto done; |
819 | 4891 } |
428 | 4892 } |
4893 | |
4894 /* If there are begin glyphs, add them to the line. */ | |
4895 else if (Dynarr_length (data.ef->begin_glyphs) > 0) | |
4896 { | |
867 | 4897 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4898 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); |
819 | 4899 |
4900 if (*prop) { | |
428 | 4901 goto done; |
819 | 4902 } |
428 | 4903 } |
4904 | |
4905 /* If at end-of-buffer, we've already processed begin and | |
4906 end-glyphs at this point and there's no text to process, | |
4907 so we're done. */ | |
826 | 4908 else if (data.byte_charpos == byte_string_zv) |
428 | 4909 goto done; |
4910 | |
4911 else | |
4912 { | |
4913 Lisp_Object entry = Qnil; | |
4914 /* Get the character at the current buffer position. */ | |
867 | 4915 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4916 if (!NILP (face_dt) || !NILP (window_dt)) |
4917 entry = display_table_entry (data.ch, face_dt, window_dt); | |
4918 | |
4919 /* If there is a display table entry for it, hand it off to | |
4187 | 4920 add_disp_table_entry_runes and let it worry about it. */ |
428 | 4921 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
4922 { | |
4923 *prop = add_disp_table_entry_runes (&data, entry); | |
4924 | |
4925 if (*prop) | |
4926 goto done; | |
4927 } | |
4928 | |
4929 /* Check if we have hit a newline character. If so, add a marker | |
4187 | 4930 to the line and end this loop. */ |
428 | 4931 else if (data.ch == '\n') |
4932 { | |
4933 /* We aren't going to be adding an end glyph so give its | |
4187 | 4934 space back in order to make sure that the cursor can |
4935 fit. */ | |
819 | 4936 data.max_pixpos += data.end_glyph_width; |
428 | 4937 goto done; |
4938 } | |
4939 | |
4940 /* If the current character is considered to be printable, then | |
4187 | 4941 just add it. */ |
428 | 4942 else if (data.ch >= printable_min) |
4943 { | |
867 | 4944 *prop = add_ichar_rune (&data); |
428 | 4945 if (*prop) |
4946 goto done; | |
4947 } | |
4948 | |
4949 /* If the current character is a tab, determine the next tab | |
4187 | 4950 starting position and add a blank rune which extends from the |
4951 current pixel position to that starting position. */ | |
428 | 4952 else if (data.ch == '\t') |
4953 { | |
4954 int tab_start_pixpos = data.pixpos; | |
4955 int next_tab_start; | |
4956 int char_tab_width; | |
4957 int prop_width = 0; | |
4958 | |
4959 if (data.start_col > 1) | |
4960 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); | |
4961 | |
4962 next_tab_start = | |
4963 next_tab_position (w, tab_start_pixpos, | |
4964 dl->bounds.left_in + | |
4965 data.hscroll_glyph_width_adjust); | |
4966 if (next_tab_start > data.max_pixpos) | |
4967 { | |
4968 prop_width = next_tab_start - data.max_pixpos; | |
4969 next_tab_start = data.max_pixpos; | |
4970 } | |
4971 data.blank_width = next_tab_start - data.pixpos; | |
4972 char_tab_width = | |
4973 (next_tab_start - tab_start_pixpos) / space_width (w); | |
4974 | |
4975 *prop = add_blank_rune (&data, w, char_tab_width); | |
4976 | |
4977 /* add_blank_rune is only supposed to be called with | |
819 | 4978 sizes guaranteed to fit in the available space. */ |
428 | 4979 assert (!(*prop)); |
4980 | |
4981 if (prop_width) | |
4982 { | |
4983 struct prop_block pb; | |
4984 *prop = Dynarr_new (prop_block); | |
4985 | |
4986 pb.type = PROP_BLANK; | |
4987 pb.data.p_blank.width = prop_width; | |
4988 pb.data.p_blank.findex = data.findex; | |
4989 Dynarr_add (*prop, pb); | |
4990 | |
4991 goto done; | |
4992 } | |
4993 } | |
4994 | |
4995 /* If character is a control character, pass it off to | |
4187 | 4996 add_control_char_runes. |
428 | 4997 |
4998 The is_*() routines have undefined results on | |
4999 arguments outside of the range [-1, 255]. (This | |
5000 often bites people who carelessly use `char' instead | |
5001 of `unsigned char'.) | |
5002 */ | |
867 | 5003 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
428 | 5004 { |
5005 *prop = add_control_char_runes (&data, b); | |
5006 | |
5007 if (*prop) | |
5008 goto done; | |
5009 } | |
5010 | |
5011 /* If the character is above the ASCII range and we have not | |
4187 | 5012 already handled it, then print it as an octal number. */ |
428 | 5013 else if (data.ch >= 0200) |
5014 { | |
5015 *prop = add_octal_runes (&data); | |
5016 | |
5017 if (*prop) | |
5018 goto done; | |
5019 } | |
5020 | |
5021 /* Assume the current character is considered to be printable, | |
4187 | 5022 then just add it. */ |
428 | 5023 else |
5024 { | |
867 | 5025 *prop = add_ichar_rune (&data); |
428 | 5026 if (*prop) |
5027 goto done; | |
5028 } | |
5029 | |
826 | 5030 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 5031 } |
5032 } | |
5033 | |
819 | 5034 done: |
428 | 5035 |
5036 /* Determine the starting point of the next line if we did not hit the | |
5037 end of the buffer. */ | |
826 | 5038 if (data.byte_charpos < byte_string_zv) |
428 | 5039 { |
5040 /* #### This check is not correct. If the line terminated | |
5041 due to a begin-glyph or end-glyph hitting window-end, then | |
826 | 5042 data.ch will not point to the character at data.byte_charpos. If |
428 | 5043 you make the two changes mentioned at the top of this loop, |
5044 you should be able to say '(if (*prop))'. That should also | |
826 | 5045 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 5046 check. */ |
5047 | |
5048 /* The common case is that the line ended because we hit a newline. | |
4187 | 5049 In that case, the next character is just the next buffer |
5050 position. */ | |
428 | 5051 if (data.ch == '\n') |
5052 { | |
826 | 5053 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 5054 } |
5055 | |
5056 /* Otherwise we have a buffer line which cannot fit on one display | |
4187 | 5057 line. */ |
428 | 5058 else |
5059 { | |
5060 struct glyph_block gb; | |
5061 struct glyph_cachel *cachel; | |
5062 | |
5063 /* If the line is to be truncated then we actually have to look | |
4187 | 5064 for the next newline. We also add the end-of-line glyph which |
5065 we know will fit because we adjusted the right border before | |
5066 we starting laying out the line. */ | |
819 | 5067 data.max_pixpos += data.end_glyph_width; |
428 | 5068 data.findex = default_face; |
5069 gb.extent = Qnil; | |
5070 | |
5071 if (truncate_win) | |
5072 { | |
826 | 5073 Bytecount byte_pos; |
428 | 5074 |
5075 /* Now find the start of the next line. */ | |
867 | 5076 byte_pos = byte_find_next_ichar_in_string (disp_string, '\n', |
826 | 5077 data.byte_charpos, 1); |
428 | 5078 |
5079 data.cursor_type = NO_CURSOR; | |
826 | 5080 data.byte_charpos = byte_pos; |
428 | 5081 gb.glyph = Vtruncation_glyph; |
5082 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
5083 } | |
5084 else | |
5085 { | |
5086 /* The cursor can never be on the continuation glyph. */ | |
5087 data.cursor_type = NO_CURSOR; | |
5088 | |
826 | 5089 /* data.byte_charpos is already at the start of the next line. */ |
428 | 5090 |
442 | 5091 dl->line_continuation = 1; |
428 | 5092 gb.glyph = Vcontinuation_glyph; |
5093 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
5094 } | |
5095 | |
819 | 5096 if (data.end_glyph_width) |
428 | 5097 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
5098 | |
826 | 5099 if (truncate_win && data.byte_charpos == byte_string_zv) |
428 | 5100 { |
867 | 5101 const Ibyte *endb = itext_n_addr (XSTRING_DATA (disp_string), |
826 | 5102 byte_string_zv); |
867 | 5103 DEC_IBYTEPTR (endb); |
5104 if (itext_ichar (endb) != '\n') | |
428 | 5105 { |
5106 /* #### Damn this losing shit. */ | |
826 | 5107 data.byte_charpos++; |
428 | 5108 } |
5109 } | |
5110 } | |
5111 } | |
826 | 5112 else if (data.byte_charpos == byte_string_zv) |
428 | 5113 { |
5114 /* create_text_block () adds a bogus \n marker here which screws | |
5115 up subwindow display. Since we never have a cursor in the | |
5116 gutter we can safely ignore it. */ | |
5117 } | |
5118 /* Calculate left whitespace boundary. */ | |
5119 { | |
5120 int elt = 0; | |
5121 | |
5122 /* Whitespace past a newline is considered right whitespace. */ | |
5123 while (elt < Dynarr_length (db->runes)) | |
5124 { | |
5125 struct rune *rb = Dynarr_atp (db->runes, elt); | |
5126 | |
5127 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
5128 || rb->type == RUNE_BLANK) | |
5129 { | |
5130 dl->bounds.left_white += rb->width; | |
5131 elt++; | |
5132 } | |
5133 else | |
5134 elt = Dynarr_length (db->runes); | |
5135 } | |
5136 } | |
5137 | |
5138 /* Calculate right whitespace boundary. */ | |
5139 { | |
5140 int elt = Dynarr_length (db->runes) - 1; | |
5141 int done = 0; | |
5142 | |
5143 while (!done && elt >= 0) | |
5144 { | |
5145 struct rune *rb = Dynarr_atp (db->runes, elt); | |
5146 | |
5147 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
5148 && isspace (rb->object.chr.ch)) | |
5149 && !rb->type == RUNE_BLANK) | |
5150 { | |
5151 dl->bounds.right_white = rb->xpos + rb->width; | |
5152 done = 1; | |
5153 } | |
5154 | |
5155 elt--; | |
5156 | |
5157 } | |
5158 | |
5159 /* The line is blank so everything is considered to be right | |
5160 whitespace. */ | |
5161 if (!done) | |
5162 dl->bounds.right_white = dl->bounds.left_in; | |
5163 } | |
5164 | |
5165 /* Set the display blocks bounds. */ | |
5166 db->start_pos = dl->bounds.left_in; | |
5167 if (Dynarr_length (db->runes)) | |
5168 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
5169 struct rune *rb = Dynarr_lastp (db->runes); |
428 | 5170 |
5171 db->end_pos = rb->xpos + rb->width; | |
5172 } | |
5173 else | |
5174 db->end_pos = dl->bounds.right_white; | |
5175 | |
819 | 5176 calculate_baseline (&data); |
428 | 5177 |
5178 dl->ascent = data.new_ascent; | |
5179 dl->descent = data.new_descent; | |
5180 | |
5181 { | |
5182 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
5183 | |
5184 if (dl->ascent < ascent) | |
5185 dl->ascent = ascent; | |
5186 } | |
5187 { | |
5188 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
5189 | |
5190 if (dl->descent < descent) | |
5191 dl->descent = descent; | |
5192 } | |
5193 | |
819 | 5194 calculate_yoffset (dl, db); |
5195 | |
428 | 5196 dl->cursor_elt = data.cursor_x; |
5197 /* #### lossage lossage lossage! Fix this shit! */ | |
826 | 5198 if (data.byte_charpos > byte_string_zv) |
5199 dl->end_charpos = buffer_or_string_bytexpos_to_charxpos (disp_string, | |
5200 byte_string_zv); | |
428 | 5201 else |
826 | 5202 dl->end_charpos = |
5203 buffer_or_string_bytexpos_to_charxpos (disp_string, | |
5204 data.byte_charpos) - 1; | |
428 | 5205 if (truncate_win) |
434 | 5206 data.dl->num_chars = |
826 | 5207 string_column_at_point (disp_string, dl->end_charpos, |
793 | 5208 b ? XINT (b->tab_width) : 8); |
428 | 5209 else |
5210 /* This doesn't correctly take into account tabs and control | |
5211 characters but if the window isn't being truncated then this | |
5212 value isn't going to end up being used anyhow. */ | |
826 | 5213 data.dl->num_chars = dl->end_charpos - dl->charpos; |
428 | 5214 |
5215 /* #### handle horizontally scrolled line with text none of which | |
5216 was actually laid out. */ | |
5217 | |
5218 /* #### handle any remainder of overlay arrow */ | |
5219 | |
5220 if (*prop == ADD_FAILED) | |
5221 *prop = NULL; | |
5222 | |
5223 if (truncate_win && *prop) | |
5224 { | |
5225 Dynarr_free (*prop); | |
5226 *prop = NULL; | |
5227 } | |
5228 | |
5229 extent_fragment_delete (data.ef); | |
5230 | |
5231 /* #### If we started at EOB, then make sure we return a value past | |
5232 it so that regenerate_window will exit properly. This is bogus. | |
5233 The main loop should get fixed so that it isn't necessary to call | |
5234 this function if we are already at EOB. */ | |
5235 | |
826 | 5236 if (data.byte_charpos == byte_string_zv && byte_start_pos == byte_string_zv) |
793 | 5237 return string_index_byte_to_char (disp_string, |
826 | 5238 data.byte_charpos) + 1; /* Yuck! */ |
428 | 5239 else |
826 | 5240 return string_index_byte_to_char (disp_string, data.byte_charpos); |
428 | 5241 } |
5242 | |
5243 /* Given a display line and a starting position, ensure that the | |
5244 contents of the display line accurately represent the visual | |
5245 representation of the buffer contents starting from the given | |
5246 position when displayed in the given window. The display line ends | |
5247 when the contents of the line reach the right boundary of the given | |
434 | 5248 window. |
5249 | |
428 | 5250 This is very similar to generate_display_line but with the same |
5251 limitations as create_string_text_block. I have taken the liberty | |
665 | 5252 of fixing the bytebpos stuff though.*/ |
5253 | |
5254 static Charbpos | |
428 | 5255 generate_string_display_line (struct window *w, Lisp_Object disp_string, |
5256 struct display_line *dl, | |
826 | 5257 Charcount start_pos, |
428 | 5258 prop_block_dynarr **prop, |
5259 face_index default_face) | |
5260 { | |
826 | 5261 Charcount ret_charcount; |
428 | 5262 |
5263 /* you must set bounds before calling this. */ | |
434 | 5264 |
428 | 5265 /* Reset what this line is using. */ |
5266 if (dl->display_blocks) | |
5267 Dynarr_reset (dl->display_blocks); | |
5268 if (dl->left_glyphs) | |
5269 { | |
5270 Dynarr_free (dl->left_glyphs); | |
5271 dl->left_glyphs = 0; | |
5272 } | |
5273 if (dl->right_glyphs) | |
5274 { | |
5275 Dynarr_free (dl->right_glyphs); | |
5276 dl->right_glyphs = 0; | |
5277 } | |
5278 | |
5279 /* We aren't generating a modeline at the moment. */ | |
5280 dl->modeline = 0; | |
5281 | |
5282 /* Create a display block for the text region of the line. */ | |
826 | 5283 ret_charcount = create_string_text_block (w, disp_string, dl, start_pos, |
5284 prop, default_face); | |
5285 dl->charpos = start_pos; | |
5286 if (dl->end_charpos < dl->charpos) | |
5287 dl->end_charpos = dl->charpos; | |
428 | 5288 |
5289 /* If there are left glyphs associated with any character in the | |
5290 text block, then create a display block to handle them. */ | |
5291 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
5292 create_left_glyph_block (w, dl, 0); | |
5293 | |
5294 /* If there are right glyphs associated with any character in the | |
5295 text block, then create a display block to handle them. */ | |
5296 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
5297 create_right_glyph_block (w, dl); | |
5298 | |
826 | 5299 return ret_charcount; |
428 | 5300 } |
5301 | |
2518 | 5302 /* |
5303 | |
5038 | 5304 Info on reentrancy crashes, with backtraces given: |
5305 | |
5306 (Info-goto-node "(internals)Critical Redisplay Sections") | |
5307 | |
1318 | 5308 */ |
5309 | |
5310 | |
428 | 5311 /* This is ripped off from regenerate_window. All we want to do is |
5312 loop through elements in the string creating display lines until we | |
5313 have covered the provided area. Simple really. */ | |
5314 void | |
5315 generate_displayable_area (struct window *w, Lisp_Object disp_string, | |
5316 int xpos, int ypos, int width, int height, | |
5317 display_line_dynarr* dla, | |
826 | 5318 Charcount start_pos, |
428 | 5319 face_index default_face) |
5320 { | |
5321 int yend = ypos + height; | |
5322 Charcount s_zv; | |
5323 prop_block_dynarr *prop = 0; | |
5324 layout_bounds bounds; | |
2518 | 5325 int depth = -1; |
5326 | |
428 | 5327 /* if there's nothing to do then do nothing. code after this assumes |
5328 there is something to do. */ | |
5329 if (NILP (disp_string)) | |
5330 return; | |
5331 | |
2518 | 5332 /* See comment in regenerate_window() */ |
5333 if (!in_display) | |
5334 depth = enter_redisplay_critical_section (); | |
5335 | |
5336 assert (dla); | |
5337 Dynarr_reset (dla); | |
5338 | |
826 | 5339 s_zv = string_char_length (disp_string); |
428 | 5340 |
5341 bounds.left_out = xpos; | |
5342 bounds.right_out = xpos + width; | |
5343 /* The inner boundaries mark where the glyph margins are located. */ | |
5344 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
5345 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
5346 /* We cannot fully calculate the whitespace boundaries as they | |
5347 depend on the contents of the line being displayed. */ | |
5348 bounds.left_white = bounds.left_in; | |
5349 bounds.right_white = bounds.right_in; | |
5350 | |
5351 while (ypos < yend) | |
5352 { | |
5353 struct display_line dl; | |
5354 struct display_line *dlp; | |
826 | 5355 Charcount next_pos; |
428 | 5356 int local; |
851 | 5357 int pos_of_dlp = -1; |
428 | 5358 |
5359 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5360 { | |
851 | 5361 pos_of_dlp = Dynarr_length (dla); |
5362 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5363 local = 0; |
5364 } | |
5365 else | |
5366 { | |
4207 | 5367 DISPLAY_LINE_INIT (dl); |
428 | 5368 dlp = &dl; |
5369 local = 1; | |
5370 } | |
5371 | |
5372 dlp->bounds = bounds; | |
5373 dlp->offset = 0; | |
1318 | 5374 Dynarr_lock (dla); |
428 | 5375 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos, |
5376 &prop, default_face); | |
1318 | 5377 Dynarr_unlock (dla); |
428 | 5378 /* we need to make sure that we continue along the line if there |
4187 | 5379 is more left to display otherwise we just end up redisplaying |
5380 the same chunk over and over again. */ | |
428 | 5381 if (next_pos == start_pos && next_pos < s_zv) |
5382 start_pos++; | |
5383 else | |
5384 start_pos = next_pos; | |
5385 | |
5386 dlp->ypos = ypos + dlp->ascent; | |
5387 ypos = dlp->ypos + dlp->descent; | |
5388 | |
5389 if (ypos > yend) | |
5390 { | |
5391 int visible_height = dlp->ascent + dlp->descent; | |
5392 | |
5393 dlp->clip = (ypos - yend); | |
5394 visible_height -= dlp->clip; | |
5395 | |
5396 if (visible_height < VERTICAL_CLIP (w, 1)) | |
5397 { | |
5398 if (local) | |
5399 free_display_line (dlp); | |
5400 break; | |
5401 } | |
5402 } | |
5403 else | |
5404 dlp->clip = 0; | |
5405 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5406 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
|
5407 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
|
5408 else if (pos_of_dlp == Dynarr_length (dla)) |
5038 | 5409 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
|
5410 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5411 ABORT (); |
428 | 5412 |
5413 /* #### This type of check needs to be done down in the | |
5414 generate_display_line call. */ | |
5415 if (start_pos >= s_zv) | |
5416 break; | |
5417 } | |
5418 | |
5419 if (prop) | |
5420 Dynarr_free (prop); | |
2518 | 5421 |
5422 if (depth >= 0) | |
5423 exit_redisplay_critical_section (depth); | |
428 | 5424 } |
5425 | |
5426 | |
5427 /***************************************************************************/ | |
5428 /* */ | |
5429 /* window-regeneration routines */ | |
5430 /* */ | |
5431 /***************************************************************************/ | |
5432 | |
5433 /* For a given window and starting position in the buffer it contains, | |
5434 ensure that the TYPE display lines accurately represent the | |
5435 presentation of the window. We pass the buffer instead of getting | |
5436 it from the window since redisplay_window may have temporarily | |
5437 changed it to the echo area buffer. */ | |
5438 | |
5439 static void | |
2518 | 5440 regenerate_window (struct window *w, Charbpos start_pos, Charbpos point, |
5441 int type) | |
428 | 5442 { |
5443 struct frame *f = XFRAME (w->frame); | |
5444 struct buffer *b = XBUFFER (w->buffer); | |
5445 int ypos = WINDOW_TEXT_TOP (w); | |
5446 int yend; /* set farther down */ | |
5447 int yclip = WINDOW_TEXT_TOP_CLIP (w); | |
442 | 5448 int force; |
2518 | 5449 int depth = -1; |
428 | 5450 |
5451 prop_block_dynarr *prop; | |
5452 layout_bounds bounds; | |
5453 display_line_dynarr *dla; | |
5454 int need_modeline; | |
5455 | |
5456 /* The lines had better exist by this point. */ | |
5457 if (!(dla = window_display_lines (w, type))) | |
2500 | 5458 ABORT (); |
2518 | 5459 |
5460 if (!in_display) | |
5461 depth = enter_redisplay_critical_section (); | |
5462 | |
5038 | 5463 /* This is one spot where a reentrancy crash will occur, due to a check |
2518 | 5464 in the dynarr to make sure it isn't "locked" */ |
5465 /* | |
5466 | |
5038 | 5467 Info on reentrancy crashes, with backtraces given: |
5468 | |
5469 (Info-goto-node "(internals)Critical Redisplay Sections") | |
2518 | 5470 */ |
5471 | |
428 | 5472 Dynarr_reset (dla); |
5473 w->max_line_len = 0; | |
5474 | |
4968 | 5475 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
5476 because we initialized them at startup and the only way to reduce | |
5477 their number is through calling reset_face_cachels() or | |
5478 reset_glyph_cachels(), which as a side effect sets up a number of | |
5479 standard entries */ | |
5480 assert (Dynarr_length (w->face_cachels)); | |
5481 assert (Dynarr_length (w->glyph_cachels)); | |
5482 | |
5483 #if 0 | |
5484 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
5485 not needed */ | |
428 | 5486 /* Normally these get updated in redisplay_window but it is possible |
5487 for this function to get called from some other points where that | |
5488 update may not have occurred. This acts as a safety check. */ | |
5489 if (!Dynarr_length (w->face_cachels)) | |
5490 reset_face_cachels (w); | |
5491 if (!Dynarr_length (w->glyph_cachels)) | |
5492 reset_glyph_cachels (w); | |
4968 | 5493 #endif |
428 | 5494 |
5495 Fset_marker (w->start[type], make_int (start_pos), w->buffer); | |
5496 Fset_marker (w->pointm[type], make_int (point), w->buffer); | |
5497 w->last_point_x[type] = -1; | |
5498 w->last_point_y[type] = -1; | |
5499 | |
5500 /* Make sure a modeline is in the structs if needed. */ | |
5501 need_modeline = ensure_modeline_generated (w, type); | |
5502 | |
5503 /* Wait until here to set this so that the structs have a modeline | |
5504 generated in the case where one didn't exist. */ | |
5505 yend = WINDOW_TEXT_BOTTOM (w); | |
5506 | |
5507 bounds = calculate_display_line_boundaries (w, 0); | |
5508 | |
5509 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */ | |
5510 if (MINI_WINDOW_P (w) | |
5511 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt)) | |
5512 && !echo_area_active (f) | |
5513 && start_pos == BUF_BEGV (b)) | |
5514 { | |
5515 struct prop_block pb; | |
5516 Lisp_Object string; | |
5517 prop = Dynarr_new (prop_block); | |
5518 | |
5519 string = concat2(Vminibuf_preprompt, Vminibuf_prompt); | |
5520 pb.type = PROP_MINIBUF_PROMPT; | |
5521 pb.data.p_string.str = XSTRING_DATA(string); | |
5522 pb.data.p_string.len = XSTRING_LENGTH(string); | |
5523 Dynarr_add (prop, pb); | |
5524 } | |
5525 else | |
5526 prop = 0; | |
5527 | |
442 | 5528 /* When we are computing things for scrolling purposes, make |
5529 sure at least one line is always generated */ | |
5530 force = (type == CMOTION_DISP); | |
5531 | |
5532 /* Make sure this is set always */ | |
5533 /* Note the conversion at end */ | |
5534 w->window_end_pos[type] = start_pos; | |
5535 while (ypos < yend || force) | |
428 | 5536 { |
5537 struct display_line dl; | |
5538 struct display_line *dlp; | |
5539 int local; | |
851 | 5540 int pos_of_dlp = -1; |
428 | 5541 |
5542 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5543 { | |
851 | 5544 pos_of_dlp = Dynarr_length (dla); |
5545 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5546 local = 0; |
5547 } | |
5548 else | |
5549 { | |
4207 | 5550 DISPLAY_LINE_INIT (dl); |
428 | 5551 dlp = &dl; |
5552 local = 1; | |
5553 } | |
5554 | |
5555 dlp->bounds = bounds; | |
5556 dlp->offset = 0; | |
1318 | 5557 Dynarr_lock (dla); |
428 | 5558 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); |
1318 | 5559 Dynarr_unlock (dla); |
428 | 5560 |
5561 if (yclip > dlp->ascent) | |
5562 { | |
5563 /* this should never happen, but if it does just display the | |
5564 whole line */ | |
5565 yclip = 0; | |
5566 } | |
5567 | |
5568 dlp->ypos = (ypos + dlp->ascent) - yclip; | |
5569 ypos = dlp->ypos + dlp->descent; | |
5570 | |
5571 /* See if we've been asked to start midway through a line, for | |
4187 | 5572 partial display line scrolling. */ |
434 | 5573 if (yclip) |
428 | 5574 { |
5575 dlp->top_clip = yclip; | |
5576 yclip = 0; | |
5577 } | |
5578 else | |
5579 dlp->top_clip = 0; | |
5580 | |
5581 if (ypos > yend) | |
5582 { | |
5583 int visible_height = dlp->ascent + dlp->descent; | |
5584 | |
5585 dlp->clip = (ypos - yend); | |
5586 /* Although this seems strange we could have a single very | |
5587 tall line visible for which we need to account for both | |
5588 the top clip and the bottom clip. */ | |
5589 visible_height -= (dlp->clip + dlp->top_clip); | |
5590 | |
442 | 5591 if (visible_height < VERTICAL_CLIP (w, 1) && !force) |
428 | 5592 { |
5593 if (local) | |
5594 free_display_line (dlp); | |
5595 break; | |
5596 } | |
5597 } | |
5598 else | |
5599 dlp->clip = 0; | |
5600 | |
5601 if (dlp->cursor_elt != -1) | |
5602 { | |
5603 /* #### This check is steaming crap. Have to get things | |
4187 | 5604 fixed so when create_text_block hits EOB, we're done, |
5605 period. */ | |
428 | 5606 if (w->last_point_x[type] == -1) |
5607 { | |
5608 w->last_point_x[type] = dlp->cursor_elt; | |
5609 w->last_point_y[type] = Dynarr_length (dla); | |
5610 } | |
5611 else | |
5612 { | |
5613 /* #### This means that we've added a cursor at EOB | |
4187 | 5614 twice. Yuck oh yuck. */ |
1318 | 5615 struct display_block *db; |
5616 | |
5617 Dynarr_lock (dla); | |
5618 db = get_display_block_from_line (dlp, TEXT); | |
5619 Dynarr_unlock (dla); | |
428 | 5620 |
5621 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR; | |
5622 dlp->cursor_elt = -1; | |
5623 } | |
5624 } | |
5625 | |
5626 if (dlp->num_chars > w->max_line_len) | |
5627 w->max_line_len = dlp->num_chars; | |
5628 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5629 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
|
5630 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
|
5631 else if (pos_of_dlp == Dynarr_length (dla)) |
5038 | 5632 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
|
5633 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5634 ABORT (); |
428 | 5635 |
5636 /* #### This isn't right, but it is close enough for now. */ | |
5637 w->window_end_pos[type] = start_pos; | |
5638 | |
5639 /* #### This type of check needs to be done down in the | |
5640 generate_display_line call. */ | |
5641 if (start_pos > BUF_ZV (b)) | |
5642 break; | |
442 | 5643 |
5644 force = 0; | |
428 | 5645 } |
5646 | |
5647 if (prop) | |
5648 Dynarr_free (prop); | |
5649 | |
5650 /* #### More not quite right, but close enough. */ | |
442 | 5651 /* Ben sez: apparently window_end_pos[] is measured |
428 | 5652 as the number of characters between the window end and the |
5653 end of the buffer? This seems rather weirdo. What's | |
442 | 5654 the justification for this? |
5655 | |
5656 JV sez: Because BUF_Z (b) would be a good initial value, however | |
5657 that can change. This representation allows initalizing with 0. | |
5658 */ | |
428 | 5659 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; |
5660 | |
5661 if (need_modeline) | |
5662 { | |
5663 /* We know that this is the right thing to use because we put it | |
4187 | 5664 there when we first started working in this function. */ |
4967 | 5665 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 5666 } |
2518 | 5667 |
5668 if (depth >= 0) | |
5669 exit_redisplay_critical_section (depth); | |
428 | 5670 } |
5671 | |
826 | 5672 #define REGEN_INC_FIND_START_END \ |
5673 do { \ | |
5674 /* Determine start and end of lines. */ \ | |
5675 if (!Dynarr_length (cdla)) \ | |
5676 return 0; \ | |
5677 else \ | |
5678 { \ | |
4967 | 5679 if (Dynarr_begin (cdla)->modeline && Dynarr_begin (ddla)->modeline) \ |
826 | 5680 { \ |
5681 dla_start = 1; \ | |
5682 } \ | |
4967 | 5683 else if (!Dynarr_begin (cdla)->modeline \ |
5684 && !Dynarr_begin (ddla)->modeline) \ | |
826 | 5685 { \ |
5686 dla_start = 0; \ | |
5687 } \ | |
5688 else \ | |
2500 | 5689 ABORT (); /* structs differ */ \ |
826 | 5690 \ |
5691 dla_end = Dynarr_length (cdla) - 1; \ | |
5692 } \ | |
5693 \ | |
5694 start_pos = (Dynarr_atp (cdla, dla_start)->charpos \ | |
5695 + Dynarr_atp (cdla, dla_start)->offset); \ | |
5696 /* If this isn't true, then startp has changed and we need to do a \ | |
5697 full regen. */ \ | |
5698 if (startp != start_pos) \ | |
5699 return 0; \ | |
5700 \ | |
5701 /* Point is outside the visible region so give up. */ \ | |
5702 if (pointm < start_pos) \ | |
5703 return 0; \ | |
5704 \ | |
428 | 5705 } while (0) |
5706 | |
5707 /* This attempts to incrementally update the display structures. It | |
5708 returns a boolean indicating success or failure. This function is | |
5709 very similar to regenerate_window_incrementally and is in fact only | |
5710 called from that function. However, because of the nature of the | |
5711 changes it deals with it sometimes makes different assumptions | |
5712 which can lead to success which are much more difficult to make | |
5713 when dealing with buffer changes. */ | |
5714 | |
5715 static int | |
665 | 5716 regenerate_window_extents_only_changed (struct window *w, Charbpos startp, |
5717 Charbpos pointm, | |
428 | 5718 Charcount beg_unchanged, |
5719 Charcount end_unchanged) | |
5720 { | |
5721 struct buffer *b = XBUFFER (w->buffer); | |
5722 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5723 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5724 | |
5725 int dla_start = 0; | |
5726 int dla_end, line; | |
5727 int first_line, last_line; | |
665 | 5728 Charbpos start_pos; |
428 | 5729 /* Don't define this in the loop where it is used because we |
5730 definitely want its value to survive between passes. */ | |
5731 prop_block_dynarr *prop = NULL; | |
5732 | |
5733 /* If we don't have any buffer change recorded but the modiff flag has | |
5734 been incremented, then fail. I'm not sure of the exact circumstances | |
5735 under which this can happen, but I believe that it is probably a | |
5736 reasonable happening. */ | |
5737 if (!point_visible (w, pointm, CURRENT_DISP) | |
5738 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)) | |
5739 return 0; | |
5740 | |
5741 /* If the cursor is moved we attempt to update it. If we succeed we | |
5742 go ahead and proceed with the optimization attempt. */ | |
5743 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5744 || pointm != marker_position (w->last_point[CURRENT_DISP])) | |
5745 { | |
5746 struct frame *f = XFRAME (w->frame); | |
5747 struct device *d = XDEVICE (f->device); | |
5748 struct frame *sel_f = device_selected_frame (d); | |
5749 int success = 0; | |
5750 | |
5751 if (w->last_point_x[CURRENT_DISP] != -1 | |
5752 && w->last_point_y[CURRENT_DISP] != -1) | |
5753 { | |
5754 | |
5755 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w))) | |
5756 { | |
5757 /* Always regenerate the modeline in case it is | |
4187 | 5758 displaying the current line or column. */ |
428 | 5759 regenerate_modeline (w); |
5760 success = 1; | |
5761 } | |
5762 } | |
5763 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f))) | |
5764 { | |
5765 if (f->modeline_changed) | |
5766 regenerate_modeline (w); | |
5767 success = 1; | |
5768 } | |
5769 | |
5770 if (!success) | |
5771 return 0; | |
5772 } | |
5773 | |
5774 if (beg_unchanged == -1 && end_unchanged == -1) | |
5775 return 1; | |
5776 | |
5777 /* assert: There are no buffer modifications or they are all below the | |
5778 visible region. We assume that regenerate_window_incrementally has | |
5779 not called us unless this is true. */ | |
5780 | |
5781 REGEN_INC_FIND_START_END; | |
5782 | |
5783 /* If the changed are starts before the visible area, give up. */ | |
5784 if (beg_unchanged < startp) | |
5785 return 0; | |
5786 | |
5787 /* Find what display line the extent changes first affect. */ | |
5788 line = dla_start; | |
5789 while (line <= dla_end) | |
5790 { | |
5791 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5792 Charbpos lstart = dl->charpos + dl->offset; |
5793 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5794 |
5795 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5796 break; | |
5797 | |
5798 line++; | |
5799 } | |
5800 | |
5801 /* If the changes are below the visible area then if point hasn't | |
5802 moved return success otherwise fail in order to be safe. */ | |
5803 if (line > dla_end) | |
5804 { | |
5805 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5806 && pointm == marker_position (w->last_point[CURRENT_DISP])) | |
5807 return 1; | |
5808 else | |
5809 return 0; | |
5810 } | |
5811 | |
5812 /* At this point we know what line the changes first affect. We now | |
5813 begin redrawing lines as long as we are still in the affected | |
5814 region and the line's size and positioning don't change. | |
5815 Otherwise we fail. If we fail we will have altered the desired | |
5816 structs which could lead to an assertion failure. However, if we | |
5817 fail the next thing that is going to happen is a full regen so we | |
5818 will actually end up being safe. */ | |
5819 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
5820 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
5821 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
5822 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
5823 | |
5824 first_line = last_line = line; | |
5825 while (line <= dla_end) | |
5826 { | |
2286 | 5827 Charbpos old_start, old_end; |
428 | 5828 struct display_line *cdl = Dynarr_atp (cdla, line); |
5829 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5830 struct display_block *db; | |
5831 int initial_size; | |
5832 | |
826 | 5833 assert (cdl->charpos == ddl->charpos); |
5834 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5835 assert (cdl->offset == ddl->offset); |
5836 | |
5837 db = get_display_block_from_line (ddl, TEXT); | |
5838 initial_size = Dynarr_length (db->runes); | |
826 | 5839 old_start = ddl->charpos + ddl->offset; |
5840 old_end = ddl->end_charpos + ddl->offset; | |
428 | 5841 |
5842 /* If this is the first line being updated and it used | |
4187 | 5843 propagation data, fail. Otherwise we'll be okay because |
5844 we'll have the necessary propagation data. */ | |
428 | 5845 if (line == first_line && ddl->used_prop_data) |
5846 return 0; | |
5847 | |
2286 | 5848 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
5849 &prop, DESIRED_DISP); | |
428 | 5850 ddl->offset = 0; |
5851 | |
5852 /* #### If there is propagated stuff the fail. We could | |
4187 | 5853 probably actually deal with this if the line had propagated |
5854 information when originally created by a full | |
5855 regeneration. */ | |
428 | 5856 if (prop) |
5857 { | |
5858 Dynarr_free (prop); | |
5859 return 0; | |
5860 } | |
5861 | |
5862 /* If any line position parameters have changed or a | |
4187 | 5863 cursor has disappeared or disappeared, fail. */ |
428 | 5864 db = get_display_block_from_line (ddl, TEXT); |
5865 if (cdl->ypos != ddl->ypos | |
5866 || cdl->ascent != ddl->ascent | |
5867 || cdl->descent != ddl->descent | |
5868 || cdl->top_clip != ddl->top_clip | |
5869 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
5870 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
826 | 5871 || old_start != ddl->charpos |
5872 || old_end != ddl->end_charpos | |
428 | 5873 || initial_size != Dynarr_length (db->runes)) |
5874 { | |
5875 return 0; | |
5876 } | |
5877 | |
5878 if (ddl->cursor_elt != -1) | |
5879 { | |
5880 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
5881 w->last_point_y[DESIRED_DISP] = line; | |
5882 } | |
5883 | |
5884 last_line = line; | |
5885 | |
5886 /* If the extent changes end on the line we just updated then | |
4187 | 5887 we're done. Otherwise go on to the next line. */ |
826 | 5888 if (end_unchanged <= ddl->end_charpos) |
428 | 5889 break; |
5890 else | |
5891 line++; | |
5892 } | |
5893 | |
5894 redisplay_update_line (w, first_line, last_line, 1); | |
5895 return 1; | |
5896 } | |
5897 | |
5898 /* Attempt to update the display data structures based on knowledge of | |
5899 the changed region in the buffer. Returns a boolean indicating | |
5900 success or failure. If this function returns a failure then a | |
5901 regenerate_window _must_ be performed next in order to maintain | |
5902 invariants located here. */ | |
5903 | |
5904 static int | |
665 | 5905 regenerate_window_incrementally (struct window *w, Charbpos startp, |
5906 Charbpos pointm) | |
428 | 5907 { |
5908 struct buffer *b = XBUFFER (w->buffer); | |
5909 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5910 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5911 Charcount beg_unchanged, end_unchanged; | |
5912 Charcount extent_beg_unchanged, extent_end_unchanged; | |
5913 | |
5914 int dla_start = 0; | |
5915 int dla_end, line; | |
665 | 5916 Charbpos start_pos; |
428 | 5917 |
5918 /* If this function is called, the current and desired structures | |
5919 had better be identical. If they are not, then that is a bug. */ | |
5920 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
5921 | |
5922 /* We don't handle minibuffer windows yet. The minibuffer prompt | |
5923 screws us up. */ | |
5924 if (MINI_WINDOW_P (w)) | |
5925 return 0; | |
5926 | |
5927 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b); | |
5928 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1 | |
5929 ? -1 | |
5930 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b)); | |
5931 | |
5932 /* If nothing has changed in the buffer, then make sure point is ok | |
5933 and succeed. */ | |
5934 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1) | |
5935 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5936 extent_beg_unchanged, | |
5937 extent_end_unchanged); | |
5938 | |
5939 /* We can't deal with deleted newlines. */ | |
5940 if (BUF_NEWLINE_WAS_DELETED (b)) | |
5941 return 0; | |
5942 | |
5943 beg_unchanged = BUF_BEGIN_UNCHANGED (b); | |
5944 end_unchanged = (BUF_END_UNCHANGED (b) == -1 | |
5945 ? -1 | |
5946 : BUF_Z (b) - BUF_END_UNCHANGED (b)); | |
5947 | |
5948 REGEN_INC_FIND_START_END; | |
5949 | |
5950 /* If the changed area starts before the visible area, give up. */ | |
5951 if (beg_unchanged < startp) | |
5952 return 0; | |
5953 | |
5954 /* Find what display line the buffer changes first affect. */ | |
5955 line = dla_start; | |
5956 while (line <= dla_end) | |
5957 { | |
5958 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5959 Charbpos lstart = dl->charpos + dl->offset; |
5960 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5961 |
5962 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5963 break; | |
5964 | |
5965 line++; | |
5966 } | |
5967 | |
5968 /* If the changes are below the visible area then if point hasn't | |
5969 moved return success otherwise fail in order to be safe. */ | |
5970 if (line > dla_end) | |
5971 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5972 extent_beg_unchanged, | |
5973 extent_end_unchanged); | |
5974 else | |
5975 /* At this point we know what line the changes first affect. We | |
5976 now redraw that line. If the changes are contained within it | |
5977 we are going to succeed and can update just that one line. | |
5978 Otherwise we fail. If we fail we will have altered the desired | |
5979 structs which could lead to an assertion failure. However, if | |
5980 we fail the next thing that is going to happen is a full regen | |
5981 so we will actually end up being safe. */ | |
5982 { | |
5983 prop_block_dynarr *prop = NULL; | |
5984 struct display_line *cdl = Dynarr_atp (cdla, line); | |
5985 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5986 | |
826 | 5987 assert (cdl->charpos == ddl->charpos); |
5988 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5989 assert (cdl->offset == ddl->offset); |
5990 | |
442 | 5991 /* If the line continues to next display line, fail. */ |
5992 if (ddl->line_continuation) | |
5993 return 0; | |
428 | 5994 |
5995 /* If the line was generated using propagation data, fail. */ | |
5996 if (ddl->used_prop_data) | |
5997 return 0; | |
5998 | |
2286 | 5999 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
6000 &prop, DESIRED_DISP); | |
428 | 6001 ddl->offset = 0; |
6002 | |
6003 /* If there is propagated stuff then it is pretty much a | |
4187 | 6004 guarantee that more than just the one line is affected. */ |
428 | 6005 if (prop) |
6006 { | |
6007 Dynarr_free (prop); | |
6008 return 0; | |
6009 } | |
6010 | |
442 | 6011 /* If the line continues to next display line, fail. */ |
6012 if (ddl->line_continuation) | |
6013 return 0; | |
428 | 6014 |
6015 /* If any line position parameters have changed or a | |
4187 | 6016 cursor has disappeared or disappeared, fail. */ |
428 | 6017 if (cdl->ypos != ddl->ypos |
6018 || cdl->ascent != ddl->ascent | |
6019 || cdl->descent != ddl->descent | |
6020 || cdl->top_clip != ddl->top_clip | |
6021 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
6022 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) | |
6023 { | |
6024 return 0; | |
6025 } | |
6026 | |
6027 /* If the changed area also ends on this line, then we may be in | |
4187 | 6028 business. Update everything and return success. */ |
826 | 6029 if (end_unchanged >= ddl->charpos && end_unchanged <= ddl->end_charpos) |
428 | 6030 { |
6031 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
6032 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
6033 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), | |
6034 w->buffer); | |
6035 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), | |
6036 w->buffer); | |
6037 | |
6038 if (ddl->cursor_elt != -1) | |
6039 { | |
6040 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
6041 w->last_point_y[DESIRED_DISP] = line; | |
6042 } | |
6043 | |
6044 redisplay_update_line (w, line, line, 1); | |
6045 regenerate_modeline (w); | |
6046 | |
6047 /* #### For now we just flush the cache until this has been | |
4187 | 6048 tested. After that is done, this should correct the |
6049 cache directly. */ | |
428 | 6050 Dynarr_reset (w->line_start_cache); |
6051 | |
6052 /* Adjust the extent changed boundaries to remove any | |
4187 | 6053 overlap with the buffer changes since we've just |
6054 successfully updated that area. */ | |
428 | 6055 if (extent_beg_unchanged != -1 |
6056 && extent_beg_unchanged >= beg_unchanged | |
6057 && extent_beg_unchanged < end_unchanged) | |
6058 extent_beg_unchanged = end_unchanged; | |
6059 | |
6060 if (extent_end_unchanged != -1 | |
6061 && extent_end_unchanged >= beg_unchanged | |
6062 && extent_end_unchanged < end_unchanged) | |
6063 extent_end_unchanged = beg_unchanged - 1; | |
6064 | |
6065 if (extent_end_unchanged <= extent_beg_unchanged) | |
6066 extent_beg_unchanged = extent_end_unchanged = -1; | |
6067 | |
6068 /* This could lead to odd results if it fails, but since the | |
4187 | 6069 buffer changes update succeeded this probably will to. |
6070 We already know that the extent changes start at or after | |
6071 the line because we checked before entering the loop. */ | |
428 | 6072 if (extent_beg_unchanged != -1 |
6073 && extent_end_unchanged != -1 | |
826 | 6074 && ((extent_beg_unchanged < ddl->charpos) |
6075 || (extent_end_unchanged > ddl->end_charpos))) | |
428 | 6076 return regenerate_window_extents_only_changed (w, startp, pointm, |
6077 extent_beg_unchanged, | |
6078 extent_end_unchanged); | |
6079 else | |
6080 return 1; | |
6081 } | |
6082 } | |
6083 | |
6084 /* Oh, well. */ | |
6085 return 0; | |
6086 } | |
6087 | |
6088 /* Given a window and a point, update the given display lines such | |
6089 that point is displayed in the middle of the window. | |
6090 Return the window's new start position. */ | |
6091 | |
665 | 6092 static Charbpos |
6093 regenerate_window_point_center (struct window *w, Charbpos point, int type) | |
428 | 6094 { |
665 | 6095 Charbpos startp; |
428 | 6096 |
6097 /* We need to make sure that the modeline is generated so that the | |
6098 window height can be calculated correctly. */ | |
6099 ensure_modeline_generated (w, type); | |
6100 | |
6101 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w)); | |
6102 regenerate_window (w, startp, point, type); | |
6103 Fset_marker (w->start[type], make_int (startp), w->buffer); | |
6104 | |
6105 return startp; | |
6106 } | |
6107 | |
6108 /* Given a window and a set of display lines, return a boolean | |
6109 indicating whether the given point is contained within. */ | |
6110 | |
6111 static int | |
665 | 6112 point_visible (struct window *w, Charbpos point, int type) |
428 | 6113 { |
6114 struct buffer *b = XBUFFER (w->buffer); | |
6115 display_line_dynarr *dla = window_display_lines (w, type); | |
6116 int first_line; | |
6117 | |
4967 | 6118 if (Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
428 | 6119 first_line = 1; |
6120 else | |
6121 first_line = 0; | |
6122 | |
6123 if (Dynarr_length (dla) > first_line) | |
6124 { | |
665 | 6125 Charbpos start, end; |
428 | 6126 struct display_line *dl = Dynarr_atp (dla, first_line); |
6127 | |
826 | 6128 start = dl->charpos; |
428 | 6129 end = BUF_Z (b) - w->window_end_pos[type] - 1; |
6130 | |
6131 if (point >= start && point <= end) | |
6132 { | |
6133 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines) | |
6134 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
6135 dl = Dynarr_lastp (dla); |
428 | 6136 |
826 | 6137 if (point >= (dl->charpos + dl->offset) |
6138 && point <= (dl->end_charpos + dl->offset)) | |
428 | 6139 return !dl->clip; |
6140 else | |
6141 return 1; | |
6142 } | |
6143 else | |
6144 return 1; | |
6145 } | |
6146 else | |
6147 return 0; | |
6148 } | |
6149 else | |
6150 return 0; | |
6151 } | |
6152 | |
6153 /* Return pixel position the middle of the window, not including the | |
6154 modeline and any potential horizontal scrollbar. */ | |
6155 | |
6156 int | |
6157 window_half_pixpos (struct window *w) | |
6158 { | |
6159 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1); | |
6160 } | |
6161 | |
6162 /* Return the display line which is currently in the middle of the | |
6163 window W for display lines TYPE. */ | |
6164 | |
6165 int | |
665 | 6166 line_at_center (struct window *w, int type, Charbpos start, Charbpos point) |
428 | 6167 { |
6168 display_line_dynarr *dla; | |
6169 int half; | |
6170 int elt; | |
6171 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1); | |
6172 | |
6173 if (type == CMOTION_DISP) | |
6174 regenerate_window (w, start, point, type); | |
6175 | |
6176 dla = window_display_lines (w, type); | |
6177 half = window_half_pixpos (w); | |
6178 | |
6179 for (elt = first_elt; elt < Dynarr_length (dla); elt++) | |
6180 { | |
6181 struct display_line *dl = Dynarr_atp (dla, elt); | |
6182 int line_bot = dl->ypos + dl->descent; | |
6183 | |
6184 if (line_bot > half) | |
6185 return elt; | |
6186 } | |
6187 | |
6188 /* We may not have a line at the middle if the end of the buffer is | |
6189 being displayed. */ | |
6190 return -1; | |
6191 } | |
6192 | |
6193 /* Return a value for point that would place it at the beginning of | |
6194 the line which is in the middle of the window. */ | |
6195 | |
665 | 6196 Charbpos |
6197 point_at_center (struct window *w, int type, Charbpos start, Charbpos point) | |
428 | 6198 { |
6199 /* line_at_center will regenerate the display structures, if necessary. */ | |
6200 int line = line_at_center (w, type, start, point); | |
6201 | |
6202 if (line == -1) | |
6203 return BUF_ZV (XBUFFER (w->buffer)); | |
6204 else | |
6205 { | |
6206 display_line_dynarr *dla = window_display_lines (w, type); | |
6207 struct display_line *dl = Dynarr_atp (dla, line); | |
6208 | |
826 | 6209 return dl->charpos; |
428 | 6210 } |
6211 } | |
6212 | |
6213 /* For a given window, ensure that the current visual representation | |
6214 is accurate. */ | |
6215 | |
6216 static void | |
6217 redisplay_window (Lisp_Object window, int skip_selected) | |
6218 { | |
6219 struct window *w = XWINDOW (window); | |
6220 struct frame *f = XFRAME (w->frame); | |
6221 struct device *d = XDEVICE (f->device); | |
6222 Lisp_Object old_buffer = w->buffer; | |
6223 Lisp_Object the_buffer = w->buffer; | |
6224 struct buffer *b; | |
6225 int echo_active = 0; | |
6226 int startp = 1; | |
6227 int pointm; | |
6228 int old_startp = 1; | |
6229 int old_pointm = 1; | |
6230 int selected_in_its_frame; | |
6231 int selected_globally; | |
6232 int skip_output = 0; | |
6233 int truncation_changed; | |
6234 int inactive_minibuffer = | |
6235 (MINI_WINDOW_P (w) && | |
6236 (f != device_selected_frame (d)) && | |
6237 !is_surrogate_for_selected_frame (f)); | |
6238 | |
6239 /* #### In the new world this function actually does a bunch of | |
6240 optimizations such as buffer-based scrolling, but none of that is | |
6241 implemented yet. */ | |
6242 | |
6243 /* If this is a combination window, do its children; that's all. | |
6244 The selected window is always a leaf so we don't check for | |
6245 skip_selected here. */ | |
6246 if (!NILP (w->vchild)) | |
6247 { | |
6248 redisplay_windows (w->vchild, skip_selected); | |
6249 return; | |
6250 } | |
6251 if (!NILP (w->hchild)) | |
6252 { | |
6253 redisplay_windows (w->hchild, skip_selected); | |
6254 return; | |
6255 } | |
6256 | |
6257 /* Is this window the selected window on its frame? */ | |
6258 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f))); | |
6259 selected_globally = | |
6260 selected_in_its_frame && | |
6261 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
6262 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d && | |
6263 XFRAME(DEVICE_SELECTED_FRAME(d)) == f; | |
6264 if (skip_selected && selected_in_its_frame) | |
6265 return; | |
6266 | |
6267 /* It is possible that the window is not fully initialized yet. */ | |
6268 if (NILP (w->buffer)) | |
6269 return; | |
6270 | |
6271 if (MINI_WINDOW_P (w) && echo_area_active (f)) | |
6272 { | |
6273 w->buffer = the_buffer = Vecho_area_buffer; | |
6274 echo_active = 1; | |
6275 } | |
6276 | |
6277 b = XBUFFER (w->buffer); | |
6278 | |
6279 if (echo_active) | |
6280 { | |
6281 old_pointm = selected_globally | |
4187 | 6282 ? BUF_PT (b) |
6283 : marker_position (w->pointm[CURRENT_DISP]); | |
428 | 6284 pointm = 1; |
6285 } | |
6286 else | |
6287 { | |
6288 if (selected_globally) | |
6289 { | |
6290 pointm = BUF_PT (b); | |
6291 } | |
6292 else | |
6293 { | |
6294 pointm = marker_position (w->pointm[CURRENT_DISP]); | |
6295 | |
6296 if (pointm < BUF_BEGV (b)) | |
6297 pointm = BUF_BEGV (b); | |
6298 else if (pointm > BUF_ZV (b)) | |
6299 pointm = BUF_ZV (b); | |
6300 } | |
6301 } | |
6302 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); | |
6303 | |
4968 | 6304 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
6305 because we initialized them at startup and the only way to reduce | |
6306 their number is through calling reset_face_cachels() or | |
6307 reset_glyph_cachels(), which as a side effect sets up a number of | |
6308 standard entries */ | |
6309 assert (Dynarr_length (w->face_cachels)); | |
6310 assert (Dynarr_length (w->glyph_cachels)); | |
6311 | |
428 | 6312 /* If the buffer has changed we have to invalidate all of our face |
6313 cache elements. */ | |
6314 if ((!echo_active && b != window_display_buffer (w)) | |
4968 | 6315 #if 0 |
6316 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
6317 not needed */ | |
428 | 6318 || !Dynarr_length (w->face_cachels) |
4968 | 6319 #endif |
428 | 6320 || f->faces_changed) |
6321 reset_face_cachels (w); | |
6322 else | |
6323 mark_face_cachels_as_not_updated (w); | |
6324 | |
6325 /* Ditto the glyph cache elements, although we do *not* invalidate | |
6326 the cache purely because glyphs have changed - this is now | |
6327 handled by the dirty flag.*/ | |
6328 if ((!echo_active && b != window_display_buffer (w)) | |
4968 | 6329 #if 0 |
6330 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
6331 not needed */ | |
6332 || !Dynarr_length (w->glyph_cachels) | |
6333 #endif | |
6334 || f->faces_changed) | |
428 | 6335 reset_glyph_cachels (w); |
6336 else | |
6337 mark_glyph_cachels_as_not_updated (w); | |
6338 | |
6339 /* If the marker's buffer is not the window's buffer, then we need | |
6340 to find a new starting position. */ | |
6341 if (!MINI_WINDOW_P (w) | |
6342 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer)) | |
6343 { | |
6344 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6345 | |
6346 goto regeneration_done; | |
6347 } | |
6348 | |
6349 if (echo_active) | |
6350 { | |
6351 old_startp = marker_position (w->start[CURRENT_DISP]); | |
6352 startp = 1; | |
6353 } | |
6354 else | |
6355 { | |
6356 startp = marker_position (w->start[CURRENT_DISP]); | |
6357 if (startp < BUF_BEGV (b)) | |
6358 startp = BUF_BEGV (b); | |
6359 else if (startp > BUF_ZV (b)) | |
6360 startp = BUF_ZV (b); | |
6361 } | |
6362 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer); | |
6363 | |
6364 truncation_changed = (find_window_mirror (w)->truncate_win != | |
647 | 6365 (unsigned int) window_truncation_on (w)); |
428 | 6366 |
6367 /* If w->force_start is set, then some function set w->start and we | |
6368 should display from there and change point, if necessary, to | |
6369 ensure that it is visible. */ | |
6370 if (w->force_start || inactive_minibuffer) | |
6371 { | |
6372 w->force_start = 0; | |
6373 w->last_modified[DESIRED_DISP] = Qzero; | |
6374 w->last_facechange[DESIRED_DISP] = Qzero; | |
6375 | |
6376 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6377 | |
6378 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer) | |
6379 { | |
6380 pointm = point_at_center (w, DESIRED_DISP, 0, 0); | |
6381 | |
6382 if (selected_globally) | |
6383 BUF_SET_PT (b, pointm); | |
6384 | |
6385 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), | |
6386 the_buffer); | |
6387 | |
6388 /* #### BUFU amounts of overkill just to get the cursor | |
4187 | 6389 location marked properly. FIX ME FIX ME FIX ME */ |
428 | 6390 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6391 } | |
6392 | |
6393 goto regeneration_done; | |
6394 } | |
6395 | |
6396 /* If nothing has changed since the last redisplay, then we just | |
6397 need to make sure that point is still visible. */ | |
6398 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) | |
6399 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b) | |
6400 && pointm >= startp | |
6401 /* This check is to make sure we restore the minibuffer after a | |
4187 | 6402 temporary change to the echo area. */ |
428 | 6403 && !(MINI_WINDOW_P (w) && f->buffers_changed) |
6404 && !f->frame_changed | |
6405 && !truncation_changed | |
442 | 6406 /* check whether start is really at the beginning of a line GE */ |
428 | 6407 && (!w->start_at_line_beg || beginning_of_line_p (b, startp)) |
6408 ) | |
6409 { | |
6410 /* Check if the cursor has actually moved. */ | |
6411 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
6412 && pointm == marker_position (w->last_point[CURRENT_DISP]) | |
6413 && selected_globally | |
6414 && !w->windows_changed | |
6415 && !f->clip_changed | |
6416 && !f->extents_changed | |
6417 && !f->faces_changed | |
6418 && !f->glyphs_changed | |
6419 && !f->subwindows_changed | |
442 | 6420 /* && !f->subwindows_state_changed*/ |
428 | 6421 && !f->point_changed |
6422 && !f->windows_structure_changed) | |
6423 { | |
6424 /* If not, we're done. */ | |
6425 if (f->modeline_changed) | |
6426 regenerate_modeline (w); | |
6427 | |
6428 skip_output = 1; | |
6429 goto regeneration_done; | |
6430 } | |
6431 else | |
6432 { | |
6433 /* If the new point is visible in the redisplay structures, | |
4187 | 6434 then let the output update routines handle it, otherwise |
6435 do things the hard way. */ | |
428 | 6436 if (!w->windows_changed |
6437 && !f->clip_changed | |
6438 && !f->extents_changed | |
6439 && !f->faces_changed | |
6440 && !f->glyphs_changed | |
6441 && !f->subwindows_changed | |
442 | 6442 /* && !f->subwindows_state_changed*/ |
428 | 6443 && !f->windows_structure_changed) |
6444 { | |
6445 if (point_visible (w, pointm, CURRENT_DISP) | |
6446 && w->last_point_x[CURRENT_DISP] != -1 | |
6447 && w->last_point_y[CURRENT_DISP] != -1) | |
6448 { | |
6449 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f))) | |
6450 { | |
6451 /* Always regenerate in case it is displaying | |
4187 | 6452 the current line or column. */ |
428 | 6453 regenerate_modeline (w); |
6454 | |
6455 skip_output = 1; | |
6456 goto regeneration_done; | |
6457 } | |
6458 } | |
6459 else if (!selected_in_its_frame && !f->point_changed) | |
6460 { | |
6461 if (f->modeline_changed) | |
6462 regenerate_modeline (w); | |
6463 | |
6464 skip_output = 1; | |
6465 goto regeneration_done; | |
6466 } | |
6467 } | |
6468 | |
6469 /* If we weren't able to take the shortcut method, then use | |
4187 | 6470 the brute force method. */ |
428 | 6471 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6472 | |
6473 if (point_visible (w, pointm, DESIRED_DISP)) | |
6474 goto regeneration_done; | |
6475 } | |
6476 } | |
6477 | |
6478 /* Check if the starting point is no longer at the beginning of a | |
6479 line, in which case find a new starting point. We also recenter | |
6480 if our start position is equal to point-max. Otherwise we'll end | |
6481 up with a blank window. */ | |
6482 else if (((w->start_at_line_beg || MINI_WINDOW_P (w)) | |
6483 && !(startp == BUF_BEGV (b) | |
6484 || BUF_FETCH_CHAR (b, startp - 1) == '\n')) | |
6485 || (pointm == startp && | |
6486 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) && | |
6487 startp < marker_position (w->last_start[CURRENT_DISP])) | |
6488 || (startp == BUF_ZV (b))) | |
6489 { | |
6490 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6491 | |
6492 goto regeneration_done; | |
6493 } | |
6494 /* See if we can update the data structures locally based on | |
6495 knowledge of what changed in the buffer. */ | |
6496 else if (!w->windows_changed | |
6497 && !f->clip_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 && !f->frame_changed | |
6504 && !truncation_changed | |
6505 && pointm >= startp | |
6506 && regenerate_window_incrementally (w, startp, pointm)) | |
6507 { | |
6508 if (f->modeline_changed | |
6509 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b) | |
6510 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b)) | |
6511 regenerate_modeline (w); | |
6512 | |
6513 skip_output = 1; | |
6514 goto regeneration_done; | |
6515 } | |
6516 /* #### This is where a check for structure based scrolling would go. */ | |
6517 /* If all else fails, try just regenerating and see what happens. */ | |
6518 else | |
6519 { | |
6520 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6521 | |
6522 if (point_visible (w, pointm, DESIRED_DISP)) | |
6523 goto regeneration_done; | |
6524 } | |
6525 | |
6526 /* We still haven't gotten the window regenerated with point | |
6527 visible. Next we try scrolling a little and see if point comes | |
6528 back onto the screen. */ | |
6529 if (scroll_step > 0) | |
6530 { | |
6531 int scrolled = scroll_conservatively; | |
6532 for (; scrolled >= 0; scrolled -= scroll_step) | |
6533 { | |
6534 startp = vmotion (w, startp, | |
6535 (pointm < startp) ? -scroll_step : scroll_step, 0); | |
6536 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6537 | |
6538 if (point_visible (w, pointm, DESIRED_DISP)) | |
6539 goto regeneration_done; | |
6540 } | |
6541 } | |
6542 | |
6543 /* We still haven't managed to get the screen drawn with point on | |
6544 the screen, so just center it and be done with it. */ | |
6545 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6546 | |
6547 | |
6548 regeneration_done: | |
6549 | |
6550 /* If the window's frame is changed then reset the current display | |
6551 lines in order to force a full repaint. */ | |
6552 if (f->frame_changed) | |
6553 { | |
6554 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
6555 | |
6556 Dynarr_reset (cla); | |
6557 } | |
6558 | |
6559 /* Must do this before calling redisplay_output_window because it | |
6560 sets some markers on the window. */ | |
6561 if (echo_active) | |
6562 { | |
6563 w->buffer = old_buffer; | |
6564 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer); | |
6565 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer); | |
6566 } | |
6567 | |
6568 /* These also have to be set before calling redisplay_output_window | |
6569 since it sets the CURRENT_DISP values based on them. */ | |
6570 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
6571 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
6572 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
6573 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
6574 | |
6575 if (!skip_output) | |
6576 { | |
665 | 6577 Charbpos start = marker_position (w->start[DESIRED_DISP]); |
6578 Charbpos end = (w->window_end_pos[DESIRED_DISP] == -1 | |
428 | 6579 ? BUF_ZV (b) |
6580 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1); | |
6581 /* Don't pollute the cache if not sure if we are correct */ | |
6582 if (w->start_at_line_beg) | |
6583 update_line_start_cache (w, start, end, pointm, 1); | |
6584 redisplay_output_window (w); | |
6585 /* | |
6586 * If we just displayed the echo area, the line start cache is | |
6587 * no longer valid, because the minibuffer window is associated | |
6588 * with the window now. | |
6589 */ | |
6590 if (echo_active) | |
6591 w->line_cache_last_updated = make_int (-1); | |
6592 } | |
6593 | |
6594 /* #### This should be dependent on face changes and will need to be | |
6595 somewhere else once tty updates occur on a per-frame basis. */ | |
6596 mark_face_cachels_as_clean (w); | |
6597 | |
438 | 6598 /* The glyph cachels only get dirty if someone changed something. |
6599 Since redisplay has now effectively ended we can reset the dirty | |
6600 flag since everything must be up-to-date. */ | |
428 | 6601 if (glyphs_changed) |
6602 mark_glyph_cachels_as_clean (w); | |
6603 | |
6604 w->windows_changed = 0; | |
6605 } | |
6606 | |
6607 /* Call buffer_reset_changes for all buffers present in any window | |
6608 currently visible in all frames on all devices. #### There has to | |
6609 be a better way to do this. */ | |
6610 | |
6611 static int | |
2286 | 6612 reset_buffer_changes_mapfun (struct window *w, void *UNUSED (closure)) |
428 | 6613 { |
6614 buffer_reset_changes (XBUFFER (w->buffer)); | |
6615 return 0; | |
6616 } | |
6617 | |
6618 static void | |
6619 reset_buffer_changes (void) | |
6620 { | |
6621 Lisp_Object frmcons, devcons, concons; | |
6622 | |
6623 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
6624 { | |
6625 struct frame *f = XFRAME (XCAR (frmcons)); | |
6626 | |
6627 if (FRAME_REPAINT_P (f)) | |
6628 map_windows (f, reset_buffer_changes_mapfun, 0); | |
6629 } | |
6630 } | |
6631 | |
6632 /* Ensure that all windows underneath the given window in the window | |
6633 hierarchy are correctly displayed. */ | |
6634 | |
6635 static void | |
6636 redisplay_windows (Lisp_Object window, int skip_selected) | |
6637 { | |
6638 for (; !NILP (window) ; window = XWINDOW (window)->next) | |
6639 { | |
6640 redisplay_window (window, skip_selected); | |
6641 } | |
6642 } | |
6643 | |
1318 | 6644 /* Register an action to be called at the end of redisplay. |
6645 in_display is 0 when this is called. | |
6646 This is used when it is discovered that an action needs to be taken, | |
6647 but it's during redisplay, so it's not safe. (Typically, it's an action | |
6648 that needs to enter redisplay, which can't happen reentrantly.) | |
6649 | |
6650 NEVER signal an error in these functions. | |
6651 */ | |
6652 | |
6653 void | |
6654 register_post_redisplay_action (void (*fun) (Lisp_Object), Lisp_Object arg) | |
6655 { | |
6656 Vpost_redisplay_actions = nconc2 (Vpost_redisplay_actions, | |
6657 list1 (Fcons (make_opaque_ptr | |
6658 ((void *) fun), arg))); | |
6659 } | |
6660 | |
1320 | 6661 static int running_post_redisplay_actions; |
6662 | |
1318 | 6663 static void |
6664 run_post_redisplay_actions (void) | |
6665 { | |
1320 | 6666 int depth; |
6667 | |
6668 if (running_post_redisplay_actions) | |
6669 return; | |
6670 | |
6671 depth = internal_bind_int (&running_post_redisplay_actions, 1); | |
6672 /* If the function pushes further actions, they will be tacked onto | |
6673 the end of the list, and we'll run them when we're done with the | |
6674 current ones. */ | |
1318 | 6675 while (!NILP (Vpost_redisplay_actions)) |
6676 { | |
6677 Lisp_Object car = XCAR (Vpost_redisplay_actions); | |
6678 void (*fun) (Lisp_Object) = | |
6679 (void (*)(Lisp_Object)) get_opaque_ptr (XCAR (car)); | |
6680 (*fun) (XCDR (car)); | |
6681 free_opaque_ptr (XCAR (car)); | |
6682 free_cons (car); | |
6683 Vpost_redisplay_actions = XCDR (Vpost_redisplay_actions); | |
6684 } | |
1320 | 6685 unbind_to (depth); |
1318 | 6686 } |
6687 | |
6688 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
6689 | |
6690 static Lisp_Object | |
2286 | 6691 commit_ritual_suicide (Lisp_Object UNUSED (ceci_nest_pas_une_pipe)) |
1318 | 6692 { |
6693 assert (!in_display); | |
6694 return Qnil; | |
6695 } | |
6696 | |
6697 #endif | |
6698 | |
6699 /* Within the guts of redisplay, we are defenseless and cannot allow any of | |
6700 the following to happen: | |
6701 | |
6702 1) garbage collection | |
6703 2) QUIT | |
6704 3) any non-local exits | |
6705 4) frame size changes | |
6706 5) deletion of any buffers, windows, frames, etc. | |
6707 6) modification of buffer text | |
6708 7) reentrant entry of redisplay (see the stack trace above | |
6709 generate_displayable_area()) | |
6710 | |
6711 The general reason is that the redisplay code is written to assume that | |
6712 it is the only code running, and thus (a) cannot tolerate structures | |
6713 changed out from under it (hence 1, 4, 5, 6, 7) and (b) at various points | |
6714 within redisplay the redisplay structures may be in an inconsistent | |
6715 state and there are no unwind-protects to clean the structures up in | |
6716 case of non-local exit (hence 2, 3). Fixing redisplay to address these | |
6717 issues is hard and perhaps not worth it (and might slow things down a | |
6718 fair amount). We address 1, 4, 5 and 6 ourselves inside of | |
6719 enter_redisplay_critical_section() by simply inhibiting them, but we | |
6720 cannot handle 2 and 3, which must be handled at the actual point where | |
6721 they may occur (especially, internal_equal() or any place that may call | |
6722 Lisp), by wrapping the code in call_trapping_problems() or | |
6723 call_with_suspended_errors(). [[ NOTE: We could address QUIT by inhibiting | |
6724 it but this would be anti-social because it would prevent the user from | |
6725 interrupting any Lisp code called within the critical section. With the | |
6726 call_*() wrapping, C-g will interrupt the Lisp code and throw back to | |
6727 the innermost wrapping. ]] In fact we do turn off QUIT handling, since | |
6728 it's just too dangerous otherwise. See below. | |
6729 | |
6730 Code calling enter_redisplay_critical_section() must check for reentrancy | |
6731 (#7) and take appropriate corrective action. | |
6732 | |
6733 To help debug potential problems, we arrange (when | |
6734 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every time | |
6735 we execute QUIT or call Lisp code unless proper wrapping is in place, as | |
6736 well as further checks when we actually Fsignal(), Fthrow(), | |
6737 garbage_collect_1(). | |
6738 | |
6739 #### If a frame-size change does occur we should probably actually be | |
6740 preempting redisplay. */ | |
6741 | |
6742 /* Count of number of recursive times we call | |
6743 enter_redisplay_critical_section() or | |
6744 enter_redisplay_critical_section_maybe(). | |
6745 enter_redisplay_critical_section() cannot occur reentrantly but we have | |
6746 to know in the *maybe() version whether to exit the section when we're | |
6747 done. */ | |
6748 static int in_display_nesting; | |
6749 | |
6750 static Lisp_Object | |
2286 | 6751 end_hold_frame_size_changes (Lisp_Object UNUSED (obj)) |
1318 | 6752 { |
6753 if (!hold_frame_size_changes) | |
6754 { | |
6755 /* we used to have a function to do this for only one frame, and | |
6756 it was typical to call it at the end of a critical section | |
6757 (which occurs once per frame); but what then happens if multiple | |
6758 frames have frame changes held up? | |
4187 | 6759 |
1318 | 6760 This means we are O(N^2) over frames. I seriously doubt it matters. |
6761 --ben */ | |
6762 Lisp_Object frmcons, devcons, concons; | |
4187 | 6763 |
1318 | 6764 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
6765 { | |
6766 struct frame *f = XFRAME (XCAR (frmcons)); | |
6767 if (f->size_change_pending) | |
5043 | 6768 change_frame_size (f, f->new_width, f->new_height, 0); |
1318 | 6769 } |
6770 } | |
6771 return Qnil; | |
6772 } | |
6773 | |
6774 /* Call this to temporarily prevent frame-size changes from being processed. | |
6775 To undo, use unbind_to(), passing it the value returned by this function. | |
6776 */ | |
6777 | |
6778 int | |
6779 begin_hold_frame_size_changes (void) | |
6780 { | |
6781 int depth = specpdl_depth (); | |
6782 record_unwind_protect (end_hold_frame_size_changes, Qnil); | |
6783 internal_bind_int (&hold_frame_size_changes, 1 + hold_frame_size_changes); | |
6784 return depth; | |
6785 } | |
6786 | |
6787 int | |
6788 enter_redisplay_critical_section (void) | |
6789 { | |
6790 int depth = specpdl_depth (); | |
6791 | |
6792 /* Reentrant entry is deadly. The calling function must check for this. */ | |
6793 assert (!in_display); | |
6794 begin_hold_frame_size_changes (); | |
6795 /* Make sure in_display gets reset, but don't set it yet so that | |
6796 commit_ritual_suicide() can be used. */ | |
6797 internal_bind_int (&in_display, 0); | |
6798 internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6799 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
6800 /* Force every call to QUIT to check for in_displayness. This will | |
6801 verify proper wrapping, as in the previous comment, aborting if not. */ | |
6802 something_happened++; | |
6803 /* Verify that no nonlocal exits blow past us. */ | |
6804 record_unwind_protect (commit_ritual_suicide, Qnil); | |
6805 #endif | |
6806 in_display++; | |
6807 | |
6808 set_trapping_problems_flags (INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY); | |
6809 /* Even checking for QUIT can cause arbitrary Lisp code to be executed, | |
6810 e.g. through a menu handler. We really don't want that happening | |
6811 inside of redisplay. Code that we `eval' is at least written with the | |
6812 expectation that it's inside of redisplay, and shouldn't try anything | |
6813 weird; but that's not the case for menu code (e.g. custom loads huge | |
6814 amounts of LISP FILES from a menu handler! FMH!). Safest just to turn | |
6815 this off. We could turn it on using UNINHIBIT_QUIT or | |
6816 begin_do_check_for_quit() in certain places if we want, if we know | |
6817 it's not in an especially tricky place. */ | |
6818 begin_dont_check_for_quit (); | |
6819 return depth; | |
6820 } | |
6821 | |
6822 void | |
6823 exit_redisplay_critical_section (int depth) | |
6824 { | |
6825 in_display--; | |
6826 assert (!in_display); | |
6827 unbind_to (depth); | |
6828 | |
6829 run_post_redisplay_actions (); | |
6830 } | |
6831 | |
6832 /* Enter the redisplay critical section if we're not already in it. This | |
6833 is for code that needs frame changes held up and other protections from | |
6834 being inside, but doesn't modify the redisplay structures, and doesn't | |
6835 look at them in a way that they will be confused by inconsistencies. */ | |
6836 | |
6837 int | |
6838 enter_redisplay_critical_section_maybe (void) | |
6839 { | |
6840 if (!in_display) | |
6841 return enter_redisplay_critical_section (); | |
6842 else | |
6843 return internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6844 } | |
6845 | |
6846 void | |
6847 exit_redisplay_critical_section_maybe (int depth) | |
6848 { | |
6849 if (in_display_nesting == 1) | |
6850 exit_redisplay_critical_section (depth); | |
6851 else | |
6852 unbind_to (depth); | |
6853 } | |
6854 | |
1279 | 6855 /* Ensure that all windows on the given frame are correctly displayed. |
6856 Return non-zero if pre-empted. */ | |
428 | 6857 |
442 | 6858 int |
428 | 6859 redisplay_frame (struct frame *f, int preemption_check) |
6860 { | |
6861 struct device *d = XDEVICE (f->device); | |
853 | 6862 int depth; |
428 | 6863 |
1279 | 6864 assert (f->init_finished); |
6865 | |
1318 | 6866 /* NOTE: Without sufficient checks for stream frames, we got weird |
6867 crashes in pdump. These came and went very easily -- adding the | |
6868 critical-section code for redisplay was enough to trigger them. | |
6869 Perhaps I should have debugged them but there didn't seem to be any | |
6870 point. --ben */ | |
1279 | 6871 if (FRAME_STREAM_P (f)) /* nothing to do */ |
6872 return 0; | |
6873 | |
1318 | 6874 /* Reentrancy into redisplay can be deadly. See stack trace above |
6875 generate_displayable_area(). */ | |
6876 if (in_display) | |
6877 return 1; | |
6878 | |
545 | 6879 if (preemption_check |
6880 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) | |
428 | 6881 { |
6882 /* The preemption check itself takes a lot of time, | |
6883 so normally don't do it here. We do it if called | |
6884 from Lisp, though (`redisplay-frame'). */ | |
6885 int preempted; | |
6886 | |
6887 REDISPLAY_PREEMPTION_CHECK; | |
6888 if (preempted) | |
6889 return 1; | |
6890 } | |
6891 | |
442 | 6892 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) |
6893 { | |
6894 Lisp_Object frame; | |
6895 | |
6896 f->old_buffer_alist = Freplace_list (f->old_buffer_alist, | |
6897 f->buffer_alist); | |
793 | 6898 frame = wrap_frame (f); |
442 | 6899 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); |
6900 } | |
6901 | |
428 | 6902 /* Before we put a hold on frame size changes, attempt to process |
6903 any which are already pending. */ | |
6904 if (f->size_change_pending) | |
5043 | 6905 change_frame_size (f, f->new_width, f->new_height, 0); |
428 | 6906 |
6907 /* If frame size might need to be changed, due to changed size | |
6908 of toolbars, scrollbars etc, change it now */ | |
6909 if (f->size_slipped) | |
6910 { | |
6911 adjust_frame_size (f); | |
6912 assert (!f->size_slipped); | |
6913 } | |
6914 | |
1318 | 6915 /* The menubar, toolbar, and icon updates should be done before |
853 | 6916 enter_redisplay_critical_section is called and we are officially |
3025 | 6917 `in_display'. They is because they tend to eval Lisp code, which |
1318 | 6918 needs to be carefully wrapped within the critical section (and hence |
6919 is difficult to debug). */ | |
428 | 6920 |
6921 #ifdef HAVE_MENUBARS | |
6922 /* Update the menubar. It is done first since it could change | |
6923 the menubar's visibility. This way we avoid having flashing | |
6924 caused by an Expose event generated by the visibility change | |
6925 being handled. */ | |
6926 update_frame_menubars (f); | |
6927 #endif /* HAVE_MENUBARS */ | |
6928 #ifdef HAVE_TOOLBARS | |
905 | 6929 /* Update the toolbars geometry. We don't update the toolbars |
6930 themselves at this point since the space they are trying to | |
6931 occupy may currently by occupied by gutter elements. Instead we | |
6932 update the geometry, then update the gutter geometry, then update | |
6933 the gutters - which will cause mapped windows to be repositioned | |
6934 - and finally update the toolbars. */ | |
6935 update_frame_toolbars_geometry (f); | |
428 | 6936 #endif /* HAVE_TOOLBARS */ |
442 | 6937 /* Gutter update proper has to be done inside display when no frame |
6938 size changes can occur, thus we separately update the gutter | |
6939 geometry here if it needs it. */ | |
6940 update_frame_gutter_geometry (f); | |
428 | 6941 |
6942 /* If we clear the frame we have to force its contents to be redrawn. */ | |
6943 if (f->clear) | |
6944 f->frame_changed = 1; | |
6945 | |
442 | 6946 /* Invalidate the subwindow caches. We use subwindows_changed here |
6947 to cause subwindows to get instantiated. This is because | |
428 | 6948 subwindows_state_changed is less strict - dealing with things |
6949 like the clicked state of button. We have to do this before | |
6950 redisplaying the gutters as subwindows get unmapped in the | |
6951 process.*/ | |
442 | 6952 if (f->frame_changed) |
6953 reset_frame_subwindow_instance_cache (f); | |
6954 | |
6955 if (f->frame_changed || f->subwindows_changed) | |
6956 { | |
428 | 6957 /* we have to do this so the gutter gets regenerated. */ |
6958 reset_gutter_display_lines (f); | |
6959 } | |
6960 | |
853 | 6961 depth = enter_redisplay_critical_section (); |
428 | 6962 |
6963 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ | |
1318 | 6964 |
6965 /* See comments in enter_redisplay_critical_section() */ | |
428 | 6966 |
442 | 6967 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
6968 | |
6969 /* We can now update the gutters, safe in the knowledge that our | |
6970 efforts won't get undone. */ | |
6971 | |
6972 /* This can call lisp, but redisplay is protected by binding | |
6973 inhibit_quit. More importantly the code involving display lines | |
6974 *assumes* that GC will not happen and so does not GCPRO | |
6975 anything. Since we use this code the whole time with the gutters | |
1318 | 6976 we cannot allow GC to happen when manipulating the gutters. |
6977 | |
6978 This must be inside of the critical section for various reasons. | |
6979 For example, it messes with display structures, which be left in | |
6980 an inconsistent state. */ | |
442 | 6981 update_frame_gutters (f); |
6982 | |
428 | 6983 /* Erase the frame before outputting its contents. */ |
6984 if (f->clear) | |
6985 { | |
442 | 6986 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 6987 } |
6988 | |
6989 /* Do the selected window first. */ | |
6990 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); | |
6991 | |
6992 /* Then do the rest. */ | |
6993 redisplay_windows (f->root_window, 1); | |
6994 | |
442 | 6995 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 6996 |
6997 update_frame_title (f); | |
6998 | |
905 | 6999 #ifdef HAVE_TOOLBARS |
7000 /* Finally update the toolbars. It seems its possible to get in a | |
7001 cycle between updating the gutter and the toolbars. Basically we | |
7002 want to end up with both being up-to-date and this doesn't seem | |
7003 possible in a single pass. */ | |
7004 update_frame_toolbars (f); | |
7005 #endif /* HAVE_TOOLBARS */ | |
7006 | |
428 | 7007 CLASS_RESET_CHANGED_FLAGS (f); |
7008 f->window_face_cache_reset = 0; | |
7009 f->echo_area_garbaged = 0; | |
7010 f->clear = 0; | |
7011 | |
7012 if (!f->size_change_pending) | |
7013 f->size_changed = 0; | |
7014 | |
7015 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */ | |
7016 | |
853 | 7017 /* Allow frame size changes to occur again. */ |
7018 exit_redisplay_critical_section (depth); | |
428 | 7019 |
7020 return 0; | |
7021 } | |
7022 | |
440 | 7023 /* Ensure that all frames on the given device are correctly displayed. |
7024 If AUTOMATIC is non-zero, and the device implementation indicates | |
7025 no automatic redisplay, as printers do, then the device is not | |
7026 redisplayed. AUTOMATIC is set to zero when called from lisp | |
7027 functions (redraw-device) and (redisplay-device), and to non-zero | |
7028 when called from "lazy" redisplay(); | |
7029 */ | |
428 | 7030 |
7031 static int | |
440 | 7032 redisplay_device (struct device *d, int automatic) |
428 | 7033 { |
7034 Lisp_Object frame, frmcons; | |
7035 int size_change_failed = 0; | |
7036 struct frame *f; | |
7037 | |
545 | 7038 if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) |
440 | 7039 return 0; |
7040 | |
428 | 7041 if (DEVICE_STREAM_P (d)) /* nothing to do */ |
7042 return 0; | |
7043 | |
7044 /* It is possible that redisplay has been called before the | |
545 | 7045 device is fully initialized, or that the console implementation |
7046 allows frameless devices. If so then continue with the next | |
7047 device. */ | |
428 | 7048 if (NILP (DEVICE_SELECTED_FRAME (d))) |
7049 return 0; | |
7050 | |
545 | 7051 if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) |
7052 { | |
7053 int preempted; | |
7054 REDISPLAY_PREEMPTION_CHECK; | |
7055 if (preempted) | |
7056 return 1; | |
7057 } | |
428 | 7058 |
7059 /* Always do the selected frame first. */ | |
7060 frame = DEVICE_SELECTED_FRAME (d); | |
7061 | |
7062 f = XFRAME (frame); | |
7063 | |
7064 if (f->icon_changed || f->windows_changed) | |
7065 update_frame_icon (f); | |
7066 | |
7067 if (FRAME_REPAINT_P (f)) | |
7068 { | |
7069 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) | |
7070 { | |
588 | 7071 int preempted = redisplay_frame (f, 1); |
545 | 7072 if (preempted) |
7073 return 1; | |
7074 } | |
428 | 7075 |
7076 /* If the frame redisplay did not get preempted, then this flag | |
4187 | 7077 should have gotten set to 0. It might be possible for that |
7078 not to happen if a size change event were to occur at an odd | |
7079 time. To make sure we don't miss anything we simply don't | |
7080 reset the top level flags until the condition ends up being | |
7081 in the right state. */ | |
428 | 7082 if (f->size_changed) |
7083 size_change_failed = 1; | |
7084 } | |
7085 | |
7086 DEVICE_FRAME_LOOP (frmcons, d) | |
7087 { | |
7088 f = XFRAME (XCAR (frmcons)); | |
7089 | |
7090 if (f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
7091 continue; | |
7092 | |
7093 if (f->icon_changed || f->windows_changed) | |
7094 update_frame_icon (f); | |
7095 | |
7096 if (FRAME_REPAINT_P (f)) | |
7097 { | |
430 | 7098 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
428 | 7099 { |
588 | 7100 int preempted = redisplay_frame (f, 1); |
545 | 7101 if (preempted) |
7102 return 1; | |
428 | 7103 } |
7104 | |
7105 if (f->size_change_pending) | |
7106 size_change_failed = 1; | |
7107 } | |
7108 } | |
7109 | |
7110 /* If we get here then we redisplayed all of our frames without | |
7111 getting preempted so mark ourselves as clean. */ | |
7112 CLASS_RESET_CHANGED_FLAGS (d); | |
7113 | |
7114 if (!size_change_failed) | |
7115 d->size_changed = 0; | |
7116 | |
7117 return 0; | |
7118 } | |
7119 | |
7120 /* Ensure that all windows on all frames on all devices are displaying | |
7121 the current contents of their respective buffers. */ | |
7122 | |
7123 static void | |
7124 redisplay_without_hooks (void) | |
7125 { | |
7126 Lisp_Object devcons, concons; | |
7127 int size_change_failed = 0; | |
1292 | 7128 PROFILE_DECLARE (); |
7129 | |
7130 PROFILE_RECORD_ENTERING_SECTION (QSin_redisplay); | |
428 | 7131 |
7132 if (asynch_device_change_pending) | |
7133 handle_asynch_device_change (); | |
7134 | |
7135 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && | |
430 | 7136 !disable_preemption && preemption_count < max_preempts) |
428 | 7137 goto done; |
7138 | |
7139 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
7140 { | |
7141 struct device *d = XDEVICE (XCAR (devcons)); | |
7142 int preempted; | |
7143 | |
430 | 7144 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) |
428 | 7145 { |
440 | 7146 preempted = redisplay_device (d, 1); |
428 | 7147 |
7148 if (preempted) | |
7149 { | |
7150 preemption_count++; | |
7151 RESET_CHANGED_SET_FLAGS; | |
7152 goto done; | |
7153 } | |
7154 | |
7155 /* See comment in redisplay_device. */ | |
7156 if (d->size_changed) | |
7157 size_change_failed = 1; | |
7158 } | |
7159 } | |
7160 preemption_count = 0; | |
7161 | |
7162 /* Mark redisplay as accurate */ | |
7163 GLOBAL_RESET_CHANGED_FLAGS; | |
7164 RESET_CHANGED_SET_FLAGS; | |
7165 | |
7166 if (faces_changed) | |
7167 { | |
7168 mark_all_faces_as_clean (); | |
7169 faces_changed = 0; | |
7170 } | |
7171 | |
7172 if (!size_change_failed) | |
7173 size_changed = 0; | |
7174 | |
7175 reset_buffer_changes (); | |
7176 | |
7177 done: | |
800 | 7178 #ifdef ERROR_CHECK_DISPLAY |
7179 sledgehammer_check_redisplay_structs (); | |
7180 #endif /* ERROR_CHECK_DISPLAY */ | |
1292 | 7181 |
7182 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay); | |
428 | 7183 } |
7184 | |
1318 | 7185 /* Note: All places in the C code that call redisplay() are prepared to |
7186 handle GCing, which can happen from run_pre_idle_hook(). However, we | |
7187 can't currently handle GC inside the guts of redisplay; see | |
7188 enter_redisplay_critical_section(). | |
853 | 7189 |
7190 (#### What about other external entry points to the redisplay code? | |
7191 Someone should go through and make sure that all callers can handle | |
7192 GC there, too.) | |
7193 */ | |
7194 | |
428 | 7195 void |
7196 redisplay (void) | |
7197 { | |
853 | 7198 run_pre_idle_hook (); |
7199 redisplay_no_pre_idle_hook (); | |
7200 } | |
7201 | |
7202 void | |
7203 redisplay_no_pre_idle_hook (void) | |
7204 { | |
428 | 7205 if (last_display_warning_tick != display_warning_tick && |
7206 !inhibit_warning_display) | |
7207 { | |
7208 /* If an error occurs during this function, oh well. | |
4187 | 7209 If we report another warning, we could get stuck in an |
428 | 7210 infinite loop reporting warnings. */ |
853 | 7211 call0_trapping_problems |
7212 (0, Qdisplay_warning_buffer, | |
7213 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 7214 last_display_warning_tick = display_warning_tick; |
7215 } | |
7216 | |
7217 redisplay_without_hooks (); | |
7218 } | |
7219 | |
853 | 7220 Lisp_Object |
7221 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker) | |
7222 { | |
7223 return | |
7224 eval_in_buffer_trapping_problems | |
7225 ("Error calling function within redisplay", current_buffer, | |
1318 | 7226 dont_trust_this_damn_sucker, 0); |
853 | 7227 } |
428 | 7228 |
7229 /* Efficiently determine the window line number, and return a pointer | |
7230 to its printed representation. Do this regardless of whether | |
7231 line-number-mode is on. The first line in the buffer is counted as | |
7232 1. If narrowing is in effect, the lines are counted from the | |
7233 beginning of the visible portion of the buffer. */ | |
4970 | 7234 static Ascbyte * |
428 | 7235 window_line_number (struct window *w, int type) |
7236 { | |
7237 struct device *d = XDEVICE (XFRAME (w->frame)->device); | |
7238 struct buffer *b = XBUFFER (w->buffer); | |
7239 /* Be careful in the order of these tests. The first clause will | |
7240 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be). | |
7241 This can occur when the frame title is computed really early */ | |
665 | 7242 Charbpos pos = |
428 | 7243 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) && |
7244 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) && | |
7245 EQ(DEVICE_CONSOLE(d), Vselected_console) && | |
7246 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d ) | |
7247 ? BUF_PT (b) | |
7248 : marker_position (w->pointm[type])); | |
7249 EMACS_INT line; | |
7250 | |
7251 line = buffer_line_number (b, pos, 1); | |
7252 | |
603 | 7253 { |
4970 | 7254 static Ascbyte window_line_number_buf[DECIMAL_PRINT_SIZE (long)]; |
603 | 7255 |
7256 long_to_string (window_line_number_buf, line + 1); | |
7257 | |
7258 return window_line_number_buf; | |
7259 } | |
428 | 7260 } |
7261 | |
7262 | |
7263 /* Given a character representing an object in a modeline | |
7264 specification, return a string (stored into the global array | |
867 | 7265 `mode_spec_ibyte_string') with the information that object |
428 | 7266 represents. |
7267 | |
7268 This function is largely unchanged from previous versions of the | |
7269 redisplay engine. | |
7270 | |
7271 Warning! This code is also used for frame titles and can be called | |
7272 very early in the device/frame update process! JV | |
7273 */ | |
7274 | |
7275 static void | |
867 | 7276 decode_mode_spec (struct window *w, Ichar spec, int type) |
428 | 7277 { |
7278 Lisp_Object obj = Qnil; | |
4970 | 7279 const Ascbyte *str = NULL; |
428 | 7280 struct buffer *b = XBUFFER (w->buffer); |
7281 | |
867 | 7282 Dynarr_reset (mode_spec_ibyte_string); |
428 | 7283 |
7284 switch (spec) | |
7285 { | |
7286 /* print buffer name */ | |
7287 case 'b': | |
7288 obj = b->name; | |
7289 break; | |
7290 | |
7291 /* print visited file name */ | |
7292 case 'f': | |
7293 obj = b->filename; | |
7294 break; | |
7295 | |
7296 /* print the current column */ | |
7297 case 'c': | |
7298 { | |
4187 | 7299 Charbpos pt = (w == XWINDOW (Fselected_window (Qnil))) |
7300 ? BUF_PT (b) | |
7301 : marker_position (w->pointm[type]); | |
428 | 7302 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one; |
4970 | 7303 Ascbyte buf[DECIMAL_PRINT_SIZE (long)]; |
428 | 7304 |
7305 long_to_string (buf, col); | |
7306 | |
867 | 7307 Dynarr_add_many (mode_spec_ibyte_string, |
7308 (const Ibyte *) buf, strlen (buf)); | |
428 | 7309 |
7310 goto decode_mode_spec_done; | |
7311 } | |
7312 /* print the file coding system */ | |
7313 case 'C': | |
7314 { | |
4187 | 7315 Lisp_Object codesys = b->buffer_file_coding_system; |
7316 /* Be very careful here not to get an error. */ | |
428 | 7317 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys)) |
4187 | 7318 { |
7319 codesys = find_coding_system_for_text_file (codesys, 0); | |
428 | 7320 if (CODING_SYSTEMP (codesys)) |
4187 | 7321 obj = XCODING_SYSTEM_MNEMONIC (codesys); |
7322 } | |
428 | 7323 } |
7324 break; | |
7325 | |
7326 /* print the current line number */ | |
7327 case 'l': | |
7328 str = window_line_number (w, type); | |
7329 break; | |
7330 | |
7331 /* print value of mode-name (obsolete) */ | |
7332 case 'm': | |
7333 obj = b->mode_name; | |
7334 break; | |
7335 | |
7336 /* print hyphen and frame number, if != 1 */ | |
7337 case 'N': | |
7338 #ifdef HAVE_TTY | |
7339 { | |
7340 struct frame *f = XFRAME (w->frame); | |
7341 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999) | |
7342 { | |
7343 /* Naughty, naughty */ | |
4970 | 7344 Ascbyte *writable_str = alloca_array (Ascbyte, 10); |
428 | 7345 sprintf (writable_str, "-%d", f->order_count); |
7346 str = writable_str; | |
7347 } | |
7348 } | |
7349 #endif /* HAVE_TTY */ | |
7350 break; | |
7351 | |
7352 /* print Narrow if appropriate */ | |
7353 case 'n': | |
7354 if (BUF_BEGV (b) > BUF_BEG (b) | |
7355 || BUF_ZV (b) < BUF_Z (b)) | |
7356 str = " Narrow"; | |
7357 break; | |
7358 | |
7359 /* print %, * or hyphen, if buffer is read-only, modified or neither */ | |
7360 case '*': | |
7361 str = (!NILP (b->read_only) | |
7362 ? "%" | |
7363 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7364 ? "*" | |
7365 : "-")); | |
7366 break; | |
7367 | |
7368 /* print * or hyphen -- XEmacs change to allow a buffer to be | |
4187 | 7369 read-only but still indicate whether it is modified. */ |
428 | 7370 case '+': |
7371 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7372 ? "*" | |
7373 : (!NILP (b->read_only) | |
7374 ? "%" | |
7375 : "-")); | |
7376 break; | |
7377 | |
7378 /* #### defined in 19.29 decode_mode_spec, but not in | |
4187 | 7379 modeline-format doc string. */ |
428 | 7380 /* This differs from %* in that it ignores read-only-ness. */ |
7381 case '&': | |
7382 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7383 ? "*" | |
7384 : "-"); | |
7385 break; | |
7386 | |
7387 /* print process status */ | |
7388 case 's': | |
7389 obj = Fget_buffer_process (w->buffer); | |
7390 if (NILP (obj)) | |
7391 str = GETTEXT ("no process"); | |
7392 else | |
7393 obj = Fsymbol_name (Fprocess_status (obj)); | |
7394 break; | |
7395 | |
7396 /* Print name of selected frame. */ | |
7397 case 'S': | |
7398 obj = XFRAME (w->frame)->name; | |
7399 break; | |
7400 | |
7401 /* indicate TEXT or BINARY */ | |
7402 case 't': | |
7403 /* #### NT does not use this any more. Now what? */ | |
7404 str = "T"; | |
7405 break; | |
7406 | |
7407 /* print percent of buffer above top of window, or Top, Bot or All */ | |
7408 case 'p': | |
7409 { | |
665 | 7410 Charbpos pos = marker_position (w->start[type]); |
428 | 7411 |
7412 /* This had better be while the desired lines are being done. */ | |
7413 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) | |
7414 { | |
7415 if (pos <= BUF_BEGV (b)) | |
7416 str = "All"; | |
7417 else | |
7418 str = "Bottom"; | |
7419 } | |
7420 else if (pos <= BUF_BEGV (b)) | |
7421 str = "Top"; | |
7422 else | |
7423 { | |
7424 /* This hard limit is ok since the string it will hold has a | |
4187 | 7425 fixed maximum length of 3. But just to be safe... */ |
4970 | 7426 Ascbyte buf[10]; |
428 | 7427 Charcount chars = pos - BUF_BEGV (b); |
7428 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7429 | |
7430 /* Avoid overflow on big buffers */ | |
7431 int percent = total > LONG_MAX/200 ? | |
7432 (chars + total/200) / (total / 100) : | |
7433 (chars * 100 + total/2) / total; | |
7434 | |
7435 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7436 2-digit number that is close. */ |
428 | 7437 if (percent == 100) |
7438 percent = 99; | |
7439 | |
7440 sprintf (buf, "%d%%", percent); | |
867 | 7441 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7442 strlen (buf)); |
7443 | |
7444 goto decode_mode_spec_done; | |
7445 } | |
7446 break; | |
7447 } | |
7448 | |
7449 /* print percent of buffer above bottom of window, perhaps plus | |
7450 Top, or print Bottom or All */ | |
7451 case 'P': | |
7452 { | |
665 | 7453 Charbpos toppos = marker_position (w->start[type]); |
7454 Charbpos botpos = BUF_Z (b) - w->window_end_pos[type]; | |
428 | 7455 |
7456 /* botpos is only accurate as of the last redisplay, so we can | |
4187 | 7457 only treat it as a hint. In particular, after erase-buffer, |
7458 botpos may be negative. */ | |
428 | 7459 if (botpos < toppos) |
7460 botpos = toppos; | |
7461 | |
7462 if (botpos >= BUF_ZV (b)) | |
7463 { | |
7464 if (toppos <= BUF_BEGV (b)) | |
7465 str = "All"; | |
7466 else | |
7467 str = "Bottom"; | |
7468 } | |
7469 else | |
7470 { | |
7471 /* This hard limit is ok since the string it will hold has a | |
4187 | 7472 fixed maximum length of around 6. But just to be safe... */ |
4970 | 7473 Ascbyte buf[10]; |
428 | 7474 Charcount chars = botpos - BUF_BEGV (b); |
7475 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7476 | |
7477 /* Avoid overflow on big buffers */ | |
7478 int percent = total > LONG_MAX/200 ? | |
7479 (chars + total/200) / (total / 100) : | |
7480 (chars * 100 + total/2) / max (total, 1); | |
7481 | |
7482 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7483 2-digit number that is close. */ |
428 | 7484 if (percent == 100) |
7485 percent = 99; | |
7486 | |
7487 if (toppos <= BUF_BEGV (b)) | |
7488 sprintf (buf, "Top%d%%", percent); | |
7489 else | |
7490 sprintf (buf, "%d%%", percent); | |
7491 | |
867 | 7492 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7493 strlen (buf)); |
7494 | |
7495 goto decode_mode_spec_done; | |
7496 } | |
7497 break; | |
7498 } | |
7499 | |
7500 /* print % */ | |
7501 case '%': | |
7502 str = "%"; | |
7503 break; | |
7504 | |
7505 /* print one [ for each recursive editing level. */ | |
7506 case '[': | |
7507 { | |
7508 int i; | |
7509 | |
7510 if (command_loop_level > 5) | |
7511 { | |
7512 str = "[[[... "; | |
7513 break; | |
7514 } | |
7515 | |
7516 for (i = 0; i < command_loop_level; i++) | |
867 | 7517 Dynarr_add (mode_spec_ibyte_string, '['); |
428 | 7518 |
7519 goto decode_mode_spec_done; | |
7520 } | |
7521 | |
7522 /* print one ] for each recursive editing level. */ | |
7523 case ']': | |
7524 { | |
7525 int i; | |
7526 | |
7527 if (command_loop_level > 5) | |
7528 { | |
7529 str = "...]]]"; | |
7530 break; | |
7531 } | |
7532 | |
7533 for (i = 0; i < command_loop_level; i++) | |
867 | 7534 Dynarr_add (mode_spec_ibyte_string, ']'); |
428 | 7535 |
7536 goto decode_mode_spec_done; | |
7537 } | |
7538 | |
7539 /* print infinitely many dashes -- handle at top level now */ | |
7540 case '-': | |
7541 break; | |
7542 | |
7543 } | |
7544 | |
7545 if (STRINGP (obj)) | |
867 | 7546 Dynarr_add_many (mode_spec_ibyte_string, |
428 | 7547 XSTRING_DATA (obj), |
7548 XSTRING_LENGTH (obj)); | |
7549 else if (str) | |
867 | 7550 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) str, strlen (str)); |
428 | 7551 |
7552 decode_mode_spec_done: | |
867 | 7553 Dynarr_add (mode_spec_ibyte_string, '\0'); |
428 | 7554 } |
7555 | |
7556 /* Given a display line, free all of its data structures. */ | |
7557 | |
7558 static void | |
7559 free_display_line (struct display_line *dl) | |
7560 { | |
7561 int block; | |
7562 | |
7563 if (dl->display_blocks) | |
7564 { | |
7565 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
4187 | 7566 { |
428 | 7567 struct display_block *db = Dynarr_atp (dl->display_blocks, block); |
7568 | |
7569 Dynarr_free (db->runes); | |
7570 } | |
7571 | |
7572 Dynarr_free (dl->display_blocks); | |
7573 dl->display_blocks = NULL; | |
7574 } | |
7575 | |
7576 if (dl->left_glyphs) | |
7577 { | |
7578 Dynarr_free (dl->left_glyphs); | |
7579 dl->left_glyphs = NULL; | |
7580 } | |
7581 | |
7582 if (dl->right_glyphs) | |
7583 { | |
7584 Dynarr_free (dl->right_glyphs); | |
7585 dl->right_glyphs = NULL; | |
7586 } | |
7587 } | |
7588 | |
7589 | |
7590 /* Given an array of display lines, free them and all data structures | |
7591 contained within them. */ | |
7592 | |
7593 void | |
7594 free_display_lines (display_line_dynarr *dla) | |
7595 { | |
7596 int line; | |
7597 | |
7598 for (line = 0; line < Dynarr_largest (dla); line++) | |
7599 { | |
7600 free_display_line (Dynarr_atp (dla, line)); | |
7601 } | |
7602 | |
7603 Dynarr_free (dla); | |
7604 } | |
7605 | |
7606 /* Call internal free routine for each set of display lines. */ | |
7607 | |
7608 void | |
7609 free_display_structs (struct window_mirror *mir) | |
7610 { | |
7611 if (mir->current_display_lines) | |
7612 { | |
7613 free_display_lines (mir->current_display_lines); | |
7614 mir->current_display_lines = 0; | |
7615 } | |
7616 | |
7617 if (mir->desired_display_lines) | |
7618 { | |
7619 free_display_lines (mir->desired_display_lines); | |
7620 mir->desired_display_lines = 0; | |
7621 } | |
7622 } | |
7623 | |
7624 | |
7625 static void | |
7626 mark_glyph_block_dynarr (glyph_block_dynarr *gba) | |
7627 { | |
7628 if (gba) | |
7629 { | |
4967 | 7630 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
|
7631 glyph_block *gb_last = Dynarr_past_lastp (gba); |
428 | 7632 |
7633 for (; gb < gb_last; gb++) | |
7634 { | |
7635 if (!NILP (gb->glyph)) | |
7636 mark_object (gb->glyph); | |
7637 if (!NILP (gb->extent)) | |
7638 mark_object (gb->extent); | |
7639 } | |
7640 } | |
7641 } | |
7642 | |
442 | 7643 /* See the comment in image_instantiate_cache_result as to why marking |
7644 the glyph will also mark the image_instance. */ | |
7645 void | |
428 | 7646 mark_redisplay_structs (display_line_dynarr *dla) |
7647 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7648 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
|
7649 display_line *dl_last = Dynarr_past_lastp (dla); |
428 | 7650 |
7651 for (; dl < dl_last; dl++) | |
7652 { | |
7653 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
|
7654 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
|
7655 display_block *db_last = Dynarr_past_lastp (dba); |
428 | 7656 |
7657 for (; db < db_last; db++) | |
7658 { | |
7659 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
|
7660 rune *r = Dynarr_begin (ra); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7661 rune *r_last = Dynarr_past_lastp (ra); |
428 | 7662 |
7663 for (; r < r_last; r++) | |
7664 { | |
7665 if (r->type == RUNE_DGLYPH) | |
7666 { | |
7667 if (!NILP (r->object.dglyph.glyph)) | |
7668 mark_object (r->object.dglyph.glyph); | |
7669 if (!NILP (r->object.dglyph.extent)) | |
7670 mark_object (r->object.dglyph.extent); | |
7671 } | |
7672 } | |
7673 } | |
7674 | |
7675 mark_glyph_block_dynarr (dl->left_glyphs); | |
7676 mark_glyph_block_dynarr (dl->right_glyphs); | |
7677 } | |
7678 } | |
7679 | |
7680 | |
2367 | 7681 |
7682 /* | |
7683 | |
7684 Info on line-start cache: | |
7685 | |
7686 (Info-goto-node "(internals)Line Start Cache") | |
7687 */ | |
428 | 7688 |
7689 /* This will get used quite a bit so we don't want to be constantly | |
7690 allocating and freeing it. */ | |
7691 static line_start_cache_dynarr *internal_cache; | |
7692 | |
7693 /* Makes internal_cache represent the TYPE display structs and only | |
7694 the TYPE display structs. */ | |
7695 | |
7696 static void | |
7697 update_internal_cache_list (struct window *w, int type) | |
7698 { | |
7699 int line; | |
7700 display_line_dynarr *dla = window_display_lines (w, type); | |
7701 | |
7702 Dynarr_reset (internal_cache); | |
7703 for (line = 0; line < Dynarr_length (dla); line++) | |
7704 { | |
7705 struct display_line *dl = Dynarr_atp (dla, line); | |
7706 | |
7707 if (dl->modeline) | |
7708 continue; | |
7709 else | |
7710 { | |
7711 struct line_start_cache lsc; | |
434 | 7712 |
826 | 7713 lsc.start = dl->charpos; |
7714 lsc.end = dl->end_charpos; | |
428 | 7715 lsc.height = dl->ascent + dl->descent; |
7716 | |
7717 Dynarr_add (internal_cache, lsc); | |
7718 } | |
7719 } | |
7720 } | |
7721 | |
7722 /* Reset the line cache if necessary. This should be run at the | |
7723 beginning of any function which access the cache. */ | |
7724 | |
7725 static void | |
7726 validate_line_start_cache (struct window *w) | |
7727 { | |
7728 struct buffer *b = XBUFFER (w->buffer); | |
7729 struct frame *f = XFRAME (w->frame); | |
7730 | |
7731 if (!w->line_cache_validation_override) | |
7732 { | |
7733 /* f->extents_changed used to be in here because extent face and | |
4187 | 7734 size changes can cause text shifting. However, the extent |
7735 covering the region is constantly having its face set and | |
7736 priority altered by the mouse code. This means that the line | |
7737 start cache is constantly being invalidated. This is bad | |
7738 since the mouse code also triggers heavy usage of the cache. | |
7739 Since it is an unlikely that f->extents being changed | |
7740 indicates that the cache really needs to be updated and if it | |
7741 does redisplay will catch it pretty quickly we no longer | |
7742 invalidate the cache if it is set. This greatly speeds up | |
7743 dragging out regions with the mouse. */ | |
428 | 7744 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b) |
7745 || f->faces_changed | |
7746 || f->clip_changed) | |
7747 { | |
7748 Dynarr_reset (w->line_start_cache); | |
7749 } | |
7750 } | |
7751 } | |
7752 | |
7753 /* Return the very first buffer position contained in the given | |
7754 window's cache, or -1 if the cache is empty. Assumes that the | |
7755 cache is valid. */ | |
7756 | |
665 | 7757 static Charbpos |
428 | 7758 line_start_cache_start (struct window *w) |
7759 { | |
7760 line_start_cache_dynarr *cache = w->line_start_cache; | |
7761 | |
7762 if (!Dynarr_length (cache)) | |
7763 return -1; | |
7764 else | |
4967 | 7765 return Dynarr_begin (cache)->start; |
428 | 7766 } |
7767 | |
7768 /* Return the very last buffer position contained in the given | |
7769 window's cache, or -1 if the cache is empty. Assumes that the | |
7770 cache is valid. */ | |
7771 | |
665 | 7772 static Charbpos |
428 | 7773 line_start_cache_end (struct window *w) |
7774 { | |
7775 line_start_cache_dynarr *cache = w->line_start_cache; | |
7776 | |
7777 if (!Dynarr_length (cache)) | |
7778 return -1; | |
7779 else | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7780 return Dynarr_lastp (cache)->end; |
428 | 7781 } |
7782 | |
7783 /* Return the index of the line POINT is contained within in window | |
7784 W's line start cache. It will enlarge the cache or move the cache | |
7785 window in order to have POINT be present in the cache. MIN_PAST is | |
7786 a guarantee of the number of entries in the cache present on either | |
7787 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1 | |
7788 then it will be treated as 0, but the cache window will not be | |
7789 allowed to shift. Returns -1 if POINT cannot be found in the cache | |
7790 for any reason. */ | |
7791 | |
7792 int | |
665 | 7793 point_in_line_start_cache (struct window *w, Charbpos point, int min_past) |
428 | 7794 { |
7795 struct buffer *b = XBUFFER (w->buffer); | |
7796 line_start_cache_dynarr *cache = w->line_start_cache; | |
647 | 7797 int top, bottom, pos; |
428 | 7798 |
7799 validate_line_start_cache (w); | |
7800 w->line_cache_validation_override++; | |
7801 | |
7802 /* Let functions pass in negative values, but we still treat -1 | |
7803 specially. */ | |
7804 /* #### bogosity alert */ | |
7805 if (min_past < 0 && min_past != -1) | |
7806 min_past = -min_past; | |
7807 | |
7808 if (!Dynarr_length (cache) || line_start_cache_start (w) > point | |
7809 || line_start_cache_end (w) < point) | |
7810 { | |
7811 int loop; | |
7812 int win_char_height = window_char_height (w, 1); | |
7813 | |
7814 /* Occasionally we get here with a 0 height | |
4187 | 7815 window. find_next_newline_no_quit will abort if we pass it a |
7816 count of 0 so handle that case. */ | |
428 | 7817 if (!win_char_height) |
7818 win_char_height = 1; | |
7819 | |
7820 if (!Dynarr_length (cache)) | |
7821 { | |
665 | 7822 Charbpos from = find_next_newline_no_quit (b, point, -1); |
7823 Charbpos to = find_next_newline_no_quit (b, from, win_char_height); | |
428 | 7824 |
7825 update_line_start_cache (w, from, to, point, 0); | |
7826 | |
7827 if (!Dynarr_length (cache)) | |
7828 { | |
7829 w->line_cache_validation_override--; | |
7830 return -1; | |
7831 } | |
7832 } | |
7833 | |
7834 assert (Dynarr_length (cache)); | |
7835 | |
7836 loop = 0; | |
7837 while (line_start_cache_start (w) > point | |
7838 && (loop < cache_adjustment || min_past == -1)) | |
7839 { | |
665 | 7840 Charbpos from, to; |
428 | 7841 |
7842 from = line_start_cache_start (w); | |
7843 if (from <= BUF_BEGV (b)) | |
7844 break; | |
7845 | |
7846 from = find_next_newline_no_quit (b, from, -win_char_height); | |
7847 to = line_start_cache_end (w); | |
7848 | |
7849 update_line_start_cache (w, from, to, point, 0); | |
7850 loop++; | |
7851 } | |
7852 | |
7853 if (line_start_cache_start (w) > point) | |
7854 { | |
665 | 7855 Charbpos from, to; |
428 | 7856 |
7857 from = find_next_newline_no_quit (b, point, -1); | |
7858 if (from >= BUF_ZV (b)) | |
7859 { | |
7860 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7861 from = to; | |
7862 to = BUF_ZV (b); | |
7863 } | |
7864 else | |
7865 to = find_next_newline_no_quit (b, from, win_char_height); | |
7866 | |
7867 update_line_start_cache (w, from, to, point, 0); | |
7868 } | |
7869 | |
7870 loop = 0; | |
7871 while (line_start_cache_end (w) < point | |
7872 && (loop < cache_adjustment || min_past == -1)) | |
7873 { | |
665 | 7874 Charbpos from, to; |
428 | 7875 |
7876 to = line_start_cache_end (w); | |
7877 if (to >= BUF_ZV (b)) | |
7878 break; | |
7879 | |
7880 from = line_start_cache_end (w); | |
7881 to = find_next_newline_no_quit (b, from, win_char_height); | |
7882 | |
7883 update_line_start_cache (w, from, to, point, 0); | |
7884 loop++; | |
7885 } | |
7886 | |
7887 if (line_start_cache_end (w) < point) | |
7888 { | |
665 | 7889 Charbpos from, to; |
428 | 7890 |
7891 from = find_next_newline_no_quit (b, point, -1); | |
7892 if (from >= BUF_ZV (b)) | |
7893 { | |
7894 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7895 from = to; | |
7896 to = BUF_ZV (b); | |
7897 } | |
7898 else | |
7899 to = find_next_newline_no_quit (b, from, win_char_height); | |
7900 | |
7901 update_line_start_cache (w, from, to, point, 0); | |
7902 } | |
7903 } | |
7904 | |
7905 assert (Dynarr_length (cache)); | |
7906 | |
7907 if (min_past == -1) | |
7908 min_past = 0; | |
7909 | |
7910 /* This could happen if the buffer is narrowed. */ | |
7911 if (line_start_cache_start (w) > point | |
7912 || line_start_cache_end (w) < point) | |
7913 { | |
7914 w->line_cache_validation_override--; | |
7915 return -1; | |
7916 } | |
7917 | |
7918 find_point_loop: | |
7919 | |
7920 top = Dynarr_length (cache) - 1; | |
7921 bottom = 0; | |
7922 | |
7923 while (1) | |
7924 { | |
647 | 7925 int new_pos; |
665 | 7926 Charbpos start, end; |
428 | 7927 |
7928 pos = (bottom + top + 1) >> 1; | |
7929 start = Dynarr_atp (cache, pos)->start; | |
7930 end = Dynarr_atp (cache, pos)->end; | |
7931 | |
7932 if (point >= start && point <= end) | |
7933 { | |
7934 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b)) | |
7935 { | |
665 | 7936 Charbpos from = |
428 | 7937 find_next_newline_no_quit (b, line_start_cache_start (w), |
7938 -min_past - 1); | |
665 | 7939 Charbpos to = line_start_cache_end (w); |
428 | 7940 |
7941 update_line_start_cache (w, from, to, point, 0); | |
7942 goto find_point_loop; | |
7943 } | |
7944 else if ((Dynarr_length (cache) - pos - 1) < min_past | |
7945 && line_start_cache_end (w) < BUF_ZV (b)) | |
7946 { | |
665 | 7947 Charbpos from = line_start_cache_end (w); |
7948 Charbpos to = find_next_newline_no_quit (b, from, | |
428 | 7949 (min_past |
7950 ? min_past | |
7951 : 1)); | |
7952 | |
7953 update_line_start_cache (w, from, to, point, 0); | |
7954 goto find_point_loop; | |
7955 } | |
7956 else | |
7957 { | |
7958 w->line_cache_validation_override--; | |
7959 return pos; | |
7960 } | |
7961 } | |
7962 else if (point > end) | |
7963 bottom = pos + 1; | |
7964 else if (point < start) | |
7965 top = pos - 1; | |
7966 else | |
2500 | 7967 ABORT (); |
428 | 7968 |
7969 new_pos = (bottom + top + 1) >> 1; | |
7970 if (pos == new_pos) | |
7971 { | |
7972 w->line_cache_validation_override--; | |
7973 return -1; | |
7974 } | |
7975 } | |
7976 } | |
7977 | |
7978 /* Return a boolean indicating if POINT would be visible in window W | |
1708 | 7979 if display of the window was to begin at STARTP. If PARTIALLY is |
7980 zero, then if POINT has fewer visible pixels than the window clip, | |
7981 0 is returned; otherwise, 1 is returned if POINT has any visible | |
7982 pixels. */ | |
428 | 7983 int |
1708 | 7984 point_would_be_visible (struct window *w, Charbpos startp, Charbpos point, |
7985 int partially) | |
428 | 7986 { |
7987 struct buffer *b = XBUFFER (w->buffer); | |
430 | 7988 int pixpos = -WINDOW_TEXT_TOP_CLIP(w); |
428 | 7989 int bottom = WINDOW_TEXT_HEIGHT (w); |
7990 int start_elt; | |
7991 | |
7992 /* If point is before the intended start it obviously can't be visible. */ | |
7993 if (point < startp) | |
7994 return 0; | |
7995 | |
7996 /* If point or start are not in the accessible buffer range, then | |
7997 fail. */ | |
7998 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b) | |
7999 || point < BUF_BEGV (b) || point > BUF_ZV (b)) | |
8000 return 0; | |
8001 | |
8002 validate_line_start_cache (w); | |
8003 w->line_cache_validation_override++; | |
8004 | |
8005 start_elt = point_in_line_start_cache (w, startp, 0); | |
8006 if (start_elt == -1) | |
8007 { | |
8008 w->line_cache_validation_override--; | |
8009 return 0; | |
8010 } | |
8011 | |
8012 assert (line_start_cache_start (w) <= startp | |
8013 && line_start_cache_end (w) >= startp); | |
8014 | |
8015 while (1) | |
8016 { | |
8017 int height; | |
8018 | |
8019 /* Expand the cache if necessary. */ | |
8020 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8021 { | |
665 | 8022 Charbpos old_startp = |
428 | 8023 Dynarr_atp (w->line_start_cache, start_elt - 1)->start; |
8024 | |
8025 start_elt = point_in_line_start_cache (w, old_startp, | |
8026 window_char_height (w, 0)); | |
8027 | |
8028 /* We've already actually processed old_startp, so increment | |
4187 | 8029 immediately. */ |
428 | 8030 start_elt++; |
8031 | |
8032 /* If this happens we didn't add any extra elements. Bummer. */ | |
8033 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8034 { | |
8035 w->line_cache_validation_override--; | |
8036 return 0; | |
8037 } | |
8038 } | |
8039 | |
8040 height = Dynarr_atp (w->line_start_cache, start_elt)->height; | |
8041 | |
8042 if (pixpos + height > bottom) | |
8043 { | |
1708 | 8044 if (bottom - pixpos < (partially ? 0 : VERTICAL_CLIP (w, 0))) |
428 | 8045 { |
8046 w->line_cache_validation_override--; | |
8047 return 0; | |
8048 } | |
8049 } | |
8050 | |
8051 pixpos += height; | |
8052 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end) | |
8053 { | |
8054 w->line_cache_validation_override--; | |
8055 return 1; | |
8056 } | |
8057 | |
8058 start_elt++; | |
8059 } | |
8060 } | |
8061 | |
8062 /* For the given window W, if display starts at STARTP, what will be | |
8063 the buffer position at the beginning or end of the last line | |
8064 displayed. The end of the last line is also know as the window end | |
8065 position. | |
8066 | |
442 | 8067 WARNING: It is possible that redisplay failed to layout any lines for the |
8068 windows. Under normal circumstances this is rare. However it seems that it | |
8069 does occur in the following situation: A mouse event has come in and we | |
8070 need to compute its location in a window. That code (in | |
8071 pixel_to_glyph_translation) already can handle 0 as an error return value. | |
8072 | |
428 | 8073 #### With a little work this could probably be reworked as just a |
8074 call to start_with_line_at_pixpos. */ | |
8075 | |
665 | 8076 static Charbpos |
8077 start_end_of_last_line (struct window *w, Charbpos startp, int end, | |
4187 | 8078 int may_error) |
428 | 8079 { |
8080 struct buffer *b = XBUFFER (w->buffer); | |
8081 line_start_cache_dynarr *cache = w->line_start_cache; | |
8082 int pixpos = 0; | |
8083 int bottom = WINDOW_TEXT_HEIGHT (w); | |
665 | 8084 Charbpos cur_start; |
428 | 8085 int start_elt; |
8086 | |
8087 validate_line_start_cache (w); | |
8088 w->line_cache_validation_override++; | |
8089 | |
8090 if (startp < BUF_BEGV (b)) | |
8091 startp = BUF_BEGV (b); | |
8092 else if (startp > BUF_ZV (b)) | |
8093 startp = BUF_ZV (b); | |
8094 cur_start = startp; | |
8095 | |
8096 start_elt = point_in_line_start_cache (w, cur_start, 0); | |
8097 if (start_elt == -1) | |
442 | 8098 return may_error ? 0 : startp; |
428 | 8099 |
8100 while (1) | |
8101 { | |
8102 int height = Dynarr_atp (cache, start_elt)->height; | |
8103 | |
8104 cur_start = Dynarr_atp (cache, start_elt)->start; | |
8105 | |
8106 if (pixpos + height > bottom) | |
8107 { | |
8108 /* Adjust for any possible clip. */ | |
8109 if (bottom - pixpos < VERTICAL_CLIP (w, 0)) | |
8110 start_elt--; | |
8111 | |
8112 if (start_elt < 0) | |
8113 { | |
8114 w->line_cache_validation_override--; | |
8115 if (end) | |
8116 return BUF_ZV (b); | |
8117 else | |
8118 return BUF_BEGV (b); | |
8119 } | |
8120 else | |
8121 { | |
8122 w->line_cache_validation_override--; | |
8123 if (end) | |
8124 return Dynarr_atp (cache, start_elt)->end; | |
8125 else | |
8126 return Dynarr_atp (cache, start_elt)->start; | |
8127 } | |
8128 } | |
8129 | |
8130 pixpos += height; | |
8131 start_elt++; | |
8132 if (start_elt == Dynarr_length (cache)) | |
8133 { | |
665 | 8134 Charbpos from = line_start_cache_end (w); |
428 | 8135 int win_char_height = window_char_height (w, 0); |
665 | 8136 Charbpos to = find_next_newline_no_quit (b, from, |
428 | 8137 (win_char_height |
8138 ? win_char_height | |
8139 : 1)); | |
8140 | |
8141 /* We've hit the end of the bottom so that's what it is. */ | |
8142 if (from >= BUF_ZV (b)) | |
8143 { | |
8144 w->line_cache_validation_override--; | |
8145 return BUF_ZV (b); | |
8146 } | |
8147 | |
8148 update_line_start_cache (w, from, to, BUF_PT (b), 0); | |
8149 | |
8150 /* Updating the cache invalidates any current indexes. */ | |
8151 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1; | |
8152 } | |
8153 } | |
8154 } | |
8155 | |
8156 /* For the given window W, if display starts at STARTP, what will be | |
8157 the buffer position at the beginning of the last line displayed. */ | |
8158 | |
665 | 8159 Charbpos |
8160 start_of_last_line (struct window *w, Charbpos startp) | |
428 | 8161 { |
442 | 8162 return start_end_of_last_line (w, startp, 0 , 0); |
428 | 8163 } |
8164 | |
8165 /* For the given window W, if display starts at STARTP, what will be | |
8166 the buffer position at the end of the last line displayed. This is | |
8167 also know as the window end position. */ | |
8168 | |
665 | 8169 Charbpos |
8170 end_of_last_line (struct window *w, Charbpos startp) | |
428 | 8171 { |
442 | 8172 return start_end_of_last_line (w, startp, 1, 0); |
428 | 8173 } |
8174 | |
665 | 8175 static Charbpos |
8176 end_of_last_line_may_error (struct window *w, Charbpos startp) | |
442 | 8177 { |
8178 return start_end_of_last_line (w, startp, 1, 1); | |
8179 } | |
8180 | |
8181 | |
428 | 8182 /* For window W, what does the starting position have to be so that |
8183 the line containing POINT will cover pixel position PIXPOS. */ | |
8184 | |
665 | 8185 Charbpos |
8186 start_with_line_at_pixpos (struct window *w, Charbpos point, int pixpos) | |
428 | 8187 { |
8188 struct buffer *b = XBUFFER (w->buffer); | |
8189 int cur_elt; | |
665 | 8190 Charbpos cur_pos, prev_pos = point; |
428 | 8191 int point_line_height; |
8192 int pixheight = pixpos - WINDOW_TEXT_TOP (w); | |
8193 | |
8194 validate_line_start_cache (w); | |
8195 w->line_cache_validation_override++; | |
8196 | |
8197 cur_elt = point_in_line_start_cache (w, point, 0); | |
8198 /* #### See comment in update_line_start_cache about big minibuffers. */ | |
8199 if (cur_elt < 0) | |
8200 { | |
8201 w->line_cache_validation_override--; | |
8202 return point; | |
8203 } | |
8204 | |
8205 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8206 | |
8207 while (1) | |
8208 { | |
8209 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8210 | |
8211 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8212 | |
8213 /* Do not take into account the value of vertical_clip here. | |
4187 | 8214 That is the responsibility of the calling functions. */ |
428 | 8215 if (pixheight < 0) |
8216 { | |
8217 w->line_cache_validation_override--; | |
8218 if (-pixheight > point_line_height) | |
8219 /* We can't make the target line cover pixpos, so put it | |
8220 above pixpos. That way it will at least be visible. */ | |
8221 return prev_pos; | |
8222 else | |
8223 return cur_pos; | |
8224 } | |
8225 | |
8226 cur_elt--; | |
8227 while (cur_elt < 0) | |
8228 { | |
665 | 8229 Charbpos from, to; |
428 | 8230 int win_char_height; |
8231 | |
8232 if (cur_pos <= BUF_BEGV (b)) | |
8233 { | |
8234 w->line_cache_validation_override--; | |
8235 return BUF_BEGV (b); | |
8236 } | |
8237 | |
8238 win_char_height = window_char_height (w, 0); | |
8239 if (!win_char_height) | |
8240 win_char_height = 1; | |
8241 | |
8242 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); | |
8243 to = line_start_cache_end (w); | |
8244 update_line_start_cache (w, from, to, point, 0); | |
8245 | |
8246 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; | |
8247 assert (cur_elt >= -1); | |
8248 /* This used to be cur_elt>=0 under the assumption that if | |
8249 point is in the top line and not at BUF_BEGV, then | |
434 | 8250 setting the window_start to a newline before the start of |
428 | 8251 the first line will always cause scrolling. |
8252 | |
8253 However in my (jv) opinion this is wrong. That new line | |
8254 can be hidden in various ways: invisible extents, an | |
8255 explicit window-start not at a newline character etc. | |
8256 The existence of those are indeed known to create crashes | |
8257 on that assert. So we have no option but to continue the | |
8258 search if we found point at the top of the line_start_cache | |
8259 again. */ | |
4967 | 8260 cur_pos = Dynarr_begin (w->line_start_cache)->start; |
428 | 8261 } |
8262 prev_pos = cur_pos; | |
8263 } | |
8264 } | |
8265 | |
8266 /* For window W, what does the starting position have to be so that | |
8267 the line containing point is on display line LINE. If LINE is | |
8268 positive it is considered to be the number of lines from the top of | |
8269 the window (0 is the top line). If it is negative the number is | |
8270 considered to be the number of lines from the bottom (-1 is the | |
8271 bottom line). */ | |
8272 | |
665 | 8273 Charbpos |
8274 start_with_point_on_display_line (struct window *w, Charbpos point, int line) | |
428 | 8275 { |
8276 validate_line_start_cache (w); | |
8277 w->line_cache_validation_override++; | |
8278 | |
8279 if (line >= 0) | |
8280 { | |
8281 int cur_elt = point_in_line_start_cache (w, point, line); | |
8282 | |
8283 if (cur_elt - line < 0) | |
8284 cur_elt = 0; /* Hit the top */ | |
8285 else | |
8286 cur_elt -= line; | |
8287 | |
8288 w->line_cache_validation_override--; | |
8289 return Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8290 } | |
8291 else | |
8292 { | |
8293 /* The calculated value of pixpos is correct for the bottom line | |
4187 | 8294 or what we want when line is -1. Therefore we subtract one |
8295 because we have already handled one line. */ | |
428 | 8296 int new_line = -line - 1; |
8297 int cur_elt = point_in_line_start_cache (w, point, new_line); | |
8298 int pixpos = WINDOW_TEXT_BOTTOM (w); | |
665 | 8299 Charbpos retval, search_point; |
428 | 8300 |
8301 /* If scroll_on_clipped_lines is false, the last "visible" line of | |
4187 | 8302 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1. |
8303 If s_o_c_l is true, then we don't want to count a clipped | |
8304 line, so back up from the bottom by the height of the line | |
8305 containing point. */ | |
428 | 8306 if (scroll_on_clipped_lines) |
8307 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8308 else | |
8309 pixpos -= 1; | |
8310 | |
8311 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache)) | |
8312 { | |
8313 /* Hit the bottom of the buffer. */ | |
8314 int adjustment = | |
8315 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1; | |
8316 Lisp_Object window; | |
8317 int defheight; | |
8318 | |
793 | 8319 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
|
8320 default_face_width_and_height (window, 0, &defheight); |
428 | 8321 |
8322 cur_elt = Dynarr_length (w->line_start_cache) - 1; | |
8323 | |
8324 pixpos -= (adjustment * defheight); | |
8325 if (pixpos < WINDOW_TEXT_TOP (w)) | |
8326 pixpos = WINDOW_TEXT_TOP (w); | |
8327 } | |
8328 else | |
8329 cur_elt = cur_elt + new_line; | |
8330 | |
8331 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8332 | |
8333 retval = start_with_line_at_pixpos (w, search_point, pixpos); | |
8334 w->line_cache_validation_override--; | |
8335 return retval; | |
8336 } | |
8337 } | |
8338 | |
8339 /* This is used to speed up vertical scrolling by caching the known | |
8340 buffer starting positions for display lines. This allows the | |
8341 scrolling routines to avoid costly calls to regenerate_window. If | |
8342 NO_REGEN is true then it will only add the values in the DESIRED | |
8343 display structs which are in the given range. | |
8344 | |
8345 Note also that the FROM/TO values are minimums. It is possible | |
8346 that this function will actually add information outside of the | |
8347 lines containing those positions. This can't hurt but it could | |
8348 possibly help. | |
8349 | |
8350 #### We currently force the cache to have only 1 contiguous region. | |
8351 It might help to make the cache a dynarr of caches so that we can | |
8352 cover more areas. This might, however, turn out to be a lot of | |
8353 overhead for too little gain. */ | |
8354 | |
8355 static void | |
665 | 8356 update_line_start_cache (struct window *w, Charbpos from, Charbpos to, |
8357 Charbpos point, int no_regen) | |
428 | 8358 { |
8359 struct buffer *b = XBUFFER (w->buffer); | |
8360 line_start_cache_dynarr *cache = w->line_start_cache; | |
665 | 8361 Charbpos low_bound, high_bound; |
428 | 8362 |
8363 validate_line_start_cache (w); | |
8364 w->line_cache_validation_override++; | |
8365 | |
8366 if (from < BUF_BEGV (b)) | |
8367 from = BUF_BEGV (b); | |
8368 if (to > BUF_ZV (b)) | |
8369 to = BUF_ZV (b); | |
8370 | |
8371 if (from > to) | |
8372 { | |
8373 w->line_cache_validation_override--; | |
8374 return; | |
8375 } | |
8376 | |
8377 if (Dynarr_length (cache)) | |
8378 { | |
8379 low_bound = line_start_cache_start (w); | |
8380 high_bound = line_start_cache_end (w); | |
8381 | |
8382 /* Check to see if the desired range is already in the cache. */ | |
8383 if (from >= low_bound && to <= high_bound) | |
8384 { | |
8385 w->line_cache_validation_override--; | |
8386 return; | |
8387 } | |
8388 | |
8389 /* Check to make sure that the desired range is adjacent to the | |
8390 current cache. If not, invalidate the cache. */ | |
8391 if (to < low_bound || from > high_bound) | |
8392 { | |
8393 Dynarr_reset (cache); | |
8394 low_bound = high_bound = -1; | |
8395 } | |
8396 } | |
8397 else | |
8398 { | |
8399 low_bound = high_bound = -1; | |
8400 } | |
8401 | |
8402 w->line_cache_last_updated = make_int (BUF_MODIFF (b)); | |
8403 | |
8404 /* This could be integrated into the next two sections, but it is easier | |
8405 to follow what's going on by having it separate. */ | |
8406 if (no_regen) | |
8407 { | |
665 | 8408 Charbpos start, end; |
428 | 8409 |
8410 update_internal_cache_list (w, DESIRED_DISP); | |
8411 if (!Dynarr_length (internal_cache)) | |
8412 { | |
8413 w->line_cache_validation_override--; | |
8414 return; | |
8415 } | |
8416 | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8417 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
|
8418 end = Dynarr_lastp (internal_cache)->end; |
428 | 8419 |
8420 /* We aren't allowed to generate additional information to fill in | |
4187 | 8421 gaps, so if the DESIRED structs don't overlap the cache, reset the |
8422 cache. */ | |
428 | 8423 if (Dynarr_length (cache)) |
8424 { | |
8425 if (end < low_bound || start > high_bound) | |
8426 Dynarr_reset (cache); | |
8427 | |
8428 /* #### What should really happen if what we are doing is | |
4187 | 8429 extending a line (the last line)? */ |
428 | 8430 if (Dynarr_length (cache) == 1 |
8431 && Dynarr_length (internal_cache) == 1) | |
8432 Dynarr_reset (cache); | |
8433 } | |
8434 | |
8435 if (!Dynarr_length (cache)) | |
8436 { | |
4967 | 8437 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8438 Dynarr_length (internal_cache)); |
8439 w->line_cache_validation_override--; | |
8440 return; | |
8441 } | |
8442 | |
8443 /* An extra check just in case the calling function didn't pass in | |
4187 | 8444 the bounds of the DESIRED structs in the first place. */ |
428 | 8445 if (start >= low_bound && end <= high_bound) |
8446 { | |
8447 w->line_cache_validation_override--; | |
8448 return; | |
8449 } | |
8450 | |
8451 /* At this point we know that the internal cache partially overlaps | |
4187 | 8452 the main cache. */ |
428 | 8453 if (start < low_bound) |
8454 { | |
8455 int ic_elt = Dynarr_length (internal_cache) - 1; | |
8456 while (ic_elt >= 0) | |
8457 { | |
8458 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound) | |
8459 break; | |
8460 else | |
8461 ic_elt--; | |
8462 } | |
8463 | |
8464 if (!(ic_elt >= 0)) | |
8465 { | |
8466 Dynarr_reset (cache); | |
4967 | 8467 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8468 Dynarr_length (internal_cache)); |
8469 w->line_cache_validation_override--; | |
8470 return; | |
8471 } | |
8472 | |
5038 | 8473 Dynarr_prepend_many (cache, Dynarr_begin (internal_cache), |
428 | 8474 ic_elt + 1); |
8475 } | |
8476 | |
8477 if (end > high_bound) | |
8478 { | |
8479 int ic_elt = 0; | |
8480 | |
8481 while (ic_elt < Dynarr_length (internal_cache)) | |
8482 { | |
8483 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound) | |
8484 break; | |
8485 else | |
8486 ic_elt++; | |
8487 } | |
8488 | |
8489 if (!(ic_elt < Dynarr_length (internal_cache))) | |
8490 { | |
8491 Dynarr_reset (cache); | |
4967 | 8492 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8493 Dynarr_length (internal_cache)); |
8494 w->line_cache_validation_override--; | |
8495 return; | |
8496 } | |
8497 | |
8498 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), | |
8499 Dynarr_length (internal_cache) - ic_elt); | |
8500 } | |
8501 | |
8502 w->line_cache_validation_override--; | |
8503 return; | |
8504 } | |
8505 | |
8506 if (!Dynarr_length (cache) || from < low_bound) | |
8507 { | |
665 | 8508 Charbpos startp = find_next_newline_no_quit (b, from, -1); |
428 | 8509 int marker = 0; |
8510 int old_lb = low_bound; | |
8511 | |
8512 while (startp < old_lb || low_bound == -1) | |
8513 { | |
8514 int ic_elt; | |
4187 | 8515 Charbpos new_startp; |
428 | 8516 |
8517 regenerate_window (w, startp, point, CMOTION_DISP); | |
8518 update_internal_cache_list (w, CMOTION_DISP); | |
8519 | |
8520 /* If this assert is triggered then regenerate_window failed | |
4187 | 8521 to layout a single line. This is not possible since we |
442 | 8522 force at least a single line to be layout for CMOTION_DISP */ |
8523 assert (Dynarr_length (internal_cache)); | |
4967 | 8524 assert (startp == Dynarr_begin (internal_cache)->start); |
428 | 8525 |
8526 ic_elt = Dynarr_length (internal_cache) - 1; | |
8527 if (low_bound != -1) | |
8528 { | |
8529 while (ic_elt >= 0) | |
8530 { | |
8531 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb) | |
8532 break; | |
8533 else | |
8534 ic_elt--; | |
8535 } | |
8536 } | |
8537 assert (ic_elt >= 0); | |
8538 | |
8539 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1; | |
8540 | |
4187 | 8541 /* |
8542 * Handle invisible text properly: | |
8543 * If the last line we're inserting has the same end as the | |
8544 * line before which it will be added, merge the two lines. | |
8545 */ | |
8546 if (Dynarr_length (cache) && | |
8547 Dynarr_atp (internal_cache, ic_elt)->end == | |
8548 Dynarr_atp (cache, marker)->end) | |
8549 { | |
8550 Dynarr_atp (cache, marker)->start | |
8551 = Dynarr_atp (internal_cache, ic_elt)->start; | |
8552 Dynarr_atp (cache, marker)->height | |
8553 = Dynarr_atp (internal_cache, ic_elt)->height; | |
8554 ic_elt--; | |
8555 } | |
8556 | |
8557 if (ic_elt >= 0) /* we still have lines to add.. */ | |
8558 { | |
4967 | 8559 Dynarr_insert_many (cache, Dynarr_begin (internal_cache), |
4187 | 8560 ic_elt + 1, marker); |
8561 marker += (ic_elt + 1); | |
8562 } | |
428 | 8563 |
8564 if (startp < low_bound || low_bound == -1) | |
8565 low_bound = startp; | |
8566 startp = new_startp; | |
8567 if (startp > BUF_ZV (b)) | |
8568 { | |
8569 w->line_cache_validation_override--; | |
8570 return; | |
8571 } | |
8572 } | |
8573 } | |
8574 | |
8575 assert (Dynarr_length (cache)); | |
8576 assert (from >= low_bound); | |
8577 | |
8578 /* Readjust the high_bound to account for any changes made while | |
8579 correcting the low_bound. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8580 high_bound = Dynarr_lastp (cache)->end; |
428 | 8581 |
8582 if (to > high_bound) | |
8583 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8584 Charbpos startp = Dynarr_lastp (cache)->end + 1; |
428 | 8585 |
8586 do | |
8587 { | |
8588 regenerate_window (w, startp, point, CMOTION_DISP); | |
8589 update_internal_cache_list (w, CMOTION_DISP); | |
8590 | |
8591 /* See comment above about regenerate_window failing. */ | |
8592 assert (Dynarr_length (internal_cache)); | |
8593 | |
4967 | 8594 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8595 Dynarr_length (internal_cache)); |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8596 high_bound = Dynarr_lastp (cache)->end; |
428 | 8597 startp = high_bound + 1; |
8598 } | |
8599 while (to > high_bound); | |
8600 } | |
8601 | |
8602 w->line_cache_validation_override--; | |
8603 assert (to <= high_bound); | |
8604 } | |
8605 | |
8606 | |
8607 /* Given x and y coordinates in characters, relative to a window, | |
8608 return the pixel location corresponding to those coordinates. The | |
8609 pixel location returned is the center of the given character | |
8610 position. The pixel values are generated relative to the window, | |
8611 not the frame. | |
8612 | |
8613 The modeline is considered to be part of the window. */ | |
8614 | |
8615 void | |
8616 glyph_to_pixel_translation (struct window *w, int char_x, int char_y, | |
8617 int *pix_x, int *pix_y) | |
8618 { | |
8619 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
8620 int num_disp_lines, modeline; | |
8621 Lisp_Object window; | |
8622 int defheight, defwidth; | |
8623 | |
793 | 8624 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
|
8625 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 8626 |
8627 /* If we get a bogus value indicating somewhere above or to the left of | |
8628 the window, use the first window line or character position | |
8629 instead. */ | |
8630 if (char_y < 0) | |
8631 char_y = 0; | |
8632 if (char_x < 0) | |
8633 char_x = 0; | |
8634 | |
8635 num_disp_lines = Dynarr_length (dla); | |
8636 modeline = 0; | |
8637 if (num_disp_lines) | |
8638 { | |
4967 | 8639 if (Dynarr_begin (dla)->modeline) |
428 | 8640 { |
8641 num_disp_lines--; | |
8642 modeline = 1; | |
8643 } | |
8644 } | |
8645 | |
8646 /* First check if the y position intersects the display lines. */ | |
8647 if (char_y < num_disp_lines) | |
8648 { | |
8649 struct display_line *dl = Dynarr_atp (dla, char_y + modeline); | |
8650 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
8651 | |
8652 *pix_y = (dl->ypos - dl->ascent + | |
647 | 8653 ((dl->ascent + dl->descent - dl->clip) >> 1)); |
428 | 8654 |
8655 if (char_x < Dynarr_length (db->runes)) | |
8656 { | |
8657 struct rune *rb = Dynarr_atp (db->runes, char_x); | |
8658 | |
8659 *pix_x = rb->xpos + (rb->width >> 1); | |
8660 } | |
8661 else | |
8662 { | |
8663 int last_rune = Dynarr_length (db->runes) - 1; | |
8664 struct rune *rb = Dynarr_atp (db->runes, last_rune); | |
8665 | |
8666 char_x -= last_rune; | |
8667 | |
8668 *pix_x = rb->xpos + rb->width; | |
8669 *pix_x += ((char_x - 1) * defwidth); | |
8670 *pix_x += (defwidth >> 1); | |
8671 } | |
8672 } | |
8673 else | |
8674 { | |
8675 /* It didn't intersect, so extrapolate. #### For now, we include the | |
8676 modeline in this since we don't have true character positions in | |
8677 it. */ | |
8678 | |
8679 if (!Dynarr_length (w->face_cachels)) | |
8680 reset_face_cachels (w); | |
8681 | |
8682 char_y -= num_disp_lines; | |
8683 | |
8684 if (Dynarr_length (dla)) | |
8685 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8686 struct display_line *dl = Dynarr_lastp (dla); |
428 | 8687 *pix_y = dl->ypos + dl->descent - dl->clip; |
8688 } | |
8689 else | |
8690 *pix_y = WINDOW_TEXT_TOP (w); | |
8691 | |
8692 *pix_y += (char_y * defheight); | |
8693 *pix_y += (defheight >> 1); | |
8694 | |
8695 *pix_x = WINDOW_TEXT_LEFT (w); | |
8696 /* Don't adjust by one because this is still the unadjusted value. */ | |
8697 *pix_x += (char_x * defwidth); | |
8698 *pix_x += (defwidth >> 1); | |
8699 } | |
8700 | |
8701 if (*pix_x > w->pixel_left + w->pixel_width) | |
8702 *pix_x = w->pixel_left + w->pixel_width; | |
8703 if (*pix_y > w->pixel_top + w->pixel_height) | |
8704 *pix_y = w->pixel_top + w->pixel_height; | |
8705 | |
8706 *pix_x -= w->pixel_left; | |
8707 *pix_y -= w->pixel_top; | |
8708 } | |
8709 | |
8710 /* Given a display line and a position, determine if there is a glyph | |
8711 there and return information about it if there is. */ | |
8712 | |
8713 static void | |
8714 get_position_object (struct display_line *dl, Lisp_Object *obj1, | |
8715 Lisp_Object *obj2, int x_coord, int *low_x_coord, | |
8716 int *high_x_coord) | |
8717 { | |
8718 struct display_block *db; | |
8719 int elt; | |
8720 int block = | |
8721 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0); | |
8722 | |
8723 /* We use get_next_display_block to get the actual display block | |
8724 that would be displayed at x_coord. */ | |
8725 | |
8726 if (block == NO_BLOCK) | |
8727 return; | |
8728 else | |
8729 db = Dynarr_atp (dl->display_blocks, block); | |
8730 | |
8731 for (elt = 0; elt < Dynarr_length (db->runes); elt++) | |
8732 { | |
8733 struct rune *rb = Dynarr_atp (db->runes, elt); | |
8734 | |
8735 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) | |
8736 { | |
8737 if (rb->type == RUNE_DGLYPH) | |
8738 { | |
8739 *obj1 = rb->object.dglyph.glyph; | |
8740 *obj2 = rb->object.dglyph.extent; | |
8741 } | |
8742 else | |
8743 { | |
8744 *obj1 = Qnil; | |
8745 *obj2 = Qnil; | |
8746 } | |
8747 | |
8748 if (low_x_coord) | |
8749 *low_x_coord = rb->xpos; | |
8750 if (high_x_coord) | |
8751 *high_x_coord = rb->xpos + rb->width; | |
8752 | |
8753 return; | |
8754 } | |
8755 } | |
8756 } | |
8757 | |
8758 #define UPDATE_CACHE_RETURN \ | |
8759 do { \ | |
8760 d->pixel_to_glyph_cache.valid = 1; \ | |
8761 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \ | |
8762 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \ | |
8763 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \ | |
8764 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \ | |
8765 d->pixel_to_glyph_cache.frame = f; \ | |
8766 d->pixel_to_glyph_cache.col = *col; \ | |
8767 d->pixel_to_glyph_cache.row = *row; \ | |
8768 d->pixel_to_glyph_cache.obj_x = *obj_x; \ | |
8769 d->pixel_to_glyph_cache.obj_y = *obj_y; \ | |
8770 d->pixel_to_glyph_cache.w = *w; \ | |
5090 | 8771 d->pixel_to_glyph_cache.charpos = *charpos; \ |
428 | 8772 d->pixel_to_glyph_cache.closest = *closest; \ |
8773 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \ | |
8774 d->pixel_to_glyph_cache.obj1 = *obj1; \ | |
8775 d->pixel_to_glyph_cache.obj2 = *obj2; \ | |
8776 d->pixel_to_glyph_cache.retval = position; \ | |
8777 RETURN_SANS_WARNINGS position; \ | |
8778 } while (0) | |
8779 | |
8780 /* Given x and y coordinates in pixels relative to a frame, return | |
8781 information about what is located under those coordinates. | |
8782 | |
8783 The return value will be one of: | |
8784 | |
8785 OVER_TOOLBAR: over one of the 4 frame toolbars | |
8786 OVER_MODELINE: over a modeline | |
8787 OVER_BORDER: over an internal border | |
5090 | 8788 OVER_V_DIVIDER: over a vertical divider between windows (used as a |
8789 grab bar for resizing) | |
428 | 8790 OVER_NOTHING: over the text area, but not over text |
8791 OVER_OUTSIDE: outside of the frame border | |
8792 OVER_TEXT: over text in the text area | |
8793 | |
5090 | 8794 #### GEOM! We need to also have an OVER_GUTTER, OVER_SCROLLBAR and |
8795 OVER_DEAD_BOX. | |
8796 | |
428 | 8797 OBJ1 is one of |
8798 | |
8799 -- a toolbar button | |
8800 -- a glyph | |
8801 -- nil if the coordinates are not over a glyph or a toolbar button. | |
8802 | |
8803 OBJ2 is one of | |
8804 | |
8805 -- an extent, if the coordinates are over a glyph in the text area | |
8806 -- nil otherwise. | |
8807 | |
8808 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the | |
8809 equivalent coordinates relative to the upper-left corner of the glyph. | |
8810 | |
8811 If the coordinates are over a character, OBJ_X and OBJ_Y give the | |
8812 equivalent coordinates relative to the upper-left corner of the character. | |
8813 | |
8814 Otherwise, OBJ_X and OBJ_Y are undefined. | |
8815 */ | |
8816 | |
8817 int | |
8818 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, | |
8819 int *col, int *row, int *obj_x, int *obj_y, | |
826 | 8820 struct window **w, Charbpos *charpos, |
665 | 8821 Charbpos *closest, Charcount *modeline_closest, |
428 | 8822 Lisp_Object *obj1, Lisp_Object *obj2) |
8823 { | |
8824 struct device *d; | |
8825 struct pixel_to_glyph_translation_cache *cache; | |
8826 Lisp_Object window; | |
8827 int frm_left, frm_right, frm_top, frm_bottom; | |
8828 int low_x_coord, high_x_coord, low_y_coord, high_y_coord; | |
8829 int position = OVER_NOTHING; | |
8830 int device_check_failed = 0; | |
8831 display_line_dynarr *dla; | |
8832 | |
8833 /* This is a safety valve in case this got called with a frame in | |
8834 the middle of being deleted. */ | |
8835 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device))) | |
8836 { | |
8837 device_check_failed = 1; | |
8838 d = NULL, cache = NULL; /* Warning suppression */ | |
8839 } | |
8840 else | |
8841 { | |
8842 d = XDEVICE (f->device); | |
8843 cache = &d->pixel_to_glyph_cache; | |
8844 } | |
8845 | |
8846 if (!device_check_failed | |
8847 && cache->valid | |
8848 && cache->frame == f | |
8849 && cache->low_x_coord <= x_coord | |
8850 && cache->high_x_coord > x_coord | |
8851 && cache->low_y_coord <= y_coord | |
8852 && cache->high_y_coord > y_coord) | |
8853 { | |
8854 *col = cache->col; | |
8855 *row = cache->row; | |
8856 *obj_x = cache->obj_x; | |
8857 *obj_y = cache->obj_y; | |
8858 *w = cache->w; | |
826 | 8859 *charpos = cache->charpos; |
428 | 8860 *closest = cache->closest; |
8861 *modeline_closest = cache->modeline_closest; | |
8862 *obj1 = cache->obj1; | |
8863 *obj2 = cache->obj2; | |
8864 | |
8865 return cache->retval; | |
8866 } | |
8867 else | |
8868 { | |
8869 *col = 0; | |
8870 *row = 0; | |
8871 *obj_x = 0; | |
8872 *obj_y = 0; | |
8873 *w = 0; | |
826 | 8874 *charpos = 0; |
428 | 8875 *closest = 0; |
8876 *modeline_closest = -1; | |
8877 *obj1 = Qnil; | |
8878 *obj2 = Qnil; | |
8879 | |
8880 low_x_coord = x_coord; | |
8881 high_x_coord = x_coord + 1; | |
8882 low_y_coord = y_coord; | |
8883 high_y_coord = y_coord + 1; | |
8884 } | |
8885 | |
8886 if (device_check_failed) | |
8887 return OVER_NOTHING; | |
8888 | |
5090 | 8889 /* #### GEOM! The gutter is just inside of this. We should also have an |
8890 OVER_GUTTER return value to indicate that we're over a gutter. See | |
8891 above. */ | |
8892 frm_left = FRAME_LEFT_INTERNAL_BORDER_END (f); | |
8893 frm_right = FRAME_RIGHT_INTERNAL_BORDER_START (f); | |
8894 frm_top = FRAME_TOP_INTERNAL_BORDER_END (f); | |
8895 frm_bottom = FRAME_BOTTOM_INTERNAL_BORDER_START (f); | |
428 | 8896 |
8897 /* Check if the mouse is outside of the text area actually used by | |
8898 redisplay. */ | |
8899 if (y_coord < frm_top) | |
8900 { | |
5090 | 8901 if (y_coord >= FRAME_TOP_INTERNAL_BORDER_START (f)) |
8902 { | |
8903 low_y_coord = FRAME_TOP_INTERNAL_BORDER_START (f); | |
428 | 8904 high_y_coord = frm_top; |
8905 position = OVER_BORDER; | |
8906 } | |
8907 else if (y_coord >= 0) | |
8908 { | |
8909 low_y_coord = 0; | |
5090 | 8910 high_y_coord = FRAME_TOP_INTERNAL_BORDER_START (f); |
428 | 8911 position = OVER_TOOLBAR; |
8912 } | |
8913 else | |
8914 { | |
8915 low_y_coord = y_coord; | |
8916 high_y_coord = 0; | |
8917 position = OVER_OUTSIDE; | |
8918 } | |
8919 } | |
8920 else if (y_coord >= frm_bottom) | |
8921 { | |
5090 | 8922 if (y_coord < FRAME_BOTTOM_INTERNAL_BORDER_END (f)) |
428 | 8923 { |
8924 low_y_coord = frm_bottom; | |
5090 | 8925 high_y_coord = FRAME_BOTTOM_INTERNAL_BORDER_END (f); |
428 | 8926 position = OVER_BORDER; |
8927 } | |
8928 else if (y_coord < FRAME_PIXHEIGHT (f)) | |
8929 { | |
5090 | 8930 low_y_coord = FRAME_BOTTOM_INTERNAL_BORDER_END (f); |
428 | 8931 high_y_coord = FRAME_PIXHEIGHT (f); |
8932 position = OVER_TOOLBAR; | |
8933 } | |
8934 else | |
8935 { | |
8936 low_y_coord = FRAME_PIXHEIGHT (f); | |
8937 high_y_coord = y_coord; | |
8938 position = OVER_OUTSIDE; | |
8939 } | |
8940 } | |
8941 | |
8942 if (position != OVER_TOOLBAR && position != OVER_BORDER) | |
8943 { | |
8944 if (x_coord < frm_left) | |
8945 { | |
5090 | 8946 if (x_coord >= FRAME_LEFT_INTERNAL_BORDER_START (f)) |
8947 { | |
8948 low_x_coord = FRAME_LEFT_INTERNAL_BORDER_START (f); | |
428 | 8949 high_x_coord = frm_left; |
8950 position = OVER_BORDER; | |
8951 } | |
8952 else if (x_coord >= 0) | |
8953 { | |
8954 low_x_coord = 0; | |
5090 | 8955 high_x_coord = FRAME_LEFT_INTERNAL_BORDER_START (f); |
428 | 8956 position = OVER_TOOLBAR; |
8957 } | |
8958 else | |
8959 { | |
8960 low_x_coord = x_coord; | |
8961 high_x_coord = 0; | |
8962 position = OVER_OUTSIDE; | |
8963 } | |
8964 } | |
8965 else if (x_coord >= frm_right) | |
8966 { | |
5090 | 8967 if (x_coord < FRAME_RIGHT_INTERNAL_BORDER_END (f)) |
428 | 8968 { |
8969 low_x_coord = frm_right; | |
5090 | 8970 high_x_coord = FRAME_RIGHT_INTERNAL_BORDER_END (f); |
428 | 8971 position = OVER_BORDER; |
8972 } | |
8973 else if (x_coord < FRAME_PIXWIDTH (f)) | |
8974 { | |
5090 | 8975 low_x_coord = FRAME_RIGHT_INTERNAL_BORDER_END (f); |
428 | 8976 high_x_coord = FRAME_PIXWIDTH (f); |
8977 position = OVER_TOOLBAR; | |
8978 } | |
8979 else | |
8980 { | |
8981 low_x_coord = FRAME_PIXWIDTH (f); | |
8982 high_x_coord = x_coord; | |
8983 position = OVER_OUTSIDE; | |
8984 } | |
8985 } | |
8986 } | |
8987 | |
8988 #ifdef HAVE_TOOLBARS | |
8989 if (position == OVER_TOOLBAR) | |
8990 { | |
8991 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord); | |
8992 *obj2 = Qnil; | |
8993 *w = 0; | |
8994 UPDATE_CACHE_RETURN; | |
8995 } | |
8996 #endif /* HAVE_TOOLBARS */ | |
8997 | |
8998 /* We still have to return the window the pointer is next to and its | |
8999 relative y position even if it is outside the x boundary. */ | |
9000 if (x_coord < frm_left) | |
9001 x_coord = frm_left; | |
9002 else if (x_coord > frm_right) | |
9003 x_coord = frm_right; | |
9004 | |
9005 /* Same in reverse. */ | |
9006 if (y_coord < frm_top) | |
9007 y_coord = frm_top; | |
9008 else if (y_coord > frm_bottom) | |
9009 y_coord = frm_bottom; | |
9010 | |
9011 /* Find what window the given coordinates are actually in. */ | |
9012 window = f->root_window; | |
9013 *w = find_window_by_pixel_pos (x_coord, y_coord, window); | |
9014 | |
9015 /* If we didn't find a window, we're done. */ | |
9016 if (!*w) | |
9017 { | |
9018 UPDATE_CACHE_RETURN; | |
9019 } | |
9020 else if (position != OVER_NOTHING) | |
9021 { | |
9022 *closest = 0; | |
9023 *modeline_closest = -1; | |
9024 | |
9025 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) | |
9026 { | |
9027 *w = 0; | |
9028 UPDATE_CACHE_RETURN; | |
9029 } | |
9030 } | |
9031 | |
9032 /* Check if the window is a minibuffer but isn't active. */ | |
9033 if (MINI_WINDOW_P (*w) && !minibuf_level) | |
9034 { | |
9035 /* Must reset the window value since some callers will ignore | |
4187 | 9036 the return value if it is set. */ |
428 | 9037 *w = 0; |
9038 UPDATE_CACHE_RETURN; | |
9039 } | |
9040 | |
9041 /* See if the point is over window vertical divider */ | |
9042 if (window_needs_vertical_divider (*w)) | |
9043 { | |
9044 int div_x_high = WINDOW_RIGHT (*w); | |
9045 int div_x_low = div_x_high - window_divider_width (*w); | |
9046 int div_y_high = WINDOW_BOTTOM (*w); | |
9047 int div_y_low = WINDOW_TOP (*w); | |
9048 | |
9049 if (div_x_low < x_coord && x_coord <= div_x_high && | |
9050 div_y_low < y_coord && y_coord <= div_y_high) | |
9051 { | |
9052 low_x_coord = div_x_low; | |
9053 high_x_coord = div_x_high; | |
9054 low_y_coord = div_y_low; | |
9055 high_y_coord = div_y_high; | |
9056 position = OVER_V_DIVIDER; | |
9057 UPDATE_CACHE_RETURN; | |
9058 } | |
9059 } | |
9060 | |
9061 dla = window_display_lines (*w, CURRENT_DISP); | |
9062 | |
9063 for (*row = 0; *row < Dynarr_length (dla); (*row)++) | |
9064 { | |
9065 int really_over_nothing = 0; | |
9066 struct display_line *dl = Dynarr_atp (dla, *row); | |
9067 | |
9068 if ((int) (dl->ypos - dl->ascent) <= y_coord | |
9069 && y_coord <= (int) (dl->ypos + dl->descent)) | |
9070 { | |
9071 int check_margin_glyphs = 0; | |
9072 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
9073 struct rune *rb = 0; | |
9074 | |
9075 if (x_coord < dl->bounds.left_white | |
9076 || x_coord >= dl->bounds.right_white) | |
9077 check_margin_glyphs = 1; | |
9078 | |
9079 low_y_coord = dl->ypos - dl->ascent; | |
9080 high_y_coord = dl->ypos + dl->descent + 1; | |
9081 | |
9082 if (position == OVER_BORDER | |
9083 || position == OVER_OUTSIDE | |
9084 || check_margin_glyphs) | |
9085 { | |
9086 int x_check, left_bound; | |
9087 | |
9088 if (check_margin_glyphs) | |
9089 { | |
9090 x_check = x_coord; | |
9091 left_bound = dl->bounds.left_white; | |
9092 } | |
9093 else | |
9094 { | |
9095 x_check = high_x_coord; | |
9096 left_bound = frm_left; | |
9097 } | |
9098 | |
9099 if (Dynarr_length (db->runes)) | |
9100 { | |
9101 if (x_check <= left_bound) | |
9102 { | |
9103 if (dl->modeline) | |
4967 | 9104 *modeline_closest = Dynarr_begin (db->runes)->charpos; |
428 | 9105 else |
4967 | 9106 *closest = Dynarr_begin (db->runes)->charpos; |
428 | 9107 } |
9108 else | |
9109 { | |
9110 if (dl->modeline) | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9111 *modeline_closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9112 else |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9113 *closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9114 } |
9115 | |
9116 if (dl->modeline) | |
9117 *modeline_closest += dl->offset; | |
9118 else | |
9119 *closest += dl->offset; | |
9120 } | |
9121 else | |
9122 { | |
9123 /* #### What should be here. */ | |
9124 if (dl->modeline) | |
9125 *modeline_closest = 0; | |
9126 else | |
9127 *closest = 0; | |
9128 } | |
9129 | |
9130 if (check_margin_glyphs) | |
9131 { | |
9132 if (x_coord < dl->bounds.left_in | |
9133 || x_coord >= dl->bounds.right_in) | |
9134 { | |
9135 /* If we are over the outside margins then we | |
4187 | 9136 know the loop over the text block isn't going |
9137 to accomplish anything. So we go ahead and | |
9138 set what information we can right here and | |
9139 return. */ | |
428 | 9140 (*row)--; |
9141 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9142 get_position_object (dl, obj1, obj2, x_coord, | |
9143 &low_x_coord, &high_x_coord); | |
9144 | |
9145 UPDATE_CACHE_RETURN; | |
9146 } | |
9147 } | |
9148 else | |
9149 UPDATE_CACHE_RETURN; | |
9150 } | |
9151 | |
9152 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++) | |
9153 { | |
9154 int past_end = (*col == Dynarr_length (db->runes)); | |
9155 | |
9156 if (!past_end) | |
9157 rb = Dynarr_atp (db->runes, *col); | |
9158 | |
9159 if (past_end || | |
9160 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width)) | |
9161 { | |
9162 if (past_end) | |
9163 { | |
9164 (*col)--; | |
9165 rb = Dynarr_atp (db->runes, *col); | |
9166 } | |
9167 | |
826 | 9168 *charpos = rb->charpos + dl->offset; |
428 | 9169 low_x_coord = rb->xpos; |
9170 high_x_coord = rb->xpos + rb->width; | |
9171 | |
9172 if (rb->type == RUNE_DGLYPH) | |
9173 { | |
9174 int elt = *col + 1; | |
9175 | |
9176 /* Find the first character after the glyph. */ | |
9177 while (elt < Dynarr_length (db->runes)) | |
9178 { | |
9179 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH) | |
9180 { | |
9181 if (dl->modeline) | |
9182 *modeline_closest = | |
826 | 9183 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9184 dl->offset); |
9185 else | |
9186 *closest = | |
826 | 9187 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9188 dl->offset); |
9189 break; | |
9190 } | |
9191 | |
9192 elt++; | |
9193 } | |
9194 | |
9195 /* In this case we failed to find a non-glyph | |
4187 | 9196 character so we return the last position |
9197 displayed on the line. */ | |
428 | 9198 if (elt == Dynarr_length (db->runes)) |
9199 { | |
9200 if (dl->modeline) | |
826 | 9201 *modeline_closest = dl->end_charpos + dl->offset; |
428 | 9202 else |
826 | 9203 *closest = dl->end_charpos + dl->offset; |
428 | 9204 really_over_nothing = 1; |
9205 } | |
9206 } | |
9207 else | |
9208 { | |
9209 if (dl->modeline) | |
826 | 9210 *modeline_closest = rb->charpos + dl->offset; |
428 | 9211 else |
826 | 9212 *closest = rb->charpos + dl->offset; |
428 | 9213 } |
9214 | |
9215 if (dl->modeline) | |
9216 { | |
9217 *row = window_displayed_height (*w); | |
9218 | |
9219 if (position == OVER_NOTHING) | |
9220 position = OVER_MODELINE; | |
9221 | |
9222 if (rb->type == RUNE_DGLYPH) | |
9223 { | |
9224 *obj1 = rb->object.dglyph.glyph; | |
9225 *obj2 = rb->object.dglyph.extent; | |
9226 } | |
9227 else if (rb->type == RUNE_CHAR) | |
9228 { | |
9229 *obj1 = Qnil; | |
9230 *obj2 = Qnil; | |
9231 } | |
9232 else | |
9233 { | |
9234 *obj1 = Qnil; | |
9235 *obj2 = Qnil; | |
9236 } | |
9237 | |
9238 UPDATE_CACHE_RETURN; | |
9239 } | |
9240 else if (past_end | |
9241 || (rb->type == RUNE_CHAR | |
9242 && rb->object.chr.ch == '\n')) | |
9243 { | |
9244 (*row)--; | |
9245 /* At this point we may have glyphs in the right | |
4187 | 9246 inside margin. */ |
428 | 9247 if (check_margin_glyphs) |
9248 get_position_object (dl, obj1, obj2, x_coord, | |
9249 &low_x_coord, &high_x_coord); | |
9250 UPDATE_CACHE_RETURN; | |
9251 } | |
9252 else | |
9253 { | |
9254 (*row)--; | |
9255 if (rb->type == RUNE_DGLYPH) | |
9256 { | |
9257 *obj1 = rb->object.dglyph.glyph; | |
9258 *obj2 = rb->object.dglyph.extent; | |
9259 } | |
9260 else if (rb->type == RUNE_CHAR) | |
9261 { | |
9262 *obj1 = Qnil; | |
9263 *obj2 = Qnil; | |
9264 } | |
9265 else | |
9266 { | |
9267 *obj1 = Qnil; | |
9268 *obj2 = Qnil; | |
9269 } | |
9270 | |
9271 *obj_x = x_coord - rb->xpos; | |
9272 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9273 | |
9274 /* At this point we may have glyphs in the left | |
4187 | 9275 inside margin. */ |
428 | 9276 if (check_margin_glyphs) |
9277 get_position_object (dl, obj1, obj2, x_coord, 0, 0); | |
9278 | |
9279 if (position == OVER_NOTHING && !really_over_nothing) | |
9280 position = OVER_TEXT; | |
9281 | |
9282 UPDATE_CACHE_RETURN; | |
9283 } | |
9284 } | |
9285 } | |
9286 } | |
9287 } | |
9288 | |
9289 *row = Dynarr_length (dla) - 1; | |
9290 if (FRAME_WIN_P (f)) | |
9291 { | |
9292 int bot_elt = Dynarr_length (dla) - 1; | |
9293 | |
9294 if (bot_elt >= 0) | |
9295 { | |
9296 struct display_line *dl = Dynarr_atp (dla, bot_elt); | |
9297 int adj_area = y_coord - (dl->ypos + dl->descent); | |
9298 Lisp_Object lwin; | |
9299 int defheight; | |
9300 | |
793 | 9301 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
|
9302 default_face_width_and_height (lwin, 0, &defheight); |
428 | 9303 |
9304 *row += (adj_area / defheight); | |
9305 } | |
9306 } | |
9307 | |
9308 /* #### This should be checked out some more to determine what | |
9309 should really be going on. */ | |
9310 if (!MARKERP ((*w)->start[CURRENT_DISP])) | |
9311 *closest = 0; | |
9312 else | |
442 | 9313 *closest = end_of_last_line_may_error (*w, |
428 | 9314 marker_position ((*w)->start[CURRENT_DISP])); |
9315 *col = 0; | |
9316 UPDATE_CACHE_RETURN; | |
9317 } | |
9318 #undef UPDATE_CACHE_RETURN | |
9319 | |
9320 | |
9321 /***************************************************************************/ | |
9322 /* */ | |
9323 /* Lisp functions */ | |
9324 /* */ | |
9325 /***************************************************************************/ | |
9326 | |
9327 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /* | |
9328 Ensure that all minibuffers are correctly showing the echo area. | |
9329 */ | |
9330 ()) | |
9331 { | |
9332 Lisp_Object devcons, concons; | |
9333 | |
1318 | 9334 if (in_display) |
9335 return Qnil; | |
9336 | |
428 | 9337 DEVICE_LOOP_NO_BREAK (devcons, concons) |
9338 { | |
9339 struct device *d = XDEVICE (XCAR (devcons)); | |
9340 Lisp_Object frmcons; | |
9341 | |
1279 | 9342 if (DEVICE_STREAM_P (d)) |
9343 continue; | |
9344 | |
428 | 9345 DEVICE_FRAME_LOOP (frmcons, d) |
9346 { | |
9347 struct frame *f = XFRAME (XCAR (frmcons)); | |
853 | 9348 int depth; |
428 | 9349 |
9350 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) | |
9351 { | |
9352 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); | |
442 | 9353 |
9354 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
9355 | |
428 | 9356 /* |
9357 * If the frame size has changed, there may be random | |
9358 * chud on the screen left from previous messages | |
9359 * because redisplay_frame hasn't been called yet. | |
9360 * Clear the screen to get rid of the potential mess. | |
9361 */ | |
9362 if (f->echo_area_garbaged) | |
9363 { | |
442 | 9364 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 9365 f->echo_area_garbaged = 0; |
9366 } | |
853 | 9367 depth = enter_redisplay_critical_section (); |
428 | 9368 redisplay_window (window, 0); |
853 | 9369 exit_redisplay_critical_section (depth); |
442 | 9370 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 9371 } |
9372 } | |
9373 } | |
9374 | |
9375 return Qnil; | |
9376 } | |
9377 | |
9378 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /* | |
9379 Clear frame FRAME and output again what is supposed to appear on it. | |
9380 FRAME defaults to the selected frame if omitted. | |
9381 Normally, redisplay is preempted as normal if input arrives. However, | |
9382 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9383 input and is guaranteed to proceed to completion. | |
9384 */ | |
9385 (frame, no_preempt)) | |
9386 { | |
9387 struct frame *f = decode_frame (frame); | |
9388 int count = specpdl_depth (); | |
9389 | |
9390 if (!NILP (no_preempt)) | |
853 | 9391 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9392 |
9393 f->clear = 1; | |
9394 redisplay_frame (f, 1); | |
9395 | |
442 | 9396 /* See the comment in Fredisplay_frame. */ |
9397 RESET_CHANGED_SET_FLAGS; | |
9398 | |
771 | 9399 return unbind_to (count); |
428 | 9400 } |
9401 | |
9402 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* | |
9403 Ensure that FRAME's contents are correctly displayed. | |
9404 This differs from `redraw-frame' in that it only redraws what needs to | |
9405 be updated, as opposed to unconditionally clearing and redrawing | |
9406 the frame. | |
9407 FRAME defaults to the selected frame if omitted. | |
9408 Normally, redisplay is preempted as normal if input arrives. However, | |
9409 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9410 input and is guaranteed to proceed to completion. | |
9411 */ | |
9412 (frame, no_preempt)) | |
9413 { | |
9414 struct frame *f = decode_frame (frame); | |
9415 int count = specpdl_depth (); | |
9416 | |
9417 if (!NILP (no_preempt)) | |
853 | 9418 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9419 |
9420 redisplay_frame (f, 1); | |
9421 | |
442 | 9422 /* If we don't reset the global redisplay flags here, subsequent |
9423 changes to the display will not get registered by redisplay | |
9424 because it thinks it already has registered changes. If you | |
9425 really knew what you were doing you could confuse redisplay by | |
9426 calling Fredisplay_frame while updating another frame. We assume | |
9427 that if you know what you are doing you will not be that | |
9428 stupid. */ | |
9429 RESET_CHANGED_SET_FLAGS; | |
9430 | |
771 | 9431 return unbind_to (count); |
428 | 9432 } |
9433 | |
9434 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* | |
9435 Clear device DEVICE and output again what is supposed to appear on it. | |
9436 DEVICE defaults to the selected device if omitted. | |
9437 Normally, redisplay is preempted as normal if input arrives. However, | |
9438 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9439 input and is guaranteed to proceed to completion. | |
9440 */ | |
9441 (device, no_preempt)) | |
9442 { | |
9443 struct device *d = decode_device (device); | |
9444 Lisp_Object frmcons; | |
9445 int count = specpdl_depth (); | |
9446 | |
9447 if (!NILP (no_preempt)) | |
853 | 9448 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9449 |
9450 DEVICE_FRAME_LOOP (frmcons, d) | |
9451 { | |
9452 XFRAME (XCAR (frmcons))->clear = 1; | |
9453 } | |
440 | 9454 redisplay_device (d, 0); |
428 | 9455 |
442 | 9456 /* See the comment in Fredisplay_frame. */ |
9457 RESET_CHANGED_SET_FLAGS; | |
9458 | |
771 | 9459 return unbind_to (count); |
428 | 9460 } |
9461 | |
9462 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* | |
9463 Ensure that DEVICE's contents are correctly displayed. | |
9464 This differs from `redraw-device' in that it only redraws what needs to | |
9465 be updated, as opposed to unconditionally clearing and redrawing | |
9466 the device. | |
9467 DEVICE defaults to the selected device if omitted. | |
9468 Normally, redisplay is preempted as normal if input arrives. However, | |
9469 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9470 input and is guaranteed to proceed to completion. | |
853 | 9471 |
9472 Note: If you simply want everything redisplayed, the current idiom is | |
9473 `(sit-for 0)'. | |
428 | 9474 */ |
9475 (device, no_preempt)) | |
9476 { | |
9477 struct device *d = decode_device (device); | |
9478 int count = specpdl_depth (); | |
9479 | |
9480 if (!NILP (no_preempt)) | |
853 | 9481 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9482 |
440 | 9483 redisplay_device (d, 0); |
428 | 9484 |
442 | 9485 /* See the comment in Fredisplay_frame. */ |
9486 RESET_CHANGED_SET_FLAGS; | |
9487 | |
771 | 9488 return unbind_to (count); |
428 | 9489 } |
9490 | |
9491 /* Big lie. Big lie. This will force all modelines to be updated | |
9492 regardless if the all flag is set or not. It remains in existence | |
9493 solely for backwards compatibility. */ | |
9494 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /* | |
9495 Force the modeline of the current buffer to be redisplayed. | |
9496 With optional non-nil ALL, force redisplay of all modelines. | |
9497 */ | |
2286 | 9498 (UNUSED (all))) |
428 | 9499 { |
9500 MARK_MODELINE_CHANGED; | |
9501 return Qnil; | |
9502 } | |
9503 | |
9504 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /* | |
9505 Force an immediate update of the cursor on FRAME. | |
9506 FRAME defaults to the selected frame if omitted. | |
9507 */ | |
9508 (frame)) | |
9509 { | |
1279 | 9510 struct frame *f = decode_frame (frame); |
9511 | |
9512 if (!FRAME_STREAM_P (f)) | |
9513 redisplay_redraw_cursor (f, 1); | |
428 | 9514 return Qnil; |
9515 } | |
9516 | |
9517 | |
9518 /***************************************************************************/ | |
9519 /* */ | |
872 | 9520 /* Change flags */ |
428 | 9521 /* */ |
9522 /***************************************************************************/ | |
9523 | |
9524 static void | |
2286 | 9525 margin_width_changed_in_frame (Lisp_Object UNUSED (specifier), |
9526 struct frame *UNUSED (f), | |
9527 Lisp_Object UNUSED (oldval)) | |
428 | 9528 { |
9529 /* Nothing to be done? */ | |
9530 } | |
9531 | |
9532 int | |
2286 | 9533 redisplay_variable_changed (Lisp_Object UNUSED (sym), |
9534 Lisp_Object *UNUSED (val), | |
9535 Lisp_Object UNUSED (in_object), | |
9536 int UNUSED (flags)) | |
428 | 9537 { |
9538 /* #### clip_changed should really be renamed something like | |
9539 global_redisplay_change. */ | |
9540 MARK_CLIP_CHANGED; | |
9541 return 0; | |
9542 } | |
9543 | |
9544 /* This is called if the built-in glyphs have their properties | |
9545 changed. */ | |
9546 void | |
2286 | 9547 redisplay_glyph_changed (Lisp_Object UNUSED (glyph), |
9548 Lisp_Object UNUSED (property), Lisp_Object locale) | |
428 | 9549 { |
9550 if (WINDOWP (locale)) | |
9551 { | |
9552 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale)))); | |
9553 } | |
9554 else if (FRAMEP (locale)) | |
9555 { | |
9556 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale)); | |
9557 } | |
9558 else if (DEVICEP (locale)) | |
9559 { | |
9560 Lisp_Object frmcons; | |
9561 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale)) | |
9562 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9563 } | |
9564 else if (CONSOLEP (locale)) | |
9565 { | |
9566 Lisp_Object frmcons, devcons; | |
9567 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale)) | |
9568 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9569 } | |
9570 else /* global or buffer */ | |
9571 { | |
9572 Lisp_Object frmcons, devcons, concons; | |
9573 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
9574 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9575 } | |
9576 } | |
9577 | |
9578 static void | |
2286 | 9579 text_cursor_visible_p_changed (Lisp_Object UNUSED (specifier), |
9580 struct window *w, Lisp_Object UNUSED (oldval)) | |
428 | 9581 { |
9582 if (XFRAME (w->frame)->init_finished) | |
9583 Fforce_cursor_redisplay (w->frame); | |
9584 } | |
9585 | |
872 | 9586 void |
9587 mark_buffers_changed (void) | |
9588 { | |
9589 MARK_TYPE_CHANGED (buffers); | |
9590 } | |
9591 | |
9592 void | |
9593 mark_clip_changed (void) | |
9594 { | |
9595 MARK_TYPE_CHANGED (clip); | |
9596 } | |
9597 | |
9598 void | |
9599 mark_extents_changed (void) | |
9600 { | |
9601 MARK_TYPE_CHANGED (extents); | |
9602 } | |
9603 | |
9604 void | |
9605 mark_icon_changed (void) | |
9606 { | |
9607 MARK_TYPE_CHANGED (icon); | |
9608 } | |
9609 | |
9610 void | |
9611 mark_menubar_changed (void) | |
9612 { | |
9613 MARK_TYPE_CHANGED (menubar); | |
9614 } | |
9615 | |
9616 void | |
9617 mark_modeline_changed (void) | |
9618 { | |
9619 MARK_TYPE_CHANGED (modeline); | |
9620 } | |
9621 | |
9622 void | |
9623 mark_point_changed (void) | |
9624 { | |
9625 MARK_TYPE_CHANGED (point); | |
9626 } | |
9627 | |
9628 void | |
9629 mark_toolbar_changed (void) | |
9630 { | |
9631 MARK_TYPE_CHANGED (toolbar); | |
9632 } | |
9633 | |
9634 void | |
9635 mark_gutter_changed (void) | |
9636 { | |
9637 MARK_TYPE_CHANGED (gutter); | |
9638 } | |
9639 | |
9640 void | |
9641 mark_glyphs_changed (void) | |
9642 { | |
9643 MARK_TYPE_CHANGED (glyphs); | |
9644 } | |
9645 | |
9646 void | |
9647 mark_subwindows_changed (void) | |
9648 { | |
9649 MARK_TYPE_CHANGED (subwindows); | |
9650 } | |
9651 | |
9652 void | |
9653 mark_subwindows_state_changed (void) | |
9654 { | |
9655 MARK_TYPE_CHANGED (subwindows_state); | |
9656 } | |
9657 | |
428 | 9658 #ifdef MEMORY_USAGE_STATS |
9659 | |
9660 | |
9661 /***************************************************************************/ | |
9662 /* */ | |
9663 /* memory usage computation */ | |
9664 /* */ | |
9665 /***************************************************************************/ | |
9666 | |
9667 static int | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9668 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
|
9669 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9670 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9671 } |
9672 | |
9673 static int | |
9674 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
|
9675 struct usage_stats *ustats) |
428 | 9676 { |
9677 int total, i; | |
9678 | |
9679 if (!dyn) | |
9680 return 0; | |
9681 | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9682 total = Dynarr_memory_usage (dyn, ustats); |
428 | 9683 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
|
9684 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ustats); |
428 | 9685 |
9686 return total; | |
9687 } | |
9688 | |
9689 static int | |
9690 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
|
9691 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
|
9692 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9693 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9694 } |
9695 | |
9696 int | |
9697 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
|
9698 struct usage_stats *ustats) |
428 | 9699 { |
9700 int total, i; | |
9701 | |
9702 if (!dyn) | |
9703 return 0; | |
9704 | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9705 total = Dynarr_memory_usage (dyn, ustats); |
428 | 9706 for (i = 0; i < Dynarr_largest (dyn); i++) |
9707 { | |
9708 struct display_line *dl = &Dynarr_at (dyn, i); | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9709 total += compute_display_block_dynarr_usage(dl->display_blocks, ustats); |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9710 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
|
9711 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ustats); |
428 | 9712 } |
9713 | |
9714 return total; | |
9715 } | |
9716 | |
9717 int | |
9718 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
|
9719 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
|
9720 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9721 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9722 } |
9723 | |
9724 #endif /* MEMORY_USAGE_STATS */ | |
9725 | |
1204 | 9726 #ifdef ERROR_CHECK_DISPLAY |
9727 | |
800 | 9728 static int |
2286 | 9729 sledgehammer_check_redisplay_structs_1 (struct window *w, |
9730 void *UNUSED (closure)) | |
800 | 9731 { |
9732 int i, j; | |
9733 display_line_dynarr *dl; | |
9734 | |
9735 dl = window_display_lines (w, CURRENT_DISP); | |
4187 | 9736 |
800 | 9737 for (i = 0; i < Dynarr_largest (dl); i++) |
9738 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9739 assert (Dynarr_atp (dl, i)->display_blocks != | |
9740 Dynarr_atp (dl, j)->display_blocks); | |
9741 | |
9742 dl = window_display_lines (w, DESIRED_DISP); | |
9743 | |
9744 for (i = 0; i < Dynarr_largest (dl); i++) | |
9745 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9746 assert (Dynarr_atp (dl, i)->display_blocks != | |
9747 Dynarr_atp (dl, j)->display_blocks); | |
9748 | |
9749 return 0; | |
9750 } | |
9751 | |
9752 static void | |
9753 sledgehammer_check_redisplay_structs (void) | |
9754 { | |
9755 map_windows (0, sledgehammer_check_redisplay_structs_1, NULL); | |
9756 } | |
9757 | |
1204 | 9758 #endif /* ERROR_CHECK_DISPLAY */ |
9759 | |
428 | 9760 |
9761 /***************************************************************************/ | |
9762 /* */ | |
9763 /* initialization */ | |
9764 /* */ | |
9765 /***************************************************************************/ | |
9766 | |
9767 void | |
9768 init_redisplay (void) | |
9769 { | |
9770 disable_preemption = 0; | |
9771 preemption_count = 0; | |
9772 | |
9773 #ifndef PDUMP | |
9774 if (!initialized) | |
9775 #endif | |
9776 { | |
440 | 9777 if (!cmotion_display_lines) |
9778 cmotion_display_lines = Dynarr_new (display_line); | |
867 | 9779 if (!mode_spec_ibyte_string) |
9780 mode_spec_ibyte_string = Dynarr_new (Ibyte); | |
440 | 9781 if (!formatted_string_extent_dynarr) |
9782 formatted_string_extent_dynarr = Dynarr_new (EXTENT); | |
9783 if (!formatted_string_extent_start_dynarr) | |
9784 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); | |
9785 if (!formatted_string_extent_end_dynarr) | |
9786 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); | |
9787 if (!internal_cache) | |
9788 internal_cache = Dynarr_new (line_start_cache); | |
428 | 9789 } |
9790 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9791 if (!initialized) |
428 | 9792 return; |
9793 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9794 if (noninteractive) |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9795 { |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9796 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
|
9797 return; |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9798 } |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9799 |
428 | 9800 /* If the user wants to use a window system, we shouldn't bother |
9801 initializing the terminal. This is especially important when the | |
9802 terminal is so dumb that emacs gives up before and doesn't bother | |
9803 using the window system. | |
9804 | |
9805 If the DISPLAY environment variable is set, try to use X, and die | |
9806 with an error message if that doesn't work. */ | |
9807 | |
9808 #ifdef HAVE_X_WINDOWS | |
9809 if (!strcmp (display_use, "x")) | |
9810 { | |
9811 /* Some stuff checks this way early. */ | |
9812 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
|
9813 Vinitial_device_type = Qx; |
428 | 9814 return; |
9815 } | |
9816 #endif /* HAVE_X_WINDOWS */ | |
9817 | |
462 | 9818 #ifdef HAVE_GTK |
9819 if (!strcmp (display_use, "gtk")) | |
9820 { | |
9821 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
|
9822 Vinitial_device_type = Qgtk; |
462 | 9823 return; |
9824 } | |
9825 #endif | |
9826 | |
428 | 9827 #ifdef HAVE_MS_WINDOWS |
9828 if (!strcmp (display_use, "mswindows")) | |
9829 { | |
9830 /* Some stuff checks this way early. */ | |
9831 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
|
9832 Vinitial_device_type = Qmswindows; |
428 | 9833 return; |
9834 } | |
9835 #endif /* HAVE_MS_WINDOWS */ | |
9836 | |
9837 #ifdef HAVE_TTY | |
9838 /* If no window system has been specified, try to use the terminal. */ | |
9839 if (!isatty (0)) | |
9840 { | |
9841 stderr_out ("XEmacs: standard input is not a tty\n"); | |
9842 exit (1); | |
9843 } | |
9844 | |
9845 /* Look at the TERM variable */ | |
771 | 9846 if (!egetenv ("TERM")) |
428 | 9847 { |
9848 stderr_out ("Please set the environment variable TERM; see tset(1).\n"); | |
9849 exit (1); | |
9850 } | |
9851 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9852 Vinitial_device_type = Qtty; |
428 | 9853 return; |
9854 #else /* not HAVE_TTY */ | |
9855 /* No DISPLAY specified, and no TTY support. */ | |
9856 stderr_out ("XEmacs: Cannot open display.\n\ | |
9857 Please set the environmental variable DISPLAY to an appropriate value.\n"); | |
9858 exit (1); | |
9859 #endif | |
9860 /* Unreached. */ | |
9861 } | |
9862 | |
9863 void | |
9864 syms_of_redisplay (void) | |
9865 { | |
563 | 9866 DEFSYMBOL (Qcursor_in_echo_area); |
9867 DEFSYMBOL (Qdisplay_warning_buffer); | |
9868 DEFSYMBOL (Qbar_cursor); | |
9869 DEFSYMBOL (Qtop_bottom); | |
9870 DEFSYMBOL (Qbuffer_list_changed_hook); | |
428 | 9871 |
9872 DEFSUBR (Fredisplay_echo_area); | |
9873 DEFSUBR (Fredraw_frame); | |
9874 DEFSUBR (Fredisplay_frame); | |
9875 DEFSUBR (Fredraw_device); | |
9876 DEFSUBR (Fredisplay_device); | |
9877 DEFSUBR (Fredraw_modeline); | |
9878 DEFSUBR (Fforce_cursor_redisplay); | |
9879 } | |
9880 | |
9881 void | |
9882 vars_of_redisplay (void) | |
9883 { | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
9884 QSin_redisplay = build_defer_string ("(in redisplay)"); |
1292 | 9885 staticpro (&QSin_redisplay); |
428 | 9886 |
1318 | 9887 Vpost_redisplay_actions = Qnil; |
9888 staticpro (&Vpost_redisplay_actions); | |
9889 | |
428 | 9890 #if 0 |
9891 staticpro (&last_arrow_position); | |
9892 staticpro (&last_arrow_string); | |
9893 last_arrow_position = Qnil; | |
9894 last_arrow_string = Qnil; | |
9895 #endif /* 0 */ | |
9896 | |
9897 /* #### Probably temporary */ | |
9898 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* | |
9899 \(Temporary) Setting this will impact the performance of the internal | |
9900 line start cache. | |
9901 */ ); | |
9902 cache_adjustment = 2; | |
9903 | |
1268 | 9904 DEFVAR_INT ("maximum-preempts", &max_preempts /* |
9905 Maximum number of times redisplay can be preempted by user input. | |
9906 */ ); | |
9907 max_preempts = INIT_MAX_PREEMPTS; | |
9908 | |
428 | 9909 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /* |
9910 Minimum pixel height for clipped bottom display line. | |
9911 A clipped line shorter than this won't be displayed. | |
9912 */ , | |
9913 redisplay_variable_changed); | |
9914 vertical_clip = 5; | |
9915 | |
9916 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /* | |
9917 Minimum visible area for clipped glyphs at right boundary. | |
9918 Clipped glyphs shorter than this won't be displayed. | |
9919 Only pixmap glyph instances are currently allowed to be clipped. | |
9920 */ , | |
9921 redisplay_variable_changed); | |
9922 horizontal_clip = 5; | |
9923 | |
9924 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /* | |
9925 String displayed by modeline-format's "%m" specification. | |
9926 */ ); | |
9927 Vglobal_mode_string = Qnil; | |
9928 | |
9929 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /* | |
9930 Marker for where to display an arrow on top of the buffer text. | |
9931 This must be the beginning of a line in order to work. | |
9932 See also `overlay-arrow-string'. | |
9933 */ , | |
9934 redisplay_variable_changed); | |
9935 Voverlay_arrow_position = Qnil; | |
9936 | |
9937 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* | |
442 | 9938 String or glyph to display as an arrow. See also `overlay-arrow-position'. |
444 | 9939 \(Note that despite the name of this variable, it can be set to a glyph as |
442 | 9940 well as a string.) |
428 | 9941 */ , |
9942 redisplay_variable_changed); | |
9943 Voverlay_arrow_string = Qnil; | |
9944 | |
9945 DEFVAR_INT ("scroll-step", &scroll_step /* | |
9946 *The number of lines to try scrolling a window by when point moves out. | |
9947 If that fails to bring point back on frame, point is centered instead. | |
9948 If this is zero, point is always centered after it moves off screen. | |
9949 */ ); | |
9950 scroll_step = 0; | |
9951 | |
9952 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /* | |
9953 *Scroll up to this many lines, to bring point back on screen. | |
9954 */ ); | |
9955 scroll_conservatively = 0; | |
9956 | |
9957 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows", | |
9958 &truncate_partial_width_windows /* | |
9959 *Non-nil means truncate lines in all windows less than full frame wide. | |
9960 */ , | |
9961 redisplay_variable_changed); | |
9962 truncate_partial_width_windows = 1; | |
9963 | |
442 | 9964 DEFVAR_LISP ("visible-bell", &Vvisible_bell /* |
9965 *Non-nil substitutes a visual signal for the audible bell. | |
9966 | |
9967 Default behavior is to flash the whole screen. On some platforms, | |
9968 special effects are available using the following values: | |
9969 | |
3025 | 9970 `display' Flash the whole screen (ie, the default behavior). |
9971 `top-bottom' Flash only the top and bottom lines of the selected frame. | |
442 | 9972 |
9973 When effects are unavailable on a platform, the visual bell is the | |
9974 default, whole screen. (Currently only X supports any special effects.) | |
428 | 9975 */ ); |
442 | 9976 Vvisible_bell = Qnil; |
428 | 9977 |
9978 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* | |
9979 *Non-nil means no need to redraw entire frame after suspending. | |
9980 A non-nil value is useful if the terminal can automatically preserve | |
9981 Emacs's frame display when you reenter Emacs. | |
9982 It is up to you to set this variable if your terminal can do that. | |
9983 */ ); | |
9984 no_redraw_on_reenter = 0; | |
9985 | |
9986 DEFVAR_LISP ("window-system", &Vwindow_system /* | |
9987 A symbol naming the window-system under which Emacs is running, | |
9988 such as `x', or nil if emacs is running on an ordinary terminal. | |
9989 | |
9990 Do not use this variable, except for GNU Emacs compatibility, as it | |
9991 gives wrong values in a multi-device environment. Use `console-type' | |
9992 instead. | |
9993 */ ); | |
9994 Vwindow_system = Qnil; | |
9995 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9996 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
|
9997 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
|
9998 |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9999 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
|
10000 to Lisp what type the initial device to be created should be. |
428 | 10001 */ ); |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10002 Vinitial_device_type = Qnil; |
428 | 10003 |
10004 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* | |
10005 Non-nil means put cursor in minibuffer, at end of any message there. | |
10006 */ ); | |
10007 cursor_in_echo_area = 0; | |
10008 | |
10009 /* #### Shouldn't this be generalized as follows: | |
10010 | |
10011 if nil, use block cursor. | |
10012 if a number, use a bar cursor of that width. | |
10013 Otherwise, use a 1-pixel bar cursor. | |
10014 | |
10015 #### Or better yet, this variable should be trashed entirely | |
10016 (use a Lisp-magic variable to maintain compatibility) | |
10017 and a specifier `cursor-shape' added, which allows a block | |
10018 cursor, a bar cursor, a flashing block or bar cursor, | |
10019 maybe a caret cursor, etc. */ | |
10020 | |
10021 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /* | |
448 | 10022 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. |
428 | 10023 */ ); |
10024 Vbar_cursor = Qnil; | |
10025 | |
442 | 10026 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* |
10027 Function or functions to call when a frame's buffer list has changed. | |
10028 This is called during redisplay, before redisplaying each frame. | |
10029 Functions on this hook are called with one argument, the frame. | |
10030 */ ); | |
10031 Vbuffer_list_changed_hook = Qnil; | |
10032 | |
428 | 10033 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* |
10034 Bump this to tell the C code to call `display-warning-buffer' | |
10035 at next redisplay. You should not normally change this; the function | |
10036 `display-warning' automatically does this at appropriate times. | |
10037 */ ); | |
10038 display_warning_tick = 0; | |
10039 | |
10040 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /* | |
10041 Non-nil means inhibit display of warning messages. | |
10042 You should *bind* this, not set it. Any pending warning messages | |
10043 will be displayed when the binding no longer applies. | |
10044 */ ); | |
10045 /* reset to 0 by startup.el after the splash screen has displayed. | |
10046 This way, the warnings don't obliterate the splash screen. */ | |
10047 inhibit_warning_display = 1; | |
10048 | |
10049 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /* | |
10050 *Non-nil means column display number starts at 1. | |
10051 */ ); | |
10052 column_number_start_at_one = 0; | |
10053 } | |
10054 | |
10055 void | |
10056 specifier_vars_of_redisplay (void) | |
10057 { | |
10058 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /* | |
10059 *Width of left margin. | |
10060 This is a specifier; use `set-specifier' to change it. | |
10061 */ ); | |
10062 Vleft_margin_width = Fmake_specifier (Qnatnum); | |
10063 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10064 set_specifier_caching (Vleft_margin_width, | |
438 | 10065 offsetof (struct window, left_margin_width), |
428 | 10066 some_window_value_changed, |
438 | 10067 offsetof (struct frame, left_margin_width), |
444 | 10068 margin_width_changed_in_frame, 0); |
428 | 10069 |
10070 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* | |
10071 *Width of right margin. | |
10072 This is a specifier; use `set-specifier' to change it. | |
10073 */ ); | |
10074 Vright_margin_width = Fmake_specifier (Qnatnum); | |
10075 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10076 set_specifier_caching (Vright_margin_width, | |
438 | 10077 offsetof (struct window, right_margin_width), |
428 | 10078 some_window_value_changed, |
438 | 10079 offsetof (struct frame, right_margin_width), |
444 | 10080 margin_width_changed_in_frame, 0); |
428 | 10081 |
10082 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* | |
10083 *Minimum ascent height of lines. | |
10084 This is a specifier; use `set-specifier' to change it. | |
10085 */ ); | |
10086 Vminimum_line_ascent = Fmake_specifier (Qnatnum); | |
10087 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); | |
10088 set_specifier_caching (Vminimum_line_ascent, | |
438 | 10089 offsetof (struct window, minimum_line_ascent), |
428 | 10090 some_window_value_changed, |
444 | 10091 0, 0, 0); |
428 | 10092 |
10093 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* | |
10094 *Minimum descent height of lines. | |
10095 This is a specifier; use `set-specifier' to change it. | |
10096 */ ); | |
10097 Vminimum_line_descent = Fmake_specifier (Qnatnum); | |
10098 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); | |
10099 set_specifier_caching (Vminimum_line_descent, | |
438 | 10100 offsetof (struct window, minimum_line_descent), |
428 | 10101 some_window_value_changed, |
444 | 10102 0, 0, 0); |
428 | 10103 |
10104 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* | |
10105 *Non-nil means use the left outside margin as extra whitespace when | |
3025 | 10106 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10107 This is a specifier; use `set-specifier' to change it. |
10108 */ ); | |
10109 Vuse_left_overflow = Fmake_specifier (Qboolean); | |
10110 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); | |
10111 set_specifier_caching (Vuse_left_overflow, | |
438 | 10112 offsetof (struct window, use_left_overflow), |
428 | 10113 some_window_value_changed, |
444 | 10114 0, 0, 0); |
428 | 10115 |
10116 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* | |
10117 *Non-nil means use the right outside margin as extra whitespace when | |
3025 | 10118 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10119 This is a specifier; use `set-specifier' to change it. |
10120 */ ); | |
10121 Vuse_right_overflow = Fmake_specifier (Qboolean); | |
10122 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); | |
10123 set_specifier_caching (Vuse_right_overflow, | |
438 | 10124 offsetof (struct window, use_right_overflow), |
428 | 10125 some_window_value_changed, |
444 | 10126 0, 0, 0); |
428 | 10127 |
10128 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* | |
10129 *Non-nil means the text cursor is visible (this is usually the case). | |
10130 This is a specifier; use `set-specifier' to change it. | |
10131 */ ); | |
10132 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); | |
10133 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); | |
10134 set_specifier_caching (Vtext_cursor_visible_p, | |
438 | 10135 offsetof (struct window, text_cursor_visible_p), |
428 | 10136 text_cursor_visible_p_changed, |
444 | 10137 0, 0, 0); |
428 | 10138 |
10139 } |