#include "e.h"

typedef struct _Config_Glob Config_Glob;
typedef struct _Config_Mime Config_Mime;

struct _Config_Glob
{
   const char *name;
};

struct _Config_Mime
{
   const char *mime;
   Eina_List  *globs;
};

struct _E_Config_Dialog_Data
{
   struct
   {
      Evas_Object *deflist, *mimelist, *entry;
   } obj;
   Efreet_Ini          *ini;
   Eina_List           *mimes;
   Eina_List           *desks;

   const char          *selmime;
   const char          *selapp;

   const char         **seldest;

   char                *browser_custom;

   const char          *browser_desktop;
   const char          *mailto_desktop;
   const char          *file_desktop;
   const char          *trash_desktop;
   const char          *terminal_desktop;

   Ecore_Event_Handler *desk_change_handler;
   int                  gen;
};

/* local function prototypes */
static void        *_create_data(E_Config_Dialog *cfd);
static void         _free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata);
static Evas_Object *_basic_create(E_Config_Dialog *cfd EINA_UNUSED, Evas *evas, E_Config_Dialog_Data *cfdata);
static int          _basic_apply(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata);

static Eina_Bool    _desks_update(void *data, int ev_type EINA_UNUSED, void *ev EINA_UNUSED);
static void         _load_mimes(E_Config_Dialog_Data *cfdata, char *file);
static void         _load_globs(E_Config_Dialog_Data *cfdata, char *file);
static int          _sort_mimes(const void *data1, const void *data2);
static Config_Mime *_find_mime(E_Config_Dialog_Data *cfdata, char *mime);
static Config_Glob *_find_glob(Config_Mime *mime, char *glob);
static int          _cb_desks_sort(const void *data1, const void *data2);
static void         _fill_apps_list(E_Config_Dialog_Data *cfdata, Evas_Object *il, const char **desktop, int general);

E_Config_Dialog *
e_int_config_defapps(Evas_Object *parent EINA_UNUSED, const char *params EINA_UNUSED)
{
   E_Config_Dialog *cfd;
   E_Config_Dialog_View *v;

   if (e_config_dialog_find("E", "applications/default_applications"))
     return NULL;

   v = E_NEW(E_Config_Dialog_View, 1);
   v->create_cfdata = _create_data;
   v->free_cfdata = _free_data;
   v->basic.create_widgets = _basic_create;
   v->basic.apply_cfdata = _basic_apply;

   cfd = e_config_dialog_new(NULL, _("Default Applications"),
                             "E", "applications/default_applications",
                             "preferences-desktop-default-applications", 0, v, NULL);
   return cfd;
}

