Use std::swap instead of temporary values
[geeqie.git] / src / filedata.cc
index 3a045ef..c0a04ab 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "main.h"
 #include "filedata.h"
 
-#include "filefilter.h"
-#include "cache.h"
-#include "thumb-standard.h"
-#include "ui-fileops.h"
-#include "metadata.h"
-#include "trash.h"
-#include "histogram.h"
-#include "secure-save.h"
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
-#include "exif.h"
-#include "misc.h"
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <utility>
 
+#include <glib-object.h>
 #include <grp.h>
+#include <pwd.h>
+
+#include <config.h>
+
+#include "cache.h"
+#include "debug.h"
+#include "exif.h"
+#include "filefilter.h"
+#include "histogram.h"
+#include "intl.h"
+#include "main-defines.h"
+#include "main.h"
+#include "metadata.h"
+#include "misc.h"
+#include "options.h"
+#include "secure-save.h"
+#include "thumb-standard.h"
+#include "trash.h"
+#include "ui-fileops.h"
 
 #ifdef DEBUG_FILEDATA
 gint global_file_data_count = 0;
@@ -50,6 +68,7 @@ static void file_data_disconnect_sidecar_file(FileData *target, FileData *sfd);
 
 static SortType filelist_sort_method = SORT_NONE;
 static gboolean filelist_sort_ascend = TRUE;
