sucklessConfigs

configurations of the suckless.org software that I use
Log | Files | Refs

graphics.c (128226B)


      1 /* The MIT License
      2 
      3    Copyright (c) 2021-2024 Sergei Grechanik <sergei.grechanik@gmail.com>
      4 
      5    Permission is hereby granted, free of charge, to any person obtaining
      6    a copy of this software and associated documentation files (the
      7    "Software"), to deal in the Software without restriction, including
      8    without limitation the rights to use, copy, modify, merge, publish,
      9    distribute, sublicense, and/or sell copies of the Software, and to
     10    permit persons to whom the Software is furnished to do so, subject to
     11    the following conditions:
     12 
     13    The above copyright notice and this permission notice shall be
     14    included in all copies or substantial portions of the Software.
     15 
     16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     20    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     21    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23    SOFTWARE.
     24 */
     25 
     26 ////////////////////////////////////////////////////////////////////////////////
     27 //
     28 // This file implements a subset of the kitty graphics protocol.
     29 //
     30 ////////////////////////////////////////////////////////////////////////////////
     31 
     32 #define _POSIX_C_SOURCE 200809L
     33 
     34 #include <zlib.h>
     35 #include <Imlib2.h>
     36 #include <X11/Xlib.h>
     37 #include <X11/extensions/Xrender.h>
     38 #include <assert.h>
     39 #include <ctype.h>
     40 #include <spawn.h>
     41 #include <stdarg.h>
     42 #include <stdio.h>
     43 #include <stdlib.h>
     44 #include <string.h>
     45 #include <sys/stat.h>
     46 #include <time.h>
     47 #include <unistd.h>
     48 #include <errno.h>
     49 
     50 #include "graphics.h"
     51 #include "khash.h"
     52 #include "kvec.h"
     53 
     54 extern char **environ;
     55 
     56 #define MAX_FILENAME_SIZE 256
     57 #define MAX_INFO_LEN 256
     58 #define MAX_IMAGE_RECTS 20
     59 
     60 /// The type used in this file to represent time. Used both for time differences
     61 /// and absolute times (as milliseconds since an arbitrary point in time, see
     62 /// `initialization_time`).
     63 typedef int64_t Milliseconds;
     64 
     65 enum ScaleMode {
     66 	SCALE_MODE_UNSET = 0,
     67 	/// Stretch or shrink the image to fill the box, ignoring aspect ratio.
     68 	SCALE_MODE_FILL = 1,
     69 	/// Preserve aspect ratio and fit to width or to height so that the
     70 	/// whole image is visible.
     71 	SCALE_MODE_CONTAIN = 2,
     72 	/// Do not scale. The image may be cropped if the box is too small.
     73 	SCALE_MODE_NONE = 3,
     74 	/// Do not scale, unless the box is too small, in which case the image
     75 	/// will be shrunk like with `SCALE_MODE_CONTAIN`.
     76 	SCALE_MODE_NONE_OR_CONTAIN = 4,
     77 };
     78 
     79 enum AnimationState {
     80 	ANIMATION_STATE_UNSET = 0,
     81 	/// The animation is stopped. Display the current frame, but don't
     82 	/// advance to the next one.
     83 	ANIMATION_STATE_STOPPED = 1,
     84 	/// Run the animation to then end, then wait for the next frame.
     85 	ANIMATION_STATE_LOADING = 2,
     86 	/// Run the animation in a loop.
     87 	ANIMATION_STATE_LOOPING = 3,
     88 };
     89 
     90 /// The status of an image. Each image uploaded to the terminal is cached on
     91 /// disk, then it is loaded to ram when needed.
     92 enum ImageStatus {
     93 	STATUS_UNINITIALIZED = 0,
     94 	STATUS_UPLOADING = 1,
     95 	STATUS_UPLOADING_ERROR = 2,
     96 	STATUS_UPLOADING_SUCCESS = 3,
     97 	STATUS_RAM_LOADING_ERROR = 4,
     98 	STATUS_RAM_LOADING_IN_PROGRESS = 5,
     99 	STATUS_RAM_LOADING_SUCCESS = 6,
    100 };
    101 
    102 const char *image_status_strings[6] = {
    103 	"STATUS_UNINITIALIZED",
    104 	"STATUS_UPLOADING",
    105 	"STATUS_UPLOADING_ERROR",
    106 	"STATUS_UPLOADING_SUCCESS",
    107 	"STATUS_RAM_LOADING_ERROR",
    108 	"STATUS_RAM_LOADING_SUCCESS",
    109 };
    110 
    111 enum ImageUploadingFailure {
    112 	ERROR_OVER_SIZE_LIMIT = 1,
    113 	ERROR_CANNOT_OPEN_CACHED_FILE = 2,
    114 	ERROR_UNEXPECTED_SIZE = 3,
    115 	ERROR_CANNOT_COPY_FILE = 4,
    116 };
    117 
    118 const char *image_uploading_failure_strings[5] = {
    119 	"NO_ERROR",
    120 	"ERROR_OVER_SIZE_LIMIT",
    121 	"ERROR_CANNOT_OPEN_CACHED_FILE",
    122 	"ERROR_UNEXPECTED_SIZE",
    123 	"ERROR_CANNOT_COPY_FILE",
    124 };
    125 
    126 ////////////////////////////////////////////////////////////////////////////////
    127 //
    128 // We use the following structures to represent images and placements:
    129 //
    130 //   - Image: this is the main structure representing an image, usually created
    131 //     by actions 'a=t', 'a=T`. Each image has an id (image id aka client id,
    132 //     specified by 'i='). An image may have multiple frames (ImageFrame) and
    133 //     placements (ImagePlacement).
    134 //
    135 //   - ImageFrame: represents a single frame of an image, usually created by
    136 //     the action 'a=f' (and the first frame is created with the image itself).
    137 //     Each frame has an index and also:
    138 //     - a file containing the frame data (considered to be "on disk", although
    139 //       it's probably in tmpfs),
    140 //     - an imlib object containing the fully composed frame (i.e. the frame
    141 //       data from the file composed onto the background frame or color). It is
    142 //       not ready for display yet, because it needs to be scaled and uploaded
    143 //       to the X server.
    144 //
    145 //   - ImagePlacement: represents a placement of an image, created by 'a=p' and
    146 //     'a=T'. Each placement has an id (placement id, specified by 'p='). Also
    147 //     each placement has an array of pixmaps: one for each frame of the image.
    148 //     Each pixmap is a scaled and uploaded image ready to be displayed.
    149 //
    150 // Images are store in the `images` hash table, mapping image ids to Image
    151 // objects (allocated on the heap).
    152 //
    153 // Placements are stored in the `placements` hash table of each Image object,
    154 // mapping placement ids to ImagePlacement objects (also allocated on the heap).
    155 //
    156 // ImageFrames are stored in the `first_frame` field and in the
    157 // `frames_beyond_the_first` array of each Image object. They are stored by
    158 // value, so ImageFrame pointer may be invalidated when frames are
    159 // added/deleted, be careful.
    160 //
    161 ////////////////////////////////////////////////////////////////////////////////
    162 
    163 struct Image;
    164 struct ImageFrame;
    165 struct ImagePlacement;
    166 
    167 KHASH_MAP_INIT_INT(id2image, struct Image *)
    168 KHASH_MAP_INIT_INT(id2placement, struct ImagePlacement *)
    169 
    170 typedef struct ImageFrame {
    171 	/// The image this frame belongs to.
    172 	struct Image *image;
    173 	/// The 1-based index of the frame. Zero if the frame isn't initialized.
    174 	int index;
    175 	/// The last time when the frame was displayed or otherwise touched.
    176 	Milliseconds atime;
    177 	/// The background color of the frame in the 0xRRGGBBAA format.
    178 	uint32_t background_color;
    179 	/// The index of the background frame. Zero to use the color instead.
    180 	int background_frame_index;
    181 	/// The duration of the frame in milliseconds.
    182 	int gap;
    183 	/// The expected size of the frame image file (specified with 'S='),
    184 	/// used to check if uploading succeeded.
    185 	unsigned expected_size;
    186 	/// Format specification (see the `f=` key).
    187 	int format;
    188 	/// Pixel width and height of the non-composed (on-disk) frame data. May
    189 	/// differ from the image (i.e. first frame) dimensions.
    190 	int data_pix_width, data_pix_height;
    191 	/// The offset of the frame relative to the first frame.
    192 	int x, y;
    193 	/// Compression mode (see the `o=` key).
    194 	char compression;
    195 	/// The status (see `ImageStatus`).
    196 	char status;
    197 	/// The reason of uploading failure (see `ImageUploadingFailure`).
    198 	char uploading_failure;
    199 	/// Whether failures and successes should be reported ('q=').
    200 	char quiet;
    201 	/// Whether to blend the frame with the background or replace it.
    202 	char blend;
    203 	/// The file corresponding to the on-disk cache, used when uploading.
    204 	FILE *open_file;
    205 	/// The size of the corresponding file cached on disk.
    206 	unsigned disk_size;
    207 	/// The imlib object containing the fully composed frame. It's not
    208 	/// scaled for screen display yet.
    209 	Imlib_Image imlib_object;
    210 } ImageFrame;
    211 
    212 typedef struct Image {
    213 	/// The client id (the one specified with 'i='). Must be nonzero.
    214 	uint32_t image_id;
    215 	/// The client id specified in the query command (`a=q`). This one must
    216 	/// be used to create the response if it's non-zero.
    217 	uint32_t query_id;
    218 	/// The number specified in the transmission command (`I=`). If
    219 	/// non-zero, it may be used to identify the image instead of the
    220 	/// image_id, and it also should be mentioned in responses.
    221 	uint32_t image_number;
    222 	/// The last time when the image was displayed or otherwise touched.
    223 	Milliseconds atime;
    224 	/// The total duration of the animation in milliseconds.
    225 	int total_duration;
    226 	/// The total size of cached image files for all frames.
    227 	int total_disk_size;
    228 	/// The global index of the creation command. Used to decide which image
    229 	/// is newer if they have the same image number.
    230 	uint64_t global_command_index;
    231 	/// The 1-based index of the currently displayed frame.
    232 	int current_frame;
    233 	/// The state of the animation, see `AnimationState`.
    234 	char animation_state;
    235 	/// The absolute time that is assumed to be the start of the current
    236 	/// frame (in ms since initialization).
    237 	Milliseconds current_frame_time;
    238 	/// The absolute time of the last redraw (in ms since initialization).
    239 	/// Used to check whether it's the first time we draw the image in the
    240 	/// current redraw cycle.
    241 	Milliseconds last_redraw;
    242 	/// The absolute time of the next redraw (in ms since initialization).
    243 	/// 0 means no redraw is scheduled.
    244 	Milliseconds next_redraw;
    245 	/// The unscaled pixel width and height of the image. Usually inherited
    246 	/// from the first frame.
    247 	int pix_width, pix_height;
    248 	/// The first frame.
    249 	ImageFrame first_frame;
    250 	/// The array of frames beyond the first one.
    251 	kvec_t(ImageFrame) frames_beyond_the_first;
    252 	/// Image placements.
    253 	khash_t(id2placement) *placements;
    254 	/// The default placement.
    255 	uint32_t default_placement;
    256 	/// The initial placement id, specified with the transmission command,
    257 	/// used to report success or failure.
    258 	uint32_t initial_placement_id;
    259 } Image;
    260 
    261 typedef struct ImagePlacement {
    262 	/// The image this placement belongs to.
    263 	Image *image;
    264 	/// The id of the placement. Must be nonzero.
    265 	uint32_t placement_id;
    266 	/// The last time when the placement was displayed or otherwise touched.
    267 	Milliseconds atime;
    268 	/// The 1-based index of the protected pixmap. We protect a pixmap in
    269 	/// gr_load_pixmap to avoid unloading it right after it was loaded.
    270 	int protected_frame;
    271 	/// Whether the placement is used only for Unicode placeholders.
    272 	char virtual;
    273 	/// The scaling mode (see `ScaleMode`).
    274 	char scale_mode;
    275 	/// Height and width in cells.
    276 	uint16_t rows, cols;
    277 	/// Top-left corner of the source rectangle ('x=' and 'y=').
    278 	int src_pix_x, src_pix_y;
    279 	/// Height and width of the source rectangle (zero if full image).
    280 	int src_pix_width, src_pix_height;
    281 	/// The image appropriately scaled and uploaded to the X server. This
    282 	/// pixmap is premultiplied by alpha.
    283 	Pixmap first_pixmap;
    284 	/// The array of pixmaps beyond the first one.
    285 	kvec_t(Pixmap) pixmaps_beyond_the_first;
    286 	/// The dimensions of the cell used to scale the image. If cell
    287 	/// dimensions are changed (font change), the image will be rescaled.
    288 	uint16_t scaled_cw, scaled_ch;
    289 	/// If true, do not move the cursor when displaying this placement
    290 	/// (non-virtual placements only).
    291 	char do_not_move_cursor;
    292 } ImagePlacement;
    293 
    294 /// A rectangular piece of an image to be drawn.
    295 typedef struct {
    296 	uint32_t image_id;
    297 	uint32_t placement_id;
    298 	/// The position of the rectangle in pixels.
    299 	int screen_x_pix, screen_y_pix;
    300 	/// The starting row on the screen.
    301 	int screen_y_row;
    302 	/// The part of the whole image to be drawn, in cells. Starts are
    303 	/// zero-based, ends are exclusive.
    304 	int img_start_col, img_end_col, img_start_row, img_end_row;
    305 	/// The current cell width and height in pixels.
    306 	int cw, ch;
    307 	/// Whether colors should be inverted.
    308 	int reverse;
    309 } ImageRect;
    310 
    311 /// Executes `code` for each frame of an image. Example:
    312 ///
    313 ///     foreach_frame(image, frame, {
    314 ///         printf("Frame %d\n", frame->index);
    315 ///     });
    316 ///
    317 #define foreach_frame(image, framevar, code) { size_t __i; \
    318 	for (__i = 0; __i <= kv_size((image).frames_beyond_the_first); ++__i) { \
    319 		ImageFrame *framevar = \
    320 			__i == 0 ? &(image).first_frame \
    321 			: &kv_A((image).frames_beyond_the_first, __i - 1); \
    322 		code; \
    323 	} }
    324 
    325 /// Executes `code` for each pixmap of a placement. Example:
    326 ///
    327 ///     foreach_pixmap(placement, pixmap, {
    328 ///         ...
    329 ///     });
    330 ///
    331 #define foreach_pixmap(placement, pixmapvar, code) { size_t __i; \
    332 	for (__i = 0; __i <= kv_size((placement).pixmaps_beyond_the_first); ++__i) { \
    333 		Pixmap pixmapvar = \
    334 			__i == 0 ? (placement).first_pixmap \
    335 			: kv_A((placement).pixmaps_beyond_the_first, __i - 1); \
    336 		code; \
    337 	} }
    338 
    339 
    340 static Image *gr_find_image(uint32_t image_id);
    341 static void gr_get_frame_filename(ImageFrame *frame, char *out, size_t max_len);
    342 static void gr_delete_image(Image *img);
    343 static void gr_check_limits();
    344 static char *gr_base64dec(const char *src, size_t *size);
    345 static void sanitize_str(char *str, size_t max_len);
    346 static const char *sanitized_filename(const char *str);
    347 
    348 /// The array of image rectangles to draw. It is reset each frame.
    349 static ImageRect image_rects[MAX_IMAGE_RECTS] = {{0}};
    350 /// The known images (including the ones being uploaded).
    351 static khash_t(id2image) *images = NULL;
    352 /// The total number of placements in all images.
    353 static unsigned total_placement_count = 0;
    354 /// The total size of all image files stored in the on-disk cache.
    355 static int64_t images_disk_size = 0;
    356 /// The total size of all images and placements loaded into ram.
    357 static int64_t images_ram_size = 0;
    358 /// The id of the last loaded image.
    359 static uint32_t last_image_id = 0;
    360 /// Current cell width and heigh in pixels.
    361 static int current_cw = 0, current_ch = 0;
    362 /// The id of the currently uploaded image (when using direct uploading).
    363 static uint32_t current_upload_image_id = 0;
    364 /// The index of the frame currently being uploaded.
    365 static int current_upload_frame_index = 0;
    366 /// The time when the graphics module was initialized.
    367 static struct timespec initialization_time = {0};
    368 /// The time when the current frame drawing started, used for debugging fps and
    369 /// to calculate the current frame for animations.
    370 static Milliseconds drawing_start_time;
    371 /// The global index of the current command.
    372 static uint64_t global_command_counter = 0;
    373 /// The next redraw times for each row of the terminal. Used for animations.
    374 /// 0 means no redraw is scheduled.
    375 static kvec_t(Milliseconds) next_redraw_times = {0, 0, NULL};
    376 /// The number of files loaded in the current redraw cycle.
    377 static int this_redraw_cycle_loaded_files = 0;
    378 /// The number of pixmaps loaded in the current redraw cycle.
    379 static int this_redraw_cycle_loaded_pixmaps = 0;
    380 
    381 /// The directory where the cache files are stored.
    382 static char cache_dir[MAX_FILENAME_SIZE - 16];
    383 
    384 /// The table used for color inversion.
    385 static unsigned char reverse_table[256];
    386 
    387 // Declared in the header.
    388 GraphicsDebugMode graphics_debug_mode = GRAPHICS_DEBUG_NONE;
    389 char graphics_display_images = 1;
    390 GraphicsCommandResult graphics_command_result = {0};
    391 int graphics_next_redraw_delay = INT_MAX;
    392 
    393 // Defined in config.h
    394 extern const char graphics_cache_dir_template[];
    395 extern unsigned graphics_max_single_image_file_size;
    396 extern unsigned graphics_total_file_cache_size;
    397 extern unsigned graphics_max_single_image_ram_size;
    398 extern unsigned graphics_max_total_ram_size;
    399 extern unsigned graphics_max_total_placements;
    400 extern double graphics_excess_tolerance_ratio;
    401 extern unsigned graphics_animation_min_delay;
    402 
    403 
    404 ////////////////////////////////////////////////////////////////////////////////
    405 // Basic helpers.
    406 ////////////////////////////////////////////////////////////////////////////////
    407 
    408 #define MIN(a, b)		((a) < (b) ? (a) : (b))
    409 #define MAX(a, b)		((a) < (b) ? (b) : (a))
    410 
    411 /// Returns the difference between `end` and `start` in milliseconds.
    412 static int64_t gr_timediff_ms(const struct timespec *end,
    413 			      const struct timespec *start) {
    414 	return (end->tv_sec - start->tv_sec) * 1000 +
    415 	       (end->tv_nsec - start->tv_nsec) / 1000000;
    416 }
    417 
    418 /// Returns the current time in milliseconds since the initialization.
    419 static Milliseconds gr_now_ms() {
    420 	struct timespec now;
    421 	clock_gettime(CLOCK_MONOTONIC, &now);
    422 	return gr_timediff_ms(&now, &initialization_time);
    423 }
    424 
    425 ////////////////////////////////////////////////////////////////////////////////
    426 // Logging.
    427 ////////////////////////////////////////////////////////////////////////////////
    428 
    429 #define GR_LOG(...) \
    430 	do { if(graphics_debug_mode) fprintf(stderr, __VA_ARGS__); } while(0)
    431 
    432 ////////////////////////////////////////////////////////////////////////////////
    433 // Basic image management functions (create, delete, find, etc).
    434 ////////////////////////////////////////////////////////////////////////////////
    435 
    436 /// Returns the 1-based index of the last frame. Note that you may want to use
    437 /// `gr_last_uploaded_frame_index` instead since the last frame may be not
    438 /// fully uploaded yet.
    439 static inline int gr_last_frame_index(Image *img) {
    440 	return kv_size(img->frames_beyond_the_first) + 1;
    441 }
    442 
    443 /// Returns the frame with the given index. Returns NULL if the index is out of
    444 /// bounds. The index is 1-based.
    445 static ImageFrame *gr_get_frame(Image *img, int index) {
    446 	if (!img)
    447 		return NULL;
    448 	if (index == 1)
    449 		return &img->first_frame;
    450 	if (2 <= index && index <= gr_last_frame_index(img))
    451 		return &kv_A(img->frames_beyond_the_first, index - 2);
    452 	return NULL;
    453 }
    454 
    455 /// Returns the last frame of the image. Returns NULL if `img` is NULL.
    456 static ImageFrame *gr_get_last_frame(Image *img) {
    457 	if (!img)
    458 		return NULL;
    459 	return gr_get_frame(img, gr_last_frame_index(img));
    460 }
    461 
    462 /// Returns the 1-based index of the last frame or the second-to-last frame if
    463 /// the last frame is not fully uploaded yet.
    464 static inline int gr_last_uploaded_frame_index(Image *img) {
    465 	int last_index = gr_last_frame_index(img);
    466 	if (last_index > 1 &&
    467 	    gr_get_frame(img, last_index)->status < STATUS_UPLOADING_SUCCESS)
    468 		return last_index - 1;
    469 	return last_index;
    470 }
    471 
    472 /// Returns the pixmap for the frame with the given index. Returns 0 if the
    473 /// index is out of bounds. The index is 1-based.
    474 static Pixmap gr_get_frame_pixmap(ImagePlacement *placement, int index) {
    475 	if (index == 1)
    476 		return placement->first_pixmap;
    477 	if (2 <= index &&
    478 	    index <= kv_size(placement->pixmaps_beyond_the_first) + 1)
    479 		return kv_A(placement->pixmaps_beyond_the_first, index - 2);
    480 	return 0;
    481 }
    482 
    483 /// Sets the pixmap for the frame with the given index. The index is 1-based.
    484 /// The array of pixmaps is resized if needed.
    485 static void gr_set_frame_pixmap(ImagePlacement *placement, int index,
    486 				Pixmap pixmap) {
    487 	if (index == 1) {
    488 		placement->first_pixmap = pixmap;
    489 		return;
    490 	}
    491 	// Resize the array if needed.
    492 	size_t old_size = kv_size(placement->pixmaps_beyond_the_first);
    493 	if (old_size < index - 1) {
    494 		kv_a(Pixmap, placement->pixmaps_beyond_the_first, index - 2);
    495 		for (size_t i = old_size; i < index - 1; i++)
    496 			kv_A(placement->pixmaps_beyond_the_first, i) = 0;
    497 	}
    498 	kv_A(placement->pixmaps_beyond_the_first, index - 2) = pixmap;
    499 }
    500 
    501 /// Finds the image corresponding to the client id. Returns NULL if cannot find.
    502 static Image *gr_find_image(uint32_t image_id) {
    503 	khiter_t k = kh_get(id2image, images, image_id);
    504 	if (k == kh_end(images))
    505 		return NULL;
    506 	Image *res = kh_value(images, k);
    507 	return res;
    508 }
    509 
    510 /// Finds the newest image corresponding to the image number. Returns NULL if
    511 /// cannot find.
    512 static Image *gr_find_image_by_number(uint32_t image_number) {
    513 	if (image_number == 0)
    514 		return NULL;
    515 	Image *newest_img = NULL;
    516 	Image *img = NULL;
    517 	kh_foreach_value(images, img, {
    518 		if (img->image_number == image_number &&
    519 		    (!newest_img || newest_img->global_command_index <
    520 					    img->global_command_index))
    521 			newest_img = img;
    522 	});
    523 	if (!newest_img)
    524 		GR_LOG("Image number %u not found\n", image_number);
    525 	else
    526 		GR_LOG("Found image number %u, its id is %u\n", image_number,
    527 		       img->image_id);
    528 	return newest_img;
    529 }
    530 
    531 /// Finds the placement corresponding to the id. If the placement id is 0,
    532 /// returns some default placement.
    533 static ImagePlacement *gr_find_placement(Image *img, uint32_t placement_id) {
    534 	if (!img)
    535 		return NULL;
    536 	if (placement_id == 0) {
    537 		// Try to get the default placement.
    538 		ImagePlacement *dflt = NULL;
    539 		if (img->default_placement != 0)
    540 			dflt = gr_find_placement(img, img->default_placement);
    541 		if (dflt)
    542 			return dflt;
    543 		// If there is no default placement, return the first one and
    544 		// set it as the default.
    545 		kh_foreach_value(img->placements, dflt, {
    546 			img->default_placement = dflt->placement_id;
    547 			return dflt;
    548 		});
    549 		// If there are no placements, return NULL.
    550 		return NULL;
    551 	}
    552 	khiter_t k = kh_get(id2placement, img->placements, placement_id);
    553 	if (k == kh_end(img->placements))
    554 		return NULL;
    555 	ImagePlacement *res = kh_value(img->placements, k);
    556 	return res;
    557 }
    558 
    559 /// Finds the placement by image id and placement id.
    560 static ImagePlacement *gr_find_image_and_placement(uint32_t image_id,
    561 						   uint32_t placement_id) {
    562 	return gr_find_placement(gr_find_image(image_id), placement_id);
    563 }
    564 
    565 /// Writes the name of the on-disk cache file to `out`. `max_len` should be the
    566 /// size of `out`. The name will be something like
    567 /// "/tmp/st-images-xxx/img-ID-FRAME".
    568 static void gr_get_frame_filename(ImageFrame *frame, char *out,
    569 				  size_t max_len) {
    570 	snprintf(out, max_len, "%s/img-%.3u-%.3u", cache_dir,
    571 		 frame->image->image_id, frame->index);
    572 }
    573 
    574 /// Returns the (estimation) of the RAM size used by the frame right now.
    575 static unsigned gr_frame_current_ram_size(ImageFrame *frame) {
    576 	if (!frame->imlib_object)
    577 		return 0;
    578 	return (unsigned)frame->image->pix_width * frame->image->pix_height * 4;
    579 }
    580 
    581 /// Returns the (estimation) of the RAM size used by a single frame pixmap.
    582 static unsigned gr_placement_single_frame_ram_size(ImagePlacement *placement) {
    583 	return (unsigned)placement->rows * placement->cols *
    584 	       placement->scaled_ch * placement->scaled_cw * 4;
    585 }
    586 
    587 /// Returns the (estimation) of the RAM size used by the placemenet right now.
    588 static unsigned gr_placement_current_ram_size(ImagePlacement *placement) {
    589 	unsigned single_frame_size =
    590 		gr_placement_single_frame_ram_size(placement);
    591 	unsigned result = 0;
    592 	foreach_pixmap(*placement, pixmap, {
    593 		if (pixmap)
    594 			result += single_frame_size;
    595 	});
    596 	return result;
    597 }
    598 
    599 /// Unload the frame from RAM (i.e. delete the corresponding imlib object).
    600 /// If the on-disk file of the frame is preserved, it can be reloaded later.
    601 static void gr_unload_frame(ImageFrame *frame) {
    602 	if (!frame->imlib_object)
    603 		return;
    604 
    605 	unsigned frame_ram_size = gr_frame_current_ram_size(frame);
    606 	images_ram_size -= frame_ram_size;
    607 
    608 	imlib_context_set_image(frame->imlib_object);
    609 	imlib_free_image_and_decache();
    610 	frame->imlib_object = NULL;
    611 
    612 	GR_LOG("After unloading image %u frame %u (atime %ld ms ago) "
    613 	       "ram: %ld KiB  (- %u KiB)\n",
    614 	       frame->image->image_id, frame->index,
    615 	       drawing_start_time - frame->atime, images_ram_size / 1024,
    616 	       frame_ram_size / 1024);
    617 }
    618 
    619 /// Unload all frames of the image.
    620 static void gr_unload_all_frames(Image *img) {
    621 	foreach_frame(*img, frame, {
    622 		gr_unload_frame(frame);
    623 	});
    624 }
    625 
    626 /// Unload the placement from RAM (i.e. free all of the corresponding pixmaps).
    627 /// If the on-disk files or imlib objects of the corresponding image are
    628 /// preserved, the placement can be reloaded later.
    629 static void gr_unload_placement(ImagePlacement *placement) {
    630 	unsigned placement_ram_size = gr_placement_current_ram_size(placement);
    631 	images_ram_size -= placement_ram_size;
    632 
    633 	Display *disp = imlib_context_get_display();
    634 	foreach_pixmap(*placement, pixmap, {
    635 		if (pixmap)
    636 			XFreePixmap(disp, pixmap);
    637 	});
    638 
    639 	placement->first_pixmap = 0;
    640 	placement->pixmaps_beyond_the_first.n = 0;
    641 	placement->scaled_ch = placement->scaled_cw = 0;
    642 
    643 	GR_LOG("After unloading placement %u/%u (atime %ld ms ago) "
    644 	       "ram: %ld KiB  (- %u KiB)\n",
    645 	       placement->image->image_id, placement->placement_id,
    646 	       drawing_start_time - placement->atime, images_ram_size / 1024,
    647 	       placement_ram_size / 1024);
    648 }
    649 
    650 /// Unload a single pixmap of the placement from RAM.
    651 static void gr_unload_pixmap(ImagePlacement *placement, int frameidx) {
    652 	Pixmap pixmap = gr_get_frame_pixmap(placement, frameidx);
    653 	if (!pixmap)
    654 		return;
    655 
    656 	Display *disp = imlib_context_get_display();
    657 	XFreePixmap(disp, pixmap);
    658 	gr_set_frame_pixmap(placement, frameidx, 0);
    659 	images_ram_size -= gr_placement_single_frame_ram_size(placement);
    660 
    661 	GR_LOG("After unloading pixmap %ld of "
    662 	       "placement %u/%u (atime %ld ms ago) "
    663 	       "frame %u (atime %ld ms ago) "
    664 	       "ram: %ld KiB  (- %u KiB)\n",
    665 	       pixmap, placement->image->image_id, placement->placement_id,
    666 	       drawing_start_time - placement->atime, frameidx,
    667 	       drawing_start_time -
    668 		       gr_get_frame(placement->image, frameidx)->atime,
    669 	       images_ram_size / 1024,
    670 	       gr_placement_single_frame_ram_size(placement) / 1024);
    671 }
    672 
    673 /// Deletes the on-disk cache file corresponding to the frame. The in-ram image
    674 /// object (if it exists) is not deleted, placements are not unloaded either.
    675 static void gr_delete_imagefile(ImageFrame *frame) {
    676 	// It may still be being loaded. Close the file in this case.
    677 	if (frame->open_file) {
    678 		fclose(frame->open_file);
    679 		frame->open_file = NULL;
    680 	}
    681 
    682 	if (frame->disk_size == 0)
    683 		return;
    684 
    685 	char filename[MAX_FILENAME_SIZE];
    686 	gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE);
    687 	remove(filename);
    688 
    689 	unsigned disk_size = frame->disk_size;
    690 	images_disk_size -= disk_size;
    691 	frame->image->total_disk_size -= disk_size;
    692 	frame->disk_size = 0;
    693 
    694 	GR_LOG("After deleting image file %u frame %u (atime %ld ms ago) "
    695 	       "disk: %ld KiB  (- %u KiB)\n",
    696 	       frame->image->image_id, frame->index,
    697 	       drawing_start_time - frame->atime, images_disk_size / 1024,
    698 	       disk_size / 1024);
    699 }
    700 
    701 /// Deletes all on-disk cache files of the image (for each frame).
    702 static void gr_delete_imagefiles(Image *img) {
    703 	foreach_frame(*img, frame, {
    704 		gr_delete_imagefile(frame);
    705 	});
    706 }
    707 
    708 /// Deletes the given placement: unloads, frees the object, but doesn't change
    709 /// the `placements` hash table.
    710 static void gr_delete_placement_keep_id(ImagePlacement *placement) {
    711 	if (!placement)
    712 		return;
    713 	GR_LOG("Deleting placement %u/%u\n", placement->image->image_id,
    714 	       placement->placement_id);
    715 	gr_unload_placement(placement);
    716 	kv_destroy(placement->pixmaps_beyond_the_first);
    717 	free(placement);
    718 	total_placement_count--;
    719 }
    720 
    721 /// Deletes all placements of `img`.
    722 static void gr_delete_all_placements(Image *img) {
    723 	ImagePlacement *placement = NULL;
    724 	kh_foreach_value(img->placements, placement, {
    725 		gr_delete_placement_keep_id(placement);
    726 	});
    727 	kh_clear(id2placement, img->placements);
    728 }
    729 
    730 /// Deletes the given image: unloads, deletes the file, frees the Image object,
    731 /// but doesn't change the `images` hash table.
    732 static void gr_delete_image_keep_id(Image *img) {
    733 	if (!img)
    734 		return;
    735 	GR_LOG("Deleting image %u\n", img->image_id);
    736 	foreach_frame(*img, frame, {
    737 		gr_delete_imagefile(frame);
    738 		gr_unload_frame(frame);
    739 	});
    740 	kv_destroy(img->frames_beyond_the_first);
    741 	gr_delete_all_placements(img);
    742 	kh_destroy(id2placement, img->placements);
    743 	free(img);
    744 }
    745 
    746 /// Deletes the given image: unloads, deletes the file, frees the Image object,
    747 /// and also removes it from `images`.
    748 static void gr_delete_image(Image *img) {
    749 	if (!img)
    750 		return;
    751 	uint32_t id = img->image_id;
    752 	gr_delete_image_keep_id(img);
    753 	khiter_t k = kh_get(id2image, images, id);
    754 	kh_del(id2image, images, k);
    755 }
    756 
    757 /// Deletes the given placement: unloads, frees the object, and also removes it
    758 /// from `placements`.
    759 static void gr_delete_placement(ImagePlacement *placement) {
    760 	if (!placement)
    761 		return;
    762 	uint32_t id = placement->placement_id;
    763 	Image *img = placement->image;
    764 	gr_delete_placement_keep_id(placement);
    765 	khiter_t k = kh_get(id2placement, img->placements, id);
    766 	kh_del(id2placement, img->placements, k);
    767 }
    768 
    769 /// Deletes all images and clears `images`.
    770 static void gr_delete_all_images() {
    771 	Image *img = NULL;
    772 	kh_foreach_value(images, img, {
    773 		gr_delete_image_keep_id(img);
    774 	});
    775 	kh_clear(id2image, images);
    776 }
    777 
    778 /// Update the atime of the image.
    779 static void gr_touch_image(Image *img) {
    780 	img->atime = gr_now_ms();
    781 }
    782 
    783 /// Update the atime of the frame.
    784 static void gr_touch_frame(ImageFrame *frame) {
    785 	frame->image->atime = frame->atime = gr_now_ms();
    786 }
    787 
    788 /// Update the atime of the placement. Touches the images too.
    789 static void gr_touch_placement(ImagePlacement *placement) {
    790 	placement->image->atime = placement->atime = gr_now_ms();
    791 }
    792 
    793 /// Creates a new image with the given id. If an image with that id already
    794 /// exists, it is deleted first. If the provided id is 0, generates a
    795 /// random id.
    796 static Image *gr_new_image(uint32_t id) {
    797 	if (id == 0) {
    798 		do {
    799 			id = rand();
    800 			// Avoid IDs that don't need full 32 bits.
    801 		} while ((id & 0xFF000000) == 0 || (id & 0x00FFFF00) == 0 ||
    802 			 gr_find_image(id));
    803 		GR_LOG("Generated random image id %u\n", id);
    804 	}
    805 	Image *img = gr_find_image(id);
    806 	gr_delete_image_keep_id(img);
    807 	GR_LOG("Creating image %u\n", id);
    808 	img = malloc(sizeof(Image));
    809 	memset(img, 0, sizeof(Image));
    810 	img->placements = kh_init(id2placement);
    811 	int ret;
    812 	khiter_t k = kh_put(id2image, images, id, &ret);
    813 	kh_value(images, k) = img;
    814 	img->image_id = id;
    815 	gr_touch_image(img);
    816 	img->global_command_index = global_command_counter;
    817 	return img;
    818 }
    819 
    820 /// Creates a new frame at the end of the frame array. It may be the first frame
    821 /// if there are no frames yet.
    822 static ImageFrame *gr_append_new_frame(Image *img) {
    823 	ImageFrame *frame = NULL;
    824 	if (img->first_frame.index == 0 &&
    825 	    kv_size(img->frames_beyond_the_first) == 0) {
    826 		frame = &img->first_frame;
    827 		frame->index = 1;
    828 	} else {
    829 		frame = kv_pushp(ImageFrame, img->frames_beyond_the_first);
    830 		memset(frame, 0, sizeof(ImageFrame));
    831 		frame->index = kv_size(img->frames_beyond_the_first) + 1;
    832 	}
    833 	frame->image = img;
    834 	gr_touch_frame(frame);
    835 	GR_LOG("Appending frame %d to image %u\n", frame->index, img->image_id);
    836 	return frame;
    837 }
    838 
    839 /// Creates a new placement with the given id. If a placement with that id
    840 /// already exists, it is deleted first. If the provided id is 0, generates a
    841 /// random id.
    842 static ImagePlacement *gr_new_placement(Image *img, uint32_t id) {
    843 	if (id == 0) {
    844 		do {
    845 			// Currently we support only 24-bit IDs.
    846 			id = rand() & 0xFFFFFF;
    847 			// Avoid IDs that need only one byte.
    848 		} while ((id & 0x00FFFF00) == 0 || gr_find_placement(img, id));
    849 	}
    850 	ImagePlacement *placement = gr_find_placement(img, id);
    851 	gr_delete_placement_keep_id(placement);
    852 	GR_LOG("Creating placement %u/%u\n", img->image_id, id);
    853 	placement = malloc(sizeof(ImagePlacement));
    854 	memset(placement, 0, sizeof(ImagePlacement));
    855 	total_placement_count++;
    856 	int ret;
    857 	khiter_t k = kh_put(id2placement, img->placements, id, &ret);
    858 	kh_value(img->placements, k) = placement;
    859 	placement->image = img;
    860 	placement->placement_id = id;
    861 	gr_touch_placement(placement);
    862 	if (img->default_placement == 0)
    863 		img->default_placement = id;
    864 	return placement;
    865 }
    866 
    867 static int64_t ceil_div(int64_t a, int64_t b) {
    868 	return (a + b - 1) / b;
    869 }
    870 
    871 /// Computes the best number of rows and columns for a placement if it's not
    872 /// specified, and also adjusts the source rectangle size.
    873 static void gr_infer_placement_size_maybe(ImagePlacement *placement) {
    874 	// The size of the image.
    875 	int image_pix_width = placement->image->pix_width;
    876 	int image_pix_height = placement->image->pix_height;
    877 	// Negative values are not allowed. Quietly set them to 0.
    878 	if (placement->src_pix_x < 0)
    879 		placement->src_pix_x = 0;
    880 	if (placement->src_pix_y < 0)
    881 		placement->src_pix_y = 0;
    882 	if (placement->src_pix_width < 0)
    883 		placement->src_pix_width = 0;
    884 	if (placement->src_pix_height < 0)
    885 		placement->src_pix_height = 0;
    886 	// If the source rectangle is outside the image, truncate it.
    887 	if (placement->src_pix_x > image_pix_width)
    888 		placement->src_pix_x = image_pix_width;
    889 	if (placement->src_pix_y > image_pix_height)
    890 		placement->src_pix_y = image_pix_height;
    891 	// If the source rectangle is not specified, use the whole image. If
    892 	// it's partially outside the image, truncate it.
    893 	if (placement->src_pix_width == 0 ||
    894 	    placement->src_pix_x + placement->src_pix_width > image_pix_width)
    895 		placement->src_pix_width =
    896 			image_pix_width - placement->src_pix_x;
    897 	if (placement->src_pix_height == 0 ||
    898 	    placement->src_pix_y + placement->src_pix_height > image_pix_height)
    899 		placement->src_pix_height =
    900 			image_pix_height - placement->src_pix_y;
    901 
    902 	if (placement->cols != 0 && placement->rows != 0)
    903 		return;
    904 	if (placement->src_pix_width == 0 || placement->src_pix_height == 0)
    905 		return;
    906 	if (current_cw == 0 || current_ch == 0)
    907 		return;
    908 
    909 	// If no size is specified, use the image size.
    910 	if (placement->cols == 0 && placement->rows == 0) {
    911 		placement->cols =
    912 			ceil_div(placement->src_pix_width, current_cw);
    913 		placement->rows =
    914 			ceil_div(placement->src_pix_height, current_ch);
    915 		return;
    916 	}
    917 
    918 	// Some applications specify only one of the dimensions.
    919 	if (placement->scale_mode == SCALE_MODE_CONTAIN) {
    920 		// If we preserve aspect ratio and fit to width/height, the most
    921 		// logical thing is to find the minimum size of the
    922 		// non-specified dimension that allows the image to fit the
    923 		// specified dimension.
    924 		if (placement->cols == 0) {
    925 			placement->cols = ceil_div(
    926 				placement->src_pix_width * placement->rows *
    927 					current_ch,
    928 				placement->src_pix_height * current_cw);
    929 			return;
    930 		}
    931 		if (placement->rows == 0) {
    932 			placement->rows =
    933 				ceil_div(placement->src_pix_height *
    934 						 placement->cols * current_cw,
    935 					 placement->src_pix_width * current_ch);
    936 			return;
    937 		}
    938 	} else {
    939 		// Otherwise we stretch the image or preserve the original size.
    940 		// In both cases we compute the best number of columns from the
    941 		// pixel size and cell size.
    942 		// TODO: In the case of stretching it's not the most logical
    943 		//       thing to do, may need to revisit in the future.
    944 		//       Currently we switch to SCALE_MODE_CONTAIN when only one
    945 		//       of the dimensions is specified, so this case shouldn't
    946 		//       happen in practice.
    947 		if (!placement->cols)
    948 			placement->cols =
    949 				ceil_div(placement->src_pix_width, current_cw);
    950 		if (!placement->rows)
    951 			placement->rows =
    952 				ceil_div(placement->src_pix_height, current_ch);
    953 	}
    954 }
    955 
    956 /// Adjusts the current frame index if enough time has passed since the display
    957 /// of the current frame. Also computes the time of the next redraw of this
    958 /// image (`img->next_redraw`). The current time is passed as an argument so
    959 /// that all animations are in sync.
    960 static void gr_update_frame_index(Image *img, Milliseconds now) {
    961 	if (img->current_frame == 0) {
    962 		img->current_frame_time = now;
    963 		img->current_frame = 1;
    964 		img->next_redraw = now + MAX(1, img->first_frame.gap);
    965 		return;
    966 	}
    967 	// If the animation is stopped, show the current frame.
    968 	if (!img->animation_state ||
    969 	    img->animation_state == ANIMATION_STATE_STOPPED ||
    970 	    img->animation_state == ANIMATION_STATE_UNSET) {
    971 		// The next redraw is never (unless the state is changed).
    972 		img->next_redraw = 0;
    973 		return;
    974 	}
    975 	int last_uploaded_frame_index = gr_last_uploaded_frame_index(img);
    976 	// If we are loading and we reached the last frame, show the last frame.
    977 	if (img->animation_state == ANIMATION_STATE_LOADING &&
    978 	    img->current_frame == last_uploaded_frame_index) {
    979 		// The next redraw is never (unless the state is changed or
    980 		// frames are added).
    981 		img->next_redraw = 0;
    982 		return;
    983 	}
    984 
    985 	// Check how many milliseconds passed since the current frame was shown.
    986 	int passed_ms = now - img->current_frame_time;
    987 	// If the animation is looping and too much time has passes, we can
    988 	// make a shortcut.
    989 	if (img->animation_state == ANIMATION_STATE_LOOPING &&
    990 	    img->total_duration > 0 && passed_ms >= img->total_duration) {
    991 		passed_ms %= img->total_duration;
    992 		img->current_frame_time = now - passed_ms;
    993 	}
    994 	// Find the next frame.
    995 	int original_frame_index = img->current_frame;
    996 	while (1) {
    997 		ImageFrame *frame = gr_get_frame(img, img->current_frame);
    998 		if (!frame) {
    999 			// The frame doesn't exist, go to the first frame.
   1000 			img->current_frame = 1;
   1001 			img->current_frame_time = now;
   1002 			img->next_redraw = now + MAX(1, img->first_frame.gap);
   1003 			return;
   1004 		}
   1005 		if (frame->gap >= 0 && passed_ms < frame->gap) {
   1006 			// Not enough time has passed, we are still in the same
   1007 			// frame, and it's not a gapless frame.
   1008 			img->next_redraw =
   1009 				img->current_frame_time + MAX(1, frame->gap);
   1010 			return;
   1011 		}
   1012 		// Otherwise go to the next frame.
   1013 		passed_ms -= MAX(0, frame->gap);
   1014 		if (img->current_frame >= last_uploaded_frame_index) {
   1015 			// It's the last frame, if the animation is loading,
   1016 			// remain on it.
   1017 			if (img->animation_state == ANIMATION_STATE_LOADING) {
   1018 				img->next_redraw = 0;
   1019 				return;
   1020 			}
   1021 			// Otherwise the animation is looping.
   1022 			img->current_frame = 1;
   1023 			// TODO: Support finite number of loops.
   1024 		} else {
   1025 			img->current_frame++;
   1026 		}
   1027 		// Make sure we don't get stuck in an infinite loop.
   1028 		if (img->current_frame == original_frame_index) {
   1029 			// We looped through all frames, but haven't reached the
   1030 			// next frame yet. This may happen if too much time has
   1031 			// passed since the last redraw or all the frames are
   1032 			// gapless. Just move on to the next frame.
   1033 			img->current_frame++;
   1034 			if (img->current_frame >
   1035 			    last_uploaded_frame_index)
   1036 				img->current_frame = 1;
   1037 			img->current_frame_time = now;
   1038 			img->next_redraw = now + MAX(
   1039 				1, gr_get_frame(img, img->current_frame)->gap);
   1040 			return;
   1041 		}
   1042 		// Adjust the start time of the frame. The next redraw time will
   1043 		// be set in the next iteration.
   1044 		img->current_frame_time += MAX(0, frame->gap);
   1045 	}
   1046 }
   1047 
   1048 ////////////////////////////////////////////////////////////////////////////////
   1049 // Unloading and deleting images to save resources.
   1050 ////////////////////////////////////////////////////////////////////////////////
   1051 
   1052 /// A helper to compare frames by atime for qsort.
   1053 static int gr_cmp_frames_by_atime(const void *a, const void *b) {
   1054 	ImageFrame *frame_a = *(ImageFrame *const *)a;
   1055 	ImageFrame *frame_b = *(ImageFrame *const *)b;
   1056 	if (frame_a->atime == frame_b->atime)
   1057 		return frame_a->image->global_command_index -
   1058 		       frame_b->image->global_command_index;
   1059 	return frame_a->atime - frame_b->atime;
   1060 }
   1061 
   1062 /// A helper to compare images by atime for qsort.
   1063 static int gr_cmp_images_by_atime(const void *a, const void *b) {
   1064 	Image *img_a = *(Image *const *)a;
   1065 	Image *img_b = *(Image *const *)b;
   1066 	if (img_a->atime == img_b->atime)
   1067 		return img_a->global_command_index -
   1068 		       img_b->global_command_index;
   1069 	return img_a->atime - img_b->atime;
   1070 }
   1071 
   1072 /// A helper to compare placements by atime for qsort.
   1073 static int gr_cmp_placements_by_atime(const void *a, const void *b) {
   1074 	ImagePlacement *p_a = *(ImagePlacement **)a;
   1075 	ImagePlacement *p_b = *(ImagePlacement **)b;
   1076 	if (p_a->atime == p_b->atime)
   1077 		return p_a->image->global_command_index -
   1078 		       p_b->image->global_command_index;
   1079 	return p_a->atime - p_b->atime;
   1080 }
   1081 
   1082 typedef kvec_t(Image *) ImageVec;
   1083 typedef kvec_t(ImagePlacement *) ImagePlacementVec;
   1084 typedef kvec_t(ImageFrame *) ImageFrameVec;
   1085 
   1086 /// Returns an array of pointers to all images sorted by atime.
   1087 static ImageVec gr_get_images_sorted_by_atime() {
   1088 	ImageVec vec;
   1089 	kv_init(vec);
   1090 	if (kh_size(images) == 0)
   1091 		return vec;
   1092 	kv_resize(Image *, vec, kh_size(images));
   1093 	Image *img = NULL;
   1094 	kh_foreach_value(images, img, { kv_push(Image *, vec, img); });
   1095 	qsort(vec.a, kv_size(vec), sizeof(Image *), gr_cmp_images_by_atime);
   1096 	return vec;
   1097 }
   1098 
   1099 /// Returns an array of pointers to all placements sorted by atime.
   1100 static ImagePlacementVec gr_get_placements_sorted_by_atime() {
   1101 	ImagePlacementVec vec;
   1102 	kv_init(vec);
   1103 	if (total_placement_count == 0)
   1104 		return vec;
   1105 	kv_resize(ImagePlacement *, vec, total_placement_count);
   1106 	Image *img = NULL;
   1107 	ImagePlacement *placement = NULL;
   1108 	kh_foreach_value(images, img, {
   1109 		kh_foreach_value(img->placements, placement, {
   1110 			kv_push(ImagePlacement *, vec, placement);
   1111 		});
   1112 	});
   1113 	qsort(vec.a, kv_size(vec), sizeof(ImagePlacement *),
   1114 	      gr_cmp_placements_by_atime);
   1115 	return vec;
   1116 }
   1117 
   1118 /// Returns an array of pointers to all frames sorted by atime.
   1119 static ImageFrameVec gr_get_frames_sorted_by_atime() {
   1120 	ImageFrameVec frames;
   1121 	kv_init(frames);
   1122 	Image *img = NULL;
   1123 	kh_foreach_value(images, img, {
   1124 		foreach_frame(*img, frame, {
   1125 			kv_push(ImageFrame *, frames, frame);
   1126 		});
   1127 	});
   1128 	qsort(frames.a, kv_size(frames), sizeof(ImageFrame *),
   1129 	      gr_cmp_frames_by_atime);
   1130 	return frames;
   1131 }
   1132 
   1133 /// An object that can be unloaded from RAM.
   1134 typedef struct {
   1135 	/// Some score, probably based on access time. The lower the score, the
   1136 	/// more likely that the object should be unloaded.
   1137 	int64_t score;
   1138 	union {
   1139 		ImagePlacement *placement;
   1140 		ImageFrame *frame;
   1141 	};
   1142 	/// If zero, the object is the imlib object of `frame`, if non-zero,
   1143 	/// the object is a pixmap of `frameidx`-th frame of `placement`.
   1144 	int frameidx;
   1145 } UnloadableObject;
   1146 
   1147 typedef kvec_t(UnloadableObject) UnloadableObjectVec;
   1148 
   1149 /// A helper to compare unloadable objects by score for qsort.
   1150 static int gr_cmp_unloadable_objects(const void *a, const void *b) {
   1151 	UnloadableObject *obj_a = (UnloadableObject *)a;
   1152 	UnloadableObject *obj_b = (UnloadableObject *)b;
   1153 	return obj_a->score - obj_b->score;
   1154 }
   1155 
   1156 /// Unloads an unloadable object from RAM.
   1157 static void gr_unload_object(UnloadableObject *obj) {
   1158 	if (obj->frameidx) {
   1159 		if (obj->placement->protected_frame == obj->frameidx)
   1160 			return;
   1161 		gr_unload_pixmap(obj->placement, obj->frameidx);
   1162 	} else {
   1163 		gr_unload_frame(obj->frame);
   1164 	}
   1165 }
   1166 
   1167 /// Returns the recency threshold for an image. Frames that were accessed within
   1168 /// this threshold from now are considered recent and may be handled
   1169 /// differently because we may need them again very soon.
   1170 static Milliseconds gr_recency_threshold(Image *img) {
   1171 	return img->total_duration * 2 + 1000;
   1172 }
   1173 
   1174 /// Creates an unloadable object for the imlib object of a frame.
   1175 static UnloadableObject gr_unloadable_object_for_frame(Milliseconds now,
   1176 						       ImageFrame *frame) {
   1177 	UnloadableObject obj = {0};
   1178 	obj.frameidx = 0;
   1179 	obj.frame = frame;
   1180 	Milliseconds atime = frame->atime;
   1181 	obj.score = atime;
   1182 	if (atime >= now - gr_recency_threshold(frame->image)) {
   1183 		// This is a recent frame, probably from an active animation.
   1184 		// Score it above `now` to prefer unloading non-active frames.
   1185 		// Randomize the score because it's not very clear in which
   1186 		// order we want to unload them: reloading a frame may require
   1187 		// reloading other frames.
   1188 		obj.score = now + 1000 + rand() % 1000;
   1189 	}
   1190 	return obj;
   1191 }
   1192 
   1193 /// Creates an unloadable object for a pixmap.
   1194 static UnloadableObject
   1195 gr_unloadable_object_for_pixmap(Milliseconds now, ImageFrame *frame,
   1196 				ImagePlacement *placement) {
   1197 	UnloadableObject obj = {0};
   1198 	obj.frameidx = frame->index;
   1199 	obj.placement = placement;
   1200 	obj.score = placement->atime;
   1201 	// Since we don't store pixmap atimes, use the
   1202 	// oldest atime of the frame and the placement.
   1203 	Milliseconds atime = MIN(placement->atime, frame->atime);
   1204 	obj.score = atime;
   1205 	if (atime >= now - gr_recency_threshold(frame->image)) {
   1206 		// This is a recent pixmap, probably from an active animation.
   1207 		// Score it above `now` to prefer unloading non-active frames.
   1208 		// Also assign higher scores to frames that are closer to the
   1209 		// current frame (more likely to be used soon).
   1210 		int num_frames = gr_last_frame_index(frame->image);
   1211 		int dist = frame->index - frame->image->current_frame;
   1212 		if (dist < 0)
   1213 			dist += num_frames;
   1214 		obj.score =
   1215 			now + 1000 + (num_frames - dist) * 1000 / num_frames;
   1216 		// If the pixmap is much larger than the imlib image, prefer to
   1217 		// unload the pixmap by adding up to -1000 to the score. If the
   1218 		// imlib image is larger, add up to +1000.
   1219 		float imlib_size = gr_frame_current_ram_size(frame);
   1220 		float pixmap_size =
   1221 			gr_placement_single_frame_ram_size(placement);
   1222 		obj.score +=
   1223 			2000 * (imlib_size / (imlib_size + pixmap_size) - 0.5);
   1224 	}
   1225 	return obj;
   1226 }
   1227 
   1228 /// Returns an array of unloadable objects sorted by score.
   1229 static UnloadableObjectVec
   1230 gr_get_unloadable_objects_sorted_by_score(Milliseconds now) {
   1231 	UnloadableObjectVec objects;
   1232 	kv_init(objects);
   1233 	Image *img = NULL;
   1234 	ImagePlacement *placement = NULL;
   1235 	kh_foreach_value(images, img, {
   1236 		foreach_frame(*img, frame, {
   1237 			if (!frame->imlib_object)
   1238 				continue;
   1239 			kv_push(UnloadableObject, objects,
   1240 				gr_unloadable_object_for_frame(now, frame));
   1241 			int frameidx = frame->index;
   1242 			kh_foreach_value(img->placements, placement, {
   1243 				if (!gr_get_frame_pixmap(placement, frameidx))
   1244 					continue;
   1245 				kv_push(UnloadableObject, objects,
   1246 					gr_unloadable_object_for_pixmap(
   1247 						now, frame, placement));
   1248 			});
   1249 		});
   1250 	});
   1251 	qsort(objects.a, kv_size(objects), sizeof(UnloadableObject),
   1252 	      gr_cmp_unloadable_objects);
   1253 	return objects;
   1254 }
   1255 
   1256 /// Returns the limit adjusted by the excess tolerance ratio.
   1257 static inline unsigned apply_tolerance(unsigned limit) {
   1258 	return limit + (unsigned)(limit * graphics_excess_tolerance_ratio);
   1259 }
   1260 
   1261 /// Checks RAM and disk cache limits and deletes/unloads some images.
   1262 static void gr_check_limits() {
   1263 	Milliseconds now = gr_now_ms();
   1264 	ImageVec images_sorted = {0};
   1265 	ImagePlacementVec placements_sorted = {0};
   1266 	ImageFrameVec frames_sorted = {0};
   1267 	UnloadableObjectVec objects_sorted = {0};
   1268 	int images_begin = 0;
   1269 	int placements_begin = 0;
   1270 	char changed = 0;
   1271 	// First reduce the number of images if there are too many.
   1272 	if (kh_size(images) > apply_tolerance(graphics_max_total_placements)) {
   1273 		GR_LOG("Too many images: %d\n", kh_size(images));
   1274 		changed = 1;
   1275 		images_sorted = gr_get_images_sorted_by_atime();
   1276 		int to_delete = kv_size(images_sorted) -
   1277 				graphics_max_total_placements;
   1278 		for (; images_begin < to_delete; images_begin++)
   1279 			gr_delete_image(images_sorted.a[images_begin]);
   1280 	}
   1281 	// Then reduce the number of placements if there are too many.
   1282 	if (total_placement_count >
   1283 	    apply_tolerance(graphics_max_total_placements)) {
   1284 		GR_LOG("Too many placements: %d\n", total_placement_count);
   1285 		changed = 1;
   1286 		placements_sorted = gr_get_placements_sorted_by_atime();
   1287 		int to_delete = kv_size(placements_sorted) -
   1288 				graphics_max_total_placements;
   1289 		for (; placements_begin < to_delete; placements_begin++) {
   1290 			ImagePlacement *placement =
   1291 				placements_sorted.a[placements_begin];
   1292 			if (placement->protected_frame)
   1293 				break;
   1294 			gr_delete_placement(placement);
   1295 		}
   1296 	}
   1297 	// Then reduce the size of the image file cache. The files correspond to
   1298 	// image frames.
   1299 	if (images_disk_size >
   1300 	    apply_tolerance(graphics_total_file_cache_size)) {
   1301 		GR_LOG("Too big disk cache: %ld KiB\n",
   1302 		       images_disk_size / 1024);
   1303 		changed = 1;
   1304 		frames_sorted = gr_get_frames_sorted_by_atime();
   1305 		for (int i = 0; i < kv_size(frames_sorted); i++) {
   1306 			if (images_disk_size <= graphics_total_file_cache_size)
   1307 				break;
   1308 			gr_delete_imagefile(kv_A(frames_sorted, i));
   1309 		}
   1310 	}
   1311 	// Then unload images from RAM.
   1312 	if (images_ram_size > apply_tolerance(graphics_max_total_ram_size)) {
   1313 		changed = 1;
   1314 		int frames_begin = 0;
   1315 		GR_LOG("Too much ram: %ld KiB\n", images_ram_size / 1024);
   1316 		objects_sorted = gr_get_unloadable_objects_sorted_by_score(now);
   1317 		for (int i = 0; i < kv_size(objects_sorted); i++) {
   1318 			if (images_ram_size <= graphics_max_total_ram_size)
   1319 				break;
   1320 			gr_unload_object(&kv_A(objects_sorted, i));
   1321 		}
   1322 	}
   1323 	if (changed) {
   1324 		GR_LOG("After cleaning:  ram: %ld KiB  disk: %ld KiB  "
   1325 		       "img count: %d  placement count: %d\n",
   1326 		       images_ram_size / 1024, images_disk_size / 1024,
   1327 		       kh_size(images), total_placement_count);
   1328 	}
   1329 	kv_destroy(images_sorted);
   1330 	kv_destroy(placements_sorted);
   1331 	kv_destroy(frames_sorted);
   1332 	kv_destroy(objects_sorted);
   1333 }
   1334 
   1335 /// Unloads all images by user request.
   1336 void gr_unload_images_to_reduce_ram() {
   1337 	Image *img = NULL;
   1338 	ImagePlacement *placement = NULL;
   1339 	kh_foreach_value(images, img, {
   1340 		kh_foreach_value(img->placements, placement, {
   1341 			if (placement->protected_frame)
   1342 				continue;
   1343 			gr_unload_placement(placement);
   1344 		});
   1345 		gr_unload_all_frames(img);
   1346 	});
   1347 }
   1348 
   1349 ////////////////////////////////////////////////////////////////////////////////
   1350 // Image loading.
   1351 ////////////////////////////////////////////////////////////////////////////////
   1352 
   1353 /// Copies `num_pixels` pixels (not bytes!) from a buffer `from` to an imlib2
   1354 /// image data `to`. The format may be 24 (RGB) or 32 (RGBA), and it's converted
   1355 /// to imlib2's representation, which is 0xAARRGGBB (having BGRA memory layout
   1356 /// on little-endian architectures).
   1357 static inline void gr_copy_pixels(DATA32 *to, unsigned char *from, int format,
   1358 				  size_t num_pixels) {
   1359 	size_t pixel_size = format == 24 ? 3 : 4;
   1360 	if (format == 32) {
   1361 		for (unsigned i = 0; i < num_pixels; ++i) {
   1362 			unsigned byte_i = i * pixel_size;
   1363 			to[i] = ((DATA32)from[byte_i + 2]) |
   1364 				((DATA32)from[byte_i + 1]) << 8 |
   1365 				((DATA32)from[byte_i]) << 16 |
   1366 				((DATA32)from[byte_i + 3]) << 24;
   1367 		}
   1368 	} else {
   1369 		for (unsigned i = 0; i < num_pixels; ++i) {
   1370 			unsigned byte_i = i * pixel_size;
   1371 			to[i] = ((DATA32)from[byte_i + 2]) |
   1372 				((DATA32)from[byte_i + 1]) << 8 |
   1373 				((DATA32)from[byte_i]) << 16 | 0xFF000000;
   1374 		}
   1375 	}
   1376 }
   1377 
   1378 /// Loads uncompressed RGB or RGBA image data from a file.
   1379 static void gr_load_raw_pixel_data_uncompressed(DATA32 *data, FILE *file,
   1380 						int format,
   1381 						size_t total_pixels) {
   1382 	unsigned char chunk[BUFSIZ];
   1383 	size_t pixel_size = format == 24 ? 3 : 4;
   1384 	size_t chunk_size_pix = BUFSIZ / 4;
   1385 	size_t chunk_size_bytes = chunk_size_pix * pixel_size;
   1386 	size_t bytes = total_pixels * pixel_size;
   1387 	for (size_t chunk_start_pix = 0; chunk_start_pix < total_pixels;
   1388 	     chunk_start_pix += chunk_size_pix) {
   1389 		size_t read_size = fread(chunk, 1, chunk_size_bytes, file);
   1390 		size_t read_pixels = read_size / pixel_size;
   1391 		if (chunk_start_pix + read_pixels > total_pixels)
   1392 			read_pixels = total_pixels - chunk_start_pix;
   1393 		gr_copy_pixels(data + chunk_start_pix, chunk, format,
   1394 			       read_pixels);
   1395 	}
   1396 }
   1397 
   1398 #define COMPRESSED_CHUNK_SIZE BUFSIZ
   1399 #define DECOMPRESSED_CHUNK_SIZE (BUFSIZ * 4)
   1400 
   1401 /// Loads compressed RGB or RGBA image data from a file.
   1402 static int gr_load_raw_pixel_data_compressed(DATA32 *data, FILE *file,
   1403 					     int format, size_t total_pixels) {
   1404 	size_t pixel_size = format == 24 ? 3 : 4;
   1405 	unsigned char compressed_chunk[COMPRESSED_CHUNK_SIZE];
   1406 	unsigned char decompressed_chunk[DECOMPRESSED_CHUNK_SIZE];
   1407 
   1408 	z_stream strm;
   1409 	strm.zalloc = Z_NULL;
   1410 	strm.zfree = Z_NULL;
   1411 	strm.opaque = Z_NULL;
   1412 	strm.next_out = decompressed_chunk;
   1413 	strm.avail_out = DECOMPRESSED_CHUNK_SIZE;
   1414 	strm.avail_in = 0;
   1415 	strm.next_in = Z_NULL;
   1416 	int ret = inflateInit(&strm);
   1417 	if (ret != Z_OK)
   1418 	    return 1;
   1419 
   1420 	int error = 0;
   1421 	int progress = 0;
   1422 	size_t total_copied_pixels = 0;
   1423 	while (1) {
   1424 		// If we don't have enough data in the input buffer, try to read
   1425 		// from the file.
   1426 		if (strm.avail_in <= COMPRESSED_CHUNK_SIZE / 4) {
   1427 			// Move the existing data to the beginning.
   1428 			memmove(compressed_chunk, strm.next_in, strm.avail_in);
   1429 			strm.next_in = compressed_chunk;
   1430 			// Read more data.
   1431 			size_t bytes_read = fread(
   1432 				compressed_chunk + strm.avail_in, 1,
   1433 				COMPRESSED_CHUNK_SIZE - strm.avail_in, file);
   1434 			strm.avail_in += bytes_read;
   1435 			if (bytes_read != 0)
   1436 				progress = 1;
   1437 		}
   1438 
   1439 		// Try to inflate the data.
   1440 		int ret = inflate(&strm, Z_SYNC_FLUSH);
   1441 		if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) {
   1442 			error = 1;
   1443 			fprintf(stderr,
   1444 				"error: could not decompress the image, error "
   1445 				"%s\n",
   1446 				ret == Z_MEM_ERROR ? "Z_MEM_ERROR"
   1447 						   : "Z_DATA_ERROR");
   1448 			break;
   1449 		}
   1450 
   1451 		// Copy the data from the output buffer to the image.
   1452 		size_t full_pixels =
   1453 			(DECOMPRESSED_CHUNK_SIZE - strm.avail_out) / pixel_size;
   1454 		// Make sure we don't overflow the image.
   1455 		if (full_pixels > total_pixels - total_copied_pixels)
   1456 			full_pixels = total_pixels - total_copied_pixels;
   1457 		if (full_pixels > 0) {
   1458 			// Copy pixels.
   1459 			gr_copy_pixels(data, decompressed_chunk, format,
   1460 				       full_pixels);
   1461 			data += full_pixels;
   1462 			total_copied_pixels += full_pixels;
   1463 			if (total_copied_pixels >= total_pixels) {
   1464 				// We filled the whole image, there may be some
   1465 				// data left, but we just truncate it.
   1466 				break;
   1467 			}
   1468 			// Move the remaining data to the beginning.
   1469 			size_t copied_bytes = full_pixels * pixel_size;
   1470 			size_t leftover =
   1471 				(DECOMPRESSED_CHUNK_SIZE - strm.avail_out) -
   1472 				copied_bytes;
   1473 			memmove(decompressed_chunk,
   1474 				decompressed_chunk + copied_bytes, leftover);
   1475 			strm.next_out -= copied_bytes;
   1476 			strm.avail_out += copied_bytes;
   1477 			progress = 1;
   1478 		}
   1479 
   1480 		// If we haven't made any progress, then we have reached the end
   1481 		// of both the file and the inflated data.
   1482 		if (!progress)
   1483 			break;
   1484 		progress = 0;
   1485 	}
   1486 
   1487 	inflateEnd(&strm);
   1488 	return error;
   1489 }
   1490 
   1491 #undef COMPRESSED_CHUNK_SIZE
   1492 #undef DECOMPRESSED_CHUNK_SIZE
   1493 
   1494 /// Load the image from a file containing raw pixel data (RGB or RGBA), the data
   1495 /// may be compressed.
   1496 static Imlib_Image gr_load_raw_pixel_data(ImageFrame *frame,
   1497 					  const char *filename) {
   1498 	size_t total_pixels = frame->data_pix_width * frame->data_pix_height;
   1499 	if (total_pixels * 4 > graphics_max_single_image_ram_size) {
   1500 		fprintf(stderr,
   1501 			"error: image %u frame %u is too big too load: %zu > %u\n",
   1502 			frame->image->image_id, frame->index, total_pixels * 4,
   1503 			graphics_max_single_image_ram_size);
   1504 		return NULL;
   1505 	}
   1506 
   1507 	FILE* file = fopen(filename, "rb");
   1508 	if (!file) {
   1509 		fprintf(stderr,
   1510 			"error: could not open image file: %s\n",
   1511 			sanitized_filename(filename));
   1512 		return NULL;
   1513 	}
   1514 
   1515 	Imlib_Image image = imlib_create_image(frame->data_pix_width,
   1516 					       frame->data_pix_height);
   1517 	if (!image) {
   1518 		fprintf(stderr,
   1519 			"error: could not create an image of size %d x %d\n",
   1520 			frame->data_pix_width, frame->data_pix_height);
   1521 		fclose(file);
   1522 		return NULL;
   1523 	}
   1524 
   1525 	imlib_context_set_image(image);
   1526 	imlib_image_set_has_alpha(1);
   1527 	DATA32* data = imlib_image_get_data();
   1528 
   1529 	// The default format is 32.
   1530 	int format = frame->format ? frame->format : 32;
   1531 
   1532 	if (frame->compression == 0) {
   1533 		gr_load_raw_pixel_data_uncompressed(data, file, format,
   1534 						    total_pixels);
   1535 	} else {
   1536 		int ret = gr_load_raw_pixel_data_compressed(data, file, format,
   1537 							    total_pixels);
   1538 		if (ret != 0) {
   1539 			imlib_image_put_back_data(data);
   1540 			imlib_free_image();
   1541 			fclose(file);
   1542 			return NULL;
   1543 		}
   1544 	}
   1545 
   1546 	fclose(file);
   1547 	imlib_image_put_back_data(data);
   1548 	return image;
   1549 }
   1550 
   1551 /// Loads the unscaled frame into RAM as an imlib object. The frame imlib object
   1552 /// is fully composed on top of the background frame. If the frame is already
   1553 /// loaded, does nothing. Loading may fail, in which case the status of the
   1554 /// frame will be set to STATUS_RAM_LOADING_ERROR.
   1555 static void gr_load_imlib_object(ImageFrame *frame) {
   1556 	if (frame->imlib_object)
   1557 		return;
   1558 
   1559 	// If the image is uninitialized or uploading has failed, or the file
   1560 	// has been deleted, we cannot load the image.
   1561 	if (frame->status < STATUS_UPLOADING_SUCCESS)
   1562 		return;
   1563 	if (frame->disk_size == 0) {
   1564 		if (frame->status != STATUS_RAM_LOADING_ERROR) {
   1565 			fprintf(stderr,
   1566 				"error: cached image was deleted: %u frame %u\n",
   1567 				frame->image->image_id, frame->index);
   1568 		}
   1569 		frame->status = STATUS_RAM_LOADING_ERROR;
   1570 		return;
   1571 	}
   1572 
   1573 	// Prevent recursive dependences between frames.
   1574 	if (frame->status == STATUS_RAM_LOADING_IN_PROGRESS) {
   1575 		fprintf(stderr,
   1576 			"error: recursive loading of image %u frame %u\n",
   1577 			frame->image->image_id, frame->index);
   1578 		frame->status = STATUS_RAM_LOADING_ERROR;
   1579 		return;
   1580 	}
   1581 	frame->status = STATUS_RAM_LOADING_IN_PROGRESS;
   1582 
   1583 	// Load the background frame if needed. Hopefully it's not recursive.
   1584 	ImageFrame *bg_frame = NULL;
   1585 	if (frame->background_frame_index) {
   1586 		bg_frame = gr_get_frame(frame->image,
   1587 					frame->background_frame_index);
   1588 		if (!bg_frame) {
   1589 			fprintf(stderr,
   1590 				"error: could not find background "
   1591 				"frame %d for image %u frame %d\n",
   1592 				frame->background_frame_index,
   1593 				frame->image->image_id, frame->index);
   1594 			frame->status = STATUS_RAM_LOADING_ERROR;
   1595 			return;
   1596 		}
   1597 		gr_load_imlib_object(bg_frame);
   1598 		if (!bg_frame->imlib_object) {
   1599 			fprintf(stderr,
   1600 				"error: could not load background frame %d for "
   1601 				"image %u frame %d\n",
   1602 				frame->background_frame_index,
   1603 				frame->image->image_id, frame->index);
   1604 			frame->status = STATUS_RAM_LOADING_ERROR;
   1605 			return;
   1606 		}
   1607 	}
   1608 
   1609 	// Load the frame data image.
   1610 	Imlib_Image frame_data_image = NULL;
   1611 	char filename[MAX_FILENAME_SIZE];
   1612 	gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE);
   1613 	GR_LOG("Loading image: %s\n", sanitized_filename(filename));
   1614 	if (frame->format == 100 || frame->format == 0)
   1615 		frame_data_image = imlib_load_image(filename);
   1616 	if (frame->format == 32 || frame->format == 24 ||
   1617 	    (!frame_data_image && frame->format == 0))
   1618 		frame_data_image = gr_load_raw_pixel_data(frame, filename);
   1619 	this_redraw_cycle_loaded_files++;
   1620 
   1621 	if (!frame_data_image) {
   1622 		if (frame->status != STATUS_RAM_LOADING_ERROR) {
   1623 			fprintf(stderr, "error: could not load image: %s\n",
   1624 				sanitized_filename(filename));
   1625 		}
   1626 		frame->status = STATUS_RAM_LOADING_ERROR;
   1627 		return;
   1628 	}
   1629 
   1630 	imlib_context_set_image(frame_data_image);
   1631 	int frame_data_width = imlib_image_get_width();
   1632 	int frame_data_height = imlib_image_get_height();
   1633 	GR_LOG("Successfully loaded, size %d x %d\n", frame_data_width,
   1634 	       frame_data_height);
   1635 	// If imlib loading succeeded, and it is the first frame, set the
   1636 	// information about the original image size, unless it's already set.
   1637 	if (frame->index == 1 && frame->image->pix_width == 0 &&
   1638 	    frame->image->pix_height == 0) {
   1639 		frame->image->pix_width = frame_data_width;
   1640 		frame->image->pix_height = frame_data_height;
   1641 	}
   1642 
   1643 	int image_width = frame->image->pix_width;
   1644 	int image_height = frame->image->pix_height;
   1645 
   1646 	// Compose the image with the background color or frame.
   1647 	if (frame->background_color != 0 || bg_frame ||
   1648 	    image_width != frame_data_width ||
   1649 	    image_height != frame_data_height) {
   1650 		GR_LOG("Composing the frame bg = 0x%08X, bgframe = %d\n",
   1651 		       frame->background_color, frame->background_frame_index);
   1652 		Imlib_Image composed_image = imlib_create_image(
   1653 			image_width, image_height);
   1654 		imlib_context_set_image(composed_image);
   1655 		imlib_image_set_has_alpha(1);
   1656 		imlib_context_set_anti_alias(0);
   1657 
   1658 		// Start with the background frame or color.
   1659 		imlib_context_set_blend(0);
   1660 		if (bg_frame && bg_frame->imlib_object) {
   1661 			imlib_blend_image_onto_image(
   1662 				bg_frame->imlib_object, 1, 0, 0,
   1663 				image_width, image_height, 0, 0,
   1664 				image_width, image_height);
   1665 		} else {
   1666 			int r = (frame->background_color >> 24) & 0xFF;
   1667 			int g = (frame->background_color >> 16) & 0xFF;
   1668 			int b = (frame->background_color >> 8) & 0xFF;
   1669 			int a = frame->background_color & 0xFF;
   1670 			imlib_context_set_color(r, g, b, a);
   1671 			imlib_image_fill_rectangle(0, 0, image_width,
   1672 						   image_height);
   1673 		}
   1674 
   1675 		// Blend the frame data image onto the background.
   1676 		imlib_context_set_blend(1);
   1677 		imlib_blend_image_onto_image(
   1678 			frame_data_image, 1, 0, 0, frame->data_pix_width,
   1679 			frame->data_pix_height, frame->x, frame->y,
   1680 			frame->data_pix_width, frame->data_pix_height);
   1681 
   1682 		// Free the frame data image.
   1683 		imlib_context_set_image(frame_data_image);
   1684 		imlib_free_image();
   1685 
   1686 		frame_data_image = composed_image;
   1687 	}
   1688 
   1689 	frame->imlib_object = frame_data_image;
   1690 
   1691 	images_ram_size += gr_frame_current_ram_size(frame);
   1692 	frame->status = STATUS_RAM_LOADING_SUCCESS;
   1693 
   1694 	GR_LOG("After loading image %u frame %d ram: %ld KiB  (+ %u KiB)\n",
   1695 	       frame->image->image_id, frame->index,
   1696 	       images_ram_size / 1024, gr_frame_current_ram_size(frame) / 1024);
   1697 }
   1698 
   1699 /// Premultiplies the alpha channel of the image data. The data is an array of
   1700 /// pixels such that each pixel is a 32-bit integer in the format 0xAARRGGBB.
   1701 static void gr_premultiply_alpha(DATA32 *data, size_t num_pixels) {
   1702 	for (size_t i = 0; i < num_pixels; ++i) {
   1703 		DATA32 pixel = data[i];
   1704 		unsigned char a = pixel >> 24;
   1705 		if (a == 0) {
   1706 			data[i] = 0;
   1707 		} else if (a != 255) {
   1708 			unsigned char b = (pixel & 0xFF) * a / 255;
   1709 			unsigned char g = ((pixel >> 8) & 0xFF) * a / 255;
   1710 			unsigned char r = ((pixel >> 16) & 0xFF) * a / 255;
   1711 			data[i] = (a << 24) | (r << 16) | (g << 8) | b;
   1712 		}
   1713 	}
   1714 }
   1715 
   1716 /// Creates a pixmap for the frame of an image placement. The pixmap contain the
   1717 /// image data correctly scaled and fit to the box defined by the number of
   1718 /// rows/columns of the image placement and the provided cell dimensions in
   1719 /// pixels. If the placement is already loaded, it will be reloaded only if the
   1720 /// cell dimensions have changed.
   1721 Pixmap gr_load_pixmap(ImagePlacement *placement, int frameidx, int cw, int ch) {
   1722 	Image *img = placement->image;
   1723 	ImageFrame *frame = gr_get_frame(img, frameidx);
   1724 
   1725 	// Update the atime uncoditionally.
   1726 	gr_touch_placement(placement);
   1727 	if (frame)
   1728 		gr_touch_frame(frame);
   1729 
   1730 	// If cw or ch are different, unload all the pixmaps.
   1731 	if (placement->scaled_cw != cw || placement->scaled_ch != ch) {
   1732 		gr_unload_placement(placement);
   1733 		placement->scaled_cw = cw;
   1734 		placement->scaled_ch = ch;
   1735 	}
   1736 
   1737 	// If it's already loaded, do nothing.
   1738 	Pixmap pixmap = gr_get_frame_pixmap(placement, frameidx);
   1739 	if (pixmap)
   1740 		return pixmap;
   1741 
   1742 	GR_LOG("Loading placement: %u/%u frame %u\n", img->image_id,
   1743 	       placement->placement_id, frameidx);
   1744 
   1745 	// Load the imlib object for the frame.
   1746 	if (!frame) {
   1747 		fprintf(stderr,
   1748 			"error: could not find frame %u for image %u\n",
   1749 			frameidx, img->image_id);
   1750 		return 0;
   1751 	}
   1752 	gr_load_imlib_object(frame);
   1753 	if (!frame->imlib_object)
   1754 		return 0;
   1755 
   1756 	// Infer the placement size if needed.
   1757 	gr_infer_placement_size_maybe(placement);
   1758 
   1759 	// Create the scaled image. This is temporary, we will scale it
   1760 	// appropriately, upload to the X server, and then delete immediately.
   1761 	int scaled_w = (int)placement->cols * cw;
   1762 	int scaled_h = (int)placement->rows * ch;
   1763 	if (scaled_w * scaled_h * 4 > graphics_max_single_image_ram_size) {
   1764 		fprintf(stderr,
   1765 			"error: placement %u/%u would be too big to load: %d x "
   1766 			"%d x 4 > %u\n",
   1767 			img->image_id, placement->placement_id, scaled_w,
   1768 			scaled_h, graphics_max_single_image_ram_size);
   1769 		return 0;
   1770 	}
   1771 	Imlib_Image scaled_image = imlib_create_image(scaled_w, scaled_h);
   1772 	if (!scaled_image) {
   1773 		fprintf(stderr,
   1774 			"error: imlib_create_image(%d, %d) returned "
   1775 			"null\n",
   1776 			scaled_w, scaled_h);
   1777 		return 0;
   1778 	}
   1779 	imlib_context_set_image(scaled_image);
   1780 	imlib_image_set_has_alpha(1);
   1781 
   1782 	// First fill the scaled image with the transparent color.
   1783 	imlib_context_set_blend(0);
   1784 	imlib_context_set_color(0, 0, 0, 0);
   1785 	imlib_image_fill_rectangle(0, 0, scaled_w, scaled_h);
   1786 	imlib_context_set_anti_alias(1);
   1787 	imlib_context_set_blend(1);
   1788 
   1789 	// The source rectangle.
   1790 	int src_x = placement->src_pix_x;
   1791 	int src_y = placement->src_pix_y;
   1792 	int src_w = placement->src_pix_width;
   1793 	int src_h = placement->src_pix_height;
   1794 	// Whether the box is too small to use the true size of the image.
   1795 	char box_too_small = scaled_w < src_w || scaled_h < src_h;
   1796 	char mode = placement->scale_mode;
   1797 
   1798 	// Then blend the original image onto the transparent background.
   1799 	if (src_w <= 0 || src_h <= 0) {
   1800 		fprintf(stderr, "warning: image of zero size\n");
   1801 	} else if (mode == SCALE_MODE_FILL) {
   1802 		imlib_blend_image_onto_image(frame->imlib_object, 1, src_x,
   1803 					     src_y, src_w, src_h, 0, 0,
   1804 					     scaled_w, scaled_h);
   1805 	} else if (mode == SCALE_MODE_NONE ||
   1806 		   (mode == SCALE_MODE_NONE_OR_CONTAIN && !box_too_small)) {
   1807 		imlib_blend_image_onto_image(frame->imlib_object, 1, src_x,
   1808 					     src_y, src_w, src_h, 0, 0, src_w,
   1809 					     src_h);
   1810 	} else {
   1811 		if (mode != SCALE_MODE_CONTAIN &&
   1812 		    mode != SCALE_MODE_NONE_OR_CONTAIN) {
   1813 			fprintf(stderr,
   1814 				"warning: unknown scale mode %u, using "
   1815 				"'contain' instead\n",
   1816 				mode);
   1817 		}
   1818 		int dest_x, dest_y;
   1819 		int dest_w, dest_h;
   1820 		if (scaled_w * src_h > src_w * scaled_h) {
   1821 			// If the box is wider than the original image, fit to
   1822 			// height.
   1823 			dest_h = scaled_h;
   1824 			dest_y = 0;
   1825 			dest_w = src_w * scaled_h / src_h;
   1826 			dest_x = (scaled_w - dest_w) / 2;
   1827 		} else {
   1828 			// Otherwise, fit to width.
   1829 			dest_w = scaled_w;
   1830 			dest_x = 0;
   1831 			dest_h = src_h * scaled_w / src_w;
   1832 			dest_y = (scaled_h - dest_h) / 2;
   1833 		}
   1834 		imlib_blend_image_onto_image(frame->imlib_object, 1, src_x,
   1835 					     src_y, src_w, src_h, dest_x,
   1836 					     dest_y, dest_w, dest_h);
   1837 	}
   1838 
   1839 	// XRender needs the alpha channel premultiplied.
   1840 	DATA32 *data = imlib_image_get_data();
   1841 	gr_premultiply_alpha(data, scaled_w * scaled_h);
   1842 
   1843 	// Upload the image to the X server.
   1844 	Display *disp = imlib_context_get_display();
   1845 	Visual *vis = imlib_context_get_visual();
   1846 	Colormap cmap = imlib_context_get_colormap();
   1847 	Drawable drawable = imlib_context_get_drawable();
   1848 	if (!drawable)
   1849 		drawable = DefaultRootWindow(disp);
   1850 	pixmap = XCreatePixmap(disp, drawable, scaled_w, scaled_h, 32);
   1851 	XVisualInfo visinfo;
   1852 	XMatchVisualInfo(disp, DefaultScreen(disp), 32, TrueColor, &visinfo);
   1853 	XImage *ximage = XCreateImage(disp, visinfo.visual, 32, ZPixmap, 0,
   1854 				      (char *)data, scaled_w, scaled_h, 32, 0);
   1855 	GC gc = XCreateGC(disp, pixmap, 0, NULL);
   1856 	XPutImage(disp, pixmap, gc, ximage, 0, 0, 0, 0, scaled_w,
   1857 		  scaled_h);
   1858 	XFreeGC(disp, gc);
   1859 	// XDestroyImage will free the data as well, but it is managed by imlib,
   1860 	// so set it to NULL.
   1861 	ximage->data = NULL;
   1862 	XDestroyImage(ximage);
   1863 	imlib_image_put_back_data(data);
   1864 	imlib_free_image();
   1865 
   1866 	// Assign the pixmap to the frame and increase the ram size.
   1867 	gr_set_frame_pixmap(placement, frameidx, pixmap);
   1868 	images_ram_size += gr_placement_single_frame_ram_size(placement);
   1869 	this_redraw_cycle_loaded_pixmaps++;
   1870 
   1871 	GR_LOG("After loading placement %u/%u frame %d ram: %ld KiB  (+ %u "
   1872 	       "KiB)\n",
   1873 	       frame->image->image_id, placement->placement_id, frame->index,
   1874 	       images_ram_size / 1024,
   1875 	       gr_placement_single_frame_ram_size(placement) / 1024);
   1876 
   1877 	// Free up ram if needed, but keep the pixmap we've loaded no matter
   1878 	// what.
   1879 	placement->protected_frame = frameidx;
   1880 	gr_check_limits();
   1881 	placement->protected_frame = 0;
   1882 
   1883 	return pixmap;
   1884 }
   1885 
   1886 ////////////////////////////////////////////////////////////////////////////////
   1887 // Initialization and deinitialization.
   1888 ////////////////////////////////////////////////////////////////////////////////
   1889 
   1890 /// Creates a temporary directory.
   1891 static int gr_create_cache_dir() {
   1892 	strncpy(cache_dir, graphics_cache_dir_template, sizeof(cache_dir));
   1893 	if (!mkdtemp(cache_dir)) {
   1894 		fprintf(stderr,
   1895 			"error: could not create temporary dir from template "
   1896 			"%s\n",
   1897 			sanitized_filename(cache_dir));
   1898 		return 0;
   1899 	}
   1900 	fprintf(stderr, "Graphics cache directory: %s\n", cache_dir);
   1901 	return 1;
   1902 }
   1903 
   1904 /// Checks whether `tmp_dir` exists and recreates it if it doesn't.
   1905 static void gr_make_sure_tmpdir_exists() {
   1906 	struct stat st;
   1907 	if (stat(cache_dir, &st) == 0 && S_ISDIR(st.st_mode))
   1908 		return;
   1909 	fprintf(stderr,
   1910 		"error: %s is not a directory, will need to create a new "
   1911 		"graphics cache directory\n",
   1912 		sanitized_filename(cache_dir));
   1913 	gr_create_cache_dir();
   1914 }
   1915 
   1916 /// Initialize the graphics module.
   1917 void gr_init(Display *disp, Visual *vis, Colormap cm) {
   1918 	// Set the initialization time.
   1919 	clock_gettime(CLOCK_MONOTONIC, &initialization_time);
   1920 
   1921 	// Create the temporary dir.
   1922 	if (!gr_create_cache_dir())
   1923 		abort();
   1924 
   1925 	// Initialize imlib.
   1926 	imlib_context_set_display(disp);
   1927 	imlib_context_set_visual(vis);
   1928 	imlib_context_set_colormap(cm);
   1929 	imlib_context_set_anti_alias(1);
   1930 	imlib_context_set_blend(1);
   1931 	// Imlib2 checks only the file name when caching, which is not enough
   1932 	// for us since we reuse file names. Disable caching.
   1933 	imlib_set_cache_size(0);
   1934 
   1935 	// Prepare for color inversion.
   1936 	for (size_t i = 0; i < 256; ++i)
   1937 		reverse_table[i] = 255 - i;
   1938 
   1939 	// Create data structures.
   1940 	images = kh_init(id2image);
   1941 	kv_init(next_redraw_times);
   1942 
   1943 	atexit(gr_deinit);
   1944 }
   1945 
   1946 /// Deinitialize the graphics module.
   1947 void gr_deinit() {
   1948 	// Remove the cache dir.
   1949 	remove(cache_dir);
   1950 	kv_destroy(next_redraw_times);
   1951 	if (images) {
   1952 		// Delete all images.
   1953 		gr_delete_all_images();
   1954 		// Destroy the data structures.
   1955 		kh_destroy(id2image, images);
   1956 		images = NULL;
   1957 	}
   1958 }
   1959 
   1960 ////////////////////////////////////////////////////////////////////////////////
   1961 // Dumping, debugging, and image preview.
   1962 ////////////////////////////////////////////////////////////////////////////////
   1963 
   1964 /// Returns a string containing a time difference in a human-readable format.
   1965 /// Uses a static buffer, so be careful.
   1966 static const char *gr_ago(Milliseconds diff) {
   1967 	static char result[32];
   1968 	double seconds = (double)diff / 1000.0;
   1969 	if (seconds < 1)
   1970 		snprintf(result, sizeof(result), "%.2f sec ago", seconds);
   1971 	else if (seconds < 60)
   1972 		snprintf(result, sizeof(result), "%d sec ago", (int)seconds);
   1973 	else if (seconds < 3600)
   1974 		snprintf(result, sizeof(result), "%d min %d sec ago",
   1975 			 (int)(seconds / 60), (int)(seconds) % 60);
   1976 	else {
   1977 		snprintf(result, sizeof(result), "%d hr %d min %d sec ago",
   1978 			 (int)(seconds / 3600), (int)(seconds) % 3600 / 60,
   1979 			 (int)(seconds) % 60);
   1980 	}
   1981 	return result;
   1982 }
   1983 
   1984 /// Prints to `file` with an indentation of `ind` spaces.
   1985 static void fprintf_ind(FILE *file, int ind, const char *format, ...) {
   1986 	fprintf(file, "%*s", ind, "");
   1987 	va_list args;
   1988 	va_start(args, format);
   1989 	vfprintf(file, format, args);
   1990 	va_end(args);
   1991 }
   1992 
   1993 /// Dumps the image info to `file` with an indentation of `ind` spaces.
   1994 static void gr_dump_image_info(FILE *file, Image *img, int ind) {
   1995 	if (!img) {
   1996 		fprintf_ind(file, ind, "Image is NULL\n");
   1997 		return;
   1998 	}
   1999 	Milliseconds now = gr_now_ms();
   2000 	fprintf_ind(file, ind, "Image %u\n", img->image_id);
   2001 	ind += 4;
   2002 	fprintf_ind(file, ind, "number: %u\n", img->image_number);
   2003 	fprintf_ind(file, ind, "global command index: %lu\n",
   2004 		img->global_command_index);
   2005 	fprintf_ind(file, ind, "accessed: %ld  %s\n", img->atime,
   2006 		    gr_ago(now - img->atime));
   2007 	fprintf_ind(file, ind, "pix size: %ux%u\n", img->pix_width,
   2008 		    img->pix_height);
   2009 	fprintf_ind(file, ind, "cur frame start time: %ld  %s\n",
   2010 		    img->current_frame_time,
   2011 		    gr_ago(now - img->current_frame_time));
   2012 	if (img->next_redraw)
   2013 		fprintf_ind(file, ind, "next redraw: %ld  in %ld ms\n",
   2014 			    img->next_redraw, img->next_redraw - now);
   2015 	fprintf_ind(file, ind, "total disk size: %u KiB\n",
   2016 		img->total_disk_size / 1024);
   2017 	fprintf_ind(file, ind, "total duration: %d\n", img->total_duration);
   2018 	fprintf_ind(file, ind, "frames: %d\n", gr_last_frame_index(img));
   2019 	fprintf_ind(file, ind, "cur frame: %d\n", img->current_frame);
   2020 	fprintf_ind(file, ind, "animation state: %d\n", img->animation_state);
   2021 	fprintf_ind(file, ind, "default_placement: %u\n",
   2022 		    img->default_placement);
   2023 }
   2024 
   2025 /// Dumps the frame info to `file` with an indentation of `ind` spaces.
   2026 static void gr_dump_frame_info(FILE *file, ImageFrame *frame, int ind) {
   2027 	if (!frame) {
   2028 		fprintf_ind(file, ind, "Frame is NULL\n");
   2029 		return;
   2030 	}
   2031 	Milliseconds now = gr_now_ms();
   2032 	fprintf_ind(file, ind, "Frame %d\n", frame->index);
   2033 	ind += 4;
   2034 	if (frame->index == 0) {
   2035 		fprintf_ind(file, ind, "NOT INITIALIZED\n");
   2036 		return;
   2037 	}
   2038 	if (frame->uploading_failure)
   2039 		fprintf_ind(file, ind, "uploading failure: %s\n",
   2040 			    image_uploading_failure_strings
   2041 				    [frame->uploading_failure]);
   2042 	fprintf_ind(file, ind, "gap: %d\n", frame->gap);
   2043 	fprintf_ind(file, ind, "accessed: %ld  %s\n", frame->atime,
   2044 		    gr_ago(now - frame->atime));
   2045 	fprintf_ind(file, ind, "data pix size: %ux%u\n", frame->data_pix_width,
   2046 		    frame->data_pix_height);
   2047 	char filename[MAX_FILENAME_SIZE];
   2048 	gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE);
   2049 	if (access(filename, F_OK) != -1)
   2050 		fprintf_ind(file, ind, "file: %s\n",
   2051 			    sanitized_filename(filename));
   2052 	else
   2053 		fprintf_ind(file, ind, "not on disk\n");
   2054 	fprintf_ind(file, ind, "disk size: %u KiB\n", frame->disk_size / 1024);
   2055 	if (frame->imlib_object) {
   2056 		unsigned ram_size = gr_frame_current_ram_size(frame);
   2057 		fprintf_ind(file, ind,
   2058 			    "loaded into ram, size: %d "
   2059 			    "KiB\n",
   2060 			    ram_size / 1024);
   2061 	} else {
   2062 		fprintf_ind(file, ind, "not loaded into ram\n");
   2063 	}
   2064 }
   2065 
   2066 /// Dumps the placement info to `file` with an indentation of `ind` spaces.
   2067 static void gr_dump_placement_info(FILE *file, ImagePlacement *placement,
   2068 				   int ind) {
   2069 	if (!placement) {
   2070 		fprintf_ind(file, ind, "Placement is NULL\n");
   2071 		return;
   2072 	}
   2073 	Milliseconds now = gr_now_ms();
   2074 	fprintf_ind(file, ind, "Placement %u\n", placement->placement_id);
   2075 	ind += 4;
   2076 	fprintf_ind(file, ind, "accessed: %ld  %s\n", placement->atime,
   2077 		    gr_ago(now - placement->atime));
   2078 	fprintf_ind(file, ind, "scale_mode: %u\n", placement->scale_mode);
   2079 	fprintf_ind(file, ind, "size: %u cols x %u rows\n", placement->cols,
   2080 		    placement->rows);
   2081 	fprintf_ind(file, ind, "cell size: %ux%u\n", placement->scaled_cw,
   2082 		    placement->scaled_ch);
   2083 	fprintf_ind(file, ind, "ram per frame: %u KiB\n",
   2084 		    gr_placement_single_frame_ram_size(placement) / 1024);
   2085 	unsigned ram_size = gr_placement_current_ram_size(placement);
   2086 	fprintf_ind(file, ind, "ram size: %d KiB\n", ram_size / 1024);
   2087 }
   2088 
   2089 /// Dumps placement pixmaps to `file` with an indentation of `ind` spaces.
   2090 static void gr_dump_placement_pixmaps(FILE *file, ImagePlacement *placement,
   2091 				      int ind) {
   2092 	if (!placement)
   2093 		return;
   2094 	int frameidx = 1;
   2095 	foreach_pixmap(*placement, pixmap, {
   2096 		fprintf_ind(file, ind, "Frame %d pixmap %lu\n", frameidx,
   2097 			    pixmap);
   2098 		++frameidx;
   2099 	});
   2100 }
   2101 
   2102 /// Dumps the internal state (images and placements) to stderr.
   2103 void gr_dump_state() {
   2104 	FILE *file = stderr;
   2105 	int ind = 0;
   2106 	fprintf_ind(file, ind, "======= Graphics module state dump =======\n");
   2107 	fprintf_ind(file, ind,
   2108 		"sizeof(Image) = %lu  sizeof(ImageFrame) = %lu  "
   2109 		"sizeof(ImagePlacement) = %lu\n",
   2110 		sizeof(Image), sizeof(ImageFrame), sizeof(ImagePlacement));
   2111 	fprintf_ind(file, ind, "Image count: %u\n", kh_size(images));
   2112 	fprintf_ind(file, ind, "Placement count: %u\n", total_placement_count);
   2113 	fprintf_ind(file, ind, "Estimated RAM usage: %ld KiB\n",
   2114 		images_ram_size / 1024);
   2115 	fprintf_ind(file, ind, "Estimated Disk usage: %ld KiB\n",
   2116 		images_disk_size / 1024);
   2117 
   2118 	Milliseconds now = gr_now_ms();
   2119 
   2120 	int64_t images_ram_size_computed = 0;
   2121 	int64_t images_disk_size_computed = 0;
   2122 
   2123 	Image *img = NULL;
   2124 	ImagePlacement *placement = NULL;
   2125 	kh_foreach_value(images, img, {
   2126 		fprintf_ind(file, ind, "----------------\n");
   2127 		gr_dump_image_info(file, img, 0);
   2128 		int64_t total_disk_size_computed = 0;
   2129 		int total_duration_computed = 0;
   2130 		foreach_frame(*img, frame, {
   2131 			gr_dump_frame_info(file, frame, 4);
   2132 			if (frame->image != img)
   2133 				fprintf_ind(file, 8,
   2134 					    "ERROR: WRONG IMAGE POINTER\n");
   2135 			total_duration_computed += frame->gap;
   2136 			images_disk_size_computed += frame->disk_size;
   2137 			total_disk_size_computed += frame->disk_size;
   2138 			if (frame->imlib_object)
   2139 				images_ram_size_computed +=
   2140 					gr_frame_current_ram_size(frame);
   2141 		});
   2142 		if (img->total_disk_size != total_disk_size_computed) {
   2143 			fprintf_ind(file, ind,
   2144 				"    ERROR: total_disk_size is %u, but "
   2145 				"computed value is %ld\n",
   2146 				img->total_disk_size, total_disk_size_computed);
   2147 		}
   2148 		if (img->total_duration != total_duration_computed) {
   2149 			fprintf_ind(file, ind,
   2150 				"    ERROR: total_duration is %d, but computed "
   2151 				"value is %d\n",
   2152 				img->total_duration, total_duration_computed);
   2153 		}
   2154 		kh_foreach_value(img->placements, placement, {
   2155 			gr_dump_placement_info(file, placement, 4);
   2156 			if (placement->image != img)
   2157 				fprintf_ind(file, 8,
   2158 					    "ERROR: WRONG IMAGE POINTER\n");
   2159 			fprintf_ind(file, 8,
   2160 				    "Pixmaps:\n");
   2161 			gr_dump_placement_pixmaps(file, placement, 12);
   2162 			unsigned ram_size =
   2163 				gr_placement_current_ram_size(placement);
   2164 			images_ram_size_computed += ram_size;
   2165 		});
   2166 	});
   2167 	if (images_ram_size != images_ram_size_computed) {
   2168 		fprintf_ind(file, ind,
   2169 			"ERROR: images_ram_size is %ld, but computed value "
   2170 			"is %ld\n",
   2171 			images_ram_size, images_ram_size_computed);
   2172 	}
   2173 	if (images_disk_size != images_disk_size_computed) {
   2174 		fprintf_ind(file, ind,
   2175 			"ERROR: images_disk_size is %ld, but computed value "
   2176 			"is %ld\n",
   2177 			images_disk_size, images_disk_size_computed);
   2178 	}
   2179 	fprintf_ind(file, ind, "===========================================\n");
   2180 }
   2181 
   2182 /// Executes `command` with the name of the file corresponding to `image_id` as
   2183 /// the argument. Executes xmessage with an error message on failure.
   2184 // TODO: Currently we do this for the first frame only. Not sure what to do with
   2185 //       animations.
   2186 void gr_preview_image(uint32_t image_id, const char *exec) {
   2187 	char command[256];
   2188 	size_t len;
   2189 	Image *img = gr_find_image(image_id);
   2190 	if (img) {
   2191 		ImageFrame *frame = &img->first_frame;
   2192 		char filename[MAX_FILENAME_SIZE];
   2193 		gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE);
   2194 		if (frame->disk_size == 0) {
   2195 			len = snprintf(command, 255,
   2196 				       "xmessage 'Image with id=%u is not "
   2197 				       "fully copied to %s'",
   2198 				       image_id, sanitized_filename(filename));
   2199 		} else {
   2200 			len = snprintf(command, 255, "%s %s &", exec,
   2201 				       sanitized_filename(filename));
   2202 		}
   2203 	} else {
   2204 		len = snprintf(command, 255,
   2205 			       "xmessage 'Cannot find image with id=%u'",
   2206 			       image_id);
   2207 	}
   2208 	if (len > 255) {
   2209 		fprintf(stderr, "error: command too long: %s\n", command);
   2210 		snprintf(command, 255, "xmessage 'error: command too long'");
   2211 	}
   2212 	if (system(command) != 0) {
   2213 		fprintf(stderr, "error: could not execute command %s\n",
   2214 			command);
   2215 	}
   2216 }
   2217 
   2218 /// Executes `<st> -e less <file>` where <file> is the name of a temporary file
   2219 /// containing the information about an image and placement, and <st> is
   2220 /// specified with `st_executable`.
   2221 void gr_show_image_info(uint32_t image_id, uint32_t placement_id,
   2222 			uint32_t imgcol, uint32_t imgrow,
   2223 			char is_classic_placeholder, int32_t diacritic_count,
   2224 			char *st_executable) {
   2225 	char filename[MAX_FILENAME_SIZE];
   2226 	snprintf(filename, sizeof(filename), "%s/info-%u", cache_dir, image_id);
   2227 	FILE *file = fopen(filename, "w");
   2228 	if (!file) {
   2229 		perror("fopen");
   2230 		return;
   2231 	}
   2232 	// Basic information about the cell.
   2233 	fprintf(file, "image_id = %u = 0x%08X\n", image_id, image_id);
   2234 	fprintf(file, "placement_id = %u = 0x%08X\n", placement_id, placement_id);
   2235 	fprintf(file, "column = %d, row = %d\n", imgcol, imgrow);
   2236 	fprintf(file, "classic/unicode placeholder = %s\n",
   2237 		is_classic_placeholder ? "classic" : "unicode");
   2238 	fprintf(file, "original diacritic count = %d\n", diacritic_count);
   2239 	// Information about the image and the placement.
   2240 	Image *img = gr_find_image(image_id);
   2241 	ImagePlacement *placement = gr_find_placement(img, placement_id);
   2242 	gr_dump_image_info(file, img, 0);
   2243 	gr_dump_placement_info(file, placement, 0);
   2244 	if (img) {
   2245 		fprintf(file, "Frames:\n");
   2246 		foreach_frame(*img, frame, {
   2247 			gr_dump_frame_info(file, frame, 4);
   2248 		});
   2249 	}
   2250 	if (placement) {
   2251 		fprintf(file, "Placement pixmaps:\n");
   2252 		gr_dump_placement_pixmaps(file, placement, 4);
   2253 	}
   2254 	fclose(file);
   2255 	char *argv[] = {st_executable, "-e", "less", filename, NULL};
   2256 	if (posix_spawnp(NULL, st_executable, NULL, NULL, argv, environ) != 0) {
   2257 		perror("posix_spawnp");
   2258 		return;
   2259 	}
   2260 }
   2261 
   2262 ////////////////////////////////////////////////////////////////////////////////
   2263 // Appending and displaying image rectangles.
   2264 ////////////////////////////////////////////////////////////////////////////////
   2265 
   2266 /// Displays debug information in the rectangle using colors col1 and col2.
   2267 static void gr_displayinfo(Drawable buf, ImageRect *rect, int col1, int col2,
   2268 			   const char *message) {
   2269 	int w_pix = (rect->img_end_col - rect->img_start_col) * rect->cw;
   2270 	int h_pix = (rect->img_end_row - rect->img_start_row) * rect->ch;
   2271 	Display *disp = imlib_context_get_display();
   2272 	GC gc = XCreateGC(disp, buf, 0, NULL);
   2273 	char info[MAX_INFO_LEN];
   2274 	if (rect->placement_id)
   2275 		snprintf(info, MAX_INFO_LEN, "%s%u/%u [%d:%d)x[%d:%d)", message,
   2276 			 rect->image_id, rect->placement_id,
   2277 			 rect->img_start_col, rect->img_end_col,
   2278 			 rect->img_start_row, rect->img_end_row);
   2279 	else
   2280 		snprintf(info, MAX_INFO_LEN, "%s%u [%d:%d)x[%d:%d)", message,
   2281 			 rect->image_id, rect->img_start_col, rect->img_end_col,
   2282 			 rect->img_start_row, rect->img_end_row);
   2283 	XSetForeground(disp, gc, col1);
   2284 	XDrawString(disp, buf, gc, rect->screen_x_pix + 4,
   2285 		    rect->screen_y_pix + h_pix - 3, info, strlen(info));
   2286 	XSetForeground(disp, gc, col2);
   2287 	XDrawString(disp, buf, gc, rect->screen_x_pix + 2,
   2288 		    rect->screen_y_pix + h_pix - 5, info, strlen(info));
   2289 	XFreeGC(disp, gc);
   2290 }
   2291 
   2292 /// Draws a rectangle (bounding box) for debugging.
   2293 static void gr_showrect(Drawable buf, ImageRect *rect) {
   2294 	int w_pix = (rect->img_end_col - rect->img_start_col) * rect->cw;
   2295 	int h_pix = (rect->img_end_row - rect->img_start_row) * rect->ch;
   2296 	Display *disp = imlib_context_get_display();
   2297 	GC gc = XCreateGC(disp, buf, 0, NULL);
   2298 	XSetForeground(disp, gc, 0xFF00FF00);
   2299 	XDrawRectangle(disp, buf, gc, rect->screen_x_pix, rect->screen_y_pix,
   2300 		       w_pix - 1, h_pix - 1);
   2301 	XSetForeground(disp, gc, 0xFFFF0000);
   2302 	XDrawRectangle(disp, buf, gc, rect->screen_x_pix + 1,
   2303 		       rect->screen_y_pix + 1, w_pix - 3, h_pix - 3);
   2304 	XFreeGC(disp, gc);
   2305 }
   2306 
   2307 /// Updates the next redraw time for the given row. Resizes the
   2308 /// next_redraw_times array if needed.
   2309 static void gr_update_next_redraw_time(int row, Milliseconds next_redraw) {
   2310 	if (next_redraw == 0)
   2311 		return;
   2312 	if (row >= kv_size(next_redraw_times)) {
   2313 		size_t old_size = kv_size(next_redraw_times);
   2314 		kv_a(Milliseconds, next_redraw_times, row);
   2315 		for (size_t i = old_size; i <= row; ++i)
   2316 			kv_A(next_redraw_times, i) = 0;
   2317 	}
   2318 	Milliseconds old_value = kv_A(next_redraw_times, row);
   2319 	if (old_value == 0 || old_value > next_redraw)
   2320 		kv_A(next_redraw_times, row) = next_redraw;
   2321 }
   2322 
   2323 /// Draws the given part of an image.
   2324 static void gr_drawimagerect(Drawable buf, ImageRect *rect) {
   2325 	ImagePlacement *placement =
   2326 		gr_find_image_and_placement(rect->image_id, rect->placement_id);
   2327 	// If the image does not exist or image display is switched off, draw
   2328 	// the bounding box.
   2329 	if (!placement || !graphics_display_images) {
   2330 		gr_showrect(buf, rect);
   2331 		if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES)
   2332 			gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, "");
   2333 		return;
   2334 	}
   2335 
   2336 	Image *img = placement->image;
   2337 
   2338 	if (img->last_redraw < drawing_start_time) {
   2339 		// This is the first time we draw this image in this redraw
   2340 		// cycle. Update the frame index we are going to display. Note
   2341 		// that currently all image placements are synchronized.
   2342 		int old_frame = img->current_frame;
   2343 		gr_update_frame_index(img, drawing_start_time);
   2344 		img->last_redraw = drawing_start_time;
   2345 	}
   2346 
   2347 	// Adjust next redraw times for the rows of this image rect.
   2348 	if (img->next_redraw) {
   2349 		for (int row = rect->screen_y_row;
   2350 		     row <= rect->screen_y_row + rect->img_end_row -
   2351 					  rect->img_start_row - 1; ++row) {
   2352 			gr_update_next_redraw_time(
   2353 				row, img->next_redraw);
   2354 		}
   2355 	}
   2356 
   2357 	// Load the frame.
   2358 	Pixmap pixmap = gr_load_pixmap(placement, img->current_frame, rect->cw,
   2359 				       rect->ch);
   2360 
   2361 	// If the image couldn't be loaded, display the bounding box.
   2362 	if (!pixmap) {
   2363 		gr_showrect(buf, rect);
   2364 		if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES)
   2365 			gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, "");
   2366 		return;
   2367 	}
   2368 
   2369 	int src_x = rect->img_start_col * rect->cw;
   2370 	int src_y = rect->img_start_row * rect->ch;
   2371 	int width = (rect->img_end_col - rect->img_start_col) * rect->cw;
   2372 	int height = (rect->img_end_row - rect->img_start_row) * rect->ch;
   2373 	int dst_x = rect->screen_x_pix;
   2374 	int dst_y = rect->screen_y_pix;
   2375 
   2376 	// Display the image.
   2377 	Display *disp = imlib_context_get_display();
   2378 	Visual *vis = imlib_context_get_visual();
   2379 
   2380 	// Create an xrender picture for the window.
   2381 	XRenderPictFormat *win_format =
   2382 		XRenderFindVisualFormat(disp, vis);
   2383 	Picture window_pic =
   2384 		XRenderCreatePicture(disp, buf, win_format, 0, NULL);
   2385 
   2386 	// If needed, invert the image pixmap. Note that this naive approach of
   2387 	// inverting the pixmap is not entirely correct, because the pixmap is
   2388 	// premultiplied. But the result is good enough to visually indicate
   2389 	// selection.
   2390 	if (rect->reverse) {
   2391 		unsigned pixmap_w =
   2392 			(unsigned)placement->cols * placement->scaled_cw;
   2393 		unsigned pixmap_h =
   2394 			(unsigned)placement->rows * placement->scaled_ch;
   2395 		Pixmap invpixmap =
   2396 			XCreatePixmap(disp, buf, pixmap_w, pixmap_h, 32);
   2397 		XGCValues gcv = {.function = GXcopyInverted};
   2398 		GC gc = XCreateGC(disp, invpixmap, GCFunction, &gcv);
   2399 		XCopyArea(disp, pixmap, invpixmap, gc, 0, 0, pixmap_w,
   2400 			  pixmap_h, 0, 0);
   2401 		XFreeGC(disp, gc);
   2402 		pixmap = invpixmap;
   2403 	}
   2404 
   2405 	// Create a picture for the image pixmap.
   2406 	XRenderPictFormat *pic_format =
   2407 		XRenderFindStandardFormat(disp, PictStandardARGB32);
   2408 	Picture pixmap_pic =
   2409 		XRenderCreatePicture(disp, pixmap, pic_format, 0, NULL);
   2410 
   2411 	// Composite the image onto the window. In the reverse mode we ignore
   2412 	// the alpha channel of the image because the naive inversion above
   2413 	// seems to invert the alpha channel as well.
   2414 	int pictop = rect->reverse ? PictOpSrc : PictOpOver;
   2415 	XRenderComposite(disp, pictop, pixmap_pic, 0, window_pic,
   2416 			 src_x, src_y, src_x, src_y, dst_x, dst_y, width,
   2417 			 height);
   2418 
   2419 	// Free resources
   2420 	XRenderFreePicture(disp, pixmap_pic);
   2421 	XRenderFreePicture(disp, window_pic);
   2422 	if (rect->reverse)
   2423 		XFreePixmap(disp, pixmap);
   2424 
   2425 	// In debug mode always draw bounding boxes and print info.
   2426 	if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES) {
   2427 		gr_showrect(buf, rect);
   2428 		gr_displayinfo(buf, rect, 0xFF000000, 0xFFFFFFFF, "");
   2429 	}
   2430 }
   2431 
   2432 /// Removes the given image rectangle.
   2433 static void gr_freerect(ImageRect *rect) { memset(rect, 0, sizeof(ImageRect)); }
   2434 
   2435 /// Returns the bottom coordinate of the rect.
   2436 static int gr_getrectbottom(ImageRect *rect) {
   2437 	return rect->screen_y_pix +
   2438 	       (rect->img_end_row - rect->img_start_row) * rect->ch;
   2439 }
   2440 
   2441 /// Prepare for image drawing. `cw` and `ch` are dimensions of the cell.
   2442 void gr_start_drawing(Drawable buf, int cw, int ch) {
   2443 	current_cw = cw;
   2444 	current_ch = ch;
   2445 	this_redraw_cycle_loaded_files = 0;
   2446 	this_redraw_cycle_loaded_pixmaps = 0;
   2447 	drawing_start_time = gr_now_ms();
   2448 	imlib_context_set_drawable(buf);
   2449 }
   2450 
   2451 /// Finish image drawing. This functions will draw all the rectangles left to
   2452 /// draw.
   2453 void gr_finish_drawing(Drawable buf) {
   2454 	// Draw and then delete all known image rectangles.
   2455 	for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) {
   2456 		ImageRect *rect = &image_rects[i];
   2457 		if (!rect->image_id)
   2458 			continue;
   2459 		gr_drawimagerect(buf, rect);
   2460 		gr_freerect(rect);
   2461 	}
   2462 
   2463 	// Compute the delay until the next redraw as the minimum of the next
   2464 	// redraw delays for all rows.
   2465 	Milliseconds drawing_end_time = gr_now_ms();
   2466 	graphics_next_redraw_delay = INT_MAX;
   2467 	for (int row = 0; row < kv_size(next_redraw_times); ++row) {
   2468 		Milliseconds row_next_redraw = kv_A(next_redraw_times, row);
   2469 		if (row_next_redraw > 0) {
   2470 			int delay = MAX(graphics_animation_min_delay,
   2471 					row_next_redraw - drawing_end_time);
   2472 			graphics_next_redraw_delay =
   2473 				MIN(graphics_next_redraw_delay, delay);
   2474 		}
   2475 	}
   2476 
   2477 	// In debug mode display additional info.
   2478 	if (graphics_debug_mode) {
   2479 		int milliseconds = drawing_end_time - drawing_start_time;
   2480 
   2481 		Display *disp = imlib_context_get_display();
   2482 		GC gc = XCreateGC(disp, buf, 0, NULL);
   2483 		const char *debug_mode_str =
   2484 			graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES
   2485 				? "(boxes shown) "
   2486 				: "";
   2487 		int redraw_delay = graphics_next_redraw_delay == INT_MAX
   2488 					   ? -1
   2489 					   : graphics_next_redraw_delay;
   2490 		char info[MAX_INFO_LEN];
   2491 		snprintf(info, MAX_INFO_LEN,
   2492 			 "%sRender time: %d ms  ram %ld K  disk %ld K  count "
   2493 			 "%d  cell %dx%d  delay %d",
   2494 			 debug_mode_str, milliseconds, images_ram_size / 1024,
   2495 			 images_disk_size / 1024, kh_size(images), current_cw,
   2496 			 current_ch, redraw_delay);
   2497 		XSetForeground(disp, gc, 0xFF000000);
   2498 		XFillRectangle(disp, buf, gc, 0, 0, 600, 16);
   2499 		XSetForeground(disp, gc, 0xFFFFFFFF);
   2500 		XDrawString(disp, buf, gc, 0, 14, info, strlen(info));
   2501 		XFreeGC(disp, gc);
   2502 
   2503 		if (milliseconds > 0) {
   2504 			fprintf(stderr, "%s  (loaded %d files, %d pixmaps)\n",
   2505 				info, this_redraw_cycle_loaded_files,
   2506 				this_redraw_cycle_loaded_pixmaps);
   2507 		}
   2508 	}
   2509 
   2510 	// Check the limits in case we have used too much ram for placements.
   2511 	gr_check_limits();
   2512 }
   2513 
   2514 // Add an image rectangle to the list of rectangles to draw.
   2515 void gr_append_imagerect(Drawable buf, uint32_t image_id, uint32_t placement_id,
   2516 			 int img_start_col, int img_end_col, int img_start_row,
   2517 			 int img_end_row, int x_col, int y_row, int x_pix,
   2518 			 int y_pix, int cw, int ch, int reverse) {
   2519 	current_cw = cw;
   2520 	current_ch = ch;
   2521 
   2522 	ImageRect new_rect;
   2523 	new_rect.image_id = image_id;
   2524 	new_rect.placement_id = placement_id;
   2525 	new_rect.img_start_col = img_start_col;
   2526 	new_rect.img_end_col = img_end_col;
   2527 	new_rect.img_start_row = img_start_row;
   2528 	new_rect.img_end_row = img_end_row;
   2529 	new_rect.screen_y_row = y_row;
   2530 	new_rect.screen_x_pix = x_pix;
   2531 	new_rect.screen_y_pix = y_pix;
   2532 	new_rect.ch = ch;
   2533 	new_rect.cw = cw;
   2534 	new_rect.reverse = reverse;
   2535 
   2536 	// Display some red text in debug mode.
   2537 	if (graphics_debug_mode == GRAPHICS_DEBUG_LOG_AND_BOXES)
   2538 		gr_displayinfo(buf, &new_rect, 0xFF000000, 0xFFFF0000, "? ");
   2539 
   2540 	// If it's the empty image (image_id=0) or an empty rectangle, do
   2541 	// nothing.
   2542 	if (image_id == 0 || img_end_col - img_start_col <= 0 ||
   2543 	    img_end_row - img_start_row <= 0)
   2544 		return;
   2545 	// Try to find a rect to merge with.
   2546 	ImageRect *free_rect = NULL;
   2547 	for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) {
   2548 		ImageRect *rect = &image_rects[i];
   2549 		if (rect->image_id == 0) {
   2550 			if (!free_rect)
   2551 				free_rect = rect;
   2552 			continue;
   2553 		}
   2554 		if (rect->image_id != image_id ||
   2555 		    rect->placement_id != placement_id || rect->cw != cw ||
   2556 		    rect->ch != ch || rect->reverse != reverse)
   2557 			continue;
   2558 		// We only support the case when the new stripe is added to the
   2559 		// bottom of an existing rectangle and they are perfectly
   2560 		// aligned.
   2561 		if (rect->img_end_row == img_start_row &&
   2562 		    gr_getrectbottom(rect) == y_pix) {
   2563 			if (rect->img_start_col == img_start_col &&
   2564 			    rect->img_end_col == img_end_col &&
   2565 			    rect->screen_x_pix == x_pix) {
   2566 				rect->img_end_row = img_end_row;
   2567 				return;
   2568 			}
   2569 		}
   2570 	}
   2571 	// If we haven't merged the new rect with any existing rect, and there
   2572 	// is no free rect, we have to render one of the existing rects.
   2573 	if (!free_rect) {
   2574 		for (size_t i = 0; i < MAX_IMAGE_RECTS; ++i) {
   2575 			ImageRect *rect = &image_rects[i];
   2576 			if (!free_rect || gr_getrectbottom(free_rect) >
   2577 						  gr_getrectbottom(rect))
   2578 				free_rect = rect;
   2579 		}
   2580 		gr_drawimagerect(buf, free_rect);
   2581 		gr_freerect(free_rect);
   2582 	}
   2583 	// Start a new rectangle in `free_rect`.
   2584 	*free_rect = new_rect;
   2585 }
   2586 
   2587 /// Mark rows containing animations as dirty if it's time to redraw them. Must
   2588 /// be called right after `gr_start_drawing`.
   2589 void gr_mark_dirty_animations(int *dirty, int rows) {
   2590 	if (rows < kv_size(next_redraw_times))
   2591 		kv_size(next_redraw_times) = rows;
   2592 	if (rows * 2 < kv_max(next_redraw_times))
   2593 		kv_resize(Milliseconds, next_redraw_times, rows);
   2594 	for (int i = 0; i < MIN(rows, kv_size(next_redraw_times)); ++i) {
   2595 		if (dirty[i]) {
   2596 			kv_A(next_redraw_times, i) = 0;
   2597 			continue;
   2598 		}
   2599 		Milliseconds next_update = kv_A(next_redraw_times, i);
   2600 		if (next_update > 0 && next_update <= drawing_start_time) {
   2601 			dirty[i] = 1;
   2602 			kv_A(next_redraw_times, i) = 0;
   2603 		}
   2604 	}
   2605 }
   2606 
   2607 ////////////////////////////////////////////////////////////////////////////////
   2608 // Command parsing and handling.
   2609 ////////////////////////////////////////////////////////////////////////////////
   2610 
   2611 /// A parsed kitty graphics protocol command.
   2612 typedef struct {
   2613 	/// The command itself, without the 'G'.
   2614 	char *command;
   2615 	/// The payload (after ';').
   2616 	char *payload;
   2617 	/// 'a=', may be 't', 'q', 'f', 'T', 'p', 'd', 'a'.
   2618 	char action;
   2619 	/// 'q=', 1 to suppress OK response, 2 to suppress errors too.
   2620 	int quiet;
   2621 	/// 'f=', use 24 or 32 for raw pixel data, 100 to autodetect with
   2622 	/// imlib2. If 'f=0', will try to load with imlib2, then fallback to
   2623 	/// 32-bit pixel data.
   2624 	int format;
   2625 	/// 'o=', may be 'z' for RFC 1950 ZLIB.
   2626 	int compression;
   2627 	/// 't=', may be 'f', 't' or 'd'.
   2628 	char transmission_medium;
   2629 	/// 'd='
   2630 	char delete_specifier;
   2631 	/// 's=', 'v=', if 'a=t' or 'a=T', used only when 'f=24' or 'f=32'.
   2632 	/// When 'a=f', this is the size of the frame rectangle when composed on
   2633 	/// top of another frame.
   2634 	int frame_pix_width, frame_pix_height;
   2635 	/// 'x=', 'y=' - top-left corner of the source rectangle.
   2636 	int src_pix_x, src_pix_y;
   2637 	/// 'w=', 'h=' - width and height of the source rectangle.
   2638 	int src_pix_width, src_pix_height;
   2639 	/// 'r=', 'c='
   2640 	int rows, columns;
   2641 	/// 'i='
   2642 	uint32_t image_id;
   2643 	/// 'I='
   2644 	uint32_t image_number;
   2645 	/// 'p='
   2646 	uint32_t placement_id;
   2647 	/// 'm=', may be 0 or 1.
   2648 	int more;
   2649 	/// True if either 'm=0' or 'm=1' is specified.
   2650 	char is_data_transmission;
   2651 	/// True if turns out that this command is a continuation of a data
   2652 	/// transmission and not the first one for this image. Populated by
   2653 	/// `gr_handle_transmit_command`.
   2654 	char is_direct_transmission_continuation;
   2655 	/// 'S=', used to check the size of uploaded data.
   2656 	int size;
   2657 	/// 'U=', whether it's a virtual placement for Unicode placeholders.
   2658 	int virtual;
   2659 	/// 'C=', if true, do not move the cursor when displaying this placement
   2660 	/// (non-virtual placements only).
   2661 	char do_not_move_cursor;
   2662 	// ---------------------------------------------------------------------
   2663 	// Animation-related fields. Their keys often overlap with keys of other
   2664 	// commands, so these make sense only if the action is 'a=f' (frame
   2665 	// transmission) or 'a=a' (animation control).
   2666 	//
   2667 	// 'x=' and 'y=', the relative position of the frame image when it's
   2668 	// composed on top of another frame.
   2669 	int frame_dst_pix_x, frame_dst_pix_y;
   2670 	/// 'X=', 'X=1' to replace colors instead of alpha blending on top of
   2671 	/// the background color or frame.
   2672 	char replace_instead_of_blending;
   2673 	/// 'Y=', the background color in the 0xRRGGBBAA format (still
   2674 	/// transmitted as a decimal number).
   2675 	uint32_t background_color;
   2676 	/// (Only for 'a=f'). 'c=', the 1-based index of the background frame.
   2677 	int background_frame;
   2678 	/// (Only for 'a=a'). 'c=', sets the index of the current frame.
   2679 	int current_frame;
   2680 	/// 'r=', the 1-based index of the frame to edit.
   2681 	int edit_frame;
   2682 	/// 'z=', the duration of the frame. Zero if not specified, negative if
   2683 	/// the frame is gapless (i.e. skipped).
   2684 	int gap;
   2685 	/// (Only for 'a=a'). 's=', if non-zero, sets the state of the
   2686 	/// animation, 1 to stop, 2 to run in loading mode, 3 to loop.
   2687 	int animation_state;
   2688 	/// (Only for 'a=a'). 'v=', if non-zero, sets the number of times the
   2689 	/// animation will loop. 1 to loop infinitely, N to loop N-1 times.
   2690 	int loops;
   2691 } GraphicsCommand;
   2692 
   2693 /// Replaces all non-printed characters in `str` with '?' and truncates the
   2694 /// string to `max_size`, maybe inserting ellipsis at the end.
   2695 static void sanitize_str(char *str, size_t max_size) {
   2696 	assert(max_size >= 4);
   2697 	for (size_t i = 0; i < max_size; ++i) {
   2698 		unsigned c = str[i];
   2699 		if (c == '\0')
   2700 			return;
   2701 		if (c >= 128 || !isprint(c))
   2702 			str[i] = '?';
   2703 	}
   2704 	str[max_size - 1] = '\0';
   2705 	str[max_size - 2] = '.';
   2706 	str[max_size - 3] = '.';
   2707 	str[max_size - 4] = '.';
   2708 }
   2709 
   2710 /// A non-destructive version of `sanitize_str`. Uses a static buffer, so be
   2711 /// careful.
   2712 static const char *sanitized_filename(const char *str) {
   2713 	static char buf[MAX_FILENAME_SIZE];
   2714 	strncpy(buf, str, sizeof(buf));
   2715 	sanitize_str(buf, sizeof(buf));
   2716 	return buf;
   2717 }
   2718 
   2719 /// Creates a response to the current command in `graphics_command_result`.
   2720 static void gr_createresponse(uint32_t image_id, uint32_t image_number,
   2721 			      uint32_t placement_id, const char *msg) {
   2722 	if (!image_id && !image_number && !placement_id) {
   2723 		// Nobody expects the response in this case, so just print it to
   2724 		// stderr.
   2725 		fprintf(stderr,
   2726 			"error: No image id or image number or placement_id, "
   2727 			"but still there is a response: %s\n",
   2728 			msg);
   2729 		return;
   2730 	}
   2731 	char *buf = graphics_command_result.response;
   2732 	size_t maxlen = MAX_GRAPHICS_RESPONSE_LEN;
   2733 	size_t written;
   2734 	written = snprintf(buf, maxlen, "\033_G");
   2735 	buf += written;
   2736 	maxlen -= written;
   2737 	if (image_id) {
   2738 		written = snprintf(buf, maxlen, "i=%u,", image_id);
   2739 		buf += written;
   2740 		maxlen -= written;
   2741 	}
   2742 	if (image_number) {
   2743 		written = snprintf(buf, maxlen, "I=%u,", image_number);
   2744 		buf += written;
   2745 		maxlen -= written;
   2746 	}
   2747 	if (placement_id) {
   2748 		written = snprintf(buf, maxlen, "p=%u,", placement_id);
   2749 		buf += written;
   2750 		maxlen -= written;
   2751 	}
   2752 	buf[-1] = ';';
   2753 	written = snprintf(buf, maxlen, "%s\033\\", msg);
   2754 	buf += written;
   2755 	maxlen -= written;
   2756 	buf[-2] = '\033';
   2757 	buf[-1] = '\\';
   2758 }
   2759 
   2760 /// Creates the 'OK' response to the current command, unless suppressed or a
   2761 /// non-final data transmission.
   2762 static void gr_reportsuccess_cmd(GraphicsCommand *cmd) {
   2763 	if (cmd->quiet < 1 && !cmd->more)
   2764 		gr_createresponse(cmd->image_id, cmd->image_number,
   2765 				  cmd->placement_id, "OK");
   2766 }
   2767 
   2768 /// Creates the 'OK' response to the current command (unless suppressed).
   2769 static void gr_reportsuccess_frame(ImageFrame *frame) {
   2770 	uint32_t id = frame->image->query_id ? frame->image->query_id
   2771 					     : frame->image->image_id;
   2772 	if (frame->quiet < 1)
   2773 		gr_createresponse(id, frame->image->image_number,
   2774 				  frame->image->initial_placement_id, "OK");
   2775 }
   2776 
   2777 /// Creates an error response to the current command (unless suppressed).
   2778 static void gr_reporterror_cmd(GraphicsCommand *cmd, const char *format, ...) {
   2779 	char errmsg[MAX_GRAPHICS_RESPONSE_LEN];
   2780 	graphics_command_result.error = 1;
   2781 	va_list args;
   2782 	va_start(args, format);
   2783 	vsnprintf(errmsg, MAX_GRAPHICS_RESPONSE_LEN, format, args);
   2784 	va_end(args);
   2785 
   2786 	fprintf(stderr, "%s  in command: %s\n", errmsg, cmd->command);
   2787 	if (cmd->quiet < 2)
   2788 		gr_createresponse(cmd->image_id, cmd->image_number,
   2789 				  cmd->placement_id, errmsg);
   2790 }
   2791 
   2792 /// Creates an error response to the current command (unless suppressed).
   2793 static void gr_reporterror_frame(ImageFrame *frame, const char *format, ...) {
   2794 	char errmsg[MAX_GRAPHICS_RESPONSE_LEN];
   2795 	graphics_command_result.error = 1;
   2796 	va_list args;
   2797 	va_start(args, format);
   2798 	vsnprintf(errmsg, MAX_GRAPHICS_RESPONSE_LEN, format, args);
   2799 	va_end(args);
   2800 
   2801 	if (!frame) {
   2802 		fprintf(stderr, "%s\n", errmsg);
   2803 		gr_createresponse(0, 0, 0, errmsg);
   2804 	} else {
   2805 		uint32_t id = frame->image->query_id ? frame->image->query_id
   2806 						     : frame->image->image_id;
   2807 		fprintf(stderr, "%s  id=%u\n", errmsg, id);
   2808 		if (frame->quiet < 2)
   2809 			gr_createresponse(id, frame->image->image_number,
   2810 					  frame->image->initial_placement_id,
   2811 					  errmsg);
   2812 	}
   2813 }
   2814 
   2815 /// Loads an image and creates a success/failure response. Returns `frame`, or
   2816 /// NULL if it's a query action and the image was deleted.
   2817 static ImageFrame *gr_loadimage_and_report(ImageFrame *frame) {
   2818 	gr_load_imlib_object(frame);
   2819 	if (!frame->imlib_object) {
   2820 		gr_reporterror_frame(frame, "EBADF: could not load image");
   2821 	} else {
   2822 		gr_reportsuccess_frame(frame);
   2823 	}
   2824 	// If it was a query action, discard the image.
   2825 	if (frame->image->query_id) {
   2826 		gr_delete_image(frame->image);
   2827 		return NULL;
   2828 	}
   2829 	return frame;
   2830 }
   2831 
   2832 /// Creates an appropriate uploading failure response to the current command.
   2833 static void gr_reportuploaderror(ImageFrame *frame) {
   2834 	switch (frame->uploading_failure) {
   2835 	case 0:
   2836 		return;
   2837 	case ERROR_CANNOT_OPEN_CACHED_FILE:
   2838 		gr_reporterror_frame(frame,
   2839 				   "EIO: could not create a file for image");
   2840 		break;
   2841 	case ERROR_OVER_SIZE_LIMIT:
   2842 		gr_reporterror_frame(
   2843 			frame,
   2844 			"EFBIG: the size of the uploaded image exceeded "
   2845 			"the image size limit %u",
   2846 			graphics_max_single_image_file_size);
   2847 		break;
   2848 	case ERROR_UNEXPECTED_SIZE:
   2849 		gr_reporterror_frame(frame,
   2850 				   "EINVAL: the size of the uploaded image %u "
   2851 				   "doesn't match the expected size %u",
   2852 				   frame->disk_size, frame->expected_size);
   2853 		break;
   2854 	};
   2855 }
   2856 
   2857 /// Displays a non-virtual placement. This functions records the information in
   2858 /// `graphics_command_result`, the placeholder itself is created by the terminal
   2859 /// after handling the current command in the graphics module.
   2860 static void gr_display_nonvirtual_placement(ImagePlacement *placement) {
   2861 	if (placement->virtual)
   2862 		return;
   2863 	if (placement->image->first_frame.status < STATUS_RAM_LOADING_SUCCESS)
   2864 		return;
   2865 	// Infer the placement size if needed.
   2866 	gr_infer_placement_size_maybe(placement);
   2867 	// Populate the information about the placeholder which will be created
   2868 	// by the terminal.
   2869 	graphics_command_result.create_placeholder = 1;
   2870 	graphics_command_result.placeholder.image_id = placement->image->image_id;
   2871 	graphics_command_result.placeholder.placement_id = placement->placement_id;
   2872 	graphics_command_result.placeholder.columns = placement->cols;
   2873 	graphics_command_result.placeholder.rows = placement->rows;
   2874 	graphics_command_result.placeholder.do_not_move_cursor =
   2875 		placement->do_not_move_cursor;
   2876 	GR_LOG("Creating a placeholder for %u/%u  %d x %d\n",
   2877 	       placement->image->image_id, placement->placement_id,
   2878 	       placement->cols, placement->rows);
   2879 }
   2880 
   2881 /// Marks the rows that are occupied by the image as dirty.
   2882 static void gr_schedule_image_redraw(Image *img) {
   2883 	if (!img)
   2884 		return;
   2885 	gr_schedule_image_redraw_by_id(img->image_id);
   2886 }
   2887 
   2888 /// Appends data from `payload` to the frame `frame` when using direct
   2889 /// transmission. Note that we report errors only for the final command
   2890 /// (`!more`) to avoid spamming the client. If the frame is not specified, use
   2891 /// the image id and frame index we are currently uploading.
   2892 static void gr_append_data(ImageFrame *frame, const char *payload, int more) {
   2893 	if (!frame) {
   2894 		Image *img = gr_find_image(current_upload_image_id);
   2895 		frame = gr_get_frame(img, current_upload_frame_index);
   2896 		GR_LOG("Appending data to image %u frame %d\n",
   2897 		       current_upload_image_id, current_upload_frame_index);
   2898 		if (!img)
   2899 			GR_LOG("ERROR: this image doesn't exist\n");
   2900 		if (!frame)
   2901 			GR_LOG("ERROR: this frame doesn't exist\n");
   2902 	}
   2903 	if (!more) {
   2904 		current_upload_image_id = 0;
   2905 		current_upload_frame_index = 0;
   2906 	}
   2907 	if (!frame) {
   2908 		if (!more)
   2909 			gr_reporterror_frame(NULL, "ENOENT: could not find the "
   2910 						   "image to append data to");
   2911 		return;
   2912 	}
   2913 	if (frame->status != STATUS_UPLOADING) {
   2914 		if (!more)
   2915 			gr_reportuploaderror(frame);
   2916 		return;
   2917 	}
   2918 
   2919 	// Decode the data.
   2920 	size_t data_size = 0;
   2921 	char *data = gr_base64dec(payload, &data_size);
   2922 
   2923 	GR_LOG("appending %u + %zu = %zu bytes\n", frame->disk_size, data_size,
   2924 	       frame->disk_size + data_size);
   2925 
   2926 	// Do not append this data if the image exceeds the size limit.
   2927 	if (frame->disk_size + data_size >
   2928 		    graphics_max_single_image_file_size ||
   2929 	    frame->expected_size > graphics_max_single_image_file_size) {
   2930 		free(data);
   2931 		gr_delete_imagefile(frame);
   2932 		frame->uploading_failure = ERROR_OVER_SIZE_LIMIT;
   2933 		if (!more)
   2934 			gr_reportuploaderror(frame);
   2935 		return;
   2936 	}
   2937 
   2938 	// If there is no open file corresponding to the image, create it.
   2939 	if (!frame->open_file) {
   2940 		gr_make_sure_tmpdir_exists();
   2941 		char filename[MAX_FILENAME_SIZE];
   2942 		gr_get_frame_filename(frame, filename, MAX_FILENAME_SIZE);
   2943 		FILE *file = fopen(filename, frame->disk_size ? "a" : "w");
   2944 		if (!file) {
   2945 			frame->status = STATUS_UPLOADING_ERROR;
   2946 			frame->uploading_failure = ERROR_CANNOT_OPEN_CACHED_FILE;
   2947 			if (!more)
   2948 				gr_reportuploaderror(frame);
   2949 			return;
   2950 		}
   2951 		frame->open_file = file;
   2952 	}
   2953 
   2954 	// Write data to the file and update disk size variables.
   2955 	fwrite(data, 1, data_size, frame->open_file);
   2956 	free(data);
   2957 	frame->disk_size += data_size;
   2958 	frame->image->total_disk_size += data_size;
   2959 	images_disk_size += data_size;
   2960 	gr_touch_frame(frame);
   2961 
   2962 	if (more) {
   2963 		current_upload_image_id = frame->image->image_id;
   2964 		current_upload_frame_index = frame->index;
   2965 	} else {
   2966 		current_upload_image_id = 0;
   2967 		current_upload_frame_index = 0;
   2968 		// Close the file.
   2969 		if (frame->open_file) {
   2970 			fclose(frame->open_file);
   2971 			frame->open_file = NULL;
   2972 		}
   2973 		frame->status = STATUS_UPLOADING_SUCCESS;
   2974 		uint32_t placement_id = frame->image->default_placement;
   2975 		if (frame->expected_size &&
   2976 		    frame->expected_size != frame->disk_size) {
   2977 			// Report failure if the uploaded image size doesn't
   2978 			// match the expected size.
   2979 			frame->status = STATUS_UPLOADING_ERROR;
   2980 			frame->uploading_failure = ERROR_UNEXPECTED_SIZE;
   2981 			gr_reportuploaderror(frame);
   2982 		} else {
   2983 			// Make sure to redraw all existing image instances.
   2984 			gr_schedule_image_redraw(frame->image);
   2985 			// Try to load the image into ram and report the result.
   2986 			frame = gr_loadimage_and_report(frame);
   2987 			// If there is a non-virtual image placement, we may
   2988 			// need to display it.
   2989 			if (frame && frame->index == 1) {
   2990 				Image *img = frame->image;
   2991 				ImagePlacement *placement = NULL;
   2992 				kh_foreach_value(img->placements, placement, {
   2993 					gr_display_nonvirtual_placement(placement);
   2994 				});
   2995 			}
   2996 		}
   2997 	}
   2998 
   2999 	// Check whether we need to delete old images.
   3000 	gr_check_limits();
   3001 }
   3002 
   3003 /// Finds the image either by id or by number specified in the command and sets
   3004 /// the image_id of `cmd` if the image was found.
   3005 static Image *gr_find_image_for_command(GraphicsCommand *cmd) {
   3006 	if (cmd->image_id)
   3007 		return gr_find_image(cmd->image_id);
   3008 	Image *img = NULL;
   3009 	// If the image number is not specified, we can't find the image, unless
   3010 	// it's a put command, in which case we will try the last image.
   3011 	if (cmd->image_number == 0 && cmd->action == 'p')
   3012 		img = gr_find_image(last_image_id);
   3013 	else
   3014 		img = gr_find_image_by_number(cmd->image_number);
   3015 	if (img)
   3016 		cmd->image_id = img->image_id;
   3017 	return img;
   3018 }
   3019 
   3020 /// Creates a new image or a new frame in an existing image (depending on the
   3021 /// command's action) and initializes its parameters from the command.
   3022 static ImageFrame *gr_new_image_or_frame_from_command(GraphicsCommand *cmd) {
   3023 	if (cmd->format != 0 && cmd->format != 32 && cmd->format != 24 &&
   3024 	    cmd->compression != 0) {
   3025 		gr_reporterror_cmd(cmd, "EINVAL: compression is supported only "
   3026 					"for raw pixel data (f=32 or f=24)");
   3027 		// Even though we report an error, we still create an image.
   3028 	}
   3029 
   3030 	Image *img = NULL;
   3031 	if (cmd->action == 'f') {
   3032 		// If it's a frame transmission action, there must be an
   3033 		// existing image.
   3034 		img = gr_find_image_for_command(cmd);
   3035 		if (!img) {
   3036 			gr_reporterror_cmd(cmd, "ENOENT: image not found");
   3037 			return NULL;
   3038 		}
   3039 	} else {
   3040 		// Otherwise create a new image object. If the action is `q`,
   3041 		// we'll use random id instead of the one specified in the
   3042 		// command.
   3043 		uint32_t image_id = cmd->action == 'q' ? 0 : cmd->image_id;
   3044 		img = gr_new_image(image_id);
   3045 		if (!img)
   3046 			return NULL;
   3047 		if (cmd->action == 'q')
   3048 			img->query_id = cmd->image_id;
   3049 		else if (!cmd->image_id)
   3050 			cmd->image_id = img->image_id;
   3051 		// Set the image number.
   3052 		img->image_number = cmd->image_number;
   3053 	}
   3054 
   3055 	ImageFrame *frame = gr_append_new_frame(img);
   3056 	// Initialize the frame.
   3057 	frame->expected_size = cmd->size;
   3058 	frame->format = cmd->format;
   3059 	frame->compression = cmd->compression;
   3060 	frame->background_color = cmd->background_color;
   3061 	frame->background_frame_index = cmd->background_frame;
   3062 	frame->gap = cmd->gap;
   3063 	img->total_duration += frame->gap;
   3064 	frame->blend = !cmd->replace_instead_of_blending;
   3065 	frame->data_pix_width = cmd->frame_pix_width;
   3066 	frame->data_pix_height = cmd->frame_pix_height;
   3067 	if (cmd->action == 'f') {
   3068 		frame->x = cmd->frame_dst_pix_x;
   3069 		frame->y = cmd->frame_dst_pix_y;
   3070 	}
   3071 	// We save the quietness information in the frame because for direct
   3072 	// transmission subsequent transmission command won't contain this info.
   3073 	frame->quiet = cmd->quiet;
   3074 	return frame;
   3075 }
   3076 
   3077 /// Removes a file if it actually looks like a temporary file.
   3078 static void gr_delete_tmp_file(const char *filename) {
   3079 	if (strstr(filename, "tty-graphics-protocol") == NULL)
   3080 		return;
   3081 	if (strstr(filename, "/tmp/") != filename) {
   3082 		const char *tmpdir = getenv("TMPDIR");
   3083 		if (!tmpdir || !tmpdir[0] ||
   3084 		    strstr(filename, tmpdir) != filename)
   3085 			return;
   3086 	}
   3087 	unlink(filename);
   3088 }
   3089 
   3090 /// Handles a data transmission command.
   3091 static ImageFrame *gr_handle_transmit_command(GraphicsCommand *cmd) {
   3092 	// The default is direct transmission.
   3093 	if (!cmd->transmission_medium)
   3094 		cmd->transmission_medium = 'd';
   3095 
   3096 	// If neither id, nor image number is specified, and the transmission
   3097 	// medium is 'd' (or unspecified), and there is an active direct upload,
   3098 	// this is a continuation of the upload.
   3099 	if (current_upload_image_id != 0 && cmd->image_id == 0 &&
   3100 	    cmd->image_number == 0 && cmd->transmission_medium == 'd') {
   3101 		cmd->image_id = current_upload_image_id;
   3102 		GR_LOG("No images id is specified, continuing uploading %u\n",
   3103 		       cmd->image_id);
   3104 	}
   3105 
   3106 	ImageFrame *frame = NULL;
   3107 	if (cmd->transmission_medium == 'f' ||
   3108 	    cmd->transmission_medium == 't') {
   3109 		// File transmission.
   3110 		// Create a new image or a new frame of an existing image.
   3111 		frame = gr_new_image_or_frame_from_command(cmd);
   3112 		if (!frame)
   3113 			return NULL;
   3114 		last_image_id = frame->image->image_id;
   3115 		// Decode the filename.
   3116 		char *original_filename = gr_base64dec(cmd->payload, NULL);
   3117 		GR_LOG("Copying image %s\n",
   3118 		       sanitized_filename(original_filename));
   3119 		// Stat the file and check that it's a regular file and not too
   3120 		// big.
   3121 		struct stat st;
   3122 		int stat_res = stat(original_filename, &st);
   3123 		const char *stat_error = NULL;
   3124 		if (stat_res)
   3125 			stat_error = strerror(errno);
   3126 		else if (!S_ISREG(st.st_mode))
   3127 			stat_error = "Not a regular file";
   3128 		else if (st.st_size == 0)
   3129 			stat_error = "The size of the file is zero";
   3130 		else if (st.st_size > graphics_max_single_image_file_size)
   3131 			stat_error = "The file is too large";
   3132 		if (stat_error) {
   3133 			gr_reporterror_cmd(cmd,
   3134 					   "EBADF: %s", stat_error);
   3135 			fprintf(stderr, "Could not load the file %s\n",
   3136 				sanitized_filename(original_filename));
   3137 			frame->status = STATUS_UPLOADING_ERROR;
   3138 			frame->uploading_failure = ERROR_CANNOT_COPY_FILE;
   3139 		} else {
   3140 			gr_make_sure_tmpdir_exists();
   3141 			// Build the filename for the cached copy of the file.
   3142 			char cache_filename[MAX_FILENAME_SIZE];
   3143 			gr_get_frame_filename(frame, cache_filename,
   3144 					      MAX_FILENAME_SIZE);
   3145 			// We will create a symlink to the original file, and
   3146 			// then copy the file to the temporary cache dir. We do
   3147 			// this symlink trick mostly to be able to use cp for
   3148 			// copying, and avoid escaping file name characters when
   3149 			// calling system at the same time.
   3150 			char tmp_filename_symlink[MAX_FILENAME_SIZE + 4] = {0};
   3151 			strcat(tmp_filename_symlink, cache_filename);
   3152 			strcat(tmp_filename_symlink, ".sym");
   3153 			char command[MAX_FILENAME_SIZE + 256];
   3154 			size_t len =
   3155 				snprintf(command, MAX_FILENAME_SIZE + 255,
   3156 					 "cp '%s' '%s'", tmp_filename_symlink,
   3157 					 cache_filename);
   3158 			if (len > MAX_FILENAME_SIZE + 255 ||
   3159 			    symlink(original_filename, tmp_filename_symlink) ||
   3160 			    system(command) != 0) {
   3161 				gr_reporterror_cmd(cmd,
   3162 						   "EBADF: could not copy the "
   3163 						   "image to the cache dir");
   3164 				fprintf(stderr,
   3165 					"Could not copy the image "
   3166 					"%s (symlink %s) to %s",
   3167 					sanitized_filename(original_filename),
   3168 					tmp_filename_symlink, cache_filename);
   3169 				frame->status = STATUS_UPLOADING_ERROR;
   3170 				frame->uploading_failure = ERROR_CANNOT_COPY_FILE;
   3171 			} else {
   3172 				// Get the file size of the copied file.
   3173 				frame->status = STATUS_UPLOADING_SUCCESS;
   3174 				frame->disk_size = st.st_size;
   3175 				frame->image->total_disk_size += st.st_size;
   3176 				images_disk_size += frame->disk_size;
   3177 				if (frame->expected_size &&
   3178 				    frame->expected_size != frame->disk_size) {
   3179 					// The file has unexpected size.
   3180 					frame->status = STATUS_UPLOADING_ERROR;
   3181 					frame->uploading_failure =
   3182 						ERROR_UNEXPECTED_SIZE;
   3183 					gr_reportuploaderror(frame);
   3184 				} else {
   3185 					// Everything seems fine, try to load
   3186 					// and redraw existing instances.
   3187 					gr_schedule_image_redraw(frame->image);
   3188 					frame = gr_loadimage_and_report(frame);
   3189 				}
   3190 			}
   3191 			// Delete the symlink.
   3192 			unlink(tmp_filename_symlink);
   3193 			// Delete the original file if it's temporary.
   3194 			if (cmd->transmission_medium == 't')
   3195 				gr_delete_tmp_file(original_filename);
   3196 		}
   3197 		free(original_filename);
   3198 		gr_check_limits();
   3199 	} else if (cmd->transmission_medium == 'd') {
   3200 		// Direct transmission (default if 't' is not specified).
   3201 		frame = gr_get_last_frame(gr_find_image_for_command(cmd));
   3202 		if (frame && frame->status == STATUS_UPLOADING) {
   3203 			// This is a continuation of the previous transmission.
   3204 			cmd->is_direct_transmission_continuation = 1;
   3205 			gr_append_data(frame, cmd->payload, cmd->more);
   3206 			return frame;
   3207 		}
   3208 		// If no action is specified, it's not the first transmission
   3209 		// command. If we couldn't find the image, something went wrong
   3210 		// and we should just drop this command.
   3211 		if (cmd->action == 0)
   3212 			return NULL;
   3213 		// Otherwise create a new image or frame structure.
   3214 		frame = gr_new_image_or_frame_from_command(cmd);
   3215 		if (!frame)
   3216 			return NULL;
   3217 		last_image_id = frame->image->image_id;
   3218 		frame->status = STATUS_UPLOADING;
   3219 		// Start appending data.
   3220 		gr_append_data(frame, cmd->payload, cmd->more);
   3221 	} else {
   3222 		gr_reporterror_cmd(
   3223 			cmd,
   3224 			"EINVAL: transmission medium '%c' is not supported",
   3225 			cmd->transmission_medium);
   3226 		return NULL;
   3227 	}
   3228 
   3229 	return frame;
   3230 }
   3231 
   3232 /// Handles the 'put' command by creating a placement.
   3233 static void gr_handle_put_command(GraphicsCommand *cmd) {
   3234 	if (cmd->image_id == 0 && cmd->image_number == 0) {
   3235 		gr_reporterror_cmd(cmd,
   3236 				   "EINVAL: neither image id nor image number "
   3237 				   "are specified or both are zero");
   3238 		return;
   3239 	}
   3240 
   3241 	// Find the image with the id or number.
   3242 	Image *img = gr_find_image_for_command(cmd);
   3243 	if (!img) {
   3244 		gr_reporterror_cmd(cmd, "ENOENT: image not found");
   3245 		return;
   3246 	}
   3247 
   3248 	// Create a placement. If a placement with the same id already exists,
   3249 	// it will be deleted. If the id is zero, a random id will be generated.
   3250 	ImagePlacement *placement = gr_new_placement(img, cmd->placement_id);
   3251 	placement->virtual = cmd->virtual;
   3252 	placement->src_pix_x = cmd->src_pix_x;
   3253 	placement->src_pix_y = cmd->src_pix_y;
   3254 	placement->src_pix_width = cmd->src_pix_width;
   3255 	placement->src_pix_height = cmd->src_pix_height;
   3256 	placement->cols = cmd->columns;
   3257 	placement->rows = cmd->rows;
   3258 	placement->do_not_move_cursor = cmd->do_not_move_cursor;
   3259 
   3260 	if (placement->virtual) {
   3261 		placement->scale_mode = SCALE_MODE_CONTAIN;
   3262 	} else if (placement->cols && placement->rows) {
   3263 		// For classic placements the default is to stretch the image if
   3264 		// both cols and rows are specified.
   3265 		placement->scale_mode = SCALE_MODE_FILL;
   3266 	} else if (placement->cols || placement->rows) {
   3267 		// But if only one of them is specified, the default is to
   3268 		// contain.
   3269 		placement->scale_mode = SCALE_MODE_CONTAIN;
   3270 	} else {
   3271 		// If none of them are specified, the default is to use the
   3272 		// original size.
   3273 		placement->scale_mode = SCALE_MODE_NONE;
   3274 	}
   3275 
   3276 	// Display the placement unless it's virtual.
   3277 	gr_display_nonvirtual_placement(placement);
   3278 
   3279 	// Report success.
   3280 	gr_reportsuccess_cmd(cmd);
   3281 }
   3282 
   3283 /// Information about what to delete.
   3284 typedef struct DeletionData {
   3285 	uint32_t image_id;
   3286 	uint32_t placement_id;
   3287 	/// If true, delete the image object if there are no more placements.
   3288 	char delete_image_if_no_ref;
   3289 } DeletionData;
   3290 
   3291 /// The callback called for each cell to perform deletion.
   3292 static int gr_deletion_callback(void *data, uint32_t image_id,
   3293 					    uint32_t placement_id, int col,
   3294 					    int row, char is_classic) {
   3295 	DeletionData *del_data = data;
   3296 	// Leave unicode placeholders alone.
   3297 	if (!is_classic)
   3298 		return 0;
   3299 	if (del_data->image_id && del_data->image_id != image_id)
   3300 		return 0;
   3301 	if (del_data->placement_id && del_data->placement_id != placement_id)
   3302 		return 0;
   3303 	Image *img = gr_find_image(image_id);
   3304 	// If the image is already deleted, just erase the placeholder.
   3305 	if (!img)
   3306 		return 1;
   3307 	// Delete the placement.
   3308 	if (placement_id)
   3309 		gr_delete_placement(gr_find_placement(img, placement_id));
   3310 	// Delete the image if image deletion is requested (uppercase delete
   3311 	// specifier) and there are no more placements.
   3312 	if (del_data->delete_image_if_no_ref && kh_size(img->placements) == 0)
   3313 		gr_delete_image(img);
   3314 	return 1;
   3315 }
   3316 
   3317 /// Handles the delete command.
   3318 static void gr_handle_delete_command(GraphicsCommand *cmd) {
   3319 	DeletionData del_data = {0};
   3320 	del_data.delete_image_if_no_ref = isupper(cmd->delete_specifier) != 0;
   3321 	char d = tolower(cmd->delete_specifier);
   3322 
   3323 	if (d == 'n') {
   3324 		d = 'i';
   3325 		Image *img = gr_find_image_by_number(cmd->image_number);
   3326 		if (!img)
   3327 			return;
   3328 		del_data.image_id = img->image_id;
   3329 	}
   3330 
   3331 	if (!d || d == 'a') {
   3332 		// Delete all visible placements.
   3333 		gr_for_each_image_cell(gr_deletion_callback, &del_data);
   3334 	} else if (d == 'i') {
   3335 		// Delete the specified image by image id and maybe placement
   3336 		// id.
   3337 		if (!del_data.image_id)
   3338 			del_data.image_id = cmd->image_id;
   3339 		if (!del_data.image_id) {
   3340 			fprintf(stderr,
   3341 				"ERROR: image id is not specified in the "
   3342 				"delete command\n");
   3343 			return;
   3344 		}
   3345 		del_data.placement_id = cmd->placement_id;
   3346 		// NOTE: It's not very clear whether we should delete the image
   3347 		// even if there are no _visible_ placements to delete. We do
   3348 		// this because otherwise there is no way to delete an image
   3349 		// with virtual placements in one command.
   3350 		if (!del_data.placement_id && del_data.delete_image_if_no_ref)
   3351 			gr_delete_image(gr_find_image(cmd->image_id));
   3352 		gr_for_each_image_cell(gr_deletion_callback, &del_data);
   3353 	} else {
   3354 		fprintf(stderr,
   3355 			"WARNING: unsupported value of the d key: '%c'. The "
   3356 			"command is ignored.\n",
   3357 			cmd->delete_specifier);
   3358 	}
   3359 }
   3360 
   3361 static void gr_handle_animation_control_command(GraphicsCommand *cmd) {
   3362 	if (cmd->image_id == 0 && cmd->image_number == 0) {
   3363 		gr_reporterror_cmd(cmd,
   3364 				   "EINVAL: neither image id nor image number "
   3365 				   "are specified or both are zero");
   3366 		return;
   3367 	}
   3368 
   3369 	// Find the image with the id or number.
   3370 	Image *img = gr_find_image_for_command(cmd);
   3371 	if (!img) {
   3372 		gr_reporterror_cmd(cmd, "ENOENT: image not found");
   3373 		return;
   3374 	}
   3375 
   3376 	// Find the frame to edit, if requested.
   3377 	ImageFrame *frame = NULL;
   3378 	if (cmd->edit_frame)
   3379 		frame = gr_get_frame(img, cmd->edit_frame);
   3380 	if (cmd->edit_frame || cmd->gap) {
   3381 		if (!frame) {
   3382 			gr_reporterror_cmd(cmd, "ENOENT: frame %d not found",
   3383 					   cmd->edit_frame);
   3384 			return;
   3385 		}
   3386 		if (cmd->gap) {
   3387 			img->total_duration -= frame->gap;
   3388 			frame->gap = cmd->gap;
   3389 			img->total_duration += frame->gap;
   3390 		}
   3391 	}
   3392 
   3393 	// Set animation-related parameters of the image.
   3394 	if (cmd->current_frame)
   3395 		img->current_frame = cmd->current_frame;
   3396 	if (cmd->animation_state) {
   3397 		if (cmd->animation_state == 1) {
   3398 			img->animation_state = ANIMATION_STATE_STOPPED;
   3399 		} else if (cmd->animation_state == 2) {
   3400 			img->animation_state = ANIMATION_STATE_LOADING;
   3401 		} else if (cmd->animation_state == 3) {
   3402 			img->animation_state = ANIMATION_STATE_LOOPING;
   3403 		} else {
   3404 			gr_reporterror_cmd(
   3405 				cmd, "EINVAL: invalid animation state: %d",
   3406 				cmd->animation_state);
   3407 		}
   3408 	}
   3409 	// TODO: Set the number of loops to cmd->loops
   3410 
   3411 	// Make sure we redraw all instances of the image.
   3412 	gr_schedule_image_redraw(img);
   3413 }
   3414 
   3415 /// Handles a command.
   3416 static void gr_handle_command(GraphicsCommand *cmd) {
   3417 	if (!cmd->image_id && !cmd->image_number) {
   3418 		// If there is no image id or image number, nobody expects a
   3419 		// response, so set quiet to 2.
   3420 		cmd->quiet = 2;
   3421 	}
   3422 	ImageFrame *frame = NULL;
   3423 	switch (cmd->action) {
   3424 	case 0:
   3425 		// If no action is specified, it may be a data transmission
   3426 		// command if 'm=' is specified.
   3427 		if (cmd->is_data_transmission) {
   3428 			gr_handle_transmit_command(cmd);
   3429 			break;
   3430 		}
   3431 		gr_reporterror_cmd(cmd, "EINVAL: no action specified");
   3432 		break;
   3433 	case 't':
   3434 	case 'q':
   3435 	case 'f':
   3436 		// Transmit data. 'q' means query, which is basically the same
   3437 		// as transmit, but the image is discarded, and the id is fake.
   3438 		// 'f' appends a frame to an existing image.
   3439 		gr_handle_transmit_command(cmd);
   3440 		break;
   3441 	case 'p':
   3442 		// Display (put) the image.
   3443 		gr_handle_put_command(cmd);
   3444 		break;
   3445 	case 'T':
   3446 		// Transmit and display.
   3447 		frame = gr_handle_transmit_command(cmd);
   3448 		if (frame && !cmd->is_direct_transmission_continuation) {
   3449 			gr_handle_put_command(cmd);
   3450 			if (cmd->placement_id)
   3451 				frame->image->initial_placement_id =
   3452 					cmd->placement_id;
   3453 		}
   3454 		break;
   3455 	case 'd':
   3456 		gr_handle_delete_command(cmd);
   3457 		break;
   3458 	case 'a':
   3459 		gr_handle_animation_control_command(cmd);
   3460 		break;
   3461 	default:
   3462 		gr_reporterror_cmd(cmd, "EINVAL: unsupported action: %c",
   3463 				   cmd->action);
   3464 		return;
   3465 	}
   3466 }
   3467 
   3468 /// A partially parsed key-value pair.
   3469 typedef struct KeyAndValue {
   3470 	char *key_start;
   3471 	char *val_start;
   3472 	unsigned key_len, val_len;
   3473 } KeyAndValue;
   3474 
   3475 /// Parses the value of a key and assigns it to the appropriate field of `cmd`.
   3476 static void gr_set_keyvalue(GraphicsCommand *cmd, KeyAndValue *kv) {
   3477 	char *key_start = kv->key_start;
   3478 	char *key_end = key_start + kv->key_len;
   3479 	char *value_start = kv->val_start;
   3480 	char *value_end = value_start + kv->val_len;
   3481 	// Currently all keys are one-character.
   3482 	if (key_end - key_start != 1) {
   3483 		gr_reporterror_cmd(cmd, "EINVAL: unknown key of length %ld: %s",
   3484 				   key_end - key_start, key_start);
   3485 		return;
   3486 	}
   3487 	long num = 0;
   3488 	if (*key_start == 'a' || *key_start == 't' || *key_start == 'd' ||
   3489 	    *key_start == 'o') {
   3490 		// Some keys have one-character values.
   3491 		if (value_end - value_start != 1) {
   3492 			gr_reporterror_cmd(
   3493 				cmd,
   3494 				"EINVAL: value of 'a', 't' or 'd' must be a "
   3495 				"single char: %s",
   3496 				key_start);
   3497 			return;
   3498 		}
   3499 	} else {
   3500 		// All the other keys have integer values.
   3501 		char *num_end = NULL;
   3502 		num = strtol(value_start, &num_end, 10);
   3503 		if (num_end != value_end) {
   3504 			gr_reporterror_cmd(
   3505 				cmd, "EINVAL: could not parse number value: %s",
   3506 				key_start);
   3507 			return;
   3508 		}
   3509 	}
   3510 	switch (*key_start) {
   3511 	case 'a':
   3512 		cmd->action = *value_start;
   3513 		break;
   3514 	case 't':
   3515 		cmd->transmission_medium = *value_start;
   3516 		break;
   3517 	case 'd':
   3518 		cmd->delete_specifier = *value_start;
   3519 		break;
   3520 	case 'q':
   3521 		cmd->quiet = num;
   3522 		break;
   3523 	case 'f':
   3524 		cmd->format = num;
   3525 		if (num != 0 && num != 24 && num != 32 && num != 100) {
   3526 			gr_reporterror_cmd(
   3527 				cmd,
   3528 				"EINVAL: unsupported format specification: %s",
   3529 				key_start);
   3530 		}
   3531 		break;
   3532 	case 'o':
   3533 		cmd->compression = *value_start;
   3534 		if (cmd->compression != 'z') {
   3535 			gr_reporterror_cmd(cmd,
   3536 					   "EINVAL: unsupported compression "
   3537 					   "specification: %s",
   3538 					   key_start);
   3539 		}
   3540 		break;
   3541 	case 's':
   3542 		if (cmd->action == 'a')
   3543 			cmd->animation_state = num;
   3544 		else
   3545 			cmd->frame_pix_width = num;
   3546 		break;
   3547 	case 'v':
   3548 		if (cmd->action == 'a')
   3549 			cmd->loops = num;
   3550 		else
   3551 			cmd->frame_pix_height = num;
   3552 		break;
   3553 	case 'i':
   3554 		cmd->image_id = num;
   3555 		break;
   3556 	case 'I':
   3557 		cmd->image_number = num;
   3558 		break;
   3559 	case 'p':
   3560 		cmd->placement_id = num;
   3561 		break;
   3562 	case 'x':
   3563 		cmd->src_pix_x = num;
   3564 		cmd->frame_dst_pix_x = num;
   3565 		break;
   3566 	case 'y':
   3567 		if (cmd->action == 'f')
   3568 			cmd->frame_dst_pix_y = num;
   3569 		else
   3570 			cmd->src_pix_y = num;
   3571 		break;
   3572 	case 'w':
   3573 		cmd->src_pix_width = num;
   3574 		break;
   3575 	case 'h':
   3576 		cmd->src_pix_height = num;
   3577 		break;
   3578 	case 'c':
   3579 		if (cmd->action == 'f')
   3580 			cmd->background_frame = num;
   3581 		else if (cmd->action == 'a')
   3582 			cmd->current_frame = num;
   3583 		else
   3584 			cmd->columns = num;
   3585 		break;
   3586 	case 'r':
   3587 		if (cmd->action == 'f' || cmd->action == 'a')
   3588 			cmd->edit_frame = num;
   3589 		else
   3590 			cmd->rows = num;
   3591 		break;
   3592 	case 'm':
   3593 		cmd->is_data_transmission = 1;
   3594 		cmd->more = num;
   3595 		break;
   3596 	case 'S':
   3597 		cmd->size = num;
   3598 		break;
   3599 	case 'U':
   3600 		cmd->virtual = num;
   3601 		break;
   3602 	case 'X':
   3603 		if (cmd->action == 'f')
   3604 			cmd->replace_instead_of_blending = num;
   3605 		else
   3606 			break; /*ignore*/
   3607 		break;
   3608 	case 'Y':
   3609 		if (cmd->action == 'f')
   3610 			cmd->background_color = num;
   3611 		else
   3612 			break; /*ignore*/
   3613 		break;
   3614 	case 'z':
   3615 		if (cmd->action == 'f' || cmd->action == 'a')
   3616 			cmd->gap = num;
   3617 		else
   3618 			break; /*ignore*/
   3619 		break;
   3620 	case 'C':
   3621 		cmd->do_not_move_cursor = num;
   3622 		break;
   3623 	default:
   3624 		gr_reporterror_cmd(cmd, "EINVAL: unsupported key: %s",
   3625 				   key_start);
   3626 		return;
   3627 	}
   3628 }
   3629 
   3630 /// Parse and execute a graphics command. `buf` must start with 'G' and contain
   3631 /// at least `len + 1` characters. Returns 1 on success.
   3632 int gr_parse_command(char *buf, size_t len) {
   3633 	if (buf[0] != 'G')
   3634 		return 0;
   3635 
   3636 	memset(&graphics_command_result, 0, sizeof(GraphicsCommandResult));
   3637 
   3638 	global_command_counter++;
   3639 	GR_LOG("### Command %lu: %.80s\n", global_command_counter, buf);
   3640 
   3641 	// Eat the 'G'.
   3642 	++buf;
   3643 	--len;
   3644 
   3645 	GraphicsCommand cmd = {.command = buf};
   3646 	// The state of parsing. 'k' to parse key, 'v' to parse value, 'p' to
   3647 	// parse the payload.
   3648 	char state = 'k';
   3649 	// An array of partially parsed key-value pairs.
   3650 	KeyAndValue key_vals[32];
   3651 	unsigned key_vals_count = 0;
   3652 	char *key_start = buf;
   3653 	char *key_end = NULL;
   3654 	char *val_start = NULL;
   3655 	char *val_end = NULL;
   3656 	char *c = buf;
   3657 	while (c - buf < len + 1) {
   3658 		if (state == 'k') {
   3659 			switch (*c) {
   3660 			case ',':
   3661 			case ';':
   3662 			case '\0':
   3663 				state = *c == ',' ? 'k' : 'p';
   3664 				key_end = c;
   3665 				gr_reporterror_cmd(
   3666 					&cmd, "EINVAL: key without value: %s ",
   3667 					key_start);
   3668 				break;
   3669 			case '=':
   3670 				key_end = c;
   3671 				state = 'v';
   3672 				val_start = c + 1;
   3673 				break;
   3674 			default:
   3675 				break;
   3676 			}
   3677 		} else if (state == 'v') {
   3678 			switch (*c) {
   3679 			case ',':
   3680 			case ';':
   3681 			case '\0':
   3682 				state = *c == ',' ? 'k' : 'p';
   3683 				val_end = c;
   3684 				if (key_vals_count >=
   3685 				    sizeof(key_vals) / sizeof(*key_vals)) {
   3686 					gr_reporterror_cmd(&cmd,
   3687 							   "EINVAL: too many "
   3688 							   "key-value pairs");
   3689 					break;
   3690 				}
   3691 				key_vals[key_vals_count].key_start = key_start;
   3692 				key_vals[key_vals_count].val_start = val_start;
   3693 				key_vals[key_vals_count].key_len =
   3694 					key_end - key_start;
   3695 				key_vals[key_vals_count].val_len =
   3696 					val_end - val_start;
   3697 				++key_vals_count;
   3698 				key_start = c + 1;
   3699 				break;
   3700 			default:
   3701 				break;
   3702 			}
   3703 		} else if (state == 'p') {
   3704 			cmd.payload = c;
   3705 			// break out of the loop, we don't check the payload
   3706 			break;
   3707 		}
   3708 		++c;
   3709 	}
   3710 
   3711 	// Set the action key ('a=') first because we need it to disambiguate
   3712 	// some keys. Also set 'i=' and 'I=' for better error reporting.
   3713 	for (unsigned i = 0; i < key_vals_count; ++i) {
   3714 		if (key_vals[i].key_len == 1) {
   3715 			char *start = key_vals[i].key_start;
   3716 			if (*start == 'a' || *start == 'i' || *start == 'I') {
   3717 				gr_set_keyvalue(&cmd, &key_vals[i]);
   3718 				break;
   3719 			}
   3720 		}
   3721 	}
   3722 	// Set the rest of the keys.
   3723 	for (unsigned i = 0; i < key_vals_count; ++i)
   3724 		gr_set_keyvalue(&cmd, &key_vals[i]);
   3725 
   3726 	if (!cmd.payload)
   3727 		cmd.payload = buf + len;
   3728 
   3729 	if (cmd.payload && cmd.payload[0])
   3730 		GR_LOG("    payload size: %ld\n", strlen(cmd.payload));
   3731 
   3732 	if (!graphics_command_result.error)
   3733 		gr_handle_command(&cmd);
   3734 
   3735 	if (graphics_debug_mode) {
   3736 		fprintf(stderr, "Response: ");
   3737 		for (const char *resp = graphics_command_result.response;
   3738 		     *resp != '\0'; ++resp) {
   3739 			if (isprint(*resp))
   3740 				fprintf(stderr, "%c", *resp);
   3741 			else
   3742 				fprintf(stderr, "(0x%x)", *resp);
   3743 		}
   3744 		fprintf(stderr, "\n");
   3745 	}
   3746 
   3747 	// Make sure that we suppress response if needed. Usually cmd.quiet is
   3748 	// taken into account when creating the response, but it's not very
   3749 	// reliable in the current implementation.
   3750 	if (cmd.quiet) {
   3751 		if (!graphics_command_result.error || cmd.quiet >= 2)
   3752 			graphics_command_result.response[0] = '\0';
   3753 	}
   3754 
   3755 	return 1;
   3756 }
   3757 
   3758 ////////////////////////////////////////////////////////////////////////////////
   3759 // base64 decoding part is basically copied from st.c
   3760 ////////////////////////////////////////////////////////////////////////////////
   3761 
   3762 static const char gr_base64_digits[] = {
   3763 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3764 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3765 	0,  0,  0,  0,  0,  0,  0,  0,  0,  62, 0,  0,  0,  63, 52, 53, 54,
   3766 	55, 56, 57, 58, 59, 60, 61, 0,  0,  0,  -1, 0,  0,  0,  0,  1,  2,
   3767 	3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
   3768 	20, 21, 22, 23, 24, 25, 0,  0,  0,  0,  0,  0,  26, 27, 28, 29, 30,
   3769 	31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
   3770 	48, 49, 50, 51, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3771 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3772 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3773 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3774 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3775 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3776 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   3777 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
   3778 
   3779 static char gr_base64_getc(const char **src) {
   3780 	while (**src && !isprint(**src))
   3781 		(*src)++;
   3782 	return **src ? *((*src)++) : '='; /* emulate padding if string ends */
   3783 }
   3784 
   3785 char *gr_base64dec(const char *src, size_t *size) {
   3786 	size_t in_len = strlen(src);
   3787 	char *result, *dst;
   3788 
   3789 	result = dst = malloc((in_len + 3) / 4 * 3 + 1);
   3790 	while (*src) {
   3791 		int a = gr_base64_digits[(unsigned char)gr_base64_getc(&src)];
   3792 		int b = gr_base64_digits[(unsigned char)gr_base64_getc(&src)];
   3793 		int c = gr_base64_digits[(unsigned char)gr_base64_getc(&src)];
   3794 		int d = gr_base64_digits[(unsigned char)gr_base64_getc(&src)];
   3795 
   3796 		if (a == -1 || b == -1)
   3797 			break;
   3798 
   3799 		*dst++ = (a << 2) | ((b & 0x30) >> 4);
   3800 		if (c == -1)
   3801 			break;
   3802 		*dst++ = ((b & 0x0f) << 4) | ((c & 0x3c) >> 2);
   3803 		if (d == -1)
   3804 			break;
   3805 		*dst++ = ((c & 0x03) << 6) | d;
   3806 	}
   3807 	*dst = '\0';
   3808 	if (size) {
   3809 		*size = dst - result;
   3810 	}
   3811 	return result;
   3812 }