1 /*
2 This file is part of darktable,
3 Copyright (C) 2020 darktable developers.
4 darktable is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 darktable is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with darktable. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "dtwin.h"
19
win_image_find_duplicates(const char * filename)20 GList* win_image_find_duplicates(const char* filename)
21 {
22 // find all duplicates of an image
23 gchar pattern[PATH_MAX] = { 0 };
24 GList* files = NULL;
25 gchar *imgpath = g_path_get_dirname(filename);
26 // Windows only accepts generic wildcards for filename
27 static const gchar *glob_patterns[] = { "", "_????", NULL };
28 const gchar *c3 = filename + strlen(filename);
29 while(*c3 != '\\' && c3 > filename) c3--;
30 if(*c3 == '\\') c3++;
31 const gchar **glob_pattern = glob_patterns;
32 files = NULL;
33 while(*glob_pattern)
34 {
35 g_strlcpy(pattern, filename, sizeof(pattern));
36 gchar *c1 = pattern + strlen(pattern);
37 while(*c1 != '.' && c1 > pattern) c1--;
38 g_strlcpy(c1, *glob_pattern, pattern + sizeof(pattern) - c1);
39 const gchar *c2 = filename + strlen(filename);
40 while(*c2 != '.' && c2 > filename) c2--;
41 snprintf(c1 + strlen(*glob_pattern), pattern + sizeof(pattern) - c1 - strlen(*glob_pattern), "%s.xmp", c2);
42 wchar_t *wpattern = g_utf8_to_utf16(pattern, -1, NULL, NULL, NULL);
43 WIN32_FIND_DATAW data;
44 HANDLE handle = FindFirstFileW(wpattern, &data);
45 g_free(wpattern);
46 gchar *imgfile_without_path=g_strndup(c3,c2-c3); /*Need to remove path from front of filename*/
47 if(handle != INVALID_HANDLE_VALUE)
48 {
49 do
50 {
51 gchar *file = g_utf16_to_utf8(data.cFileName, -1, NULL, NULL, NULL);
52 gchar *short_file_name = g_strndup(file, strlen(file) - 4 + c2 - filename - strlen(filename));
53 gboolean valid_xmp_name = FALSE;
54 if(!(valid_xmp_name = (strlen(short_file_name) == strlen(imgfile_without_path))))
55 {
56 // if not the same length, make sure the extra char are 2-4 digits preceded by '_'
57 gchar *c4 = short_file_name + strlen(short_file_name);
58 int i=0;
59 do
60 {
61 c4--;
62 i++;
63 }
64 while(g_ascii_isdigit(*c4) && c4 > short_file_name && i <= 4);
65 valid_xmp_name = (*c4 == '_' && strlen(short_file_name) == strlen(imgfile_without_path) + i);
66 }
67
68 if(valid_xmp_name)
69 files = g_list_append(files, g_build_filename(imgpath, file, NULL));
70
71 g_free(short_file_name);
72 g_free(file);
73 }
74 while(FindNextFileW(handle, &data));
75
76 }
77
78 g_free(imgfile_without_path);
79 FindClose(handle);
80 glob_pattern++;
81 }
82
83 g_free(imgpath);
84 return files;
85 }
86
87 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
88 // vim: shiftwidth=2 expandtab tabstop=2 cindent
89 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
90