aboutsummaryrefslogtreecommitdiff
path: root/src/imv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/imv.c')
-rw-r--r--src/imv.c190
1 files changed, 160 insertions, 30 deletions
diff --git a/src/imv.c b/src/imv.c
index afefce7..db2a9fb 100644
--- a/src/imv.c
+++ b/src/imv.c
@@ -24,11 +24,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
+#include <wordexp.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include "commands.h"
+#include "ini.h"
#include "list.h"
#include "loader.h"
#include "texture.h"
@@ -91,6 +93,11 @@ struct imv {
bool ttf_init;
};
+enum config_section {
+ CFG_OPTIONS,
+ CFG_BINDS
+};
+
void command_quit(struct imv_list *args, void *data);
void command_pan(struct imv_list *args, void *data);
void command_select_rel(struct imv_list *args, void *data);
@@ -187,12 +194,56 @@ void imv_free(struct imv *imv)
free(imv);
}
+static bool parse_bg(struct imv *imv, const char *bg)
+{
+ if(strcmp("checks", bg) == 0) {
+ imv->background_type = BACKGROUND_CHEQUERED;
+ } else {
+ imv->background_type = BACKGROUND_SOLID;
+ if(*bg == '#')
+ ++bg;
+ char *ep;
+ uint32_t n = strtoul(bg, &ep, 16);
+ if(*ep != '\0' || ep - bg != 6 || n > 0xFFFFFF) {
+ fprintf(stderr, "Invalid hex color: '%s'\n", bg);
+ return false;
+ }
+ imv->background_color.b = n & 0xFF;
+ imv->background_color.g = (n >> 8) & 0xFF;
+ imv->background_color.r = (n >> 16);
+ }
+ return true;
+}
+
+static bool parse_slideshow_duration(struct imv *imv, const char *duration)
+{
+ char *decimal;
+ imv->slideshow_image_duration = strtoul(duration, &decimal, 10);
+ imv->slideshow_image_duration *= 1000;
+ if (*decimal == '.') {
+ char *ep;
+ long delay = strtoul(++decimal, &ep, 10);
+ for (int i = 3 - (ep - decimal); i; i--) {
+ delay *= 10;
+ }
+ if (delay < 1000) {
+ imv->slideshow_image_duration += delay;
+ } else {
+ imv->slideshow_image_duration = ULONG_MAX;
+ }
+ }
+ if (imv->slideshow_image_duration == ULONG_MAX) {
+ fprintf(stderr, "Wrong slideshow delay '%s'. Aborting.\n", optarg);
+ return false;
+ }
+ return true;
+}
+
bool imv_parse_args(struct imv *imv, int argc, char **argv)
{
/* Do not print getopt errors */
opterr = 0;
- char *argp, *ep = *argv;
int o;
while((o = getopt(argc, argv, "frasSudxhln:b:e:t:")) != -1) {
@@ -226,37 +277,12 @@ bool imv_parse_args(struct imv *imv, int argc, char **argv)
imv->quit = true;
return true;
case 'b':
- if(strcmp("checks", optarg) == 0) {
- imv->background_type = BACKGROUND_CHEQUERED;
- } else {
- imv->background_type = BACKGROUND_SOLID;
- 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);
- return false;
- }
- imv->background_color.b = n & 0xFF;
- imv->background_color.g = (n >> 8) & 0xFF;
- imv->background_color.r = (n >> 16);
+ if(!parse_bg(imv, optarg)) {
+ return false;
}
break;
case 't':
- imv->slideshow_image_duration = strtoul(optarg, &argp, 10);
- imv->slideshow_image_duration *= 1000;
- if (*argp == '.') {
- long delay = strtoul(++argp, &ep, 10);
- for (int i = 3 - (ep - argp); i; i--) {
- delay *= 10;
- }
- if (delay < 1000) {
- imv->slideshow_image_duration += delay;
- } else {
- imv->slideshow_image_duration = ULONG_MAX;
- }
- }
- if (imv->slideshow_image_duration == ULONG_MAX) {
- fprintf(stderr, "Wrong slideshow delay '%s'. Aborting.\n", optarg);
+ if(!parse_slideshow_duration(imv, optarg)) {
return false;
}
break;
@@ -409,7 +435,7 @@ int imv_run(struct imv *imv)
imv_navigator_remove(imv->navigator, err_path);
/* special case: the image came from stdin */
- if(strncmp(err_path, "-", 2) == 0) {
+ if(strcmp(err_path, "-") == 0) {
if(imv->stdin_image_data) {
free(imv->stdin_image_data);
imv->stdin_image_data = NULL;
@@ -834,6 +860,110 @@ static void render_window(struct imv *imv)
imv->need_redraw = false;
}
+static char *get_config_path(void)
+{
+ const char *config_paths[] = {
+ "$HOME/.imv_config",
+ "$HOME/.imv/config",
+ "$XDG_CONFIG_HOME/imv/config",
+ };
+
+ for(size_t i = 0; i < sizeof(config_paths) / sizeof(char*); ++i) {
+ wordexp_t word;
+ if(wordexp(config_paths[i], &word, 0) == 0) {
+ char *path = strdup(word.we_wordv[0]);
+ wordfree(&word);
+
+ if(!path || access(path, R_OK) == -1) {
+ free(path);
+ continue;
+ }
+
+ return path;
+ }
+ }
+ return NULL;
+}
+
+static bool parse_bool(const char *str)
+{
+ return (
+ !strcmp(str, "1") ||
+ !strcmp(str, "yes") ||
+ !strcmp(str, "true") ||
+ !strcmp(str, "on")
+ );
+}
+
+bool imv_load_config(struct imv *imv)
+{
+ const char *path = get_config_path();
+ if(!path) {
+ return true;
+ }
+
+ FILE *f = fopen(path, "r");
+ if (!f) {
+ fprintf(stderr, "Unable to open config file: %s\n", path);
+ return false;
+ }
+
+ enum config_section sect = CFG_OPTIONS;
+ int type;
+ do {
+ char key[128], value[128];
+ type = parse_ini_file(f, &key[0], sizeof(key), &value[0], sizeof(value));
+
+ if(type == INI_SECTION) {
+ if(!strcmp(key, "binds")) {
+ sect = CFG_BINDS;
+ } else {
+ fprintf(stderr, "Unknown config section: %s\n", key);
+ return false;
+ }
+ } else if(type == INI_VALUE) {
+ if(sect == CFG_OPTIONS) {
+ if(!strcmp(key, "fullscreen")) {
+ imv->fullscreen = parse_bool(value);
+ } else if(!strcmp(key, "overlay")) {
+ imv->overlay_enabled = parse_bool(value);
+ } else if(!strcmp(key, "sampling")) {
+ imv->nearest_neighbour = !strcmp(value, "nearest_neighbour");
+ } else if(!strcmp(key, "recursive")) {
+ imv->recursive_load = parse_bool(value);
+ } else if(!strcmp(key, "cycle_input")) {
+ imv->cycle_input = parse_bool(value);
+ } else if(!strcmp(key, "list_at_exit")) {
+ imv->list_at_exit = parse_bool(value);
+ } else if(!strcmp(key, "scaling")) {
+ if(!strcmp(value, "none")) {
+ imv->scaling_mode = SCALING_NONE;
+ } else if(!strcmp(value, "shrink")) {
+ imv->scaling_mode = SCALING_DOWN;
+ } else if(!strcmp(value, "full")) {
+ imv->scaling_mode = SCALING_FULL;
+ }
+ } else if(!strcmp(key, "background")) {
+ if(!parse_bg(imv, value)) {
+ return false;
+ }
+ } else if(!strcmp(key, "slideshow")) {
+ if(!parse_slideshow_duration(imv, value)) {
+ return false;
+ }
+ } else if(!strcmp(key, "overlay_font")) {
+ free(imv->font_name);
+ imv->font_name = strdup(value);
+ } else {
+ fprintf(stderr, "Ignoring unknown option: %s\n", key);
+ }
+ }
+ }
+ } while(type);
+
+ return true;
+}
+
void command_quit(struct imv_list *args, void *data)
{
(void)args;