static void *
_create_data(E_Config_Dialog *cfd EINA_UNUSED)
{
   E_Config_Dialog_Data *cfdata;
   Efreet_Ini *ini, *myini;
   Eina_Iterator *it;
   char buf[PATH_MAX];
   const char *key, *s, *homedir;
   Eina_List *l;
   E_Config_Env_Var *evr;

   cfdata = E_NEW(E_Config_Dialog_Data, 1);
   if (!cfdata) return NULL;

   cfdata->desk_change_handler = ecore_event_handler_add
       (EFREET_EVENT_DESKTOP_CACHE_UPDATE, _desks_update, cfdata);

   snprintf(buf, sizeof(buf), "%s/mimeapps.list",
            efreet_config_home_get());
   myini = efreet_ini_new(buf);
   if (myini)
     {
        cfdata->ini = myini;
        if (!efreet_ini_section_set(myini, "Default Applications"))
          {
             efreet_ini_section_add(myini, "Default Applications");
             efreet_ini_section_set(myini, "Default Applications");
          }
        EINA_LIST_FOREACH(efreet_data_dirs_get(), l, s)
          {
             snprintf(buf, sizeof(buf), "%s/applications/defaults.list", s);
             ini = efreet_ini_new(buf);
             if ((ini) &&
                 (efreet_ini_section_set(ini, "Default Applications")) &&
                 (ini->section) &&
                 (it = eina_hash_iterator_key_new(ini->section)))
               {
                  EINA_ITERATOR_FOREACH(it, key)
                    {
                       if (!efreet_ini_string_get(myini, key))
                         {
                            s = efreet_ini_string_get(ini, key);
                            if (s) efreet_ini_string_set(myini, key, s);
                         }
                    }
                  eina_iterator_free(it);
               }
             if (ini) efreet_ini_free(ini);
          }
        s = efreet_ini_string_get(myini, "x-scheme-handler/http");
        if (!s) s = efreet_ini_string_get(myini, "x-scheme-handler/https");
        if (s) cfdata->browser_desktop = eina_stringshare_add(s);
        s = efreet_ini_string_get(myini, "x-scheme-handler/mailto");
        if (s) cfdata->mailto_desktop = eina_stringshare_add(s);
        s = efreet_ini_string_get(myini, "inode/directory");
        if (s) cfdata->file_desktop = eina_stringshare_add(s);
        s = efreet_ini_string_get(myini, "x-scheme-handler/trash");
        if (s) cfdata->trash_desktop = eina_stringshare_add(s);
        s = efreet_ini_string_get(myini, "x-scheme-handler/terminal");
        if (s) cfdata->terminal_desktop = eina_stringshare_add(s);
     }

   EINA_LIST_FOREACH(e_config->env_vars, l, evr)
     {
        if (!strcmp(evr->var, "BROWSER"))
          {
             if ((evr->val) && (!evr->unset))
               cfdata->browser_custom = strdup(evr->val);
             break;
          }
     }

   homedir = e_user_homedir_get();

   snprintf(buf, sizeof(buf), "/usr/local/etc/mime.types");
   if (ecore_file_exists(buf)) _load_mimes(cfdata, buf);
   snprintf(buf, sizeof(buf), "/etc/mime.types");
   if (ecore_file_exists(buf)) _load_mimes(cfdata, buf);

   EINA_LIST_FOREACH(efreet_config_dirs_get(), l, s)
     {
        snprintf(buf, sizeof(buf), "%s/mime/globs", s);
        if (ecore_file_exists(buf)) _load_globs(cfdata, buf);
     }

   snprintf(buf, sizeof(buf), "%s/.mime.types", homedir);
   if (ecore_file_exists(buf)) _load_mimes(cfdata, buf);

   snprintf(buf, sizeof(buf), "%s/mime/globs", efreet_data_home_get());
   if (ecore_file_exists(buf)) _load_globs(cfdata, buf);

   cfdata->mimes = eina_list_sort(cfdata->mimes, 0, _sort_mimes);
   return cfdata;
}

