Command line auto-completion - further enhancements
[geeqie.git] / src / main.cc
index 322f10d..f03e1f5 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <signal.h>
-#include <sys/mman.h>
+#include "main.h"
+
+#include <unistd.h>
+
+#include <clocale>
+#include <csignal>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
 
-#ifdef G_OS_UNIX
-#include <pwd.h>
+#include <config.h>
+
+#if HAVE_CLUTTER
+#  include <clutter-gtk/clutter-gtk.h>
+#  include <clutter/clutter.h>
 #endif
-#include <locale.h>
 
-#include "main.h"
+#if HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
+#include <gdk/gdk.h>
+#include <gio/gio.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#ifdef ENABLE_NLS
+#  include <libintl.h>
+#endif
+
+#if HAVE_DEVELOPER
+#include "third-party/backward.h"
+#endif
 
+#include "cache-maint.h"
 #include "cache.h"
-#include "collect.h"
 #include "collect-io.h"
+#include "collect.h"
+#include "compat.h"
+#include "debug.h"
+#include "exif.h"
 #include "filedata.h"
 #include "filefilter.h"
+#include "glua.h"
+#include "histogram.h"
 #include "history-list.h"
 #include "image.h"
 #include "img-view.h"
+#include "intl.h"
 #include "layout-image.h"
 #include "layout-util.h"
+#include "layout.h"
+#include "main-defines.h"
+#include "metadata.h"
 #include "misc.h"
+#include "options.h"
+#include "pixbuf-util.h"
 #include "rcfile.h"
 #include "remote.h"
 #include "secure-save.h"
+#include "third-party/whereami.h"
+#include "thumb.h"
 #include "ui-fileops.h"
 #include "ui-utildlg.h"
-#include "cache-maint.h"
-#include "thumb.h"
-#include "metadata.h"
-#include "exif.h"
-#include "histogram.h"
-#include "pixbuf-util.h"
-#include "glua.h"
-#include "whereami.h"
-
-#ifdef HAVE_CLUTTER
-#include <clutter-gtk/clutter-gtk.h>
-#endif
-
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
 
 gboolean thumb_format_changed = FALSE;
-static RemoteConnection *remote_connection = NULL;
+static RemoteConnection *remote_connection = nullptr;
 
 gchar *gq_prefix;
 gchar *gq_localedir;
@@ -76,15 +98,15 @@ gchar *desktop_file_template;
 gchar *instance_identifier;
 
 #if defined(SA_SIGINFO)
-void sig_handler_cb(int signo, siginfo_t *info, void *UNUSED(context))
+void sig_handler_cb(int signo, siginfo_t *info, void *)
 {
        gchar hex_char[16];
-       const gchar *signal_name = NULL;
+       const gchar *signal_name = nullptr;
        gint i = 0;
        guint64 addr;
        guint64 char_index;
        ssize_t len;
-#ifdef HAVE_EXECINFO_H
+#if HAVE_EXECINFO_H
        gint bt_size;
        void *bt[1024];
 #endif
@@ -149,7 +171,7 @@ void sig_handler_cb(int signo, siginfo_t *info, void *UNUSED(context))
 
        len = write(STDERR_FILENO, "Address: ", 9);
 
-       if (info->si_addr == 0)
+       if (info->si_addr == nullptr)
                {
                len = write(STDERR_FILENO, "0x0\n", 4);
                }
@@ -170,17 +192,20 @@ void sig_handler_cb(int signo, siginfo_t *info, void *UNUSED(context))
                len = write(STDERR_FILENO, "\n", 1);
                }
 
-#ifdef HAVE_EXECINFO_H
+#if HAVE_EXECINFO_H
        bt_size = backtrace(bt, 1024);
        backtrace_symbols_fd(bt, bt_size, STDERR_FILENO);
 #endif
 
+       /* Avoid "not used" warning */
+       len++;
+
        exit(EXIT_FAILURE);
 }
 #else /* defined(SA_SIGINFO) */
-void sig_handler_cb(int UNUSED(signo))
+void sig_handler_cb(int)
 {
-#ifdef HAVE_EXECINFO_H
+#if HAVE_EXECINFO_H
        gint bt_size;
        void *bt[1024];
 #endif
@@ -188,7 +213,7 @@ void sig_handler_cb(int UNUSED(signo))
        write(STDERR_FILENO, "Geeqie fatal error\n", 19);
        write(STDERR_FILENO, "Signal: Segmentation fault\n", 27);
 
-#ifdef HAVE_EXECINFO_H
+#if HAVE_EXECINFO_H
        bt_size = backtrace(bt, 1024);
        backtrace_symbols_fd(bt, bt_size, STDERR_FILENO);
 #endif
@@ -197,53 +222,6 @@ void sig_handler_cb(int UNUSED(signo))
 }
 #endif /* defined(SA_SIGINFO) */
 
