X-Git-Url: http://git.chise.org/gitweb/?p=chise%2Fxemacs-chise.git.1;a=blobdiff_plain;f=src%2Fredisplay.c;h=dc7048e9f90611873e02a175039c1c904d7b07d9;hp=c3ef67cd800530e689c0f368de6489dbb696fa7c;hb=21db8709c0c2dcedbd278c7fe571290d5ce80a71;hpb=3890a2e3064a7f562107c58e59d928284ec04741 diff --git a/src/redisplay.c b/src/redisplay.c index c3ef67c..dc7048e 100644 --- a/src/redisplay.c +++ b/src/redisplay.c @@ -40,7 +40,6 @@ Boston, MA 02111-1307, USA. */ #include #include "lisp.h" -#include #include "buffer.h" #include "commands.h" @@ -64,11 +63,10 @@ Boston, MA 02111-1307, USA. */ #include "file-coding.h" #endif +#include "sysfile.h" + #ifdef HAVE_TTY #include "console-tty.h" -#ifdef HAVE_UNISTD_H -#include /* for isatty() */ -#endif #endif /* HAVE_TTY */ /* Note: We have to be careful throughout this code to properly handle @@ -87,16 +85,10 @@ Boston, MA 02111-1307, USA. */ #define LEFT_GLYPHS 2 #define RIGHT_GLYPHS 3 -/* Set the vertical clip to 0 if we are currently updating the line - start cache. Otherwise for buffers of line height 1 it may fail to - be able to work properly because regenerate_window will not layout - a single line. */ #define VERTICAL_CLIP(w, display) \ - (updating_line_start_cache \ - ? 0 \ - : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \ + ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \ ? INT_MAX \ - : vertical_clip)) + : vertical_clip) /* The following structures are completely private to redisplay.c so we put them here instead of in a header file, for modularity. */ @@ -308,7 +300,7 @@ static Bytecount_dynarr *formatted_string_extent_end_dynarr; /* #### probably temporary */ -int cache_adjustment; +Fixnum cache_adjustment; /* This holds a string representing the text corresponding to a single modeline % spec. */ @@ -323,13 +315,10 @@ int disable_preemption; /* Used for debugging redisplay and for static int preemption_count; /* Minimum pixel height of clipped bottom display line. */ -int vertical_clip; +Fixnum vertical_clip; /* Minimum visible pixel width of clipped glyphs at right margin. */ -int horizontal_clip; - -/* Set if currently inside update_line_start_cache. */ -static int updating_line_start_cache; +Fixnum horizontal_clip; /* Nonzero means reading single-character input with prompt so put cursor on minibuffer after the prompt. */ @@ -364,8 +353,7 @@ int frame_changed; int glyphs_changed; int glyphs_changed_set; -/* non-zero if any displayed subwindow is in need of updating - somewhere. */ +/* non-zero if any subwindow has been deleted. */ int subwindows_changed; int subwindows_changed_set; @@ -419,9 +407,9 @@ int windows_structure_changed; Lisp_Object Vbar_cursor; Lisp_Object Qbar_cursor; -int visible_bell; /* If true and the terminal will support it - then the frame will flash instead of - beeping when an error occurs */ +Lisp_Object Vvisible_bell; /* If true and the terminal will support it + then the frame will flash instead of + beeping when an error occurs */ /* Nonzero means no need to redraw the entire frame on resuming a suspended Emacs. This is useful on terminals with multiple pages, @@ -437,10 +425,10 @@ Lisp_Object Vglobal_mode_string; /* The number of lines scroll a window by when point leaves the window; if it is <=0 then point is centered in the window */ -int scroll_step; +Fixnum scroll_step; /* Scroll up to this many lines, to bring point back on screen. */ -int scroll_conservatively; +Fixnum scroll_conservatively; /* Marker for where to display an arrow on top of the buffer text. */ Lisp_Object Voverlay_arrow_position; @@ -451,6 +439,9 @@ Lisp_Object Vwindow_size_change_functions; Lisp_Object Vwindow_scroll_functions; Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions; +Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook; + + #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about this more. */ #ifndef INHIBIT_REDISPLAY_HOOKS @@ -460,7 +451,8 @@ Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook; Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook; #endif /* INHIBIT_REDISPLAY_HOOKS */ -static int last_display_warning_tick, display_warning_tick; +static Fixnum last_display_warning_tick; +static Fixnum display_warning_tick; Lisp_Object Qdisplay_warning_buffer; int inhibit_warning_display; @@ -471,8 +463,9 @@ Lisp_Object Vtext_cursor_visible_p; int column_number_start_at_one; -#define WINDOW_SCROLLED(w) \ -(w->hscroll > 0 || w->left_xoffset) +Lisp_Object Qtop_bottom; + +#define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset) /***************************************************************************/ @@ -803,7 +796,7 @@ add_hscroll_rune (pos_data *data) gb.glyph = Vhscroll_glyph; { int oldpixpos = data->pixpos; - retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, + retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, GLYPH_CACHEL (XWINDOW (data->window), HSCROLL_GLYPH_INDEX)); data->hscroll_glyph_width_adjust = @@ -923,9 +916,7 @@ add_emchar_rune (pos_data *data) else if (data->is_modeline) crb->bufpos = data->modeline_charpos; else - /* fuckme if this shouldn't be an abort. */ - /* abort (); fuckme harder, this abort gets tripped quite often, - in propagation and whatnot. #### fixme */ + /* Text but not in buffer */ crb->bufpos = 0; crb->type = RUNE_CHAR; crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch; @@ -981,6 +972,8 @@ add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string, for (pos = c_string; pos < end;) { + Bufbyte *old_pos = pos; + data->ch = charptr_emchar (pos); prop = add_emchar_rune (data); @@ -1006,6 +999,9 @@ add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string, } INC_CHARPTR (pos); assert (pos <= end); + /* #### Duplicate code from add_string_to_fstring_db_runes + should we do more?*/ + data->bytepos += pos - old_pos; } return NULL; @@ -1320,6 +1316,7 @@ add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) case '%': dst += set_charptr_emchar (dst, '%'); break; + /* #### unimplemented */ } } } @@ -1528,10 +1525,12 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, glyph sizes might have changed too */ invalidate_glyph_geometry_maybe (gb->glyph, w); - /* This makes sure the glyph is in the cachels. + /* This makes sure the glyph is in the cachels. - #### We need to change this so that we hold onto the glyph_index - here, not the glyph itself. */ + #### We do this to make sure the glyph is in the glyph cachels, + so that the dirty flag can be reset after redisplay has + finished. We should do this some other way, maybe by iterating + over the window cache of subwindows. */ get_glyph_cachel_index (w, gb->glyph); /* A nil extent indicates a special glyph (ex. truncator). */ @@ -1539,7 +1538,8 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, || (pos_type == BEGIN_GLYPHS && extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) || (pos_type == END_GLYPHS && - extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)) + extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) + || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) { struct rune rb; int width; @@ -1547,6 +1547,8 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, int ascent, descent; Lisp_Object baseline; Lisp_Object face; + Lisp_Object instance; + face_index findex; if (cachel) width = cachel->width; @@ -1658,10 +1660,32 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, face = glyph_face (gb->glyph, data->window); if (NILP (face)) - rb.findex = data->findex; + findex = data->findex; else - rb.findex = get_builtin_face_cache_index (w, face); + findex = get_builtin_face_cache_index (w, face); + instance = glyph_image_instance (gb->glyph, data->window, + ERROR_ME_NOT, 1); + if (TEXT_IMAGE_INSTANCEP (instance)) + { + Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); + face_index orig_findex = data->findex; + Bytind orig_bufpos = data->bi_bufpos; + Bytind orig_start_col_enabled = data->bi_start_col_enabled; + + data->findex = findex; + data->bi_start_col_enabled = 0; + if (!allow_cursor) + data->bi_bufpos = 0; + add_bufbyte_string_runes (data, XSTRING_DATA (string), + XSTRING_LENGTH (string), 0); + data->findex = orig_findex; + data->bi_bufpos = orig_bufpos; + data->bi_start_col_enabled = orig_start_col_enabled; + return NULL; + } + + rb.findex = findex; rb.xpos = data->pixpos; rb.width = width; rb.bufpos = 0; /* glyphs are never "at" anywhere */ @@ -1672,13 +1696,6 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, else rb.endpos = 0; rb.type = RUNE_DGLYPH; - /* #### Ben sez: this is way bogus if the glyph is a string. - You should not make the output routines have to cope with - this. The string could contain Mule characters, or non- - printable characters, or characters to be passed through - the display table, or non-character objects (when this gets - implemented), etc. Instead, this routine here should parse - the string into a series of runes. */ rb.object.dglyph.glyph = gb->glyph; rb.object.dglyph.extent = gb->extent; rb.object.dglyph.xoffset = xoffset; @@ -1881,6 +1898,7 @@ create_text_block (struct window *w, struct display_line *dl, dl->used_prop_data = 0; dl->num_chars = 0; + dl->line_continuation = 0; xzero (data); data.ef = extent_fragment_new (w->buffer, f); @@ -2471,11 +2489,12 @@ done: /* data.bi_bufpos is already at the start of the next line. */ + dl->line_continuation = 1; gb.glyph = Vcontinuation_glyph; cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); } - add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel); + add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b) && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n') @@ -2723,8 +2742,26 @@ add_margin_runes (struct display_line *dl, struct display_block *db, int start, ? dl->left_glyphs : dl->right_glyphs); int elt, end; - int xpos = start; int reverse; + struct window *w = XWINDOW (window); + struct frame *f = XFRAME (w->frame); + struct device *d = XDEVICE (f->device); + pos_data data; + + xzero (data); + data.d = d; + data.window = window; + data.db = db; + data.dl = dl; + data.pixpos = start; + data.cursor_type = NO_CURSOR; + data.cursor_x = -1; + data.last_charset = Qunbound; + data.last_findex = DEFAULT_INDEX; + data.result_str = Qnil; + data.string = Qnil; + data.new_ascent = dl->ascent; + data.new_descent = dl->descent; if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) @@ -2753,79 +2790,31 @@ add_margin_runes (struct display_line *dl, struct display_block *db, int start, || (side == RIGHT_GLYPHS && extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) { - struct rune rb; - - rb.width = gb->width; - rb.findex = gb->findex; - rb.xpos = xpos; - rb.bufpos = -1; - rb.endpos = 0; - rb.type = RUNE_DGLYPH; - rb.object.dglyph.glyph = gb->glyph; - rb.object.dglyph.extent = gb->extent; - rb.object.dglyph.xoffset = 0; - rb.cursor_type = CURSOR_OFF; - - Dynarr_add (db->runes, rb); - xpos += rb.width; + data.findex = gb->findex; + data.max_pixpos = data.pixpos + gb->width; + add_glyph_rune (&data, gb, side, 0, NULL); count--; gb->active = 0; - - if (glyph_contrib_p (gb->glyph, window)) - { - unsigned short ascent, descent; - Lisp_Object baseline = glyph_baseline (gb->glyph, window); - - ascent = glyph_ascent (gb->glyph, window); - descent = glyph_descent (gb->glyph, window); - - /* A pixmap that has not had a baseline explicitly set. - We use the existing ascent / descent ratio of the - line. */ - if (NILP (baseline)) - { - int gheight = ascent + descent; - int line_height = dl->ascent + dl->descent; - int pix_ascent, pix_descent; - - pix_descent = (int) (gheight * dl->descent) / line_height; - pix_ascent = gheight - pix_descent; - - dl->ascent = max ((int) dl->ascent, pix_ascent); - dl->descent = max ((int) dl->descent, pix_descent); - } - - /* A string so determine contribution normally. */ - else if (EQ (baseline, Qt)) - { - dl->ascent = max (dl->ascent, ascent); - dl->descent = max (dl->descent, descent); - } - - /* A pixmap with an explicitly set baseline. We determine the - contribution here. */ - else if (INTP (baseline)) - { - int height = ascent + descent; - int pix_ascent, pix_descent; - - pix_ascent = height * XINT (baseline) / 100; - pix_descent = height - pix_ascent; - - dl->ascent = max ((int) dl->ascent, pix_ascent); - dl->descent = max ((int) dl->descent, pix_descent); - } - - /* Otherwise something is screwed up. */ - else - abort (); - } } (reverse ? elt-- : elt++); } - return xpos; + if (data.max_pixmap_height) + { + int height = data.new_ascent + data.new_descent; + int pix_ascent, pix_descent; + + pix_descent = data.max_pixmap_height * data.new_descent / height; + pix_ascent = data.max_pixmap_height - pix_descent; + data.new_ascent = max (data.new_ascent, pix_ascent); + data.new_descent = max (data.new_descent, pix_descent); + } + + dl->ascent = data.new_ascent; + dl->descent = data.new_descent; + + return data.pixpos; } /* Add a blank to a margin display block. */ @@ -3516,7 +3505,7 @@ generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, /* result_str is nil when we're building a frame or icon title. Otherwise, we're building a modeline, so the offset starts at the modeline - horizontal scrolling ammount */ + horizontal scrolling amount */ if (! NILP (result_str)) offset = w->modeline_hscroll; generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, @@ -3553,6 +3542,8 @@ generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, Bufbyte *strdata; struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); + in_modeline_generation = 1; + detach_all_extents (result_str); resize_string (XSTRING (result_str), -1, data.bytepos - XSTRING_LENGTH (result_str)); @@ -3589,6 +3580,8 @@ generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, Dynarr_at (formatted_string_extent_end_dynarr, elt), result_str); } + + in_modeline_generation = 0; } } @@ -3632,10 +3625,6 @@ generate_modeline (struct window *w, struct display_line *dl, int type) /* The modeline is at the bottom of the gutters. */ dl->ypos = WINDOW_BOTTOM (w); - /* adjust for the bottom gutter */ - if (window_is_lowest (w)) - dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f); - rb.findex = MODELINE_INDEX; rb.xpos = dl->bounds.left_out; rb.width = dl->bounds.right_out - dl->bounds.left_out; @@ -3689,9 +3678,6 @@ generate_modeline (struct window *w, struct display_line *dl, int type) set this until we've generated the modeline in order to account for any embedded faces. */ dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj; - /* adjust for the bottom gutter */ - if (window_is_lowest (w)) - dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f); } static Charcount @@ -3989,8 +3975,8 @@ tail_recurse: * - If first element is another symbol, process the cadr or caddr * recursively according to whether the symbol's value is non-nil or * nil. - * - If first element is a face, process the cdr recursively - * without altering the depth. + * - If first element is an extent, process the cdr recursively + * and handle the extent's face. */ Lisp_Object car, tem; @@ -4303,9 +4289,9 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, int truncate_win = b ? window_truncation_on (w) : 0; int end_glyph_width = 0; - /* we're going to ditch selective display for static text, its an - FSF thing and invisble extents are the way to go - here. Implementing it also relies on a number of buffer-specific + /* We're going to ditch selective display for static text, it's an + FSF thing and invisible extents are the way to go here. + Implementing it also relies on a number of buffer-specific functions that we don't have the luxury of being able to use here. */ @@ -4371,6 +4357,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, dl->used_prop_data = 0; dl->num_chars = 0; + dl->line_continuation = 0; /* set up faces to use for clearing areas, used by output_display_line */ @@ -4528,7 +4515,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, goto done; } - /* #### What if we we're dealing with a display table? */ + /* #### What if we're dealing with a display table? */ if (data.start_col) data.start_col--; @@ -4763,6 +4750,7 @@ done: /* data.bi_bufpos is already at the start of the next line. */ + dl->line_continuation = 1; gb.glyph = Vcontinuation_glyph; cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); } @@ -5104,6 +5092,7 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type) int ypos = WINDOW_TEXT_TOP (w); int yend; /* set farther down */ int yclip = WINDOW_TEXT_TOP_CLIP (w); + int force; prop_block_dynarr *prop; layout_bounds bounds; @@ -5157,7 +5146,14 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type) else prop = 0; - while (ypos < yend) + /* When we are computing things for scrolling purposes, make + sure at least one line is always generated */ + force = (type == CMOTION_DISP); + + /* Make sure this is set always */ + /* Note the conversion at end */ + w->window_end_pos[type] = start_pos; + while (ypos < yend || force) { struct display_line dl; struct display_line *dlp; @@ -5210,7 +5206,7 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type) the top clip and the bottom clip. */ visible_height -= (dlp->clip + dlp->top_clip); - if (visible_height < VERTICAL_CLIP (w, 1)) + if (visible_height < VERTICAL_CLIP (w, 1) && !force) { if (local) free_display_line (dlp); @@ -5254,16 +5250,22 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type) generate_display_line call. */ if (start_pos > BUF_ZV (b)) break; + + force = 0; } if (prop) Dynarr_free (prop); /* #### More not quite right, but close enough. */ - /* #### Ben sez: apparently window_end_pos[] is measured + /* Ben sez: apparently window_end_pos[] is measured as the number of characters between the window end and the end of the buffer? This seems rather weirdo. What's - the justification for this? */ + the justification for this? + + JV sez: Because BUF_Z (b) would be a good initial value, however + that can change. This representation allows initalizing with 0. + */ w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; if (need_modeline) @@ -5594,20 +5596,9 @@ regenerate_window_incrementally (struct window *w, Bufpos startp, assert (cdl->end_bufpos == ddl->end_bufpos); assert (cdl->offset == ddl->offset); - /* If the last rune is already a continuation glyph, fail. - #### We should be able to handle this better. */ - { - struct display_block *db = get_display_block_from_line (ddl, TEXT); - if (Dynarr_length (db->runes)) - { - struct rune *rb = - Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); - - if (rb->type == RUNE_DGLYPH - && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)) - return 0; - } - } + /* If the line continues to next display line, fail. */ + if (ddl->line_continuation) + return 0; /* If the line was generated using propagation data, fail. */ if (ddl->used_prop_data) @@ -5625,19 +5616,9 @@ regenerate_window_incrementally (struct window *w, Bufpos startp, return 0; } - /* If the last rune is now a continuation glyph, fail. */ - { - struct display_block *db = get_display_block_from_line (ddl, TEXT); - if (Dynarr_length (db->runes)) - { - struct rune *rb = - Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); - - if (rb->type == RUNE_DGLYPH - && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)) - return 0; - } - } + /* If the line continues to next display line, fail. */ + if (ddl->line_continuation) + return 0; /* If any line position parameters have changed or a cursor has disappeared or disappeared, fail. */ @@ -6013,7 +5994,7 @@ redisplay_window (Lisp_Object window, int skip_selected) && !(MINI_WINDOW_P (w) && f->buffers_changed) && !f->frame_changed && !truncation_changed - /* check whether start is really at the begining of a line GE */ + /* check whether start is really at the beginning of a line GE */ && (!w->start_at_line_beg || beginning_of_line_p (b, startp)) ) { @@ -6290,12 +6271,13 @@ call_redisplay_end_triggers (struct window *w, void *closure) /* Ensure that all windows on the given frame are correctly displayed. */ -static int +int redisplay_frame (struct frame *f, int preemption_check) { struct device *d = XDEVICE (f->device); - if (preemption_check) + if (preemption_check + && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) { /* The preemption check itself takes a lot of time, so normally don't do it here. We do it if called @@ -6307,6 +6289,16 @@ redisplay_frame (struct frame *f, int preemption_check) return 1; } + if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) + { + Lisp_Object frame; + + f->old_buffer_alist = Freplace_list (f->old_buffer_alist, + f->buffer_alist); + XSETFRAME (frame, f); + va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); + } + /* Before we put a hold on frame size changes, attempt to process any which are already pending. */ if (f->size_change_pending) @@ -6332,47 +6324,33 @@ redisplay_frame (struct frame *f, int preemption_check) being handled. */ update_frame_menubars (f); #endif /* HAVE_MENUBARS */ - /* widgets are similar to menus in that they can call lisp to - determine activation etc. Therefore update them before we get - into redisplay. This is primarily for connected widgets such as - radio buttons. */ - update_frame_subwindows (f); #ifdef HAVE_TOOLBARS /* Update the toolbars. */ update_frame_toolbars (f); #endif /* HAVE_TOOLBARS */ + /* Gutter update proper has to be done inside display when no frame + size changes can occur, thus we separately update the gutter + geometry here if it needs it. */ + update_frame_gutter_geometry (f); /* If we clear the frame we have to force its contents to be redrawn. */ if (f->clear) f->frame_changed = 1; - /* invalidate the subwindow cache. We use subwindows_changed here to - cause subwindows to get instantiated. This is because + /* Invalidate the subwindow caches. We use subwindows_changed here + to cause subwindows to get instantiated. This is because subwindows_state_changed is less strict - dealing with things like the clicked state of button. We have to do this before redisplaying the gutters as subwindows get unmapped in the process.*/ - if (!Dynarr_length (f->subwindow_cachels) - || f->subwindows_changed - || f->faces_changed - || f->frame_changed) + if (f->frame_changed) + reset_frame_subwindow_instance_cache (f); + + if (f->frame_changed || f->subwindows_changed) { - reset_subwindow_cachels (f); /* we have to do this so the gutter gets regenerated. */ reset_gutter_display_lines (f); } - else - mark_subwindow_cachels_as_not_updated (f); - - /* We can now update the gutters, safe in the knowledge that our - efforts won't get undone. */ - - /* #### This can call lisp, it may be that if the subwindow cachels - have been reset there are no remaining references to the - displayed glyphs and so they get garbage collected. We should - consider putting this call inside the critical redisplay - section. */ - update_frame_gutters (f); hold_frame_size_changes (); @@ -6400,10 +6378,22 @@ redisplay_frame (struct frame *f, int preemption_check) #### If a frame-size change does occur we should probably actually be preempting redisplay. */ + MAYBE_DEVMETH (d, frame_output_begin, (f)); + + /* We can now update the gutters, safe in the knowledge that our + efforts won't get undone. */ + + /* This can call lisp, but redisplay is protected by binding + inhibit_quit. More importantly the code involving display lines + *assumes* that GC will not happen and so does not GCPRO + anything. Since we use this code the whole time with the gutters + we cannot allow GC to happen when manipulating the gutters. */ + update_frame_gutters (f); + /* Erase the frame before outputting its contents. */ if (f->clear) { - DEVMETH (d, clear_frame, (f)); + MAYBE_DEVMETH (d, clear_frame, (f)); } /* Do the selected window first. */ @@ -6412,11 +6402,7 @@ redisplay_frame (struct frame *f, int preemption_check) /* Then do the rest. */ redisplay_windows (f->root_window, 1); - /* We now call the output_end routine for tty frames. We delay - doing so in order to avoid cursor flicker. So much for 100% - encapsulation. */ - if (FRAME_TTY_P (f)) - DEVMETH (d, output_end, (d)); + MAYBE_DEVMETH (d, frame_output_end, (f)); update_frame_title (f); @@ -6451,27 +6437,29 @@ static int redisplay_device (struct device *d, int automatic) { Lisp_Object frame, frmcons; - int preempted = 0; int size_change_failed = 0; struct frame *f; - if (automatic - && (MAYBE_INT_DEVMETH (d, device_implementation_flags, ()) - & XDEVIMPF_NO_AUTO_REDISPLAY)) + if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) return 0; if (DEVICE_STREAM_P (d)) /* nothing to do */ return 0; /* It is possible that redisplay has been called before the - device is fully initialized. If so then continue with the - next device. */ + device is fully initialized, or that the console implementation + allows frameless devices. If so then continue with the next + device. */ if (NILP (DEVICE_SELECTED_FRAME (d))) return 0; - REDISPLAY_PREEMPTION_CHECK; - if (preempted) - return 1; + if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) + { + int preempted; + REDISPLAY_PREEMPTION_CHECK; + if (preempted) + return 1; + } /* Always do the selected frame first. */ frame = DEVICE_SELECTED_FRAME (d); @@ -6485,12 +6473,11 @@ redisplay_device (struct device *d, int automatic) { if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) { - preempted = redisplay_frame (f, 0); + int preempted = redisplay_frame (f, 0); + if (preempted) + return 1; } - if (preempted) - return 1; - /* If the frame redisplay did not get preempted, then this flag should have gotten set to 0. It might be possible for that not to happen if a size change event were to occur at an odd @@ -6515,12 +6502,11 @@ redisplay_device (struct device *d, int automatic) { if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) { - preempted = redisplay_frame (f, 0); + int preempted = redisplay_frame (f, 0); + if (preempted) + return 1; } - if (preempted) - return 1; - if (f->size_change_pending) size_change_failed = 1; } @@ -7114,6 +7100,10 @@ mark_redisplay (void) FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) { struct frame *f = XFRAME (XCAR (frmcons)); + /* #### urk! this does tons o' crap, such as creating lots of + structs, doing window system actions, etc. we DO NOT want to + be doing this -- marking should never change any state. + i think we can just delete this. --ben */ update_frame_window_mirror (f); mark_window_mirror (f->root_mirror); mark_gutters (f); @@ -7553,11 +7543,18 @@ point_would_be_visible (struct window *w, Bufpos startp, Bufpos point) displayed. The end of the last line is also know as the window end position. + WARNING: It is possible that redisplay failed to layout any lines for the + windows. Under normal circumstances this is rare. However it seems that it + does occur in the following situation: A mouse event has come in and we + need to compute its location in a window. That code (in + pixel_to_glyph_translation) already can handle 0 as an error return value. + #### With a little work this could probably be reworked as just a call to start_with_line_at_pixpos. */ static Bufpos -start_end_of_last_line (struct window *w, Bufpos startp, int end) +start_end_of_last_line (struct window *w, Bufpos startp, int end, + int may_error) { struct buffer *b = XBUFFER (w->buffer); line_start_cache_dynarr *cache = w->line_start_cache; @@ -7577,7 +7574,7 @@ start_end_of_last_line (struct window *w, Bufpos startp, int end) start_elt = point_in_line_start_cache (w, cur_start, 0); if (start_elt == -1) - abort (); /* this had better never happen */ + return may_error ? 0 : startp; while (1) { @@ -7641,7 +7638,7 @@ start_end_of_last_line (struct window *w, Bufpos startp, int end) Bufpos start_of_last_line (struct window *w, Bufpos startp) { - return start_end_of_last_line (w, startp, 0); + return start_end_of_last_line (w, startp, 0 , 0); } /* For the given window W, if display starts at STARTP, what will be @@ -7651,9 +7648,16 @@ start_of_last_line (struct window *w, Bufpos startp) Bufpos end_of_last_line (struct window *w, Bufpos startp) { - return start_end_of_last_line (w, startp, 1); + return start_end_of_last_line (w, startp, 1, 0); +} + +static Bufpos +end_of_last_line_may_error (struct window *w, Bufpos startp) +{ + return start_end_of_last_line (w, startp, 1, 1); } + /* For window W, what does the starting position have to be so that the line containing POINT will cover pixel position PIXPOS. */ @@ -7837,7 +7841,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, validate_line_start_cache (w); w->line_cache_validation_override++; - updating_line_start_cache = 1; if (from < BUF_BEGV (b)) from = BUF_BEGV (b); @@ -7846,7 +7849,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, if (from > to) { - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -7859,7 +7861,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, /* Check to see if the desired range is already in the cache. */ if (from >= low_bound && to <= high_bound) { - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -7888,7 +7889,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, update_internal_cache_list (w, DESIRED_DISP); if (!Dynarr_length (internal_cache)) { - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -7916,7 +7916,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, { Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), Dynarr_length (internal_cache)); - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -7925,7 +7924,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, the bounds of the DESIRED structs in the first place. */ if (start >= low_bound && end <= high_bound) { - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -7948,7 +7946,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, Dynarr_reset (cache); Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), Dynarr_length (internal_cache)); - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -7974,7 +7971,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, Dynarr_reset (cache); Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), Dynarr_length (internal_cache)); - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -7983,7 +7979,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, Dynarr_length (internal_cache) - ic_elt); } - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -8003,23 +7998,9 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, update_internal_cache_list (w, CMOTION_DISP); /* If this assert is triggered then regenerate_window failed - to layout a single line. That is not supposed to be - possible because we impose a minimum height on the buffer - and override vertical clip when we are in here. */ - /* #### Ah, but it is because the window may temporarily - exist but not have any lines at all if the minibuffer is - real big. Look into that situation better. */ - if (!Dynarr_length (internal_cache)) - { - if (old_lb == -1 && low_bound == -1) - { - updating_line_start_cache = 0; - w->line_cache_validation_override--; - return; - } - - assert (Dynarr_length (internal_cache)); - } + to layout a single line. This is not possible since we + force at least a single line to be layout for CMOTION_DISP */ + assert (Dynarr_length (internal_cache)); assert (startp == Dynarr_atp (internal_cache, 0)->start); ic_elt = Dynarr_length (internal_cache) - 1; @@ -8065,7 +8046,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, startp = new_startp; if (startp > BUF_ZV (b)) { - updating_line_start_cache = 0; w->line_cache_validation_override--; return; } @@ -8099,7 +8079,6 @@ update_line_start_cache (struct window *w, Bufpos from, Bufpos to, while (to > high_bound); } - updating_line_start_cache = 0; w->line_cache_validation_override--; assert (to <= high_bound); } @@ -8807,7 +8786,7 @@ pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, if (!MARKERP ((*w)->start[CURRENT_DISP])) *closest = 0; else - *closest = end_of_last_line (*w, + *closest = end_of_last_line_may_error (*w, marker_position ((*w)->start[CURRENT_DISP])); *col = 0; UPDATE_CACHE_RETURN; @@ -8840,6 +8819,9 @@ Ensure that all minibuffers are correctly showing the echo area. if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) { Lisp_Object window = FRAME_MINIBUF_WINDOW (f); + + MAYBE_DEVMETH (d, frame_output_begin, (f)); + /* * If the frame size has changed, there may be random * chud on the screen left from previous messages @@ -8848,19 +8830,15 @@ Ensure that all minibuffers are correctly showing the echo area. */ if (f->echo_area_garbaged) { - DEVMETH (d, clear_frame, (f)); + MAYBE_DEVMETH (d, clear_frame, (f)); f->echo_area_garbaged = 0; } redisplay_window (window, 0); + MAYBE_DEVMETH (d, frame_output_end, (f)); + call_redisplay_end_triggers (XWINDOW (window), 0); } } - - /* We now call the output_end routine for tty frames. We delay - doing so in order to avoid cursor flicker. So much for 100% - encapsulation. */ - if (DEVICE_TTY_P (d)) - DEVMETH (d, output_end, (d)); } return Qnil; @@ -8895,6 +8873,9 @@ input and is guaranteed to proceed to completion. f->clear = 1; redisplay_frame (f, 1); + /* See the comment in Fredisplay_frame. */ + RESET_CHANGED_SET_FLAGS; + return unbind_to (count, Qnil); } @@ -8922,6 +8903,15 @@ input and is guaranteed to proceed to completion. redisplay_frame (f, 1); + /* If we don't reset the global redisplay flags here, subsequent + changes to the display will not get registered by redisplay + because it thinks it already has registered changes. If you + really knew what you were doing you could confuse redisplay by + calling Fredisplay_frame while updating another frame. We assume + that if you know what you are doing you will not be that + stupid. */ + RESET_CHANGED_SET_FLAGS; + return unbind_to (count, Qnil); } @@ -8951,6 +8941,9 @@ input and is guaranteed to proceed to completion. } redisplay_device (d, 0); + /* See the comment in Fredisplay_frame. */ + RESET_CHANGED_SET_FLAGS; + return unbind_to (count, Qnil); } @@ -8978,6 +8971,9 @@ input and is guaranteed to proceed to completion. redisplay_device (d, 0); + /* See the comment in Fredisplay_frame. */ + RESET_CHANGED_SET_FLAGS; + return unbind_to (count, Qnil); } @@ -9192,6 +9188,15 @@ init_redisplay (void) } #endif /* HAVE_X_WINDOWS */ +#ifdef HAVE_GTK + if (!strcmp (display_use, "gtk")) + { + Vwindow_system = Qgtk; + Vinitial_window_system = Qgtk; + return; + } +#endif + #ifdef HAVE_MS_WINDOWS if (!strcmp (display_use, "mswindows")) { @@ -9240,6 +9245,8 @@ syms_of_redisplay (void) defsymbol (&Qbar_cursor, "bar-cursor"); defsymbol (&Qredisplay_end_trigger_functions, "redisplay-end-trigger-functions"); + defsymbol (&Qtop_bottom, "top-bottom"); + defsymbol (&Qbuffer_list_changed_hook, "buffer-list-changed-hook"); DEFSUBR (Fredisplay_echo_area); DEFSUBR (Fredraw_frame); @@ -9251,15 +9258,8 @@ syms_of_redisplay (void) } void -reinit_vars_of_redisplay (void) -{ - updating_line_start_cache = 0; -} - -void vars_of_redisplay (void) { - reinit_vars_of_redisplay (); #if 0 staticpro (&last_arrow_position); @@ -9304,7 +9304,9 @@ See also `overlay-arrow-string'. Voverlay_arrow_position = Qnil; DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* -String to display as an arrow. See also `overlay-arrow-position'. +String or glyph to display as an arrow. See also `overlay-arrow-position'. +\(Note that despite the name of this variable, it can be set to a glyph as +well as a string.) */ , redisplay_variable_changed); Voverlay_arrow_string = Qnil; @@ -9328,10 +9330,19 @@ If this is zero, point is always centered after it moves off screen. redisplay_variable_changed); truncate_partial_width_windows = 1; - DEFVAR_BOOL ("visible-bell", &visible_bell /* -*Non-nil means try to flash the frame to represent a bell. + DEFVAR_LISP ("visible-bell", &Vvisible_bell /* +*Non-nil substitutes a visual signal for the audible bell. + +Default behavior is to flash the whole screen. On some platforms, +special effects are available using the following values: + +'display Flash the whole screen (ie, the default behavior). +'top-bottom Flash only the top and bottom lines of the selected frame. + +When effects are unavailable on a platform, the visual bell is the +default, whole screen. (Currently only X supports any special effects.) */ ); - visible_bell = 0; + Vvisible_bell = Qnil; DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* *Non-nil means no need to redraw entire frame after suspending. @@ -9375,24 +9386,29 @@ Non-nil means put cursor in minibuffer, at end of any message there. maybe a caret cursor, etc. */ DEFVAR_LISP ("bar-cursor", &Vbar_cursor /* -Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. +*Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2. */ ); Vbar_cursor = Qnil; #ifndef INHIBIT_REDISPLAY_HOOKS xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /* Function or functions to run before every redisplay. -Functions on this hook must be careful to avoid signalling errors! */ ); Vpre_redisplay_hook = Qnil; xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /* Function or functions to run after every redisplay. -Functions on this hook must be careful to avoid signalling errors! */ ); Vpost_redisplay_hook = Qnil; #endif /* INHIBIT_REDISPLAY_HOOKS */ + DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* +Function or functions to call when a frame's buffer list has changed. +This is called during redisplay, before redisplaying each frame. +Functions on this hook are called with one argument, the frame. +*/ ); + Vbuffer_list_changed_hook = Qnil; + DEFVAR_INT ("display-warning-tick", &display_warning_tick /* Bump this to tell the C code to call `display-warning-buffer' at next redisplay. You should not normally change this; the function @@ -9454,7 +9470,7 @@ This is a specifier; use `set-specifier' to change it. offsetof (struct window, left_margin_width), some_window_value_changed, offsetof (struct frame, left_margin_width), - margin_width_changed_in_frame); + margin_width_changed_in_frame, 0); DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* *Width of right margin. @@ -9466,7 +9482,7 @@ This is a specifier; use `set-specifier' to change it. offsetof (struct window, right_margin_width), some_window_value_changed, offsetof (struct frame, right_margin_width), - margin_width_changed_in_frame); + margin_width_changed_in_frame, 0); DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* *Minimum ascent height of lines. @@ -9477,7 +9493,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vminimum_line_ascent, offsetof (struct window, minimum_line_ascent), some_window_value_changed, - 0, 0); + 0, 0, 0); DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* *Minimum descent height of lines. @@ -9488,7 +9504,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vminimum_line_descent, offsetof (struct window, minimum_line_descent), some_window_value_changed, - 0, 0); + 0, 0, 0); DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* *Non-nil means use the left outside margin as extra whitespace when @@ -9500,7 +9516,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vuse_left_overflow, offsetof (struct window, use_left_overflow), some_window_value_changed, - 0, 0); + 0, 0, 0); DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* *Non-nil means use the right outside margin as extra whitespace when @@ -9512,7 +9528,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vuse_right_overflow, offsetof (struct window, use_right_overflow), some_window_value_changed, - 0, 0); + 0, 0, 0); DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* *Non-nil means the text cursor is visible (this is usually the case). @@ -9523,6 +9539,6 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vtext_cursor_visible_p, offsetof (struct window, text_cursor_visible_p), text_cursor_visible_p_changed, - 0, 0); + 0, 0, 0); }