static void
_free_data(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
{
   Config_Mime *m;
   Efreet_Desktop *desk;

   if (cfdata->selmime) eina_stringshare_del(cfdata->selmime);
   if (cfdata->selapp) eina_stringshare_del(cfdata->selapp);
   free(cfdata->browser_custom);
   if (cfdata->browser_desktop) eina_stringshare_del(cfdata->browser_desktop);
   if (cfdata->mailto_desktop) eina_stringshare_del(cfdata->mailto_desktop);
   if (cfdata->file_desktop) eina_stringshare_del(cfdata->file_desktop);
   if (cfdata->trash_desktop) eina_stringshare_del(cfdata->trash_desktop);
   if (cfdata->terminal_desktop) eina_stringshare_del(cfdata->terminal_desktop);
   EINA_LIST_FREE(cfdata->mimes, m)
     {
        Config_Glob *g;

        if (!m) continue;
        EINA_LIST_FREE(m->globs, g)
          {
             if (!g) continue;
             eina_stringshare_del(g->name);
             E_FREE(g);
          }
        eina_stringshare_del(m->mime);
        E_FREE(m);
     }
   if (cfdata->ini) efreet_ini_free(cfdata->ini);
   EINA_LIST_FREE(cfdata->desks, desk)
     efreet_desktop_free(desk);
   if (cfdata->desk_change_handler)
     ecore_event_handler_del(cfdata->desk_change_handler);
   E_FREE(cfdata);
}

static Eina_Bool
_desks_update(void *data, int ev_type EINA_UNUSED, void *ev EINA_UNUSED)
{
   E_Config_Dialog_Data *cfdata = data;
   Efreet_Desktop *desk;
   EINA_LIST_FREE(cfdata->desks, desk)
     efreet_desktop_free(desk);
   if (cfdata->gen)
     _fill_apps_list(cfdata, cfdata->obj.deflist, &(cfdata->selapp), 1);
   else
     _fill_apps_list(cfdata, cfdata->obj.deflist, cfdata->seldest, 0);
   return ECORE_CALLBACK_PASS_ON;
}

static void
_def_browser_cb(void *data)
{
   E_Config_Dialog_Data *cfdata = data;
   cfdata->seldest = &(cfdata->browser_desktop);
   _fill_apps_list(cfdata, cfdata->obj.deflist, cfdata->seldest, 0);
   cfdata->gen = 0;
}

static void
_def_mailto_cb(void *data)
{
   E_Config_Dialog_Data *cfdata = data;
   cfdata->seldest = &(cfdata->mailto_desktop);
   _fill_apps_list(cfdata, cfdata->obj.deflist, cfdata->seldest, 0);
   cfdata->gen = 0;
}

static void
_def_file_cb(void *data)
{
   E_Config_Dialog_Data *cfdata = data;
   cfdata->seldest = &(cfdata->file_desktop);
   _fill_apps_list(cfdata, cfdata->obj.deflist, cfdata->seldest, 0);
   cfdata->gen = 0;
}

static void
_def_trash_cb(void *data)
{
   E_Config_Dialog_Data *cfdata = data;
   cfdata->seldest = &(cfdata->trash_desktop);
   _fill_apps_list(cfdata, cfdata->obj.deflist, cfdata->seldest, 0);
   cfdata->gen = 0;
}

static void
_def_terminal_cb(void *data)
{
   E_Config_Dialog_Data *cfdata = data;
   cfdata->seldest = &(cfdata->terminal_desktop);
   _fill_apps_list(cfdata, cfdata->obj.deflist, cfdata->seldest, 0);
   cfdata->gen = 0;
}

static void
_sel_mime_cb(void *data)
{
   E_Config_Dialog_Data *cfdata = data;
   if (cfdata->selapp) eina_stringshare_del(cfdata->selapp);
   cfdata->selapp = NULL;
   if (cfdata->selmime)
     {
        const char *s = efreet_ini_string_get(cfdata->ini, cfdata->selmime);
        if (s) cfdata->selapp = eina_stringshare_add(s);
     }
   _fill_apps_list(cfdata, cfdata->obj.mimelist, &(cfdata->selapp), 1);
   cfdata->gen = 1;
}

static Evas_Object *
_basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata)
{
   Evas_Object *otb, *ot, *ob, *of, *il;
   Eina_List *l;
   Config_Mime *m;

   e_dialog_resizable_set(cfd->dia, 1);
   otb = e_widget_toolbook_add(evas, 24, 24);

   ot = e_widget_table_add(e_win_evas_win_get(evas), EINA_FALSE);

   ob = e_widget_label_add(evas, _("Custom Browser Command"));
   e_widget_table_object_append(ot, ob, 0, 0, 1, 1, 1, 1, 0, 0);

   ob = e_widget_entry_add(cfd->dia->win, &(cfdata->browser_custom), NULL, NULL, NULL);
   cfdata->obj.entry = ob;
   e_widget_table_object_append(ot, ob, 1, 0, 1, 1, 1, 1, 1, 0);

   of = e_widget_framelist_add(evas, _("Default Applications"), 0);
   il = e_widget_ilist_add(evas, 24, 24, NULL);
   evas_event_freeze(evas);
   edje_freeze();
   e_widget_ilist_freeze(il);
   e_widget_ilist_selector_set(il, 1);
   e_widget_ilist_append(il, NULL, _("Browser"), _def_browser_cb, cfdata, NULL);
   e_widget_ilist_append(il, NULL, _("E-Mail"), _def_mailto_cb, cfdata, NULL);
   e_widget_ilist_append(il, NULL, _("File"), _def_file_cb, cfdata, NULL);
   e_widget_ilist_append(il, NULL, _("Trash"), _def_trash_cb, cfdata, NULL);
   e_widget_ilist_append(il, NULL, _("Terminal"), _def_terminal_cb, cfdata, NULL);
   e_widget_ilist_go(il);
   e_widget_ilist_thaw(il);
   edje_thaw();
   evas_event_thaw(evas);
   e_widget_framelist_object_append_full(of, il, 1, 1, 1, 1, 0.5, 0.5, 120, 200, 9999, 9999);
   e_widget_table_object_append(ot, of, 0, 1, 1, 1, 1, 1, 0, 1);

   of = e_widget_framelist_add(evas, _("Selected Application"), 0);
   il = e_widget_ilist_add(evas, 24, 24, &(cfdata->selapp));
   cfdata->obj.deflist = il;
   e_widget_ilist_selector_set(il, 1);
   e_widget_ilist_go(il);
   e_widget_framelist_object_append_full(of, il, 1, 1, 1, 1, 0.5, 0.5, 120, 200, 9999, 9999);
   e_widget_table_object_append(ot, of, 1, 1, 1, 1, 1, 1, 1, 1);

   e_widget_toolbook_page_append(otb, NULL, _("Core"), ot,
                                 1, 1, 1, 1, 0.5, 0.0);

   ot = e_widget_table_add(e_win_evas_win_get(evas), EINA_FALSE);

   of = e_widget_framelist_add(evas, _("Types"), 0);
   il = e_widget_ilist_add(evas, 24, 24, &(cfdata->selmime));
   evas_event_freeze(evas);
   edje_freeze();
   e_widget_ilist_freeze(il);
   e_widget_ilist_selector_set(il, 1);
   EINA_LIST_FOREACH(cfdata->mimes, l, m)
     e_widget_ilist_append(il, NULL, m->mime, _sel_mime_cb, cfdata, m->mime);
   e_widget_ilist_go(il);
   e_widget_ilist_thaw(il);
   edje_thaw();
   evas_event_thaw(evas);
   e_widget_framelist_object_append_full(of, il, 1, 1, 1, 1, 0.5, 0.5, 120, 200, 9999, 9999);
   e_widget_table_object_append(ot, of, 0, 0, 1, 1, 1, 1, 1, 1);

   of = e_widget_framelist_add(evas, _("Selected Application"), 0);
   il = e_widget_ilist_add(evas, 24, 24, &(cfdata->selapp));
   cfdata->obj.mimelist = il;
   e_widget_ilist_selector_set(il, 1);
   e_widget_ilist_go(il);
   e_widget_framelist_object_append_full(of, il, 1, 1, 1, 1, 0.5, 0.5, 120, 200, 9999, 9999);
   e_widget_table_object_append(ot, of, 1, 0, 1, 1, 1, 1, 1, 1);

   e_widget_toolbook_page_append(otb, NULL, _("General"), ot,
                                 1, 1, 1, 1, 0.5, 0.0);

   e_widget_toolbook_page_show(otb, 0);

   elm_win_center(cfd->dia->win, 1, 1);
   return otb;
}

