X-Git-Url: http://git.chise.org/gitweb/?p=chise%2Fxemacs-chise.git.1;a=blobdiff_plain;f=src%2Fredisplay.c;h=e664075d4b6d06156fd95b37a057838e6f1a63d0;hp=6604dd2032d269647e1e6ebe8be737a58e166117;hb=ac7d0619aad74b1d57c4748ebb3ab29d9c32e3d8;hpb=59eec5f21669e81977b5b1fe9bf717cab49cf7fb diff --git a/src/redisplay.c b/src/redisplay.c index 6604dd2..e664075 100644 --- a/src/redisplay.c +++ b/src/redisplay.c @@ -147,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). @@ -163,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. */ @@ -192,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. */ @@ -229,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; }; @@ -265,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,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. */ @@ -315,10 +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; +Fixnum horizontal_clip; /* Nonzero means reading single-character input with prompt so put cursor on minibuffer after the prompt. */ @@ -392,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; @@ -425,10 +451,10 @@ Lisp_Object Vglobal_mode_string; /* The number of lines scroll a window by when point leaves the window; if it is <=0 then point is centered in the window */ -int scroll_step; +Fixnum scroll_step; /* Scroll up to this many lines, to bring point back on screen. */ -int scroll_conservatively; +Fixnum scroll_conservatively; /* Marker for where to display an arrow on top of the buffer text. */ Lisp_Object Voverlay_arrow_position; @@ -451,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; @@ -464,8 +491,7 @@ int column_number_start_at_one; Lisp_Object Qtop_bottom; -#define WINDOW_SCROLLED(w) \ -(w->hscroll > 0 || w->left_xoffset) +#define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset) /***************************************************************************/ @@ -680,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 @@ -811,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; @@ -868,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; } @@ -953,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; @@ -972,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) { @@ -997,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; @@ -1106,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) @@ -1171,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 @@ -1256,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)) { @@ -1315,7 +1465,7 @@ add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry) } } } - prop = add_bufbyte_string_runes (data, result, dst - result, 0); + prop = add_bufbyte_string_runes (data, result, dst - result, 0, 0); } } @@ -1544,6 +1694,7 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, Lisp_Object face; Lisp_Object instance; face_index findex; + prop_block_dynarr *retval = 0; if (cachel) width = cachel->width; @@ -1555,7 +1706,6 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, if (data->start_col || data->start_col_xoffset) { - prop_block_dynarr *retval; int glyph_char_width = width / space_width (w); /* If we still have not fully scrolled horizontally after @@ -1591,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) @@ -1617,6 +1791,8 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, baseline = glyph_baseline (gb->glyph, data->window); + rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */ + if (glyph_contrib_p (gb->glyph, data->window)) { /* A pixmap that has not had a baseline explicitly set. Its @@ -1624,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); } @@ -1646,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. */ @@ -1673,11 +1853,11 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, if (!allow_cursor) data->bi_bufpos = 0; add_bufbyte_string_runes (data, XSTRING_DATA (string), - XSTRING_LENGTH (string), 0); + XSTRING_LENGTH (string), 0, 1); data->findex = orig_findex; data->bi_bufpos = orig_bufpos; data->bi_start_col_enabled = orig_start_col_enabled; - return NULL; + return retval; } rb.findex = findex; @@ -1694,6 +1874,9 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, 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) { @@ -1729,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 { @@ -1758,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 @@ -1818,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 @@ -1916,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)) { @@ -2012,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); @@ -2085,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; @@ -2109,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 @@ -2155,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 @@ -2236,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)) { @@ -2445,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; @@ -2580,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; @@ -2617,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)) @@ -2695,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)) { @@ -2706,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; @@ -2724,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; } @@ -2795,20 +3007,13 @@ add_margin_runes (struct display_line *dl, struct display_block *db, int start, (reverse ? elt-- : elt++); } - 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; + calculate_yoffset (dl, data.db); + return data.pixpos; } @@ -4238,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 @@ -4282,7 +4487,6 @@ 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, it's an FSF thing and invisible extents are the way to go here. @@ -4390,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; @@ -4452,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) @@ -4510,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--; @@ -4547,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 @@ -4591,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; } @@ -4633,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) @@ -4689,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. */ @@ -4722,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; @@ -4750,7 +4962,7 @@ done: 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) @@ -4829,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; @@ -4866,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) @@ -6271,7 +6466,8 @@ 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 @@ -6319,8 +6515,13 @@ redisplay_frame (struct frame *f, int preemption_check) update_frame_menubars (f); #endif /* HAVE_MENUBARS */ #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 @@ -6400,6 +6601,14 @@ redisplay_frame (struct frame *f, int preemption_check) 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; @@ -6431,27 +6640,29 @@ static int redisplay_device (struct device *d, int automatic) { Lisp_Object frame, frmcons; - int preempted = 0; int size_change_failed = 0; struct frame *f; - if (automatic - && (MAYBE_INT_DEVMETH (d, device_implementation_flags, ()) - & XDEVIMPF_NO_AUTO_REDISPLAY)) + if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY)) return 0; if (DEVICE_STREAM_P (d)) /* nothing to do */ return 0; /* It is possible that redisplay has been called before the - device is fully initialized. If so then continue with the - next device. */ + device is fully initialized, or that the console implementation + allows frameless devices. If so then continue with the next + device. */ if (NILP (DEVICE_SELECTED_FRAME (d))) return 0; - REDISPLAY_PREEMPTION_CHECK; - if (preempted) - return 1; + if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) + { + int preempted; + REDISPLAY_PREEMPTION_CHECK; + if (preempted) + return 1; + } /* Always do the selected frame first. */ frame = DEVICE_SELECTED_FRAME (d); @@ -6465,12 +6676,11 @@ redisplay_device (struct device *d, int automatic) { if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) { - preempted = redisplay_frame (f, 0); + int preempted = redisplay_frame (f, 0); + if (preempted) + return 1; } - if (preempted) - return 1; - /* If the frame redisplay did not get preempted, then this flag should have gotten set to 0. It might be possible for that not to happen if a size change event were to occur at an odd @@ -6495,12 +6705,11 @@ redisplay_device (struct device *d, int automatic) { if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) { - preempted = redisplay_frame (f, 0); + int preempted = redisplay_frame (f, 0); + if (preempted) + return 1; } - if (preempted) - return 1; - if (f->size_change_pending) size_change_failed = 1; } @@ -7094,7 +7303,6 @@ mark_redisplay (void) FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) { struct frame *f = XFRAME (XCAR (frmcons)); - update_frame_window_mirror (f); mark_window_mirror (f->root_mirror); mark_gutters (f); } @@ -7266,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++; @@ -7394,7 +7603,7 @@ find_point_loop: while (1) { - unsigned int new_pos; + EMACS_INT new_pos; Bufpos start, end; pos = (bottom + top + 1) >> 1; @@ -9178,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")) { @@ -9286,7 +9504,7 @@ See also `overlay-arrow-string'. DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* 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 +\(Note that despite the name of this variable, it can be set to a glyph as well as a string.) */ , redisplay_variable_changed); @@ -9367,7 +9585,7 @@ 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; @@ -9451,7 +9669,7 @@ This is a specifier; use `set-specifier' to change it. offsetof (struct window, left_margin_width), some_window_value_changed, offsetof (struct frame, left_margin_width), - margin_width_changed_in_frame); + margin_width_changed_in_frame, 0); DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* *Width of right margin. @@ -9463,7 +9681,7 @@ This is a specifier; use `set-specifier' to change it. offsetof (struct window, right_margin_width), some_window_value_changed, offsetof (struct frame, right_margin_width), - margin_width_changed_in_frame); + margin_width_changed_in_frame, 0); DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* *Minimum ascent height of lines. @@ -9474,7 +9692,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vminimum_line_ascent, offsetof (struct window, minimum_line_ascent), some_window_value_changed, - 0, 0); + 0, 0, 0); DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* *Minimum descent height of lines. @@ -9485,7 +9703,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vminimum_line_descent, offsetof (struct window, minimum_line_descent), some_window_value_changed, - 0, 0); + 0, 0, 0); DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* *Non-nil means use the left outside margin as extra whitespace when @@ -9497,7 +9715,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vuse_left_overflow, offsetof (struct window, use_left_overflow), some_window_value_changed, - 0, 0); + 0, 0, 0); DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* *Non-nil means use the right outside margin as extra whitespace when @@ -9509,7 +9727,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vuse_right_overflow, offsetof (struct window, use_right_overflow), some_window_value_changed, - 0, 0); + 0, 0, 0); DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* *Non-nil means the text cursor is visible (this is usually the case). @@ -9520,6 +9738,6 @@ This is a specifier; use `set-specifier' to change it. set_specifier_caching (Vtext_cursor_visible_p, offsetof (struct window, text_cursor_visible_p), text_cursor_visible_p_changed, - 0, 0); + 0, 0, 0); }