update for beta release
[framework/uifw/e17.git] / src / modules / everything / evry_plug_files.c
1 /***************************************************
2    TODO option for maximum items to cache
3    TODO keep common list for recent file instances
4    FIXME
5  */
6
7 #include "e.h"
8 #include "evry_api.h"
9 #include <Efreet_Trash.h>
10
11 #define MOD_CONFIG_FILE_EPOCH      0x0001
12 #define MOD_CONFIG_FILE_GENERATION 0x008d
13 #define MOD_CONFIG_FILE_VERSION \
14   ((MOD_CONFIG_FILE_EPOCH << 16) | MOD_CONFIG_FILE_GENERATION)
15
16 #define MAX_ITEMS                  10
17 #define MAX_SHOWN                  300
18 #define TERM_ACTION_DIR            "%s"
19
20 #define CMD_NONE                   0
21 #define CMD_SHOW_ROOT              1
22 #define CMD_SHOW_HIDDEN            2
23 #define CMD_SHOW_PARENT            3
24
25 #define ACT_TRASH                  1
26 #define ACT_DELETE                 2
27 #define ACT_COPY                   3
28 #define ACT_MOVE                   4
29 #define ACT_SORT_DATE              5
30 #define ACT_SORT_NAME              6
31
32 #define ONE_DAY                    86400.0
33 #define SIX_DAYS_AGO               (ecore_time_unix_get() - ONE_DAY * 6)
34 #define MIN_USAGE                  0.0
35
36 /* #undef DBG
37  * #define DBG(...) ERR(__VA_ARGS__) */
38
39 typedef struct _Plugin        Plugin;
40 typedef struct _Data          Data;
41 typedef struct _Module_Config Module_Config;
42
43 struct _Plugin
44 {
45    Evry_Plugin         base;
46
47    Eina_List          *files;
48    const char         *directory;
49    const char         *input;
50    unsigned int        command;
51    unsigned int        min_query;
52    Eina_Bool           parent;
53    Eina_Bool           show_hidden;
54    Eina_Bool           dirs_only;
55    Eina_Bool           show_recent;
56    Eina_Bool           sort_by_date;
57
58    Ecore_Thread       *thread;
59    Ecore_File_Monitor *dir_mon;
60    int                 waiting_to_finish;
61 };
62
63 struct _Data
64 {
65    Plugin    *plugin;
66    char      *directory;
67    long       id;
68    int        level;
69    int        cnt;
70    Eina_List *files;
71    DIR       *dirp;
72    int        run_cnt;
73 };
74
75 struct _Module_Config
76 {
77    int              version;
78
79    unsigned char    show_homedir;
80    unsigned char    show_recent;
81    unsigned char    search_recent;
82    unsigned char    cache_dirs;
83    unsigned char    search_cache;
84
85    // TODO
86    int              sort_by;
87    Eina_List       *search_dirs;
88
89    E_Config_Dialog *cfd;
90    E_Module        *module;
91 };
92
93 static const Evry_API *evry = NULL;
94 static Evry_Module *evry_module = NULL;
95
96 static Module_Config *_conf;
97 static char _module_icon[] = "system-file-manager";
98 static Eina_List *_plugins = NULL;
99 static Eina_List *_actions = NULL;
100 static const char *_mime_dir;
101 static const char *_mime_mount;
102 static const char *_mime_unknown;
103 static Eina_Bool clear_cache = EINA_FALSE;
104
105 /***************************************************************************/
106
107 static void
108 _item_fill(Evry_Item_File *file)
109 {
110    if (!file->mime)
111      {
112         const char *mime = efreet_mime_type_get(file->path);
113
114         if (mime)
115           file->mime = eina_stringshare_ref(mime);
116         else
117           file->mime = eina_stringshare_add("unknown");
118      }
119
120    if ((file->mime == _mime_dir) ||
121        (file->mime == _mime_mount))
122      EVRY_ITEM(file)->browseable = EINA_TRUE;
123
124    EVRY_ITEM(file)->context = eina_stringshare_ref(file->mime);
125
126    if (!EVRY_ITEM(file)->detail)
127      evry->util_file_detail_set(file);
128
129    evry->util_file_detail_set(file);
130 }
131
132 static int
133 _cb_sort(const void *data1, const void *data2)
134 {
135    const Evry_Item *it1 = data1;
136    const Evry_Item *it2 = data2;
137
138    if (it1->browseable && !it2->browseable)
139      return -1;
140
141    if (!it1->browseable && it2->browseable)
142      return 1;
143
144    if (it1->fuzzy_match && it2->fuzzy_match)
145      if (it1->fuzzy_match - it2->fuzzy_match)
146        return it1->fuzzy_match - it2->fuzzy_match;
147
148    return strcasecmp(it1->label, it2->label);
149 }
150
151 static int
152 _cb_sort_date(const void *data1, const void *data2)
153 {
154    const Evry_Item_File *it1 = data1;
155    const Evry_Item_File *it2 = data2;
156
157    return it2->modified - it1->modified;
158 }
159
160 static void
161 _scan_func(void *data, Ecore_Thread *thread)
162 {
163    Data *d = data;
164    Eina_Iterator *ls;
165    Eina_File_Direct_Info *info;
166    Evry_Item_File *file;
167
168    if (!(ls = eina_file_stat_ls(d->directory)))
169      return;
170
171    EINA_ITERATOR_FOREACH (ls, info)
172      {
173         if ((d->plugin->show_hidden) != (*(info->path + info->name_start) == '.'))
174           continue;
175
176         file = EVRY_ITEM_NEW(Evry_Item_File, d->plugin, NULL, NULL, evry_item_file_free);
177         file->path = strdup(info->path);
178         EVRY_ITEM(file)->label = strdup(info->path + info->name_start);
179         EVRY_ITEM(file)->browseable = (info->type == EINA_FILE_DIR);
180
181         d->files = eina_list_append(d->files, file);
182         /* TODO dont append files in thread, run mime scan
183          * simultaneously. ecore_thread_feedback(thread, file); */
184
185         if (ecore_thread_check(thread))
186           break;
187      }
188
189    eina_iterator_free(ls);
190 }
191
192 static void
193 _scan_mime_func(void *data, Ecore_Thread *thread)
194 {
195    Data *d = data;
196    Evry_Item_File *file;
197    Eina_List *l;
198    int cnt = 0;
199
200    EINA_LIST_FOREACH (d->files, l, file)
201      {
202         if (ecore_thread_check(thread))
203           break;
204
205         if ((file->mime = efreet_mime_type_get(file->path)))
206           {
207              if (!strncmp(file->mime, "inode/", 6) &&
208                  ecore_file_is_dir(file->path))
209                EVRY_ITEM(file)->browseable = EINA_TRUE;
210           }
211         else
212           file->mime = _mime_unknown;
213
214         if (cnt++ > MAX_ITEMS * d->run_cnt) break;
215      }
216 }
217
218 static int
219 _files_filter(Plugin *p)
220 {
221    int match;
222    int cnt = 0;
223    Evry_Item *it;
224    Eina_List *l;
225    unsigned int len = p->input ? strlen(p->input) : 0;
226
227    EVRY_PLUGIN_ITEMS_CLEAR(p);
228
229    if (!p->command && p->min_query)
230      {
231         if (!p->input)
232           return 0;
233         if (len < p->min_query)
234           return 0;
235      }
236
237    EINA_LIST_FOREACH (p->files, l, it)
238      {
239         if (cnt >= MAX_SHOWN) break;
240
241         if (p->dirs_only && !it->browseable)
242           continue;
243
244         if (len && (match = evry->fuzzy_match(it->label, p->input)))
245           {
246              it->fuzzy_match = match;
247              if (!it->browseable)
248                it->priority = 1;
249              EVRY_PLUGIN_ITEM_APPEND(p, it);
250              cnt++;
251           }
252         else if (len == 0)
253           {
254              if (!it->browseable)
255                it->priority = 1;
256              EVRY_PLUGIN_ITEM_APPEND(p, it);
257              cnt++;
258           }
259      }
260    return cnt;
261 }
262
263 static void
264 _scan_cancel_func(void *data, Ecore_Thread *thread __UNUSED__)
265 {
266    Data *d = data;
267    Plugin *p = d->plugin;
268    Evry_Item_File *file;
269
270    /* EINA_LIST_FREE(p->files, file)
271     *   EVRY_ITEM_FREE(file); */
272
273    EINA_LIST_FREE (d->files, file)
274      {
275         if (file->base.label) free((char *)(file->base.label));
276         if (file->path) free((char *)file->path);
277         E_FREE(file);
278      }
279
280    p->thread = NULL;
281
282    if (p->waiting_to_finish)
283      E_FREE(p);
284
285    free(d->directory);
286    E_FREE(d);
287 }
288
289 static void
290 _cache_mime_get(History_Types *ht, Evry_Item_File *file)
291 {
292    History_Entry *he;
293    History_Item *hi;
294    Eina_List *l;
295
296    if ((he = eina_hash_find(ht->types, file->path)))
297      {
298         EINA_LIST_FOREACH (he->items, l, hi)
299           {
300              if (!hi->data)
301                continue;
302
303              if (!file->mime)
304                file->mime = hi->data;
305
306              hi->transient = 0;
307              EVRY_ITEM(file)->hi = hi;
308              break;
309           }
310      }
311 }
312
313 static void
314 _cache_dir_add(Eina_List *files)
315 {
316    Eina_List *l;
317    Evry_Item *item;
318    History_Item *hi;
319    int cnt = 0;
320
321    EINA_LIST_REVERSE_FOREACH (files, l, item)
322      {
323         GET_FILE(file, item);
324
325         if (!(item->hi) &&
326             (hi = evry->history_item_add(item, NULL, NULL)))
327           {
328              hi->last_used = SIX_DAYS_AGO;
329              hi->usage = MIN_USAGE * (double)cnt++;
330              hi->data = eina_stringshare_ref(file->mime);
331              item->hi = hi;
332           }
333         else if (item->hi && (item->hi->count == 1) &&
334                  (item->hi->last_used < SIX_DAYS_AGO))
335           {
336              item->hi->last_used = SIX_DAYS_AGO;
337              item->hi->usage = MIN_USAGE * (double)cnt++;
338           }
339      }
340 }
341
342 static void
343 _file_add(Plugin *p, Evry_Item *item)
344 {
345    GET_FILE(file, item);
346
347    char *filename = (char *)item->label;
348    char *path = (char *)file->path;
349
350    file->path = eina_stringshare_add(path);
351    file->mime = eina_stringshare_ref(file->mime);
352
353    item->label = eina_stringshare_add(filename);
354    item->id = eina_stringshare_ref(file->path);
355    item->context = eina_stringshare_ref(file->mime);
356
357    evry->util_file_detail_set(file);
358
359    p->files = eina_list_append(p->files, file);
360
361    E_FREE(filename);
362    E_FREE(path);
363 }
364
365 static void
366 _scan_end_func(void *data, Ecore_Thread *thread __UNUSED__)
367 {
368    Data *d = data;
369    Plugin *p = d->plugin;
370    Evry_Item *item;
371    Evry_Item_File *file;
372    Eina_List *l, *ll;
373    History_Types *ht = NULL;
374
375    if (_conf->cache_dirs)
376      ht = evry->history_types_get(EVRY_TYPE_FILE);
377
378    if (!d->run_cnt) /* _scan_func finished */
379      {
380         EINA_LIST_FOREACH_SAFE (d->files, l, ll, item)
381           {
382              GET_FILE(file, item);
383
384              if (item->browseable)
385                file->mime = _mime_dir;
386              else if (ht)
387                _cache_mime_get(ht, file);
388
389              if (file->mime)
390                {
391                   d->files = eina_list_remove_list(d->files, l);
392                   _file_add(p, item);
393                }
394           }
395
396         /* sort files by name for mimetypes scan */
397         if (d->files)
398           d->files = eina_list_sort(d->files, -1, _cb_sort);
399      }
400    else /* _scan_mime_func finished */
401      {
402         EINA_LIST_FREE (d->files, file)
403           {
404              if (!file->mime) break;
405              _file_add(p, (Evry_Item *)file);
406           }
407      }
408
409    if (d->files) /* scan mimetypes */
410      {
411         d->run_cnt++;
412         p->thread = ecore_thread_run(_scan_mime_func,
413                                      _scan_end_func,
414                                      _scan_cancel_func, d);
415
416         /* wait for first mime scan to finish */
417         if (d->run_cnt == 1) return;
418      }
419    else /* finished all file/mime scan */
420      {
421         free(d->directory);
422         E_FREE(d);
423         p->thread = NULL;
424
425         if (_conf->cache_dirs && !(p->command == CMD_SHOW_HIDDEN))
426           _cache_dir_add(p->files);
427      }
428
429    p->files = eina_list_sort(p->files, -1, _cb_sort);
430
431    _files_filter(p);
432
433    EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
434 }
435
436 static void
437 _dir_watcher(void *data, Ecore_File_Monitor *em __UNUSED__, Ecore_File_Event event, const char *path)
438 {
439    Plugin *p = data;
440    Evry_Item_File *file;
441    const char *label;
442    Eina_List *ll, *l;
443
444    switch (event)
445      {
446       case ECORE_FILE_EVENT_DELETED_SELF:
447         EINA_LIST_FREE (p->files, file)
448           evry->item_free(EVRY_ITEM(file));
449         break;
450
451       case ECORE_FILE_EVENT_CREATED_DIRECTORY:
452       case ECORE_FILE_EVENT_CREATED_FILE:
453         label = ecore_file_file_get(path);
454
455         file = EVRY_ITEM_NEW(Evry_Item_File, p, label, NULL, evry_item_file_free);
456         file->path = eina_stringshare_add(path);
457
458         if (event == ECORE_FILE_EVENT_CREATED_DIRECTORY)
459           file->mime = eina_stringshare_ref(_mime_dir);
460
461         _item_fill(file);
462         p->files = eina_list_append(p->files, file);
463         break;
464
465       case ECORE_FILE_EVENT_DELETED_FILE:
466       case ECORE_FILE_EVENT_DELETED_DIRECTORY:
467         label = eina_stringshare_add(path);
468
469         EINA_LIST_FOREACH_SAFE (p->files, l, ll, file)
470           {
471              if (file->path != label) continue;
472
473              p->files = eina_list_remove_list(p->files, l);
474
475              EVRY_ITEM_FREE(file);
476              break;
477           }
478         eina_stringshare_del(label);
479         break;
480
481       default:
482         return;
483      }
484
485    _files_filter(p);
486
487    EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
488 }
489
490 static void
491 _read_directory(Plugin *p)
492 {
493    Data *d = E_NEW(Data, 1);
494    d->plugin = p;
495    d->directory = strdup(p->directory);
496    d->run_cnt = 0;
497
498    p->thread = ecore_thread_run(_scan_func, _scan_end_func, _scan_cancel_func, d);
499
500    if (p->dir_mon)
501      ecore_file_monitor_del(p->dir_mon);
502
503    p->dir_mon = ecore_file_monitor_add(p->directory, _dir_watcher, p);
504 }
505
506 static Evry_Plugin *
507 _browse(Evry_Plugin *plugin, const Evry_Item *it)
508 {
509    Plugin *p = NULL;
510
511    if (!it || !(CHECK_TYPE(it, EVRY_TYPE_FILE)))
512      return NULL;
513
514    GET_FILE(file, it);
515
516    if (!evry->file_path_get(file) ||
517        !ecore_file_is_dir(file->path))
518      return NULL;
519
520    EVRY_PLUGIN_INSTANCE(p, plugin);
521
522    p->directory = eina_stringshare_add(file->path);
523    p->parent = EINA_TRUE;
524
525    _read_directory(p);
526
527    return EVRY_PLUGIN(p);
528 }
529
530 static Evry_Plugin *
531 _begin(Evry_Plugin *plugin, const Evry_Item *it)
532 {
533    Plugin *p = NULL;
534
535    if (it)
536      {
537         const char *dir = NULL;
538
539         if ((CHECK_TYPE(it, EVRY_TYPE_FILE)) ||
540             (CHECK_SUBTYPE(it, EVRY_TYPE_FILE)))
541           {
542              /* browse */
543              GET_FILE(file, it);
544              if (!evry->file_path_get(file))
545                return NULL;
546
547              if (!ecore_file_is_dir(file->path))
548                {
549                   char *tmp = ecore_file_dir_get(file->path);
550                   dir = eina_stringshare_add(tmp);
551                   E_FREE(tmp);
552                }
553              else
554                {
555                   dir = eina_stringshare_add(file->path);
556                }
557           }
558         else
559           {
560              /* provide object */
561              if (!CHECK_TYPE(it, EVRY_TYPE_ACTION))
562                return NULL;
563           }
564
565         if (!dir)
566           dir = eina_stringshare_add(e_user_homedir_get());
567
568         EVRY_PLUGIN_INSTANCE(p, plugin);
569         p->directory = dir;
570         p->parent = EINA_FALSE;
571         p->min_query = 0;
572         _read_directory(p);
573
574         return EVRY_PLUGIN(p);
575      }
576    else
577      {
578         /* provide subject */
579         EVRY_PLUGIN_INSTANCE(p, plugin);
580         p->parent = EINA_FALSE;
581         p->directory = eina_stringshare_add(e_user_homedir_get());
582         p->min_query = plugin->config->min_query;
583         _read_directory(p);
584
585         return EVRY_PLUGIN(p);
586      }
587
588    return NULL;
589 }
590
591 static void
592 _folder_item_add(Plugin *p, const char *path, int prio)
593 {
594    Evry_Item_File *file;
595
596    file = EVRY_ITEM_NEW(Evry_Item_File, p, path, NULL, evry_item_file_free);
597    file->path = eina_stringshare_add(path);
598    file->mime = eina_stringshare_ref(_mime_dir);
599    EVRY_ITEM(file)->browseable = EINA_TRUE;
600    EVRY_ITEM(file)->priority = prio;
601    EVRY_ITEM(file)->usage = -1;
602    p->files = eina_list_append(p->files, file);
603    EVRY_PLUGIN_ITEM_APPEND(p, file);
604 }
605
606 static void
607 _free_files(Plugin *p)
608 {
609    Evry_Item_File *file;
610
611    EVRY_PLUGIN_ITEMS_CLEAR(p);
612
613    if (p->thread)
614      ecore_thread_cancel(p->thread);
615    p->thread = NULL;
616
617    EINA_LIST_FREE (p->files, file)
618      EVRY_ITEM_FREE(file);
619
620    if (p->dir_mon)
621      ecore_file_monitor_del(p->dir_mon);
622    p->dir_mon = NULL;
623 }
624
625 static void
626 _finish(Evry_Plugin *plugin)
627 {
628    GET_PLUGIN(p, plugin);
629
630    IF_RELEASE(p->input);
631    IF_RELEASE(p->directory);
632
633    if (p->thread)
634      p->waiting_to_finish = 1;
635
636    _free_files(p);
637
638    if (!p->waiting_to_finish)
639      E_FREE(p);
640 }
641
642 static int
643 _fetch(Evry_Plugin *plugin, const char *input)
644 {
645    GET_PLUGIN(p, plugin);
646    unsigned int len = (input ? strlen(input) : 0);
647
648    if (!p->command)
649      EVRY_PLUGIN_ITEMS_CLEAR(p);
650
651    IF_RELEASE(p->input);
652
653    if (!p->parent && input && !strncmp(input, "/", 1))
654      {
655         char *path = NULL;
656
657         if (p->command != CMD_SHOW_ROOT)
658           {
659              _free_files(p);
660
661              IF_RELEASE(p->directory);
662
663              if (path)
664                {
665                   p->directory = eina_stringshare_add(path);
666                   free(path);
667                }
668              else
669                {
670                   p->directory = eina_stringshare_add("/");
671                }
672
673              _read_directory(p);
674
675              p->command = CMD_SHOW_ROOT;
676
677              return 0;
678           }
679         int len = strlen(p->directory);
680         len = (len == 1) ? len : len + 1;
681
682         p->input = eina_stringshare_add(input + len);
683      }
684    else if (p->directory && input && !strncmp(input, "..", 2))
685      {
686         if (p->command != CMD_SHOW_PARENT)
687           {
688              char *dir;
689              char buf[PATH_MAX];
690              int prio = 0;
691
692              if (strncmp(p->directory, "/", 1))
693                return 0;
694
695              _free_files(p);
696
697              strncpy(buf, p->directory, PATH_MAX);
698
699              _folder_item_add(p, p->directory, prio++);
700
701              while (strlen(buf) > 1)
702                {
703                   buf[PATH_MAX - 1] = 0;
704                   dir = dirname(buf);
705                   _folder_item_add(p, dir, prio++);
706                   strncpy(buf, dir, PATH_MAX);
707                }
708
709              p->command = CMD_SHOW_PARENT;
710           }
711         return 1;
712      }
713    else if (p->directory && input && !strncmp(input, ".", 1))
714      {
715         if (p->command != CMD_SHOW_HIDDEN)
716           {
717              _free_files(p);
718
719              p->show_hidden = EINA_TRUE;
720              _read_directory(p);
721
722              p->command = CMD_SHOW_HIDDEN;
723
724              return 0;
725           }
726         p->input = eina_stringshare_add(input);
727      }
728    else if (p->command)
729      {
730         /* clear command items */
731         _free_files(p);
732
733         if (p->command == CMD_SHOW_ROOT)
734           {
735              IF_RELEASE(p->directory);
736              p->directory = eina_stringshare_add(e_user_homedir_get());
737           }
738
739         p->command = CMD_NONE;
740         p->show_hidden = EINA_FALSE;
741
742         _read_directory(p);
743      }
744
745    if (input && !p->command)
746      p->input = eina_stringshare_add(input);
747
748    if ((p->command) || (!p->min_query) || (len >= p->min_query))
749      _files_filter(p);
750
751    return EVRY_PLUGIN_HAS_ITEMS(p);
752 }
753
754 /***************************************************************************/
755 /* recent files */
756
757 static int
758 _cb_sort_recent(const void *data1, const void *data2)
759 {
760    const Evry_Item *it1 = data1;
761    const Evry_Item *it2 = data2;
762
763    if (it1->browseable && !it2->browseable)
764      return -1;
765
766    if (!it1->browseable && it2->browseable)
767      return 1;
768
769    if (it1->hi && it2->hi)
770      return it1->hi->last_used > it2->hi->last_used ? -1 : 1;
771
772    if (it1->fuzzy_match && it2->fuzzy_match)
773      if (it1->fuzzy_match - it2->fuzzy_match)
774        return it1->fuzzy_match - it2->fuzzy_match;
775
776    return strcasecmp(it1->label, it2->label);
777 }
778
779 static int
780 _recentf_files_filter(Plugin *p)
781 {
782    int match;
783    int cnt = 0;
784    Evry_Item *it;
785    Eina_List *l, *new = NULL;
786
787    EVRY_PLUGIN_ITEMS_CLEAR(p);
788
789    EINA_LIST_FOREACH (p->files, l, it)
790      {
791         if (p->dirs_only && !it->browseable)
792           continue;
793
794         if (!p->input)
795           {
796              if (!it->browseable)
797                it->priority = 1;
798              new = eina_list_append(new, it);
799              continue;
800           }
801
802         if (it->fuzzy_match <= 0)
803           {
804              if ((match = evry->fuzzy_match(it->label, p->input)) ||
805                  (match = evry->fuzzy_match(EVRY_FILE(it)->path, p->input)))
806                it->fuzzy_match = match;
807              else
808                it->fuzzy_match = 0;
809
810              DBG("check match %d %s", it->fuzzy_match, it->label);
811           }
812
813         if (it->fuzzy_match)
814           {
815              if (!it->browseable)
816                it->priority = 1;
817              new = eina_list_append(new, it);
818           }
819      }
820
821    new = eina_list_sort(new, -1, _cb_sort_recent);
822
823    EINA_LIST_FREE (new, it)
824      {
825         if (cnt++ < MAX_SHOWN)
826           EVRY_PLUGIN_ITEM_APPEND(p, it);
827      }
828
829    return cnt;
830 }
831
832 #if 0
833 /* use thread only to not block ui for ecore_file_exists ... */
834
835 static void
836 _recentf_func(void *data)
837 {
838    Data *d = data;
839    Eina_List *l;
840    Evry_Item_File *file;
841
842    EINA_LIST_FOREACH (d->files, l, file)
843      {
844         if ((!evry->file_path_get(file)) ||
845             (!ecore_file_exists(file->path)))
846           {
847              EVRY_ITEM(file)->hi->last_used -= ONE_DAY;
848              EVRY_ITEM(file)->hi = NULL;
849           }
850      }
851 }
852
853 static void
854 _recentf_cancel_func(void *data)
855 {
856    Data *d = data;
857    Plugin *p = d->plugin;
858    Evry_Item_File *file;
859
860    EINA_LIST_FREE (d->files, file)
861      EVRY_ITEM_FREE(file);
862
863    E_FREE(d);
864
865    if (p->waiting_to_finish)
866      E_FREE(p);
867 }
868
869 static void
870 _recentf_end_func(void *data)
871 {
872    Data *d = data;
873    Plugin *p = d->plugin;
874    Evry_Item *it;
875
876    EINA_LIST_FREE (d->files, it)
877      {
878         GET_FILE(file, it);
879
880         if (!it->hi)
881           {
882              evry->item_free(it);
883              continue;
884           }
885
886         _item_fill(file);
887
888         if (!it->hi->data)
889           it->hi->data = eina_stringshare_ref(file->mime);
890
891         p->files = eina_list_append(p->files, it);
892      }
893
894    _recentf_files_filter(p);
895
896    EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
897
898    p->thread = NULL;
899    E_FREE(d);
900 }
901
902 #endif
903
904 static Eina_Bool
905 _recentf_items_add_cb(const Eina_Hash *hash __UNUSED__, const void *key, void *data, void *fdata)
906 {
907    History_Entry *he = data;
908    History_Item *hi = NULL, *hi2;
909    Eina_List *l, *ll;
910    Evry_Item_File *file;
911    double last_used = 0.0;
912    Data *d = fdata;
913    Plugin *p = d->plugin;
914    const char *label;
915    const char *path;
916    int match = 0;
917
918    EINA_LIST_FOREACH (he->items, l, hi2)
919      if (hi2->last_used > last_used)
920        {
921           last_used = hi2->last_used;
922           hi = hi2;
923        }
924
925    if (!hi)
926      return EINA_TRUE;
927
928    if (clear_cache)
929      {
930         DBG("clear %s", (char *)key);
931
932         /* transient marks them for deletion */
933         if (hi->count == 1)
934           {
935              hi->usage = 0;
936              hi->count = 0;
937              hi->transient = 1;
938           }
939
940         return EINA_TRUE;
941      }
942
943    if (hi->transient)
944      return EINA_TRUE;
945
946    if (!_conf->search_cache)
947      {
948         if ((hi->count == 1) && (hi->last_used < SIX_DAYS_AGO))
949           return EINA_TRUE;
950      }
951
952    path = (const char *)key;
953
954    if (!(label = ecore_file_file_get(path)))
955      return EINA_TRUE;
956
957    path = eina_stringshare_add(path);
958
959    EINA_LIST_FOREACH (p->files, ll, file)
960      {
961         if (file->path == path)
962           {
963              eina_stringshare_del(path);
964              EVRY_ITEM(file)->fuzzy_match = -1;
965              return EINA_TRUE;
966           }
967      }
968
969    /* searching subdirs */
970    if (p->directory)
971      {
972         /* dont show recent files from same dir */
973         int len = strlen(p->directory);
974         char *end = strrchr(path, '/');
975         if (strncmp(path, p->directory, len) ||
976             (end - path) <= len)
977           {
978              /* DBG("not in dir %s", path); */
979              eina_stringshare_del(path);
980              return EINA_TRUE;
981           }
982      }
983
984    if (!(match = evry->fuzzy_match(label, p->input)) &&
985        !(match = evry->fuzzy_match(path, p->input)))
986      {
987         eina_stringshare_del(path);
988         return EINA_TRUE;
989      }
990
991    file = EVRY_ITEM_NEW(Evry_Item_File, p, label, NULL, evry_item_file_free);
992    file->path = path;
993
994    if (hi->data)
995      file->mime = eina_stringshare_add(hi->data);
996
997    EVRY_ITEM(file)->hi = hi;
998    EVRY_ITEM(file)->fuzzy_match = match;
999    EVRY_ITEM(file)->id = eina_stringshare_ref(file->path);
1000
1001    _item_fill(file);
1002
1003    if (!hi->data)
1004      hi->data = eina_stringshare_ref(file->mime);
1005
1006    d->files = eina_list_append(d->files, file);
1007
1008    if (eina_list_count(d->files) > 100)
1009      return EINA_FALSE;
1010
1011    return EINA_TRUE;
1012 }
1013
1014 static Evry_Plugin *
1015 _recentf_browse(Evry_Plugin *plugin, const Evry_Item *it)
1016 {
1017    Plugin *p = NULL;
1018
1019    if (!it || !CHECK_TYPE(it, EVRY_TYPE_FILE))
1020      return NULL;
1021
1022    GET_FILE(file, it);
1023
1024    if (!evry->file_path_get(file) ||
1025        !ecore_file_is_dir(file->path))
1026      return NULL;
1027
1028    EVRY_PLUGIN_INSTANCE(p, plugin);
1029    p->directory = eina_stringshare_add(file->path);
1030    p->parent = EINA_TRUE;
1031
1032    return EVRY_PLUGIN(p);
1033 }
1034
1035 static Evry_Plugin *
1036 _recentf_begin(Evry_Plugin *plugin, const Evry_Item *it)
1037 {
1038    Plugin *p;
1039
1040    if (it && !CHECK_TYPE(it, EVRY_TYPE_ACTION))
1041      return NULL;
1042
1043    EVRY_PLUGIN_INSTANCE(p, plugin);
1044    p->parent = EINA_FALSE;
1045
1046    if (it)
1047      {
1048         /* provide object */
1049      }
1050    else
1051      {
1052         /* provide subject */
1053         p->min_query = plugin->config->min_query;
1054
1055         if (clear_cache)
1056           {
1057              History_Types *ht = evry->history_types_get(EVRY_TYPE_FILE);
1058              if (ht)
1059                eina_hash_foreach(ht->types, _recentf_items_add_cb, p);
1060
1061              clear_cache = EINA_FALSE;
1062           }
1063      }
1064
1065    return EVRY_PLUGIN(p);
1066 }
1067
1068 static int
1069 _recentf_fetch(Evry_Plugin *plugin, const char *input)
1070 {
1071    GET_PLUGIN(p, plugin);
1072    Evry_Item_File *file;
1073    History_Types *ht;
1074    size_t len = (input ? strlen(input) : 0);
1075
1076    IF_RELEASE(p->input);
1077
1078    /* if (p->thread)
1079     *   ecore_thread_cancel(p->thread);
1080     * p->thread = NULL; */
1081
1082    if (input && isspace(input[len - 1]))
1083      return EVRY_PLUGIN_HAS_ITEMS(p);
1084
1085    if (len >= plugin->config->min_query)
1086      {
1087         if (input)
1088           p->input = eina_stringshare_add(input);
1089
1090         if ((ht = evry->history_types_get(EVRY_TYPE_FILE)))
1091           {
1092              Data *d = E_NEW(Data, 1);
1093              d->plugin = p;
1094              eina_hash_foreach(ht->types, _recentf_items_add_cb, d);
1095              EINA_LIST_FREE (d->files, file)
1096                p->files = eina_list_append(p->files, file);
1097              E_FREE(d);
1098
1099              _recentf_files_filter(p);
1100
1101              /* _recentf_end_func(d);
1102               * p->thread = NULL; */
1103              /* p->thread = ecore_thread_run(_recentf_func, _recentf_end_func,
1104               *           _recentf_cancel_func, d); */
1105           }
1106         return EVRY_PLUGIN_HAS_ITEMS(p);
1107      }
1108
1109    EVRY_PLUGIN_ITEMS_CLEAR(p);
1110
1111    return 0;
1112 }
1113
1114 /***************************************************************************/
1115 /* actions */
1116
1117 static int
1118 _open_folder_check(Evry_Action *act __UNUSED__, const Evry_Item *it)
1119 {
1120    return it->browseable && e_action_find("fileman");
1121 }
1122
1123 static int
1124 _open_folder_action(Evry_Action *act)
1125 {
1126    E_Action *action;
1127    Eina_List *m;
1128    char *dir;
1129
1130    if (!(action = e_action_find("fileman")))
1131      return 0;
1132
1133    GET_FILE(file, act->it1.item);
1134
1135    if (!(evry->file_path_get(file)))
1136      return 0;
1137
1138    m = e_manager_list();
1139
1140    if (!IS_BROWSEABLE(file))
1141      {
1142         dir = ecore_file_dir_get(file->path);
1143         if (!dir) return 0;
1144         action->func.go(E_OBJECT(m->data), dir);
1145         free(dir);
1146      }
1147    else
1148      {
1149         action->func.go(E_OBJECT(m->data), file->path);
1150      }
1151
1152    return 1;
1153 }
1154
1155 static int
1156 _file_trash_action(Evry_Action *act)
1157 {
1158    Efreet_Uri *euri;
1159    int ok = 0;
1160    int force = (EVRY_ITEM_DATA_INT_GET(act) == ACT_DELETE);
1161
1162    GET_FILE(file, act->it1.item);
1163
1164    if (!(evry->file_url_get(file)))
1165      return 0;
1166
1167    euri = efreet_uri_decode(file->url);
1168
1169    if (euri)
1170      {
1171         ok = efreet_trash_delete_uri(euri, force);
1172         efreet_uri_free(euri);
1173      }
1174
1175    return ok > 0;
1176 }
1177
1178 static int
1179 _file_copy_action(Evry_Action *act)
1180 {
1181    GET_FILE(src, act->it1.item);
1182    GET_FILE(dst, act->it2.item);
1183
1184    char buf[PATH_MAX];
1185    char *ddst;
1186
1187    if (!(evry->file_path_get(src)))
1188      return 0;
1189
1190    if (!(evry->file_path_get(dst)))
1191      return 0;
1192
1193    if (!ecore_file_is_dir(dst->path))
1194      ddst = ecore_file_dir_get(dst->path);
1195    else
1196      ddst = strdup(dst->path);
1197    if (!ddst)
1198      return 0;
1199
1200    snprintf(buf, sizeof(buf), "%s/%s", ddst, ecore_file_file_get(src->path));
1201    free(ddst);
1202
1203    DBG(" %s -> %s\n", src->path, buf);
1204
1205    if (EVRY_ITEM_DATA_INT_GET(act) == ACT_COPY)
1206      {
1207         return ecore_file_cp(src->path, buf);
1208      }
1209    else if (EVRY_ITEM_DATA_INT_GET(act) == ACT_MOVE)
1210      {
1211         return ecore_file_mv(src->path, buf);
1212      }
1213
1214    return 0;
1215 }
1216
1217 static void
1218 _sort_by_date(Plugin *p)
1219 {
1220    Eina_List *l;
1221    Evry_Item_File *file;
1222    struct stat s;
1223
1224    EINA_LIST_FOREACH (p->files, l, file)
1225      {
1226         if (file->modified)
1227           continue;
1228
1229         if (lstat(file->path, &s) == 0)
1230           file->modified = s.st_mtime;
1231
1232         EVRY_ITEM(file)->usage = -1;
1233      }
1234
1235    p->files = eina_list_sort(p->files, -1, _cb_sort_date);
1236    _files_filter(p);
1237
1238    EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
1239 }
1240
1241 static void
1242 _sort_by_name(Plugin *p)
1243 {
1244    Eina_List *l;
1245    Evry_Item *it;
1246
1247    EINA_LIST_FOREACH (p->files, l, it)
1248      it->usage = 0;
1249
1250    p->files = eina_list_sort(p->files, -1, _cb_sort);
1251    _files_filter(p);
1252
1253    EVRY_PLUGIN_UPDATE(p, EVRY_UPDATE_ADD);
1254 }
1255
1256 static int
1257 _file_sort_action(Evry_Action *act)
1258 {
1259    GET_PLUGIN(p, act->it1.item);
1260    if (!p) return 0;
1261
1262    if (EVRY_ITEM_DATA_INT_GET(act) == ACT_SORT_DATE)
1263      {
1264         _sort_by_date(p);
1265      }
1266    else
1267      {
1268         _sort_by_name(p);
1269      }
1270
1271    return 0;
1272 }
1273
1274 static int
1275 _cb_key_down(Evry_Plugin *plugin, const Ecore_Event_Key *ev)
1276 {
1277    GET_PLUGIN(p, plugin);
1278
1279    if (!strcmp(ev->key, "F1"))
1280      {
1281         _sort_by_name(p);
1282         return 1;
1283      }
1284    if (!strcmp(ev->key, "F2"))
1285      {
1286         _sort_by_date(p);
1287         return 1;
1288      }
1289
1290    return 0;
1291 }
1292
1293 static int
1294 _plugins_init(const Evry_API *api)
1295 {
1296    Evry_Action *act, *act_sort_date, *act_sort_name;
1297    Evry_Plugin *p;
1298    int prio = 0;
1299    const char *config_path;
1300
1301    evry = api;
1302
1303    if (!evry->api_version_check(EVRY_API_VERSION))
1304      return EINA_FALSE;
1305
1306    config_path = eina_stringshare_add("launcher/everything-files");
1307    _mime_dir = eina_stringshare_add("inode/directory");
1308    _mime_mount = eina_stringshare_add("inode/mountpoint");
1309    _mime_unknown = eina_stringshare_add("unknown");
1310
1311 #define ACTION_NEW(_name, _type2, _icon, _act, _check, _register)            \
1312   act = EVRY_ACTION_NEW(_name, EVRY_TYPE_FILE, _type2, _icon, _act, _check); \
1313   if (_register) evry->action_register(act, prio++);                         \
1314   _actions = eina_list_append(_actions, act);                                \
1315
1316    ACTION_NEW("Copy To ...", EVRY_TYPE_FILE, "go-next",
1317               _file_copy_action, NULL, 1);
1318    act->it2.subtype = EVRY_TYPE_DIR;
1319    EVRY_ITEM_DATA_INT_SET(act, ACT_COPY);
1320
1321    ACTION_NEW("Move To ...", EVRY_TYPE_FILE, "go-next",
1322               _file_copy_action, NULL, 1);
1323    act->it2.subtype = EVRY_TYPE_DIR;
1324    EVRY_ITEM_DATA_INT_SET(act, ACT_MOVE);
1325
1326    ACTION_NEW("Move to Trash", 0, "user-trash",
1327               _file_trash_action, NULL, 1);
1328    EVRY_ITEM_DATA_INT_SET(act, ACT_TRASH);
1329
1330    ACTION_NEW("Open Folder (EFM)", 0, "folder-open",
1331               _open_folder_action, _open_folder_check, 1);
1332    act->remember_context = EINA_TRUE;
1333
1334    ACTION_NEW("Sort by Date", 0, "go-up",
1335               _file_sort_action, NULL, 0);
1336    EVRY_ITEM_DATA_INT_SET(act, ACT_SORT_DATE);
1337    act_sort_date = act;
1338
1339    ACTION_NEW("Sort by Name", 0, "go-up",
1340               _file_sort_action, NULL, 0);
1341    EVRY_ITEM_DATA_INT_SET(act, ACT_SORT_NAME);
1342    act_sort_name = act;
1343
1344 #undef ACTION_NEW
1345
1346    p = EVRY_PLUGIN_BASE("Files", _module_icon, EVRY_TYPE_FILE,
1347                         _begin, _finish, _fetch);
1348    p->input_type = EVRY_TYPE_FILE;
1349    p->cb_key_down = &_cb_key_down;
1350    p->browse = &_browse;
1351    p->config_path = eina_stringshare_ref(config_path);
1352    p->actions = eina_list_append(p->actions, act_sort_date);
1353    p->actions = eina_list_append(p->actions, act_sort_name);
1354    _plugins = eina_list_append(_plugins, p);
1355
1356    if (evry->plugin_register(p, EVRY_PLUGIN_SUBJECT, 2))
1357      p->config->min_query = 1;
1358
1359    p = EVRY_PLUGIN_BASE("Files", _module_icon, EVRY_TYPE_FILE,
1360                         _begin, _finish, _fetch);
1361    p->cb_key_down = &_cb_key_down;
1362    p->browse = &_browse;
1363    p->config_path = eina_stringshare_ref(config_path);
1364    p->actions = eina_list_append(p->actions, act_sort_date);
1365    p->actions = eina_list_append(p->actions, act_sort_name);
1366    _plugins = eina_list_append(_plugins, p);
1367    evry->plugin_register(p, EVRY_PLUGIN_OBJECT, 2);
1368
1369    if (!_conf->show_recent && !_conf->search_recent)
1370      return EINA_TRUE;
1371
1372    p = EVRY_PLUGIN_BASE("Recent Files", _module_icon, EVRY_TYPE_FILE,
1373                         _recentf_begin, _finish, _recentf_fetch);
1374    p->browse = &_recentf_browse;
1375    p->config_path = eina_stringshare_ref(config_path);
1376
1377    if (evry->plugin_register(p, EVRY_PLUGIN_SUBJECT, 3))
1378      {
1379         p->config->top_level = EINA_FALSE;
1380         p->config->min_query = 3;
1381      }
1382    _plugins = eina_list_append(_plugins, p);
1383
1384    p = EVRY_PLUGIN_BASE("Recent Files", _module_icon, EVRY_TYPE_FILE,
1385                         _recentf_begin, _finish, _recentf_fetch);
1386    p->browse = &_recentf_browse;
1387    p->config_path = eina_stringshare_ref(config_path);
1388
1389    if (evry->plugin_register(p, EVRY_PLUGIN_OBJECT, 3))
1390      {
1391         p->config->top_level = EINA_FALSE;
1392         p->config->min_query = 3;
1393      }
1394    _plugins = eina_list_append(_plugins, p);
1395    eina_stringshare_del(config_path);
1396
1397    return EINA_TRUE;
1398 }
1399
1400 static void
1401 _plugins_shutdown(void)
1402 {
1403    Evry_Action *act;
1404    Evry_Plugin *p;
1405
1406    eina_stringshare_del(_mime_dir);
1407    eina_stringshare_del(_mime_mount);
1408    eina_stringshare_del(_mime_unknown);
1409
1410    EINA_LIST_FREE (_plugins, p)
1411      {
1412         if (p->actions)
1413           eina_list_free(p->actions);
1414         EVRY_PLUGIN_FREE(p);
1415      }
1416
1417    EINA_LIST_FREE (_actions, act)
1418      evry->action_free(act);
1419 }
1420
1421 /***************************************************************************/
1422
1423 static E_Config_DD *conf_edd = NULL;
1424
1425 struct _E_Config_Dialog_Data
1426 {
1427    int show_homedir;
1428    int show_recent;
1429    int search_recent;
1430    int search_cache;
1431    int cache_dirs;
1432 };
1433
1434 static void        *_create_data(E_Config_Dialog *cfd);
1435 static void         _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
1436 static void         _fill_data(E_Config_Dialog_Data *cfdata);
1437 static Evas_Object *_basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata);
1438 static int          _basic_apply(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata);
1439
1440 static E_Config_Dialog *
1441 _conf_dialog(E_Container *con, const char *params __UNUSED__)
1442 {
1443    E_Config_Dialog *cfd = NULL;
1444    E_Config_Dialog_View *v = NULL;
1445
1446    if (e_config_dialog_find("everything-files", "extensions/everything-files")) return NULL;
1447
1448    v = E_NEW(E_Config_Dialog_View, 1);
1449    if (!v) return NULL;
1450
1451    v->create_cfdata = _create_data;
1452    v->free_cfdata = _free_data;
1453    v->basic.create_widgets = _basic_create;
1454    v->basic.apply_cfdata = _basic_apply;
1455
1456    cfd = e_config_dialog_new(con, _("Everything Files"), "everything-files",
1457                              "extensions/everything-files", _module_icon, 0, v, NULL);
1458
1459    _conf->cfd = cfd;
1460    return cfd;
1461 }
1462
1463 static void
1464 _clear_cache_cb(void *data __UNUSED__, void *data2 __UNUSED__)
1465 {
1466    clear_cache = EINA_TRUE;
1467 }
1468
1469 static Evas_Object *
1470 _basic_create(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data *cfdata)
1471 {
1472    Evas_Object *o = NULL, *of = NULL, *ow = NULL;
1473
1474    o = e_widget_list_add(evas, 0, 0);
1475
1476    of = e_widget_framelist_add(evas, _("General"), 0);
1477    e_widget_framelist_content_align_set(of, 0.0, 0.0);
1478
1479    /* ow = e_widget_check_add(evas, _("Show home directory"),
1480     *          &(cfdata->show_homedir));
1481     * e_widget_framelist_object_append(of, ow); */
1482
1483    ow = e_widget_check_add(evas, _("Show recent files"),
1484                            &(cfdata->show_recent));
1485    e_widget_framelist_object_append(of, ow);
1486
1487    ow = e_widget_check_add(evas, _("Search recent files"),
1488                            &(cfdata->search_recent));
1489    e_widget_framelist_object_append(of, ow);
1490
1491    ow = e_widget_check_add(evas, _("Search cached files"),
1492                            &(cfdata->search_cache));
1493    e_widget_framelist_object_append(of, ow);
1494
1495    ow = e_widget_check_add(evas, _("Cache visited directories"),
1496                            &(cfdata->cache_dirs));
1497    e_widget_framelist_object_append(of, ow);
1498
1499    ow = e_widget_button_add(evas, _("Clear cache"), NULL,
1500                             _clear_cache_cb,
1501                             NULL, NULL);
1502    e_widget_framelist_object_append(of, ow);
1503
1504    e_widget_list_object_append(o, of, 1, 1, 0.5);
1505    return o;
1506 }
1507
1508 static void *
1509 _create_data(E_Config_Dialog *cfd __UNUSED__)
1510 {
1511    E_Config_Dialog_Data *cfdata = NULL;
1512
1513    cfdata = E_NEW(E_Config_Dialog_Data, 1);
1514    _fill_data(cfdata);
1515    return cfdata;
1516 }
1517
1518 static void
1519 _free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
1520 {
1521    _conf->cfd = NULL;
1522    E_FREE(cfdata);
1523 }
1524
1525 static void
1526 _fill_data(E_Config_Dialog_Data *cfdata)
1527 {
1528 #define C(_name) cfdata->_name = _conf->_name;
1529    C(show_homedir);
1530    C(show_recent);
1531    C(search_recent);
1532    C(search_cache);
1533    C(cache_dirs);
1534 #undef C
1535 }
1536
1537 static int
1538 _basic_apply(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
1539 {
1540 #define C(_name) _conf->_name = cfdata->_name;
1541    C(show_homedir);
1542    C(show_recent);
1543    C(search_recent);
1544    C(search_cache);
1545    C(cache_dirs);
1546 #undef C
1547
1548    e_config_domain_save("module.everything-files", conf_edd, _conf);
1549    e_config_save_queue();
1550    return 1;
1551 }
1552
1553 static void
1554 _conf_new(void)
1555 {
1556    _conf = E_NEW(Module_Config, 1);
1557    _conf->version = (MOD_CONFIG_FILE_EPOCH << 16);
1558
1559 #define IFMODCFG(v) if ((_conf->version & 0xffff) < v) {
1560 #define IFMODCFGEND }
1561
1562     /* setup defaults */
1563     IFMODCFG(0x008d);
1564     _conf->show_recent = 0;
1565     _conf->show_homedir = 1;
1566     _conf->search_recent = 1;
1567     _conf->cache_dirs = 0;
1568     _conf->search_cache = 0;
1569     IFMODCFGEND;
1570
1571     _conf->version = MOD_CONFIG_FILE_VERSION;
1572 }
1573
1574 static void
1575 _conf_free(void)
1576 {
1577    E_FREE(_conf);
1578 }
1579
1580 static void
1581 _conf_init(E_Module *m)
1582 {
1583    char title[4096];
1584
1585    snprintf(title, sizeof(title), "%s: %s", _("Everything Plugin"), _("Files"));
1586
1587    e_configure_registry_item_add("launcher/everything-files", 110, title,
1588                                  NULL, _module_icon, _conf_dialog);
1589
1590    conf_edd = E_CONFIG_DD_NEW("Module_Config", Module_Config);
1591
1592 #undef T
1593 #undef D
1594 #define T Module_Config
1595 #define D conf_edd
1596    E_CONFIG_VAL(D, T, version, INT);
1597    E_CONFIG_VAL(D, T, show_homedir, UCHAR);
1598    E_CONFIG_VAL(D, T, show_recent, UCHAR);
1599    E_CONFIG_VAL(D, T, search_recent, UCHAR);
1600    E_CONFIG_VAL(D, T, search_cache, UCHAR);
1601    E_CONFIG_VAL(D, T, cache_dirs, UCHAR);
1602 #undef T
1603 #undef D
1604
1605    _conf = e_config_domain_load("module.everything-files", conf_edd);
1606
1607    if (_conf && !e_util_module_config_check(_("Everything Files"),
1608                                             _conf->version,
1609                                             MOD_CONFIG_FILE_VERSION))
1610      _conf_free();
1611
1612    if (!_conf) _conf_new();
1613
1614    _conf->module = m;
1615 }
1616
1617 static void
1618 _conf_shutdown(void)
1619 {
1620    e_configure_registry_item_del("launcher/everything-files");
1621
1622    E_FREE(_conf);
1623    E_CONFIG_DD_FREE(conf_edd);
1624 }
1625
1626 /***************************************************************************/
1627
1628 Eina_Bool
1629 evry_plug_files_init(E_Module *m)
1630 {
1631    _conf_init(m);
1632
1633    EVRY_MODULE_NEW(evry_module, evry, _plugins_init, _plugins_shutdown);
1634
1635    return EINA_TRUE;
1636 }
1637
1638 void
1639 evry_plug_files_shutdown(void)
1640 {
1641    EVRY_MODULE_FREE(evry_module);
1642
1643    _conf_shutdown();
1644 }
1645
1646 void
1647 evry_plug_files_save(void)
1648 {
1649    e_config_domain_save("module.everything-files", conf_edd, _conf);
1650 }
1651