-/*
- *-----------------------------------------------------------------------------
- * keyboard functions
- *-----------------------------------------------------------------------------
- */
-
-void keyboard_scroll_calc(gint *x, gint *y, GdkEventKey *event)
-{
-       static gint delta = 0;
-       static guint32 time_old = 0;
-       static guint keyval_old = 0;
-
-       if (event->state & GDK_CONTROL_MASK)
-               {
-               if (*x < 0) *x = G_MININT / 2;
-               if (*x > 0) *x = G_MAXINT / 2;
-               if (*y < 0) *y = G_MININT / 2;
-               if (*y > 0) *y = G_MAXINT / 2;
-
-               return;
-               }
-
-       if (options->progressive_key_scrolling)
-               {
-               guint32 time_diff;
-
-               time_diff = event->time - time_old;
-
-               /* key pressed within 125ms ? (1/8 second) */
-               if (time_diff > 125 || event->keyval != keyval_old) delta = 0;
-
-               time_old = event->time;
-               keyval_old = event->keyval;
-
-               delta += 2;
-               }
-       else
-               {
-               delta = 8;
-               }
-
-       *x = *x * delta * options->keyboard_scroll_step;
-       *y = *y * delta * options->keyboard_scroll_step;
-}
-
-
-
 /*
  *-----------------------------------------------------------------------------
  * command line parser (private) hehe, who needs popt anyway?
@@ -270,8 +248,7 @@ static void parse_command_line_add_file(const gchar *file_path, gchar **path, gc
                }
 }
 
-static void parse_command_line_add_dir(const gchar *dir, gchar **UNUSED(path), gchar **UNUSED(file),
-                                      GList **UNUSED(list))
+static void parse_command_line_add_dir(const gchar *dir, gchar **, gchar **, GList **)
 {
 #if 0
        /* This is broken because file filter is not initialized yet.
@@ -327,7 +304,7 @@ static void parse_command_line_process_dir(const gchar *dir, gchar **path, gchar
                        {
                        parse_command_line_add_dir(*first_dir, path, file, list);
                        g_free(*first_dir);
-                       *first_dir = NULL;
+                       *first_dir = nullptr;
                        }
                parse_command_line_add_dir(dir, path, file, list);
                }
@@ -341,30 +318,30 @@ static void parse_command_line_process_file(const gchar *file_path, gchar **path
                {
                parse_command_line_add_dir(*first_dir, path, file, list);
                g_free(*first_dir);
-               *first_dir = NULL;
+               *first_dir = nullptr;
                }
        parse_command_line_add_file(file_path, path, file, list, collection_list);
 }
 
 static void parse_command_line(gint argc, gchar *argv[])
 {
-       GList *list = NULL;
-       GList *remote_list = NULL;
-       GList *remote_errors = NULL;
+       GList *list = nullptr;
+       GList *remote_list = nullptr;
+       GList *remote_errors = nullptr;
        gboolean remote_do = FALSE;
-       gchar *first_dir = NULL;
+       gchar *first_dir = nullptr;
        gchar *app_lock;
        gchar *pwd;
        gchar *current_dir;
-       gchar *geometry = NULL;
+       gchar *geometry = nullptr;
        GtkWidget *dialog_warning;
-       GString *command_line_errors = g_string_new(NULL);
+       GString *command_line_errors = g_string_new(nullptr);
 
        command_line = g_new0(CommandLine, 1);
 
        command_line->argc = argc;
        command_line->argv = argv;
-       command_line->regexp = NULL;
+       command_line->regexp = nullptr;
 
        if (argc > 1)
                {
@@ -394,12 +371,12 @@ static void parse_command_line(gint argc, gchar *argv[])
                                parse_command_line_process_file(cmd_all, &command_line->path, &command_line->file,
                                                                &list, &command_line->collection_list, &first_dir);
                                }
-                       else if (download_web_file(cmd_line, FALSE, NULL))
+                       else if (download_web_file(cmd_line, FALSE, nullptr))
                                {
                                }
                        else if (is_collection(cmd_line))
                                {
-                               gchar *path = NULL;
+                               gchar *path = nullptr;
 
                                path = collection_path(cmd_line);
                                parse_command_line_process_file(path, &command_line->path, &command_line->file,
@@ -414,12 +391,12 @@ static void parse_command_line(gint argc, gchar *argv[])
                                {
                                /* do nothing but do not produce warnings */
                                }
-                       else if (strcmp(cmd_line, "+t") == 0 ||
+                       else if (strcmp(cmd_line, "-T") == 0 ||
                                 strcmp(cmd_line, "--with-tools") == 0)
                                {
                                command_line->tools_show = TRUE;
 
-                               remote_list = g_list_append(remote_list, g_strdup("+t"));
+                               remote_list = g_list_append(remote_list, g_strdup("-T"));
                                }
                        else if (strcmp(cmd_line, "-t") == 0 ||
                                 strcmp(cmd_line, "--without-tools") == 0)
@@ -456,26 +433,26 @@ static void parse_command_line(gint argc, gchar *argv[])
                                        remote_list = remote_build_list(remote_list, argc - i, &argv[i], &remote_errors);
                                        }
                                }
