From 66e6f2edc4abe7ef1ac33e0707b860568f59296b Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Wed, 12 Apr 2017 22:00:49 +0100 Subject: Move basic functionality into commands --- src/main.c | 322 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 200 insertions(+), 122 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 1e3df67..8a5ba78 100644 --- a/src/main.c +++ b/src/main.c @@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include +#include "commands.h" +#include "list.h" #include "loader.h" #include "texture.h" #include "navigator.h" @@ -170,10 +172,44 @@ static void parse_args(int argc, char** argv) } } +struct { + struct imv_navigator nav; + struct imv_loader ldr; + struct imv_texture tex; + struct imv_viewport view; + SDL_Window *window; + SDL_Renderer *renderer; + 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; +} g_state; + +void cmd_quit(struct imv_list *args); +void cmd_pan(struct imv_list *args); +void cmd_select_rel(struct imv_list *args); +void cmd_select_abs(struct imv_list *args); +void cmd_zoom(struct imv_list *args); +void cmd_remove(struct imv_list *args); +void cmd_fullscreen(struct imv_list *args); +void cmd_overlay(struct imv_list *args); + int main(int argc, char** argv) { - struct imv_navigator nav; - imv_navigator_init(&nav); + imv_command_register("quit", &cmd_quit); + imv_command_register("pan", &cmd_pan); + imv_command_register("select_rel", &cmd_select_rel); + imv_command_register("select_abs", &cmd_select_abs); + imv_command_register("zoom", &cmd_zoom); + imv_command_register("remove", &cmd_remove); + imv_command_register("fullscreen", &cmd_fullscreen); + imv_command_register("overlay", &cmd_overlay); + + imv_navigator_init(&g_state.nav); /* parse any command line options given */ parse_args(argc, argv); @@ -202,8 +238,8 @@ int main(int argc, char** argv) buf[--len] = 0; } if(len > 0) { - if(imv_navigator_add(&nav, buf, g_options.recursive) != 0) { - imv_navigator_destroy(&nav); + if(imv_navigator_add(&g_state.nav, buf, g_options.recursive) != 0) { + imv_navigator_destroy(&g_state.nav); exit(1); } break; @@ -237,25 +273,25 @@ int main(int argc, char** argv) errno = 0; /* clear errno */ } /* add the given path to the list to load */ - if(imv_navigator_add(&nav, argv[i], g_options.recursive) != 0) { - imv_navigator_destroy(&nav); + if(imv_navigator_add(&g_state.nav, argv[i], g_options.recursive) != 0) { + imv_navigator_destroy(&g_state.nav); exit(1); } } /* if we weren't given any paths we have nothing to view. exit */ - if(!imv_navigator_selection(&nav)) { + if(!imv_navigator_selection(&g_state.nav)) { fprintf(stderr, "No input files. Exiting.\n"); exit(1); } /* go to the chosen starting image if possible */ if(g_options.start_at) { - int start_index = imv_navigator_find_path(&nav, 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(&nav, start_index); + imv_navigator_select_str(&g_state.nav, start_index); } /* we've got something to display, so create an SDL window */ @@ -269,23 +305,23 @@ int main(int argc, char** argv) const int width = 1280; const int height = 720; - SDL_Window *window = SDL_CreateWindow( + g_state.window = SDL_CreateWindow( "imv", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE); - if(!window) { + if(!g_state.window) { fprintf(stderr, "SDL Failed to create window: %s\n", SDL_GetError()); 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) { + g_state.renderer = SDL_CreateRenderer(g_state.window, -1, 0); + if(!g_state.renderer) { fprintf(stderr, "SDL Failed to create renderer: %s\n", SDL_GetError()); - SDL_DestroyWindow(window); + SDL_DestroyWindow(g_state.window); SDL_Quit(); exit(1); } @@ -297,7 +333,7 @@ int main(int argc, char** argv) /* construct a chequered background texture */ SDL_Texture *chequered_tex = NULL; if(!g_options.solid_bg) { - chequered_tex = create_chequered(renderer); + chequered_tex = create_chequered(g_state.renderer); } /* set up the required fonts and surfaces for displaying the overlay */ @@ -308,18 +344,15 @@ int main(int argc, char** argv) } /* create our main classes on the stack*/ - struct imv_loader ldr; - imv_init_loader(&ldr); + imv_init_loader(&g_state.ldr); - struct imv_texture tex; - imv_init_texture(&tex, renderer); + imv_init_texture(&g_state.tex, g_state.renderer); - struct imv_viewport view; - imv_init_viewport(&view, window); + imv_init_viewport(&g_state.view, g_state.window); /* put us in fullscren mode to begin with if requested */ if(g_options.fullscreen) { - imv_viewport_toggle_fullscreen(&view); + imv_viewport_toggle_fullscreen(&g_state.view); } /* help keeping track of time */ @@ -329,56 +362,50 @@ int main(int argc, char** argv) /* keep file change polling rate under control */ static uint8_t poll_countdown = UINT8_MAX; - /* do we need to redraw the window? */ - int need_redraw = 1; - int need_rescale = 0; + g_state.need_redraw = 1; + g_state.need_rescale = 0; /* keep title buffer around for reuse */ char title[256]; - /* used to calculate when to skip to the next image in slideshow mode */ - unsigned long delay_msec = 0; + g_state.delay_msec = 0; /* initialize variables holding image dimentions */ int iw = 0, ih = 0; - int quit = 0; - while(!quit) { + g_state.quit = 0; + while(!g_state.quit) { /* handle any input/window events sent by SDL */ SDL_Event e; - while(!quit && SDL_PollEvent(&e)) { + while(!g_state.quit && SDL_PollEvent(&e)) { switch(e.type) { case SDL_QUIT: - quit = 1; + imv_command_exec("quit"); break; case SDL_KEYDOWN: SDL_ShowCursor(SDL_DISABLE); switch (e.key.keysym.sym) { case SDLK_q: - quit = 1; + imv_command_exec("quit"); break; case SDLK_LEFTBRACKET: case SDLK_LEFT: - imv_navigator_select_rel(&nav, -1); - /* reset slideshow delay */ - delay_msec = 0; + imv_command_exec("select_rel -1"); break; case SDLK_RIGHTBRACKET: case SDLK_RIGHT: - imv_navigator_select_rel(&nav, 1); - /* reset slideshow delay */ - delay_msec = 0; + imv_command_exec("select_rel 1"); break; case SDLK_EQUALS: case SDLK_PLUS: case SDLK_i: case SDLK_UP: - imv_viewport_zoom(&view, &tex, IMV_ZOOM_KEYBOARD, 1); + 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(&view, &tex, IMV_ZOOM_KEYBOARD, -1); + imv_viewport_zoom(&g_state.view, &g_state.tex, IMV_ZOOM_KEYBOARD, -1); break; case SDLK_s: if(!e.key.repeat) { @@ -389,71 +416,58 @@ int main(int argc, char** argv) /* FALLTHROUGH */ case SDLK_r: if(!e.key.repeat) { - need_rescale = 1; - need_redraw = 1; + g_state.need_rescale = 1; + g_state.need_redraw = 1; } break; case SDLK_a: if(!e.key.repeat) { - imv_viewport_scale_to_actual(&view, &tex); + imv_viewport_scale_to_actual(&g_state.view, &g_state.tex); } break; case SDLK_c: if(!e.key.repeat) { - imv_viewport_center(&view, &tex); + imv_viewport_center(&g_state.view, &g_state.tex); } break; case SDLK_j: - imv_viewport_move(&view, 0, -50); + imv_command_exec("pan 0 -50"); break; case SDLK_k: - imv_viewport_move(&view, 0, 50); + imv_command_exec("pan 0 50"); break; case SDLK_h: - imv_viewport_move(&view, 50, 0); + imv_command_exec("pan 50 0"); break; case SDLK_l: - imv_viewport_move(&view, -50, 0); + imv_command_exec("pan -50 0"); break; case SDLK_x: if(!e.key.repeat) { - char* path = strdup(imv_navigator_selection(&nav)); - imv_navigator_remove(&nav, path); - - if (SDL_GetModState() & KMOD_SHIFT) { - if (remove(path)) { - fprintf(stderr, "Warning: can't remove %s from disk.\n", path); - } - } - - free(path); - - /* reset slideshow delay */ - delay_msec = 0; + imv_command_exec("remove"); } break; case SDLK_f: if(!e.key.repeat) { - imv_viewport_toggle_fullscreen(&view); + imv_command_exec("fullscreen"); } break; case SDLK_PERIOD: - imv_loader_load_next_frame(&ldr); + imv_loader_load_next_frame(&g_state.ldr); break; case SDLK_SPACE: if(!e.key.repeat) { - imv_viewport_toggle_playing(&view); + imv_viewport_toggle_playing(&g_state.view); } break; case SDLK_p: if(!e.key.repeat) { - puts(imv_navigator_selection(&nav)); + puts(imv_navigator_selection(&g_state.nav)); } break; case SDLK_d: if(!e.key.repeat) { - g_options.overlay = !g_options.overlay; - need_redraw = 1; + imv_command_exec("overlay"); } break; case SDLK_t: @@ -464,35 +478,35 @@ int main(int argc, char** argv) } else { g_options.delay += 1000; } - need_redraw = 1; + g_state.need_redraw = 1; break; } break; case SDL_MOUSEWHEEL: - imv_viewport_zoom(&view, &tex, IMV_ZOOM_MOUSE, e.wheel.y); + imv_viewport_zoom(&g_state.view, &g_state.tex, IMV_ZOOM_MOUSE, e.wheel.y); SDL_ShowCursor(SDL_ENABLE); break; case SDL_MOUSEMOTION: if(e.motion.state & SDL_BUTTON_LMASK) { - imv_viewport_move(&view, e.motion.xrel, e.motion.yrel); + imv_viewport_move(&g_state.view, e.motion.xrel, e.motion.yrel); } SDL_ShowCursor(SDL_ENABLE); break; case SDL_WINDOWEVENT: - imv_viewport_update(&view, &tex); + imv_viewport_update(&g_state.view, &g_state.tex); break; } } /* if we're quitting, don't bother drawing any more images */ - if(quit) { + 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(&ldr); + char *err_path = imv_loader_get_error(&g_state.ldr); if(err_path) { - imv_navigator_remove(&nav, err_path); + imv_navigator_remove(&g_state.nav, err_path); if (strncmp(err_path, "-", 2) == 0) { free(stdin_buffer); stdin_buffer_size = 0; @@ -506,13 +520,13 @@ int main(int argc, char** argv) } /* Check if navigator wrapped around paths lists */ - if(!g_options.cycle && imv_navigator_wrapped(&nav)) { + 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(&nav, poll_countdown--)) { - const char *current_path = imv_navigator_selection(&nav); + if(imv_navigator_poll_changed(&g_state.nav, poll_countdown--)) { + const char *current_path = imv_navigator_selection(&g_state.nav); if(!current_path) { if(g_options.stdin_list) { continue; @@ -522,37 +536,37 @@ int main(int argc, char** argv) } snprintf(title, sizeof(title), "imv - [%i/%i] [LOADING] %s [%s]", - nav.cur_path + 1, nav.num_paths, current_path, + g_state.nav.cur_path + 1, g_state.nav.num_paths, current_path, scaling_label[g_options.scaling]); - imv_viewport_set_title(&view, title); + imv_viewport_set_title(&g_state.view, title); - imv_loader_load(&ldr, current_path, stdin_buffer, stdin_buffer_size); - view.playing = 1; + imv_loader_load(&g_state.ldr, current_path, stdin_buffer, stdin_buffer_size); + g_state.view.playing = 1; } /* get window height and width */ int ww, wh; - SDL_GetWindowSize(window, &ww, &wh); + SDL_GetWindowSize(g_state.window, &ww, &wh); /* check if a new image is available to display */ FIBITMAP *bmp; int is_new_image; - if(imv_loader_get_image(&ldr, &bmp, &is_new_image)) { - imv_texture_set_image(&tex, bmp); + 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); - need_redraw = 1; - need_rescale += is_new_image; + g_state.need_redraw = 1; + g_state.need_rescale += is_new_image; } - if(need_rescale) { - need_rescale = 0; + if(g_state.need_rescale) { + g_state.need_rescale = 0; if(g_options.scaling == NONE || (g_options.scaling == DOWN && ww > iw && wh > ih)) { - imv_viewport_scale_to_actual(&view, &tex); + imv_viewport_scale_to_actual(&g_state.view, &g_state.tex); } else { - imv_viewport_scale_to_window(&view, &tex); + imv_viewport_scale_to_window(&g_state.view, &g_state.tex); } } @@ -560,7 +574,7 @@ int main(int argc, char** argv) /* if we're playing an animated gif, tell the loader how much time has * passed */ - if(view.playing) { + 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 @@ -568,49 +582,49 @@ int main(int argc, char** argv) if(dt > 100) { dt = 100; } - imv_loader_time_passed(&ldr, dt / 1000.0); + imv_loader_time_passed(&g_state.ldr, dt / 1000.0); } /* handle slideshow */ if(g_options.delay) { unsigned int dt = current_time - last_time; - delay_msec += dt; - need_redraw = 1; - if(delay_msec >= g_options.delay) { - imv_navigator_select_rel(&nav, 1); - delay_msec = 0; + 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(&view)) { - need_redraw = 1; + if(imv_viewport_needs_redraw(&g_state.view)) { + g_state.need_redraw = 1; } /* only redraw when something's changed */ - if(need_redraw) { + if(g_state.need_redraw) { /* update window title */ int len; - const char *current_path = imv_navigator_selection(&nav); + const char *current_path = imv_navigator_selection(&g_state.nav); len = snprintf(title, sizeof(title), "imv - [%i/%i] [%ix%i] [%.2f%%] %s [%s]", - nav.cur_path + 1, nav.num_paths, tex.width, tex.height, - 100.0 * view.scale, + 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]", - delay_msec / 1000 + 1, g_options.delay / 1000); + g_state.delay_msec / 1000 + 1, g_options.delay / 1000); } - imv_viewport_set_title(&view, title); + imv_viewport_set_title(&g_state.view, title); /* first we draw the background */ if(g_options.solid_bg) { /* solid background */ - SDL_SetRenderDrawColor(renderer, + SDL_SetRenderDrawColor(g_state.renderer, g_options.bg_r, g_options.bg_g, g_options.bg_b, 255); - SDL_RenderClear(renderer); + SDL_RenderClear(g_state.renderer); } else { /* chequered background */ int img_w, img_h; @@ -619,30 +633,30 @@ int main(int argc, char** argv) 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, chequered_tex, NULL, &dst_rect); + SDL_RenderCopy(g_state.renderer, chequered_tex, NULL, &dst_rect); } } } /* draw our actual texture */ - imv_texture_draw(&tex, view.x, view.y, view.scale); + 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 && font) { SDL_Color fg = {255,255,255,255}; SDL_Color bg = {0,0,0,160}; - imv_printf(renderer, font, 0, 0, &fg, &bg, "%s", + imv_printf(g_state.renderer, font, 0, 0, &fg, &bg, "%s", title + strlen("imv - ")); } /* redraw complete, unset the flag */ - need_redraw = 0; + g_state.need_redraw = 0; /* reset poll countdown timer */ poll_countdown = UINT8_MAX; /* tell SDL to show the newly drawn frame */ - SDL_RenderPresent(renderer); + SDL_RenderPresent(g_state.renderer); } /* sleep a little bit so we don't waste CPU time */ @@ -668,10 +682,10 @@ int main(int argc, char** argv) buf[--len] = 0; } if(len > 0) { - if(imv_navigator_add(&nav, buf, g_options.recursive)) { + if(imv_navigator_add(&g_state.nav, buf, g_options.recursive)) { break; } - need_redraw = 1; + g_state.need_redraw = 1; } } } else { @@ -679,18 +693,18 @@ int main(int argc, char** argv) } } while(g_options.list) { - const char *path = imv_navigator_selection(&nav); + const char *path = imv_navigator_selection(&g_state.nav); if(!path) { break; } fprintf(stdout, "%s\n", path); - imv_navigator_remove(&nav, path); + imv_navigator_remove(&g_state.nav, path); } /* clean up our resources now that we're exiting */ - imv_destroy_loader(&ldr); - imv_destroy_texture(&tex); - imv_navigator_destroy(&nav); - imv_destroy_viewport(&view); + imv_destroy_loader(&g_state.ldr); + imv_destroy_texture(&g_state.tex); + imv_navigator_destroy(&g_state.nav); + imv_destroy_viewport(&g_state.view); if(font) { TTF_CloseFont(font); @@ -699,12 +713,76 @@ int main(int argc, char** argv) if(chequered_tex) { SDL_DestroyTexture(chequered_tex); } - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); + SDL_DestroyRenderer(g_state.renderer); + SDL_DestroyWindow(g_state.window); SDL_Quit(); return 0; } +void cmd_quit(struct imv_list *args) +{ + (void)args; + g_state.quit = 1; +} + +void cmd_pan(struct imv_list *args) +{ + if(args->len != 3) { + return; + } + + 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) +{ + if(args->len != 2) { + return; + } + + 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)args; +} + +void cmd_zoom(struct imv_list *args) +{ + (void)args; +} + +void cmd_remove(struct imv_list *args) +{ + (void)args; + 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)args; + imv_viewport_toggle_fullscreen(&g_state.view); +} + +void cmd_overlay(struct imv_list *args) +{ + (void)args; + g_options.overlay = !g_options.overlay; + g_state.need_redraw = 1; +} /* vim:set ts=2 sts=2 sw=2 et: */ -- cgit v1.2.3 From 83959687adbd90303ee2ff630f659b8994000808 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 16:17:21 +0100 Subject: Add a rough command mode --- src/main.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 8a5ba78..1318e8f 100644 --- a/src/main.c +++ b/src/main.c @@ -187,6 +187,9 @@ struct { /* 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); @@ -370,6 +373,9 @@ int main(int argc, char** argv) g_state.delay_msec = 0; + /* start outside of command mode */ + g_state.command_buffer = NULL; + /* initialize variables holding image dimentions */ int iw = 0, ih = 0; @@ -382,9 +388,48 @@ int main(int argc, char** argv) case SDL_QUIT: imv_command_exec("quit"); break; + case SDL_KEYDOWN: SDL_ShowCursor(SDL_DISABLE); + + if(g_state.command_buffer) { + /* in command mode, update the buffer */ + if(e.key.keysym.sym == SDLK_ESCAPE) { + free(g_state.command_buffer); + g_state.command_buffer = NULL; + g_state.need_redraw = 1; + } else if(e.key.keysym.sym == SDLK_RETURN) { + imv_command_exec(g_state.command_buffer); + free(g_state.command_buffer); + g_state.command_buffer = NULL; + g_state.need_redraw = 1; + } else if(e.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; + } + } else if(e.key.keysym.sym >= ' ' && e.key.keysym.sym <= '~') { + const size_t len = strlen(g_state.command_buffer); + if(len + 1 < 1024) { + g_state.command_buffer[len] = e.key.keysym.sym; + g_state.command_buffer[len+1] = '\0'; + g_state.need_redraw = 1; + } + } + + /* input has been consumed by command input, move onto next event */ + continue; + } + switch (e.key.keysym.sym) { + case SDLK_SEMICOLON: + if(e.key.keysym.mod & KMOD_SHIFT) { + g_state.command_buffer = malloc(1024); + g_state.command_buffer[0] = '\0'; + g_state.need_redraw = 1; + } + break; case SDLK_q: imv_command_exec("quit"); break; @@ -649,6 +694,17 @@ int main(int argc, char** argv) title + strlen("imv - ")); } + /* draw command entry bar if needed */ + if(g_state.command_buffer && font) { + SDL_Color fg = {255,255,255,255}; + SDL_Color bg = {0,0,0,160}; + imv_printf(g_state.renderer, + font, + 0, wh - TTF_FontHeight(font), + &fg, &bg, + ":%s", g_state.command_buffer); + } + /* redraw complete, unset the flag */ g_state.need_redraw = 0; @@ -700,7 +756,12 @@ int main(int argc, char** argv) 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_destroy_loader(&g_state.ldr); imv_destroy_texture(&g_state.tex); imv_navigator_destroy(&g_state.nav); -- cgit v1.2.3 From 93f68f6b4c2212a80492274b9aea9a9fb43d7ec4 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 16:23:58 +0100 Subject: Add some aliases --- src/main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 1318e8f..9ad0531 100644 --- a/src/main.c +++ b/src/main.c @@ -212,6 +212,12 @@ int main(int argc, char** argv) imv_command_register("fullscreen", &cmd_fullscreen); imv_command_register("overlay", &cmd_overlay); + imv_command_alias("q", "quit"); + imv_command_alias("next", "select_rel 1"); + imv_command_alias("previous", "select_rel -1"); + imv_command_alias("n", "select_rel 1"); + imv_command_alias("p", "select_rel -1"); + imv_navigator_init(&g_state.nav); /* parse any command line options given */ -- cgit v1.2.3 From 50759fb279b38c5db7cacf88206188b827f564b2 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 16:44:07 +0100 Subject: Let's not have imv_commands use hidden globals --- src/commands.c | 55 +++++++++++++++++++++++++++++++------------------------ src/commands.h | 14 +++++++++++--- src/main.c | 55 +++++++++++++++++++++++++++++-------------------------- 3 files changed, 71 insertions(+), 53 deletions(-) (limited to 'src/main.c') diff --git a/src/commands.c b/src/commands.c index f9a4ff3..a3a59b1 100644 --- a/src/commands.c +++ b/src/commands.c @@ -18,58 +18,65 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "commands.h" #include "list.h" -struct imv_command { - const char* command; +struct command { + char* command; void (*handler)(struct imv_list *args); - const char* alias; + char* alias; }; -struct imv_list *g_commands = NULL; +struct imv_commands *imv_commands_create(void) +{ + struct imv_commands *cmds = malloc(sizeof(struct imv_commands)); + cmds->command_list = imv_list_create(); + return cmds; +} -void imv_command_register(const char *command, void (*handler)()) +void imv_commands_free(struct imv_commands *cmds) { - if(!g_commands) { - g_commands = imv_list_create(); + for(size_t i = 0; i < cmds->command_list->len; ++i) { + struct command *cmd = cmds->command_list->items[i]; + free(cmd->command); + if(cmd->alias) { + free(cmd->alias); + } + free(cmd); } + imv_list_free(cmds->command_list); + free(cmds); +} - struct imv_command *cmd = malloc(sizeof(struct imv_command)); +void imv_command_register(struct imv_commands *cmds, const char *command, void (*handler)()) +{ + struct command *cmd = malloc(sizeof(struct command)); cmd->command = strdup(command); cmd->handler = handler; cmd->alias = NULL; - imv_list_append(g_commands, cmd); + imv_list_append(cmds->command_list, cmd); } -void imv_command_alias(const char *command, const char *alias) +void imv_command_alias(struct imv_commands *cmds, const char *command, const char *alias) { - if(!g_commands) { - g_commands = imv_list_create(); - } - - struct imv_command *cmd = malloc(sizeof(struct imv_command)); + struct command *cmd = malloc(sizeof(struct command)); cmd->command = strdup(command); cmd->handler = NULL; cmd->alias = strdup(alias); - imv_list_append(g_commands, cmd); + imv_list_append(cmds->command_list, cmd); } -int imv_command_exec(const char *command) +int imv_command_exec(struct imv_commands *cmds, const char *command) { - if(!g_commands) { - return 1; - } - struct imv_list *args = imv_split_string(command, ' '); int ret = 1; if(args->len > 0) { - for(size_t i = 0; i < g_commands->len; ++i) { - struct imv_command *cmd = g_commands->items[i]; + for(size_t i = 0; i < cmds->command_list->len; ++i) { + struct command *cmd = cmds->command_list->items[i]; if(!strcmp(cmd->command, args->items[0])) { if(cmd->handler) { cmd->handler(args); ret = 0; } else if(cmd->alias) { - ret = imv_command_exec(cmd->alias); + ret = imv_command_exec(cmds, cmd->alias); } break; } diff --git a/src/commands.h b/src/commands.h index b3a78e6..df8b43b 100644 --- a/src/commands.h +++ b/src/commands.h @@ -18,9 +18,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef COMMANDS_H #define COMMANDS_H -void imv_command_register(const char *command, void (*handler)()); -void imv_command_alias(const char *command, const char *alias); -int imv_command_exec(const char *command); +struct imv_list; + +struct imv_commands { + struct imv_list *command_list; +}; + +struct imv_commands *imv_commands_create(void); +void imv_commands_free(struct imv_commands *cmds); +void imv_command_register(struct imv_commands *cmds, const char *command, void (*handler)()); +void imv_command_alias(struct imv_commands *cmds, const char *command, const char *alias); +int imv_command_exec(struct imv_commands *cmds, const char *command); #endif diff --git a/src/main.c b/src/main.c index 9ad0531..56971c1 100644 --- a/src/main.c +++ b/src/main.c @@ -177,6 +177,7 @@ struct { struct imv_loader ldr; struct imv_texture tex; struct imv_viewport view; + struct imv_commands *cmds; SDL_Window *window; SDL_Renderer *renderer; int quit; @@ -203,20 +204,21 @@ void cmd_overlay(struct imv_list *args); int main(int argc, char** argv) { - imv_command_register("quit", &cmd_quit); - imv_command_register("pan", &cmd_pan); - imv_command_register("select_rel", &cmd_select_rel); - imv_command_register("select_abs", &cmd_select_abs); - imv_command_register("zoom", &cmd_zoom); - imv_command_register("remove", &cmd_remove); - imv_command_register("fullscreen", &cmd_fullscreen); - imv_command_register("overlay", &cmd_overlay); - - imv_command_alias("q", "quit"); - imv_command_alias("next", "select_rel 1"); - imv_command_alias("previous", "select_rel -1"); - imv_command_alias("n", "select_rel 1"); - imv_command_alias("p", "select_rel -1"); + 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"); imv_navigator_init(&g_state.nav); @@ -392,7 +394,7 @@ int main(int argc, char** argv) while(!g_state.quit && SDL_PollEvent(&e)) { switch(e.type) { case SDL_QUIT: - imv_command_exec("quit"); + imv_command_exec(g_state.cmds, "quit"); break; case SDL_KEYDOWN: @@ -405,7 +407,7 @@ int main(int argc, char** argv) g_state.command_buffer = NULL; g_state.need_redraw = 1; } else if(e.key.keysym.sym == SDLK_RETURN) { - imv_command_exec(g_state.command_buffer); + imv_command_exec(g_state.cmds, g_state.command_buffer); free(g_state.command_buffer); g_state.command_buffer = NULL; g_state.need_redraw = 1; @@ -437,15 +439,15 @@ int main(int argc, char** argv) } break; case SDLK_q: - imv_command_exec("quit"); + imv_command_exec(g_state.cmds, "quit"); break; case SDLK_LEFTBRACKET: case SDLK_LEFT: - imv_command_exec("select_rel -1"); + imv_command_exec(g_state.cmds, "select_rel -1"); break; case SDLK_RIGHTBRACKET: case SDLK_RIGHT: - imv_command_exec("select_rel 1"); + imv_command_exec(g_state.cmds, "select_rel 1"); break; case SDLK_EQUALS: case SDLK_PLUS: @@ -482,25 +484,25 @@ int main(int argc, char** argv) } break; case SDLK_j: - imv_command_exec("pan 0 -50"); + imv_command_exec(g_state.cmds, "pan 0 -50"); break; case SDLK_k: - imv_command_exec("pan 0 50"); + imv_command_exec(g_state.cmds, "pan 0 50"); break; case SDLK_h: - imv_command_exec("pan 50 0"); + imv_command_exec(g_state.cmds, "pan 50 0"); break; case SDLK_l: - imv_command_exec("pan -50 0"); + imv_command_exec(g_state.cmds, "pan -50 0"); break; case SDLK_x: if(!e.key.repeat) { - imv_command_exec("remove"); + imv_command_exec(g_state.cmds, "remove"); } break; case SDLK_f: if(!e.key.repeat) { - imv_command_exec("fullscreen"); + imv_command_exec(g_state.cmds, "fullscreen"); } break; case SDLK_PERIOD: @@ -518,7 +520,7 @@ int main(int argc, char** argv) break; case SDLK_d: if(!e.key.repeat) { - imv_command_exec("overlay"); + imv_command_exec(g_state.cmds, "overlay"); } break; case SDLK_t: @@ -772,6 +774,7 @@ int main(int argc, char** argv) imv_destroy_texture(&g_state.tex); imv_navigator_destroy(&g_state.nav); imv_destroy_viewport(&g_state.view); + imv_commands_free(g_state.cmds); if(font) { TTF_CloseFont(font); -- cgit v1.2.3 From 5a8932cb21f63af86dffa419ec5da5f4a5d29d70 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 16:49:17 +0100 Subject: Refactor loader to new style --- src/loader.c | 7 +++++-- src/loader.h | 8 ++++---- src/main.c | 18 +++++++++--------- test/loader.c | 15 ++++++++------- 4 files changed, 26 insertions(+), 22 deletions(-) (limited to 'src/main.c') diff --git a/src/loader.c b/src/loader.c index d70b66d..c5b64a6 100644 --- a/src/loader.c +++ b/src/loader.c @@ -44,15 +44,17 @@ static int is_thread_cancelled(void) return sigismember(&sigmask, SIGUSR1); } -void imv_init_loader(struct imv_loader *ldr) +struct imv_loader *imv_loader_create(void) { + struct imv_loader *ldr = malloc(sizeof(struct imv_loader)); memset(ldr, 0, sizeof(struct imv_loader)); pthread_mutex_init(&ldr->lock, NULL); /* ignore this signal in case we accidentally receive it */ block_usr1_signal(); + return ldr; } -void imv_destroy_loader(struct imv_loader *ldr) +void imv_loader_free(struct imv_loader *ldr) { /* wait for any existing bg thread to finish */ pthread_join(ldr->bg_thread, NULL); @@ -70,6 +72,7 @@ void imv_destroy_loader(struct imv_loader *ldr) if(ldr->path) { free(ldr->path); } + free(ldr); } void imv_loader_load(struct imv_loader *ldr, const char *path, diff --git a/src/loader.h b/src/loader.h index d2418a2..04dc640 100644 --- a/src/loader.h +++ b/src/loader.h @@ -44,11 +44,11 @@ struct imv_loader { double frame_time; }; -/* Initialises an instance of imv_loader */ -void imv_init_loader(struct imv_loader *img); +/* Creates an instance of imv_loader */ +struct imv_loader *imv_loader_create(void); -/* Cleans up all resources owned by a imv_loader instance */ -void imv_destroy_loader(struct imv_loader *img); +/* Cleans up an imv_loader instance */ +void imv_loader_free(struct imv_loader *ldr); /* Asynchronously load the given file */ void imv_loader_load(struct imv_loader *ldr, const char *path, diff --git a/src/main.c b/src/main.c index 56971c1..e2c0654 100644 --- a/src/main.c +++ b/src/main.c @@ -174,7 +174,7 @@ static void parse_args(int argc, char** argv) struct { struct imv_navigator nav; - struct imv_loader ldr; + struct imv_loader *ldr; struct imv_texture tex; struct imv_viewport view; struct imv_commands *cmds; @@ -354,8 +354,8 @@ int main(int argc, char** argv) fprintf(stderr, "Error loading font: %s\n", TTF_GetError()); } - /* create our main classes on the stack*/ - imv_init_loader(&g_state.ldr); + /* create our main classes */ + g_state.ldr = imv_loader_create(); imv_init_texture(&g_state.tex, g_state.renderer); @@ -506,7 +506,7 @@ int main(int argc, char** argv) } break; case SDLK_PERIOD: - imv_loader_load_next_frame(&g_state.ldr); + imv_loader_load_next_frame(g_state.ldr); break; case SDLK_SPACE: if(!e.key.repeat) { @@ -557,7 +557,7 @@ int main(int argc, char** argv) } /* 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); + char *err_path = imv_loader_get_error(g_state.ldr); if(err_path) { imv_navigator_remove(&g_state.nav, err_path); if (strncmp(err_path, "-", 2) == 0) { @@ -593,7 +593,7 @@ int main(int argc, char** argv) 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); + imv_loader_load(g_state.ldr, current_path, stdin_buffer, stdin_buffer_size); g_state.view.playing = 1; } @@ -604,7 +604,7 @@ int main(int argc, char** argv) /* 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)) { + 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); @@ -635,7 +635,7 @@ int main(int argc, char** argv) if(dt > 100) { dt = 100; } - imv_loader_time_passed(&g_state.ldr, dt / 1000.0); + imv_loader_time_passed(g_state.ldr, dt / 1000.0); } /* handle slideshow */ @@ -770,7 +770,7 @@ int main(int argc, char** argv) free(g_state.command_buffer); } - imv_destroy_loader(&g_state.ldr); + imv_loader_free(g_state.ldr); imv_destroy_texture(&g_state.tex); imv_navigator_destroy(&g_state.nav); imv_destroy_viewport(&g_state.view); diff --git a/test/loader.c b/test/loader.c index bbbb8d7..e8791c0 100644 --- a/test/loader.c +++ b/test/loader.c @@ -10,24 +10,25 @@ static void test_jpeg_rotation(void **state) { (void)state; - struct imv_loader ldr; + struct imv_loader *ldr = imv_loader_create(); void *retval; char *error; unsigned int width; - imv_init_loader(&ldr); - imv_loader_load(&ldr, "test/orientation.jpg", NULL, 0); - pthread_join(ldr.bg_thread, &retval); + imv_loader_load(ldr, "test/orientation.jpg", NULL, 0); + pthread_join(ldr->bg_thread, &retval); - error = imv_loader_get_error(&ldr); + error = imv_loader_get_error(ldr); assert_false(error); assert_false(retval == PTHREAD_CANCELED); - assert_false(ldr.out_bmp == NULL); + assert_false(ldr->out_bmp == NULL); - width = FreeImage_GetWidth(ldr.out_bmp); + width = FreeImage_GetWidth(ldr->out_bmp); assert_true(width == 1); + + imv_loader_free(ldr); } int main(void) -- cgit v1.2.3 From b9dd2cbc01bdd071fc44db771187d12860191d13 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 16:56:06 +0100 Subject: Refactor texture to new style --- src/main.c | 29 ++++++++++++++--------------- src/texture.c | 7 +++++-- src/texture.h | 8 ++++---- 3 files changed, 23 insertions(+), 21 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index e2c0654..2f13b33 100644 --- a/src/main.c +++ b/src/main.c @@ -175,7 +175,7 @@ static void parse_args(int argc, char** argv) struct { struct imv_navigator nav; struct imv_loader *ldr; - struct imv_texture tex; + struct imv_texture *tex; struct imv_viewport view; struct imv_commands *cmds; SDL_Window *window; @@ -356,8 +356,7 @@ int main(int argc, char** argv) /* create our main classes */ g_state.ldr = imv_loader_create(); - - imv_init_texture(&g_state.tex, g_state.renderer); + g_state.tex = imv_texture_create(g_state.renderer); imv_init_viewport(&g_state.view, g_state.window); @@ -453,12 +452,12 @@ int main(int argc, char** argv) case SDLK_PLUS: case SDLK_i: case SDLK_UP: - imv_viewport_zoom(&g_state.view, &g_state.tex, IMV_ZOOM_KEYBOARD, 1); + 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); + imv_viewport_zoom(&g_state.view, g_state.tex, IMV_ZOOM_KEYBOARD, -1); break; case SDLK_s: if(!e.key.repeat) { @@ -475,12 +474,12 @@ int main(int argc, char** argv) break; case SDLK_a: if(!e.key.repeat) { - imv_viewport_scale_to_actual(&g_state.view, &g_state.tex); + imv_viewport_scale_to_actual(&g_state.view, g_state.tex); } break; case SDLK_c: if(!e.key.repeat) { - imv_viewport_center(&g_state.view, &g_state.tex); + imv_viewport_center(&g_state.view, g_state.tex); } break; case SDLK_j: @@ -536,7 +535,7 @@ int main(int argc, char** argv) } break; case SDL_MOUSEWHEEL: - imv_viewport_zoom(&g_state.view, &g_state.tex, IMV_ZOOM_MOUSE, e.wheel.y); + imv_viewport_zoom(&g_state.view, g_state.tex, IMV_ZOOM_MOUSE, e.wheel.y); SDL_ShowCursor(SDL_ENABLE); break; case SDL_MOUSEMOTION: @@ -546,7 +545,7 @@ int main(int argc, char** argv) SDL_ShowCursor(SDL_ENABLE); break; case SDL_WINDOWEVENT: - imv_viewport_update(&g_state.view, &g_state.tex); + imv_viewport_update(&g_state.view, g_state.tex); break; } } @@ -605,7 +604,7 @@ int main(int argc, char** argv) 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); + imv_texture_set_image(g_state.tex, bmp); iw = FreeImage_GetWidth(bmp); ih = FreeImage_GetHeight(bmp); FreeImage_Unload(bmp); @@ -617,9 +616,9 @@ int main(int argc, char** argv) 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); + imv_viewport_scale_to_actual(&g_state.view, g_state.tex); } else { - imv_viewport_scale_to_window(&g_state.view, &g_state.tex); + imv_viewport_scale_to_window(&g_state.view, g_state.tex); } } @@ -663,7 +662,7 @@ int main(int argc, char** argv) int len; const char *current_path = imv_navigator_selection(&g_state.nav); 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, + 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) { @@ -692,7 +691,7 @@ int main(int argc, char** argv) } /* draw our actual texture */ - imv_texture_draw(&g_state.tex, g_state.view.x, g_state.view.y, g_state.view.scale); + 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 && font) { @@ -771,7 +770,7 @@ int main(int argc, char** argv) } imv_loader_free(g_state.ldr); - imv_destroy_texture(&g_state.tex); + imv_texture_free(g_state.tex); imv_navigator_destroy(&g_state.nav); imv_destroy_viewport(&g_state.view); imv_commands_free(g_state.cmds); diff --git a/src/texture.c b/src/texture.c index 52ec521..bdfe91f 100644 --- a/src/texture.c +++ b/src/texture.c @@ -17,8 +17,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "texture.h" -void imv_init_texture(struct imv_texture *tex, SDL_Renderer *r) +struct imv_texture *imv_texture_create(SDL_Renderer *r) { + struct imv_texture *tex = malloc(sizeof(struct imv_texture)); memset(tex, 0, sizeof(struct imv_texture)); tex->renderer = r; @@ -26,9 +27,10 @@ void imv_init_texture(struct imv_texture *tex, SDL_Renderer *r) SDL_GetRendererInfo(r, &ri); tex->chunk_width = ri.max_texture_width != 0 ? ri.max_texture_width : 4096; tex->chunk_height = ri.max_texture_height != 0 ? ri.max_texture_height : 4096; + return tex; } -void imv_destroy_texture(struct imv_texture *tex) +void imv_texture_free(struct imv_texture *tex) { if(tex->num_chunks > 0) { for(int i = 0; i < tex->num_chunks; ++i) { @@ -39,6 +41,7 @@ void imv_destroy_texture(struct imv_texture *tex) tex->chunks = NULL; tex->renderer = NULL; } + free(tex); } int imv_texture_set_image(struct imv_texture *tex, FIBITMAP *image) diff --git a/src/texture.h b/src/texture.h index 4d2aea9..2931525 100644 --- a/src/texture.h +++ b/src/texture.h @@ -36,11 +36,11 @@ struct imv_texture { }; -/* Initialises an instance of imv_texture */ -void imv_init_texture(struct imv_texture *tex, SDL_Renderer *r); +/* Creates an instance of imv_texture */ +struct imv_texture *imv_texture_create(SDL_Renderer *r); -/* Cleans up all resources owned by a imv_texture instance */ -void imv_destroy_texture(struct imv_texture *tex); +/* Cleans up an imv_texture instance */ +void imv_texture_free(struct imv_texture *tex); /* Updates the texture to contain the data in the image parameter */ int imv_texture_set_image(struct imv_texture *tex, FIBITMAP *image); -- cgit v1.2.3 From e352474df09257342410e74e8fb686f424819b9a Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 17:02:28 +0100 Subject: Refactor viewport to new style --- src/main.c | 47 +++++++++++++++++++++++------------------------ src/viewport.c | 9 +++++---- src/viewport.h | 8 ++++---- 3 files changed, 32 insertions(+), 32 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 2f13b33..4006747 100644 --- a/src/main.c +++ b/src/main.c @@ -176,7 +176,7 @@ struct { struct imv_navigator nav; struct imv_loader *ldr; struct imv_texture *tex; - struct imv_viewport view; + struct imv_viewport *view; struct imv_commands *cmds; SDL_Window *window; SDL_Renderer *renderer; @@ -357,12 +357,11 @@ int main(int argc, char** argv) /* create our main classes */ g_state.ldr = imv_loader_create(); g_state.tex = imv_texture_create(g_state.renderer); - - imv_init_viewport(&g_state.view, g_state.window); + g_state.view = imv_viewport_create(g_state.window); /* put us in fullscren mode to begin with if requested */ if(g_options.fullscreen) { - imv_viewport_toggle_fullscreen(&g_state.view); + imv_viewport_toggle_fullscreen(g_state.view); } /* help keeping track of time */ @@ -452,12 +451,12 @@ int main(int argc, char** argv) case SDLK_PLUS: case SDLK_i: case SDLK_UP: - imv_viewport_zoom(&g_state.view, g_state.tex, IMV_ZOOM_KEYBOARD, 1); + 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); + imv_viewport_zoom(g_state.view, g_state.tex, IMV_ZOOM_KEYBOARD, -1); break; case SDLK_s: if(!e.key.repeat) { @@ -474,12 +473,12 @@ int main(int argc, char** argv) break; case SDLK_a: if(!e.key.repeat) { - imv_viewport_scale_to_actual(&g_state.view, g_state.tex); + imv_viewport_scale_to_actual(g_state.view, g_state.tex); } break; case SDLK_c: if(!e.key.repeat) { - imv_viewport_center(&g_state.view, g_state.tex); + imv_viewport_center(g_state.view, g_state.tex); } break; case SDLK_j: @@ -509,7 +508,7 @@ int main(int argc, char** argv) break; case SDLK_SPACE: if(!e.key.repeat) { - imv_viewport_toggle_playing(&g_state.view); + imv_viewport_toggle_playing(g_state.view); } break; case SDLK_p: @@ -535,17 +534,17 @@ int main(int argc, char** argv) } break; case SDL_MOUSEWHEEL: - imv_viewport_zoom(&g_state.view, g_state.tex, IMV_ZOOM_MOUSE, e.wheel.y); + imv_viewport_zoom(g_state.view, g_state.tex, IMV_ZOOM_MOUSE, e.wheel.y); SDL_ShowCursor(SDL_ENABLE); break; case SDL_MOUSEMOTION: if(e.motion.state & SDL_BUTTON_LMASK) { - imv_viewport_move(&g_state.view, e.motion.xrel, e.motion.yrel); + imv_viewport_move(g_state.view, e.motion.xrel, e.motion.yrel); } SDL_ShowCursor(SDL_ENABLE); break; case SDL_WINDOWEVENT: - imv_viewport_update(&g_state.view, g_state.tex); + imv_viewport_update(g_state.view, g_state.tex); break; } } @@ -590,10 +589,10 @@ int main(int argc, char** argv) 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_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; + g_state.view->playing = 1; } /* get window height and width */ @@ -616,9 +615,9 @@ int main(int argc, char** argv) 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); + imv_viewport_scale_to_actual(g_state.view, g_state.tex); } else { - imv_viewport_scale_to_window(&g_state.view, g_state.tex); + imv_viewport_scale_to_window(g_state.view, g_state.tex); } } @@ -626,7 +625,7 @@ int main(int argc, char** argv) /* if we're playing an animated gif, tell the loader how much time has * passed */ - if(g_state.view.playing) { + 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 @@ -652,7 +651,7 @@ int main(int argc, char** argv) last_time = current_time; /* check if the viewport needs a redraw */ - if(imv_viewport_needs_redraw(&g_state.view)) { + if(imv_viewport_needs_redraw(g_state.view)) { g_state.need_redraw = 1; } @@ -663,13 +662,13 @@ int main(int argc, char** argv) const char *current_path = imv_navigator_selection(&g_state.nav); 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, + 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); + imv_viewport_set_title(g_state.view, title); /* first we draw the background */ if(g_options.solid_bg) { @@ -691,7 +690,7 @@ int main(int argc, char** argv) } /* draw our actual texture */ - imv_texture_draw(g_state.tex, g_state.view.x, g_state.view.y, g_state.view.scale); + 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 && font) { @@ -772,7 +771,7 @@ int main(int argc, char** argv) imv_loader_free(g_state.ldr); imv_texture_free(g_state.tex); imv_navigator_destroy(&g_state.nav); - imv_destroy_viewport(&g_state.view); + imv_viewport_free(g_state.view); imv_commands_free(g_state.cmds); if(font) { @@ -804,7 +803,7 @@ void cmd_pan(struct imv_list *args) 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); + imv_viewport_move(g_state.view, x, y); } void cmd_select_rel(struct imv_list *args) @@ -844,7 +843,7 @@ void cmd_remove(struct imv_list *args) void cmd_fullscreen(struct imv_list *args) { (void)args; - imv_viewport_toggle_fullscreen(&g_state.view); + imv_viewport_toggle_fullscreen(g_state.view); } void cmd_overlay(struct imv_list *args) diff --git a/src/viewport.c b/src/viewport.c index e706643..d096a45 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -17,19 +17,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "viewport.h" -void imv_init_viewport(struct imv_viewport *view, SDL_Window *window) +struct imv_viewport *imv_viewport_create(SDL_Window *window) { + struct imv_viewport *view = malloc(sizeof(struct imv_viewport)); view->window = window; view->scale = 1; view->x = view->y = view->fullscreen = view->redraw = 0; view->playing = 1; view->locked = 0; + return view; } -void imv_destroy_viewport(struct imv_viewport *view) +void imv_viewport_free(struct imv_viewport *view) { - view->window = NULL; - return; + free(view); } void imv_viewport_toggle_fullscreen(struct imv_viewport *view) diff --git a/src/viewport.h b/src/viewport.h index 0f19b85..d1803d4 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -37,11 +37,11 @@ enum imv_zoom_source { IMV_ZOOM_KEYBOARD }; -/* Initialises an instance of imv_viewport */ -void imv_init_viewport(struct imv_viewport *view, SDL_Window *window); +/* Creates an instance of imv_viewport */ +struct imv_viewport *imv_viewport_create(SDL_Window *window); -/* Cleans up all resources owned by a imv_viewport instance */ -void imv_destroy_viewport(struct imv_viewport *view); +/* Cleans up an imv_viewport instance */ +void imv_viewport_free(struct imv_viewport *view); /* Toggle their viewport's fullscreen mode. Triggers a redraw */ void imv_viewport_toggle_fullscreen(struct imv_viewport *view); -- cgit v1.2.3 From 4fde6ea289328b5f1668ceb69657e0c4a334b1fb Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 17:10:23 +0100 Subject: Refactor navigator to new style --- src/main.c | 50 ++++++++++++++++++------------------- src/navigator.c | 8 +++--- src/navigator.h | 8 +++--- test/navigator.c | 76 +++++++++++++++++++++++++++----------------------------- 4 files changed, 71 insertions(+), 71 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 4006747..adee798 100644 --- a/src/main.c +++ b/src/main.c @@ -173,7 +173,7 @@ static void parse_args(int argc, char** argv) } struct { - struct imv_navigator nav; + struct imv_navigator *nav; struct imv_loader *ldr; struct imv_texture *tex; struct imv_viewport *view; @@ -220,7 +220,7 @@ int main(int argc, char** argv) imv_command_alias(g_state.cmds, "n", "select_rel 1"); imv_command_alias(g_state.cmds, "p", "select_rel -1"); - imv_navigator_init(&g_state.nav); + g_state.nav = imv_navigator_create(); /* parse any command line options given */ parse_args(argc, argv); @@ -249,8 +249,8 @@ int main(int argc, char** argv) buf[--len] = 0; } if(len > 0) { - if(imv_navigator_add(&g_state.nav, buf, g_options.recursive) != 0) { - imv_navigator_destroy(&g_state.nav); + if(imv_navigator_add(g_state.nav, buf, g_options.recursive) != 0) { + imv_navigator_free(g_state.nav); exit(1); } break; @@ -284,25 +284,25 @@ int main(int argc, char** argv) 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_destroy(&g_state.nav); + 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)) { + if(!imv_navigator_selection(g_state.nav)) { fprintf(stderr, "No input files. Exiting.\n"); 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); + 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); + imv_navigator_select_str(g_state.nav, start_index); } /* we've got something to display, so create an SDL window */ @@ -513,7 +513,7 @@ int main(int argc, char** argv) break; case SDLK_p: if(!e.key.repeat) { - puts(imv_navigator_selection(&g_state.nav)); + puts(imv_navigator_selection(g_state.nav)); } break; case SDLK_d: @@ -557,7 +557,7 @@ int main(int argc, char** argv) /* 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); + imv_navigator_remove(g_state.nav, err_path); if (strncmp(err_path, "-", 2) == 0) { free(stdin_buffer); stdin_buffer_size = 0; @@ -571,13 +571,13 @@ int main(int argc, char** argv) } /* Check if navigator wrapped around paths lists */ - if(!g_options.cycle && imv_navigator_wrapped(&g_state.nav)) { + 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, poll_countdown--)) { - const char *current_path = imv_navigator_selection(&g_state.nav); + if(imv_navigator_poll_changed(g_state.nav, poll_countdown--)) { + const char *current_path = imv_navigator_selection(g_state.nav); if(!current_path) { if(g_options.stdin_list) { continue; @@ -587,7 +587,7 @@ int main(int argc, char** argv) } snprintf(title, sizeof(title), "imv - [%i/%i] [LOADING] %s [%s]", - g_state.nav.cur_path + 1, g_state.nav.num_paths, current_path, + 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); @@ -643,7 +643,7 @@ int main(int argc, char** argv) 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); + imv_navigator_select_rel(g_state.nav, 1); g_state.delay_msec = 0; } } @@ -659,9 +659,9 @@ int main(int argc, char** argv) if(g_state.need_redraw) { /* update window title */ int len; - const char *current_path = imv_navigator_selection(&g_state.nav); + const char *current_path = imv_navigator_selection(g_state.nav); 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, + 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) { @@ -744,7 +744,7 @@ int main(int argc, char** argv) buf[--len] = 0; } if(len > 0) { - if(imv_navigator_add(&g_state.nav, buf, g_options.recursive)) { + if(imv_navigator_add(g_state.nav, buf, g_options.recursive)) { break; } g_state.need_redraw = 1; @@ -755,12 +755,12 @@ int main(int argc, char** argv) } } while(g_options.list) { - const char *path = imv_navigator_selection(&g_state.nav); + const char *path = imv_navigator_selection(g_state.nav); if(!path) { break; } fprintf(stdout, "%s\n", path); - imv_navigator_remove(&g_state.nav, path); + imv_navigator_remove(g_state.nav, path); } /* clean up our resources now that we're exiting */ @@ -770,7 +770,7 @@ int main(int argc, char** argv) imv_loader_free(g_state.ldr); imv_texture_free(g_state.tex); - imv_navigator_destroy(&g_state.nav); + imv_navigator_free(g_state.nav); imv_viewport_free(g_state.view); imv_commands_free(g_state.cmds); @@ -813,7 +813,7 @@ void cmd_select_rel(struct imv_list *args) } long int index = strtol(args->items[1], NULL, 10); - imv_navigator_select_rel(&g_state.nav, index); + imv_navigator_select_rel(g_state.nav, index); /* reset slideshow delay */ g_state.delay_msec = 0; @@ -832,8 +832,8 @@ void cmd_zoom(struct imv_list *args) void cmd_remove(struct imv_list *args) { (void)args; - char* path = strdup(imv_navigator_selection(&g_state.nav)); - imv_navigator_remove(&g_state.nav, path); + char* path = strdup(imv_navigator_selection(g_state.nav)); + imv_navigator_remove(g_state.nav, path); free(path); /* reset slideshow delay */ diff --git a/src/navigator.c b/src/navigator.c index 97772cd..6abbfb1 100644 --- a/src/navigator.c +++ b/src/navigator.c @@ -24,13 +24,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include -void imv_navigator_init(struct imv_navigator *nav) +struct imv_navigator *imv_navigator_create(void) { + struct imv_navigator *nav = malloc(sizeof(struct imv_navigator)); memset(nav, 0, sizeof(struct imv_navigator)); nav->last_move_direction = 1; + return nav; } -void imv_navigator_destroy(struct imv_navigator *nav) +void imv_navigator_free(struct imv_navigator *nav) { if(nav->paths) { for(int i = 0; i < nav->num_paths; ++i) { @@ -45,7 +47,7 @@ void imv_navigator_destroy(struct imv_navigator *nav) free(nav->mtimes); } - memset(nav, 0, sizeof(struct imv_navigator)); + free(nav); } static int add_item(struct imv_navigator *nav, const char *path, diff --git a/src/navigator.h b/src/navigator.h index ac3cc59..7b7ccf8 100644 --- a/src/navigator.h +++ b/src/navigator.h @@ -32,11 +32,11 @@ struct imv_navigator { int wrapped; }; -/* Initialises an instance of imv_navigator */ -void imv_navigator_init(struct imv_navigator *nav); +/* Creates an instance of imv_navigator */ +struct imv_navigator *imv_navigator_create(void); -/* Cleans up all resources owned by a imv_navigator instance */ -void imv_navigator_destroy(struct imv_navigator *nav); +/* Cleans up an imv_navigator instance */ +void imv_navigator_free(struct imv_navigator *nav); /* Adds the given path to the navigator's internal list. * If a directory is given, all files within that directory are added. diff --git a/test/navigator.c b/test/navigator.c index 55ab392..2aba317 100644 --- a/test/navigator.c +++ b/test/navigator.c @@ -19,78 +19,76 @@ static void test_navigator_add_remove(void **state) { (void)state; - struct imv_navigator nav; - imv_navigator_init(&nav); + struct imv_navigator *nav = imv_navigator_create(); /* Check poll_changed */ - assert_false(imv_navigator_poll_changed(&nav, 0)); + assert_false(imv_navigator_poll_changed(nav, 0)); /* Add 6 paths, one non-existant should fail */ - assert_false(imv_navigator_add(&nav, FILENAME1, 0)); - assert_false(imv_navigator_add(&nav, FILENAME2, 0)); - assert_false(imv_navigator_add(&nav, FILENAME3, 0)); - assert_false(imv_navigator_add(&nav, FILENAME4, 0)); - assert_false(imv_navigator_add(&nav, FILENAME5, 0)); - assert_false(imv_navigator_add(&nav, FILENAME6, 0)); - assert_int_equal(nav.num_paths, 6); + assert_false(imv_navigator_add(nav, FILENAME1, 0)); + assert_false(imv_navigator_add(nav, FILENAME2, 0)); + assert_false(imv_navigator_add(nav, FILENAME3, 0)); + assert_false(imv_navigator_add(nav, FILENAME4, 0)); + assert_false(imv_navigator_add(nav, FILENAME5, 0)); + assert_false(imv_navigator_add(nav, FILENAME6, 0)); + assert_int_equal(nav->num_paths, 6); /* Check poll_changed */ - assert_true(imv_navigator_poll_changed(&nav, 0)); + assert_true(imv_navigator_poll_changed(nav, 0)); /* Make sure current selection is #1 */ - assert_string_equal(imv_navigator_selection(&nav), FILENAME1); + assert_string_equal(imv_navigator_selection(nav), FILENAME1); /* Move right and remove current file (#2); should get to #3 */ - imv_navigator_select_rel(&nav, 1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME2); - imv_navigator_remove(&nav, FILENAME2); - assert_int_equal(nav.num_paths, 5); - assert_string_equal(imv_navigator_selection(&nav), FILENAME3); + imv_navigator_select_rel(nav, 1); + assert_string_equal(imv_navigator_selection(nav), FILENAME2); + imv_navigator_remove(nav, FILENAME2); + assert_int_equal(nav->num_paths, 5); + assert_string_equal(imv_navigator_selection(nav), FILENAME3); /* Move left and remove current file (#1); should get to #6 */ - imv_navigator_select_rel(&nav, -1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME1); - imv_navigator_remove(&nav, FILENAME1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME6); + imv_navigator_select_rel(nav, -1); + assert_string_equal(imv_navigator_selection(nav), FILENAME1); + imv_navigator_remove(nav, FILENAME1); + assert_string_equal(imv_navigator_selection(nav), FILENAME6); /* Move left, right, remove current file (#6); should get to #3 */ - imv_navigator_select_rel(&nav, -1); - imv_navigator_select_rel(&nav, 1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME6); - imv_navigator_remove(&nav, FILENAME6); - assert_string_equal(imv_navigator_selection(&nav), FILENAME3); + imv_navigator_select_rel(nav, -1); + imv_navigator_select_rel(nav, 1); + assert_string_equal(imv_navigator_selection(nav), FILENAME6); + imv_navigator_remove(nav, FILENAME6); + assert_string_equal(imv_navigator_selection(nav), FILENAME3); /* Remove #4; should not move */ - imv_navigator_remove(&nav, FILENAME4); - assert_string_equal(imv_navigator_selection(&nav), FILENAME3); + imv_navigator_remove(nav, FILENAME4); + assert_string_equal(imv_navigator_selection(nav), FILENAME3); /* Verify that #4 is removed by moving left; should get to #5 */ - imv_navigator_select_rel(&nav, 1); - assert_string_equal(imv_navigator_selection(&nav), FILENAME5); + imv_navigator_select_rel(nav, 1); + assert_string_equal(imv_navigator_selection(nav), FILENAME5); - imv_navigator_destroy(&nav); + imv_navigator_free(nav); } static void test_navigator_file_changed(void **state) { int fd; - struct imv_navigator nav; + struct imv_navigator *nav = imv_navigator_create(); struct timespec times[2] = { {0, 0}, {0, 0} }; (void)state; - imv_navigator_init(&nav); fd = open(FILENAME1, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd == -1) { - imv_navigator_destroy(&nav); + imv_navigator_free(nav); (void)unlink(FILENAME1); skip(); } assert_false(futimens(fd, times) == -1); - assert_false(imv_navigator_add(&nav, FILENAME1, 0)); - assert_true(imv_navigator_poll_changed(&nav, 0)); - assert_false(imv_navigator_poll_changed(&nav, 0)); + assert_false(imv_navigator_add(nav, FILENAME1, 0)); + assert_true(imv_navigator_poll_changed(nav, 0)); + assert_false(imv_navigator_poll_changed(nav, 0)); assert_false(sleep(1)); @@ -103,11 +101,11 @@ static void test_navigator_file_changed(void **state) times[1].tv_sec = UTIME_NOW; assert_false(futimens(fd, times) == -1); - assert_true(imv_navigator_poll_changed(&nav, 0)); + assert_true(imv_navigator_poll_changed(nav, 0)); (void)close(fd); (void)unlink(FILENAME1); - imv_navigator_destroy(&nav); + imv_navigator_free(nav); } int main(void) -- cgit v1.2.3 From cccb00ec0fa28d58bcebad8e9c8ff054657b725c Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 22:12:33 +0100 Subject: Move event handling into its own function --- src/main.c | 320 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 163 insertions(+), 157 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index adee798..0d7688e 100644 --- a/src/main.c +++ b/src/main.c @@ -202,6 +202,8 @@ void cmd_remove(struct imv_list *args); void cmd_fullscreen(struct imv_list *args); void cmd_overlay(struct imv_list *args); +void handle_event(SDL_Event *event); + int main(int argc, char** argv) { g_state.cmds = imv_commands_create(); @@ -390,163 +392,7 @@ int main(int argc, char** argv) /* handle any input/window events sent by SDL */ SDL_Event e; while(!g_state.quit && SDL_PollEvent(&e)) { - switch(e.type) { - case SDL_QUIT: - imv_command_exec(g_state.cmds, "quit"); - break; - - case SDL_KEYDOWN: - SDL_ShowCursor(SDL_DISABLE); - - if(g_state.command_buffer) { - /* in command mode, update the buffer */ - if(e.key.keysym.sym == SDLK_ESCAPE) { - free(g_state.command_buffer); - g_state.command_buffer = NULL; - g_state.need_redraw = 1; - } else if(e.key.keysym.sym == SDLK_RETURN) { - imv_command_exec(g_state.cmds, g_state.command_buffer); - free(g_state.command_buffer); - g_state.command_buffer = NULL; - g_state.need_redraw = 1; - } else if(e.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; - } - } else if(e.key.keysym.sym >= ' ' && e.key.keysym.sym <= '~') { - const size_t len = strlen(g_state.command_buffer); - if(len + 1 < 1024) { - g_state.command_buffer[len] = e.key.keysym.sym; - g_state.command_buffer[len+1] = '\0'; - g_state.need_redraw = 1; - } - } - - /* input has been consumed by command input, move onto next event */ - continue; - } - - switch (e.key.keysym.sym) { - case SDLK_SEMICOLON: - if(e.key.keysym.mod & KMOD_SHIFT) { - g_state.command_buffer = malloc(1024); - g_state.command_buffer[0] = '\0'; - g_state.need_redraw = 1; - } - break; - case SDLK_q: - imv_command_exec(g_state.cmds, "quit"); - break; - case SDLK_LEFTBRACKET: - case SDLK_LEFT: - imv_command_exec(g_state.cmds, "select_rel -1"); - break; - case SDLK_RIGHTBRACKET: - case SDLK_RIGHT: - imv_command_exec(g_state.cmds, "select_rel 1"); - 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(!e.key.repeat) { - if((g_options.scaling += 1) > FULL) { - g_options.scaling = NONE; - } - } - /* FALLTHROUGH */ - case SDLK_r: - if(!e.key.repeat) { - g_state.need_rescale = 1; - g_state.need_redraw = 1; - } - break; - case SDLK_a: - if(!e.key.repeat) { - imv_viewport_scale_to_actual(g_state.view, g_state.tex); - } - break; - case SDLK_c: - if(!e.key.repeat) { - imv_viewport_center(g_state.view, g_state.tex); - } - break; - case SDLK_j: - imv_command_exec(g_state.cmds, "pan 0 -50"); - break; - case SDLK_k: - imv_command_exec(g_state.cmds, "pan 0 50"); - break; - case SDLK_h: - imv_command_exec(g_state.cmds, "pan 50 0"); - break; - case SDLK_l: - imv_command_exec(g_state.cmds, "pan -50 0"); - break; - case SDLK_x: - if(!e.key.repeat) { - imv_command_exec(g_state.cmds, "remove"); - } - break; - case SDLK_f: - if(!e.key.repeat) { - imv_command_exec(g_state.cmds, "fullscreen"); - } - break; - case SDLK_PERIOD: - imv_loader_load_next_frame(g_state.ldr); - break; - case SDLK_SPACE: - if(!e.key.repeat) { - imv_viewport_toggle_playing(g_state.view); - } - break; - case SDLK_p: - if(!e.key.repeat) { - puts(imv_navigator_selection(g_state.nav)); - } - break; - case SDLK_d: - if(!e.key.repeat) { - imv_command_exec(g_state.cmds, "overlay"); - } - break; - case SDLK_t: - if(e.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, e.wheel.y); - SDL_ShowCursor(SDL_ENABLE); - break; - case SDL_MOUSEMOTION: - if(e.motion.state & SDL_BUTTON_LMASK) { - imv_viewport_move(g_state.view, e.motion.xrel, e.motion.yrel); - } - SDL_ShowCursor(SDL_ENABLE); - break; - case SDL_WINDOWEVENT: - imv_viewport_update(g_state.view, g_state.tex); - break; - } + handle_event(&e); } /* if we're quitting, don't bother drawing any more images */ @@ -853,4 +699,164 @@ void cmd_overlay(struct imv_list *args) g_state.need_redraw = 1; } +void handle_event(SDL_Event *event) +{ + switch(event->type) { + case SDL_QUIT: + imv_command_exec(g_state.cmds, "quit"); + 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) { + 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); + 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; + } + } else if(event->key.keysym.sym >= ' ' && event->key.keysym.sym <= '~') { + const size_t len = strlen(g_state.command_buffer); + if(len + 1 < 1024) { + g_state.command_buffer[len] = event->key.keysym.sym; + 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) { + g_state.command_buffer = malloc(1024); + g_state.command_buffer[0] = '\0'; + g_state.need_redraw = 1; + } + break; + case SDLK_q: + imv_command_exec(g_state.cmds, "quit"); + break; + case SDLK_LEFTBRACKET: + case SDLK_LEFT: + imv_command_exec(g_state.cmds, "select_rel -1"); + break; + case SDLK_RIGHTBRACKET: + case SDLK_RIGHT: + imv_command_exec(g_state.cmds, "select_rel 1"); + 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"); + break; + case SDLK_k: + imv_command_exec(g_state.cmds, "pan 0 50"); + break; + case SDLK_h: + imv_command_exec(g_state.cmds, "pan 50 0"); + break; + case SDLK_l: + imv_command_exec(g_state.cmds, "pan -50 0"); + break; + case SDLK_x: + if(!event->key.repeat) { + imv_command_exec(g_state.cmds, "remove"); + } + break; + case SDLK_f: + if(!event->key.repeat) { + imv_command_exec(g_state.cmds, "fullscreen"); + } + 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"); + } + 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; + } +} + /* vim:set ts=2 sts=2 sw=2 et: */ -- cgit v1.2.3 From f085f13f429d01a8f72e3b348a694124d5ba7533 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 22:34:14 +0100 Subject: Refactor navigator poll rate limiting --- src/main.c | 8 +------- src/navigator.c | 18 +++++++++++++++--- src/navigator.h | 4 +++- test/navigator.c | 13 ++++++++----- 4 files changed, 27 insertions(+), 16 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 0d7688e..4bdfe50 100644 --- a/src/main.c +++ b/src/main.c @@ -370,9 +370,6 @@ int main(int argc, char** argv) unsigned int last_time = SDL_GetTicks(); unsigned int current_time; - /* keep file change polling rate under control */ - static uint8_t poll_countdown = UINT8_MAX; - g_state.need_redraw = 1; g_state.need_rescale = 0; @@ -422,7 +419,7 @@ int main(int argc, char** argv) } /* if the user has changed image, start loading the new one */ - if(imv_navigator_poll_changed(g_state.nav, poll_countdown--)) { + 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) { @@ -560,9 +557,6 @@ int main(int argc, char** argv) /* redraw complete, unset the flag */ g_state.need_redraw = 0; - /* reset poll countdown timer */ - poll_countdown = UINT8_MAX; - /* tell SDL to show the newly drawn frame */ SDL_RenderPresent(g_state.renderer); } diff --git a/src/navigator.c b/src/navigator.c index 6abbfb1..ae7bccd 100644 --- a/src/navigator.c +++ b/src/navigator.c @@ -47,6 +47,10 @@ void imv_navigator_free(struct imv_navigator *nav) free(nav->mtimes); } + if(nav->ctimes) { + free(nav->ctimes); + } + free(nav); } @@ -56,19 +60,23 @@ static int add_item(struct imv_navigator *nav, const char *path, if(nav->num_paths % BUFFER_SIZE == 0) { char **new_paths; time_t *new_mtimes; + time_t *new_ctimes; size_t new_size = nav->num_paths + BUFFER_SIZE; new_paths = realloc(nav->paths, sizeof(char*) * new_size); new_mtimes = realloc(nav->mtimes, sizeof(time_t) * new_size); - if (new_paths == NULL || new_mtimes == NULL) { + new_ctimes = realloc(nav->ctimes, sizeof(time_t) * new_size); + if (new_paths == NULL || new_mtimes == NULL || new_ctimes == NULL) { return 1; } nav->paths = new_paths; nav->mtimes = new_mtimes; + nav->ctimes = new_ctimes; } if((nav->paths[nav->num_paths] = strndup(path, PATH_MAX)) == NULL) { return 1; } nav->mtimes[nav->num_paths] = mtime; + nav->ctimes[nav->num_paths] = time(NULL); nav->num_paths += 1; if(nav->num_paths == 1) { nav->changed = 1; @@ -218,7 +226,7 @@ int imv_navigator_find_path(struct imv_navigator *nav, const char *path) return -1; } -int imv_navigator_poll_changed(struct imv_navigator *nav, const int nopoll) +int imv_navigator_poll_changed(struct imv_navigator *nav) { if(nav->changed) { nav->changed = 0; @@ -229,7 +237,11 @@ int imv_navigator_poll_changed(struct imv_navigator *nav, const int nopoll) return 0; }; - if(!nopoll) { + time_t cur_time = time(NULL); + /* limit polling to once per second */ + if(nav->ctimes[nav->cur_path] < cur_time - 1) { + nav->ctimes[nav->cur_path] = cur_time; + struct stat file_info; if(stat(nav->paths[nav->cur_path], &file_info) == -1) { return 0; diff --git a/src/navigator.h b/src/navigator.h index 7b7ccf8..0d56fa7 100644 --- a/src/navigator.h +++ b/src/navigator.h @@ -27,9 +27,11 @@ struct imv_navigator { int cur_path; char **paths; time_t *mtimes; + time_t *ctimes; int last_move_direction; int changed; int wrapped; + int poll_countdown; }; /* Creates an instance of imv_navigator */ @@ -65,7 +67,7 @@ int imv_navigator_find_path(struct imv_navigator *nav, const char *path); /* Returns 1 if either the currently selected path or underlying file has * changed since last called */ -int imv_navigator_poll_changed(struct imv_navigator *nav, const int nopoll); +int imv_navigator_poll_changed(struct imv_navigator *nav); /* Check whether navigator wrapped around paths list */ int imv_navigator_wrapped(struct imv_navigator *nav); diff --git a/test/navigator.c b/test/navigator.c index 2aba317..3f2c50f 100644 --- a/test/navigator.c +++ b/test/navigator.c @@ -22,7 +22,7 @@ static void test_navigator_add_remove(void **state) struct imv_navigator *nav = imv_navigator_create(); /* Check poll_changed */ - assert_false(imv_navigator_poll_changed(nav, 0)); + assert_false(imv_navigator_poll_changed(nav)); /* Add 6 paths, one non-existant should fail */ assert_false(imv_navigator_add(nav, FILENAME1, 0)); @@ -34,7 +34,7 @@ static void test_navigator_add_remove(void **state) assert_int_equal(nav->num_paths, 6); /* Check poll_changed */ - assert_true(imv_navigator_poll_changed(nav, 0)); + assert_true(imv_navigator_poll_changed(nav)); /* Make sure current selection is #1 */ assert_string_equal(imv_navigator_selection(nav), FILENAME1); @@ -87,8 +87,8 @@ static void test_navigator_file_changed(void **state) assert_false(futimens(fd, times) == -1); assert_false(imv_navigator_add(nav, FILENAME1, 0)); - assert_true(imv_navigator_poll_changed(nav, 0)); - assert_false(imv_navigator_poll_changed(nav, 0)); + assert_true(imv_navigator_poll_changed(nav)); + assert_false(imv_navigator_poll_changed(nav)); assert_false(sleep(1)); @@ -101,7 +101,10 @@ static void test_navigator_file_changed(void **state) times[1].tv_sec = UTIME_NOW; assert_false(futimens(fd, times) == -1); - assert_true(imv_navigator_poll_changed(nav, 0)); + /* sleep to ensure we don't hit the poll rate-limiting */ + sleep(1); + + assert_true(imv_navigator_poll_changed(nav)); (void)close(fd); (void)unlink(FILENAME1); -- cgit v1.2.3 From c5c40915248fbd45af8820138a81057400fbcb55 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 22:42:38 +0100 Subject: Move rendering into its own function --- src/main.c | 129 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 69 insertions(+), 60 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 4bdfe50..3a9c4e4 100644 --- a/src/main.c +++ b/src/main.c @@ -42,7 +42,7 @@ enum scaling_mode { FULL }; -static char *scaling_label[] = { +static const char *scaling_label[] = { "actual size", "best fit", "perfect fit" @@ -203,6 +203,7 @@ void cmd_fullscreen(struct imv_list *args); void cmd_overlay(struct imv_list *args); void handle_event(SDL_Event *event); +void render_window(TTF_Font *text_font, SDL_Texture *bg_texture); int main(int argc, char** argv) { @@ -500,65 +501,7 @@ int main(int argc, char** argv) /* only redraw when something's changed */ if(g_state.need_redraw) { - /* update window title */ - int len; - const char *current_path = imv_navigator_selection(g_state.nav); - 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(g_state.renderer, - g_options.bg_r, g_options.bg_g, g_options.bg_b, 255); - SDL_RenderClear(g_state.renderer); - } else { - /* chequered background */ - int img_w, img_h; - SDL_QueryTexture(chequered_tex, 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(g_state.renderer, chequered_tex, 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 && font) { - SDL_Color fg = {255,255,255,255}; - SDL_Color bg = {0,0,0,160}; - imv_printf(g_state.renderer, font, 0, 0, &fg, &bg, "%s", - title + strlen("imv - ")); - } - - /* draw command entry bar if needed */ - if(g_state.command_buffer && font) { - SDL_Color fg = {255,255,255,255}; - SDL_Color bg = {0,0,0,160}; - imv_printf(g_state.renderer, - font, - 0, wh - TTF_FontHeight(font), - &fg, &bg, - ":%s", g_state.command_buffer); - } - - /* redraw complete, unset the flag */ - g_state.need_redraw = 0; - - /* tell SDL to show the newly drawn frame */ - SDL_RenderPresent(g_state.renderer); + render_window(font, chequered_tex); } /* sleep a little bit so we don't waste CPU time */ @@ -853,4 +796,70 @@ void handle_event(SDL_Event *event) } } +void render_window(TTF_Font *text_font, SDL_Texture *bg_texture) +{ + char title[1024]; + int ww, wh; + SDL_GetWindowSize(g_state.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(g_state.renderer, + g_options.bg_r, g_options.bg_g, g_options.bg_b, 255); + SDL_RenderClear(g_state.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(g_state.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(g_state.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(g_state.renderer, + text_font, + 0, wh - TTF_FontHeight(text_font), + &fg, &bg, + ":%s", g_state.command_buffer); + } + + /* redraw complete, unset the flag */ + g_state.need_redraw = 0; + + /* tell SDL to show the newly drawn frame */ + SDL_RenderPresent(g_state.renderer); +} + /* vim:set ts=2 sts=2 sw=2 et: */ -- cgit v1.2.3 From a461d4f26fd2d62433ff553f0305de52b1f407aa Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 22:55:54 +0100 Subject: Move some globals back to locals --- src/main.c | 55 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 3a9c4e4..dad28b1 100644 --- a/src/main.c +++ b/src/main.c @@ -178,8 +178,6 @@ struct { struct imv_texture *tex; struct imv_viewport *view; struct imv_commands *cmds; - SDL_Window *window; - SDL_Renderer *renderer; int quit; /* used to calculate when to skip to the next image in slideshow mode */ @@ -203,7 +201,11 @@ void cmd_fullscreen(struct imv_list *args); void cmd_overlay(struct imv_list *args); void handle_event(SDL_Event *event); -void render_window(TTF_Font *text_font, SDL_Texture *bg_texture); +void render_window( + SDL_Window *window, + SDL_Renderer *renderer, + TTF_Font *text_font, + SDL_Texture *bg_texture); int main(int argc, char** argv) { @@ -319,23 +321,23 @@ int main(int argc, char** argv) const int width = 1280; const int height = 720; - g_state.window = SDL_CreateWindow( + SDL_Window *window = SDL_CreateWindow( "imv", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE); - if(!g_state.window) { + if(!window) { fprintf(stderr, "SDL Failed to create window: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } /* we'll use SDL's built-in renderer, hardware accelerated if possible */ - g_state.renderer = SDL_CreateRenderer(g_state.window, -1, 0); - if(!g_state.renderer) { + SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); + if(!renderer) { fprintf(stderr, "SDL Failed to create renderer: %s\n", SDL_GetError()); - SDL_DestroyWindow(g_state.window); + SDL_DestroyWindow(window); SDL_Quit(); exit(1); } @@ -347,7 +349,7 @@ int main(int argc, char** argv) /* construct a chequered background texture */ SDL_Texture *chequered_tex = NULL; if(!g_options.solid_bg) { - chequered_tex = create_chequered(g_state.renderer); + chequered_tex = create_chequered(renderer); } /* set up the required fonts and surfaces for displaying the overlay */ @@ -359,8 +361,8 @@ int main(int argc, char** argv) /* create our main classes */ g_state.ldr = imv_loader_create(); - g_state.tex = imv_texture_create(g_state.renderer); - g_state.view = imv_viewport_create(g_state.window); + 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) { @@ -441,7 +443,7 @@ int main(int argc, char** argv) /* get window height and width */ int ww, wh; - SDL_GetWindowSize(g_state.window, &ww, &wh); + SDL_GetWindowSize(window, &ww, &wh); /* check if a new image is available to display */ FIBITMAP *bmp; @@ -501,7 +503,9 @@ int main(int argc, char** argv) /* only redraw when something's changed */ if(g_state.need_redraw) { - render_window(font, chequered_tex); + render_window(window, renderer, font, chequered_tex); + /* tell SDL to show the newly drawn frame */ + SDL_RenderPresent(renderer); } /* sleep a little bit so we don't waste CPU time */ @@ -564,8 +568,8 @@ int main(int argc, char** argv) if(chequered_tex) { SDL_DestroyTexture(chequered_tex); } - SDL_DestroyRenderer(g_state.renderer); - SDL_DestroyWindow(g_state.window); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); SDL_Quit(); return 0; @@ -796,11 +800,15 @@ void handle_event(SDL_Event *event) } } -void render_window(TTF_Font *text_font, SDL_Texture *bg_texture) +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(g_state.window, &ww, &wh); + SDL_GetWindowSize(window, &ww, &wh); /* update window title */ const char *current_path = imv_navigator_selection(g_state.nav); @@ -817,9 +825,9 @@ void render_window(TTF_Font *text_font, SDL_Texture *bg_texture) /* first we draw the background */ if(g_options.solid_bg) { /* solid background */ - SDL_SetRenderDrawColor(g_state.renderer, + SDL_SetRenderDrawColor(renderer, g_options.bg_r, g_options.bg_g, g_options.bg_b, 255); - SDL_RenderClear(g_state.renderer); + SDL_RenderClear(renderer); } else { /* background */ int img_w, img_h; @@ -828,7 +836,7 @@ void render_window(TTF_Font *text_font, SDL_Texture *bg_texture) 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(g_state.renderer, bg_texture, NULL, &dst_rect); + SDL_RenderCopy(renderer, bg_texture, NULL, &dst_rect); } } } @@ -840,7 +848,7 @@ void render_window(TTF_Font *text_font, SDL_Texture *bg_texture) if(g_options.overlay && text_font) { SDL_Color fg = {255,255,255,255}; SDL_Color bg = {0,0,0,160}; - imv_printf(g_state.renderer, text_font, 0, 0, &fg, &bg, "%s", + imv_printf(renderer, text_font, 0, 0, &fg, &bg, "%s", title + strlen("imv - ")); } @@ -848,7 +856,7 @@ void render_window(TTF_Font *text_font, SDL_Texture *bg_texture) if(g_state.command_buffer && text_font) { SDL_Color fg = {255,255,255,255}; SDL_Color bg = {0,0,0,160}; - imv_printf(g_state.renderer, + imv_printf(renderer, text_font, 0, wh - TTF_FontHeight(text_font), &fg, &bg, @@ -857,9 +865,6 @@ void render_window(TTF_Font *text_font, SDL_Texture *bg_texture) /* redraw complete, unset the flag */ g_state.need_redraw = 0; - - /* tell SDL to show the newly drawn frame */ - SDL_RenderPresent(g_state.renderer); } /* vim:set ts=2 sts=2 sw=2 et: */ -- cgit v1.2.3 From 3900415f5bde879b11c43b7b1daa4ff5533b0794 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 22:56:58 +0100 Subject: Move parse_args to end of main.c --- src/main.c | 182 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 92 insertions(+), 90 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index dad28b1..0406c04 100644 --- a/src/main.c +++ b/src/main.c @@ -82,96 +82,6 @@ struct { .font = "Monospace:24", }; -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); - } - } -} - struct { struct imv_navigator *nav; struct imv_loader *ldr; @@ -200,6 +110,7 @@ void cmd_remove(struct imv_list *args); void cmd_fullscreen(struct imv_list *args); void cmd_overlay(struct imv_list *args); +static void parse_args(int argc, char** argv); void handle_event(SDL_Event *event); void render_window( SDL_Window *window, @@ -640,6 +551,97 @@ void cmd_overlay(struct imv_list *args) 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); + } + } +} + + void handle_event(SDL_Event *event) { switch(event->type) { -- cgit v1.2.3 From b2fc7c3978d2da4d1f559b15ba36f36fafbf297d Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 23:29:51 +0100 Subject: Minor clean up of main.c --- src/main.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 0406c04..09394c5 100644 --- a/src/main.c +++ b/src/main.c @@ -110,7 +110,7 @@ void cmd_remove(struct imv_list *args); void cmd_fullscreen(struct imv_list *args); void cmd_overlay(struct imv_list *args); -static void parse_args(int argc, char** argv); +static void parse_args(int *argc, char ***argv); void handle_event(SDL_Event *event); void render_window( SDL_Window *window, @@ -139,10 +139,7 @@ int main(int argc, char** argv) g_state.nav = imv_navigator_create(); /* parse any command line options given */ - parse_args(argc, argv); - - argc -= optind; - argv += optind; + parse_args(&argc, &argv); /* if no names are given, expect them on stdin */ if(argc == 0) { @@ -185,12 +182,16 @@ int main(int argc, char** argv) /* handle any image paths given as arguments */ for(int i = 0; i < argc; ++i) { - /* special case: '-' is actually an option */ + + /* 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); @@ -209,6 +210,7 @@ int main(int argc, char** argv) /* 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); } @@ -224,6 +226,7 @@ int main(int argc, char** argv) /* 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); } @@ -240,6 +243,7 @@ int main(int argc, char** argv) 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); } @@ -248,6 +252,7 @@ int main(int argc, char** argv) 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); @@ -315,6 +320,8 @@ int main(int argc, char** argv) 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; @@ -336,11 +343,11 @@ int main(int argc, char** argv) 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) { - continue; + if(!g_options.stdin_list) { + fprintf(stderr, "No input files left. Exiting.\n"); + g_state.quit = 1; } - fprintf(stderr, "No input files left. Exiting.\n"); - exit(1); + continue; } snprintf(title, sizeof(title), "imv - [%i/%i] [LOADING] %s [%s]", @@ -352,9 +359,6 @@ int main(int argc, char** argv) g_state.view->playing = 1; } - /* get window height and width */ - int ww, wh; - SDL_GetWindowSize(window, &ww, &wh); /* check if a new image is available to display */ FIBITMAP *bmp; @@ -369,6 +373,9 @@ int main(int argc, char** argv) } 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)) { @@ -419,7 +426,7 @@ int main(int argc, char** argv) SDL_RenderPresent(renderer); } - /* sleep a little bit so we don't waste CPU time */ + /* 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"); @@ -449,6 +456,7 @@ int main(int argc, char** argv) } } } else { + /* sleep a little bit so we don't waste CPU time */ SDL_Delay(10); } } @@ -569,15 +577,15 @@ static void print_usage(void) , IMV_VERSION); } -static void parse_args(int argc, char** argv) +static void parse_args(int *argc, char ***argv) { /* Do not print getopt errors */ opterr = 0; - char *argp, *ep = *argv; + char *argp, *ep = **argv; int o; - while((o = getopt(argc, argv, "firasSudxhln:b:e:t:")) != -1) { + while((o = getopt(*argc, *argv, "firasSudxhln:b:e:t:")) != -1) { switch(o) { case 'f': g_options.fullscreen = 1; break; case 'i': @@ -639,6 +647,9 @@ static void parse_args(int argc, char** argv) exit(1); } } + + *argc -= optind; + *argv += optind; } -- cgit v1.2.3 From ec0923e5cf9715943b198ea5c6f60e1037cef248 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 14 Apr 2017 23:49:43 +0100 Subject: Fix command text input --- src/main.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 09394c5..d0cfb78 100644 --- a/src/main.c +++ b/src/main.c @@ -299,6 +299,7 @@ int main(int argc, char** argv) /* start outside of command mode */ g_state.command_buffer = NULL; + SDL_StopTextInput(); /* initialize variables holding image dimentions */ int iw = 0, ih = 0; @@ -655,22 +656,30 @@ static void parse_args(int *argc, char ***argv) 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"); 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); + SDL_StopTextInput(); free(g_state.command_buffer); g_state.command_buffer = NULL; g_state.need_redraw = 1; @@ -680,13 +689,6 @@ void handle_event(SDL_Event *event) g_state.command_buffer[len - 1] = '\0'; g_state.need_redraw = 1; } - } else if(event->key.keysym.sym >= ' ' && event->key.keysym.sym <= '~') { - const size_t len = strlen(g_state.command_buffer); - if(len + 1 < 1024) { - g_state.command_buffer[len] = event->key.keysym.sym; - g_state.command_buffer[len+1] = '\0'; - g_state.need_redraw = 1; - } } return; @@ -695,7 +697,8 @@ void handle_event(SDL_Event *event) switch (event->key.keysym.sym) { case SDLK_SEMICOLON: if(event->key.keysym.mod & KMOD_SHIFT) { - g_state.command_buffer = malloc(1024); + SDL_StartTextInput(); + g_state.command_buffer = malloc(command_buffer_len); g_state.command_buffer[0] = '\0'; g_state.need_redraw = 1; } -- cgit v1.2.3 From a6bb8ad100348693a39ea13ba6af361f2dab5101 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Sat, 15 Apr 2017 10:58:31 +0100 Subject: Let commands take an arbitrary pointer --- src/commands.c | 8 ++++---- src/commands.h | 4 ++-- src/main.c | 64 +++++++++++++++++++++++++++++++++------------------------- 3 files changed, 42 insertions(+), 34 deletions(-) (limited to 'src/main.c') diff --git a/src/commands.c b/src/commands.c index a3a59b1..0f31bfc 100644 --- a/src/commands.c +++ b/src/commands.c @@ -20,7 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. struct command { char* command; - void (*handler)(struct imv_list *args); + void (*handler)(struct imv_list *args, void *data); char* alias; }; @@ -63,7 +63,7 @@ void imv_command_alias(struct imv_commands *cmds, const char *command, const cha imv_list_append(cmds->command_list, cmd); } -int imv_command_exec(struct imv_commands *cmds, const char *command) +int imv_command_exec(struct imv_commands *cmds, const char *command, void *data) { struct imv_list *args = imv_split_string(command, ' '); int ret = 1; @@ -73,10 +73,10 @@ int imv_command_exec(struct imv_commands *cmds, const char *command) struct command *cmd = cmds->command_list->items[i]; if(!strcmp(cmd->command, args->items[0])) { if(cmd->handler) { - cmd->handler(args); + cmd->handler(args, data); ret = 0; } else if(cmd->alias) { - ret = imv_command_exec(cmds, cmd->alias); + ret = imv_command_exec(cmds, cmd->alias, data); } break; } diff --git a/src/commands.h b/src/commands.h index df8b43b..89f94a2 100644 --- a/src/commands.h +++ b/src/commands.h @@ -24,11 +24,11 @@ struct imv_commands { struct imv_list *command_list; }; -struct imv_commands *imv_commands_create(void); +struct imv_commands *imv_commands_create(); void imv_commands_free(struct imv_commands *cmds); void imv_command_register(struct imv_commands *cmds, const char *command, void (*handler)()); void imv_command_alias(struct imv_commands *cmds, const char *command, const char *alias); -int imv_command_exec(struct imv_commands *cmds, const char *command); +int imv_command_exec(struct imv_commands *cmds, const char *command, void *data); #endif diff --git a/src/main.c b/src/main.c index d0cfb78..8cbd095 100644 --- a/src/main.c +++ b/src/main.c @@ -101,14 +101,14 @@ struct { char *command_buffer; } g_state; -void cmd_quit(struct imv_list *args); -void cmd_pan(struct imv_list *args); -void cmd_select_rel(struct imv_list *args); -void cmd_select_abs(struct imv_list *args); -void cmd_zoom(struct imv_list *args); -void cmd_remove(struct imv_list *args); -void cmd_fullscreen(struct imv_list *args); -void cmd_overlay(struct imv_list *args); +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); @@ -495,14 +495,16 @@ int main(int argc, char** argv) return 0; } -void cmd_quit(struct imv_list *args) +void cmd_quit(struct imv_list *args, void *data) { (void)args; + (void)data; g_state.quit = 1; } -void cmd_pan(struct imv_list *args) +void cmd_pan(struct imv_list *args, void *data) { + (void)data; if(args->len != 3) { return; } @@ -513,8 +515,9 @@ void cmd_pan(struct imv_list *args) imv_viewport_move(g_state.view, x, y); } -void cmd_select_rel(struct imv_list *args) +void cmd_select_rel(struct imv_list *args, void *data) { + (void)data; if(args->len != 2) { return; } @@ -526,19 +529,22 @@ void cmd_select_rel(struct imv_list *args) g_state.delay_msec = 0; } -void cmd_select_abs(struct imv_list *args) +void cmd_select_abs(struct imv_list *args, void *data) { (void)args; + (void)data; } -void cmd_zoom(struct imv_list *args) +void cmd_zoom(struct imv_list *args, void *data) { (void)args; + (void)data; } -void cmd_remove(struct imv_list *args) +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); @@ -547,15 +553,17 @@ void cmd_remove(struct imv_list *args) g_state.delay_msec = 0; } -void cmd_fullscreen(struct imv_list *args) +void cmd_fullscreen(struct imv_list *args, void *data) { (void)args; + (void)data; imv_viewport_toggle_fullscreen(g_state.view); } -void cmd_overlay(struct imv_list *args) +void cmd_overlay(struct imv_list *args, void *data) { (void)args; + (void)data; g_options.overlay = !g_options.overlay; g_state.need_redraw = 1; } @@ -659,7 +667,7 @@ 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"); + imv_command_exec(g_state.cmds, "quit", NULL); break; case SDL_TEXTINPUT: @@ -678,7 +686,7 @@ void handle_event(SDL_Event *event) 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); + imv_command_exec(g_state.cmds, g_state.command_buffer, NULL); SDL_StopTextInput(); free(g_state.command_buffer); g_state.command_buffer = NULL; @@ -704,15 +712,15 @@ void handle_event(SDL_Event *event) } break; case SDLK_q: - imv_command_exec(g_state.cmds, "quit"); + imv_command_exec(g_state.cmds, "quit", NULL); break; case SDLK_LEFTBRACKET: case SDLK_LEFT: - imv_command_exec(g_state.cmds, "select_rel -1"); + 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"); + imv_command_exec(g_state.cmds, "select_rel 1", NULL); break; case SDLK_EQUALS: case SDLK_PLUS: @@ -749,25 +757,25 @@ void handle_event(SDL_Event *event) } break; case SDLK_j: - imv_command_exec(g_state.cmds, "pan 0 -50"); + imv_command_exec(g_state.cmds, "pan 0 -50", NULL); break; case SDLK_k: - imv_command_exec(g_state.cmds, "pan 0 50"); + imv_command_exec(g_state.cmds, "pan 0 50", NULL); break; case SDLK_h: - imv_command_exec(g_state.cmds, "pan 50 0"); + imv_command_exec(g_state.cmds, "pan 50 0", NULL); break; case SDLK_l: - imv_command_exec(g_state.cmds, "pan -50 0"); + 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"); + imv_command_exec(g_state.cmds, "remove", NULL); } break; case SDLK_f: if(!event->key.repeat) { - imv_command_exec(g_state.cmds, "fullscreen"); + imv_command_exec(g_state.cmds, "fullscreen", NULL); } break; case SDLK_PERIOD: @@ -785,7 +793,7 @@ void handle_event(SDL_Event *event) break; case SDLK_d: if(!event->key.repeat) { - imv_command_exec(g_state.cmds, "overlay"); + imv_command_exec(g_state.cmds, "overlay", NULL); } break; case SDLK_t: -- cgit v1.2.3 From eff4ee3fb359d747610ee706e904c8914841a6ba Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Tue, 6 Jun 2017 20:27:21 +0100 Subject: Switch to new implementation --- src/main.c | 876 +------------------------------------------------------------ 1 file changed, 11 insertions(+), 865 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 8cbd095..c2eb394 100644 --- a/src/main.c +++ b/src/main.c @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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: */ -- cgit v1.2.3