static int
_basic_apply(E_Config_Dialog *cfd EINA_UNUSED, E_Config_Dialog_Data *cfdata)
{
   Eina_List *l;
   E_Config_Env_Var *evr = NULL;

   if (cfdata->ini)
     {
        char buf[PATH_MAX];

        if ((cfdata->browser_desktop) && (cfdata->browser_desktop[0]))
          {
             efreet_ini_string_set(cfdata->ini, "x-scheme-handler/http",
                                   cfdata->browser_desktop);
             efreet_ini_string_set(cfdata->ini, "x-scheme-handler/https",
                                   cfdata->browser_desktop);
          }
        if ((cfdata->mailto_desktop) && (cfdata->mailto_desktop[0]))
          efreet_ini_string_set(cfdata->ini, "x-scheme-handler/mailto",
                                cfdata->mailto_desktop);
        if ((cfdata->file_desktop) && (cfdata->file_desktop[0]))
          efreet_ini_string_set(cfdata->ini, "inode/directory",
                                cfdata->file_desktop);
        if ((cfdata->trash_desktop) && (cfdata->trash_desktop[0]))
          efreet_ini_string_set(cfdata->ini, "x-scheme-handler/trash",
                                cfdata->trash_desktop);
        if ((cfdata->terminal_desktop) && (cfdata->terminal_desktop[0]))
          efreet_ini_string_set(cfdata->ini, "x-scheme-handler/terminal",
                                cfdata->terminal_desktop);
        snprintf(buf, sizeof(buf), "%s/mimeapps.list",
                 efreet_config_home_get());
        efreet_ini_save(cfdata->ini, buf);
     }
   if ((cfdata->browser_custom) && (cfdata->browser_custom[0]))
     {
        EINA_LIST_FOREACH(e_config->env_vars, l, evr)
          {
             if (!strcmp(evr->var, "BROWSER")) break;
             evr = NULL;
          }
        if (evr)
          {
             evr->unset = 0;
             if (evr->val) eina_stringshare_del(evr->val);
          }
        else
          {
             evr = E_NEW(E_Config_Env_Var, 1);
             if (evr)
               {
                  evr->var = eina_stringshare_add("BROWSER");
                  evr->unset = 0;
                  e_config->env_vars = eina_list_append(e_config->env_vars, evr);
               }
          }
        if (evr)
          {
             evr->val = eina_stringshare_add(cfdata->browser_custom);
             e_env_set(evr->var, evr->val);
          }
     }
   else
     {
        EINA_LIST_FOREACH(e_config->env_vars, l, evr)
          {
             if (!e_util_strcmp(evr->var, "BROWSER"))
               {
                  e_config->env_vars = eina_list_remove_list(e_config->env_vars, l);
                  if (evr->val) eina_stringshare_del(evr->val);
                  if (evr->var) eina_stringshare_del(evr->var);
                  free(evr);
                  break;
               }
          }
        e_env_unset("BROWSER");
     }
   e_config_save_queue();
   return 1;
}

