+/****************************************************************************
+ 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
+ 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,
+ int fullheight_p, Lisp_Object ignored_subwindow)
+{
+ /* assume dest->xpos >= 0 */
+ int clear_x;
+ struct frame* f = XFRAME (XWINDOW (window)->frame);
+
+ if (glyphsrc->xoffset > 0)
+ {
+ clear_x = dest->xpos + glyphsrc->xoffset;
+ }
+ else
+ {
+ clear_x = dest->xpos;
+ }
+
+ /* If we need the whole height cleared then just do it. */
+ if (fullheight_p)
+ {
+ redisplay_clear_region (window, findex, clear_x, dest->ypos,
+ glyphsrc->width, dest->height);
+ }
+ else
+ {
+ 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,
+ glyphsrc->width, dest->height,
+ ignored_subwindow);
+ /* first the top box */
+ if (yoffset > 0)
+ {
+ 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,
+ dest->height - (yoffset + glyphsrc->height));
+
+ }
+ }
+}
+
+/*****************************************************************************
+ redisplay_normalize_glyph_area
+ redisplay_normalize_display_box
+
+ Calculate the visible box for displaying src in dest.
+ ****************************************************************************/
+int
+redisplay_normalize_glyph_area (struct display_box* dest,
+ struct display_glyph_area* glyphsrc)
+{
+ if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
+ ||
+ dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
+ ||
+ -glyphsrc->xoffset >= glyphsrc->width
+ ||
+ -glyphsrc->yoffset >= glyphsrc->height)
+ {
+ /* It's all clipped out */
+ return 0;
+ }
+
+ /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
+ if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
+ {
+ if (glyphsrc->xoffset > 0)
+ glyphsrc->width = dest->width - glyphsrc->xoffset;
+ else
+ glyphsrc->width = dest->width;
+ }
+
+ if (glyphsrc->xoffset < 0)
+ glyphsrc->width += glyphsrc->xoffset;
+
+ /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
+ if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
+ {
+ if (glyphsrc->yoffset > 0)
+ glyphsrc->height = dest->height - glyphsrc->yoffset;
+ else
+ glyphsrc->height = dest->height;
+ }
+
+ if (glyphsrc->yoffset < 0)
+ glyphsrc->height += glyphsrc->yoffset;
+
+ return 1;
+}
+
+static void
+redisplay_normalize_display_box (struct display_box* dest,
+ struct display_glyph_area* glyphsrc)
+{
+ /* Adjust the destination area. At the end of this the destination
+ area will exactly enclose the glyph area. The only remaining
+ adjustment will be offsets into the glyph area. */
+
+ /* Horizontal adjustment. */
+ if (glyphsrc->xoffset > 0)
+ {
+ dest->xpos += glyphsrc->xoffset;
+ dest->width -= glyphsrc->xoffset;
+ glyphsrc->xoffset = 0;
+ }
+ else
+ glyphsrc->xoffset = -glyphsrc->xoffset;
+
+ if (glyphsrc->width < dest->width)
+ dest->width = glyphsrc->width;
+
+ /* Vertical adjustment. */
+ if (glyphsrc->yoffset > 0)
+ {
+ dest->ypos += glyphsrc->yoffset;
+ dest->height -= glyphsrc->yoffset;
+ glyphsrc->yoffset = 0;
+ }
+ else
+ glyphsrc->yoffset = -glyphsrc->yoffset;
+
+ if (glyphsrc->height < dest->height)
+ dest->height = glyphsrc->height;
+}
+
+/*****************************************************************************
+ 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
+ the display_box is in the window but the display_glyph_area is not.
+ ****************************************************************************/
+static int
+redisplay_display_boxes_in_window_p (struct window* w,
+ struct display_box* db,
+ struct display_glyph_area* dga)
+{
+ int left = WINDOW_TEXT_LEFT (w);
+ int right = WINDOW_TEXT_RIGHT (w);
+ int top = WINDOW_TEXT_TOP (w);
+ int bottom = WINDOW_TEXT_BOTTOM (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;
+
+ if (db->xpos + dga->xoffset >= left
+ &&
+ db->ypos + dga->yoffset >= top
+ &&
+ db->xpos + dga->xoffset + dga->width <= right
+ &&
+ db->ypos + dga->yoffset + dga->height <= bottom)
+ return 1;
+
+ return -1;
+}
+
+/*****************************************************************************
+ redisplay_calculate_display_boxes
+
+ Convert from rune/display_line co-ordinates to display_box
+ co-ordinates.
+ ****************************************************************************/
+int
+redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
+ int xoffset, int start_pixpos, int width,
+ struct display_box* dest,
+ struct display_glyph_area* src)
+{
+ dest->xpos = xpos;
+ dest->ypos = DISPLAY_LINE_YPOS (dl);
+ dest->width = width;
+ dest->height = DISPLAY_LINE_HEIGHT (dl);
+
+ src->xoffset = -xoffset;
+ src->yoffset = -dl->top_clip;
+ src->width = 0;
+ src->height = 0;
+
+ if (start_pixpos >=0 && start_pixpos > xpos)
+ {
+ /* Oops, we're asking for a start outside of the displayable
+ area. */
+ if (start_pixpos > xpos + width)
+ return 0;
+ dest->xpos = start_pixpos;
+ dest->width -= (start_pixpos - xpos);
+ /* Offsets are -ve when we want to clip pixels off the displayed
+ glyph. */
+ src->xoffset -= (start_pixpos - xpos);
+ }
+
+ return 1;
+}
+