comparison src/redisplay.c @ 1318:b531bf8658e9

[xemacs-hg @ 2003-02-21 06:56:46 by ben] redisplay fixes et al. PROBLEMS: Add comment about Cygwin, unexec and sysmalloc. Move some non-general stuff out of general. Make a section for x86. configure.in: Add check for broken alloca in funcalls. mule/mule-cmds.el: Alias file-name to native not vice-versa. Do set EOL of native but not of process output to fix various problems and be consistent with code-init.el. code-cmds.el: Return a name not a coding system. code-init.el: Reindent. Remove `file-name' since it should always be the same as native. unicode.el: Rename to load-unicode-mapping-table as suggested by the anonymous (but rather Turnbullian) comment in unicode.c. xemacs.dsp: Add /k to default build. alloc.c: Make gc_currently_forbidden static. config.h.in, lisp.h: Move some stuff to lisp.h. console-gtk.h, console-impl.h, console-msw.h, console-x.h, event-Xt.c, event-msw.c, redisplay-gtk.c, redisplay-msw.c, redisplay-output.c, redisplay-x.c, gtk-xemacs.c: Remove duplicated code to redraw exposed area. Add deadbox method needed by the generalized redraw code. Defer redrawing if already in redisplay. frame-msw.c, event-stream.c, frame.c: Add comments about calling Lisp. debug.c, general-slots.h: Move generalish symbols to general-slots.h. doprnt.c: reindent. lisp.h, dynarr.c: Add debug code for locking a dynarr to catch invalid mods. Use in redisplay.c. eval.c: file-coding.c: Define file-name as alias for native not vice-versa. frame-gtk.c, frame-x.c: Move Qwindow_id to general-slots. dialog-msw.c, glyphs-gtk.c, glyphs-msw.c, glyphs-widget.c, glyphs-x.c, gui.c, gui.h, menubar-msw.c, menubar.c: Ensure that various glyph functions that eval within redisplay protect the evals. Same for calls to internal_equal(). Modify various functions, e.g. gui_item_*(), to protect evals within redisplay, taking an in_redisplay parameter if it's possible for them to be called both inside and outside of redisplay. gutter.c: Defer specifier-changed updating till after redisplay, if necessary, since we need to enter redisplay to do it. gutter.c: Do nothing if in redisplay. lisp.h: Add version of alloca() for use in function calls. lisp.h: Add XCAD[D+]R up to 6 D's, and aliases X1ST, X2ND, etc. frame.c, frame.h, redisplay.c, redisplay.h, signal.c, toolbar.c: Redo critical-section code and move from frame.c to redisplay.c. Require that every place inside of redisplay catch errors itself, not at the edge of the critical section (thereby bypassing the rest of redisplay and leaving things in an inconsistent state). Introduce separate means of holding frame-size changes without entering a complete critical section. Introduce "post-redisplay" methods for deferring things till after redisplay. Abort if we enter redisplay reentrantly. Disable all quit checking in redisplay since it's too dangerous. Ensure that all calls to QUIT trigger an abort if unprotected. redisplay.c, scrollbar-gtk.c, scrollbar-x.c, scrollbar.c: Create enter/exit_redisplay_critical_section_maybe() for code that needs to ensure it's in a critical section but doesn't interfere with an existing critical section. sysdep.c: Use _wexecve() when under Windows NT for Unicode correctness. text.c, text.h: Add new_dfc() functions, which return an alloca()ed value rather than requiring an lvalue. (Not really used yet; used in another workspace, to come.) Add some macros for SIZED_EXTERNAL. Update the encoding aliases after involved scrutinization of the X manual. unicode.c: Answer the anonymous but suspiciously Turnbullian questions. Rename parse-unicode-translation-table to load-unicode-mapping-table, as suggested.
author ben
date Fri, 21 Feb 2003 06:57:21 +0000
parents f3437b56874d
children 4f58e6e65139
comparison
equal deleted inserted replaced
1317:d9d08dc5e617 1318:b531bf8658e9
36 First: It Is Better To Be Correct Than Fast 36 First: It Is Better To Be Correct Than Fast
37 Second: Thou Shalt Use Due Caution When Running Elisp From Within Redisplay 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 38 Third: It Is Better To Be Fast Than Not To Be
39 ****************************************************************************/ 39 ****************************************************************************/
40 40
41 /* Note: The second rule used to prohibit running Elisp from within redisplay, 41 /* Note: The second rule used to prohibit running Elisp from within
42 but that's not correct. 42 redisplay, but that's not correct any more -- use
43 43 call*_trapping_problems() or call_with_suspended_errors() instead.
44 Use
45
46 callN_trapping_problems (..., INHIBIT_GC
47 | INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY)
48
49 instead.
50 44
51 --ben 45 --ben
52 */ 46 */
53 47
54 #include <config.h> 48 #include <config.h>
66 #include "glyphs.h" 60 #include "glyphs.h"
67 #include "gutter.h" 61 #include "gutter.h"
68 #include "insdel.h" 62 #include "insdel.h"
69 #include "menubar.h" 63 #include "menubar.h"
70 #include "objects-impl.h" 64 #include "objects-impl.h"
65 #include "opaque.h"
71 #include "process.h" 66 #include "process.h"
72 #include "profile.h" 67 #include "profile.h"
73 #include "redisplay.h" 68 #include "redisplay.h"
74 #include "toolbar.h" 69 #include "toolbar.h"
75 #include "window-impl.h" 70 #include "window-impl.h"
317 #define INIT_MAX_PREEMPTS 30 312 #define INIT_MAX_PREEMPTS 30
318 static Fixnum max_preempts; 313 static Fixnum max_preempts;
319 314
320 #define QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION 4 315 #define QUEUED_EVENTS_REQUIRED_FOR_PREEMPTION 4
321 316
317 /* Note that doing this can call Lisp. */
322 #define REDISPLAY_PREEMPTION_CHECK \ 318 #define REDISPLAY_PREEMPTION_CHECK \
323 ((void) \ 319 ((void) \
324 (preempted = \ 320 (preempted = \
325 (!disable_preemption && \ 321 (!disable_preemption && \
326 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \ 322 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
356 modeline % spec. */ 352 modeline % spec. */
357 static Ibyte_dynarr *mode_spec_ibyte_string; 353 static Ibyte_dynarr *mode_spec_ibyte_string;
358 354
359 int in_display; /* 1 if in redisplay. */ 355 int in_display; /* 1 if in redisplay. */
360 356
357 /* Whether we should delay size changes. Broken out of
358 enter_redisplay_critical_section(). */
359 int hold_frame_size_changes;
360
361 int disable_preemption; /* Used for debugging redisplay and for 361 int disable_preemption; /* Used for debugging redisplay and for
362 force-redisplay. */ 362 force-redisplay. */
363 363
364 /* We only allow max_preempts preemptions before we force a redisplay. */ 364 /* We only allow max_preempts preemptions before we force a redisplay. */
365 static int preemption_count; 365 static int preemption_count;
500 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; 500 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
501 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; 501 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
502 Lisp_Object Vtext_cursor_visible_p; 502 Lisp_Object Vtext_cursor_visible_p;
503 503
504 static Lisp_Object QSin_redisplay; 504 static Lisp_Object QSin_redisplay;
505
506 static Lisp_Object Vpost_redisplay_actions;
505 507
506 int column_number_start_at_one; 508 int column_number_start_at_one;
507 509
508 Lisp_Object Qtop_bottom; 510 Lisp_Object Qtop_bottom;
509 511
5312 create_right_glyph_block (w, dl); 5314 create_right_glyph_block (w, dl);
5313 5315
5314 return ret_charcount; 5316 return ret_charcount;
5315 } 5317 }
5316 5318
5319
5320 /* Tricky tricky tricky. generate_displayable_area() can (could) be called reentrantly, and redisplay is not prepared to handle this:
5321
5322 assert_failed(const char * 0x0129c8c8 `string', int 5328, const char * 0x01274068 `string') line 3620
5323 Dynarr_verify_mod_1(void * 0x0250f228, const char * 0x0129c8c8 `string', int 5328) line 1256 + 36 bytes
5324 generate_displayable_area(window * 0x02480028, long 38776292, int 0, int 0, int 265, int 169, display_line_dynarr * 0x0250f228, long 0, int 2) line 5328 + 25 bytes
5325 output_gutter(frame * 0x0228ad90, gutter_pos TOP_GUTTER, int 1) line 409 + 69 bytes
5326 redraw_exposed_gutter(frame * 0x0228ad90, gutter_pos TOP_GUTTER, int 8, int 23, int 249, int 127) line 687 + 15 bytes
5327 redraw_exposed_gutters(frame * 0x0228ad90, int 8, int 23, int 249, int 127) line 703 + 29 bytes
5328 mswindows_redraw_exposed_area(frame * 0x0228ad90, int 8, int 23, int 249, int 127) line 862 + 25 bytes
5329 mswindows_handle_paint(frame * 0x0228ad90) line 2176 + 25 bytes
5330 mswindows_wnd_proc(HWND__ * 0x001003e2, unsigned int 15, unsigned int 0, long 0) line 3233 + 45 bytes
5331 intercepted_wnd_proc(HWND__ * 0x001003e2, unsigned int 15, unsigned int 0, long 0) line 2488
5332 USER32! 77e3a244()
5333 USER32! 77e14730()
5334 USER32! 77e1558a()
5335 NTDLL! KiUserCallbackDispatcher@12 + 19 bytes
5336 USER32! 77e14680()
5337 USER32! 77e1a792()
5338 qxeIsDialogMessage(HWND__ * 0x001003e2, tagMSG * 0x0082a93c {msg=0x0000000f wp=0x00000000 lp=0x00000000}) line 2298 + 14 bytes
5339 mswindows_is_dialog_msg(tagMSG * 0x0082a93c {msg=0x0000000f wp=0x00000000 lp=0x00000000}) line 165 + 13 bytes
5340 mswindows_drain_windows_queue(int 0) line 1282 + 9 bytes
5341 emacs_mswindows_drain_queue() line 1326 + 7 bytes
5342 event_stream_drain_queue() line 1887
5343 event_stream_quit_p() line 1992
5344 check_quit() line 993
5345 unbind_to_hairy(int 35) line 5963
5346 unbind_to_1(int 35, long 20888208) line 5945 + 200 bytes
5347 specifier_instance_from_inst_list(long 21379344, long 38135616, long 36220304, long 20888208, _error_behavior_struct_ {...}, int 1, long 3) line 2522 + 16 bytes
5348 specifier_instance(long 21379344, long 38135616, long 36220304, _error_behavior_struct_ {...}, int 1, int 0, long 3) line 2625 + 65 bytes
5349 specifier_instance_no_quit(long 21379344, long 38135616, long 36220304, _error_behavior_struct_ {...}, int 0, long 1) line 2658 + 31 bytes
5350 face_property_matching_instance(long 22612340, long 20860632, long 22530956, long 36220304, _error_behavior_struct_ {...}, int 0, long 1) line 565 + 48 bytes
5351 ensure_face_cachel_contains_charset(face_cachel * 0x0082b014, long 36220304, long 22530956) line 1104 + 35 bytes
5352 update_face_cachel_data(face_cachel * 0x0082b014, long 36220304, long 22612340) line 1304 + 19 bytes
5353 query_string_geometry(long 21110576, long 22612340, int * 0x00000000, int * 0x0082b5b4, int * 0x00000000, long 38852960) line 2370 + 23 bytes
5354 mswindows_widget_query_string_geometry(long 21110576, long 22612340, int * 0x0082b5b8, int * 0x0082b5b4, long 38852960) line 2914 + 25 bytes
5355 widget_query_string_geometry(long 21110576, long 22612340, int * 0x0082b5b8, int * 0x0082b5b4, long 38852960) line 514 + 32 bytes
5356 edit_field_query_geometry(long 38857648, int * 0x0082b7b4, int * 0x0082b7b8, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long 38852960) line 920 + 390 bytes
5357 widget_query_geometry(long 38857648, int * 0x0082b7b4, int * 0x0082b7b8, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long 38852960) line 567 + 26 bytes
5358 image_instance_query_geometry(long 38857648, int * 0x0082b7b4, int * 0x0082b7b8, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long 38852960) line 2015 + 26 bytes
5359 glyph_query_geometry(long 38853384, int * 0x0082b7b4, int * 0x0082b7b8, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long 38852960) line 4197 + 25 bytes
5360 layout_query_geometry(long 38852960, int * 0x0082b9cc, int * 0x0082b9d0, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long 38404624) line 1351 + 25 bytes
5361 widget_query_geometry(long 38852960, int * 0x0082b9cc, int * 0x0082b9d0, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long 38404624) line 567 + 26 bytes
5362 image_instance_query_geometry(long 38852960, int * 0x0082b9cc, int * 0x0082b9d0, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long 38404624) line 2015 + 26 bytes
5363 glyph_query_geometry(long 38537976, int * 0x0082b9cc, int * 0x0082b9d0, image_instance_geometry IMAGE_DESIRED_GEOMETRY, long 38404624) line 4197 + 25 bytes
5364 layout_layout(long 38404624, int 265, int 156, int -2, int -2, long 38273064) line 1468 + 23 bytes
5365 widget_layout(long 38404624, int 265, int 156, int -2, int -2, long 38273064) line 626 + 30 bytes
5366 image_instance_layout(long 38404624, int 265, int 156, int -2, int -2, long 38273064) line 2102 + 51 bytes
5367 glyph_ascent(long 38404624, long 38273064) line 4009 + 21 bytes
5368 update_glyph_cachel_data(window * 0x02480028, long 36201168, glyph_cachel * 0x0248c3d8) line 4272 + 13 bytes
5369 get_glyph_cachel_index(window * 0x02480028, long 36201168) line 4306 + 17 bytes
5370 add_glyph_rune(position_redisplay_data_type * 0x0082bf2c, glyph_block * 0x024bd028, int 0, int 0, glyph_cachel * 0x00000000) line 1800 + 15 bytes
5371 add_glyph_runes(position_redisplay_data_type * 0x0082bf2c, int 0) line 2085 + 31 bytes
5372 create_string_text_block(window * 0x02480028, long 38776292, display_line * 0x02514500, long 0, prop_block_dynarr * * 0x0082c13c, int 2) line 4907 + 14 bytes
5373 generate_string_display_line(window * 0x02480028, long 38776292, display_line * 0x02514500, long 0, prop_block_dynarr * * 0x0082c13c, int 2) line 5293 + 29 bytes
5374 generate_displayable_area(window * 0x02480028, long 38776292, int 0, int 0, int 265, int 169, display_line_dynarr * 0x0250f228, long 0, int 2) line 5372 + 29 bytes
5375 output_gutter(frame * 0x0228ad90, gutter_pos TOP_GUTTER, int 0) line 409 + 69 bytes
5376 update_frame_gutters(frame * 0x0228ad90) line 639 + 15 bytes
5377 redisplay_frame(frame * 0x0228ad90, int 1) line 6792 + 9 bytes
5378 redisplay_device(device * 0x0171df00, int 1) line 6911 + 11 bytes
5379 redisplay_without_hooks() line 6957 + 11 bytes
5380 redisplay_no_pre_idle_hook() line 7029
5381 redisplay() line 7011
5382 mswindows_wnd_proc(HWND__ * 0x001003e2, unsigned int 5, unsigned int 0, long 10223881) line 3424
5383 intercepted_wnd_proc(HWND__ * 0x001003e2, unsigned int 5, unsigned int 0, long 10223881) line 2488
5384 USER32! 77e3a244()
5385 USER32! 77e16362()
5386 USER32! 77e14c1a()
5387 USER32! 77e1dd30()
5388 mswindows_wnd_proc(HWND__ * 0x001003e2, unsigned int 71, unsigned int 0, long 8578308) line 3926 + 21 bytes
5389 intercepted_wnd_proc(HWND__ * 0x001003e2, unsigned int 71, unsigned int 0, long 8578308) line 2488
5390 USER32! 77e3a244()
5391 USER32! 77e14730()
5392 USER32! 77e174b4()
5393 NTDLL! KiUserCallbackDispatcher@12 + 19 bytes
5394 mswindows_set_frame_size(frame * 0x0228ad90, int 265, int 156) line 355
5395 internal_set_frame_size(frame * 0x0228ad90, int 265, int 156, int 0) line 2754 + 24 bytes
5396 Fset_frame_displayable_pixel_size(long 36220304, long 531, long 313, long 20888208) line 3004 + 32 bytes
5397 Ffuncall(int 4, long * 0x0082e778) line 3844 + 168 bytes
5398 execute_optimized_program(const unsigned char * 0x02286e48, int 40, long * 0x01529b80) line 609 + 16 bytes
5399 funcall_compiled_function(long 22433308, int 0, long * 0x0082ec08) line 3452 + 85 bytes
5400 Ffuncall(int 1, long * 0x0082ec04) line 3883 + 17 bytes
5401 execute_optimized_program(const unsigned char * 0x02286d40, int 6, long * 0x01548ddc) line 609 + 16 bytes
5402 funcall_compiled_function(long 22505864, int 11, long * 0x0082f00c) line 3452 + 85 bytes
5403 Ffuncall(int 12, long * 0x0082f008) line 3883 + 17 bytes
5404 execute_optimized_program(const unsigned char * 0x02503e38, int 47, long * 0x0152dc48) line 609 + 16 bytes
5405 funcall_compiled_function(long 22436784, int 0, long * 0x0082f534) line 3452 + 85 bytes
5406 Ffuncall(int 1, long * 0x0082f530) line 3883 + 17 bytes
5407 apply1(long 22436784, long 20888208) line 4458 + 11 bytes
5408 Fcall_interactively(long 20742816, long 20888208, long 20888208) line 460 + 13 bytes
5409 Ffuncall(int 2, long * 0x0082f8ec) line 3844 + 127 bytes
5410 call1(long 20854392, long 20742816) line 4489 + 11 bytes
5411 execute_command_event(command_builder * 0x01798f98, long 24439276) line 4198 + 69 bytes
5412 Fdispatch_event(long 24439276) line 4569 + 13 bytes
5413 Fcommand_loop_1() line 569 + 9 bytes
5414 command_loop_1(long 20888208) line 489
5415 condition_case_1(long 20886024, long (long)* 0x010955a0 command_loop_1(long), long 20888208, long (long, long)* 0x01095150 cmd_error(long, long), long 20888208) line 1917 + 7 bytes
5416 command_loop_3() line 251 + 35 bytes
5417 command_loop_2(long 20888208) line 264
5418 internal_catch(long 20650992, long (long)* 0x010952c0 command_loop_2(long), long 20888208, int * volatile 0x00000000, long * volatile 0x00000000) line 1527 + 7 bytes
5419 initial_command_loop(long 20888208) line 300 + 28 bytes
5420 xemacs_21_5_b10_i586_pc_win32(int 1, char * * 0x00e52620, char * * 0x00e52bb0, int 0) line 2356
5421 main(int 1, char * * 0x00e52620, char * * 0x00e52bb0) line 2733
5422 mainCRTStartup() line 338 + 17 bytes
5423 KERNEL32! 77ea847c()
5424
5425 */
5426
5427
5317 /* This is ripped off from regenerate_window. All we want to do is 5428 /* This is ripped off from regenerate_window. All we want to do is
5318 loop through elements in the string creating display lines until we 5429 loop through elements in the string creating display lines until we
5319 have covered the provided area. Simple really. */ 5430 have covered the provided area. Simple really. */
5320 void 5431 void
5321 generate_displayable_area (struct window *w, Lisp_Object disp_string, 5432 generate_displayable_area (struct window *w, Lisp_Object disp_string,
5371 local = 1; 5482 local = 1;
5372 } 5483 }
5373 5484
5374 dlp->bounds = bounds; 5485 dlp->bounds = bounds;
5375 dlp->offset = 0; 5486 dlp->offset = 0;
5487 Dynarr_lock (dla);
5376 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos, 5488 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5377 &prop, default_face); 5489 &prop, default_face);
5490 Dynarr_unlock (dla);
5378 /* we need to make sure that we continue along the line if there 5491 /* we need to make sure that we continue along the line if there
5379 is more left to display otherwise we just end up redisplaying 5492 is more left to display otherwise we just end up redisplaying
5380 the same chunk over and over again. */ 5493 the same chunk over and over again. */
5381 if (next_pos == start_pos && next_pos < s_zv) 5494 if (next_pos == start_pos && next_pos < s_zv)
5382 start_pos++; 5495 start_pos++;
5519 local = 1; 5632 local = 1;
5520 } 5633 }
5521 5634
5522 dlp->bounds = bounds; 5635 dlp->bounds = bounds;
5523 dlp->offset = 0; 5636 dlp->offset = 0;
5637 Dynarr_lock (dla);
5524 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); 5638 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
5639 Dynarr_unlock (dla);
5525 5640
5526 if (yclip > dlp->ascent) 5641 if (yclip > dlp->ascent)
5527 { 5642 {
5528 /* this should never happen, but if it does just display the 5643 /* this should never happen, but if it does just display the
5529 whole line */ 5644 whole line */
5575 } 5690 }
5576 else 5691 else
5577 { 5692 {
5578 /* #### This means that we've added a cursor at EOB 5693 /* #### This means that we've added a cursor at EOB
5579 twice. Yuck oh yuck. */ 5694 twice. Yuck oh yuck. */
5580 struct display_block *db = 5695 struct display_block *db;
5581 get_display_block_from_line (dlp, TEXT); 5696
5697 Dynarr_lock (dla);
5698 db = get_display_block_from_line (dlp, TEXT);
5699 Dynarr_unlock (dla);
5582 5700
5583 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR; 5701 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
5584 dlp->cursor_elt = -1; 5702 dlp->cursor_elt = -1;
5585 } 5703 }
5586 } 5704 }
6578 { 6696 {
6579 redisplay_window (window, skip_selected); 6697 redisplay_window (window, skip_selected);
6580 } 6698 }
6581 } 6699 }
6582 6700
6701 /* Register an action to be called at the end of redisplay.
6702 in_display is 0 when this is called.
6703 This is used when it is discovered that an action needs to be taken,
6704 but it's during redisplay, so it's not safe. (Typically, it's an action
6705 that needs to enter redisplay, which can't happen reentrantly.)
6706
6707 NEVER signal an error in these functions.
6708 */
6709
6710 void
6711 register_post_redisplay_action (void (*fun) (Lisp_Object), Lisp_Object arg)
6712 {
6713 Vpost_redisplay_actions = nconc2 (Vpost_redisplay_actions,
6714 list1 (Fcons (make_opaque_ptr
6715 ((void *) fun), arg)));
6716 }
6717
6718 static void
6719 run_post_redisplay_actions (void)
6720 {
6721 while (!NILP (Vpost_redisplay_actions))
6722 {
6723 Lisp_Object car = XCAR (Vpost_redisplay_actions);
6724 void (*fun) (Lisp_Object) =
6725 (void (*)(Lisp_Object)) get_opaque_ptr (XCAR (car));
6726 (*fun) (XCDR (car));
6727 free_opaque_ptr (XCAR (car));
6728 free_cons (car);
6729 Vpost_redisplay_actions = XCDR (Vpost_redisplay_actions);
6730 }
6731 }
6732
6733 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS
6734
6735 static Lisp_Object
6736 commit_ritual_suicide (Lisp_Object ceci_nest_pas_une_pipe)
6737 {
6738 assert (!in_display);
6739 return Qnil;
6740 }
6741
6742 #endif
6743
6744 /* Within the guts of redisplay, we are defenseless and cannot allow any of
6745 the following to happen:
6746
6747 1) garbage collection
6748 2) QUIT
6749 3) any non-local exits
6750 4) frame size changes
6751 5) deletion of any buffers, windows, frames, etc.
6752 6) modification of buffer text
6753 7) reentrant entry of redisplay (see the stack trace above
6754 generate_displayable_area())
6755
6756 The general reason is that the redisplay code is written to assume that
6757 it is the only code running, and thus (a) cannot tolerate structures
6758 changed out from under it (hence 1, 4, 5, 6, 7) and (b) at various points
6759 within redisplay the redisplay structures may be in an inconsistent
6760 state and there are no unwind-protects to clean the structures up in
6761 case of non-local exit (hence 2, 3). Fixing redisplay to address these
6762 issues is hard and perhaps not worth it (and might slow things down a
6763 fair amount). We address 1, 4, 5 and 6 ourselves inside of
6764 enter_redisplay_critical_section() by simply inhibiting them, but we
6765 cannot handle 2 and 3, which must be handled at the actual point where
6766 they may occur (especially, internal_equal() or any place that may call
6767 Lisp), by wrapping the code in call_trapping_problems() or
6768 call_with_suspended_errors(). [[ NOTE: We could address QUIT by inhibiting
6769 it but this would be anti-social because it would prevent the user from
6770 interrupting any Lisp code called within the critical section. With the
6771 call_*() wrapping, C-g will interrupt the Lisp code and throw back to
6772 the innermost wrapping. ]] In fact we do turn off QUIT handling, since
6773 it's just too dangerous otherwise. See below.
6774
6775 Code calling enter_redisplay_critical_section() must check for reentrancy
6776 (#7) and take appropriate corrective action.
6777
6778 To help debug potential problems, we arrange (when
6779 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every time
6780 we execute QUIT or call Lisp code unless proper wrapping is in place, as
6781 well as further checks when we actually Fsignal(), Fthrow(),
6782 garbage_collect_1().
6783
6784 #### If a frame-size change does occur we should probably actually be
6785 preempting redisplay. */
6786
6787 /* Count of number of recursive times we call
6788 enter_redisplay_critical_section() or
6789 enter_redisplay_critical_section_maybe().
6790 enter_redisplay_critical_section() cannot occur reentrantly but we have
6791 to know in the *maybe() version whether to exit the section when we're
6792 done. */
6793 static int in_display_nesting;
6794
6795 static Lisp_Object
6796 end_hold_frame_size_changes (Lisp_Object obj)
6797 {
6798 if (!hold_frame_size_changes)
6799 {
6800 /* we used to have a function to do this for only one frame, and
6801 it was typical to call it at the end of a critical section
6802 (which occurs once per frame); but what then happens if multiple
6803 frames have frame changes held up?
6804
6805 This means we are O(N^2) over frames. I seriously doubt it matters.
6806 --ben */
6807 Lisp_Object frmcons, devcons, concons;
6808
6809 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6810 {
6811 struct frame *f = XFRAME (XCAR (frmcons));
6812 if (f->size_change_pending)
6813 change_frame_size (f, f->new_height, f->new_width, 0);
6814 }
6815 }
6816 return Qnil;
6817 }
6818
6819 /* Call this to temporarily prevent frame-size changes from being processed.
6820 To undo, use unbind_to(), passing it the value returned by this function.
6821 */
6822
6823 int
6824 begin_hold_frame_size_changes (void)
6825 {
6826 int depth = specpdl_depth ();
6827 record_unwind_protect (end_hold_frame_size_changes, Qnil);
6828 internal_bind_int (&hold_frame_size_changes, 1 + hold_frame_size_changes);
6829 return depth;
6830 }
6831
6832 int
6833 enter_redisplay_critical_section (void)
6834 {
6835 int depth = specpdl_depth ();
6836
6837 /* Reentrant entry is deadly. The calling function must check for this. */
6838 assert (!in_display);
6839 begin_hold_frame_size_changes ();
6840 /* Make sure in_display gets reset, but don't set it yet so that
6841 commit_ritual_suicide() can be used. */
6842 internal_bind_int (&in_display, 0);
6843 internal_bind_int (&in_display_nesting, 1 + in_display_nesting);
6844 #ifdef ERROR_CHECK_TRAPPING_PROBLEMS
6845 /* Force every call to QUIT to check for in_displayness. This will
6846 verify proper wrapping, as in the previous comment, aborting if not. */
6847 something_happened++;
6848 /* Verify that no nonlocal exits blow past us. */
6849 record_unwind_protect (commit_ritual_suicide, Qnil);
6850 #endif
6851 in_display++;
6852
6853 set_trapping_problems_flags (INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY);
6854 /* Even checking for QUIT can cause arbitrary Lisp code to be executed,
6855 e.g. through a menu handler. We really don't want that happening
6856 inside of redisplay. Code that we `eval' is at least written with the
6857 expectation that it's inside of redisplay, and shouldn't try anything
6858 weird; but that's not the case for menu code (e.g. custom loads huge
6859 amounts of LISP FILES from a menu handler! FMH!). Safest just to turn
6860 this off. We could turn it on using UNINHIBIT_QUIT or
6861 begin_do_check_for_quit() in certain places if we want, if we know
6862 it's not in an especially tricky place. */
6863 begin_dont_check_for_quit ();
6864 return depth;
6865 }
6866
6867 void
6868 exit_redisplay_critical_section (int depth)
6869 {
6870 in_display--;
6871 assert (!in_display);
6872 unbind_to (depth);
6873
6874 run_post_redisplay_actions ();
6875 }
6876
6877 /* Enter the redisplay critical section if we're not already in it. This
6878 is for code that needs frame changes held up and other protections from
6879 being inside, but doesn't modify the redisplay structures, and doesn't
6880 look at them in a way that they will be confused by inconsistencies. */
6881
6882 int
6883 enter_redisplay_critical_section_maybe (void)
6884 {
6885 if (!in_display)
6886 return enter_redisplay_critical_section ();
6887 else
6888 return internal_bind_int (&in_display_nesting, 1 + in_display_nesting);
6889 }
6890
6891 void
6892 exit_redisplay_critical_section_maybe (int depth)
6893 {
6894 if (in_display_nesting == 1)
6895 exit_redisplay_critical_section (depth);
6896 else
6897 unbind_to (depth);
6898 }
6899
6583 /* Ensure that all windows on the given frame are correctly displayed. 6900 /* Ensure that all windows on the given frame are correctly displayed.
6584 Return non-zero if pre-empted. */ 6901 Return non-zero if pre-empted. */
6585 6902
6586 int 6903 int
6587 redisplay_frame (struct frame *f, int preemption_check) 6904 redisplay_frame (struct frame *f, int preemption_check)
6589 struct device *d = XDEVICE (f->device); 6906 struct device *d = XDEVICE (f->device);
6590 int depth; 6907 int depth;
6591 6908
6592 assert (f->init_finished); 6909 assert (f->init_finished);
6593 6910
6911 /* NOTE: Without sufficient checks for stream frames, we got weird
6912 crashes in pdump. These came and went very easily -- adding the
6913 critical-section code for redisplay was enough to trigger them.
6914 Perhaps I should have debugged them but there didn't seem to be any
6915 point. --ben */
6594 if (FRAME_STREAM_P (f)) /* nothing to do */ 6916 if (FRAME_STREAM_P (f)) /* nothing to do */
6595 return 0; 6917 return 0;
6918
6919 /* Reentrancy into redisplay can be deadly. See stack trace above
6920 generate_displayable_area(). */
6921 if (in_display)
6922 return 1;
6596 6923
6597 if (preemption_check 6924 if (preemption_check
6598 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) 6925 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY))
6599 { 6926 {
6600 /* The preemption check itself takes a lot of time, 6927 /* The preemption check itself takes a lot of time,
6628 { 6955 {
6629 adjust_frame_size (f); 6956 adjust_frame_size (f);
6630 assert (!f->size_slipped); 6957 assert (!f->size_slipped);
6631 } 6958 }
6632 6959
6633 /* The menubar, toolbar, and icon updates must be done before 6960 /* The menubar, toolbar, and icon updates should be done before
6634 enter_redisplay_critical_section is called and we are officially 6961 enter_redisplay_critical_section is called and we are officially
6635 'in_display'. They may eval lisp code which may call QUIT. 6962 'in_display'. They is because they tend to eval Lisp code, which
6636 If in_display is set, QUIT will abort (unless the code is wrapped 6963 needs to be carefully wrapped within the critical section (and hence
6637 to protect against errors). */ 6964 is difficult to debug). */
6638 6965
6639 #ifdef HAVE_MENUBARS 6966 #ifdef HAVE_MENUBARS
6640 /* Update the menubar. It is done first since it could change 6967 /* Update the menubar. It is done first since it could change
6641 the menubar's visibility. This way we avoid having flashing 6968 the menubar's visibility. This way we avoid having flashing
6642 caused by an Expose event generated by the visibility change 6969 caused by an Expose event generated by the visibility change
6677 } 7004 }
6678 7005
6679 depth = enter_redisplay_critical_section (); 7006 depth = enter_redisplay_critical_section ();
6680 7007
6681 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ 7008 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6682 /* Within this section, we are defenseless and assume that the 7009
6683 following cannot happen: 7010 /* See comments in enter_redisplay_critical_section() */
6684
6685 1) garbage collection
6686 2) QUIT
6687 3) Any non-local exits
6688 4) frame size changes
6689
6690 We ensure (4) by calling enter_redisplay_critical_section(), which
6691 will cause any pending frame size changes to get put on hold
6692 till after the end of the critical section. (2) is required because
6693 of the possibility of (3). (2) and (3) mean that any place that
6694 can execute QUIT (e.g. internal_equal()), and especially any place
6695 that executes Lisp code, need to be properly wrapped to protect
6696 against these possibilities. This wrapping happens using
6697 call_trapping_problems(..., INHIBIT_GC), or related functions.
6698
6699 To help debug potential problems, we arrange (when
6700 ERROR_CHECK_TRAPPING_PROBLEMS is set) to crash automatically every
6701 time we execute QUIT or check to see whether garbage collection is
6702 necessary, inside of an unprotected critical section, as well as
6703 further checks when we actually Fsignal(), Fthrow(),
6704 garbage_collect_1().
6705
6706 #### If a frame-size change does occur we should probably
6707 actually be preempting redisplay. */
6708 7011
6709 MAYBE_DEVMETH (d, frame_output_begin, (f)); 7012 MAYBE_DEVMETH (d, frame_output_begin, (f));
6710 7013
6711 /* We can now update the gutters, safe in the knowledge that our 7014 /* We can now update the gutters, safe in the knowledge that our
6712 efforts won't get undone. */ 7015 efforts won't get undone. */
6713 7016
6714 /* This can call lisp, but redisplay is protected by binding 7017 /* This can call lisp, but redisplay is protected by binding
6715 inhibit_quit. More importantly the code involving display lines 7018 inhibit_quit. More importantly the code involving display lines
6716 *assumes* that GC will not happen and so does not GCPRO 7019 *assumes* that GC will not happen and so does not GCPRO
6717 anything. Since we use this code the whole time with the gutters 7020 anything. Since we use this code the whole time with the gutters
6718 we cannot allow GC to happen when manipulating the gutters. */ 7021 we cannot allow GC to happen when manipulating the gutters.
7022
7023 This must be inside of the critical section for various reasons.
7024 For example, it messes with display structures, which be left in
7025 an inconsistent state. */
6719 update_frame_gutters (f); 7026 update_frame_gutters (f);
6720 7027
6721 /* Erase the frame before outputting its contents. */ 7028 /* Erase the frame before outputting its contents. */
6722 if (f->clear) 7029 if (f->clear)
6723 { 7030 {
6918 #endif /* ERROR_CHECK_DISPLAY */ 7225 #endif /* ERROR_CHECK_DISPLAY */
6919 7226
6920 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay); 7227 PROFILE_RECORD_EXITING_SECTION (QSin_redisplay);
6921 } 7228 }
6922 7229
6923 /* Note: All places in the C code that call redisplay() are prepared 7230 /* Note: All places in the C code that call redisplay() are prepared to
6924 to handle GCing. However, we can't currently handle GC inside the 7231 handle GCing, which can happen from run_pre_idle_hook(). However, we
6925 guts of redisplay (#### someone should fix this), so we need to use 7232 can't currently handle GC inside the guts of redisplay; see
6926 INHIBIT_GC when calling Lisp. 7233 enter_redisplay_critical_section().
6927
6928 #### We probably can't handle any deletion of existing buffers, frames,
6929 windows, devices, consoles, text changes, etc. either. We should
6930
6931 (a) Create the appropriate INHIBIT_ flags for this.
6932 (b) In the longer run, fix redisplay to handle this.
6933 7234
6934 (#### What about other external entry points to the redisplay code? 7235 (#### What about other external entry points to the redisplay code?
6935 Someone should go through and make sure that all callers can handle 7236 Someone should go through and make sure that all callers can handle
6936 GC there, too.) 7237 GC there, too.)
6937 */ 7238 */
6965 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker) 7266 eval_within_redisplay (Lisp_Object dont_trust_this_damn_sucker)
6966 { 7267 {
6967 return 7268 return
6968 eval_in_buffer_trapping_problems 7269 eval_in_buffer_trapping_problems
6969 ("Error calling function within redisplay", current_buffer, 7270 ("Error calling function within redisplay", current_buffer,
6970 dont_trust_this_damn_sucker, 7271 dont_trust_this_damn_sucker, 0);
6971 INHIBIT_GC | INHIBIT_ANY_CHANGE_AFFECTING_REDISPLAY);
6972 } 7272 }
6973 7273
6974 /* Efficiently determine the window line number, and return a pointer 7274 /* Efficiently determine the window line number, and return a pointer
6975 to its printed representation. Do this regardless of whether 7275 to its printed representation. Do this regardless of whether
6976 line-number-mode is on. The first line in the buffer is counted as 7276 line-number-mode is on. The first line in the buffer is counted as
7306 int block; 7606 int block;
7307 7607
7308 if (dl->display_blocks) 7608 if (dl->display_blocks)
7309 { 7609 {
7310 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++) 7610 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
7311 { 7611 {
7312 struct display_block *db = Dynarr_atp (dl->display_blocks, block); 7612 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
7313 7613
7314 Dynarr_free (db->runes); 7614 Dynarr_free (db->runes);
7315 } 7615 }
7316 7616
9118 */ 9418 */
9119 ()) 9419 ())
9120 { 9420 {
9121 Lisp_Object devcons, concons; 9421 Lisp_Object devcons, concons;
9122 9422
9423 if (in_display)
9424 return Qnil;
9425
9123 DEVICE_LOOP_NO_BREAK (devcons, concons) 9426 DEVICE_LOOP_NO_BREAK (devcons, concons)
9124 { 9427 {
9125 struct device *d = XDEVICE (XCAR (devcons)); 9428 struct device *d = XDEVICE (XCAR (devcons));
9126 Lisp_Object frmcons; 9429 Lisp_Object frmcons;
9127 9430
9659 vars_of_redisplay (void) 9962 vars_of_redisplay (void)
9660 { 9963 {
9661 QSin_redisplay = build_msg_string ("(in redisplay)"); 9964 QSin_redisplay = build_msg_string ("(in redisplay)");
9662 staticpro (&QSin_redisplay); 9965 staticpro (&QSin_redisplay);
9663 9966
9967 Vpost_redisplay_actions = Qnil;
9968 staticpro (&Vpost_redisplay_actions);
9969
9664 #if 0 9970 #if 0
9665 staticpro (&last_arrow_position); 9971 staticpro (&last_arrow_position);
9666 staticpro (&last_arrow_string); 9972 staticpro (&last_arrow_string);
9667 last_arrow_position = Qnil; 9973 last_arrow_position = Qnil;
9668 last_arrow_string = Qnil; 9974 last_arrow_string = Qnil;