-                       else if ((strcmp(cmd_line, "+w") == 0) ||
+                       else if ((strcmp(cmd_line, "-w") == 0) ||
                                                strcmp(cmd_line, "--show-log-window") == 0)
                                {
                                command_line->log_window_show = TRUE;
                                }
-                       else if (strncmp(cmd_line, "-o:", 3) == 0)
+                       else if (strncmp(cmd_line, "-o", 2) == 0)
                                {
-                               command_line->log_file = g_strdup(cmd_line + 3);
+                               command_line->log_file = g_strdup(cmd_line + 2);
                                }
-                       else if (strncmp(cmd_line, "--log-file:", 11) == 0)
+                       else if (strncmp(cmd_line, "--log-file=", 11) == 0)
                                {
                                command_line->log_file = g_strdup(cmd_line + 11);
                                }
-                       else if (strncmp(cmd_line, "-g:", 3) == 0)
+                       else if (strncmp(cmd_line, "-g", 2) == 0)
                                {
-                               set_regexp(g_strdup(cmd_line+3));
+                               set_regexp(g_strdup(cmd_line + 2));
                                }
-                       else if (strncmp(cmd_line, "-grep:", 6) == 0)
+                       else if (strncmp(cmd_line, "--grep=", 7) == 0)
                                {
-                               set_regexp(g_strdup(cmd_line+3));
+                               set_regexp(g_strdup(cmd_line + 7));
                                }
                        else if (strncmp(cmd_line, "-n", 2) == 0)
                                {
@@ -485,8 +462,7 @@ static void parse_command_line(gint argc, gchar *argv[])
                                {
                                command_line->new_instance = TRUE;
                                }
-                       else if (strcmp(cmd_line, "-rh") == 0 ||
-                                strcmp(cmd_line, "--remote-help") == 0)
+                       else if (strcmp(cmd_line, "--remote-help") == 0)
                                {
                                remote_help();
                                exit(0);
@@ -501,12 +477,6 @@ static void parse_command_line(gint argc, gchar *argv[])
                                printf_term(FALSE, "%s %s GTK%d\n", GQ_APPNAME, VERSION, gtk_major_version);
                                exit(0);
                                }
-                       else if (strcmp(cmd_line, "--alternate") == 0)
-                               {
-                               /* enable faster experimental algorithm */
-                               log_printf("Alternate similarity algorithm enabled\n");
-                               image_sim_alternate_set(TRUE);
-                               }
                        else if (strcmp(cmd_line, "-h") == 0 ||
                                 strcmp(cmd_line, "--help") == 0)
                                {
@@ -514,32 +484,28 @@ static void parse_command_line(gint argc, gchar *argv[])
                                printf_term(FALSE, _("Usage: %s [options] [path]\n\n"), GQ_APPNAME_LC);
                                print_term(FALSE, _("Valid options:\n"));
                                print_term(FALSE, _("      --blank                      start with blank file list\n"));
-                               print_term(FALSE, _("      --cache-maintenance <path>   run cache maintenance in non-GUI mode\n"));
+                               print_term(FALSE, _("      --cache-maintenance=<path>   run cache maintenance in non-GUI mode\n"));
                                print_term(FALSE, _("      --disable-clutter            disable use of Clutter library (i.e. GPU accel.)\n"));
                                print_term(FALSE, _("  -f, --fullscreen                 start in full screen mode\n"));
                                print_term(FALSE, _("      --geometry=WxH+XOFF+YOFF     set main window location\n"));
                                print_term(FALSE, _("  -h, --help                       show this message\n"));
                                print_term(FALSE, _("  -l, --list [files] [collections] open collection window for command line\n"));
-                               print_term(FALSE, _("  -n, --new-instance               open a new instance of Geeqie\n"));
-                               print_term(FALSE, _("  -o:, --log-file:<file>     save log data to file\n"));
+                               print_term(FALSE, _("  -n, --new-instance               open a new instance of Geeqie *\n"));
+                               print_term(FALSE, _("  -o, --log-file=<file>            save log data to file\n"));
                                print_term(FALSE, _("  -r, --remote                     send following commands to open window\n"));
-                               print_term(FALSE, _("  -rh, --remote-help               print remote command list\n"));
+                               print_term(FALSE, _("      --remote-help                print remote command list\n"));
                                print_term(FALSE, _("  -s, --slideshow                  start in slideshow mode\n"));
-                               print_term(FALSE, _("  +t, --with-tools                 force show of tools\n"));
+                               print_term(FALSE, _("  -T, --with-tools                 force show of tools\n"));
                                print_term(FALSE, _("  -t, --without-tools              force hide of tools\n"));
                                print_term(FALSE, _("  -v, --version                    print version info\n"));
-                               print_term(FALSE, _("  +w, --show-log-window            show log window\n"));
+                               print_term(FALSE, _("  -w, --show-log-window            show log window\n"));
 #ifdef DEBUG
                                print_term(FALSE, _("      --debug[=level]              turn on debug output\n"));
-                               print_term(FALSE, _("  -g:, --grep:<regexp>     filter debug output\n"));
+                               print_term(FALSE, _("  -g, --grep=<regexp>              filter debug output\n"));
 #endif
 
-#if 0
-                               /* these options are not officially supported!
-                                * only for testing new features, no need to translate them */
-                               print_term(FALSE, "  --alternate                use alternate similarity algorithm\n");
-#endif
                                print_term(FALSE, "\n");
+                               print_term(FALSE, "* Normally a single set of configuration files is used for all instances.\nHowever, the environment variables XDG_CONFIG_HOME, XDG_CACHE_HOME, XDG_DATA_HOME\ncan be used to modify this behavior on an individual basis e.g.\n\nXDG_CONFIG_HOME=/tmp/a XDG_CACHE_HOME=/tmp/b geeqie\n\n");
 
                                remote_help();
 
@@ -548,8 +514,7 @@ static void parse_command_line(gint argc, gchar *argv[])
                                }
                        else if (!remote_do)
                                {
-                               command_line_errors = g_string_append(command_line_errors, cmd_line);
-                               command_line_errors = g_string_append(command_line_errors, "\n");
+                               g_string_append_printf(command_line_errors, is_remote_command(cmd_line) ? _("%s\n\nThis is a --remote command option\n") : _("%s\n\nThis option is unknown\n"), cmd_line);
                                }
 
                        g_free(cmd_all);
@@ -559,12 +524,12 @@ static void parse_command_line(gint argc, gchar *argv[])
 
                if (command_line_errors->len > 0)
                        {
-                       dialog_warning = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", "Invalid parameter(s):");
+                       dialog_warning = gtk_message_dialog_new(nullptr, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", "Invalid parameter(s):");
                        gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog_warning), "%s", command_line_errors->str);
                        gtk_window_set_title(GTK_WINDOW(dialog_warning), GQ_APPNAME);
-                       gtk_window_set_keep_above(GTK_WINDOW(dialog_warning), TRUE);
+                       gq_gtk_window_set_keep_above(GTK_WINDOW(dialog_warning), TRUE);
                        gtk_dialog_run(GTK_DIALOG(dialog_warning));
-                       gtk_widget_destroy(dialog_warning);
+                       g_object_unref(dialog_warning);
                        g_string_free(command_line_errors, TRUE);
 
                        exit(EXIT_FAILURE);
@@ -580,7 +545,7 @@ static void parse_command_line(gint argc, gchar *argv[])
        if (!command_line->path && first_dir)
                {
                command_line->path = first_dir;
-               first_dir = NULL;
+               first_dir = nullptr;
 
                parse_out_relatives(command_line->path);
                }
@@ -620,12 +585,12 @@ static void parse_command_line(gint argc, gchar *argv[])
                                work = work->next;
                                }
 
-                       dialog_warning = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", "Invalid parameter(s):");
+                       dialog_warning = gtk_message_dialog_new(nullptr, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", "Invalid parameter(s):");
                        gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog_warning), "%s", command_line_errors->str);
                        gtk_window_set_title(GTK_WINDOW(dialog_warning), GQ_APPNAME);
