X-Git-Url: http://git.chise.org/gitweb/?p=chise%2Fxemacs-chise.git.1;a=blobdiff_plain;f=src%2Fredisplay.c;h=e664075d4b6d06156fd95b37a057838e6f1a63d0;hp=7e29d59caa0acfd787926fdbbcf7b48efc3bf2ef;hb=ac7d0619aad74b1d57c4748ebb3ab29d9c32e3d8;hpb=46f51e794ddb493a8a76ec2f3be00b41e3b0be22 diff --git a/src/redisplay.c b/src/redisplay.c index 7e29d59..e664075 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; }; @@ -246,18 +257,13 @@ typedef struct } prop_block_dynarr; -static void generate_formatted_string_db (Lisp_Object format_str, - Lisp_Object result_str, - struct window *w, - struct display_line *dl, - struct display_block *db, - face_index findex, int min_pixpos, - int max_pixpos, int type); static Charcount generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, Charcount min_pos, Charcount max_pos, Lisp_Object elt, int depth, int max_pixsize, - face_index findex, int type); + face_index findex, int type, + Charcount *offset, + Lisp_Object cur_ext); static prop_block_dynarr *add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, int allow_cursor, @@ -278,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 @@ -300,10 +309,6 @@ static int max_preempts; isn't any reason we need more than a single set. */ display_line_dynarr *cmotion_display_lines; -/* Used by generate_formatted_string. Global because they get used so - much that the dynamic allocation time adds up. */ -static Emchar_dynarr *formatted_string_emchar_dynarr; -static struct display_line formatted_string_display_line; /* We store the extents that we need to generate in a Dynarr and then frob them all on at the end of generating the string. We do it this way rather than adding them as we generate the string because @@ -317,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. */ @@ -332,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. */ @@ -373,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; @@ -413,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; @@ -428,10 +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, @@ -447,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; @@ -461,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 @@ -470,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; @@ -481,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) /***************************************************************************/ @@ -697,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 @@ -813,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 = @@ -828,12 +939,14 @@ 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; @@ -869,7 +982,7 @@ add_emchar_rune (pos_data *data) Lisp_Object font_instance = ensure_face_cachel_contains_charset (cachel, data->window, charset); - struct Lisp_Font_Instance *fi; + Lisp_Font_Instance *fi; if (EQ (font_instance, Vthe_null_font_instance)) { @@ -885,8 +998,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; } @@ -933,9 +1051,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; @@ -972,13 +1088,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; @@ -991,9 +1118,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) { @@ -1016,6 +1145,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; @@ -1125,12 +1257,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) @@ -1190,7 +1321,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 @@ -1275,7 +1406,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)) { @@ -1330,10 +1461,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); } } @@ -1351,7 +1483,7 @@ add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) prop_block_dynarr *prop = NULL; if (VECTORP (entry)) { - struct Lisp_Vector *de = XVECTOR (entry); + Lisp_Vector *de = XVECTOR (entry); EMACS_INT len = vector_length (de); int elt; @@ -1534,12 +1666,25 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, { struct window *w = XWINDOW (data->window); + /* If window faces changed, and glyph instance is text, then + glyph sizes might have changed too */ + invalidate_glyph_geometry_maybe (gb->glyph, w); + + /* This makes sure the glyph is in the cachels. + + #### 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). */ if (NILP (gb->extent) || (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,18 +1692,20 @@ 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; else - width = glyph_width (gb->glyph, Qnil, data->findex, data->window); + width = glyph_width (gb->glyph, data->window); if (!width) return NULL; 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 +1741,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) @@ -1614,13 +1785,14 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, } else { - ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window); - descent = glyph_descent (gb->glyph, Qnil, data->findex, - data->window); + ascent = glyph_ascent (gb->glyph, data->window); + descent = glyph_descent (gb->glyph, data->window); } 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 @@ -1628,6 +1800,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); } @@ -1650,6 +1823,9 @@ 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. */ @@ -1659,10 +1835,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, 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 */ @@ -1673,16 +1871,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) { @@ -1718,7 +1912,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 { @@ -1747,7 +1941,7 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, 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 @@ -1807,7 +2001,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 @@ -1882,6 +2075,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); @@ -1904,10 +2098,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)) { @@ -2000,10 +2194,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); @@ -2073,9 +2282,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; @@ -2097,19 +2306,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 @@ -2143,7 +2392,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 @@ -2224,7 +2473,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)) { @@ -2433,7 +2682,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; @@ -2472,11 +2721,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') @@ -2567,26 +2817,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; @@ -2604,6 +2835,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)) @@ -2682,7 +2915,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)) { @@ -2693,17 +2926,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; @@ -2711,6 +2934,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; } @@ -2724,8 +2949,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)) @@ -2754,79 +2997,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, Qnil, gb->findex, window); - descent = glyph_descent (gb->glyph, Qnil, gb->findex, 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. */ @@ -2892,7 +3080,7 @@ create_left_glyph_block (struct window *w, struct display_line *dl, { int width; - width = glyph_width (gb->glyph, Qnil, gb->findex, window); + width = glyph_width (gb->glyph, window); if (white_in_start - width >= left_in_end) { @@ -2943,7 +3131,7 @@ create_left_glyph_block (struct window *w, struct display_line *dl, if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { - gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window); + gb->width = glyph_width (gb->glyph, window); used_in += gb->width; Dynarr_add (ib, *gb); } @@ -3012,7 +3200,7 @@ create_left_glyph_block (struct window *w, struct display_line *dl, if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (used_out) { @@ -3054,7 +3242,7 @@ create_left_glyph_block (struct window *w, struct display_line *dl, if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (out_end + width <= in_out_start) { @@ -3211,7 +3399,7 @@ create_right_glyph_block (struct window *w, struct display_line *dl) if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (white_in_end + width <= dl->bounds.right_in) { @@ -3261,7 +3449,7 @@ create_right_glyph_block (struct window *w, struct display_line *dl) if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { - gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window); + gb->width = glyph_width (gb->glyph, window); used_in += gb->width; Dynarr_add (ib, *gb); } @@ -3325,7 +3513,7 @@ create_right_glyph_block (struct window *w, struct display_line *dl) if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (used_out) { @@ -3366,7 +3554,7 @@ create_right_glyph_block (struct window *w, struct display_line *dl) if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) { - int width = glyph_width (gb->glyph, Qnil, gb->findex, window); + int width = glyph_width (gb->glyph, window); if (out_start - width >= in_out_end) { @@ -3482,9 +3670,123 @@ create_right_glyph_block (struct window *w, struct display_line *dl) /* */ /***************************************************************************/ +/* This function is also used in frame.c by `generate_title_string' */ +void +generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, + struct window *w, struct display_line *dl, + struct display_block *db, face_index findex, + int min_pixpos, int max_pixpos, int type) +{ + struct frame *f = XFRAME (w->frame); + struct device *d = XDEVICE (f->device); + + pos_data data; + int c_pixpos; + Charcount offset = 0; + + xzero (data); + data.d = d; + data.db = db; + data.dl = dl; + data.findex = findex; + data.pixpos = min_pixpos; + data.max_pixpos = max_pixpos; + data.cursor_type = NO_CURSOR; + data.last_charset = Qunbound; + data.last_findex = DEFAULT_INDEX; + data.result_str = result_str; + data.is_modeline = 1; + data.string = Qnil; + XSETWINDOW (data.window, w); + + Dynarr_reset (formatted_string_extent_dynarr); + Dynarr_reset (formatted_string_extent_start_dynarr); + Dynarr_reset (formatted_string_extent_end_dynarr); + + /* 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 amount */ + if (! NILP (result_str)) + offset = w->modeline_hscroll; + generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, + max_pixpos - min_pixpos, findex, type, &offset, + Qnil); + + if (Dynarr_length (db->runes)) + { + struct rune *rb = + Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); + c_pixpos = rb->xpos + rb->width; + } + else + c_pixpos = min_pixpos; + + /* If we don't reach the right side of the window, add a blank rune + to make up the difference. This usually only occurs if the + modeline face is using a proportional width font or a fixed width + font of a different size from the default face font. */ + + if (c_pixpos < max_pixpos) + { + data.pixpos = c_pixpos; + data.blank_width = max_pixpos - data.pixpos; + + add_blank_rune (&data, NULL, 0); + } + + /* Now create the result string and frob the extents into it. */ + if (!NILP (result_str)) + { + int elt; + Bytecount len; + 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)); + + strdata = XSTRING_DATA (result_str); + + for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++) + { + if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) + { + len += (set_charptr_emchar + (strdata + len, Dynarr_atp (db->runes, + elt)->object.chr.ch)); + } + } + + for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr); + elt++) + { + Lisp_Object extent = Qnil; + Lisp_Object child; + + XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt)); + child = Fgethash (extent, buf->modeline_extent_table, Qnil); + if (NILP (child)) + { + child = Fmake_extent (Qnil, Qnil, result_str); + Fputhash (extent, child, buf->modeline_extent_table); + } + Fset_extent_parent (child, extent); + set_extent_endpoints + (XEXTENT (child), + Dynarr_at (formatted_string_extent_start_dynarr, elt), + Dynarr_at (formatted_string_extent_end_dynarr, elt), + result_str); + } + + in_modeline_generation = 0; + } +} + /* Ensure that the given display line DL accurately represents the modeline for the given window. */ - static void generate_modeline (struct window *w, struct display_line *dl, int type) { @@ -3523,10 +3825,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; @@ -3551,151 +3849,44 @@ generate_modeline (struct window *w, struct display_line *dl, int type) return; } - /* !!#### not right; needs to compute the max height of - all the charsets */ - font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); - - dl->ascent = XFONT_INSTANCE (font_inst)->ascent; - dl->descent = XFONT_INSTANCE (font_inst)->descent; - - min_pixpos = dl->bounds.left_out; - max_pixpos = dl->bounds.right_out; - - if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) - { - int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); - - ypos_adj = shadow_thickness; - min_pixpos += shadow_thickness; - max_pixpos -= shadow_thickness; - } - else - ypos_adj = 0; - - generate_formatted_string_db (b->modeline_format, - b->generated_modeline_string, w, dl, db, - MODELINE_INDEX, min_pixpos, max_pixpos, type); - - /* The modeline is at the bottom of the gutters. We have to wait to - 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 void -generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, - struct window *w, struct display_line *dl, - struct display_block *db, face_index findex, - int min_pixpos, int max_pixpos, int type) -{ - struct frame *f = XFRAME (w->frame); - struct device *d = XDEVICE (f->device); - - pos_data data; - int c_pixpos; - - xzero (data); - data.d = d; - data.db = db; - data.dl = dl; - data.findex = findex; - data.pixpos = min_pixpos; - data.max_pixpos = max_pixpos; - data.cursor_type = NO_CURSOR; - data.last_charset = Qunbound; - data.last_findex = DEFAULT_INDEX; - data.result_str = result_str; - data.is_modeline = 1; - data.string = Qnil; - XSETWINDOW (data.window, w); - - Dynarr_reset (formatted_string_extent_dynarr); - Dynarr_reset (formatted_string_extent_start_dynarr); - Dynarr_reset (formatted_string_extent_end_dynarr); - - /* This recursively builds up the modeline. */ - generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, - max_pixpos - min_pixpos, findex, type); - - if (Dynarr_length (db->runes)) - { - struct rune *rb = - Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); - c_pixpos = rb->xpos + rb->width; - } - else - c_pixpos = min_pixpos; - - /* If we don't reach the right side of the window, add a blank rune - to make up the difference. This usually only occurs if the - modeline face is using a proportional width font or a fixed width - font of a different size from the default face font. */ - - if (c_pixpos < max_pixpos) - { - data.pixpos = c_pixpos; - data.blank_width = max_pixpos - data.pixpos; - - add_blank_rune (&data, NULL, 0); - } - - /* Now create the result string and frob the extents into it. */ - if (!NILP (result_str)) - { - int elt; - Bytecount len; - Bufbyte *strdata; - struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); - - detach_all_extents (result_str); - resize_string (XSTRING (result_str), -1, - data.bytepos - XSTRING_LENGTH (result_str)); + /* !!#### not right; needs to compute the max height of + all the charsets */ + font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); - strdata = XSTRING_DATA (result_str); + dl->ascent = XFONT_INSTANCE (font_inst)->ascent; + dl->descent = XFONT_INSTANCE (font_inst)->descent; - for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++) - { - if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) - { - len += (set_charptr_emchar - (strdata + len, Dynarr_atp (db->runes, - elt)->object.chr.ch)); - } - } + min_pixpos = dl->bounds.left_out; + max_pixpos = dl->bounds.right_out; - for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr); - elt++) - { - Lisp_Object extent = Qnil; - Lisp_Object child; + if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) + { + int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); - XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt)); - child = Fgethash (extent, buf->modeline_extent_table, Qnil); - if (NILP (child)) - { - child = Fmake_extent (Qnil, Qnil, result_str); - Fputhash (extent, child, buf->modeline_extent_table); - } - Fset_extent_parent (child, extent); - set_extent_endpoints - (XEXTENT (child), - Dynarr_at (formatted_string_extent_start_dynarr, elt), - Dynarr_at (formatted_string_extent_end_dynarr, elt), - result_str); - } + ypos_adj = shadow_thickness; + min_pixpos += shadow_thickness; + max_pixpos -= shadow_thickness; } + else + ypos_adj = 0; + + generate_formatted_string_db (b->modeline_format, + b->generated_modeline_string, w, dl, db, + MODELINE_INDEX, min_pixpos, max_pixpos, type); + + /* The modeline is at the bottom of the gutters. We have to wait to + 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; } static Charcount -add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str, +add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str, Charcount pos, Charcount min_pos, Charcount max_pos) { /* This function has been Mule-ized. */ Charcount end; - CONST Bufbyte *cur_pos = str; + const Bufbyte *cur_pos = str; struct display_block *db = data->db; data->blank_width = space_width (XWINDOW (data->window)); @@ -3703,13 +3894,13 @@ add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str, add_blank_rune (data, NULL, 0); end = (Dynarr_length (db->runes) + - bytecount_to_charcount (str, strlen ((CONST char *) str))); + bytecount_to_charcount (str, strlen ((const char *) str))); if (max_pos != -1) end = min (max_pos, end); while (pos < end && *cur_pos) { - CONST Bufbyte *old_cur_pos = cur_pos; + const Bufbyte *old_cur_pos = cur_pos; int succeeded; data->ch = charptr_emchar (cur_pos); @@ -3734,7 +3925,8 @@ add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str, modeline extents. */ static Charcount add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, - Charcount pos, Charcount min_pos, Charcount max_pos) + Charcount pos, Charcount min_pos, + Charcount max_pos, Lisp_Object extent) { /* This function has been Mule-ized. */ Charcount end; @@ -3750,7 +3942,7 @@ add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, end = min (max_pos, end); gb.glyph = glyph; - gb.extent = Qnil; + gb.extent = extent; add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); pos++; @@ -3777,7 +3969,8 @@ static Charcount generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, Charcount min_pos, Charcount max_pos, Lisp_Object elt, int depth, int max_pixsize, - face_index findex, int type) + face_index findex, int type, Charcount *offset, + Lisp_Object cur_ext) { /* This function has been Mule-ized. */ /* #### The other losing things in this function are: @@ -3809,13 +4002,22 @@ tail_recurse: if (this != last) { - /* The string is just a string. */ + /* No %-construct */ Charcount size = - bytecount_to_charcount (last, this - last) + pos; - Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos)); + bytecount_to_charcount (last, this - last); + + if (size <= *offset) + *offset -= size; + else + { + Charcount tmp_max = (max_pos == -1 ? pos + size - *offset : + min (pos + size - *offset, max_pos)); + const Bufbyte *tmp_last = charptr_n_addr (last, *offset); - pos = add_string_to_fstring_db_runes (data, last, pos, pos, - tmp_max); + pos = add_string_to_fstring_db_runes (data, tmp_last, + pos, pos, tmp_max); + *offset = 0; + } } else /* *this == '%' */ { @@ -3840,7 +4042,7 @@ tail_recurse: pos = generate_fstring_runes (w, data, pos, spec_width, max_pos, Vglobal_mode_string, depth, max_pixsize, findex, - type); + type, offset, cur_ext); } else if (*this == '-') { @@ -3867,17 +4069,35 @@ tail_recurse: while (num_to_add--) pos = add_string_to_fstring_db_runes - (data, (CONST Bufbyte *) "-", pos, pos, max_pos); + (data, (const Bufbyte *) "-", pos, pos, max_pos); } else if (*this != 0) { - Bufbyte *str; Emchar ch = charptr_emchar (this); + Bufbyte *str; + Charcount size; + decode_mode_spec (w, ch, type); str = Dynarr_atp (mode_spec_bufbyte_string, 0); - pos = add_string_to_fstring_db_runes (data,str, pos, pos, - max_pos); + size = bytecount_to_charcount + /* Skip the null character added by `decode_mode_spec' */ + (str, Dynarr_length (mode_spec_bufbyte_string)) - 1; + + if (size <= *offset) + *offset -= size; + else + { + const Bufbyte *tmp_str = charptr_n_addr (str, *offset); + + /* #### NOTE: I don't understand why a tmp_max is not + computed and used here as in the plain string case + above. -- dv */ + pos = add_string_to_fstring_db_runes (data, tmp_str, + pos, pos, + max_pos); + *offset = 0; + } } /* NOT this++. There could be any sort of character at @@ -3903,13 +4123,26 @@ tail_recurse: if (!UNBOUNDP (tem)) { - /* If value is a string, output that string literally: + /* If value is a string, output that string literally: don't check for % within it. */ if (STRINGP (tem)) { - pos = - add_string_to_fstring_db_runes - (data, XSTRING_DATA (tem), pos, min_pos, max_pos); + Bufbyte *str = XSTRING_DATA (tem); + Charcount size = XSTRING_CHAR_LENGTH (tem); + + if (size <= *offset) + *offset -= size; + else + { + const Bufbyte *tmp_str = charptr_n_addr (str, *offset); + + /* #### NOTE: I don't understand why a tmp_max is not + computed and used here as in the plain string case + above. -- dv */ + pos = add_string_to_fstring_db_runes (data, tmp_str, pos, + min_pos, max_pos); + *offset = 0; + } } /* Give up right away for nil or t. */ else if (!EQ (tem, elt)) @@ -3934,50 +4167,53 @@ tail_recurse: else if (CONSP (elt)) { /* A cons cell: four distinct cases. - * If first element is a string or a cons, process all the elements - * and effectively concatenate them. - * If first element is a negative number, truncate displaying cdr to - * at most that many characters. If positive, pad (with spaces) - * to at least that many characters. - * If first element is a 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 a string or a cons, process all the elements + * and effectively concatenate them. + * - If first element is a negative number, truncate displaying cdr to + * at most that many characters. If positive, pad (with spaces) + * to at least that many characters. + * - 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 an extent, process the cdr recursively + * and handle the extent's face. */ + Lisp_Object car, tem; car = XCAR (elt); if (SYMBOLP (car)) - { - elt = XCDR (elt); - if (!CONSP (elt)) - goto invalid; - tem = symbol_value_in_buffer (car, w->buffer); - /* elt is now the cdr, and we know it is a cons cell. - Use its car if CAR has a non-nil value. */ - if (!UNBOUNDP (tem)) - { - if (!NILP (tem)) - { - elt = XCAR (elt); - goto tail_recurse; - } - } - /* Symbol's value is nil (or symbol is unbound) - * Get the cddr of the original list - * and if possible find the caddr and use that. - */ - elt = XCDR (elt); - if (NILP (elt)) - ; - else if (!CONSP (elt)) - goto invalid; - else - { - elt = XCAR (elt); - goto tail_recurse; - } - } + { + elt = XCDR (elt); + if (!CONSP (elt)) + goto invalid; + + tem = symbol_value_in_buffer (car, w->buffer); + /* elt is now the cdr, and we know it is a cons cell. + Use its car if CAR has a non-nil value. */ + if (!UNBOUNDP (tem)) + { + if (!NILP (tem)) + { + elt = XCAR (elt); + goto tail_recurse; + } + } + /* Symbol's value is nil (or symbol is unbound) + * Get the cddr of the original list + * and if possible find the caddr and use that. + */ + elt = XCDR (elt); + if (NILP (elt)) + ; + else if (!CONSP (elt)) + goto invalid; + else + { + elt = XCAR (elt); + goto tail_recurse; + } + } else if (INTP (car)) { Charcount lim = XINT (car); @@ -4016,13 +4252,14 @@ tail_recurse: else if (STRINGP (car) || CONSP (car)) { int limit = 50; + /* LIMIT is to protect against circular lists. */ while (CONSP (elt) && --limit > 0 && (pos < max_pos || max_pos == -1)) { pos = generate_fstring_runes (w, data, pos, pos, max_pos, - XCAR (elt), depth, - max_pixsize, findex, type); + XCAR (elt), depth, max_pixsize, + findex, type, offset, cur_ext); elt = XCDR (elt); } } @@ -4061,7 +4298,8 @@ tail_recurse: data->findex = new_findex; pos = generate_fstring_runes (w, data, pos, pos, max_pos, XCDR (elt), depth - 1, - max_pixsize, new_findex, type); + max_pixsize, new_findex, type, + offset, car); data->findex = old_findex; Dynarr_add (formatted_string_extent_dynarr, ext); Dynarr_add (formatted_string_extent_start_dynarr, start); @@ -4071,57 +4309,46 @@ tail_recurse: } else if (GLYPHP (elt)) { - pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos); + /* Glyphs are considered as one character with respect to the modeline + horizontal scrolling facility. -- dv */ + if (*offset > 0) + *offset -= 1; + else + pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos, + cur_ext); } else { invalid: - pos = - add_string_to_fstring_db_runes - (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos, - max_pos); + { + char *str = GETTEXT ("*invalid*"); + Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */ + + if (size <= *offset) + *offset -= size; + else + { + const Bufbyte *tmp_str = + charptr_n_addr ((const Bufbyte *) str, *offset); + + /* #### NOTE: I don't understand why a tmp_max is not computed and + used here as in the plain string case above. -- dv */ + pos = add_string_to_fstring_db_runes (data, tmp_str, pos, + min_pos, max_pos); + *offset = 0; + } + } } if (min_pos > pos) { - add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos, - -1); + add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos, + min_pos, -1); } return pos; } -/* The caller is responsible for freeing the returned string. */ -Bufbyte * -generate_formatted_string (struct window *w, Lisp_Object format_str, - Lisp_Object result_str, face_index findex, int type) -{ - struct display_line *dl; - struct display_block *db; - int elt = 0; - - dl = &formatted_string_display_line; - db = get_display_block_from_line (dl, TEXT); - Dynarr_reset (db->runes); - - generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0, - -1, type); - - Dynarr_reset (formatted_string_emchar_dynarr); - while (elt < Dynarr_length (db->runes)) - { - if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR) - Dynarr_add (formatted_string_emchar_dynarr, - Dynarr_atp (db->runes, elt)->object.chr.ch); - elt++; - } - - return - convert_emchar_string_into_malloced_string - ( Dynarr_atp (formatted_string_emchar_dynarr, 0), - Dynarr_length (formatted_string_emchar_dynarr), 0); -} - /* Update just the modeline. Assumes the desired display structs. If they do not have a modeline block, it does nothing. */ static void @@ -4216,9 +4443,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 @@ -4250,7 +4477,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, against this case. */ struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; struct device *d = XDEVICE (f->device); - struct Lisp_String* s = XSTRING (disp_string); + Lisp_String* s = XSTRING (disp_string); /* we're working with these a lot so precalculate them */ Bytecount slen = XSTRING_LENGTH (disp_string); @@ -4260,11 +4487,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. */ @@ -4330,6 +4556,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 */ @@ -4367,13 +4594,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; @@ -4429,10 +4650,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) @@ -4487,7 +4716,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--; @@ -4524,17 +4753,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 @@ -4568,7 +4803,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; } @@ -4610,7 +4845,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) @@ -4666,7 +4901,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. */ @@ -4699,7 +4934,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; @@ -4722,16 +4957,17 @@ 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) { - CONST Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv); + const Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv); DEC_CHARPTR (endb); if (charptr_emchar (endb) != '\n') { @@ -4805,26 +5041,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; @@ -4842,6 +5059,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) @@ -5063,6 +5282,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; @@ -5116,7 +5336,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; @@ -5169,7 +5396,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); @@ -5213,16 +5440,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) @@ -5553,20 +5786,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) @@ -5584,19 +5806,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. */ @@ -5900,7 +6112,7 @@ redisplay_window (Lisp_Object window, int skip_selected) the cache purely because glyphs have changed - this is now handled by the dirty flag.*/ if ((!echo_active && b != window_display_buffer (w)) - || !Dynarr_length (w->glyph_cachels)) + || !Dynarr_length (w->glyph_cachels) || f->faces_changed) reset_glyph_cachels (w); else mark_glyph_cachels_as_not_updated (w); @@ -5972,7 +6184,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)) ) { @@ -5986,7 +6198,7 @@ redisplay_window (Lisp_Object window, int skip_selected) && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed - && !f->subwindows_state_changed + /* && !f->subwindows_state_changed*/ && !f->point_changed && !f->windows_structure_changed) { @@ -6008,7 +6220,7 @@ redisplay_window (Lisp_Object window, int skip_selected) && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed - && !f->subwindows_state_changed + /* && !f->subwindows_state_changed*/ && !f->windows_structure_changed) { if (point_visible (w, pointm, CURRENT_DISP) @@ -6067,7 +6279,7 @@ redisplay_window (Lisp_Object window, int skip_selected) && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed - && !f->subwindows_state_changed + /* && !f->subwindows_state_changed*/ && !f->windows_structure_changed && !f->frame_changed && !truncation_changed @@ -6164,7 +6376,9 @@ regeneration_done: somewhere else once tty updates occur on a per-frame basis. */ mark_face_cachels_as_clean (w); - /* The glyph cachels only get dirty if someone changed something. */ + /* The glyph cachels only get dirty if someone changed something. + Since redisplay has now effectively ended we can reset the dirty + flag since everything must be up-to-date. */ if (glyphs_changed) mark_glyph_cachels_as_clean (w); @@ -6247,12 +6461,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 @@ -6264,6 +6479,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) @@ -6289,40 +6514,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. */ - update_frame_gutters (f); hold_frame_size_changes (); @@ -6350,10 +6573,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. */ @@ -6362,14 +6597,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; @@ -6389,28 +6628,41 @@ redisplay_frame (struct frame *f, int preemption_check) return 0; } -/* Ensure that all frames on the given device are correctly displayed. */ +/* Ensure that all frames on the given device are correctly displayed. + If AUTOMATIC is non-zero, and the device implementation indicates + no automatic redisplay, as printers do, then the device is not + redisplayed. AUTOMATIC is set to zero when called from lisp + functions (redraw-device) and (redisplay-device), and to non-zero + when called from "lazy" redisplay(); +*/ static int -redisplay_device (struct device *d) +redisplay_device (struct device *d, int automatic) { Lisp_Object frame, frmcons; - int preempted = 0; int size_change_failed = 0; struct frame *f; + 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); @@ -6424,12 +6676,11 @@ redisplay_device (struct device *d) { 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 @@ -6454,12 +6705,11 @@ redisplay_device (struct device *d) { 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; } @@ -6513,7 +6763,7 @@ redisplay_without_hooks (void) if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) { - preempted = redisplay_device (d); + preempted = redisplay_device (d, 1); if (preempted) { @@ -6627,7 +6877,7 @@ static void decode_mode_spec (struct window *w, Emchar spec, int type) { Lisp_Object obj = Qnil; - CONST char *str = NULL; + const char *str = NULL; struct buffer *b = XBUFFER (w->buffer); Dynarr_reset (mode_spec_bufbyte_string); @@ -6656,7 +6906,7 @@ decode_mode_spec (struct window *w, Emchar spec, int type) long_to_string (buf, col); Dynarr_add_many (mode_spec_bufbyte_string, - (CONST Bufbyte *) buf, strlen (buf)); + (const Bufbyte *) buf, strlen (buf)); goto decode_mode_spec_done; } @@ -6993,7 +7243,9 @@ mark_glyph_block_dynarr (glyph_block_dynarr *gba) } } -static void +/* See the comment in image_instantiate_cache_result as to why marking + the glyph will also mark the image_instance. */ +void mark_redisplay_structs (display_line_dynarr *dla) { display_line *dl = Dynarr_atp (dla, 0); @@ -7051,8 +7303,8 @@ 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); } } @@ -7222,7 +7474,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++; @@ -7350,7 +7603,7 @@ find_point_loop: while (1) { - unsigned int new_pos; + EMACS_INT new_pos; Bufpos start, end; pos = (bottom + top + 1) >> 1; @@ -7489,11 +7742,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; @@ -7513,7 +7773,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) { @@ -7577,7 +7837,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 @@ -7587,9 +7847,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. */ @@ -7773,7 +8040,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); @@ -7782,7 +8048,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; } @@ -7795,7 +8060,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; } @@ -7824,7 +8088,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; } @@ -7852,7 +8115,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; } @@ -7861,7 +8123,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; } @@ -7884,7 +8145,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; } @@ -7910,7 +8170,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; } @@ -7919,7 +8178,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; } @@ -7939,23 +8197,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; @@ -8001,7 +8245,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; } @@ -8035,7 +8278,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); } @@ -8743,7 +8985,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; @@ -8776,6 +9018,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 @@ -8784,19 +9029,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; @@ -8831,6 +9072,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); } @@ -8858,6 +9102,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); } @@ -8885,7 +9138,10 @@ input and is guaranteed to proceed to completion. { XFRAME (XCAR (frmcons))->clear = 1; } - redisplay_device (d); + redisplay_device (d, 0); + + /* See the comment in Fredisplay_frame. */ + RESET_CHANGED_SET_FLAGS; return unbind_to (count, Qnil); } @@ -8912,7 +9168,10 @@ input and is guaranteed to proceed to completion. disable_preemption++; } - redisplay_device (d); + redisplay_device (d, 0); + + /* See the comment in Fredisplay_frame. */ + RESET_CHANGED_SET_FLAGS; return unbind_to (count, Qnil); } @@ -9092,14 +9351,18 @@ init_redisplay (void) if (!initialized) #endif { - cmotion_display_lines = Dynarr_new (display_line); - mode_spec_bufbyte_string = Dynarr_new (Bufbyte); - formatted_string_emchar_dynarr = Dynarr_new (Emchar); - formatted_string_extent_dynarr = Dynarr_new (EXTENT); - formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); - formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); - internal_cache = Dynarr_new (line_start_cache); - xzero (formatted_string_display_line); + if (!cmotion_display_lines) + cmotion_display_lines = Dynarr_new (display_line); + if (!mode_spec_bufbyte_string) + mode_spec_bufbyte_string = Dynarr_new (Bufbyte); + if (!formatted_string_extent_dynarr) + formatted_string_extent_dynarr = Dynarr_new (EXTENT); + if (!formatted_string_extent_start_dynarr) + formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); + if (!formatted_string_extent_end_dynarr) + formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); + if (!internal_cache) + internal_cache = Dynarr_new (line_start_cache); } /* window system is nil when in -batch mode */ @@ -9124,6 +9387,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")) { @@ -9172,6 +9444,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); @@ -9183,15 +9457,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); @@ -9236,7 +9503,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; @@ -9260,10 +9529,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. @@ -9307,24 +9585,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 @@ -9383,10 +9666,10 @@ This is a specifier; use `set-specifier' to change it. Vleft_margin_width = Fmake_specifier (Qnatnum); set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); set_specifier_caching (Vleft_margin_width, - slot_offset (struct window, left_margin_width), + offsetof (struct window, left_margin_width), some_window_value_changed, - slot_offset (struct frame, left_margin_width), - margin_width_changed_in_frame); + offsetof (struct frame, left_margin_width), + margin_width_changed_in_frame, 0); DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* *Width of right margin. @@ -9395,10 +9678,10 @@ This is a specifier; use `set-specifier' to change it. Vright_margin_width = Fmake_specifier (Qnatnum); set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); set_specifier_caching (Vright_margin_width, - slot_offset (struct window, right_margin_width), + offsetof (struct window, right_margin_width), some_window_value_changed, - slot_offset (struct frame, right_margin_width), - margin_width_changed_in_frame); + offsetof (struct frame, right_margin_width), + margin_width_changed_in_frame, 0); DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* *Minimum ascent height of lines. @@ -9407,9 +9690,9 @@ This is a specifier; use `set-specifier' to change it. Vminimum_line_ascent = Fmake_specifier (Qnatnum); set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); set_specifier_caching (Vminimum_line_ascent, - slot_offset (struct window, minimum_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. @@ -9418,9 +9701,9 @@ This is a specifier; use `set-specifier' to change it. Vminimum_line_descent = Fmake_specifier (Qnatnum); set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); set_specifier_caching (Vminimum_line_descent, - slot_offset (struct window, minimum_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 @@ -9430,9 +9713,9 @@ This is a specifier; use `set-specifier' to change it. Vuse_left_overflow = Fmake_specifier (Qboolean); set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); set_specifier_caching (Vuse_left_overflow, - slot_offset (struct window, use_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 @@ -9442,9 +9725,9 @@ This is a specifier; use `set-specifier' to change it. Vuse_right_overflow = Fmake_specifier (Qboolean); set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); set_specifier_caching (Vuse_right_overflow, - slot_offset (struct window, use_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). @@ -9453,8 +9736,8 @@ This is a specifier; use `set-specifier' to change it. Vtext_cursor_visible_p = Fmake_specifier (Qboolean); set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); set_specifier_caching (Vtext_cursor_visible_p, - slot_offset (struct window, text_cursor_visible_p), + offsetof (struct window, text_cursor_visible_p), text_cursor_visible_p_changed, - 0, 0); + 0, 0, 0); }