+static gboolean filelist_sort_case = TRUE;
 
 /*
  *-----------------------------------------------------------------------------
@@ -59,9 +78,13 @@ static gboolean filelist_sort_ascend = TRUE;
 
 gchar *text_from_size(gint64 size)
 {
-       gchar *a, *b;
-       gchar *s, *d;
-       gint l, n, i;
+       gchar *a;
+       gchar *b;
+       gchar *s;
+       gchar *d;
+       gint l;
+       gint n;
+       gint i;
 
        /* what I would like to use is printf("%'d", size)
         * BUT: not supported on every libc :(
@@ -281,16 +304,10 @@ static void file_data_set_collate_keys(FileData *fd)
        g_free(fd->collate_key_name);
        g_free(fd->collate_key_name_nocase);
 
-       if (options->file_sort.natural)
-               {
-               fd->collate_key_name = g_utf8_collate_key_for_filename(fd->name, -1);
-               fd->collate_key_name_nocase = g_utf8_collate_key_for_filename(caseless_name, -1);
-               }
-       else
-               {
-               fd->collate_key_name = g_utf8_collate_key(valid_name, -1);
-               fd->collate_key_name_nocase = g_utf8_collate_key(caseless_name, -1);
-               }
+       fd->collate_key_name_natural = g_utf8_collate_key_for_filename(fd->name, -1);
+       fd->collate_key_name_nocase_natural = g_utf8_collate_key_for_filename(caseless_name, -1);
+       fd->collate_key_name = g_utf8_collate_key(valid_name, -1);
+       fd->collate_key_name_nocase = g_utf8_collate_key(caseless_name, -1);
 
        g_free(valid_name);
        g_free(caseless_name);
@@ -337,7 +354,8 @@ static void file_data_set_path(FileData *fd, const gchar *path)
                file_data_set_collate_keys(fd);
                return;
                }
-       else if (strcmp(fd->name, ".") == 0)
+
+       if (strcmp(fd->name, ".") == 0)
                {
                g_free(fd->path);
                fd->path = remove_level_from_path(path);
@@ -402,12 +420,12 @@ static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean
 
        if (fd)
                {
-               gboolean changed;
-
                if (disable_sidecars) file_data_disable_grouping(fd, TRUE);
 
-
-               changed = file_data_check_changed_single_file(fd, st);
+#ifdef DEBUG_FILEDATA
+               gboolean changed =
+#endif
+               file_data_check_changed_single_file(fd, st);
 
                DEBUG_2("file_data_pool hit: '%s' %s", fd->path, changed ? "(changed)" : "");
 
@@ -512,7 +530,12 @@ void read_exif_time_data(FileData *file)
                if (tmp)
                        {
                        struct tm time_str;
-                       uint year, month, day, hour, min, sec;
+                       uint year;
+                       uint month;
+                       uint day;
+                       uint hour;
+                       uint min;
+                       uint sec;
 
                        sscanf(tmp, "%4u:%2u:%2u %2u:%2u:%2u", &year, &month, &day, &hour, &min, &sec);
                        time_str.tm_year  = year - 1900;
@@ -550,7 +573,12 @@ void read_exif_time_digitized_data(FileData *file)
                if (tmp)
                        {
                        struct tm time_str;
-                       uint year, month, day, hour, min, sec;
+                       uint year;
+                       uint month;
+                       uint day;
+                       uint hour;
+                       uint min;
+                       uint sec;
 
                        sscanf(tmp, "%4u:%2u:%2u %2u:%2u:%2u", &year, &month, &day, &hour, &min, &sec);
                        time_str.tm_year  = year - 1900;
@@ -583,49 +611,52 @@ void read_rating_data(FileData *file)
                }
 }
 
-//void set_exif_time_data(GList *files)
-//{
-       //DEBUG_1("%s set_exif_time_data: ...", get_exec_time());
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+void set_exif_time_data_unused(GList *files)
+{
+       DEBUG_1("%s set_exif_time_data: ...", get_exec_time());
 
-       //while (files)
-               //{
-               //FileData *file = files->data;
+       while (files)
+               {
+               auto *file = static_cast<FileData *>(files->data);
 
-               //read_exif_time_data(file);
-               //files = files->next;
-               //}
-//}
+               read_exif_time_data(file);
+               files = files->next;
+               }
+}
 
-//void set_exif_time_digitized_data(GList *files)
-//{
-       //DEBUG_1("%s set_exif_time_digitized_data: ...", get_exec_time());
+void set_exif_time_digitized_data_unused(GList *files)
+{
+       DEBUG_1("%s set_exif_time_digitized_data: ...", get_exec_time());
 
-       //while (files)
-               //{
-               //FileData *file = files->data;
+       while (files)
+               {
+               auto *file = static_cast<FileData *>(files->data);
 
-               //read_exif_time_digitized_data(file);
-               //files = files->next;
-               //}
-//}
+               read_exif_time_digitized_data(file);
+               files = files->next;
+               }
+}
 
-//void set_rating_data(GList *files)
-//{
-       //gchar *rating_str;
-       //DEBUG_1("%s set_rating_data: ...", get_exec_time());
+void set_rating_data_unused(GList *files)
+{
+       gchar *rating_str;
+       DEBUG_1("%s set_rating_data: ...", get_exec_time());
 
-       //while (files)
-               //{
-               //FileData *file = files->data;
-               //rating_str = metadata_read_string(file, RATING_KEY, METADATA_PLAIN);
-               //if (rating_str )
-                       //{
-                       //file->rating = atoi(rating_str);
-                       //g_free(rating_str);
-                       //}
-               //files = files->next;
-               //}
-//}
+       while (files)
+               {
+               auto *file = static_cast<FileData *>(files->data);
+               rating_str = metadata_read_string(file, RATING_KEY, METADATA_PLAIN);
+               if (rating_str )
+                       {
+                       file->rating = atoi(rating_str);
+                       g_free(rating_str);
+                       }
+               files = files->next;
+               }
+}
+#pragma GCC diagnostic pop
 
 FileData *file_data_new_no_grouping(const gchar *path_utf8)
 {
@@ -708,11 +739,12 @@ void file_data_dump()
                log_printf("%d", global_file_data_count);
                log_printf("%d", g_list_length(list));
 
-               while (list)
+               GList *work = list;
+               while (work)
                        {
-                       fd = static_cast<FileData *>(list->data);
+                       fd = static_cast<FileData *>(work->data);
                        log_printf("%-4d %s", fd->ref, fd->path);
-                       list = list->next;
+                       work = work->next;
                        }
 
                g_list_free(list);
@@ -788,15 +820,7 @@ static void file_data_consider_free(FileData *fd)
        DEBUG_2("file_data_consider_free: deleting '%s', parent '%s'",
                fd->path, fd->parent ? parent->path : "-");
 
-       work = parent->sidecar_files;
-       while (work)
-               {
-               auto sfd = static_cast<FileData *>(work->data);
-               file_data_free(sfd);
-               work = work->next;
-               }
-
-       g_list_free(parent->sidecar_files);
+       g_list_free_full(parent->sidecar_files, reinterpret_cast<GDestroyNotify>(file_data_free));
        parent->sidecar_files = nullptr;
 
        file_data_free(parent);
@@ -950,7 +974,8 @@ static void file_data_check_sidecars(const GList *basename_list)
        /* all files in the list have ref count > 0 */
 
        const GList *work;
-       GList *s_work, *new_sidecars;
+       GList *s_work;
+       GList *new_sidecars;
        FileData *parent_fd;
 
        if (!basename_list) return;
@@ -1147,9 +1172,7 @@ gint filelist_sort_compare_filedata(FileData *fa, FileData *fb)
        gint ret;
        if (!filelist_sort_ascend)
                {
-               FileData *tmp = fa;
-               fa = fb;
-               fb = tmp;
+               std::swap(fa, fb);
                }
 
        switch (filelist_sort_method)
