diff options
author | Harry Jeffery <harry@exec64.co.uk> | 2017-06-06 20:27:21 +0100 |
---|---|---|
committer | Harry Jeffery <harry@exec64.co.uk> | 2017-06-06 20:31:33 +0100 |
commit | eff4ee3fb359d747610ee706e904c8914841a6ba (patch) | |
tree | fb8cb483f1662930687dc376c99bbc764e251953 /src | |
parent | 508e6344711bebc9193774bcb0a4ea3eeb2a8071 (diff) | |
download | imv-eff4ee3fb359d747610ee706e904c8914841a6ba.tar.gz |
Switch to new implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 876 |
1 files changed, 11 insertions, 865 deletions
@@ -1,4 +1,4 @@ -/* Copyright (c) 2015 imv authors +/* Copyright (c) 2017 imv authors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -15,880 +15,26 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include <limits.h> -#include <stdio.h> -#include <stddef.h> -#include <stdint.h> -#include <unistd.h> -#include <SDL2/SDL.h> -#include <SDL2/SDL_ttf.h> -#include <FreeImage.h> -#include <getopt.h> -#include <ctype.h> -#include <poll.h> -#include <errno.h> - -#include "commands.h" -#include "list.h" -#include "loader.h" -#include "texture.h" -#include "navigator.h" -#include "viewport.h" -#include "util.h" - -enum scaling_mode { - NONE, - DOWN, - FULL -}; - -static const char *scaling_label[] = { - "actual size", - "best fit", - "perfect fit" -}; - -struct { - int fullscreen; - int stdin_list; - int recursive; - int scaling; - int nearest_neighbour; - int solid_bg; - int list; - unsigned long delay; - int cycle; - unsigned char bg_r; - unsigned char bg_g; - unsigned char bg_b; - int overlay; - const char *start_at; - const char *font; -} g_options = { - .fullscreen = 0, - .stdin_list = 0, - .recursive = 0, - .scaling = FULL, - .nearest_neighbour = 0, - .solid_bg = 1, - .list = 0, - .delay = 0, - .cycle = 1, - .bg_r = 0, - .bg_g = 0, - .bg_b = 0, - .overlay = 0, - .start_at = NULL, - .font = "Monospace:24", -}; - -struct { - struct imv_navigator *nav; - struct imv_loader *ldr; - struct imv_texture *tex; - struct imv_viewport *view; - struct imv_commands *cmds; - int quit; - - /* used to calculate when to skip to the next image in slideshow mode */ - unsigned long delay_msec; - - /* do we need to redraw the window? */ - int need_redraw; - int need_rescale; - - /* buffer for command input - NULL when not in command mode */ - char *command_buffer; -} g_state; - -void cmd_quit(struct imv_list *args, void *data); -void cmd_pan(struct imv_list *args, void *data); -void cmd_select_rel(struct imv_list *args, void *data); -void cmd_select_abs(struct imv_list *args, void *data); -void cmd_zoom(struct imv_list *args, void *data); -void cmd_remove(struct imv_list *args, void *data); -void cmd_fullscreen(struct imv_list *args, void *data); -void cmd_overlay(struct imv_list *args, void *data); - -static void parse_args(int *argc, char ***argv); -void handle_event(SDL_Event *event); -void render_window( - SDL_Window *window, - SDL_Renderer *renderer, - TTF_Font *text_font, - SDL_Texture *bg_texture); +#include "imv.h" int main(int argc, char** argv) { - g_state.cmds = imv_commands_create(); - imv_command_register(g_state.cmds, "quit", &cmd_quit); - imv_command_register(g_state.cmds, "pan", &cmd_pan); - imv_command_register(g_state.cmds, "select_rel", &cmd_select_rel); - imv_command_register(g_state.cmds, "select_abs", &cmd_select_abs); - imv_command_register(g_state.cmds, "zoom", &cmd_zoom); - imv_command_register(g_state.cmds, "remove", &cmd_remove); - imv_command_register(g_state.cmds, "fullscreen", &cmd_fullscreen); - imv_command_register(g_state.cmds, "overlay", &cmd_overlay); - - imv_command_alias(g_state.cmds, "q", "quit"); - imv_command_alias(g_state.cmds, "next", "select_rel 1"); - imv_command_alias(g_state.cmds, "previous", "select_rel -1"); - imv_command_alias(g_state.cmds, "n", "select_rel 1"); - imv_command_alias(g_state.cmds, "p", "select_rel -1"); - - g_state.nav = imv_navigator_create(); - - /* parse any command line options given */ - parse_args(&argc, &argv); - - /* if no names are given, expect them on stdin */ - if(argc == 0) { - g_options.stdin_list = 1; - } - - /* if the user asked to load paths from stdin, set up poll(2)ing and read - the first path */ - struct pollfd rfds[1]; - if(g_options.stdin_list) { - rfds[0].fd = STDIN_FILENO; - rfds[0].events = POLLIN; - fprintf(stderr, "Reading paths from stdin..."); - - char buf[PATH_MAX]; - char *stdin_ok; - while((stdin_ok = fgets(buf, sizeof(buf), stdin)) != NULL) { - size_t len = strlen(buf); - if(buf[len-1] == '\n') { - buf[--len] = 0; - } - if(len > 0) { - if(imv_navigator_add(g_state.nav, buf, g_options.recursive) != 0) { - imv_navigator_free(g_state.nav); - exit(1); - } - break; - } - } - if(!stdin_ok) { - fprintf(stderr, " no input!\n"); - return -1; - } - fprintf(stderr, "\n"); - } - - void *stdin_buffer = NULL; - size_t stdin_buffer_size = 0; - int stdin_error = 0; - - /* handle any image paths given as arguments */ - for(int i = 0; i < argc; ++i) { - - /* special case: '-' means load raw image data from stdin */ - if(!strcmp("-",argv[i])) { - /* did we already load data from stdin? */ - if (stdin_buffer) { - fprintf(stderr, "Can't read from stdin twice\n"); - imv_navigator_free(g_state.nav); - exit(1); - } - /* actually load the data from stdin */ - stdin_buffer_size = read_from_stdin(&stdin_buffer); - if (stdin_buffer_size == 0) { - perror(NULL); - continue; /* we can't recover from the freed buffer, just ignore it */ - } - stdin_error = errno; - errno = 0; /* clear errno */ - } - /* add the given path to the list to load */ - if(imv_navigator_add(g_state.nav, argv[i], g_options.recursive) != 0) { - imv_navigator_free(g_state.nav); - exit(1); - } - } - - /* if we weren't given any paths we have nothing to view. exit */ - if(!imv_navigator_selection(g_state.nav)) { - fprintf(stderr, "No input files. Exiting.\n"); - imv_navigator_free(g_state.nav); - exit(1); - } - - /* go to the chosen starting image if possible */ - if(g_options.start_at) { - int start_index = imv_navigator_find_path(g_state.nav, g_options.start_at); - if(start_index < 0) { - start_index = strtol(g_options.start_at,NULL,10) - 1; - } - imv_navigator_select_str(g_state.nav, start_index); - } - - /* we've got something to display, so create an SDL window */ - if(SDL_Init(SDL_INIT_VIDEO) != 0) { - fprintf(stderr, "SDL Failed to Init: %s\n", SDL_GetError()); - imv_navigator_free(g_state.nav); - exit(1); - } - - /* width and height arbitrarily chosen. Perhaps there's a smarter way to - * set this */ - const int width = 1280; - const int height = 720; - - SDL_Window *window = SDL_CreateWindow( - "imv", - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - width, height, - SDL_WINDOW_RESIZABLE); - if(!window) { - fprintf(stderr, "SDL Failed to create window: %s\n", SDL_GetError()); - imv_navigator_free(g_state.nav); - SDL_Quit(); - exit(1); - } - - /* we'll use SDL's built-in renderer, hardware accelerated if possible */ - SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); - if(!renderer) { - fprintf(stderr, "SDL Failed to create renderer: %s\n", SDL_GetError()); - imv_navigator_free(g_state.nav); - SDL_DestroyWindow(window); - SDL_Quit(); - exit(1); - } - - /* use the appropriate resampling method */ - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, - g_options.nearest_neighbour ? "0" : "1"); - - /* construct a chequered background texture */ - SDL_Texture *chequered_tex = NULL; - if(!g_options.solid_bg) { - chequered_tex = create_chequered(renderer); - } - - /* set up the required fonts and surfaces for displaying the overlay */ - TTF_Init(); - TTF_Font *font = load_font(g_options.font); - if(!font) { - fprintf(stderr, "Error loading font: %s\n", TTF_GetError()); - } - - /* create our main classes */ - g_state.ldr = imv_loader_create(); - g_state.tex = imv_texture_create(renderer); - g_state.view = imv_viewport_create(window); - - /* put us in fullscren mode to begin with if requested */ - if(g_options.fullscreen) { - imv_viewport_toggle_fullscreen(g_state.view); - } - - /* help keeping track of time */ - unsigned int last_time = SDL_GetTicks(); - unsigned int current_time; - - g_state.need_redraw = 1; - g_state.need_rescale = 0; - - /* keep title buffer around for reuse */ - char title[256]; - - g_state.delay_msec = 0; - - /* start outside of command mode */ - g_state.command_buffer = NULL; - SDL_StopTextInput(); - - /* initialize variables holding image dimentions */ - int iw = 0, ih = 0; - - g_state.quit = 0; - while(!g_state.quit) { - /* handle any input/window events sent by SDL */ - SDL_Event e; - while(!g_state.quit && SDL_PollEvent(&e)) { - handle_event(&e); - } - - /* if we're quitting, don't bother drawing any more images */ - if(g_state.quit) { - break; - } - - /* check if an image failed to load, if so, remove it from our image list */ - char *err_path = imv_loader_get_error(g_state.ldr); - if(err_path) { - imv_navigator_remove(g_state.nav, err_path); - - /* special case: the image came from stdin */ - if (strncmp(err_path, "-", 2) == 0) { - free(stdin_buffer); - stdin_buffer_size = 0; - if (stdin_error != 0) { - errno = stdin_error; - perror("Failed to load image from standard input"); - errno = 0; - } - } - free(err_path); - } - - /* Check if navigator wrapped around paths lists */ - if(!g_options.cycle && imv_navigator_wrapped(g_state.nav)) { - break; - } - - /* if the user has changed image, start loading the new one */ - if(imv_navigator_poll_changed(g_state.nav)) { - const char *current_path = imv_navigator_selection(g_state.nav); - if(!current_path) { - if(!g_options.stdin_list) { - fprintf(stderr, "No input files left. Exiting.\n"); - g_state.quit = 1; - } - continue; - } - - snprintf(title, sizeof(title), "imv - [%i/%i] [LOADING] %s [%s]", - g_state.nav->cur_path + 1, g_state.nav->num_paths, current_path, - scaling_label[g_options.scaling]); - imv_viewport_set_title(g_state.view, title); - - imv_loader_load(g_state.ldr, current_path, stdin_buffer, stdin_buffer_size); - g_state.view->playing = 1; - } - - - /* check if a new image is available to display */ - FIBITMAP *bmp; - int is_new_image; - if(imv_loader_get_image(g_state.ldr, &bmp, &is_new_image)) { - imv_texture_set_image(g_state.tex, bmp); - iw = FreeImage_GetWidth(bmp); - ih = FreeImage_GetHeight(bmp); - FreeImage_Unload(bmp); - g_state.need_redraw = 1; - g_state.need_rescale += is_new_image; - } - - if(g_state.need_rescale) { - int ww, wh; - SDL_GetWindowSize(window, &ww, &wh); - - g_state.need_rescale = 0; - if(g_options.scaling == NONE || - (g_options.scaling == DOWN && ww > iw && wh > ih)) { - imv_viewport_scale_to_actual(g_state.view, g_state.tex); - } else { - imv_viewport_scale_to_window(g_state.view, g_state.tex); - } - } - - current_time = SDL_GetTicks(); - - /* if we're playing an animated gif, tell the loader how much time has - * passed */ - if(g_state.view->playing) { - unsigned int dt = current_time - last_time; - /* We cap the delta-time to 100 ms so that if imv is asleep for several - * seconds or more (e.g. suspended), upon waking up it doesn't try to - * catch up all the time it missed by playing through the gif quickly. */ - if(dt > 100) { - dt = 100; - } - imv_loader_time_passed(g_state.ldr, dt / 1000.0); - } - - /* handle slideshow */ - if(g_options.delay) { - unsigned int dt = current_time - last_time; - - g_state.delay_msec += dt; - g_state.need_redraw = 1; - if(g_state.delay_msec >= g_options.delay) { - imv_navigator_select_rel(g_state.nav, 1); - g_state.delay_msec = 0; - } - } - - last_time = current_time; - - /* check if the viewport needs a redraw */ - if(imv_viewport_needs_redraw(g_state.view)) { - g_state.need_redraw = 1; - } - - /* only redraw when something's changed */ - if(g_state.need_redraw) { - render_window(window, renderer, font, chequered_tex); - /* tell SDL to show the newly drawn frame */ - SDL_RenderPresent(renderer); - } - - /* try to read some more paths from stdin */ - if(g_options.stdin_list) { - if(poll(rfds, 1, 10) != 1 || rfds[0].revents & (POLLERR|POLLNVAL)) { - fprintf(stderr, "error polling stdin"); - return 1; - } - if(rfds[0].revents & (POLLIN|POLLHUP)) { - char buf[PATH_MAX]; - if(fgets(buf, sizeof(buf), stdin) == NULL && ferror(stdin)) { - clearerr(stdin); - continue; - } - if(feof(stdin)) { - g_options.stdin_list = 0; - fprintf(stderr, "done with stdin\n"); - continue; - } - - size_t len = strlen(buf); - if(buf[len-1] == '\n') { - buf[--len] = 0; - } - if(len > 0) { - if(imv_navigator_add(g_state.nav, buf, g_options.recursive)) { - break; - } - g_state.need_redraw = 1; - } - } - } else { - /* sleep a little bit so we don't waste CPU time */ - SDL_Delay(10); - } - } - while(g_options.list) { - const char *path = imv_navigator_selection(g_state.nav); - if(!path) { - break; - } - fprintf(stdout, "%s\n", path); - imv_navigator_remove(g_state.nav, path); - } - - /* clean up our resources now that we're exiting */ - if(g_state.command_buffer) { - free(g_state.command_buffer); - } - - imv_loader_free(g_state.ldr); - imv_texture_free(g_state.tex); - imv_navigator_free(g_state.nav); - imv_viewport_free(g_state.view); - imv_commands_free(g_state.cmds); - - if(font) { - TTF_CloseFont(font); - } - TTF_Quit(); - if(chequered_tex) { - SDL_DestroyTexture(chequered_tex); - } - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - SDL_Quit(); - - return 0; -} - -void cmd_quit(struct imv_list *args, void *data) -{ - (void)args; - (void)data; - g_state.quit = 1; -} + struct imv *imv = imv_create(); -void cmd_pan(struct imv_list *args, void *data) -{ - (void)data; - if(args->len != 3) { - return; + if(!imv) { + return 1; } - long int x = strtol(args->items[1], NULL, 10); - long int y = strtol(args->items[2], NULL, 10); - - imv_viewport_move(g_state.view, x, y); -} - -void cmd_select_rel(struct imv_list *args, void *data) -{ - (void)data; - if(args->len != 2) { - return; + if(!imv_parse_args(imv, argc, argv)) { + imv_free(imv); + return 1; } - long int index = strtol(args->items[1], NULL, 10); - imv_navigator_select_rel(g_state.nav, index); - - /* reset slideshow delay */ - g_state.delay_msec = 0; -} - -void cmd_select_abs(struct imv_list *args, void *data) -{ - (void)args; - (void)data; -} - -void cmd_zoom(struct imv_list *args, void *data) -{ - (void)args; - (void)data; -} - -void cmd_remove(struct imv_list *args, void *data) -{ - (void)args; - (void)data; - char* path = strdup(imv_navigator_selection(g_state.nav)); - imv_navigator_remove(g_state.nav, path); - free(path); - - /* reset slideshow delay */ - g_state.delay_msec = 0; -} - -void cmd_fullscreen(struct imv_list *args, void *data) -{ - (void)args; - (void)data; - imv_viewport_toggle_fullscreen(g_state.view); -} + int ret = imv_run(imv); -void cmd_overlay(struct imv_list *args, void *data) -{ - (void)args; - (void)data; - g_options.overlay = !g_options.overlay; - g_state.need_redraw = 1; -} - -static void print_usage(void) -{ - fprintf(stdout, - "imv %s\n" - "See manual for usage information.\n" - "\n" - "Legal:\n" - "This program is free software; you can redistribute it and/or\n" - "modify it under the terms of the GNU General Public License\n" - "as published by the Free Software Foundation; either version 2\n" - "of the License, or (at your option) any later version.\n" - "\n" - "This software uses the FreeImage open source image library.\n" - "See http://freeimage.sourceforge.net for details.\n" - "FreeImage is used under the GNU GPLv2.\n" - , IMV_VERSION); -} - -static void parse_args(int *argc, char ***argv) -{ - /* Do not print getopt errors */ - opterr = 0; - - char *argp, *ep = **argv; - int o; - - while((o = getopt(*argc, *argv, "firasSudxhln:b:e:t:")) != -1) { - switch(o) { - case 'f': g_options.fullscreen = 1; break; - case 'i': - g_options.stdin_list = 1; - fprintf(stderr, "Warning: '-i' is deprecated. No flag is needed.\n"); - break; - case 'r': g_options.recursive = 1; break; - case 'a': g_options.scaling = NONE; break; - case 's': g_options.scaling = DOWN; break; - case 'S': g_options.scaling = FULL; break; - case 'u': g_options.nearest_neighbour = 1; break; - case 'd': g_options.overlay = 1; break; - case 'x': g_options.cycle = 0; break; - case 'h': print_usage(); exit(0); break; - case 'l': g_options.list = 1; break; - case 'n': - g_options.start_at = optarg; - break; - case 'b': - if(strcmp("checks", optarg) == 0) { - g_options.solid_bg = 0; - } else { - g_options.solid_bg = 1; - argp = (*optarg == '#') ? optarg + 1 : optarg; - uint32_t n = strtoul(argp, &ep, 16); - if(*ep != '\0' || ep - argp != 6 || n > 0xFFFFFF) { - fprintf(stderr, "Invalid hex color: '%s'\n", optarg); - exit(1); - } - g_options.bg_b = n & 0xFF; - g_options.bg_g = (n >> 8) & 0xFF; - g_options.bg_r = (n >> 16); - } - break; - case 'e': - g_options.font = optarg; - break; - case 't': - g_options.delay = strtoul(optarg, &argp, 10); - g_options.delay *= 1000; - if (*argp == '.') { - long delay = strtoul(++argp, &ep, 10); - for (int i = 3 - (ep - argp); i; i--) { - delay *= 10; - } - if (delay < 1000) { - g_options.delay += delay; - } else { - g_options.delay = ULONG_MAX; - } - } - if (g_options.delay == ULONG_MAX) { - fprintf(stderr, "Wrong slideshow delay '%s'. Aborting.\n", optarg); - exit(1); - } - break; - case '?': - fprintf(stderr, "Unknown argument '%c'. Aborting.\n", optopt); - exit(1); - } - } - - *argc -= optind; - *argv += optind; -} - - -void handle_event(SDL_Event *event) -{ - const int command_buffer_len = 1024; - switch(event->type) { - case SDL_QUIT: - imv_command_exec(g_state.cmds, "quit", NULL); - break; - - case SDL_TEXTINPUT: - strncat(g_state.command_buffer, event->text.text, command_buffer_len - 1); - g_state.need_redraw = 1; - break; - - case SDL_KEYDOWN: - SDL_ShowCursor(SDL_DISABLE); - - if(g_state.command_buffer) { - /* in command mode, update the buffer */ - if(event->key.keysym.sym == SDLK_ESCAPE) { - SDL_StopTextInput(); - free(g_state.command_buffer); - g_state.command_buffer = NULL; - g_state.need_redraw = 1; - } else if(event->key.keysym.sym == SDLK_RETURN) { - imv_command_exec(g_state.cmds, g_state.command_buffer, NULL); - SDL_StopTextInput(); - free(g_state.command_buffer); - g_state.command_buffer = NULL; - g_state.need_redraw = 1; - } else if(event->key.keysym.sym == SDLK_BACKSPACE) { - const size_t len = strlen(g_state.command_buffer); - if(len > 0) { - g_state.command_buffer[len - 1] = '\0'; - g_state.need_redraw = 1; - } - } - - return; - } - - switch (event->key.keysym.sym) { - case SDLK_SEMICOLON: - if(event->key.keysym.mod & KMOD_SHIFT) { - SDL_StartTextInput(); - g_state.command_buffer = malloc(command_buffer_len); - g_state.command_buffer[0] = '\0'; - g_state.need_redraw = 1; - } - break; - case SDLK_q: - imv_command_exec(g_state.cmds, "quit", NULL); - break; - case SDLK_LEFTBRACKET: - case SDLK_LEFT: - imv_command_exec(g_state.cmds, "select_rel -1", NULL); - break; - case SDLK_RIGHTBRACKET: - case SDLK_RIGHT: - imv_command_exec(g_state.cmds, "select_rel 1", NULL); - break; - case SDLK_EQUALS: - case SDLK_PLUS: - case SDLK_i: - case SDLK_UP: - imv_viewport_zoom(g_state.view, g_state.tex, IMV_ZOOM_KEYBOARD, 1); - break; - case SDLK_MINUS: - case SDLK_o: - case SDLK_DOWN: - imv_viewport_zoom(g_state.view, g_state.tex, IMV_ZOOM_KEYBOARD, -1); - break; - case SDLK_s: - if(!event->key.repeat) { - if((g_options.scaling += 1) > FULL) { - g_options.scaling = NONE; - } - } - /* FALLTHROUGH */ - case SDLK_r: - if(!event->key.repeat) { - g_state.need_rescale = 1; - g_state.need_redraw = 1; - } - break; - case SDLK_a: - if(!event->key.repeat) { - imv_viewport_scale_to_actual(g_state.view, g_state.tex); - } - break; - case SDLK_c: - if(!event->key.repeat) { - imv_viewport_center(g_state.view, g_state.tex); - } - break; - case SDLK_j: - imv_command_exec(g_state.cmds, "pan 0 -50", NULL); - break; - case SDLK_k: - imv_command_exec(g_state.cmds, "pan 0 50", NULL); - break; - case SDLK_h: - imv_command_exec(g_state.cmds, "pan 50 0", NULL); - break; - case SDLK_l: - imv_command_exec(g_state.cmds, "pan -50 0", NULL); - break; - case SDLK_x: - if(!event->key.repeat) { - imv_command_exec(g_state.cmds, "remove", NULL); - } - break; - case SDLK_f: - if(!event->key.repeat) { - imv_command_exec(g_state.cmds, "fullscreen", NULL); - } - break; - case SDLK_PERIOD: - imv_loader_load_next_frame(g_state.ldr); - break; - case SDLK_SPACE: - if(!event->key.repeat) { - imv_viewport_toggle_playing(g_state.view); - } - break; - case SDLK_p: - if(!event->key.repeat) { - puts(imv_navigator_selection(g_state.nav)); - } - break; - case SDLK_d: - if(!event->key.repeat) { - imv_command_exec(g_state.cmds, "overlay", NULL); - } - break; - case SDLK_t: - if(event->key.keysym.mod & (KMOD_SHIFT|KMOD_CAPS)) { - if(g_options.delay >= 1000) { - g_options.delay -= 1000; - } - } else { - g_options.delay += 1000; - } - g_state.need_redraw = 1; - break; - } - break; - case SDL_MOUSEWHEEL: - imv_viewport_zoom(g_state.view, g_state.tex, IMV_ZOOM_MOUSE, event->wheel.y); - SDL_ShowCursor(SDL_ENABLE); - break; - case SDL_MOUSEMOTION: - if(event->motion.state & SDL_BUTTON_LMASK) { - imv_viewport_move(g_state.view, event->motion.xrel, event->motion.yrel); - } - SDL_ShowCursor(SDL_ENABLE); - break; - case SDL_WINDOWEVENT: - imv_viewport_update(g_state.view, g_state.tex); - break; - } -} - -void render_window( - SDL_Window *window, - SDL_Renderer *renderer, - TTF_Font *text_font, - SDL_Texture *bg_texture) -{ - char title[1024]; - int ww, wh; - SDL_GetWindowSize(window, &ww, &wh); - - /* update window title */ - const char *current_path = imv_navigator_selection(g_state.nav); - int len = snprintf(title, sizeof(title), "imv - [%i/%i] [%ix%i] [%.2f%%] %s [%s]", - g_state.nav->cur_path + 1, g_state.nav->num_paths, g_state.tex->width, g_state.tex->height, - 100.0 * g_state.view->scale, - current_path, scaling_label[g_options.scaling]); - if(g_options.delay >= 1000) { - len += snprintf(title + len, sizeof(title) - len, "[%lu/%lus]", - g_state.delay_msec / 1000 + 1, g_options.delay / 1000); - } - imv_viewport_set_title(g_state.view, title); - - /* first we draw the background */ - if(g_options.solid_bg) { - /* solid background */ - SDL_SetRenderDrawColor(renderer, - g_options.bg_r, g_options.bg_g, g_options.bg_b, 255); - SDL_RenderClear(renderer); - } else { - /* background */ - int img_w, img_h; - SDL_QueryTexture(bg_texture, NULL, NULL, &img_w, &img_h); - /* tile the texture so it fills the window */ - for(int y = 0; y < wh; y += img_h) { - for(int x = 0; x < ww; x += img_w) { - SDL_Rect dst_rect = {x,y,img_w,img_h}; - SDL_RenderCopy(renderer, bg_texture, NULL, &dst_rect); - } - } - } - - /* draw our actual texture */ - imv_texture_draw(g_state.tex, g_state.view->x, g_state.view->y, g_state.view->scale); - - /* if the overlay needs to be drawn, draw that too */ - if(g_options.overlay && text_font) { - SDL_Color fg = {255,255,255,255}; - SDL_Color bg = {0,0,0,160}; - imv_printf(renderer, text_font, 0, 0, &fg, &bg, "%s", - title + strlen("imv - ")); - } - - /* draw command entry bar if needed */ - if(g_state.command_buffer && text_font) { - SDL_Color fg = {255,255,255,255}; - SDL_Color bg = {0,0,0,160}; - imv_printf(renderer, - text_font, - 0, wh - TTF_FontHeight(text_font), - &fg, &bg, - ":%s", g_state.command_buffer); - } + imv_free(imv); - /* redraw complete, unset the flag */ - g_state.need_redraw = 0; + return ret; } /* vim:set ts=2 sts=2 sw=2 et: */ |