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