@@ -1191,11 +1214,16 @@ gint filelist_sort_compare_filedata(FileData *fa, FileData *fb)
                        if (fa->format_class > fb->format_class) return 1;
                        /* fall back to name */
                        break;
+               case SORT_NUMBER:
+                       ret = strcmp(fa->collate_key_name_natural, fb->collate_key_name_natural);
+                       if (ret != 0) return ret;
+                       /* fall back to name */
+                       break;
                default:
                        break;
                }
 
-       if (options->file_sort.case_sensitive)
+       if (filelist_sort_case)
                ret = strcmp(fa->collate_key_name, fb->collate_key_name);
        else
                ret = strcmp(fa->collate_key_name_nocase, fb->collate_key_name_nocase);
@@ -1220,29 +1248,34 @@ static gint filelist_sort_file_cb(gpointer a, gpointer b)
        return filelist_sort_compare_filedata(static_cast<FileData *>(a), static_cast<FileData *>(b));
 }
 
-GList *filelist_sort_full(GList *list, SortType method, gboolean ascend, GCompareFunc cb)
+GList *filelist_sort_full(GList *list, SortType method, gboolean ascend, gboolean case_sensitive, GCompareFunc cb)
 {
        filelist_sort_method = method;
        filelist_sort_ascend = ascend;
+       filelist_sort_case = case_sensitive;
        return g_list_sort(list, cb);
 }
 
-GList *filelist_insert_sort_full(GList *list, gpointer data, SortType method, gboolean ascend, GCompareFunc cb)
+GList *filelist_insert_sort_full(GList *list, gpointer data, SortType method, gboolean ascend, gboolean case_sensitive, GCompareFunc cb)
 {
        filelist_sort_method = method;
        filelist_sort_ascend = ascend;
+       filelist_sort_case = case_sensitive;
        return g_list_insert_sorted(list, data, cb);
 }
 