static void
_load_mimes(E_Config_Dialog_Data *cfdata, char *file)
{
   FILE *f;
   char buf[4096], mimetype[4096], ext[4096];
   char *p, *pp;
   Config_Mime *config_mime;
   Config_Glob *config_glob;

   if (!cfdata) return;

   f = fopen(file, "rb");
   if (!f) return;
   while (fgets(buf, sizeof(buf), f))
     {
        p = buf;
        while (isblank(*p) && (*p != 0) && (*p != '\n'))
          p++;
        if (*p == '#') continue;
        if ((*p == '\n') || (*p == 0)) continue;
        pp = p;
        while (!isblank(*p) && (*p != 0) && (*p != '\n'))
          p++;
        if ((*p == '\n') || (*p == 0)) continue;
        strncpy(mimetype, pp, (p - pp));
        mimetype[p - pp] = 0;
        do
          {
             while (isblank(*p) && (*p != 0) && (*p != '\n'))
               p++;
             if ((*p == '\n') || (*p == 0)) continue;
             pp = p;
             while (!isblank(*p) && (*p != 0) && (*p != '\n'))
               p++;
             strncpy(ext, pp, (p - pp));
             ext[p - pp] = 0;
             config_mime = _find_mime(cfdata, mimetype);
             if (!config_mime)
               {
                  config_mime = E_NEW(Config_Mime, 1);
                  if (config_mime)
                    {
                       config_mime->mime = eina_stringshare_add(mimetype);
                       if (!config_mime->mime)
                         free(config_mime);
                       else
                         {
                            config_glob = E_NEW(Config_Glob, 1);
                            config_glob->name = eina_stringshare_add(ext);
                            config_mime->globs = eina_list_append(config_mime->globs, config_glob);
                            cfdata->mimes = eina_list_append(cfdata->mimes, config_mime);
                         }
                    }
               }
             else
               {
                  config_glob = _find_glob(config_mime, ext);
                  if (!config_glob)
                    {
                       config_glob = E_NEW(Config_Glob, 1);
                       config_glob->name = eina_stringshare_add(ext);
                       config_mime->globs = eina_list_append(config_mime->globs, config_glob);
                    }
               }
          }
        while ((*p != '\n') && (*p != 0));
     }
   fclose(f);
}

