X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fredisplay.c;h=ac3416fca8776c9816e04067cb56bfb036737a0f;hb=cd2292bbfe34d2aba639cf019094dcb85802508c;hp=c3ef67cd800530e689c0f368de6489dbb696fa7c;hpb=3890a2e3064a7f562107c58e59d928284ec04741;p=chise%2Fxemacs-chise.git.1 diff --git a/src/redisplay.c b/src/redisplay.c index c3ef67c..ac3416f 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. */ @@ -155,9 +147,9 @@ typedef struct position_redisplay_data_type to be skipped before anything is displayed. */ Bytind bi_start_col_enabled; int start_col_xoffset; /* Number of pixels that still need to - be skipped. This is used for - horizontal scrolling of glyphs, where we want - to be able to scroll over part of the glyph. */ + be skipped. This is used for + horizontal scrolling of glyphs, where we want + to be able to scroll over part of the glyph. */ int hscroll_glyph_width_adjust; /* how much the width of the hscroll glyph differs from space_width (w). @@ -171,18 +163,20 @@ typedef struct position_redisplay_data_type struct extent_fragment *ef; face_index findex; - /* The height of a pixmap may either be predetermined if the user - has set a baseline value, or it may be dependent on whatever the - line ascent and descent values end up being, based just on font - information. In the first case we can immediately update the - values, thus their inclusion here. In the last case we cannot - determine the actual contribution to the line height until we - have finished laying out all text on the line. Thus we propagate - the max height of such pixmaps and do a final calculation after - all text has been added to the line. */ + /* The height of a pixmap may either be predetermined if the user has set a + baseline value, or it may be dependent on whatever the line ascent and + descent values end up being, based just on font and pixmap-ascent + information. In the first case we can immediately update the values, thus + their inclusion here. In the last case we cannot determine the actual + contribution to the line height until we have finished laying out all text + on the line. Thus we propagate the max height of such pixmaps and do a + final calculation (in calculate_baseline()) after all text has been added + to the line. */ int new_ascent; int new_descent; int max_pixmap_height; + int need_baseline_computation; + int end_glyph_width; /* Well, it is the kitchen sink after all ... */ Lisp_Object result_str; /* String where we put the result of generating a formatted string in the modeline. */ @@ -200,15 +194,24 @@ enum prop_type PROP_STRING, PROP_CHAR, PROP_MINIBUF_PROMPT, - PROP_BLANK + PROP_BLANK, + PROP_GLYPH }; /* Data that should be propagated to the next line. Either a single - Emchar or a string of Bufbyte's. + Emchar, a string of Bufbyte's or a glyph. The actual data that is propagated ends up as a Dynarr of these blocks. + prop_blocks are used to indicate that data that was supposed to go + on the previous line couldn't actually be displayed. Generally this + shouldn't happen if we are clipping the end of lines. If we are + wrapping then we need to display the propagation data before moving + on. Its questionable whether we should wrap or clip glyphs in this + instance. Most e-lisp relies on clipping so we preserve this + behavior. + #### It's unclean that both Emchars and Bufbytes are here. */ @@ -237,6 +240,14 @@ struct prop_block int width; face_index findex; } p_blank; + + struct + { + /* Not used as yet, but could be used to wrap rather than clip glyphs. */ + int width; + Lisp_Object glyph; + } p_glyph; + } data; }; @@ -273,6 +284,9 @@ static void free_display_line (struct display_line *dl); static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to, Bufpos point, int no_regen); static int point_visible (struct window *w, Bufpos point, int type); +static void calculate_yoffset (struct display_line *dl, + struct display_block *fixup); +static void calculate_baseline (pos_data *data); /* This used to be 10 but 30 seems to give much better performance. */ #define INIT_MAX_PREEMPTS 30 @@ -308,7 +322,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 +337,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 +375,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; @@ -404,6 +414,10 @@ int asynch_device_change_pending; int toolbar_changed; int toolbar_changed_set; +/* Nonzero if some frame has changed the layout of internal elements + (gutters or toolbars). */ +int frame_layout_changed; + /* non-nil if any gutter has changed */ int gutter_changed; int gutter_changed_set; @@ -419,9 +433,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 +451,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 +465,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 +477,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 +489,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) /***************************************************************************/ @@ -482,13 +501,13 @@ int column_number_start_at_one; /***************************************************************************/ static int -redisplay_text_width_emchar_string (struct window *w, int findex, - Emchar *str, Charcount len) +redisplay_text_width_charc_string (struct window *w, int findex, + Charc *str, Charcount len) { - unsigned char charsets[NUM_LEADING_BYTES]; + Charset_ID charsets[NUM_LEADING_BYTES]; Lisp_Object window; - find_charsets_in_emchar_string (charsets, str, len); + find_charsets_in_charc_string (charsets, str, len); XSETWINDOW (window, w); ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window, charsets); @@ -497,24 +516,24 @@ redisplay_text_width_emchar_string (struct window *w, int findex, WINDOW_FACE_CACHEL (w, findex), str, len)); } -static Emchar_dynarr *rtw_emchar_dynarr; +static Charc_dynarr *rtw_charc_dynarr; int redisplay_text_width_string (struct window *w, int findex, Bufbyte *nonreloc, Lisp_Object reloc, Bytecount offset, Bytecount len) { - if (!rtw_emchar_dynarr) - rtw_emchar_dynarr = Dynarr_new (Emchar); - Dynarr_reset (rtw_emchar_dynarr); + if (!rtw_charc_dynarr) + rtw_charc_dynarr = Dynarr_new (Charc); + Dynarr_reset (rtw_charc_dynarr); fixup_internal_substring (nonreloc, reloc, offset, &len); if (STRINGP (reloc)) nonreloc = XSTRING_DATA (reloc); - convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr); - return redisplay_text_width_emchar_string - (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0), - Dynarr_length (rtw_emchar_dynarr)); + convert_bufbyte_string_into_charc_dynarr (nonreloc, len, rtw_charc_dynarr); + return redisplay_text_width_charc_string + (w, findex, Dynarr_atp (rtw_charc_dynarr, 0), + Dynarr_length (rtw_charc_dynarr)); } int @@ -522,26 +541,26 @@ redisplay_frame_text_width_string (struct frame *f, Lisp_Object face, Bufbyte *nonreloc, Lisp_Object reloc, Bytecount offset, Bytecount len) { - unsigned char charsets[NUM_LEADING_BYTES]; + Charset_ID charsets[NUM_LEADING_BYTES]; Lisp_Object frame; struct face_cachel cachel; - if (!rtw_emchar_dynarr) - rtw_emchar_dynarr = Dynarr_new (Emchar); - Dynarr_reset (rtw_emchar_dynarr); + if (!rtw_charc_dynarr) + rtw_charc_dynarr = Dynarr_new (Charc); + Dynarr_reset (rtw_charc_dynarr); fixup_internal_substring (nonreloc, reloc, offset, &len); if (STRINGP (reloc)) nonreloc = XSTRING_DATA (reloc); - convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr); + convert_bufbyte_string_into_charc_dynarr (nonreloc, len, rtw_charc_dynarr); find_charsets_in_bufbyte_string (charsets, nonreloc, len); reset_face_cachel (&cachel); cachel.face = face; XSETFRAME (frame, f); ensure_face_cachel_complete (&cachel, frame, charsets); return DEVMETH (XDEVICE (FRAME_DEVICE (f)), - text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0), - Dynarr_length (rtw_emchar_dynarr))); + text_width, (f, &cachel, Dynarr_atp (rtw_charc_dynarr, 0), + Dynarr_length (rtw_charc_dynarr))); } /* Return the display block from DL of the given TYPE. A display line @@ -687,6 +706,108 @@ calculate_display_line_boundaries (struct window *w, int modeline) return bounds; } +/* This takes a display_block and its containing line and corrects the yoffset + of each glyph in the block to cater for the ascent of the line as a + whole. Must be called *after* the line-ascent is known! */ + +static void +calculate_yoffset (struct display_line *dl, struct display_block *fixup) +{ + int i; + for (i=0; irunes); i++) + { + struct rune *r = Dynarr_atp (fixup->runes,i); + if (r->type == RUNE_DGLYPH) + { + if (r->object.dglyph.ascent < dl->ascent) + r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent + + r->object.dglyph.descent; + } + } +} + +/* Calculate the textual baseline (the ascent and descent values for the + display_line as a whole). + + If the baseline is completely blank, or contains no manually positioned + glyphs, then the textual baseline is simply the baseline of the default font. + (The `contains no manually positioned glyphs' part is actually done for + us by `add_emchar_rune'.) + + If the baseline contains pixmaps, and they're all manually positioned, then + the textual baseline location is constrained that way, and we need do no + work. + + If the baseline contains pixmaps, and at least one is automatically + positioned, then the textual ascent is the largest ascent on the line, and + the textual descent is the largest descent (which is how things are set up at + entry to this function anyway): except that if the max_ascent + max_descent + is too small for the height of the line (say you've adjusted the baseline of + a short glyph, and there's a tall one next to it), then take the ascent and + descent for the line individually from the largest of the explicitly set + ascent/descent, and the rescaled ascent/descent of the default font, scaled + such that the largest glyph will fit. + + This means that if you have a short glyph (but taller than the default + font's descent) forced right under the baseline, and a really tall + automatically positioned glyph, that the descent for the line is just big + enough for the manually positioned short glyph, and the tall one uses as + much of that space as the default font would were it as tall as the tall + glyph; but that the ascent is big enough for the tall glyph to fit. + + This behaviour means that under no circumstances will changing the baseline + of a short glyph cause a tall glyph to move around; nor will it move the + textual baseline more than necessary. (Changing a tall glyph's baseline + might move the text's baseline arbitrarily, of course.) */ + +static void +calculate_baseline (pos_data *data) +{ + /* Blank line: baseline is default font's baseline. */ + + if (!data->new_ascent && !data->new_descent) + { + /* We've got a blank line so initialize these values from the default + face. */ + default_face_font_info (data->window, &data->new_ascent, + &data->new_descent, 0, 0, 0); + } + + /* No automatically positioned glyphs? Return at once. */ + if (!data->need_baseline_computation) + return; + + /* Is the tallest glyph on the line automatically positioned? + If it's manually positioned, or it's automatically positioned + and there's enough room for it anyway, we need do no more work. */ + if (data->max_pixmap_height > data->new_ascent + data->new_descent) + { + int default_font_ascent, default_font_descent, default_font_height; + int scaled_default_font_ascent, scaled_default_font_descent; + + default_face_font_info (data->window, &default_font_ascent, + &default_font_descent, &default_font_height, + 0, 0); + + scaled_default_font_ascent = data->max_pixmap_height * + default_font_ascent / default_font_height; + + data->new_ascent = max (data->new_ascent, scaled_default_font_ascent); + + /* The ascent may have expanded now. Do we still need to grow the descent, + or are things big enough? + + The +1 caters for the baseline row itself. */ + if (data->max_pixmap_height > data->new_ascent + data->new_descent) + { + scaled_default_font_descent = (data->max_pixmap_height * + default_font_descent / default_font_height) + 1; + + data->new_descent = max (data->new_descent, scaled_default_font_descent); + } + } +} + /* Given a display line and a starting position, ensure that the contents of the display line accurately represent the visual representation of the buffer contents starting from the given @@ -803,7 +924,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 = @@ -818,15 +939,18 @@ add_hscroll_rune (pos_data *data) return retval; } -/* Adds a character rune to a display block. If there is not enough - room to fit the rune on the display block (as determined by the - MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */ +/* Adds a character rune to a display block. If there is not enough room + to fit the rune on the display block (as determined by the MAX_PIXPOS) + then it adds nothing and returns ADD_FAILED. If + NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't allow the char's height + to affect the total line height. (See add_intbyte_string_runes()). */ static prop_block_dynarr * -add_emchar_rune (pos_data *data) +add_emchar_rune_1 (pos_data *data, int no_contribute_to_line_height) { struct rune rb, *crb; int width, local; + Charc char_glyph; if (data->start_col) { @@ -843,13 +967,17 @@ add_emchar_rune (pos_data *data) if (data->ch == '\n') { + char_glyph = ASCII_TO_CHARC ('\n'); data->font_is_bogus = 0; /* Cheesy end-of-line pseudo-character. */ width = data->blank_width; } else { - Lisp_Object charset = CHAR_CHARSET (data->ch); + Lisp_Object charset; + + char_glyph = CHAR_TO_CHARC (data->ch); + charset = CHARC_CHARSET (char_glyph); if (!EQ (charset, data->last_charset) || data->findex != data->last_findex) { @@ -875,8 +1003,13 @@ add_emchar_rune (pos_data *data) data->last_char_width = fi->width; else data->last_char_width = -1; - data->new_ascent = max (data->new_ascent, (int) fi->ascent); - data->new_descent = max (data->new_descent, (int) fi->descent); + + if (!no_contribute_to_line_height) + { + data->new_ascent = max (data->new_ascent, (int) fi->ascent); + data->new_descent = max (data->new_descent, (int) fi->descent); + } + data->last_charset = charset; data->last_findex = data->findex; } @@ -885,9 +1018,9 @@ add_emchar_rune (pos_data *data) if (width < 0) { /* bummer. Proportional fonts. */ - width = redisplay_text_width_emchar_string (XWINDOW (data->window), - data->findex, - &data->ch, 1); + width = redisplay_text_width_charc_string (XWINDOW (data->window), + data->findex, + &char_glyph, 1); } } @@ -918,17 +1051,18 @@ add_emchar_rune (pos_data *data) data->bi_bufpos); else crb->bufpos = - bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos); + bytecount_to_charcount (XSTRING_DATA (data->string), + data->bi_bufpos); } 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; + crb->object.cglyph = data->font_is_bogus + ? ASCII_TO_CHARC ('~') + : char_glyph; crb->endpos = 0; if (data->cursor_type == CURSOR_ON) @@ -962,13 +1096,24 @@ add_emchar_rune (pos_data *data) return NULL; } -/* Given a string C_STRING of length C_LENGTH, call add_emchar_rune - for each character in the string. Propagate any left-over data - unless NO_PROP is non-zero. */ - +static prop_block_dynarr * +add_emchar_rune (pos_data *data) +{ + return add_emchar_rune_1 (data, 0); +} + +/* Given a string C_STRING of length C_LENGTH, call add_emchar_rune for + each character in the string. Propagate any left-over data unless + NO_PROP is non-zero. If NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't + allow this character to increase the total height of the line. (This is + used when the character is part of a text glyph. In that case, the + glyph code itself adjusts the line height as necessary, depending on + whether glyph-contrib-p is true.) */ + static prop_block_dynarr * add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string, - Bytecount c_length, int no_prop) + Bytecount c_length, int no_prop, + int no_contribute_to_line_height) { Bufbyte *pos, *end = c_string + c_length; prop_block_dynarr *prop; @@ -981,9 +1126,11 @@ 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); + prop = add_emchar_rune_1 (data, no_contribute_to_line_height); if (prop) { @@ -1006,6 +1153,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; @@ -1115,12 +1265,11 @@ add_blank_rune (pos_data *data, struct window *w, int char_tab_width) static prop_block_dynarr * add_octal_runes (pos_data *data) { - prop_block_dynarr *prop, *add_failed; + prop_block_dynarr *add_failed, *prop = 0; Emchar orig_char = data->ch; unsigned int orig_cursor_type = data->cursor_type; /* Initialize */ - prop = NULL; add_failed = NULL; if (data->start_col) @@ -1180,7 +1329,7 @@ add_octal_runes (pos_data *data) ADD_NEXT_OCTAL_RUNE_CHAR; data->cursor_type = orig_cursor_type; - return prop; + return NULL; } #undef ADD_NEXT_OCTAL_RUNE_CHAR @@ -1265,7 +1414,7 @@ add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) prop = add_bufbyte_string_runes (data, XSTRING_DATA (entry), XSTRING_LENGTH (entry), - 0); + 0, 0); } else if (GLYPHP (entry)) { @@ -1320,10 +1469,11 @@ add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) case '%': dst += set_charptr_emchar (dst, '%'); break; + /* #### unimplemented */ } } } - prop = add_bufbyte_string_runes (data, result, dst - result, 0); + prop = add_bufbyte_string_runes (data, result, dst - result, 0, 0); } } @@ -1493,7 +1643,7 @@ add_propagation_runes (prop_block_dynarr **prop, pos_data *data) } break; default: - abort (); + ABORT (); } } @@ -1528,10 +1678,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 +1691,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 +1700,9 @@ 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; + prop_block_dynarr *retval = 0; if (cachel) width = cachel->width; @@ -1558,7 +1714,6 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, if (data->start_col || data->start_col_xoffset) { - prop_block_dynarr *retval; int glyph_char_width = width / space_width (w); /* If we still have not fully scrolled horizontally after @@ -1594,17 +1749,41 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, if (data->pixpos + width > data->max_pixpos) { /* If this is the first object we are attempting to add to - the line then we ignore the horizontal_clip threshold. - Otherwise we will loop until the bottom of the window - continually failing to add this glyph because it is wider - than the window. We could alternatively just completely - ignore the glyph and proceed from there but I think that - this is a better solution. */ + the line then we ignore the horizontal_clip threshold. + Otherwise we will loop until the bottom of the window + continually failing to add this glyph because it is wider + than the window. We could alternatively just completely + ignore the glyph and proceed from there but I think that + this is a better solution. + + This does, however, create a different problem in that we + can end up adding the object to every single line, never + getting any further - for instance an extent with a long + start-glyph that covers multitple following + characters. */ if (Dynarr_length (data->db->runes) && data->max_pixpos - data->pixpos < horizontal_clip) return ADD_FAILED; - else + else { + struct prop_block pb; + + /* We need to account for the width of the end-of-line + glyph if there is nothing more in the line to display, + since we will not display it in this instance. It seems + kind of gross doing it here, but otherwise we have to + search the runes in create_text_block(). */ + if (data->ch == '\n') + data->max_pixpos += data->end_glyph_width; width = data->max_pixpos - data->pixpos; + /* Add the glyph we are displaying, but clipping, to the + propagation data so that we don't try and do it + again. */ + retval = Dynarr_new (prop_block); + pb.type = PROP_GLYPH; + pb.data.p_glyph.glyph = gb->glyph; + pb.data.p_glyph.width = width; + Dynarr_add (retval, pb); + } } if (cachel) @@ -1620,6 +1799,8 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, baseline = glyph_baseline (gb->glyph, data->window); + rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ + if (glyph_contrib_p (gb->glyph, data->window)) { /* A pixmap that has not had a baseline explicitly set. Its @@ -1627,6 +1808,7 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, if (NILP (baseline)) { int height = ascent + descent; + data->need_baseline_computation = 1; data->max_pixmap_height = max (data->max_pixmap_height, height); } @@ -1649,19 +1831,44 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, data->new_ascent = max (data->new_ascent, pix_ascent); data->new_descent = max (data->new_descent, pix_descent); + data->max_pixmap_height = max (data->max_pixmap_height, height); + + rb.object.dglyph.descent = pix_descent; } /* Otherwise something is screwed up. */ else - abort (); + ABORT (); } 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, 1); + data->findex = orig_findex; + data->bi_bufpos = orig_bufpos; + data->bi_start_col_enabled = orig_start_col_enabled; + return retval; + } + + rb.findex = findex; rb.xpos = data->pixpos; rb.width = width; rb.bufpos = 0; /* glyphs are never "at" anywhere */ @@ -1672,16 +1879,12 @@ 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; + rb.object.dglyph.ascent = ascent; + rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has + a normal (textual) baseline. */ if (allow_cursor) { @@ -1717,7 +1920,7 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, Dynarr_add (data->db->runes, rb); data->pixpos += width; - return NULL; + return retval; } else { @@ -1743,10 +1946,10 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, return NULL; } else - abort (); /* there are no unknown types */ + ABORT (); /* there are no unknown types */ } - return NULL; /* shut up compiler */ + return NULL; } /* Add all glyphs at position POS_TYPE that are contained in the given @@ -1806,7 +2009,6 @@ create_text_block (struct window *w, struct display_line *dl, is_surrogate_for_selected_frame (f)); int truncate_win = window_truncation_on (w); - int end_glyph_width; /* If the buffer's value of selective_display is an integer then only lines that start with less than selective_display columns of @@ -1881,6 +2083,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); @@ -1903,10 +2106,10 @@ create_text_block (struct window *w, struct display_line *dl, glyph. Save the width of the end glyph for later use. */ data.max_pixpos = dl->bounds.right_in; if (truncate_win) - end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); + data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); else - end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); - data.max_pixpos -= end_glyph_width; + data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); + data.max_pixpos -= data.end_glyph_width; if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f)) { @@ -1999,10 +2202,25 @@ create_text_block (struct window *w, struct display_line *dl, /* Check for face changes. */ if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end)) { + Lisp_Object last_glyph = Qnil; + + /* Deal with glyphs that we have already displayed. The + theory is that if we end up with a PROP_GLYPH in the + propagation data then we are clipping the glyph and there + can be no propagation data before that point. The theory + works because we always recalculate the extent-fragments + for propagated data, we never actually propagate the + fragments that still need to be displayed. */ + if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH) + { + last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph; + Dynarr_free (*prop); + *prop = 0; + } /* Now compute the face and begin/end-glyph information. */ data.findex = /* Remember that the extent-fragment routines deal in Bytind's. */ - extent_fragment_update (w, data.ef, data.bi_bufpos); + extent_fragment_update (w, data.ef, data.bi_bufpos, last_glyph); get_display_tables (w, data.findex, &face_dt, &window_dt); @@ -2072,9 +2290,9 @@ create_text_block (struct window *w, struct display_line *dl, } /* If there is propagation data, then it represents the current - buffer position being displayed. Add them and advance the - position counter. This might also add the minibuffer - prompt. */ + buffer position being displayed. Add them and advance the + position counter. This might also add the minibuffer + prompt. */ else if (*prop) { dl->used_prop_data = 1; @@ -2096,19 +2314,59 @@ create_text_block (struct window *w, struct display_line *dl, here rather than doing them at the end of handling the previous run so that glyphs at the beginning and end of a line are handled correctly. */ - else if (Dynarr_length (data.ef->end_glyphs) > 0) + else if (Dynarr_length (data.ef->end_glyphs) > 0 + || Dynarr_length (data.ef->begin_glyphs) > 0) { - *prop = add_glyph_runes (&data, END_GLYPHS); - if (*prop) - goto done; - } + glyph_block_dynarr* tmpglyphs = 0; + /* #### I think this is safe, but could be wrong. */ + data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos); - /* If there are begin glyphs, add them to the line. */ - else if (Dynarr_length (data.ef->begin_glyphs) > 0) - { - *prop = add_glyph_runes (&data, BEGIN_GLYPHS); - if (*prop) - goto done; + if (Dynarr_length (data.ef->end_glyphs) > 0) + { + *prop = add_glyph_runes (&data, END_GLYPHS); + tmpglyphs = data.ef->end_glyphs; + } + + /* If there are begin glyphs, add them to the line. */ + if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0) + { + *prop = add_glyph_runes (&data, BEGIN_GLYPHS); + tmpglyphs = data.ef->begin_glyphs; + } + + if (*prop) + { + /* If we just clipped a glyph and we are at the end of a + line and there are more glyphs to display then do + appropriate processing to not get a continuation + glyph. */ + if (*prop != ADD_FAILED + && Dynarr_atp (*prop, 0)->type == PROP_GLYPH + && data.ch == '\n') + { + /* If there are no more glyphs then do the normal + processing. + + #### This doesn't actually work if the same glyph is + present more than once in the block. To solve + this we would have to carry the index around + which might be problematic since the fragment is + recalculated for each line. */ + if (EQ (Dynarr_end (tmpglyphs)->glyph, + Dynarr_atp (*prop, 0)->data.p_glyph.glyph)) + { + Dynarr_free (*prop); + *prop = 0; + } + else { + data.blank_width = DEVMETH (d, eol_cursor_width, ()); + add_emchar_rune (&data); /* discard prop data. */ + goto done; + } + } + else + goto done; + } } /* If at end-of-buffer, we've already processed begin and @@ -2142,7 +2400,7 @@ create_text_block (struct window *w, struct display_line *dl, /* We aren't going to be adding an end glyph so give its space back in order to make sure that the cursor can fit. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; if (selective > 0 && (bi_spaces_at_point @@ -2223,7 +2481,7 @@ create_text_block (struct window *w, struct display_line *dl, /* We won't be adding a truncation or continuation glyph so give up the room allocated for them. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; if (!NILP (b->selective_display_ellipses)) { @@ -2261,7 +2519,7 @@ create_text_block (struct window *w, struct display_line *dl, /* This had better be a newline but doing it this way we'll see obvious incorrect results if it isn't. No - need to abort here. */ + need to ABORT here. */ data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos); goto done; @@ -2432,7 +2690,7 @@ done: for the next newline. We also add the end-of-line glyph which we know will fit because we adjusted the right border before we starting laying out the line. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; data.findex = DEFAULT_INDEX; gb.extent = Qnil; @@ -2471,11 +2729,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') @@ -2517,7 +2776,7 @@ done: { struct rune *rb = Dynarr_atp (db->runes, elt); - if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') + if ((rb->type == RUNE_CHAR && CHARC_ASCII_EQ (rb->object.cglyph, ' ')) || rb->type == RUNE_BLANK) { dl->bounds.left_white += rb->width; @@ -2537,8 +2796,7 @@ done: { struct rune *rb = Dynarr_atp (db->runes, elt); - if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 - && isspace (rb->object.chr.ch)) + if (!(rb->type == RUNE_CHAR && CHARC_IS_SPACE (rb->object.cglyph)) && !rb->type == RUNE_BLANK) { dl->bounds.right_white = rb->xpos + rb->width; @@ -2566,26 +2824,7 @@ done: else db->end_pos = dl->bounds.right_white; - /* update line height parameters */ - if (!data.new_ascent && !data.new_descent) - { - /* We've got a blank line so initialize these values from the default - face. */ - default_face_font_info (data.window, &data.new_ascent, - &data.new_descent, 0, 0, 0); - } - - 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); - } + calculate_baseline (&data); dl->ascent = data.new_ascent; dl->descent = data.new_descent; @@ -2603,6 +2842,8 @@ done: dl->descent = descent; } + calculate_yoffset (dl, db); + dl->cursor_elt = data.cursor_x; /* #### lossage lossage lossage! Fix this shit! */ if (data.bi_bufpos > BI_BUF_ZV (b)) @@ -2681,7 +2922,7 @@ create_overlay_glyph_block (struct window *w, struct display_line *dl) (&data, XSTRING_DATA (Voverlay_arrow_string), XSTRING_LENGTH (Voverlay_arrow_string), - 1); + 1, 0); } else if (GLYPHP (Voverlay_arrow_string)) { @@ -2692,17 +2933,7 @@ create_overlay_glyph_block (struct window *w, struct display_line *dl) add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0); } - 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); - } + calculate_baseline (&data); dl->ascent = data.new_ascent; dl->descent = data.new_descent; @@ -2710,6 +2941,8 @@ create_overlay_glyph_block (struct window *w, struct display_line *dl) data.db->start_pos = dl->bounds.left_in; data.db->end_pos = data.pixpos; + calculate_yoffset (dl, data.db); + return data.pixpos - dl->bounds.left_in; } @@ -2723,8 +2956,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)) @@ -2745,7 +2996,7 @@ add_margin_runes (struct display_line *dl, struct display_block *db, int start, struct glyph_block *gb = Dynarr_atp (gbd, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (gb->active && ((side == LEFT_GLYPHS && @@ -2753,79 +3004,24 @@ 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; + calculate_baseline (&data); + + dl->ascent = data.new_ascent; + dl->descent = data.new_descent; + + calculate_yoffset (dl, data.db); + + return data.pixpos; } /* Add a blank to a margin display block. */ @@ -2885,7 +3081,7 @@ create_left_glyph_block (struct window *w, struct display_line *dl, struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) { @@ -2937,7 +3133,7 @@ create_left_glyph_block (struct window *w, struct display_line *dl, struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) @@ -3006,7 +3202,7 @@ create_left_glyph_block (struct window *w, struct display_line *dl, struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) @@ -3048,7 +3244,7 @@ create_left_glyph_block (struct window *w, struct display_line *dl, struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) @@ -3206,7 +3402,7 @@ create_right_glyph_block (struct window *w, struct display_line *dl) struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) { @@ -3256,7 +3452,7 @@ create_right_glyph_block (struct window *w, struct display_line *dl) struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { @@ -3320,7 +3516,7 @@ create_right_glyph_block (struct window *w, struct display_line *dl) struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { @@ -3361,7 +3557,7 @@ create_right_glyph_block (struct window *w, struct display_line *dl) struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt); if (NILP (gb->extent)) - abort (); /* these should have been handled in add_glyph_rune */ + ABORT (); /* these should have been handled in add_glyph_rune */ if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) { @@ -3516,7 +3712,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 +3749,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)); @@ -3564,8 +3762,9 @@ generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) { len += (set_charptr_emchar - (strdata + len, Dynarr_atp (db->runes, - elt)->object.chr.ch)); + (strdata + len, + CHARC_TO_CHAR (Dynarr_atp (db->runes, + elt)->object.cglyph))); } } @@ -3589,6 +3788,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 +3833,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 +3886,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 +4183,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; @@ -4257,9 +4451,9 @@ real_current_modeline_height (struct window *w) /***************************************************************************/ -/* */ -/* displayable string routines */ -/* */ +/* */ +/* displayable string routines */ +/* */ /***************************************************************************/ /* Given a position for a string in a window, ensure that the given @@ -4301,11 +4495,10 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, pos_data data; 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 +4564,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 */ @@ -4408,13 +4602,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, /* Set the right boundary adjusting it to take into account any end glyph. Save the width of the end glyph for later use. */ data.max_pixpos = dl->bounds.right_in; -#if 0 - if (truncate_win) - end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); - else - end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); -#endif - data.max_pixpos -= end_glyph_width; + data.max_pixpos -= data.end_glyph_width; data.cursor_type = NO_CURSOR; data.cursor_x = -1; @@ -4470,10 +4658,18 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, /* Check for face changes. */ if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end)) { + Lisp_Object last_glyph = Qnil; + /* Deal with clipped glyphs that we have already displayed. */ + if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH) + { + last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph; + Dynarr_free (*prop); + *prop = 0; + } /* Now compute the face and begin/end-glyph information. */ data.findex = /* Remember that the extent-fragment routines deal in Bytind's. */ - extent_fragment_update (w, data.ef, data.bi_bufpos); + extent_fragment_update (w, data.ef, data.bi_bufpos, last_glyph); /* This is somewhat cheesy but the alternative is to propagate default_face into extent_fragment_update. */ if (data.findex == DEFAULT_INDEX) @@ -4528,7 +4724,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--; @@ -4552,7 +4748,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, else if (data.bi_bufpos == bi_string_zv) goto done; else if (data.bi_bufpos < 0) - /* #### urk urk urk! Aborts are not very fun! Fix this please! */ + /* #### urk urk urk! ABORTs are not very fun! Fix this please! */ data.bi_bufpos = 0; else INC_CHARBYTIND (string_data (s), data.bi_bufpos); @@ -4565,17 +4761,23 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, a line are handled correctly. */ else if (Dynarr_length (data.ef->end_glyphs) > 0) { + data.ch = string_char (s, data.bi_bufpos); *prop = add_glyph_runes (&data, END_GLYPHS); - if (*prop) + + if (*prop) { goto done; + } } /* If there are begin glyphs, add them to the line. */ else if (Dynarr_length (data.ef->begin_glyphs) > 0) { + data.ch = string_char (s, data.bi_bufpos); *prop = add_glyph_runes (&data, BEGIN_GLYPHS); - if (*prop) + + if (*prop) { goto done; + } } /* If at end-of-buffer, we've already processed begin and @@ -4609,7 +4811,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, /* We aren't going to be adding an end glyph so give its space back in order to make sure that the cursor can fit. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; goto done; } @@ -4651,7 +4853,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, *prop = add_blank_rune (&data, w, char_tab_width); /* add_blank_rune is only supposed to be called with - sizes guaranteed to fit in the available space. */ + sizes guaranteed to fit in the available space. */ assert (!(*prop)); if (prop_width) @@ -4707,7 +4909,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, } } -done: + done: /* Determine the starting point of the next line if we did not hit the end of the buffer. */ @@ -4740,7 +4942,7 @@ done: for the next newline. We also add the end-of-line glyph which we know will fit because we adjusted the right border before we starting laying out the line. */ - data.max_pixpos += end_glyph_width; + data.max_pixpos += data.end_glyph_width; data.findex = default_face; gb.extent = Qnil; @@ -4763,11 +4965,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); } - if (end_glyph_width) + if (data.end_glyph_width) add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); if (truncate_win && data.bi_bufpos == bi_string_zv) @@ -4797,7 +5000,7 @@ done: { struct rune *rb = Dynarr_atp (db->runes, elt); - if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') + if ((rb->type == RUNE_CHAR && CHARC_ASCII_EQ (rb->object.cglyph, ' ')) || rb->type == RUNE_BLANK) { dl->bounds.left_white += rb->width; @@ -4817,8 +5020,7 @@ done: { struct rune *rb = Dynarr_atp (db->runes, elt); - if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 - && isspace (rb->object.chr.ch)) + if (!(rb->type == RUNE_CHAR && CHARC_IS_SPACE (rb->object.cglyph)) && !rb->type == RUNE_BLANK) { dl->bounds.right_white = rb->xpos + rb->width; @@ -4846,26 +5048,7 @@ done: else db->end_pos = dl->bounds.right_white; - /* update line height parameters */ - if (!data.new_ascent && !data.new_descent) - { - /* We've got a blank line so initialize these values from the default - face. */ - default_face_font_info (data.window, &data.new_ascent, - &data.new_descent, 0, 0, 0); - } - - 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); - } + calculate_baseline (&data); dl->ascent = data.new_ascent; dl->descent = data.new_descent; @@ -4883,6 +5066,8 @@ done: dl->descent = descent; } + calculate_yoffset (dl, db); + dl->cursor_elt = data.cursor_x; /* #### lossage lossage lossage! Fix this shit! */ if (data.bi_bufpos > bi_string_zv) @@ -5104,6 +5289,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; @@ -5112,7 +5298,7 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type) /* The lines had better exist by this point. */ if (!(dla = window_display_lines (w, type))) - abort (); + ABORT (); Dynarr_reset (dla); w->max_line_len = 0; @@ -5157,7 +5343,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 +5403,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 +5447,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) @@ -5291,7 +5490,7 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type) dla_start = 0; \ } \ else \ - abort (); /* structs differ */ \ + ABORT (); /* structs differ */ \ \ dla_end = Dynarr_length (cdla) - 1; \ } \ @@ -5594,20 +5793,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 +5813,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 +6191,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 +6468,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 +6486,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) @@ -6323,7 +6512,7 @@ redisplay_frame (struct frame *f, int preemption_check) /* The menubar, toolbar, and icon updates must be done before hold_frame_size_changes is called and we are officially 'in_display'. They may eval lisp code which may call Fsignal. - If in_display is set Fsignal will abort. */ + If in_display is set Fsignal will ABORT. */ #ifdef HAVE_MENUBARS /* Update the menubar. It is done first since it could change @@ -6332,47 +6521,38 @@ 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); + /* Update the toolbars geometry. We don't update the toolbars + themselves at this point since the space they are trying to + occupy may currently by occupied by gutter elements. Instead we + update the geometry, then update the gutter geometry, then update + the gutters - which will cause mapped windows to be repositioned + - and finally update the toolbars. */ + update_frame_toolbars_geometry (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 (); @@ -6392,18 +6572,30 @@ redisplay_frame (struct frame *f, int preemption_check) We need to remove them. If Fsignal() is called during this critical section, we - will abort(). + will ABORT(). If garbage collection is called during this critical section, - we simply return. #### We should abort instead. + we simply return. #### We should ABORT instead. #### 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,14 +6604,18 @@ 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); +#ifdef HAVE_TOOLBARS + /* Finally update the toolbars. It seems its possible to get in a + cycle between updating the gutter and the toolbars. Basically we + want to end up with both being up-to-date and this doesn't seem + possible in a single pass. */ + update_frame_toolbars (f); +#endif /* HAVE_TOOLBARS */ + CLASS_RESET_CHANGED_FLAGS (f); f->window_face_cache_reset = 0; f->echo_area_garbaged = 0; @@ -6451,27 +6647,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 +6683,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 +6712,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,7 +7310,6 @@ mark_redisplay (void) FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) { struct frame *f = XFRAME (XCAR (frmcons)); - update_frame_window_mirror (f); mark_window_mirror (f->root_mirror); mark_gutters (f); } @@ -7286,7 +7481,8 @@ point_in_line_start_cache (struct window *w, Bufpos point, int min_past) { struct buffer *b = XBUFFER (w->buffer); line_start_cache_dynarr *cache = w->line_start_cache; - unsigned int top, bottom, pos; + unsigned int top, bottom; + EMACS_INT pos; validate_line_start_cache (w); w->line_cache_validation_override++; @@ -7304,7 +7500,7 @@ point_in_line_start_cache (struct window *w, Bufpos point, int min_past) int win_char_height = window_char_height (w, 1); /* Occasionally we get here with a 0 height - window. find_next_newline_no_quit will abort if we pass it a + window. find_next_newline_no_quit will ABORT if we pass it a count of 0 so handle that case. */ if (!win_char_height) win_char_height = 1; @@ -7414,7 +7610,7 @@ find_point_loop: while (1) { - unsigned int new_pos; + EMACS_INT new_pos; Bufpos start, end; pos = (bottom + top + 1) >> 1; @@ -7456,7 +7652,7 @@ find_point_loop: else if (point < start) top = pos - 1; else - abort (); + ABORT (); new_pos = (bottom + top + 1) >> 1; if (pos == new_pos) @@ -7553,11 +7749,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 +7780,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 +7844,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 +7854,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 +8047,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 +8055,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 +8067,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 +8095,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 +8122,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 +8130,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 +8152,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 +8177,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 +8185,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 +8204,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 +8252,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 +8285,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); } @@ -8736,7 +8921,7 @@ pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord, } else if (past_end || (rb->type == RUNE_CHAR - && rb->object.chr.ch == '\n')) + && CHARC_ASCII_EQ (rb->object.cglyph, '\n'))) { (*row)--; /* At this point we may have glyphs in the right @@ -8807,7 +8992,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 +9025,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 +9036,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 +9079,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 +9109,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 +9147,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 +9177,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 +9394,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 +9451,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 +9464,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 +9510,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 +9536,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 +9592,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 +9676,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 +9688,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 +9699,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 +9710,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 +9722,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 +9734,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 +9745,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); }