-                       gtk_window_set_keep_above(GTK_WINDOW(dialog_warning), TRUE);
+                       gq_gtk_window_set_keep_above(GTK_WINDOW(dialog_warning), TRUE);
                        gtk_dialog_run(GTK_DIALOG(dialog_warning));
-                       gtk_widget_destroy(dialog_warning);
+                       g_object_unref(dialog_warning);
                        g_string_free(command_line_errors, TRUE);
 
                        exit(EXIT_FAILURE);
@@ -635,7 +600,7 @@ static void parse_command_line(gint argc, gchar *argv[])
                 * for use by any remote command that needs it
                 */
                current_dir = g_get_current_dir();
-               pwd = g_strconcat("--PWD:", current_dir, NULL);
+               pwd = g_strconcat("--PWD=", current_dir, NULL);
                remote_list = g_list_prepend(remote_list, pwd);
 
                remote_control(argv[0], remote_list, command_line->path, list, command_line->collection_list);
@@ -653,20 +618,20 @@ static void parse_command_line(gint argc, gchar *argv[])
                }
        else
                {
-               string_list_free(list);
-               command_line->cmd_list = NULL;
+               g_list_free_full(list, g_free);
+               command_line->cmd_list = nullptr;
                }
 
        if (command_line->startup_blank)
                {
                g_free(command_line->path);
-               command_line->path = NULL;
+               command_line->path = nullptr;
                g_free(command_line->file);
-               command_line->file = NULL;
+               command_line->file = nullptr;
                filelist_free(command_line->cmd_list);
-               command_line->cmd_list = NULL;
-               string_list_free(command_line->collection_list);
-               command_line->collection_list = NULL;
+               command_line->cmd_list = nullptr;
+               g_list_free_full(command_line->collection_list, g_free);
+               command_line->collection_list = nullptr;
                }
 }
 
@@ -704,7 +669,7 @@ static void parse_command_line_for_debug_option(gint argc, gchar *argv[])
 #endif
 }
 