static void
_load_globs(E_Config_Dialog_Data *cfdata, char *file)
{
   FILE *f;
   char buf[4096], mimetype[4096], ext[4096];
   char *p, *pp;
   Config_Mime *config_mime;
   Config_Glob *config_glob;

   if (!cfdata) return;

   f = fopen(file, "rb");
   if (!f) return;
   while (fgets(buf, sizeof(buf), f))
     {
        p = buf;
        while (isblank(*p) && (*p != 0) && (*p != '\n'))
          p++;
        if (*p == '#') continue;
        if ((*p == '\n') || (*p == 0)) continue;
        pp = p;
        while ((*p != ':') && (*p != 0) && (*p != '\n'))
          p++;
        if ((*p == '\n') || (*p == 0)) continue;
        strncpy(mimetype, pp, (p - pp));
        mimetype[p - pp] = 0;
        p++;
        pp = ext;
        while ((*p != 0) && (*p != '\n'))
          {
             *pp = *p;
             pp++;
             p++;
          }
        *pp = 0;
        config_mime = _find_mime(cfdata, mimetype);
        if (!config_mime)
          {
             config_mime = E_NEW(Config_Mime, 1);
             if (config_mime)
               {
                  config_mime->mime = eina_stringshare_add(mimetype);
                  if (!config_mime->mime)
                    free(config_mime);
                  else
                    {
                       config_glob = E_NEW(Config_Glob, 1);
                       config_glob->name = eina_stringshare_add(ext);
                       config_mime->globs = eina_list_append(config_mime->globs, config_glob);
                       cfdata->mimes = eina_list_append(cfdata->mimes, config_mime);
                    }
               }
          }
        else
          {
             config_glob = _find_glob(config_mime, ext);
             if (!config_glob)
               {
                  config_glob = E_NEW(Config_Glob, 1);
                  config_glob->name = eina_stringshare_add(ext);
                  config_mime->globs = eina_list_append(config_mime->globs, config_glob);
               }
          }
     }
   fclose(f);
}

static int
_sort_mimes(const void *data1, const void *data2)
{
   const Config_Mime *m1 = data1, *m2 = data2;
   if (!m1) return 1;
   if (!m2) return -1;
   return strcmp(m1->mime, m2->mime);
}

static Config_Mime *
_find_mime(E_Config_Dialog_Data *cfdata, char *mime)
{
   Config_Mime *cm;
   Eina_List *l;

   if (!cfdata) return NULL;
   EINA_LIST_FOREACH(cfdata->mimes, l, cm)
     {
        if (!cm) continue;
        if (!strcmp(cm->mime, mime)) return cm;
     }
   return NULL;
}

static Config_Glob *
_find_glob(Config_Mime *mime, char *globbing)
{
   Config_Glob *g;
   Eina_List *l;

   if (!mime) return NULL;
   EINA_LIST_FOREACH(mime->globs, l, g)
     {
        if (!g) continue;
        if (strcmp(g->name, globbing)) continue;
        return g;
     }
   return NULL;
}

static int
_cb_desks_sort(const void *data1, const void *data2)
{
   const Efreet_Desktop *d1, *d2;

   if (!(d1 = data1)) return 1;
   if (!d1->name) return 1;
   if (!(d2 = data2)) return -1;
   if (!d2->name) return -1;
   return strcmp(d1->name, d2->name);
}

static void
_sel_desk_gen_cb(void *data)
{
   E_Config_Dialog_Data *cfdata = data;
   const char *s = e_widget_ilist_selected_value_get(cfdata->obj.mimelist);
   if ((s) && (cfdata->selmime))
     {
        if (cfdata->ini)
          efreet_ini_string_set(cfdata->ini, cfdata->selmime, s);
     }
}

