1 /* iconsel.c
2  * Copyright (C) 2002-2004 Pascal Eberhard <pascal.ebo@netcourrier.com>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program 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 GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 
21 #include "common.h"
22 #include <dirent.h>
23 #include <string.h>
24 #include <errno.h>
25 
26 #include "iconsel_private.h"
27 
28 #define _GNU_SOURCE 1
29 #include <fnmatch.h>
30 
31 //#ifndef FNM_CASEFOLD            // case insensitive but is not defined... ?
32 //#define FNM_CASEFOLD  (1 << 4)
33 //#endif
34 
35 // ----------------------------------------------------------------------------
icon_dir_new(gchar * path,gboolean selected,gboolean recursive)36 icon_dir_t *icon_dir_new(gchar *path, gboolean selected, gboolean recursive)
37 {
38   icon_dir_t *icon_dir;
39   g_assert(path != NULL);
40   icon_dir = (icon_dir_t *) malloc(sizeof(icon_dir_t));
41   g_assert(icon_dir != NULL);
42   icon_dir->path = path;
43   icon_dir->selected = selected;
44   icon_dir->recursive = recursive;
45   return icon_dir;
46 }
47 // ----------------------------------------------------------------------------
icon_dir_free(icon_dir_t * icon_dir)48 void icon_dir_free(icon_dir_t *icon_dir)
49 {
50   g_assert(icon_dir != NULL);
51   if (icon_dir->path)
52     g_free(icon_dir->path);
53   g_free(icon_dir);
54 }
55 // ----------------------------------------------------------------------------
icon_dir_compare(icon_dir_t * a,icon_dir_t * b)56 gint icon_dir_compare(icon_dir_t *a, icon_dir_t *b)
57 {
58   g_assert(a != NULL && b != NULL);
59   return strcmp(a->path, b->path);
60 }
61 // ----------------------------------------------------------------------------
icon_dir_list_append(GList ** list,icon_dir_t * dir)62 void icon_dir_list_append(GList **list, icon_dir_t *dir)
63 {
64   g_assert(list != NULL && dir != NULL);
65   *list = g_list_insert_sorted(*list, dir, (GCompareFunc) icon_dir_compare);
66 }
67 // ----------------------------------------------------------------------------
icon_dir_list_find(GList * list,char * olddir)68 icon_dir_t * icon_dir_list_find(GList *list, char *olddir)
69 {
70   GList *hamster;
71   icon_dir_t *dir;
72   g_assert(olddir != NULL);
73   hamster = g_list_first(list);
74   while(hamster != NULL)
75   {
76     dir = hamster->data;
77     if (strcmp(dir->path, olddir) == 0)
78       break;
79     hamster = g_list_next(hamster);
80   }
81   if (hamster == NULL)
82     return NULL;
83   else
84     return dir;
85 }
86 // ----------------------------------------------------------------------------
icon_dir_list_remove(GList ** list,char * olddir)87 void icon_dir_list_remove(GList **list, char *olddir)
88 {
89   GList *hamster;
90   icon_dir_t *dir;
91   g_assert(list != NULL && olddir != NULL);
92   hamster = g_list_first(*list);
93   while(hamster != NULL)
94   {
95     dir = hamster->data;
96     if (strcmp(dir->path, olddir) == 0)
97       break;
98     hamster = g_list_next(hamster);
99   }
100   if (hamster == NULL)
101     ERR("icon_dir_list_remove() olddir:%s not found", olddir);
102 
103   *list = g_list_remove(*list, dir);
104   icon_dir_free(dir);
105 }
106 // ----------------------------------------------------------------------------
icon_dir_list_modify(GList ** list,char * olddir,char * newdir)107 void icon_dir_list_modify(GList **list, char *olddir, char *newdir)
108 {
109   GList *hamster;
110   icon_dir_t *dir;
111   g_assert(list != NULL && olddir != NULL && newdir != NULL);
112   hamster = g_list_first(*list);
113   while(hamster != NULL)
114   {
115     dir = hamster->data;
116     if (strcmp(dir->path, newdir) == 0)
117       break;
118     hamster = g_list_next(hamster);
119   }
120   if (hamster != NULL)
121   {
122       WARN("icon_dir_list_modify() olddir:%s, newdir:%s, "
123                 "newdir already exist", olddir, newdir);
124       return;
125    }
126 
127   hamster = g_list_first(*list);
128   while(hamster != NULL)
129   {
130     dir = hamster->data;
131     if (strcmp(dir->path, olddir) == 0)
132       break;
133     hamster = g_list_next(hamster);
134   }
135   if (hamster == NULL)
136     ERR("icon_dir_list_modify() olddir:%s not found", olddir);
137   g_free(dir->path);
138   dir->path = g_strdup(newdir);
139   *list = g_list_sort(*list, (GCompareFunc) icon_dir_compare);
140 }
141 // ----------------------------------------------------------------------------
142 // ----------------------------------------------------------------------------
143 // ----------------------------------------------------------------------------
144 // ----------------------------------------------------------------------------
file_ext_new(gchar * extension,gboolean selected)145 file_ext_t *file_ext_new(gchar *extension, gboolean selected)
146 {
147   file_ext_t *file_ext;
148   g_assert(extension != NULL);
149   file_ext = (file_ext_t *) malloc(sizeof(file_ext_t));
150   g_assert(file_ext != NULL);
151   file_ext->extension = extension;
152   file_ext->selected = selected;
153   return file_ext;
154 }
155 // ----------------------------------------------------------------------------
file_ext_free(file_ext_t * file_ext)156 void file_ext_free(file_ext_t *file_ext)
157 {
158   if (file_ext->extension)
159     g_free(file_ext->extension);
160   g_free(file_ext);
161 }
162 // ----------------------------------------------------------------------------
file_ext_compare(file_ext_t * a,file_ext_t * b)163 gint file_ext_compare(file_ext_t *a, file_ext_t *b)
164 {
165   g_assert(a != NULL && b != NULL);
166   return strcmp(a->extension, b->extension);
167 }
168 // ----------------------------------------------------------------------------
file_ext_list_append(GList ** list,file_ext_t * ext)169 void file_ext_list_append(GList **list, file_ext_t *ext)
170 {
171   g_assert(list != NULL && ext != NULL);
172   *list = g_list_insert_sorted(*list, ext, (GCompareFunc) file_ext_compare);
173 }
174 // ----------------------------------------------------------------------------
file_ext_list_find(GList * list,char * oldext)175 file_ext_t * file_ext_list_find(GList *list, char *oldext)
176 {
177   GList *hamster;
178   file_ext_t *ext;
179   g_assert(oldext != NULL);
180   hamster = g_list_first(list);
181   while(hamster != NULL)
182   {
183     ext = hamster->data;
184     if (strcmp(ext->extension, oldext) == 0)
185       break;
186     hamster = g_list_next(hamster);
187   }
188   if (hamster == NULL)
189     return NULL;
190   else
191     return ext;
192 }
193 // ----------------------------------------------------------------------------
file_ext_list_remove(GList ** list,char * oldext)194 void file_ext_list_remove(GList **list, char *oldext)
195 {
196   GList *hamster;
197   file_ext_t *ext;
198   g_assert(list != NULL && oldext != NULL);
199   hamster = g_list_first(*list);
200   while(hamster != NULL)
201   {
202     ext = hamster->data;
203     if (strcmp(ext->extension, oldext) == 0)
204       break;
205     hamster = g_list_next(hamster);
206   }
207   if (hamster == NULL)
208     ERR("file_ext_list_remove() oldext:%s not found", oldext);
209 
210   *list = g_list_remove(*list, ext);
211   file_ext_free(ext);
212 }
213 // ----------------------------------------------------------------------------
file_ext_list_modify(GList ** list,char * oldext,char * newext)214 void file_ext_list_modify(GList **list, char *oldext, char *newext)
215 {
216   GList *hamster;
217   file_ext_t *ext;
218   g_assert(list != NULL && oldext != NULL && newext != NULL);
219   hamster = g_list_first(*list);
220   while(hamster != NULL)
221   {
222     ext = hamster->data;
223     if (strcmp(ext->extension, newext) == 0)
224       break;
225     hamster = g_list_next(hamster);
226   }
227   if (hamster != NULL)
228   {
229     WARN("file_ext_list_modify() oldext:%s, newext:%s, "
230               "newext already exist", oldext, newext);
231     return;
232   }
233   hamster = g_list_first(*list);
234   while(hamster != NULL)
235   {
236     ext = hamster->data;
237     if (strcmp(ext->extension, oldext) == 0)
238       break;
239     hamster = g_list_next(hamster);
240   }
241   if (hamster == NULL)
242     ERR("file_ext_list_modify() oldext:%s not found", oldext);
243   g_free(ext->extension);
244   ext->extension = g_strdup(newext);
245   *list = g_list_sort(*list, (GCompareFunc) file_ext_compare);
246 }
247 // ----------------------------------------------------------------------------
248 // ----------------------------------------------------------------------------
249 // ----------------------------------------------------------------------------
250 // ----------------------------------------------------------------------------
251 // ----------------------------------------------------------------------------
iconsel_pref_new(GList * icon_dirs,GList * file_exts,gboolean eq48,gboolean lt48,gboolean gt48,gint sort)252 iconsel_pref_t * iconsel_pref_new(GList *icon_dirs, GList *file_exts,
253                                   gboolean eq48, gboolean lt48,
254                                   gboolean gt48, gint sort)
255 {
256   iconsel_pref_t *ispref;
257   TRACE("%s", "");
258   ispref = (iconsel_pref_t *) malloc(sizeof(iconsel_pref_t));
259   g_assert(ispref != NULL);
260   ispref->icon_dirs = icon_dirs;
261   ispref->file_exts = file_exts;
262   ispref->select_48 = eq48;
263   ispref->select_lt48 = lt48;
264   ispref->select_gt48 = gt48;
265   if (sort < 0 || sort > ICONSEL_SORT_LAST)
266   {
267     WARN("sort_mode:%d invalid, set to default:%d",
268               sort, ICONSEL_SORT_DEFAULT);
269     sort = ICONSEL_SORT_DEFAULT;
270   }
271   ispref->sort_mode = sort;
272   return ispref;
273 }
274 // ----------------------------------------------------------------------------
275 // ----------------------------------------------------------------------------
276 // ----------------------------------------------------------------------------
277 // ----------------------------------------------------------------------------
278 // ----------------------------------------------------------------------------
279 // ----------------------------------------------------------------------------
280 // ----------------------------------------------------------------------------
281 // ----------------------------------------------------------------------------
icon_selection_new(struct apwalapp_t * apwal)282 icon_selection_t* icon_selection_new(struct apwalapp_t *apwal)
283 {
284   icon_selection_t *iconsel;
285 
286   g_assert(apwal != NULL);
287   TRACE("%s", "");
288 
289   iconsel = (icon_selection_t *) malloc(sizeof(icon_selection_t));
290   g_assert(iconsel != NULL);
291 
292   iconsel->apwal = apwal;
293   iconsel->filter = g_strdup("*");
294 
295   iconsel->image = NULL;
296 
297   iconsel->dblclick_timer = NULL;
298   iconsel->dblclick_selected_timer = NULL;
299 
300   iconsel->never_refreshed = TRUE;
301 
302   iconsel->icons = icon_list_new(iconsel);
303   iconsel_build_interface(iconsel);
304   return iconsel;
305 }
306 
307 // ----------------------------------------------------------------------------
icon_selection_load_icons_with_splash(icon_selection_t * iconsel)308 void icon_selection_load_icons_with_splash(icon_selection_t *iconsel)
309 {
310   GList      *hamster;
311   icon_dir_t *icon_dir;
312   g_assert(iconsel != NULL);
313   splash_show(iconsel->apwal->splash);
314   hamster = iconsel->apwal->iconsel_pref->icon_dirs;
315   while(hamster != NULL)
316   {
317     splash_update(iconsel->apwal->splash);
318     icon_dir = hamster->data;
319     icon_list_append(iconsel->icons, icon_dir->path,
320                      icon_dir->selected, icon_dir->recursive);
321     hamster = g_list_next(hamster);
322   }
323   splash_hide(iconsel->apwal->splash);
324   iconsel_path_refresh(iconsel);
325 }
326 // ----------------------------------------------------------------------------
327 // ----------------------------------------------------------------------------
328 // usage: icon_list_select(iconsel->icons, iconsel_select_func, iconsel);
iconsel_select_func(ico_t * ico,void * data)329 gboolean iconsel_select_func(ico_t *ico, void *data)
330 {
331   gboolean selected;
332   int      cc;
333   icon_selection_t *iconsel = (icon_selection_t *) data;
334   g_assert(ico != NULL && iconsel != NULL);
335 
336   selected = TRUE;
337   while (1)     // begin of a 'block' which can be aborted by a break
338   {
339  #if 0
340   GList      *ext_hamster;
341   file_ext_t *ext;
342     // check if the size is selected
343     if ((iconsel->ispref->select_48 == TRUE) &&
344         (ico->width == 48) && (ico->height == 48))
345       selected = TRUE;
346     else if ((iconsel->ispref->select_gt48 == TRUE) &&
347              ((ico->width > 48) || (ico->height > 48)))
348       selected = TRUE;
349     else if ((iconsel->ispref->select_lt48 == TRUE) &&
350              ((ico->width < 48) || (ico->height < 48)))
351       selected = TRUE;
352     else
353     {
354       selected = FALSE;
355       break;
356     }
357 
358     // check if the name is matching one of the patterns
359     // if name matches pattern then go out the loop with cc=0
360     // if name don't match any pattern then cc!=0 at the end of the loop
361     // after the loop, if cc!=0 then don't select the name and return 0
362     ext_hamster = g_list_first(iconsel->ispref->file_exts);
363     while(ext_hamster != NULL)
364     {
365       ext = ext_hamster->data;
366       if (ext->selected == TRUE)
367       {
368         cc = fnmatch(ext->extension, ico->name, FNM_CASEFOLD);
369         //TRACE("ext:%s, name:%s, cc:%d", ext->extension, ico->name, cc);
370         if (cc == 0)        // success
371           break;
372 
373         if ((cc != 0) && (cc != FNM_NOMATCH))      // error during match
374           WARN("fnmatch, ext:%s, name:%s, E:%d",
375                     ext->extension, ico->name, cc);
376       }
377       ext_hamster = g_list_next(ext_hamster);
378     } //end while ext
379     if (cc != 0 || ext_hamster == NULL)      // not match
380     {
381       selected = FALSE;
382       break;
383     }
384  #endif
385 
386     // check if the name match the filter
387     cc = fnmatch(iconsel->filter, ico->name, FNM_CASEFOLD);
388     if (cc != 0)
389     {
390       selected = FALSE;
391       if (cc != FNM_NOMATCH)
392         WARN("fnmatch filter:%s, name:%s, E:%d",
393              iconsel->filter, ico->name, cc);
394       break;
395     }
396     break; // end of the 'block'
397   } // end of the 'block'
398   return selected;
399 }
400 // ----------------------------------------------------------------------------
401 // ----------------------------------------------------------------------------
iconsel_set_filename(icon_selection_t * iconsel,const char * filename)402 void iconsel_set_filename(icon_selection_t *iconsel, const char *filename)
403 {
404   g_assert(iconsel != NULL);
405   TRACE("%s", "");
406   icon_list_set_selected_icon_from_filename(iconsel->icons, filename);
407 }
408 // ----------------------------------------------------------------------------
409 // ----------------------------------------------------------------------------
iconsel_get_filename(icon_selection_t * iconsel)410 char *iconsel_get_filename(icon_selection_t *iconsel)
411 {
412   g_assert(iconsel != NULL);
413   TRACE("%s", "");
414   return icon_list_get_selected_icon_filename(iconsel->icons);
415 }
416 // ----------------------------------------------------------------------------
417 // ----------------------------------------------------------------------------
418 // ----------------------------------------------------------------------------
419 // ----------------------------------------------------------------------------
420