diff --git a/grid.c b/grid.c index 6bd8e3162..9a425d522 100644 --- a/grid.c +++ b/grid.c @@ -80,7 +80,7 @@ grid_entry_image(struct grid_line *gl, struct grid_cell_entry *gce) gee = &gl->extddata[gce->offset]; if (~gee->flags & GRID_FLAG_IMAGE) return (0); - return (gee->image_id); + return (image_get_id_by_grid_id(gee->image_id)); } #endif @@ -211,7 +211,7 @@ grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce, gee->us = gc->us; gee->link = gc->link; #ifdef ENABLE_IMAGES - gee->image_id = gc->image_id; + gee->image_id = image_get_grid_id(gc->image_id); gee->image_x = gc->image_x; gee->image_y = gc->image_y; #endif @@ -684,7 +684,7 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc) gc->us = gee->us; gc->link = gee->link; #ifdef ENABLE_IMAGES - gc->image_id = gee->image_id; + gc->image_id = image_get_id_by_grid_id(gee->image_id); gc->image_x = gee->image_x; gc->image_y = gee->image_y; #endif diff --git a/image.c b/image.c index 180582b9a..dcc1edae0 100644 --- a/image.c +++ b/image.c @@ -48,6 +48,7 @@ struct image_cell { /* Immutable image data and cell geometry. */ struct image { u_int id; + u_short grid_id; u_int references; u_int flags; u_int parent_id; @@ -83,6 +84,8 @@ struct image_rectangle { static struct images images = RB_INITIALIZER(&images); static u_int image_next_id; +static u_short image_next_grid_id; +static struct image *image_grid_ids[USHRT_MAX + 1]; #define IMAGE_BACKEND_GRAPHICAL 0x1 #define IMAGE_BACKEND_SCROLLS 0x2 @@ -356,6 +359,16 @@ image_create1(u_int width, u_int height, u_int canvas_width, u_int canvas_height, u_int sx, u_int sy, size_t stride, u_char *pixels) { struct image *im; + u_int i; + + for (i = 0; i < USHRT_MAX; i++) { + if (++image_next_grid_id == 0) + image_next_grid_id++; + if (image_grid_ids[image_next_grid_id] == NULL) + break; + } + if (i == USHRT_MAX) + return (NULL); im = xcalloc(1, sizeof *im); do { @@ -365,6 +378,7 @@ image_create1(u_int width, u_int height, u_int canvas_width, } while (image_find(im->id) != NULL); im->references = 1; + im->grid_id = image_next_grid_id; im->source_id = im->id; im->width = width; im->height = height; @@ -377,6 +391,7 @@ image_create1(u_int width, u_int height, u_int canvas_width, im->pixels = pixels; RB_INSERT(images, &images, im); + image_grid_ids[im->grid_id] = im; log_debug("%s: image %u is %ux%u pixels on %ux%u canvas, " "%ux%u cells", __func__, im->id, width, height, canvas_width, canvas_height, sx, sy); @@ -394,7 +409,8 @@ image_create(u_int width, u_int height, u_int canvas_width, return (NULL); if ((uint64_t)width * height * 4 > SIZE_MAX) return (NULL); - if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells) + if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells || + sx > USHRT_MAX || sy > USHRT_MAX) return (NULL); im = image_create1(width, height, canvas_width, canvas_height, sx, sy, (size_t)width * 4, pixels); @@ -413,18 +429,41 @@ image_create_view(struct image *source, u_int x, u_int y, u_int width, height > source->height - y || canvas_width < width || canvas_height < height || sx == 0 || sy == 0) return (NULL); - if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells) + if ((uint64_t)sx * sy > SIZE_MAX / sizeof *im->cells || + sx > USHRT_MAX || sy > USHRT_MAX) return (NULL); im = image_create1(width, height, canvas_width, canvas_height, sx, sy, source->stride, source->pixels + (size_t)y * source->stride + (size_t)x * 4); + if (im == NULL) + return (NULL); im->parent_id = source->id; im->source_id = source->source_id; image_ref(source->id); return (im); } +u_short +image_get_grid_id(u_int id) +{ + struct image *im = image_find(id); + + if (im == NULL) + return (0); + return (im->grid_id); +} + +u_int +image_get_id_by_grid_id(u_short grid_id) +{ + struct image *im; + + if (grid_id == 0 || (im = image_grid_ids[grid_id]) == NULL) + return (0); + return (im->id); +} + void image_ref(u_int id) { @@ -449,6 +488,7 @@ image_free(u_int id) log_debug("%s: freeing image %u", __func__, id); RB_REMOVE(images, &images, im); + image_grid_ids[im->grid_id] = NULL; if (im->parent_id == 0) free(im->pixels); else diff --git a/tmux.h b/tmux.h index 523631c0b..043bfd5c9 100644 --- a/tmux.h +++ b/tmux.h @@ -887,9 +887,9 @@ struct grid_extd_entry { int us; u_int link; #ifdef ENABLE_IMAGES - u_int image_id; - u_int image_x; - u_int image_y; + u_short image_id; + u_short image_x; + u_short image_y; #endif } __packed; @@ -4241,6 +4241,8 @@ struct image *image_create_view(struct image *, u_int, u_int, u_int, u_int, u_int, u_int, u_int, u_int); struct image *image_find(u_int); u_int image_get_id(const struct image *); +u_short image_get_grid_id(u_int); +u_int image_get_id_by_grid_id(u_short); void image_get_dimensions(const struct image *, u_int *, u_int *); void image_get_canvas_dimensions(const struct image *, u_int *, u_int *); void image_get_cell_dimensions(const struct image *, u_int *, u_int *);