Mercurial > hg > xemacs-beta
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; |