Mercurial > hg > xemacs-beta
annotate src/redisplay.c @ 5518:3cc7470ea71c
gnuclient: if TMPDIR was set and connect failed, try again with /tmp
2011-06-03 Aidan Kehoe <kehoea@parhasard.net>
* gnuslib.c (connect_to_unix_server):
Retry with /tmp as a directory in which to search for Unix sockets
if an attempt to connect with some other directory failed (which
may be because gnuclient and gnuserv don't share an environment
value for TMPDIR, or because gnuserv was compiled with USE_TMPDIR
turned off).
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Fri, 03 Jun 2011 18:40:57 +0100 |
parents | 58e320bde005 |
children | 56144c8593a8 |
rev | line source |
---|---|
428 | 1 /* Display generation from window structure and buffer text. |
2 Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1995 Free Software Foundation, Inc. | |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
4 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2005, 2010 Ben Wing. |
428 | 5 Copyright (C) 1995 Sun Microsystems, Inc. |
6 Copyright (C) 1996 Chuck Thompson. | |
7 | |
8 This file is part of XEmacs. | |
9 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5198
diff
changeset
|
10 XEmacs is free software: you can redistribute it and/or modify it |
428 | 11 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5198
diff
changeset
|
12 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5198
diff
changeset
|
13 option) any later version. |
428 | 14 |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5198
diff
changeset
|
21 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 22 |
23 /* Synched up with: Not in FSF. */ | |
24 | |
25 /* Author: Chuck Thompson */ | |
26 | |
27 /* Fixed up by Ben Wing for Mule */ | |
28 | |
29 /* This file has been Mule-ized. */ | |
30 | |
31 /***************************************************************************** | |
32 The Golden Rules of Redisplay | |
33 | |
853 | 34 First: It Is Better To Be Correct Than Fast |
35 Second: Thou Shalt Use Due Caution When Running Elisp From Within Redisplay | |
36 Third: It Is Better To Be Fast Than Not To Be | |
428 | 37 ****************************************************************************/ |
38 | |
1318 | 39 /* Note: The second rule used to prohibit running Elisp from within |
40 redisplay, but that's not correct any more -- use | |
41 call*_trapping_problems() or call_with_suspended_errors() instead. | |
853 | 42 |
43 --ben | |
44 */ | |
45 | |
428 | 46 #include <config.h> |
47 #include "lisp.h" | |
48 | |
49 #include "buffer.h" | |
50 #include "commands.h" | |
51 #include "debug.h" | |
872 | 52 #include "device-impl.h" |
428 | 53 #include "elhash.h" |
853 | 54 #include "events.h" |
872 | 55 #include "extents-impl.h" |
428 | 56 #include "faces.h" |
872 | 57 #include "frame-impl.h" |
428 | 58 #include "glyphs.h" |
59 #include "gutter.h" | |
60 #include "insdel.h" | |
61 #include "menubar.h" | |
5176
8b2f75cecb89
rename objects* (.c, .h and .el files) to fontcolor*
Ben Wing <ben@xemacs.org>
parents:
5049
diff
changeset
|
62 #include "fontcolor-impl.h" |
1318 | 63 #include "opaque.h" |
428 | 64 #include "process.h" |
1292 | 65 #include "profile.h" |
428 | 66 #include "redisplay.h" |
67 #include "toolbar.h" | |
872 | 68 #include "window-impl.h" |
428 | 69 #include "line-number.h" |
70 #include "file-coding.h" | |
71 | |
442 | 72 #include "sysfile.h" |
73 | |
428 | 74 #ifdef HAVE_TTY |
75 #include "console-tty.h" | |
76 #endif /* HAVE_TTY */ | |
77 | |
78 /* Note: We have to be careful throughout this code to properly handle | |
867 | 79 and differentiate between Ibytes and Ichars. |
80 | |
81 Since strings are generally composed of Ibytes, I've taken the tack | |
82 that any contiguous set of Ibytes is called a "string", while | |
83 any contiguous set of Ichars is called an "array". */ | |
428 | 84 |
85 /* Return value to indicate a failure by an add_*_rune routine to add | |
86 a rune, but no propagation information needs to be returned. */ | |
87 #define ADD_FAILED (prop_block_dynarr *) 1 | |
88 | |
89 #define BEGIN_GLYPHS 0 | |
90 #define END_GLYPHS 1 | |
91 #define LEFT_GLYPHS 2 | |
92 #define RIGHT_GLYPHS 3 | |
93 | |
94 #define VERTICAL_CLIP(w, display) \ | |
442 | 95 ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \ |
428 | 96 ? INT_MAX \ |
442 | 97 : vertical_clip) |
428 | 98 |
99 /* The following structures are completely private to redisplay.c so | |
100 we put them here instead of in a header file, for modularity. */ | |
101 | |
826 | 102 /* NOTE: Bytexpos's not Charxpos's in this structure. */ |
428 | 103 |
104 typedef struct position_redisplay_data_type | |
105 { | |
106 /* This information is normally filled in by the create_*_block | |
107 routines and is used by the add_*_rune routines. */ | |
108 Lisp_Object window; | |
109 /* if we are working with strings rather than buffers we need a | |
110 handle to the string */ | |
111 Lisp_Object string; | |
112 struct device *d; | |
113 struct display_block *db; | |
114 struct display_line *dl; | |
867 | 115 Ichar ch; /* Character that is to be added. This is |
428 | 116 used to communicate this information to |
867 | 117 add_ichar_rune(). */ |
428 | 118 Lisp_Object last_charset; /* The charset of the previous character. |
119 Used to optimize some lookups -- we | |
120 only have to do some things when | |
121 the charset changes. */ | |
122 face_index last_findex; /* The face index of the previous character. | |
123 Needed to ensure the validity of the | |
124 last_charset optimization. */ | |
125 | |
126 int last_char_width; /* The width of the previous character. */ | |
127 int font_is_bogus; /* If true, it means we couldn't instantiate | |
128 the font for this charset, so we substitute | |
129 ~'s from the ASCII charset. */ | |
826 | 130 Bytexpos byte_charpos; /* Position of character we are processing. This |
131 is a Bytexpos, meaning it refers to bytes (not | |
132 chars) and can refer to either buffers (1-based) | |
133 or strings (0-based). We need to be careful | |
134 when doing anything that references the text in | |
135 the buffer or string. */ | |
136 Bytexpos byte_endpos; /* ????? Unknown, under-used. */ | |
428 | 137 int pixpos; |
138 int max_pixpos; | |
139 int blank_width; /* Width of the blank that is to be added. | |
140 This is used to communicate this information | |
141 to add_blank_rune(). | |
142 | |
143 This is also used rather cheesily to | |
144 communicate the width of the eol-cursor-size | |
145 blank that exists at the end of the line. | |
867 | 146 add_ichar_rune() is called cheesily with |
428 | 147 the non-printing char '\n', which is stuck |
148 in the output routines with its width being | |
149 BLANK_WIDTH. */ | |
826 | 150 Bytexpos byte_cursor_charpos; /* This stores the buffer position of the |
151 cursor. */ | |
428 | 152 unsigned int cursor_type :3; |
153 int cursor_x; /* rune block cursor is at */ | |
154 int start_col; /* Number of character columns (each column has | |
155 a width of the default char width) that still | |
156 need to be skipped. This is used for horizontal | |
157 scrolling, where a certain number of columns | |
158 (those off the left side of the screen) need | |
159 to be skipped before anything is displayed. */ | |
826 | 160 Bytexpos byte_start_col_enabled; |
428 | 161 int start_col_xoffset; /* Number of pixels that still need to |
4187 | 162 be skipped. This is used for |
163 horizontal scrolling of glyphs, where we want | |
164 to be able to scroll over part of the glyph. */ | |
428 | 165 |
166 int hscroll_glyph_width_adjust; /* how much the width of the hscroll | |
167 glyph differs from space_width (w). | |
168 0 if no hscroll glyph was used, | |
169 i.e. the window is not scrolled | |
170 horizontally. Used in tab | |
171 calculations. */ | |
172 | |
173 /* Information about the face the text should be displayed in and | |
174 any begin-glyphs and end-glyphs. */ | |
175 struct extent_fragment *ef; | |
176 face_index findex; | |
177 | |
819 | 178 /* The height of a pixmap may either be predetermined if the user has set a |
179 baseline value, or it may be dependent on whatever the line ascent and | |
180 descent values end up being, based just on font and pixmap-ascent | |
181 information. In the first case we can immediately update the values, thus | |
182 their inclusion here. In the last case we cannot determine the actual | |
183 contribution to the line height until we have finished laying out all text | |
184 on the line. Thus we propagate the max height of such pixmaps and do a | |
185 final calculation (in calculate_baseline()) after all text has been added | |
186 to the line. */ | |
428 | 187 int new_ascent; |
188 int new_descent; | |
189 int max_pixmap_height; | |
819 | 190 int need_baseline_computation; |
191 int end_glyph_width; /* Well, it is the kitchen sink after all ... */ | |
428 | 192 |
193 Lisp_Object result_str; /* String where we put the result of | |
194 generating a formatted string in the modeline. */ | |
195 int is_modeline; /* Non-zero if we're generating the modeline. */ | |
196 Charcount modeline_charpos; /* Number of chars used in result_str so far; | |
197 corresponds to bytepos. */ | |
198 Bytecount bytepos; /* Number of bytes used in result_str so far. | |
4187 | 199 We don't actually copy the bytes into result_str |
428 | 200 until the end because we don't know how big the |
201 string is going to be until then. */ | |
202 } pos_data; | |
203 | |
204 enum prop_type | |
205 { | |
206 PROP_STRING, | |
207 PROP_CHAR, | |
208 PROP_MINIBUF_PROMPT, | |
819 | 209 PROP_BLANK, |
210 PROP_GLYPH | |
428 | 211 }; |
212 | |
213 /* Data that should be propagated to the next line. Either a single | |
867 | 214 Ichar, a string of Ibyte's or a glyph. |
428 | 215 |
216 The actual data that is propagated ends up as a Dynarr of these | |
217 blocks. | |
218 | |
819 | 219 prop_blocks are used to indicate that data that was supposed to go |
220 on the previous line couldn't actually be displayed. Generally this | |
221 shouldn't happen if we are clipping the end of lines. If we are | |
222 wrapping then we need to display the propagation data before moving | |
223 on. Its questionable whether we should wrap or clip glyphs in this | |
224 instance. Most e-lisp relies on clipping so we preserve this | |
225 behavior. | |
226 | |
867 | 227 #### It's unclean that both Ichars and Ibytes are here. |
428 | 228 */ |
229 | |
230 typedef struct prop_block prop_block; | |
231 struct prop_block | |
232 { | |
233 enum prop_type type; | |
234 | |
235 union data | |
236 { | |
237 struct | |
238 { | |
867 | 239 Ibyte *str; |
428 | 240 Bytecount len; /* length of the string. */ |
241 } p_string; | |
242 | |
243 struct | |
244 { | |
867 | 245 Ichar ch; |
826 | 246 Bytebpos byte_cursor_charpos; /* NOTE: is in Bytebpos's */ |
428 | 247 unsigned int cursor_type :3; |
248 } p_char; | |
249 | |
250 struct | |
251 { | |
252 int width; | |
253 face_index findex; | |
254 } p_blank; | |
819 | 255 |
256 struct | |
257 { | |
258 /* Not used as yet, but could be used to wrap rather than clip glyphs. */ | |
4187 | 259 int width; |
819 | 260 Lisp_Object glyph; |
261 } p_glyph; | |
262 | |
428 | 263 } data; |
264 }; | |
265 | |
266 typedef struct | |
267 { | |
268 Dynarr_declare (prop_block); | |
269 } prop_block_dynarr; | |
270 | |
271 | |
272 static Charcount generate_fstring_runes (struct window *w, pos_data *data, | |
273 Charcount pos, Charcount min_pos, | |
274 Charcount max_pos, Lisp_Object elt, | |
275 int depth, int max_pixsize, | |
438 | 276 face_index findex, int type, |
277 Charcount *offset, | |
278 Lisp_Object cur_ext); | |
428 | 279 static prop_block_dynarr *add_glyph_rune (pos_data *data, |
280 struct glyph_block *gb, | |
281 int pos_type, int allow_cursor, | |
282 struct glyph_cachel *cachel); | |
665 | 283 static Bytebpos create_text_block (struct window *w, struct display_line *dl, |
826 | 284 Bytebpos byte_start_pos, |
285 prop_block_dynarr **prop, | |
286 int type); | |
428 | 287 static int create_overlay_glyph_block (struct window *w, |
288 struct display_line *dl); | |
289 static void create_left_glyph_block (struct window *w, | |
290 struct display_line *dl, | |
291 int overlay_width); | |
292 static void create_right_glyph_block (struct window *w, | |
293 struct display_line *dl); | |
294 static void redisplay_windows (Lisp_Object window, int skip_selected); | |
867 | 295 static void decode_mode_spec (struct window *w, Ichar spec, int type); |
428 | 296 static void free_display_line (struct display_line *dl); |
826 | 297 static void update_line_start_cache (struct window *w, Charbpos from, |
298 Charbpos to, Charbpos point, | |
299 int no_regen); | |
665 | 300 static int point_visible (struct window *w, Charbpos point, int type); |
819 | 301 static void calculate_yoffset (struct display_line *dl, |
4187 | 302 struct display_block *fixup); |
819 | 303 static void calculate_baseline (pos_data *data); |
428 | 304 |
1204 | 305 #ifdef ERROR_CHECK_DISPLAY |
800 | 306 static void sledgehammer_check_redisplay_structs (void); |
1204 | 307 #endif /* ERROR_CHECK_DISPLAY */ |
800 | 308 |
428 | 309 /* This used to be 10 but 30 seems to give much better performance. */ |
310 #define INIT_MAX_PREEMPTS 30 | |
1268 | 311 static Fixnum max_preempts; |
312 | |
313 #define QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION 4 | |
428 | 314 |
1318 | 315 /* Note that doing this can call Lisp. */ |
428 | 316 #define REDISPLAY_PREEMPTION_CHECK \ |
317 ((void) \ | |
318 (preempted = \ | |
319 (!disable_preemption && \ | |
320 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \ | |
4187 | 321 (!INTERACTIVE || \ |
1268 | 322 detect_input_pending (QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION))))) |
428 | 323 |
324 /* | |
325 * Redisplay global variables. | |
326 */ | |
327 | |
328 /* We need a third set of display structures for the cursor motion | |
329 routines. We used to just give each window a third set. However, | |
330 we always fully regenerate the structures when needed so there | |
331 isn't any reason we need more than a single set. */ | |
332 display_line_dynarr *cmotion_display_lines; | |
333 | |
334 /* We store the extents that we need to generate in a Dynarr and then | |
335 frob them all on at the end of generating the string. We do it | |
336 this way rather than adding them as we generate the string because | |
337 we don't store the text into the resulting string until we're done | |
338 (to avoid having to resize the string multiple times), and we don't | |
339 want to go around adding extents to a string when the extents might | |
340 stretch off the end of the string. */ | |
341 static EXTENT_dynarr *formatted_string_extent_dynarr; | |
342 static Bytecount_dynarr *formatted_string_extent_start_dynarr; | |
343 static Bytecount_dynarr *formatted_string_extent_end_dynarr; | |
344 | |
345 | |
346 /* #### probably temporary */ | |
458 | 347 Fixnum cache_adjustment; |
428 | 348 |
349 /* This holds a string representing the text corresponding to a single | |
350 modeline % spec. */ | |
867 | 351 static Ibyte_dynarr *mode_spec_ibyte_string; |
428 | 352 |
353 int in_display; /* 1 if in redisplay. */ | |
354 | |
1318 | 355 /* Whether we should delay size changes. Broken out of |
356 enter_redisplay_critical_section(). */ | |
357 int hold_frame_size_changes; | |
358 | |
428 | 359 int disable_preemption; /* Used for debugging redisplay and for |
360 force-redisplay. */ | |
361 | |
362 /* We only allow max_preempts preemptions before we force a redisplay. */ | |
363 static int preemption_count; | |
364 | |
365 /* Minimum pixel height of clipped bottom display line. */ | |
458 | 366 Fixnum vertical_clip; |
428 | 367 |
368 /* Minimum visible pixel width of clipped glyphs at right margin. */ | |
458 | 369 Fixnum horizontal_clip; |
428 | 370 |
371 /* Nonzero means reading single-character input with prompt | |
372 so put cursor on minibuffer after the prompt. */ | |
373 int cursor_in_echo_area; | |
374 Lisp_Object Qcursor_in_echo_area; | |
375 | |
376 /* Nonzero means truncate lines in all windows less wide than the frame */ | |
377 int truncate_partial_width_windows; | |
378 | |
379 /* non-nil if a buffer has changed since the last time redisplay completed */ | |
380 int buffers_changed; | |
381 int buffers_changed_set; | |
382 | |
383 /* non-nil if hscroll has changed somewhere or a buffer has been | |
384 narrowed or widened */ | |
385 int clip_changed; | |
386 int clip_changed_set; | |
387 | |
388 /* non-nil if any extent has changed since the last time redisplay completed */ | |
389 int extents_changed; | |
390 int extents_changed_set; | |
391 | |
392 /* non-nil if any face has changed since the last time redisplay completed */ | |
393 int faces_changed; | |
394 | |
395 /* Nonzero means some frames have been marked as garbaged */ | |
396 int frame_changed; | |
397 | |
398 /* non-zero if any of the builtin display glyphs (continuation, | |
399 hscroll, control-arrow, etc) is in need of updating | |
400 somewhere. */ | |
401 int glyphs_changed; | |
402 int glyphs_changed_set; | |
403 | |
442 | 404 /* non-zero if any subwindow has been deleted. */ |
428 | 405 int subwindows_changed; |
406 int subwindows_changed_set; | |
407 | |
408 /* non-zero if any displayed subwindow is in need of updating | |
409 somewhere. */ | |
410 int subwindows_state_changed; | |
411 int subwindows_state_changed_set; | |
412 | |
413 /* This variable is 1 if the icon has to be updated. | |
414 It is set to 1 when `frame-icon-glyph' changes. */ | |
415 int icon_changed; | |
416 int icon_changed_set; | |
417 | |
418 /* This variable is 1 if the menubar widget has to be updated. | |
419 It is set to 1 by set-menubar-dirty-flag and cleared when the widget | |
420 has been updated. */ | |
421 int menubar_changed; | |
422 int menubar_changed_set; | |
423 | |
424 /* true iff we should redraw the modelines on the next redisplay */ | |
425 int modeline_changed; | |
426 int modeline_changed_set; | |
427 | |
428 /* non-nil if point has changed in some buffer since the last time | |
429 redisplay completed */ | |
430 int point_changed; | |
431 int point_changed_set; | |
432 | |
433 /* non-nil if some frame has changed its size */ | |
434 int size_changed; | |
435 | |
436 /* non-nil if some device has signaled that it wants to change size */ | |
437 int asynch_device_change_pending; | |
438 | |
439 /* non-nil if any toolbar has changed */ | |
440 int toolbar_changed; | |
441 int toolbar_changed_set; | |
442 | |
905 | 443 /* Nonzero if some frame has changed the layout of internal elements |
444 (gutters or toolbars). */ | |
445 int frame_layout_changed; | |
446 | |
428 | 447 /* non-nil if any gutter has changed */ |
448 int gutter_changed; | |
449 int gutter_changed_set; | |
450 | |
451 /* non-nil if any window has changed since the last time redisplay completed */ | |
452 int windows_changed; | |
453 | |
454 /* non-nil if any frame's window structure has changed since the last | |
455 time redisplay completed */ | |
456 int windows_structure_changed; | |
457 | |
458 /* If non-nil, use vertical bar cursor. */ | |
459 Lisp_Object Vbar_cursor; | |
460 Lisp_Object Qbar_cursor; | |
461 | |
442 | 462 Lisp_Object Vvisible_bell; /* If true and the terminal will support it |
463 then the frame will flash instead of | |
464 beeping when an error occurs */ | |
428 | 465 |
466 /* Nonzero means no need to redraw the entire frame on resuming | |
467 a suspended Emacs. This is useful on terminals with multiple pages, | |
468 where one page is used for Emacs and another for all else. */ | |
469 int no_redraw_on_reenter; | |
470 | |
3360 | 471 Lisp_Object Vwindow_system; /* #### this variable is deprecated |
472 nil or a symbol naming the window system | |
428 | 473 under which emacs is running |
3360 | 474 (`x', `gtk', `mswindows', and `tty' are |
475 supported -- yes, TTYs are window systems | |
476 for this purpose. */ | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
477 Lisp_Object Vinitial_device_type; |
428 | 478 |
479 Lisp_Object Vglobal_mode_string; | |
480 | |
481 /* The number of lines scroll a window by when point leaves the window; if | |
482 it is <=0 then point is centered in the window */ | |
458 | 483 Fixnum scroll_step; |
428 | 484 |
485 /* Scroll up to this many lines, to bring point back on screen. */ | |
458 | 486 Fixnum scroll_conservatively; |
428 | 487 |
488 /* Marker for where to display an arrow on top of the buffer text. */ | |
489 Lisp_Object Voverlay_arrow_position; | |
490 /* String to display for the arrow. */ | |
491 Lisp_Object Voverlay_arrow_string; | |
492 | |
442 | 493 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook; |
494 | |
458 | 495 static Fixnum last_display_warning_tick; |
496 static Fixnum display_warning_tick; | |
428 | 497 Lisp_Object Qdisplay_warning_buffer; |
498 int inhibit_warning_display; | |
499 | |
500 Lisp_Object Vleft_margin_width, Vright_margin_width; | |
501 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; | |
502 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; | |
503 Lisp_Object Vtext_cursor_visible_p; | |
504 | |
1292 | 505 static Lisp_Object QSin_redisplay; |
506 | |
1318 | 507 static Lisp_Object Vpost_redisplay_actions; |
508 | |
428 | 509 int column_number_start_at_one; |
510 | |
442 | 511 Lisp_Object Qtop_bottom; |
512 | |
444 | 513 #define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset) |
428 | 514 |
1204 | 515 static const struct memory_description rune_dglyph_description_1[] = { |
516 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, glyph) }, | |
517 { XD_LISP_OBJECT, offsetof (struct rune_dglyph, extent) }, | |
518 { XD_END } | |
519 }; | |
520 | |
521 static const struct sized_memory_description rune_dglyph_description = { | |
522 sizeof (struct rune_dglyph), rune_dglyph_description_1 | |
523 }; | |
524 | |
525 static const struct memory_description rune_object_description_1[] = { | |
2551 | 526 { XD_BLOCK_ARRAY, RUNE_DGLYPH, 1, { &rune_dglyph_description } }, |
1204 | 527 { XD_END } |
528 }; | |
529 | |
530 static const struct sized_memory_description rune_object_description = { | |
531 0, rune_object_description_1 | |
532 }; | |
533 | |
534 static const struct memory_description rune_description_1[] = { | |
535 { XD_INT, offsetof (rune, type) }, | |
536 { XD_UNION, offsetof (rune, object), | |
2551 | 537 XD_INDIRECT (0, 0), { &rune_object_description } }, |
1204 | 538 { XD_END } |
539 }; | |
540 | |
541 static const struct sized_memory_description rune_description = { | |
542 sizeof (rune), | |
543 rune_description_1 | |
544 }; | |
545 | |
546 static const struct memory_description rune_dynarr_description_1[] = { | |
547 XD_DYNARR_DESC (rune_dynarr, &rune_description), | |
548 { XD_END } | |
549 }; | |
550 | |
551 static const struct sized_memory_description rune_dynarr_description = { | |
552 sizeof (rune_dynarr), | |
553 rune_dynarr_description_1 | |
554 }; | |
555 | |
556 static const struct memory_description display_block_description_1[] = { | |
2367 | 557 { XD_BLOCK_PTR, offsetof (display_block, runes), |
2551 | 558 1, { &rune_dynarr_description } }, |
1204 | 559 { XD_END } |
560 }; | |
561 | |
562 static const struct sized_memory_description display_block_description = { | |
563 sizeof (display_block), | |
564 display_block_description_1 | |
565 }; | |
566 | |
567 static const struct memory_description display_block_dynarr_description_1[] = { | |
568 XD_DYNARR_DESC (display_block_dynarr, &display_block_description), | |
569 { XD_END } | |
570 }; | |
571 | |
572 static const struct sized_memory_description display_block_dynarr_description = { | |
573 sizeof (display_block_dynarr), | |
574 display_block_dynarr_description_1 | |
575 }; | |
576 | |
577 static const struct memory_description glyph_block_description_1[] = { | |
578 { XD_LISP_OBJECT, offsetof (glyph_block, glyph) }, | |
579 { XD_LISP_OBJECT, offsetof (glyph_block, extent) }, | |
580 { XD_END } | |
581 }; | |
582 | |
583 static const struct sized_memory_description glyph_block_description = { | |
584 sizeof (glyph_block), | |
585 glyph_block_description_1 | |
586 }; | |
587 | |
588 static const struct memory_description glyph_block_dynarr_description_1[] = { | |
589 XD_DYNARR_DESC (glyph_block_dynarr, &glyph_block_description), | |
590 { XD_END } | |
591 }; | |
592 | |
593 static const struct sized_memory_description glyph_block_dynarr_description = { | |
594 sizeof (glyph_block_dynarr), | |
595 glyph_block_dynarr_description_1 | |
596 }; | |
597 | |
598 static const struct memory_description display_line_description_1[] = { | |
2367 | 599 { XD_BLOCK_PTR, offsetof (display_line, display_blocks), |
2551 | 600 1, { &display_block_dynarr_description } }, |
2367 | 601 { XD_BLOCK_PTR, offsetof (display_line, left_glyphs), |
2551 | 602 1, { &glyph_block_dynarr_description } }, |
2367 | 603 { XD_BLOCK_PTR, offsetof (display_line, right_glyphs), |
2551 | 604 1, { &glyph_block_dynarr_description } }, |
1204 | 605 { XD_END } |
606 }; | |
607 | |
608 static const struct sized_memory_description display_line_description = { | |
609 sizeof (display_line), | |
610 display_line_description_1 | |
611 }; | |
612 | |
613 static const struct memory_description display_line_dynarr_description_1[] = { | |
614 XD_DYNARR_DESC (display_line_dynarr, &display_line_description), | |
615 { XD_END } | |
616 }; | |
617 | |
618 const struct sized_memory_description display_line_dynarr_description = { | |
619 sizeof (display_line_dynarr), | |
620 display_line_dynarr_description_1 | |
621 }; | |
622 | |
428 | 623 |
624 /***************************************************************************/ | |
625 /* */ | |
626 /* low-level interfaces onto device routines */ | |
627 /* */ | |
628 /***************************************************************************/ | |
629 | |
630 static int | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
631 redisplay_window_text_width_ichar_string (struct window *w, int findex, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
632 Ichar *str, Charcount len) |
428 | 633 { |
634 unsigned char charsets[NUM_LEADING_BYTES]; | |
635 Lisp_Object window; | |
636 | |
867 | 637 find_charsets_in_ichar_string (charsets, str, len); |
793 | 638 window = wrap_window (w); |
428 | 639 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window, |
640 charsets); | |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
641 return DEVMETH (WINDOW_XDEVICE (w), |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
642 text_width, (w, WINDOW_FACE_CACHEL (w, findex), str, |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
643 len)); |
428 | 644 } |
645 | |
867 | 646 static Ichar_dynarr *rtw_ichar_dynarr; |
428 | 647 |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
648 static int |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
649 redisplay_window_text_width_string (struct window *w, int findex, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
650 Ibyte *nonreloc, Lisp_Object reloc, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
651 Bytecount offset, Bytecount len) |
428 | 652 { |
867 | 653 if (!rtw_ichar_dynarr) |
654 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
655 Dynarr_reset (rtw_ichar_dynarr); | |
428 | 656 |
657 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
658 if (STRINGP (reloc)) | |
659 nonreloc = XSTRING_DATA (reloc); | |
867 | 660 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
661 return redisplay_window_text_width_ichar_string |
4967 | 662 (w, findex, Dynarr_begin (rtw_ichar_dynarr), |
867 | 663 Dynarr_length (rtw_ichar_dynarr)); |
428 | 664 } |
665 | |
666 int | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
667 redisplay_text_width_string (Lisp_Object domain, Lisp_Object face, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
668 Ibyte *nonreloc, Lisp_Object reloc, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
669 Bytecount offset, Bytecount len) |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
670 { |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
671 Lisp_Object window = DOMAIN_WINDOW (domain); |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
672 Lisp_Object frame = DOMAIN_FRAME (domain); |
428 | 673 unsigned char charsets[NUM_LEADING_BYTES]; |
674 struct face_cachel cachel; | |
675 | |
867 | 676 if (!rtw_ichar_dynarr) |
677 rtw_ichar_dynarr = Dynarr_new (Ichar); | |
678 Dynarr_reset (rtw_ichar_dynarr); | |
428 | 679 |
680 fixup_internal_substring (nonreloc, reloc, offset, &len); | |
681 if (STRINGP (reloc)) | |
682 nonreloc = XSTRING_DATA (reloc); | |
867 | 683 convert_ibyte_string_into_ichar_dynarr (nonreloc, len, rtw_ichar_dynarr); |
684 find_charsets_in_ibyte_string (charsets, nonreloc, len); | |
428 | 685 reset_face_cachel (&cachel); |
686 cachel.face = face; | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
687 ensure_face_cachel_complete (&cachel, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
688 NILP (window) ? frame : window, |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
689 charsets); |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
690 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (frame))), |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
691 /* #### Not clear if we're always passed a window, but |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
692 I think so. If not, we will get an abort here, |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
693 and then we need to either fix the callers to pass in |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
694 a window, or change *text_width() to take a domain |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
695 argument. */ |
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
4844
diff
changeset
|
696 text_width, (XWINDOW (window), |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
697 &cachel, |
4967 | 698 Dynarr_begin (rtw_ichar_dynarr), |
867 | 699 Dynarr_length (rtw_ichar_dynarr))); |
428 | 700 } |
701 | |
702 /* Return the display block from DL of the given TYPE. A display line | |
703 can have only one display block of each possible type. If DL does | |
704 not have a block of type TYPE, one will be created and added to DL. */ | |
705 | |
706 struct display_block * | |
707 get_display_block_from_line (struct display_line *dl, enum display_type type) | |
708 { | |
709 int elt; | |
710 struct display_block db; | |
711 | |
712 /* Check if this display line already has a block of the desired type and | |
713 if so, return it. */ | |
714 if (dl->display_blocks) | |
715 { | |
716 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++) | |
717 { | |
718 if (Dynarr_at (dl->display_blocks, elt).type == type) | |
719 return Dynarr_atp (dl->display_blocks, elt); | |
720 } | |
721 | |
722 /* There isn't an active block of the desired type, but there | |
4187 | 723 might still be allocated blocks we need to reuse. */ |
428 | 724 if (elt < Dynarr_largest (dl->display_blocks)) |
725 { | |
726 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt); | |
727 | |
3025 | 728 /* "add" the block to the list */ |
5038 | 729 Dynarr_incrementr (dl->display_blocks); |
428 | 730 |
731 /* initialize and return */ | |
732 dbp->type = type; | |
733 return dbp; | |
734 } | |
735 } | |
736 else | |
737 { | |
738 /* This line doesn't have any display blocks, so initialize the display | |
4187 | 739 bock array. */ |
428 | 740 dl->display_blocks = Dynarr_new (display_block); |
741 } | |
742 | |
743 /* The line doesn't have a block of the desired type so go ahead and create | |
744 one and add it to the line. */ | |
745 xzero (db); | |
746 db.type = type; | |
747 db.runes = Dynarr_new (rune); | |
748 Dynarr_add (dl->display_blocks, db); | |
749 | |
750 /* Return the newly added display block. */ | |
751 elt = Dynarr_length (dl->display_blocks) - 1; | |
752 | |
753 return Dynarr_atp (dl->display_blocks, elt); | |
754 } | |
755 | |
756 static int | |
757 tab_char_width (struct window *w) | |
758 { | |
759 struct buffer *b = XBUFFER (w->buffer); | |
760 int char_tab_width = XINT (b->tab_width); | |
761 | |
762 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8; | |
763 | |
764 return char_tab_width; | |
765 } | |
766 | |
767 static int | |
768 space_width (struct window *w) | |
769 { | |
3659 | 770 /* While tabs are traditionally composed of spaces, for variable-width |
428 | 771 fonts the space character tends to give too narrow a value. So |
772 we use 'n' instead. Except that we don't. We use the default | |
773 character width for the default face. If this is actually | |
774 defined by the font then it is probably the best thing to | |
775 actually use. If it isn't, we have assumed it is 'n' and have | |
776 already calculated its width. Thus we can avoid a call to | |
777 XTextWidth on X frames by just querying the default width. */ | |
778 return XFONT_INSTANCE | |
779 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width; | |
780 } | |
781 | |
782 static int | |
783 tab_pix_width (struct window *w) | |
784 { | |
785 return space_width (w) * tab_char_width (w); | |
786 } | |
787 | |
788 /* Given a pixel position in a window, return the pixel location of | |
789 the next tabstop. Tabs are calculated from the left window edge in | |
790 terms of spaces displayed in the default face. Formerly the space | |
791 width was determined using the currently active face. That method | |
792 leads to tabstops which do not line up. */ | |
793 | |
794 static int | |
795 next_tab_position (struct window *w, int start_pixpos, int left_pixpos) | |
796 { | |
797 int n_pos = left_pixpos; | |
798 int pix_tab_width = tab_pix_width (w); | |
799 | |
800 /* Adjust n_pos for any hscrolling which has happened. */ | |
801 if (WINDOW_SCROLLED (w)) | |
802 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset; | |
803 | |
804 while (n_pos <= start_pixpos) | |
805 n_pos += pix_tab_width; | |
806 | |
807 return n_pos; | |
808 } | |
809 | |
810 /* For the given window, calculate the outside and margin boundaries for a | |
811 display line. The whitespace boundaries must be calculated by the text | |
812 layout routines. */ | |
813 | |
814 layout_bounds | |
815 calculate_display_line_boundaries (struct window *w, int modeline) | |
816 { | |
817 layout_bounds bounds; | |
818 | |
819 /* Set the outermost boundaries which are the boundaries of the | |
820 window itself minus the gutters (and minus the scrollbars if this | |
821 is for the modeline). */ | |
822 if (!modeline) | |
823 { | |
824 bounds.left_out = WINDOW_TEXT_LEFT (w); | |
825 bounds.right_out = WINDOW_TEXT_RIGHT (w); | |
826 } | |
827 else | |
828 { | |
829 bounds.left_out = WINDOW_MODELINE_LEFT (w); | |
830 bounds.right_out = WINDOW_MODELINE_RIGHT (w); | |
831 } | |
832 | |
833 /* The inner boundaries mark where the glyph margins are located. */ | |
834 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
835 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
836 | |
837 /* We cannot fully calculate the whitespace boundaries as they | |
838 depend on the contents of the line being displayed. */ | |
839 bounds.left_white = bounds.left_in; | |
840 bounds.right_white = bounds.right_in; | |
841 | |
842 return bounds; | |
843 } | |
844 | |
819 | 845 /* This takes a display_block and its containing line and corrects the yoffset |
846 of each glyph in the block to cater for the ascent of the line as a | |
847 whole. Must be called *after* the line-ascent is known! */ | |
848 | |
849 static void | |
850 calculate_yoffset (struct display_line *dl, struct display_block *fixup) | |
851 { | |
852 int i; | |
853 for (i=0; i<Dynarr_length (fixup->runes); i++) | |
854 { | |
855 struct rune *r = Dynarr_atp (fixup->runes,i); | |
856 if (r->type == RUNE_DGLYPH) | |
4187 | 857 { |
858 if (r->object.dglyph.ascent < dl->ascent) | |
859 r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent + | |
819 | 860 r->object.dglyph.descent; |
4187 | 861 } |
819 | 862 } |
863 } | |
864 | |
865 /* Calculate the textual baseline (the ascent and descent values for the | |
866 display_line as a whole). | |
867 | |
868 If the baseline is completely blank, or contains no manually positioned | |
869 glyphs, then the textual baseline is simply the baseline of the default font. | |
870 (The `contains no manually positioned glyphs' part is actually done for | |
867 | 871 us by `add_ichar_rune'.) |
819 | 872 |
873 If the baseline contains pixmaps, and they're all manually positioned, then | |
874 the textual baseline location is constrained that way, and we need do no | |
875 work. | |
876 | |
877 If the baseline contains pixmaps, and at least one is automatically | |
878 positioned, then the textual ascent is the largest ascent on the line, and | |
879 the textual descent is the largest descent (which is how things are set up at | |
880 entry to this function anyway): except that if the max_ascent + max_descent | |
881 is too small for the height of the line (say you've adjusted the baseline of | |
882 a short glyph, and there's a tall one next to it), then take the ascent and | |
883 descent for the line individually from the largest of the explicitly set | |
884 ascent/descent, and the rescaled ascent/descent of the default font, scaled | |
885 such that the largest glyph will fit. | |
886 | |
887 This means that if you have a short glyph (but taller than the default | |
888 font's descent) forced right under the baseline, and a really tall | |
889 automatically positioned glyph, that the descent for the line is just big | |
890 enough for the manually positioned short glyph, and the tall one uses as | |
891 much of that space as the default font would were it as tall as the tall | |
892 glyph; but that the ascent is big enough for the tall glyph to fit. | |
893 | |
894 This behaviour means that under no circumstances will changing the baseline | |
895 of a short glyph cause a tall glyph to move around; nor will it move the | |
896 textual baseline more than necessary. (Changing a tall glyph's baseline | |
897 might move the text's baseline arbitrarily, of course.) */ | |
898 | |
899 static void | |
900 calculate_baseline (pos_data *data) | |
901 { | |
902 /* Blank line: baseline is default font's baseline. */ | |
903 | |
904 if (!data->new_ascent && !data->new_descent) | |
905 { | |
906 /* We've got a blank line so initialize these values from the default | |
4187 | 907 face. */ |
819 | 908 default_face_font_info (data->window, &data->new_ascent, |
909 &data->new_descent, 0, 0, 0); | |
910 } | |
4187 | 911 |
819 | 912 /* No automatically positioned glyphs? Return at once. */ |
913 if (!data->need_baseline_computation) | |
914 return; | |
915 | |
916 /* Is the tallest glyph on the line automatically positioned? | |
917 If it's manually positioned, or it's automatically positioned | |
918 and there's enough room for it anyway, we need do no more work. */ | |
919 if (data->max_pixmap_height > data->new_ascent + data->new_descent) | |
920 { | |
921 int default_font_ascent, default_font_descent, default_font_height; | |
922 int scaled_default_font_ascent, scaled_default_font_descent; | |
4187 | 923 |
819 | 924 default_face_font_info (data->window, &default_font_ascent, |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
925 &default_font_descent, 0, &default_font_height, |
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
926 0); |
819 | 927 |
928 scaled_default_font_ascent = data->max_pixmap_height * | |
929 default_font_ascent / default_font_height; | |
930 | |
931 data->new_ascent = max (data->new_ascent, scaled_default_font_ascent); | |
932 | |
933 /* The ascent may have expanded now. Do we still need to grow the descent, | |
4187 | 934 or are things big enough? |
935 | |
936 The +1 caters for the baseline row itself. */ | |
819 | 937 if (data->max_pixmap_height > data->new_ascent + data->new_descent) |
4187 | 938 { |
939 scaled_default_font_descent = (data->max_pixmap_height * | |
819 | 940 default_font_descent / default_font_height) + 1; |
941 | |
4187 | 942 data->new_descent = max (data->new_descent, scaled_default_font_descent); |
943 } | |
819 | 944 } |
945 } | |
946 | |
428 | 947 /* Given a display line and a starting position, ensure that the |
948 contents of the display line accurately represent the visual | |
949 representation of the buffer contents starting from the given | |
950 position when displayed in the given window. The display line ends | |
951 when the contents of the line reach the right boundary of the given | |
952 window. */ | |
953 | |
665 | 954 static Charbpos |
428 | 955 generate_display_line (struct window *w, struct display_line *dl, int bounds, |
665 | 956 Charbpos start_pos, prop_block_dynarr **prop, |
428 | 957 int type) |
958 { | |
826 | 959 Charbpos ret_charpos; |
428 | 960 int overlay_width; |
961 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); | |
962 | |
963 /* If our caller hasn't already set the boundaries, then do so now. */ | |
964 if (!bounds) | |
965 dl->bounds = calculate_display_line_boundaries (w, 0); | |
966 | |
967 /* Reset what this line is using. */ | |
968 if (dl->display_blocks) | |
969 Dynarr_reset (dl->display_blocks); | |
970 if (dl->left_glyphs) | |
971 { | |
972 Dynarr_free (dl->left_glyphs); | |
973 dl->left_glyphs = 0; | |
974 } | |
975 if (dl->right_glyphs) | |
976 { | |
977 Dynarr_free (dl->right_glyphs); | |
978 dl->right_glyphs = 0; | |
979 } | |
980 | |
981 /* We aren't generating a modeline at the moment. */ | |
982 dl->modeline = 0; | |
983 | |
984 /* Create a display block for the text region of the line. */ | |
985 { | |
986 /* #### urk urk urk!!! Chuck fix this shit! */ | |
665 | 987 Bytebpos hacked_up_bytebpos = |
988 create_text_block (w, dl, charbpos_to_bytebpos (b, start_pos), | |
428 | 989 prop, type); |
826 | 990 if (hacked_up_bytebpos > BYTE_BUF_ZV (b)) |
991 ret_charpos = BUF_ZV (b) + 1; | |
428 | 992 else |
826 | 993 ret_charpos = bytebpos_to_charbpos (b, hacked_up_bytebpos); |
428 | 994 } |
826 | 995 dl->charpos = start_pos; |
996 if (dl->end_charpos < dl->charpos) | |
997 dl->end_charpos = dl->charpos; | |
428 | 998 |
999 if (MARKERP (Voverlay_arrow_position) | |
1000 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position)) | |
1001 && start_pos == marker_position (Voverlay_arrow_position) | |
1002 && (STRINGP (Voverlay_arrow_string) | |
1003 || GLYPHP (Voverlay_arrow_string))) | |
1004 { | |
1005 overlay_width = create_overlay_glyph_block (w, dl); | |
1006 } | |
1007 else | |
1008 overlay_width = 0; | |
1009 | |
1010 /* If there are left glyphs associated with any character in the | |
1011 text block, then create a display block to handle them. */ | |
1012 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
1013 create_left_glyph_block (w, dl, overlay_width); | |
1014 | |
1015 /* If there are right glyphs associated with any character in the | |
1016 text block, then create a display block to handle them. */ | |
1017 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
1018 create_right_glyph_block (w, dl); | |
1019 | |
1020 /* In the future additional types of display blocks may be generated | |
1021 here. */ | |
1022 | |
826 | 1023 w->last_redisplay_pos = ret_charpos; |
1024 | |
1025 return ret_charpos; | |
428 | 1026 } |
1027 | |
1028 /* Adds an hscroll glyph to a display block. If this is called, then | |
1029 the block had better be empty. | |
1030 | |
1031 Yes, there are multiple places where this function is called but | |
1032 that is the way it has to be. Each calling function has to deal | |
826 | 1033 with byte_start_col_enabled a little differently depending on the |
428 | 1034 object being worked with. */ |
1035 | |
1036 static prop_block_dynarr * | |
1037 add_hscroll_rune (pos_data *data) | |
1038 { | |
1039 struct glyph_block gb; | |
1040 prop_block_dynarr *retval; | |
826 | 1041 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
647 | 1042 int old_cursor_type = data->cursor_type; |
826 | 1043 Bytebpos byte_old_charpos = data->byte_charpos; |
428 | 1044 |
1045 if (data->cursor_type == CURSOR_ON | |
826 | 1046 && data->byte_cursor_charpos >= data->byte_start_col_enabled |
1047 && data->byte_cursor_charpos <= data->byte_charpos) | |
1048 { | |
1049 data->byte_cursor_charpos = data->byte_start_col_enabled; | |
428 | 1050 } |
1051 else | |
1052 { | |
1053 data->cursor_type = NO_CURSOR; | |
1054 } | |
1055 | |
826 | 1056 data->byte_endpos = data->byte_charpos; |
1057 data->byte_charpos = data->byte_start_col_enabled; | |
428 | 1058 |
1059 gb.extent = Qnil; | |
1060 gb.glyph = Vhscroll_glyph; | |
1061 { | |
1062 int oldpixpos = data->pixpos; | |
442 | 1063 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, |
428 | 1064 GLYPH_CACHEL (XWINDOW (data->window), |
1065 HSCROLL_GLYPH_INDEX)); | |
1066 data->hscroll_glyph_width_adjust = | |
1067 data->pixpos - oldpixpos - space_width (XWINDOW (data->window)); | |
1068 } | |
826 | 1069 data->byte_endpos = 0; |
1070 data->byte_cursor_charpos = byte_old_cursor_charpos; | |
428 | 1071 data->cursor_type = old_cursor_type; |
826 | 1072 data->byte_charpos = byte_old_charpos; |
1073 | |
1074 data->byte_start_col_enabled = 0; | |
428 | 1075 return retval; |
1076 } | |
1077 | |
793 | 1078 /* Adds a character rune to a display block. If there is not enough room |
1079 to fit the rune on the display block (as determined by the MAX_PIXPOS) | |
1080 then it adds nothing and returns ADD_FAILED. If | |
1081 NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't allow the char's height | |
867 | 1082 to affect the total line height. (See add_ibyte_string_runes()). */ |
428 | 1083 |
1084 static prop_block_dynarr * | |
867 | 1085 add_ichar_rune_1 (pos_data *data, int no_contribute_to_line_height) |
428 | 1086 { |
1087 struct rune rb, *crb; | |
1088 int width, local; | |
1089 | |
1090 if (data->start_col) | |
1091 { | |
1092 data->start_col--; | |
1093 | |
1094 if (data->start_col) | |
1095 return NULL; | |
1096 } | |
1097 | |
826 | 1098 if (data->byte_start_col_enabled) |
428 | 1099 { |
1100 return add_hscroll_rune (data); | |
1101 } | |
1102 | |
1103 if (data->ch == '\n') | |
1104 { | |
1105 data->font_is_bogus = 0; | |
1106 /* Cheesy end-of-line pseudo-character. */ | |
1107 width = data->blank_width; | |
1108 } | |
1109 else | |
1110 { | |
867 | 1111 Lisp_Object charset = ichar_charset (data->ch); |
428 | 1112 if (!EQ (charset, data->last_charset) || |
1113 data->findex != data->last_findex) | |
1114 { | |
1115 /* OK, we need to do things the hard way. */ | |
1116 struct window *w = XWINDOW (data->window); | |
1117 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex); | |
1118 Lisp_Object font_instance = | |
1119 ensure_face_cachel_contains_charset (cachel, data->window, | |
1120 charset); | |
440 | 1121 Lisp_Font_Instance *fi; |
428 | 1122 |
1123 if (EQ (font_instance, Vthe_null_font_instance)) | |
1124 { | |
1125 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); | |
1126 data->font_is_bogus = 1; | |
1127 } | |
1128 else | |
1129 data->font_is_bogus = 0; | |
1130 | |
1131 fi = XFONT_INSTANCE (font_instance); | |
771 | 1132 if (!fi->proportional_p || data->font_is_bogus) |
1133 { | |
867 | 1134 Ichar ch = data->font_is_bogus ? '~' : data->ch; |
771 | 1135 |
1136 data->last_char_width = | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1137 redisplay_window_text_width_ichar_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1138 (XWINDOW (data->window), data->findex, &ch, 1); |
771 | 1139 } |
428 | 1140 else |
1141 data->last_char_width = -1; | |
819 | 1142 |
793 | 1143 if (!no_contribute_to_line_height) |
1144 { | |
1145 data->new_ascent = max (data->new_ascent, (int) fi->ascent); | |
1146 data->new_descent = max (data->new_descent, (int) fi->descent); | |
1147 } | |
819 | 1148 |
428 | 1149 data->last_charset = charset; |
1150 data->last_findex = data->findex; | |
1151 } | |
1152 | |
1153 width = data->last_char_width; | |
771 | 1154 if (width < 0) /* proportional fonts */ |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1155 width = redisplay_window_text_width_ichar_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
1156 (XWINDOW (data->window), data->findex, &data->ch, 1); |
428 | 1157 } |
1158 | |
1159 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos)) | |
1160 { | |
1161 return ADD_FAILED; | |
1162 } | |
1163 | |
1164 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes)) | |
1165 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
1166 crb = Dynarr_past_lastp (data->db->runes); |
428 | 1167 local = 0; |
1168 } | |
1169 else | |
1170 { | |
1171 crb = &rb; | |
1172 local = 1; | |
1173 } | |
1174 | |
1175 crb->findex = data->findex; | |
1176 crb->xpos = data->pixpos; | |
1177 crb->width = width; | |
826 | 1178 if (data->byte_charpos) |
428 | 1179 { |
1180 if (NILP (data->string)) | |
826 | 1181 crb->charpos = |
793 | 1182 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER |
1183 (XWINDOW (data->window))), | |
826 | 1184 data->byte_charpos); |
428 | 1185 else |
826 | 1186 crb->charpos = |
1187 string_index_byte_to_char (data->string, data->byte_charpos); | |
428 | 1188 } |
1189 else if (data->is_modeline) | |
826 | 1190 crb->charpos = data->modeline_charpos; |
428 | 1191 else |
442 | 1192 /* Text but not in buffer */ |
826 | 1193 crb->charpos = 0; |
428 | 1194 crb->type = RUNE_CHAR; |
1195 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch; | |
1196 crb->endpos = 0; | |
1197 | |
1198 if (data->cursor_type == CURSOR_ON) | |
1199 { | |
826 | 1200 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 1201 { |
1202 crb->cursor_type = CURSOR_ON; | |
1203 data->cursor_x = Dynarr_length (data->db->runes); | |
1204 } | |
1205 else | |
1206 crb->cursor_type = CURSOR_OFF; | |
1207 } | |
1208 else if (data->cursor_type == NEXT_CURSOR) | |
1209 { | |
1210 crb->cursor_type = CURSOR_ON; | |
1211 data->cursor_x = Dynarr_length (data->db->runes); | |
1212 data->cursor_type = NO_CURSOR; | |
1213 } | |
1214 else if (data->cursor_type == IGNORE_CURSOR) | |
1215 crb->cursor_type = IGNORE_CURSOR; | |
1216 else | |
1217 crb->cursor_type = CURSOR_OFF; | |
1218 | |
1219 if (local) | |
1220 Dynarr_add (data->db->runes, *crb); | |
1221 else | |
5038 | 1222 Dynarr_incrementr (data->db->runes); |
428 | 1223 |
1224 data->pixpos += width; | |
1225 | |
1226 return NULL; | |
1227 } | |
1228 | |
793 | 1229 static prop_block_dynarr * |
867 | 1230 add_ichar_rune (pos_data *data) |
1231 { | |
1232 return add_ichar_rune_1 (data, 0); | |
1233 } | |
1234 | |
1235 /* Given a string C_STRING of length C_LENGTH, call add_ichar_rune for | |
793 | 1236 each character in the string. Propagate any left-over data unless |
1237 NO_PROP is non-zero. If NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't | |
1238 allow this character to increase the total height of the line. (This is | |
1239 used when the character is part of a text glyph. In that case, the | |
1240 glyph code itself adjusts the line height as necessary, depending on | |
1241 whether glyph-contrib-p is true.) */ | |
428 | 1242 |
1243 static prop_block_dynarr * | |
867 | 1244 add_ibyte_string_runes (pos_data *data, Ibyte *c_string, |
793 | 1245 Bytecount c_length, int no_prop, |
1246 int no_contribute_to_line_height) | |
428 | 1247 { |
867 | 1248 Ibyte *pos, *end = c_string + c_length; |
428 | 1249 prop_block_dynarr *prop; |
1250 | |
1251 /* #### This function is too simplistic. It needs to do the same | |
1252 sort of character interpretation (display-table lookup, | |
1253 ctl-arrow checking), etc. that create_text_block() does. | |
1254 The functionality to do this in that routine needs to be | |
1255 modularized. */ | |
1256 | |
1257 for (pos = c_string; pos < end;) | |
1258 { | |
867 | 1259 Ibyte *old_pos = pos; |
1260 | |
1261 data->ch = itext_ichar (pos); | |
1262 | |
1263 prop = add_ichar_rune_1 (data, no_contribute_to_line_height); | |
428 | 1264 |
1265 if (prop) | |
1266 { | |
1267 if (no_prop) | |
1268 return ADD_FAILED; | |
1269 else | |
1270 { | |
1271 struct prop_block pb; | |
1272 Bytecount len = end - pos; | |
1273 prop = Dynarr_new (prop_block); | |
1274 | |
1275 pb.type = PROP_STRING; | |
867 | 1276 pb.data.p_string.str = xnew_array (Ibyte, len); |
4970 | 1277 qxestrncpy (pb.data.p_string.str, pos, len); |
428 | 1278 pb.data.p_string.len = len; |
1279 | |
1280 Dynarr_add (prop, pb); | |
1281 return prop; | |
1282 } | |
1283 } | |
867 | 1284 INC_IBYTEPTR (pos); |
428 | 1285 assert (pos <= end); |
464 | 1286 /* #### Duplicate code from add_string_to_fstring_db_runes |
1287 should we do more?*/ | |
1288 data->bytepos += pos - old_pos; | |
428 | 1289 } |
1290 | |
1291 return NULL; | |
1292 } | |
1293 | |
1294 /* Add a single rune of the specified width. The area covered by this | |
1295 rune will be displayed in the foreground color of the associated | |
1296 face. */ | |
1297 | |
1298 static prop_block_dynarr * | |
1299 add_blank_rune (pos_data *data, struct window *w, int char_tab_width) | |
1300 { | |
1301 struct rune rb; | |
1302 | |
1303 /* If data->start_col is not 0 then this call to add_blank_rune must have | |
1304 been to add it as a tab. */ | |
1305 if (data->start_col) | |
1306 { | |
1307 /* assert (w != NULL) */ | |
1308 prop_block_dynarr *retval; | |
1309 | |
1310 /* If we have still not fully scrolled horizontally, subtract | |
4187 | 1311 the width of this tab and return. */ |
428 | 1312 if (char_tab_width < data->start_col) |
1313 { | |
1314 data->start_col -= char_tab_width; | |
1315 return NULL; | |
1316 } | |
1317 else if (char_tab_width == data->start_col) | |
1318 data->blank_width = 0; | |
1319 else | |
1320 { | |
1321 int spcwid = space_width (w); | |
1322 | |
1323 if (spcwid >= data->blank_width) | |
1324 data->blank_width = 0; | |
1325 else | |
1326 data->blank_width -= spcwid; | |
1327 } | |
1328 | |
1329 data->start_col = 0; | |
1330 retval = add_hscroll_rune (data); | |
1331 | |
1332 /* Could be caused by the handling of the hscroll rune. */ | |
1333 if (retval != NULL || !data->blank_width) | |
1334 return retval; | |
1335 } | |
1336 | |
1337 /* Blank runes are always calculated to fit. */ | |
1338 assert (data->pixpos + data->blank_width <= data->max_pixpos); | |
1339 | |
1340 rb.findex = data->findex; | |
1341 rb.xpos = data->pixpos; | |
1342 rb.width = data->blank_width; | |
826 | 1343 if (data->byte_charpos) |
1344 rb.charpos = | |
665 | 1345 bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))), |
826 | 1346 data->byte_charpos); |
428 | 1347 else |
1348 /* #### and this is really correct too? */ | |
826 | 1349 rb.charpos = 0; |
428 | 1350 rb.endpos = 0; |
1351 rb.type = RUNE_BLANK; | |
1352 | |
1353 if (data->cursor_type == CURSOR_ON) | |
1354 { | |
826 | 1355 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 1356 { |
1357 rb.cursor_type = CURSOR_ON; | |
1358 data->cursor_x = Dynarr_length (data->db->runes); | |
1359 } | |
1360 else | |
1361 rb.cursor_type = CURSOR_OFF; | |
1362 } | |
1363 else if (data->cursor_type == NEXT_CURSOR) | |
1364 { | |
1365 rb.cursor_type = CURSOR_ON; | |
1366 data->cursor_x = Dynarr_length (data->db->runes); | |
1367 data->cursor_type = NO_CURSOR; | |
1368 } | |
1369 else | |
1370 rb.cursor_type = CURSOR_OFF; | |
1371 | |
1372 Dynarr_add (data->db->runes, rb); | |
1373 data->pixpos += data->blank_width; | |
1374 | |
1375 return NULL; | |
1376 } | |
1377 | |
1378 /* Add runes representing a character in octal. */ | |
1379 | |
1380 #define ADD_NEXT_OCTAL_RUNE_CHAR do \ | |
1381 { \ | |
867 | 1382 if (add_failed || (add_failed = add_ichar_rune (data))) \ |
428 | 1383 { \ |
1384 struct prop_block pb; \ | |
1385 if (!prop) \ | |
1386 prop = Dynarr_new (prop_block); \ | |
1387 \ | |
1388 pb.type = PROP_CHAR; \ | |
1389 pb.data.p_char.ch = data->ch; \ | |
1390 pb.data.p_char.cursor_type = data->cursor_type; \ | |
1391 Dynarr_add (prop, pb); \ | |
1392 } \ | |
1393 } while (0) | |
1394 | |
1395 static prop_block_dynarr * | |
1396 add_octal_runes (pos_data *data) | |
1397 { | |
819 | 1398 prop_block_dynarr *add_failed, *prop = 0; |
867 | 1399 Ichar orig_char = data->ch; |
647 | 1400 int orig_cursor_type = data->cursor_type; |
428 | 1401 |
1402 /* Initialize */ | |
1403 add_failed = NULL; | |
1404 | |
1405 if (data->start_col) | |
1406 data->start_col--; | |
1407 | |
1408 if (!data->start_col) | |
1409 { | |
826 | 1410 if (data->byte_start_col_enabled) |
428 | 1411 { |
1412 add_failed = add_hscroll_rune (data); | |
1413 } | |
1414 else | |
1415 { | |
1416 struct glyph_block gb; | |
1417 struct window *w = XWINDOW (data->window); | |
1418 | |
1419 gb.extent = Qnil; | |
1420 gb.glyph = Voctal_escape_glyph; | |
1421 add_failed = | |
1422 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
1423 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX)); | |
1424 } | |
1425 } | |
1426 | |
1427 /* We only propagate information if the glyph was partially | |
1428 added. */ | |
1429 if (add_failed) | |
1430 return add_failed; | |
1431 | |
1432 data->cursor_type = IGNORE_CURSOR; | |
1433 | |
1434 if (data->ch >= 0x100) | |
1435 { | |
1436 /* If the character is an extended Mule character, it could have | |
3498 | 1437 up to 21 bits. For the moment, we treat it as a seven-digit |
428 | 1438 octal number. This is not that pretty, but whatever. */ |
1439 data->ch = (7 & (orig_char >> 18)) + '0'; | |
1440 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1441 | |
1442 data->ch = (7 & (orig_char >> 15)) + '0'; | |
1443 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1444 | |
1445 data->ch = (7 & (orig_char >> 12)) + '0'; | |
1446 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1447 | |
1448 data->ch = (7 & (orig_char >> 9)) + '0'; | |
1449 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1450 } | |
1451 | |
1452 data->ch = (7 & (orig_char >> 6)) + '0'; | |
1453 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1454 | |
1455 data->ch = (7 & (orig_char >> 3)) + '0'; | |
1456 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1457 | |
1458 data->ch = (7 & orig_char) + '0'; | |
1459 ADD_NEXT_OCTAL_RUNE_CHAR; | |
1460 | |
1461 data->cursor_type = orig_cursor_type; | |
819 | 1462 return NULL; |
428 | 1463 } |
1464 | |
1465 #undef ADD_NEXT_OCTAL_RUNE_CHAR | |
1466 | |
1467 /* Add runes representing a control character to a display block. */ | |
1468 | |
1469 static prop_block_dynarr * | |
1470 add_control_char_runes (pos_data *data, struct buffer *b) | |
1471 { | |
1472 if (!NILP (b->ctl_arrow)) | |
1473 { | |
1474 prop_block_dynarr *prop; | |
867 | 1475 Ichar orig_char = data->ch; |
647 | 1476 int old_cursor_type = data->cursor_type; |
428 | 1477 |
1478 /* Initialize */ | |
1479 prop = NULL; | |
1480 | |
1481 if (data->start_col) | |
1482 data->start_col--; | |
1483 | |
1484 if (!data->start_col) | |
1485 { | |
826 | 1486 if (data->byte_start_col_enabled) |
428 | 1487 { |
1488 prop_block_dynarr *retval; | |
1489 | |
1490 retval = add_hscroll_rune (data); | |
1491 if (retval) | |
1492 return retval; | |
1493 } | |
1494 else | |
1495 { | |
1496 struct glyph_block gb; | |
1497 struct window *w = XWINDOW (data->window); | |
1498 | |
1499 gb.extent = Qnil; | |
1500 gb.glyph = Vcontrol_arrow_glyph; | |
1501 | |
1502 /* We only propagate information if the glyph was partially | |
1503 added. */ | |
1504 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, | |
1505 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX))) | |
1506 return ADD_FAILED; | |
1507 } | |
1508 } | |
1509 | |
1510 if (orig_char == 0177) | |
1511 data->ch = '?'; | |
1512 else | |
1513 data->ch = orig_char ^ 0100; | |
1514 data->cursor_type = IGNORE_CURSOR; | |
1515 | |
867 | 1516 if (add_ichar_rune (data)) |
428 | 1517 { |
1518 struct prop_block pb; | |
1519 if (!prop) | |
1520 prop = Dynarr_new (prop_block); | |
1521 | |
1522 pb.type = PROP_CHAR; | |
1523 pb.data.p_char.ch = data->ch; | |
1524 pb.data.p_char.cursor_type = data->cursor_type; | |
1525 Dynarr_add (prop, pb); | |
1526 } | |
1527 | |
1528 data->cursor_type = old_cursor_type; | |
1529 return prop; | |
1530 } | |
1531 else | |
1532 { | |
1533 return add_octal_runes (data); | |
1534 } | |
1535 } | |
1536 | |
1537 static prop_block_dynarr * | |
1538 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) | |
1539 { | |
1540 prop_block_dynarr *prop = NULL; | |
1541 | |
1542 if (STRINGP (entry)) | |
1543 { | |
867 | 1544 prop = add_ibyte_string_runes (data, |
428 | 1545 XSTRING_DATA (entry), |
1546 XSTRING_LENGTH (entry), | |
793 | 1547 0, 0); |
428 | 1548 } |
1549 else if (GLYPHP (entry)) | |
1550 { | |
1551 if (data->start_col) | |
1552 data->start_col--; | |
1553 | |
826 | 1554 if (!data->start_col && data->byte_start_col_enabled) |
428 | 1555 { |
1556 prop = add_hscroll_rune (data); | |
1557 } | |
1558 else | |
1559 { | |
1560 struct glyph_block gb; | |
1561 | |
1562 gb.glyph = entry; | |
1563 gb.extent = Qnil; | |
1564 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); | |
1565 } | |
1566 } | |
1567 else if (CHAR_OR_CHAR_INTP (entry)) | |
1568 { | |
1569 data->ch = XCHAR_OR_CHAR_INT (entry); | |
867 | 1570 prop = add_ichar_rune (data); |
428 | 1571 } |
1572 else if (CONSP (entry)) | |
1573 { | |
1574 if (EQ (XCAR (entry), Qformat) | |
1575 && CONSP (XCDR (entry)) | |
1576 && STRINGP (XCAR (XCDR (entry)))) | |
1577 { | |
1578 Lisp_Object format = XCAR (XCDR (entry)); | |
665 | 1579 Bytebpos len = XSTRING_LENGTH (format); |
867 | 1580 Ibyte *src = XSTRING_DATA (format), *end = src + len; |
2367 | 1581 Ibyte *result = alloca_ibytes (len); |
867 | 1582 Ibyte *dst = result; |
428 | 1583 |
1584 while (src < end) | |
1585 { | |
867 | 1586 Ichar c = itext_ichar (src); |
1587 INC_IBYTEPTR (src); | |
428 | 1588 if (c != '%' || src == end) |
867 | 1589 dst += set_itext_ichar (dst, c); |
428 | 1590 else |
1591 { | |
867 | 1592 c = itext_ichar (src); |
1593 INC_IBYTEPTR (src); | |
428 | 1594 switch (c) |
1595 { | |
1596 /*case 'x': | |
1597 dst += long_to_string_base ((char *)dst, data->ch, 16); | |
1598 break;*/ | |
1599 case '%': | |
867 | 1600 dst += set_itext_ichar (dst, '%'); |
428 | 1601 break; |
442 | 1602 /* #### unimplemented */ |
428 | 1603 } |
1604 } | |
1605 } | |
867 | 1606 prop = add_ibyte_string_runes (data, result, dst - result, 0, 0); |
428 | 1607 } |
1608 } | |
1609 | |
1610 /* Else blow it off because someone added a bad entry and we don't | |
1611 have any safe way of signaling an error. */ | |
1612 return prop; | |
1613 } | |
1614 | |
1615 /* Given a display table entry, call the appropriate functions to | |
1616 display each element of the entry. */ | |
1617 | |
1618 static prop_block_dynarr * | |
1619 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) | |
1620 { | |
1621 prop_block_dynarr *prop = NULL; | |
1622 if (VECTORP (entry)) | |
1623 { | |
440 | 1624 Lisp_Vector *de = XVECTOR (entry); |
428 | 1625 EMACS_INT len = vector_length (de); |
1626 int elt; | |
1627 | |
1628 for (elt = 0; elt < len; elt++) | |
1629 { | |
1630 if (NILP (vector_data (de)[elt])) | |
1631 continue; | |
1632 else | |
1633 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]); | |
1634 /* Else blow it off because someone added a bad entry and we | |
1635 don't have any safe way of signaling an error. Hey, this | |
1636 comment sounds familiar. */ | |
1637 | |
1638 /* #### Still need to add any remaining elements to the | |
4187 | 1639 propagation information. */ |
428 | 1640 if (prop) |
1641 return prop; | |
1642 } | |
1643 } | |
1644 else | |
1645 prop = add_disp_table_entry_runes_1 (data, entry); | |
1646 return prop; | |
1647 } | |
1648 | |
1649 /* Add runes which were propagated from the previous line. */ | |
1650 | |
1651 static prop_block_dynarr * | |
1652 add_propagation_runes (prop_block_dynarr **prop, pos_data *data) | |
1653 { | |
1654 /* #### Remember to handle start_col parameter of data when the rest of | |
1655 this is finished. */ | |
1656 /* #### Chuck -- I've redone this function a bit. It looked like the | |
1657 case of not all the propagation blocks being added was not handled | |
1658 well. */ | |
1659 /* #### Chuck -- I also think the double indirection of PROP is kind | |
1660 of bogus. A cleaner solution is just to check for | |
1661 Dynarr_length (prop) > 0. */ | |
1662 /* #### This function also doesn't even pay attention to ADD_FAILED! | |
1663 This is seriously fucked! Seven ####'s in 130 lines -- is that a | |
1664 record? */ | |
1665 int elt; | |
1666 prop_block_dynarr *add_failed; | |
826 | 1667 Bytebpos byte_old_cursor_charpos = data->byte_cursor_charpos; |
647 | 1668 int old_cursor_type = data->cursor_type; |
428 | 1669 |
1670 for (elt = 0; elt < Dynarr_length (*prop); elt++) | |
1671 { | |
1672 struct prop_block *pb = Dynarr_atp (*prop, elt); | |
1673 | |
1674 switch (pb->type) | |
1675 { | |
1676 case PROP_CHAR: | |
1677 data->ch = pb->data.p_char.ch; | |
826 | 1678 data->byte_cursor_charpos = pb->data.p_char.byte_cursor_charpos; |
428 | 1679 data->cursor_type = pb->data.p_char.cursor_type; |
867 | 1680 add_failed = add_ichar_rune (data); |
428 | 1681 |
1682 if (add_failed) | |
1683 goto oops_no_more_space; | |
1684 break; | |
1685 case PROP_STRING: | |
1686 if (pb->data.p_string.str) | |
5169
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
1687 { |
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
1688 xfree (pb->data.p_string.str); |
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
1689 pb->data.p_string.str = 0; |
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
1690 } |
428 | 1691 /* #### bogus bogus -- this doesn't do anything! |
867 | 1692 Should probably call add_ibyte_string_runes(), |
428 | 1693 once that function is fixed. */ |
1694 break; | |
1695 case PROP_MINIBUF_PROMPT: | |
1696 { | |
1697 face_index old_findex = data->findex; | |
826 | 1698 Bytebpos byte_old_charpos = data->byte_charpos; |
428 | 1699 |
1700 data->findex = DEFAULT_INDEX; | |
826 | 1701 data->byte_charpos = 0; |
428 | 1702 data->cursor_type = NO_CURSOR; |
1703 | |
1704 while (pb->data.p_string.len > 0) | |
1705 { | |
867 | 1706 data->ch = itext_ichar (pb->data.p_string.str); |
1707 add_failed = add_ichar_rune (data); | |
428 | 1708 |
1709 if (add_failed) | |
1710 { | |
1711 data->findex = old_findex; | |
826 | 1712 data->byte_charpos = byte_old_charpos; |
428 | 1713 goto oops_no_more_space; |
1714 } | |
1715 else | |
1716 { | |
1717 /* Complicated equivalent of ptr++, len-- */ | |
867 | 1718 Ibyte *oldpos = pb->data.p_string.str; |
1719 INC_IBYTEPTR (pb->data.p_string.str); | |
428 | 1720 pb->data.p_string.len -= pb->data.p_string.str - oldpos; |
1721 } | |
1722 } | |
1723 | |
1724 data->findex = old_findex; | |
1725 /* ##### FIXME FIXME FIXME -- Upon successful return from | |
826 | 1726 this function, data->byte_charpos is automatically incremented. |
428 | 1727 However, we don't want that to happen if we were adding |
1728 the minibuffer prompt. */ | |
1729 { | |
1730 struct buffer *buf = | |
1731 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))); | |
1732 /* #### Chuck fix this shit or I'm gonna scream! */ | |
826 | 1733 if (byte_old_charpos > BYTE_BUF_BEGV (buf)) |
4187 | 1734 data->byte_charpos = prev_bytebpos (buf, byte_old_charpos); |
1735 else | |
428 | 1736 /* #### is this correct? Does anyone know? |
1737 Does anyone care? Is this a cheesy hack or what? */ | |
4187 | 1738 data->byte_charpos = BYTE_BUF_BEGV (buf) - 1; |
428 | 1739 } |
1740 } | |
1741 break; | |
1742 case PROP_BLANK: | |
1743 { | |
1744 /* #### I think it's unnecessary and misleading to preserve | |
1745 the blank_width, as it implies that the value carries | |
1746 over from one rune to the next, which is wrong. */ | |
1747 int old_width = data->blank_width; | |
1748 face_index old_findex = data->findex; | |
1749 | |
1750 data->findex = pb->data.p_blank.findex; | |
1751 data->blank_width = pb->data.p_blank.width; | |
826 | 1752 data->byte_cursor_charpos = 0; |
428 | 1753 data->cursor_type = IGNORE_CURSOR; |
1754 | |
1755 if (data->pixpos + data->blank_width > data->max_pixpos) | |
1756 data->blank_width = data->max_pixpos - data->pixpos; | |
1757 | |
1758 /* We pass a bogus value of char_tab_width. It shouldn't | |
4187 | 1759 matter because unless something is really screwed up |
1760 this call won't cause that arg to be used. */ | |
428 | 1761 add_failed = add_blank_rune (data, XWINDOW (data->window), 0); |
1762 | |
1763 /* This can happen in the case where we have a tab which | |
4187 | 1764 is wider than the window. */ |
428 | 1765 if (data->blank_width != pb->data.p_blank.width) |
1766 { | |
1767 pb->data.p_blank.width -= data->blank_width; | |
1768 add_failed = ADD_FAILED; | |
1769 } | |
1770 | |
1771 data->findex = old_findex; | |
1772 data->blank_width = old_width; | |
1773 | |
1774 if (add_failed) | |
1775 goto oops_no_more_space; | |
1776 } | |
1777 break; | |
1778 default: | |
2500 | 1779 ABORT (); |
428 | 1780 } |
1781 } | |
1782 | |
1783 oops_no_more_space: | |
1784 | |
826 | 1785 data->byte_cursor_charpos = byte_old_cursor_charpos; |
428 | 1786 data->cursor_type = old_cursor_type; |
1787 if (elt < Dynarr_length (*prop)) | |
1788 { | |
1789 Dynarr_delete_many (*prop, 0, elt); | |
1790 return *prop; | |
1791 } | |
1792 else | |
1793 { | |
1794 Dynarr_free (*prop); | |
1795 return NULL; | |
1796 } | |
1797 } | |
1798 | |
3025 | 1799 /* Add `text' layout glyphs at position POS_TYPE that are contained to |
428 | 1800 the display block, but add all other types to the appropriate list |
1801 of the display line. They will be added later by different | |
1802 routines. */ | |
1803 | |
1804 static prop_block_dynarr * | |
1805 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, | |
1806 int allow_cursor, struct glyph_cachel *cachel) | |
1807 { | |
1808 struct window *w = XWINDOW (data->window); | |
1809 | |
440 | 1810 /* If window faces changed, and glyph instance is text, then |
1811 glyph sizes might have changed too */ | |
1812 invalidate_glyph_geometry_maybe (gb->glyph, w); | |
1813 | |
442 | 1814 /* This makes sure the glyph is in the cachels. |
1815 | |
1816 #### We do this to make sure the glyph is in the glyph cachels, | |
1817 so that the dirty flag can be reset after redisplay has | |
1818 finished. We should do this some other way, maybe by iterating | |
1819 over the window cache of subwindows. */ | |
1820 get_glyph_cachel_index (w, gb->glyph); | |
1821 | |
428 | 1822 /* A nil extent indicates a special glyph (ex. truncator). */ |
1823 if (NILP (gb->extent) | |
1824 || (pos_type == BEGIN_GLYPHS && | |
1825 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) | |
1826 || (pos_type == END_GLYPHS && | |
442 | 1827 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) |
1828 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) | |
428 | 1829 { |
1830 struct rune rb; | |
1831 int width; | |
1832 int xoffset = 0; | |
1833 int ascent, descent; | |
1834 Lisp_Object baseline; | |
1835 Lisp_Object face; | |
442 | 1836 Lisp_Object instance; |
1837 face_index findex; | |
819 | 1838 prop_block_dynarr *retval = 0; |
428 | 1839 |
1840 if (cachel) | |
1841 width = cachel->width; | |
1842 else | |
438 | 1843 width = glyph_width (gb->glyph, data->window); |
428 | 1844 |
1845 if (!width) | |
1846 return NULL; | |
1847 | |
1848 if (data->start_col || data->start_col_xoffset) | |
1849 { | |
1850 int glyph_char_width = width / space_width (w); | |
1851 | |
1852 /* If we still have not fully scrolled horizontally after | |
4187 | 1853 taking into account the width of the glyph, subtract its |
1854 width and return. */ | |
428 | 1855 if (glyph_char_width < data->start_col) |
1856 { | |
1857 data->start_col -= glyph_char_width; | |
1858 return NULL; | |
1859 } | |
1860 else if (glyph_char_width == data->start_col) | |
1861 width = 0; | |
1862 else | |
1863 { | |
1864 xoffset = space_width (w) * data->start_col; | |
1865 width -= xoffset; | |
1866 | |
1867 /* #### Can this happen? */ | |
1868 if (width < 0) | |
1869 width = 0; | |
1870 } | |
1871 | |
1872 data->start_col = 0; | |
1873 retval = add_hscroll_rune (data); | |
1874 | |
1875 /* Could be caused by the handling of the hscroll rune. */ | |
1876 if (retval != NULL || !width) | |
1877 return retval; | |
1878 } | |
1879 else | |
1880 xoffset = 0; | |
1881 | |
1882 if (data->pixpos + width > data->max_pixpos) | |
1883 { | |
1884 /* If this is the first object we are attempting to add to | |
819 | 1885 the line then we ignore the horizontal_clip threshold. |
1886 Otherwise we will loop until the bottom of the window | |
1887 continually failing to add this glyph because it is wider | |
1888 than the window. We could alternatively just completely | |
1889 ignore the glyph and proceed from there but I think that | |
1890 this is a better solution. | |
4187 | 1891 |
819 | 1892 This does, however, create a different problem in that we |
1893 can end up adding the object to every single line, never | |
1894 getting any further - for instance an extent with a long | |
1895 start-glyph that covers multitple following | |
1896 characters. */ | |
428 | 1897 if (Dynarr_length (data->db->runes) |
1898 && data->max_pixpos - data->pixpos < horizontal_clip) | |
1899 return ADD_FAILED; | |
819 | 1900 else { |
1901 struct prop_block pb; | |
1902 | |
1903 /* We need to account for the width of the end-of-line | |
1904 glyph if there is nothing more in the line to display, | |
1905 since we will not display it in this instance. It seems | |
1906 kind of gross doing it here, but otherwise we have to | |
1907 search the runes in create_text_block(). */ | |
1908 if (data->ch == '\n') | |
1909 data->max_pixpos += data->end_glyph_width; | |
428 | 1910 width = data->max_pixpos - data->pixpos; |
819 | 1911 /* Add the glyph we are displaying, but clipping, to the |
1912 propagation data so that we don't try and do it | |
4187 | 1913 again. */ |
819 | 1914 retval = Dynarr_new (prop_block); |
1915 pb.type = PROP_GLYPH; | |
1916 pb.data.p_glyph.glyph = gb->glyph; | |
1917 pb.data.p_glyph.width = width; | |
1918 Dynarr_add (retval, pb); | |
1919 } | |
428 | 1920 } |
1921 | |
1922 if (cachel) | |
1923 { | |
1924 ascent = cachel->ascent; | |
1925 descent = cachel->descent; | |
1926 } | |
1927 else | |
1928 { | |
438 | 1929 ascent = glyph_ascent (gb->glyph, data->window); |
1930 descent = glyph_descent (gb->glyph, data->window); | |
428 | 1931 } |
1932 | |
1933 baseline = glyph_baseline (gb->glyph, data->window); | |
1934 | |
819 | 1935 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ |
1936 | |
428 | 1937 if (glyph_contrib_p (gb->glyph, data->window)) |
1938 { | |
1939 /* A pixmap that has not had a baseline explicitly set. Its | |
1940 contribution will be determined later. */ | |
1941 if (NILP (baseline)) | |
1942 { | |
1943 int height = ascent + descent; | |
819 | 1944 data->need_baseline_computation = 1; |
428 | 1945 data->max_pixmap_height = max (data->max_pixmap_height, height); |
1946 } | |
1947 | |
1948 /* A string so determine contribution normally. */ | |
1949 else if (EQ (baseline, Qt)) | |
1950 { | |
1951 data->new_ascent = max (data->new_ascent, ascent); | |
1952 data->new_descent = max (data->new_descent, descent); | |
1953 } | |
1954 | |
1955 /* A pixmap with an explicitly set baseline. We determine the | |
1956 contribution here. */ | |
1957 else if (INTP (baseline)) | |
1958 { | |
1959 int height = ascent + descent; | |
1960 int pix_ascent, pix_descent; | |
1961 | |
1962 pix_ascent = height * XINT (baseline) / 100; | |
1963 pix_descent = height - pix_ascent; | |
1964 | |
1965 data->new_ascent = max (data->new_ascent, pix_ascent); | |
1966 data->new_descent = max (data->new_descent, pix_descent); | |
819 | 1967 data->max_pixmap_height = max (data->max_pixmap_height, height); |
4187 | 1968 |
819 | 1969 rb.object.dglyph.descent = pix_descent; |
428 | 1970 } |
1971 | |
1972 /* Otherwise something is screwed up. */ | |
1973 else | |
2500 | 1974 ABORT (); |
428 | 1975 } |
1976 | |
1977 face = glyph_face (gb->glyph, data->window); | |
1978 if (NILP (face)) | |
442 | 1979 findex = data->findex; |
428 | 1980 else |
442 | 1981 findex = get_builtin_face_cache_index (w, face); |
1982 | |
1983 instance = glyph_image_instance (gb->glyph, data->window, | |
793 | 1984 ERROR_ME_DEBUG_WARN, 1); |
442 | 1985 if (TEXT_IMAGE_INSTANCEP (instance)) |
1986 { | |
1987 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); | |
1988 face_index orig_findex = data->findex; | |
826 | 1989 Bytebpos orig_charpos = data->byte_charpos; |
1990 Bytebpos orig_start_col_enabled = data->byte_start_col_enabled; | |
442 | 1991 |
1992 data->findex = findex; | |
826 | 1993 data->byte_start_col_enabled = 0; |
442 | 1994 if (!allow_cursor) |
826 | 1995 data->byte_charpos = 0; |
867 | 1996 add_ibyte_string_runes (data, XSTRING_DATA (string), |
793 | 1997 XSTRING_LENGTH (string), 0, 1); |
442 | 1998 data->findex = orig_findex; |
826 | 1999 data->byte_charpos = orig_charpos; |
2000 data->byte_start_col_enabled = orig_start_col_enabled; | |
819 | 2001 return retval; |
442 | 2002 } |
2003 | |
2004 rb.findex = findex; | |
428 | 2005 rb.xpos = data->pixpos; |
2006 rb.width = width; | |
826 | 2007 rb.charpos = 0; /* glyphs are never "at" anywhere */ |
2008 if (data->byte_endpos) | |
428 | 2009 /* #### is this necessary at all? */ |
665 | 2010 rb.endpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
826 | 2011 data->byte_endpos); |
428 | 2012 else |
4187 | 2013 rb.endpos = 0; |
428 | 2014 rb.type = RUNE_DGLYPH; |
2015 rb.object.dglyph.glyph = gb->glyph; | |
2016 rb.object.dglyph.extent = gb->extent; | |
2017 rb.object.dglyph.xoffset = xoffset; | |
819 | 2018 rb.object.dglyph.ascent = ascent; |
2019 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has | |
2020 a normal (textual) baseline. */ | |
428 | 2021 |
2022 if (allow_cursor) | |
2023 { | |
826 | 2024 rb.charpos = bytebpos_to_charbpos (XBUFFER (WINDOW_BUFFER (w)), |
2025 data->byte_charpos); | |
428 | 2026 |
2027 if (data->cursor_type == CURSOR_ON) | |
2028 { | |
826 | 2029 if (data->byte_charpos == data->byte_cursor_charpos) |
428 | 2030 { |
2031 rb.cursor_type = CURSOR_ON; | |
2032 data->cursor_x = Dynarr_length (data->db->runes); | |
2033 } | |
2034 else | |
2035 rb.cursor_type = CURSOR_OFF; | |
2036 } | |
2037 else if (data->cursor_type == NEXT_CURSOR) | |
2038 { | |
2039 rb.cursor_type = CURSOR_ON; | |
2040 data->cursor_x = Dynarr_length (data->db->runes); | |
2041 data->cursor_type = NO_CURSOR; | |
2042 } | |
2043 else if (data->cursor_type == IGNORE_CURSOR) | |
2044 rb.cursor_type = IGNORE_CURSOR; | |
2045 else if (data->cursor_type == NO_CURSOR) | |
2046 rb.cursor_type = NO_CURSOR; | |
2047 else | |
2048 rb.cursor_type = CURSOR_OFF; | |
2049 } | |
2050 else | |
2051 rb.cursor_type = CURSOR_OFF; | |
2052 | |
2053 Dynarr_add (data->db->runes, rb); | |
2054 data->pixpos += width; | |
2055 | |
819 | 2056 return retval; |
428 | 2057 } |
2058 else | |
2059 { | |
2060 if (!NILP (glyph_face (gb->glyph, data->window))) | |
2061 gb->findex = | |
2062 get_builtin_face_cache_index (w, glyph_face (gb->glyph, | |
2063 data->window)); | |
2064 else | |
2065 gb->findex = data->findex; | |
2066 | |
2067 if (pos_type == BEGIN_GLYPHS) | |
2068 { | |
2069 if (!data->dl->left_glyphs) | |
2070 data->dl->left_glyphs = Dynarr_new (glyph_block); | |
2071 Dynarr_add (data->dl->left_glyphs, *gb); | |
2072 return NULL; | |
2073 } | |
2074 else if (pos_type == END_GLYPHS) | |
2075 { | |
2076 if (!data->dl->right_glyphs) | |
2077 data->dl->right_glyphs = Dynarr_new (glyph_block); | |
2078 Dynarr_add (data->dl->right_glyphs, *gb); | |
2079 return NULL; | |
2080 } | |
2081 else | |
2500 | 2082 ABORT (); /* there are no unknown types */ |
428 | 2083 } |
2084 | |
819 | 2085 return NULL; |
428 | 2086 } |
2087 | |
2088 /* Add all glyphs at position POS_TYPE that are contained in the given | |
2089 data. */ | |
2090 | |
2091 static prop_block_dynarr * | |
2092 add_glyph_runes (pos_data *data, int pos_type) | |
2093 { | |
2094 /* #### This still needs to handle the start_col parameter. Duh, Chuck, | |
2095 why didn't you just modify add_glyph_rune in the first place? */ | |
2096 int elt; | |
2097 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS | |
2098 ? data->ef->begin_glyphs | |
2099 : data->ef->end_glyphs); | |
2100 prop_block_dynarr *prop; | |
2101 | |
2102 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++) | |
2103 { | |
2104 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0, | |
2105 0); | |
2106 | |
2107 if (prop) | |
2108 { | |
2109 /* #### Add some propagation information. */ | |
2110 return prop; | |
2111 } | |
2112 } | |
2113 | |
2114 Dynarr_reset (glyph_arr); | |
2115 | |
2116 return NULL; | |
2117 } | |
2118 | |
2119 /* Given a position for a buffer in a window, ensure that the given | |
2120 display line DL accurately represents the text on a line starting | |
2121 at the given position. | |
2122 | |
826 | 2123 NOTE NOTE NOTE NOTE: This function works with and returns Bytebpos's. |
428 | 2124 You must do appropriate conversion. */ |
2125 | |
665 | 2126 static Bytebpos |
428 | 2127 create_text_block (struct window *w, struct display_line *dl, |
826 | 2128 Bytebpos byte_start_pos, prop_block_dynarr **prop, |
428 | 2129 int type) |
2130 { | |
2131 struct frame *f = XFRAME (w->frame); | |
2132 struct buffer *b = XBUFFER (w->buffer); | |
2133 struct device *d = XDEVICE (f->device); | |
2134 | |
2135 pos_data data; | |
2136 | |
2137 /* Don't display anything in the minibuffer if this window is not on | |
2138 a selected frame. We consider all other windows to be active | |
2139 minibuffers as it simplifies the coding. */ | |
2140 int active_minibuffer = (!MINI_WINDOW_P (w) || | |
2141 (f == device_selected_frame (d)) || | |
2142 is_surrogate_for_selected_frame (f)); | |
2143 | |
2144 int truncate_win = window_truncation_on (w); | |
2145 | |
2146 /* If the buffer's value of selective_display is an integer then | |
2147 only lines that start with less than selective_display columns of | |
2148 space will be displayed. If selective_display is t then all text | |
2149 after a ^M is invisible. */ | |
2150 int selective = (INTP (b->selective_display) | |
2151 ? XINT (b->selective_display) | |
434 | 2152 : (!NILP (b->selective_display) ? -1 : 0)); |
428 | 2153 |
2154 /* The variable ctl-arrow allows the user to specify what characters | |
2155 can actually be displayed and which octal should be used for. | |
2156 #### This variable should probably have some rethought done to | |
2157 it. | |
2158 | |
2367 | 2159 See also |
2160 | |
2161 (Info-goto-node "(internals)Future Work -- Display Tables") | |
2162 | |
2163 */ | |
867 | 2164 Ichar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
428 | 2165 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
2166 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
2167 ? 255 : 160)); | |
2168 | |
2169 Lisp_Object face_dt, window_dt; | |
2170 | |
2171 /* The text display block for this display line. */ | |
2172 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
2173 | |
2174 /* The first time through the main loop we need to force the glyph | |
2175 data to be updated. */ | |
2176 int initial = 1; | |
2177 | |
2178 /* Apparently the new extent_fragment_update returns an end position | |
2179 equal to the position passed in if there are no more runs to be | |
2180 displayed. */ | |
2181 int no_more_frags = 0; | |
2182 | |
2183 Lisp_Object synch_minibuffers_value = | |
2184 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer); | |
2185 | |
2186 dl->used_prop_data = 0; | |
2187 dl->num_chars = 0; | |
442 | 2188 dl->line_continuation = 0; |
428 | 2189 |
2190 xzero (data); | |
2191 data.ef = extent_fragment_new (w->buffer, f); | |
2192 | |
2193 /* These values are used by all of the rune addition routines. We add | |
2194 them to this structure for ease of passing. */ | |
2195 data.d = d; | |
793 | 2196 data.window = wrap_window (w); |
428 | 2197 data.string = Qnil; |
2198 data.db = db; | |
2199 data.dl = dl; | |
2200 | |
826 | 2201 data.byte_charpos = byte_start_pos; |
428 | 2202 data.pixpos = dl->bounds.left_in; |
2203 data.last_charset = Qunbound; | |
2204 data.last_findex = DEFAULT_INDEX; | |
2205 data.result_str = Qnil; | |
2206 | |
2207 /* Set the right boundary adjusting it to take into account any end | |
2208 glyph. Save the width of the end glyph for later use. */ | |
2209 data.max_pixpos = dl->bounds.right_in; | |
2210 if (truncate_win) | |
819 | 2211 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); |
428 | 2212 else |
819 | 2213 data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); |
2214 data.max_pixpos -= data.end_glyph_width; | |
428 | 2215 |
2216 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f)) | |
2217 { | |
826 | 2218 data.byte_cursor_charpos = BYTE_BUF_ZV (b); |
428 | 2219 data.cursor_type = CURSOR_ON; |
2220 } | |
2221 else if (MINI_WINDOW_P (w) && !active_minibuffer) | |
2222 data.cursor_type = NO_CURSOR; | |
2223 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) && | |
5198 | 2224 EQ (DEVICE_CONSOLE (d), Vselected_console) && |
2225 d == XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d))))&& | |
2226 f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
428 | 2227 { |
826 | 2228 data.byte_cursor_charpos = BYTE_BUF_PT (b); |
428 | 2229 data.cursor_type = CURSOR_ON; |
2230 } | |
2231 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f))) | |
2232 { | |
826 | 2233 data.byte_cursor_charpos = byte_marker_position (w->pointm[type]); |
428 | 2234 data.cursor_type = CURSOR_ON; |
2235 } | |
2236 else | |
2237 data.cursor_type = NO_CURSOR; | |
2238 data.cursor_x = -1; | |
2239 | |
2240 data.start_col = w->hscroll; | |
2241 data.start_col_xoffset = w->left_xoffset; | |
826 | 2242 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
428 | 2243 data.hscroll_glyph_width_adjust = 0; |
2244 | |
2245 /* We regenerate the line from the very beginning. */ | |
2246 Dynarr_reset (db->runes); | |
2247 | |
2248 /* Why is this less than or equal and not just less than? If the | |
2249 starting position is already equal to the maximum we can't add | |
2250 anything else, right? Wrong. We might still have a newline to | |
2251 add. A newline can use the room allocated for an end glyph since | |
2252 if we add it we know we aren't going to be adding any end | |
2253 glyph. */ | |
2254 | |
2255 /* #### Chuck -- I think this condition should be while (1). | |
2256 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
2257 and the begin-glyph ends exactly at the end of the window, the | |
2258 end-glyph and text might not be displayed. while (1) ensures | |
2259 that the loop terminates only when either (a) there is | |
2260 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
2261 | |
2262 #### Also I think you need to ensure that the operation | |
2263 "add begin glyphs; add end glyphs; add text" is atomic and | |
2264 can't get interrupted in the middle. If you run off the end | |
2265 of the line during that operation, then you keep accumulating | |
2266 propagation data until you're done. Otherwise, if the (e.g.) | |
2267 there's a begin glyph at a particular position and attempting | |
2268 to display that glyph results in window-end being hit and | |
2269 propagation data being generated, then the character at that | |
2270 position won't be displayed. | |
2271 | |
2272 #### See also the comment after the end of this loop, below. | |
2273 */ | |
2274 while (data.pixpos <= data.max_pixpos | |
2275 && (active_minibuffer || !NILP (synch_minibuffers_value))) | |
2276 { | |
2277 /* #### This check probably should not be necessary. */ | |
826 | 2278 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
428 | 2279 { |
2280 /* #### urk! More of this lossage! */ | |
826 | 2281 data.byte_charpos--; |
428 | 2282 goto done; |
2283 } | |
2284 | |
2285 /* If selective display was an integer and we aren't working on | |
4187 | 2286 a continuation line then find the next line we are actually |
2287 supposed to display. */ | |
428 | 2288 if (selective > 0 |
826 | 2289 && (data.byte_charpos == BYTE_BUF_BEGV (b) |
2290 || BUF_FETCH_CHAR (b, prev_bytebpos (b, data.byte_charpos)) == '\n')) | |
2291 { | |
2292 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
428 | 2293 { |
826 | 2294 data.byte_charpos = |
2295 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2296 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
428 | 2297 { |
826 | 2298 data.byte_charpos = BYTE_BUF_ZV (b); |
428 | 2299 goto done; |
2300 } | |
2301 } | |
2302 } | |
2303 | |
2304 /* Check for face changes. */ | |
826 | 2305 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
428 | 2306 { |
819 | 2307 Lisp_Object last_glyph = Qnil; |
2308 | |
2309 /* Deal with glyphs that we have already displayed. The | |
2310 theory is that if we end up with a PROP_GLYPH in the | |
2311 propagation data then we are clipping the glyph and there | |
2312 can be no propagation data before that point. The theory | |
2313 works because we always recalculate the extent-fragments | |
2314 for propagated data, we never actually propagate the | |
2315 fragments that still need to be displayed. */ | |
4967 | 2316 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
2317 { | |
2318 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
819 | 2319 Dynarr_free (*prop); |
2320 *prop = 0; | |
2321 } | |
428 | 2322 /* Now compute the face and begin/end-glyph information. */ |
2323 data.findex = | |
665 | 2324 /* Remember that the extent-fragment routines deal in Bytebpos's. */ |
826 | 2325 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
428 | 2326 |
2327 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
2328 | |
826 | 2329 if (data.byte_charpos == data.ef->end) |
428 | 2330 no_more_frags = 1; |
2331 } | |
2332 initial = 0; | |
2333 | |
2334 /* Determine what is next to be displayed. We first handle any | |
4187 | 2335 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
2336 display then we determine what to do based on the character at the | |
2337 current buffer position. */ | |
428 | 2338 |
2339 /* If the current position is covered by an invisible extent, do | |
4187 | 2340 nothing (except maybe add some ellipses). |
428 | 2341 |
2342 #### The behavior of begin and end-glyphs at the edge of an | |
2343 invisible extent should be investigated further. This is | |
2344 fairly low priority though. */ | |
2345 if (data.ef->invisible) | |
2346 { | |
2347 /* #### Chuck, perhaps you could look at this code? I don't | |
2348 really know what I'm doing. */ | |
2349 if (*prop) | |
2350 { | |
2351 Dynarr_free (*prop); | |
2352 *prop = 0; | |
2353 } | |
2354 | |
2355 /* The extent fragment code only sets this when we should | |
2356 really display the ellipses. It makes sure the ellipses | |
2357 don't get displayed more than once in a row. */ | |
2358 if (data.ef->invisible_ellipses) | |
2359 { | |
2360 struct glyph_block gb; | |
2361 | |
2362 data.ef->invisible_ellipses_already_displayed = 1; | |
2363 data.ef->invisible_ellipses = 0; | |
2364 gb.extent = Qnil; | |
2365 gb.glyph = Vinvisible_text_glyph; | |
2366 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2367 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2368 /* Perhaps they shouldn't propagate if the very next thing | |
2369 is to display a newline (for compatibility with | |
2370 selective-display-ellipses)? Maybe that's too | |
2371 abstruse. */ | |
2372 if (*prop) | |
2373 goto done; | |
2374 } | |
2375 | |
2376 /* If point is in an invisible region we place it on the | |
4187 | 2377 next visible character. */ |
428 | 2378 if (data.cursor_type == CURSOR_ON |
826 | 2379 && data.byte_charpos == data.byte_cursor_charpos) |
428 | 2380 { |
2381 data.cursor_type = NEXT_CURSOR; | |
2382 } | |
2383 | |
2384 /* #### What if we we're dealing with a display table? */ | |
2385 if (data.start_col) | |
2386 data.start_col--; | |
2387 | |
826 | 2388 if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2389 goto done; |
2390 else | |
826 | 2391 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2392 } |
2393 | |
2394 /* If there is propagation data, then it represents the current | |
819 | 2395 buffer position being displayed. Add them and advance the |
2396 position counter. This might also add the minibuffer | |
2397 prompt. */ | |
428 | 2398 else if (*prop) |
2399 { | |
2400 dl->used_prop_data = 1; | |
2401 *prop = add_propagation_runes (prop, &data); | |
2402 | |
2403 if (*prop) | |
2404 goto done; /* gee, a really narrow window */ | |
826 | 2405 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2406 goto done; |
826 | 2407 else if (data.byte_charpos < BYTE_BUF_BEGV (b)) |
428 | 2408 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
826 | 2409 data.byte_charpos = BYTE_BUF_BEGV (b); |
428 | 2410 else |
826 | 2411 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2412 } |
2413 | |
2414 /* If there are end glyphs, add them to the line. These are | |
2415 the end glyphs for the previous run of text. We add them | |
2416 here rather than doing them at the end of handling the | |
2417 previous run so that glyphs at the beginning and end of | |
2418 a line are handled correctly. */ | |
819 | 2419 else if (Dynarr_length (data.ef->end_glyphs) > 0 |
2420 || Dynarr_length (data.ef->begin_glyphs) > 0) | |
2421 { | |
2422 glyph_block_dynarr* tmpglyphs = 0; | |
2423 /* #### I think this is safe, but could be wrong. */ | |
826 | 2424 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
819 | 2425 |
4187 | 2426 if (Dynarr_length (data.ef->end_glyphs) > 0) |
819 | 2427 { |
2428 *prop = add_glyph_runes (&data, END_GLYPHS); | |
2429 tmpglyphs = data.ef->end_glyphs; | |
2430 } | |
2431 | |
2432 /* If there are begin glyphs, add them to the line. */ | |
4187 | 2433 if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0) |
819 | 2434 { |
2435 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); | |
2436 tmpglyphs = data.ef->begin_glyphs; | |
2437 } | |
2438 | |
4187 | 2439 if (*prop) |
819 | 2440 { |
2441 /* If we just clipped a glyph and we are at the end of a | |
2442 line and there are more glyphs to display then do | |
2443 appropriate processing to not get a continuation | |
2444 glyph. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2445 if (*prop != ADD_FAILED |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2446 && Dynarr_begin (*prop)->type == PROP_GLYPH |
819 | 2447 && data.ch == '\n') |
4187 | 2448 { |
819 | 2449 /* If there are no more glyphs then do the normal |
4187 | 2450 processing. |
819 | 2451 |
2452 #### This doesn't actually work if the same glyph is | |
2453 present more than once in the block. To solve | |
2454 this we would have to carry the index around | |
2455 which might be problematic since the fragment is | |
2456 recalculated for each line. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2457 if (EQ (Dynarr_lastp (tmpglyphs)->glyph, |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2458 Dynarr_begin (*prop)->data.p_glyph.glyph)) |
819 | 2459 { |
2460 Dynarr_free (*prop); | |
2461 *prop = 0; | |
2462 } | |
2463 else { | |
2464 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2465 add_ichar_rune (&data); /* discard prop data. */ |
819 | 2466 goto done; |
2467 } | |
2468 } | |
2469 else | |
2470 goto done; | |
2471 } | |
428 | 2472 } |
2473 | |
2474 /* If at end-of-buffer, we've already processed begin and | |
2475 end-glyphs at this point and there's no text to process, | |
2476 so we're done. */ | |
826 | 2477 else if (data.byte_charpos == BYTE_BUF_ZV (b)) |
428 | 2478 goto done; |
2479 | |
2480 else | |
2481 { | |
2482 Lisp_Object entry = Qnil; | |
2483 /* Get the character at the current buffer position. */ | |
826 | 2484 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
428 | 2485 if (!NILP (face_dt) || !NILP (window_dt)) |
2486 entry = display_table_entry (data.ch, face_dt, window_dt); | |
2487 | |
2488 /* If there is a display table entry for it, hand it off to | |
4187 | 2489 add_disp_table_entry_runes and let it worry about it. */ |
428 | 2490 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
2491 { | |
2492 *prop = add_disp_table_entry_runes (&data, entry); | |
2493 | |
2494 if (*prop) | |
2495 goto done; | |
2496 } | |
2497 | |
2498 /* Check if we have hit a newline character. If so, add a marker | |
4187 | 2499 to the line and end this loop. */ |
428 | 2500 else if (data.ch == '\n') |
2501 { | |
2502 /* We aren't going to be adding an end glyph so give its | |
4187 | 2503 space back in order to make sure that the cursor can |
2504 fit. */ | |
819 | 2505 data.max_pixpos += data.end_glyph_width; |
428 | 2506 |
2507 if (selective > 0 | |
826 | 2508 && (byte_spaces_at_point |
2509 (b, next_bytebpos (b, data.byte_charpos)) | |
428 | 2510 >= selective)) |
2511 { | |
2512 if (!NILP (b->selective_display_ellipses)) | |
2513 { | |
2514 struct glyph_block gb; | |
2515 | |
2516 gb.extent = Qnil; | |
2517 gb.glyph = Vinvisible_text_glyph; | |
2518 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2519 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2520 } | |
2521 else | |
2522 { | |
2523 /* Cheesy, cheesy, cheesy. We mark the end of the | |
2524 line with a special "character rune" whose width | |
2525 is the EOL cursor width and whose character is | |
2526 the non-printing character '\n'. */ | |
2527 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2528 *prop = add_ichar_rune (&data); |
428 | 2529 } |
2530 | |
826 | 2531 /* We need to set data.byte_charpos to the start of the |
4187 | 2532 next visible region in order to make this line |
2533 appear to contain all of the invisible area. | |
2534 Otherwise, the line cache won't work | |
2535 correctly. */ | |
826 | 2536 INC_BYTEBPOS (b, data.byte_charpos); |
2537 while (byte_spaces_at_point (b, data.byte_charpos) >= selective) | |
428 | 2538 { |
826 | 2539 data.byte_charpos = |
2540 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2541 if (data.byte_charpos >= BYTE_BUF_ZV (b)) | |
428 | 2542 { |
826 | 2543 data.byte_charpos = BYTE_BUF_ZV (b); |
428 | 2544 break; |
2545 } | |
2546 } | |
826 | 2547 if (BYTE_BUF_FETCH_CHAR |
2548 (b, prev_bytebpos (b, data.byte_charpos)) == '\n') | |
2549 DEC_BYTEBPOS (b, data.byte_charpos); | |
428 | 2550 } |
2551 else | |
2552 { | |
2553 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
867 | 2554 *prop = add_ichar_rune (&data); |
428 | 2555 } |
2556 | |
2557 goto done; | |
2558 } | |
2559 | |
2560 /* If the current character is ^M, and selective display is | |
4187 | 2561 enabled, then add the invisible-text-glyph if |
2562 selective-display-ellipses is set. In any case, this | |
2563 line is done. */ | |
428 | 2564 else if (data.ch == (('M' & 037)) && selective == -1) |
2565 { | |
826 | 2566 Bytebpos byte_next_charpos; |
428 | 2567 |
2568 /* Find the buffer position at the end of the line. */ | |
826 | 2569 byte_next_charpos = |
2570 byte_find_next_newline_no_quit (b, data.byte_charpos, 1); | |
2571 if (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_next_charpos)) | |
428 | 2572 == '\n') |
826 | 2573 DEC_BYTEBPOS (b, byte_next_charpos); |
428 | 2574 |
2575 /* If the cursor is somewhere in the elided text make | |
4187 | 2576 sure that the cursor gets drawn appropriately. */ |
428 | 2577 if (data.cursor_type == CURSOR_ON |
826 | 2578 && (data.byte_cursor_charpos >= data.byte_charpos && |
2579 data.byte_cursor_charpos < byte_next_charpos)) | |
428 | 2580 { |
2581 data.cursor_type = NEXT_CURSOR; | |
2582 } | |
2583 | |
2584 /* We won't be adding a truncation or continuation glyph | |
4187 | 2585 so give up the room allocated for them. */ |
819 | 2586 data.max_pixpos += data.end_glyph_width; |
428 | 2587 |
2588 if (!NILP (b->selective_display_ellipses)) | |
2589 { | |
2590 /* We don't propagate anything from the invisible | |
4187 | 2591 text glyph if it fails to fit. This is |
2592 intentional. */ | |
428 | 2593 struct glyph_block gb; |
2594 | |
2595 gb.extent = Qnil; | |
2596 gb.glyph = Vinvisible_text_glyph; | |
2597 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, | |
2598 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
2599 } | |
2600 | |
2601 /* Set the buffer position to the end of the line. We | |
4187 | 2602 need to do this before potentially adding a newline |
2603 so that the cursor flag will get set correctly (if | |
2604 needed). */ | |
826 | 2605 data.byte_charpos = byte_next_charpos; |
428 | 2606 |
2607 if (NILP (b->selective_display_ellipses) | |
826 | 2608 || data.byte_cursor_charpos == byte_next_charpos) |
428 | 2609 { |
2610 /* We have to at least add a newline character so | |
4187 | 2611 that the cursor shows up properly. */ |
428 | 2612 data.ch = '\n'; |
2613 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2614 data.findex = DEFAULT_INDEX; | |
2615 data.start_col = 0; | |
2616 data.start_col_xoffset = 0; | |
826 | 2617 data.byte_start_col_enabled = 0; |
428 | 2618 |
867 | 2619 add_ichar_rune (&data); |
428 | 2620 } |
2621 | |
2622 /* This had better be a newline but doing it this way | |
4187 | 2623 we'll see obvious incorrect results if it isn't. No |
2624 need to abort here. */ | |
826 | 2625 data.ch = BYTE_BUF_FETCH_CHAR (b, data.byte_charpos); |
428 | 2626 |
2627 goto done; | |
2628 } | |
2629 | |
2630 /* If the current character is considered to be printable, then | |
4187 | 2631 just add it. */ |
428 | 2632 else if (data.ch >= printable_min) |
2633 { | |
867 | 2634 *prop = add_ichar_rune (&data); |
428 | 2635 if (*prop) |
2636 goto done; | |
2637 } | |
2638 | |
2639 /* If the current character is a tab, determine the next tab | |
4187 | 2640 starting position and add a blank rune which extends from the |
2641 current pixel position to that starting position. */ | |
428 | 2642 else if (data.ch == '\t') |
2643 { | |
2644 int tab_start_pixpos = data.pixpos; | |
2645 int next_tab_start; | |
2646 int char_tab_width; | |
2647 int prop_width = 0; | |
2648 | |
2649 if (data.start_col > 1) | |
434 | 2650 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)) |
428 | 2651 + data.start_col_xoffset; |
2652 | |
2653 next_tab_start = | |
2654 next_tab_position (w, tab_start_pixpos, | |
2655 dl->bounds.left_in + | |
2656 data.hscroll_glyph_width_adjust); | |
2657 if (next_tab_start > data.max_pixpos) | |
2658 { | |
2659 prop_width = next_tab_start - data.max_pixpos; | |
2660 next_tab_start = data.max_pixpos; | |
2661 } | |
2662 data.blank_width = next_tab_start - data.pixpos; | |
2663 char_tab_width = | |
2664 (next_tab_start - tab_start_pixpos) / space_width (w); | |
2665 | |
2666 *prop = add_blank_rune (&data, w, char_tab_width); | |
2667 | |
2668 /* add_blank_rune is only supposed to be called with | |
4187 | 2669 sizes guaranteed to fit in the available space. */ |
428 | 2670 assert (!(*prop)); |
2671 | |
2672 if (prop_width) | |
2673 { | |
2674 struct prop_block pb; | |
2675 *prop = Dynarr_new (prop_block); | |
2676 | |
2677 pb.type = PROP_BLANK; | |
2678 pb.data.p_blank.width = prop_width; | |
2679 pb.data.p_blank.findex = data.findex; | |
2680 Dynarr_add (*prop, pb); | |
2681 | |
2682 goto done; | |
2683 } | |
2684 } | |
2685 | |
2686 /* If character is a control character, pass it off to | |
4187 | 2687 add_control_char_runes. |
428 | 2688 |
2689 The is_*() routines have undefined results on | |
2690 arguments outside of the range [-1, 255]. (This | |
2691 often bites people who carelessly use `char' instead | |
2692 of `unsigned char'.) | |
2693 */ | |
867 | 2694 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
428 | 2695 { |
2696 *prop = add_control_char_runes (&data, b); | |
2697 | |
2698 if (*prop) | |
2699 goto done; | |
2700 } | |
2701 | |
2702 /* If the character is above the ASCII range and we have not | |
4187 | 2703 already handled it, then print it as an octal number. */ |
428 | 2704 else if (data.ch >= 0200) |
2705 { | |
2706 *prop = add_octal_runes (&data); | |
2707 | |
2708 if (*prop) | |
2709 goto done; | |
2710 } | |
2711 | |
2712 /* Assume the current character is considered to be printable, | |
4187 | 2713 then just add it. */ |
428 | 2714 else |
2715 { | |
867 | 2716 *prop = add_ichar_rune (&data); |
428 | 2717 if (*prop) |
2718 goto done; | |
2719 } | |
2720 | |
826 | 2721 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2722 } |
2723 } | |
2724 | |
2725 done: | |
2726 | |
2727 /* Determine the starting point of the next line if we did not hit the | |
2728 end of the buffer. */ | |
826 | 2729 if (data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 2730 && (active_minibuffer || !NILP (synch_minibuffers_value))) |
2731 { | |
2732 /* #### This check is not correct. If the line terminated | |
2733 due to a begin-glyph or end-glyph hitting window-end, then | |
826 | 2734 data.ch will not point to the character at data.byte_charpos. If |
428 | 2735 you make the two changes mentioned at the top of this loop, |
2736 you should be able to say '(if (*prop))'. That should also | |
826 | 2737 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 2738 check. */ |
2739 | |
2740 /* The common case is that the line ended because we hit a newline. | |
4187 | 2741 In that case, the next character is just the next buffer |
2742 position. */ | |
428 | 2743 if (data.ch == '\n') |
2744 { | |
2745 /* If data.start_col_enabled is still true, then the window is | |
4187 | 2746 scrolled far enough so that nothing on this line is visible. |
2747 We need to stick a truncation glyph at the beginning of the | |
2748 line in that case unless the line is completely blank. */ | |
826 | 2749 if (data.byte_start_col_enabled) |
428 | 2750 { |
2751 if (data.cursor_type == CURSOR_ON) | |
2752 { | |
826 | 2753 if (data.byte_cursor_charpos >= byte_start_pos |
2754 && data.byte_cursor_charpos <= data.byte_charpos) | |
2755 data.byte_cursor_charpos = data.byte_charpos; | |
428 | 2756 } |
2757 data.findex = DEFAULT_INDEX; | |
2758 data.start_col = 0; | |
826 | 2759 data.byte_start_col_enabled = 0; |
2760 | |
2761 if (data.byte_charpos != byte_start_pos) | |
428 | 2762 { |
2763 struct glyph_block gb; | |
2764 | |
2765 gb.extent = Qnil; | |
2766 gb.glyph = Vhscroll_glyph; | |
2767 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
2768 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX)); | |
2769 } | |
2770 else | |
2771 { | |
2772 /* This duplicates code down below to add a newline to | |
4187 | 2773 the end of an otherwise empty line.*/ |
428 | 2774 data.ch = '\n'; |
2775 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2776 | |
867 | 2777 add_ichar_rune (&data); |
428 | 2778 } |
2779 } | |
2780 | |
826 | 2781 INC_BYTEBPOS (b, data.byte_charpos); |
428 | 2782 } |
2783 | |
2784 /* Otherwise we have a buffer line which cannot fit on one display | |
4187 | 2785 line. */ |
428 | 2786 else |
2787 { | |
2788 struct glyph_block gb; | |
2789 struct glyph_cachel *cachel; | |
2790 | |
2791 /* If the line is to be truncated then we actually have to look | |
4187 | 2792 for the next newline. We also add the end-of-line glyph which |
2793 we know will fit because we adjusted the right border before | |
2794 we starting laying out the line. */ | |
819 | 2795 data.max_pixpos += data.end_glyph_width; |
428 | 2796 data.findex = DEFAULT_INDEX; |
2797 gb.extent = Qnil; | |
2798 | |
2799 if (truncate_win) | |
2800 { | |
826 | 2801 Bytebpos byte_pos; |
428 | 2802 |
2803 /* Now find the start of the next line. */ | |
826 | 2804 byte_pos = byte_find_next_newline_no_quit (b, data.byte_charpos, 1); |
428 | 2805 |
2806 /* If the cursor is past the truncation line then we | |
4187 | 2807 make it appear on the truncation glyph. If we've hit |
2808 the end of the buffer then we also make the cursor | |
2809 appear unless eob is immediately preceded by a | |
2810 newline. In that case the cursor should actually | |
2811 appear on the next line. */ | |
428 | 2812 if (data.cursor_type == CURSOR_ON |
826 | 2813 && data.byte_cursor_charpos >= data.byte_charpos |
2814 && (data.byte_cursor_charpos < byte_pos || | |
2815 (byte_pos == BYTE_BUF_ZV (b) | |
2816 && (byte_pos == BYTE_BUF_BEGV (b) | |
2817 || (BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, byte_pos)) | |
428 | 2818 != '\n'))))) |
826 | 2819 data.byte_cursor_charpos = byte_pos; |
428 | 2820 else |
2821 data.cursor_type = NO_CURSOR; | |
2822 | |
826 | 2823 data.byte_charpos = byte_pos; |
428 | 2824 gb.glyph = Vtruncation_glyph; |
2825 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
2826 } | |
2827 else | |
2828 { | |
2829 /* The cursor can never be on the continuation glyph. */ | |
2830 data.cursor_type = NO_CURSOR; | |
2831 | |
826 | 2832 /* data.byte_charpos is already at the start of the next line. */ |
428 | 2833 |
442 | 2834 dl->line_continuation = 1; |
428 | 2835 gb.glyph = Vcontinuation_glyph; |
2836 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
2837 } | |
2838 | |
442 | 2839 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
428 | 2840 |
826 | 2841 if (truncate_win && data.byte_charpos == BYTE_BUF_ZV (b) |
2842 && BYTE_BUF_FETCH_CHAR (b, prev_bytebpos (b, BYTE_BUF_ZV (b))) != '\n') | |
428 | 2843 /* #### Damn this losing shit. */ |
826 | 2844 data.byte_charpos++; |
428 | 2845 } |
2846 } | |
2847 else if ((active_minibuffer || !NILP (synch_minibuffers_value)) | |
826 | 2848 && (!echo_area_active (f) || data.byte_charpos == BYTE_BUF_ZV (b))) |
428 | 2849 { |
2850 /* We need to add a marker to the end of the line since there is no | |
4187 | 2851 newline character in order for the cursor to get drawn. We label |
2852 it as a newline so that it gets handled correctly by the | |
2853 whitespace routines below. */ | |
428 | 2854 |
2855 data.ch = '\n'; | |
2856 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | |
2857 data.findex = DEFAULT_INDEX; | |
2858 data.start_col = 0; | |
2859 data.start_col_xoffset = 0; | |
826 | 2860 data.byte_start_col_enabled = 0; |
428 | 2861 |
2862 data.max_pixpos += data.blank_width; | |
867 | 2863 add_ichar_rune (&data); |
428 | 2864 data.max_pixpos -= data.blank_width; |
2865 | |
2866 /* #### urk! Chuck, this shit is bad news. Going around | |
2867 manipulating invalid positions is guaranteed to result in | |
2868 trouble sooner or later. */ | |
826 | 2869 data.byte_charpos = BYTE_BUF_ZV (b) + 1; |
428 | 2870 } |
2871 | |
2872 /* Calculate left whitespace boundary. */ | |
2873 { | |
2874 int elt = 0; | |
2875 | |
2876 /* Whitespace past a newline is considered right whitespace. */ | |
2877 while (elt < Dynarr_length (db->runes)) | |
2878 { | |
2879 struct rune *rb = Dynarr_atp (db->runes, elt); | |
2880 | |
2881 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
2882 || rb->type == RUNE_BLANK) | |
2883 { | |
2884 dl->bounds.left_white += rb->width; | |
2885 elt++; | |
2886 } | |
2887 else | |
2888 elt = Dynarr_length (db->runes); | |
2889 } | |
2890 } | |
2891 | |
2892 /* Calculate right whitespace boundary. */ | |
2893 { | |
2894 int elt = Dynarr_length (db->runes) - 1; | |
2895 int done = 0; | |
2896 | |
2897 while (!done && elt >= 0) | |
2898 { | |
2899 struct rune *rb = Dynarr_atp (db->runes, elt); | |
2900 | |
2901 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
2902 && isspace (rb->object.chr.ch)) | |
2903 && !rb->type == RUNE_BLANK) | |
2904 { | |
2905 dl->bounds.right_white = rb->xpos + rb->width; | |
2906 done = 1; | |
2907 } | |
2908 | |
2909 elt--; | |
2910 | |
2911 } | |
2912 | |
2913 /* The line is blank so everything is considered to be right | |
2914 whitespace. */ | |
2915 if (!done) | |
2916 dl->bounds.right_white = dl->bounds.left_in; | |
2917 } | |
2918 | |
2919 /* Set the display blocks bounds. */ | |
2920 db->start_pos = dl->bounds.left_in; | |
2921 if (Dynarr_length (db->runes)) | |
2922 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
2923 struct rune *rb = Dynarr_lastp (db->runes); |
428 | 2924 |
2925 db->end_pos = rb->xpos + rb->width; | |
2926 } | |
2927 else | |
2928 db->end_pos = dl->bounds.right_white; | |
2929 | |
819 | 2930 calculate_baseline (&data); |
428 | 2931 |
2932 dl->ascent = data.new_ascent; | |
2933 dl->descent = data.new_descent; | |
2934 | |
2935 { | |
2936 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
2937 | |
2938 if (dl->ascent < ascent) | |
2939 dl->ascent = ascent; | |
2940 } | |
2941 { | |
2942 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
2943 | |
2944 if (dl->descent < descent) | |
2945 dl->descent = descent; | |
2946 } | |
2947 | |
819 | 2948 calculate_yoffset (dl, db); |
2949 | |
428 | 2950 dl->cursor_elt = data.cursor_x; |
2951 /* #### lossage lossage lossage! Fix this shit! */ | |
826 | 2952 if (data.byte_charpos > BYTE_BUF_ZV (b)) |
2953 dl->end_charpos = BUF_ZV (b); | |
428 | 2954 else |
826 | 2955 dl->end_charpos = bytebpos_to_charbpos (b, data.byte_charpos) - 1; |
428 | 2956 if (truncate_win) |
826 | 2957 data.dl->num_chars = column_at_point (b, dl->end_charpos, 0); |
428 | 2958 else |
2959 /* This doesn't correctly take into account tabs and control | |
2960 characters but if the window isn't being truncated then this | |
2961 value isn't going to end up being used anyhow. */ | |
826 | 2962 data.dl->num_chars = dl->end_charpos - dl->charpos; |
428 | 2963 |
2964 /* #### handle horizontally scrolled line with text none of which | |
2965 was actually laid out. */ | |
2966 | |
2967 /* #### handle any remainder of overlay arrow */ | |
2968 | |
2969 if (*prop == ADD_FAILED) | |
2970 *prop = NULL; | |
2971 | |
2972 if (truncate_win && *prop) | |
2973 { | |
2974 Dynarr_free (*prop); | |
2975 *prop = NULL; | |
2976 } | |
2977 | |
2978 extent_fragment_delete (data.ef); | |
2979 | |
2980 /* #### If we started at EOB, then make sure we return a value past | |
2981 it so that regenerate_window will exit properly. This is bogus. | |
2982 The main loop should get fixed so that it isn't necessary to call | |
2983 this function if we are already at EOB. */ | |
2984 | |
826 | 2985 if (data.byte_charpos == BYTE_BUF_ZV (b) && byte_start_pos == BYTE_BUF_ZV (b)) |
2986 return data.byte_charpos + 1; /* Yuck! */ | |
428 | 2987 else |
826 | 2988 return data.byte_charpos; |
428 | 2989 } |
2990 | |
2991 /* Display the overlay arrow at the beginning of the given line. */ | |
2992 | |
2993 static int | |
2994 create_overlay_glyph_block (struct window *w, struct display_line *dl) | |
2995 { | |
2996 struct frame *f = XFRAME (w->frame); | |
2997 struct device *d = XDEVICE (f->device); | |
2998 pos_data data; | |
2999 | |
3000 /* If Voverlay_arrow_string isn't valid then just fail silently. */ | |
3001 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string)) | |
3002 return 0; | |
3003 | |
3004 xzero (data); | |
3005 data.ef = NULL; | |
3006 data.d = d; | |
793 | 3007 data.window = wrap_window (w); |
428 | 3008 data.db = get_display_block_from_line (dl, OVERWRITE); |
3009 data.dl = dl; | |
3010 data.pixpos = dl->bounds.left_in; | |
3011 data.max_pixpos = dl->bounds.right_in; | |
3012 data.cursor_type = NO_CURSOR; | |
3013 data.cursor_x = -1; | |
3014 data.findex = DEFAULT_INDEX; | |
3015 data.last_charset = Qunbound; | |
3016 data.last_findex = DEFAULT_INDEX; | |
3017 data.result_str = Qnil; | |
3018 data.string = Qnil; | |
3019 | |
3020 Dynarr_reset (data.db->runes); | |
3021 | |
3022 if (STRINGP (Voverlay_arrow_string)) | |
3023 { | |
867 | 3024 add_ibyte_string_runes |
428 | 3025 (&data, |
3026 XSTRING_DATA (Voverlay_arrow_string), | |
3027 XSTRING_LENGTH (Voverlay_arrow_string), | |
793 | 3028 1, 0); |
428 | 3029 } |
3030 else if (GLYPHP (Voverlay_arrow_string)) | |
3031 { | |
3032 struct glyph_block gb; | |
3033 | |
3034 gb.glyph = Voverlay_arrow_string; | |
3035 gb.extent = Qnil; | |
3036 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0); | |
3037 } | |
4187 | 3038 |
428 | 3039 if (data.max_pixmap_height) |
3040 { | |
3041 int height = data.new_ascent + data.new_descent; | |
3042 int pix_ascent, pix_descent; | |
4187 | 3043 |
428 | 3044 pix_descent = data.max_pixmap_height * data.new_descent / height; |
3045 pix_ascent = data.max_pixmap_height - pix_descent; | |
819 | 3046 calculate_baseline (&data); |
428 | 3047 |
3048 data.new_ascent = max (data.new_ascent, pix_ascent); | |
3049 data.new_descent = max (data.new_descent, pix_descent); | |
3050 } | |
3051 | |
3052 dl->ascent = data.new_ascent; | |
3053 dl->descent = data.new_descent; | |
3054 | |
3055 data.db->start_pos = dl->bounds.left_in; | |
3056 data.db->end_pos = data.pixpos; | |
3057 | |
819 | 3058 calculate_yoffset (dl, data.db); |
3059 | |
428 | 3060 return data.pixpos - dl->bounds.left_in; |
3061 } | |
3062 | |
3063 /* Add a type of glyph to a margin display block. */ | |
3064 | |
3065 static int | |
3066 add_margin_runes (struct display_line *dl, struct display_block *db, int start, | |
3067 int count, enum glyph_layout layout, int side, Lisp_Object window) | |
3068 { | |
3069 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS | |
3070 ? dl->left_glyphs | |
3071 : dl->right_glyphs); | |
3072 int elt, end; | |
3073 int reverse; | |
442 | 3074 struct window *w = XWINDOW (window); |
3075 struct frame *f = XFRAME (w->frame); | |
3076 struct device *d = XDEVICE (f->device); | |
3077 pos_data data; | |
3078 | |
3079 xzero (data); | |
3080 data.d = d; | |
3081 data.window = window; | |
3082 data.db = db; | |
3083 data.dl = dl; | |
3084 data.pixpos = start; | |
3085 data.cursor_type = NO_CURSOR; | |
3086 data.cursor_x = -1; | |
3087 data.last_charset = Qunbound; | |
3088 data.last_findex = DEFAULT_INDEX; | |
3089 data.result_str = Qnil; | |
3090 data.string = Qnil; | |
3091 data.new_ascent = dl->ascent; | |
3092 data.new_descent = dl->descent; | |
428 | 3093 |
3094 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) | |
3095 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) | |
3096 { | |
3097 reverse = 1; | |
3098 elt = Dynarr_length (gbd) - 1; | |
3099 end = 0; | |
3100 } | |
3101 else | |
3102 { | |
3103 reverse = 0; | |
3104 elt = 0; | |
3105 end = Dynarr_length (gbd); | |
3106 } | |
3107 | |
3108 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) | |
3109 { | |
3110 struct glyph_block *gb = Dynarr_atp (gbd, elt); | |
3111 | |
3112 if (NILP (gb->extent)) | |
2500 | 3113 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3114 |
3115 if (gb->active && | |
3116 ((side == LEFT_GLYPHS && | |
3117 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout) | |
3118 || (side == RIGHT_GLYPHS && | |
3119 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) | |
3120 { | |
442 | 3121 data.findex = gb->findex; |
3122 data.max_pixpos = data.pixpos + gb->width; | |
3123 add_glyph_rune (&data, gb, side, 0, NULL); | |
428 | 3124 count--; |
3125 gb->active = 0; | |
3126 } | |
3127 | |
3128 (reverse ? elt-- : elt++); | |
3129 } | |
3130 | |
819 | 3131 calculate_baseline (&data); |
442 | 3132 |
3133 dl->ascent = data.new_ascent; | |
3134 dl->descent = data.new_descent; | |
3135 | |
819 | 3136 calculate_yoffset (dl, data.db); |
3137 | |
442 | 3138 return data.pixpos; |
428 | 3139 } |
3140 | |
3141 /* Add a blank to a margin display block. */ | |
3142 | |
3143 static void | |
2286 | 3144 add_margin_blank (struct display_line *UNUSED (dl), struct display_block *db, |
428 | 3145 struct window *w, int xpos, int width, int side) |
3146 { | |
3147 struct rune rb; | |
3148 | |
3149 rb.findex = (side == LEFT_GLYPHS | |
3150 ? get_builtin_face_cache_index (w, Vleft_margin_face) | |
3151 : get_builtin_face_cache_index (w, Vright_margin_face)); | |
3152 rb.xpos = xpos; | |
3153 rb.width = width; | |
826 | 3154 rb.charpos = -1; |
428 | 3155 rb.endpos = 0; |
3156 rb.type = RUNE_BLANK; | |
3157 rb.cursor_type = CURSOR_OFF; | |
3158 | |
3159 Dynarr_add (db->runes, rb); | |
3160 } | |
3161 | |
3162 /* Display glyphs in the left outside margin, left inside margin and | |
3163 left whitespace area. */ | |
3164 | |
3165 static void | |
3166 create_left_glyph_block (struct window *w, struct display_line *dl, | |
3167 int overlay_width) | |
3168 { | |
3169 Lisp_Object window; | |
3170 | |
3171 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1); | |
3172 int elt, end_xpos; | |
3173 int out_end, in_out_start, in_in_end, white_out_start, white_in_start; | |
3174 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
3175 int left_in_start = dl->bounds.left_in; | |
3176 int left_in_end = dl->bounds.left_in + overlay_width; | |
3177 | |
3178 struct display_block *odb, *idb; | |
3179 | |
793 | 3180 window = wrap_window (w); |
428 | 3181 |
3182 /* We have to add the glyphs to the line in the order outside, | |
3183 inside, whitespace. However the precedence dictates that we | |
3184 determine how many will fit in the reverse order. */ | |
3185 | |
3186 /* Determine how many whitespace glyphs we can display and where | |
3187 they should start. */ | |
3188 white_in_start = dl->bounds.left_white; | |
3189 white_out_start = left_in_start; | |
3190 white_out_cnt = white_in_cnt = 0; | |
3191 elt = 0; | |
3192 | |
3193 while (elt < Dynarr_length (dl->left_glyphs)) | |
3194 { | |
3195 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3196 | |
3197 if (NILP (gb->extent)) | |
2500 | 3198 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3199 |
3200 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
3201 { | |
3202 int width; | |
3203 | |
438 | 3204 width = glyph_width (gb->glyph, window); |
428 | 3205 |
3206 if (white_in_start - width >= left_in_end) | |
3207 { | |
3208 white_in_cnt++; | |
3209 white_in_start -= width; | |
3210 gb->width = width; | |
3211 gb->active = 1; | |
3212 } | |
3213 else if (use_overflow | |
3214 && (white_out_start - width > dl->bounds.left_out)) | |
3215 { | |
3216 white_out_cnt++; | |
3217 white_out_start -= width; | |
3218 gb->width = width; | |
3219 gb->active = 1; | |
3220 } | |
3221 else | |
3222 gb->active = 0; | |
3223 } | |
3224 | |
3225 elt++; | |
3226 } | |
3227 | |
3228 /* Determine how many inside margin glyphs we can display and where | |
3229 they should start. The inside margin glyphs get whatever space | |
3230 is left after the whitespace glyphs have been displayed. These | |
3231 are tricky to calculate since if we decide to use the overflow | |
3232 area we basically have to start over. So for these we build up a | |
3233 list of just the inside margin glyphs and manipulate it to | |
3234 determine the needed info. */ | |
3235 { | |
3236 glyph_block_dynarr *ib; | |
3237 int avail_in, avail_out; | |
3238 int done = 0; | |
3239 int marker = 0; | |
3240 int used_in, used_out; | |
3241 | |
3242 elt = 0; | |
3243 used_in = used_out = 0; | |
3244 ib = Dynarr_new (glyph_block); | |
3245 while (elt < Dynarr_length (dl->left_glyphs)) | |
3246 { | |
3247 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3248 | |
3249 if (NILP (gb->extent)) | |
2500 | 3250 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3251 |
3252 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3253 GL_INSIDE_MARGIN) | |
3254 { | |
438 | 3255 gb->width = glyph_width (gb->glyph, window); |
428 | 3256 used_in += gb->width; |
3257 Dynarr_add (ib, *gb); | |
3258 } | |
3259 | |
3260 elt++; | |
3261 } | |
3262 | |
3263 if (white_out_cnt) | |
3264 avail_in = 0; | |
3265 else | |
3266 { | |
3267 avail_in = white_in_start - left_in_end; | |
3268 if (avail_in < 0) | |
3269 avail_in = 0; | |
3270 } | |
3271 | |
3272 if (!use_overflow) | |
3273 avail_out = 0; | |
3274 else | |
3275 avail_out = white_out_start - dl->bounds.left_out; | |
3276 | |
3277 marker = 0; | |
3278 while (!done && marker < Dynarr_length (ib)) | |
3279 { | |
3280 int width = Dynarr_atp (ib, marker)->width; | |
3281 | |
3282 /* If everything now fits in the available inside margin | |
4187 | 3283 space, we're done. */ |
428 | 3284 if (used_in <= avail_in) |
3285 done = 1; | |
3286 else | |
3287 { | |
3288 /* Otherwise see if we have room to move a glyph to the | |
4187 | 3289 outside. */ |
428 | 3290 if (used_out + width <= avail_out) |
3291 { | |
3292 used_out += width; | |
3293 used_in -= width; | |
3294 } | |
3295 else | |
3296 done = 1; | |
3297 } | |
3298 | |
3299 if (!done) | |
3300 marker++; | |
3301 } | |
3302 | |
3303 /* At this point we now know that everything from marker on goes in | |
3304 the inside margin and everything before it goes in the outside | |
3305 margin. The stuff going into the outside margin is guaranteed | |
3306 to fit, but we may have to trim some stuff from the inside. */ | |
3307 | |
3308 in_in_end = left_in_end; | |
3309 in_out_start = white_out_start; | |
3310 in_out_cnt = in_in_cnt = 0; | |
3311 | |
3312 Dynarr_free (ib); | |
3313 elt = 0; | |
3314 while (elt < Dynarr_length (dl->left_glyphs)) | |
3315 { | |
3316 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3317 | |
3318 if (NILP (gb->extent)) | |
2500 | 3319 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3320 |
3321 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3322 GL_INSIDE_MARGIN) | |
3323 { | |
438 | 3324 int width = glyph_width (gb->glyph, window); |
428 | 3325 |
3326 if (used_out) | |
3327 { | |
3328 in_out_cnt++; | |
3329 in_out_start -= width; | |
3330 gb->width = width; | |
3331 gb->active = 1; | |
3332 used_out -= width; | |
3333 } | |
3334 else if (in_in_end + width < white_in_start) | |
3335 { | |
3336 in_in_cnt++; | |
3337 in_in_end += width; | |
3338 gb->width = width; | |
3339 gb->active = 1; | |
3340 } | |
3341 else | |
3342 gb->active = 0; | |
3343 } | |
3344 | |
3345 elt++; | |
3346 } | |
3347 } | |
3348 | |
3349 /* Determine how many outside margin glyphs we can display. They | |
3350 always start at the left outside margin and can only use the | |
3351 outside margin space. */ | |
3352 out_end = dl->bounds.left_out; | |
3353 out_cnt = 0; | |
3354 elt = 0; | |
3355 | |
3356 while (elt < Dynarr_length (dl->left_glyphs)) | |
3357 { | |
3358 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); | |
3359 | |
3360 if (NILP (gb->extent)) | |
2500 | 3361 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3362 |
3363 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | |
3364 GL_OUTSIDE_MARGIN) | |
3365 { | |
438 | 3366 int width = glyph_width (gb->glyph, window); |
428 | 3367 |
3368 if (out_end + width <= in_out_start) | |
3369 { | |
3370 out_cnt++; | |
3371 out_end += width; | |
3372 gb->width = width; | |
3373 gb->active = 1; | |
3374 } | |
3375 else | |
3376 gb->active = 0; | |
3377 } | |
3378 | |
3379 elt++; | |
3380 } | |
3381 | |
3382 /* Now that we know where everything goes, we add the glyphs as | |
3383 runes to the appropriate display blocks. */ | |
3384 if (out_cnt || in_out_cnt || white_out_cnt) | |
3385 { | |
3386 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN); | |
3387 odb->start_pos = dl->bounds.left_out; | |
3388 /* #### We should stop adding a blank to account for the space | |
4187 | 3389 between the end of the glyphs and the margin and instead set |
3390 this accordingly. */ | |
428 | 3391 odb->end_pos = dl->bounds.left_in; |
3392 Dynarr_reset (odb->runes); | |
3393 } | |
3394 else | |
3395 odb = 0; | |
3396 | |
3397 if (in_in_cnt || white_in_cnt) | |
3398 { | |
3399 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN); | |
3400 idb->start_pos = dl->bounds.left_in; | |
3401 /* #### See above comment for odb->end_pos */ | |
3402 idb->end_pos = dl->bounds.left_white; | |
3403 Dynarr_reset (idb->runes); | |
3404 } | |
3405 else | |
3406 idb = 0; | |
3407 | |
3408 /* First add the outside margin glyphs. */ | |
3409 if (out_cnt) | |
3410 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt, | |
3411 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window); | |
3412 else | |
3413 end_xpos = dl->bounds.left_out; | |
3414 | |
3415 /* There may be blank space between the outside margin glyphs and | |
3416 the inside margin glyphs. If so, add a blank. */ | |
3417 if (in_out_cnt && (in_out_start - end_xpos)) | |
3418 { | |
3419 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos, | |
3420 LEFT_GLYPHS); | |
3421 } | |
3422 | |
3423 /* Next add the inside margin glyphs which are actually in the | |
3424 outside margin. */ | |
3425 if (in_out_cnt) | |
3426 { | |
3427 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt, | |
3428 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
3429 } | |
3430 | |
3431 /* If we didn't add any inside margin glyphs to the outside margin, | |
3432 but are adding whitespace glyphs, then we need to add a blank | |
3433 here. */ | |
3434 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) | |
3435 { | |
3436 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos, | |
3437 LEFT_GLYPHS); | |
3438 } | |
3439 | |
3440 /* Next add the whitespace margin glyphs which are actually in the | |
3441 outside margin. */ | |
3442 if (white_out_cnt) | |
3443 { | |
3444 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt, | |
3445 GL_WHITESPACE, LEFT_GLYPHS, window); | |
3446 } | |
3447 | |
3448 /* We take care of clearing between the end of the glyphs and the | |
3449 start of the inside margin for lines which have glyphs. */ | |
3450 if (odb && (left_in_start - end_xpos)) | |
3451 { | |
3452 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos, | |
3453 LEFT_GLYPHS); | |
3454 } | |
3455 | |
3456 /* Next add the inside margin glyphs which are actually in the | |
3457 inside margin. */ | |
3458 if (in_in_cnt) | |
3459 { | |
3460 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt, | |
3461 GL_INSIDE_MARGIN, LEFT_GLYPHS, window); | |
3462 } | |
3463 else | |
3464 end_xpos = left_in_end; | |
3465 | |
3466 /* Make sure that the area between the end of the inside margin | |
3467 glyphs and the whitespace glyphs is cleared. */ | |
3468 if (idb && (white_in_start - end_xpos > 0)) | |
3469 { | |
3470 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos, | |
3471 LEFT_GLYPHS); | |
3472 } | |
3473 | |
3474 /* Next add the whitespace margin glyphs which are actually in the | |
3475 inside margin. */ | |
3476 if (white_in_cnt) | |
3477 { | |
3478 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE, | |
3479 LEFT_GLYPHS, window); | |
3480 } | |
3481 | |
3482 /* Whitespace glyphs always end right next to the text block so | |
3483 there is nothing we have to make sure is cleared after them. */ | |
3484 } | |
3485 | |
3486 /* Display glyphs in the right outside margin, right inside margin and | |
3487 right whitespace area. */ | |
3488 | |
3489 static void | |
3490 create_right_glyph_block (struct window *w, struct display_line *dl) | |
3491 { | |
3492 Lisp_Object window; | |
3493 | |
3494 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1); | |
3495 int elt, end_xpos; | |
3496 int out_start, in_out_end, in_in_start, white_out_end, white_in_end; | |
3497 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt; | |
3498 | |
3499 struct display_block *odb, *idb; | |
3500 | |
793 | 3501 window = wrap_window (w); |
428 | 3502 |
3503 /* We have to add the glyphs to the line in the order outside, | |
3504 inside, whitespace. However the precedence dictates that we | |
3505 determine how many will fit in the reverse order. */ | |
3506 | |
3507 /* Determine how many whitespace glyphs we can display and where | |
3508 they should start. */ | |
3509 white_in_end = dl->bounds.right_white; | |
3510 white_out_end = dl->bounds.right_in; | |
3511 white_out_cnt = white_in_cnt = 0; | |
3512 elt = 0; | |
3513 | |
3514 while (elt < Dynarr_length (dl->right_glyphs)) | |
3515 { | |
3516 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3517 | |
3518 if (NILP (gb->extent)) | |
2500 | 3519 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3520 |
3521 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | |
3522 { | |
438 | 3523 int width = glyph_width (gb->glyph, window); |
428 | 3524 |
3525 if (white_in_end + width <= dl->bounds.right_in) | |
3526 { | |
3527 white_in_cnt++; | |
3528 white_in_end += width; | |
3529 gb->width = width; | |
3530 gb->active = 1; | |
3531 } | |
3532 else if (use_overflow | |
3533 && (white_out_end + width <= dl->bounds.right_out)) | |
3534 { | |
3535 white_out_cnt++; | |
3536 white_out_end += width; | |
3537 gb->width = width; | |
3538 gb->active = 1; | |
3539 } | |
3540 else | |
3541 gb->active = 0; | |
3542 } | |
3543 | |
3544 elt++; | |
3545 } | |
3546 | |
3547 /* Determine how many inside margin glyphs we can display and where | |
3548 they should start. The inside margin glyphs get whatever space | |
3549 is left after the whitespace glyphs have been displayed. These | |
3550 are tricky to calculate since if we decide to use the overflow | |
3551 area we basically have to start over. So for these we build up a | |
3552 list of just the inside margin glyphs and manipulate it to | |
3553 determine the needed info. */ | |
3554 { | |
3555 glyph_block_dynarr *ib; | |
3556 int avail_in, avail_out; | |
3557 int done = 0; | |
3558 int marker = 0; | |
3559 int used_in, used_out; | |
3560 | |
3561 elt = 0; | |
3562 used_in = used_out = 0; | |
3563 ib = Dynarr_new (glyph_block); | |
3564 while (elt < Dynarr_length (dl->right_glyphs)) | |
3565 { | |
3566 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3567 | |
3568 if (NILP (gb->extent)) | |
2500 | 3569 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3570 |
3571 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
3572 { | |
438 | 3573 gb->width = glyph_width (gb->glyph, window); |
428 | 3574 used_in += gb->width; |
3575 Dynarr_add (ib, *gb); | |
3576 } | |
3577 | |
3578 elt++; | |
3579 } | |
3580 | |
3581 if (white_out_cnt) | |
3582 avail_in = 0; | |
3583 else | |
3584 avail_in = dl->bounds.right_in - white_in_end; | |
3585 | |
3586 if (!use_overflow) | |
3587 avail_out = 0; | |
3588 else | |
3589 avail_out = dl->bounds.right_out - white_out_end; | |
3590 | |
3591 marker = 0; | |
3592 while (!done && marker < Dynarr_length (ib)) | |
3593 { | |
3594 int width = Dynarr_atp (ib, marker)->width; | |
3595 | |
3596 /* If everything now fits in the available inside margin | |
4187 | 3597 space, we're done. */ |
428 | 3598 if (used_in <= avail_in) |
3599 done = 1; | |
3600 else | |
3601 { | |
3602 /* Otherwise see if we have room to move a glyph to the | |
4187 | 3603 outside. */ |
428 | 3604 if (used_out + width <= avail_out) |
3605 { | |
3606 used_out += width; | |
3607 used_in -= width; | |
3608 } | |
3609 else | |
3610 done = 1; | |
3611 } | |
3612 | |
3613 if (!done) | |
3614 marker++; | |
3615 } | |
3616 | |
3617 /* At this point we now know that everything from marker on goes in | |
3618 the inside margin and everything before it goes in the outside | |
3619 margin. The stuff going into the outside margin is guaranteed | |
3620 to fit, but we may have to trim some stuff from the inside. */ | |
3621 | |
3622 in_in_start = dl->bounds.right_in; | |
3623 in_out_end = dl->bounds.right_in; | |
3624 in_out_cnt = in_in_cnt = 0; | |
3625 | |
3626 Dynarr_free (ib); | |
3627 elt = 0; | |
3628 while (elt < Dynarr_length (dl->right_glyphs)) | |
3629 { | |
3630 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3631 | |
3632 if (NILP (gb->extent)) | |
2500 | 3633 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3634 |
3635 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | |
3636 { | |
438 | 3637 int width = glyph_width (gb->glyph, window); |
428 | 3638 |
3639 if (used_out) | |
3640 { | |
3641 in_out_cnt++; | |
3642 in_out_end += width; | |
3643 gb->width = width; | |
3644 gb->active = 1; | |
3645 used_out -= width; | |
3646 } | |
3647 else if (in_in_start - width >= white_in_end) | |
3648 { | |
3649 in_in_cnt++; | |
3650 in_in_start -= width; | |
3651 gb->width = width; | |
3652 gb->active = 1; | |
3653 } | |
3654 else | |
3655 gb->active = 0; | |
3656 } | |
3657 | |
3658 elt++; | |
3659 } | |
3660 } | |
3661 | |
3662 /* Determine how many outside margin glyphs we can display. They | |
3663 always start at the right outside margin and can only use the | |
3664 outside margin space. */ | |
3665 out_start = dl->bounds.right_out; | |
3666 out_cnt = 0; | |
3667 elt = 0; | |
3668 | |
3669 while (elt < Dynarr_length (dl->right_glyphs)) | |
3670 { | |
3671 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); | |
3672 | |
3673 if (NILP (gb->extent)) | |
2500 | 3674 ABORT (); /* these should have been handled in add_glyph_rune */ |
428 | 3675 |
3676 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) | |
3677 { | |
438 | 3678 int width = glyph_width (gb->glyph, window); |
428 | 3679 |
3680 if (out_start - width >= in_out_end) | |
3681 { | |
3682 out_cnt++; | |
3683 out_start -= width; | |
3684 gb->width = width; | |
3685 gb->active = 1; | |
3686 } | |
3687 else | |
3688 gb->active = 0; | |
3689 } | |
3690 | |
3691 elt++; | |
3692 } | |
3693 | |
3694 /* Now that we now where everything goes, we add the glyphs as runes | |
3695 to the appropriate display blocks. */ | |
3696 if (out_cnt || in_out_cnt || white_out_cnt) | |
3697 { | |
3698 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN); | |
3699 /* #### See comments before odb->start_pos init in | |
4187 | 3700 create_left_glyph_block */ |
428 | 3701 odb->start_pos = dl->bounds.right_in; |
3702 odb->end_pos = dl->bounds.right_out; | |
3703 Dynarr_reset (odb->runes); | |
3704 } | |
3705 else | |
3706 odb = 0; | |
3707 | |
3708 if (in_in_cnt || white_in_cnt) | |
3709 { | |
3710 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN); | |
3711 idb->start_pos = dl->bounds.right_white; | |
3712 /* #### See comments before odb->start_pos init in | |
4187 | 3713 create_left_glyph_block */ |
428 | 3714 idb->end_pos = dl->bounds.right_in; |
3715 Dynarr_reset (idb->runes); | |
3716 } | |
3717 else | |
3718 idb = 0; | |
3719 | |
3720 /* First add the whitespace margin glyphs which are actually in the | |
3721 inside margin. */ | |
3722 if (white_in_cnt) | |
3723 { | |
3724 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white, | |
3725 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS, | |
3726 window); | |
3727 } | |
3728 else | |
3729 end_xpos = dl->bounds.right_white; | |
3730 | |
3731 /* Make sure that the area between the end of the whitespace glyphs | |
3732 and the inside margin glyphs is cleared. */ | |
3733 if (in_in_cnt && (in_in_start - end_xpos)) | |
3734 { | |
3735 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos, | |
3736 RIGHT_GLYPHS); | |
3737 } | |
3738 | |
3739 /* Next add the inside margin glyphs which are actually in the | |
3740 inside margin. */ | |
3741 if (in_in_cnt) | |
3742 { | |
3743 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt, | |
3744 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
3745 } | |
3746 | |
3747 /* If we didn't add any inside margin glyphs then make sure the rest | |
3748 of the inside margin area gets cleared. */ | |
3749 if (idb && (dl->bounds.right_in - end_xpos)) | |
3750 { | |
3751 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos, | |
3752 RIGHT_GLYPHS); | |
3753 } | |
3754 | |
3755 /* Next add any whitespace glyphs in the outside margin. */ | |
3756 if (white_out_cnt) | |
3757 { | |
3758 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt, | |
3759 GL_WHITESPACE, RIGHT_GLYPHS, window); | |
3760 } | |
3761 else | |
3762 end_xpos = dl->bounds.right_in; | |
3763 | |
3764 /* Next add any inside margin glyphs in the outside margin. */ | |
3765 if (in_out_cnt) | |
3766 { | |
3767 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt, | |
3768 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window); | |
3769 } | |
3770 | |
3771 /* There may be space between any whitespace or inside margin glyphs | |
3772 in the outside margin and the actual outside margin glyphs. */ | |
3773 if (odb && (out_start - end_xpos)) | |
3774 { | |
3775 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos, | |
3776 RIGHT_GLYPHS); | |
3777 } | |
3778 | |
3779 /* Finally, add the outside margin glyphs. */ | |
3780 if (out_cnt) | |
3781 { | |
3782 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN, | |
3783 RIGHT_GLYPHS, window); | |
3784 } | |
3785 } | |
3786 | |
3787 | |
3788 /***************************************************************************/ | |
3789 /* */ | |
3790 /* modeline routines */ | |
3791 /* */ | |
3792 /***************************************************************************/ | |
3793 | |
438 | 3794 /* This function is also used in frame.c by `generate_title_string' */ |
3795 void | |
3796 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, | |
4187 | 3797 struct window *w, struct display_line *dl, |
3798 struct display_block *db, face_index findex, | |
3799 int min_pixpos, int max_pixpos, int type) | |
438 | 3800 { |
3801 struct frame *f = XFRAME (w->frame); | |
3802 struct device *d = XDEVICE (f->device); | |
3803 | |
3804 pos_data data; | |
3805 int c_pixpos; | |
3806 Charcount offset = 0; | |
3807 | |
3808 xzero (data); | |
3809 data.d = d; | |
3810 data.db = db; | |
3811 data.dl = dl; | |
3812 data.findex = findex; | |
3813 data.pixpos = min_pixpos; | |
3814 data.max_pixpos = max_pixpos; | |
3815 data.cursor_type = NO_CURSOR; | |
3816 data.last_charset = Qunbound; | |
3817 data.last_findex = DEFAULT_INDEX; | |
3818 data.result_str = result_str; | |
3819 data.is_modeline = 1; | |
3820 data.string = Qnil; | |
793 | 3821 data.window = wrap_window (w); |
438 | 3822 |
3823 Dynarr_reset (formatted_string_extent_dynarr); | |
3824 Dynarr_reset (formatted_string_extent_start_dynarr); | |
3825 Dynarr_reset (formatted_string_extent_end_dynarr); | |
3826 | |
3827 /* result_str is nil when we're building a frame or icon title. Otherwise, | |
3828 we're building a modeline, so the offset starts at the modeline | |
442 | 3829 horizontal scrolling amount */ |
438 | 3830 if (! NILP (result_str)) |
3831 offset = w->modeline_hscroll; | |
3832 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, | |
4187 | 3833 max_pixpos - min_pixpos, findex, type, &offset, |
438 | 3834 Qnil); |
3835 | |
3836 if (Dynarr_length (db->runes)) | |
3837 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3838 struct rune *rb = Dynarr_lastp (db->runes); |
438 | 3839 c_pixpos = rb->xpos + rb->width; |
3840 } | |
3841 else | |
3842 c_pixpos = min_pixpos; | |
3843 | |
3844 /* If we don't reach the right side of the window, add a blank rune | |
3845 to make up the difference. This usually only occurs if the | |
3846 modeline face is using a proportional width font or a fixed width | |
3847 font of a different size from the default face font. */ | |
3848 | |
3849 if (c_pixpos < max_pixpos) | |
3850 { | |
3851 data.pixpos = c_pixpos; | |
3852 data.blank_width = max_pixpos - data.pixpos; | |
3853 | |
3854 add_blank_rune (&data, NULL, 0); | |
3855 } | |
3856 | |
3857 /* Now create the result string and frob the extents into it. */ | |
3858 if (!NILP (result_str)) | |
3859 { | |
3860 int elt; | |
3861 Bytecount len; | |
867 | 3862 Ibyte *strdata; |
438 | 3863 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); |
3864 | |
442 | 3865 in_modeline_generation = 1; |
3866 | |
771 | 3867 sledgehammer_check_ascii_begin (result_str); |
438 | 3868 detach_all_extents (result_str); |
793 | 3869 resize_string (result_str, -1, |
4187 | 3870 data.bytepos - XSTRING_LENGTH (result_str)); |
438 | 3871 |
3872 strdata = XSTRING_DATA (result_str); | |
3873 | |
3874 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++) | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3875 { |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3876 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3877 { |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3878 len += (set_itext_ichar |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3879 (strdata + len, Dynarr_atp (db->runes, |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3880 elt)->object.chr.ch)); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3881 } |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
3882 } |
438 | 3883 |
771 | 3884 init_string_ascii_begin (result_str); |
3885 bump_string_modiff (result_str); | |
3886 sledgehammer_check_ascii_begin (result_str); | |
3887 | |
438 | 3888 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr); |
4187 | 3889 elt++) |
3890 { | |
3891 Lisp_Object extent = Qnil; | |
3892 Lisp_Object child; | |
3893 | |
3894 extent = wrap_extent (Dynarr_at (formatted_string_extent_dynarr, elt)); | |
3895 child = Fgethash (extent, buf->modeline_extent_table, Qnil); | |
3896 if (NILP (child)) | |
3897 { | |
3898 child = Fmake_extent (Qnil, Qnil, result_str); | |
3899 Fputhash (extent, child, buf->modeline_extent_table); | |
3900 } | |
3901 Fset_extent_parent (child, extent); | |
3902 set_extent_endpoints | |
3903 (XEXTENT (child), | |
3904 Dynarr_at (formatted_string_extent_start_dynarr, elt), | |
3905 Dynarr_at (formatted_string_extent_end_dynarr, elt), | |
3906 result_str); | |
3907 } | |
442 | 3908 |
3909 in_modeline_generation = 0; | |
438 | 3910 } |
3911 } | |
3912 | |
428 | 3913 /* Ensure that the given display line DL accurately represents the |
3914 modeline for the given window. */ | |
3915 static void | |
3916 generate_modeline (struct window *w, struct display_line *dl, int type) | |
3917 { | |
3918 struct buffer *b = XBUFFER (w->buffer); | |
3919 struct frame *f = XFRAME (w->frame); | |
3920 struct device *d = XDEVICE (f->device); | |
3921 | |
3922 /* Unlike display line and rune pointers, this one can't change underneath | |
3923 our feet. */ | |
3924 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
3925 int max_pixpos, min_pixpos, ypos_adj; | |
3926 Lisp_Object font_inst; | |
3927 | |
3928 /* This will actually determine incorrect inside boundaries for the | |
3929 modeline since it ignores the margins. However being aware of this fact | |
3930 we never use those values anywhere so it doesn't matter. */ | |
3931 dl->bounds = calculate_display_line_boundaries (w, 1); | |
3932 | |
3933 /* We are generating a modeline. */ | |
3934 dl->modeline = 1; | |
3935 dl->cursor_elt = -1; | |
3936 | |
3937 /* Reset the runes on the modeline. */ | |
3938 Dynarr_reset (db->runes); | |
3939 | |
3940 if (!WINDOW_HAS_MODELINE_P (w)) | |
3941 { | |
3942 struct rune rb; | |
3943 | |
3944 /* If there is a horizontal scrollbar, don't add anything. */ | |
3945 if (window_scrollbar_height (w)) | |
3946 return; | |
3947 | |
3948 dl->ascent = DEVMETH (d, divider_height, ()); | |
3949 dl->descent = 0; | |
3950 /* The modeline is at the bottom of the gutters. */ | |
3951 dl->ypos = WINDOW_BOTTOM (w); | |
3952 | |
3953 rb.findex = MODELINE_INDEX; | |
3954 rb.xpos = dl->bounds.left_out; | |
3955 rb.width = dl->bounds.right_out - dl->bounds.left_out; | |
826 | 3956 rb.charpos = 0; |
428 | 3957 rb.endpos = 0; |
3958 rb.type = RUNE_HLINE; | |
3959 rb.object.hline.thickness = 1; | |
3960 rb.object.hline.yoffset = 0; | |
3961 rb.cursor_type = NO_CURSOR; | |
3962 | |
3963 if (!EQ (Qzero, w->modeline_shadow_thickness) | |
3964 && FRAME_WIN_P (f)) | |
3965 { | |
3966 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
3967 | |
3968 dl->ypos -= shadow_thickness; | |
3969 rb.xpos += shadow_thickness; | |
3970 rb.width -= 2 * shadow_thickness; | |
3971 } | |
3972 | |
3973 Dynarr_add (db->runes, rb); | |
3974 return; | |
3975 } | |
3976 | |
3977 /* !!#### not right; needs to compute the max height of | |
3978 all the charsets */ | |
3979 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); | |
3980 | |
3981 dl->ascent = XFONT_INSTANCE (font_inst)->ascent; | |
3982 dl->descent = XFONT_INSTANCE (font_inst)->descent; | |
3983 | |
3984 min_pixpos = dl->bounds.left_out; | |
3985 max_pixpos = dl->bounds.right_out; | |
3986 | |
3987 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
3988 { | |
3989 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
3990 | |
3991 ypos_adj = shadow_thickness; | |
3992 min_pixpos += shadow_thickness; | |
3993 max_pixpos -= shadow_thickness; | |
3994 } | |
3995 else | |
3996 ypos_adj = 0; | |
3997 | |
3998 generate_formatted_string_db (b->modeline_format, | |
3999 b->generated_modeline_string, w, dl, db, | |
4000 MODELINE_INDEX, min_pixpos, max_pixpos, type); | |
4001 | |
4002 /* The modeline is at the bottom of the gutters. We have to wait to | |
4003 set this until we've generated the modeline in order to account | |
4004 for any embedded faces. */ | |
4005 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj; | |
4006 } | |
4007 | |
4008 static Charcount | |
867 | 4009 add_string_to_fstring_db_runes (pos_data *data, const Ibyte *str, |
4187 | 4010 Charcount pos, Charcount min_pos, |
771 | 4011 Charcount max_pos) |
428 | 4012 { |
4013 /* This function has been Mule-ized. */ | |
4014 Charcount end; | |
867 | 4015 const Ibyte *cur_pos = str; |
428 | 4016 struct display_block *db = data->db; |
4017 | |
4018 data->blank_width = space_width (XWINDOW (data->window)); | |
4019 while (Dynarr_length (db->runes) < pos) | |
4020 add_blank_rune (data, NULL, 0); | |
4021 | |
4022 end = (Dynarr_length (db->runes) + | |
4970 | 4023 bytecount_to_charcount (str, qxestrlen (str))); |
428 | 4024 if (max_pos != -1) |
4025 end = min (max_pos, end); | |
4026 | |
4027 while (pos < end && *cur_pos) | |
4028 { | |
867 | 4029 const Ibyte *old_cur_pos = cur_pos; |
428 | 4030 int succeeded; |
4031 | |
867 | 4032 data->ch = itext_ichar (cur_pos); |
4033 succeeded = (add_ichar_rune (data) != ADD_FAILED); | |
4034 INC_IBYTEPTR (cur_pos); | |
428 | 4035 if (succeeded) |
4187 | 4036 { |
4037 pos++; | |
4038 data->modeline_charpos++; | |
4039 data->bytepos += cur_pos - old_cur_pos; | |
4040 } | |
428 | 4041 } |
4042 | |
4043 while (Dynarr_length (db->runes) < min_pos && | |
4187 | 4044 (data->pixpos + data->blank_width <= data->max_pixpos)) |
428 | 4045 add_blank_rune (data, NULL, 0); |
4046 | |
4047 return Dynarr_length (db->runes); | |
4048 } | |
4049 | |
4050 /* #### Urk! Should also handle begin-glyphs and end-glyphs in | |
4051 modeline extents. */ | |
4052 static Charcount | |
4053 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, | |
4187 | 4054 Charcount pos, Charcount UNUSED (min_pos), |
438 | 4055 Charcount max_pos, Lisp_Object extent) |
428 | 4056 { |
4057 /* This function has been Mule-ized. */ | |
4058 Charcount end; | |
4059 struct display_block *db = data->db; | |
4060 struct glyph_block gb; | |
4061 | |
4062 data->blank_width = space_width (XWINDOW (data->window)); | |
4063 while (Dynarr_length (db->runes) < pos) | |
4064 add_blank_rune (data, NULL, 0); | |
4065 | |
4066 end = Dynarr_length (db->runes) + 1; | |
4067 if (max_pos != -1) | |
4068 end = min (max_pos, end); | |
4069 | |
4070 gb.glyph = glyph; | |
438 | 4071 gb.extent = extent; |
428 | 4072 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); |
4073 pos++; | |
4074 | |
4075 while (Dynarr_length (db->runes) < pos && | |
4187 | 4076 (data->pixpos + data->blank_width <= data->max_pixpos)) |
428 | 4077 add_blank_rune (data, NULL, 0); |
4078 | |
4079 return Dynarr_length (db->runes); | |
4080 } | |
4081 | |
4082 /* If max_pos is == -1, it is considered to be infinite. The same is | |
4083 true of max_pixsize. */ | |
4084 #define SET_CURRENT_MODE_CHARS_PIXSIZE \ | |
4085 if (Dynarr_length (data->db->runes)) \ | |
4967 | 4086 cur_pixsize = data->pixpos - Dynarr_begin (data->db->runes)->xpos; \ |
428 | 4087 else \ |
4088 cur_pixsize = 0; | |
4089 | |
4090 /* Note that this function does "positions" in terms of characters and | |
4091 not in terms of columns. This is necessary to make the formatting | |
4092 work correctly when proportional width fonts are used in the | |
4093 modeline. */ | |
4094 static Charcount | |
4095 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, | |
4187 | 4096 Charcount min_pos, Charcount max_pos, |
4097 Lisp_Object elt, int depth, int max_pixsize, | |
4098 face_index findex, int type, Charcount *offset, | |
438 | 4099 Lisp_Object cur_ext) |
428 | 4100 { |
4101 /* This function has been Mule-ized. */ | |
4102 /* #### The other losing things in this function are: | |
4103 | |
4104 -- C zero-terminated-string lossage. | |
4105 -- Non-printable characters should be converted into something | |
4187 | 4106 appropriate (e.g. ^F) instead of blindly being printed anyway. |
428 | 4107 */ |
4108 | |
4109 tail_recurse: | |
4110 if (depth > 10) | |
4111 goto invalid; | |
4112 | |
4113 depth++; | |
4114 | |
4115 if (STRINGP (elt)) | |
4116 { | |
4117 /* A string. Add to the display line and check for %-constructs | |
4187 | 4118 within it. */ |
428 | 4119 |
2552 | 4120 Ibyte *this_str = XSTRING_DATA (elt); |
4121 | |
4122 while ((pos < max_pos || max_pos == -1) && *this_str) | |
4187 | 4123 { |
4124 Ibyte *last = this_str; | |
4125 | |
4126 while (*this_str && *this_str != '%') | |
4127 this_str++; | |
4128 | |
4129 if (this_str != last) | |
4130 { | |
4131 /* No %-construct */ | |
4132 Charcount size = | |
2552 | 4133 bytecount_to_charcount (last, this_str - last); |
438 | 4134 |
4135 if (size <= *offset) | |
4136 *offset -= size; | |
4137 else | |
4138 { | |
4139 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset : | |
4140 min (pos + size - *offset, max_pos)); | |
867 | 4141 const Ibyte *tmp_last = itext_n_addr (last, *offset); |
438 | 4142 |
4143 pos = add_string_to_fstring_db_runes (data, tmp_last, | |
4144 pos, pos, tmp_max); | |
4145 *offset = 0; | |
4146 } | |
4187 | 4147 } |
4148 else /* *this_str == '%' */ | |
4149 { | |
4150 Charcount spec_width = 0; | |
4151 | |
4152 this_str++; /* skip over '%' */ | |
4153 | |
4154 /* We can't allow -ve args due to the "%-" construct. | |
4155 * Argument specifies minwidth but not maxwidth | |
4156 * (maxwidth can be specified by | |
4157 * (<negative-number> . <stuff>) modeline elements) | |
4158 */ | |
4159 while (isdigit (*this_str)) | |
4160 { | |
4161 spec_width = spec_width * 10 + (*this_str - '0'); | |
4162 this_str++; | |
4163 } | |
4164 spec_width += pos; | |
4165 | |
4166 if (*this_str == 'M') | |
4167 { | |
4168 pos = generate_fstring_runes (w, data, pos, spec_width, | |
4169 max_pos, Vglobal_mode_string, | |
4170 depth, max_pixsize, findex, | |
4171 type, offset, cur_ext); | |
4172 } | |
4173 else if (*this_str == '-') | |
4174 { | |
4175 Charcount num_to_add; | |
4176 | |
4177 if (max_pixsize < 0) | |
4178 num_to_add = 0; | |
4179 else if (max_pos != -1) | |
4180 num_to_add = max_pos - pos; | |
4181 else | |
4182 { | |
4183 int cur_pixsize; | |
4184 int dash_pixsize; | |
4185 Ibyte ch = '-'; | |
4186 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
4187 | |
4188 dash_pixsize = | |
4815
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4189 redisplay_window_text_width_string |
6540302eedf5
Fix query_string_geometry lookup domain
Didier Verna <didier@lrde.epita.fr>
parents:
4528
diff
changeset
|
4190 (w, findex, &ch, Qnil, 0, 1); |
4187 | 4191 |
4192 if (dash_pixsize == 0) | |
3094 | 4193 num_to_add = 0; |
4194 else { | |
4195 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize; | |
4196 num_to_add++; | |
4197 } | |
4187 | 4198 } |
4199 | |
4200 while (num_to_add--) | |
4201 pos = add_string_to_fstring_db_runes | |
4202 (data, (const Ibyte *) "-", pos, pos, max_pos); | |
4203 } | |
4204 else if (*this_str != 0) | |
4205 { | |
4206 Ichar ch = itext_ichar (this_str); | |
4207 Ibyte *str; | |
438 | 4208 Charcount size; |
4209 | |
4187 | 4210 decode_mode_spec (w, ch, type); |
4211 | |
4967 | 4212 str = Dynarr_begin (mode_spec_ibyte_string); |
438 | 4213 size = bytecount_to_charcount |
4214 /* Skip the null character added by `decode_mode_spec' */ | |
867 | 4215 (str, Dynarr_length (mode_spec_ibyte_string)) - 1; |
438 | 4216 |
4217 if (size <= *offset) | |
4218 *offset -= size; | |
4219 else | |
4220 { | |
867 | 4221 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
438 | 4222 |
440 | 4223 /* #### NOTE: I don't understand why a tmp_max is not |
438 | 4224 computed and used here as in the plain string case |
4225 above. -- dv */ | |
4226 pos = add_string_to_fstring_db_runes (data, tmp_str, | |
4227 pos, pos, | |
4228 max_pos); | |
4229 *offset = 0; | |
4230 } | |
4187 | 4231 } |
4232 | |
4233 /* NOT this_str++. There could be any sort of character at | |
4234 the current position. */ | |
4235 INC_IBYTEPTR (this_str); | |
4236 } | |
4237 | |
4238 if (max_pixsize > 0) | |
4239 { | |
4240 int cur_pixsize; | |
4241 SET_CURRENT_MODE_CHARS_PIXSIZE; | |
4242 | |
4243 if (cur_pixsize >= max_pixsize) | |
4244 break; | |
4245 } | |
4246 } | |
428 | 4247 } |
4248 else if (SYMBOLP (elt)) | |
4249 { | |
4250 /* A symbol: process the value of the symbol recursively | |
4187 | 4251 as if it appeared here directly. */ |
428 | 4252 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); |
4253 | |
4254 if (!UNBOUNDP (tem)) | |
4187 | 4255 { |
438 | 4256 /* If value is a string, output that string literally: |
4187 | 4257 don't check for % within it. */ |
4258 if (STRINGP (tem)) | |
4259 { | |
867 | 4260 Ibyte *str = XSTRING_DATA (tem); |
826 | 4261 Charcount size = string_char_length (tem); |
438 | 4262 |
4263 if (size <= *offset) | |
4264 *offset -= size; | |
4265 else | |
4266 { | |
867 | 4267 const Ibyte *tmp_str = itext_n_addr (str, *offset); |
438 | 4268 |
440 | 4269 /* #### NOTE: I don't understand why a tmp_max is not |
438 | 4270 computed and used here as in the plain string case |
4271 above. -- dv */ | |
4272 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4273 min_pos, max_pos); | |
4274 *offset = 0; | |
4275 } | |
4187 | 4276 } |
4277 /* Give up right away for nil or t. */ | |
4278 else if (!EQ (tem, elt)) | |
4279 { | |
4280 elt = tem; | |
4281 goto tail_recurse; | |
4282 } | |
4283 } | |
428 | 4284 } |
4285 else if (GENERIC_SPECIFIERP (elt)) | |
4286 { | |
4287 Lisp_Object window, tem; | |
793 | 4288 window = wrap_window (w); |
428 | 4289 tem = specifier_instance_no_quit (elt, Qunbound, window, |
793 | 4290 ERROR_ME_DEBUG_WARN, 0, Qzero); |
428 | 4291 if (!UNBOUNDP (tem)) |
4292 { | |
4293 elt = tem; | |
4294 goto tail_recurse; | |
4295 } | |
4296 } | |
4297 else if (CONSP (elt)) | |
4298 { | |
4299 /* A cons cell: four distinct cases. | |
438 | 4300 * - If first element is a string or a cons, process all the elements |
4301 * and effectively concatenate them. | |
4302 * - If first element is a negative number, truncate displaying cdr to | |
4303 * at most that many characters. If positive, pad (with spaces) | |
4304 * to at least that many characters. | |
771 | 4305 * - If first element is another symbol or a boolean specifier, process |
4306 * the cadr or caddr recursively according to whether the symbol's | |
4307 * value or specifier's instance is non-nil or nil. | |
4308 * - If first element is , process the cadr or caddr | |
4309 * recursively according to whether the instance of the specifier in | |
4310 * the modeline's window is non-nil or nil. | |
442 | 4311 * - If first element is an extent, process the cdr recursively |
4312 * and handle the extent's face. | |
428 | 4313 */ |
438 | 4314 |
428 | 4315 Lisp_Object car, tem; |
4316 | |
4317 car = XCAR (elt); | |
771 | 4318 if (SYMBOLP (car) || BOOLEAN_SPECIFIERP (car)) |
438 | 4319 { |
4320 elt = XCDR (elt); | |
4321 if (!CONSP (elt)) | |
4322 goto invalid; | |
4323 | |
771 | 4324 if (SYMBOLP (car)) |
4325 tem = symbol_value_in_buffer (car, w->buffer); | |
4326 else | |
4327 tem = specifier_instance_no_quit (car, Qunbound, wrap_window (w), | |
793 | 4328 ERROR_ME_DEBUG_WARN, 0, Qzero); |
438 | 4329 /* elt is now the cdr, and we know it is a cons cell. |
4330 Use its car if CAR has a non-nil value. */ | |
771 | 4331 if (!UNBOUNDP (tem) && !NILP (tem)) |
438 | 4332 { |
771 | 4333 elt = XCAR (elt); |
4334 goto tail_recurse; | |
438 | 4335 } |
771 | 4336 /* Symbol's value or specifier's instance is nil or unbound |
438 | 4337 * Get the cddr of the original list |
4338 * and if possible find the caddr and use that. | |
4339 */ | |
4340 elt = XCDR (elt); | |
4341 if (NILP (elt)) | |
4342 ; | |
4343 else if (!CONSP (elt)) | |
4344 goto invalid; | |
4345 else | |
4346 { | |
4347 elt = XCAR (elt); | |
4348 goto tail_recurse; | |
4349 } | |
4350 } | |
428 | 4351 else if (INTP (car)) |
4187 | 4352 { |
4353 Charcount lim = XINT (car); | |
4354 | |
4355 elt = XCDR (elt); | |
4356 | |
4357 if (lim < 0) | |
4358 { | |
4359 /* Negative int means reduce maximum width. | |
4360 * DO NOT change MIN_PIXPOS here! | |
4361 * (20 -10 . foo) should truncate foo to 10 col | |
4362 * and then pad to 20. | |
4363 */ | |
4364 if (max_pos == -1) | |
4365 max_pos = pos - lim; | |
4366 else | |
4367 max_pos = min (max_pos, pos - lim); | |
4368 } | |
4369 else if (lim > 0) | |
4370 { | |
4371 /* Padding specified. Don't let it be more than | |
4372 * current maximum. | |
4373 */ | |
4374 lim += pos; | |
4375 if (max_pos != -1 && lim > max_pos) | |
4376 lim = max_pos; | |
4377 /* If that's more padding than already wanted, queue it. | |
4378 * But don't reduce padding already specified even if | |
4379 * that is beyond the current truncation point. | |
4380 */ | |
4381 if (lim > min_pos) | |
4382 min_pos = lim; | |
4383 } | |
4384 goto tail_recurse; | |
4385 } | |
428 | 4386 else if (STRINGP (car) || CONSP (car)) |
4187 | 4387 { |
4388 int limit = 50; | |
4389 | |
4390 /* LIMIT is to protect against circular lists. */ | |
4391 while (CONSP (elt) && --limit > 0 | |
4392 && (pos < max_pos || max_pos == -1)) | |
4393 { | |
4394 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
4395 XCAR (elt), depth, max_pixsize, | |
438 | 4396 findex, type, offset, cur_ext); |
4187 | 4397 elt = XCDR (elt); |
4398 } | |
4399 } | |
428 | 4400 else if (EXTENTP (car)) |
4187 | 4401 { |
4402 struct extent *ext = XEXTENT (car); | |
4403 | |
4404 if (EXTENT_LIVE_P (ext)) | |
4405 { | |
4406 face_index old_findex = data->findex; | |
4407 Lisp_Object face; | |
4408 Lisp_Object font_inst; | |
4409 face_index new_findex; | |
4410 Bytecount start = data->bytepos; | |
4411 | |
4412 face = extent_face (ext); | |
4413 if (FACEP (face)) | |
4414 { | |
4415 /* #### needs to merge faces, sigh */ | |
4416 /* #### needs to handle list of faces */ | |
4417 new_findex = get_builtin_face_cache_index (w, face); | |
4418 /* !!#### not right; needs to compute the max height of | |
4419 all the charsets */ | |
4420 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex, | |
4421 Vcharset_ascii); | |
4422 | |
4423 data->dl->ascent = max (data->dl->ascent, | |
4424 XFONT_INSTANCE (font_inst)->ascent); | |
4425 data->dl->descent = max (data->dl->descent, | |
4426 XFONT_INSTANCE (font_inst)-> | |
4427 descent); | |
4428 } | |
4429 else | |
4430 new_findex = old_findex; | |
4431 | |
4432 data->findex = new_findex; | |
4433 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | |
4434 XCDR (elt), depth - 1, | |
438 | 4435 max_pixsize, new_findex, type, |
4436 offset, car); | |
4187 | 4437 data->findex = old_findex; |
4438 Dynarr_add (formatted_string_extent_dynarr, ext); | |
4439 Dynarr_add (formatted_string_extent_start_dynarr, start); | |
4440 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); | |
4441 } | |
4442 } | |
428 | 4443 } |
4444 else if (GLYPHP (elt)) | |
4445 { | |
438 | 4446 /* Glyphs are considered as one character with respect to the modeline |
4447 horizontal scrolling facility. -- dv */ | |
4448 if (*offset > 0) | |
4449 *offset -= 1; | |
4450 else | |
4451 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos, | |
4452 cur_ext); | |
428 | 4453 } |
4454 else | |
4455 { | |
4456 invalid: | |
438 | 4457 { |
4970 | 4458 const Ascbyte *str = GETTEXT ("*invalid*"); |
438 | 4459 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */ |
4460 | |
4461 if (size <= *offset) | |
4462 *offset -= size; | |
4463 else | |
4464 { | |
867 | 4465 const Ibyte *tmp_str = |
4466 itext_n_addr ((const Ibyte *) str, *offset); | |
438 | 4467 |
440 | 4468 /* #### NOTE: I don't understand why a tmp_max is not computed and |
438 | 4469 used here as in the plain string case above. -- dv */ |
4470 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4471 min_pos, max_pos); | |
4472 *offset = 0; | |
4473 } | |
4474 } | |
428 | 4475 } |
4476 | |
4477 if (min_pos > pos) | |
4478 { | |
867 | 4479 add_string_to_fstring_db_runes (data, (const Ibyte *) "", pos, |
438 | 4480 min_pos, -1); |
428 | 4481 } |
4482 | |
4483 return pos; | |
4484 } | |
4485 | |
4486 /* Update just the modeline. Assumes the desired display structs. If | |
4487 they do not have a modeline block, it does nothing. */ | |
4488 static void | |
4489 regenerate_modeline (struct window *w) | |
4490 { | |
4491 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP); | |
4492 | |
4967 | 4493 if (!Dynarr_length (dla) || !Dynarr_begin (dla)->modeline) |
428 | 4494 return; |
4495 else | |
4496 { | |
4967 | 4497 generate_modeline (w, Dynarr_begin (dla), DESIRED_DISP); |
428 | 4498 redisplay_update_line (w, 0, 0, 0); |
4499 } | |
4500 } | |
4501 | |
4502 /* Make sure that modeline display line is present in the given | |
4503 display structs if the window has a modeline and update that | |
4504 line. Returns true if a modeline was needed. */ | |
4505 static int | |
4506 ensure_modeline_generated (struct window *w, int type) | |
4507 { | |
4508 int need_modeline; | |
4509 | |
4510 /* minibuffer windows don't have modelines */ | |
4511 if (MINI_WINDOW_P (w)) | |
4512 need_modeline = 0; | |
4513 /* windows which haven't had it turned off do */ | |
4514 else if (WINDOW_HAS_MODELINE_P (w)) | |
4515 need_modeline = 1; | |
4516 /* windows which have it turned off don't have a divider if there is | |
4517 a horizontal scrollbar */ | |
4518 else if (window_scrollbar_height (w)) | |
4519 need_modeline = 0; | |
4520 /* and in this case there is none */ | |
4521 else | |
4522 need_modeline = 1; | |
4523 | |
4524 if (need_modeline) | |
4525 { | |
4526 display_line_dynarr *dla; | |
4527 | |
4528 dla = window_display_lines (w, type); | |
4529 | |
4530 /* We don't care if there is a display line which is not | |
4187 | 4531 currently a modeline because it is definitely going to become |
4532 one if we have gotten to this point. */ | |
428 | 4533 if (Dynarr_length (dla) == 0) |
4534 { | |
4535 if (Dynarr_largest (dla) > 0) | |
5038 | 4536 Dynarr_incrementr (dla); |
428 | 4537 else |
4538 { | |
4539 struct display_line modeline; | |
4207 | 4540 |
4541 DISPLAY_LINE_INIT (modeline); | |
428 | 4542 Dynarr_add (dla, modeline); |
4543 } | |
4544 } | |
4545 | |
4546 /* If we're adding a new place marker go ahead and generate the | |
4187 | 4547 modeline so that it is available for use by |
4548 window_modeline_height. */ | |
4967 | 4549 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 4550 } |
4551 | |
4552 return need_modeline; | |
4553 } | |
4554 | |
4555 /* #### Kludge or not a kludge. I tend towards the former. */ | |
4556 int | |
4557 real_current_modeline_height (struct window *w) | |
4558 { | |
4559 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer); | |
4560 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer); | |
4561 | |
4562 if (ensure_modeline_generated (w, CMOTION_DISP)) | |
4563 { | |
4564 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP); | |
4565 | |
4566 if (Dynarr_length (dla)) | |
4567 { | |
4967 | 4568 if (Dynarr_begin (dla)->modeline) |
4569 return (Dynarr_begin (dla)->ascent + | |
4570 Dynarr_begin (dla)->descent); | |
428 | 4571 } |
4572 } | |
4573 return 0; | |
4574 } | |
4575 | |
4576 | |
4577 /***************************************************************************/ | |
819 | 4578 /* */ |
826 | 4579 /* displayable string routines */ |
819 | 4580 /* */ |
428 | 4581 /***************************************************************************/ |
4582 | |
4583 /* Given a position for a string in a window, ensure that the given | |
4584 display line DL accurately represents the text on a line starting | |
4585 at the given position. | |
4586 | |
4587 Yes, this is duplicating the code of create_text_block, but it | |
4588 looked just too hard to change create_text_block to handle strings | |
4589 *and* buffers. We already make a distinction between the two | |
4590 elsewhere in the code so I think unifying them would require a | |
4591 complete MULE rewrite. Besides, the other distinction is that these | |
4592 functions cover text that the user *cannot edit* so we can remove | |
4593 everything to do with cursors, minibuffers etc. Eventually the | |
4594 modeline routines should be modified to use this code as it copes | |
4595 with many more types of display situation. */ | |
4596 | |
665 | 4597 static Charbpos |
428 | 4598 create_string_text_block (struct window *w, Lisp_Object disp_string, |
4599 struct display_line *dl, | |
826 | 4600 Charcount start_pos, |
428 | 4601 prop_block_dynarr **prop, |
4602 face_index default_face) | |
4603 { | |
4604 struct frame *f = XFRAME (w->frame); | |
4605 /* Note that a lot of the buffer controlled stuff has been left in | |
4606 because you might well want to make use of it (selective display | |
4607 etc), its just the buffer text that we do not use. However, it | |
4608 seems to be possible for buffer to be nil sometimes so protect | |
4609 against this case. */ | |
4610 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; | |
4611 struct device *d = XDEVICE (f->device); | |
4612 | |
4613 /* we're working with these a lot so precalculate them */ | |
4614 Bytecount slen = XSTRING_LENGTH (disp_string); | |
826 | 4615 Bytecount byte_string_zv = slen; |
4616 Bytecount byte_start_pos = string_index_char_to_byte (disp_string, start_pos); | |
428 | 4617 |
4618 pos_data data; | |
4619 | |
4620 int truncate_win = b ? window_truncation_on (w) : 0; | |
4621 | |
442 | 4622 /* We're going to ditch selective display for static text, it's an |
4623 FSF thing and invisible extents are the way to go here. | |
4624 Implementing it also relies on a number of buffer-specific | |
428 | 4625 functions that we don't have the luxury of being able to use |
4626 here. */ | |
4627 | |
4628 /* The variable ctl-arrow allows the user to specify what characters | |
4629 can actually be displayed and which octal should be used for. | |
4630 #### This variable should probably have some rethought done to | |
4631 it. | |
4632 | |
4633 #### It would also be really nice if you could specify that | |
4634 the characters come out in hex instead of in octal. Mule | |
4635 does that by adding a ctl-hexa variable similar to ctl-arrow, | |
4636 but that's bogus -- we need a more general solution. I | |
4637 think you need to extend the concept of display tables | |
4638 into a more general conversion mechanism. Ideally you | |
4639 could specify a Lisp function that converts characters, | |
4640 but this violates the Second Golden Rule and besides would | |
4641 make things way way way way slow. | |
4642 | |
4643 So instead, we extend the display-table concept, which was | |
4644 historically limited to 256-byte vectors, to one of the | |
4645 following: | |
4646 | |
4647 a) A 256-entry vector, for backward compatibility; | |
4648 b) char-table, mapping characters to values; | |
4649 c) range-table, mapping ranges of characters to values; | |
4650 d) a list of the above. | |
4651 | |
4652 The (d) option allows you to specify multiple display tables | |
4653 instead of just one. Each display table can specify conversions | |
4654 for some characters and leave others unchanged. The way the | |
4655 character gets displayed is determined by the first display table | |
4656 with a binding for that character. This way, you could call a | |
4657 function `enable-hex-display' that adds a hex display-table to | |
4658 the list of display tables for the current buffer. | |
4659 | |
4660 #### ...not yet implemented... Also, we extend the concept of | |
4661 "mapping" to include a printf-like spec. Thus you can make all | |
4662 extended characters show up as hex with a display table like | |
4663 this: | |
4664 | |
4187 | 4665 #s(range-table data ((256 524288) (format "%x"))) |
428 | 4666 |
4667 Since more than one display table is possible, you have | |
4668 great flexibility in mapping ranges of characters. */ | |
867 | 4669 Ichar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) |
428 | 4670 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) |
4671 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
4672 ? 255 : 160)) : 255; | |
4673 | |
4674 Lisp_Object face_dt, window_dt; | |
4675 | |
4676 /* The text display block for this display line. */ | |
4677 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
4678 | |
4679 /* The first time through the main loop we need to force the glyph | |
4680 data to be updated. */ | |
4681 int initial = 1; | |
4682 | |
4683 /* Apparently the new extent_fragment_update returns an end position | |
4684 equal to the position passed in if there are no more runs to be | |
4685 displayed. */ | |
4686 int no_more_frags = 0; | |
4687 | |
4688 dl->used_prop_data = 0; | |
4689 dl->num_chars = 0; | |
442 | 4690 dl->line_continuation = 0; |
428 | 4691 |
4187 | 4692 /* Set up faces to use for clearing areas, used by output_display_line. */ |
428 | 4693 dl->default_findex = default_face; |
4187 | 4694 if (default_face > DEFAULT_INDEX) |
428 | 4695 { |
4696 dl->left_margin_findex = default_face; | |
4697 dl->right_margin_findex = default_face; | |
4698 } | |
4699 else | |
4700 { | |
434 | 4701 dl->left_margin_findex = |
428 | 4702 get_builtin_face_cache_index (w, Vleft_margin_face); |
434 | 4703 dl->right_margin_findex = |
428 | 4704 get_builtin_face_cache_index (w, Vright_margin_face); |
4705 } | |
4706 | |
4707 xzero (data); | |
4708 data.ef = extent_fragment_new (disp_string, f); | |
4709 | |
4710 /* These values are used by all of the rune addition routines. We add | |
4711 them to this structure for ease of passing. */ | |
4712 data.d = d; | |
793 | 4713 data.window = wrap_window (w); |
428 | 4714 data.db = db; |
4715 data.dl = dl; | |
4716 | |
826 | 4717 data.byte_charpos = byte_start_pos; |
428 | 4718 data.pixpos = dl->bounds.left_in; |
4719 data.last_charset = Qunbound; | |
4720 data.last_findex = default_face; | |
4721 data.result_str = Qnil; | |
4722 data.string = disp_string; | |
4723 | |
4724 /* Set the right boundary adjusting it to take into account any end | |
4725 glyph. Save the width of the end glyph for later use. */ | |
4726 data.max_pixpos = dl->bounds.right_in; | |
819 | 4727 data.max_pixpos -= data.end_glyph_width; |
428 | 4728 |
4729 data.cursor_type = NO_CURSOR; | |
4730 data.cursor_x = -1; | |
4731 | |
4732 data.start_col = 0; | |
4733 /* I don't think we want this, string areas should not scroll with | |
434 | 4734 the window |
428 | 4735 data.start_col = w->hscroll; |
826 | 4736 data.byte_start_col_enabled = (w->hscroll ? byte_start_pos : 0); |
428 | 4737 */ |
826 | 4738 data.byte_start_col_enabled = 0; |
428 | 4739 data.hscroll_glyph_width_adjust = 0; |
4740 | |
4741 /* We regenerate the line from the very beginning. */ | |
4742 Dynarr_reset (db->runes); | |
4743 | |
4744 /* Why is this less than or equal and not just less than? If the | |
4745 starting position is already equal to the maximum we can't add | |
4746 anything else, right? Wrong. We might still have a newline to | |
4747 add. A newline can use the room allocated for an end glyph since | |
4748 if we add it we know we aren't going to be adding any end | |
4749 glyph. */ | |
4750 | |
4751 /* #### Chuck -- I think this condition should be while (1). | |
4752 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
4753 and the begin-glyph ends exactly at the end of the window, the | |
4754 end-glyph and text might not be displayed. while (1) ensures | |
4755 that the loop terminates only when either (a) there is | |
4756 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
4757 | |
4758 #### Also I think you need to ensure that the operation | |
4759 "add begin glyphs; add end glyphs; add text" is atomic and | |
4760 can't get interrupted in the middle. If you run off the end | |
4761 of the line during that operation, then you keep accumulating | |
4762 propagation data until you're done. Otherwise, if the (e.g.) | |
4763 there's a begin glyph at a particular position and attempting | |
4764 to display that glyph results in window-end being hit and | |
4765 propagation data being generated, then the character at that | |
4766 position won't be displayed. | |
4767 | |
4768 #### See also the comment after the end of this loop, below. | |
4769 */ | |
4770 while (data.pixpos <= data.max_pixpos) | |
4771 { | |
4772 /* #### This check probably should not be necessary. */ | |
826 | 4773 if (data.byte_charpos > byte_string_zv) |
428 | 4774 { |
4775 /* #### urk! More of this lossage! */ | |
826 | 4776 data.byte_charpos--; |
428 | 4777 goto done; |
4778 } | |
4779 | |
4780 /* Check for face changes. */ | |
826 | 4781 if (initial || (!no_more_frags && data.byte_charpos == data.ef->end)) |
428 | 4782 { |
819 | 4783 Lisp_Object last_glyph = Qnil; |
4784 /* Deal with clipped glyphs that we have already displayed. */ | |
4967 | 4785 if (*prop && Dynarr_begin (*prop)->type == PROP_GLYPH) |
4786 { | |
4787 last_glyph = Dynarr_begin (*prop)->data.p_glyph.glyph; | |
819 | 4788 Dynarr_free (*prop); |
4789 *prop = 0; | |
4790 } | |
428 | 4791 /* Now compute the face and begin/end-glyph information. */ |
4792 data.findex = | |
793 | 4793 /* Remember that the extent-fragment routines deal in |
4187 | 4794 Bytexpos's. */ |
826 | 4795 extent_fragment_update (w, data.ef, data.byte_charpos, last_glyph); |
428 | 4796 /* This is somewhat cheesy but the alternative is to |
4187 | 4797 propagate default_face into extent_fragment_update. */ |
428 | 4798 if (data.findex == DEFAULT_INDEX) |
4799 data.findex = default_face; | |
4800 | |
4801 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
4802 | |
826 | 4803 if (data.byte_charpos == data.ef->end) |
428 | 4804 no_more_frags = 1; |
4805 } | |
4806 initial = 0; | |
4807 | |
4808 /* Determine what is next to be displayed. We first handle any | |
4187 | 4809 glyphs returned by glyphs_at_charbpos. If there are no glyphs to |
4810 display then we determine what to do based on the character at the | |
4811 current buffer position. */ | |
428 | 4812 |
4813 /* If the current position is covered by an invisible extent, do | |
4187 | 4814 nothing (except maybe add some ellipses). |
428 | 4815 |
4816 #### The behavior of begin and end-glyphs at the edge of an | |
4817 invisible extent should be investigated further. This is | |
4818 fairly low priority though. */ | |
4819 if (data.ef->invisible) | |
4820 { | |
4821 /* #### Chuck, perhaps you could look at this code? I don't | |
4822 really know what I'm doing. */ | |
4823 if (*prop) | |
4824 { | |
4825 Dynarr_free (*prop); | |
4826 *prop = 0; | |
4827 } | |
4828 | |
4829 /* The extent fragment code only sets this when we should | |
4830 really display the ellipses. It makes sure the ellipses | |
4831 don't get displayed more than once in a row. */ | |
4832 if (data.ef->invisible_ellipses) | |
4833 { | |
4834 struct glyph_block gb; | |
4835 | |
4836 data.ef->invisible_ellipses_already_displayed = 1; | |
4837 data.ef->invisible_ellipses = 0; | |
4838 gb.extent = Qnil; | |
4839 gb.glyph = Vinvisible_text_glyph; | |
4840 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
4841 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
4842 /* Perhaps they shouldn't propagate if the very next thing | |
4843 is to display a newline (for compatibility with | |
4844 selective-display-ellipses)? Maybe that's too | |
4845 abstruse. */ | |
4846 if (*prop) | |
4847 goto done; | |
4848 } | |
4849 | |
638 | 4850 /* #### What if we're dealing with a display table? */ |
428 | 4851 if (data.start_col) |
4852 data.start_col--; | |
4853 | |
826 | 4854 if (data.byte_charpos == byte_string_zv) |
428 | 4855 goto done; |
4856 else | |
826 | 4857 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 4858 } |
4859 | |
4860 /* If there is propagation data, then it represents the current | |
4187 | 4861 buffer position being displayed. Add them and advance the |
4862 position counter. This might also add the minibuffer | |
4863 prompt. */ | |
428 | 4864 else if (*prop) |
4865 { | |
4866 dl->used_prop_data = 1; | |
4867 *prop = add_propagation_runes (prop, &data); | |
4868 | |
4869 if (*prop) | |
4870 goto done; /* gee, a really narrow window */ | |
826 | 4871 else if (data.byte_charpos == byte_string_zv) |
428 | 4872 goto done; |
826 | 4873 else if (data.byte_charpos < 0) |
428 | 4874 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ |
826 | 4875 data.byte_charpos = 0; |
428 | 4876 else |
826 | 4877 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 4878 } |
4879 | |
4880 /* If there are end glyphs, add them to the line. These are | |
4881 the end glyphs for the previous run of text. We add them | |
4882 here rather than doing them at the end of handling the | |
4883 previous run so that glyphs at the beginning and end of | |
4884 a line are handled correctly. */ | |
4885 else if (Dynarr_length (data.ef->end_glyphs) > 0) | |
4886 { | |
867 | 4887 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4888 *prop = add_glyph_runes (&data, END_GLYPHS); |
819 | 4889 |
4890 if (*prop) { | |
428 | 4891 goto done; |
819 | 4892 } |
428 | 4893 } |
4894 | |
4895 /* If there are begin glyphs, add them to the line. */ | |
4896 else if (Dynarr_length (data.ef->begin_glyphs) > 0) | |
4897 { | |
867 | 4898 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4899 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); |
819 | 4900 |
4901 if (*prop) { | |
428 | 4902 goto done; |
819 | 4903 } |
428 | 4904 } |
4905 | |
4906 /* If at end-of-buffer, we've already processed begin and | |
4907 end-glyphs at this point and there's no text to process, | |
4908 so we're done. */ | |
826 | 4909 else if (data.byte_charpos == byte_string_zv) |
428 | 4910 goto done; |
4911 | |
4912 else | |
4913 { | |
4914 Lisp_Object entry = Qnil; | |
4915 /* Get the character at the current buffer position. */ | |
867 | 4916 data.ch = string_ichar (disp_string, data.byte_charpos); |
428 | 4917 if (!NILP (face_dt) || !NILP (window_dt)) |
4918 entry = display_table_entry (data.ch, face_dt, window_dt); | |
4919 | |
4920 /* If there is a display table entry for it, hand it off to | |
4187 | 4921 add_disp_table_entry_runes and let it worry about it. */ |
428 | 4922 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) |
4923 { | |
4924 *prop = add_disp_table_entry_runes (&data, entry); | |
4925 | |
4926 if (*prop) | |
4927 goto done; | |
4928 } | |
4929 | |
4930 /* Check if we have hit a newline character. If so, add a marker | |
4187 | 4931 to the line and end this loop. */ |
428 | 4932 else if (data.ch == '\n') |
4933 { | |
4934 /* We aren't going to be adding an end glyph so give its | |
4187 | 4935 space back in order to make sure that the cursor can |
4936 fit. */ | |
819 | 4937 data.max_pixpos += data.end_glyph_width; |
428 | 4938 goto done; |
4939 } | |
4940 | |
4941 /* If the current character is considered to be printable, then | |
4187 | 4942 just add it. */ |
428 | 4943 else if (data.ch >= printable_min) |
4944 { | |
867 | 4945 *prop = add_ichar_rune (&data); |
428 | 4946 if (*prop) |
4947 goto done; | |
4948 } | |
4949 | |
4950 /* If the current character is a tab, determine the next tab | |
4187 | 4951 starting position and add a blank rune which extends from the |
4952 current pixel position to that starting position. */ | |
428 | 4953 else if (data.ch == '\t') |
4954 { | |
4955 int tab_start_pixpos = data.pixpos; | |
4956 int next_tab_start; | |
4957 int char_tab_width; | |
4958 int prop_width = 0; | |
4959 | |
4960 if (data.start_col > 1) | |
4961 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); | |
4962 | |
4963 next_tab_start = | |
4964 next_tab_position (w, tab_start_pixpos, | |
4965 dl->bounds.left_in + | |
4966 data.hscroll_glyph_width_adjust); | |
4967 if (next_tab_start > data.max_pixpos) | |
4968 { | |
4969 prop_width = next_tab_start - data.max_pixpos; | |
4970 next_tab_start = data.max_pixpos; | |
4971 } | |
4972 data.blank_width = next_tab_start - data.pixpos; | |
4973 char_tab_width = | |
4974 (next_tab_start - tab_start_pixpos) / space_width (w); | |
4975 | |
4976 *prop = add_blank_rune (&data, w, char_tab_width); | |
4977 | |
4978 /* add_blank_rune is only supposed to be called with | |
819 | 4979 sizes guaranteed to fit in the available space. */ |
428 | 4980 assert (!(*prop)); |
4981 | |
4982 if (prop_width) | |
4983 { | |
4984 struct prop_block pb; | |
4985 *prop = Dynarr_new (prop_block); | |
4986 | |
4987 pb.type = PROP_BLANK; | |
4988 pb.data.p_blank.width = prop_width; | |
4989 pb.data.p_blank.findex = data.findex; | |
4990 Dynarr_add (*prop, pb); | |
4991 | |
4992 goto done; | |
4993 } | |
4994 } | |
4995 | |
4996 /* If character is a control character, pass it off to | |
4187 | 4997 add_control_char_runes. |
428 | 4998 |
4999 The is_*() routines have undefined results on | |
5000 arguments outside of the range [-1, 255]. (This | |
5001 often bites people who carelessly use `char' instead | |
5002 of `unsigned char'.) | |
5003 */ | |
867 | 5004 else if (data.ch < 0x100 && iscntrl ((Ibyte) data.ch)) |
428 | 5005 { |
5006 *prop = add_control_char_runes (&data, b); | |
5007 | |
5008 if (*prop) | |
5009 goto done; | |
5010 } | |
5011 | |
5012 /* If the character is above the ASCII range and we have not | |
4187 | 5013 already handled it, then print it as an octal number. */ |
428 | 5014 else if (data.ch >= 0200) |
5015 { | |
5016 *prop = add_octal_runes (&data); | |
5017 | |
5018 if (*prop) | |
5019 goto done; | |
5020 } | |
5021 | |
5022 /* Assume the current character is considered to be printable, | |
4187 | 5023 then just add it. */ |
428 | 5024 else |
5025 { | |
867 | 5026 *prop = add_ichar_rune (&data); |
428 | 5027 if (*prop) |
5028 goto done; | |
5029 } | |
5030 | |
826 | 5031 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 5032 } |
5033 } | |
5034 | |
819 | 5035 done: |
428 | 5036 |
5037 /* Determine the starting point of the next line if we did not hit the | |
5038 end of the buffer. */ | |
826 | 5039 if (data.byte_charpos < byte_string_zv) |
428 | 5040 { |
5041 /* #### This check is not correct. If the line terminated | |
5042 due to a begin-glyph or end-glyph hitting window-end, then | |
826 | 5043 data.ch will not point to the character at data.byte_charpos. If |
428 | 5044 you make the two changes mentioned at the top of this loop, |
5045 you should be able to say '(if (*prop))'. That should also | |
826 | 5046 make it possible to eliminate the data.byte_charpos < BYTE_BUF_ZV (b) |
428 | 5047 check. */ |
5048 | |
5049 /* The common case is that the line ended because we hit a newline. | |
4187 | 5050 In that case, the next character is just the next buffer |
5051 position. */ | |
428 | 5052 if (data.ch == '\n') |
5053 { | |
826 | 5054 INC_BYTECOUNT (XSTRING_DATA (disp_string), data.byte_charpos); |
428 | 5055 } |
5056 | |
5057 /* Otherwise we have a buffer line which cannot fit on one display | |
4187 | 5058 line. */ |
428 | 5059 else |
5060 { | |
5061 struct glyph_block gb; | |
5062 struct glyph_cachel *cachel; | |
5063 | |
5064 /* If the line is to be truncated then we actually have to look | |
4187 | 5065 for the next newline. We also add the end-of-line glyph which |
5066 we know will fit because we adjusted the right border before | |
5067 we starting laying out the line. */ | |
819 | 5068 data.max_pixpos += data.end_glyph_width; |
428 | 5069 data.findex = default_face; |
5070 gb.extent = Qnil; | |
5071 | |
5072 if (truncate_win) | |
5073 { | |
826 | 5074 Bytecount byte_pos; |
428 | 5075 |
5076 /* Now find the start of the next line. */ | |
867 | 5077 byte_pos = byte_find_next_ichar_in_string (disp_string, '\n', |
826 | 5078 data.byte_charpos, 1); |
428 | 5079 |
5080 data.cursor_type = NO_CURSOR; | |
826 | 5081 data.byte_charpos = byte_pos; |
428 | 5082 gb.glyph = Vtruncation_glyph; |
5083 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
5084 } | |
5085 else | |
5086 { | |
5087 /* The cursor can never be on the continuation glyph. */ | |
5088 data.cursor_type = NO_CURSOR; | |
5089 | |
826 | 5090 /* data.byte_charpos is already at the start of the next line. */ |
428 | 5091 |
442 | 5092 dl->line_continuation = 1; |
428 | 5093 gb.glyph = Vcontinuation_glyph; |
5094 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
5095 } | |
5096 | |
819 | 5097 if (data.end_glyph_width) |
428 | 5098 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); |
5099 | |
826 | 5100 if (truncate_win && data.byte_charpos == byte_string_zv) |
428 | 5101 { |
867 | 5102 const Ibyte *endb = itext_n_addr (XSTRING_DATA (disp_string), |
826 | 5103 byte_string_zv); |
867 | 5104 DEC_IBYTEPTR (endb); |
5105 if (itext_ichar (endb) != '\n') | |
428 | 5106 { |
5107 /* #### Damn this losing shit. */ | |
826 | 5108 data.byte_charpos++; |
428 | 5109 } |
5110 } | |
5111 } | |
5112 } | |
826 | 5113 else if (data.byte_charpos == byte_string_zv) |
428 | 5114 { |
5115 /* create_text_block () adds a bogus \n marker here which screws | |
5116 up subwindow display. Since we never have a cursor in the | |
5117 gutter we can safely ignore it. */ | |
5118 } | |
5119 /* Calculate left whitespace boundary. */ | |
5120 { | |
5121 int elt = 0; | |
5122 | |
5123 /* Whitespace past a newline is considered right whitespace. */ | |
5124 while (elt < Dynarr_length (db->runes)) | |
5125 { | |
5126 struct rune *rb = Dynarr_atp (db->runes, elt); | |
5127 | |
5128 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
5129 || rb->type == RUNE_BLANK) | |
5130 { | |
5131 dl->bounds.left_white += rb->width; | |
5132 elt++; | |
5133 } | |
5134 else | |
5135 elt = Dynarr_length (db->runes); | |
5136 } | |
5137 } | |
5138 | |
5139 /* Calculate right whitespace boundary. */ | |
5140 { | |
5141 int elt = Dynarr_length (db->runes) - 1; | |
5142 int done = 0; | |
5143 | |
5144 while (!done && elt >= 0) | |
5145 { | |
5146 struct rune *rb = Dynarr_atp (db->runes, elt); | |
5147 | |
5148 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
5149 && isspace (rb->object.chr.ch)) | |
5150 && !rb->type == RUNE_BLANK) | |
5151 { | |
5152 dl->bounds.right_white = rb->xpos + rb->width; | |
5153 done = 1; | |
5154 } | |
5155 | |
5156 elt--; | |
5157 | |
5158 } | |
5159 | |
5160 /* The line is blank so everything is considered to be right | |
5161 whitespace. */ | |
5162 if (!done) | |
5163 dl->bounds.right_white = dl->bounds.left_in; | |
5164 } | |
5165 | |
5166 /* Set the display blocks bounds. */ | |
5167 db->start_pos = dl->bounds.left_in; | |
5168 if (Dynarr_length (db->runes)) | |
5169 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
5170 struct rune *rb = Dynarr_lastp (db->runes); |
428 | 5171 |
5172 db->end_pos = rb->xpos + rb->width; | |
5173 } | |
5174 else | |
5175 db->end_pos = dl->bounds.right_white; | |
5176 | |
819 | 5177 calculate_baseline (&data); |
428 | 5178 |
5179 dl->ascent = data.new_ascent; | |
5180 dl->descent = data.new_descent; | |
5181 | |
5182 { | |
5183 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
5184 | |
5185 if (dl->ascent < ascent) | |
5186 dl->ascent = ascent; | |
5187 } | |
5188 { | |
5189 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
5190 | |
5191 if (dl->descent < descent) | |
5192 dl->descent = descent; | |
5193 } | |
5194 | |
819 | 5195 calculate_yoffset (dl, db); |
5196 | |
428 | 5197 dl->cursor_elt = data.cursor_x; |
5198 /* #### lossage lossage lossage! Fix this shit! */ | |
826 | 5199 if (data.byte_charpos > byte_string_zv) |
5200 dl->end_charpos = buffer_or_string_bytexpos_to_charxpos (disp_string, | |
5201 byte_string_zv); | |
428 | 5202 else |
826 | 5203 dl->end_charpos = |
5204 buffer_or_string_bytexpos_to_charxpos (disp_string, | |
5205 data.byte_charpos) - 1; | |
428 | 5206 if (truncate_win) |
434 | 5207 data.dl->num_chars = |
826 | 5208 string_column_at_point (disp_string, dl->end_charpos, |
793 | 5209 b ? XINT (b->tab_width) : 8); |
428 | 5210 else |
5211 /* This doesn't correctly take into account tabs and control | |
5212 characters but if the window isn't being truncated then this | |
5213 value isn't going to end up being used anyhow. */ | |
826 | 5214 data.dl->num_chars = dl->end_charpos - dl->charpos; |
428 | 5215 |
5216 /* #### handle horizontally scrolled line with text none of which | |
5217 was actually laid out. */ | |
5218 | |
5219 /* #### handle any remainder of overlay arrow */ | |
5220 | |
5221 if (*prop == ADD_FAILED) | |
5222 *prop = NULL; | |
5223 | |
5224 if (truncate_win && *prop) | |
5225 { | |
5226 Dynarr_free (*prop); | |
5227 *prop = NULL; | |
5228 } | |
5229 | |
5230 extent_fragment_delete (data.ef); | |
5231 | |
5232 /* #### If we started at EOB, then make sure we return a value past | |
5233 it so that regenerate_window will exit properly. This is bogus. | |
5234 The main loop should get fixed so that it isn't necessary to call | |
5235 this function if we are already at EOB. */ | |
5236 | |
826 | 5237 if (data.byte_charpos == byte_string_zv && byte_start_pos == byte_string_zv) |
793 | 5238 return string_index_byte_to_char (disp_string, |
826 | 5239 data.byte_charpos) + 1; /* Yuck! */ |
428 | 5240 else |
826 | 5241 return string_index_byte_to_char (disp_string, data.byte_charpos); |
428 | 5242 } |
5243 | |
5244 /* Given a display line and a starting position, ensure that the | |
5245 contents of the display line accurately represent the visual | |
5246 representation of the buffer contents starting from the given | |
5247 position when displayed in the given window. The display line ends | |
5248 when the contents of the line reach the right boundary of the given | |
434 | 5249 window. |
5250 | |
428 | 5251 This is very similar to generate_display_line but with the same |
5252 limitations as create_string_text_block. I have taken the liberty | |
665 | 5253 of fixing the bytebpos stuff though.*/ |
5254 | |
5255 static Charbpos | |
428 | 5256 generate_string_display_line (struct window *w, Lisp_Object disp_string, |
5257 struct display_line *dl, | |
826 | 5258 Charcount start_pos, |
428 | 5259 prop_block_dynarr **prop, |
5260 face_index default_face) | |
5261 { | |
826 | 5262 Charcount ret_charcount; |
428 | 5263 |
5264 /* you must set bounds before calling this. */ | |
434 | 5265 |
428 | 5266 /* Reset what this line is using. */ |
5267 if (dl->display_blocks) | |
5268 Dynarr_reset (dl->display_blocks); | |
5269 if (dl->left_glyphs) | |
5270 { | |
5271 Dynarr_free (dl->left_glyphs); | |
5272 dl->left_glyphs = 0; | |
5273 } | |
5274 if (dl->right_glyphs) | |
5275 { | |
5276 Dynarr_free (dl->right_glyphs); | |
5277 dl->right_glyphs = 0; | |
5278 } | |
5279 | |
5280 /* We aren't generating a modeline at the moment. */ | |
5281 dl->modeline = 0; | |
5282 | |
5283 /* Create a display block for the text region of the line. */ | |
826 | 5284 ret_charcount = create_string_text_block (w, disp_string, dl, start_pos, |
5285 prop, default_face); | |
5286 dl->charpos = start_pos; | |
5287 if (dl->end_charpos < dl->charpos) | |
5288 dl->end_charpos = dl->charpos; | |
428 | 5289 |
5290 /* If there are left glyphs associated with any character in the | |
5291 text block, then create a display block to handle them. */ | |
5292 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
5293 create_left_glyph_block (w, dl, 0); | |
5294 | |
5295 /* If there are right glyphs associated with any character in the | |
5296 text block, then create a display block to handle them. */ | |
5297 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
5298 create_right_glyph_block (w, dl); | |
5299 | |
826 | 5300 return ret_charcount; |
428 | 5301 } |
5302 | |
2518 | 5303 /* |
5304 | |
5038 | 5305 Info on reentrancy crashes, with backtraces given: |
5306 | |
5307 (Info-goto-node "(internals)Critical Redisplay Sections") | |
5308 | |
1318 | 5309 */ |
5310 | |
5311 | |
428 | 5312 /* This is ripped off from regenerate_window. All we want to do is |
5313 loop through elements in the string creating display lines until we | |
5314 have covered the provided area. Simple really. */ | |
5315 void | |
5316 generate_displayable_area (struct window *w, Lisp_Object disp_string, | |
5317 int xpos, int ypos, int width, int height, | |
5318 display_line_dynarr* dla, | |
826 | 5319 Charcount start_pos, |
428 | 5320 face_index default_face) |
5321 { | |
5322 int yend = ypos + height; | |
5323 Charcount s_zv; | |
5324 prop_block_dynarr *prop = 0; | |
5325 layout_bounds bounds; | |
2518 | 5326 int depth = -1; |
5327 | |
428 | 5328 /* if there's nothing to do then do nothing. code after this assumes |
5329 there is something to do. */ | |
5330 if (NILP (disp_string)) | |
5331 return; | |
5332 | |
2518 | 5333 /* See comment in regenerate_window() */ |
5334 if (!in_display) | |
5335 depth = enter_redisplay_critical_section (); | |
5336 | |
5337 assert (dla); | |
5338 Dynarr_reset (dla); | |
5339 | |
826 | 5340 s_zv = string_char_length (disp_string); |
428 | 5341 |
5342 bounds.left_out = xpos; | |
5343 bounds.right_out = xpos + width; | |
5344 /* The inner boundaries mark where the glyph margins are located. */ | |
5345 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
5346 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
5347 /* We cannot fully calculate the whitespace boundaries as they | |
5348 depend on the contents of the line being displayed. */ | |
5349 bounds.left_white = bounds.left_in; | |
5350 bounds.right_white = bounds.right_in; | |
5351 | |
5352 while (ypos < yend) | |
5353 { | |
5354 struct display_line dl; | |
5355 struct display_line *dlp; | |
826 | 5356 Charcount next_pos; |
428 | 5357 int local; |
851 | 5358 int pos_of_dlp = -1; |
428 | 5359 |
5360 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5361 { | |
851 | 5362 pos_of_dlp = Dynarr_length (dla); |
5363 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5364 local = 0; |
5365 } | |
5366 else | |
5367 { | |
4207 | 5368 DISPLAY_LINE_INIT (dl); |
428 | 5369 dlp = &dl; |
5370 local = 1; | |
5371 } | |
5372 | |
5373 dlp->bounds = bounds; | |
5374 dlp->offset = 0; | |
1318 | 5375 Dynarr_lock (dla); |
428 | 5376 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos, |
5377 &prop, default_face); | |
1318 | 5378 Dynarr_unlock (dla); |
428 | 5379 /* we need to make sure that we continue along the line if there |
4187 | 5380 is more left to display otherwise we just end up redisplaying |
5381 the same chunk over and over again. */ | |
428 | 5382 if (next_pos == start_pos && next_pos < s_zv) |
5383 start_pos++; | |
5384 else | |
5385 start_pos = next_pos; | |
5386 | |
5387 dlp->ypos = ypos + dlp->ascent; | |
5388 ypos = dlp->ypos + dlp->descent; | |
5389 | |
5390 if (ypos > yend) | |
5391 { | |
5392 int visible_height = dlp->ascent + dlp->descent; | |
5393 | |
5394 dlp->clip = (ypos - yend); | |
5395 visible_height -= dlp->clip; | |
5396 | |
5397 if (visible_height < VERTICAL_CLIP (w, 1)) | |
5398 { | |
5399 if (local) | |
5400 free_display_line (dlp); | |
5401 break; | |
5402 } | |
5403 } | |
5404 else | |
5405 dlp->clip = 0; | |
5406 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5407 if (pos_of_dlp < 0) |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5408 Dynarr_add (dla, *dlp); |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5409 else if (pos_of_dlp == Dynarr_length (dla)) |
5038 | 5410 Dynarr_incrementr (dla); |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5411 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5412 ABORT (); |
428 | 5413 |
5414 /* #### This type of check needs to be done down in the | |
5415 generate_display_line call. */ | |
5416 if (start_pos >= s_zv) | |
5417 break; | |
5418 } | |
5419 | |
5420 if (prop) | |
5421 Dynarr_free (prop); | |
2518 | 5422 |
5423 if (depth >= 0) | |
5424 exit_redisplay_critical_section (depth); | |
428 | 5425 } |
5426 | |
5427 | |
5428 /***************************************************************************/ | |
5429 /* */ | |
5430 /* window-regeneration routines */ | |
5431 /* */ | |
5432 /***************************************************************************/ | |
5433 | |
5434 /* For a given window and starting position in the buffer it contains, | |
5435 ensure that the TYPE display lines accurately represent the | |
5436 presentation of the window. We pass the buffer instead of getting | |
5437 it from the window since redisplay_window may have temporarily | |
5438 changed it to the echo area buffer. */ | |
5439 | |
5440 static void | |
2518 | 5441 regenerate_window (struct window *w, Charbpos start_pos, Charbpos point, |
5442 int type) | |
428 | 5443 { |
5444 struct frame *f = XFRAME (w->frame); | |
5445 struct buffer *b = XBUFFER (w->buffer); | |
5446 int ypos = WINDOW_TEXT_TOP (w); | |
5447 int yend; /* set farther down */ | |
5448 int yclip = WINDOW_TEXT_TOP_CLIP (w); | |
442 | 5449 int force; |
2518 | 5450 int depth = -1; |
428 | 5451 |
5452 prop_block_dynarr *prop; | |
5453 layout_bounds bounds; | |
5454 display_line_dynarr *dla; | |
5455 int need_modeline; | |
5456 | |
5457 /* The lines had better exist by this point. */ | |
5458 if (!(dla = window_display_lines (w, type))) | |
2500 | 5459 ABORT (); |
2518 | 5460 |
5461 if (!in_display) | |
5462 depth = enter_redisplay_critical_section (); | |
5463 | |
5038 | 5464 /* This is one spot where a reentrancy crash will occur, due to a check |
2518 | 5465 in the dynarr to make sure it isn't "locked" */ |
5466 /* | |
5467 | |
5038 | 5468 Info on reentrancy crashes, with backtraces given: |
5469 | |
5470 (Info-goto-node "(internals)Critical Redisplay Sections") | |
2518 | 5471 */ |
5472 | |
428 | 5473 Dynarr_reset (dla); |
5474 w->max_line_len = 0; | |
5475 | |
4968 | 5476 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
5477 because we initialized them at startup and the only way to reduce | |
5478 their number is through calling reset_face_cachels() or | |
5479 reset_glyph_cachels(), which as a side effect sets up a number of | |
5480 standard entries */ | |
5481 assert (Dynarr_length (w->face_cachels)); | |
5482 assert (Dynarr_length (w->glyph_cachels)); | |
5483 | |
5484 #if 0 | |
5485 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
5486 not needed */ | |
428 | 5487 /* Normally these get updated in redisplay_window but it is possible |
5488 for this function to get called from some other points where that | |
5489 update may not have occurred. This acts as a safety check. */ | |
5490 if (!Dynarr_length (w->face_cachels)) | |
5491 reset_face_cachels (w); | |
5492 if (!Dynarr_length (w->glyph_cachels)) | |
5493 reset_glyph_cachels (w); | |
4968 | 5494 #endif |
428 | 5495 |
5496 Fset_marker (w->start[type], make_int (start_pos), w->buffer); | |
5497 Fset_marker (w->pointm[type], make_int (point), w->buffer); | |
5498 w->last_point_x[type] = -1; | |
5499 w->last_point_y[type] = -1; | |
5500 | |
5501 /* Make sure a modeline is in the structs if needed. */ | |
5502 need_modeline = ensure_modeline_generated (w, type); | |
5503 | |
5504 /* Wait until here to set this so that the structs have a modeline | |
5505 generated in the case where one didn't exist. */ | |
5506 yend = WINDOW_TEXT_BOTTOM (w); | |
5507 | |
5508 bounds = calculate_display_line_boundaries (w, 0); | |
5509 | |
5510 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */ | |
5511 if (MINI_WINDOW_P (w) | |
5512 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt)) | |
5513 && !echo_area_active (f) | |
5514 && start_pos == BUF_BEGV (b)) | |
5515 { | |
5516 struct prop_block pb; | |
5517 Lisp_Object string; | |
5518 prop = Dynarr_new (prop_block); | |
5519 | |
5198 | 5520 string = concat2 (Vminibuf_preprompt, Vminibuf_prompt); |
428 | 5521 pb.type = PROP_MINIBUF_PROMPT; |
5198 | 5522 pb.data.p_string.str = XSTRING_DATA (string); |
5523 pb.data.p_string.len = XSTRING_LENGTH (string); | |
428 | 5524 Dynarr_add (prop, pb); |
5525 } | |
5526 else | |
5527 prop = 0; | |
5528 | |
442 | 5529 /* When we are computing things for scrolling purposes, make |
5530 sure at least one line is always generated */ | |
5531 force = (type == CMOTION_DISP); | |
5532 | |
5533 /* Make sure this is set always */ | |
5534 /* Note the conversion at end */ | |
5535 w->window_end_pos[type] = start_pos; | |
5536 while (ypos < yend || force) | |
428 | 5537 { |
5538 struct display_line dl; | |
5539 struct display_line *dlp; | |
5540 int local; | |
851 | 5541 int pos_of_dlp = -1; |
428 | 5542 |
5543 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5544 { | |
851 | 5545 pos_of_dlp = Dynarr_length (dla); |
5546 dlp = Dynarr_atp (dla, pos_of_dlp); | |
428 | 5547 local = 0; |
5548 } | |
5549 else | |
5550 { | |
4207 | 5551 DISPLAY_LINE_INIT (dl); |
428 | 5552 dlp = &dl; |
5553 local = 1; | |
5554 } | |
5555 | |
5556 dlp->bounds = bounds; | |
5557 dlp->offset = 0; | |
1318 | 5558 Dynarr_lock (dla); |
428 | 5559 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); |
1318 | 5560 Dynarr_unlock (dla); |
428 | 5561 |
5562 if (yclip > dlp->ascent) | |
5563 { | |
5564 /* this should never happen, but if it does just display the | |
5565 whole line */ | |
5566 yclip = 0; | |
5567 } | |
5568 | |
5569 dlp->ypos = (ypos + dlp->ascent) - yclip; | |
5570 ypos = dlp->ypos + dlp->descent; | |
5571 | |
5572 /* See if we've been asked to start midway through a line, for | |
4187 | 5573 partial display line scrolling. */ |
434 | 5574 if (yclip) |
428 | 5575 { |
5576 dlp->top_clip = yclip; | |
5577 yclip = 0; | |
5578 } | |
5579 else | |
5580 dlp->top_clip = 0; | |
5581 | |
5582 if (ypos > yend) | |
5583 { | |
5584 int visible_height = dlp->ascent + dlp->descent; | |
5585 | |
5586 dlp->clip = (ypos - yend); | |
5587 /* Although this seems strange we could have a single very | |
5588 tall line visible for which we need to account for both | |
5589 the top clip and the bottom clip. */ | |
5590 visible_height -= (dlp->clip + dlp->top_clip); | |
5591 | |
442 | 5592 if (visible_height < VERTICAL_CLIP (w, 1) && !force) |
428 | 5593 { |
5594 if (local) | |
5595 free_display_line (dlp); | |
5596 break; | |
5597 } | |
5598 } | |
5599 else | |
5600 dlp->clip = 0; | |
5601 | |
5602 if (dlp->cursor_elt != -1) | |
5603 { | |
5604 /* #### This check is steaming crap. Have to get things | |
4187 | 5605 fixed so when create_text_block hits EOB, we're done, |
5606 period. */ | |
428 | 5607 if (w->last_point_x[type] == -1) |
5608 { | |
5609 w->last_point_x[type] = dlp->cursor_elt; | |
5610 w->last_point_y[type] = Dynarr_length (dla); | |
5611 } | |
5612 else | |
5613 { | |
5614 /* #### This means that we've added a cursor at EOB | |
4187 | 5615 twice. Yuck oh yuck. */ |
1318 | 5616 struct display_block *db; |
5617 | |
5618 Dynarr_lock (dla); | |
5619 db = get_display_block_from_line (dlp, TEXT); | |
5620 Dynarr_unlock (dla); | |
428 | 5621 |
5622 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR; | |
5623 dlp->cursor_elt = -1; | |
5624 } | |
5625 } | |
5626 | |
5627 if (dlp->num_chars > w->max_line_len) | |
5628 w->max_line_len = dlp->num_chars; | |
5629 | |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5630 if (pos_of_dlp < 0) |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5631 Dynarr_add (dla, *dlp); |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5632 else if (pos_of_dlp == Dynarr_length (dla)) |
5038 | 5633 Dynarr_incrementr (dla); |
4418
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5634 else |
9bcdf9a3a783
Use Dynarr_increment instead of Dynarr_add when building a line in place.
Jerry James <james@xemacs.org>
parents:
4207
diff
changeset
|
5635 ABORT (); |
428 | 5636 |
5637 /* #### This isn't right, but it is close enough for now. */ | |
5638 w->window_end_pos[type] = start_pos; | |
5639 | |
5640 /* #### This type of check needs to be done down in the | |
5641 generate_display_line call. */ | |
5642 if (start_pos > BUF_ZV (b)) | |
5643 break; | |
442 | 5644 |
5645 force = 0; | |
428 | 5646 } |
5647 | |
5648 if (prop) | |
5649 Dynarr_free (prop); | |
5650 | |
5651 /* #### More not quite right, but close enough. */ | |
442 | 5652 /* Ben sez: apparently window_end_pos[] is measured |
428 | 5653 as the number of characters between the window end and the |
5654 end of the buffer? This seems rather weirdo. What's | |
442 | 5655 the justification for this? |
5656 | |
5657 JV sez: Because BUF_Z (b) would be a good initial value, however | |
5658 that can change. This representation allows initalizing with 0. | |
5659 */ | |
428 | 5660 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; |
5661 | |
5662 if (need_modeline) | |
5663 { | |
5664 /* We know that this is the right thing to use because we put it | |
4187 | 5665 there when we first started working in this function. */ |
4967 | 5666 generate_modeline (w, Dynarr_begin (dla), type); |
428 | 5667 } |
2518 | 5668 |
5669 if (depth >= 0) | |
5670 exit_redisplay_critical_section (depth); | |
428 | 5671 } |
5672 | |
826 | 5673 #define REGEN_INC_FIND_START_END \ |
5674 do { \ | |
5675 /* Determine start and end of lines. */ \ | |
5676 if (!Dynarr_length (cdla)) \ | |
5677 return 0; \ | |
5678 else \ | |
5679 { \ | |
4967 | 5680 if (Dynarr_begin (cdla)->modeline && Dynarr_begin (ddla)->modeline) \ |
826 | 5681 { \ |
5682 dla_start = 1; \ | |
5683 } \ | |
4967 | 5684 else if (!Dynarr_begin (cdla)->modeline \ |
5685 && !Dynarr_begin (ddla)->modeline) \ | |
826 | 5686 { \ |
5687 dla_start = 0; \ | |
5688 } \ | |
5689 else \ | |
2500 | 5690 ABORT (); /* structs differ */ \ |
826 | 5691 \ |
5692 dla_end = Dynarr_length (cdla) - 1; \ | |
5693 } \ | |
5694 \ | |
5695 start_pos = (Dynarr_atp (cdla, dla_start)->charpos \ | |
5696 + Dynarr_atp (cdla, dla_start)->offset); \ | |
5697 /* If this isn't true, then startp has changed and we need to do a \ | |
5698 full regen. */ \ | |
5699 if (startp != start_pos) \ | |
5700 return 0; \ | |
5701 \ | |
5702 /* Point is outside the visible region so give up. */ \ | |
5703 if (pointm < start_pos) \ | |
5704 return 0; \ | |
5705 \ | |
428 | 5706 } while (0) |
5707 | |
5708 /* This attempts to incrementally update the display structures. It | |
5709 returns a boolean indicating success or failure. This function is | |
5710 very similar to regenerate_window_incrementally and is in fact only | |
5711 called from that function. However, because of the nature of the | |
5712 changes it deals with it sometimes makes different assumptions | |
5713 which can lead to success which are much more difficult to make | |
5714 when dealing with buffer changes. */ | |
5715 | |
5716 static int | |
665 | 5717 regenerate_window_extents_only_changed (struct window *w, Charbpos startp, |
5718 Charbpos pointm, | |
428 | 5719 Charcount beg_unchanged, |
5720 Charcount end_unchanged) | |
5721 { | |
5722 struct buffer *b = XBUFFER (w->buffer); | |
5723 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5724 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5725 | |
5726 int dla_start = 0; | |
5727 int dla_end, line; | |
5728 int first_line, last_line; | |
665 | 5729 Charbpos start_pos; |
428 | 5730 /* Don't define this in the loop where it is used because we |
5731 definitely want its value to survive between passes. */ | |
5732 prop_block_dynarr *prop = NULL; | |
5733 | |
5734 /* If we don't have any buffer change recorded but the modiff flag has | |
5735 been incremented, then fail. I'm not sure of the exact circumstances | |
5736 under which this can happen, but I believe that it is probably a | |
5737 reasonable happening. */ | |
5738 if (!point_visible (w, pointm, CURRENT_DISP) | |
5739 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)) | |
5740 return 0; | |
5741 | |
5742 /* If the cursor is moved we attempt to update it. If we succeed we | |
5743 go ahead and proceed with the optimization attempt. */ | |
5744 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5745 || pointm != marker_position (w->last_point[CURRENT_DISP])) | |
5746 { | |
5747 struct frame *f = XFRAME (w->frame); | |
5748 struct device *d = XDEVICE (f->device); | |
5749 struct frame *sel_f = device_selected_frame (d); | |
5750 int success = 0; | |
5751 | |
5752 if (w->last_point_x[CURRENT_DISP] != -1 | |
5753 && w->last_point_y[CURRENT_DISP] != -1) | |
5754 { | |
5755 | |
5756 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w))) | |
5757 { | |
5758 /* Always regenerate the modeline in case it is | |
4187 | 5759 displaying the current line or column. */ |
428 | 5760 regenerate_modeline (w); |
5761 success = 1; | |
5762 } | |
5763 } | |
5764 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f))) | |
5765 { | |
5766 if (f->modeline_changed) | |
5767 regenerate_modeline (w); | |
5768 success = 1; | |
5769 } | |
5770 | |
5771 if (!success) | |
5772 return 0; | |
5773 } | |
5774 | |
5775 if (beg_unchanged == -1 && end_unchanged == -1) | |
5776 return 1; | |
5777 | |
5778 /* assert: There are no buffer modifications or they are all below the | |
5779 visible region. We assume that regenerate_window_incrementally has | |
5780 not called us unless this is true. */ | |
5781 | |
5782 REGEN_INC_FIND_START_END; | |
5783 | |
5784 /* If the changed are starts before the visible area, give up. */ | |
5785 if (beg_unchanged < startp) | |
5786 return 0; | |
5787 | |
5788 /* Find what display line the extent changes first affect. */ | |
5789 line = dla_start; | |
5790 while (line <= dla_end) | |
5791 { | |
5792 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5793 Charbpos lstart = dl->charpos + dl->offset; |
5794 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5795 |
5796 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5797 break; | |
5798 | |
5799 line++; | |
5800 } | |
5801 | |
5802 /* If the changes are below the visible area then if point hasn't | |
5803 moved return success otherwise fail in order to be safe. */ | |
5804 if (line > dla_end) | |
5805 { | |
5806 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
5807 && pointm == marker_position (w->last_point[CURRENT_DISP])) | |
5808 return 1; | |
5809 else | |
5810 return 0; | |
5811 } | |
5812 | |
5813 /* At this point we know what line the changes first affect. We now | |
5814 begin redrawing lines as long as we are still in the affected | |
5815 region and the line's size and positioning don't change. | |
5816 Otherwise we fail. If we fail we will have altered the desired | |
5817 structs which could lead to an assertion failure. However, if we | |
5818 fail the next thing that is going to happen is a full regen so we | |
5819 will actually end up being safe. */ | |
5820 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
5821 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
5822 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
5823 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
5824 | |
5825 first_line = last_line = line; | |
5826 while (line <= dla_end) | |
5827 { | |
2286 | 5828 Charbpos old_start, old_end; |
428 | 5829 struct display_line *cdl = Dynarr_atp (cdla, line); |
5830 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5831 struct display_block *db; | |
5832 int initial_size; | |
5833 | |
826 | 5834 assert (cdl->charpos == ddl->charpos); |
5835 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5836 assert (cdl->offset == ddl->offset); |
5837 | |
5838 db = get_display_block_from_line (ddl, TEXT); | |
5839 initial_size = Dynarr_length (db->runes); | |
826 | 5840 old_start = ddl->charpos + ddl->offset; |
5841 old_end = ddl->end_charpos + ddl->offset; | |
428 | 5842 |
5843 /* If this is the first line being updated and it used | |
4187 | 5844 propagation data, fail. Otherwise we'll be okay because |
5845 we'll have the necessary propagation data. */ | |
428 | 5846 if (line == first_line && ddl->used_prop_data) |
5847 return 0; | |
5848 | |
2286 | 5849 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
5850 &prop, DESIRED_DISP); | |
428 | 5851 ddl->offset = 0; |
5852 | |
5853 /* #### If there is propagated stuff the fail. We could | |
4187 | 5854 probably actually deal with this if the line had propagated |
5855 information when originally created by a full | |
5856 regeneration. */ | |
428 | 5857 if (prop) |
5858 { | |
5859 Dynarr_free (prop); | |
5860 return 0; | |
5861 } | |
5862 | |
5863 /* If any line position parameters have changed or a | |
4187 | 5864 cursor has disappeared or disappeared, fail. */ |
428 | 5865 db = get_display_block_from_line (ddl, TEXT); |
5866 if (cdl->ypos != ddl->ypos | |
5867 || cdl->ascent != ddl->ascent | |
5868 || cdl->descent != ddl->descent | |
5869 || cdl->top_clip != ddl->top_clip | |
5870 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
5871 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
826 | 5872 || old_start != ddl->charpos |
5873 || old_end != ddl->end_charpos | |
428 | 5874 || initial_size != Dynarr_length (db->runes)) |
5875 { | |
5876 return 0; | |
5877 } | |
5878 | |
5879 if (ddl->cursor_elt != -1) | |
5880 { | |
5881 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
5882 w->last_point_y[DESIRED_DISP] = line; | |
5883 } | |
5884 | |
5885 last_line = line; | |
5886 | |
5887 /* If the extent changes end on the line we just updated then | |
4187 | 5888 we're done. Otherwise go on to the next line. */ |
826 | 5889 if (end_unchanged <= ddl->end_charpos) |
428 | 5890 break; |
5891 else | |
5892 line++; | |
5893 } | |
5894 | |
5895 redisplay_update_line (w, first_line, last_line, 1); | |
5896 return 1; | |
5897 } | |
5898 | |
5899 /* Attempt to update the display data structures based on knowledge of | |
5900 the changed region in the buffer. Returns a boolean indicating | |
5901 success or failure. If this function returns a failure then a | |
5902 regenerate_window _must_ be performed next in order to maintain | |
5903 invariants located here. */ | |
5904 | |
5905 static int | |
665 | 5906 regenerate_window_incrementally (struct window *w, Charbpos startp, |
5907 Charbpos pointm) | |
428 | 5908 { |
5909 struct buffer *b = XBUFFER (w->buffer); | |
5910 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
5911 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
5912 Charcount beg_unchanged, end_unchanged; | |
5913 Charcount extent_beg_unchanged, extent_end_unchanged; | |
5914 | |
5915 int dla_start = 0; | |
5916 int dla_end, line; | |
665 | 5917 Charbpos start_pos; |
428 | 5918 |
5919 /* If this function is called, the current and desired structures | |
5920 had better be identical. If they are not, then that is a bug. */ | |
5921 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
5922 | |
5923 /* We don't handle minibuffer windows yet. The minibuffer prompt | |
5924 screws us up. */ | |
5925 if (MINI_WINDOW_P (w)) | |
5926 return 0; | |
5927 | |
5928 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b); | |
5929 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1 | |
5930 ? -1 | |
5931 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b)); | |
5932 | |
5933 /* If nothing has changed in the buffer, then make sure point is ok | |
5934 and succeed. */ | |
5935 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1) | |
5936 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5937 extent_beg_unchanged, | |
5938 extent_end_unchanged); | |
5939 | |
5940 /* We can't deal with deleted newlines. */ | |
5941 if (BUF_NEWLINE_WAS_DELETED (b)) | |
5942 return 0; | |
5943 | |
5944 beg_unchanged = BUF_BEGIN_UNCHANGED (b); | |
5945 end_unchanged = (BUF_END_UNCHANGED (b) == -1 | |
5946 ? -1 | |
5947 : BUF_Z (b) - BUF_END_UNCHANGED (b)); | |
5948 | |
5949 REGEN_INC_FIND_START_END; | |
5950 | |
5951 /* If the changed area starts before the visible area, give up. */ | |
5952 if (beg_unchanged < startp) | |
5953 return 0; | |
5954 | |
5955 /* Find what display line the buffer changes first affect. */ | |
5956 line = dla_start; | |
5957 while (line <= dla_end) | |
5958 { | |
5959 struct display_line *dl = Dynarr_atp (cdla, line); | |
826 | 5960 Charbpos lstart = dl->charpos + dl->offset; |
5961 Charbpos lend = dl->end_charpos + dl->offset; | |
428 | 5962 |
5963 if (beg_unchanged >= lstart && beg_unchanged <= lend) | |
5964 break; | |
5965 | |
5966 line++; | |
5967 } | |
5968 | |
5969 /* If the changes are below the visible area then if point hasn't | |
5970 moved return success otherwise fail in order to be safe. */ | |
5971 if (line > dla_end) | |
5972 return regenerate_window_extents_only_changed (w, startp, pointm, | |
5973 extent_beg_unchanged, | |
5974 extent_end_unchanged); | |
5975 else | |
5976 /* At this point we know what line the changes first affect. We | |
5977 now redraw that line. If the changes are contained within it | |
5978 we are going to succeed and can update just that one line. | |
5979 Otherwise we fail. If we fail we will have altered the desired | |
5980 structs which could lead to an assertion failure. However, if | |
5981 we fail the next thing that is going to happen is a full regen | |
5982 so we will actually end up being safe. */ | |
5983 { | |
5984 prop_block_dynarr *prop = NULL; | |
5985 struct display_line *cdl = Dynarr_atp (cdla, line); | |
5986 struct display_line *ddl = Dynarr_atp (ddla, line); | |
5987 | |
826 | 5988 assert (cdl->charpos == ddl->charpos); |
5989 assert (cdl->end_charpos == ddl->end_charpos); | |
428 | 5990 assert (cdl->offset == ddl->offset); |
5991 | |
442 | 5992 /* If the line continues to next display line, fail. */ |
5993 if (ddl->line_continuation) | |
5994 return 0; | |
428 | 5995 |
5996 /* If the line was generated using propagation data, fail. */ | |
5997 if (ddl->used_prop_data) | |
5998 return 0; | |
5999 | |
2286 | 6000 generate_display_line (w, ddl, 0, ddl->charpos + ddl->offset, |
6001 &prop, DESIRED_DISP); | |
428 | 6002 ddl->offset = 0; |
6003 | |
6004 /* If there is propagated stuff then it is pretty much a | |
4187 | 6005 guarantee that more than just the one line is affected. */ |
428 | 6006 if (prop) |
6007 { | |
6008 Dynarr_free (prop); | |
6009 return 0; | |
6010 } | |
6011 | |
442 | 6012 /* If the line continues to next display line, fail. */ |
6013 if (ddl->line_continuation) | |
6014 return 0; | |
428 | 6015 |
6016 /* If any line position parameters have changed or a | |
4187 | 6017 cursor has disappeared or disappeared, fail. */ |
428 | 6018 if (cdl->ypos != ddl->ypos |
6019 || cdl->ascent != ddl->ascent | |
6020 || cdl->descent != ddl->descent | |
6021 || cdl->top_clip != ddl->top_clip | |
6022 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | |
6023 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) | |
6024 { | |
6025 return 0; | |
6026 } | |
6027 | |
6028 /* If the changed area also ends on this line, then we may be in | |
4187 | 6029 business. Update everything and return success. */ |
826 | 6030 if (end_unchanged >= ddl->charpos && end_unchanged <= ddl->end_charpos) |
428 | 6031 { |
6032 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
6033 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
6034 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), | |
6035 w->buffer); | |
6036 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), | |
6037 w->buffer); | |
6038 | |
6039 if (ddl->cursor_elt != -1) | |
6040 { | |
6041 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt; | |
6042 w->last_point_y[DESIRED_DISP] = line; | |
6043 } | |
6044 | |
6045 redisplay_update_line (w, line, line, 1); | |
6046 regenerate_modeline (w); | |
6047 | |
6048 /* #### For now we just flush the cache until this has been | |
4187 | 6049 tested. After that is done, this should correct the |
6050 cache directly. */ | |
428 | 6051 Dynarr_reset (w->line_start_cache); |
6052 | |
6053 /* Adjust the extent changed boundaries to remove any | |
4187 | 6054 overlap with the buffer changes since we've just |
6055 successfully updated that area. */ | |
428 | 6056 if (extent_beg_unchanged != -1 |
6057 && extent_beg_unchanged >= beg_unchanged | |
6058 && extent_beg_unchanged < end_unchanged) | |
6059 extent_beg_unchanged = end_unchanged; | |
6060 | |
6061 if (extent_end_unchanged != -1 | |
6062 && extent_end_unchanged >= beg_unchanged | |
6063 && extent_end_unchanged < end_unchanged) | |
6064 extent_end_unchanged = beg_unchanged - 1; | |
6065 | |
6066 if (extent_end_unchanged <= extent_beg_unchanged) | |
6067 extent_beg_unchanged = extent_end_unchanged = -1; | |
6068 | |
6069 /* This could lead to odd results if it fails, but since the | |
4187 | 6070 buffer changes update succeeded this probably will to. |
6071 We already know that the extent changes start at or after | |
6072 the line because we checked before entering the loop. */ | |
428 | 6073 if (extent_beg_unchanged != -1 |
6074 && extent_end_unchanged != -1 | |
826 | 6075 && ((extent_beg_unchanged < ddl->charpos) |
6076 || (extent_end_unchanged > ddl->end_charpos))) | |
428 | 6077 return regenerate_window_extents_only_changed (w, startp, pointm, |
6078 extent_beg_unchanged, | |
6079 extent_end_unchanged); | |
6080 else | |
6081 return 1; | |
6082 } | |
6083 } | |
6084 | |
6085 /* Oh, well. */ | |
6086 return 0; | |
6087 } | |
6088 | |
6089 /* Given a window and a point, update the given display lines such | |
6090 that point is displayed in the middle of the window. | |
6091 Return the window's new start position. */ | |
6092 | |
665 | 6093 static Charbpos |
6094 regenerate_window_point_center (struct window *w, Charbpos point, int type) | |
428 | 6095 { |
665 | 6096 Charbpos startp; |
428 | 6097 |
6098 /* We need to make sure that the modeline is generated so that the | |
6099 window height can be calculated correctly. */ | |
6100 ensure_modeline_generated (w, type); | |
6101 | |
6102 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w)); | |
6103 regenerate_window (w, startp, point, type); | |
6104 Fset_marker (w->start[type], make_int (startp), w->buffer); | |
6105 | |
6106 return startp; | |
6107 } | |
6108 | |
6109 /* Given a window and a set of display lines, return a boolean | |
6110 indicating whether the given point is contained within. */ | |
6111 | |
6112 static int | |
665 | 6113 point_visible (struct window *w, Charbpos point, int type) |
428 | 6114 { |
6115 struct buffer *b = XBUFFER (w->buffer); | |
6116 display_line_dynarr *dla = window_display_lines (w, type); | |
6117 int first_line; | |
6118 | |
4967 | 6119 if (Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
428 | 6120 first_line = 1; |
6121 else | |
6122 first_line = 0; | |
6123 | |
6124 if (Dynarr_length (dla) > first_line) | |
6125 { | |
665 | 6126 Charbpos start, end; |
428 | 6127 struct display_line *dl = Dynarr_atp (dla, first_line); |
6128 | |
826 | 6129 start = dl->charpos; |
428 | 6130 end = BUF_Z (b) - w->window_end_pos[type] - 1; |
6131 | |
6132 if (point >= start && point <= end) | |
6133 { | |
6134 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines) | |
6135 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
6136 dl = Dynarr_lastp (dla); |
428 | 6137 |
826 | 6138 if (point >= (dl->charpos + dl->offset) |
6139 && point <= (dl->end_charpos + dl->offset)) | |
428 | 6140 return !dl->clip; |
6141 else | |
6142 return 1; | |
6143 } | |
6144 else | |
6145 return 1; | |
6146 } | |
6147 else | |
6148 return 0; | |
6149 } | |
6150 else | |
6151 return 0; | |
6152 } | |
6153 | |
6154 /* Return pixel position the middle of the window, not including the | |
6155 modeline and any potential horizontal scrollbar. */ | |
6156 | |
6157 int | |
6158 window_half_pixpos (struct window *w) | |
6159 { | |
6160 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1); | |
6161 } | |
6162 | |
6163 /* Return the display line which is currently in the middle of the | |
6164 window W for display lines TYPE. */ | |
6165 | |
6166 int | |
665 | 6167 line_at_center (struct window *w, int type, Charbpos start, Charbpos point) |
428 | 6168 { |
6169 display_line_dynarr *dla; | |
6170 int half; | |
6171 int elt; | |
6172 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1); | |
6173 | |
6174 if (type == CMOTION_DISP) | |
6175 regenerate_window (w, start, point, type); | |
6176 | |
6177 dla = window_display_lines (w, type); | |
6178 half = window_half_pixpos (w); | |
6179 | |
6180 for (elt = first_elt; elt < Dynarr_length (dla); elt++) | |
6181 { | |
6182 struct display_line *dl = Dynarr_atp (dla, elt); | |
6183 int line_bot = dl->ypos + dl->descent; | |
6184 | |
6185 if (line_bot > half) | |
6186 return elt; | |
6187 } | |
6188 | |
6189 /* We may not have a line at the middle if the end of the buffer is | |
6190 being displayed. */ | |
6191 return -1; | |
6192 } | |
6193 | |
6194 /* Return a value for point that would place it at the beginning of | |
6195 the line which is in the middle of the window. */ | |
6196 | |
665 | 6197 Charbpos |
6198 point_at_center (struct window *w, int type, Charbpos start, Charbpos point) | |
428 | 6199 { |
6200 /* line_at_center will regenerate the display structures, if necessary. */ | |
6201 int line = line_at_center (w, type, start, point); | |
6202 | |
6203 if (line == -1) | |
6204 return BUF_ZV (XBUFFER (w->buffer)); | |
6205 else | |
6206 { | |
6207 display_line_dynarr *dla = window_display_lines (w, type); | |
6208 struct display_line *dl = Dynarr_atp (dla, line); | |
6209 | |
826 | 6210 return dl->charpos; |
428 | 6211 } |
6212 } | |
6213 | |
6214 /* For a given window, ensure that the current visual representation | |
6215 is accurate. */ | |
6216 | |
6217 static void | |
6218 redisplay_window (Lisp_Object window, int skip_selected) | |
6219 { | |
6220 struct window *w = XWINDOW (window); | |
6221 struct frame *f = XFRAME (w->frame); | |
6222 struct device *d = XDEVICE (f->device); | |
6223 Lisp_Object old_buffer = w->buffer; | |
6224 Lisp_Object the_buffer = w->buffer; | |
6225 struct buffer *b; | |
6226 int echo_active = 0; | |
6227 int startp = 1; | |
6228 int pointm; | |
6229 int old_startp = 1; | |
6230 int old_pointm = 1; | |
6231 int selected_in_its_frame; | |
6232 int selected_globally; | |
6233 int skip_output = 0; | |
6234 int truncation_changed; | |
6235 int inactive_minibuffer = | |
6236 (MINI_WINDOW_P (w) && | |
6237 (f != device_selected_frame (d)) && | |
6238 !is_surrogate_for_selected_frame (f)); | |
6239 | |
6240 /* #### In the new world this function actually does a bunch of | |
6241 optimizations such as buffer-based scrolling, but none of that is | |
6242 implemented yet. */ | |
6243 | |
6244 /* If this is a combination window, do its children; that's all. | |
6245 The selected window is always a leaf so we don't check for | |
6246 skip_selected here. */ | |
6247 if (!NILP (w->vchild)) | |
6248 { | |
6249 redisplay_windows (w->vchild, skip_selected); | |
6250 return; | |
6251 } | |
6252 if (!NILP (w->hchild)) | |
6253 { | |
6254 redisplay_windows (w->hchild, skip_selected); | |
6255 return; | |
6256 } | |
6257 | |
6258 /* Is this window the selected window on its frame? */ | |
6259 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f))); | |
6260 selected_globally = | |
6261 selected_in_its_frame && | |
5198 | 6262 EQ (DEVICE_CONSOLE (d), Vselected_console) && |
6263 XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d)))) == d && | |
6264 XFRAME (DEVICE_SELECTED_FRAME (d)) == f; | |
428 | 6265 if (skip_selected && selected_in_its_frame) |
6266 return; | |
6267 | |
6268 /* It is possible that the window is not fully initialized yet. */ | |
6269 if (NILP (w->buffer)) | |
6270 return; | |
6271 | |
6272 if (MINI_WINDOW_P (w) && echo_area_active (f)) | |
6273 { | |
6274 w->buffer = the_buffer = Vecho_area_buffer; | |
6275 echo_active = 1; | |
6276 } | |
6277 | |
6278 b = XBUFFER (w->buffer); | |
6279 | |
6280 if (echo_active) | |
6281 { | |
6282 old_pointm = selected_globally | |
4187 | 6283 ? BUF_PT (b) |
6284 : marker_position (w->pointm[CURRENT_DISP]); | |
428 | 6285 pointm = 1; |
6286 } | |
6287 else | |
6288 { | |
6289 if (selected_globally) | |
6290 { | |
6291 pointm = BUF_PT (b); | |
6292 } | |
6293 else | |
6294 { | |
6295 pointm = marker_position (w->pointm[CURRENT_DISP]); | |
6296 | |
6297 if (pointm < BUF_BEGV (b)) | |
6298 pointm = BUF_BEGV (b); | |
6299 else if (pointm > BUF_ZV (b)) | |
6300 pointm = BUF_ZV (b); | |
6301 } | |
6302 } | |
6303 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); | |
6304 | |
4968 | 6305 /* Added 2-1-10 -- we should never have empty face or glyph cachels |
6306 because we initialized them at startup and the only way to reduce | |
6307 their number is through calling reset_face_cachels() or | |
6308 reset_glyph_cachels(), which as a side effect sets up a number of | |
6309 standard entries */ | |
6310 assert (Dynarr_length (w->face_cachels)); | |
6311 assert (Dynarr_length (w->glyph_cachels)); | |
6312 | |
428 | 6313 /* If the buffer has changed we have to invalidate all of our face |
6314 cache elements. */ | |
6315 if ((!echo_active && b != window_display_buffer (w)) | |
4968 | 6316 #if 0 |
6317 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
6318 not needed */ | |
428 | 6319 || !Dynarr_length (w->face_cachels) |
4968 | 6320 #endif |
428 | 6321 || f->faces_changed) |
6322 reset_face_cachels (w); | |
6323 else | |
6324 mark_face_cachels_as_not_updated (w); | |
6325 | |
6326 /* Ditto the glyph cache elements, although we do *not* invalidate | |
6327 the cache purely because glyphs have changed - this is now | |
6328 handled by the dirty flag.*/ | |
6329 if ((!echo_active && b != window_display_buffer (w)) | |
4968 | 6330 #if 0 |
6331 /* #### Delete this code sometime later than 2-1-10 when we're sure it's | |
6332 not needed */ | |
6333 || !Dynarr_length (w->glyph_cachels) | |
6334 #endif | |
6335 || f->faces_changed) | |
428 | 6336 reset_glyph_cachels (w); |
6337 else | |
6338 mark_glyph_cachels_as_not_updated (w); | |
6339 | |
6340 /* If the marker's buffer is not the window's buffer, then we need | |
6341 to find a new starting position. */ | |
6342 if (!MINI_WINDOW_P (w) | |
6343 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer)) | |
6344 { | |
6345 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6346 | |
6347 goto regeneration_done; | |
6348 } | |
6349 | |
6350 if (echo_active) | |
6351 { | |
6352 old_startp = marker_position (w->start[CURRENT_DISP]); | |
6353 startp = 1; | |
6354 } | |
6355 else | |
6356 { | |
6357 startp = marker_position (w->start[CURRENT_DISP]); | |
6358 if (startp < BUF_BEGV (b)) | |
6359 startp = BUF_BEGV (b); | |
6360 else if (startp > BUF_ZV (b)) | |
6361 startp = BUF_ZV (b); | |
6362 } | |
6363 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer); | |
6364 | |
6365 truncation_changed = (find_window_mirror (w)->truncate_win != | |
647 | 6366 (unsigned int) window_truncation_on (w)); |
428 | 6367 |
6368 /* If w->force_start is set, then some function set w->start and we | |
6369 should display from there and change point, if necessary, to | |
6370 ensure that it is visible. */ | |
6371 if (w->force_start || inactive_minibuffer) | |
6372 { | |
6373 w->force_start = 0; | |
6374 w->last_modified[DESIRED_DISP] = Qzero; | |
6375 w->last_facechange[DESIRED_DISP] = Qzero; | |
6376 | |
6377 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6378 | |
6379 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer) | |
6380 { | |
6381 pointm = point_at_center (w, DESIRED_DISP, 0, 0); | |
6382 | |
6383 if (selected_globally) | |
6384 BUF_SET_PT (b, pointm); | |
6385 | |
6386 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), | |
6387 the_buffer); | |
6388 | |
6389 /* #### BUFU amounts of overkill just to get the cursor | |
4187 | 6390 location marked properly. FIX ME FIX ME FIX ME */ |
428 | 6391 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6392 } | |
6393 | |
6394 goto regeneration_done; | |
6395 } | |
6396 | |
6397 /* If nothing has changed since the last redisplay, then we just | |
6398 need to make sure that point is still visible. */ | |
6399 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) | |
6400 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b) | |
6401 && pointm >= startp | |
6402 /* This check is to make sure we restore the minibuffer after a | |
4187 | 6403 temporary change to the echo area. */ |
428 | 6404 && !(MINI_WINDOW_P (w) && f->buffers_changed) |
6405 && !f->frame_changed | |
6406 && !truncation_changed | |
442 | 6407 /* check whether start is really at the beginning of a line GE */ |
428 | 6408 && (!w->start_at_line_beg || beginning_of_line_p (b, startp)) |
6409 ) | |
6410 { | |
6411 /* Check if the cursor has actually moved. */ | |
6412 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer) | |
6413 && pointm == marker_position (w->last_point[CURRENT_DISP]) | |
6414 && selected_globally | |
6415 && !w->windows_changed | |
6416 && !f->clip_changed | |
6417 && !f->extents_changed | |
6418 && !f->faces_changed | |
6419 && !f->glyphs_changed | |
6420 && !f->subwindows_changed | |
442 | 6421 /* && !f->subwindows_state_changed*/ |
428 | 6422 && !f->point_changed |
6423 && !f->windows_structure_changed) | |
6424 { | |
6425 /* If not, we're done. */ | |
6426 if (f->modeline_changed) | |
6427 regenerate_modeline (w); | |
6428 | |
6429 skip_output = 1; | |
6430 goto regeneration_done; | |
6431 } | |
6432 else | |
6433 { | |
6434 /* If the new point is visible in the redisplay structures, | |
4187 | 6435 then let the output update routines handle it, otherwise |
6436 do things the hard way. */ | |
428 | 6437 if (!w->windows_changed |
6438 && !f->clip_changed | |
6439 && !f->extents_changed | |
6440 && !f->faces_changed | |
6441 && !f->glyphs_changed | |
6442 && !f->subwindows_changed | |
442 | 6443 /* && !f->subwindows_state_changed*/ |
428 | 6444 && !f->windows_structure_changed) |
6445 { | |
6446 if (point_visible (w, pointm, CURRENT_DISP) | |
6447 && w->last_point_x[CURRENT_DISP] != -1 | |
6448 && w->last_point_y[CURRENT_DISP] != -1) | |
6449 { | |
6450 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f))) | |
6451 { | |
6452 /* Always regenerate in case it is displaying | |
4187 | 6453 the current line or column. */ |
428 | 6454 regenerate_modeline (w); |
6455 | |
6456 skip_output = 1; | |
6457 goto regeneration_done; | |
6458 } | |
6459 } | |
6460 else if (!selected_in_its_frame && !f->point_changed) | |
6461 { | |
6462 if (f->modeline_changed) | |
6463 regenerate_modeline (w); | |
6464 | |
6465 skip_output = 1; | |
6466 goto regeneration_done; | |
6467 } | |
6468 } | |
6469 | |
6470 /* If we weren't able to take the shortcut method, then use | |
4187 | 6471 the brute force method. */ |
428 | 6472 regenerate_window (w, startp, pointm, DESIRED_DISP); |
6473 | |
6474 if (point_visible (w, pointm, DESIRED_DISP)) | |
6475 goto regeneration_done; | |
6476 } | |
6477 } | |
6478 | |
6479 /* Check if the starting point is no longer at the beginning of a | |
6480 line, in which case find a new starting point. We also recenter | |
6481 if our start position is equal to point-max. Otherwise we'll end | |
6482 up with a blank window. */ | |
6483 else if (((w->start_at_line_beg || MINI_WINDOW_P (w)) | |
6484 && !(startp == BUF_BEGV (b) | |
6485 || BUF_FETCH_CHAR (b, startp - 1) == '\n')) | |
6486 || (pointm == startp && | |
6487 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) && | |
6488 startp < marker_position (w->last_start[CURRENT_DISP])) | |
6489 || (startp == BUF_ZV (b))) | |
6490 { | |
6491 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6492 | |
6493 goto regeneration_done; | |
6494 } | |
6495 /* See if we can update the data structures locally based on | |
6496 knowledge of what changed in the buffer. */ | |
6497 else if (!w->windows_changed | |
6498 && !f->clip_changed | |
6499 && !f->faces_changed | |
6500 && !f->glyphs_changed | |
6501 && !f->subwindows_changed | |
442 | 6502 /* && !f->subwindows_state_changed*/ |
428 | 6503 && !f->windows_structure_changed |
6504 && !f->frame_changed | |
6505 && !truncation_changed | |
6506 && pointm >= startp | |
6507 && regenerate_window_incrementally (w, startp, pointm)) | |
6508 { | |
6509 if (f->modeline_changed | |
6510 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b) | |
6511 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b)) | |
6512 regenerate_modeline (w); | |
6513 | |
6514 skip_output = 1; | |
6515 goto regeneration_done; | |
6516 } | |
6517 /* #### This is where a check for structure based scrolling would go. */ | |
6518 /* If all else fails, try just regenerating and see what happens. */ | |
6519 else | |
6520 { | |
6521 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6522 | |
6523 if (point_visible (w, pointm, DESIRED_DISP)) | |
6524 goto regeneration_done; | |
6525 } | |
6526 | |
6527 /* We still haven't gotten the window regenerated with point | |
6528 visible. Next we try scrolling a little and see if point comes | |
6529 back onto the screen. */ | |
6530 if (scroll_step > 0) | |
6531 { | |
6532 int scrolled = scroll_conservatively; | |
6533 for (; scrolled >= 0; scrolled -= scroll_step) | |
6534 { | |
6535 startp = vmotion (w, startp, | |
6536 (pointm < startp) ? -scroll_step : scroll_step, 0); | |
6537 regenerate_window (w, startp, pointm, DESIRED_DISP); | |
6538 | |
6539 if (point_visible (w, pointm, DESIRED_DISP)) | |
6540 goto regeneration_done; | |
6541 } | |
6542 } | |
6543 | |
6544 /* We still haven't managed to get the screen drawn with point on | |
6545 the screen, so just center it and be done with it. */ | |
6546 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP); | |
6547 | |
6548 | |
6549 regeneration_done: | |
6550 | |
6551 /* If the window's frame is changed then reset the current display | |
6552 lines in order to force a full repaint. */ | |
6553 if (f->frame_changed) | |
6554 { | |
6555 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
6556 | |
6557 Dynarr_reset (cla); | |
6558 } | |
6559 | |
6560 /* Must do this before calling redisplay_output_window because it | |
6561 sets some markers on the window. */ | |
6562 if (echo_active) | |
6563 { | |
6564 w->buffer = old_buffer; | |
6565 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer); | |
6566 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer); | |
6567 } | |
6568 | |
6569 /* These also have to be set before calling redisplay_output_window | |
6570 since it sets the CURRENT_DISP values based on them. */ | |
6571 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b)); | |
6572 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b)); | |
6573 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer); | |
6574 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer); | |
6575 | |
6576 if (!skip_output) | |
6577 { | |
665 | 6578 Charbpos start = marker_position (w->start[DESIRED_DISP]); |
6579 Charbpos end = (w->window_end_pos[DESIRED_DISP] == -1 | |
428 | 6580 ? BUF_ZV (b) |
6581 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1); | |
6582 /* Don't pollute the cache if not sure if we are correct */ | |
6583 if (w->start_at_line_beg) | |
6584 update_line_start_cache (w, start, end, pointm, 1); | |
6585 redisplay_output_window (w); | |
6586 /* | |
6587 * If we just displayed the echo area, the line start cache is | |
6588 * no longer valid, because the minibuffer window is associated | |
6589 * with the window now. | |
6590 */ | |
6591 if (echo_active) | |
6592 w->line_cache_last_updated = make_int (-1); | |
6593 } | |
6594 | |
6595 /* #### This should be dependent on face changes and will need to be | |
6596 somewhere else once tty updates occur on a per-frame basis. */ | |
6597 mark_face_cachels_as_clean (w); | |
6598 | |
438 | 6599 /* The glyph cachels only get dirty if someone changed something. |
6600 Since redisplay has now effectively ended we can reset the dirty | |
6601 flag since everything must be up-to-date. */ | |
428 | 6602 if (glyphs_changed) |
6603 mark_glyph_cachels_as_clean (w); | |
6604 | |
6605 w->windows_changed = 0; | |
6606 } | |
6607 | |
6608 /* Call buffer_reset_changes for all buffers present in any window | |
6609 currently visible in all frames on all devices. #### There has to | |
6610 be a better way to do this. */ | |
6611 | |
6612 static int | |
2286 | 6613 reset_buffer_changes_mapfun (struct window *w, void *UNUSED (closure)) |
428 | 6614 { |
6615 buffer_reset_changes (XBUFFER (w->buffer)); | |
6616 return 0; | |
6617 } | |
6618 | |
6619 static void | |
6620 reset_buffer_changes (void) | |
6621 { | |
6622 Lisp_Object frmcons, devcons, concons; | |
6623 | |
6624 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
6625 { | |
6626 struct frame *f = XFRAME (XCAR (frmcons)); | |
6627 | |
6628 if (FRAME_REPAINT_P (f)) | |
6629 map_windows (f, reset_buffer_changes_mapfun, 0); | |
6630 } | |
6631 } | |
6632 | |
6633 /* Ensure that all windows underneath the given window in the window | |
6634 hierarchy are correctly displayed. */ | |
6635 | |
6636 static void | |
6637 redisplay_windows (Lisp_Object window, int skip_selected) | |
6638 { | |
6639 for (; !NILP (window) ; window = XWINDOW (window)->next) | |
6640 { | |
6641 redisplay_window (window, skip_selected); | |
6642 } | |
6643 } | |
6644 | |
1318 | 6645 /* Register an action to be called at the end of redisplay. |
6646 in_display is 0 when this is called. | |
6647 This is used when it is discovered that an action needs to be taken, | |
6648 but it's during redisplay, so it's not safe. (Typically, it's an action | |
6649 that needs to enter redisplay, which can't happen reentrantly.) | |
6650 | |
6651 NEVER signal an error in these functions. | |
6652 */ | |
6653 | |
6654 void | |
6655 register_post_redisplay_action (void (*fun) (Lisp_Object), Lisp_Object arg) | |
6656 { | |
6657 Vpost_redisplay_actions = nconc2 (Vpost_redisplay_actions, | |
6658 list1 (Fcons (make_opaque_ptr | |
6659 ((void *) fun), arg))); | |
6660 } | |
6661 | |
1320 | 6662 static int running_post_redisplay_actions; |
6663 | |
1318 | 6664 static void |
6665 run_post_redisplay_actions (void) | |
6666 { | |
1320 | 6667 int depth; |
6668 | |
6669 if (running_post_redisplay_actions) | |
6670 return; | |
6671 | |
6672 depth = internal_bind_int (&running_post_redisplay_actions, 1); | |
6673 /* If the function pushes further actions, they will be tacked onto | |
6674 the end of the list, and we'll run them when we're done with the | |
6675 current ones. */ | |
1318 | 6676 while (!NILP (Vpost_redisplay_actions)) |
6677 { | |
6678 Lisp_Object car = XCAR (Vpost_redisplay_actions); | |
6679 void (*fun) (Lisp_Object) = | |
6680 (void (*)(Lisp_Object)) get_opaque_ptr (XCAR (car)); | |
6681 (*fun) (XCDR (car)); | |
6682 free_opaque_ptr (XCAR (car)); | |
6683 free_cons (car); | |
6684 Vpost_redisplay_actions = XCDR (Vpost_redisplay_actions); | |
6685 } | |
1320 | 6686 unbind_to (depth); |
1318 | 6687 } |
6688 | |
5348
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6689 static int the_ritual_suicide_has_been_cancelled = 0; |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6690 |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6691 void |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6692 redisplay_cancel_ritual_suicide(void) |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6693 { |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6694 the_ritual_suicide_has_been_cancelled = 1; |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6695 } |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6696 |
1318 | 6697 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS |
6698 | |
6699 static Lisp_Object | |
2286 | 6700 commit_ritual_suicide (Lisp_Object UNUSED (ceci_nest_pas_une_pipe)) |
1318 | 6701 { |
5348
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6702 if (!the_ritual_suicide_has_been_cancelled) |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6703 { |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6704 assert (!in_display); |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6705 } |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6706 else |
39304a35b6b3
Don't commit suicide when an X device dies.
Mike Sperber <sperber@deinprogramm.de>
parents:
5198
diff
changeset
|
6707 the_ritual_suicide_has_been_cancelled = 0; |
1318 | 6708 return Qnil; |
6709 } | |
6710 | |
6711 #endif | |
6712 | |
6713 /* Within the guts of redisplay, we are defenseless and cannot allow any of | |
6714 the following to happen: | |
6715 | |
6716 1) garbage collection | |
6717 2) QUIT | |
6718 3) any non-local exits | |
6719 4) frame size changes | |
6720 5) deletion of any buffers, windows, frames, etc. | |
6721 6) modification of buffer text | |
6722 7) reentrant entry of redisplay (see the stack trace above | |
6723 generate_displayable_area()) | |
6724 | |
6725 The general reason is that the redisplay code is written to assume that | |
6726 it is the only code running, and thus (a) cannot tolerate structures | |
6727 changed out from under it (hence 1, 4, 5, 6, 7) and (b) at various points | |
6728 within redisplay the redisplay structures may be in an inconsistent | |
6729 state and there are no unwind-protects to clean the structures up in | |
6730 case of non-local exit (hence 2, 3). Fixing redisplay to address these | |
6731 issues is hard and perhaps not worth it (and might slow things down a | |
6732 fair amount). We address 1, 4, 5 and 6 ourselves inside of | |
6733 enter_redisplay_critical_section() by simply inhibiting them, but we | |
6734 cannot handle 2 and 3, which must be handled at the actual point where | |
6735 they may occur (especially, internal_equal() or any place that may call | |
6736 Lisp), by wrapping the code in call_trapping_problems() or | |
6737 call_with_suspended_errors(). [[ NOTE: We could address QUIT by inhibiting | |
6738 it but this would be anti-social because it would prevent the user from | |
6739 interrupting any Lisp code called within the critical section. With the | |
6740 call_*() wrapping, C-g will interrupt the Lisp code and throw back to | |
6741 the innermost wrapping. ]] In fact we do turn off QUIT handling, since | |
6742 it's just too dangerous otherwise. See below. | |
6743 | |
6744 Code calling enter_redisplay_critical_section() must check for reentrancy | |
6745 (#7) and take appropriate corrective action. | |
6746 | |
6747 To help debug potential problems, we arrange (when | |
6748 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every time | |
6749 we execute QUIT or call Lisp code unless proper wrapping is in place, as | |
6750 well as further checks when we actually Fsignal(), Fthrow(), | |
6751 garbage_collect_1(). | |
6752 | |
6753 #### If a frame-size change does occur we should probably actually be | |
6754 preempting redisplay. */ | |
6755 | |
6756 /* Count of number of recursive times we call | |
6757 enter_redisplay_critical_section() or | |
6758 enter_redisplay_critical_section_maybe(). | |
6759 enter_redisplay_critical_section() cannot occur reentrantly but we have | |
6760 to know in the *maybe() version whether to exit the section when we're | |
6761 done. */ | |
6762 static int in_display_nesting; | |
6763 | |
6764 static Lisp_Object | |
2286 | 6765 end_hold_frame_size_changes (Lisp_Object UNUSED (obj)) |
1318 | 6766 { |
6767 if (!hold_frame_size_changes) | |
6768 { | |
6769 /* we used to have a function to do this for only one frame, and | |
6770 it was typical to call it at the end of a critical section | |
6771 (which occurs once per frame); but what then happens if multiple | |
6772 frames have frame changes held up? | |
4187 | 6773 |
1318 | 6774 This means we are O(N^2) over frames. I seriously doubt it matters. |
6775 --ben */ | |
6776 Lisp_Object frmcons, devcons, concons; | |
4187 | 6777 |
1318 | 6778 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
6779 { | |
6780 struct frame *f = XFRAME (XCAR (frmcons)); | |
6781 if (f->size_change_pending) | |
5043 | 6782 change_frame_size (f, f->new_width, f->new_height, 0); |
1318 | 6783 } |
6784 } | |
6785 return Qnil; | |
6786 } | |
6787 | |
6788 /* Call this to temporarily prevent frame-size changes from being processed. | |
6789 To undo, use unbind_to(), passing it the value returned by this function. | |
6790 */ | |
6791 | |
6792 int | |
6793 begin_hold_frame_size_changes (void) | |
6794 { | |
6795 int depth = specpdl_depth (); | |
6796 record_unwind_protect (end_hold_frame_size_changes, Qnil); | |
6797 internal_bind_int (&hold_frame_size_changes, 1 + hold_frame_size_changes); | |
6798 return depth; | |
6799 } | |
6800 | |
6801 int | |
6802 enter_redisplay_critical_section (void) | |
6803 { | |
6804 int depth = specpdl_depth (); | |
6805 | |
6806 /* Reentrant entry is deadly. The calling function must check for this. */ | |
6807 assert (!in_display); | |
6808 begin_hold_frame_size_changes (); | |
6809 /* Make sure in_display gets reset, but don't set it yet so that | |
6810 commit_ritual_suicide() can be used. */ | |
6811 internal_bind_int (&in_display, 0); | |
6812 internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6813 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS | |
6814 /* Force every call to QUIT to check for in_displayness. This will | |
6815 verify proper wrapping, as in the previous comment, aborting if not. */ | |
6816 something_happened++; | |
6817 /* Verify that no nonlocal exits blow past us. */ | |
6818 record_unwind_protect (commit_ritual_suicide, Qnil); | |
6819 #endif | |
6820 in_display++; | |
6821 | |
6822 set_trapping_problems_flags (INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY); | |
6823 /* Even checking for QUIT can cause arbitrary Lisp code to be executed, | |
6824 e.g. through a menu handler. We really don't want that happening | |
6825 inside of redisplay. Code that we `eval' is at least written with the | |
6826 expectation that it's inside of redisplay, and shouldn't try anything | |
6827 weird; but that's not the case for menu code (e.g. custom loads huge | |
6828 amounts of LISP FILES from a menu handler! FMH!). Safest just to turn | |
6829 this off. We could turn it on using UNINHIBIT_QUIT or | |
6830 begin_do_check_for_quit() in certain places if we want, if we know | |
6831 it's not in an especially tricky place. */ | |
6832 begin_dont_check_for_quit (); | |
6833 return depth; | |
6834 } | |
6835 | |
6836 void | |
6837 exit_redisplay_critical_section (int depth) | |
6838 { | |
6839 in_display--; | |
6840 assert (!in_display); | |
6841 unbind_to (depth); | |
6842 | |
6843 run_post_redisplay_actions (); | |
6844 } | |
6845 | |
6846 /* Enter the redisplay critical section if we're not already in it. This | |
6847 is for code that needs frame changes held up and other protections from | |
6848 being inside, but doesn't modify the redisplay structures, and doesn't | |
6849 look at them in a way that they will be confused by inconsistencies. */ | |
6850 | |
6851 int | |
6852 enter_redisplay_critical_section_maybe (void) | |
6853 { | |
6854 if (!in_display) | |
6855 return enter_redisplay_critical_section (); | |
6856 else | |
6857 return internal_bind_int (&in_display_nesting, 1 + in_display_nesting); | |
6858 } | |
6859 | |
6860 void | |
6861 exit_redisplay_critical_section_maybe (int depth) | |
6862 { | |
6863 if (in_display_nesting == 1) | |
6864 exit_redisplay_critical_section (depth); | |
6865 else | |
6866 unbind_to (depth); | |
6867 } | |
6868 | |
1279 | 6869 /* Ensure that all windows on the given frame are correctly displayed. |
6870 Return non-zero if pre-empted. */ | |
428 | 6871 |
442 | 6872 int |
428 | 6873 redisplay_frame (struct frame *f, int preemption_check) |
6874 { | |
6875 struct device *d = XDEVICE (f->device); | |
853 | 6876 int depth; |
428 | 6877 |
1279 | 6878 assert (f->init_finished); |
6879 | |
1318 | 6880 /* NOTE: Without sufficient checks for stream frames, we got weird |
6881 crashes in pdump. These came and went very easily -- adding the | |
6882 critical-section code for redisplay was enough to trigger them. | |
6883 Perhaps I should have debugged them but there didn't seem to be any | |
6884 point. --ben */ | |
1279 | 6885 if (FRAME_STREAM_P (f)) /* nothing to do */ |
6886 return 0; | |
6887 | |
1318 | 6888 /* Reentrancy into redisplay can be deadly. See stack trace above |
6889 generate_displayable_area(). */ | |
6890 if (in_display) | |
6891 return 1; | |
6892 | |
545 | 6893 if (preemption_check |
6894 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) | |
428 | 6895 { |
6896 /* The preemption check itself takes a lot of time, | |
6897 so normally don't do it here. We do it if called | |
6898 from Lisp, though (`redisplay-frame'). */ | |
6899 int preempted; | |
6900 | |
6901 REDISPLAY_PREEMPTION_CHECK; | |
6902 if (preempted) | |
6903 return 1; | |
6904 } | |
6905 | |
442 | 6906 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) |
6907 { | |
6908 Lisp_Object frame; | |
6909 | |
6910 f->old_buffer_alist = Freplace_list (f->old_buffer_alist, | |
6911 f->buffer_alist); | |
793 | 6912 frame = wrap_frame (f); |
442 | 6913 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); |
6914 } | |
6915 | |
428 | 6916 /* Before we put a hold on frame size changes, attempt to process |
6917 any which are already pending. */ | |
6918 if (f->size_change_pending) | |
5043 | 6919 change_frame_size (f, f->new_width, f->new_height, 0); |
428 | 6920 |
6921 /* If frame size might need to be changed, due to changed size | |
6922 of toolbars, scrollbars etc, change it now */ | |
6923 if (f->size_slipped) | |
6924 { | |
6925 adjust_frame_size (f); | |
6926 assert (!f->size_slipped); | |
6927 } | |
6928 | |
1318 | 6929 /* The menubar, toolbar, and icon updates should be done before |
853 | 6930 enter_redisplay_critical_section is called and we are officially |
3025 | 6931 `in_display'. They is because they tend to eval Lisp code, which |
1318 | 6932 needs to be carefully wrapped within the critical section (and hence |
6933 is difficult to debug). */ | |
428 | 6934 |
6935 #ifdef HAVE_MENUBARS | |
6936 /* Update the menubar. It is done first since it could change | |
6937 the menubar's visibility. This way we avoid having flashing | |
6938 caused by an Expose event generated by the visibility change | |
6939 being handled. */ | |
6940 update_frame_menubars (f); | |
6941 #endif /* HAVE_MENUBARS */ | |
6942 #ifdef HAVE_TOOLBARS | |
905 | 6943 /* Update the toolbars geometry. We don't update the toolbars |
6944 themselves at this point since the space they are trying to | |
6945 occupy may currently by occupied by gutter elements. Instead we | |
6946 update the geometry, then update the gutter geometry, then update | |
6947 the gutters - which will cause mapped windows to be repositioned | |
6948 - and finally update the toolbars. */ | |
6949 update_frame_toolbars_geometry (f); | |
428 | 6950 #endif /* HAVE_TOOLBARS */ |
442 | 6951 /* Gutter update proper has to be done inside display when no frame |
6952 size changes can occur, thus we separately update the gutter | |
6953 geometry here if it needs it. */ | |
6954 update_frame_gutter_geometry (f); | |
428 | 6955 |
6956 /* If we clear the frame we have to force its contents to be redrawn. */ | |
6957 if (f->clear) | |
6958 f->frame_changed = 1; | |
6959 | |
442 | 6960 /* Invalidate the subwindow caches. We use subwindows_changed here |
6961 to cause subwindows to get instantiated. This is because | |
428 | 6962 subwindows_state_changed is less strict - dealing with things |
6963 like the clicked state of button. We have to do this before | |
6964 redisplaying the gutters as subwindows get unmapped in the | |
6965 process.*/ | |
442 | 6966 if (f->frame_changed) |
6967 reset_frame_subwindow_instance_cache (f); | |
6968 | |
6969 if (f->frame_changed || f->subwindows_changed) | |
6970 { | |
428 | 6971 /* we have to do this so the gutter gets regenerated. */ |
6972 reset_gutter_display_lines (f); | |
6973 } | |
6974 | |
853 | 6975 depth = enter_redisplay_critical_section (); |
428 | 6976 |
6977 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ | |
1318 | 6978 |
6979 /* See comments in enter_redisplay_critical_section() */ | |
428 | 6980 |
442 | 6981 MAYBE_DEVMETH (d, frame_output_begin, (f)); |
6982 | |
6983 /* We can now update the gutters, safe in the knowledge that our | |
6984 efforts won't get undone. */ | |
6985 | |
6986 /* This can call lisp, but redisplay is protected by binding | |
6987 inhibit_quit. More importantly the code involving display lines | |
6988 *assumes* that GC will not happen and so does not GCPRO | |
6989 anything. Since we use this code the whole time with the gutters | |
1318 | 6990 we cannot allow GC to happen when manipulating the gutters. |
6991 | |
6992 This must be inside of the critical section for various reasons. | |
6993 For example, it messes with display structures, which be left in | |
6994 an inconsistent state. */ | |
442 | 6995 update_frame_gutters (f); |
6996 | |
428 | 6997 /* Erase the frame before outputting its contents. */ |
6998 if (f->clear) | |
6999 { | |
442 | 7000 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 7001 } |
7002 | |
7003 /* Do the selected window first. */ | |
7004 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); | |
7005 | |
7006 /* Then do the rest. */ | |
7007 redisplay_windows (f->root_window, 1); | |
7008 | |
442 | 7009 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 7010 |
7011 update_frame_title (f); | |
7012 | |
905 | 7013 #ifdef HAVE_TOOLBARS |
7014 /* Finally update the toolbars. It seems its possible to get in a | |
7015 cycle between updating the gutter and the toolbars. Basically we | |
7016 want to end up with both being up-to-date and this doesn't seem | |
7017 possible in a single pass. */ | |
7018 update_frame_toolbars (f); | |
7019 #endif /* HAVE_TOOLBARS */ | |
7020 | |
428 | 7021 CLASS_RESET_CHANGED_FLAGS (f); |
7022 f->window_face_cache_reset = 0; | |
7023 f->echo_area_garbaged = 0; | |
7024 f->clear = 0; | |
7025 | |
7026 if (!f->size_change_pending) | |
7027 f->size_changed = 0; | |
7028 | |
7029 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */ | |
7030 | |
853 | 7031 /* Allow frame size changes to occur again. */ |
7032 exit_redisplay_critical_section (depth); | |
428 | 7033 |
7034 return 0; | |
7035 } | |
7036 | |
440 | 7037 /* Ensure that all frames on the given device are correctly displayed. |
7038 If AUTOMATIC is non-zero, and the device implementation indicates | |
7039 no automatic redisplay, as printers do, then the device is not | |
7040 redisplayed. AUTOMATIC is set to zero when called from lisp | |
7041 functions (redraw-device) and (redisplay-device), and to non-zero | |
7042 when called from "lazy" redisplay(); | |
7043 */ | |
428 | 7044 |
7045 static int | |
440 | 7046 redisplay_device (struct device *d, int automatic) |
428 | 7047 { |
7048 Lisp_Object frame, frmcons; | |
7049 int size_change_failed = 0; | |
7050 struct frame *f; | |
7051 | |
545 | 7052 if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) |
440 | 7053 return 0; |
7054 | |
428 | 7055 if (DEVICE_STREAM_P (d)) /* nothing to do */ |
7056 return 0; | |
7057 | |
7058 /* It is possible that redisplay has been called before the | |
545 | 7059 device is fully initialized, or that the console implementation |
7060 allows frameless devices. If so then continue with the next | |
7061 device. */ | |
428 | 7062 if (NILP (DEVICE_SELECTED_FRAME (d))) |
7063 return 0; | |
7064 | |
545 | 7065 if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) |
7066 { | |
7067 int preempted; | |
7068 REDISPLAY_PREEMPTION_CHECK; | |
7069 if (preempted) | |
7070 return 1; | |
7071 } | |
428 | 7072 |
7073 /* Always do the selected frame first. */ | |
7074 frame = DEVICE_SELECTED_FRAME (d); | |
7075 | |
7076 f = XFRAME (frame); | |
7077 | |
7078 if (f->icon_changed || f->windows_changed) | |
7079 update_frame_icon (f); | |
7080 | |
7081 if (FRAME_REPAINT_P (f)) | |
7082 { | |
5198 | 7083 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
428 | 7084 { |
588 | 7085 int preempted = redisplay_frame (f, 1); |
545 | 7086 if (preempted) |
7087 return 1; | |
7088 } | |
428 | 7089 |
7090 /* If the frame redisplay did not get preempted, then this flag | |
4187 | 7091 should have gotten set to 0. It might be possible for that |
7092 not to happen if a size change event were to occur at an odd | |
7093 time. To make sure we don't miss anything we simply don't | |
7094 reset the top level flags until the condition ends up being | |
7095 in the right state. */ | |
428 | 7096 if (f->size_changed) |
7097 size_change_failed = 1; | |
7098 } | |
7099 | |
7100 DEVICE_FRAME_LOOP (frmcons, d) | |
7101 { | |
7102 f = XFRAME (XCAR (frmcons)); | |
7103 | |
7104 if (f == XFRAME (DEVICE_SELECTED_FRAME (d))) | |
7105 continue; | |
7106 | |
7107 if (f->icon_changed || f->windows_changed) | |
7108 update_frame_icon (f); | |
7109 | |
7110 if (FRAME_REPAINT_P (f)) | |
7111 { | |
430 | 7112 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) |
428 | 7113 { |
588 | 7114 int preempted = redisplay_frame (f, 1); |
545 | 7115 if (preempted) |
7116 return 1; | |
428 | 7117 } |
7118 | |
7119 if (f->size_change_pending) | |
7120 size_change_failed = 1; | |
7121 } | |
7122 } | |
7123 | |
7124 /* If we get here then we redisplayed all of our frames without | |
7125 getting preempted so mark ourselves as clean. */ | |
7126 CLASS_RESET_CHANGED_FLAGS (d); | |
7127 | |
7128 if (!size_change_failed) | |
7129 d->size_changed = 0; | |
7130 | |
7131 return 0; | |
7132 } | |
7133 | |
7134 /* Ensure that all windows on all frames on all devices are displaying | |
7135 the current contents of their respective buffers. */ | |
7136 | |
7137 static void | |
7138 redisplay_without_hooks (void) | |
7139 { | |
7140 Lisp_Object devcons, concons; | |
7141 int size_change_failed = 0; | |
1292 | 7142 PROFILE_DECLARE (); |
7143 | |
7144 PROFILE_RECORD_ENTERING_SECTION (QSin_redisplay); | |
428 | 7145 |
7146 if (asynch_device_change_pending) | |
7147 handle_asynch_device_change (); | |
7148 | |
7149 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && | |
430 | 7150 !disable_preemption && preemption_count < max_preempts) |
428 | 7151 goto done; |
7152 | |
7153 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
7154 { | |
7155 struct device *d = XDEVICE (XCAR (devcons)); | |
7156 int preempted; | |
7157 | |
430 | 7158 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) |
428 | 7159 { |
440 | 7160 preempted = redisplay_device (d, 1); |
428 | 7161 |
7162 if (preempted) | |
7163 { | |
7164 preemption_count++; | |
7165 RESET_CHANGED_SET_FLAGS; | |
7166 goto done; | |
7167 } | |
7168 | |
7169 /* See comment in redisplay_device. */ | |
7170 if (d->size_changed) | |
7171 size_change_failed = 1; | |
7172 } | |
7173 } | |
7174 preemption_count = 0; | |
7175 | |
7176 /* Mark redisplay as accurate */ | |
7177 GLOBAL_RESET_CHANGED_FLAGS; | |
7178 RESET_CHANGED_SET_FLAGS; | |
7179 | |
7180 if (faces_changed) | |
7181 { | |
7182 mark_all_faces_as_clean (); | |
7183 faces_changed = 0; | |
7184 } | |
7185 | |
7186 if (!size_change_failed) | |
7187 size_changed = 0; | |
7188 | |
7189 reset_buffer_changes (); | |
7190 | |
7191 done: | |
800 | 7192 #ifdef ERROR_CHECK_DISPLAY |
7193 sledgehammer_check_redisplay_structs (); | |
7194 #endif /* ERROR_CHECK_DISPLAY */ | |
1292 | 7195 |
7196 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay); | |
428 | 7197 } |
7198 | |
1318 | 7199 /* Note: All places in the C code that call redisplay() are prepared to |
7200 handle GCing, which can happen from run_pre_idle_hook(). However, we | |
7201 can't currently handle GC inside the guts of redisplay; see | |
7202 enter_redisplay_critical_section(). | |
853 | 7203 |
7204 (#### What about other external entry points to the redisplay code? | |
7205 Someone should go through and make sure that all callers can handle | |
7206 GC there, too.) | |
7207 */ | |
7208 | |
428 | 7209 void |
7210 redisplay (void) | |
7211 { | |
853 | 7212 run_pre_idle_hook (); |
7213 redisplay_no_pre_idle_hook (); | |
7214 } | |
7215 | |
7216 void | |
7217 redisplay_no_pre_idle_hook (void) | |
7218 { | |
428 | 7219 if (last_display_warning_tick != display_warning_tick && |
7220 !inhibit_warning_display) | |
7221 { | |
7222 /* If an error occurs during this function, oh well. | |
4187 | 7223 If we report another warning, we could get stuck in an |
428 | 7224 infinite loop reporting warnings. */ |
853 | 7225 call0_trapping_problems |
7226 (0, Qdisplay_warning_buffer, | |
7227 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION); | |
428 | 7228 last_display_warning_tick = display_warning_tick; |
7229 } | |
7230 | |
7231 redisplay_without_hooks (); | |
7232 } | |
7233 | |
853 | 7234 Lisp_Object |
7235 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker) | |
7236 { | |
7237 return | |
7238 eval_in_buffer_trapping_problems | |
7239 ("Error calling function within redisplay", current_buffer, | |
1318 | 7240 dont_trust_this_damn_sucker, 0); |
853 | 7241 } |
428 | 7242 |
7243 /* Efficiently determine the window line number, and return a pointer | |
7244 to its printed representation. Do this regardless of whether | |
7245 line-number-mode is on. The first line in the buffer is counted as | |
7246 1. If narrowing is in effect, the lines are counted from the | |
7247 beginning of the visible portion of the buffer. */ | |
4970 | 7248 static Ascbyte * |
428 | 7249 window_line_number (struct window *w, int type) |
7250 { | |
7251 struct device *d = XDEVICE (XFRAME (w->frame)->device); | |
7252 struct buffer *b = XBUFFER (w->buffer); | |
7253 /* Be careful in the order of these tests. The first clause will | |
7254 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be). | |
7255 This can occur when the frame title is computed really early */ | |
665 | 7256 Charbpos pos = |
5198 | 7257 ((EQ (DEVICE_SELECTED_FRAME (d), w->frame) && |
7258 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d)))) && | |
7259 EQ (DEVICE_CONSOLE (d), Vselected_console) && | |
7260 XDEVICE (CONSOLE_SELECTED_DEVICE (XCONSOLE (DEVICE_CONSOLE (d)))) == d ) | |
428 | 7261 ? BUF_PT (b) |
7262 : marker_position (w->pointm[type])); | |
7263 EMACS_INT line; | |
7264 | |
7265 line = buffer_line_number (b, pos, 1); | |
7266 | |
603 | 7267 { |
4970 | 7268 static Ascbyte window_line_number_buf[DECIMAL_PRINT_SIZE (long)]; |
603 | 7269 |
7270 long_to_string (window_line_number_buf, line + 1); | |
7271 | |
7272 return window_line_number_buf; | |
7273 } | |
428 | 7274 } |
7275 | |
7276 | |
7277 /* Given a character representing an object in a modeline | |
7278 specification, return a string (stored into the global array | |
867 | 7279 `mode_spec_ibyte_string') with the information that object |
428 | 7280 represents. |
7281 | |
7282 This function is largely unchanged from previous versions of the | |
7283 redisplay engine. | |
7284 | |
7285 Warning! This code is also used for frame titles and can be called | |
7286 very early in the device/frame update process! JV | |
7287 */ | |
7288 | |
7289 static void | |
867 | 7290 decode_mode_spec (struct window *w, Ichar spec, int type) |
428 | 7291 { |
7292 Lisp_Object obj = Qnil; | |
4970 | 7293 const Ascbyte *str = NULL; |
428 | 7294 struct buffer *b = XBUFFER (w->buffer); |
7295 | |
867 | 7296 Dynarr_reset (mode_spec_ibyte_string); |
428 | 7297 |
7298 switch (spec) | |
7299 { | |
7300 /* print buffer name */ | |
7301 case 'b': | |
7302 obj = b->name; | |
7303 break; | |
7304 | |
7305 /* print visited file name */ | |
7306 case 'f': | |
7307 obj = b->filename; | |
7308 break; | |
7309 | |
7310 /* print the current column */ | |
7311 case 'c': | |
7312 { | |
4187 | 7313 Charbpos pt = (w == XWINDOW (Fselected_window (Qnil))) |
7314 ? BUF_PT (b) | |
7315 : marker_position (w->pointm[type]); | |
428 | 7316 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one; |
4970 | 7317 Ascbyte buf[DECIMAL_PRINT_SIZE (long)]; |
428 | 7318 |
7319 long_to_string (buf, col); | |
7320 | |
867 | 7321 Dynarr_add_many (mode_spec_ibyte_string, |
7322 (const Ibyte *) buf, strlen (buf)); | |
428 | 7323 |
7324 goto decode_mode_spec_done; | |
7325 } | |
7326 /* print the file coding system */ | |
7327 case 'C': | |
7328 { | |
4187 | 7329 Lisp_Object codesys = b->buffer_file_coding_system; |
7330 /* Be very careful here not to get an error. */ | |
428 | 7331 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys)) |
4187 | 7332 { |
7333 codesys = find_coding_system_for_text_file (codesys, 0); | |
428 | 7334 if (CODING_SYSTEMP (codesys)) |
4187 | 7335 obj = XCODING_SYSTEM_MNEMONIC (codesys); |
7336 } | |
428 | 7337 } |
7338 break; | |
7339 | |
7340 /* print the current line number */ | |
7341 case 'l': | |
7342 str = window_line_number (w, type); | |
7343 break; | |
7344 | |
7345 /* print value of mode-name (obsolete) */ | |
7346 case 'm': | |
7347 obj = b->mode_name; | |
7348 break; | |
7349 | |
7350 /* print hyphen and frame number, if != 1 */ | |
7351 case 'N': | |
7352 #ifdef HAVE_TTY | |
7353 { | |
7354 struct frame *f = XFRAME (w->frame); | |
7355 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999) | |
7356 { | |
7357 /* Naughty, naughty */ | |
4970 | 7358 Ascbyte *writable_str = alloca_array (Ascbyte, 10); |
428 | 7359 sprintf (writable_str, "-%d", f->order_count); |
7360 str = writable_str; | |
7361 } | |
7362 } | |
7363 #endif /* HAVE_TTY */ | |
7364 break; | |
7365 | |
7366 /* print Narrow if appropriate */ | |
7367 case 'n': | |
7368 if (BUF_BEGV (b) > BUF_BEG (b) | |
7369 || BUF_ZV (b) < BUF_Z (b)) | |
7370 str = " Narrow"; | |
7371 break; | |
7372 | |
7373 /* print %, * or hyphen, if buffer is read-only, modified or neither */ | |
7374 case '*': | |
7375 str = (!NILP (b->read_only) | |
7376 ? "%" | |
7377 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7378 ? "*" | |
7379 : "-")); | |
7380 break; | |
7381 | |
7382 /* print * or hyphen -- XEmacs change to allow a buffer to be | |
4187 | 7383 read-only but still indicate whether it is modified. */ |
428 | 7384 case '+': |
7385 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7386 ? "*" | |
7387 : (!NILP (b->read_only) | |
7388 ? "%" | |
7389 : "-")); | |
7390 break; | |
7391 | |
7392 /* #### defined in 19.29 decode_mode_spec, but not in | |
4187 | 7393 modeline-format doc string. */ |
428 | 7394 /* This differs from %* in that it ignores read-only-ness. */ |
7395 case '&': | |
7396 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b)) | |
7397 ? "*" | |
7398 : "-"); | |
7399 break; | |
7400 | |
7401 /* print process status */ | |
7402 case 's': | |
7403 obj = Fget_buffer_process (w->buffer); | |
7404 if (NILP (obj)) | |
7405 str = GETTEXT ("no process"); | |
7406 else | |
7407 obj = Fsymbol_name (Fprocess_status (obj)); | |
7408 break; | |
7409 | |
7410 /* Print name of selected frame. */ | |
7411 case 'S': | |
7412 obj = XFRAME (w->frame)->name; | |
7413 break; | |
7414 | |
7415 /* indicate TEXT or BINARY */ | |
7416 case 't': | |
7417 /* #### NT does not use this any more. Now what? */ | |
7418 str = "T"; | |
7419 break; | |
7420 | |
7421 /* print percent of buffer above top of window, or Top, Bot or All */ | |
7422 case 'p': | |
7423 { | |
665 | 7424 Charbpos pos = marker_position (w->start[type]); |
428 | 7425 |
7426 /* This had better be while the desired lines are being done. */ | |
7427 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) | |
7428 { | |
7429 if (pos <= BUF_BEGV (b)) | |
7430 str = "All"; | |
7431 else | |
7432 str = "Bottom"; | |
7433 } | |
7434 else if (pos <= BUF_BEGV (b)) | |
7435 str = "Top"; | |
7436 else | |
7437 { | |
7438 /* This hard limit is ok since the string it will hold has a | |
4187 | 7439 fixed maximum length of 3. But just to be safe... */ |
4970 | 7440 Ascbyte buf[10]; |
428 | 7441 Charcount chars = pos - BUF_BEGV (b); |
7442 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7443 | |
7444 /* Avoid overflow on big buffers */ | |
7445 int percent = total > LONG_MAX/200 ? | |
7446 (chars + total/200) / (total / 100) : | |
7447 (chars * 100 + total/2) / total; | |
7448 | |
7449 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7450 2-digit number that is close. */ |
428 | 7451 if (percent == 100) |
7452 percent = 99; | |
7453 | |
7454 sprintf (buf, "%d%%", percent); | |
867 | 7455 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7456 strlen (buf)); |
7457 | |
7458 goto decode_mode_spec_done; | |
7459 } | |
7460 break; | |
7461 } | |
7462 | |
7463 /* print percent of buffer above bottom of window, perhaps plus | |
7464 Top, or print Bottom or All */ | |
7465 case 'P': | |
7466 { | |
665 | 7467 Charbpos toppos = marker_position (w->start[type]); |
7468 Charbpos botpos = BUF_Z (b) - w->window_end_pos[type]; | |
428 | 7469 |
7470 /* botpos is only accurate as of the last redisplay, so we can | |
4187 | 7471 only treat it as a hint. In particular, after erase-buffer, |
7472 botpos may be negative. */ | |
428 | 7473 if (botpos < toppos) |
7474 botpos = toppos; | |
7475 | |
7476 if (botpos >= BUF_ZV (b)) | |
7477 { | |
7478 if (toppos <= BUF_BEGV (b)) | |
7479 str = "All"; | |
7480 else | |
7481 str = "Bottom"; | |
7482 } | |
7483 else | |
7484 { | |
7485 /* This hard limit is ok since the string it will hold has a | |
4187 | 7486 fixed maximum length of around 6. But just to be safe... */ |
4970 | 7487 Ascbyte buf[10]; |
428 | 7488 Charcount chars = botpos - BUF_BEGV (b); |
7489 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
7490 | |
7491 /* Avoid overflow on big buffers */ | |
7492 int percent = total > LONG_MAX/200 ? | |
7493 (chars + total/200) / (total / 100) : | |
7494 (chars * 100 + total/2) / max (total, 1); | |
7495 | |
7496 /* We can't normally display a 3-digit number, so get us a | |
4187 | 7497 2-digit number that is close. */ |
428 | 7498 if (percent == 100) |
7499 percent = 99; | |
7500 | |
7501 if (toppos <= BUF_BEGV (b)) | |
7502 sprintf (buf, "Top%d%%", percent); | |
7503 else | |
7504 sprintf (buf, "%d%%", percent); | |
7505 | |
867 | 7506 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) buf, |
428 | 7507 strlen (buf)); |
7508 | |
7509 goto decode_mode_spec_done; | |
7510 } | |
7511 break; | |
7512 } | |
7513 | |
7514 /* print % */ | |
7515 case '%': | |
7516 str = "%"; | |
7517 break; | |
7518 | |
7519 /* print one [ for each recursive editing level. */ | |
7520 case '[': | |
7521 { | |
7522 int i; | |
7523 | |
7524 if (command_loop_level > 5) | |
7525 { | |
7526 str = "[[[... "; | |
7527 break; | |
7528 } | |
7529 | |
7530 for (i = 0; i < command_loop_level; i++) | |
867 | 7531 Dynarr_add (mode_spec_ibyte_string, '['); |
428 | 7532 |
7533 goto decode_mode_spec_done; | |
7534 } | |
7535 | |
7536 /* print one ] for each recursive editing level. */ | |
7537 case ']': | |
7538 { | |
7539 int i; | |
7540 | |
7541 if (command_loop_level > 5) | |
7542 { | |
7543 str = "...]]]"; | |
7544 break; | |
7545 } | |
7546 | |
7547 for (i = 0; i < command_loop_level; i++) | |
867 | 7548 Dynarr_add (mode_spec_ibyte_string, ']'); |
428 | 7549 |
7550 goto decode_mode_spec_done; | |
7551 } | |
7552 | |
7553 /* print infinitely many dashes -- handle at top level now */ | |
7554 case '-': | |
7555 break; | |
7556 | |
7557 } | |
7558 | |
7559 if (STRINGP (obj)) | |
867 | 7560 Dynarr_add_many (mode_spec_ibyte_string, |
428 | 7561 XSTRING_DATA (obj), |
7562 XSTRING_LENGTH (obj)); | |
7563 else if (str) | |
867 | 7564 Dynarr_add_many (mode_spec_ibyte_string, (Ibyte *) str, strlen (str)); |
428 | 7565 |
7566 decode_mode_spec_done: | |
867 | 7567 Dynarr_add (mode_spec_ibyte_string, '\0'); |
428 | 7568 } |
7569 | |
7570 /* Given a display line, free all of its data structures. */ | |
7571 | |
7572 static void | |
7573 free_display_line (struct display_line *dl) | |
7574 { | |
7575 int block; | |
7576 | |
7577 if (dl->display_blocks) | |
7578 { | |
7579 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) | |
4187 | 7580 { |
428 | 7581 struct display_block *db = Dynarr_atp (dl->display_blocks, block); |
7582 | |
7583 Dynarr_free (db->runes); | |
7584 } | |
7585 | |
7586 Dynarr_free (dl->display_blocks); | |
7587 dl->display_blocks = NULL; | |
7588 } | |
7589 | |
7590 if (dl->left_glyphs) | |
7591 { | |
7592 Dynarr_free (dl->left_glyphs); | |
7593 dl->left_glyphs = NULL; | |
7594 } | |
7595 | |
7596 if (dl->right_glyphs) | |
7597 { | |
7598 Dynarr_free (dl->right_glyphs); | |
7599 dl->right_glyphs = NULL; | |
7600 } | |
7601 } | |
7602 | |
7603 | |
7604 /* Given an array of display lines, free them and all data structures | |
7605 contained within them. */ | |
7606 | |
7607 void | |
7608 free_display_lines (display_line_dynarr *dla) | |
7609 { | |
7610 int line; | |
7611 | |
7612 for (line = 0; line < Dynarr_largest (dla); line++) | |
7613 { | |
7614 free_display_line (Dynarr_atp (dla, line)); | |
7615 } | |
7616 | |
7617 Dynarr_free (dla); | |
7618 } | |
7619 | |
7620 /* Call internal free routine for each set of display lines. */ | |
7621 | |
7622 void | |
7623 free_display_structs (struct window_mirror *mir) | |
7624 { | |
7625 if (mir->current_display_lines) | |
7626 { | |
7627 free_display_lines (mir->current_display_lines); | |
7628 mir->current_display_lines = 0; | |
7629 } | |
7630 | |
7631 if (mir->desired_display_lines) | |
7632 { | |
7633 free_display_lines (mir->desired_display_lines); | |
7634 mir->desired_display_lines = 0; | |
7635 } | |
7636 } | |
7637 | |
7638 | |
7639 static void | |
7640 mark_glyph_block_dynarr (glyph_block_dynarr *gba) | |
7641 { | |
7642 if (gba) | |
7643 { | |
4967 | 7644 glyph_block *gb = Dynarr_begin (gba); |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7645 glyph_block *gb_last = Dynarr_past_lastp (gba); |
428 | 7646 |
7647 for (; gb < gb_last; gb++) | |
7648 { | |
7649 if (!NILP (gb->glyph)) | |
7650 mark_object (gb->glyph); | |
7651 if (!NILP (gb->extent)) | |
7652 mark_object (gb->extent); | |
7653 } | |
7654 } | |
7655 } | |
7656 | |
442 | 7657 /* See the comment in image_instantiate_cache_result as to why marking |
7658 the glyph will also mark the image_instance. */ | |
7659 void | |
428 | 7660 mark_redisplay_structs (display_line_dynarr *dla) |
7661 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7662 display_line *dl = Dynarr_begin (dla); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7663 display_line *dl_last = Dynarr_past_lastp (dla); |
428 | 7664 |
7665 for (; dl < dl_last; dl++) | |
7666 { | |
7667 display_block_dynarr *dba = dl->display_blocks; | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7668 display_block *db = Dynarr_begin (dba); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7669 display_block *db_last = Dynarr_past_lastp (dba); |
428 | 7670 |
7671 for (; db < db_last; db++) | |
7672 { | |
7673 rune_dynarr *ra = db->runes; | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7674 rune *r = Dynarr_begin (ra); |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7675 rune *r_last = Dynarr_past_lastp (ra); |
428 | 7676 |
7677 for (; r < r_last; r++) | |
7678 { | |
7679 if (r->type == RUNE_DGLYPH) | |
7680 { | |
7681 if (!NILP (r->object.dglyph.glyph)) | |
7682 mark_object (r->object.dglyph.glyph); | |
7683 if (!NILP (r->object.dglyph.extent)) | |
7684 mark_object (r->object.dglyph.extent); | |
7685 } | |
7686 } | |
7687 } | |
7688 | |
7689 mark_glyph_block_dynarr (dl->left_glyphs); | |
7690 mark_glyph_block_dynarr (dl->right_glyphs); | |
7691 } | |
7692 } | |
7693 | |
7694 | |
2367 | 7695 |
7696 /* | |
7697 | |
7698 Info on line-start cache: | |
7699 | |
7700 (Info-goto-node "(internals)Line Start Cache") | |
7701 */ | |
428 | 7702 |
7703 /* This will get used quite a bit so we don't want to be constantly | |
7704 allocating and freeing it. */ | |
7705 static line_start_cache_dynarr *internal_cache; | |
7706 | |
7707 /* Makes internal_cache represent the TYPE display structs and only | |
7708 the TYPE display structs. */ | |
7709 | |
7710 static void | |
7711 update_internal_cache_list (struct window *w, int type) | |
7712 { | |
7713 int line; | |
7714 display_line_dynarr *dla = window_display_lines (w, type); | |
7715 | |
7716 Dynarr_reset (internal_cache); | |
7717 for (line = 0; line < Dynarr_length (dla); line++) | |
7718 { | |
7719 struct display_line *dl = Dynarr_atp (dla, line); | |
7720 | |
7721 if (dl->modeline) | |
7722 continue; | |
7723 else | |
7724 { | |
7725 struct line_start_cache lsc; | |
434 | 7726 |
826 | 7727 lsc.start = dl->charpos; |
7728 lsc.end = dl->end_charpos; | |
428 | 7729 lsc.height = dl->ascent + dl->descent; |
7730 | |
7731 Dynarr_add (internal_cache, lsc); | |
7732 } | |
7733 } | |
7734 } | |
7735 | |
7736 /* Reset the line cache if necessary. This should be run at the | |
7737 beginning of any function which access the cache. */ | |
7738 | |
7739 static void | |
7740 validate_line_start_cache (struct window *w) | |
7741 { | |
7742 struct buffer *b = XBUFFER (w->buffer); | |
7743 struct frame *f = XFRAME (w->frame); | |
7744 | |
7745 if (!w->line_cache_validation_override) | |
7746 { | |
7747 /* f->extents_changed used to be in here because extent face and | |
4187 | 7748 size changes can cause text shifting. However, the extent |
7749 covering the region is constantly having its face set and | |
7750 priority altered by the mouse code. This means that the line | |
7751 start cache is constantly being invalidated. This is bad | |
7752 since the mouse code also triggers heavy usage of the cache. | |
7753 Since it is an unlikely that f->extents being changed | |
7754 indicates that the cache really needs to be updated and if it | |
7755 does redisplay will catch it pretty quickly we no longer | |
7756 invalidate the cache if it is set. This greatly speeds up | |
7757 dragging out regions with the mouse. */ | |
428 | 7758 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b) |
7759 || f->faces_changed | |
7760 || f->clip_changed) | |
7761 { | |
7762 Dynarr_reset (w->line_start_cache); | |
7763 } | |
7764 } | |
7765 } | |
7766 | |
7767 /* Return the very first buffer position contained in the given | |
7768 window's cache, or -1 if the cache is empty. Assumes that the | |
7769 cache is valid. */ | |
7770 | |
665 | 7771 static Charbpos |
428 | 7772 line_start_cache_start (struct window *w) |
7773 { | |
7774 line_start_cache_dynarr *cache = w->line_start_cache; | |
7775 | |
7776 if (!Dynarr_length (cache)) | |
7777 return -1; | |
7778 else | |
4967 | 7779 return Dynarr_begin (cache)->start; |
428 | 7780 } |
7781 | |
7782 /* Return the very last buffer position contained in the given | |
7783 window's cache, or -1 if the cache is empty. Assumes that the | |
7784 cache is valid. */ | |
7785 | |
665 | 7786 static Charbpos |
428 | 7787 line_start_cache_end (struct window *w) |
7788 { | |
7789 line_start_cache_dynarr *cache = w->line_start_cache; | |
7790 | |
7791 if (!Dynarr_length (cache)) | |
7792 return -1; | |
7793 else | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
7794 return Dynarr_lastp (cache)->end; |
428 | 7795 } |
7796 | |
7797 /* Return the index of the line POINT is contained within in window | |
7798 W's line start cache. It will enlarge the cache or move the cache | |
7799 window in order to have POINT be present in the cache. MIN_PAST is | |
7800 a guarantee of the number of entries in the cache present on either | |
7801 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1 | |
7802 then it will be treated as 0, but the cache window will not be | |
7803 allowed to shift. Returns -1 if POINT cannot be found in the cache | |
7804 for any reason. */ | |
7805 | |
7806 int | |
665 | 7807 point_in_line_start_cache (struct window *w, Charbpos point, int min_past) |
428 | 7808 { |
7809 struct buffer *b = XBUFFER (w->buffer); | |
7810 line_start_cache_dynarr *cache = w->line_start_cache; | |
647 | 7811 int top, bottom, pos; |
428 | 7812 |
7813 validate_line_start_cache (w); | |
7814 w->line_cache_validation_override++; | |
7815 | |
7816 /* Let functions pass in negative values, but we still treat -1 | |
7817 specially. */ | |
7818 /* #### bogosity alert */ | |
7819 if (min_past < 0 && min_past != -1) | |
7820 min_past = -min_past; | |
7821 | |
7822 if (!Dynarr_length (cache) || line_start_cache_start (w) > point | |
7823 || line_start_cache_end (w) < point) | |
7824 { | |
7825 int loop; | |
7826 int win_char_height = window_char_height (w, 1); | |
7827 | |
7828 /* Occasionally we get here with a 0 height | |
4187 | 7829 window. find_next_newline_no_quit will abort if we pass it a |
7830 count of 0 so handle that case. */ | |
428 | 7831 if (!win_char_height) |
7832 win_char_height = 1; | |
7833 | |
7834 if (!Dynarr_length (cache)) | |
7835 { | |
665 | 7836 Charbpos from = find_next_newline_no_quit (b, point, -1); |
7837 Charbpos to = find_next_newline_no_quit (b, from, win_char_height); | |
428 | 7838 |
7839 update_line_start_cache (w, from, to, point, 0); | |
7840 | |
7841 if (!Dynarr_length (cache)) | |
7842 { | |
7843 w->line_cache_validation_override--; | |
7844 return -1; | |
7845 } | |
7846 } | |
7847 | |
7848 assert (Dynarr_length (cache)); | |
7849 | |
7850 loop = 0; | |
7851 while (line_start_cache_start (w) > point | |
7852 && (loop < cache_adjustment || min_past == -1)) | |
7853 { | |
665 | 7854 Charbpos from, to; |
428 | 7855 |
7856 from = line_start_cache_start (w); | |
7857 if (from <= BUF_BEGV (b)) | |
7858 break; | |
7859 | |
7860 from = find_next_newline_no_quit (b, from, -win_char_height); | |
7861 to = line_start_cache_end (w); | |
7862 | |
7863 update_line_start_cache (w, from, to, point, 0); | |
7864 loop++; | |
7865 } | |
7866 | |
7867 if (line_start_cache_start (w) > point) | |
7868 { | |
665 | 7869 Charbpos from, to; |
428 | 7870 |
7871 from = find_next_newline_no_quit (b, point, -1); | |
7872 if (from >= BUF_ZV (b)) | |
7873 { | |
7874 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7875 from = to; | |
7876 to = BUF_ZV (b); | |
7877 } | |
7878 else | |
7879 to = find_next_newline_no_quit (b, from, win_char_height); | |
7880 | |
7881 update_line_start_cache (w, from, to, point, 0); | |
7882 } | |
7883 | |
7884 loop = 0; | |
7885 while (line_start_cache_end (w) < point | |
7886 && (loop < cache_adjustment || min_past == -1)) | |
7887 { | |
665 | 7888 Charbpos from, to; |
428 | 7889 |
7890 to = line_start_cache_end (w); | |
7891 if (to >= BUF_ZV (b)) | |
7892 break; | |
7893 | |
7894 from = line_start_cache_end (w); | |
7895 to = find_next_newline_no_quit (b, from, win_char_height); | |
7896 | |
7897 update_line_start_cache (w, from, to, point, 0); | |
7898 loop++; | |
7899 } | |
7900 | |
7901 if (line_start_cache_end (w) < point) | |
7902 { | |
665 | 7903 Charbpos from, to; |
428 | 7904 |
7905 from = find_next_newline_no_quit (b, point, -1); | |
7906 if (from >= BUF_ZV (b)) | |
7907 { | |
7908 to = find_next_newline_no_quit (b, from, -win_char_height); | |
7909 from = to; | |
7910 to = BUF_ZV (b); | |
7911 } | |
7912 else | |
7913 to = find_next_newline_no_quit (b, from, win_char_height); | |
7914 | |
7915 update_line_start_cache (w, from, to, point, 0); | |
7916 } | |
7917 } | |
7918 | |
7919 assert (Dynarr_length (cache)); | |
7920 | |
7921 if (min_past == -1) | |
7922 min_past = 0; | |
7923 | |
7924 /* This could happen if the buffer is narrowed. */ | |
7925 if (line_start_cache_start (w) > point | |
7926 || line_start_cache_end (w) < point) | |
7927 { | |
7928 w->line_cache_validation_override--; | |
7929 return -1; | |
7930 } | |
7931 | |
7932 find_point_loop: | |
7933 | |
7934 top = Dynarr_length (cache) - 1; | |
7935 bottom = 0; | |
7936 | |
7937 while (1) | |
7938 { | |
647 | 7939 int new_pos; |
665 | 7940 Charbpos start, end; |
428 | 7941 |
7942 pos = (bottom + top + 1) >> 1; | |
7943 start = Dynarr_atp (cache, pos)->start; | |
7944 end = Dynarr_atp (cache, pos)->end; | |
7945 | |
7946 if (point >= start && point <= end) | |
7947 { | |
7948 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b)) | |
7949 { | |
665 | 7950 Charbpos from = |
428 | 7951 find_next_newline_no_quit (b, line_start_cache_start (w), |
7952 -min_past - 1); | |
665 | 7953 Charbpos to = line_start_cache_end (w); |
428 | 7954 |
7955 update_line_start_cache (w, from, to, point, 0); | |
7956 goto find_point_loop; | |
7957 } | |
7958 else if ((Dynarr_length (cache) - pos - 1) < min_past | |
7959 && line_start_cache_end (w) < BUF_ZV (b)) | |
7960 { | |
665 | 7961 Charbpos from = line_start_cache_end (w); |
7962 Charbpos to = find_next_newline_no_quit (b, from, | |
428 | 7963 (min_past |
7964 ? min_past | |
7965 : 1)); | |
7966 | |
7967 update_line_start_cache (w, from, to, point, 0); | |
7968 goto find_point_loop; | |
7969 } | |
7970 else | |
7971 { | |
7972 w->line_cache_validation_override--; | |
7973 return pos; | |
7974 } | |
7975 } | |
7976 else if (point > end) | |
7977 bottom = pos + 1; | |
7978 else if (point < start) | |
7979 top = pos - 1; | |
7980 else | |
2500 | 7981 ABORT (); |
428 | 7982 |
7983 new_pos = (bottom + top + 1) >> 1; | |
7984 if (pos == new_pos) | |
7985 { | |
7986 w->line_cache_validation_override--; | |
7987 return -1; | |
7988 } | |
7989 } | |
7990 } | |
7991 | |
7992 /* Return a boolean indicating if POINT would be visible in window W | |
1708 | 7993 if display of the window was to begin at STARTP. If PARTIALLY is |
7994 zero, then if POINT has fewer visible pixels than the window clip, | |
7995 0 is returned; otherwise, 1 is returned if POINT has any visible | |
7996 pixels. */ | |
428 | 7997 int |
1708 | 7998 point_would_be_visible (struct window *w, Charbpos startp, Charbpos point, |
7999 int partially) | |
428 | 8000 { |
8001 struct buffer *b = XBUFFER (w->buffer); | |
5198 | 8002 int pixpos = -WINDOW_TEXT_TOP_CLIP (w); |
428 | 8003 int bottom = WINDOW_TEXT_HEIGHT (w); |
8004 int start_elt; | |
8005 | |
8006 /* If point is before the intended start it obviously can't be visible. */ | |
8007 if (point < startp) | |
8008 return 0; | |
8009 | |
8010 /* If point or start are not in the accessible buffer range, then | |
8011 fail. */ | |
8012 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b) | |
8013 || point < BUF_BEGV (b) || point > BUF_ZV (b)) | |
8014 return 0; | |
8015 | |
8016 validate_line_start_cache (w); | |
8017 w->line_cache_validation_override++; | |
8018 | |
8019 start_elt = point_in_line_start_cache (w, startp, 0); | |
8020 if (start_elt == -1) | |
8021 { | |
8022 w->line_cache_validation_override--; | |
8023 return 0; | |
8024 } | |
8025 | |
8026 assert (line_start_cache_start (w) <= startp | |
8027 && line_start_cache_end (w) >= startp); | |
8028 | |
8029 while (1) | |
8030 { | |
8031 int height; | |
8032 | |
8033 /* Expand the cache if necessary. */ | |
8034 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8035 { | |
665 | 8036 Charbpos old_startp = |
428 | 8037 Dynarr_atp (w->line_start_cache, start_elt - 1)->start; |
8038 | |
8039 start_elt = point_in_line_start_cache (w, old_startp, | |
8040 window_char_height (w, 0)); | |
8041 | |
8042 /* We've already actually processed old_startp, so increment | |
4187 | 8043 immediately. */ |
428 | 8044 start_elt++; |
8045 | |
8046 /* If this happens we didn't add any extra elements. Bummer. */ | |
8047 if (start_elt == Dynarr_length (w->line_start_cache)) | |
8048 { | |
8049 w->line_cache_validation_override--; | |
8050 return 0; | |
8051 } | |
8052 } | |
8053 | |
8054 height = Dynarr_atp (w->line_start_cache, start_elt)->height; | |
8055 | |
8056 if (pixpos + height > bottom) | |
8057 { | |
1708 | 8058 if (bottom - pixpos < (partially ? 0 : VERTICAL_CLIP (w, 0))) |
428 | 8059 { |
8060 w->line_cache_validation_override--; | |
8061 return 0; | |
8062 } | |
8063 } | |
8064 | |
8065 pixpos += height; | |
8066 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end) | |
8067 { | |
8068 w->line_cache_validation_override--; | |
8069 return 1; | |
8070 } | |
8071 | |
8072 start_elt++; | |
8073 } | |
8074 } | |
8075 | |
8076 /* For the given window W, if display starts at STARTP, what will be | |
8077 the buffer position at the beginning or end of the last line | |
8078 displayed. The end of the last line is also know as the window end | |
8079 position. | |
8080 | |
442 | 8081 WARNING: It is possible that redisplay failed to layout any lines for the |
8082 windows. Under normal circumstances this is rare. However it seems that it | |
8083 does occur in the following situation: A mouse event has come in and we | |
8084 need to compute its location in a window. That code (in | |
8085 pixel_to_glyph_translation) already can handle 0 as an error return value. | |
8086 | |
428 | 8087 #### With a little work this could probably be reworked as just a |
8088 call to start_with_line_at_pixpos. */ | |
8089 | |
665 | 8090 static Charbpos |
8091 start_end_of_last_line (struct window *w, Charbpos startp, int end, | |
4187 | 8092 int may_error) |
428 | 8093 { |
8094 struct buffer *b = XBUFFER (w->buffer); | |
8095 line_start_cache_dynarr *cache = w->line_start_cache; | |
8096 int pixpos = 0; | |
8097 int bottom = WINDOW_TEXT_HEIGHT (w); | |
665 | 8098 Charbpos cur_start; |
428 | 8099 int start_elt; |
8100 | |
8101 validate_line_start_cache (w); | |
8102 w->line_cache_validation_override++; | |
8103 | |
8104 if (startp < BUF_BEGV (b)) | |
8105 startp = BUF_BEGV (b); | |
8106 else if (startp > BUF_ZV (b)) | |
8107 startp = BUF_ZV (b); | |
8108 cur_start = startp; | |
8109 | |
8110 start_elt = point_in_line_start_cache (w, cur_start, 0); | |
8111 if (start_elt == -1) | |
442 | 8112 return may_error ? 0 : startp; |
428 | 8113 |
8114 while (1) | |
8115 { | |
8116 int height = Dynarr_atp (cache, start_elt)->height; | |
8117 | |
8118 cur_start = Dynarr_atp (cache, start_elt)->start; | |
8119 | |
8120 if (pixpos + height > bottom) | |
8121 { | |
8122 /* Adjust for any possible clip. */ | |
8123 if (bottom - pixpos < VERTICAL_CLIP (w, 0)) | |
8124 start_elt--; | |
8125 | |
8126 if (start_elt < 0) | |
8127 { | |
8128 w->line_cache_validation_override--; | |
8129 if (end) | |
8130 return BUF_ZV (b); | |
8131 else | |
8132 return BUF_BEGV (b); | |
8133 } | |
8134 else | |
8135 { | |
8136 w->line_cache_validation_override--; | |
8137 if (end) | |
8138 return Dynarr_atp (cache, start_elt)->end; | |
8139 else | |
8140 return Dynarr_atp (cache, start_elt)->start; | |
8141 } | |
8142 } | |
8143 | |
8144 pixpos += height; | |
8145 start_elt++; | |
8146 if (start_elt == Dynarr_length (cache)) | |
8147 { | |
665 | 8148 Charbpos from = line_start_cache_end (w); |
428 | 8149 int win_char_height = window_char_height (w, 0); |
665 | 8150 Charbpos to = find_next_newline_no_quit (b, from, |
428 | 8151 (win_char_height |
8152 ? win_char_height | |
8153 : 1)); | |
8154 | |
8155 /* We've hit the end of the bottom so that's what it is. */ | |
8156 if (from >= BUF_ZV (b)) | |
8157 { | |
8158 w->line_cache_validation_override--; | |
8159 return BUF_ZV (b); | |
8160 } | |
8161 | |
8162 update_line_start_cache (w, from, to, BUF_PT (b), 0); | |
8163 | |
8164 /* Updating the cache invalidates any current indexes. */ | |
8165 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1; | |
8166 } | |
8167 } | |
8168 } | |
8169 | |
8170 /* For the given window W, if display starts at STARTP, what will be | |
8171 the buffer position at the beginning of the last line displayed. */ | |
8172 | |
665 | 8173 Charbpos |
8174 start_of_last_line (struct window *w, Charbpos startp) | |
428 | 8175 { |
442 | 8176 return start_end_of_last_line (w, startp, 0 , 0); |
428 | 8177 } |
8178 | |
8179 /* For the given window W, if display starts at STARTP, what will be | |
8180 the buffer position at the end of the last line displayed. This is | |
8181 also know as the window end position. */ | |
8182 | |
665 | 8183 Charbpos |
8184 end_of_last_line (struct window *w, Charbpos startp) | |
428 | 8185 { |
442 | 8186 return start_end_of_last_line (w, startp, 1, 0); |
428 | 8187 } |
8188 | |
665 | 8189 static Charbpos |
8190 end_of_last_line_may_error (struct window *w, Charbpos startp) | |
442 | 8191 { |
8192 return start_end_of_last_line (w, startp, 1, 1); | |
8193 } | |
8194 | |
8195 | |
428 | 8196 /* For window W, what does the starting position have to be so that |
8197 the line containing POINT will cover pixel position PIXPOS. */ | |
8198 | |
665 | 8199 Charbpos |
8200 start_with_line_at_pixpos (struct window *w, Charbpos point, int pixpos) | |
428 | 8201 { |
8202 struct buffer *b = XBUFFER (w->buffer); | |
8203 int cur_elt; | |
665 | 8204 Charbpos cur_pos, prev_pos = point; |
428 | 8205 int point_line_height; |
8206 int pixheight = pixpos - WINDOW_TEXT_TOP (w); | |
8207 | |
8208 validate_line_start_cache (w); | |
8209 w->line_cache_validation_override++; | |
8210 | |
8211 cur_elt = point_in_line_start_cache (w, point, 0); | |
8212 /* #### See comment in update_line_start_cache about big minibuffers. */ | |
8213 if (cur_elt < 0) | |
8214 { | |
8215 w->line_cache_validation_override--; | |
8216 return point; | |
8217 } | |
8218 | |
8219 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8220 | |
8221 while (1) | |
8222 { | |
8223 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8224 | |
8225 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8226 | |
8227 /* Do not take into account the value of vertical_clip here. | |
4187 | 8228 That is the responsibility of the calling functions. */ |
428 | 8229 if (pixheight < 0) |
8230 { | |
8231 w->line_cache_validation_override--; | |
8232 if (-pixheight > point_line_height) | |
8233 /* We can't make the target line cover pixpos, so put it | |
8234 above pixpos. That way it will at least be visible. */ | |
8235 return prev_pos; | |
8236 else | |
8237 return cur_pos; | |
8238 } | |
8239 | |
8240 cur_elt--; | |
8241 while (cur_elt < 0) | |
8242 { | |
665 | 8243 Charbpos from, to; |
428 | 8244 int win_char_height; |
8245 | |
8246 if (cur_pos <= BUF_BEGV (b)) | |
8247 { | |
8248 w->line_cache_validation_override--; | |
8249 return BUF_BEGV (b); | |
8250 } | |
8251 | |
8252 win_char_height = window_char_height (w, 0); | |
8253 if (!win_char_height) | |
8254 win_char_height = 1; | |
8255 | |
8256 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); | |
8257 to = line_start_cache_end (w); | |
8258 update_line_start_cache (w, from, to, point, 0); | |
8259 | |
8260 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; | |
8261 assert (cur_elt >= -1); | |
8262 /* This used to be cur_elt>=0 under the assumption that if | |
8263 point is in the top line and not at BUF_BEGV, then | |
434 | 8264 setting the window_start to a newline before the start of |
428 | 8265 the first line will always cause scrolling. |
8266 | |
8267 However in my (jv) opinion this is wrong. That new line | |
8268 can be hidden in various ways: invisible extents, an | |
8269 explicit window-start not at a newline character etc. | |
8270 The existence of those are indeed known to create crashes | |
8271 on that assert. So we have no option but to continue the | |
8272 search if we found point at the top of the line_start_cache | |
8273 again. */ | |
4967 | 8274 cur_pos = Dynarr_begin (w->line_start_cache)->start; |
428 | 8275 } |
8276 prev_pos = cur_pos; | |
8277 } | |
8278 } | |
8279 | |
8280 /* For window W, what does the starting position have to be so that | |
8281 the line containing point is on display line LINE. If LINE is | |
8282 positive it is considered to be the number of lines from the top of | |
8283 the window (0 is the top line). If it is negative the number is | |
8284 considered to be the number of lines from the bottom (-1 is the | |
8285 bottom line). */ | |
8286 | |
665 | 8287 Charbpos |
8288 start_with_point_on_display_line (struct window *w, Charbpos point, int line) | |
428 | 8289 { |
8290 validate_line_start_cache (w); | |
8291 w->line_cache_validation_override++; | |
8292 | |
8293 if (line >= 0) | |
8294 { | |
8295 int cur_elt = point_in_line_start_cache (w, point, line); | |
8296 | |
8297 if (cur_elt - line < 0) | |
8298 cur_elt = 0; /* Hit the top */ | |
8299 else | |
8300 cur_elt -= line; | |
8301 | |
8302 w->line_cache_validation_override--; | |
8303 return Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8304 } | |
8305 else | |
8306 { | |
8307 /* The calculated value of pixpos is correct for the bottom line | |
4187 | 8308 or what we want when line is -1. Therefore we subtract one |
8309 because we have already handled one line. */ | |
428 | 8310 int new_line = -line - 1; |
8311 int cur_elt = point_in_line_start_cache (w, point, new_line); | |
8312 int pixpos = WINDOW_TEXT_BOTTOM (w); | |
665 | 8313 Charbpos retval, search_point; |
428 | 8314 |
8315 /* If scroll_on_clipped_lines is false, the last "visible" line of | |
4187 | 8316 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1. |
8317 If s_o_c_l is true, then we don't want to count a clipped | |
8318 line, so back up from the bottom by the height of the line | |
8319 containing point. */ | |
428 | 8320 if (scroll_on_clipped_lines) |
8321 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height; | |
8322 else | |
8323 pixpos -= 1; | |
8324 | |
8325 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache)) | |
8326 { | |
8327 /* Hit the bottom of the buffer. */ | |
8328 int adjustment = | |
8329 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1; | |
8330 Lisp_Object window; | |
8331 int defheight; | |
8332 | |
793 | 8333 window = wrap_window (w); |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
8334 default_face_width_and_height (window, 0, &defheight); |
428 | 8335 |
8336 cur_elt = Dynarr_length (w->line_start_cache) - 1; | |
8337 | |
8338 pixpos -= (adjustment * defheight); | |
8339 if (pixpos < WINDOW_TEXT_TOP (w)) | |
8340 pixpos = WINDOW_TEXT_TOP (w); | |
8341 } | |
8342 else | |
8343 cur_elt = cur_elt + new_line; | |
8344 | |
8345 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start; | |
8346 | |
8347 retval = start_with_line_at_pixpos (w, search_point, pixpos); | |
8348 w->line_cache_validation_override--; | |
8349 return retval; | |
8350 } | |
8351 } | |
8352 | |
8353 /* This is used to speed up vertical scrolling by caching the known | |
8354 buffer starting positions for display lines. This allows the | |
8355 scrolling routines to avoid costly calls to regenerate_window. If | |
8356 NO_REGEN is true then it will only add the values in the DESIRED | |
8357 display structs which are in the given range. | |
8358 | |
8359 Note also that the FROM/TO values are minimums. It is possible | |
8360 that this function will actually add information outside of the | |
8361 lines containing those positions. This can't hurt but it could | |
8362 possibly help. | |
8363 | |
8364 #### We currently force the cache to have only 1 contiguous region. | |
8365 It might help to make the cache a dynarr of caches so that we can | |
8366 cover more areas. This might, however, turn out to be a lot of | |
8367 overhead for too little gain. */ | |
8368 | |
8369 static void | |
665 | 8370 update_line_start_cache (struct window *w, Charbpos from, Charbpos to, |
8371 Charbpos point, int no_regen) | |
428 | 8372 { |
8373 struct buffer *b = XBUFFER (w->buffer); | |
8374 line_start_cache_dynarr *cache = w->line_start_cache; | |
665 | 8375 Charbpos low_bound, high_bound; |
428 | 8376 |
8377 validate_line_start_cache (w); | |
8378 w->line_cache_validation_override++; | |
8379 | |
8380 if (from < BUF_BEGV (b)) | |
8381 from = BUF_BEGV (b); | |
8382 if (to > BUF_ZV (b)) | |
8383 to = BUF_ZV (b); | |
8384 | |
8385 if (from > to) | |
8386 { | |
8387 w->line_cache_validation_override--; | |
8388 return; | |
8389 } | |
8390 | |
8391 if (Dynarr_length (cache)) | |
8392 { | |
8393 low_bound = line_start_cache_start (w); | |
8394 high_bound = line_start_cache_end (w); | |
8395 | |
8396 /* Check to see if the desired range is already in the cache. */ | |
8397 if (from >= low_bound && to <= high_bound) | |
8398 { | |
8399 w->line_cache_validation_override--; | |
8400 return; | |
8401 } | |
8402 | |
8403 /* Check to make sure that the desired range is adjacent to the | |
8404 current cache. If not, invalidate the cache. */ | |
8405 if (to < low_bound || from > high_bound) | |
8406 { | |
8407 Dynarr_reset (cache); | |
8408 low_bound = high_bound = -1; | |
8409 } | |
8410 } | |
8411 else | |
8412 { | |
8413 low_bound = high_bound = -1; | |
8414 } | |
8415 | |
8416 w->line_cache_last_updated = make_int (BUF_MODIFF (b)); | |
8417 | |
8418 /* This could be integrated into the next two sections, but it is easier | |
8419 to follow what's going on by having it separate. */ | |
8420 if (no_regen) | |
8421 { | |
665 | 8422 Charbpos start, end; |
428 | 8423 |
8424 update_internal_cache_list (w, DESIRED_DISP); | |
8425 if (!Dynarr_length (internal_cache)) | |
8426 { | |
8427 w->line_cache_validation_override--; | |
8428 return; | |
8429 } | |
8430 | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8431 start = Dynarr_begin (internal_cache)->start; |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8432 end = Dynarr_lastp (internal_cache)->end; |
428 | 8433 |
8434 /* We aren't allowed to generate additional information to fill in | |
4187 | 8435 gaps, so if the DESIRED structs don't overlap the cache, reset the |
8436 cache. */ | |
428 | 8437 if (Dynarr_length (cache)) |
8438 { | |
8439 if (end < low_bound || start > high_bound) | |
8440 Dynarr_reset (cache); | |
8441 | |
8442 /* #### What should really happen if what we are doing is | |
4187 | 8443 extending a line (the last line)? */ |
428 | 8444 if (Dynarr_length (cache) == 1 |
8445 && Dynarr_length (internal_cache) == 1) | |
8446 Dynarr_reset (cache); | |
8447 } | |
8448 | |
8449 if (!Dynarr_length (cache)) | |
8450 { | |
4967 | 8451 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8452 Dynarr_length (internal_cache)); |
8453 w->line_cache_validation_override--; | |
8454 return; | |
8455 } | |
8456 | |
8457 /* An extra check just in case the calling function didn't pass in | |
4187 | 8458 the bounds of the DESIRED structs in the first place. */ |
428 | 8459 if (start >= low_bound && end <= high_bound) |
8460 { | |
8461 w->line_cache_validation_override--; | |
8462 return; | |
8463 } | |
8464 | |
8465 /* At this point we know that the internal cache partially overlaps | |
4187 | 8466 the main cache. */ |
428 | 8467 if (start < low_bound) |
8468 { | |
8469 int ic_elt = Dynarr_length (internal_cache) - 1; | |
8470 while (ic_elt >= 0) | |
8471 { | |
8472 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound) | |
8473 break; | |
8474 else | |
8475 ic_elt--; | |
8476 } | |
8477 | |
8478 if (!(ic_elt >= 0)) | |
8479 { | |
8480 Dynarr_reset (cache); | |
4967 | 8481 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8482 Dynarr_length (internal_cache)); |
8483 w->line_cache_validation_override--; | |
8484 return; | |
8485 } | |
8486 | |
5038 | 8487 Dynarr_prepend_many (cache, Dynarr_begin (internal_cache), |
428 | 8488 ic_elt + 1); |
8489 } | |
8490 | |
8491 if (end > high_bound) | |
8492 { | |
8493 int ic_elt = 0; | |
8494 | |
8495 while (ic_elt < Dynarr_length (internal_cache)) | |
8496 { | |
8497 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound) | |
8498 break; | |
8499 else | |
8500 ic_elt++; | |
8501 } | |
8502 | |
8503 if (!(ic_elt < Dynarr_length (internal_cache))) | |
8504 { | |
8505 Dynarr_reset (cache); | |
4967 | 8506 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8507 Dynarr_length (internal_cache)); |
8508 w->line_cache_validation_override--; | |
8509 return; | |
8510 } | |
8511 | |
8512 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), | |
8513 Dynarr_length (internal_cache) - ic_elt); | |
8514 } | |
8515 | |
8516 w->line_cache_validation_override--; | |
8517 return; | |
8518 } | |
8519 | |
8520 if (!Dynarr_length (cache) || from < low_bound) | |
8521 { | |
665 | 8522 Charbpos startp = find_next_newline_no_quit (b, from, -1); |
428 | 8523 int marker = 0; |
8524 int old_lb = low_bound; | |
8525 | |
8526 while (startp < old_lb || low_bound == -1) | |
8527 { | |
8528 int ic_elt; | |
4187 | 8529 Charbpos new_startp; |
428 | 8530 |
8531 regenerate_window (w, startp, point, CMOTION_DISP); | |
8532 update_internal_cache_list (w, CMOTION_DISP); | |
8533 | |
8534 /* If this assert is triggered then regenerate_window failed | |
4187 | 8535 to layout a single line. This is not possible since we |
442 | 8536 force at least a single line to be layout for CMOTION_DISP */ |
8537 assert (Dynarr_length (internal_cache)); | |
4967 | 8538 assert (startp == Dynarr_begin (internal_cache)->start); |
428 | 8539 |
8540 ic_elt = Dynarr_length (internal_cache) - 1; | |
8541 if (low_bound != -1) | |
8542 { | |
8543 while (ic_elt >= 0) | |
8544 { | |
8545 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb) | |
8546 break; | |
8547 else | |
8548 ic_elt--; | |
8549 } | |
8550 } | |
8551 assert (ic_elt >= 0); | |
8552 | |
8553 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1; | |
8554 | |
4187 | 8555 /* |
8556 * Handle invisible text properly: | |
8557 * If the last line we're inserting has the same end as the | |
8558 * line before which it will be added, merge the two lines. | |
8559 */ | |
8560 if (Dynarr_length (cache) && | |
8561 Dynarr_atp (internal_cache, ic_elt)->end == | |
8562 Dynarr_atp (cache, marker)->end) | |
8563 { | |
8564 Dynarr_atp (cache, marker)->start | |
8565 = Dynarr_atp (internal_cache, ic_elt)->start; | |
8566 Dynarr_atp (cache, marker)->height | |
8567 = Dynarr_atp (internal_cache, ic_elt)->height; | |
8568 ic_elt--; | |
8569 } | |
8570 | |
8571 if (ic_elt >= 0) /* we still have lines to add.. */ | |
8572 { | |
4967 | 8573 Dynarr_insert_many (cache, Dynarr_begin (internal_cache), |
4187 | 8574 ic_elt + 1, marker); |
8575 marker += (ic_elt + 1); | |
8576 } | |
428 | 8577 |
8578 if (startp < low_bound || low_bound == -1) | |
8579 low_bound = startp; | |
8580 startp = new_startp; | |
8581 if (startp > BUF_ZV (b)) | |
8582 { | |
8583 w->line_cache_validation_override--; | |
8584 return; | |
8585 } | |
8586 } | |
8587 } | |
8588 | |
8589 assert (Dynarr_length (cache)); | |
8590 assert (from >= low_bound); | |
8591 | |
8592 /* Readjust the high_bound to account for any changes made while | |
8593 correcting the low_bound. */ | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8594 high_bound = Dynarr_lastp (cache)->end; |
428 | 8595 |
8596 if (to > high_bound) | |
8597 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8598 Charbpos startp = Dynarr_lastp (cache)->end + 1; |
428 | 8599 |
8600 do | |
8601 { | |
8602 regenerate_window (w, startp, point, CMOTION_DISP); | |
8603 update_internal_cache_list (w, CMOTION_DISP); | |
8604 | |
8605 /* See comment above about regenerate_window failing. */ | |
8606 assert (Dynarr_length (internal_cache)); | |
8607 | |
4967 | 8608 Dynarr_add_many (cache, Dynarr_begin (internal_cache), |
428 | 8609 Dynarr_length (internal_cache)); |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8610 high_bound = Dynarr_lastp (cache)->end; |
428 | 8611 startp = high_bound + 1; |
8612 } | |
8613 while (to > high_bound); | |
8614 } | |
8615 | |
8616 w->line_cache_validation_override--; | |
8617 assert (to <= high_bound); | |
8618 } | |
8619 | |
8620 | |
8621 /* Given x and y coordinates in characters, relative to a window, | |
8622 return the pixel location corresponding to those coordinates. The | |
8623 pixel location returned is the center of the given character | |
8624 position. The pixel values are generated relative to the window, | |
8625 not the frame. | |
8626 | |
8627 The modeline is considered to be part of the window. */ | |
8628 | |
8629 void | |
8630 glyph_to_pixel_translation (struct window *w, int char_x, int char_y, | |
8631 int *pix_x, int *pix_y) | |
8632 { | |
8633 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
8634 int num_disp_lines, modeline; | |
8635 Lisp_Object window; | |
8636 int defheight, defwidth; | |
8637 | |
793 | 8638 window = wrap_window (w); |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
8639 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 8640 |
8641 /* If we get a bogus value indicating somewhere above or to the left of | |
8642 the window, use the first window line or character position | |
8643 instead. */ | |
8644 if (char_y < 0) | |
8645 char_y = 0; | |
8646 if (char_x < 0) | |
8647 char_x = 0; | |
8648 | |
8649 num_disp_lines = Dynarr_length (dla); | |
8650 modeline = 0; | |
8651 if (num_disp_lines) | |
8652 { | |
4967 | 8653 if (Dynarr_begin (dla)->modeline) |
428 | 8654 { |
8655 num_disp_lines--; | |
8656 modeline = 1; | |
8657 } | |
8658 } | |
8659 | |
8660 /* First check if the y position intersects the display lines. */ | |
8661 if (char_y < num_disp_lines) | |
8662 { | |
8663 struct display_line *dl = Dynarr_atp (dla, char_y + modeline); | |
8664 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
8665 | |
8666 *pix_y = (dl->ypos - dl->ascent + | |
647 | 8667 ((dl->ascent + dl->descent - dl->clip) >> 1)); |
428 | 8668 |
8669 if (char_x < Dynarr_length (db->runes)) | |
8670 { | |
8671 struct rune *rb = Dynarr_atp (db->runes, char_x); | |
8672 | |
8673 *pix_x = rb->xpos + (rb->width >> 1); | |
8674 } | |
8675 else | |
8676 { | |
8677 int last_rune = Dynarr_length (db->runes) - 1; | |
8678 struct rune *rb = Dynarr_atp (db->runes, last_rune); | |
8679 | |
8680 char_x -= last_rune; | |
8681 | |
8682 *pix_x = rb->xpos + rb->width; | |
8683 *pix_x += ((char_x - 1) * defwidth); | |
8684 *pix_x += (defwidth >> 1); | |
8685 } | |
8686 } | |
8687 else | |
8688 { | |
8689 /* It didn't intersect, so extrapolate. #### For now, we include the | |
8690 modeline in this since we don't have true character positions in | |
8691 it. */ | |
8692 | |
8693 if (!Dynarr_length (w->face_cachels)) | |
8694 reset_face_cachels (w); | |
8695 | |
8696 char_y -= num_disp_lines; | |
8697 | |
8698 if (Dynarr_length (dla)) | |
8699 { | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
8700 struct display_line *dl = Dynarr_lastp (dla); |
428 | 8701 *pix_y = dl->ypos + dl->descent - dl->clip; |
8702 } | |
8703 else | |
8704 *pix_y = WINDOW_TEXT_TOP (w); | |
8705 | |
8706 *pix_y += (char_y * defheight); | |
8707 *pix_y += (defheight >> 1); | |
8708 | |
8709 *pix_x = WINDOW_TEXT_LEFT (w); | |
8710 /* Don't adjust by one because this is still the unadjusted value. */ | |
8711 *pix_x += (char_x * defwidth); | |
8712 *pix_x += (defwidth >> 1); | |
8713 } | |
8714 | |
8715 if (*pix_x > w->pixel_left + w->pixel_width) | |
8716 *pix_x = w->pixel_left + w->pixel_width; | |
8717 if (*pix_y > w->pixel_top + w->pixel_height) | |
8718 *pix_y = w->pixel_top + w->pixel_height; | |
8719 | |
8720 *pix_x -= w->pixel_left; | |
8721 *pix_y -= w->pixel_top; | |
8722 } | |
8723 | |
8724 /* Given a display line and a position, determine if there is a glyph | |
8725 there and return information about it if there is. */ | |
8726 | |
8727 static void | |
8728 get_position_object (struct display_line *dl, Lisp_Object *obj1, | |
8729 Lisp_Object *obj2, int x_coord, int *low_x_coord, | |
8730 int *high_x_coord) | |
8731 { | |
8732 struct display_block *db; | |
8733 int elt; | |
8734 int block = | |
8735 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0); | |
8736 | |
8737 /* We use get_next_display_block to get the actual display block | |
8738 that would be displayed at x_coord. */ | |
8739 | |
8740 if (block == NO_BLOCK) | |
8741 return; | |
8742 else | |
8743 db = Dynarr_atp (dl->display_blocks, block); | |
8744 | |
8745 for (elt = 0; elt < Dynarr_length (db->runes); elt++) | |
8746 { | |
8747 struct rune *rb = Dynarr_atp (db->runes, elt); | |
8748 | |
8749 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) | |
8750 { | |
8751 if (rb->type == RUNE_DGLYPH) | |
8752 { | |
8753 *obj1 = rb->object.dglyph.glyph; | |
8754 *obj2 = rb->object.dglyph.extent; | |
8755 } | |
8756 else | |
8757 { | |
8758 *obj1 = Qnil; | |
8759 *obj2 = Qnil; | |
8760 } | |
8761 | |
8762 if (low_x_coord) | |
8763 *low_x_coord = rb->xpos; | |
8764 if (high_x_coord) | |
8765 *high_x_coord = rb->xpos + rb->width; | |
8766 | |
8767 return; | |
8768 } | |
8769 } | |
8770 } | |
8771 | |
8772 #define UPDATE_CACHE_RETURN \ | |
8773 do { \ | |
8774 d->pixel_to_glyph_cache.valid = 1; \ | |
8775 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \ | |
8776 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \ | |
8777 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \ | |
8778 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \ | |
8779 d->pixel_to_glyph_cache.frame = f; \ | |
8780 d->pixel_to_glyph_cache.col = *col; \ | |
8781 d->pixel_to_glyph_cache.row = *row; \ | |
8782 d->pixel_to_glyph_cache.obj_x = *obj_x; \ | |
8783 d->pixel_to_glyph_cache.obj_y = *obj_y; \ | |
8784 d->pixel_to_glyph_cache.w = *w; \ | |
5090 | 8785 d->pixel_to_glyph_cache.charpos = *charpos; \ |
428 | 8786 d->pixel_to_glyph_cache.closest = *closest; \ |
8787 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \ | |
8788 d->pixel_to_glyph_cache.obj1 = *obj1; \ | |
8789 d->pixel_to_glyph_cache.obj2 = *obj2; \ | |
8790 d->pixel_to_glyph_cache.retval = position; \ | |
8791 RETURN_SANS_WARNINGS position; \ | |
8792 } while (0) | |
8793 | |
8794 /* Given x and y coordinates in pixels relative to a frame, return | |
8795 information about what is located under those coordinates. | |
8796 | |
8797 The return value will be one of: | |
8798 | |
8799 OVER_TOOLBAR: over one of the 4 frame toolbars | |
8800 OVER_MODELINE: over a modeline | |
8801 OVER_BORDER: over an internal border | |
5090 | 8802 OVER_V_DIVIDER: over a vertical divider between windows (used as a |
8803 grab bar for resizing) | |
428 | 8804 OVER_NOTHING: over the text area, but not over text |
8805 OVER_OUTSIDE: outside of the frame border | |
8806 OVER_TEXT: over text in the text area | |
8807 | |
5090 | 8808 #### GEOM! We need to also have an OVER_GUTTER, OVER_SCROLLBAR and |
8809 OVER_DEAD_BOX. | |
8810 | |
428 | 8811 OBJ1 is one of |
8812 | |
8813 -- a toolbar button | |
8814 -- a glyph | |
8815 -- nil if the coordinates are not over a glyph or a toolbar button. | |
8816 | |
8817 OBJ2 is one of | |
8818 | |
8819 -- an extent, if the coordinates are over a glyph in the text area | |
8820 -- nil otherwise. | |
8821 | |
8822 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the | |
8823 equivalent coordinates relative to the upper-left corner of the glyph. | |
8824 | |
8825 If the coordinates are over a character, OBJ_X and OBJ_Y give the | |
8826 equivalent coordinates relative to the upper-left corner of the character. | |
8827 | |
8828 Otherwise, OBJ_X and OBJ_Y are undefined. | |
8829 */ | |
8830 | |
8831 int | |
8832 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, | |
8833 int *col, int *row, int *obj_x, int *obj_y, | |
826 | 8834 struct window **w, Charbpos *charpos, |
665 | 8835 Charbpos *closest, Charcount *modeline_closest, |
428 | 8836 Lisp_Object *obj1, Lisp_Object *obj2) |
8837 { | |
8838 struct device *d; | |
8839 struct pixel_to_glyph_translation_cache *cache; | |
8840 Lisp_Object window; | |
8841 int frm_left, frm_right, frm_top, frm_bottom; | |
8842 int low_x_coord, high_x_coord, low_y_coord, high_y_coord; | |
8843 int position = OVER_NOTHING; | |
8844 int device_check_failed = 0; | |
8845 display_line_dynarr *dla; | |
8846 | |
8847 /* This is a safety valve in case this got called with a frame in | |
8848 the middle of being deleted. */ | |
8849 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device))) | |
8850 { | |
8851 device_check_failed = 1; | |
8852 d = NULL, cache = NULL; /* Warning suppression */ | |
8853 } | |
8854 else | |
8855 { | |
8856 d = XDEVICE (f->device); | |
8857 cache = &d->pixel_to_glyph_cache; | |
8858 } | |
8859 | |
8860 if (!device_check_failed | |
8861 && cache->valid | |
8862 && cache->frame == f | |
8863 && cache->low_x_coord <= x_coord | |
8864 && cache->high_x_coord > x_coord | |
8865 && cache->low_y_coord <= y_coord | |
8866 && cache->high_y_coord > y_coord) | |
8867 { | |
8868 *col = cache->col; | |
8869 *row = cache->row; | |
8870 *obj_x = cache->obj_x; | |
8871 *obj_y = cache->obj_y; | |
8872 *w = cache->w; | |
826 | 8873 *charpos = cache->charpos; |
428 | 8874 *closest = cache->closest; |
8875 *modeline_closest = cache->modeline_closest; | |
8876 *obj1 = cache->obj1; | |
8877 *obj2 = cache->obj2; | |
8878 | |
8879 return cache->retval; | |
8880 } | |
8881 else | |
8882 { | |
8883 *col = 0; | |
8884 *row = 0; | |
8885 *obj_x = 0; | |
8886 *obj_y = 0; | |
8887 *w = 0; | |
826 | 8888 *charpos = 0; |
428 | 8889 *closest = 0; |
8890 *modeline_closest = -1; | |
8891 *obj1 = Qnil; | |
8892 *obj2 = Qnil; | |
8893 | |
8894 low_x_coord = x_coord; | |
8895 high_x_coord = x_coord + 1; | |
8896 low_y_coord = y_coord; | |
8897 high_y_coord = y_coord + 1; | |
8898 } | |
8899 | |
8900 if (device_check_failed) | |
8901 return OVER_NOTHING; | |
8902 | |
5090 | 8903 /* #### GEOM! The gutter is just inside of this. We should also have an |
8904 OVER_GUTTER return value to indicate that we're over a gutter. See | |
8905 above. */ | |
8906 frm_left = FRAME_LEFT_INTERNAL_BORDER_END (f); | |
8907 frm_right = FRAME_RIGHT_INTERNAL_BORDER_START (f); | |
8908 frm_top = FRAME_TOP_INTERNAL_BORDER_END (f); | |
8909 frm_bottom = FRAME_BOTTOM_INTERNAL_BORDER_START (f); | |
428 | 8910 |
8911 /* Check if the mouse is outside of the text area actually used by | |
8912 redisplay. */ | |
8913 if (y_coord < frm_top) | |
8914 { | |
5090 | 8915 if (y_coord >= FRAME_TOP_INTERNAL_BORDER_START (f)) |
8916 { | |
8917 low_y_coord = FRAME_TOP_INTERNAL_BORDER_START (f); | |
428 | 8918 high_y_coord = frm_top; |
8919 position = OVER_BORDER; | |
8920 } | |
8921 else if (y_coord >= 0) | |
8922 { | |
8923 low_y_coord = 0; | |
5090 | 8924 high_y_coord = FRAME_TOP_INTERNAL_BORDER_START (f); |
428 | 8925 position = OVER_TOOLBAR; |
8926 } | |
8927 else | |
8928 { | |
8929 low_y_coord = y_coord; | |
8930 high_y_coord = 0; | |
8931 position = OVER_OUTSIDE; | |
8932 } | |
8933 } | |
8934 else if (y_coord >= frm_bottom) | |
8935 { | |
5090 | 8936 if (y_coord < FRAME_BOTTOM_INTERNAL_BORDER_END (f)) |
428 | 8937 { |
8938 low_y_coord = frm_bottom; | |
5090 | 8939 high_y_coord = FRAME_BOTTOM_INTERNAL_BORDER_END (f); |
428 | 8940 position = OVER_BORDER; |
8941 } | |
8942 else if (y_coord < FRAME_PIXHEIGHT (f)) | |
8943 { | |
5090 | 8944 low_y_coord = FRAME_BOTTOM_INTERNAL_BORDER_END (f); |
428 | 8945 high_y_coord = FRAME_PIXHEIGHT (f); |
8946 position = OVER_TOOLBAR; | |
8947 } | |
8948 else | |
8949 { | |
8950 low_y_coord = FRAME_PIXHEIGHT (f); | |
8951 high_y_coord = y_coord; | |
8952 position = OVER_OUTSIDE; | |
8953 } | |
8954 } | |
8955 | |
8956 if (position != OVER_TOOLBAR && position != OVER_BORDER) | |
8957 { | |
8958 if (x_coord < frm_left) | |
8959 { | |
5090 | 8960 if (x_coord >= FRAME_LEFT_INTERNAL_BORDER_START (f)) |
8961 { | |
8962 low_x_coord = FRAME_LEFT_INTERNAL_BORDER_START (f); | |
428 | 8963 high_x_coord = frm_left; |
8964 position = OVER_BORDER; | |
8965 } | |
8966 else if (x_coord >= 0) | |
8967 { | |
8968 low_x_coord = 0; | |
5090 | 8969 high_x_coord = FRAME_LEFT_INTERNAL_BORDER_START (f); |
428 | 8970 position = OVER_TOOLBAR; |
8971 } | |
8972 else | |
8973 { | |
8974 low_x_coord = x_coord; | |
8975 high_x_coord = 0; | |
8976 position = OVER_OUTSIDE; | |
8977 } | |
8978 } | |
8979 else if (x_coord >= frm_right) | |
8980 { | |
5090 | 8981 if (x_coord < FRAME_RIGHT_INTERNAL_BORDER_END (f)) |
428 | 8982 { |
8983 low_x_coord = frm_right; | |
5090 | 8984 high_x_coord = FRAME_RIGHT_INTERNAL_BORDER_END (f); |
428 | 8985 position = OVER_BORDER; |
8986 } | |
8987 else if (x_coord < FRAME_PIXWIDTH (f)) | |
8988 { | |
5090 | 8989 low_x_coord = FRAME_RIGHT_INTERNAL_BORDER_END (f); |
428 | 8990 high_x_coord = FRAME_PIXWIDTH (f); |
8991 position = OVER_TOOLBAR; | |
8992 } | |
8993 else | |
8994 { | |
8995 low_x_coord = FRAME_PIXWIDTH (f); | |
8996 high_x_coord = x_coord; | |
8997 position = OVER_OUTSIDE; | |
8998 } | |
8999 } | |
9000 } | |
9001 | |
9002 #ifdef HAVE_TOOLBARS | |
9003 if (position == OVER_TOOLBAR) | |
9004 { | |
9005 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord); | |
9006 *obj2 = Qnil; | |
9007 *w = 0; | |
9008 UPDATE_CACHE_RETURN; | |
9009 } | |
9010 #endif /* HAVE_TOOLBARS */ | |
9011 | |
9012 /* We still have to return the window the pointer is next to and its | |
9013 relative y position even if it is outside the x boundary. */ | |
9014 if (x_coord < frm_left) | |
9015 x_coord = frm_left; | |
9016 else if (x_coord > frm_right) | |
9017 x_coord = frm_right; | |
9018 | |
9019 /* Same in reverse. */ | |
9020 if (y_coord < frm_top) | |
9021 y_coord = frm_top; | |
9022 else if (y_coord > frm_bottom) | |
9023 y_coord = frm_bottom; | |
9024 | |
9025 /* Find what window the given coordinates are actually in. */ | |
9026 window = f->root_window; | |
9027 *w = find_window_by_pixel_pos (x_coord, y_coord, window); | |
9028 | |
9029 /* If we didn't find a window, we're done. */ | |
9030 if (!*w) | |
9031 { | |
9032 UPDATE_CACHE_RETURN; | |
9033 } | |
9034 else if (position != OVER_NOTHING) | |
9035 { | |
9036 *closest = 0; | |
9037 *modeline_closest = -1; | |
9038 | |
9039 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) | |
9040 { | |
9041 *w = 0; | |
9042 UPDATE_CACHE_RETURN; | |
9043 } | |
9044 } | |
9045 | |
9046 /* Check if the window is a minibuffer but isn't active. */ | |
9047 if (MINI_WINDOW_P (*w) && !minibuf_level) | |
9048 { | |
9049 /* Must reset the window value since some callers will ignore | |
4187 | 9050 the return value if it is set. */ |
428 | 9051 *w = 0; |
9052 UPDATE_CACHE_RETURN; | |
9053 } | |
9054 | |
9055 /* See if the point is over window vertical divider */ | |
9056 if (window_needs_vertical_divider (*w)) | |
9057 { | |
9058 int div_x_high = WINDOW_RIGHT (*w); | |
9059 int div_x_low = div_x_high - window_divider_width (*w); | |
9060 int div_y_high = WINDOW_BOTTOM (*w); | |
9061 int div_y_low = WINDOW_TOP (*w); | |
9062 | |
9063 if (div_x_low < x_coord && x_coord <= div_x_high && | |
9064 div_y_low < y_coord && y_coord <= div_y_high) | |
9065 { | |
9066 low_x_coord = div_x_low; | |
9067 high_x_coord = div_x_high; | |
9068 low_y_coord = div_y_low; | |
9069 high_y_coord = div_y_high; | |
9070 position = OVER_V_DIVIDER; | |
9071 UPDATE_CACHE_RETURN; | |
9072 } | |
9073 } | |
9074 | |
9075 dla = window_display_lines (*w, CURRENT_DISP); | |
9076 | |
9077 for (*row = 0; *row < Dynarr_length (dla); (*row)++) | |
9078 { | |
9079 int really_over_nothing = 0; | |
9080 struct display_line *dl = Dynarr_atp (dla, *row); | |
9081 | |
9082 if ((int) (dl->ypos - dl->ascent) <= y_coord | |
9083 && y_coord <= (int) (dl->ypos + dl->descent)) | |
9084 { | |
9085 int check_margin_glyphs = 0; | |
9086 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
9087 struct rune *rb = 0; | |
9088 | |
9089 if (x_coord < dl->bounds.left_white | |
9090 || x_coord >= dl->bounds.right_white) | |
9091 check_margin_glyphs = 1; | |
9092 | |
9093 low_y_coord = dl->ypos - dl->ascent; | |
9094 high_y_coord = dl->ypos + dl->descent + 1; | |
9095 | |
9096 if (position == OVER_BORDER | |
9097 || position == OVER_OUTSIDE | |
9098 || check_margin_glyphs) | |
9099 { | |
9100 int x_check, left_bound; | |
9101 | |
9102 if (check_margin_glyphs) | |
9103 { | |
9104 x_check = x_coord; | |
9105 left_bound = dl->bounds.left_white; | |
9106 } | |
9107 else | |
9108 { | |
9109 x_check = high_x_coord; | |
9110 left_bound = frm_left; | |
9111 } | |
9112 | |
9113 if (Dynarr_length (db->runes)) | |
9114 { | |
9115 if (x_check <= left_bound) | |
9116 { | |
9117 if (dl->modeline) | |
4967 | 9118 *modeline_closest = Dynarr_begin (db->runes)->charpos; |
428 | 9119 else |
4967 | 9120 *closest = Dynarr_begin (db->runes)->charpos; |
428 | 9121 } |
9122 else | |
9123 { | |
9124 if (dl->modeline) | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9125 *modeline_closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9126 else |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4815
diff
changeset
|
9127 *closest = Dynarr_lastp (db->runes)->charpos; |
428 | 9128 } |
9129 | |
9130 if (dl->modeline) | |
9131 *modeline_closest += dl->offset; | |
9132 else | |
9133 *closest += dl->offset; | |
9134 } | |
9135 else | |
9136 { | |
9137 /* #### What should be here. */ | |
9138 if (dl->modeline) | |
9139 *modeline_closest = 0; | |
9140 else | |
9141 *closest = 0; | |
9142 } | |
9143 | |
9144 if (check_margin_glyphs) | |
9145 { | |
9146 if (x_coord < dl->bounds.left_in | |
9147 || x_coord >= dl->bounds.right_in) | |
9148 { | |
9149 /* If we are over the outside margins then we | |
4187 | 9150 know the loop over the text block isn't going |
9151 to accomplish anything. So we go ahead and | |
9152 set what information we can right here and | |
9153 return. */ | |
428 | 9154 (*row)--; |
9155 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9156 get_position_object (dl, obj1, obj2, x_coord, | |
9157 &low_x_coord, &high_x_coord); | |
9158 | |
9159 UPDATE_CACHE_RETURN; | |
9160 } | |
9161 } | |
9162 else | |
9163 UPDATE_CACHE_RETURN; | |
9164 } | |
9165 | |
9166 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++) | |
9167 { | |
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9168 if (*col == Dynarr_length (db->runes)) |
428 | 9169 { |
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9170 /* We've run out of runes to look at. Treat the same as |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9171 the case below where we failed to find a non-glyph |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9172 character. */ |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9173 if (dl->modeline) |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9174 *modeline_closest = dl->end_charpos + dl->offset; |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9175 else |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9176 *closest = dl->end_charpos + dl->offset; |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9177 |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9178 if (check_margin_glyphs) |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9179 get_position_object (dl, obj1, obj2, x_coord, |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9180 &low_x_coord, &high_x_coord); |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9181 |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9182 UPDATE_CACHE_RETURN; |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9183 } |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9184 |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9185 rb = Dynarr_atp (db->runes, *col); |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9186 |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9187 if (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width) |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9188 { |
428 | 9189 |
826 | 9190 *charpos = rb->charpos + dl->offset; |
428 | 9191 low_x_coord = rb->xpos; |
9192 high_x_coord = rb->xpos + rb->width; | |
9193 | |
9194 if (rb->type == RUNE_DGLYPH) | |
9195 { | |
9196 int elt = *col + 1; | |
9197 | |
9198 /* Find the first character after the glyph. */ | |
9199 while (elt < Dynarr_length (db->runes)) | |
9200 { | |
9201 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH) | |
9202 { | |
9203 if (dl->modeline) | |
9204 *modeline_closest = | |
826 | 9205 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9206 dl->offset); |
9207 else | |
9208 *closest = | |
826 | 9209 (Dynarr_atp (db->runes, elt)->charpos + |
428 | 9210 dl->offset); |
9211 break; | |
9212 } | |
9213 | |
9214 elt++; | |
9215 } | |
9216 | |
9217 /* In this case we failed to find a non-glyph | |
4187 | 9218 character so we return the last position |
9219 displayed on the line. */ | |
428 | 9220 if (elt == Dynarr_length (db->runes)) |
9221 { | |
9222 if (dl->modeline) | |
826 | 9223 *modeline_closest = dl->end_charpos + dl->offset; |
428 | 9224 else |
826 | 9225 *closest = dl->end_charpos + dl->offset; |
428 | 9226 really_over_nothing = 1; |
9227 } | |
9228 } | |
9229 else | |
9230 { | |
9231 if (dl->modeline) | |
826 | 9232 *modeline_closest = rb->charpos + dl->offset; |
428 | 9233 else |
826 | 9234 *closest = rb->charpos + dl->offset; |
428 | 9235 } |
9236 | |
9237 if (dl->modeline) | |
9238 { | |
9239 *row = window_displayed_height (*w); | |
9240 | |
9241 if (position == OVER_NOTHING) | |
9242 position = OVER_MODELINE; | |
9243 | |
9244 if (rb->type == RUNE_DGLYPH) | |
9245 { | |
9246 *obj1 = rb->object.dglyph.glyph; | |
9247 *obj2 = rb->object.dglyph.extent; | |
9248 } | |
9249 else if (rb->type == RUNE_CHAR) | |
9250 { | |
9251 *obj1 = Qnil; | |
9252 *obj2 = Qnil; | |
9253 } | |
9254 else | |
9255 { | |
9256 *obj1 = Qnil; | |
9257 *obj2 = Qnil; | |
9258 } | |
9259 | |
9260 UPDATE_CACHE_RETURN; | |
9261 } | |
5486
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9262 else if (rb->type == RUNE_CHAR |
58e320bde005
Handle redisplay edge case.
Mike Kupfer <mike.kupfer@xemacs.org>
parents:
5470
diff
changeset
|
9263 && rb->object.chr.ch == '\n') |
428 | 9264 { |
9265 (*row)--; | |
9266 /* At this point we may have glyphs in the right | |
4187 | 9267 inside margin. */ |
428 | 9268 if (check_margin_glyphs) |
9269 get_position_object (dl, obj1, obj2, x_coord, | |
9270 &low_x_coord, &high_x_coord); | |
9271 UPDATE_CACHE_RETURN; | |
9272 } | |
9273 else | |
9274 { | |
9275 (*row)--; | |
9276 if (rb->type == RUNE_DGLYPH) | |
9277 { | |
9278 *obj1 = rb->object.dglyph.glyph; | |
9279 *obj2 = rb->object.dglyph.extent; | |
9280 } | |
9281 else if (rb->type == RUNE_CHAR) | |
9282 { | |
9283 *obj1 = Qnil; | |
9284 *obj2 = Qnil; | |
9285 } | |
9286 else | |
9287 { | |
9288 *obj1 = Qnil; | |
9289 *obj2 = Qnil; | |
9290 } | |
9291 | |
9292 *obj_x = x_coord - rb->xpos; | |
9293 *obj_y = y_coord - (dl->ypos - dl->ascent); | |
9294 | |
9295 /* At this point we may have glyphs in the left | |
4187 | 9296 inside margin. */ |
428 | 9297 if (check_margin_glyphs) |
9298 get_position_object (dl, obj1, obj2, x_coord, 0, 0); | |
9299 | |
9300 if (position == OVER_NOTHING && !really_over_nothing) | |
9301 position = OVER_TEXT; | |
9302 | |
9303 UPDATE_CACHE_RETURN; | |
9304 } | |
9305 } | |
9306 } | |
9307 } | |
9308 } | |
9309 | |
9310 *row = Dynarr_length (dla) - 1; | |
9311 if (FRAME_WIN_P (f)) | |
9312 { | |
9313 int bot_elt = Dynarr_length (dla) - 1; | |
9314 | |
9315 if (bot_elt >= 0) | |
9316 { | |
9317 struct display_line *dl = Dynarr_atp (dla, bot_elt); | |
9318 int adj_area = y_coord - (dl->ypos + dl->descent); | |
9319 Lisp_Object lwin; | |
9320 int defheight; | |
9321 | |
793 | 9322 lwin = wrap_window (*w); |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
9323 default_face_width_and_height (lwin, 0, &defheight); |
428 | 9324 |
9325 *row += (adj_area / defheight); | |
9326 } | |
9327 } | |
9328 | |
9329 /* #### This should be checked out some more to determine what | |
9330 should really be going on. */ | |
9331 if (!MARKERP ((*w)->start[CURRENT_DISP])) | |
9332 *closest = 0; | |
9333 else | |
442 | 9334 *closest = end_of_last_line_may_error (*w, |
428 | 9335 marker_position ((*w)->start[CURRENT_DISP])); |
9336 *col = 0; | |
9337 UPDATE_CACHE_RETURN; | |
9338 } | |
9339 #undef UPDATE_CACHE_RETURN | |
9340 | |
9341 | |
9342 /***************************************************************************/ | |
9343 /* */ | |
9344 /* Lisp functions */ | |
9345 /* */ | |
9346 /***************************************************************************/ | |
9347 | |
9348 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /* | |
9349 Ensure that all minibuffers are correctly showing the echo area. | |
9350 */ | |
9351 ()) | |
9352 { | |
9353 Lisp_Object devcons, concons; | |
9354 | |
1318 | 9355 if (in_display) |
9356 return Qnil; | |
9357 | |
428 | 9358 DEVICE_LOOP_NO_BREAK (devcons, concons) |
9359 { | |
9360 struct device *d = XDEVICE (XCAR (devcons)); | |
9361 Lisp_Object frmcons; | |
9362 | |
1279 | 9363 if (DEVICE_STREAM_P (d)) |
9364 continue; | |
9365 | |
428 | 9366 DEVICE_FRAME_LOOP (frmcons, d) |
9367 { | |
9368 struct frame *f = XFRAME (XCAR (frmcons)); | |
853 | 9369 int depth; |
428 | 9370 |
9371 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) | |
9372 { | |
9373 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); | |
442 | 9374 |
9375 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
9376 | |
428 | 9377 /* |
9378 * If the frame size has changed, there may be random | |
9379 * chud on the screen left from previous messages | |
9380 * because redisplay_frame hasn't been called yet. | |
9381 * Clear the screen to get rid of the potential mess. | |
9382 */ | |
9383 if (f->echo_area_garbaged) | |
9384 { | |
442 | 9385 MAYBE_DEVMETH (d, clear_frame, (f)); |
428 | 9386 f->echo_area_garbaged = 0; |
9387 } | |
853 | 9388 depth = enter_redisplay_critical_section (); |
428 | 9389 redisplay_window (window, 0); |
853 | 9390 exit_redisplay_critical_section (depth); |
442 | 9391 MAYBE_DEVMETH (d, frame_output_end, (f)); |
428 | 9392 } |
9393 } | |
9394 } | |
9395 | |
9396 return Qnil; | |
9397 } | |
9398 | |
9399 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /* | |
9400 Clear frame FRAME and output again what is supposed to appear on it. | |
9401 FRAME defaults to the selected frame if omitted. | |
9402 Normally, redisplay is preempted as normal if input arrives. However, | |
9403 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9404 input and is guaranteed to proceed to completion. | |
9405 */ | |
9406 (frame, no_preempt)) | |
9407 { | |
9408 struct frame *f = decode_frame (frame); | |
9409 int count = specpdl_depth (); | |
9410 | |
9411 if (!NILP (no_preempt)) | |
853 | 9412 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9413 |
9414 f->clear = 1; | |
9415 redisplay_frame (f, 1); | |
9416 | |
442 | 9417 /* See the comment in Fredisplay_frame. */ |
9418 RESET_CHANGED_SET_FLAGS; | |
9419 | |
771 | 9420 return unbind_to (count); |
428 | 9421 } |
9422 | |
9423 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* | |
9424 Ensure that FRAME's contents are correctly displayed. | |
9425 This differs from `redraw-frame' in that it only redraws what needs to | |
9426 be updated, as opposed to unconditionally clearing and redrawing | |
9427 the frame. | |
9428 FRAME defaults to the selected frame if omitted. | |
9429 Normally, redisplay is preempted as normal if input arrives. However, | |
9430 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9431 input and is guaranteed to proceed to completion. | |
9432 */ | |
9433 (frame, no_preempt)) | |
9434 { | |
9435 struct frame *f = decode_frame (frame); | |
9436 int count = specpdl_depth (); | |
9437 | |
9438 if (!NILP (no_preempt)) | |
853 | 9439 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9440 |
9441 redisplay_frame (f, 1); | |
9442 | |
442 | 9443 /* If we don't reset the global redisplay flags here, subsequent |
9444 changes to the display will not get registered by redisplay | |
9445 because it thinks it already has registered changes. If you | |
9446 really knew what you were doing you could confuse redisplay by | |
9447 calling Fredisplay_frame while updating another frame. We assume | |
9448 that if you know what you are doing you will not be that | |
9449 stupid. */ | |
9450 RESET_CHANGED_SET_FLAGS; | |
9451 | |
771 | 9452 return unbind_to (count); |
428 | 9453 } |
9454 | |
9455 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* | |
9456 Clear device DEVICE and output again what is supposed to appear on it. | |
9457 DEVICE defaults to the selected device if omitted. | |
9458 Normally, redisplay is preempted as normal if input arrives. However, | |
9459 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9460 input and is guaranteed to proceed to completion. | |
9461 */ | |
9462 (device, no_preempt)) | |
9463 { | |
9464 struct device *d = decode_device (device); | |
9465 Lisp_Object frmcons; | |
9466 int count = specpdl_depth (); | |
9467 | |
9468 if (!NILP (no_preempt)) | |
853 | 9469 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9470 |
9471 DEVICE_FRAME_LOOP (frmcons, d) | |
9472 { | |
9473 XFRAME (XCAR (frmcons))->clear = 1; | |
9474 } | |
440 | 9475 redisplay_device (d, 0); |
428 | 9476 |
442 | 9477 /* See the comment in Fredisplay_frame. */ |
9478 RESET_CHANGED_SET_FLAGS; | |
9479 | |
771 | 9480 return unbind_to (count); |
428 | 9481 } |
9482 | |
9483 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* | |
9484 Ensure that DEVICE's contents are correctly displayed. | |
9485 This differs from `redraw-device' in that it only redraws what needs to | |
9486 be updated, as opposed to unconditionally clearing and redrawing | |
9487 the device. | |
9488 DEVICE defaults to the selected device if omitted. | |
9489 Normally, redisplay is preempted as normal if input arrives. However, | |
9490 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for | |
9491 input and is guaranteed to proceed to completion. | |
853 | 9492 |
9493 Note: If you simply want everything redisplayed, the current idiom is | |
9494 `(sit-for 0)'. | |
428 | 9495 */ |
9496 (device, no_preempt)) | |
9497 { | |
9498 struct device *d = decode_device (device); | |
9499 int count = specpdl_depth (); | |
9500 | |
9501 if (!NILP (no_preempt)) | |
853 | 9502 internal_bind_int (&disable_preemption, 1 + disable_preemption); |
428 | 9503 |
440 | 9504 redisplay_device (d, 0); |
428 | 9505 |
442 | 9506 /* See the comment in Fredisplay_frame. */ |
9507 RESET_CHANGED_SET_FLAGS; | |
9508 | |
771 | 9509 return unbind_to (count); |
428 | 9510 } |
9511 | |
9512 /* Big lie. Big lie. This will force all modelines to be updated | |
9513 regardless if the all flag is set or not. It remains in existence | |
9514 solely for backwards compatibility. */ | |
9515 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /* | |
9516 Force the modeline of the current buffer to be redisplayed. | |
9517 With optional non-nil ALL, force redisplay of all modelines. | |
9518 */ | |
2286 | 9519 (UNUSED (all))) |
428 | 9520 { |
9521 MARK_MODELINE_CHANGED; | |
9522 return Qnil; | |
9523 } | |
9524 | |
9525 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /* | |
9526 Force an immediate update of the cursor on FRAME. | |
9527 FRAME defaults to the selected frame if omitted. | |
9528 */ | |
9529 (frame)) | |
9530 { | |
1279 | 9531 struct frame *f = decode_frame (frame); |
9532 | |
9533 if (!FRAME_STREAM_P (f)) | |
9534 redisplay_redraw_cursor (f, 1); | |
428 | 9535 return Qnil; |
9536 } | |
9537 | |
9538 | |
9539 /***************************************************************************/ | |
9540 /* */ | |
872 | 9541 /* Change flags */ |
428 | 9542 /* */ |
9543 /***************************************************************************/ | |
9544 | |
9545 static void | |
2286 | 9546 margin_width_changed_in_frame (Lisp_Object UNUSED (specifier), |
9547 struct frame *UNUSED (f), | |
9548 Lisp_Object UNUSED (oldval)) | |
428 | 9549 { |
9550 /* Nothing to be done? */ | |
9551 } | |
9552 | |
9553 int | |
2286 | 9554 redisplay_variable_changed (Lisp_Object UNUSED (sym), |
9555 Lisp_Object *UNUSED (val), | |
9556 Lisp_Object UNUSED (in_object), | |
9557 int UNUSED (flags)) | |
428 | 9558 { |
9559 /* #### clip_changed should really be renamed something like | |
9560 global_redisplay_change. */ | |
9561 MARK_CLIP_CHANGED; | |
9562 return 0; | |
9563 } | |
9564 | |
9565 /* This is called if the built-in glyphs have their properties | |
9566 changed. */ | |
9567 void | |
2286 | 9568 redisplay_glyph_changed (Lisp_Object UNUSED (glyph), |
9569 Lisp_Object UNUSED (property), Lisp_Object locale) | |
428 | 9570 { |
9571 if (WINDOWP (locale)) | |
9572 { | |
9573 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale)))); | |
9574 } | |
9575 else if (FRAMEP (locale)) | |
9576 { | |
9577 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale)); | |
9578 } | |
9579 else if (DEVICEP (locale)) | |
9580 { | |
9581 Lisp_Object frmcons; | |
9582 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale)) | |
9583 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9584 } | |
9585 else if (CONSOLEP (locale)) | |
9586 { | |
9587 Lisp_Object frmcons, devcons; | |
9588 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale)) | |
9589 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9590 } | |
9591 else /* global or buffer */ | |
9592 { | |
9593 Lisp_Object frmcons, devcons, concons; | |
9594 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | |
9595 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons))); | |
9596 } | |
9597 } | |
9598 | |
9599 static void | |
2286 | 9600 text_cursor_visible_p_changed (Lisp_Object UNUSED (specifier), |
9601 struct window *w, Lisp_Object UNUSED (oldval)) | |
428 | 9602 { |
9603 if (XFRAME (w->frame)->init_finished) | |
9604 Fforce_cursor_redisplay (w->frame); | |
9605 } | |
9606 | |
872 | 9607 void |
9608 mark_buffers_changed (void) | |
9609 { | |
9610 MARK_TYPE_CHANGED (buffers); | |
9611 } | |
9612 | |
9613 void | |
9614 mark_clip_changed (void) | |
9615 { | |
9616 MARK_TYPE_CHANGED (clip); | |
9617 } | |
9618 | |
9619 void | |
9620 mark_extents_changed (void) | |
9621 { | |
9622 MARK_TYPE_CHANGED (extents); | |
9623 } | |
9624 | |
9625 void | |
9626 mark_icon_changed (void) | |
9627 { | |
9628 MARK_TYPE_CHANGED (icon); | |
9629 } | |
9630 | |
9631 void | |
9632 mark_menubar_changed (void) | |
9633 { | |
9634 MARK_TYPE_CHANGED (menubar); | |
9635 } | |
9636 | |
9637 void | |
9638 mark_modeline_changed (void) | |
9639 { | |
9640 MARK_TYPE_CHANGED (modeline); | |
9641 } | |
9642 | |
9643 void | |
9644 mark_point_changed (void) | |
9645 { | |
9646 MARK_TYPE_CHANGED (point); | |
9647 } | |
9648 | |
9649 void | |
9650 mark_toolbar_changed (void) | |
9651 { | |
9652 MARK_TYPE_CHANGED (toolbar); | |
9653 } | |
9654 | |
9655 void | |
9656 mark_gutter_changed (void) | |
9657 { | |
9658 MARK_TYPE_CHANGED (gutter); | |
9659 } | |
9660 | |
9661 void | |
9662 mark_glyphs_changed (void) | |
9663 { | |
9664 MARK_TYPE_CHANGED (glyphs); | |
9665 } | |
9666 | |
9667 void | |
9668 mark_subwindows_changed (void) | |
9669 { | |
9670 MARK_TYPE_CHANGED (subwindows); | |
9671 } | |
9672 | |
9673 void | |
9674 mark_subwindows_state_changed (void) | |
9675 { | |
9676 MARK_TYPE_CHANGED (subwindows_state); | |
9677 } | |
9678 | |
428 | 9679 #ifdef MEMORY_USAGE_STATS |
9680 | |
9681 | |
9682 /***************************************************************************/ | |
9683 /* */ | |
9684 /* memory usage computation */ | |
9685 /* */ | |
9686 /***************************************************************************/ | |
9687 | |
9688 static int | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9689 compute_rune_dynarr_usage (rune_dynarr *dyn, struct usage_stats *ustats) |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9690 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9691 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9692 } |
9693 | |
9694 static int | |
9695 compute_display_block_dynarr_usage (display_block_dynarr *dyn, | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9696 struct usage_stats *ustats) |
428 | 9697 { |
9698 int total, i; | |
9699 | |
9700 if (!dyn) | |
9701 return 0; | |
9702 | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9703 total = Dynarr_memory_usage (dyn, ustats); |
428 | 9704 for (i = 0; i < Dynarr_largest (dyn); i++) |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9705 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ustats); |
428 | 9706 |
9707 return total; | |
9708 } | |
9709 | |
9710 static int | |
9711 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn, | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9712 struct usage_stats *ustats) |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9713 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9714 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9715 } |
9716 | |
9717 int | |
9718 compute_display_line_dynarr_usage (display_line_dynarr *dyn, | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9719 struct usage_stats *ustats) |
428 | 9720 { |
9721 int total, i; | |
9722 | |
9723 if (!dyn) | |
9724 return 0; | |
9725 | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9726 total = Dynarr_memory_usage (dyn, ustats); |
428 | 9727 for (i = 0; i < Dynarr_largest (dyn); i++) |
9728 { | |
9729 struct display_line *dl = &Dynarr_at (dyn, i); | |
5198 | 9730 total += compute_display_block_dynarr_usage (dl->display_blocks, ustats); |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9731 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ustats); |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9732 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ustats); |
428 | 9733 } |
9734 | |
9735 return total; | |
9736 } | |
9737 | |
9738 int | |
9739 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn, | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9740 struct usage_stats *ustats) |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9741 { |
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5090
diff
changeset
|
9742 return dyn ? Dynarr_memory_usage (dyn, ustats) : 0; |
428 | 9743 } |
9744 | |
9745 #endif /* MEMORY_USAGE_STATS */ | |
9746 | |
1204 | 9747 #ifdef ERROR_CHECK_DISPLAY |
9748 | |
800 | 9749 static int |
2286 | 9750 sledgehammer_check_redisplay_structs_1 (struct window *w, |
9751 void *UNUSED (closure)) | |
800 | 9752 { |
9753 int i, j; | |
9754 display_line_dynarr *dl; | |
9755 | |
9756 dl = window_display_lines (w, CURRENT_DISP); | |
4187 | 9757 |
800 | 9758 for (i = 0; i < Dynarr_largest (dl); i++) |
9759 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9760 assert (Dynarr_atp (dl, i)->display_blocks != | |
9761 Dynarr_atp (dl, j)->display_blocks); | |
9762 | |
9763 dl = window_display_lines (w, DESIRED_DISP); | |
9764 | |
9765 for (i = 0; i < Dynarr_largest (dl); i++) | |
9766 for (j = i + 1; j < Dynarr_largest (dl); j++) | |
9767 assert (Dynarr_atp (dl, i)->display_blocks != | |
9768 Dynarr_atp (dl, j)->display_blocks); | |
9769 | |
9770 return 0; | |
9771 } | |
9772 | |
9773 static void | |
9774 sledgehammer_check_redisplay_structs (void) | |
9775 { | |
9776 map_windows (0, sledgehammer_check_redisplay_structs_1, NULL); | |
9777 } | |
9778 | |
1204 | 9779 #endif /* ERROR_CHECK_DISPLAY */ |
9780 | |
428 | 9781 |
9782 /***************************************************************************/ | |
9783 /* */ | |
9784 /* initialization */ | |
9785 /* */ | |
9786 /***************************************************************************/ | |
9787 | |
9788 void | |
9789 init_redisplay (void) | |
9790 { | |
9791 disable_preemption = 0; | |
9792 preemption_count = 0; | |
9793 | |
9794 #ifndef PDUMP | |
9795 if (!initialized) | |
9796 #endif | |
9797 { | |
440 | 9798 if (!cmotion_display_lines) |
9799 cmotion_display_lines = Dynarr_new (display_line); | |
867 | 9800 if (!mode_spec_ibyte_string) |
9801 mode_spec_ibyte_string = Dynarr_new (Ibyte); | |
440 | 9802 if (!formatted_string_extent_dynarr) |
9803 formatted_string_extent_dynarr = Dynarr_new (EXTENT); | |
9804 if (!formatted_string_extent_start_dynarr) | |
9805 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); | |
9806 if (!formatted_string_extent_end_dynarr) | |
9807 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); | |
9808 if (!internal_cache) | |
9809 internal_cache = Dynarr_new (line_start_cache); | |
428 | 9810 } |
9811 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9812 if (!initialized) |
428 | 9813 return; |
9814 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9815 if (noninteractive) |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9816 { |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9817 Vinitial_device_type = Qstream; |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9818 return; |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9819 } |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9820 |
428 | 9821 /* If the user wants to use a window system, we shouldn't bother |
9822 initializing the terminal. This is especially important when the | |
9823 terminal is so dumb that emacs gives up before and doesn't bother | |
9824 using the window system. | |
9825 | |
9826 If the DISPLAY environment variable is set, try to use X, and die | |
9827 with an error message if that doesn't work. */ | |
9828 | |
9829 #ifdef HAVE_X_WINDOWS | |
9830 if (!strcmp (display_use, "x")) | |
9831 { | |
9832 /* Some stuff checks this way early. */ | |
9833 Vwindow_system = Qx; | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9834 Vinitial_device_type = Qx; |
428 | 9835 return; |
9836 } | |
9837 #endif /* HAVE_X_WINDOWS */ | |
9838 | |
462 | 9839 #ifdef HAVE_GTK |
9840 if (!strcmp (display_use, "gtk")) | |
9841 { | |
9842 Vwindow_system = Qgtk; | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9843 Vinitial_device_type = Qgtk; |
462 | 9844 return; |
9845 } | |
9846 #endif | |
9847 | |
428 | 9848 #ifdef HAVE_MS_WINDOWS |
9849 if (!strcmp (display_use, "mswindows")) | |
9850 { | |
9851 /* Some stuff checks this way early. */ | |
9852 Vwindow_system = Qmswindows; | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9853 Vinitial_device_type = Qmswindows; |
428 | 9854 return; |
9855 } | |
9856 #endif /* HAVE_MS_WINDOWS */ | |
9857 | |
9858 #ifdef HAVE_TTY | |
9859 /* If no window system has been specified, try to use the terminal. */ | |
9860 if (!isatty (0)) | |
9861 { | |
9862 stderr_out ("XEmacs: standard input is not a tty\n"); | |
9863 exit (1); | |
9864 } | |
9865 | |
9866 /* Look at the TERM variable */ | |
771 | 9867 if (!egetenv ("TERM")) |
428 | 9868 { |
9869 stderr_out ("Please set the environment variable TERM; see tset(1).\n"); | |
9870 exit (1); | |
9871 } | |
9872 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
9873 Vinitial_device_type = Qtty; |
428 | 9874 return; |
9875 #else /* not HAVE_TTY */ | |
9876 /* No DISPLAY specified, and no TTY support. */ | |
9877 stderr_out ("XEmacs: Cannot open display.\n\ | |
9878 Please set the environmental variable DISPLAY to an appropriate value.\n"); | |
9879 exit (1); | |
9880 #endif | |
9881 /* Unreached. */ | |
9882 } | |
9883 | |
9884 void | |
9885 syms_of_redisplay (void) | |
9886 { | |
563 | 9887 DEFSYMBOL (Qcursor_in_echo_area); |
9888 DEFSYMBOL (Qdisplay_warning_buffer); | |
9889 DEFSYMBOL (Qbar_cursor); | |
9890 DEFSYMBOL (Qtop_bottom); | |
9891 DEFSYMBOL (Qbuffer_list_changed_hook); | |
428 | 9892 |
9893 DEFSUBR (Fredisplay_echo_area); | |
9894 DEFSUBR (Fredraw_frame); | |
9895 DEFSUBR (Fredisplay_frame); | |
9896 DEFSUBR (Fredraw_device); | |
9897 DEFSUBR (Fredisplay_device); | |
9898 DEFSUBR (Fredraw_modeline); | |
9899 DEFSUBR (Fforce_cursor_redisplay); | |
9900 } | |
9901 | |
9902 void | |
9903 vars_of_redisplay (void) | |
9904 { | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
9905 QSin_redisplay = build_defer_string ("(in redisplay)"); |
1292 | 9906 staticpro (&QSin_redisplay); |
428 | 9907 |
1318 | 9908 Vpost_redisplay_actions = Qnil; |
9909 staticpro (&Vpost_redisplay_actions); | |
9910 | |
428 | 9911 #if 0 |
9912 staticpro (&last_arrow_position); | |
9913 staticpro (&last_arrow_string); | |
9914 last_arrow_position = Qnil; | |
9915 last_arrow_string = Qnil; | |
9916 #endif /* 0 */ | |
9917 | |
9918 /* #### Probably temporary */ | |
9919 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* | |
9920 \(Temporary) Setting this will impact the performance of the internal | |
9921 line start cache. | |
9922 */ ); | |
9923 cache_adjustment = 2; | |
9924 | |
1268 | 9925 DEFVAR_INT ("maximum-preempts", &max_preempts /* |
9926 Maximum number of times redisplay can be preempted by user input. | |
9927 */ ); | |
9928 max_preempts = INIT_MAX_PREEMPTS; | |
9929 | |
428 | 9930 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /* |
9931 Minimum pixel height for clipped bottom display line. | |
9932 A clipped line shorter than this won't be displayed. | |
9933 */ , | |
9934 redisplay_variable_changed); | |
9935 vertical_clip = 5; | |
9936 | |
9937 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /* | |
9938 Minimum visible area for clipped glyphs at right boundary. | |
9939 Clipped glyphs shorter than this won't be displayed. | |
9940 Only pixmap glyph instances are currently allowed to be clipped. | |
9941 */ , | |
9942 redisplay_variable_changed); | |
9943 horizontal_clip = 5; | |
9944 | |
9945 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /* | |
9946 String displayed by modeline-format's "%m" specification. | |
9947 */ ); | |
9948 Vglobal_mode_string = Qnil; | |
9949 | |
9950 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /* | |
9951 Marker for where to display an arrow on top of the buffer text. | |
9952 This must be the beginning of a line in order to work. | |
9953 See also `overlay-arrow-string'. | |
9954 */ , | |
9955 redisplay_variable_changed); | |
9956 Voverlay_arrow_position = Qnil; | |
9957 | |
9958 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* | |
442 | 9959 String or glyph to display as an arrow. See also `overlay-arrow-position'. |
444 | 9960 \(Note that despite the name of this variable, it can be set to a glyph as |
442 | 9961 well as a string.) |
428 | 9962 */ , |
9963 redisplay_variable_changed); | |
9964 Voverlay_arrow_string = Qnil; | |
9965 | |
9966 DEFVAR_INT ("scroll-step", &scroll_step /* | |
9967 *The number of lines to try scrolling a window by when point moves out. | |
9968 If that fails to bring point back on frame, point is centered instead. | |
9969 If this is zero, point is always centered after it moves off screen. | |
9970 */ ); | |
9971 scroll_step = 0; | |
9972 | |
9973 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /* | |
9974 *Scroll up to this many lines, to bring point back on screen. | |
9975 */ ); | |
9976 scroll_conservatively = 0; | |
9977 | |
9978 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows", | |
9979 &truncate_partial_width_windows /* | |
9980 *Non-nil means truncate lines in all windows less than full frame wide. | |
9981 */ , | |
9982 redisplay_variable_changed); | |
9983 truncate_partial_width_windows = 1; | |
9984 | |
442 | 9985 DEFVAR_LISP ("visible-bell", &Vvisible_bell /* |
9986 *Non-nil substitutes a visual signal for the audible bell. | |
9987 | |
9988 Default behavior is to flash the whole screen. On some platforms, | |
9989 special effects are available using the following values: | |
9990 | |
3025 | 9991 `display' Flash the whole screen (ie, the default behavior). |
9992 `top-bottom' Flash only the top and bottom lines of the selected frame. | |
442 | 9993 |
9994 When effects are unavailable on a platform, the visual bell is the | |
9995 default, whole screen. (Currently only X supports any special effects.) | |
428 | 9996 */ ); |
442 | 9997 Vvisible_bell = Qnil; |
428 | 9998 |
9999 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* | |
10000 *Non-nil means no need to redraw entire frame after suspending. | |
10001 A non-nil value is useful if the terminal can automatically preserve | |
10002 Emacs's frame display when you reenter Emacs. | |
10003 It is up to you to set this variable if your terminal can do that. | |
10004 */ ); | |
10005 no_redraw_on_reenter = 0; | |
10006 | |
10007 DEFVAR_LISP ("window-system", &Vwindow_system /* | |
10008 A symbol naming the window-system under which Emacs is running, | |
10009 such as `x', or nil if emacs is running on an ordinary terminal. | |
10010 | |
10011 Do not use this variable, except for GNU Emacs compatibility, as it | |
10012 gives wrong values in a multi-device environment. Use `console-type' | |
10013 instead. | |
10014 */ ); | |
10015 Vwindow_system = Qnil; | |
10016 | |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10017 DEFVAR_CONST_LISP ("initial-device-type", &Vinitial_device_type /* |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10018 The type of the first XEmacs device to be created. |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10019 |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10020 This is constant; it's used by the command line handling code to communicate |
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10021 to Lisp what type the initial device to be created should be. |
428 | 10022 */ ); |
4477
e34711681f30
Don't determine whether to call general device-type code at startup,
Aidan Kehoe <kehoea@parhasard.net>
parents:
4418
diff
changeset
|
10023 Vinitial_device_type = Qnil; |
428 | 10024 |
10025 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* | |
10026 Non-nil means put cursor in minibuffer, at end of any message there. | |
10027 */ ); | |
10028 cursor_in_echo_area = 0; | |
10029 | |
10030 /* #### Shouldn't this be generalized as follows: | |
10031 | |
10032 if nil, use block cursor. | |
10033 if a number, use a bar cursor of that width. | |
10034 Otherwise, use a 1-pixel bar cursor. | |
10035 | |
10036 #### Or better yet, this variable should be trashed entirely | |
10037 (use a Lisp-magic variable to maintain compatibility) | |
10038 and a specifier `cursor-shape' added, which allows a block | |
10039 cursor, a bar cursor, a flashing block or bar cursor, | |
10040 maybe a caret cursor, etc. */ | |
10041 | |
10042 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /* | |
448 | 10043 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. |
428 | 10044 */ ); |
10045 Vbar_cursor = Qnil; | |
10046 | |
442 | 10047 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* |
10048 Function or functions to call when a frame's buffer list has changed. | |
10049 This is called during redisplay, before redisplaying each frame. | |
10050 Functions on this hook are called with one argument, the frame. | |
10051 */ ); | |
10052 Vbuffer_list_changed_hook = Qnil; | |
10053 | |
428 | 10054 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* |
10055 Bump this to tell the C code to call `display-warning-buffer' | |
10056 at next redisplay. You should not normally change this; the function | |
10057 `display-warning' automatically does this at appropriate times. | |
10058 */ ); | |
10059 display_warning_tick = 0; | |
10060 | |
10061 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /* | |
10062 Non-nil means inhibit display of warning messages. | |
10063 You should *bind* this, not set it. Any pending warning messages | |
10064 will be displayed when the binding no longer applies. | |
10065 */ ); | |
10066 /* reset to 0 by startup.el after the splash screen has displayed. | |
10067 This way, the warnings don't obliterate the splash screen. */ | |
10068 inhibit_warning_display = 1; | |
10069 | |
10070 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /* | |
10071 *Non-nil means column display number starts at 1. | |
10072 */ ); | |
10073 column_number_start_at_one = 0; | |
10074 } | |
10075 | |
10076 void | |
10077 specifier_vars_of_redisplay (void) | |
10078 { | |
10079 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /* | |
10080 *Width of left margin. | |
10081 This is a specifier; use `set-specifier' to change it. | |
10082 */ ); | |
10083 Vleft_margin_width = Fmake_specifier (Qnatnum); | |
10084 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10085 set_specifier_caching (Vleft_margin_width, | |
438 | 10086 offsetof (struct window, left_margin_width), |
428 | 10087 some_window_value_changed, |
438 | 10088 offsetof (struct frame, left_margin_width), |
444 | 10089 margin_width_changed_in_frame, 0); |
428 | 10090 |
10091 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* | |
10092 *Width of right margin. | |
10093 This is a specifier; use `set-specifier' to change it. | |
10094 */ ); | |
10095 Vright_margin_width = Fmake_specifier (Qnatnum); | |
10096 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); | |
10097 set_specifier_caching (Vright_margin_width, | |
438 | 10098 offsetof (struct window, right_margin_width), |
428 | 10099 some_window_value_changed, |
438 | 10100 offsetof (struct frame, right_margin_width), |
444 | 10101 margin_width_changed_in_frame, 0); |
428 | 10102 |
10103 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* | |
10104 *Minimum ascent height of lines. | |
10105 This is a specifier; use `set-specifier' to change it. | |
10106 */ ); | |
10107 Vminimum_line_ascent = Fmake_specifier (Qnatnum); | |
10108 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); | |
10109 set_specifier_caching (Vminimum_line_ascent, | |
438 | 10110 offsetof (struct window, minimum_line_ascent), |
428 | 10111 some_window_value_changed, |
444 | 10112 0, 0, 0); |
428 | 10113 |
10114 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* | |
10115 *Minimum descent height of lines. | |
10116 This is a specifier; use `set-specifier' to change it. | |
10117 */ ); | |
10118 Vminimum_line_descent = Fmake_specifier (Qnatnum); | |
10119 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); | |
10120 set_specifier_caching (Vminimum_line_descent, | |
438 | 10121 offsetof (struct window, minimum_line_descent), |
428 | 10122 some_window_value_changed, |
444 | 10123 0, 0, 0); |
428 | 10124 |
10125 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* | |
10126 *Non-nil means use the left outside margin as extra whitespace when | |
3025 | 10127 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10128 This is a specifier; use `set-specifier' to change it. |
10129 */ ); | |
10130 Vuse_left_overflow = Fmake_specifier (Qboolean); | |
10131 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); | |
10132 set_specifier_caching (Vuse_left_overflow, | |
438 | 10133 offsetof (struct window, use_left_overflow), |
428 | 10134 some_window_value_changed, |
444 | 10135 0, 0, 0); |
428 | 10136 |
10137 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* | |
10138 *Non-nil means use the right outside margin as extra whitespace when | |
3025 | 10139 displaying `whitespace' or `inside-margin' glyphs. |
428 | 10140 This is a specifier; use `set-specifier' to change it. |
10141 */ ); | |
10142 Vuse_right_overflow = Fmake_specifier (Qboolean); | |
10143 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); | |
10144 set_specifier_caching (Vuse_right_overflow, | |
438 | 10145 offsetof (struct window, use_right_overflow), |
428 | 10146 some_window_value_changed, |
444 | 10147 0, 0, 0); |
428 | 10148 |
10149 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* | |
10150 *Non-nil means the text cursor is visible (this is usually the case). | |
10151 This is a specifier; use `set-specifier' to change it. | |
10152 */ ); | |
10153 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); | |
10154 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); | |
10155 set_specifier_caching (Vtext_cursor_visible_p, | |
438 | 10156 offsetof (struct window, text_cursor_visible_p), |
428 | 10157 text_cursor_visible_p_changed, |
444 | 10158 0, 0, 0); |
428 | 10159 |
10160 } |