4 * Copyright (C) 2008 The Geeqie Team
8 * This software is released under the GNU General Public License (GNU GPL).
9 * Please read the included file COPYING for more information.
10 * This software comes with no warranty of any kind, use at your own risk!
17 #include "filefilter.h"
21 #include "secure_save.h"
22 #include "thumb_standard.h"
23 #include "ui_fileops.h"
26 static gint sidecar_file_priority(const gchar *path);
30 *-----------------------------------------------------------------------------
31 * text conversion utils
32 *-----------------------------------------------------------------------------
35 gchar *text_from_size(gint64 size)
41 /* what I would like to use is printf("%'d", size)
42 * BUT: not supported on every libc :(
46 /* the %lld conversion is not valid in all libcs, so use a simple work-around */
47 a = g_strdup_printf("%d%09d", (guint)(size / 1000000000), (guint)(size % 1000000000));
51 a = g_strdup_printf("%d", (guint)size);
57 b = g_new(gchar, l + n + 1);
82 gchar *text_from_size_abrev(gint64 size)
84 if (size < (gint64)1024)
86 return g_strdup_printf(_("%d bytes"), (gint)size);
88 if (size < (gint64)1048576)
90 return g_strdup_printf(_("%.1f K"), (double)size / 1024.0);
92 if (size < (gint64)1073741824)
94 return g_strdup_printf(_("%.1f MB"), (double)size / 1048576.0);
97 /* to avoid overflowing the double, do division in two steps */
99 return g_strdup_printf(_("%.1f GB"), (double)size / 1024.0);
102 /* note: returned string is valid until next call to text_from_time() */
103 const gchar *text_from_time(time_t t)
105 static gchar *ret = NULL;
109 GError *error = NULL;
111 btime = localtime(&t);
113 /* the %x warning about 2 digit years is not an error */
114 buflen = strftime(buf, sizeof(buf), "%x %H:%M", btime);
115 if (buflen < 1) return "";
118 ret = g_locale_to_utf8(buf, buflen, NULL, NULL, &error);
121 printf("Error converting locale strftime to UTF-8: %s\n", error->message);
130 *-----------------------------------------------------------------------------
132 *-----------------------------------------------------------------------------
135 FileData *file_data_merge_sidecar_files(FileData *target, FileData *source);
136 static void file_data_check_sidecars(FileData *fd);
137 FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd);
140 static void file_data_set_path(FileData *fd, const gchar *path)
143 if (strcmp(path, "/") == 0)
145 fd->path = g_strdup(path);
147 fd->extension = fd->name + 1;
151 fd->path = g_strdup(path);
152 fd->name = filename_from_path(fd->path);
154 if (strcmp(fd->name, "..") == 0)
156 gchar *dir = remove_level_from_path(path);
158 fd->path = remove_level_from_path(dir);
161 fd->extension = fd->name + 2;
164 else if (strcmp(fd->name, ".") == 0)
167 fd->path = remove_level_from_path(path);
169 fd->extension = fd->name + 1;
173 fd->extension = extension_from_path(fd->path);
174 if (fd->extension == NULL)
175 fd->extension = fd->name + strlen(fd->name);
178 static void file_data_check_changed_files(FileData *fd, struct stat *st)
181 if (fd->size != st->st_size ||
182 fd->date != st->st_mtime)
184 fd->size = st->st_size;
185 fd->date = st->st_mtime;
186 if (fd->pixbuf) g_object_unref(fd->pixbuf);
190 work = fd->sidecar_files;
193 FileData *sfd = work->data;
196 if (!stat_utf8(sfd->path, &st))
198 file_data_disconnect_sidecar_file(fd, sfd);
201 file_data_check_changed_files(sfd, &st);
206 static GHashTable *file_data_pool = NULL;
208 static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars)
212 DEBUG_2("file_data_new: '%s' %d", path_utf8, check_sidecars);
215 file_data_pool = g_hash_table_new(g_str_hash, g_str_equal);
217 fd = g_hash_table_lookup(file_data_pool, path_utf8);
220 file_data_check_changed_files(fd, st);
221 DEBUG_2("file_data_pool hit: '%s'", fd->path);
222 return file_data_ref(fd);
225 fd = g_new0(FileData, 1);
227 file_data_set_path(fd, path_utf8);
229 fd->original_path = g_strdup(path_utf8);
230 fd->size = st->st_size;
231 fd->date = st->st_mtime;
233 fd->sidecar_files = NULL;
235 fd->magick = 0x12345678;
237 g_hash_table_insert(file_data_pool, fd->original_path, fd);
239 if (check_sidecars && sidecar_file_priority(fd->extension))
240 file_data_check_sidecars(fd);
244 static void file_data_check_sidecars(FileData *fd)
246 int base_len = fd->extension - fd->path;
247 GString *fname = g_string_new_len(fd->path, base_len);
248 FileData *parent_fd = NULL;
249 GList *work = sidecar_ext_get_list();
252 /* check for possible sidecar files;
253 the sidecar files created here are referenced only via fd->sidecar_files or fd->parent,
254 they have fd->ref set to 0 and file_data unref must chack and free them all together
255 (using fd->ref would cause loops and leaks)
260 gchar *ext = work->data;
263 if (strcmp(ext, fd->extension) == 0)
265 new_fd = fd; /* processing the original file */
270 g_string_truncate(fname, base_len);
271 g_string_append(fname, ext);
273 if (!stat_utf8(fname->str, &nst))
276 new_fd = file_data_new(fname->str, &nst, FALSE);
277 new_fd->ref--; /* do not use ref here */
281 parent_fd = new_fd; /* parent is the one with the highest prio, found first */
283 file_data_merge_sidecar_files(parent_fd, new_fd);
285 g_string_free(fname, TRUE);
289 static FileData *file_data_new_local(const gchar *path, struct stat *st, gboolean check_sidecars)
291 gchar *path_utf8 = path_to_utf8(path);
292 FileData *ret = file_data_new(path_utf8, st, check_sidecars);
297 FileData *file_data_new_simple(const gchar *path_utf8)
301 if (!stat_utf8(path_utf8, &st))
307 return file_data_new(path_utf8, &st, TRUE);
310 FileData *file_data_add_sidecar_file(FileData *target, FileData *sfd)
312 sfd->parent = target;
313 if(!g_list_find(target->sidecar_files, sfd))
314 target->sidecar_files = g_list_prepend(target->sidecar_files, sfd);
319 FileData *file_data_merge_sidecar_files(FileData *target, FileData *source)
322 file_data_add_sidecar_file(target, source);
324 work = source->sidecar_files;
327 FileData *sfd = work->data;
328 file_data_add_sidecar_file(target, sfd);
332 g_list_free(source->sidecar_files);
333 source->sidecar_files = NULL;
335 target->sidecar_files = filelist_sort(target->sidecar_files, SORT_NAME, TRUE);
341 FileData *file_data_ref(FileData *fd)
343 if (fd == NULL) return NULL;
345 // return g_memdup(fd, sizeof(FileData));
346 g_assert(fd->magick == 0x12345678);
351 static void file_data_free(FileData *fd)
353 g_assert(fd->magick == 0x12345678);
354 g_assert(fd->ref == 0);
356 g_hash_table_remove(file_data_pool, fd->original_path);
359 g_free(fd->original_path);
360 if (fd->pixbuf) g_object_unref(fd->pixbuf);
363 g_assert(fd->sidecar_files == NULL); /* sidecar files must be freed before calling this */
365 file_data_change_info_free(NULL, fd);
369 void file_data_unref(FileData *fd)
371 if (fd == NULL) return;
372 g_assert(fd->magick == 0x12345678);
375 DEBUG_2("file_data_unref (%d): '%s'", fd->ref, fd->path);
379 FileData *parent = fd->parent ? fd->parent : fd;
386 work = parent->sidecar_files;
389 FileData *sfd = work->data;
395 /* none of parent/children is referenced, we can free everything */
397 DEBUG_2("file_data_unref: deleting '%s', parent '%s'", fd->path, parent->path);
399 work = parent->sidecar_files;
402 FileData *sfd = work->data;
407 g_list_free(parent->sidecar_files);
408 parent->sidecar_files = NULL;
410 file_data_free(parent);
415 FileData *file_data_disconnect_sidecar_file(FileData *target, FileData *sfd)
417 sfd->parent = target;
418 g_assert(g_list_find(target->sidecar_files, sfd));
420 target->sidecar_files = g_list_remove(target->sidecar_files, sfd);
431 /* compare name without extension */
432 gint file_data_compare_name_without_ext(FileData *fd1, FileData *fd2)
434 size_t len1 = fd1->extension - fd1->name;
435 size_t len2 = fd2->extension - fd2->name;
437 if (len1 < len2) return -1;
438 if (len1 > len2) return 1;
440 return strncmp(fd1->name, fd2->name, len1);
443 gboolean file_data_add_change_info(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest)
446 FileDataChangeInfo *fdci;
448 if (fd->change) return FALSE;
450 fdci = g_new0(FileDataChangeInfo, 1);
455 fdci->source = g_strdup(src);
457 fdci->source = g_strdup(fd->path);
460 fdci->dest = g_strdup(dest);
466 void file_data_change_info_free(FileDataChangeInfo *fdci, FileData *fd)
474 g_free(fdci->source);
487 *-----------------------------------------------------------------------------
488 * sidecar file info struct
489 *-----------------------------------------------------------------------------
494 static gint sidecar_file_priority(const gchar *path)
496 const char *extension = extension_from_path(path);
499 if (extension == NULL)
502 work = sidecar_ext_get_list();
505 gchar *ext = work->data;
507 if (strcmp(extension, ext) == 0) return i;
515 *-----------------------------------------------------------------------------
517 *-----------------------------------------------------------------------------
520 static SortType filelist_sort_method = SORT_NONE;
521 static gint filelist_sort_ascend = TRUE;
524 gint filelist_sort_compare_filedata(FileData *fa, FileData *fb)
526 if (!filelist_sort_ascend)
533 switch (filelist_sort_method)
536 if (fa->size < fb->size) return -1;
537 if (fa->size > fb->size) return 1;
538 return CASE_SORT(fa->name, fb->name); /* fall back to name */
541 if (fa->date < fb->date) return -1;
542 if (fa->date > fb->date) return 1;
543 return CASE_SORT(fa->name, fb->name); /* fall back to name */
545 #ifdef HAVE_STRVERSCMP
547 return strverscmp(fa->name, fb->name);
552 return CASE_SORT(fa->name, fb->name);
557 gint filelist_sort_compare_filedata_full(FileData *fa, FileData *fb, SortType method, gint ascend)
559 filelist_sort_method = method;
560 filelist_sort_ascend = ascend;
561 return filelist_sort_compare_filedata(fa, fb);
564 static gint filelist_sort_file_cb(void *a, void *b)
566 return filelist_sort_compare_filedata(a, b);
569 GList *filelist_sort_full(GList *list, SortType method, gint ascend, GCompareFunc cb)
571 filelist_sort_method = method;
572 filelist_sort_ascend = ascend;
573 return g_list_sort(list, cb);
576 GList *filelist_insert_sort_full(GList *list, void *data, SortType method, gint ascend, GCompareFunc cb)
578 filelist_sort_method = method;
579 filelist_sort_ascend = ascend;
580 return g_list_insert_sorted(list, data, cb);
583 GList *filelist_sort(GList *list, SortType method, gint ascend)
585 return filelist_sort_full(list, method, ascend, (GCompareFunc) filelist_sort_file_cb);
588 GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend)
590 return filelist_insert_sort_full(list, fd, method, ascend, (GCompareFunc) filelist_sort_file_cb);
594 static GList *filelist_filter_out_sidecars(GList *flist)
597 GList *flist_filtered = NULL;
601 FileData *fd = work->data;
603 if (fd->parent) /* remove fd's that are children */
606 flist_filtered = g_list_prepend(flist_filtered, fd);
609 return flist_filtered;
612 static gint filelist_read_real(const gchar *path, GList **files, GList **dirs, gint follow_symlinks)
616 struct stat ent_sbuf;
624 pathl = path_from_utf8(path);
625 if (!pathl || (dp = opendir(pathl)) == NULL)
628 if (files) *files = NULL;
629 if (dirs) *dirs = NULL;
634 if (pathl[0] == '/' && pathl[1] == '\0')
637 pathl = g_strdup("");
640 while ((dir = readdir(dp)) != NULL)
642 gchar *name = dir->d_name;
643 if (options->file_filter.show_hidden_files || !ishidden(name))
645 gchar *filepath = g_strconcat(pathl, "/", name, NULL);
646 if ((follow_symlinks ?
647 stat(filepath, &ent_sbuf) :
648 lstat(filepath, &ent_sbuf)) >= 0)
650 if (S_ISDIR(ent_sbuf.st_mode))
652 /* we ignore the .thumbnails dir for cleanliness */
654 !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) &&
655 strcmp(name, GQ_CACHE_LOCAL_THUMB) != 0 &&
656 strcmp(name, GQ_CACHE_LOCAL_METADATA) != 0 &&
657 strcmp(name, THUMB_FOLDER_LOCAL) != 0)
659 dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf, FALSE));
664 if ((files) && filter_name_exists(name))
666 flist = g_list_prepend(flist, file_data_new_local(filepath, &ent_sbuf, TRUE));
678 flist = filelist_filter_out_sidecars(flist);
680 if (dirs) *dirs = dlist;
681 if (files) *files = flist;
686 gint filelist_read(const gchar *path, GList **files, GList **dirs)
688 return filelist_read_real(path, files, dirs, TRUE);
691 gint filelist_read_lstat(const gchar *path, GList **files, GList **dirs)
693 return filelist_read_real(path, files, dirs, FALSE);
696 void filelist_free(GList *list)
703 file_data_unref((FileData *)work->data);
711 GList *filelist_copy(GList *list)
713 GList *new_list = NULL;
724 new_list = g_list_prepend(new_list, file_data_ref(fd));
727 return g_list_reverse(new_list);
730 GList *filelist_from_path_list(GList *list)
732 GList *new_list = NULL;
743 new_list = g_list_prepend(new_list, file_data_new_simple(path));
746 return g_list_reverse(new_list);
749 GList *filelist_to_path_list(GList *list)
751 GList *new_list = NULL;
762 new_list = g_list_prepend(new_list, g_strdup(fd->path));
765 return g_list_reverse(new_list);
768 GList *filelist_filter(GList *list, gint is_dir_list)
772 if (!is_dir_list && options->file_filter.disable && options->file_filter.show_hidden_files) return list;
777 FileData *fd = (FileData *)(work->data);
778 const gchar *name = fd->name;
780 if ((!options->file_filter.show_hidden_files && ishidden(name)) ||
781 (!is_dir_list && !filter_name_exists(name)) ||
782 (is_dir_list && name[0] == '.' && (strcmp(name, GQ_CACHE_LOCAL_THUMB) == 0 ||
783 strcmp(name, GQ_CACHE_LOCAL_METADATA) == 0)) )
787 list = g_list_remove_link(list, link);
801 *-----------------------------------------------------------------------------
803 *-----------------------------------------------------------------------------
806 static gint filelist_sort_path_cb(gconstpointer a, gconstpointer b)
808 return CASE_SORT(((FileData *)a)->path, ((FileData *)b)->path);
811 GList *filelist_sort_path(GList *list)
813 return g_list_sort(list, filelist_sort_path_cb);
816 static void filelist_recursive_append(GList **list, GList *dirs)
823 FileData *fd = (FileData *)(work->data);
824 const gchar *path = fd->path;
828 if (filelist_read(path, &f, &d))
830 f = filelist_filter(f, FALSE);
831 f = filelist_sort_path(f);
832 *list = g_list_concat(*list, f);
834 d = filelist_filter(d, TRUE);
835 d = filelist_sort_path(d);
836 filelist_recursive_append(list, d);
844 GList *filelist_recursive(const gchar *path)
849 if (!filelist_read(path, &list, &d)) return NULL;
850 list = filelist_filter(list, FALSE);
851 list = filelist_sort_path(list);
853 d = filelist_filter(d, TRUE);
854 d = filelist_sort_path(d);
855 filelist_recursive_append(&list, d);
864 * file_data - operates on the given fd
865 * file_data_sc - operates on the given fd + sidecars - all fds linked via fd->sidecar_files or fd->parent
869 /* return list of sidecar file extensions in a string */
870 gchar *file_data_sc_list_to_string(FileData *fd)
873 GString *result = g_string_new("");
875 work = fd->sidecar_files;
878 FileData *sfd = work->data;
879 result = g_string_append(result, "+ ");
880 result = g_string_append(result, sfd->extension);
882 if (work) result = g_string_append_c(result, ' ');
885 return g_string_free(result, FALSE);
889 /* disables / enables grouping for particular file, sends UPDATE notification */
890 void file_data_disable_grouping(FileData *fd); // now file_data_disconnect_sidecar_file, broken
891 void file_data_disable_grouping(FileData *fd);
893 /* runs stat on a file and sends UPDATE notification if it has been changed */
894 void file_data_sc_update(FileData *fd);
900 * add FileDataChangeInfo (see typedefs.h) for the given operation
901 * uses file_data_add_change_info
903 * fails if the fd->change already exists - change operations can't run in parallel
904 * fd->change_info works as a lock
906 * dest can be NULL - in this case the current name is used for now, it will
911 FileDataChangeInfo types:
913 MOVE - patch is changed, name may be changed too
914 RENAME - path remains unchanged, name is changed
915 extension should remain (FIXME should we allow editing extension? it will make problems wth grouping)
916 sidecar names are changed too, extensions are not changed
918 UPDATE - file size, date or grouping has been changed
921 gboolean file_data_add_ci(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest)
924 FileDataChangeInfo *fdci;
926 if (fd->change) return FALSE;
928 fdci = g_new0(FileDataChangeInfo, 1);
933 fdci->source = g_strdup(src);
935 fdci->source = g_strdup(fd->path);
938 fdci->dest = g_strdup(dest);
945 void file_data_free_ci(FileData *fd)
947 FileDataChangeInfo *fdci = fd->change;
952 g_free(fdci->source);
961 static gboolean file_data_sc_add_ci(FileData *fd, FileDataChangeType type)
964 if (fd->parent) fd = fd->parent;
966 if (fd->change) return FALSE;
967 work = fd->sidecar_files;
970 FileData *sfd = work->data;
971 if (sfd->change) return FALSE;
975 file_data_add_ci(fd, type, NULL, NULL);
977 work = fd->sidecar_files;
980 FileData *sfd = work->data;
981 file_data_add_ci(sfd, type, NULL, NULL);
988 static gboolean file_data_sc_check_ci(FileData *fd, FileDataChangeType type)
991 if (fd->parent) fd = fd->parent;
993 if (!fd->change) return FALSE;
994 if (fd->change->type != type) return FALSE;
995 work = fd->sidecar_files;
998 FileData *sfd = work->data;
999 if (!sfd->change) return FALSE;
1000 if (sfd->change->type != type) return FALSE;
1007 gboolean file_data_sc_add_ci_copy(FileData *fd, gchar *dest_path)
1009 if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_COPY)) return FALSE;
1010 file_data_sc_update_ci_copy(fd, dest_path);
1014 gboolean file_data_sc_add_ci_move(FileData *fd, gchar *dest_path)
1016 if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_MOVE)) return FALSE;
1017 file_data_sc_update_ci_move(fd, dest_path);
1021 gboolean file_data_sc_add_ci_rename(FileData *fd, gchar *dest_path)
1023 if (!file_data_sc_add_ci(fd, FILEDATA_CHANGE_RENAME)) return FALSE;
1024 file_data_sc_update_ci_rename(fd, dest_path);
1028 gboolean file_data_sc_add_ci_delete(FileData *fd)
1030 return file_data_sc_add_ci(fd, FILEDATA_CHANGE_DELETE);
1033 gboolean file_data_sc_add_ci_update(FileData *fd)
1035 return file_data_sc_add_ci(fd, FILEDATA_CHANGE_UPDATE);
1038 void file_data_sc_free_ci(FileData *fd)
1041 if (fd->parent) fd = fd->parent;
1043 file_data_free_ci(fd);
1045 work = fd->sidecar_files;
1048 FileData *sfd = work->data;
1049 file_data_free_ci(sfd);
1056 * update existing fd->change, it will be used from dialog callbacks for interactive editing
1057 * fails if fd->change does not exist or the change type does not match
1060 static void file_data_update_ci_dest(FileData *fd, gchar *dest_path)
1062 g_free(fd->change->dest);
1063 fd->change->dest = g_strdup(dest_path);
1066 static void file_data_update_ci_dest_preserve_ext(FileData *fd, gchar *dest_path)
1068 const char *extension = extension_from_path(fd->change->source);
1069 g_free(fd->change->dest);
1070 fd->change->dest = g_strdup_printf("%*s%s", (int)(extension_from_path(dest_path) - dest_path), dest_path, extension);
1073 static void file_data_sc_update_ci(FileData *fd, gchar *dest_path)
1076 if (fd->parent) fd = fd->parent;
1078 file_data_update_ci_dest(fd, dest_path);
1079 work = fd->sidecar_files;
1082 FileData *sfd = work->data;
1083 file_data_update_ci_dest_preserve_ext(sfd, dest_path);
1088 gint file_data_sc_update_ci_copy(FileData *fd, gchar *dest_path)
1090 if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_COPY)) return FALSE;
1091 file_data_sc_update_ci(fd, dest_path);
1095 gint file_data_sc_update_ci_move(FileData *fd, gchar *dest_path)
1097 if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_MOVE)) return FALSE;
1098 file_data_sc_update_ci(fd, dest_path);
1102 gint file_data_sc_update_ci_rename(FileData *fd, gchar *dest_path)
1104 if (!file_data_sc_check_ci(fd, FILEDATA_CHANGE_RENAME)) return FALSE;
1105 file_data_sc_update_ci(fd, dest_path);
1112 * check dest paths - dest image exists, etc.
1114 * it should detect all possible problems with the planned operation
1117 gint file_data_sc_check_ci_dest(FileData *fd)
1125 * perform the change described by FileFataChangeInfo
1126 * it is used for internal operations,
1127 * this function actually operates with files on the filesystem
1128 * it should implement safe delete
1131 static gboolean file_data_perform_move(FileData *fd)
1133 g_assert(!strcmp(fd->change->source, fd->path));
1134 return move_file(fd->change->source, fd->change->dest);
1137 static gboolean file_data_perform_copy(FileData *fd)
1139 g_assert(!strcmp(fd->change->source, fd->path));
1140 return copy_file(fd->change->source, fd->change->dest);
1143 static gboolean file_data_perform_delete(FileData *fd)
1145 return unlink_file(fd->path);
1148 static gboolean file_data_perform_ci(FileData *fd)
1150 FileDataChangeType type = fd->change->type;
1153 case FILEDATA_CHANGE_MOVE:
1154 return file_data_perform_move(fd);
1155 case FILEDATA_CHANGE_COPY:
1156 return file_data_perform_copy(fd);
1157 case FILEDATA_CHANGE_RENAME:
1158 return file_data_perform_move(fd); /* the same as move */
1159 case FILEDATA_CHANGE_DELETE:
1160 return file_data_perform_delete(fd);
1161 case FILEDATA_CHANGE_UPDATE:
1162 /* nothing to do here */
1170 gboolean file_data_sc_perform_ci(FileData *fd)
1173 gboolean ret = TRUE;
1174 FileDataChangeType type = fd->change->type;
1175 if (!file_data_sc_check_ci(fd, type)) return FALSE;
1177 work = fd->sidecar_files;
1180 FileData *sfd = work->data;
1181 if (!file_data_perform_ci(sfd)) ret = FALSE;
1184 if (!file_data_perform_ci(fd)) ret = FALSE;
1189 * updates FileData structure according to FileDataChangeInfo
1192 static void file_data_apply_ci(FileData *fd)
1194 FileDataChangeType type = fd->change->type;
1196 if (type == FILEDATA_CHANGE_MOVE || type == FILEDATA_CHANGE_COPY || type == FILEDATA_CHANGE_RENAME)
1199 g_hash_table_remove(file_data_pool, fd->original_path);
1200 g_free(fd->original_path);
1201 file_data_set_path(fd, fd->change->dest);
1202 fd->original_path = g_strdup(fd->change->dest);
1203 g_hash_table_insert(file_data_pool, fd->original_path, fd);
1207 gint file_data_sc_apply_ci(FileData *fd)
1210 FileDataChangeType type = fd->change->type;
1211 if (!file_data_sc_check_ci(fd, type)) return FALSE;
1213 work = fd->sidecar_files;
1216 FileData *sfd = work->data;
1217 file_data_apply_ci(sfd);
1220 file_data_apply_ci(fd);
1226 * notify other modules about the change described by FileFataChangeInfo
1229 /* might use file_maint_ functions for now, later it should be changed to a system of callbacks
1230 FIXME do we need the ignore_list? It looks like a workaround for ineffective
1231 implementation in view_file_list.c */
1233 void file_data_sc_send_notification(FileData *fd)