-GList *filelist_sort(GList *list, SortType method, gboolean ascend)
+GList *filelist_sort(GList *list, SortType method, gboolean ascend, gboolean case_sensitive)
 {
-       return filelist_sort_full(list, method, ascend, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
+       return filelist_sort_full(list, method, ascend, case_sensitive, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
 }
 
-//GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gboolean ascend)
-//{
-       //return filelist_insert_sort_full(list, fd, method, ascend, (GCompareFunc) filelist_sort_file_cb);
-//}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+GList *filelist_insert_sort_unused(GList *list, FileData *fd, SortType method, gboolean ascend)
+{
+       return filelist_insert_sort_full(list, fd, method, ascend, ascend, (GCompareFunc) filelist_sort_file_cb);
+}
+#pragma GCC diagnostic pop
 
 /*
  *-----------------------------------------------------------------------------
@@ -1311,7 +1344,7 @@ static void file_data_basename_hash_insert_cb(gpointer fd, gpointer basename_has
        file_data_basename_hash_insert(static_cast<GHashTable *>(basename_hash), static_cast<FileData *>(fd));
 }
 
-static void file_data_basename_hash_remove_list(gpointer UNUSED(key), gpointer value, gpointer UNUSED(data))
+static void file_data_basename_hash_remove_list(gpointer, gpointer value, gpointer)
 {
        filelist_free(static_cast<GList *>(value));
 }
@@ -1348,7 +1381,7 @@ static GList *filelist_filter_out_sidecars(GList *flist)
        return flist_filtered;
 }
 
-static void file_data_basename_hash_to_sidecars(gpointer UNUSED(key), gpointer value, gpointer UNUSED(data))
+static void file_data_basename_hash_to_sidecars(gpointer, gpointer value, gpointer)
 {
        auto basename_list = static_cast<GList *>(value);
        file_data_check_sidecars(basename_list);
@@ -1540,15 +1573,10 @@ void filelist_free(GList *list)
 GList *filelist_copy(GList *list)
 {
        GList *new_list = nullptr;
-       GList *work;
 
-       work = list;
-       while (work)
+       for (GList *work = list; work; work = work->next)
                {
-               FileData *fd;
-
-               fd = static_cast<FileData *>(work->data);
-               work = work->next;
+               auto fd = static_cast<FileData *>(work->data);
 
                new_list = g_list_prepend(new_list, file_data_ref(fd));
                }
@@ -1605,20 +1633,18 @@ GList *filelist_filter(GList *list, gboolean is_dir_list)
                {
                auto fd = static_cast<FileData *>(work->data);
                const gchar *name = fd->name;
+               GList *link = work;
+               work = work->next;
 
                if ((!options->file_filter.show_hidden_files && is_hidden_file(name)) ||
                    (!is_dir_list && !filter_name_exists(name)) ||
                    (is_dir_list && name[0] == '.' && (strcmp(name, GQ_CACHE_LOCAL_THUMB) == 0 ||
                                                       strcmp(name, GQ_CACHE_LOCAL_METADATA) == 0)) )
                        {
-                       GList *link = work;
-
                        list = g_list_remove_link(list, link);
                        file_data_unref(fd);
                        g_list_free(link);
                        }
-
-               work = work->next;
                }
 
        return list;
@@ -1667,7 +1693,7 @@ static void filelist_recursive_append(GList **list, GList *dirs)
                }
 }
 
-static void filelist_recursive_append_full(GList **list, GList *dirs, SortType method, gboolean ascend)
+static void filelist_recursive_append_full(GList **list, GList *dirs, SortType method, gboolean ascend, gboolean case_sensitive)
 {
        GList *work;
 
@@ -1681,12 +1707,12 @@ static void filelist_recursive_append_full(GList **list, GList *dirs, SortType m
                if (filelist_read(fd, &f, &d))
                        {
                        f = filelist_filter(f, FALSE);
-                       f = filelist_sort_full(f, method, ascend, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
+                       f = filelist_sort_full(f, method, ascend, case_sensitive, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
                        *list = g_list_concat(*list, f);
 
                        d = filelist_filter(d, TRUE);
                        d = filelist_sort_path(d);
-                       filelist_recursive_append_full(list, d, method, ascend);
+                       filelist_recursive_append_full(list, d, method, ascend, case_sensitive);
                        filelist_free(d);
                        }
 
@@ -1711,18 +1737,18 @@ GList *filelist_recursive(FileData *dir_fd)
        return list;
 }
 
-GList *filelist_recursive_full(FileData *dir_fd, SortType method, gboolean ascend)
+GList *filelist_recursive_full(FileData *dir_fd, SortType method, gboolean ascend, gboolean case_sensitive)
 {
        GList *list;
        GList *d;
 
        if (!filelist_read(dir_fd, &list, &d)) return nullptr;
        list = filelist_filter(list, FALSE);
-       list = filelist_sort_full(list, method, ascend, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
+       list = filelist_sort_full(list, method, ascend, case_sensitive, reinterpret_cast<GCompareFunc>(filelist_sort_file_cb));
 
        d = filelist_filter(d, TRUE);
        d = filelist_sort_path(d);
-       filelist_recursive_append_full(&list, d, method, ascend);
+       filelist_recursive_append_full(&list, d, method, ascend, case_sensitive);
        filelist_free(d);
 
        return list;
@@ -1962,7 +1988,7 @@ GList *file_data_filter_class_list(GList *list, guint filter)
        return list;
 }
 
-static void file_data_notify_mark_func(gpointer UNUSED(key), gpointer value, gpointer UNUSED(user_data))
+static void file_data_notify_mark_func(gpointer, gpointer value, gpointer)
 {
        auto fd = static_cast<FileData *>(value);
        file_data_increment_version(fd);
@@ -1996,19 +2022,22 @@ void file_data_get_registered_mark_func(gint n, FileDataGetMarkFunc *get_mark_fu
        if (data) *data = file_data_mark_func_data[n];
 }
 
-//gint file_data_get_user_orientation(FileData *fd)
-//{
-       //return fd->user_orientation;
-//}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+gint file_data_get_user_orientation_unused(FileData *fd)
+{
+       return fd->user_orientation;
+}
 
-//void file_data_set_user_orientation(FileData *fd, gint value)
-//{
-       //if (fd->user_orientation == value) return;
+void file_data_set_user_orientation_unused(FileData *fd, gint value)
+{
+       if (fd->user_orientation == value) return;
 
-       //fd->user_orientation = value;
-       //file_data_increment_version(fd);
-       //file_data_send_notification(fd, NOTIFY_ORIENTATION);
-//}
+       fd->user_orientation = value;
+       file_data_increment_version(fd);
+       file_data_send_notification(fd, NOTIFY_ORIENTATION);
+}
+#pragma GCC diagnostic pop
 
 
 /*
@@ -2633,7 +2662,7 @@ gint file_data_verify_ci(FileData *fd, GList *list)
                         * it's location regardless of the user's preference.
                         */
                        gchar *metadata_path = nullptr;
-#ifdef HAVE_EXIV2
+#if HAVE_EXIV2
                        /* but ignore XMP if we are not able to write it */
                        metadata_path = cache_find_location(CACHE_TYPE_XMP_METADATA, fd->path);
 #endif
@@ -2661,7 +2690,6 @@ gint file_data_verify_ci(FileData *fd, GList *list)
                        if (access_file(metadata_path, W_OK) || (!isname(metadata_path) && access_file(dest_dir, W_OK)))
                                {
                                file_data_update_ci_dest(fd, metadata_path);
-                               have_dest = TRUE;
                                }
                        else
                                {
@@ -2969,15 +2997,25 @@ static gboolean file_data_perform_delete(FileData *fd)
 {
        if (isdir(fd->path) && !islink(fd->path))
                return rmdir_utf8(fd->path);
-       else
-               if (options->file_ops.safe_delete_enable)
-                       return file_util_safe_unlink(fd->path);
-               else
-                       return unlink_file(fd->path);
+
+       if (options->file_ops.safe_delete_enable)
+               return file_util_safe_unlink(fd->path);
+
+       return unlink_file(fd->path);
 }
 
 gboolean file_data_perform_ci(FileData *fd)
 {
+       /** @FIXME When a directory that is a symbolic link is deleted,
+        * at this point fd->change is null because no FileDataChangeInfo
+        * has been set up. Therefore there is a seg. fault.
+        * This code simply aborts the delete.
+        */
+       if (!fd->change)
+               {
+               return FALSE;
+               }
+
        FileDataChangeType type = fd->change->type;
 
        switch (type)
@@ -3226,23 +3264,25 @@ gboolean file_data_unregister_notify_func(FileDataNotifyFunc func, gpointer data
        return FALSE;
 }
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+gboolean file_data_send_notification_idle_cb_unused(gpointer data)
+{
+       auto *nid = (NotifyIdleData *)data;
+       GList *work = notify_func_list;
 
-//gboolean file_data_send_notification_idle_cb(gpointer data)
-//{
-       //NotifyIdleData *nid = (NotifyIdleData *)data;
-       //GList *work = notify_func_list;
-
-       //while (work)
-               //{
-               //NotifyData *nd = (NotifyData *)work->data;
+       while (work)
+               {
+               auto *nd = (NotifyData *)work->data;
 
-               //nd->func(nid->fd, nid->type, nd->data);
-               //work = work->next;
-               //}
-       //file_data_unref(nid->fd);
-       //g_free(nid);
-       //return FALSE;
-//}
+               nd->func(nid->fd, nid->type, nd->data);
+               work = work->next;
+               }
+       file_data_unref(nid->fd);
+       g_free(nid);
+       return FALSE;
+}
+#pragma GCC diagnostic pop
 
 void file_data_send_notification(FileData *fd, NotifyType type)
 {
@@ -3266,7 +3306,7 @@ void file_data_send_notification(FileData *fd, NotifyType type)
 static GHashTable *file_data_monitor_pool = nullptr;
 static guint realtime_monitor_id = 0; /* event source id */
 
-static void realtime_monitor_check_cb(gpointer key, gpointer UNUSED(value), gpointer UNUSED(data))
+static void realtime_monitor_check_cb(gpointer key, gpointer, gpointer)
 {
        auto fd = static_cast<FileData *>(key);
 
@@ -3275,7 +3315,7 @@ static void realtime_monitor_check_cb(gpointer key, gpointer UNUSED(value), gpoi
        DEBUG_1("monitor %s", fd->path);
 }
 
-static gboolean realtime_monitor_cb(gpointer UNUSED(data))
+static gboolean realtime_monitor_cb(gpointer)
 {
        if (!options->update_on_time_change) return TRUE;
        g_hash_table_foreach(file_data_monitor_pool, realtime_monitor_check_cb, nullptr);
@@ -3411,7 +3451,6 @@ gboolean marks_list_save(gchar *path, gboolean save)
 {
        SecureSaveInfo *ssi;
        gchar *pathl;
-       GString  *marks = g_string_new("");
 
        pathl = path_from_utf8(path);
        ssi = secure_open(pathl);
@@ -3424,6 +3463,7 @@ gboolean marks_list_save(gchar *path, gboolean save)
 
        secure_fprintf(ssi, "#Marks lists\n");
 
+       GString *marks = g_string_new("");
        if (save)
                {
                g_hash_table_foreach(file_data_pool, marks_get_files, marks);
@@ -3435,7 +3475,7 @@ gboolean marks_list_save(gchar *path, gboolean save)
        return (secure_close(ssi) == 0);
 }
 
-static void marks_clear(gpointer key, gpointer value, gpointer UNUSED(userdata))
+static void marks_clear(gpointer key, gpointer value, gpointer)
 {
        auto file_name = static_cast<gchar *>(key);
        gint mark_no;