X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fredisplay-output.c;h=4396a8f2d823e7ef69743e1b7f18bb82a82a3175;hb=ac155f65fdad732a944b5217c90d8340818e0c0a;hp=5b8228c0f2fee82ca1cce6ec2ec3e3e8c1d9a9b0;hpb=afa9772e3fcbb4e80e3e4cfd1a40b4fccc6d08b8;p=chise%2Fxemacs-chise.git- diff --git a/src/redisplay-output.c b/src/redisplay-output.c index 5b8228c..4396a8f 100644 --- a/src/redisplay-output.c +++ b/src/redisplay-output.c @@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA. */ #include "glyphs.h" #include "redisplay.h" #include "faces.h" +#include "gutter.h" static int compare_runes (struct window *w, struct rune *crb, struct rune *drb); @@ -47,16 +48,16 @@ static void redraw_cursor_in_window (struct window *w, int run_end_begin_glyphs); static void redisplay_output_display_block (struct window *w, struct display_line *dl, int block, int start, int end, int start_pixpos, - int cursor_start, int cursor_width, + int cursor_start, int cursor_width, int cursor_height); -static void redisplay_normalize_display_box (struct display_box* dest, +static void redisplay_normalize_display_box (struct display_box* dest, struct display_glyph_area* src); static int redisplay_display_boxes_in_window_p (struct window* w, struct display_box* db, struct display_glyph_area* dga); -static void redisplay_clear_clipped_region (Lisp_Object locale, face_index findex, - struct display_box* dest, - struct display_glyph_area* glyphsrc, +static void redisplay_clear_clipped_region (Lisp_Object locale, face_index findex, + struct display_box* dest, + struct display_glyph_area* glyphsrc, int fullheight_p, Lisp_Object); /***************************************************************************** @@ -101,7 +102,7 @@ sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra) For the given LINE in window W, make the current display line equal the desired display line. ****************************************************************************/ -static void +void sync_display_line_structs (struct window *w, int line, int do_blocks, display_line_dynarr *cdla, display_line_dynarr *ddla) @@ -181,7 +182,7 @@ sync_display_line_structs (struct window *w, int line, int do_blocks, /***************************************************************************** compare_runes - Compare to runes to see if each of their fields is equal. If so, + Compare two runes to see if each of their fields is equal. If so, return true otherwise return false. ****************************************************************************/ static int @@ -210,11 +211,8 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb) #### It would really be worth it to arrange for this function to be (almost) a single call to memcmp. */ - - if ((crb->findex != drb->findex) || - (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))) - return 0; - else if (crb->xpos != drb->xpos) + + if (crb->xpos != drb->xpos) return 0; else if (crb->width != drb->width) return 0; @@ -223,30 +221,81 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb) else if (crb->type != drb->type) return 0; else if (crb->type == RUNE_CHAR && - (crb->object.chr.ch != drb->object.chr.ch)) + !CHARC_EQ (crb->object.cglyph, drb->object.cglyph)) return 0; else if (crb->type == RUNE_HLINE && (crb->object.hline.thickness != drb->object.hline.thickness || crb->object.hline.yoffset != drb->object.hline.yoffset)) return 0; - else if (crb->type == RUNE_DGLYPH && + else if (crb->type == RUNE_DGLYPH && (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) return 0; /* Only check dirtiness if we know something has changed. */ else if (crb->type == RUNE_DGLYPH && - XFRAME (w->frame)->glyphs_changed) + (XGLYPH_DIRTYP (crb->object.dglyph.glyph) || + crb->findex != drb->findex)) { - glyph_index gindex = get_glyph_cachel_index (w, drb->object.dglyph.glyph); - /* Although doing the cachel lookup for every comparison is - very expensive.we have to do it to make sure the cache is - up-to-date. */ - if (GLYPH_CACHEL_DIRTYP (w, gindex)) + /* We need some way of telling redisplay_output_layout () that the + only reason we are outputting it is because something has + changed internally. That way we can optimize whether we need + to clear the layout first and also only output the components + that have changed. The image_instance dirty flag and + display_hash are no good to us because these will invariably + have been set anyway if the layout has changed. So it looks + like we need yet another change flag that we can set here and + then clear in redisplay_output_layout (). */ + Lisp_Object window, image; + Lisp_Image_Instance* ii; + XSETWINDOW (window, w); + image = glyph_image_instance (crb->object.dglyph.glyph, + window, ERROR_ME_NOT, 1); + + if (!IMAGE_INSTANCEP (image)) + return 0; + ii = XIMAGE_INSTANCE (image); + + if (TEXT_IMAGE_INSTANCEP (image) && + (crb->findex != drb->findex || + WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))) return 0; - else + + /* It is quite common for the two glyphs to be EQ since in many + cases they will actually be the same object. This does not + mean, however, that nothing has changed. We therefore need to + check the current hash of the glyph against the last recorded + display hash and the pending display items. See + update_subwindow (). */ + if (image_instance_changed (image) || + crb->findex != drb->findex || + WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)) + { + /* We now now we are going to re-output the glyph, but since + this is for some internal reason not related to geometry + changes, send a hint to the output routines that they can + take some short cuts. This is most useful for + layouts. This flag should get reset by the output + routines. + + #### It is possible for us to get here when the + face_cachel is dirty. I do not know what the implications + of this are.*/ + IMAGE_INSTANCE_OPTIMIZE_OUTPUT (ii) = 1; + return 0; + } + else return 1; } + /* We now do this last so that glyph checks can do their own thing + for face changes. Face changes quite often happen when we are + trying to output something in the gutter, this would normally + lead to a lot of flashing. The indices can quite often be + different and yet the faces are the same, we do not want to + re-output in this instance. */ + else if (crb->findex != drb->findex || + WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)) + return 0; else return 1; } @@ -657,7 +706,7 @@ output_display_line (struct window *w, display_line_dynarr *cdla, if (x < ddl->bounds.left_in) { findex = ddl->left_margin_findex ? - ddl->left_margin_findex + ddl->left_margin_findex : get_builtin_face_cache_index (w, Vleft_margin_face); } else if (x < ddl->bounds.right_in) @@ -668,7 +717,7 @@ output_display_line (struct window *w, display_line_dynarr *cdla, else if (x < ddl->bounds.right_out) { findex = ddl->right_margin_findex ? - ddl->right_margin_findex + ddl->right_margin_findex : get_builtin_face_cache_index (w, Vright_margin_face); } else @@ -712,10 +761,10 @@ output_display_line (struct window *w, display_line_dynarr *cdla, region or if it was a block of a different type, then output the entire ddb. Otherwise, compare cdb and ddb and output only the changed region. */ - if (!force && cdb && ddb->type == cdb->type + if (!force && cdb && ddb->type == cdb->type /* If there was no buffer being display before the compare anyway as we might be outputting a gutter. */ - && + && (b == old_b || !old_b)) { must_sync |= compare_display_blocks (w, cdl, ddl, old_block, @@ -754,7 +803,7 @@ output_display_line (struct window *w, display_line_dynarr *cdla, cursor_start, cursor_width, cursor_height); } - + start_pixpos = next_start_pixpos; } } @@ -778,7 +827,7 @@ output_display_line (struct window *w, display_line_dynarr *cdla, y -= MODELINE_SHADOW_THICKNESS (w); height += (2 * MODELINE_SHADOW_THICKNESS (w)); } - + if (window_is_leftmost (w)) clear_left_border (w, y, height); if (window_is_rightmost (w)) @@ -850,16 +899,11 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end) } else { - DEVMETH (d, output_begin, (d)); - - /* #### This is a gross kludge. Cursor handling is such a royal - pain in the ass. */ - if (rb->type == RUNE_DGLYPH && - (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) || - EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))) - rb->cursor_type = NO_CURSOR; - else - rb->cursor_type = CURSOR_OFF; + { + MAYBE_DEVMETH (d, frame_output_begin, (f)); + MAYBE_DEVMETH (d, window_output_begin, (w)); + } + rb->cursor_type = CURSOR_OFF; dl->cursor_elt = -1; output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width); } @@ -873,7 +917,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end) if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d)))) { if (!no_output_end) - DEVMETH (d, output_end, (d)); + { + MAYBE_DEVMETH (d, window_output_end, (w)); + MAYBE_DEVMETH (d, frame_output_end, (f)); + } return 1; } @@ -892,7 +939,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end) output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width); if (!no_output_end) - DEVMETH (d, output_end, (d)); + { + MAYBE_DEVMETH (d, window_output_end, (w)); + MAYBE_DEVMETH (d, frame_output_end, (f)); + } return 1; } else @@ -924,7 +974,7 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end) } } - while ((up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0))) + while (up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0)) { dl = Dynarr_atp (cla, cur_dl); db = get_display_block_from_line (dl, TEXT); @@ -956,7 +1006,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end) make_int (ADJ_BUFPOS), w->buffer); if (!no_output_end) - DEVMETH (d, output_end, (d)); + { + MAYBE_DEVMETH (d, window_output_end, (w)); + MAYBE_DEVMETH (d, frame_output_end, (f)); + } return 1; } @@ -969,7 +1022,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end) } if (!no_output_end) - DEVMETH (d, output_end, (d)); + { + MAYBE_DEVMETH (d, window_output_end, (w)); + MAYBE_DEVMETH (d, frame_output_end, (f)); + } return 0; } #undef ADJ_BUFPOS @@ -1024,12 +1080,18 @@ redraw_cursor_in_window (struct window *w, int run_end_begin_meths) (f, dl->ypos - 1, rb->xpos)); if (run_end_begin_meths) - DEVMETH (d, output_begin, (d)); + { + MAYBE_DEVMETH (d, frame_output_begin, (f)); + MAYBE_DEVMETH (d, window_output_begin, (w)); + } output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width); if (run_end_begin_meths) - DEVMETH (d, output_end, (d)); + { + MAYBE_DEVMETH (d, window_output_end, (w)); + MAYBE_DEVMETH (d, frame_output_end, (f)); + } } } @@ -1067,6 +1129,8 @@ redisplay_output_display_block (struct window *w, struct display_line *dl, int b { struct frame *f = XFRAME (w->frame); struct device *d = XDEVICE (f->device); + /* Temporarily disabled until generalization is done. */ +#if 0 struct display_block *db = Dynarr_atp (dl->display_blocks, block); rune_dynarr *rba = db->runes; struct rune *rb; @@ -1084,6 +1148,7 @@ redisplay_output_display_block (struct window *w, struct display_line *dl, int b rb = Dynarr_atp (rba, end - 1); width = rb->xpos + rb->width - xpos; +#endif /* now actually output the block. */ DEVMETH (d, output_display_block, (w, dl, block, start, end, start_pixpos, @@ -1097,25 +1162,30 @@ redisplay_output_display_block (struct window *w, struct display_line *dl, int b Remove subwindows from the area in the box defined by the given parameters. ****************************************************************************/ -static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height, - Lisp_Object ignored_window) +static void +redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height, + Lisp_Object ignored_window) { - int elt; + Lisp_Object rest; - for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) + LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))) { - struct subwindow_cachel *cachel = - Dynarr_atp (f->subwindow_cachels, elt); - - if (cachel->being_displayed + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest)); + if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) + && + IMAGE_INSTANCE_DISPLAY_X (ii) + + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) > x + && + IMAGE_INSTANCE_DISPLAY_X (ii) < x + width + && + IMAGE_INSTANCE_DISPLAY_Y (ii) + + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > y && - cachel->x + cachel->width > x && cachel->x < x + width + IMAGE_INSTANCE_DISPLAY_Y (ii) < y + height && - cachel->y + cachel->height > y && cachel->y < y + height - && - !EQ (cachel->subwindow, ignored_window)) + !EQ (XCAR (rest), ignored_window)) { - unmap_subwindow (cachel->subwindow); + unmap_subwindow (XCAR (rest)); } } } @@ -1128,16 +1198,16 @@ static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width ****************************************************************************/ void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height) { - if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) + if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))) { redisplay_unmap_subwindows (f, x, y, width, height, Qnil); } } -static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width, +static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width, int height, Lisp_Object subwindow) { - if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) + if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))) { redisplay_unmap_subwindows (f, x, y, width, height, subwindow); } @@ -1151,18 +1221,23 @@ static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, pixmaps, backgrounds etc. ****************************************************************************/ void -redisplay_output_subwindow (struct window *w, +redisplay_output_subwindow (struct window *w, Lisp_Object image_instance, struct display_box* db, struct display_glyph_area* dga, face_index findex, int cursor_start, int cursor_width, int cursor_height) { - struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); + Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); Lisp_Object window; struct display_glyph_area sdga; - dga->height = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p); - dga->width = IMAGE_INSTANCE_SUBWINDOW_WIDTH (p); + dga->height = IMAGE_INSTANCE_HEIGHT (p); + dga->width = IMAGE_INSTANCE_WIDTH (p); + + /* The first thing we are going to do is update the display + characteristics of the subwindow. This also clears the dirty + flags as a side effect. */ + redisplay_subwindow (image_instance); /* This makes the glyph area fit into the display area. */ if (!redisplay_normalize_glyph_area (db, dga)) @@ -1187,17 +1262,22 @@ redisplay_output_subwindow (struct window *w, cases.*/ sdga.xoffset = -dga->xoffset; sdga.yoffset = -dga->yoffset; - sdga.height = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p); - sdga.width = IMAGE_INSTANCE_SUBWINDOW_WIDTH (p); - - if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0) + sdga.height = IMAGE_INSTANCE_HEIGHT (p); + sdga.width = IMAGE_INSTANCE_WIDTH (p); + + if (redisplay_display_boxes_in_window_p (w, db, &sdga) == 0 + || + /* We only want to do full subwindow display for windows that + are completely in the gutter, otherwise we must clip to be + safe. */ + display_boxes_in_gutter_p (XFRAME (w->frame), db, &sdga) <= 0) { map_subwindow (image_instance, db->xpos, db->ypos, dga); } else { sdga.xoffset = sdga.yoffset = 0; - map_subwindow (image_instance, db->xpos - dga->xoffset, + map_subwindow (image_instance, db->xpos - dga->xoffset, db->ypos - dga->yoffset, &sdga); } } @@ -1206,53 +1286,64 @@ redisplay_output_subwindow (struct window *w, redisplay_output_layout Output a widget hierarchy. This can safely call itself recursively. + + The complexity of outputting layouts is deciding whether to do it or + not. Consider a layout enclosing some text, the text changes and is + marked as dirty, but the enclosing layout has not been marked as + dirty so no updates occur and the text will potentially be truncated. + Alternatively we hold a back pointer in the image instance to the + parent and mark the parent as dirty. But the layout code assumes that + if the layout is dirty then the whole layout should be redisplayed, + so we then get lots of flashing even though only the text has changed + size. Of course if the text shrinks in size then we do actually need + to redisplay the layout to repaint the exposed area. So what happens + if we make a non-structural change like changing color? Either we + redisplay everything, or we redisplay nothing. These are exactly the + issues lwlib has to grapple with. We really need to know what has + actually changed and make a layout decision based on that. We also + really need to know what has changed so that we can only make the + necessary changes in update_subwindow. This has all now been + implemented, Viva la revolution! ****************************************************************************/ void -redisplay_output_layout (struct window *w, +redisplay_output_layout (Lisp_Object domain, Lisp_Object image_instance, struct display_box* db, struct display_glyph_area* dga, face_index findex, int cursor_start, int cursor_width, int cursor_height) { - struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); - Lisp_Object window, rest; - Emchar_dynarr *buf = Dynarr_new (Emchar); - struct frame *f = XFRAME (w->frame); - struct device *d = XDEVICE (f->device); + Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); + Lisp_Object rest, window = DOMAIN_WINDOW (domain); + Charc_dynarr *buf = Dynarr_new (Charc); + struct window *w = XWINDOW (window); + struct device *d = DOMAIN_XDEVICE (domain); int layout_height, layout_width; - /* We bogusly don't take f->extents_changed and f->glyphs_changed - into account. This is because if we do we always redisplay the - entire layout. So far I have seen no ill effects to we'll see. */ - int frame_changed = (f->buffers_changed || - f->clip_changed || - f->faces_changed || - f->frame_changed || - f->modeline_changed || - f->subwindows_changed || - f->windows_changed || - f->windows_structure_changed); - XSETWINDOW (window, w); - - layout_height = glyph_height (image_instance, Qnil, findex, window); - layout_width = glyph_width (image_instance, Qnil, findex, window); + layout_height = glyph_height (image_instance, domain); + layout_width = glyph_width (image_instance, domain); dga->height = layout_height; dga->width = layout_width; - +#ifdef DEBUG_WIDGET_OUTPUT + printf ("outputing layout glyph %p\n", p); +#endif /* This makes the glyph area fit into the display area. */ if (!redisplay_normalize_glyph_area (db, dga)) return; /* Highly dodgy optimization. We want to only output the whole layout if we really have to. */ - if (frame_changed || IMAGE_INSTANCE_DIRTYP (p)) + if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p) + || IMAGE_INSTANCE_LAYOUT_CHANGED (p) + || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) + || IMAGE_INSTANCE_SIZE_CHANGED (p) + || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) { /* First clear the area we are drawing into. This is the easiest thing to do since we have many gaps that we have to make sure are filled in. */ redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil); - + /* Output a border if required */ if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p))) { @@ -1260,7 +1351,7 @@ redisplay_output_layout (struct window *w, enum edge_style style; int ypos = db->ypos; int height = dga->height; - + if (dga->xoffset >= 0) edges |= EDGE_LEFT; if (dga->width - dga->xoffset == layout_width) @@ -1269,7 +1360,7 @@ redisplay_output_layout (struct window *w, edges |= EDGE_TOP; if (dga->height - dga->yoffset == layout_height) edges |= EDGE_BOTTOM; - + if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in)) style = EDGE_ETCHED_IN; else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out)) @@ -1288,13 +1379,13 @@ redisplay_output_layout (struct window *w, else style = EDGE_BEVEL_OUT; - MAYBE_DEVMETH (d, bevel_area, + MAYBE_DEVMETH (d, bevel_area, (w, findex, db->xpos, - ypos, + ypos, dga->width, height, 2, edges, style)); } } - + /* This shrinks the display box to exactly enclose the glyph area. */ redisplay_normalize_display_box (db, dga); @@ -1302,7 +1393,8 @@ redisplay_output_layout (struct window *w, /* Flip through the widgets in the layout displaying as necessary */ LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p)) { - Lisp_Object child = XCAR (rest); + Lisp_Object child = glyph_image_instance (XCAR (rest), image_instance, + ERROR_ME_NOT, 1); struct display_box cdb; /* For losing HP-UX */ @@ -1314,13 +1406,17 @@ redisplay_output_layout (struct window *w, /* First determine if the image is visible at all */ if (IMAGE_INSTANCEP (child)) { - struct Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child); + Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child); + /* The enclosing layout offsets are +ve at this point */ struct display_glyph_area cdga; cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset; cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset; - cdga.width = glyph_width (child, Qnil, findex, window); - cdga.height = glyph_height (child, Qnil, findex, window); + cdga.width = glyph_width (child, image_instance); + cdga.height = glyph_height (child, image_instance); + + IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = + IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p); /* Although normalization is done by the output routines we have to do it here so that they don't try and @@ -1336,7 +1432,7 @@ redisplay_output_layout (struct window *w, continue; /* We have to invert the offset here as normalization will have made them positive which the output - routines will treat as a truely +ve offset. */ + routines will treat as a truly +ve offset. */ cdga.xoffset = -cdga.xoffset; cdga.yoffset = -cdga.yoffset; @@ -1346,25 +1442,35 @@ redisplay_output_layout (struct window *w, { /* #### This is well hacked and could use some generalisation.*/ - if (redisplay_normalize_glyph_area (&cdb, &cdga) - && - (frame_changed || IMAGE_INSTANCE_DIRTYP (childii))) + if (redisplay_normalize_glyph_area (&cdb, &cdga) + && + (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) || + IMAGE_INSTANCE_DIRTYP (childii))) { struct display_line dl; /* this is fake */ Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (childii); - convert_bufbyte_string_into_emchar_dynarr - (XSTRING_DATA (string), XSTRING_LENGTH (string), buf); - + Charset_ID charsets[NUM_LEADING_BYTES]; + struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex); + + find_charsets_in_bufbyte_string (charsets, + XSTRING_DATA (string), + XSTRING_LENGTH (string)); + ensure_face_cachel_complete (cachel, window, charsets); + + convert_bufbyte_string_into_charc_dynarr + (XSTRING_DATA (string), XSTRING_LENGTH (string), + buf); + redisplay_normalize_display_box (&cdb, &cdga); /* Offsets are now +ve again so be careful when fixing up the display line. */ xzero (dl); /* Munge boxes into display lines. */ dl.ypos = (cdb.ypos - cdga.yoffset) - + glyph_ascent (child, Qnil, findex, window); - dl.ascent = glyph_ascent (child, Qnil, findex, window); - dl.descent = glyph_descent (child, Qnil, findex, window); + + glyph_ascent (child, image_instance); + dl.ascent = glyph_ascent (child, image_instance); + dl.descent = glyph_descent (child, image_instance); dl.top_clip = cdga.yoffset; dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height); /* output_string doesn't understand offsets in @@ -1379,37 +1485,46 @@ redisplay_output_layout (struct window *w, } } break; - + case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: - if (frame_changed || IMAGE_INSTANCE_DIRTYP (childii)) + if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) + || IMAGE_INSTANCE_DIRTYP (childii)) redisplay_output_pixmap (w, child, &cdb, &cdga, findex, 0, 0, 0, 0); break; - + case IMAGE_WIDGET: + if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (childii), Qlayout)) + { + redisplay_output_layout (image_instance, child, &cdb, &cdga, findex, + 0, 0, 0); + break; + } case IMAGE_SUBWINDOW: - if (frame_changed || IMAGE_INSTANCE_DIRTYP (childii)) + if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) || + IMAGE_INSTANCE_DIRTYP (childii)) redisplay_output_subwindow (w, child, &cdb, &cdga, findex, 0, 0, 0); break; - - case IMAGE_LAYOUT: - redisplay_output_layout (w, child, &cdb, &cdga, findex, - 0, 0, 0); - break; - + case IMAGE_NOTHING: /* nothing is as nothing does */ break; - + case IMAGE_POINTER: default: abort (); } } + IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0; } } + + /* Update any display properties. I'm not sure whether this actually + does anything for layouts except clear the changed flags. */ + redisplay_subwindow (image_instance); + Dynarr_free (buf); } @@ -1420,7 +1535,7 @@ redisplay_output_layout (struct window *w, output a pixmap. ****************************************************************************/ void -redisplay_output_pixmap (struct window *w, +redisplay_output_pixmap (struct window *w, Lisp_Object image_instance, struct display_box* db, struct display_glyph_area* dga, face_index findex, int cursor_start, int cursor_width, @@ -1428,7 +1543,7 @@ redisplay_output_pixmap (struct window *w, { struct frame *f = XFRAME (w->frame); struct device *d = XDEVICE (f->device); - struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); + Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); Lisp_Object window; XSETWINDOW (window, w); @@ -1449,8 +1564,8 @@ redisplay_output_pixmap (struct window *w, if (!offset_bitmap) { redisplay_clear_clipped_region (window, findex, - db, dga, - (int)IMAGE_INSTANCE_PIXMAP_MASK (p), + db, dga, + (IMAGE_INSTANCE_PIXMAP_MASK (p) != 0), Qnil); /* This shrinks the display box to exactly enclose the glyph @@ -1506,7 +1621,7 @@ redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y, /* #### This isn't quite right for when this function is called from the toolbar code. */ - + /* Don't use a backing pixmap in the border area */ if (x >= FRAME_LEFT_BORDER_END (f) && x < FRAME_RIGHT_BORDER_START (f) @@ -1514,11 +1629,11 @@ redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y, && y < FRAME_BOTTOM_BORDER_START (f)) { Lisp_Object temp; - + if (w) { temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex); - + if (IMAGE_INSTANCEP (temp) && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) { @@ -1530,14 +1645,14 @@ redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y, else { temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale); - + if (IMAGE_INSTANCEP (temp) && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) { background_pixmap = temp; } } - } + } if (!UNBOUNDP (background_pixmap) && XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0) @@ -1558,13 +1673,13 @@ redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y, fcolor = (w ? WINDOW_FACE_CACHEL_BACKGROUND (w, findex) : FACE_BACKGROUND (Vdefault_face, locale)); - + } - + if (UNBOUNDP (background_pixmap)) background_pixmap = Qnil; - - DEVMETH (d, clear_region, + + DEVMETH (d, clear_region, (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap)); } @@ -1572,13 +1687,13 @@ redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y, redisplay_clear_clipped_region Clear the area in the dest display_box not covered by the src - display_glyph_area using the given face. This is a common occurance + display_glyph_area using the given face. This is a common occurrence for images shorter than the display line. Clipping can be played around with by altering these. glyphsrc should be normalized. ****************************************************************************/ static void -redisplay_clear_clipped_region (Lisp_Object window, face_index findex, - struct display_box* dest, struct display_glyph_area* glyphsrc, +redisplay_clear_clipped_region (Lisp_Object window, face_index findex, + struct display_box* dest, struct display_glyph_area* glyphsrc, int fullheight_p, Lisp_Object ignored_subwindow) { /* assume dest->xpos >= 0 */ @@ -1602,8 +1717,8 @@ redisplay_clear_clipped_region (Lisp_Object window, face_index findex, } else { - int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0); - + int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0); + /* We need to make sure that subwindows are unmapped from the whole area. */ redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos, @@ -1614,14 +1729,14 @@ redisplay_clear_clipped_region (Lisp_Object window, face_index findex, { redisplay_clear_region (window, findex, clear_x, dest->ypos, glyphsrc->width, yoffset); - + } /* Then the bottom box */ if (yoffset + glyphsrc->height < dest->height) { redisplay_clear_region (window, findex, clear_x, dest->ypos + yoffset + glyphsrc->height, - glyphsrc->width, + glyphsrc->width, dest->height - (yoffset + glyphsrc->height)); } @@ -1635,7 +1750,7 @@ redisplay_clear_clipped_region (Lisp_Object window, face_index findex, Calculate the visible box for displaying src in dest. ****************************************************************************/ int -redisplay_normalize_glyph_area (struct display_box* dest, +redisplay_normalize_glyph_area (struct display_box* dest, struct display_glyph_area* glyphsrc) { if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width @@ -1644,7 +1759,17 @@ redisplay_normalize_glyph_area (struct display_box* dest, || -glyphsrc->xoffset >= glyphsrc->width || - -glyphsrc->yoffset >= glyphsrc->height) + -glyphsrc->yoffset >= glyphsrc->height + || + /* #### Not sure why this wasn't coped with before but normalizing + to zero width or height is definitely wrong. */ + (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width + && + dest->width - glyphsrc->xoffset <= 0) + || + (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height + && + dest->height - glyphsrc->yoffset <= 0)) { /* It's all clipped out */ return 0; @@ -1678,7 +1803,7 @@ redisplay_normalize_glyph_area (struct display_box* dest, } static void -redisplay_normalize_display_box (struct display_box* dest, +redisplay_normalize_display_box (struct display_box* dest, struct display_glyph_area* glyphsrc) { /* Adjust the destination area. At the end of this the destination @@ -1715,9 +1840,9 @@ redisplay_normalize_display_box (struct display_box* dest, /***************************************************************************** redisplay_display_boxes_in_window_p - Determine whether the require display_glyph_area is completely inside - the window. 0 means the display_box is not in the window. 1 means the - display_box and the display_glyph_area are in the window. -1 means + Determine whether the required display_glyph_area is completely inside + the window. -1 means the display_box is not in the window. 1 means the + display_box and the display_glyph_area are in the window. 0 means the display_box is in the window but the display_glyph_area is not. ****************************************************************************/ static int @@ -1733,9 +1858,9 @@ redisplay_display_boxes_in_window_p (struct window* w, if (db->xpos < left || db->ypos < top || db->xpos + db->width > right || db->ypos + db->height > bottom) - /* We are not displaying in a window at all */ - return 0; - + /* We are not displaying in a window at all */ + return -1; + if (db->xpos + dga->xoffset >= left && db->ypos + dga->yoffset >= top @@ -1745,7 +1870,7 @@ redisplay_display_boxes_in_window_p (struct window* w, db->ypos + dga->yoffset + dga->height <= bottom) return 1; - return -1; + return 0; } /***************************************************************************** @@ -1757,7 +1882,7 @@ redisplay_display_boxes_in_window_p (struct window* w, int redisplay_calculate_display_boxes (struct display_line *dl, int xpos, int xoffset, int start_pixpos, int width, - struct display_box* dest, + struct display_box* dest, struct display_glyph_area* src) { dest->xpos = xpos; @@ -1791,7 +1916,7 @@ redisplay_calculate_display_boxes (struct display_line *dl, int xpos, If window is topmost, clear the internal border above it. ****************************************************************************/ -static void +void redisplay_clear_top_of_window (struct window *w) { Lisp_Object window; @@ -1838,38 +1963,38 @@ redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2) else { int height = ypos2 - ypos1; - + if (height) { Lisp_Object window; int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/ layout_bounds bounds; - + bounds = calculate_display_line_boundaries (w, bflag); XSETWINDOW (window, w); if (window_is_leftmost (w)) redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f), ypos1, FRAME_BORDER_WIDTH (f), height); - + if (bounds.left_in - bounds.left_out > 0) redisplay_clear_region (window, get_builtin_face_cache_index (w, Vleft_margin_face), bounds.left_out, ypos1, bounds.left_in - bounds.left_out, height); - + if (bounds.right_in - bounds.left_in > 0) - redisplay_clear_region (window, + redisplay_clear_region (window, DEFAULT_INDEX, bounds.left_in, ypos1, bounds.right_in - bounds.left_in, height); - + if (bounds.right_out - bounds.right_in > 0) redisplay_clear_region (window, get_builtin_face_cache_index (w, Vright_margin_face), bounds.right_in, ypos1, bounds.right_out - bounds.right_in, height); - + if (window_is_rightmost (w)) redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f), ypos1, FRAME_BORDER_WIDTH (f), height); @@ -1952,7 +2077,7 @@ redisplay_update_line (struct window *w, int first_line, int last_line, display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); - DEVMETH (d, output_begin, (d)); + MAYBE_DEVMETH (d, window_output_begin, (w)); while (first_line <= last_line) { @@ -2037,14 +2162,8 @@ redisplay_update_line (struct window *w, int first_line, int last_line, } #endif - /* This has to be done after we've updated the values. We don't - call output_end for tty frames. Redisplay will do this after all - tty windows have been updated. This cuts down on cursor - flicker. */ - if (FRAME_TTY_P (f)) - redisplay_redraw_cursor (f, 0); - else - DEVMETH (d, output_end, (d)); + redisplay_redraw_cursor (f, 0); + MAYBE_DEVMETH (d, window_output_end, (w)); } /***************************************************************************** @@ -2158,11 +2277,11 @@ redisplay_output_window (struct window *w) } /* Perform any output initialization. */ - DEVMETH (d, output_begin, (d)); + MAYBE_DEVMETH (d, window_output_begin, (w)); /* If the window's structure has changed clear the internal border above it if it is topmost (the function will check). */ - if (f->windows_structure_changed) + if (f->windows_structure_changed || f->faces_changed) redisplay_clear_top_of_window (w); /* Output each line. */ @@ -2181,7 +2300,7 @@ redisplay_output_window (struct window *w) if (window_needs_vertical_divider (w) && (f->windows_structure_changed || f->clear)) { - DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed)); + MAYBE_DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed)); } /* Clear the rest of the window, if necessary. */ @@ -2215,13 +2334,8 @@ redisplay_output_window (struct window *w) get invalidated when it should be. */ INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d); - /* We don't call output_end for tty frames. Redisplay will do this - after all tty windows have been updated. This cuts down on - cursor flicker. */ - if (FRAME_TTY_P (f)) - redisplay_redraw_cursor (f, 0); - else - DEVMETH (d, output_end, (d)); + redisplay_redraw_cursor (f, 0); + MAYBE_DEVMETH (d, window_output_end, (w)); #ifdef HAVE_SCROLLBARS update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0); @@ -2256,7 +2370,7 @@ bevel_modeline (struct window *w, struct display_line *dl) style = EDGE_BEVEL_OUT; } - MAYBE_DEVMETH (d, bevel_area, + MAYBE_DEVMETH (d, bevel_area, (w, MODELINE_INDEX, x, y, width, height, shadow_thickness, EDGE_ALL, style)); }