-#ifdef HAVE_CLUTTER
+#if HAVE_CLUTTER
 static gboolean parse_command_line_for_clutter_option(gint argc, gchar *argv[])
 {
        const gchar *clutter_option = "--disable-clutter";
@@ -731,7 +696,7 @@ static gboolean parse_command_line_for_clutter_option(gint argc, gchar *argv[])
 
 static gboolean parse_command_line_for_cache_maintenance_option(gint argc, gchar *argv[])
 {
-       const gchar *cache_maintenance_option = "--cache-maintenance";
+       const gchar *cache_maintenance_option = "--cache-maintenance=";
        gint len = strlen(cache_maintenance_option);
        gboolean ret = FALSE;
 
@@ -750,15 +715,18 @@ static gboolean parse_command_line_for_cache_maintenance_option(gint argc, gchar
 static void process_command_line_for_cache_maintenance_option(gint argc, gchar *argv[])
 {
        gchar *rc_path;
-       gchar *folder_path = NULL;
+       gchar *folder_path = nullptr;
        gsize size;
        gsize i = 0;
        gchar *buf_config_file;
        gint diff_count;
 
-       if (argc >= 3)
+       const gchar *cache_maintenance_option = "--cache-maintenance=";
+       gint len = strlen(cache_maintenance_option);
+
+       if (argc >= 2)
                {
-               folder_path = expand_tilde(argv[2]);
+               folder_path = expand_tilde(argv[1] + len);
 
                if (isdir(folder_path))
                        {
@@ -766,7 +734,7 @@ static void process_command_line_for_cache_maintenance_option(gint argc, gchar *
 
                        if (isfile(rc_path))
                                {
-                               if (g_file_get_contents(rc_path, &buf_config_file, &size, NULL))
+                               if (g_file_get_contents(rc_path, &buf_config_file, &size, nullptr))
                                        {
                                        while (i < size)
                                                {
@@ -806,7 +774,7 @@ static void process_command_line_for_cache_maintenance_option(gint argc, gchar *
                        }
                else
                        {
-                       print_term(TRUE, g_strconcat(argv[2], _(" is not a folder\n"), NULL));
+                       print_term(TRUE, g_strconcat(argv[1] + len, _(" is not a folder\n"), NULL));
                        exit(EXIT_FAILURE);
                        }
                g_free(folder_path);
@@ -827,7 +795,7 @@ static void process_command_line_for_cache_maintenance_option(gint argc, gchar *
 #define RC_HISTORY_NAME "history"
 #define RC_MARKS_NAME "marks"
 
-static void setup_env_path(void)
+static void setup_env_path()
 {
        const gchar *old_path = g_getenv("PATH");
        gchar *path = g_strconcat(gq_bindir, ":", old_path, NULL);
@@ -835,7 +803,7 @@ static void setup_env_path(void)
        g_free(path);
 }
 
-static void keys_load(void)
+static void keys_load()
 {
        gchar *path;
 
@@ -844,7 +812,7 @@ static void keys_load(void)
        g_free(path);
 }
 
-static void keys_save(void)
+static void keys_save()
 {
        gchar *path;
 
@@ -853,7 +821,7 @@ static void keys_save(void)
        g_free(path);
 }
 
-static void marks_load(void)
+static void marks_load()
 {
        gchar *path;
 
@@ -895,20 +863,21 @@ static void gq_accel_map_print(
                    GdkModifierType accel_mods,
                    gboolean    changed)
 {
-       GString *gstring = g_string_new(changed ? NULL : "; ");
+       GString *gstring = g_string_new(changed ? nullptr : "; ");
        auto ssi = static_cast<SecureSaveInfo *>(data);
-       gchar *tmp, *name;
+       gchar *tmp;
+       gchar *name;
 
        g_string_append(gstring, "(gtk_accel_path \"");
 
-       tmp = g_strescape(accel_path, NULL);
+       tmp = g_strescape(accel_path, nullptr);
        g_string_append(gstring, tmp);
        g_free(tmp);
 
        g_string_append(gstring, "\" \"");
 
        name = gtk_accelerator_name(accel_key, accel_mods);
-       tmp = g_strescape(name, NULL);
+       tmp = g_strescape(name, nullptr);
        g_free(name);
        g_string_append(gstring, tmp);
        g_free(tmp);
@@ -946,7 +915,7 @@ static gboolean gq_accel_map_save(const gchar *path)
 
        g_string_free(gstring, TRUE);
 
-       gtk_accel_map_foreach((gpointer) ssi, gq_accel_map_print);
+       gtk_accel_map_foreach(ssi, gq_accel_map_print);
 
        if (secure_close(ssi))
                {
@@ -958,12 +927,12 @@ static gboolean gq_accel_map_save(const gchar *path)
        return TRUE;
 }
 
-static gchar *accep_map_filename(void)
+static gchar *accep_map_filename()
 {
        return g_build_filename(get_rc_dir(), "accels", NULL);
 }
 
-static void accel_map_save(void)
+static void accel_map_save()
 {
        gchar *path;
 
@@ -972,7 +941,7 @@ static void accel_map_save(void)
        g_free(path);
 }
 
-static void accel_map_load(void)
+static void accel_map_load()
 {
        gchar *path;
        gchar *pathl;
@@ -984,7 +953,7 @@ static void accel_map_load(void)
        g_free(path);
 }
 
-static void gtkrc_load(void)
+static void gtkrc_load()
 {
        gchar *path;
        gchar *pathl;
@@ -999,9 +968,9 @@ static void gtkrc_load(void)
        g_free(path);
 }
 
-static void exit_program_final(void)
+static void exit_program_final()
 {
-       LayoutWindow *lw = NULL;
+       LayoutWindow *lw = nullptr;
        GList *list;
        LayoutWindow *tmp_lw;
        gchar *archive_dir;
@@ -1023,7 +992,7 @@ static void exit_program_final(void)
                        tmp_lw = static_cast<LayoutWindow *>(list->data);
                        if (!g_str_has_prefix(tmp_lw->options.id, "lw"))
                                {
-                               save_layout(static_cast<_LayoutWindow *>(list->data));
+                               save_layout(static_cast<LayoutWindow *>(list->data));
                                }
                        list = list->next;
                        }
@@ -1043,7 +1012,7 @@ static void exit_program_final(void)
        if (isdir(archive_dir))
                {
                archive_file = g_file_new_for_path(archive_dir);
-               rmdir_recursive(archive_file, NULL, NULL);
+               rmdir_recursive(archive_file, nullptr, nullptr);
                g_free(archive_dir);
                g_object_unref(archive_file);
                }
@@ -1054,7 +1023,7 @@ static void exit_program_final(void)
        if (isdir(archive_dir))
                {
                archive_file = g_file_new_for_path(archive_dir);
-               g_file_delete(archive_file, NULL, NULL);
+               g_file_delete(archive_file, nullptr, nullptr);
                g_free(archive_dir);
                g_object_unref(archive_file);
                }
@@ -1064,26 +1033,27 @@ static void exit_program_final(void)
        gtk_main_quit();
 }
 
-static GenericDialog *exit_dialog = NULL;
+static GenericDialog *exit_dialog = nullptr;
 
-static void exit_confirm_cancel_cb(GenericDialog *gd, gpointer UNUSED(data))
+static void exit_confirm_cancel_cb(GenericDialog *gd, gpointer)
 {
-       exit_dialog = NULL;
+       exit_dialog = nullptr;
        generic_dialog_close(gd);
 }
 
-static void exit_confirm_exit_cb(GenericDialog *gd, gpointer UNUSED(data))
+static void exit_confirm_exit_cb(GenericDialog *gd, gpointer)
 {
-       exit_dialog = NULL;
+       exit_dialog = nullptr;
        generic_dialog_close(gd);
        exit_program_final();
 }
 
-static gint exit_confirm_dlg(void)
+static gint exit_confirm_dlg()
 {
        GtkWidget *parent;
        LayoutWindow *lw;
        gchar *msg;
+       GString *message;
 
        if (exit_dialog)
                {
@@ -1091,10 +1061,10 @@ static gint exit_confirm_dlg(void)
                return TRUE;
                }
 
-       if (!collection_window_modified_exists()) return FALSE;
+       if (!collection_window_modified_exists() && (layout_window_count() == 1)) return FALSE;
 
-       parent = NULL;
-       lw = NULL;
+       parent = nullptr;
+       lw = nullptr;
        if (layout_valid(&lw))
                {
                parent = lw->window;
@@ -1103,29 +1073,45 @@ static gint exit_confirm_dlg(void)
        msg = g_strdup_printf("%s - %s", GQ_APPNAME, _("exit"));
        exit_dialog = generic_dialog_new(msg,
                                "exit", parent, FALSE,
-                               exit_confirm_cancel_cb, NULL);
+                               exit_confirm_cancel_cb, nullptr);
        g_free(msg);
        msg = g_strdup_printf(_("Quit %s"), GQ_APPNAME);
-       generic_dialog_add_message(exit_dialog, GTK_STOCK_DIALOG_QUESTION,
-                                  msg, _("Collections have been modified. Quit anyway?"), TRUE);
+
+       message = g_string_new(nullptr);
+
+       if (collection_window_modified_exists())
+               {
+               message = g_string_append(message, _("Collections have been modified.\n"));
+               }
+
+       if (layout_window_count() > 1)
+               {
+               g_string_append_printf(message, _("%d windows are open.\n\n"), layout_window_count());
+               }
+
+       message = g_string_append(message, _("Quit anyway?"));
+
+       generic_dialog_add_message(exit_dialog, GQ_ICON_DIALOG_QUESTION, msg, message->str, TRUE);
        g_free(msg);
-       generic_dialog_add_button(exit_dialog, GTK_STOCK_QUIT, NULL, exit_confirm_exit_cb, TRUE);
+       generic_dialog_add_button(exit_dialog, GQ_ICON_QUIT, _("Quit"), exit_confirm_exit_cb, TRUE);
 
        gtk_widget_show(exit_dialog->dialog);
 
+       g_string_free(message, TRUE);
+
        return TRUE;
 }
 
-static void exit_program_write_metadata_cb(gint success, const gchar *UNUSED(dest_path), gpointer UNUSED(data))
+static void exit_program_write_metadata_cb(gint success, const gchar *, gpointer)
 {
        if (success) exit_program();
 }
 
-void exit_program(void)
+void exit_program()
 {
-       layout_image_full_screen_stop(NULL);
+       layout_image_full_screen_stop(nullptr);
 
-       if (metadata_write_queue_confirm(FALSE, exit_program_write_metadata_cb, NULL)) return;
+       if (metadata_write_queue_confirm(FALSE, exit_program_write_metadata_cb, nullptr)) return;
 
        options->marks_save ? marks_save(TRUE) : marks_save(FALSE);
 
@@ -1139,7 +1125,7 @@ void exit_program(void)
  * This code is incorrect according to POSIX, because:
  *
  *   mmap is not async-signal-safe and thus may not be called from a signal handler
- * 
+ *
  *   mmap must be called with a valid file descriptor.  POSIX requires that
  *   a fildes argument of -1 must cause mmap to return EBADF.
  *
@@ -1147,9 +1133,12 @@ void exit_program(void)
  * an alternative approach.
  */
 /** @FIXME this probably needs some better ifdefs. Please report any compilation problems */
+/** @FIXME This section needs revising */
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
 #if defined(SIGBUS) && defined(SA_SIGINFO)
-static void sigbus_handler_cb(int UNUSED(signum), siginfo_t *info, void *UNUSED(context))
+static void sigbus_handler_cb_unused(int, siginfo_t *info, void *)
 {
        /*
         * @FIXME Design and implement a POSIX-acceptable approach,
@@ -1162,37 +1151,40 @@ static void sigbus_handler_cb(int UNUSED(signum), siginfo_t *info, void *UNUSED(
 }
 #endif
 
-//static void setup_sigbus_handler(void)
-//{
-//#if defined(SIGBUS) && defined(SA_SIGINFO)
-       //struct sigaction sigbus_action;
-       //sigfillset(&sigbus_action.sa_mask);
-       //sigbus_action.sa_sigaction = sigbus_handler_cb;
-       //sigbus_action.sa_flags = SA_SIGINFO;
+static void setup_sigbus_handler_unused()
+{
+#if defined(SIGBUS) && defined(SA_SIGINFO)
+       struct sigaction sigbus_action;
+       sigfillset(&sigbus_action.sa_mask);
+       sigbus_action.sa_sigaction = sigbus_handler_cb_unused;
+       sigbus_action.sa_flags = SA_SIGINFO;
 
-       //sigaction(SIGBUS, &sigbus_action, NULL);
-//#endif
-//}
+       sigaction(SIGBUS, &sigbus_action, nullptr);
+#endif
+}
+#pragma GCC diagnostic pop
 
-static void setup_sig_handler(void)
+#if !HAVE_DEVELOPER
+static void setup_sig_handler()
 {
        struct sigaction sigsegv_action;
        sigfillset(&sigsegv_action.sa_mask);
        sigsegv_action.sa_sigaction = sig_handler_cb;
        sigsegv_action.sa_flags = SA_SIGINFO;
 
-       sigaction(SIGABRT, &sigsegv_action, NULL);
-       sigaction(SIGBUS, &sigsegv_action, NULL);
-       sigaction(SIGFPE, &sigsegv_action, NULL);
-       sigaction(SIGILL, &sigsegv_action, NULL);
-       sigaction(SIGIOT, &sigsegv_action, NULL);
-       sigaction(SIGSEGV, &sigsegv_action, NULL);
+       sigaction(SIGABRT, &sigsegv_action, nullptr);
+       sigaction(SIGBUS, &sigsegv_action, nullptr);
+       sigaction(SIGFPE, &sigsegv_action, nullptr);
+       sigaction(SIGILL, &sigsegv_action, nullptr);
+       sigaction(SIGIOT, &sigsegv_action, nullptr);
+       sigaction(SIGSEGV, &sigsegv_action, nullptr);
 }
+#endif
 
 static void set_theme_bg_color()
 {
        GdkRGBA bg_color;
-       GdkColor theme_color;
+       GdkRGBA theme_color;
        GtkStyleContext *style_context;
        GList *work;
        LayoutWindow *lw;
@@ -1205,9 +1197,9 @@ static void set_theme_bg_color()
                style_context = gtk_widget_get_style_context(lw->window);
                gtk_style_context_get_background_color(style_context, GTK_STATE_FLAG_NORMAL, &bg_color);
 
-               theme_color.red = bg_color.red * 65535;
-               theme_color.green = bg_color.green * 65535;
-               theme_color.blue = bg_color.blue * 65535;
+               theme_color.red = bg_color.red  ;
+               theme_color.green = bg_color.green  ;
+               theme_color.blue = bg_color.blue ;
 
                while (work)
                        {
@@ -1220,7 +1212,7 @@ static void set_theme_bg_color()
        view_window_colors_update();
 }
 
-static gboolean theme_change_cb(GObject *UNUSED(gobject), GParamSpec *UNUSED(pspec), gpointer UNUSED(data))
+static gboolean theme_change_cb(GObject *, GParamSpec *, gpointer)
 {
        set_theme_bg_color();
 
@@ -1229,7 +1221,7 @@ static gboolean theme_change_cb(GObject *UNUSED(gobject), GParamSpec *UNUSED(psp
 
 /**
  * @brief Set up the application paths
- * 
+ *
  * This function is required for use of AppImages. AppImages are
  * relocatable, and therefore cannot use fixed paths to various components.
  * These paths were originally #defines created during compilation.
@@ -1242,9 +1234,9 @@ static void create_application_paths()
        gint length;
        gchar *path;
 
-       length = wai_getExecutablePath(NULL, 0, NULL);
+       length = wai_getExecutablePath(nullptr, 0, nullptr);
        path = static_cast<gchar *>(malloc(length + 1));
-       wai_getExecutablePath(path, length, NULL);
+       wai_getExecutablePath(path, length, nullptr);
        path[length] = '\0';
 
        gq_executable_path = g_strdup(path);
@@ -1256,7 +1248,7 @@ static void create_application_paths()
        gq_htmldir = g_build_filename(gq_prefix, GQ_HTMLDIR, NULL);
        gq_appdir = g_build_filename(gq_prefix, GQ_APPDIR, NULL);
        gq_bindir = g_build_filename(gq_prefix, GQ_BINDIR, NULL);
-       desktop_file_template = g_build_filename(gq_appdir, "template.desktop", NULL);
+       desktop_file_template = g_build_filename(gq_appdir, "org.geeqie.template.desktop", NULL);
 
        g_free(dirname);
        g_free(path);
@@ -1264,13 +1256,15 @@ static void create_application_paths()
 
 gint main(gint argc, gchar *argv[])
 {
-       CollectionData *first_collection = NULL;
-       gchar *buf;
-       CollectionData *cd = NULL;
+       CollectionData *cd = nullptr;
+       CollectionData *first_collection = nullptr;
        gboolean disable_clutter = FALSE;
        gboolean single_dir = TRUE;
-       LayoutWindow *lw;
+       gchar *buf;
+       GdkScreen *screen;
+       GtkCssProvider *provider;
        GtkSettings *default_settings;
+       LayoutWindow *lw;
 
        gdk_set_allowed_backends("x11,*");
 
@@ -1278,7 +1272,7 @@ gint main(gint argc, gchar *argv[])
        gdk_threads_enter();
 
        /* seg. fault handler */
-#ifdef HAVE_DEVELOPER
+#if HAVE_DEVELOPER
        backward::SignalHandling sh{};
 #else
        setup_sig_handler();
@@ -1300,12 +1294,12 @@ gint main(gint argc, gchar *argv[])
 
        exif_init();
 
-#ifdef HAVE_LUA
+#if HAVE_LUA
        lua_init();
 #endif
 
        /* setup random seed for random slideshow */
-       srand(time(NULL));
+       srand(time(nullptr));
 
 #if 0
        /* See later comment; this handler leads to UB. */
@@ -1313,18 +1307,18 @@ gint main(gint argc, gchar *argv[])
 #endif
 
        /* register global notify functions */
-       file_data_register_notify_func(cache_notify_cb, NULL, NOTIFY_PRIORITY_HIGH);
-       file_data_register_notify_func(thumb_notify_cb, NULL, NOTIFY_PRIORITY_HIGH);
-       file_data_register_notify_func(histogram_notify_cb, NULL, NOTIFY_PRIORITY_HIGH);
-       file_data_register_notify_func(collect_manager_notify_cb, NULL, NOTIFY_PRIORITY_LOW);
-       file_data_register_notify_func(metadata_notify_cb, NULL, NOTIFY_PRIORITY_LOW);
+       file_data_register_notify_func(cache_notify_cb, nullptr, NOTIFY_PRIORITY_HIGH);
+       file_data_register_notify_func(thumb_notify_cb, nullptr, NOTIFY_PRIORITY_HIGH);
+       file_data_register_notify_func(histogram_notify_cb, nullptr, NOTIFY_PRIORITY_HIGH);
+       file_data_register_notify_func(collect_manager_notify_cb, nullptr, NOTIFY_PRIORITY_LOW);
+       file_data_register_notify_func(metadata_notify_cb, nullptr, NOTIFY_PRIORITY_LOW);
 
 
        gtkrc_load();
 
        parse_command_line_for_debug_option(argc, argv);
        DEBUG_1("%s main: gtk_init", get_exec_time());
-#ifdef HAVE_CLUTTER
+#if HAVE_CLUTTER
        if (parse_command_line_for_clutter_option(argc, argv))
                {
                disable_clutter = TRUE;
@@ -1358,7 +1352,7 @@ gint main(gint argc, gchar *argv[])
        pixbuf_inline_register_stock_icons();
 
        DEBUG_1("%s main: setting default options before commandline handling", get_exec_time());
-       options = init_options(NULL);
+       options = init_options(nullptr);
        setup_default_options(options);
        if (disable_clutter)
                {
@@ -1378,6 +1372,11 @@ gint main(gint argc, gchar *argv[])
 
        setup_env_path();
 
+       screen = gdk_screen_get_default();
+       provider = gtk_css_provider_new();
+       gtk_css_provider_load_from_resource(provider, GQ_RESOURCE_PATH_UI "/custom.css");
+       gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
        if (parse_command_line_for_cache_maintenance_option(argc, argv))
                {
                process_command_line_for_cache_maintenance_option(argc, argv);
@@ -1401,7 +1400,7 @@ gint main(gint argc, gchar *argv[])
                        filter_rebuild();
                        }
 
-       #ifdef HAVE_CLUTTER
+       #if HAVE_CLUTTER
        /** @FIXME For the background of this see:
         * https://github.com/BestImageViewer/geeqie/issues/397
         * The feature CLUTTER_FEATURE_SWAP_EVENTS indictates if the
@@ -1463,7 +1462,7 @@ gint main(gint argc, gchar *argv[])
                if (command_line->cmd_list && !(command_line->startup_command_line_collection))
                        {
                        GList *work;
-                       gchar *path = NULL;
+                       gchar *path = nullptr;
 
                        work = command_line->cmd_list;
 
@@ -1497,7 +1496,7 @@ gint main(gint argc, gchar *argv[])
                        GList *work;
                        CollectWindow *cw;
 
-                       cw = collection_window_new(NULL);
+                       cw = collection_window_new(nullptr);
                        cd = cw->cd;
 
                        collection_path_changed(cd);
@@ -1520,7 +1519,7 @@ gint main(gint argc, gchar *argv[])
                                work = work->next;
                                }
 
-                       if (cd->list) layout_image_set_collection(NULL, cd, static_cast<CollectInfo *>(cd->list->data));
+                       if (cd->list) layout_image_set_collection(nullptr, cd, static_cast<CollectInfo *>(cd->list->data));
 
                        /* mem leak, we never unref this collection when !startup_command_line_collection
                         * (the image view of the main window does not hold a ref to the collection)
@@ -1533,14 +1532,14 @@ gint main(gint argc, gchar *argv[])
                        }
                else if (first_collection)
                        {
-                       layout_image_set_collection(NULL, first_collection,
+                       layout_image_set_collection(nullptr, first_collection,
                                                    collection_get_first(first_collection));
                        }
 
                /* If the files on the command line are from one folder, select those files
                 * unless it is a command line collection - then leave focus on collection window
                 */
-               lw = NULL;
+               lw = nullptr;
                layout_valid(&lw);
 
                if (single_dir && command_line->cmd_list && !command_line->startup_command_line_collection)
@@ -1549,7 +1548,7 @@ gint main(gint argc, gchar *argv[])
                        GList *selected;
                        FileData *fd;
 
-                       selected = NULL;
+                       selected = nullptr;
                        work = command_line->cmd_list;
                        while (work)
                                {
@@ -1573,9 +1572,17 @@ gint main(gint argc, gchar *argv[])
                }
 
        /* Show a fade-out notification window if the server has a newer AppImage version */
-       if (options->appimage_notifications && g_getenv("APPDIR") && strstr(g_getenv("APPDIR"), "/tmp/.mount_Geeqie"))
+       if (options->appimage_notifications)
                {
-               appimage_notification();
+               if (g_getenv("APPDIR") && strstr(g_getenv("APPDIR"), "/tmp/.mount_Geeqie"))
+                       {
+                       appimage_notification();
+                       }
+               else if (g_strstr_len(gq_executable_path, -1, "AppRun"))
+                       {
+                       /* Probably running an extracted AppImage */
+                       appimage_notification();
+                       }
                }
 
        DEBUG_1("%s main: gtk_main", get_exec_time());