static void
_sel_desk_cb(void *data)
{
   E_Config_Dialog_Data *cfdata = data;
   if (cfdata->seldest)
     {
        const char *s = e_widget_ilist_selected_value_get(cfdata->obj.deflist);
        if (*(cfdata->seldest)) eina_stringshare_del(*(cfdata->seldest));
        *(cfdata->seldest) = NULL;
        if (s) *(cfdata->seldest) = eina_stringshare_add(s);
        if ((*(cfdata->seldest)) &&
            (cfdata->seldest == &(cfdata->browser_desktop)))
          {
             Eina_List *l;
             Efreet_Desktop *desk;

             EINA_LIST_FOREACH(cfdata->desks, l, desk)
               {
                  if ((!strcmp(desk->orig_path, *(cfdata->seldest))) ||
                      (!strcmp(ecore_file_file_get(desk->orig_path), *(cfdata->seldest))))
                    {
                       if (desk->exec)
                         {
                            char *p;

                            free(cfdata->browser_custom);
                            cfdata->browser_custom = strdup(desk->exec);
                            for (p = cfdata->browser_custom; *p; p++)
                              {
                                 if (p > cfdata->browser_custom)
                                   {
                                      if ((isspace(*p)) &&
                                          (p[-1] != '\\'))
                                        {
                                           *p = 0;
                                           break;
                                        }
                                   }
                              }
                            p = strdup(cfdata->browser_custom);
                            if (p)
                              {
                                 e_widget_entry_text_set(cfdata->obj.entry, p);
                                 free(p);
                              }
                         }
                       break;
                    }
               }
          }
     }
}

static void
_fill_apps_list(E_Config_Dialog_Data *cfdata, Evas_Object *il, const char **desktop, int general)
{
   Eina_List *desks = NULL, *l;
   Efreet_Desktop *desk = NULL;
   Evas *evas;
   int sel, i;

   if (!cfdata->desks)
     {
        desks = efreet_util_desktop_name_glob_list("*");
        EINA_LIST_FREE(desks, desk)
          {
             Eina_List *ll;

             if (desk->no_display)
               {
                  efreet_desktop_free(desk);
                  continue;
               }
             ll = eina_list_search_unsorted_list(cfdata->desks, _cb_desks_sort, desk);
             if (ll)
               {
                  Efreet_Desktop *old;

                  old = eina_list_data_get(ll);
                  /*
                   * This fixes when we have several .desktop with the same name,
                   * and the only difference is that some of them are for specific
                   * desktops.
                   */
                  if ((old->only_show_in) && (!desk->only_show_in))
                    {
                       efreet_desktop_free(old);
                       eina_list_data_set(ll, desk);
                    }
                  else
                    efreet_desktop_free(desk);
               }
             else
               cfdata->desks = eina_list_append(cfdata->desks, desk);
          }
        cfdata->desks = eina_list_sort(cfdata->desks, -1, _cb_desks_sort);
     }

   evas = evas_object_evas_get(il);
   evas_event_freeze(evas);
   edje_freeze();
   e_widget_ilist_freeze(il);
   e_widget_ilist_clear(il);

   sel = -1;
   i = 0;
   EINA_LIST_FOREACH(cfdata->desks, l, desk)
     {
        Evas_Object *icon = NULL;

        if ((desktop) && (*desktop))
          {
             if ((!strcmp(desk->orig_path, *desktop)) ||
                 (!strcmp(ecore_file_file_get(desk->orig_path), *desktop)))
               sel = i;
          }

        icon = e_util_desktop_icon_add(desk, 24, evas);
        if (general)
          e_widget_ilist_append(il, icon, desk->name,
                                _sel_desk_gen_cb, cfdata,
                                ecore_file_file_get(desk->orig_path));
        else
          e_widget_ilist_append(il, icon, desk->name,
                                _sel_desk_cb, cfdata,
                                ecore_file_file_get(desk->orig_path));
        i++;
     }

   e_widget_ilist_go(il);
   e_widget_ilist_thaw(il);
   edje_thaw();
   evas_event_thaw(evas);
   if (sel >= 0)
     {
        e_widget_ilist_selected_set(il, sel);
        e_widget_ilist_nth_show(il, sel, 0);
     }
}

