update for beta release
[framework/uifw/e17.git] / src / bin / e_fm.c
1 #include "e.h"
2 #include "e_fm_device.h"
3 #include "e_fm_op.h"
4
5 #define OVERCLIP 128
6 #define ICON_BOTTOM_SPACE 100
7
8 /* in order to check files (ie: extensions) use simpler and faster
9  * strcasecmp version that instead of checking case for each
10  * character, check just the first and if it's upper, assume
11  * everything is uppercase, otherwise assume everything is lowercase.
12  */
13 //#define E_FM2_SIMPLE_STRCASE_FILES 1
14
15 /* FIXME: this is NOT complete. dnd not complete (started). only list view
16  * works. in icon view it needs to be much better about placement of icons and
17  * being able to save/load icon placement. it doesn't support backgrounds or
18  * custom frames or icons yet
19  */
20
21 typedef enum _E_Fm2_Action_Type
22 {
23    FILE_ADD,
24    FILE_DEL,
25    FILE_CHANGE
26 } E_Fm2_Action_Type;
27
28 typedef struct _E_Fm2_Smart_Data        E_Fm2_Smart_Data;
29 typedef struct _E_Fm2_Region            E_Fm2_Region;
30 typedef struct _E_Fm2_Finfo             E_Fm2_Finfo;
31 typedef struct _E_Fm2_Action            E_Fm2_Action;
32 typedef struct _E_Fm2_Client            E_Fm2_Client;
33 typedef struct _E_Fm2_Uri               E_Fm2_Uri;
34 typedef struct _E_Fm2_Context_Menu_Data E_Fm2_Context_Menu_Data;
35
36 struct _E_Fm2_Smart_Data
37 {
38    int          id;
39    Evas_Coord   x, y, w, h, pw, ph;
40    Evas_Object *obj;
41    Evas_Object *clip;
42    Evas_Object *underlay;
43    Evas_Object *overlay;
44    Evas_Object *drop;
45    Evas_Object *drop_in;
46    Evas_Object *sel_rect;
47    const char  *dev;
48    const char  *path;
49    const char  *realpath;
50
51    struct
52    {
53       Evas_Coord w, h;
54    } max, pmax;
55    struct
56    {
57       Evas_Coord x, y;
58    } pos;
59    struct
60    {
61       Eina_List *list;
62       int        member_max;
63    } regions;
64    struct
65    {
66       struct
67       {
68          E_Fm_Cb func;
69          void   *data;
70       } start, end, replace;
71       E_Fm2_Menu_Flags flags;
72    } icon_menu;
73
74    Eina_List       *icons;
75    Eina_List       *icons_place;
76    Eina_List       *queue;
77    Ecore_Timer     *scan_timer;
78    Ecore_Idler     *sort_idler;
79    Ecore_Job       *scroll_job;
80    Ecore_Job       *resize_job;
81    Ecore_Job       *refresh_job;
82    E_Menu          *menu;
83    E_Entry_Dialog  *entry_dialog;
84    E_Dialog        *image_dialog;
85    Eina_Bool        iconlist_changed : 1;
86    Eina_Bool        order_file : 1;
87    Eina_Bool        typebuf_visible : 1;
88    Eina_Bool        show_hidden_files : 1;
89    Eina_Bool        listing : 1;
90    Eina_Bool        inherited_dir_props : 1;
91    signed char      view_mode;  /* -1 = unset */
92    signed short     icon_size;  /* -1 = unset */
93    E_Fm2_View_Flags view_flags;
94
95    E_Fm2_Config    *config;
96    const char      *custom_theme;
97    const char      *custom_theme_content;
98
99    struct
100    {
101       Evas_Object *obj, *obj2;
102       Eina_List   *last_insert;
103       Eina_List  **list_index;
104       int          iter;
105    } tmp;
106
107    struct
108    {
109       Eina_List   *actions;
110       Ecore_Idler *idler;
111       Ecore_Timer *timer;
112       Eina_Bool    deletions : 1;
113    } live;
114
115    struct
116    {
117       char        *buf;
118       Ecore_Timer *timer;
119    } typebuf;
120
121    int             busy_count;
122
123    E_Object       *eobj;
124    E_Drop_Handler *drop_handler;
125    E_Fm2_Icon     *drop_icon;
126    E_Fm2_Mount    *mount;
127    signed char     drop_after;
128    Eina_Bool       drop_show : 1;
129    Eina_Bool       drop_in_show : 1;
130    Eina_Bool       drop_all : 1;
131    Eina_Bool       drag : 1;
132    Eina_Bool       selecting : 1;
133    struct
134    {
135       int ox, oy;
136       int x, y, w, h;
137    } selrect;
138
139    E_Fm2_Icon *iop_icon;
140
141    Eina_List  *event_handlers;
142 };
143
144 struct _E_Fm2_Region
145 {
146    E_Fm2_Smart_Data *sd;
147    Evas_Coord        x, y, w, h;
148    Eina_List        *list;
149    Eina_Bool         realized : 1;
150 };
151
152 struct _E_Fm2_Icon
153 {
154    E_Fm2_Smart_Data *sd;
155    E_Fm2_Region     *region;
156    Evas_Coord        x, y, w, h, min_w, min_h;
157    Evas_Object      *obj, *obj_icon;
158    int               saved_x, saved_y;
159    int               saved_rel;
160    E_Menu           *menu;
161    E_Entry_Dialog   *entry_dialog;
162    Evas_Object      *entry_widget;
163    E_Config_Dialog  *prop_dialog;
164    E_Dialog         *dialog;
165
166    E_Fm2_Icon_Info   info;
167
168    struct
169    {
170       Evas_Coord x, y;
171       Eina_Bool  start : 1;
172       Eina_Bool  dnd : 1;
173       Eina_Bool  src : 1;
174    } drag;
175
176    Eina_Bool realized : 1;
177    Eina_Bool selected : 1;
178    Eina_Bool last_selected : 1;
179    Eina_Bool saved_pos : 1;
180    Eina_Bool odd : 1;
181    Eina_Bool down_sel : 1;
182    Eina_Bool removable_state_change : 1;
183    Eina_Bool thumb_failed : 1;
184 };
185
186 struct _E_Fm2_Finfo
187 {
188    struct stat st;
189    int         broken_link;
190    const char *lnk;
191    const char *rlnk;
192 };
193
194 struct _E_Fm2_Action
195 {
196    E_Fm2_Action_Type type;
197    const char       *file;
198    const char       *file2;
199    int               flags;
200    E_Fm2_Finfo       finf;
201 };
202
203 struct _E_Fm2_Client
204 {
205    Ecore_Ipc_Client *cl;
206    int               req;
207 };
208
209 struct _E_Fm2_Uri
210 {
211    const char *hostname;
212    const char *path;
213 };
214
215 struct _E_Fm2_Context_Menu_Data
216 {
217    E_Fm2_Icon         *icon;
218    E_Fm2_Mime_Handler *handler;
219 };
220
221 static const char   *_e_fm2_dev_path_map(const char *dev, const char *path);
222 static void          _e_fm2_file_add(Evas_Object *obj, const char *file, int unique, const char *file_rel, int after, E_Fm2_Finfo *finf);
223 static void          _e_fm2_file_del(Evas_Object *obj, const char *file);
224 static void          _e_fm2_queue_process(Evas_Object *obj);
225 static void          _e_fm2_queue_free(Evas_Object *obj);
226 static void          _e_fm2_regions_free(Evas_Object *obj);
227 static void          _e_fm2_regions_populate(Evas_Object *obj);
228 static void          _e_fm2_icons_place(Evas_Object *obj);
229 static void          _e_fm2_icons_free(Evas_Object *obj);
230 static void          _e_fm2_regions_eval(Evas_Object *obj);
231 static void          _e_fm2_config_free(E_Fm2_Config *cfg);
232
233 static void          _e_fm2_dir_load_props(E_Fm2_Smart_Data *sd);
234 static void          _e_fm2_dir_save_props(E_Fm2_Smart_Data *sd);
235
236 static Evas_Object  *_e_fm2_file_fm2_find(const char *file);
237 static E_Fm2_Icon   *_e_fm2_icon_find(Evas_Object *obj, const char *file);
238 static const char   *_e_fm2_uri_escape(const char *path);
239 static Eina_List    *_e_fm2_uri_path_list_get(Eina_List *uri_list);
240 static Eina_List    *_e_fm2_uri_icon_list_get(Eina_List *uri);
241
242 static E_Fm2_Icon   *_e_fm2_icon_new(E_Fm2_Smart_Data *sd, const char *file, E_Fm2_Finfo *finf);
243 static void          _e_fm2_icon_unfill(E_Fm2_Icon *ic);
244 static int           _e_fm2_icon_fill(E_Fm2_Icon *ic, E_Fm2_Finfo *finf);
245 static void          _e_fm2_icon_free(E_Fm2_Icon *ic);
246 static void          _e_fm2_icon_realize(E_Fm2_Icon *ic);
247 static void          _e_fm2_icon_unrealize(E_Fm2_Icon *ic);
248 static Eina_Bool     _e_fm2_icon_visible(const E_Fm2_Icon *ic);
249 static void          _e_fm2_icon_label_set(E_Fm2_Icon *ic, Evas_Object *obj);
250 static Evas_Object  *_e_fm2_icon_icon_direct_set(E_Fm2_Icon *ic, Evas_Object *o, Evas_Smart_Cb gen_func, void *data, int force_gen);
251 static void          _e_fm2_icon_icon_set(E_Fm2_Icon *ic);
252 static void          _e_fm2_icon_thumb(const E_Fm2_Icon *ic, Evas_Object *oic, int force);
253 static void          _e_fm2_icon_select(E_Fm2_Icon *ic);
254 static void          _e_fm2_icon_deselect(E_Fm2_Icon *ic);
255 static int           _e_fm2_icon_desktop_load(E_Fm2_Icon *ic);
256
257 static E_Fm2_Region *_e_fm2_region_new(E_Fm2_Smart_Data *sd);
258 static void          _e_fm2_region_free(E_Fm2_Region *rg);
259 static void          _e_fm2_region_realize(E_Fm2_Region *rg);
260 static void          _e_fm2_region_unrealize(E_Fm2_Region *rg);
261 static int           _e_fm2_region_visible(E_Fm2_Region *rg);
262
263 static void          _e_fm2_icon_make_visible(E_Fm2_Icon *ic);
264 static void          _e_fm2_icon_desel_any(Evas_Object *obj);
265 static E_Fm2_Icon   *_e_fm2_icon_first_selected_find(Evas_Object *obj);
266 static E_Fm2_Icon   *_e_fm2_icon_next_find(Evas_Object *obj, int next, int (*match_func)(E_Fm2_Icon *ic, void *data), void *data);
267
268 static void          _e_fm2_icon_sel_first(Evas_Object *obj);
269 static void          _e_fm2_icon_sel_last(Evas_Object *obj);
270 static void          _e_fm2_icon_sel_any(Evas_Object *obj);
271 static void          _e_fm2_icon_sel_prev(Evas_Object *obj);
272 static void          _e_fm2_icon_sel_next(Evas_Object *obj);
273 static void          _e_fm2_icon_sel_down(Evas_Object *obj);
274 static void          _e_fm2_icon_sel_up(Evas_Object *obj);
275
276 static void          _e_fm2_typebuf_show(Evas_Object *obj);
277 static void          _e_fm2_typebuf_hide(Evas_Object *obj);
278 //static void _e_fm2_typebuf_history_prev(Evas_Object *obj);
279 //static void _e_fm2_typebuf_history_next(Evas_Object *obj);
280 static void          _e_fm2_typebuf_run(Evas_Object *obj);
281 static void          _e_fm2_typebuf_match(Evas_Object *obj, int next);
282 static void          _e_fm2_typebuf_complete(Evas_Object *obj);
283 static void          _e_fm2_typebuf_char_append(Evas_Object *obj, const char *ch);
284 static void          _e_fm2_typebuf_char_backspace(Evas_Object *obj);
285
286 static void          _e_fm2_cb_dnd_enter(void *data, const char *type, void *event);
287 static void          _e_fm2_cb_dnd_move(void *data, const char *type, void *event);
288 static void          _e_fm2_cb_dnd_leave(void *data, const char *type, void *event);
289 static void          _e_fm2_cb_dnd_drop(void *data, const char *type, void *event);
290 static void          _e_fm2_cb_icon_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
291 static void          _e_fm2_cb_icon_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
292 static void          _e_fm2_cb_icon_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
293 static void          _e_fm2_cb_icon_thumb_dnd_gen(void *data, Evas_Object *obj, void *event_info);
294 static void          _e_fm2_cb_icon_thumb_gen(void *data, Evas_Object *obj, void *event_info);
295 static void          _e_fm2_cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
296 static void          _e_fm2_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
297 static void          _e_fm2_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
298 static void          _e_fm2_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
299 static void          _e_fm2_cb_scroll_job(void *data);
300 static void          _e_fm2_cb_resize_job(void *data);
301 static int           _e_fm2_cb_icon_sort(const void *data1, const void *data2);
302 static Eina_Bool     _e_fm2_cb_scan_timer(void *data);
303 static Eina_Bool     _e_fm2_cb_sort_idler(void *data);
304 static Eina_Bool     _e_fm2_cb_theme(void *data, int type __UNUSED__, void *event __UNUSED__);
305
306 static void          _e_fm2_obj_icons_place(E_Fm2_Smart_Data *sd);
307
308 static void          _e_fm2_smart_add(Evas_Object *object);
309 static void          _e_fm2_smart_del(Evas_Object *object);
310 static void          _e_fm2_smart_move(Evas_Object *object, Evas_Coord x, Evas_Coord y);
311 static void          _e_fm2_smart_resize(Evas_Object *object, Evas_Coord w, Evas_Coord h);
312 static void          _e_fm2_smart_show(Evas_Object *object);
313 static void          _e_fm2_smart_hide(Evas_Object *object);
314 static void          _e_fm2_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
315 static void          _e_fm2_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
316 static void          _e_fm2_smart_clip_unset(Evas_Object *obj);
317
318 static void          _e_fm2_menu(Evas_Object *obj, unsigned int timestamp);
319 static void          _e_fm2_menu_post_cb(void *data, E_Menu *m);
320 static void          _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp);
321 static void          _e_fm2_icon_menu_post_cb(void *data, E_Menu *m);
322 static void          _e_fm2_icon_menu_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
323 static void          _e_fm2_icon_view_menu_pre(void *data, E_Menu *m, E_Menu_Item *mi);
324 static void          _e_fm2_toggle_inherit_dir_props(void *data, E_Menu *m, E_Menu_Item *mi);
325 static void          _e_fm2_view_menu_pre(void *data, E_Menu *m, E_Menu_Item *mi);
326 static void          _e_fm2_view_menu_grid_icons_cb(void *data, E_Menu *m, E_Menu_Item *mi);
327 static void          _e_fm2_view_menu_custom_icons_cb(void *data, E_Menu *m, E_Menu_Item *mi);
328 static void          _e_fm2_view_menu_list_cb(void *data, E_Menu *m, E_Menu_Item *mi);
329 static void          _e_fm2_view_menu_use_default_cb(void *data, E_Menu *m, E_Menu_Item *mi);
330 static void          _e_fm2_view_menu_set_background_cb(void *data, E_Menu *m, E_Menu_Item *mi);
331 static void          _e_fm2_view_menu_set_overlay_cb(void *data, E_Menu *m, E_Menu_Item *mi);
332 static void          _e_fm2_view_image_sel(E_Fm2_Smart_Data *sd, const char *title, void (*ok_cb)(void *data, E_Dialog *dia), void (*clear_cb)(void *data, E_Dialog *dia));
333 static void          _e_fm2_view_image_sel_close(void *data, E_Dialog *dia);
334 static void          _e_fm2_refresh(void *data, E_Menu *m, E_Menu_Item *mi);
335 static void          _e_fm2_toggle_hidden_files(void *data, E_Menu *m, E_Menu_Item *mi);
336 static void          _e_fm2_toggle_ordering(void *data, E_Menu *m, E_Menu_Item *mi);
337 static void          _e_fm2_sort(void *data, E_Menu *m, E_Menu_Item *mi);
338 static void          _e_fm2_new_directory(void *data, E_Menu *m, E_Menu_Item *mi);
339 static void          _e_fm2_new_directory_delete_cb(void *obj);
340 static void          _e_fm2_new_directory_yes_cb(char *text, void *data);
341 static void          _e_fm2_new_directory_no_cb(void *data);
342 static void          _e_fm2_file_rename(void *data, E_Menu *m, E_Menu_Item *mi);
343 static void          _e_fm2_file_rename_delete_cb(void *obj);
344 static void          _e_fm2_file_rename_yes_cb(char *text, void *data);
345 static void          _e_fm2_file_rename_no_cb(void *data);
346 static void          _e_fm2_file_application_properties(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__);
347 static void          _e_fm2_file_properties(void *data, E_Menu *m, E_Menu_Item *mi);
348 static void          _e_fm2_file_properties_delete_cb(void *obj);
349 static void          _e_fm2_file_do_rename(const char *text, E_Fm2_Icon *ic);
350
351 static Evas_Object  *_e_fm2_icon_entry_widget_add(E_Fm2_Icon *ic);
352 static void          _e_fm2_icon_entry_widget_del(E_Fm2_Icon *ic);
353 static void          _e_fm2_icon_entry_widget_cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
354 static void          _e_fm2_icon_entry_widget_accept(E_Fm2_Icon *ic);
355
356 static E_Dialog     *_e_fm_retry_abort_dialog(int pid, const char *str);
357 static void          _e_fm_retry_abort_delete_cb(void *obj);
358 static void          _e_fm_retry_abort_retry_cb(void *data, E_Dialog *dialog);
359 static void          _e_fm_retry_abort_abort_cb(void *data, E_Dialog *dialog);
360
361 static E_Dialog     *_e_fm_overwrite_dialog(int pid, const char *str);
362 static void          _e_fm_overwrite_delete_cb(void *obj);
363 static void          _e_fm_overwrite_no_cb(void *data, E_Dialog *dialog);
364 static void          _e_fm_overwrite_no_all_cb(void *data, E_Dialog *dialog);
365 static void          _e_fm_overwrite_yes_cb(void *data, E_Dialog *dialog);
366 static void          _e_fm_overwrite_yes_all_cb(void *data, E_Dialog *dialog);
367
368 static E_Dialog     *_e_fm_error_dialog(int pid, const char *str);
369 static void          _e_fm_error_delete_cb(void *obj);
370 static void          _e_fm_error_retry_cb(void *data, E_Dialog *dialog);
371 static void          _e_fm_error_abort_cb(void *data, E_Dialog *dialog);
372 static void          _e_fm_error_ignore_this_cb(void *data, E_Dialog *dialog);
373 static void          _e_fm_error_ignore_all_cb(void *data, E_Dialog *dialog);
374
375 static void          _e_fm_device_error_dialog(const char *title, const char *msg, const char *pstr);
376
377 static void          _e_fm2_file_delete(Evas_Object *obj);
378 static void          _e_fm2_file_delete_menu(void *data, E_Menu *m, E_Menu_Item *mi);
379 static void          _e_fm2_file_delete_delete_cb(void *obj);
380 static void          _e_fm2_file_delete_yes_cb(void *data, E_Dialog *dialog);
381 static void          _e_fm2_file_delete_no_cb(void *data, E_Dialog *dialog);
382 static void          _e_fm2_refresh_job_cb(void *data);
383 static void          _e_fm_file_buffer_clear(void);
384 static void          _e_fm2_file_cut(Evas_Object *obj);
385 static void          _e_fm2_file_copy(Evas_Object *obj);
386 static void          _e_fm2_file_paste(Evas_Object *obj);
387 static void          _e_fm2_file_symlink(Evas_Object *obj);
388 static void          _e_fm2_file_cut_menu(void *data, E_Menu *m, E_Menu_Item *mi);
389 static void          _e_fm2_file_copy_menu(void *data, E_Menu *m, E_Menu_Item *mi);
390 static void          _e_fm2_file_paste_menu(void *data, E_Menu *m, E_Menu_Item *mi);
391 static void          _e_fm2_file_symlink_menu(void *data, E_Menu *m, E_Menu_Item *mi);
392
393 static void          _e_fm2_live_file_add(Evas_Object *obj, const char *file, const char *file_rel, int after, E_Fm2_Finfo *finf);
394 static void          _e_fm2_live_file_del(Evas_Object *obj, const char *file);
395 static void          _e_fm2_live_file_changed(Evas_Object *obj, const char *file, E_Fm2_Finfo *finf);
396 static void          _e_fm2_live_process_begin(Evas_Object *obj);
397 static void          _e_fm2_live_process_end(Evas_Object *obj);
398 static void          _e_fm2_live_process(Evas_Object *obj);
399 static Eina_Bool     _e_fm2_cb_live_idler(void *data);
400 static Eina_Bool     _e_fm2_cb_live_timer(void *data);
401
402 static int           _e_fm2_theme_edje_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const char *category, const char *group);
403 static int           _e_fm2_theme_edje_icon_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const char *category, const char *group);
404
405 static void          _e_fm2_mouse_1_handler(E_Fm2_Icon *ic, int up, void *evas_event);
406
407 static void          _e_fm2_client_spawn(void);
408 static E_Fm2_Client *_e_fm2_client_get(void);
409 static int           _e_fm2_client_monitor_add(const char *path);
410 static void          _e_fm2_client_monitor_del(int id, const char *path);
411 static int           _e_fm_client_file_del(const char *args, Evas_Object *e_fm);
412 //static int _e_fm2_client_file_trash(const char *path, Evas_Object *e_fm);
413 static int           _e_fm2_client_file_mkdir(const char *path, const char *rel, int rel_to, int x, int y, int res_w, int res_h, Evas_Object *e_fm);
414 static int           _e_fm_client_file_move(const char *args, Evas_Object *e_fm);
415 static int           _e_fm2_client_file_symlink(const char *path, const char *dest, const char *rel, int rel_to, int x, int y, int res_w, int res_h, Evas_Object *e_fm);
416 static int           _e_fm_client_file_copy(const char *args, Evas_Object *e_fm);
417 static int           _e_fm_client_file_symlink(const char *args, Evas_Object *e_fm);
418
419 static void          _e_fm2_sel_rect_update(void *data);
420 static inline void   _e_fm2_context_menu_append(Evas_Object *obj, const char *path, Eina_List *l, E_Menu *mn, E_Fm2_Icon *ic);
421 static int           _e_fm2_context_list_sort(const void *data1, const void *data2);
422
423 static char         *_e_fm_string_append_char(char *str, size_t *size, size_t *len, char c);
424 static char         *_e_fm_string_append_quoted(char *str, size_t *size, size_t *len, const char *src);
425
426 void                 _e_fm2_path_parent_set(Evas_Object *obj, const char *path);
427
428 static void          _e_fm2_volume_mount(void *data, E_Menu *m, E_Menu_Item *mi);
429 static void          _e_fm2_volume_unmount(void *data, E_Menu *m, E_Menu_Item *mi);
430 static void          _e_fm2_volume_eject(void *data, E_Menu *m, E_Menu_Item *mi);
431
432 static void          _e_fm2_icon_removable_update(E_Fm2_Icon *ic);
433 static void          _e_fm2_volume_icon_update(E_Volume *v);
434
435 static void          _e_fm2_operation_abort_internal(E_Fm2_Op_Registry_Entry *ere);
436
437 static char *_e_fm2_meta_path = NULL;
438 static Evas_Smart *_e_fm2_smart = NULL;
439 static Eina_List *_e_fm2_list = NULL;
440 static Eina_List *_e_fm2_list_remove = NULL;
441 static int _e_fm2_list_walking = 0;
442 static Eina_List *_e_fm2_client_list = NULL;
443 static Eina_List *_e_fm2_menu_contexts = NULL;
444 static Eina_List *_e_fm_file_buffer = NULL; /* Files for copy&paste are saved here. */
445 static int _e_fm_file_buffer_cutting = 0;
446 static int _e_fm_file_buffer_copying = 0;
447 static const char *_e_fm2_icon_desktop_str = NULL;
448 static const char *_e_fm2_icon_thumb_str = NULL;
449 static const char *_e_fm2_mime_inode_directory = NULL;
450 static const char *_e_fm2_mime_app_desktop = NULL;
451 static const char *_e_fm2_mime_app_edje = NULL;
452 static const char *_e_fm2_mime_text_uri_list = NULL;
453
454 static Ecore_Timer *_e_fm2_mime_flush = NULL;
455 static Ecore_Timer *_e_fm2_mime_clear = NULL;
456
457 /* contains:
458  * _e_volume_edd
459  * _e_storage_edd
460  * _e_volume_free()
461  * _e_storage_free()
462  * _e_volume_edd_new()
463  * _e_storage_edd_new()
464  * _e_storage_volume_edd_init()
465  * _e_storage_volume_edd_shutdown()
466  */
467
468 #include "e_fm_shared_codec.h"
469
470 static inline Eina_Bool
471 _e_fm2_icon_realpath(const E_Fm2_Icon *ic, char *buf, int buflen)
472 {
473    int r = snprintf(buf, buflen, "%s/%s", ic->sd->realpath, ic->info.file);
474    return r < buflen;
475 }
476
477 static inline Eina_Bool
478 _e_fm2_icon_path(const E_Fm2_Icon *ic, char *buf, int buflen)
479 {
480    int r = snprintf(buf, buflen, "%s/%s", ic->sd->path, ic->info.file);
481    return r < buflen;
482 }
483
484 static inline Eina_Bool
485 _e_fm2_ext_is_edje(const char *ext)
486 {
487 #if E_FM2_SIMPLE_STRCASE_FILES
488    if ((ext[0] == 'e') && (ext[1] == 'd') && (ext[2] == 'j'))
489      return 1;
490    else if ((ext[0] == 'E') && (ext[1] == 'D') && (ext[2] == 'J'))
491      return 1;
492    else
493      return 0;
494 #else
495    return strcasecmp(ext, "edj") == 0;
496 #endif
497 }
498
499 static inline Eina_Bool
500 _e_fm2_ext_is_desktop(const char *ext)
501 {
502 #if E_FM2_SIMPLE_STRCASE_FILES
503    if ((ext[0] == 'd') &&
504        ((strcmp(ext + 1, "esktop") == 0) ||
505         (strcmp(ext + 1, "irectory") == 0)))
506      return 1;
507    else if ((ext[0] == 'D') &&
508             ((strcmp(ext + 1, "ESKTOP") == 0) ||
509              (strcmp(ext + 1, "IRECTORY") == 0)))
510      return 1;
511    else
512      return 0;
513 #else
514    if ((ext[0] != 'd') && (ext[0] != 'D'))
515      return 0;
516
517    ext++;
518    return (strcasecmp(ext, "esktop") == 0) ||
519           (strcasecmp(ext, "irectory") == 0);
520 #endif
521 }
522
523 static inline Eina_Bool
524 _e_fm2_ext_is_imc(const char *ext)
525 {
526 #if E_FM2_SIMPLE_STRCASE_FILES
527    if ((ext[0] == 'i') && (ext[1] == 'm') && (ext[2] == 'c'))
528      return 1;
529    else if ((ext[0] == 'I') && (ext[1] == 'M') && (ext[2] == 'C'))
530      return 1;
531    else
532      return 0;
533 #else
534    return strcasecmp(ext, "imc") == 0;
535 #endif
536 }
537
538 static inline Eina_Bool
539 _e_fm2_file_is_edje(const char *file)
540 {
541    const char *p = strrchr(file, '.');
542    return (p) && (_e_fm2_ext_is_edje(p + 1));
543 }
544
545 static inline Eina_Bool
546 _e_fm2_file_is_desktop(const char *file)
547 {
548    const char *p = strrchr(file, '.');
549    return (p) && (_e_fm2_ext_is_desktop(p + 1));
550 }
551
552 static inline char
553 _e_fm2_view_mode_get(const E_Fm2_Smart_Data *sd)
554 {
555    if (sd->view_mode > -1)
556      return sd->view_mode;
557    return sd->config->view.mode;
558 }
559
560 static inline Evas_Coord
561 _e_fm2_icon_w_get(const E_Fm2_Smart_Data *sd)
562 {
563    if (sd->icon_size > -1)
564      return sd->icon_size * e_scale;
565    if (sd->config->icon.icon.w)
566      return sd->config->icon.icon.w;
567    return sd->config->icon.list.w;
568 }
569
570 static inline Evas_Coord
571 _e_fm2_icon_h_get(const E_Fm2_Smart_Data *sd)
572 {
573    if (sd->icon_size > -1)
574      return sd->icon_size * e_scale;
575    if (sd->config->icon.icon.h)
576      return sd->config->icon.icon.h;
577    return sd->config->icon.list.h;
578 }
579
580 static inline unsigned int
581 _e_fm2_icon_mime_size_normalize(const E_Fm2_Icon *ic)
582 {
583    return e_util_icon_size_normalize(_e_fm2_icon_w_get(ic->sd));
584 }
585
586 static Eina_Bool
587 _e_fm2_mime_flush_cb(void *data __UNUSED__)
588 {
589    efreet_mime_type_cache_flush();
590    return ECORE_CALLBACK_RENEW;
591 }
592
593 static Eina_Bool
594 _e_fm2_mime_clear_cb(void *data __UNUSED__)
595 {
596    efreet_mime_type_cache_clear();
597    return ECORE_CALLBACK_RENEW;
598 }
599
600 static void
601 _e_fm2_op_registry_go_on(int id)
602 {
603    E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
604    if (!ere) return;
605    ere->status = E_FM2_OP_STATUS_IN_PROGRESS;
606    ere->needs_attention = 0;
607    ere->dialog = NULL;
608    e_fm2_op_registry_entry_changed(ere);
609 }
610
611 static void
612 _e_fm2_op_registry_aborted(int id)
613 {
614    E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
615    if (!ere) return;
616    ere->status = E_FM2_OP_STATUS_ABORTED;
617    ere->needs_attention = 0;
618    ere->dialog = NULL;
619    ere->finished = 1;
620    e_fm2_op_registry_entry_changed(ere);
621    // XXX e_fm2_op_registry_entry_del(id);
622 }
623
624 static void
625 _e_fm2_op_registry_error(int id, E_Dialog *dlg)
626 {
627    E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
628    if (!ere) return;
629    ere->status = E_FM2_OP_STATUS_ERROR;
630    ere->needs_attention = 1;
631    ere->dialog = dlg;
632    e_fm2_op_registry_entry_changed(ere);
633 }
634
635 static void
636 _e_fm2_op_registry_needs_attention(int id, E_Dialog *dlg)
637 {
638    E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
639    if (!ere) return;
640    ere->needs_attention = 1;
641    ere->dialog = dlg;
642    e_fm2_op_registry_entry_changed(ere);
643 }
644
645 /////////////// DBG:
646 static void
647 _e_fm2_op_registry_entry_print(const E_Fm2_Op_Registry_Entry *ere)
648 {
649    const char *status_strings[] =
650    {
651       "UNKNOWN", "IN_PROGRESS", "SUCCESSFUL", "ABORTED", "ERROR"
652    };
653    const char *status;
654
655    if (ere->status <= E_FM2_OP_STATUS_ERROR)
656      status = status_strings[ere->status];
657    else
658      status = status_strings[0];
659
660    printf("id: %8d, op: %2d [%s] finished: %hhu, needs_attention: %hhu\n"
661           "    %3d%% (%" PRIi64 "/%" PRIi64 "), start_time: %10.0f, eta: %5ds, xwin: %#x\n"
662                                             "    src=[%s]\n"
663                                             "    dst=[%s]\n",
664           ere->id, ere->op, status, ere->finished, ere->needs_attention,
665           ere->percent, ere->done, ere->total, ere->start_time, ere->eta,
666           e_fm2_op_registry_entry_xwin_get(ere),
667           ere->src, ere->dst);
668 }
669
670 static Eina_Bool
671 _e_fm2_op_registry_entry_add_cb(void *data __UNUSED__, int type __UNUSED__, void *event)
672 {
673    const E_Fm2_Op_Registry_Entry *ere = event;
674    printf("E FM OPERATION STARTED: id=%d, op=%d\n", ere->id, ere->op);
675    return ECORE_CALLBACK_RENEW;
676 }
677
678 static Eina_Bool
679 _e_fm2_op_registry_entry_del_cb(void *data __UNUSED__, int type __UNUSED__, void *event)
680 {
681    const E_Fm2_Op_Registry_Entry *ere = event;
682    puts("E FM OPERATION FINISHED:");
683    _e_fm2_op_registry_entry_print(ere);
684    puts("---");
685    return ECORE_CALLBACK_RENEW;
686 }
687
688 static Eina_Bool
689 _e_fm2_op_registry_entry_changed_cb(void *data __UNUSED__, int type __UNUSED__, void *event)
690 {
691    const E_Fm2_Op_Registry_Entry *ere = event;
692    puts("E FM OPERATION CHANGED:");
693    _e_fm2_op_registry_entry_print(ere);
694    puts("---");
695    return ECORE_CALLBACK_RENEW;
696 }
697
698 static Ecore_Event_Handler *_e_fm2_op_registry_entry_add_handler = NULL;
699 static Ecore_Event_Handler *_e_fm2_op_registry_entry_del_handler = NULL;
700 static Ecore_Event_Handler *_e_fm2_op_registry_entry_changed_handler = NULL;
701 /////////////// DBG:
702
703 /***/
704
705 EINTERN int
706 e_fm2_init(void)
707 {
708    char path[PATH_MAX];
709
710    eina_init();
711    ecore_init();
712    _e_storage_volume_edd_init();
713    e_user_dir_concat_static(path, "fileman/metadata");
714    ecore_file_mkpath(path);
715    _e_fm2_meta_path = strdup(path);
716
717    {
718       static const Evas_Smart_Class sc =
719       {
720          "e_fm",
721          EVAS_SMART_CLASS_VERSION,
722          _e_fm2_smart_add, /* add */
723          _e_fm2_smart_del, /* del */
724          _e_fm2_smart_move, /* move */
725          _e_fm2_smart_resize, /* resize */
726          _e_fm2_smart_show, /* show */
727          _e_fm2_smart_hide, /* hide */
728          _e_fm2_smart_color_set, /* color_set */
729          _e_fm2_smart_clip_set, /* clip_set */
730          _e_fm2_smart_clip_unset, /* clip_unset */
731          NULL,
732          NULL,
733          NULL,
734          NULL,
735          NULL,
736          NULL,
737          NULL
738       };
739       _e_fm2_smart = evas_smart_class_new(&sc);
740    }
741 //   _e_fm2_client_spawn();
742    e_fm2_custom_file_init();
743    e_fm2_op_registry_init();
744    efreet_mime_init();
745
746    /* XXX: move this to a central/global place? */
747    _e_fm2_mime_flush = ecore_timer_add(60.0, _e_fm2_mime_flush_cb, NULL);
748    _e_fm2_mime_clear = ecore_timer_add(600.0, _e_fm2_mime_clear_cb, NULL);
749
750    _e_fm2_icon_desktop_str = eina_stringshare_add("DESKTOP");
751    _e_fm2_icon_thumb_str = eina_stringshare_add("THUMB");
752    _e_fm2_mime_inode_directory = eina_stringshare_add("inode/directory");
753    _e_fm2_mime_app_desktop = eina_stringshare_add("application/x-desktop");
754    _e_fm2_mime_app_edje = eina_stringshare_add("application/x-extension-edj");
755    _e_fm2_mime_text_uri_list = eina_stringshare_add("text/uri-list");
756
757    /// DBG
758    if (!_e_fm2_op_registry_entry_add_handler)
759      _e_fm2_op_registry_entry_add_handler =
760        ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_ADD,
761                                _e_fm2_op_registry_entry_add_cb, NULL);
762    if (!_e_fm2_op_registry_entry_del_handler)
763      _e_fm2_op_registry_entry_del_handler =
764        ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_DEL,
765                                _e_fm2_op_registry_entry_del_cb, NULL);
766    if (!_e_fm2_op_registry_entry_changed_handler)
767      _e_fm2_op_registry_entry_changed_handler =
768        ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_CHANGED,
769                                _e_fm2_op_registry_entry_changed_cb, NULL);
770    /// DBG
771
772    return 1;
773 }
774
775 EINTERN int
776 e_fm2_shutdown(void)
777 {
778    eina_stringshare_replace(&_e_fm2_icon_desktop_str, NULL);
779    eina_stringshare_replace(&_e_fm2_icon_thumb_str, NULL);
780    eina_stringshare_replace(&_e_fm2_mime_inode_directory, NULL);
781    eina_stringshare_replace(&_e_fm2_mime_app_desktop, NULL);
782    eina_stringshare_replace(&_e_fm2_mime_app_edje, NULL);
783    eina_stringshare_replace(&_e_fm2_mime_text_uri_list, NULL);
784
785    /// DBG
786    if (_e_fm2_op_registry_entry_add_handler)
787      {
788         ecore_event_handler_del(_e_fm2_op_registry_entry_add_handler);
789         _e_fm2_op_registry_entry_add_handler = NULL;
790      }
791    if (_e_fm2_op_registry_entry_del_handler)
792      {
793         ecore_event_handler_del(_e_fm2_op_registry_entry_del_handler);
794         _e_fm2_op_registry_entry_del_handler = NULL;
795      }
796    if (_e_fm2_op_registry_entry_changed_handler)
797      {
798         ecore_event_handler_del(_e_fm2_op_registry_entry_changed_handler);
799         _e_fm2_op_registry_entry_changed_handler = NULL;
800      }
801    /// DBG
802
803    ecore_timer_del(_e_fm2_mime_flush);
804    _e_fm2_mime_flush = NULL;
805    ecore_timer_del(_e_fm2_mime_clear);
806    _e_fm2_mime_clear = NULL;
807
808    evas_smart_free(_e_fm2_smart);
809    _e_fm2_smart = NULL;
810    E_FREE(_e_fm2_meta_path);
811    e_fm2_custom_file_shutdown();
812    _e_storage_volume_edd_shutdown();
813    e_fm2_op_registry_shutdown();
814    efreet_mime_shutdown();
815    ecore_shutdown();
816    eina_shutdown();
817    return 1;
818 }
819
820 EAPI Evas_Object *
821 e_fm2_add(Evas *evas)
822 {
823    return evas_object_smart_add(evas, _e_fm2_smart);
824 }
825
826 static void
827 _e_fm2_cb_mount_ok(void *data)
828 {
829    E_Fm2_Smart_Data *sd;
830
831    sd = evas_object_smart_data_get(data);
832    if (!sd) return;  // safety
833
834    if (sd->mount->volume->efm_mode != EFM_MODE_USING_HAL_MOUNT)
835      {
836         /* Clean up typebuf. */
837         _e_fm2_typebuf_hide(data);
838         /* we only just now have the mount point so we should do stuff we couldn't do before */
839         eina_stringshare_replace(&sd->realpath, sd->mount->volume->mount_point);
840         eina_stringshare_replace(&sd->mount->mount_point, sd->mount->volume->mount_point);
841         _e_fm2_dir_load_props(sd);
842      }
843
844    if ((sd->realpath) && (strcmp(sd->mount->mount_point, sd->realpath)))
845      {
846         e_fm2_path_set(sd->obj, "/", sd->mount->mount_point);
847      }
848    else
849      {
850         sd->id = _e_fm2_client_monitor_add(sd->mount->mount_point);
851         sd->listing = EINA_TRUE;
852         evas_object_smart_callback_call(data, "dir_changed", NULL);
853         sd->tmp.iter = EINA_FALSE;
854      }
855 }
856
857 static void
858 _e_fm2_cb_mount_fail(void *data)
859 {
860    E_Fm2_Smart_Data *sd;
861
862    sd = evas_object_smart_data_get(data);
863    if (!sd) return;  // safety
864    if (sd->mount)
865      {
866         // At this moment E_Fm2_Mount object already deleted in e_fm_device.c
867           sd->mount = NULL;
868           if (sd->config->view.open_dirs_in_place)
869             e_fm2_path_set(data, "favorites", "/");
870           else
871             evas_object_smart_callback_call(data, "dir_deleted", NULL);
872      }
873 }
874
875 static void
876 _e_fm2_cb_unmount_ok(void *data)
877 {
878    E_Fm2_Smart_Data *sd;
879
880    sd = evas_object_smart_data_get(data);
881    if (!sd) return;
882    if (sd->mount)
883      {
884         sd->mount = NULL;
885         if (sd->config->view.open_dirs_in_place)
886           _e_fm2_path_parent_set(data, sd->realpath);
887         else
888           evas_object_smart_callback_call(data, "dir_deleted", NULL);
889      }
890 }
891
892 void
893 _e_fm2_path_parent_set(Evas_Object *obj, const char *path)
894 {
895    char buf[PATH_MAX], *p;
896    int idx;
897
898    p = strrchr(path, '/');
899    if (!p || (p == path))
900      e_fm2_path_set(obj, "/", "/");
901    else
902      {
903         idx = p - path;
904         if (idx < PATH_MAX)
905           {
906              strncpy(buf, path, idx);
907              buf[idx] = '\0';
908              e_fm2_path_set(obj, "/", buf);
909           }
910         else
911           e_fm2_path_set(obj, "/", "/");
912      }
913 }
914
915 EAPI void
916 e_fm2_path_set(Evas_Object *obj, const char *dev, const char *path)
917 {
918    E_Fm2_Smart_Data *sd;
919    const char *realpath;
920
921    sd = evas_object_smart_data_get(obj);
922    if (!sd || !path) return;  // safety
923    if (!evas_object_type_get(obj)) return;  // safety
924    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
925
926    /* internal config for now - don't see a pont making this configurable */
927    sd->regions.member_max = 64;
928
929    if (!sd->config)
930      {
931         sd->config = E_NEW(E_Fm2_Config, 1);
932         if (!sd->config) return;
933 //      sd->config->view.mode = E_FM2_VIEW_MODE_ICONS;
934         sd->config->view.mode = E_FM2_VIEW_MODE_LIST;
935         sd->config->view.open_dirs_in_place = EINA_TRUE;
936         sd->config->view.selector = EINA_TRUE;
937         sd->config->view.single_click = EINA_FALSE;
938         sd->config->view.single_click_delay = EINA_FALSE;
939         sd->config->view.no_subdir_jump = EINA_FALSE;
940         sd->config->icon.icon.w = 128;
941         sd->config->icon.icon.h = 128;
942         sd->config->icon.list.w = 24;
943         sd->config->icon.list.h = 24;
944         sd->config->icon.fixed.w = EINA_TRUE;
945         sd->config->icon.fixed.h = EINA_TRUE;
946         sd->config->icon.extension.show = EINA_FALSE;
947         sd->config->list.sort.no_case = EINA_TRUE;
948         sd->config->list.sort.dirs.first = EINA_TRUE;
949         sd->config->list.sort.dirs.last = EINA_FALSE;
950         sd->config->selection.single = EINA_FALSE;
951         sd->config->selection.windows_modifiers = EINA_FALSE;
952         sd->config->theme.background = NULL;
953         sd->config->theme.frame = NULL;
954         sd->config->theme.icons = NULL;
955         sd->config->theme.fixed = EINA_FALSE;
956      }
957
958    realpath = _e_fm2_dev_path_map(dev, path);
959    /* If the path doesn't exist, popup a dialog */
960    if (dev && strncmp(dev, "removable:", 10)
961        && !ecore_file_exists(realpath))
962      {
963         E_Manager *man;
964         E_Container *con;
965         E_Dialog *dialog;
966         char text[4096 + 256];
967
968         man = e_manager_current_get();
969         if (!man) return;
970         con = e_container_current_get(man);
971         if (!con) return;
972
973         dialog = e_dialog_new(con, "E", "_fm_file_unexisting_path_dialog");
974         e_dialog_button_add(dialog, _("Close"), NULL, NULL, dialog);
975         e_dialog_button_focus_num(dialog, 0);
976         e_dialog_title_set(dialog, _("Nonexistent path"));
977         e_dialog_icon_set(dialog, "dialog-error", 64);
978
979         snprintf(text, sizeof(text), _("%s doesn't exist."), realpath);
980
981         e_dialog_text_set(dialog, text);
982         e_win_centered_set(dialog->win, 1);
983         e_dialog_show(dialog);
984         return;
985      }
986
987    if (sd->realpath) _e_fm2_client_monitor_del(sd->id, sd->realpath);
988    sd->listing = EINA_FALSE;
989
990    eina_stringshare_replace(&sd->dev, dev);
991    eina_stringshare_replace(&sd->path, path);
992    eina_stringshare_del(sd->realpath);
993    sd->realpath = realpath;
994    _e_fm2_queue_free(obj);
995    _e_fm2_regions_free(obj);
996    _e_fm2_icons_free(obj);
997    edje_object_part_text_set(sd->overlay, "e.text.busy_label", "");
998
999    _e_fm2_dir_load_props(sd);
1000
1001    /* If the path change from a mountpoint to something else, we fake-unmount */
1002    if (sd->mount && sd->mount->mount_point
1003        && strncmp(sd->mount->mount_point, sd->realpath,
1004                   strlen(sd->mount->mount_point)))
1005      {
1006         e_fm2_device_unmount(sd->mount);
1007         sd->mount = NULL;
1008      }
1009
1010    /* If the path is of type removable: we add a new mountpoint */
1011    if (sd->dev && !sd->mount && !strncmp(sd->dev, "removable:", 10))
1012      {
1013         E_Volume *v = NULL;
1014
1015         v = e_fm2_device_volume_find(sd->dev + sizeof("removable:") - 1);
1016         if (v)
1017           {
1018              sd->mount = e_fm2_device_mount(v,
1019                                             _e_fm2_cb_mount_ok, _e_fm2_cb_mount_fail,
1020                                             _e_fm2_cb_unmount_ok, NULL, obj);
1021              if (v->efm_mode != EFM_MODE_USING_HAL_MOUNT) return;
1022           }
1023      }
1024    else if (sd->config->view.open_dirs_in_place == 0)
1025      {
1026         E_Fm2_Mount *m;
1027         m = e_fm2_device_mount_find(sd->realpath);
1028         if (m)
1029           sd->mount = e_fm2_device_mount(m->volume,
1030                                          _e_fm2_cb_mount_ok, _e_fm2_cb_mount_fail,
1031                                          _e_fm2_cb_unmount_ok, NULL, obj);
1032      }
1033
1034    if (!sd->mount || sd->mount->mounted)
1035      {
1036         sd->id = _e_fm2_client_monitor_add(sd->realpath);
1037         sd->listing = EINA_TRUE;
1038      }
1039
1040    /* Clean up typebuf. */
1041    _e_fm2_typebuf_hide(obj);
1042
1043    evas_object_smart_callback_call(obj, "dir_changed", NULL);
1044    sd->tmp.iter = EINA_FALSE;
1045 }
1046
1047 EAPI void
1048 e_fm2_underlay_show(Evas_Object *obj)
1049 {
1050    E_Fm2_Smart_Data *sd;
1051
1052    sd = evas_object_smart_data_get(obj);
1053    if (!sd) return;  // safety
1054    if (!evas_object_type_get(obj)) return;  // safety
1055    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1056    evas_object_show(sd->underlay);
1057 }
1058
1059 EAPI void
1060 e_fm2_underlay_hide(Evas_Object *obj)
1061 {
1062    E_Fm2_Smart_Data *sd;
1063
1064    sd = evas_object_smart_data_get(obj);
1065    if (!sd) return;  // safety
1066    if (!evas_object_type_get(obj)) return;  // safety
1067    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1068    evas_object_hide(sd->underlay);
1069 }
1070
1071 EAPI void
1072 e_fm2_all_unsel(Evas_Object *obj)
1073 {
1074    E_Fm2_Smart_Data *sd;
1075
1076    sd = evas_object_smart_data_get(obj);
1077    if (!sd) return;  // safety
1078    if (!evas_object_type_get(obj)) return;  // safety
1079    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1080    _e_fm2_icon_desel_any(obj);
1081 }
1082
1083 EAPI void
1084 e_fm2_all_sel(Evas_Object *obj)
1085 {
1086    E_Fm2_Smart_Data *sd;
1087
1088    sd = evas_object_smart_data_get(obj);
1089    if (!sd) return;  // safety
1090    if (!evas_object_type_get(obj)) return;  // safety
1091    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1092    _e_fm2_icon_sel_any(obj);
1093 }
1094
1095 EAPI void
1096 e_fm2_custom_theme_set(Evas_Object *obj, const char *path)
1097 {
1098    E_Fm2_Smart_Data *sd;
1099
1100    sd = evas_object_smart_data_get(obj);
1101    if (!sd) return;  // safety
1102    if (!evas_object_type_get(obj)) return;  // safety
1103    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1104    eina_stringshare_replace(&sd->custom_theme, path);
1105    _e_fm2_theme_edje_object_set(sd, sd->drop, "base/theme/fileman",
1106                                 "list/drop_between");
1107    _e_fm2_theme_edje_object_set(sd, sd->drop_in, "base/theme/fileman",
1108                                 "list/drop_in");
1109    _e_fm2_theme_edje_object_set(sd, sd->overlay, "base/theme/fileman",
1110                                 "overlay");
1111    _e_fm2_theme_edje_object_set(sd, sd->sel_rect, "base/theme/fileman",
1112                                 "rubberband");
1113 }
1114
1115 EAPI void
1116 e_fm2_custom_theme_content_set(Evas_Object *obj, const char *content)
1117 {
1118    E_Fm2_Smart_Data *sd;
1119
1120    sd = evas_object_smart_data_get(obj);
1121    if (!sd) return;  // safety
1122    if (!evas_object_type_get(obj)) return;  // safety
1123    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1124    eina_stringshare_replace(&sd->custom_theme_content, content);
1125    _e_fm2_theme_edje_object_set(sd, sd->drop, "base/theme/fileman",
1126                                 "list/drop_between");
1127    _e_fm2_theme_edje_object_set(sd, sd->drop_in, "base/theme/fileman",
1128                                 "list/drop_in");
1129    _e_fm2_theme_edje_object_set(sd, sd->overlay, "base/theme/fileman",
1130                                 "overlay");
1131 }
1132
1133 EAPI void
1134 e_fm2_path_get(Evas_Object *obj, const char **dev, const char **path)
1135 {
1136    E_Fm2_Smart_Data *sd;
1137
1138    if (dev) *dev = NULL;
1139    if (path) *path = NULL;
1140    sd = evas_object_smart_data_get(obj);
1141    if (!sd) return;  // safety
1142    if (!evas_object_type_get(obj)) return;  // safety
1143    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1144    if (dev) *dev = sd->dev;
1145    if (path) *path = sd->path;
1146 }
1147
1148 static E_Fm2_Custom_File *
1149 _e_fm2_dir_load_props_from_parent(const char *path)
1150 {
1151    E_Fm2_Custom_File *cf;
1152    char *parent;
1153
1154    if ((!path) || (path[0] == '\0') || (strcmp(path, "/") == 0))
1155      return NULL;
1156
1157    parent = ecore_file_dir_get(path);
1158    cf = e_fm2_custom_file_get(parent);
1159    if ((cf) && (cf->dir) && (cf->dir->prop.in_use))
1160      {
1161         free(parent);
1162         return cf;
1163      }
1164
1165    cf = _e_fm2_dir_load_props_from_parent(parent);
1166    free(parent);
1167    return cf;
1168 }
1169
1170 static void
1171 _e_fm2_dir_load_props(E_Fm2_Smart_Data *sd)
1172 {
1173    E_Fm2_Custom_File *cf;
1174
1175
1176    if (!sd->realpath) return; /* come back later */
1177    if (!(sd->view_flags & E_FM2_VIEW_LOAD_DIR_CUSTOM)) return;
1178
1179    cf = e_fm2_custom_file_get(sd->realpath);
1180    if ((cf) && (cf->dir))
1181      {
1182         Evas_Coord x, y;
1183
1184         if (sd->max.w - sd->w > 0)
1185           x = (sd->max.w - sd->w) * cf->dir->pos.x;
1186         else
1187           x = 0;
1188
1189         if (sd->max.h - sd->h > 0)
1190           y = (sd->max.h - sd->h) * cf->dir->pos.y;
1191         else
1192           y = 0;
1193
1194         e_fm2_pan_set(sd->obj, x, y);
1195
1196         if (cf->dir->prop.in_use)
1197           {
1198              sd->view_mode = cf->dir->prop.view_mode;
1199              sd->icon_size = cf->dir->prop.icon_size;
1200              sd->order_file = !!cf->dir->prop.order_file;
1201              sd->show_hidden_files = !!cf->dir->prop.show_hidden_files;
1202              sd->inherited_dir_props = EINA_FALSE;
1203              return;
1204           }
1205      }
1206    else
1207      {
1208         sd->pos.x = 0;
1209         sd->pos.y = 0;
1210      }
1211
1212    if (!(sd->view_flags & E_FM2_VIEW_INHERIT_DIR_CUSTOM))
1213      {
1214         sd->view_mode = -1;
1215         sd->icon_size = -1;
1216         sd->order_file = EINA_FALSE;
1217         sd->show_hidden_files = EINA_FALSE;
1218         sd->inherited_dir_props = EINA_FALSE;
1219         return;
1220      }
1221
1222    sd->inherited_dir_props = EINA_TRUE;
1223
1224    cf = _e_fm2_dir_load_props_from_parent(sd->realpath);
1225    if ((cf) && (cf->dir) && (cf->dir->prop.in_use))
1226      {
1227         sd->view_mode = cf->dir->prop.view_mode;
1228         sd->icon_size = cf->dir->prop.icon_size;
1229         sd->order_file = !!cf->dir->prop.order_file;
1230         sd->show_hidden_files = !!cf->dir->prop.show_hidden_files;
1231      }
1232    else
1233      {
1234         sd->view_mode = -1;
1235         sd->icon_size = -1;
1236         sd->order_file = EINA_FALSE;
1237         sd->show_hidden_files = EINA_FALSE;
1238      }
1239 }
1240
1241 static void
1242 _e_fm2_dir_save_props(E_Fm2_Smart_Data *sd)
1243 {
1244    E_Fm2_Custom_File *cf, cf0;
1245    E_Fm2_Custom_Dir dir0;
1246
1247    if (!(sd->view_flags & E_FM2_VIEW_SAVE_DIR_CUSTOM)) return;
1248
1249    cf = e_fm2_custom_file_get(sd->realpath);
1250    if (!cf)
1251      {
1252         cf = &cf0;
1253         memset(cf, 0, sizeof(*cf));
1254         cf->dir = &dir0;
1255      }
1256    else if (!cf->dir)
1257      {
1258         E_Fm2_Custom_File *cf2 = cf;
1259         cf = &cf0;
1260         memcpy(cf, cf2, sizeof(*cf2));
1261         cf->dir = &dir0;
1262      }
1263
1264    if (sd->max.w - sd->w > 0)
1265      cf->dir->pos.x = sd->pos.x / (double)(sd->max.w - sd->w);
1266    else
1267      cf->dir->pos.x = 0.0;
1268
1269    if (sd->max.h - sd->h)
1270      cf->dir->pos.y = sd->pos.y / (double)(sd->max.h - sd->h);
1271    else
1272      cf->dir->pos.y = 0.0;
1273
1274    cf->dir->prop.icon_size = sd->icon_size;
1275    cf->dir->prop.view_mode = sd->view_mode;
1276    cf->dir->prop.order_file = sd->order_file;
1277    cf->dir->prop.show_hidden_files = sd->show_hidden_files;
1278    cf->dir->prop.in_use = !sd->inherited_dir_props;
1279
1280    e_fm2_custom_file_set(sd->realpath, cf);
1281    e_fm2_custom_file_flush();
1282 }
1283
1284 EAPI void
1285 e_fm2_refresh(Evas_Object *obj)
1286 {
1287    E_Fm2_Smart_Data *sd;
1288
1289    sd = evas_object_smart_data_get(obj);
1290    if (!sd) return;  // safety
1291    if (!evas_object_type_get(obj)) return;  // safety
1292    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1293
1294    _e_fm2_dir_save_props(sd);
1295
1296    _e_fm2_queue_free(obj);
1297    _e_fm2_regions_free(obj);
1298    _e_fm2_icons_free(obj);
1299
1300    sd->order_file = EINA_FALSE;
1301
1302    if (sd->realpath)
1303      {
1304         sd->listing = EINA_FALSE;
1305         _e_fm2_client_monitor_del(sd->id, sd->realpath);
1306         sd->id = _e_fm2_client_monitor_add(sd->realpath);
1307         sd->listing = EINA_TRUE;
1308      }
1309
1310    sd->tmp.iter = EINA_FALSE;
1311 }
1312
1313 EAPI int
1314 e_fm2_has_parent_get(Evas_Object *obj)
1315 {
1316    E_Fm2_Smart_Data *sd;
1317
1318    sd = evas_object_smart_data_get(obj);
1319    if (!sd) return 0;  // safety
1320    if (!evas_object_type_get(obj)) return 0;  // safety
1321    if (strcmp(evas_object_type_get(obj), "e_fm")) return 0;  // safety
1322    if (!sd->path) return 0;
1323    if ((sd->path[0] == 0) || (!strcmp(sd->path, "/"))) return 0;
1324    return 1;
1325 }
1326
1327 EAPI const char *
1328 e_fm2_real_path_get(Evas_Object *obj)
1329 {
1330    E_Fm2_Smart_Data *sd;
1331
1332    sd = evas_object_smart_data_get(obj);
1333    if (!sd) return NULL;  // safety
1334    if (!evas_object_type_get(obj)) return NULL;  // safety
1335    if (strcmp(evas_object_type_get(obj), "e_fm")) return NULL;  // safety
1336    return sd->realpath;
1337 }
1338
1339 EAPI void
1340 e_fm2_parent_go(Evas_Object *obj)
1341 {
1342    E_Fm2_Smart_Data *sd;
1343    char *p, *path;
1344
1345    sd = evas_object_smart_data_get(obj);
1346    if (!sd) return;  // safety
1347    if (!evas_object_type_get(obj)) return;  // safety
1348    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1349    if (!sd->path) return;
1350    path = strdup(sd->path);
1351    if (!path) return;
1352    if ((p = strrchr(path, '/'))) *p = 0;
1353    if (*path == 0)
1354      e_fm2_path_set(obj, sd->dev, "/");
1355    else
1356      e_fm2_path_set(obj, sd->dev, path);
1357
1358    free(path);
1359 }
1360
1361 EAPI void
1362 e_fm2_config_set(Evas_Object *obj, E_Fm2_Config *cfg)
1363 {
1364    E_Fm2_Smart_Data *sd;
1365
1366    sd = evas_object_smart_data_get(obj);
1367    if (!sd) return;  // safety
1368    if (!evas_object_type_get(obj)) return;  // safety
1369    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1370    if (sd->config) _e_fm2_config_free(sd->config);
1371    sd->config = NULL;
1372    if (!cfg) return;
1373    sd->config = E_NEW(E_Fm2_Config, 1);
1374    if (!sd->config) return;
1375    memcpy(sd->config, cfg, sizeof(E_Fm2_Config));
1376    sd->config->icon.key_hint = eina_stringshare_add(cfg->icon.key_hint);
1377    sd->config->theme.background = eina_stringshare_add(cfg->theme.background);
1378    sd->config->theme.frame = eina_stringshare_add(cfg->theme.frame);
1379    sd->config->theme.icons = eina_stringshare_add(cfg->theme.icons);
1380 }
1381
1382 EAPI E_Fm2_Config *
1383 e_fm2_config_get(Evas_Object *obj)
1384 {
1385    E_Fm2_Smart_Data *sd;
1386
1387    sd = evas_object_smart_data_get(obj);
1388    if (!sd) return NULL;  // safety
1389    if (!evas_object_type_get(obj)) return NULL;  // safety
1390    if (strcmp(evas_object_type_get(obj), "e_fm")) return NULL;  // safety
1391    return sd->config;
1392 }
1393
1394 EAPI Eina_List *
1395 e_fm2_selected_list_get(Evas_Object *obj)
1396 {
1397    E_Fm2_Smart_Data *sd;
1398    Eina_List *list = NULL, *l;
1399    E_Fm2_Icon *ic;
1400
1401    sd = evas_object_smart_data_get(obj);
1402    if (!sd) return NULL;  // safety
1403    if (!evas_object_type_get(obj)) return NULL;  // safety
1404    if (strcmp(evas_object_type_get(obj), "e_fm")) return NULL;  // safety
1405    EINA_LIST_FOREACH(sd->icons, l, ic)
1406      {
1407         if (ic->selected)
1408           list = eina_list_append(list, &(ic->info));
1409      }
1410    return list;
1411 }
1412
1413 EAPI Eina_List *
1414 e_fm2_all_list_get(Evas_Object *obj)
1415 {
1416    E_Fm2_Smart_Data *sd;
1417    Eina_List *list = NULL, *l;
1418    E_Fm2_Icon *ic;
1419
1420    sd = evas_object_smart_data_get(obj);
1421    if (!sd) return NULL;  // safety
1422    if (!evas_object_type_get(obj)) return NULL;  // safety
1423    if (strcmp(evas_object_type_get(obj), "e_fm")) return NULL;  // safety
1424    EINA_LIST_FOREACH(sd->icons, l, ic)
1425      {
1426         list = eina_list_append(list, &(ic->info));
1427      }
1428    return list;
1429 }
1430
1431 EAPI void
1432 e_fm2_select_set(Evas_Object *obj, const char *file, int select)
1433 {
1434    E_Fm2_Smart_Data *sd;
1435    Eina_List *l;
1436    E_Fm2_Icon *ic;
1437
1438    sd = evas_object_smart_data_get(obj);
1439    if (!sd) return;  // safety
1440    if (!evas_object_type_get(obj)) return;  // safety
1441    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1442    EINA_LIST_FOREACH(sd->icons, l, ic)
1443      {
1444         if ((file) && (!strcmp(ic->info.file, file)))
1445           {
1446              if (select) _e_fm2_icon_select(ic);
1447              else _e_fm2_icon_deselect(ic);
1448           }
1449         else
1450           {
1451              if (ic->sd->config->selection.single)
1452                _e_fm2_icon_deselect(ic);
1453              ic->last_selected = EINA_FALSE;
1454           }
1455      }
1456 }
1457
1458 EAPI void
1459 e_fm2_file_show(Evas_Object *obj, const char *file)
1460 {
1461    E_Fm2_Smart_Data *sd;
1462    Eina_List *l;
1463    E_Fm2_Icon *ic;
1464
1465    sd = evas_object_smart_data_get(obj);
1466    if (!sd) return;  // safety
1467    if (!evas_object_type_get(obj)) return;  // safety
1468    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1469    EINA_LIST_FOREACH(sd->icons, l, ic)
1470      {
1471         if (!strcmp(ic->info.file, file))
1472           {
1473              _e_fm2_icon_make_visible(ic);
1474              return;
1475           }
1476      }
1477 }
1478
1479 EAPI void
1480 e_fm2_icon_menu_replace_callback_set(Evas_Object *obj, E_Fm_Cb func, void *data)
1481 {
1482    E_Fm2_Smart_Data *sd;
1483
1484    sd = evas_object_smart_data_get(obj);
1485    if (!sd) return;  // safety
1486    if (!evas_object_type_get(obj)) return;  // safety
1487    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1488    sd->icon_menu.replace.func = func;
1489    sd->icon_menu.replace.data = data;
1490 }
1491
1492 EAPI void
1493 e_fm2_icon_menu_start_extend_callback_set(Evas_Object *obj, E_Fm_Cb func, void *data)
1494 {
1495    E_Fm2_Smart_Data *sd;
1496
1497    sd = evas_object_smart_data_get(obj);
1498    if (!sd) return;  // safety
1499    if (!evas_object_type_get(obj)) return;  // safety
1500    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1501    sd->icon_menu.start.func = func;
1502    sd->icon_menu.start.data = data;
1503 }
1504
1505 EAPI void
1506 e_fm2_icon_menu_end_extend_callback_set(Evas_Object *obj, E_Fm_Cb func, void *data)
1507 {
1508    E_Fm2_Smart_Data *sd;
1509
1510    sd = evas_object_smart_data_get(obj);
1511    if (!sd) return;  // safety
1512    if (!evas_object_type_get(obj)) return;  // safety
1513    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1514    sd->icon_menu.end.func = func;
1515    sd->icon_menu.end.data = data;
1516 }
1517
1518 EAPI void
1519 e_fm2_icon_menu_flags_set(Evas_Object *obj, E_Fm2_Menu_Flags flags)
1520 {
1521    E_Fm2_Smart_Data *sd;
1522
1523    sd = evas_object_smart_data_get(obj);
1524    if (!sd) return;  // safety
1525    if (!evas_object_type_get(obj)) return;  // safety
1526    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1527    sd->icon_menu.flags = flags;
1528 }
1529
1530 EAPI E_Fm2_Menu_Flags
1531 e_fm2_icon_menu_flags_get(Evas_Object *obj)
1532 {
1533    E_Fm2_Smart_Data *sd;
1534
1535    sd = evas_object_smart_data_get(obj);
1536    if (!sd) return 0;  // safety
1537    if (!evas_object_type_get(obj)) return 0;  // safety
1538    if (strcmp(evas_object_type_get(obj), "e_fm")) return 0;  // safety
1539    return sd->icon_menu.flags;
1540 }
1541
1542 EAPI void
1543 e_fm2_view_flags_set(Evas_Object *obj, E_Fm2_View_Flags flags)
1544 {
1545    E_Fm2_Smart_Data *sd = evas_object_smart_data_get(obj);
1546    if (!sd) return;  // safety
1547    if (!evas_object_type_get(obj)) return;  // safety
1548    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1549    sd->view_flags = flags;
1550 }
1551
1552 EAPI E_Fm2_View_Flags
1553 e_fm2_view_flags_get(Evas_Object *obj)
1554 {
1555    E_Fm2_Smart_Data *sd = evas_object_smart_data_get(obj);
1556    if (!sd) return 0;  // safety
1557    if (!evas_object_type_get(obj)) return 0;  // safety
1558    if (strcmp(evas_object_type_get(obj), "e_fm")) return 0;  // safety
1559    return sd->view_flags;
1560 }
1561
1562 EAPI void
1563 e_fm2_window_object_set(Evas_Object *obj, E_Object *eobj)
1564 {
1565    E_Fm2_Smart_Data *sd;
1566    const char *drop[] = { "enlightenment/desktop", "enlightenment/border", "text/uri-list" };
1567
1568    sd = evas_object_smart_data_get(obj);
1569    if (!sd) return;  // safety
1570    if (!evas_object_type_get(obj)) return;  // safety
1571    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1572    sd->eobj = eobj;
1573    if (sd->drop_handler) e_drop_handler_del(sd->drop_handler);
1574    sd->drop_handler = e_drop_handler_add(sd->eobj,
1575                                          sd,
1576                                          _e_fm2_cb_dnd_enter,
1577                                          _e_fm2_cb_dnd_move,
1578                                          _e_fm2_cb_dnd_leave,
1579                                          _e_fm2_cb_dnd_drop,
1580                                          drop, 3,
1581                                          sd->x, sd->y, sd->w, sd->h);
1582    e_drop_handler_responsive_set(sd->drop_handler);
1583 }
1584
1585 EAPI void
1586 e_fm2_icons_update(Evas_Object *obj)
1587 {
1588    E_Fm2_Smart_Data *sd;
1589    Eina_List *l;
1590    E_Fm2_Icon *ic;
1591    char buf[PATH_MAX], *pfile;
1592    int bufused, buffree;
1593
1594    sd = evas_object_smart_data_get(obj);
1595    if (!sd) return;  // safety
1596    if (!evas_object_type_get(obj)) return;  // safety
1597    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1598
1599    bufused = eina_strlcpy(buf, sd->realpath, sizeof(buf));
1600    if (bufused >= (int)(sizeof(buf) - 2))
1601      return;
1602
1603    if ((bufused > 0) && (buf[bufused - 1] != '/'))
1604      {
1605         buf[bufused] = '/';
1606         bufused++;
1607      }
1608
1609    pfile = buf + bufused;
1610    buffree = sizeof(buf) - bufused;
1611
1612    EINA_LIST_FOREACH(sd->icons, l, ic)
1613      {
1614         E_Fm2_Custom_File *cf;
1615
1616         eina_stringshare_del(ic->info.icon);
1617         ic->info.icon = NULL;
1618         ic->info.icon_type = EINA_FALSE;
1619
1620         if (_e_fm2_file_is_desktop(ic->info.file))
1621           _e_fm2_icon_desktop_load(ic);
1622
1623         if ((int)eina_strlcpy(pfile, ic->info.file, buffree) >= buffree)
1624           continue;
1625
1626         cf = e_fm2_custom_file_get(buf);
1627         if (cf)
1628           {
1629              if (cf->icon.valid)
1630                {
1631                   eina_stringshare_replace(&ic->info.icon, cf->icon.icon);
1632                   ic->info.icon_type = cf->icon.type;
1633                }
1634           }
1635
1636         if (ic->realized)
1637           {
1638              _e_fm2_icon_unrealize(ic);
1639              _e_fm2_icon_realize(ic);
1640           }
1641      }
1642    e_fm2_custom_file_flush();
1643 }
1644
1645 EAPI void
1646 e_fm2_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1647 {
1648    E_Fm2_Smart_Data *sd;
1649
1650    sd = evas_object_smart_data_get(obj);
1651    if (!sd) return;  // safety
1652    if (!evas_object_type_get(obj)) return;  // safety
1653    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1654    if (x > (sd->max.w - sd->w)) x = sd->max.w - sd->w;
1655    if (x < 0) x = 0;
1656    if (y > (sd->max.h - sd->h)) y = sd->max.h - sd->h;
1657    if (y < 0) y = 0;
1658    if ((sd->pos.x == x) && (sd->pos.y == y)) return;
1659    sd->pos.x = x;
1660    sd->pos.y = y;
1661    if (sd->scroll_job) ecore_job_del(sd->scroll_job);
1662    sd->scroll_job = ecore_job_add(_e_fm2_cb_scroll_job, obj);
1663 }
1664
1665 EAPI void
1666 e_fm2_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1667 {
1668    E_Fm2_Smart_Data *sd;
1669
1670    sd = evas_object_smart_data_get(obj);
1671    if (!sd) return;  // safety
1672    if (!evas_object_type_get(obj)) return;  // safety
1673    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1674    if (x) *x = sd->pos.x;
1675    if (y) *y = sd->pos.y;
1676 }
1677
1678 EAPI void
1679 e_fm2_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1680 {
1681    E_Fm2_Smart_Data *sd;
1682    Evas_Coord mx, my;
1683
1684    sd = evas_object_smart_data_get(obj);
1685    if (!sd) return;  // safety
1686    if (!evas_object_type_get(obj)) return;  // safety
1687    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1688    mx = sd->max.w - sd->w;
1689    if (mx < 0) mx = 0;
1690    my = sd->max.h - sd->h;
1691    if (my < 0) my = 0;
1692    if (x) *x = mx;
1693    if (y) *y = my;
1694 }
1695
1696 EAPI void
1697 e_fm2_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
1698 {
1699    E_Fm2_Smart_Data *sd;
1700
1701    sd = evas_object_smart_data_get(obj);
1702    if (!sd) return;  // safety
1703    if (!evas_object_type_get(obj)) return;  // safety
1704    if (strcmp(evas_object_type_get(obj), "e_fm")) return;  // safety
1705    if (w) *w = sd->max.w;
1706    if (h) *h = sd->max.h;
1707 }
1708
1709 EAPI void
1710 e_fm2_all_icons_update(void)
1711 {
1712    Evas_Object *o;
1713    const Eina_List *l;
1714
1715    _e_fm2_list_walking++;
1716    EINA_LIST_FOREACH(_e_fm2_list, l, o)
1717      {
1718         if ((_e_fm2_list_walking > 0) &&
1719             (eina_list_data_find(_e_fm2_list_remove, o))) continue;
1720         e_fm2_icons_update(o);
1721      }
1722    _e_fm2_list_walking--;
1723    if (_e_fm2_list_walking == 0)
1724      {
1725         EINA_LIST_FREE(_e_fm2_list_remove, o)
1726           {
1727              _e_fm2_list = eina_list_remove(_e_fm2_list, o);
1728           }
1729      }
1730 }
1731
1732 static const char *
1733 _e_fm2_path_join(char *buf, int buflen, const char *base, const char *component)
1734 {
1735    if ((!buf) || (!component))
1736      return NULL;
1737
1738    if (component[0] == '/')
1739      return component;
1740    else if (component[0] == '\0')
1741      return base;
1742    else if (component[0] == '.')
1743      {
1744         if (component[1] == '/')
1745           {
1746              component += 2;
1747
1748              if (!base)
1749                return component;
1750
1751              if (snprintf(buf, buflen, "%s/%s", base, component) < buflen)
1752                return buf;
1753              else
1754                return NULL;
1755           }
1756         else if ((component[1] == '.') && (component[2] == '/'))
1757           {
1758              const char *p;
1759              int len;
1760
1761              component += 3;
1762
1763              if (!base)
1764                return component;
1765
1766              p = strrchr(base, '/');
1767              if (!p)
1768                return component;
1769
1770              len = p - base;
1771              if (snprintf(buf, buflen, "%.*s/%s", len, base, component) < buflen)
1772                return buf;
1773              else
1774                return NULL;
1775           }
1776      }
1777
1778    if (snprintf(buf, buflen, "%s/%s", base, component) < buflen)
1779      return buf;
1780    else
1781      return NULL;
1782 }
1783
1784 /**
1785  * Explicitly set an Edje icon from the given icon path.
1786  *
1787  * @param iconpath path to edje file that contains 'icon' group.
1788  *
1789  * @see _e_fm2_icon_explicit_get()
1790  */
1791 static Evas_Object *
1792 _e_fm2_icon_explicit_edje_get(Evas *evas, const E_Fm2_Icon *ic __UNUSED__, const char *iconpath, const char **type_ret)
1793 {
1794    Evas_Object *o = edje_object_add(evas);
1795    if (!o)
1796      return NULL;
1797
1798    if (!edje_object_file_set(o, iconpath, "icon"))
1799      {
1800         evas_object_del(o);
1801         return NULL;
1802      }
1803
1804    if (type_ret) *type_ret = "CUSTOM";
1805    return o;
1806 }
1807
1808 /**
1809  * Explicitly set icon from theme using its name.
1810  *
1811  * @param name will be prefixed by 'e/icons/' to form the group name in theme.
1812  *
1813  * @see e_util_edje_icon_set()
1814  * @see _e_fm2_icon_explicit_get()
1815  */
1816 static Evas_Object *
1817 _e_fm2_icon_explicit_theme_icon_get(Evas *evas, const E_Fm2_Icon *ic __UNUSED__, const char *name, const char **type_ret)
1818 {
1819    Evas_Object *o = e_icon_add(evas);
1820
1821    if (!o) return NULL;
1822
1823    e_icon_scale_size_set(o, _e_fm2_icon_mime_size_normalize(ic)); 
1824
1825    if (!e_util_icon_theme_set(o, name))
1826      {
1827         evas_object_del(o);
1828         return NULL;
1829      }
1830
1831    if (type_ret) *type_ret = "THEME_ICON";
1832    return o;
1833 }
1834
1835 /**
1836  * Explicitly set icon from file manager theem using its name.
1837  *
1838  * @param name will be prefixed with 'base/theme/fileman' to form the
1839  *    group name in theme.
1840  *
1841  * @see _e_fm2_theme_edje_icon_object_set()
1842  * @see _e_fm2_icon_explicit_get()
1843  */
1844 static Evas_Object *
1845 _e_fm2_icon_explicit_theme_get(Evas *evas, const E_Fm2_Icon *ic, const char *name, const char **type_ret)
1846 {
1847    Evas_Object *o = edje_object_add(evas);
1848    if (!o)
1849      return NULL;
1850
1851    if (!_e_fm2_theme_edje_icon_object_set(ic->sd, o, "base/theme/fileman", name))
1852      {
1853         evas_object_del(o);
1854         return NULL;
1855      }
1856
1857    if (type_ret) *type_ret = "THEME";
1858    return o;
1859 }
1860
1861 /**
1862  * Explicitly set icon to given value.
1863  *
1864  * This will try to identify if icon is an edje or regular file or even
1865  * an icon name to get from icon set.
1866  *
1867  * @param icon might be an absolute or relative path, or icon name or edje path.
1868  */
1869 static Evas_Object *
1870 _e_fm2_icon_explicit_get(Evas *evas, const E_Fm2_Icon *ic, const char *icon, const char **type_ret)
1871 {
1872    char buf[PATH_MAX];
1873    const char *iconpath;
1874
1875    iconpath = _e_fm2_path_join(buf, sizeof(buf), ic->sd->realpath, icon);
1876    if (!iconpath)
1877      {
1878         fprintf(stderr, "ERROR: could not create icon \"%s\".\n", icon);
1879         return NULL;
1880      }
1881
1882    if (_e_fm2_file_is_edje(iconpath))
1883      return _e_fm2_icon_explicit_edje_get(evas, ic, iconpath, type_ret);
1884    else
1885      {
1886         Evas_Object *o = e_icon_add(evas);
1887         if (!o)
1888           return NULL;
1889
1890         e_icon_scale_size_set(o, _e_fm2_icon_mime_size_normalize(ic)); 
1891         e_icon_file_set(o, iconpath);
1892         e_icon_fill_inside_set(o, 1);
1893         if (type_ret) *type_ret = "CUSTOM";
1894         return o;
1895      }
1896
1897    return NULL;
1898 }
1899
1900 /**
1901  * Creates an icon that generates a thumbnail if required.
1902  *
1903  * @param group if given, will be used in e_thumb_icon_file_set()
1904  * @param cb function to callback when thumbnail generation is over.
1905  * @param data extra data to give to @p cb
1906  * @param force_gen whenever to force generation of thumbnails, even it exists.
1907  */
1908 static Evas_Object *
1909 _e_fm2_icon_thumb_get(Evas *evas, const E_Fm2_Icon *ic, const char *group, Evas_Smart_Cb cb, void *data, int force_gen, const char **type_ret)
1910 {
1911    Evas_Object *o;
1912    char buf[PATH_MAX];
1913
1914    if (ic->thumb_failed)
1915      return NULL;
1916    
1917    if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
1918      return NULL;
1919
1920    o = e_thumb_icon_add(evas);
1921    if (!o)
1922      return NULL;
1923
1924    e_thumb_icon_file_set(o, buf, group);
1925    e_thumb_icon_size_set(o, 128, 128);
1926
1927    if (cb) evas_object_smart_callback_add(o, "e_thumb_gen", cb, data);
1928
1929    _e_fm2_icon_thumb(ic, o, force_gen);
1930    if (type_ret) *type_ret = "THUMB";
1931    return o;
1932 }
1933
1934 /**
1935  * Generates the thumbnail of the given edje file.
1936  *
1937  * It will use 'icon.key_hint' from config if set and then try some well
1938  * known groups like 'icon', 'e/desktop/background' and 'e/init/splash'.
1939  */
1940 static Evas_Object *
1941 _e_fm2_icon_thumb_edje_get(Evas *evas, const E_Fm2_Icon *ic, Evas_Smart_Cb cb, void *data, int force_gen, const char **type_ret)
1942 {
1943    char buf[PATH_MAX];
1944    const char **itr, *group;
1945    const char *known_groups[] = {
1946       NULL,
1947       "icon",
1948       "e/desktop/background",
1949       "e/init/splash",
1950       /* XXX TODO: add more? example 'screenshot', 'preview' */
1951       NULL
1952    };
1953
1954    if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
1955      return NULL;
1956
1957    known_groups[0] = ic->sd->config->icon.key_hint;
1958    if (known_groups[0])
1959      itr = known_groups;
1960    else
1961      itr = known_groups + 1;
1962
1963    for (; *itr; itr++)
1964      if (edje_file_group_exists(buf, *itr))
1965        break;
1966
1967    if (*itr)
1968      group = *itr;
1969    else
1970      {
1971         Eina_List *l = edje_file_collection_list(buf);
1972         if (!l)
1973           return NULL;
1974         group = eina_list_data_get(l);
1975         edje_file_collection_list_free(l);
1976      }
1977
1978    return _e_fm2_icon_thumb_get(evas, ic, group, cb, data, force_gen, type_ret);
1979 }
1980
1981 /**
1982  * Machinery for _e_fm2_icon_desktop_get() and others with instances of desktop.
1983  */
1984 static Evas_Object *
1985 _e_fm2_icon_desktop_get_internal(Evas *evas, const E_Fm2_Icon *ic, Efreet_Desktop *desktop, const char **type_ret)
1986 {
1987    Evas_Object *o;
1988
1989    if (!desktop->icon)
1990      return NULL;
1991
1992    if (_e_fm2_file_is_edje(desktop->icon))
1993      return _e_fm2_icon_explicit_edje_get(evas, ic, desktop->icon, type_ret);
1994
1995    o = _e_fm2_icon_explicit_theme_icon_get(evas, ic, desktop->icon, type_ret);
1996    if (o) return o;
1997
1998    o = e_util_desktop_icon_add(desktop, 48, evas);
1999 //   o = e_util_icon_theme_icon_add(desktop->icon, 48, evas);
2000    if (o && type_ret) *type_ret = "DESKTOP";
2001    return o;
2002 }
2003
2004 /**
2005  * Use freedesktop.org '.desktop' files to set icon.
2006  */
2007 static Evas_Object *
2008 _e_fm2_icon_desktop_get(Evas *evas, const E_Fm2_Icon *ic, const char **type_ret)
2009 {
2010    Efreet_Desktop *ef;
2011    Evas_Object *o;
2012    char buf[PATH_MAX];
2013
2014    if (!ic->info.file) return NULL;
2015
2016    if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
2017      return NULL;
2018
2019    ef = efreet_desktop_new(buf);
2020    if (!ef) return NULL;
2021
2022    o = _e_fm2_icon_desktop_get_internal(evas, ic, ef, type_ret);
2023    efreet_desktop_free(ef);
2024    return o;
2025 }
2026
2027 static inline const char *
2028 _e_fm2_icon_mime_type_special_match(const E_Fm2_Icon *ic)
2029 {
2030    const Eina_List *l;
2031    const E_Config_Mime_Icon *mi;
2032    const char *mime = ic->info.mime;
2033
2034    EINA_LIST_FOREACH(e_config->mime_icons, l, mi)
2035      if (mi->mime == mime) /* both in the same stringshare pool */
2036        return mi->icon;
2037
2038    return NULL;
2039 }
2040
2041 static Evas_Object *
2042 _e_fm2_icon_mime_fdo_get(Evas *evas, const E_Fm2_Icon *ic, const char **type_ret)
2043 {
2044    const char *icon;
2045    unsigned int size;
2046
2047    size = _e_fm2_icon_mime_size_normalize(ic);
2048    icon = efreet_mime_type_icon_get(ic->info.mime, e_config->icon_theme, size);
2049    if (icon)
2050       return _e_fm2_icon_explicit_get(evas, ic, icon, type_ret);
2051    return NULL;
2052 }
2053
2054 static Evas_Object *
2055 _e_fm2_icon_mime_theme_get(Evas *evas, const E_Fm2_Icon *ic, const char **type_ret __UNUSED__)
2056 {
2057    char buf[1024];
2058    const char *file;
2059
2060    if (snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", ic->info.mime) >= 
2061        (int)sizeof(buf))
2062      return NULL;
2063
2064    file = e_theme_edje_file_get("base/theme/icons", buf);
2065    if (file && file[0])
2066      {
2067         Evas_Object *o = edje_object_add(evas);
2068         if (!o) return NULL;
2069         if (!edje_object_file_set(o, file, buf))
2070           {
2071              evas_object_del(o);
2072              return NULL;
2073           }
2074         return o;
2075      }
2076
2077    return NULL;
2078 }
2079
2080 /**
2081  * Use mime type information to set icon.
2082  */
2083 static Evas_Object *
2084 _e_fm2_icon_mime_get(Evas *evas, const E_Fm2_Icon *ic, Evas_Smart_Cb gen_func __UNUSED__, void *data __UNUSED__, int force_gen __UNUSED__, const char **type_ret)
2085 {
2086    Evas_Object *o = NULL;
2087
2088    if (e_config->icon_theme_overrides)
2089      o = _e_fm2_icon_mime_fdo_get(evas, ic, type_ret);
2090    else
2091      o = _e_fm2_icon_mime_theme_get(evas, ic, type_ret);
2092
2093    if (o) return o;
2094
2095    if (!e_config->icon_theme_overrides)
2096      o = _e_fm2_icon_mime_fdo_get(evas, ic, type_ret);
2097    else
2098      o = _e_fm2_icon_mime_theme_get(evas, ic, type_ret);
2099
2100    return o;
2101 }
2102
2103 /**
2104  * Discovers the executable of Input Method Config file and set icon.
2105  */
2106 static Evas_Object *
2107 _e_fm2_icon_imc_get(Evas *evas, const E_Fm2_Icon *ic, const char **type_ret)
2108 {
2109    E_Input_Method_Config *imc;
2110    Efreet_Desktop *desktop;
2111    Eet_File *imc_ef;
2112    Evas_Object *o = NULL;
2113    char buf[PATH_MAX];
2114
2115    if (!ic->info.file)
2116      return NULL;
2117
2118    if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
2119      return NULL;
2120
2121    imc_ef = eet_open(buf, EET_FILE_MODE_READ);
2122    if (!imc_ef)
2123      return NULL;
2124
2125    imc = e_intl_input_method_config_read(imc_ef);
2126    eet_close(imc_ef);
2127
2128    if (!imc->e_im_setup_exec)
2129      {
2130         e_intl_input_method_config_free(imc);
2131         return NULL;
2132      }
2133
2134    desktop = efreet_util_desktop_exec_find(imc->e_im_setup_exec);
2135    if (desktop)
2136      {
2137         o = _e_fm2_icon_desktop_get_internal(evas, ic, desktop, type_ret);
2138         efreet_desktop_free(desktop);
2139      }
2140    e_intl_input_method_config_free(imc);
2141
2142    if ((o) && (type_ret)) *type_ret = "IMC";
2143    return o;
2144 }
2145
2146 /**
2147  * Use heuristics to discover and set icon.
2148  */
2149 static Evas_Object *
2150 _e_fm2_icon_discover_get(Evas *evas, const E_Fm2_Icon *ic, Evas_Smart_Cb gen_func, void *data, int force_gen, const char **type_ret)
2151 {
2152    const char *p;
2153
2154    p = strrchr(ic->info.file, '.');
2155    if (!p) return NULL;
2156
2157    p++;
2158    if (_e_fm2_ext_is_edje(p))
2159      return _e_fm2_icon_thumb_edje_get(evas, ic, gen_func,
2160                                        data, force_gen, type_ret);
2161    else if (_e_fm2_ext_is_desktop(p))
2162      return _e_fm2_icon_desktop_get(evas, ic, type_ret);
2163    else if (_e_fm2_ext_is_imc(p))
2164      return _e_fm2_icon_imc_get(evas, ic, type_ret);
2165    return NULL;
2166 }
2167
2168 /**
2169  * Get the object representing the icon.
2170  *
2171  * @param evas canvas instance to use to store the icon.
2172  * @param ic icon to get information in order to find the icon.
2173  * @param gen_func if thumbnails need to be generated, call this function
2174  *     when it's over.
2175  * @param data extra data to give to @p gen_func.
2176  * @param force_gen force thumbnail generation.
2177  * @param type_ret string that identifies type of icon.
2178  */
2179 EAPI Evas_Object *
2180 e_fm2_icon_get(Evas *evas, E_Fm2_Icon *ic,
2181                Evas_Smart_Cb gen_func,
2182                void *data, int force_gen, const char **type_ret)
2183 {
2184    const char *icon;
2185    Evas_Object *o = NULL;
2186    
2187    if (ic->info.icon)
2188      {
2189         if ((ic->info.icon[0] == '/') ||
2190             ((ic->info.icon[0] == '.') &&
2191              ((ic->info.icon[1] == '/') ||
2192               ((ic->info.icon[1] == '.') && (ic->info.icon[2] == '/')))))
2193           {
2194              o = _e_fm2_icon_explicit_get(evas, ic, ic->info.icon, type_ret);
2195              if (o) return o;
2196           }
2197
2198         o = _e_fm2_icon_explicit_theme_icon_get(evas, ic, ic->info.icon, type_ret);
2199         if (o) return o;
2200      }
2201
2202    /* create thumbnails for edje files */
2203    if (_e_fm2_file_is_edje(ic->info.file))
2204      {
2205         o = _e_fm2_icon_thumb_edje_get
2206           (evas, ic, gen_func, data, force_gen, type_ret);
2207         if (o) return o;
2208      }
2209
2210    /* disabled until everyone has edje in mime.types:
2211     *  use mimetype to identify edje.
2212     * if (ic->info.mime == _e_fm2_mime_app_edje)
2213     *   return _e_fm2_icon_thumb_edje_get
2214     *     (evas, ic, gen_func, data, force_gen, type_ret); */
2215
2216    /* check user preferences */
2217    icon = _e_fm2_icon_mime_type_special_match(ic);
2218    if (icon)
2219      {
2220         if (icon == _e_fm2_icon_desktop_str)
2221           o = _e_fm2_icon_desktop_get(evas, ic, type_ret);
2222         else if (icon == _e_fm2_icon_thumb_str)
2223           {
2224              if (!ic->thumb_failed)
2225                o = _e_fm2_icon_thumb_get
2226                  (evas, ic, NULL, gen_func, data, force_gen, type_ret);
2227           }
2228         else if (strncmp(icon, "e/icons/fileman/", 16) == 0)
2229           o = _e_fm2_icon_explicit_theme_get(evas, ic, icon + 16, type_ret);
2230         else
2231           o = _e_fm2_icon_explicit_get(evas, ic, icon, type_ret);
2232
2233         if (o) return o;
2234      }
2235
2236    if ((!ic->thumb_failed) && (ic->info.icon_type == 1))
2237      {
2238         o = _e_fm2_icon_thumb_get(evas, ic, NULL,
2239                                   gen_func, data, force_gen, type_ret);
2240         if (o) return o;
2241      }
2242
2243    if (ic->info.mime)
2244      {
2245         o = _e_fm2_icon_mime_get(evas, ic, gen_func, data, force_gen, type_ret);
2246         if (o) return o;
2247      }
2248    else if (ic->info.file)
2249      {
2250         o = _e_fm2_icon_discover_get(evas, ic, gen_func, data,
2251                                      force_gen, type_ret);
2252         if (o) return o;
2253      }
2254
2255 //fallback:
2256    o = _e_fm2_icon_explicit_theme_icon_get(evas, ic, "unknown", type_ret);
2257    if (o) return o;
2258    
2259    return _e_fm2_icon_explicit_theme_get(evas, ic, "text/plain", type_ret);
2260 }
2261
2262 EAPI E_Fm2_Icon_Info *
2263 e_fm2_icon_file_info_get(E_Fm2_Icon *ic)
2264 {
2265    if (!ic) return NULL;
2266    return &(ic->info);
2267 }
2268
2269 EAPI void
2270 e_fm2_icon_geometry_get(E_Fm2_Icon *ic, int *x, int *y, int *w, int *h)
2271 {
2272    int xx, yy, ww, hh;
2273
2274    if (x) *x = 0; if (y) *y = 0; if (w) *w = 0; if (h) *h = 0;
2275    if (ic)
2276      {
2277         evas_object_geometry_get(ic->obj, &xx, &yy, &ww, &hh);
2278         if (x) *x = xx;
2279         if (y) *y = yy;
2280         if (w) *w = ww;
2281         if (h) *h = hh;
2282      }
2283 }
2284
2285 /* FIXME: track real exe with exe del events etc. */
2286 static int _e_fm2_client_spawning = 0;
2287
2288 static void
2289 _e_fm2_client_spawn(void)
2290 {
2291    char buf[4096];
2292
2293    if (_e_fm2_client_spawning) return;
2294    snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_fm", e_prefix_lib_get());
2295    ecore_exe_run(buf, NULL);
2296    _e_fm2_client_spawning = 1;
2297 }
2298
2299 static E_Fm2_Client *
2300 _e_fm2_client_get(void)
2301 {
2302    Eina_List *l;
2303    E_Fm2_Client *cl, *cl_chosen = NULL;
2304    int min_req = 0x7fffffff;
2305
2306    /* if we don't have a slave - spane one */
2307    if (!_e_fm2_client_list)
2308      {
2309         _e_fm2_client_spawn();
2310         return NULL;
2311      }
2312    EINA_LIST_FOREACH(_e_fm2_client_list, l, cl)
2313      {
2314         if (cl->req < min_req)
2315           {
2316              min_req = cl->req;
2317              cl_chosen = cl;
2318           }
2319      }
2320    return cl_chosen;
2321 }
2322
2323 typedef struct _E_Fm2_Message E_Fm2_Message;
2324
2325 struct _E_Fm2_Message
2326 {
2327    int   major, minor, ref, ref_to, response;
2328    void *data;
2329    int   size;
2330 };
2331
2332 static Eina_List *_e_fm2_messages = NULL;
2333
2334 static void
2335 _e_fm2_client_message_queue(int major, int minor, int ref, int ref_to, int response, const void *data, int size)
2336 {
2337    E_Fm2_Message *msg;
2338
2339    msg = E_NEW(E_Fm2_Message, 1);
2340    if (!msg) return;
2341    msg->major = major;
2342    msg->minor = minor;
2343    msg->ref = ref;
2344    msg->ref_to = ref_to;
2345    msg->response = response;
2346    if (data)
2347      {
2348         msg->size = size;
2349         msg->data = malloc(size);
2350         if (msg->data)
2351           memcpy(msg->data, data, size);
2352         else
2353           {
2354              free(msg);
2355              return;
2356           }
2357      }
2358    _e_fm2_messages = eina_list_append(_e_fm2_messages, msg);
2359 }
2360
2361 static void
2362 _e_fm2_client_message_flush(E_Fm2_Client *cl, E_Fm2_Message *msg)
2363 {
2364    _e_fm2_messages = eina_list_remove(_e_fm2_messages, msg);
2365    ecore_ipc_client_send(cl->cl, msg->major, msg->minor,
2366                          msg->ref, msg->ref_to, msg->response,
2367                          msg->data, msg->size);
2368    cl->req++;
2369    free(msg->data);
2370    free(msg);
2371 }
2372
2373 static void
2374 _e_fm2_client_messages_flush(void)
2375 {
2376    while (_e_fm2_messages)
2377      {
2378         E_Fm2_Client *cl;
2379
2380         cl = _e_fm2_client_get();
2381         if (!cl) break;
2382         _e_fm2_client_message_flush(cl, eina_list_data_get(_e_fm2_messages));
2383      }
2384 }
2385
2386 static int
2387 _e_fm_client_send_new(int minor, void *data, int size)
2388 {
2389    static int id = 0;
2390    E_Fm2_Client *cl;
2391
2392    id++;
2393    cl = _e_fm2_client_get();
2394    if (!cl)
2395      {
2396         _e_fm2_client_message_queue(E_IPC_DOMAIN_FM, minor,
2397                                     id, 0, 0,
2398                                     data, size);
2399      }
2400    else
2401      {
2402         ecore_ipc_client_send(cl->cl, E_IPC_DOMAIN_FM, minor,
2403                               id, 0, 0,
2404                               data, size);
2405         cl->req++;
2406      }
2407
2408    return id;
2409 }
2410
2411 static int
2412 _e_fm_client_send(int minor, int id, void *data, int size)
2413 {
2414    E_Fm2_Client *cl;
2415
2416    cl = _e_fm2_client_get();
2417    if (!cl)
2418      {
2419         _e_fm2_client_message_queue(E_IPC_DOMAIN_FM, minor,
2420                                     id, 0, 0,
2421                                     data, size);
2422      }
2423    else
2424      {
2425         ecore_ipc_client_send(cl->cl, E_IPC_DOMAIN_FM, minor,
2426                               id, 0, 0,
2427                               data, size);
2428         cl->req++;
2429      }
2430
2431    return id;
2432 }
2433
2434 static int
2435 _e_fm2_client_monitor_add(const char *path)
2436 {
2437    return _e_fm_client_send_new(E_FM_OP_MONITOR_START, (void *)path, strlen(path) + 1);
2438 }
2439
2440 static void
2441 _e_fm2_client_monitor_del(int id, const char *path)
2442 {
2443    _e_fm_client_send(E_FM_OP_MONITOR_END, id, (void *)path, strlen(path) + 1);
2444 }
2445
2446 static int
2447 _e_fm_client_file_del(const char *files, Evas_Object *e_fm)
2448 {
2449    int id = _e_fm_client_send_new(E_FM_OP_REMOVE, (void *)files, strlen(files) + 1);
2450    e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_REMOVE, _e_fm2_operation_abort_internal);
2451    return id;
2452 }
2453
2454 #if 0
2455 static int
2456 _e_fm2_client_file_trash(const char *path, Evas_Object *e_fm)
2457 {
2458    int id = _e_fm_client_send_new(E_FM_OP_TRASH, (void *)path, strlen(path) + 1);
2459    e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_TRASH, _e_fm2_operation_abort_internal);
2460    return id;
2461 }
2462
2463 #endif
2464
2465 static int
2466 _e_fm2_client_file_mkdir(const char *path, const char *rel, int rel_to, int x, int y, int res_w __UNUSED__, int res_h __UNUSED__, Evas_Object *e_fm)
2467 {
2468    char *d;
2469    int l1, l2, l, id;
2470
2471    l1 = strlen(path);
2472    l2 = strlen(rel);
2473    l = l1 + 1 + l2 + 1 + (sizeof(int) * 3);
2474    d = alloca(l);
2475    strcpy(d, path);
2476    strcpy(d + l1 + 1, rel);
2477    memcpy(d + l1 + 1 + l2 + 1, &rel_to, sizeof(int));
2478    memcpy(d + l1 + 1 + l2 + 1 + sizeof(int), &x, sizeof(int));
2479    memcpy(d + l1 + 1 + l2 + 1 + (2 * sizeof(int)), &y, sizeof(int));
2480
2481    id = _e_fm_client_send_new(E_FM_OP_MKDIR, (void *)d, l);
2482    e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_MKDIR, _e_fm2_operation_abort_internal);
2483    return id;
2484 }
2485
2486 static int
2487 _e_fm_client_file_move(const char *args, Evas_Object *e_fm)
2488 {
2489    int id = _e_fm_client_send_new(E_FM_OP_MOVE, (void *)args, strlen(args) + 1);
2490    e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_MOVE, _e_fm2_operation_abort_internal);
2491    return id;
2492 }
2493
2494 static int
2495 _e_fm2_client_file_symlink(const char *path, const char *dest, const char *rel, int rel_to, int x, int y, int res_w, int res_h, Evas_Object *e_fm)
2496 {
2497 #if 0
2498    char *d;
2499    int l1, l2, l3, l, id;
2500
2501    l1 = strlen(path);
2502    l2 = strlen(dest);
2503    l3 = strlen(rel);
2504    l = l1 + 1 + l2 + 1 + l3 + 1 + (sizeof(int) * 3);
2505    d = alloca(l);
2506    strcpy(d, path);
2507    strcpy(d + l1 + 1, dest);
2508    strcpy(d + l1 + 1 + l2 + 1, rel);
2509    memcpy(d + l1 + 1 + l2 + 1 + l3 + 1, &rel_to, sizeof(int));
2510    memcpy(d + l1 + 1 + l2 + 1 + l3 + 1 + sizeof(int), &x, sizeof(int));
2511    memcpy(d + l1 + 1 + l2 + 1 + l3 + 1 + (2 * sizeof(int)), &y, sizeof(int));
2512
2513    if ((x != -9999) && (y != -9999))
2514      {
2515         E_Fm2_Custom_File *cf, cf0;
2516
2517         cf = e_fm2_custom_file_get(dest);
2518         if (!cf)
2519           {
2520              memset(&cf0, 0, sizeof(E_Fm2_Custom_File));
2521              cf = &cf0;
2522           }
2523         cf->geom.x = x;
2524         cf->geom.y = y;
2525         cf->geom.res_w = res_w;
2526         cf->geom.res_h = res_h;
2527         cf->geom.valid = 1;
2528         e_fm2_custom_file_set(dest, cf);
2529         e_fm2_custom_file_flush();
2530      }
2531
2532    id = _e_fm_client_send_new(E_FM_OP_SYMLINK, (void *)d, l);
2533    e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_SYMLINK, _e_fm2_operation_abort_internal);
2534    return id;
2535 #else
2536    char *args = NULL;
2537    size_t size = 0, length = 0;
2538
2539    args = _e_fm_string_append_quoted(args, &size, &length, path);
2540    args = _e_fm_string_append_char(args, &size, &length, ' ');
2541    args = _e_fm_string_append_quoted(args, &size, &length, dest);
2542
2543    fputs("WARNING: using new E_FM_OP_SYMLINK, remove deprecated ASAP\n", stderr);
2544    int r = _e_fm_client_file_symlink(args, e_fm);
2545    free(args);
2546    return r;
2547 #endif
2548    rel = NULL;
2549    rel_to = 0;
2550    x = 0;
2551    y= 0;
2552    res_w = 0;
2553    res_h = 0;
2554 }
2555
2556 static int
2557 _e_fm_client_file_copy(const char *args, Evas_Object *e_fm)
2558 {
2559    int id = _e_fm_client_send_new(E_FM_OP_COPY, (void *)args, strlen(args) + 1);
2560    e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_COPY, _e_fm2_operation_abort_internal);
2561    return id;
2562 }
2563
2564 static int
2565 _e_fm_client_file_symlink(const char *args, Evas_Object *e_fm)
2566 {
2567    int id = _e_fm_client_send_new(E_FM_OP_SYMLINK, (void *)args, strlen(args) + 1);
2568    e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_SYMLINK, _e_fm2_operation_abort_internal);
2569    return id;
2570 }
2571
2572 EAPI int
2573 _e_fm2_client_mount(const char *udi, const char *mountpoint)
2574 {
2575    char *d;
2576    int l, l1, l2 = 0;
2577
2578    if (!udi)
2579      return 0;
2580
2581    l1 = strlen(udi);
2582    if (mountpoint)
2583      {
2584         l2 = strlen(mountpoint);
2585         l = l1 + 1 + l2 + 1;
2586      }
2587    else
2588      l = l1 + 1;
2589    d = alloca(l);
2590    strcpy(d, udi);
2591    if (mountpoint)
2592      strcpy(d + l1 + 1, mountpoint);
2593
2594    return _e_fm_client_send_new(E_FM_OP_MOUNT, (void *)d, l);
2595 }
2596
2597 EAPI int
2598 _e_fm2_client_unmount(const char *udi)
2599 {
2600    char *d;
2601    int l, l1;
2602
2603    if (!udi)
2604      return 0;
2605
2606    l1 = strlen(udi);
2607    l = l1 + 1;
2608    d = alloca(l);
2609    strcpy(d, udi);
2610
2611    _e_fm2_client_get();
2612
2613    return _e_fm_client_send_new(E_FM_OP_UNMOUNT, (void *)d, l);
2614 }
2615
2616 EAPI int
2617 _e_fm2_client_eject(const char *udi)
2618 {
2619    char *data;
2620    int size;
2621
2622    if (!udi)
2623      return 0;
2624
2625    size = strlen(udi) + 1;
2626    data = alloca(size);
2627    strcpy(data, udi);
2628
2629    return _e_fm_client_send_new(E_FM_OP_EJECT, data, size);
2630 }
2631
2632 static void
2633 _e_fm2_client_monitor_list_end(Evas_Object *obj)
2634 {
2635    E_Fm2_Smart_Data *sd;
2636
2637    sd = evas_object_smart_data_get(obj);
2638    sd->busy_count--;
2639    if (sd->busy_count == 0)
2640      {
2641         edje_object_signal_emit(sd->overlay, "e,state,busy,stop", "e");
2642         e_fm2_custom_file_flush();
2643      }
2644    if (sd->tmp.obj)
2645      {
2646         evas_object_del(sd->tmp.obj);
2647         sd->tmp.obj = NULL;
2648      }
2649    if (sd->tmp.obj2)
2650      {
2651         evas_object_del(sd->tmp.obj2);
2652         sd->tmp.obj2 = NULL;
2653      }
2654    if (sd->scan_timer)
2655      {
2656         ecore_timer_del(sd->scan_timer);
2657         sd->scan_timer = NULL;
2658      }
2659    if (sd->sort_idler)
2660      {
2661         ecore_idler_del(sd->sort_idler);
2662         sd->sort_idler = NULL;
2663      }
2664    E_FREE(sd->tmp.list_index);
2665    _e_fm2_queue_free(obj);
2666    _e_fm2_obj_icons_place(sd);
2667    _e_fm2_live_process_begin(obj);
2668 }
2669
2670 EAPI void
2671 _e_fm2_file_force_update(const char *path)
2672 {
2673    Evas_Object *o;
2674    char *dir;
2675    Eina_List *l;
2676
2677    dir = ecore_file_dir_get(path);
2678    if (!dir) return;
2679    EINA_LIST_FOREACH(_e_fm2_list, l, o)
2680      {
2681         if ((_e_fm2_list_walking > 0) &&
2682             (eina_list_data_find(_e_fm2_list_remove, o))) continue;
2683         if (!strcmp(e_fm2_real_path_get(o), dir))
2684           {
2685              E_Fm2_Icon *ic;
2686
2687              ic = _e_fm2_icon_find(o, ecore_file_file_get(path));
2688              if (ic)
2689                {
2690                   E_Fm2_Finfo finf;
2691
2692                   memset(&finf, 0, sizeof(E_Fm2_Finfo));
2693                   memcpy(&(finf.st), &(ic->info.statinfo),
2694                          sizeof(struct stat));
2695                   finf.broken_link = ic->info.broken_link;
2696                   finf.lnk = ic->info.link;
2697                   finf.rlnk = ic->info.real_link;
2698                   ic->removable_state_change = EINA_TRUE;
2699                   _e_fm2_live_file_changed(o, ecore_file_file_get(path),
2700                                            &finf);
2701                }
2702           }
2703      }
2704    free(dir);
2705 }
2706
2707 EAPI void
2708 e_fm2_client_data(Ecore_Ipc_Event_Client_Data *e)
2709 {
2710    Evas_Object *obj;
2711    Eina_List *l, *dels = NULL;
2712    E_Fm2_Client *cl;
2713
2714    if (e->major != 6 /*E_IPC_DOMAIN_FM*/) return;
2715    EINA_LIST_FOREACH(_e_fm2_client_list, l, cl)
2716      {
2717         if (cl->cl == e->client) break;
2718      }
2719    if (!l)
2720      {
2721         cl = E_NEW(E_Fm2_Client, 1);
2722         cl->cl = e->client;
2723         _e_fm2_client_list = eina_list_prepend(_e_fm2_client_list, cl);
2724         /* FIXME: new client - send queued msgs */
2725         _e_fm2_client_spawning = 0;
2726         _e_fm2_client_messages_flush();
2727      }
2728
2729    _e_fm2_list_walking++;
2730    EINA_LIST_FOREACH(_e_fm2_list, l, obj)
2731      {
2732         unsigned char *p;
2733         char *evdir;
2734         const char *dir, *path, *lnk, *rlnk, *file;
2735         struct stat st;
2736         int broken_link;
2737         E_Fm2_Smart_Data *sd;
2738
2739         if ((_e_fm2_list_walking > 0) &&
2740             (eina_list_data_find(_e_fm2_list_remove, obj))) continue;
2741         dir = e_fm2_real_path_get(obj);
2742         sd = evas_object_smart_data_get(obj);
2743         switch (e->minor)
2744           {
2745            case E_FM_OP_HELLO: /*hello*/
2746 //             printf("E_FM_OP_HELLO\n");
2747              break;
2748
2749            case E_FM_OP_OK: /*req ok*/
2750 //             printf("E_FM_OP_OK\n");
2751              cl->req--;
2752              break;
2753
2754            case E_FM_OP_FILE_ADD: /*file add*/
2755 //             printf("E_FM_OP_FILE_ADD\n");
2756            case E_FM_OP_FILE_CHANGE: /*file change*/
2757 //             printf("E_FM_OP_FILE_CHANGE\n");
2758            {
2759               E_Fm2_Finfo finf;
2760
2761               p = e->data;
2762               /* NOTE: i am NOT converting this data to portable arch/os independent
2763                * format. i am ASSUMING e_fm_main and e are local and built together
2764                * and thus this will work. if this ever changes this here needs to
2765                * change */
2766               memcpy(&st, p, sizeof(struct stat));
2767               p += sizeof(struct stat);
2768
2769               broken_link = p[0];
2770               p += 1;
2771
2772               path = (char *)p;
2773               p += strlen(path) + 1;
2774
2775               lnk = (char *)p;
2776               p += strlen(lnk) + 1;
2777
2778               rlnk = (char *)p;
2779
2780               memcpy(&(finf.st), &st, sizeof(struct stat));
2781               finf.broken_link = broken_link;
2782               finf.lnk = lnk;
2783               finf.rlnk = rlnk;
2784
2785               evdir = ecore_file_dir_get(path);
2786               if ((evdir) && (sd->id == e->ref_to) &&
2787                   ((!strcmp(evdir, "") || ((dir) && (!strcmp(dir, evdir))))))
2788                 {
2789 //                       printf(" ch/add response = %i\n", e->response);
2790                      if (e->response == 0)  /*live changes*/
2791                        {
2792                           if (e->minor == E_FM_OP_FILE_ADD)  /*file add*/
2793                             {
2794                                _e_fm2_live_file_add
2795                                  (obj, ecore_file_file_get(path),
2796                                  NULL, 0, &finf);
2797                             }
2798                           else if (e->minor == E_FM_OP_FILE_CHANGE)  /*file change*/
2799                             {
2800                                _e_fm2_live_file_changed
2801                                  (obj, (char *)ecore_file_file_get(path),
2802                                  &finf);
2803                             }
2804                        }
2805                      else  /*file add - listing*/
2806                        {
2807                           if (e->minor == E_FM_OP_FILE_ADD)  /*file add*/
2808                             {
2809                                if (!sd->scan_timer)
2810                                  {
2811                                     sd->scan_timer =
2812                                       ecore_timer_add(0.5,
2813                                                       _e_fm2_cb_scan_timer,
2814                                                       sd->obj);
2815                                     sd->busy_count++;
2816                                     if (sd->busy_count == 1)
2817                                       edje_object_signal_emit(sd->overlay, "e,state,busy,start", "e");
2818                                  }
2819                                if (path[0] != 0)
2820                                  {
2821                                     file = ecore_file_file_get(path);
2822                                     if ((!strcmp(file, ".order")))
2823                                       sd->order_file = EINA_TRUE;
2824                                     else
2825                                       {
2826                                          if (!((file[0] == '.') &&
2827                                                (!sd->show_hidden_files)))
2828                                            _e_fm2_file_add(obj, file,
2829                                                            sd->order_file,
2830                                                            NULL, 0, &finf);
2831                                       }
2832                                  }
2833                                if (e->response == 2)  /* end of scan */
2834                                  {
2835                                     sd->listing = EINA_FALSE;
2836                                     if (sd->scan_timer)
2837                                       {
2838                                          ecore_timer_del(sd->scan_timer);
2839                                          sd->scan_timer =
2840                                            ecore_timer_add(0.0001,
2841                                                            _e_fm2_cb_scan_timer,
2842                                                            sd->obj);
2843                                       }
2844                                     else
2845                                       {
2846                                          _e_fm2_client_monitor_list_end(obj);
2847                                       }
2848                                  }
2849                             }
2850                        }
2851                 }
2852               else
2853                 {
2854 //                       printf(" ...\n");
2855                      if ((sd->id == e->ref_to) && (path[0] == 0))
2856                        {
2857 //                            printf(" end response = %i\n", e->response);
2858                             if (e->response == 2) /* end of scan */
2859                               {
2860                                  sd->listing = EINA_FALSE;
2861                                  if (sd->scan_timer)
2862                                    {
2863                                       ecore_timer_del(sd->scan_timer);
2864                                       sd->scan_timer =
2865                                         ecore_timer_add(0.0001,
2866                                                         _e_fm2_cb_scan_timer,
2867                                                         sd->obj);
2868                                    }
2869                                  else
2870                                    {
2871                                       _e_fm2_client_monitor_list_end(obj);
2872                                    }
2873                               }
2874                        }
2875                 }
2876               if (evdir) free(evdir);
2877            }
2878            break;
2879
2880            case E_FM_OP_FILE_DEL: /*file del*/
2881 //             printf("E_FM_OP_FILE_DEL\n");
2882              path = e->data;
2883              evdir = ecore_file_dir_get(path);
2884              if ((dir) && (evdir) && (sd->id == e->ref_to) && (!strcmp(dir, evdir)))
2885                {
2886                   _e_fm2_live_file_del
2887                     (obj, ecore_file_file_get(path));
2888                }
2889              if (evdir) free(evdir);
2890              break;
2891
2892            case E_FM_OP_MONITOR_END: /*mon dir del*/
2893 //             printf("E_FM_OP_MONITOR_END\n");
2894              path = e->data;
2895              /* FIXME dir should not be null but can. fix segv
2896                 when mounting cdrom with udisk here
2897                 btw monitor end seems to be a strange event for
2898                 mounting disks.
2899              */
2900              if ((dir) && (path) && (sd->id == e->ref_to) && (!strcmp(dir, path)))
2901                {
2902                   dels = eina_list_append(dels, obj);
2903                }
2904              break;
2905
2906            default:
2907              break;
2908           }
2909      }
2910    EINA_LIST_FREE(dels, obj)
2911      {
2912         E_Fm2_Smart_Data *sd;
2913
2914         sd = evas_object_smart_data_get(obj);
2915         if ((_e_fm2_list_walking > 0) &&
2916             (eina_list_data_find(_e_fm2_list_remove, obj))) continue;
2917         if (sd->config->view.open_dirs_in_place)
2918           _e_fm2_path_parent_set(obj, sd->realpath);
2919         else
2920           evas_object_smart_callback_call(obj, "dir_deleted", NULL);
2921      }
2922    _e_fm2_list_walking--;
2923    if (_e_fm2_list_walking == 0)
2924      {
2925         EINA_LIST_FREE(_e_fm2_list_remove, obj)
2926           {
2927              _e_fm2_list = eina_list_remove(_e_fm2_list, obj);
2928           }
2929      }
2930    switch (e->minor)
2931      {
2932       case E_FM_OP_MONITOR_SYNC:  /*mon list sync*/
2933         ecore_ipc_client_send(cl->cl, E_IPC_DOMAIN_FM, E_FM_OP_MONITOR_SYNC,
2934                               0, 0, e->response,
2935                               NULL, 0);
2936         break;
2937
2938       case E_FM_OP_STORAGE_ADD:  /*storage add*/
2939         if ((e->data) && (e->size > 0))
2940           {
2941              E_Storage *s;
2942
2943              s = _e_fm_shared_codec_storage_decode(e->data, e->size);
2944              if (s) e_fm2_device_storage_add(s);
2945           }
2946         break;
2947
2948       case E_FM_OP_STORAGE_DEL:  /*storage del*/
2949         if ((e->data) && (e->size > 0))
2950           {
2951              char *udi;
2952              E_Storage *s;
2953
2954              udi = e->data;
2955              s = e_fm2_device_storage_find(udi);
2956              if (s) e_fm2_device_storage_del(s);
2957           }
2958         break;
2959
2960       case E_FM_OP_VOLUME_ADD:  /*volume add*/
2961         if ((e->data) && (e->size > 0))
2962           {
2963              E_Volume *v;
2964
2965              v = _e_fm_shared_codec_volume_decode(e->data, e->size);
2966              if (v)
2967                {
2968                   e_fm2_device_volume_add(v);
2969                   if (e_config->device_auto_mount && !v->mounted && !v->first_time)
2970                     _e_fm2_client_mount(v->udi, v->mount_point);
2971                   v->first_time = 0;
2972                }
2973           }
2974         break;
2975
2976       case E_FM_OP_VOLUME_DEL:  /*volume del*/
2977         if ((e->data) && (e->size > 0))
2978           {
2979              char *udi;
2980              E_Volume *v;
2981
2982              udi = e->data;
2983              v = e_fm2_device_volume_find(udi);
2984              if (v) e_fm2_device_volume_del(v);
2985           }
2986         break;
2987
2988       case E_FM_OP_MOUNT_DONE:  /*mount done*/
2989         if ((e->data) && (e->size > 1))
2990           {
2991              E_Volume *v;
2992              char *udi, *mountpoint = NULL;
2993
2994              udi = e->data;
2995              if ((unsigned int)e->size != (strlen(udi) + 1))
2996                mountpoint = udi + strlen(udi) + 1;
2997              v = e_fm2_device_volume_find(udi);
2998              if (v)
2999                {
3000                   e_fm2_device_mount_add(v, mountpoint);
3001                   _e_fm2_volume_icon_update(v);
3002                   if (e_config->device_auto_open && !eina_list_count(v->mounts))
3003                     {
3004                        E_Action *a;
3005                        Eina_List *m;
3006
3007                        a = e_action_find("fileman");
3008                        m = e_manager_list();
3009                        if (a && a->func.go && m && eina_list_data_get(m) && mountpoint)
3010                          a->func.go(E_OBJECT(eina_list_data_get(m)), mountpoint);
3011                     }
3012                }
3013           }
3014         break;
3015
3016       case E_FM_OP_UNMOUNT_DONE:  /*unmount done*/
3017         if ((e->data) && (e->size > 1))
3018           {
3019              E_Volume *v;
3020              char *udi;
3021
3022              udi = e->data;
3023              v = e_fm2_device_volume_find(udi);
3024              if (v)
3025                {
3026                   e_fm2_device_mount_del(v);
3027                   _e_fm2_volume_icon_update(v);
3028                }
3029           }
3030         break;
3031
3032       case E_FM_OP_EJECT_DONE:
3033         break;
3034
3035       case E_FM_OP_MOUNT_ERROR:  /*mount error*/
3036         if (e->data && (e->size > 1))
3037           {
3038              E_Volume *v;
3039              char *udi;
3040
3041              udi = e->data;
3042              v = e_fm2_device_volume_find(udi);
3043              if (v)
3044                {
3045                   _e_fm_device_error_dialog(_("Mount Error"), _("Can't mount device"), e->data);
3046                   e_fm2_device_mount_fail(v);
3047                }
3048           }
3049         break;
3050
3051       case E_FM_OP_UNMOUNT_ERROR:  /*unmount error*/
3052         if (e->data && (e->size > 1))
3053           {
3054              E_Volume *v;
3055              char *udi;
3056
3057              udi = e->data;
3058              v = e_fm2_device_volume_find(udi);
3059              if (v)
3060                {
3061                   _e_fm_device_error_dialog(_("Unmount Error"), _("Can't unmount device"), e->data);
3062                   e_fm2_device_unmount_fail(v);
3063                }
3064           }
3065         break;
3066
3067       case E_FM_OP_EJECT_ERROR:
3068         if (e->data && (e->size > 1))
3069           {
3070              E_Volume *v;
3071              char *udi;
3072
3073              udi = e->data;
3074              v = e_fm2_device_volume_find(udi);
3075              if (v)
3076                _e_fm_device_error_dialog(_("Eject Error"), _("Can't eject device"), e->data);
3077           }
3078         break;
3079
3080       case E_FM_OP_ERROR:  /*error*/
3081       {
3082          E_Dialog *dlg;
3083          printf("%s:%s(%d) Error from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
3084          dlg = _e_fm_error_dialog(e->ref, e->data);
3085          _e_fm2_op_registry_error(e->ref, dlg);
3086       }
3087       break;
3088
3089       case E_FM_OP_ERROR_RETRY_ABORT:  /*error*/
3090       {
3091          E_Dialog *dlg;
3092          printf("%s:%s(%d) Error from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
3093          dlg = _e_fm_retry_abort_dialog(e->ref, (char *)e->data);
3094          _e_fm2_op_registry_error(e->ref, dlg);
3095       }
3096       break;
3097
3098       case E_FM_OP_OVERWRITE:  /*overwrite*/
3099       {
3100          E_Dialog *dlg;
3101          printf("%s:%s(%d) Overwrite from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
3102          dlg = _e_fm_overwrite_dialog(e->ref, (char *)e->data);
3103          _e_fm2_op_registry_needs_attention(e->ref, dlg);
3104       }
3105       break;
3106
3107       case E_FM_OP_PROGRESS:  /*progress*/
3108       {
3109          int percent, seconds;
3110          off_t done, total;
3111          char *src = NULL;
3112          char *dst = NULL;
3113          char *p = e->data;
3114
3115          if (!e->data) return;
3116
3117 #define UP(value, type) (value) = *(type *)p; p += sizeof(type)
3118          UP(percent, int);
3119          UP(seconds, int);
3120          UP(done, off_t);
3121          UP(total, off_t);
3122 #undef UP
3123          src = p;
3124          dst = p + strlen(src) + 1;
3125          // printf("%s:%s(%d) Progress from slave #%d:\n\t%d%% done,\n\t%d seconds left,\n\t%zd done,\n\t%zd total,\n\tsrc = %s,\n\tdst = %s.\n", __FILE__, __FUNCTION__, __LINE__, e->ref, percent, seconds, done, total, src, dst);
3126
3127          E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(e->ref);
3128          if (!ere) return;
3129          ere->percent = percent;
3130          ere->done = done;
3131          ere->total = total;
3132          ere->eta = seconds;
3133          e_fm2_op_registry_entry_files_set(ere, src, dst);
3134          if (ere->percent == 100)
3135            {
3136               ere->status = E_FM2_OP_STATUS_SUCCESSFUL;
3137               ere->finished = 1;
3138            }
3139          e_fm2_op_registry_entry_changed(ere);
3140       }
3141       break;
3142
3143       case E_FM_OP_QUIT:  /*finished*/
3144       {
3145          E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(e->ref);
3146          if (ere)
3147            {
3148               ere->finished = 1;
3149               ere->eta = 0;
3150               e_fm2_op_registry_entry_changed(ere);
3151            }
3152          e_fm2_op_registry_entry_del(e->ref);
3153       }
3154       break;
3155
3156       default:
3157         break;
3158      }
3159 }
3160
3161 EAPI void
3162 e_fm2_client_del(Ecore_Ipc_Event_Client_Del *e)
3163 {
3164    Eina_List *l;
3165    E_Fm2_Client *cl;
3166
3167    EINA_LIST_FOREACH(_e_fm2_client_list, l, cl)
3168      {
3169         if (cl->cl == e->client)
3170           {
3171              _e_fm2_client_list = eina_list_remove_list(_e_fm2_client_list, l);
3172              free(cl);
3173              break;
3174           }
3175      }
3176 }
3177
3178 /* local subsystem functions */
3179 static const char *
3180 _e_fm2_dev_path_map(const char *dev, const char *path)
3181 {
3182    char buf[PATH_MAX] = "", *s, *ss;
3183    int len;
3184
3185    /* map a device name to a mount point/path on the os (and append path) */
3186
3187    /* FIXME: load mappings from config and use them first - maybe device
3188     * discovery should be done through config and not the below (except
3189     * maybe for home directory and root fs and other simple thngs */
3190    /* FIXME: also add other virtualized dirs like "backgrounds", "themes",
3191     * "favorites" */
3192 #define CMP(x)        ((dev) && (e_util_glob_case_match(dev, x)))
3193 #define PRT(args ...) snprintf(buf, sizeof(buf), ##args)
3194
3195    if (dev)
3196      {
3197         if (dev[0] == '/')
3198           {
3199              if (dev[1] == '\0')
3200                {
3201                   if (eina_strlcpy(buf, path, sizeof(buf)) >= 
3202                       (int)sizeof(buf))
3203                     return NULL;
3204                }
3205              else
3206                {
3207                   if (PRT("%s/%s", dev, path) >= (int)sizeof(buf))
3208                     return NULL;
3209                }
3210           }
3211         else if ((dev[0] == '~') && (dev[1] == '/') && (dev[2] == '\0'))
3212           {
3213              s = (char *)e_user_homedir_get();
3214              if (PRT("%s/%s", s, path) >= (int)sizeof(buf))
3215                return NULL;
3216           }
3217         else if (strcmp(dev, "favorites") == 0)
3218           {
3219              /* this is a virtual device - it's where your favorites list is
3220               * stored - a dir with
3221                 .desktop files or symlinks (in fact anything
3222               * you like
3223               */
3224                if (e_user_dir_concat_static(buf, "fileman/favorites") >= sizeof(buf))
3225                  return NULL;
3226           }
3227         else if (strcmp(dev, "desktop") == 0)
3228           {
3229              char *custom_desktop_dir = getenv("XDG_DESKTOP_DIR");
3230              /* this is a virtual device - it's where your favorites list is
3231               * stored - a dir with
3232                 .desktop files or symlinks (in fact anything
3233               * you like
3234               */
3235              if (custom_desktop_dir)
3236                {
3237                  size_t len;
3238
3239                  custom_desktop_dir = e_util_shell_env_path_eval(custom_desktop_dir);
3240                  len = strlen(custom_desktop_dir);
3241
3242                  if (len >= sizeof(buf))
3243                    {
3244                       free(custom_desktop_dir);
3245                       return NULL;
3246                    }
3247
3248                  strncpy(buf, custom_desktop_dir, sizeof(buf));
3249
3250                  if (strcmp(path, "/"))
3251                    {
3252                       if (len + 1 + strlen(path) >= sizeof(buf))
3253                         {
3254                            free(custom_desktop_dir);
3255                            return NULL;
3256                         }
3257                       buf[len++] = '-';
3258                       strncpy(buf + len, path, sizeof(buf) - len);
3259                    }
3260                    free(custom_desktop_dir);
3261                }
3262              else
3263                {
3264                  if (strcmp(path, "/") == 0)
3265                    {
3266                       if (e_user_homedir_concat(buf, sizeof(buf),
3267                                                 _("Desktop")) >= sizeof(buf))
3268                         return NULL;
3269                    }
3270                  else
3271                    {
3272                       if (e_user_homedir_snprintf(buf, sizeof(buf), "%s-%s",
3273                                                   _("Desktop"), path)
3274                           >= sizeof(buf))
3275                         return NULL;
3276                    }
3277                }
3278                ecore_file_mkpath(buf);
3279           }
3280         else if (strcmp(dev, "temp") == 0)
3281           PRT("/tmp");
3282         /* FIXME: replace all this removable, dvd and like with hal */
3283         else if (!strncmp(dev, "removable:", sizeof("removable:") - 1))
3284           {
3285              E_Volume *v;
3286
3287              v = e_fm2_device_volume_find(dev + strlen("removable:"));
3288              if (v)
3289                {
3290                   if ((!v->mount_point) && (v->efm_mode == EFM_MODE_USING_HAL_MOUNT))
3291                     v->mount_point = e_fm2_device_volume_mountpoint_get(v);
3292                   else if (!v->mount_point) return NULL;
3293
3294                   if (PRT("%s/%s", v->mount_point, path) >= (int)sizeof(buf))
3295                     return NULL;
3296                }
3297           }
3298 /*  else if (CMP("dvd") || CMP("dvd-*")) */
3299 /*    { */
3300 /*       /\* FIXME: find dvd mountpoint optionally for dvd no. X *\/ */
3301 /*       /\* maybe make part of the device mappings config? *\/ */
3302 /*    } */
3303 /*  else if (CMP("cd") || CMP("cd-*") || CMP("cdrom") || CMP("cdrom-*") || */
3304 /*     CMP("dvd") || CMP("dvd-*")) */
3305 /*    { */
3306 /*       /\* FIXME: find cdrom or dvd mountpoint optionally for cd/dvd no. X *\/ */
3307 /*       /\* maybe make part of the device mappings config? *\/ */
3308 /*    } */
3309      }
3310    /* FIXME: add code to find USB devices (multi-card readers or single,
3311     * usb thumb drives, other usb storage devices (usb hd's etc.)
3312     */
3313    /* maybe make part of the device mappings config? */
3314    /* FIXME: add code for finding nfs shares, smb shares etc. */
3315    /* maybe make part of the device mappings config? */
3316
3317    if (buf[0] == '\0')
3318      {
3319         if (eina_strlcpy(buf, path, sizeof(buf)) >= sizeof(buf))
3320           return NULL;
3321      }
3322
3323    /* strip out excess multiple slashes */
3324    s = buf;
3325    while (*s)
3326      {
3327         if ((s[0] == '/') && (s[1] == '/'))
3328           {
3329              ss = s;
3330              do
3331                {
3332                   ss[0] = ss[1];
3333                   ss++;
3334                }
3335              while (*ss);
3336           }
3337         s++;
3338      }
3339    /* strip out slashes at the end - unless its just "/" */
3340    len = s - buf;
3341    while ((len > 1) && (buf[len - 1] == '/'))
3342      {
3343         buf[len - 1] = 0;
3344         len--;
3345      }
3346    return eina_stringshare_add(buf);
3347 }
3348
3349 static void
3350 _e_fm2_file_add(Evas_Object *obj, const char *file, int unique, const char *file_rel, int after, E_Fm2_Finfo *finf)
3351 {
3352    E_Fm2_Smart_Data *sd;
3353    E_Fm2_Icon *ic, *ic2;
3354    Eina_List *l;
3355
3356    sd = evas_object_smart_data_get(obj);
3357    if (!sd) return;
3358    /* if we only want unique icon names - if it's there - ignore */
3359    if (unique)
3360      {
3361         EINA_LIST_FOREACH(sd->icons, l, ic)
3362           {
3363              if (!strcmp(ic->info.file, file))
3364                {
3365                   sd->tmp.last_insert = NULL;
3366                   return;
3367                }
3368           }
3369         EINA_LIST_FOREACH(sd->queue, l, ic)
3370           {
3371              if (!strcmp(ic->info.file, file))
3372                {
3373                   sd->tmp.last_insert = NULL;
3374                   return;
3375                }
3376           }
3377      }
3378    /* create icon obj and append to unsorted list */
3379    ic = _e_fm2_icon_new(sd, file, finf);
3380    if (ic)
3381      {
3382         if (!file_rel)
3383           {
3384              /* respekt da ordah! */
3385               if (sd->order_file)
3386                 sd->queue = eina_list_append(sd->queue, ic);
3387               else
3388                 {
3389      /* insertion sort it here to spread the sort load into idle time */
3390                     EINA_LIST_FOREACH(sd->queue, l, ic2)
3391                       {
3392                          if (_e_fm2_cb_icon_sort(ic, ic2) < 0)
3393                            {
3394                               sd->queue = eina_list_prepend_relative_list(sd->queue, ic, l);
3395                               break;
3396                            }
3397                       }
3398                     if (!l) sd->queue = eina_list_append(sd->queue, ic);
3399                 }
3400           }
3401         else
3402           {
3403              EINA_LIST_FOREACH(sd->icons, l, ic2)
3404                {
3405                   if (!strcmp(ic2->info.file, file_rel))
3406                     {
3407                        if (after)
3408                          sd->icons = eina_list_append_relative(sd->icons, ic, ic2);
3409                        else
3410                          sd->icons = eina_list_prepend_relative(sd->icons, ic, ic2);
3411                        break;
3412                     }
3413                }
3414              if (!l)
3415                sd->icons = eina_list_append(sd->icons, ic);
3416              sd->icons_place = eina_list_append(sd->icons_place, ic);
3417           }
3418         sd->tmp.last_insert = NULL;
3419         sd->iconlist_changed = EINA_TRUE;
3420      }
3421 }
3422
3423 static void
3424 _e_fm2_file_del(Evas_Object *obj, const char *file)
3425 {
3426    E_Fm2_Smart_Data *sd;
3427    E_Fm2_Icon *ic;
3428    Eina_List *l;
3429
3430    sd = evas_object_smart_data_get(obj);
3431    if (!sd) return;
3432    EINA_LIST_FOREACH(sd->icons, l, ic)
3433      {
3434         if (!strcmp(ic->info.file, file))
3435           {
3436              sd->icons = eina_list_remove_list(sd->icons, l);
3437              sd->icons_place = eina_list_remove(sd->icons_place, ic);
3438              if (ic->region)
3439                {
3440                   ic->region->list = eina_list_remove(ic->region->list, ic);
3441                   ic->region = NULL;
3442                }
3443              _e_fm2_icon_free(ic);
3444              return;
3445           }
3446      }
3447 }
3448
3449 static void
3450 _e_fm_file_buffer_clear(void)
3451 {
3452    const char *s;
3453    EINA_LIST_FREE(_e_fm_file_buffer, s)
3454      eina_stringshare_del(s);
3455
3456    _e_fm_file_buffer_cutting = 0;
3457    _e_fm_file_buffer_copying = 0;
3458 }
3459
3460 static Eina_Bool
3461 _e_fm2_buffer_fill(Evas_Object *obj)
3462 {
3463    Eina_List *sel;
3464    char buf[PATH_MAX], *pfile;
3465    int bufused, buffree;
3466    const char *realpath;
3467    const E_Fm2_Icon_Info *ici;
3468
3469    sel = e_fm2_selected_list_get(obj);
3470    if (!sel) return EINA_FALSE;
3471
3472    realpath = e_fm2_real_path_get(obj);
3473    if (!realpath) return EINA_FALSE;
3474
3475    bufused = eina_strlcpy(buf, realpath, sizeof(buf));
3476    if (bufused >= (int)sizeof(buf) - 2) return EINA_FALSE;
3477
3478    if ((bufused > 0) && (buf[bufused - 1] != '/'))
3479      {
3480         buf[bufused] = '/';
3481         bufused++;
3482      }
3483
3484    pfile = buf + bufused;
3485    buffree = sizeof(buf) - bufused;
3486
3487    EINA_LIST_FREE(sel, ici)
3488      {
3489         if (!ici) continue;
3490         if ((int)eina_strlcpy(pfile, ici->file, buffree) >= buffree) continue;
3491         _e_fm_file_buffer = eina_list_append(_e_fm_file_buffer, _e_fm2_uri_escape(buf));
3492      }
3493
3494    return EINA_TRUE;
3495 }
3496
3497 static void
3498 _e_fm2_file_cut(Evas_Object *obj)
3499 {
3500    _e_fm_file_buffer_clear();
3501    _e_fm_file_buffer_cutting = _e_fm2_buffer_fill(obj);
3502 }
3503
3504 static void
3505 _e_fm2_file_copy(Evas_Object *obj)
3506 {
3507    _e_fm_file_buffer_clear();
3508    _e_fm_file_buffer_copying = _e_fm2_buffer_fill(obj);
3509 }
3510
3511 static void
3512 _e_fm2_file_paste(Evas_Object *obj)
3513 {
3514    E_Fm2_Smart_Data *sd;
3515    Eina_List *paths;
3516    const char *filepath;
3517    size_t length = 0;
3518    size_t size = 0;
3519    char *args = NULL;
3520
3521    sd = evas_object_smart_data_get(obj);
3522    if (!sd) return;
3523
3524    /* Convert URI list to a list of real paths. */
3525    paths = _e_fm2_uri_path_list_get(_e_fm_file_buffer);
3526    EINA_LIST_FREE(paths, filepath)
3527      {
3528         /* Get file's full path. */
3529          if (!filepath)
3530            continue;
3531
3532          /* Check if file is protected. */
3533          if (e_filereg_file_protected(filepath))
3534            {
3535               eina_stringshare_del(filepath);
3536               continue;
3537            }
3538
3539          /* Put filepath into a string of args.
3540           * If there are more files, put an additional space.
3541           */
3542          args = _e_fm_string_append_quoted(args, &size, &length, filepath);
3543          args = _e_fm_string_append_char(args, &size, &length, ' ');
3544
3545          eina_stringshare_del(filepath);
3546      }
3547
3548    /* Add destination to the arguments. */
3549    args = _e_fm_string_append_quoted(args, &size, &length, sd->realpath);
3550
3551    /* Roll the operation! */
3552    if (_e_fm_file_buffer_copying)
3553      {
3554         _e_fm_client_file_copy(args, sd->obj);
3555      }
3556    else
3557      {
3558         _e_fm_client_file_move(args, sd->obj);
3559      }
3560
3561    free(args);
3562 }
3563
3564 static void
3565 _e_fm2_file_symlink(Evas_Object *obj)
3566 {
3567    E_Fm2_Smart_Data *sd;
3568    Eina_List *paths;
3569    const char *filepath;
3570    size_t length = 0;
3571    size_t size = 0;
3572    char *args = NULL;
3573
3574    sd = evas_object_smart_data_get(obj);
3575    if (!sd) return;
3576
3577    /* Convert URI list to a list of real paths. */
3578    paths = _e_fm2_uri_path_list_get(_e_fm_file_buffer);
3579    EINA_LIST_FREE(paths, filepath)
3580      {
3581         /* Get file's full path. */
3582          if (!filepath)
3583            continue;
3584
3585          /* Check if file is protected. */
3586          if (e_filereg_file_protected(filepath))
3587            {
3588               eina_stringshare_del(filepath);
3589               continue;
3590            }
3591
3592          /* Put filepath into a string of args.
3593           * If there are more files, put an additional space.
3594           */
3595          args = _e_fm_string_append_quoted(args, &size, &length, filepath);
3596          args = _e_fm_string_append_char(args, &size, &length, ' ');
3597
3598          eina_stringshare_del(filepath);
3599      }
3600
3601    /* Add destination to the arguments. */
3602    args = _e_fm_string_append_quoted(args, &size, &length, sd->realpath);
3603
3604    /* Roll the operation! */
3605    if (_e_fm_file_buffer_copying)
3606      _e_fm_client_file_symlink(args, sd->obj);
3607
3608    free(args);
3609 }
3610
3611 static void
3612 _e_fm2_file_cut_menu(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3613 {
3614    E_Fm2_Smart_Data *sd = data;
3615    if (!sd) return;
3616    _e_fm2_file_cut(sd->obj);
3617 }
3618
3619 static void
3620 _e_fm2_file_copy_menu(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3621 {
3622    E_Fm2_Smart_Data *sd = data;
3623    if (!sd) return;
3624    _e_fm2_file_copy(sd->obj);
3625 }
3626
3627 static void
3628 _e_fm2_file_paste_menu(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3629 {
3630    E_Fm2_Smart_Data *sd = data;
3631    if (!sd) return;
3632    _e_fm2_file_paste(sd->obj);
3633 }
3634
3635 static void
3636 _e_fm2_file_symlink_menu(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
3637 {
3638    E_Fm2_Smart_Data *sd = data;
3639    if (!sd) return;
3640    _e_fm2_file_symlink(sd->obj);
3641 }
3642
3643 static void
3644 _e_fm2_queue_process(Evas_Object *obj)
3645 {
3646    E_Fm2_Smart_Data *sd;
3647    E_Fm2_Icon *ic, *ic2;
3648    Eina_List *l, **ll;
3649    int added = 0, i, p0, p1, n, v;
3650    double t;
3651    char buf[4096];
3652
3653    sd = evas_object_smart_data_get(obj);
3654    if (!sd) return;
3655    if (!sd->queue)
3656      {
3657         if (sd->resize_job) ecore_job_del(sd->resize_job);
3658         sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, obj);
3659         evas_object_smart_callback_call(sd->obj, "changed", NULL);
3660         sd->tmp.last_insert = NULL;
3661         return;
3662      }
3663 //   double tt = ecore_time_get();
3664 //   int queued = eina_list_count(sd->queue);
3665 /* take unsorted and insert into the icon list - reprocess regions */
3666    t = ecore_time_get();
3667    if (!sd->tmp.last_insert)
3668      {
3669 #if 1
3670         n = eina_list_count(sd->icons);
3671         E_FREE(sd->tmp.list_index);
3672         if (n > 0)
3673           sd->tmp.list_index = calloc(n, sizeof(Eina_List *));
3674         if (sd->tmp.list_index)
3675           {
3676              ll = sd->tmp.list_index;
3677              for (l = sd->icons; l; l = eina_list_next(l))
3678                {
3679                   *ll = l;
3680                   ll++;
3681                }
3682              /* binary search first queue */
3683              ic = eina_list_data_get(sd->queue);
3684              p0 = 0; p1 = n;
3685              i = (p0 + p1) / 2;
3686              ll = sd->tmp.list_index;
3687              if (ll[i]) do /* avoid garbage deref */
3688                {
3689                   ic2 = eina_list_data_get(ll[i]);
3690                   v = _e_fm2_cb_icon_sort(ic, ic2);
3691                   if (v < 0) /* ic should go before ic2 */
3692                     p1 = i;
3693                   else /* ic should go at or after ic2 */
3694                     p0 = i;
3695                   i = (p0 + p1) / 2;
3696                   l = ll[i];
3697                }
3698              while ((p1 - p0) > 1);
3699           }
3700         else
3701 #endif
3702         l = sd->icons;
3703      }
3704    else
3705      l = sd->tmp.last_insert;
3706    EINA_LIST_FREE(sd->queue, ic)
3707      {
3708         /* insertion sort - better than qsort for the way we are doing
3709          * things - incrimentally scan and sort as we go as we now know
3710          * that the queue files are in order, we speed up insertions to
3711          * a worst case of O(n) where n is the # of files in the list
3712          * so far
3713          */
3714           if (sd->order_file)
3715             {
3716                l = NULL;
3717             }
3718           else
3719             {
3720                EINA_LIST_FOREACH(l, l, ic2)
3721                  {
3722                     if (_e_fm2_cb_icon_sort(ic, ic2) < 0)
3723                       {
3724                          if (l == sd->icons)
3725                            sd->icons = eina_list_prepend(sd->icons, ic);
3726                          else
3727                            sd->icons = eina_list_prepend_relative_list(sd->icons,
3728                                                                        ic, l);
3729                          sd->tmp.last_insert = l;
3730                          break;
3731                       }
3732                  }
3733             }
3734           if (!l)
3735             {
3736                sd->icons = eina_list_append(sd->icons, ic);
3737                sd->tmp.last_insert = eina_list_last(sd->icons);
3738             }
3739           sd->icons_place = eina_list_append(sd->icons_place, ic);
3740           added++;
3741           /* if we spent more than 1/20th of a second inserting - give up
3742            * for now */
3743           if ((ecore_time_get() - t) > 0.05) break;
3744      }
3745 //   printf("FM: SORT %1.3f (%i files) (%i queued, %i added) [%i iter]\n",
3746 //        ecore_time_get() - tt, eina_list_count(sd->icons), queued,
3747 //        added, sd->tmp.iter);
3748    snprintf(buf, sizeof(buf), _("%i Files"), eina_list_count(sd->icons));
3749    edje_object_part_text_set(sd->overlay, "e.text.busy_label", buf);
3750    if (sd->resize_job) ecore_job_del(sd->resize_job);
3751    sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, obj);
3752    evas_object_smart_callback_call(sd->obj, "changed", NULL);
3753    sd->tmp.iter++;
3754 }
3755
3756 static void
3757 _e_fm2_queue_free(Evas_Object *obj)
3758 {
3759    E_Fm2_Smart_Data *sd;
3760    E_Fm2_Icon *ic;
3761
3762    sd = evas_object_smart_data_get(obj);
3763    if (!sd) return;
3764    /* just free the icons in the queue  and the queue itself */
3765    EINA_LIST_FREE(sd->queue, ic)
3766      _e_fm2_icon_free(ic);
3767 }
3768
3769 static void
3770 _e_fm2_regions_free(Evas_Object *obj)
3771 {
3772    E_Fm2_Smart_Data *sd;
3773    E_Fm2_Region *rg;
3774
3775    sd = evas_object_smart_data_get(obj);
3776    if (!sd) return;
3777    /* free up all regions */
3778    EINA_LIST_FREE(sd->regions.list, rg)
3779      _e_fm2_region_free(rg);
3780 }
3781
3782 static void
3783 _e_fm2_regions_populate(Evas_Object *obj)
3784 {
3785    E_Fm2_Smart_Data *sd;
3786    Eina_List *l;
3787    E_Fm2_Region *rg;
3788    E_Fm2_Icon *ic;
3789
3790    sd = evas_object_smart_data_get(obj);
3791    if (!sd) return;
3792    /* take the icon list and split into regions */
3793    rg = NULL;
3794    evas_event_freeze(evas_object_evas_get(obj));
3795    edje_freeze();
3796    EINA_LIST_FOREACH(sd->icons, l, ic)
3797      {
3798         if (!rg)
3799           {
3800              rg = _e_fm2_region_new(sd);
3801              sd->regions.list = eina_list_append(sd->regions.list, rg);
3802           }
3803         ic->region = rg;
3804         rg->list = eina_list_append(rg->list, ic);
3805         if (rg->w == 0)
3806           {
3807              rg->x = ic->x;
3808              rg->y = ic->y;
3809              rg->w = ic->w;
3810              rg->h = ic->h;
3811           }
3812         else
3813           {
3814              if (ic->x < rg->x)
3815                {
3816                   rg->w += rg->x - ic->x;
3817                   rg->x = ic->x;
3818                }
3819              if ((ic->x + ic->w) > (rg->x + rg->w))
3820                {
3821                   rg->w += (ic->x + ic->w) - (rg->x + rg->w);
3822                }
3823              if (ic->y < rg->y)
3824                {
3825                   rg->h += rg->y - ic->y;
3826                   rg->y = ic->y;
3827                }
3828              if ((ic->y + ic->h) > (rg->y + rg->h))
3829                {
3830                   rg->h += (ic->y + ic->h) - (rg->y + rg->h);
3831                }
3832           }
3833         if ((int)eina_list_count(rg->list) > sd->regions.member_max)
3834           rg = NULL;
3835      }
3836    _e_fm2_regions_eval(obj);
3837    EINA_LIST_FOREACH(sd->icons, l, ic)
3838      {
3839         if ((!ic->region->realized) && (ic->realized))
3840           _e_fm2_icon_unrealize(ic);
3841      }
3842    _e_fm2_obj_icons_place(sd);
3843    edje_thaw();
3844    evas_event_thaw(evas_object_evas_get(obj));
3845 }
3846
3847 static void
3848 _e_fm2_icons_place_icons(E_Fm2_Smart_Data *sd)
3849 {
3850    Eina_List *l;
3851    E_Fm2_Icon *ic;
3852    Evas_Coord x, y, rh;
3853
3854    x = 0; y = 0;
3855    rh = 0;
3856    EINA_LIST_FOREACH(sd->icons, l, ic)
3857      {
3858         if ((x > 0) && ((x + ic->w) > sd->w))
3859           {
3860              x = 0;
3861              y += rh;
3862              rh = 0;
3863           }
3864         ic->x = x;
3865         ic->y = y;
3866         x += ic->w;
3867         if (ic->h > rh) rh = ic->h;
3868         if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
3869         if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
3870      }
3871 }
3872
3873 static void
3874 _e_fm2_icons_place_grid_icons(E_Fm2_Smart_Data *sd)
3875 {
3876    Eina_List *l;
3877    E_Fm2_Icon *ic;
3878    Evas_Coord x, y, gw, gh;
3879    int cols = 1, col;
3880
3881    gw = 0; gh = 0;
3882    EINA_LIST_FOREACH(sd->icons, l, ic)
3883      {
3884         if (ic->w > gw) gw = ic->w;
3885         if (ic->h > gh) gh = ic->h;
3886      }
3887    if (gw > 0) cols = sd->w / gw;
3888    if (cols < 1) cols = 1;
3889    x = 0; y = 0; col = 0;
3890    EINA_LIST_FOREACH(sd->icons, l, ic)
3891      {
3892         ic->x = x + ((gw - ic->w) / 2);
3893         ic->y = y + (gh - ic->h);
3894         x += gw;
3895         col++;
3896         if (col >= cols)
3897           {
3898              col = 0;
3899              x = 0;
3900              y += gh;
3901           }
3902         if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
3903         if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
3904      }
3905 }
3906
3907 static int
3908 _e_fm2_icons_icon_overlaps(E_Fm2_Icon *ic)
3909 {
3910    Eina_List *l;
3911    E_Fm2_Icon *ic2;
3912
3913    /* this is really slow... when we have a lot of icons */
3914    EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
3915      {
3916         if ((ic2 != ic) && (ic2->saved_pos))
3917           {
3918              if (E_INTERSECTS(ic2->x, ic2->y, ic2->w, ic2->h,
3919                               ic->x, ic->y, ic->w, ic->h))
3920                return 1;
3921           }
3922      }
3923    return 0;
3924 }
3925
3926 static int
3927 _e_fm2_icons_icon_row_ok(E_Fm2_Icon *ic)
3928 {
3929    if (ic->x + ic->w > ic->sd->w) return 0;
3930    if (ic->x < 0) return 0;
3931    if (ic->y < 0) return 0;
3932    return 1;
3933 }
3934
3935 static void
3936 _e_fm2_icon_place_relative(E_Fm2_Icon *ic, E_Fm2_Icon *icr, int xrel, int yrel, int xa, int ya)
3937 {
3938    ic->x = icr->x;
3939    ic->y = icr->y;
3940
3941    if      (xrel > 0) ic->x += icr->w;
3942    else if (xrel < 0)
3943      ic->x -= ic->w;
3944    else if (xa == 1)
3945      ic->x += (icr->w - ic->w) / 2;
3946    else if (xa == 2)
3947      ic->x += icr->w - ic->w;
3948
3949    if      (yrel > 0) ic->y += icr->h;
3950    else if (yrel < 0)
3951      ic->y -= ic->h;
3952    else if (ya == 1)
3953      ic->y += (icr->h - ic->h) / 2;
3954    else if (ya == 2)
3955      ic->y += icr->h - ic->h;
3956 }
3957
3958 static void
3959 _e_fm2_icons_place_icon(E_Fm2_Icon *ic)
3960 {
3961    Eina_List *l;
3962    E_Fm2_Icon *ic2;
3963
3964    ic->x = 0;
3965    ic->y = 0;
3966    ic->saved_pos = EINA_TRUE;
3967    /* ### BLAH ### */
3968 //   if (!_e_fm2_icons_icon_overlaps(ic)) return;
3969 /*
3970    _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 2);
3971    if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
3972    _e_fm2_icon_place_relative(ic, ic2, 0, -1, 0, 0);
3973    if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
3974    _e_fm2_icon_place_relative(ic, ic2, 0, -1, 1, 0);
3975    if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
3976    _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 0);
3977    if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
3978    _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 1);
3979    if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
3980    _e_fm2_icon_place_relative(ic, ic2, 0, 1, 0, 0);
3981    if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
3982    _e_fm2_icon_place_relative(ic, ic2, 0, 1, 1, 0);
3983    if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
3984  */
3985    EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
3986      {
3987         if ((ic2 != ic) && (ic2->saved_pos))
3988           {
3989              // ###_
3990                _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 2);
3991                if (_e_fm2_icons_icon_row_ok(ic) &&
3992                    !_e_fm2_icons_icon_overlaps(ic)) goto done;
3993      // _###
3994                _e_fm2_icon_place_relative(ic, ic2, -1, 0, 0, 2);
3995                if (_e_fm2_icons_icon_row_ok(ic) &&
3996                    !_e_fm2_icons_icon_overlaps(ic)) goto done;
3997           }
3998      }
3999
4000    EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
4001      {
4002         if ((ic2 != ic) && (ic2->saved_pos))
4003           {
4004              // ###
4005              //  |
4006                  _e_fm2_icon_place_relative(ic, ic2, 0, 1, 1, 0);
4007                  if (_e_fm2_icons_icon_row_ok(ic) &&
4008                      !_e_fm2_icons_icon_overlaps(ic)) goto done;
4009      //  |
4010                  // ###
4011                  _e_fm2_icon_place_relative(ic, ic2, 0, -1, 1, 0);
4012                  if (_e_fm2_icons_icon_row_ok(ic) &&
4013                      !_e_fm2_icons_icon_overlaps(ic)) goto done;
4014           }
4015         if ((ic2 != ic) && (ic2->saved_pos))
4016           {
4017 // TODO: if uncomment this, change EINA_LIST_FOREACH to EINA_LIST_FOREACH_SAFE!
4018 //           ic->sd->icons_place = eina_list_remove_list(ic->sd->icons_place, pl);
4019           }
4020      }
4021 done:
4022    return;
4023 }
4024
4025 static void
4026 _e_fm2_icons_place_custom_icons(E_Fm2_Smart_Data *sd)
4027 {
4028    Eina_List *l;
4029    E_Fm2_Icon *ic;
4030
4031    EINA_LIST_FOREACH(sd->icons, l, ic)
4032      {
4033         if (!ic->saved_pos)
4034           {
4035              /* FIXME: place using smart place fn */
4036               _e_fm2_icons_place_icon(ic);
4037           }
4038
4039         if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4040         if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4041      }
4042 }
4043
4044 static void
4045 _e_fm2_icons_place_custom_grid_icons(E_Fm2_Smart_Data *sd)
4046 {
4047    /* FIXME: not going to implement this at this stage */
4048     Eina_List *l;
4049     E_Fm2_Icon *ic;
4050
4051     EINA_LIST_FOREACH(sd->icons, l, ic)
4052       {
4053          if (!ic->saved_pos)
4054            {
4055      /* FIXME: place using grid fn */
4056            }
4057
4058          if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4059          if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4060       }
4061 }
4062
4063 static void
4064 _e_fm2_icons_place_custom_smart_grid_icons(E_Fm2_Smart_Data *sd)
4065 {
4066    /* FIXME: not going to implement this at this stage */
4067     Eina_List *l;
4068     E_Fm2_Icon *ic;
4069
4070     EINA_LIST_FOREACH(sd->icons, l, ic)
4071       {
4072          if (!ic->saved_pos)
4073            {
4074      /* FIXME: place using smart grid fn */
4075            }
4076
4077          if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4078          if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4079       }
4080 }
4081
4082 static void
4083 _e_fm2_icons_place_list(E_Fm2_Smart_Data *sd)
4084 {
4085    Eina_List *l;
4086    E_Fm2_Icon *ic;
4087    Evas_Coord x, y;
4088    int i;
4089
4090    i = x = y = 0;
4091    EINA_LIST_FOREACH(sd->icons, l, ic)
4092      {
4093         ic->x = x;
4094         ic->y = y;
4095         if (sd->w > ic->min_w)
4096           ic->w = sd->w;
4097         else
4098           ic->w = ic->min_w;
4099         y += ic->h;
4100         ic->odd = (i & 0x01);
4101         if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4102         if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4103         i++;
4104      }
4105    EINA_LIST_FOREACH(sd->icons, l, ic)
4106      {
4107         ic->w = sd->max.w;
4108      }
4109 }
4110
4111 static void
4112 _e_fm2_icons_place(Evas_Object *obj)
4113 {
4114    E_Fm2_Smart_Data *sd;
4115
4116    sd = evas_object_smart_data_get(obj);
4117    if (!sd) return;
4118    /* take the icon list and find a location for them */
4119    sd->max.w = 0;
4120    sd->max.h = 0;
4121    switch (_e_fm2_view_mode_get(sd))
4122      {
4123       case E_FM2_VIEW_MODE_ICONS:
4124         _e_fm2_icons_place_icons(sd);
4125 //      sd->max.h += ICON_BOTTOM_SPACE;
4126         break;
4127
4128       case E_FM2_VIEW_MODE_GRID_ICONS:
4129         _e_fm2_icons_place_grid_icons(sd);
4130 //      sd->max.h += ICON_BOTTOM_SPACE;
4131         break;
4132
4133       case E_FM2_VIEW_MODE_CUSTOM_ICONS:
4134         _e_fm2_icons_place_custom_icons(sd);
4135 //      sd->max.h += ICON_BOTTOM_SPACE;
4136         break;
4137
4138       case E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS:
4139         /* FIXME: not going to implement this at this stage */
4140         _e_fm2_icons_place_custom_grid_icons(sd);
4141 //      sd->max.h += ICON_BOTTOM_SPACE;
4142         break;
4143
4144       case E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS:
4145         /* FIXME: not going to implement this at this stage */
4146         _e_fm2_icons_place_custom_smart_grid_icons(sd);
4147 //      sd->max.h += ICON_BOTTOM_SPACE;
4148         break;
4149
4150       case E_FM2_VIEW_MODE_LIST:
4151         _e_fm2_icons_place_list(sd);
4152         break;
4153
4154       default:
4155         break;
4156      }
4157    /* tell our parent scrollview - if any, that we have changed */
4158    evas_object_smart_callback_call(sd->obj, "changed", NULL);
4159 }
4160
4161 static void
4162 _e_fm2_icons_free(Evas_Object *obj)
4163 {
4164    E_Fm2_Smart_Data *sd;
4165
4166    sd = evas_object_smart_data_get(obj);
4167    if (!sd) return;
4168    _e_fm2_queue_free(obj);
4169    /* free all icons */
4170    E_FREE_LIST(sd->icons, _e_fm2_icon_free);
4171    eina_list_free(sd->icons_place);
4172    sd->icons_place = NULL;
4173    sd->tmp.last_insert = NULL;
4174    E_FREE(sd->tmp.list_index);
4175 }
4176
4177 static void
4178 _e_fm2_regions_eval(Evas_Object *obj)
4179 {
4180    E_Fm2_Smart_Data *sd;
4181    Eina_List *l;
4182    E_Fm2_Region *rg;
4183
4184    sd = evas_object_smart_data_get(obj);
4185    if (!sd) return;
4186    evas_event_freeze(evas_object_evas_get(obj));
4187    edje_freeze();
4188    EINA_LIST_FOREACH(sd->regions.list, l, rg)
4189      {
4190         if (_e_fm2_region_visible(rg))
4191           _e_fm2_region_realize(rg);
4192         else
4193           _e_fm2_region_unrealize(rg);
4194      }
4195    edje_thaw();
4196    evas_event_thaw(evas_object_evas_get(obj));
4197 }
4198
4199 static void
4200 _e_fm2_config_free(E_Fm2_Config *cfg)
4201 {
4202    if (cfg->icon.key_hint) eina_stringshare_del(cfg->icon.key_hint);
4203    if (cfg->theme.background) eina_stringshare_del(cfg->theme.background);
4204    if (cfg->theme.frame) eina_stringshare_del(cfg->theme.frame);
4205    if (cfg->theme.icons) eina_stringshare_del(cfg->theme.icons);
4206    free(cfg);
4207 }
4208
4209 static Evas_Object *
4210 _e_fm2_file_fm2_find(const char *file)
4211 {
4212    char *dir;
4213    Eina_List *l;
4214    Evas_Object *obj;
4215
4216    dir = ecore_file_dir_get(file);
4217    if (!dir) return NULL;
4218    EINA_LIST_FOREACH(_e_fm2_list, l, obj)
4219      {
4220         if ((_e_fm2_list_walking > 0) &&
4221             (eina_list_data_find(_e_fm2_list_remove, obj))) continue;
4222         if (!strcmp(e_fm2_real_path_get(obj), dir))
4223           {
4224              free(dir);
4225              return obj;
4226           }
4227      }
4228    free(dir);
4229    return NULL;
4230 }
4231
4232 static E_Fm2_Icon *
4233 _e_fm2_icon_find(Evas_Object *obj, const char *file)
4234 {
4235    E_Fm2_Smart_Data *sd;
4236    Eina_List *l;
4237    E_Fm2_Icon *ic;
4238
4239    sd = evas_object_smart_data_get(obj);
4240    if (!sd) return NULL;
4241    EINA_LIST_FOREACH(sd->icons, l, ic)
4242      {
4243         if (!strcmp(ic->info.file, file)) return ic;
4244      }
4245    return NULL;
4246 }
4247
4248 /* Escape illegal caracters within an uri and return an eina_stringshare */
4249 static const char *
4250 _e_fm2_uri_escape(const char *path)
4251 {
4252    char dest[PATH_MAX * 3 + 7];
4253    const char *p;
4254    int i;
4255
4256    if (!path) return NULL;
4257    memset(dest, 0, PATH_MAX * 3 + 7);
4258
4259    snprintf(dest, 8, "file://");
4260
4261    /* Most app doesn't handle the hostname in the uri so it's put to NULL */
4262    for (i = 7, p = path; *p != '\0'; p++, i++)
4263      {
4264         if (isalnum(*p) || strchr("/$-_.+!*'()", *p))
4265           dest[i] = *p;
4266         else
4267           {
4268              snprintf(&(dest[i]), 4, "%%%02X", (unsigned char)*p);
4269              i += 2;
4270           }
4271      }
4272
4273    return eina_stringshare_add(dest);
4274 }
4275
4276 /* Parse a single uri and return an E_Fm2_Uri struct.
4277  * If the parsing have failed it return NULL.
4278  * The E_Fm2_Uri may have hostname parameter and always a path.
4279  * If there's no hostname in the uri then the hostname parameter is NULL
4280  */
4281 static E_Fm2_Uri *
4282 _e_fm2_uri_parse(const char *val)
4283 {
4284    E_Fm2_Uri *uri;
4285    const char *p;
4286    char hostname[PATH_MAX], path[PATH_MAX];
4287    int i = 0;
4288
4289    /* if value is a raw path: /path/to/blah just return it */
4290    if (val[0] == '/')
4291      {
4292         uri = E_NEW(E_Fm2_Uri, 1);
4293         uri->hostname = NULL;
4294         uri->path = eina_stringshare_add(val);
4295         return uri;
4296      }
4297    /* The shortest possible path is file:///
4298     * anything smaller than that can't be a valid uri
4299     */
4300    if (strlen(val) <= 7 && strncmp(val, "file://", 7)) return NULL;
4301    memset(path, 0, PATH_MAX);
4302
4303    /* An uri should be in a form file://<hostname>/<path> */
4304    p = val + 7;
4305    if (*p != '/')
4306      {
4307         for (i = 0; *p != '/' && *p != '\0' && i < _POSIX_HOST_NAME_MAX; p++, i++)
4308           hostname[i] = *p;
4309      }
4310    hostname[i] = '\0';
4311
4312    /* See http://www.faqs.org/rfcs/rfc1738.html for the escaped chars */
4313    for (i = 0; *p != '\0' && i < PATH_MAX; i++, p++)
4314      {
4315         if (*p == '%')
4316           {
4317              path[i] = *(++p);
4318              path[i + 1] = *(++p);
4319              path[i] = (char)strtol(&(path[i]), NULL, 16);
4320              path[i + 1] = '\0';
4321           }
4322         else
4323           path[i] = *p;
4324      }
4325
4326    uri = E_NEW(E_Fm2_Uri, 1);
4327    if (hostname[0]) uri->hostname = eina_stringshare_add(hostname);
4328    else uri->hostname = NULL;
4329    uri->path = eina_stringshare_add(path);
4330
4331    return uri;
4332 }
4333
4334 /* Takes an Eina_List of uri and return an Eina_List of real paths */
4335 static Eina_List *
4336 _e_fm2_uri_path_list_get(Eina_List *uri_list)
4337 {
4338    E_Fm2_Uri *uri;
4339    Eina_List *l, *path_list = NULL;
4340    char current_hostname[_POSIX_HOST_NAME_MAX];
4341    const char *uri_str;
4342
4343    if (gethostname(current_hostname, _POSIX_HOST_NAME_MAX) == -1)
4344      current_hostname[0] = '\0';
4345
4346    EINA_LIST_FOREACH(uri_list, l, uri_str)
4347      {
4348         if (!(uri = _e_fm2_uri_parse(uri_str)))
4349           continue;
4350
4351         if (!uri->hostname || !strcmp(uri->hostname, "localhost")
4352             || !strcmp(uri->hostname, current_hostname))
4353           {
4354              path_list = eina_list_append(path_list, uri->path);
4355           }
4356         else
4357           eina_stringshare_del(uri->path);
4358
4359         if (uri->hostname) eina_stringshare_del(uri->hostname);
4360         E_FREE(uri);
4361      }
4362
4363    return path_list;
4364 }
4365
4366 static Eina_List *
4367 _e_fm2_uri_icon_list_get(Eina_List *uri)
4368 {
4369    Eina_List *icons = NULL;
4370    Eina_List *l;
4371    const char *path;
4372
4373    EINA_LIST_FOREACH(uri, l, path)
4374      {
4375         Evas_Object *fm;
4376         E_Fm2_Icon *ic;
4377
4378         ic = NULL;
4379         fm = _e_fm2_file_fm2_find(path);
4380         if (fm)
4381           {
4382              const char *file = ecore_file_file_get(path);
4383              ic = _e_fm2_icon_find(fm, file);
4384           }
4385         icons = eina_list_append(icons, ic);
4386      }
4387    return icons;
4388 }
4389
4390 /**************************/
4391
4392 static E_Fm2_Icon *
4393 _e_fm2_icon_new(E_Fm2_Smart_Data *sd, const char *file, E_Fm2_Finfo *finf)
4394 {
4395    E_Fm2_Icon *ic;
4396
4397    /* create icon */
4398    ic = E_NEW(E_Fm2_Icon, 1);
4399    ic->info.fm = sd->obj;
4400    ic->info.ic = ic;
4401    ic->info.file = eina_stringshare_add(file);
4402    ic->sd = sd;
4403    if (!_e_fm2_icon_fill(ic, finf))
4404      {
4405         eina_stringshare_del(ic->info.file);
4406         free(ic);
4407         return NULL;
4408      }
4409    return ic;
4410 }
4411
4412 static void
4413 _e_fm2_icon_unfill(E_Fm2_Icon *ic)
4414 {
4415    eina_stringshare_del(ic->info.mime);
4416    eina_stringshare_del(ic->info.label);
4417    eina_stringshare_del(ic->info.comment);
4418    eina_stringshare_del(ic->info.generic);
4419    eina_stringshare_del(ic->info.icon);
4420    eina_stringshare_del(ic->info.link);
4421    eina_stringshare_del(ic->info.real_link);
4422    eina_stringshare_del(ic->info.category);
4423    ic->info.mime = NULL;
4424    ic->info.label = NULL;
4425    ic->info.comment = NULL;
4426    ic->info.generic = NULL;
4427    ic->info.icon = NULL;
4428    ic->info.link = NULL;
4429    ic->info.real_link = NULL;
4430    ic->info.mount = EINA_FALSE;
4431    ic->info.removable = EINA_FALSE;
4432    ic->info.removable_full = EINA_FALSE;
4433    ic->info.deleted = EINA_FALSE;
4434    ic->info.broken_link = EINA_FALSE;
4435 }
4436
4437 static void
4438 _e_fm2_icon_geom_adjust(E_Fm2_Icon *ic, int saved_x, int saved_y, int saved_w __UNUSED__, int saved_h __UNUSED__, int saved_res_w, int saved_res_h)
4439 {
4440    int qx, qy, rx, ry, x, y;
4441
4442    if (!((_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_CUSTOM_ICONS) &&
4443          (ic->sd->config->view.fit_custom_pos) &&
4444          (saved_res_w > 0) &&
4445          (saved_res_h > 0)))
4446      return;
4447    if (saved_res_w >= 3) qx = saved_x / (saved_res_w / 3);
4448    else qx = 0;
4449    rx = saved_x - ((saved_res_w / 2) * qx);
4450    x = ((ic->sd->w / 2) * qx) + rx;
4451    ic->x = x;
4452
4453    if (saved_res_h >= 3) qy = saved_y / (saved_res_h / 3);
4454    else qy = 0;
4455    ry = saved_y - ((saved_res_h / 2) * qy);
4456    y = ((ic->sd->h / 2) * qy) + ry;
4457    ic->y = y;
4458 }
4459
4460 static int
4461 _e_fm2_icon_fill(E_Fm2_Icon *ic, E_Fm2_Finfo *finf)
4462 {
4463    Evas_Coord mw = 0, mh = 0;
4464    Evas_Object *obj, *obj2;
4465    char buf[PATH_MAX], *lnk;
4466    const char *mime;
4467    E_Fm2_Custom_File *cf;
4468
4469    if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
4470      return 0;
4471    cf = e_fm2_custom_file_get(buf);
4472    if (finf)
4473      {
4474         memcpy(&(ic->info.statinfo), &(finf->st), sizeof(struct stat));
4475         if ((finf->lnk) && (finf->lnk[0]))
4476           ic->info.link = eina_stringshare_add(finf->lnk);
4477         else
4478           ic->info.link = NULL;
4479         if ((finf->rlnk) && (finf->rlnk[0]))
4480           ic->info.real_link = eina_stringshare_add(finf->rlnk);
4481         else
4482           ic->info.real_link = NULL;
4483         ic->info.broken_link = finf->broken_link;
4484      }
4485    else
4486      {
4487         printf("FIXME: remove old non finf icon fill code\n");
4488         /* FIXME: this should go away... get this from the fm slave proc above */
4489         lnk = ecore_file_readlink(buf);
4490         if (stat(buf, &(ic->info.statinfo)) == -1)
4491           {
4492              if (lnk)
4493                ic->info.broken_link = EINA_TRUE;
4494              else
4495                {
4496                   return 0;
4497                }
4498           }
4499         if (lnk)
4500           {
4501              if (lnk[0] == '/')
4502                {
4503                   ic->info.link = eina_stringshare_add(lnk);
4504                   ic->info.real_link = eina_stringshare_add(lnk);
4505                }
4506              else
4507                {
4508                   char *rp;
4509
4510                   snprintf(buf, sizeof(buf), "%s/%s", ic->sd->realpath, lnk);
4511                   rp = ecore_file_realpath(buf);
4512                   if (rp)
4513                     {
4514                        ic->info.link = eina_stringshare_add(rp);
4515                        free(rp);
4516                     }
4517                   ic->info.real_link = eina_stringshare_add(lnk);
4518                }
4519              free(lnk);
4520           }
4521         /* FIXME: end go away chunk */
4522      }
4523
4524    if (S_ISDIR(ic->info.statinfo.st_mode))
4525      {
4526         ic->info.mime = eina_stringshare_ref(_e_fm2_mime_inode_directory);
4527      }
4528    else if (ic->info.real_link)
4529      {
4530         mime = efreet_mime_type_get(ic->info.real_link);
4531         if (!mime)
4532           /* XXX REMOVE/DEPRECATE ME LATER */
4533           mime = e_fm_mime_filename_get(ic->info.file);
4534         if (mime) ic->info.mime = eina_stringshare_add(mime);
4535      }
4536
4537    if (!ic->info.mime)
4538      {
4539         mime = efreet_mime_type_get(buf);
4540         if (!mime)
4541           /* XXX REMOVE/DEPRECATE ME LATER */
4542           mime = e_fm_mime_filename_get(ic->info.file);
4543         if (mime) ic->info.mime = eina_stringshare_add(mime);
4544      }
4545
4546    if (_e_fm2_file_is_desktop(ic->info.file))
4547      _e_fm2_icon_desktop_load(ic);
4548
4549    if (cf)
4550      {
4551         if (cf->icon.valid)
4552           {
4553              if (cf->icon.icon)
4554                {
4555                   eina_stringshare_replace(&ic->info.icon, cf->icon.icon);
4556                }
4557              ic->info.icon_type = cf->icon.type;
4558           }
4559         if (cf->geom.valid)
4560           {
4561              ic->saved_pos = EINA_TRUE;
4562              ic->x = cf->geom.x;
4563              ic->y = cf->geom.y;
4564              if (cf->geom.w > 0) ic->w = cf->geom.w;
4565              if (cf->geom.h > 0) ic->h = cf->geom.h;
4566              _e_fm2_icon_geom_adjust(ic, cf->geom.x, cf->geom.y, cf->geom.w, cf->geom.h, cf->geom.res_w, cf->geom.res_h);
4567           }
4568      }
4569
4570    evas_event_freeze(evas_object_evas_get(ic->sd->obj));
4571    edje_freeze();
4572
4573    switch (_e_fm2_view_mode_get(ic->sd))
4574      {
4575       case E_FM2_VIEW_MODE_ICONS:
4576       case E_FM2_VIEW_MODE_GRID_ICONS:
4577       case E_FM2_VIEW_MODE_CUSTOM_ICONS:
4578       case E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS:
4579       case E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS:
4580         /* FIXME: need to define icon edjes. here goes:
4581          *
4582          * fileman/icon/fixed
4583          * fileman/icon/variable
4584          * fileman/list/fixed
4585          * fileman/list/variable
4586          * fileman/list_odd/fixed
4587          * fileman/list_odd/variable
4588          *
4589          */
4590         if ((!ic->sd->config->icon.fixed.w) || (!ic->sd->config->icon.fixed.h))
4591           {
4592              obj = ic->sd->tmp.obj;
4593              if (!obj)
4594                {
4595                   obj = edje_object_add(evas_object_evas_get(ic->sd->obj));
4596                   if ((ic->sd->config->icon.fixed.w) && (ic->sd->config->icon.fixed.h))
4597                     _e_fm2_theme_edje_object_set(ic->sd, obj,
4598                                                  "base/theme/fileman",
4599                                                  "icon/fixed");
4600                   else
4601                     _e_fm2_theme_edje_object_set(ic->sd, obj,
4602                                                  "base/theme/fileman",
4603                                                  "icon/variable");
4604                   ic->sd->tmp.obj = obj;
4605                }
4606              _e_fm2_icon_label_set(ic, obj);
4607              obj2 = ic->sd->tmp.obj2;
4608              if (!obj2)
4609                {
4610                   obj2 = evas_object_rectangle_add(evas_object_evas_get(ic->sd->obj));
4611                   ic->sd->tmp.obj2 = obj2;
4612                }
4613              /* FIXME: if icons are allowed to have their own size - use it */
4614              edje_extern_object_min_size_set(obj2, _e_fm2_icon_w_get(ic->sd), _e_fm2_icon_h_get(ic->sd));
4615              edje_extern_object_max_size_set(obj2, _e_fm2_icon_w_get(ic->sd), _e_fm2_icon_h_get(ic->sd));
4616              edje_object_part_swallow(obj, "e.swallow.icon", obj2);
4617              edje_object_size_min_calc(obj, &mw, &mh);
4618           }
4619         ic->w = mw;
4620         ic->h = mh;
4621         if (ic->sd->config->icon.fixed.w) ic->w = _e_fm2_icon_w_get(ic->sd);
4622         if (ic->sd->config->icon.fixed.h) ic->h = _e_fm2_icon_h_get(ic->sd);
4623         ic->min_w = mw;
4624         ic->min_h = mh;
4625         break;
4626
4627       case E_FM2_VIEW_MODE_LIST:
4628       {
4629          obj = ic->sd->tmp.obj;
4630          if (!obj)
4631            {
4632               obj = edje_object_add(evas_object_evas_get(ic->sd->obj));
4633 // vairable sized list items are pretty usless - ignore.
4634 //                if (ic->sd->config->icon.fixed.w)
4635               _e_fm2_theme_edje_object_set(ic->sd, obj,
4636                                            "base/theme/fileman",
4637                                            "list/fixed");
4638 //                else
4639 //                  _e_fm2_theme_edje_object_set(ic->sd, obj, "base/theme/fileman",
4640 //                                          "list/variable");
4641               ic->sd->tmp.obj = obj;
4642            }
4643          _e_fm2_icon_label_set(ic, obj);
4644          obj2 = ic->sd->tmp.obj2;
4645          if (!obj2)
4646            {
4647               obj2 = evas_object_rectangle_add(evas_object_evas_get(ic->sd->obj));
4648               ic->sd->tmp.obj2 = obj2;
4649            }
4650          edje_extern_object_min_size_set(obj2, ic->sd->config->icon.list.w, ic->sd->config->icon.list.h);
4651          edje_extern_object_max_size_set(obj2, ic->sd->config->icon.list.w, ic->sd->config->icon.list.h);
4652          edje_object_part_swallow(obj, "e.swallow.icon", obj2);
4653          edje_object_size_min_calc(obj, &mw, &mh);
4654       }
4655         if (mw < ic->sd->w) ic->w = ic->sd->w;
4656         else ic->w = mw;
4657         ic->h = mh;
4658         ic->min_w = mw;
4659         ic->min_h = mh;
4660         break;
4661
4662       default:
4663         break;
4664      }
4665    edje_thaw();
4666    evas_event_thaw(evas_object_evas_get(ic->sd->obj));
4667    return 1;
4668 }
4669
4670 static void
4671 _e_fm2_icon_free(E_Fm2_Icon *ic)
4672 {
4673    /* free icon, object data etc. etc. */
4674     if (ic->sd->drop_icon == ic)
4675       {
4676          /* FIXME: call hide call */
4677           ic->sd->drop_icon = NULL;
4678       }
4679     _e_fm2_icon_unrealize(ic);
4680     if (ic->menu)
4681       {
4682          e_menu_post_deactivate_callback_set(ic->menu, NULL, NULL);
4683          e_object_del(E_OBJECT(ic->menu));
4684          ic->menu = NULL;
4685       }
4686     if (ic->dialog)
4687       {
4688          e_object_del(E_OBJECT(ic->dialog));
4689          ic->dialog = NULL;
4690       }
4691     if (ic->entry_dialog)
4692       {
4693          e_object_del(E_OBJECT(ic->entry_dialog));
4694          ic->entry_dialog = NULL;
4695       }
4696     if (ic->entry_widget)
4697       _e_fm2_icon_entry_widget_del(ic);
4698     if (ic->prop_dialog)
4699       {
4700          e_object_del(E_OBJECT(ic->prop_dialog));
4701          ic->prop_dialog = NULL;
4702       }
4703     eina_stringshare_del(ic->info.file);
4704     eina_stringshare_del(ic->info.mime);
4705     eina_stringshare_del(ic->info.label);
4706     eina_stringshare_del(ic->info.comment);
4707     eina_stringshare_del(ic->info.generic);
4708     eina_stringshare_del(ic->info.icon);
4709     eina_stringshare_del(ic->info.link);
4710     eina_stringshare_del(ic->info.real_link);
4711     eina_stringshare_del(ic->info.category);
4712     free(ic);
4713 }
4714
4715 static void
4716 _e_fm2_icon_realize(E_Fm2_Icon *ic)
4717 {
4718    if (ic->realized) return;
4719    /* actually create evas objects etc. */
4720    ic->realized = EINA_TRUE;
4721    evas_event_freeze(evas_object_evas_get(ic->sd->obj));
4722    ic->obj = edje_object_add(evas_object_evas_get(ic->sd->obj));
4723    edje_object_freeze(ic->obj);
4724    evas_object_smart_member_add(ic->obj, ic->sd->obj);
4725    evas_object_stack_below(ic->obj, ic->sd->drop);
4726    if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
4727      {
4728         const char *stacking;
4729
4730 //        if (ic->sd->config->icon.fixed.w)
4731 //        {
4732         if (ic->odd)
4733           _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
4734                                        "base/theme/widgets",
4735                                        "list_odd/fixed");
4736         else
4737           _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
4738                                        "base/theme/widgets",
4739                                        "list/fixed");
4740         stacking = edje_object_data_get(ic->obj, "stacking");
4741         if (stacking)
4742           {
4743              if (!strcmp(stacking, "below"))
4744                evas_object_stack_above(ic->obj, ic->sd->underlay);
4745              else if (!strcmp(stacking, "above"))
4746                evas_object_stack_below(ic->obj, ic->sd->drop);
4747           }
4748
4749 //        }
4750 //      else
4751 //        {
4752 //           if (ic->odd)
4753 //             _e_fm2_theme_edje_object_set(ic->sd, ic->obj, "base/theme/widgets",
4754 //                                     "list_odd/variable");
4755 //           else
4756 //             _e_fm2_theme_edje_object_set(ic->sd, ic->obj, "base/theme/widgets",
4757 //                                     "list/variable");
4758 //        }
4759      }
4760    else
4761      {
4762         if (ic->sd->config->icon.fixed.w)
4763           _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
4764                                        "base/theme/fileman",
4765                                        "icon/fixed");
4766         else
4767           _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
4768                                        "base/theme/fileman",
4769                                        "icon/variable");
4770      }
4771    _e_fm2_icon_label_set(ic, ic->obj);
4772    evas_object_clip_set(ic->obj, ic->sd->clip);
4773    evas_object_move(ic->obj,
4774                     ic->sd->x + ic->x - ic->sd->pos.x,
4775                     ic->sd->y + ic->y - ic->sd->pos.y);
4776    evas_object_resize(ic->obj, ic->w, ic->h);
4777
4778    evas_object_event_callback_add(ic->obj, EVAS_CALLBACK_MOUSE_DOWN, _e_fm2_cb_icon_mouse_down, ic);
4779    evas_object_event_callback_add(ic->obj, EVAS_CALLBACK_MOUSE_UP, _e_fm2_cb_icon_mouse_up, ic);
4780    evas_object_event_callback_add(ic->obj, EVAS_CALLBACK_MOUSE_MOVE, _e_fm2_cb_icon_mouse_move, ic);
4781
4782    _e_fm2_icon_icon_set(ic);
4783
4784    edje_object_thaw(ic->obj);
4785    evas_event_thaw(evas_object_evas_get(ic->sd->obj));
4786    evas_object_show(ic->obj);
4787
4788    if (ic->selected)
4789      {
4790         const char *selectraise;
4791
4792         /* FIXME: need new signal to INSTANTLY activate - no anim */
4793         /* FIXME: while listing dirs need to use icons in-place and not
4794          * unrealize and re-realize */
4795         edje_object_signal_emit(ic->obj, "e,state,selected", "e");
4796         edje_object_signal_emit(ic->obj_icon, "e,state,selected", "e");
4797         selectraise = edje_object_data_get(ic->obj, "selectraise");
4798         if ((selectraise) && (!strcmp(selectraise, "on")))
4799           evas_object_stack_below(ic->obj, ic->sd->drop);
4800      }
4801
4802    if (ic->info.removable)
4803      _e_fm2_icon_removable_update(ic);
4804 }
4805
4806 static void
4807 _e_fm2_icon_unrealize(E_Fm2_Icon *ic)
4808 {
4809    if (!ic->realized) return;
4810    /* delete evas objects */
4811    ic->realized = EINA_FALSE;
4812    evas_object_del(ic->obj);
4813    ic->obj = NULL;
4814    evas_object_del(ic->obj_icon);
4815    ic->obj_icon = NULL;
4816 }
4817
4818 static Eina_Bool
4819 _e_fm2_icon_visible(const E_Fm2_Icon *ic)
4820 {
4821    /* return if the icon is visible */
4822     if (
4823       ((ic->x - ic->sd->pos.x) < (ic->sd->w + OVERCLIP)) &&
4824       ((ic->x + ic->w - ic->sd->pos.x) > (-OVERCLIP)) &&
4825       ((ic->y - ic->sd->pos.y) < (ic->sd->h + OVERCLIP)) &&
4826       ((ic->y + ic->h - ic->sd->pos.y) > (-OVERCLIP))
4827       )
4828       return 1;
4829     return 0;
4830 }
4831
4832 static void
4833 _e_fm2_icon_label_set(E_Fm2_Icon *ic, Evas_Object *obj)
4834 {
4835    char buf[4096], *p;
4836    int len;
4837
4838    if (ic->info.label)
4839      {
4840         edje_object_part_text_set(obj, "e.text.label", ic->info.label);
4841         return;
4842      }
4843    if ((ic->sd->config->icon.extension.show) ||
4844        (S_ISDIR(ic->info.statinfo.st_mode)))
4845      edje_object_part_text_set(obj, "e.text.label", ic->info.file);
4846    else
4847      {
4848         /* remove extension. handle double extensions like .tar.gz too
4849          * also be fuzzy - up to 4 chars of extn is ok - eg .html but 5 or
4850          * more is considered part of the name
4851          */
4852           eina_strlcpy(buf, ic->info.file, sizeof(buf));
4853
4854           len = strlen(buf);
4855           p = strrchr(buf, '.');
4856           if ((p) && ((len - (p - buf)) < 6))
4857             {
4858                *p = 0;
4859
4860                len = strlen(buf);
4861                p = strrchr(buf, '.');
4862                if ((p) && ((len - (p - buf)) < 6)) *p = 0;
4863             }
4864           edje_object_part_text_set(obj, "e.text.label", buf);
4865      }
4866 }
4867
4868 static Evas_Object *
4869 _e_fm2_icon_icon_direct_set(E_Fm2_Icon *ic, Evas_Object *o, Evas_Smart_Cb gen_func, void *data, int force_gen)
4870 {
4871    Evas_Object *oic;
4872
4873    oic = e_fm2_icon_get(evas_object_evas_get(o), ic,
4874                         gen_func, data, force_gen, NULL);
4875    if (oic)
4876      {
4877         edje_object_part_swallow(o, "e.swallow.icon", oic);
4878         evas_object_show(oic);
4879      }
4880    return oic;
4881 }
4882
4883 static void
4884 _e_fm2_icon_icon_set(E_Fm2_Icon *ic)
4885 {
4886    if (!ic->realized) return;
4887    ic->obj_icon = _e_fm2_icon_icon_direct_set(ic, ic->obj,
4888                                               _e_fm2_cb_icon_thumb_gen,
4889                                               ic, 0);
4890 }
4891
4892 static void
4893 _e_fm2_icon_thumb(const E_Fm2_Icon *ic, Evas_Object *oic, int force)
4894 {
4895    if ((force) ||
4896        ((_e_fm2_icon_visible(ic)) &&
4897         (!ic->sd->queue) &&
4898         (!ic->sd->sort_idler) &&
4899         (!ic->sd->listing)))
4900      e_thumb_icon_begin(oic);
4901 }
4902
4903 static void
4904 _e_fm2_icon_select(E_Fm2_Icon *ic)
4905 {
4906    if (ic->selected) return;
4907    ic->selected = EINA_TRUE;
4908    ic->last_selected = EINA_TRUE;
4909    if (ic->realized)
4910      {
4911         const char *selectraise;
4912
4913         if (ic->sd->iop_icon)
4914           _e_fm2_icon_entry_widget_accept(ic->sd->iop_icon);
4915
4916         edje_object_signal_emit(ic->obj, "e,state,selected", "e");
4917         edje_object_signal_emit(ic->obj_icon, "e,state,selected", "e");
4918         evas_object_stack_below(ic->obj, ic->sd->drop);
4919         selectraise = edje_object_data_get(ic->obj, "selectraise");
4920         if ((selectraise) && (!strcmp(selectraise, "on")))
4921           evas_object_stack_below(ic->obj, ic->sd->drop);
4922      }
4923 }
4924
4925 static void
4926 _e_fm2_icon_deselect(E_Fm2_Icon *ic)
4927 {
4928    if (!ic->selected) return;
4929    ic->selected = EINA_FALSE;
4930    ic->last_selected = EINA_FALSE;
4931    if (ic->realized)
4932      {
4933         const char *stacking, *selectraise;
4934
4935         if (ic->entry_widget)
4936           _e_fm2_icon_entry_widget_accept(ic);
4937
4938         edje_object_signal_emit(ic->obj, "e,state,unselected", "e");
4939         edje_object_signal_emit(ic->obj_icon, "e,state,unselected", "e");
4940         stacking = edje_object_data_get(ic->obj, "stacking");
4941         selectraise = edje_object_data_get(ic->obj, "selectraise");
4942         if ((selectraise) && (!strcmp(selectraise, "on")))
4943           {
4944              if ((stacking) && (!strcmp(stacking, "below")))
4945                evas_object_stack_above(ic->obj, ic->sd->underlay);
4946           }
4947      }
4948 }
4949
4950 static const char *
4951 _e_fm2_icon_desktop_url_eval(const char *val)
4952 {
4953    const char *s;
4954    char *path, *p;
4955
4956    if (strlen(val) < 6) return NULL;
4957    if (strncmp(val, "file:", 5)) return NULL;
4958    path = (char *)val + 5;
4959    p = e_util_shell_env_path_eval(path);
4960    if (!p) return NULL;
4961    path = p;
4962    while (*path == '/') path++;
4963    path--;
4964    s = eina_stringshare_add(path);
4965    free(p);
4966    return s;
4967 }
4968
4969 static int
4970 _e_fm2_icon_desktop_load(E_Fm2_Icon *ic)
4971 {
4972    char buf[PATH_MAX];
4973    Efreet_Desktop *desktop;
4974
4975    if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
4976      return 0;
4977
4978    desktop = efreet_desktop_new(buf);
4979 //   printf("efreet_desktop_new(%s) = %p\n", buf, desktop);
4980    if (!desktop) goto error;
4981 //   if (desktop->type != EFREET_DESKTOP_TYPE_LINK) goto error;
4982
4983    ic->info.removable = EINA_FALSE;
4984    ic->info.removable_full = EINA_FALSE;
4985    ic->info.label = eina_stringshare_add(desktop->name);
4986    ic->info.generic = eina_stringshare_add(desktop->generic_name);
4987    ic->info.comment = eina_stringshare_add(desktop->comment);
4988    ic->info.icon = eina_stringshare_add(desktop->icon);
4989    if (desktop->url)
4990      ic->info.link = _e_fm2_icon_desktop_url_eval(desktop->url);
4991    if (desktop->x)
4992      {
4993         const char *type;
4994
4995         type = eina_hash_find(desktop->x, "X-Enlightenment-Type");
4996         if (type)
4997           {
4998              if (!strcmp(type, "Mount")) ic->info.mount = EINA_TRUE;
4999              else if (!strcmp(type, "Removable"))
5000                {
5001                   ic->info.removable = EINA_TRUE;
5002                   if ((!e_fm2_device_storage_find(ic->info.link)) &&
5003                       (!e_fm2_device_volume_find(ic->info.link)))
5004                     {
5005                        /* delete .desktop for non existing device */
5006                        if (ecore_file_remove(buf))
5007                          _e_fm2_live_file_del(ic->sd->obj, ic->info.file);
5008                        else /* ignore */
5009                          _e_fm2_file_del(ic->sd->obj, ic->info.file);
5010
5011                        efreet_desktop_free(desktop);
5012                        goto error;
5013                     }
5014                }
5015              type = eina_hash_find(desktop->x, "X-Enlightenment-Removable-State");
5016              if (type)
5017                {
5018                   if (!strcmp(type, "Full"))
5019                     ic->info.removable_full = EINA_TRUE;
5020                }
5021           }
5022      }
5023    /* FIXME: get category */
5024    ic->info.category = NULL;
5025    efreet_desktop_free(desktop);
5026
5027    return 1;
5028 error:
5029    eina_stringshare_del(ic->info.label);
5030    eina_stringshare_del(ic->info.comment);
5031    eina_stringshare_del(ic->info.generic);
5032    eina_stringshare_del(ic->info.icon);
5033    eina_stringshare_del(ic->info.link);
5034    eina_stringshare_del(ic->info.category);
5035    ic->info.label = NULL;
5036    ic->info.comment = NULL;
5037    ic->info.generic = NULL;
5038    ic->info.icon = NULL;
5039    ic->info.link = NULL;
5040    ic->info.category = NULL;
5041    //Hack
5042    if (!strncmp(ic->info.file, "|storage_", 9)) ecore_file_unlink(buf);
5043    return 0;
5044 }
5045
5046 /**************************/
5047 static E_Fm2_Region *
5048 _e_fm2_region_new(E_Fm2_Smart_Data *sd)
5049 {
5050    E_Fm2_Region *rg;
5051
5052    rg = E_NEW(E_Fm2_Region, 1);
5053    rg->sd = sd;
5054    return rg;
5055 }
5056
5057 static void
5058 _e_fm2_region_free(E_Fm2_Region *rg)
5059 {
5060    E_Fm2_Icon *ic;
5061
5062    EINA_LIST_FREE(rg->list, ic)
5063      ic->region = NULL;
5064    free(rg);
5065 }
5066
5067 static void
5068 _e_fm2_region_realize(E_Fm2_Region *rg)
5069 {
5070    const Eina_List *l;
5071    E_Fm2_Icon *ic;
5072
5073    if (rg->realized) return;
5074    /* actually create evas objects etc. */
5075    rg->realized = 1;
5076    edje_freeze();
5077    EINA_LIST_FOREACH(rg->list, l, ic) _e_fm2_icon_realize(ic);
5078    EINA_LIST_FOREACH(rg->list, l, ic)
5079      {
5080         if (ic->selected)
5081           evas_object_stack_below(ic->obj, ic->sd->drop);
5082      }
5083    edje_thaw();
5084 }
5085
5086 static void
5087 _e_fm2_region_unrealize(E_Fm2_Region *rg)
5088 {
5089    Eina_List *l;
5090    E_Fm2_Icon *ic;
5091
5092    if (!rg->realized) return;
5093    /* delete evas objects */
5094    rg->realized = 0;
5095    edje_freeze();
5096    EINA_LIST_FOREACH(rg->list, l, ic) _e_fm2_icon_unrealize(ic);
5097    edje_thaw();
5098 }
5099
5100 static int
5101 _e_fm2_region_visible(E_Fm2_Region *rg)
5102 {
5103    /* return if the icon is visible */
5104     if (
5105       ((rg->x - rg->sd->pos.x) < (rg->sd->w + OVERCLIP)) &&
5106       ((rg->x + rg->w - rg->sd->pos.x) > (-OVERCLIP)) &&
5107       ((rg->y - rg->sd->pos.y) < (rg->sd->h + OVERCLIP)) &&
5108       ((rg->y + rg->h - rg->sd->pos.y) > (-OVERCLIP))
5109       )
5110       return 1;
5111     return 0;
5112 }
5113
5114 static void
5115 _e_fm2_icon_make_visible(E_Fm2_Icon *ic)
5116 {
5117    if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
5118      {
5119         if (
5120           ((ic->y - ic->sd->pos.y) >= 0) &&
5121           ((ic->y + ic->h - ic->sd->pos.y) <= (ic->sd->h))
5122           )
5123           return;
5124         if ((ic->y - ic->sd->pos.y) < 0)
5125           e_fm2_pan_set(ic->sd->obj, ic->sd->pos.x, ic->y);
5126         else
5127           e_fm2_pan_set(ic->sd->obj, ic->sd->pos.x, ic->y - ic->sd->h + ic->h);
5128      }
5129    else
5130      {
5131         Evas_Coord x, y;
5132
5133         if (
5134           ((ic->y - ic->sd->pos.y) >= 0) &&
5135           ((ic->y + ic->h/* + ICON_BOTTOM_SPACE*/ - ic->sd->pos.y) <= (ic->sd->h)) &&
5136           ((ic->x - ic->sd->pos.x) >= 0) &&
5137           ((ic->x + ic->w - ic->sd->pos.x) <= (ic->sd->w))
5138           )
5139           return;
5140         x = ic->sd->pos.x;
5141         if ((ic->x - ic->sd->pos.x) < 0)
5142           x = ic->x;
5143         else if ((ic->x + ic->w - ic->sd->pos.x) > (ic->sd->w))
5144           x = ic->x + ic->w - ic->sd->w;
5145         y = ic->sd->pos.y;
5146         if ((ic->y - ic->sd->pos.y) < 0)
5147           y = ic->y;
5148         else if ((ic->y + ic->h/* + ICON_BOTTOM_SPACE*/ - ic->sd->pos.y) > (ic->sd->h))
5149           y = ic->y + ic->h/* + ICON_BOTTOM_SPACE*/ - ic->sd->h;
5150         e_fm2_pan_set(ic->sd->obj, x, y);
5151      }
5152    evas_object_smart_callback_call(ic->sd->obj, "pan_changed", NULL);
5153 }
5154
5155 static void
5156 _e_fm2_icon_desel_any(Evas_Object *obj)
5157 {
5158    E_Fm2_Smart_Data *sd;
5159    const Eina_List *l;
5160    E_Fm2_Icon *ic;
5161
5162    sd = evas_object_smart_data_get(obj);
5163    if (!sd) return;
5164    EINA_LIST_FOREACH(sd->icons, l, ic)
5165      {
5166         if (ic->selected) _e_fm2_icon_deselect(ic);
5167      }
5168 }
5169
5170 static E_Fm2_Icon *
5171 _e_fm2_icon_first_selected_find(Evas_Object *obj)
5172 {
5173    E_Fm2_Smart_Data *sd;
5174    const Eina_List *l;
5175    E_Fm2_Icon *ic;
5176
5177    sd = evas_object_smart_data_get(obj);
5178    if (!sd) return NULL;
5179    EINA_LIST_FOREACH(sd->icons, l, ic)
5180      {
5181         if (ic->selected) return ic;
5182      }
5183    return NULL;
5184 }
5185
5186 static void
5187 _e_fm2_icon_sel_first(Evas_Object *obj)
5188 {
5189    E_Fm2_Smart_Data *sd;
5190    E_Fm2_Icon *ic;
5191
5192    sd = evas_object_smart_data_get(obj);
5193    if (!sd) return;
5194    if (!sd->icons) return;
5195    _e_fm2_icon_desel_any(obj);
5196    ic = eina_list_data_get(sd->icons);
5197    _e_fm2_icon_select(ic);
5198    evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
5199    _e_fm2_icon_make_visible(ic);
5200 }
5201
5202 static void
5203 _e_fm2_icon_sel_last(Evas_Object *obj)
5204 {
5205    E_Fm2_Smart_Data *sd;
5206    E_Fm2_Icon *ic;
5207
5208    sd = evas_object_smart_data_get(obj);
5209    if (!sd) return;
5210    if (!sd->icons) return;
5211    _e_fm2_icon_desel_any(obj);
5212    ic = eina_list_data_get(eina_list_last(sd->icons));
5213    _e_fm2_icon_select(ic);
5214    evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
5215    _e_fm2_icon_make_visible(ic);
5216 }
5217
5218 static void
5219 _e_fm2_icon_sel_any(Evas_Object *obj)
5220 {
5221    E_Fm2_Smart_Data *sd;
5222    E_Fm2_Icon *ic;
5223    Eina_List *l;
5224
5225    sd = evas_object_smart_data_get(obj);
5226    if (!sd) return;
5227    if (!sd->icons) return;
5228    EINA_LIST_FOREACH(sd->icons, l, ic)
5229      if (!ic->selected) _e_fm2_icon_select(ic);
5230 }
5231
5232 static E_Fm2_Icon *
5233 _e_fm2_icon_next_find(Evas_Object *obj, int next, int (*match_func)(E_Fm2_Icon *ic, void *data), void *data)
5234 {
5235    E_Fm2_Smart_Data *sd;
5236    Eina_List *l;
5237    E_Fm2_Icon *ic, *ic_next;
5238    char view_mode;
5239    int x = 0, y = 0, custom = 0;
5240    int dist, min = 65535;
5241
5242    sd = evas_object_smart_data_get(obj);
5243    if (!sd) return NULL;
5244    if (!sd->icons) return NULL;
5245
5246    view_mode = _e_fm2_view_mode_get(sd);
5247    if ((view_mode == E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS) ||
5248        (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
5249        (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
5250      custom = 1;
5251
5252    ic_next = NULL;
5253    /* find selected item / current position */
5254    EINA_LIST_FOREACH(sd->icons, l, ic)
5255      {
5256         if (ic->selected)
5257           {
5258              if (!custom && !match_func)
5259                {
5260                   ic_next = ic;
5261                }
5262              else
5263                {
5264                   x = ic->x;
5265                   y = ic->y;
5266                }
5267              break;
5268           }
5269      }
5270    if (next && (custom || match_func))
5271      {
5272         /* find next item in custom grid, or list/grid when match
5273            func is given */
5274           if (next == 1)
5275             {
5276                EINA_LIST_FOREACH(sd->icons, l, ic)
5277                  {
5278                     if ((ic->x > x) &&
5279                         (custom ? (ic->y >= y) : (ic->y == y)) &&
5280                         (!match_func || match_func(ic, data)))
5281                       {
5282                          dist = 2 * (ic->y - y) + (ic->x - x);
5283                          if (dist < min)
5284                            {
5285                               min = dist;
5286                               ic_next = ic;
5287                            }
5288                       }
5289                  }
5290      /* no next item was found in row go down and begin */
5291                if (!ic_next)
5292                  {
5293                     EINA_LIST_FOREACH(sd->icons, l, ic)
5294                       {
5295                          if ((ic->y > y) && (!match_func || match_func(ic, data)))
5296                            {
5297                               dist = 2 * (abs(ic->y - y)) + ic->x;
5298                               if (dist < min)
5299                                 {
5300                                    min = dist;
5301                                    ic_next = ic;
5302                                 }
5303                            }
5304                       }
5305                  }
5306             }
5307           /* find previous item */
5308           else if (next == -1)
5309             {
5310                EINA_LIST_FOREACH(sd->icons, l, ic)
5311                  {
5312                     if ((ic->x < x) &&
5313                         (custom ? (ic->y <= y) : (ic->y == y)) &&
5314                         (!match_func || match_func(ic, data)))
5315                       {
5316                          dist = 2 * (y - ic->y) + (x - ic->x);
5317                          if (dist < min)
5318                            {
5319                               min = dist;
5320                               ic_next = ic;
5321                            }
5322                       }
5323                  }
5324      /* no prev item was found in row go to end and up */
5325                if (!ic_next)
5326                  {
5327                     EINA_LIST_FOREACH(sd->icons, l, ic)
5328                       {
5329                          if ((ic->y < y) && (!match_func || match_func(ic, data)))
5330                            {
5331                               dist = 2 * (abs(ic->y - y)) - ic->x;
5332                               if (dist < min)
5333                                 {
5334                                    min = dist;
5335                                    ic_next = ic;
5336                                 }
5337                            }
5338                       }
5339                  }
5340             }
5341      }
5342    /* not custom, items are arranged in list order */
5343    else if (ic_next)
5344      {
5345         if (next == 1)
5346           {
5347              if (!eina_list_next(l)) return NULL;
5348              ic_next = eina_list_data_get(eina_list_next(l));
5349           }
5350         if (next == -1)
5351           {
5352              if (!eina_list_prev(l)) return NULL;
5353              ic_next = eina_list_data_get(eina_list_prev(l));
5354           }
5355      }
5356
5357    return ic_next;
5358 }
5359
5360 static void
5361 _e_fm2_icon_sel_prev(Evas_Object *obj)
5362 {
5363    E_Fm2_Icon *ic_prev;
5364
5365    ic_prev = _e_fm2_icon_next_find(obj, -1, NULL, NULL);
5366
5367    if (!ic_prev)
5368      {
5369         /* FIXME this is not the bottomright item for custom grid */
5370          _e_fm2_icon_sel_last(obj);
5371          return;
5372      }
5373    _e_fm2_icon_desel_any(obj);
5374    _e_fm2_icon_select(ic_prev);
5375    evas_object_smart_callback_call(obj, "selection_change", NULL); /*XXX sd->obj*/
5376    _e_fm2_icon_make_visible(ic_prev);
5377 }
5378
5379 static void
5380 _e_fm2_icon_sel_next(Evas_Object *obj)
5381 {
5382    E_Fm2_Icon *ic_next;
5383
5384    ic_next = _e_fm2_icon_next_find(obj, 1, NULL, NULL);
5385    if (!ic_next)
5386      {
5387         /* FIXME this is not the topleft item for custom grid */
5388          _e_fm2_icon_sel_first(obj);
5389          return;
5390      }
5391    _e_fm2_icon_desel_any(obj);
5392    _e_fm2_icon_select(ic_next);
5393    evas_object_smart_callback_call(obj, "selection_change", NULL);
5394    _e_fm2_icon_make_visible(ic_next);
5395 }
5396
5397 static void
5398 _e_fm2_icon_sel_down(Evas_Object *obj)
5399 {
5400    E_Fm2_Smart_Data *sd;
5401    Eina_List *l;
5402    E_Fm2_Icon *ic, *ic_down;
5403    int found, x = -1, y = -1, custom = 0;
5404    int dist, min = 65535;
5405    char view_mode;
5406
5407    sd = evas_object_smart_data_get(obj);
5408    if (!sd) return;
5409    if (!sd->icons) return;
5410
5411    view_mode = _e_fm2_view_mode_get(sd);
5412    if ((view_mode == E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS) ||
5413        (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
5414        (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
5415      custom = 1;
5416
5417    ic_down = NULL;
5418    found = 0;
5419
5420    EINA_LIST_FOREACH(sd->icons, l, ic)
5421      {
5422         if (!found)
5423           {
5424              if (ic->selected)
5425                {
5426                   found = 1;
5427                   x = ic->x;
5428                   y = ic->y;
5429                   if (custom) break;
5430                }
5431           }
5432         else if (ic->y > y)
5433           {
5434              dist = (abs(ic->x - x)) + (ic->y - y) * 2;
5435              if (dist < min)
5436                {
5437                   min = dist;
5438                   ic_down = ic;
5439                }
5440              else break;
5441           }
5442      }
5443
5444    if (custom)
5445      {
5446         EINA_LIST_FOREACH(sd->icons, l, ic)
5447           {
5448              if (ic->y > y)
5449                {
5450                   dist = (abs(ic->x - x)) + (ic->y - y) * 2;
5451                   if (dist < min)
5452                     {
5453                        min = dist;
5454                        ic_down = ic;
5455                     }
5456                }
5457           }
5458      }
5459
5460    if (!ic_down)
5461      {
5462         if (!custom) _e_fm2_icon_sel_next(obj);
5463         return;
5464      }
5465    _e_fm2_icon_desel_any(obj);
5466    _e_fm2_icon_select(ic_down);
5467    evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
5468    _e_fm2_icon_make_visible(ic_down);
5469 }
5470
5471 static void
5472 _e_fm2_icon_sel_up(Evas_Object *obj)
5473 {
5474    E_Fm2_Smart_Data *sd;
5475    Eina_List *l;
5476    E_Fm2_Icon *ic, *ic_up;
5477    int found = 0, x = 0, y = 0, custom = 0;
5478    int dist, min = 65535;
5479    char view_mode;
5480
5481    sd = evas_object_smart_data_get(obj);
5482    if (!sd) return;
5483    if (!sd->icons) return;
5484
5485    view_mode = _e_fm2_view_mode_get(sd);
5486
5487    if ((view_mode == E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS) ||
5488        (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
5489        (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
5490      custom = 1;
5491
5492    ic_up = NULL;
5493
5494    EINA_LIST_REVERSE_FOREACH(sd->icons, l, ic)
5495    {
5496       if (!found)
5497         {
5498            if (ic->selected)
5499              {
5500                 found = 1;
5501                 x = ic->x;
5502                 y = ic->y;
5503                 if (custom) break;
5504              }
5505         }
5506       else if (ic->y < y)
5507         {
5508            dist = (abs(ic->x - x)) + (y - ic->y) * 2;
5509            if (dist < min)
5510              {
5511                 min = dist;
5512                 ic_up = ic;
5513              }
5514            else break;
5515         }
5516    }
5517
5518    if (custom && found)
5519      {
5520         EINA_LIST_FOREACH(sd->icons, l, ic)
5521           {
5522              if (!ic->selected && ic->y < y)
5523                {
5524                   dist = (abs(ic->x - x)) + (y - ic->y) * 2;
5525                   if (dist < min)
5526                     {
5527                        min = dist;
5528                        ic_up = ic;
5529                     }
5530                }
5531           }
5532      }
5533
5534    if (!ic_up)
5535      {
5536         if (!custom) _e_fm2_icon_sel_prev(obj);
5537         return;
5538      }
5539    _e_fm2_icon_desel_any(obj);
5540    _e_fm2_icon_select(ic_up);
5541    evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
5542    _e_fm2_icon_make_visible(ic_up);
5543 }
5544
5545 /* FIXME: prototype */
5546 static void
5547 _e_fm2_typebuf_show(Evas_Object *obj)
5548 {
5549    E_Fm2_Smart_Data *sd;
5550
5551    sd = evas_object_smart_data_get(obj);
5552    if (!sd) return;
5553    E_FREE(sd->typebuf.buf);
5554    sd->typebuf.buf = strdup("");
5555    edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", sd->typebuf.buf);
5556    edje_object_signal_emit(sd->overlay, "e,state,typebuf,start", "e");
5557    sd->typebuf_visible = EINA_TRUE;
5558 }
5559
5560 static void
5561 _e_fm2_typebuf_hide(Evas_Object *obj)
5562 {
5563    E_Fm2_Smart_Data *sd;
5564
5565    sd = evas_object_smart_data_get(obj);
5566    if (!sd) return;
5567    E_FREE(sd->typebuf.buf);
5568    edje_object_signal_emit(sd->overlay, "e,state,typebuf,stop", "e");
5569    sd->typebuf_visible = EINA_FALSE;
5570 }
5571
5572 #if 0
5573 static void
5574 _e_fm2_typebuf_history_prev(Evas_Object *obj)
5575 {
5576    E_Fm2_Smart_Data *sd;
5577
5578    sd = evas_object_smart_data_get(obj);
5579    if (!sd) return;
5580    /* FIXME: do */
5581 }
5582
5583 static void
5584 _e_fm2_typebuf_history_next(Evas_Object *obj)
5585 {
5586    E_Fm2_Smart_Data *sd;
5587
5588    sd = evas_object_smart_data_get(obj);
5589    if (!sd) return;
5590    /* FIXME: do */
5591 }
5592
5593 #endif
5594
5595 static int
5596 _e_fm2_inplace_open(const E_Fm2_Icon *ic)
5597 {
5598    char buf[PATH_MAX];
5599
5600    if (!((S_ISDIR(ic->info.statinfo.st_mode)) &&
5601          (ic->sd->config->view.open_dirs_in_place) &&
5602          (!ic->sd->config->view.no_subdir_jump)))
5603      return 0;
5604
5605    if (!_e_fm2_icon_path(ic, buf, sizeof(buf)))
5606      return -1;
5607
5608    e_fm2_path_set(ic->sd->obj, ic->sd->dev, buf);
5609    return 1;
5610 }
5611
5612 static void
5613 _e_fm2_typebuf_run(Evas_Object *obj)
5614 {
5615    E_Fm2_Icon *ic;
5616
5617    _e_fm2_typebuf_hide(obj);
5618    ic = _e_fm2_icon_first_selected_find(obj);
5619    if (ic)
5620      {
5621         if (_e_fm2_inplace_open(ic) == 0)
5622           evas_object_smart_callback_call(ic->sd->obj, "selected", NULL);
5623      }
5624 }
5625
5626 static int
5627 _e_fm2_typebuf_match_func(E_Fm2_Icon *ic, void *data)
5628 {
5629    char *tb = data;
5630    return ((ic->info.label) &&
5631            (e_util_glob_case_match(ic->info.label, tb))) ||
5632           ((ic->info.file) &&
5633            (e_util_glob_case_match(ic->info.file, tb)));
5634 }
5635
5636 static Eina_Bool
5637 _e_fm_typebuf_timer_cb(void *data)
5638 {
5639    Evas_Object *obj = data;
5640    E_Fm2_Smart_Data *sd;
5641
5642    if (!data) return ECORE_CALLBACK_CANCEL;
5643    sd = evas_object_smart_data_get(obj);
5644    if (!sd) return ECORE_CALLBACK_CANCEL;
5645
5646    if (!sd->typebuf_visible) return ECORE_CALLBACK_CANCEL;
5647
5648    _e_fm2_typebuf_hide(obj);
5649    sd->typebuf.timer = NULL;
5650
5651    return ECORE_CALLBACK_CANCEL;
5652 }
5653
5654 static void
5655 _e_fm2_typebuf_match(Evas_Object *obj, int next)
5656 {
5657    E_Fm2_Smart_Data *sd;
5658    E_Fm2_Icon *ic, *ic_match = NULL;
5659    Eina_List *l;
5660    char *tb;
5661    int tblen;
5662
5663    sd = evas_object_smart_data_get(obj);
5664    if (!sd) return;
5665    if (!sd->typebuf.buf) return;
5666    if (!sd->icons) return;
5667
5668    tblen = strlen(sd->typebuf.buf);
5669    tb = malloc(tblen + 2);
5670    if (!tb) return;
5671    memcpy(tb, sd->typebuf.buf, tblen);
5672    tb[tblen] = '*';
5673    tb[tblen + 1] = '\0';
5674
5675    if (!next)
5676      {
5677         EINA_LIST_FOREACH(sd->icons, l, ic)
5678           {
5679              if (_e_fm2_typebuf_match_func(ic, tb))
5680                {
5681                   ic_match = ic;
5682                   break;
5683                }
5684           }
5685      }
5686    else
5687      {
5688         ic_match = _e_fm2_icon_next_find(obj, next, &_e_fm2_typebuf_match_func, tb);
5689      }
5690
5691    if (ic_match)
5692      {
5693         _e_fm2_icon_desel_any(obj);
5694         _e_fm2_icon_select(ic_match);
5695         evas_object_smart_callback_call(obj, "selection_change", NULL);
5696         _e_fm2_icon_make_visible(ic_match);
5697      }
5698
5699    free(tb);
5700
5701    if (sd->typebuf.timer)
5702      {
5703         ecore_timer_del(sd->typebuf.timer);
5704      }
5705
5706    sd->typebuf.timer = ecore_timer_add(5.0, _e_fm_typebuf_timer_cb, obj);
5707 }
5708
5709 static void
5710 _e_fm2_typebuf_complete(Evas_Object *obj)
5711 {
5712    E_Fm2_Smart_Data *sd;
5713
5714    sd = evas_object_smart_data_get(obj);
5715    if (!sd) return;
5716    /* FIXME: do */
5717    _e_fm2_typebuf_match(obj, 0);
5718 }
5719
5720 static void
5721 _e_fm2_typebuf_char_append(Evas_Object *obj, const char *ch)
5722 {
5723    E_Fm2_Smart_Data *sd;
5724    char *ts;
5725
5726    sd = evas_object_smart_data_get(obj);
5727    if (!sd) return;
5728    if (!sd->typebuf.buf) return;
5729    ts = malloc(strlen(sd->typebuf.buf) + strlen(ch) + 1);
5730    if (!ts) return;
5731    strcpy(ts, sd->typebuf.buf);
5732    strcat(ts, ch);
5733    free(sd->typebuf.buf);
5734    sd->typebuf.buf = ts;
5735    _e_fm2_typebuf_match(obj, 0);
5736    edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", sd->typebuf.buf);
5737 }
5738
5739 static void
5740 _e_fm2_typebuf_char_backspace(Evas_Object *obj)
5741 {
5742    E_Fm2_Smart_Data *sd;
5743    char *ts;
5744    int len, p, dec;
5745
5746    sd = evas_object_smart_data_get(obj);
5747    if (!sd) return;
5748    if (!sd->typebuf.buf) return;
5749    len = strlen(sd->typebuf.buf);
5750    if (len == 0)
5751      {
5752         _e_fm2_typebuf_hide(obj);
5753         return;
5754      }
5755    p = evas_string_char_prev_get(sd->typebuf.buf, len, &dec);
5756    if (p >= 0) sd->typebuf.buf[p] = EINA_FALSE;
5757    ts = strdup(sd->typebuf.buf);
5758    if (!ts) return;
5759    free(sd->typebuf.buf);
5760    sd->typebuf.buf = ts;
5761    _e_fm2_typebuf_match(obj, 0);
5762    edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", sd->typebuf.buf);
5763 }
5764
5765 /**************************/
5766
5767 /* FIXME: prototype + reposition + implement */
5768 static void
5769 _e_fm2_dnd_drop_configure(Evas_Object *obj)
5770 {
5771    E_Fm2_Smart_Data *sd;
5772
5773    sd = evas_object_smart_data_get(obj);
5774    if (!sd) return;
5775    if (!sd->drop_icon) return;
5776    if (sd->drop_after == -1)
5777      {
5778         evas_object_move(sd->drop_in,
5779                          sd->x + sd->drop_icon->x - sd->pos.x,
5780                          sd->y + sd->drop_icon->y - sd->pos.y);
5781         evas_object_resize(sd->drop_in, sd->drop_icon->w, sd->drop_icon->h);
5782      }
5783    else if (sd->drop_after)
5784      {
5785         evas_object_move(sd->drop,
5786                          sd->x + sd->drop_icon->x - sd->pos.x,
5787                          sd->y + sd->drop_icon->y - sd->pos.y + sd->drop_icon->h - 1);
5788         evas_object_resize(sd->drop, sd->drop_icon->w, 2);
5789      }
5790    else
5791      {
5792         evas_object_move(sd->drop,
5793                          sd->x + sd->drop_icon->x - sd->pos.x,
5794                          sd->y + sd->drop_icon->y - sd->pos.y - 1);
5795         evas_object_resize(sd->drop, sd->drop_icon->w, 2);
5796      }
5797 }
5798
5799 /* FIXME: prototype + reposition + implement */
5800 static void
5801 _e_fm2_dnd_drop_all_show(Evas_Object *obj)
5802 {
5803    E_Fm2_Smart_Data *sd;
5804
5805    sd = evas_object_smart_data_get(obj);
5806    if (!sd) return;
5807    if (sd->drop_show)
5808      {
5809         edje_object_signal_emit(sd->drop, "e,state,unselected", "e");
5810         sd->drop_show = EINA_FALSE;
5811      }
5812    if (sd->drop_in_show)
5813      {
5814         edje_object_signal_emit(sd->drop_in, "e,state,unselected", "e");
5815         sd->drop_in_show = EINA_FALSE;
5816      }
5817    if (!sd->drop_all)
5818      {
5819         edje_object_signal_emit(sd->overlay, "e,state,drop,start", "e");
5820         sd->drop_all = EINA_TRUE;
5821      }
5822    sd->drop_icon = NULL;
5823    sd->drop_after = EINA_FALSE;
5824 }
5825
5826 /* FIXME: prototype + reposition + implement */
5827 static void
5828 _e_fm2_dnd_drop_all_hide(Evas_Object *obj)
5829 {
5830    E_Fm2_Smart_Data *sd;
5831
5832    sd = evas_object_smart_data_get(obj);
5833    if (!sd) return;
5834    if (sd->drop_all)
5835      {
5836         edje_object_signal_emit(sd->overlay, "e,state,drop,stop", "e");
5837         sd->drop_all = EINA_FALSE;
5838      }
5839 }
5840
5841 /* FIXME: prototype + reposition + implement */
5842 static void
5843 _e_fm2_dnd_drop_show(E_Fm2_Icon *ic, int after)
5844 {
5845    int emit = 0;
5846
5847    if ((ic->sd->drop_icon == ic) &&
5848        (ic->sd->drop_after == after)) return;
5849    if (((ic->sd->drop_icon) && (!ic)) ||
5850        ((!ic->sd->drop_icon) && (ic)) ||
5851        ((after < 0) && (ic->sd->drop_after >= 0)) ||
5852        ((after >= 0) && (ic->sd->drop_after < 0)))
5853      emit = 1;
5854    ic->sd->drop_icon = ic;
5855    ic->sd->drop_after = after;
5856    if (emit)
5857      {
5858         if (ic->sd->drop_after != -1)
5859           {
5860              edje_object_signal_emit(ic->sd->drop_in, "e,state,unselected", "e");
5861              edje_object_signal_emit(ic->sd->drop, "e,state,selected", "e");
5862              ic->sd->drop_in_show = EINA_FALSE;
5863              ic->sd->drop_show = EINA_TRUE;
5864           }
5865         else
5866           {
5867              edje_object_signal_emit(ic->sd->drop, "e,state,unselected", "e");
5868              edje_object_signal_emit(ic->sd->drop_in, "e,state,selected", "e");
5869              ic->sd->drop_in_show = EINA_TRUE;
5870              ic->sd->drop_show = EINA_FALSE;
5871           }
5872      }
5873    _e_fm2_dnd_drop_all_hide(ic->sd->obj);
5874    _e_fm2_dnd_drop_configure(ic->sd->obj);
5875 }
5876
5877 /* FIXME: prototype + reposition + implement */
5878 static void
5879 _e_fm2_dnd_drop_hide(Evas_Object *obj)
5880 {
5881    E_Fm2_Smart_Data *sd;
5882
5883    sd = evas_object_smart_data_get(obj);
5884    if (!sd) return;
5885    if (sd->drop_show)
5886      {
5887         edje_object_signal_emit(sd->drop, "e,state,unselected", "e");
5888         sd->drop_show = EINA_FALSE;
5889      }
5890    if (sd->drop_in_show)
5891      {
5892         edje_object_signal_emit(sd->drop_in, "e,state,unselected", "e");
5893         sd->drop_in_show = EINA_FALSE;
5894      }
5895    sd->drop_icon = NULL;
5896    sd->drop_after = EINA_FALSE;
5897 }
5898
5899 /* FIXME: prototype + reposition + implement */
5900 static void
5901 _e_fm2_dnd_finish(Evas_Object *obj, int refresh)
5902 {
5903    E_Fm2_Smart_Data *sd;
5904    E_Fm2_Icon *ic;
5905    const Eina_List *l;
5906
5907    sd = evas_object_smart_data_get(obj);
5908    if (!sd) return;
5909    if (!sd->drag) return;
5910    sd->drag = EINA_FALSE;
5911    EINA_LIST_FOREACH(sd->icons, l, ic)
5912      {
5913         ic->drag.dnd = EINA_FALSE;
5914         ic->drag.src = EINA_FALSE;
5915         if (ic->obj) evas_object_show(ic->obj);
5916         if (ic->obj_icon) evas_object_show(ic->obj_icon);
5917      }
5918    if (refresh) e_fm2_refresh(obj);
5919 }
5920
5921 static void
5922 _e_fm2_cb_dnd_enter(void *data __UNUSED__, const char *type, void *event)
5923 {
5924    E_Event_Dnd_Enter *ev;
5925
5926    if (type != _e_fm2_mime_text_uri_list) return;
5927    ev = (E_Event_Dnd_Enter *)event;
5928    e_drop_handler_action_set(ev->action);
5929 }
5930
5931 static void
5932 _e_fm2_cb_dnd_move(void *data, const char *type, void *event)
5933 {
5934    E_Fm2_Smart_Data *sd;
5935    E_Event_Dnd_Move *ev;
5936    E_Fm2_Icon *ic;
5937    Eina_List *l;
5938
5939    sd = data;
5940    if (type != _e_fm2_mime_text_uri_list) return;
5941    ev = (E_Event_Dnd_Move *)event;
5942    e_drop_handler_action_set(ev->action);
5943    EINA_LIST_FOREACH(sd->icons, l, ic)
5944      {
5945         if (E_INSIDE(ev->x, ev->y, ic->x - ic->sd->pos.x, ic->y - ic->sd->pos.y, ic->w, ic->h))
5946           {
5947              if (ic->drag.dnd) continue;
5948              /* if list view */
5949              if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
5950                {
5951      /* if there is a .order file - we can re-order files */
5952                    if (ic->sd->order_file)
5953                      {
5954      /* if dir: */
5955                          if ((S_ISDIR(ic->info.statinfo.st_mode)) &&
5956                              (!ic->sd->config->view.no_subdir_drop))
5957                            {
5958      /* if bottom 25% or top 25% then insert between prev or next */
5959                                /* if in middle 50% then put in dir */
5960                                 if (ev->y <= (ic->y - ic->sd->pos.y + (ic->h / 4)))
5961                                   {
5962                                      _e_fm2_dnd_drop_show(ic, 0);
5963                                   }
5964                                 else if (ev->y > (ic->y - ic->sd->pos.y + ((ic->h * 3) / 4)))
5965                                   {
5966                                      _e_fm2_dnd_drop_show(ic, 1);
5967                                   }
5968                                 else
5969                                   {
5970                                      _e_fm2_dnd_drop_show(ic, -1);
5971                                   }
5972                            }
5973                          else
5974                            {
5975      /* if top 50% or bottom 50% then insert between prev or next */
5976                                if (ev->y <= (ic->y - ic->sd->pos.y + (ic->h / 2)))
5977                                  _e_fm2_dnd_drop_show(ic, 0);
5978                                else
5979                                  _e_fm2_dnd_drop_show(ic, 1);
5980                            }
5981                      }
5982      /* if we are over subdirs or files */
5983                    else
5984                      {
5985      /*
5986       * if it's over a dir - hilight as it will be dropped info
5987       * FIXME: should there be a separate highlighting function for files?
5988       * */
5989                           if (!(S_ISDIR(ic->info.statinfo.st_mode)) ||
5990                               (!ic->sd->config->view.no_subdir_drop))
5991                             _e_fm2_dnd_drop_show(ic, -1);
5992                      }
5993                }
5994              else
5995                {
5996      /* if it's over a dir - hilight as it will be dropped in */
5997                    if (!(S_ISDIR(ic->info.statinfo.st_mode)) ||
5998                        (!ic->sd->config->view.no_subdir_drop))
5999                      _e_fm2_dnd_drop_show(ic, -1);
6000                }
6001              return;
6002           }
6003      }
6004    /* FIXME: not over icon - is it within the fm view? if so drop there */
6005    if (E_INSIDE(ev->x, ev->y, 0, 0, sd->w, sd->h))
6006      {
6007         /* if listview - it is now after last file */
6008          if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST)
6009            {
6010      /* if there is a .order file - we can re-order files */
6011                if (sd->order_file)
6012                  {
6013                     ic = eina_list_data_get(eina_list_last(sd->icons));
6014                     if (ic)
6015                       {
6016                          if (!ic->drag.dnd)
6017                            _e_fm2_dnd_drop_show(ic, 1);
6018                          else
6019                            _e_fm2_dnd_drop_all_show(sd->obj);
6020                       }
6021                     else
6022                       _e_fm2_dnd_drop_all_show(sd->obj);
6023                  }
6024                else
6025                  _e_fm2_dnd_drop_all_show(sd->obj);
6026            }
6027          else
6028            _e_fm2_dnd_drop_all_show(sd->obj);
6029          return;
6030      }
6031    /* outside fm view */
6032    _e_fm2_dnd_drop_hide(sd->obj);
6033 }
6034
6035 static void
6036 _e_fm2_cb_dnd_leave(void *data, const char *type, void *event __UNUSED__)
6037 {
6038    E_Fm2_Smart_Data *sd;
6039
6040    sd = data;
6041    if (type != _e_fm2_mime_text_uri_list) return;
6042    _e_fm2_dnd_drop_hide(sd->obj);
6043    _e_fm2_dnd_drop_all_hide(sd->obj);
6044 }
6045
6046 static void
6047 _e_fm_file_reorder(const char *file, const char *dst, const char *relative, int after)
6048 {
6049    unsigned int length = strlen(file) + 1 + strlen(dst) + 1 + strlen(relative) + 1 + sizeof(after);
6050    char *data, *p;
6051
6052    data = alloca(length);
6053    if (!data) return;
6054
6055    p = data;
6056
6057 #define P(s) memcpy(p, s, strlen(s) + 1); p += strlen(s) + 1
6058    P(file);
6059    P(dst);
6060    P(relative);
6061 #undef P
6062
6063    memcpy(p, &after, sizeof(int));
6064
6065    _e_fm_client_send_new(E_FM_OP_REORDER, data, length);
6066 }
6067
6068 static void
6069 _e_fm_icon_save_position(const char *file, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
6070 {
6071    E_Fm2_Custom_File *cf, new;
6072
6073    if (!file) return;
6074
6075    cf = e_fm2_custom_file_get(file);
6076    if (!cf)
6077      {
6078         memset(&new, 0, sizeof(E_Fm2_Custom_File));
6079         cf = &new;
6080      }
6081
6082    cf->geom.x = x;
6083    cf->geom.y = y;
6084    cf->geom.res_w = w;
6085    cf->geom.res_h = h;
6086
6087    cf->geom.valid = 1;
6088    e_fm2_custom_file_set(file, cf);
6089    e_fm2_custom_file_flush();
6090 }
6091
6092 struct e_fm_drop_menu_data
6093 {
6094    Evas_Object *e_fm;
6095    char *args;
6096 };
6097
6098 static void
6099 _e_fm_drop_menu_copy_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
6100 {
6101    struct e_fm_drop_menu_data *d = data;
6102    if (!d) return;
6103    _e_fm_client_file_copy(d->args, d->e_fm);
6104 }
6105
6106 static void
6107 _e_fm_drop_menu_move_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
6108 {
6109    struct e_fm_drop_menu_data *d = data;
6110    if (!d) return;
6111    _e_fm_client_file_move(d->args, d->e_fm);
6112 }
6113
6114 static void
6115 _e_fm_drop_menu_symlink_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
6116 {
6117    struct e_fm_drop_menu_data *d = data;
6118    if (!d) return;
6119    _e_fm_client_file_symlink(d->args, d->e_fm);
6120 }
6121
6122 static void
6123 _e_fm_drop_menu_abort_cb(void *data __UNUSED__, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
6124 {
6125 }
6126
6127 static void
6128 _e_fm_drop_menu_free(void *data)
6129 {
6130    struct e_fm_drop_menu_data *d = e_object_data_get(data);
6131    if (!d) return;
6132    free(d->args);
6133    free(d);
6134 }
6135
6136 static void
6137 _e_fm_drop_menu(char *args, Evas_Object *e_fm)
6138 {
6139    struct e_fm_drop_menu_data *d;
6140    E_Menu *menu = e_menu_new();
6141    E_Menu_Item *item = NULL;
6142    E_Manager *man = NULL;
6143    E_Container *con = NULL;
6144    E_Zone *zone = NULL;
6145    int x, y;
6146
6147    if (!menu) return;
6148
6149    d = malloc(sizeof(*d));
6150    if (!d)
6151      {
6152         e_object_del(E_OBJECT(menu));
6153         return;
6154      }
6155
6156    d->e_fm = e_fm;
6157    d->args = args;
6158
6159    e_object_data_set(E_OBJECT(menu), d);
6160    e_object_free_attach_func_set(E_OBJECT(menu), _e_fm_drop_menu_free);
6161
6162    item = e_menu_item_new(menu);
6163    e_menu_item_label_set(item, _("Copy"));
6164    e_menu_item_callback_set(item, _e_fm_drop_menu_copy_cb, d);
6165    e_util_menu_item_theme_icon_set(item, "edit-copy");
6166
6167    item = e_menu_item_new(menu);
6168    e_menu_item_label_set(item, _("Move"));
6169    e_menu_item_callback_set(item, _e_fm_drop_menu_move_cb, d);
6170    e_menu_item_icon_edje_set(item,
6171                              e_theme_edje_file_get("base/theme/fileman",
6172                                                    "e/fileman/default/button/move"),
6173                              "e/fileman/default/button/move");
6174
6175    item = e_menu_item_new(menu);
6176    e_menu_item_label_set(item, _("Link"));
6177    e_menu_item_callback_set(item, _e_fm_drop_menu_symlink_cb, d);
6178    e_util_menu_item_theme_icon_set(item, "emblem-symbolic-link");
6179
6180    item = e_menu_item_new(menu);
6181    e_menu_item_separator_set(item, 1);
6182
6183    item = e_menu_item_new(menu);
6184    e_menu_item_label_set(item, _("Abort"));
6185    e_menu_item_callback_set(item, _e_fm_drop_menu_abort_cb, d);
6186    e_menu_item_icon_edje_set(item,
6187                              e_theme_edje_file_get("base/theme/fileman",
6188                                                    "e/fileman/default/button/abort"),
6189                              "e/fileman/default/button/abort");
6190
6191    man = e_manager_current_get();
6192    if (!man) goto error;
6193    con = e_container_current_get(man);
6194    if (!con) goto error;
6195    ecore_x_pointer_xy_get(con->win, &x, &y);
6196    zone = e_util_zone_current_get(man);
6197    if (!zone) goto error;
6198    e_menu_activate_mouse(menu, zone, x, y, 1, 1, E_MENU_POP_DIRECTION_DOWN, 0);
6199
6200 error:
6201    e_object_del(E_OBJECT(menu));
6202 }
6203
6204 static void
6205 _e_fm2_cb_dnd_drop(void *data, const char *type, void *event)
6206 {
6207    E_Fm2_Smart_Data *sd;
6208    E_Event_Dnd_Drop *ev;
6209    E_Fm2_Icon *ic;
6210    Eina_List *fsel, *l, *ll, *il, *isel;
6211    char buf[4096];
6212    const char *fp;
6213    Evas_Coord ox, oy, x, y;
6214    int adjust_icons = 0;
6215
6216    char dirpath[PATH_MAX];
6217    char *args = NULL;
6218    size_t size = 0;
6219    size_t length = 0;
6220
6221    sd = data;
6222    if (type != _e_fm2_mime_text_uri_list) return;
6223    ev = (E_Event_Dnd_Drop *)event;
6224
6225    fsel = _e_fm2_uri_path_list_get(ev->data);
6226    isel = _e_fm2_uri_icon_list_get(fsel);
6227    if (!isel) return;
6228    ox = 0; oy = 0;
6229    EINA_LIST_FOREACH(isel, l, ic)
6230      {
6231         if (ic && ic->drag.src)
6232           {
6233              ox = ic->x;
6234              oy = ic->y;
6235              break;
6236           }
6237      }
6238
6239    /* note - logic.
6240     * if drop file prefix path matches extra_file_source then it can be
6241     * and indirect link - dont MOVE the file just add filename to list.
6242     * if not literally move the file in. if move can't work - try a copy.
6243     * on a literal move find any fm views for the dir of the dropped file
6244     * and refresh those, as well as refresh current target fm dir
6245     */
6246    if (sd->drop_all) /* drop arbitrarily into the dir */
6247      {
6248         /* move file into this fm dir */
6249          for (ll = fsel, il = isel; ll && il; ll = eina_list_next(ll), il = eina_list_next(il))
6250            {
6251               ic = eina_list_data_get(il);
6252               fp = eina_list_data_get(ll);
6253               if (!fp) continue;
6254
6255               if ((ic) && (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_CUSTOM_ICONS))
6256                 {
6257                    /* dnd doesn't tell me all the co-ords of the icons being dragged so i can't place them accurately.
6258                     * need to fix this. ev->data probably needs to become more compelx than a list of url's
6259                     */
6260                    
6261                      x = ev->x + (ic->x - ox) - ic->drag.x + sd->pos.x - sd->x;
6262                      y = ev->y + (ic->y - oy) - ic->drag.y + sd->pos.y - sd->y;
6263                    
6264                      if (x < 0) x = 0;
6265                      if (y < 0) y = 0;
6266
6267                      if (sd->config->view.fit_custom_pos)
6268                        {
6269                           if ((x + ic->w) > sd->w) x = (sd->w - ic->w);
6270                           if ((y + ic->h) > sd->h) y = (sd->h - ic->h);
6271                        }
6272
6273                      if (ic->sd == sd)
6274                        {
6275                           ic->x = x;
6276                           ic->y = y;
6277                           ic->saved_pos = EINA_TRUE;
6278                           adjust_icons = 1;
6279                        }
6280
6281                      snprintf(buf, sizeof(buf), "%s/%s",
6282                               sd->realpath, ecore_file_file_get(fp));
6283                      _e_fm_icon_save_position(buf, x, y, sd->w, sd->h);
6284                 }
6285
6286               args = _e_fm_string_append_quoted(args, &size, &length, fp);
6287               args = _e_fm_string_append_char(args, &size, &length, ' ');
6288
6289               eina_stringshare_del(fp);
6290            }
6291          if (adjust_icons)
6292            {
6293               sd->max.w = 0;
6294               sd->max.h = 0;
6295               EINA_LIST_FOREACH(sd->icons, l, ic)
6296                 {
6297                    if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
6298                    if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
6299                 }
6300               _e_fm2_obj_icons_place(sd);
6301               evas_object_smart_callback_call(sd->obj, "changed", NULL);
6302            }
6303
6304          args = _e_fm_string_append_quoted(args, &size, &length, sd->realpath);
6305      }
6306    else if (sd->drop_icon) /* into or before/after an icon */
6307      {
6308         if (sd->drop_after == -1) /* put into subdir/file in icon */
6309           {
6310              /* move file into dir that this icon is for */
6311               for (ll = fsel, il = isel; ll && il; ll = eina_list_next(ll), il = eina_list_next(il))
6312                 {
6313                    fp = eina_list_data_get(ll);
6314                    if (!fp) continue;
6315
6316                    args = _e_fm_string_append_quoted(args, &size, &length, fp);
6317                    args = _e_fm_string_append_char(args, &size, &length, ' ');
6318
6319                    eina_stringshare_del(fp);
6320                 }
6321
6322               if (S_ISDIR(sd->drop_icon->info.statinfo.st_mode))
6323                 snprintf(dirpath, sizeof(dirpath), "%s/%s", sd->realpath, sd->drop_icon->info.file);
6324               else
6325                 snprintf(dirpath, sizeof(dirpath), "%s", sd->realpath);
6326
6327               args = _e_fm_string_append_quoted(args, &size, &length, dirpath);
6328           }
6329         else
6330           {
6331              if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST && sd->order_file) /* list */
6332                {
6333                   for (ll = fsel, il = isel; ll && il; ll = eina_list_next(ll), il = eina_list_next(il))
6334                     {
6335                        fp = eina_list_data_get(ll);
6336                        if (!fp) continue;
6337                        snprintf(buf, sizeof(buf), "%s/%s",
6338                                 sd->realpath, ecore_file_file_get(fp));
6339                        if (sd->config->view.link_drop)
6340                          {
6341                             _e_fm2_client_file_symlink(buf, fp, sd->drop_icon->info.file, sd->drop_after, -9999, -9999, sd->h, sd->h, sd->obj);
6342                          }
6343                        else
6344                          {
6345                             args = _e_fm_string_append_quoted(args, &size, &length, fp);
6346                             args = _e_fm_string_append_char(args, &size, &length, ' ');
6347                          }
6348
6349                        _e_fm_file_reorder(ecore_file_file_get(fp), sd->realpath, sd->drop_icon->info.file, sd->drop_after);
6350
6351                        eina_stringshare_del(fp);
6352                     }
6353
6354                   args = _e_fm_string_append_quoted(args, &size, &length, sd->realpath);
6355                }
6356              else
6357                {
6358                   for (ll = fsel, il = isel; ll && il; ll = eina_list_next(ll), il = eina_list_next(il))
6359                     {
6360                        fp = eina_list_data_get(ll);
6361                        if (!fp) continue;
6362
6363                        args = _e_fm_string_append_quoted(args, &size, &length, fp);
6364                        args = _e_fm_string_append_char(args, &size, &length, ' ');
6365
6366                        eina_stringshare_del(fp);
6367                     }
6368                   args = _e_fm_string_append_quoted(args, &size, &length, sd->realpath);
6369                }
6370           }
6371      }
6372
6373    if (args)
6374      {
6375         if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_COPY)
6376           {
6377              _e_fm_client_file_copy(args, sd->obj);
6378              free(args);
6379           }
6380         else if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_MOVE)
6381           {
6382              _e_fm_client_file_move(args, sd->obj);
6383              free(args);
6384           }
6385         else if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_ASK)
6386           {
6387              _e_fm_drop_menu(args, sd->obj);
6388           }
6389      }
6390
6391    _e_fm2_dnd_drop_hide(sd->obj);
6392    _e_fm2_dnd_drop_all_hide(sd->obj);
6393    _e_fm2_list_walking++;
6394    Evas_Object *obj;
6395    EINA_LIST_FOREACH(_e_fm2_list, l, obj)
6396      {
6397         if ((_e_fm2_list_walking > 0) &&
6398             (eina_list_data_find(_e_fm2_list_remove, obj))) continue;
6399         _e_fm2_dnd_finish(obj, 0);
6400      }
6401    _e_fm2_list_walking--;
6402    if (_e_fm2_list_walking == 0)
6403      {
6404         EINA_LIST_FREE(_e_fm2_list_remove, obj)
6405           {
6406              _e_fm2_list = eina_list_remove(_e_fm2_list, obj);
6407           }
6408      }
6409    eina_list_free(fsel);
6410    eina_list_free(isel);
6411 }
6412
6413 /* FIXME: prototype */
6414 static void
6415 _e_fm2_mouse_1_handler(E_Fm2_Icon *ic, int up, void *evas_event)
6416 {
6417    Evas_Event_Mouse_Down *ed = NULL;
6418    Evas_Event_Mouse_Up *eu = NULL;
6419    Evas_Modifier *modifiers;
6420    int multi_sel = 0, range_sel = 0, sel_change = 0;
6421    static unsigned int down_timestamp = 0;
6422
6423    if (!evas_event) return;
6424
6425    if (!up)
6426      {
6427         ed = evas_event;
6428         modifiers = ed->modifiers;
6429      }
6430    else
6431      {
6432         eu = evas_event;
6433         modifiers = eu->modifiers;
6434      }
6435    if (ed && ic->sd->config->view.single_click_delay)
6436      down_timestamp = ed->timestamp;
6437
6438    if (ic->sd->config->selection.windows_modifiers)
6439      {
6440         if (evas_key_modifier_is_set(modifiers, "Shift"))
6441           range_sel = 1;
6442         else if (evas_key_modifier_is_set(modifiers, "Control"))
6443           multi_sel = 1;
6444      }
6445    else
6446      {
6447         if (evas_key_modifier_is_set(modifiers, "Control"))
6448           range_sel = 1;
6449         else if (evas_key_modifier_is_set(modifiers, "Shift"))
6450           multi_sel = 1;
6451      }
6452    if (ic->sd->config->selection.single)
6453      {
6454         multi_sel = 0;
6455         range_sel = 0;
6456      }
6457
6458    /*
6459     * On mouse up, check if we want to do inplace open
6460     */
6461    if ((eu) &&
6462        (!multi_sel) &&
6463        (!range_sel) &&
6464        (ic->sd->config->view.single_click) &&
6465        ((eu->timestamp - down_timestamp) > ic->sd->config->view.single_click_delay))
6466      {
6467         if (_e_fm2_inplace_open(ic) == 1) return;
6468      }
6469
6470    if (range_sel)
6471      {
6472         const Eina_List *l;
6473         E_Fm2_Icon *ic2;
6474         Eina_Bool seen = 0;
6475         /* find last selected - if any, and select all icons between */
6476         EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
6477           {
6478              if (ic2 == ic) seen = 1;
6479              if (ic2->last_selected)
6480                {
6481                   ic2->last_selected = 0;
6482                   if (seen)
6483                     {
6484                        EINA_LIST_REVERSE_FOREACH(l, l, ic2)
6485                        {
6486                           if (ic == ic2) break;
6487                           if (!ic2->selected) sel_change = 1;
6488                           _e_fm2_icon_select(ic2);
6489                           ic2->last_selected = 0;
6490                        }
6491                     }
6492                   else
6493                     {
6494                        EINA_LIST_FOREACH(l, l, ic2)
6495                          {
6496                             if (ic == ic2) break;
6497                             if (!ic2->selected) sel_change = 1;
6498                             _e_fm2_icon_select(ic2);
6499                             ic2->last_selected = 0;
6500                          }
6501                     }
6502                   break;
6503                }
6504           }
6505      }
6506    else if ((!multi_sel) && ((up) || ((!up) && (!ic->selected))))
6507      {
6508         const Eina_List *l;
6509         E_Fm2_Icon *ic2;
6510         /* desel others */
6511         EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
6512           {
6513              if (ic2 != ic)
6514                {
6515                   if (ic2->selected)
6516                     {
6517                        _e_fm2_icon_deselect(ic2);
6518                        sel_change = 1;
6519                     }
6520                }
6521           }
6522      }
6523    else
6524      {
6525         if (!up)
6526           {
6527              const Eina_List *l;
6528              E_Fm2_Icon *ic2;
6529              EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
6530                ic2->last_selected = 0;
6531           }
6532      }
6533    if ((multi_sel) && (ic->selected))
6534      {
6535         if ((up) && (!ic->drag.dnd) && (!ic->down_sel))
6536           {
6537              sel_change = 1;
6538              _e_fm2_icon_deselect(ic);
6539           }
6540      }
6541    else
6542      {
6543         if (!up)
6544           {
6545              if (!ic->selected) sel_change = EINA_TRUE;
6546              _e_fm2_icon_select(ic);
6547              _e_fm2_icon_make_visible(ic);
6548              ic->down_sel = EINA_TRUE;
6549              ic->last_selected = EINA_TRUE;
6550           }
6551      }
6552    if (sel_change)
6553      evas_object_smart_callback_call(ic->sd->obj, "selection_change", NULL);
6554    if (ic->sd->config->view.single_click)
6555      {
6556         if (eu && (eu->timestamp - down_timestamp) > ic->sd->config->view.single_click_delay)
6557           {
6558              int icon_pos_x = ic->x + ic->sd->x - ic->sd->pos.x;
6559              int icon_pos_y = ic->y + ic->sd->y - ic->sd->pos.y;
6560
6561              if (eu->output.x >= icon_pos_x && eu->output.x <= (icon_pos_x + ic->w) &&
6562                  eu->output.y >= icon_pos_y && eu->output.y <= (icon_pos_y + ic->h))
6563                evas_object_smart_callback_call(ic->sd->obj, "selected", NULL);
6564           }
6565      }
6566 }
6567
6568 static void
6569 _e_fm2_cb_icon_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
6570 {
6571    Evas_Event_Mouse_Down *ev;
6572    E_Fm2_Icon *ic;
6573
6574    ic = data;
6575    ev = event_info;
6576
6577    if (ic->entry_widget)
6578      return;
6579
6580    if ((ev->button == 1) && (ev->flags & EVAS_BUTTON_DOUBLE_CLICK))
6581      {
6582         /* if its a directory && open dirs in-place is set then change the dir
6583          * to be the dir + file */
6584           if (_e_fm2_inplace_open(ic) == 0)
6585             evas_object_smart_callback_call(ic->sd->obj, "selected", NULL);
6586           /* if its in file selector mode then signal that a selection has
6587            * taken place and dont do anything more */
6588
6589           /* do the below per selected file */
6590           /* if its a directory and open dirs in-place is not set, then
6591            * signal owner that a new dir should be opened */
6592           /* if its a normal file - do what the mime type says to do with
6593            * that file type */
6594      }
6595    else if (ev->button == 1)
6596      {
6597         if ((ic->sd->eobj))
6598           {
6599              ic->drag.x = ev->output.x - ic->x - ic->sd->x + ic->sd->pos.x;
6600              ic->drag.y = ev->output.y - ic->y - ic->sd->y + ic->sd->pos.y;
6601              ic->drag.start = EINA_TRUE;
6602              ic->drag.dnd = EINA_FALSE;
6603              ic->drag.src = EINA_TRUE;
6604           }
6605         _e_fm2_mouse_1_handler(ic, 0, ev);
6606      }
6607    else if (ev->button == 3)
6608      {
6609         if (!ic->selected) _e_fm2_mouse_1_handler(ic, 0, ev);
6610         _e_fm2_icon_menu(ic, ic->sd->obj, ev->timestamp);
6611      }
6612 }
6613
6614 static void
6615 _e_fm2_cb_icon_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
6616 {
6617    Evas_Event_Mouse_Up *ev;
6618    E_Fm2_Icon *ic;
6619
6620    ic = data;
6621    ev = event_info;
6622
6623    if (ic->entry_widget) return;
6624
6625    if ((ev->button == 1) && (!ic->drag.dnd))
6626      {
6627         if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
6628           _e_fm2_mouse_1_handler(ic, 1, ev);
6629         ic->drag.start = EINA_FALSE;
6630         ic->drag.dnd = EINA_FALSE;
6631         ic->drag.src = EINA_FALSE;
6632         ic->down_sel = EINA_FALSE;
6633      }
6634 }
6635
6636 static void
6637 _e_fm2_cb_drag_finished(E_Drag *drag, int dropped __UNUSED__)
6638 {
6639    E_Fm2_Uri *uri;
6640    const char *p;
6641    char buf[PATH_MAX * 3 + 7];
6642    Evas_Object *fm;
6643    int i;
6644
6645    memset(buf, 0, sizeof(buf));
6646    for (p = drag->data, i = 0; p && *p != '\0'; p++, i++)
6647      {
6648         if (*p == '\r')
6649           {
6650              p++;
6651              i = -1;
6652              uri = _e_fm2_uri_parse(buf);
6653              memset(buf, 0, sizeof(buf));
6654              if (!uri) continue;
6655
6656              fm = _e_fm2_file_fm2_find(uri->path);
6657              if (fm)
6658                {
6659                   const char *file;
6660                   E_Fm2_Icon *ic;
6661
6662                   file = ecore_file_file_get(uri->path);
6663                   ic = _e_fm2_icon_find(fm, file);
6664                   ic->drag.dnd = EINA_FALSE;
6665                   if (ic->obj) evas_object_show(ic->obj);
6666                   if (ic->obj_icon) evas_object_show(ic->obj_icon);
6667                }
6668
6669              if (uri->hostname) eina_stringshare_del(uri->hostname);
6670              eina_stringshare_del(uri->path);
6671              E_FREE(uri);
6672           }
6673         else
6674           buf[i] = *p;
6675      }
6676    free(drag->data);
6677 }
6678
6679 static void
6680 _e_fm_drag_key_down_cb(E_Drag *drag, Ecore_Event_Key *e)
6681 {
6682    if (!strncmp(e->keyname, "Alt", 3))
6683      {
6684         ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_ASK);
6685         edje_object_signal_emit(drag->object, "e,state,ask", "e");
6686      }
6687    else if (!strncmp(e->keyname, "Shift", 5))
6688      {
6689         ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
6690         edje_object_signal_emit(drag->object, "e,state,move", "e");
6691      }
6692    else if (!strncmp(e->keyname, "Control", 7))
6693      {
6694         ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_COPY);
6695         edje_object_signal_emit(drag->object, "e,state,copy", "e");
6696      }
6697 }
6698
6699 static void
6700 _e_fm_drag_key_up_cb(E_Drag *drag, Ecore_Event_Key *e)
6701 {
6702    /* Default action would be move. ;) */
6703
6704     if (!strncmp(e->keyname, "Alt", 3))
6705       ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
6706     else if (!strncmp(e->keyname, "Shift", 5))
6707       ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
6708     else if (!strncmp(e->keyname, "Control", 7))
6709       ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
6710
6711     edje_object_signal_emit(drag->object, "e,state,move", "e");
6712 }
6713
6714 static void
6715 _e_fm2_cb_icon_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
6716 {
6717    Evas_Event_Mouse_Move *ev;
6718    E_Fm2_Icon *ic;
6719    E_Fm2_Icon_Info *ici;
6720
6721    ic = data;
6722    ev = event_info;
6723
6724    if (ic->entry_widget) return;
6725
6726    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
6727    if ((ic->drag.start) && (ic->sd->eobj))
6728      {
6729         int dx, dy;
6730
6731         dx = ev->cur.output.x - (ic->drag.x + ic->x + ic->sd->x - ic->sd->pos.x);
6732         dy = ev->cur.output.y - (ic->drag.y + ic->y + ic->sd->y - ic->sd->pos.y);
6733         if (((dx * dx) + (dy * dy)) >
6734             (e_config->drag_resist * e_config->drag_resist))
6735           {
6736              E_Drag *d;
6737              Evas_Object *o, *o2;
6738              Evas_Coord x, y, w, h;
6739              const char *drag_types[] = { "text/uri-list" }, *realpath;
6740              char buf[PATH_MAX + 8], *p, *sel = NULL;
6741              E_Container *con = NULL;
6742              Eina_List *sl;
6743              int sel_length = 0, p_offset, p_length;
6744
6745              switch (ic->sd->eobj->type)
6746                {
6747                 case E_GADCON_TYPE:
6748                   con = ((E_Gadcon *)(ic->sd->eobj))->zone->container;
6749                   break;
6750
6751                 case E_WIN_TYPE:
6752                   con = ((E_Win *)(ic->sd->eobj))->container;
6753                   break;
6754
6755                 case E_ZONE_TYPE:
6756                   con = ((E_Zone *)(ic->sd->eobj))->container;
6757                   break;
6758
6759                 case E_BORDER_TYPE:
6760                   con = ((E_Border *)(ic->sd->eobj))->zone->container;
6761                   break;
6762
6763                 case E_POPUP_TYPE:
6764                   con = ((E_Popup *)(ic->sd->eobj))->zone->container;
6765                   break;
6766
6767      /* FIXME: add more types as needed */
6768                 default:
6769                   break;
6770                }
6771              if (!con) return;
6772              ic->sd->drag = EINA_TRUE;
6773              ic->drag.dnd = EINA_TRUE;
6774              if (ic->obj) evas_object_hide(ic->obj);
6775              if (ic->obj_icon) evas_object_hide(ic->obj_icon);
6776              ic->drag.start = EINA_FALSE;
6777              evas_object_geometry_get(ic->obj, &x, &y, &w, &h);
6778              realpath = e_fm2_real_path_get(ic->sd->obj);
6779              p_offset = eina_strlcpy(buf, realpath, sizeof(buf));
6780              if ((p_offset < 1) || (p_offset >= (int)sizeof(buf) - 2)) return;
6781              if (buf[p_offset - 1] != '/')
6782                {
6783                   buf[p_offset] = '/';
6784                   p_offset++;
6785                }
6786              p = buf + p_offset;
6787              p_length = sizeof(buf) - p_offset - 1;
6788
6789              sl = e_fm2_selected_list_get(ic->sd->obj);
6790              EINA_LIST_FREE(sl, ici)
6791                {
6792                   char *tmp;
6793                   const char *s;
6794                   int s_len;
6795
6796                   if ((int)eina_strlcpy(p, ici->file, p_length) >= p_length) 
6797                     continue;
6798                   s = _e_fm2_uri_escape(buf);
6799                   if (!s) continue;
6800                   s_len = strlen(s);
6801                   tmp = realloc(sel, sel_length + s_len + 2 + 1);
6802                   if (!tmp)
6803                     {
6804                        free(sel);
6805                        sel = NULL;
6806                        break;
6807                     }
6808                   sel = tmp;
6809                   memcpy(sel + sel_length, s, s_len);
6810                   memcpy(sel + sel_length + s_len, "\r\n", 2);
6811                   sel_length += s_len + 2;
6812                   eina_stringshare_del(s);
6813
6814                   ici->ic->drag.dnd = EINA_TRUE;
6815                   if (ici->ic->obj) evas_object_hide(ici->ic->obj);
6816                   if (ici->ic->obj_icon) evas_object_hide(ici->ic->obj_icon);
6817                }
6818              if (!sel) return;
6819              sel[sel_length] = '\0';
6820
6821              d = e_drag_new(con, x, y, drag_types, 1,
6822                             sel, sel_length, NULL, _e_fm2_cb_drag_finished);
6823              o = edje_object_add(e_drag_evas_get(d));
6824              if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
6825                {
6826                   if (ic->sd->config->icon.fixed.w)
6827                     {
6828                        if (ic->odd)
6829                          _e_fm2_theme_edje_object_set(ic->sd, o,
6830                                                       "base/theme/widgets",
6831                                                       "list_odd/fixed");
6832                        else
6833                          _e_fm2_theme_edje_object_set(ic->sd, o,
6834                                                       "base/theme/widgets",
6835                                                       "list/fixed");
6836                     }
6837                   else
6838                     {
6839                        if (ic->odd)
6840                          _e_fm2_theme_edje_object_set(ic->sd, o,
6841                                                       "base/theme/widgets",
6842                                                       "list_odd/variable");
6843                        else
6844                          _e_fm2_theme_edje_object_set(ic->sd, o,
6845                                                       "base/theme/widgets",
6846                                                       "list/variable");
6847                     }
6848                }
6849              else
6850                {
6851                   if (ic->sd->config->icon.fixed.w)
6852                     _e_fm2_theme_edje_object_set(ic->sd, o,
6853                                                  "base/theme/fileman",
6854                                                  "icon/fixed");
6855                   else
6856                     _e_fm2_theme_edje_object_set(ic->sd, o,
6857                                                  "base/theme/fileman",
6858                                                  "icon/variable");
6859                }
6860              _e_fm2_icon_label_set(ic, o);
6861              o2 = _e_fm2_icon_icon_direct_set(ic, o,
6862                                               _e_fm2_cb_icon_thumb_dnd_gen, o,
6863                                               1);
6864              edje_object_signal_emit(o, "e,state,selected", "e");
6865              edje_object_signal_emit(o2, "e,state,selected", "e");
6866              e_drag_object_set(d, o);
6867              edje_object_signal_emit(o, "e,state,move", "e");
6868              e_drag_resize(d, w, h);
6869
6870              e_drag_key_down_cb_set(d, _e_fm_drag_key_down_cb);
6871              e_drag_key_up_cb_set(d, _e_fm_drag_key_up_cb);
6872
6873              e_drag_xdnd_start(d,
6874                                ic->drag.x + ic->x + ic->sd->x - ic->sd->pos.x,
6875                                ic->drag.y + ic->y + ic->sd->y - ic->sd->pos.y);
6876           }
6877      }
6878 }
6879
6880 static void
6881 _e_fm2_cb_icon_thumb_dnd_gen(void *data, Evas_Object *obj, void *event_info __UNUSED__)
6882 {
6883    Evas_Object *o;
6884    Evas_Coord w = 0, h = 0;
6885    int have_alpha;
6886
6887    o = data;
6888    e_icon_size_get(obj, &w, &h);
6889    have_alpha = e_icon_alpha_get(obj);
6890 //   if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
6891    {
6892       edje_extern_object_aspect_set(obj, EDJE_ASPECT_CONTROL_BOTH, w, h);
6893    }
6894    edje_object_part_swallow(o, "e.swallow.icon", obj);
6895    if (have_alpha)
6896      edje_object_signal_emit(o, "e,action,thumb,gen,alpha", "e");
6897    else
6898      edje_object_signal_emit(o, "e,action,thumb,gen", "e");
6899 }
6900
6901 static void
6902 _e_fm2_cb_icon_thumb_gen(void *data, Evas_Object *obj, void *event_info __UNUSED__)
6903 {
6904    E_Fm2_Icon *ic;
6905
6906    ic = data;
6907    
6908    if (e_icon_file_get(obj))
6909      {
6910         Evas_Coord w = 0, h = 0;
6911         int have_alpha;
6912
6913         if (!ic->realized)
6914           return;
6915
6916         e_icon_size_get(obj, &w, &h);
6917         have_alpha = e_icon_alpha_get(obj);
6918 //      if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
6919         {
6920            edje_extern_object_aspect_set(obj,
6921                                          EDJE_ASPECT_CONTROL_BOTH, w, h);
6922         }
6923         edje_object_part_swallow(ic->obj, "e.swallow.icon", obj);
6924         if (have_alpha)
6925           edje_object_signal_emit(ic->obj, "e,action,thumb,gen,alpha", "e");
6926         else
6927           edje_object_signal_emit(ic->obj, "e,action,thumb,gen", "e");
6928      }
6929    else
6930      {
6931         ic->thumb_failed = EINA_TRUE;
6932         evas_object_del(obj);
6933
6934         if (ic->realized)
6935           _e_fm2_icon_icon_set(ic);
6936      }
6937 }
6938
6939 static void
6940 _e_fm2_cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
6941 {
6942    Evas_Event_Key_Down *ev;
6943    E_Fm2_Smart_Data *sd;
6944    E_Fm2_Icon *ic;
6945
6946    sd = data;
6947    ev = event_info;
6948
6949    if (sd->iop_icon) return;
6950
6951    if (evas_key_modifier_is_set(ev->modifiers, "Control"))
6952      {
6953         if (!strcmp(ev->key, "x"))
6954           {
6955              _e_fm2_file_cut(obj);
6956              return;
6957           }
6958         else if (!strcmp(ev->key, "c"))
6959           {
6960              _e_fm2_file_copy(obj);
6961              return;
6962           }
6963         else if (!strcmp(ev->key, "v"))
6964           {
6965              _e_fm2_file_paste(obj);
6966              return;
6967           }
6968         else if (!strcmp(ev->key, "h"))
6969           {
6970              if (sd->show_hidden_files)
6971                sd->show_hidden_files = EINA_FALSE;
6972              else
6973                sd->show_hidden_files = EINA_TRUE;
6974              sd->inherited_dir_props = EINA_FALSE;
6975              _e_fm2_refresh(data, NULL, NULL);
6976              return;
6977           }
6978         else if (!strcmp(ev->key, "1"))
6979           {
6980              if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_GRID_ICONS)
6981                return;
6982              sd->view_mode = E_FM2_VIEW_MODE_GRID_ICONS;
6983              sd->inherited_dir_props = EINA_FALSE;
6984              _e_fm2_refresh(sd, NULL, NULL);
6985              return;
6986           }
6987         else if (!strcmp(ev->key, "2"))
6988           {
6989              if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST)
6990                return;
6991              sd->view_mode = E_FM2_VIEW_MODE_LIST;
6992              sd->inherited_dir_props = EINA_FALSE;
6993              _e_fm2_refresh(sd, NULL, NULL);
6994              return;
6995           }
6996         else if (!strcmp(ev->key, "3"))
6997           {
6998              if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_CUSTOM_ICONS)
6999                return;
7000              sd->view_mode = E_FM2_VIEW_MODE_CUSTOM_ICONS;
7001              sd->inherited_dir_props = EINA_FALSE;
7002              _e_fm2_refresh(sd, NULL, NULL);
7003              return;
7004           }
7005      }
7006
7007    if (!strcmp(ev->key, "Left"))
7008      {
7009         /* FIXME: icon mode, typebuf extras */
7010         /* list mode: scroll left n pix
7011          * icon mode: prev icon
7012          * typebuf mode: cursor left
7013          */
7014            _e_fm2_icon_sel_prev(obj);
7015      }
7016    else if (!strcmp(ev->key, "Right"))
7017      {
7018         /* FIXME: icon mode, typebuf extras */
7019         /* list mode: scroll right n pix
7020          * icon mode: next icon
7021          * typebuf mode: cursor right
7022          */
7023            _e_fm2_icon_sel_next(obj);
7024      }
7025    else if (!strcmp(ev->key, "Up"))
7026      {
7027         if (sd->typebuf_visible)
7028           /* FIXME: icon mode, typebuf extras */
7029           /* is there a way to use this atm? */
7030           // _e_fm2_typebuf_history_prev(obj);
7031           _e_fm2_typebuf_match(obj, -1);
7032         else if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST)
7033           _e_fm2_icon_sel_prev(obj);
7034         else
7035           _e_fm2_icon_sel_up(obj);
7036      }
7037    else if (!strcmp(ev->key, "Down"))
7038      {
7039         if (sd->typebuf_visible)
7040           /* FIXME: icon mode, typebuf extras */
7041           /* is there a way to use this? */
7042           //_e_fm2_typebuf_history_next(obj);
7043           _e_fm2_typebuf_match(obj, 1);
7044         else if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST)
7045           _e_fm2_icon_sel_next(obj);
7046         else
7047           _e_fm2_icon_sel_down(obj);
7048      }
7049    else if (!strcmp(ev->key, "Home"))
7050      {
7051         /* FIXME: typebuf extras */
7052         /* go to first icon
7053          * typebuf mode: cursor to start
7054          */
7055            _e_fm2_icon_sel_first(obj);
7056      }
7057    else if (!strcmp(ev->key, "End"))
7058      {
7059         /* FIXME: typebuf extras */
7060         /* go to last icon
7061          * typebuf mode: cursor to end
7062          */
7063            _e_fm2_icon_sel_last(obj);
7064      }
7065    else if (!strcmp(ev->key, "Prior"))
7066      {
7067         /* up h * n pixels */
7068          e_fm2_pan_set(obj, sd->pos.x, sd->pos.y - sd->h);
7069          evas_object_smart_callback_call(sd->obj, "pan_changed", NULL);
7070      }
7071    else if (!strcmp(ev->keyname, "Next"))
7072      {
7073         /* down h * n pixels */
7074          e_fm2_pan_set(obj, sd->pos.x, sd->pos.y + sd->h);
7075          evas_object_smart_callback_call(sd->obj, "pan_changed", NULL);
7076      }
7077    else if (!strcmp(ev->key, "Escape"))
7078      {
7079         /* typebuf mode: end typebuf mode */
7080          if (sd->typebuf_visible)
7081            _e_fm2_typebuf_hide(obj);
7082          else
7083            {
7084               ic = _e_fm2_icon_first_selected_find(obj);
7085               if (ic)
7086                 _e_fm2_icon_desel_any(obj);
7087               else
7088                 {
7089                    if (e_fm2_has_parent_get(obj))
7090                      e_fm2_parent_go(obj);
7091                 }
7092            }
7093      }
7094    else if (!strcmp(ev->key, "Return"))
7095      {
7096         /* if selected - select callback.
7097          * typebuf mode: if nothing selected - run cmd
7098          */
7099           if (sd->typebuf_visible)
7100             _e_fm2_typebuf_run(obj);
7101           else
7102             {
7103                ic = _e_fm2_icon_first_selected_find(obj);
7104                if (ic)
7105                  {
7106                     if (_e_fm2_inplace_open(ic) == 0)
7107                       evas_object_smart_callback_call(ic->sd->obj, "selected", NULL);
7108                  }
7109             }
7110      }
7111    else if (!strcmp(ev->key, "Insert"))
7112      {
7113         /* dunno what to do with this yet */
7114      }
7115    else if (!strcmp(ev->key, "Tab"))
7116      {
7117         /* typebuf mode: tab complete */
7118          if (sd->typebuf_visible)
7119            _e_fm2_typebuf_complete(obj);
7120      }
7121    else if (!strcmp(ev->key, "BackSpace"))
7122      {
7123         /* typebuf mode: backspace */
7124          if (sd->typebuf_visible)
7125            _e_fm2_typebuf_char_backspace(obj);
7126          else
7127            {
7128               if (e_fm2_has_parent_get(obj))
7129                 e_fm2_parent_go(obj);
7130            }
7131      }
7132    else if (!strcmp(ev->key, "Delete"))
7133      {
7134         /* FIXME: typebuf extras */
7135          if (sd->typebuf_visible)
7136            { /* typebuf mode: delete */ }else
7137            _e_fm2_file_delete(obj);
7138      }
7139    else if (!evas_key_modifier_is_set(ev->modifiers, "Control") &&
7140             !evas_key_modifier_is_set(ev->modifiers, "Alt"))
7141      {
7142         if (ev->string)
7143           {
7144              if (!sd->typebuf_visible) _e_fm2_typebuf_show(obj);
7145              _e_fm2_typebuf_char_append(obj, ev->string);
7146           }
7147      }
7148 }
7149
7150 static void
7151 _e_fm2_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
7152 {
7153    Evas_Event_Mouse_Down *ev;
7154    E_Fm2_Smart_Data *sd;
7155
7156    sd = data;
7157    ev = event_info;
7158    if (ev->button == 1)
7159      {
7160         Eina_List *l;
7161         int multi_sel = 0, range_sel = 0, sel_change = 0;
7162
7163         if (sd->config->selection.windows_modifiers)
7164           {
7165              if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
7166                range_sel = 1;
7167              else if (evas_key_modifier_is_set(ev->modifiers, "Control"))
7168                multi_sel = 1;
7169           }
7170         else
7171           {
7172              if (evas_key_modifier_is_set(ev->modifiers, "Control"))
7173                range_sel = 1;
7174              else if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
7175                multi_sel = 1;
7176           }
7177         if (sd->config->selection.single)
7178           {
7179              multi_sel = 0;
7180              range_sel = 0;
7181           }
7182         if ((!multi_sel) && (!range_sel))
7183           {
7184              E_Fm2_Icon *ic;
7185              EINA_LIST_FOREACH(sd->icons, l, ic)
7186                {
7187                   if (ic->selected)
7188                     {
7189                        _e_fm2_icon_deselect(ic);
7190                        sel_change = 1;
7191                     }
7192                }
7193           }
7194         if (sel_change)
7195           evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
7196
7197         if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
7198           {
7199              if (!sd->config->selection.single)
7200                {
7201                   sd->selrect.ox = ev->canvas.x;
7202                   sd->selrect.oy = ev->canvas.y;
7203                   sd->selecting = EINA_TRUE;
7204                }
7205           }
7206      }
7207    else if (ev->button == 3)
7208      {
7209         _e_fm2_menu(sd->obj, ev->timestamp);
7210      }
7211 }
7212
7213 static void
7214 _e_fm2_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
7215 {
7216    E_Fm2_Smart_Data *sd;
7217
7218    sd = data;
7219    sd->selecting = EINA_FALSE;
7220    sd->selrect.ox = 0;
7221    sd->selrect.oy = 0;
7222    evas_object_hide(sd->sel_rect);
7223 }
7224
7225 static void
7226 _e_fm2_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
7227 {
7228    Evas_Event_Mouse_Move *ev;
7229    E_Fm2_Smart_Data *sd;
7230    Eina_List *l = NULL;
7231    int x, y, w, h;
7232    int sel_change = 0;
7233
7234    sd = data;
7235    ev = event_info;
7236    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
7237      {
7238         if (sd->selecting)
7239           {
7240              sd->selecting = EINA_FALSE;
7241              sd->selrect.ox = 0;
7242              sd->selrect.oy = 0;
7243              evas_object_hide(sd->sel_rect);
7244           }
7245         return;
7246      }
7247    if (!sd->selecting) return;
7248
7249    if (ev->cur.canvas.x < sd->selrect.ox)
7250      {
7251         sd->selrect.x = ev->cur.canvas.x;
7252         sd->selrect.w = (sd->selrect.ox - sd->selrect.x);
7253      }
7254    else
7255      {
7256         sd->selrect.x = MIN(sd->selrect.ox, ev->cur.canvas.x);
7257         sd->selrect.w = abs(sd->selrect.x - ev->cur.canvas.x);
7258      }
7259    if (ev->cur.canvas.y < sd->selrect.oy)
7260      {
7261         sd->selrect.y = ev->cur.canvas.y;
7262         sd->selrect.h = (sd->selrect.oy - sd->selrect.y);
7263      }
7264    else
7265      {
7266         sd->selrect.y = MIN(sd->selrect.oy, ev->cur.canvas.y);
7267         sd->selrect.h = abs(sd->selrect.y - ev->cur.canvas.y);
7268      }
7269    _e_fm2_sel_rect_update(sd);
7270
7271    evas_object_geometry_get(sd->sel_rect, &x, &y, &w, &h);
7272
7273 /*
7274  * Leave commented for now. Start of scrolling the sel_rect
7275  *
7276    int nx, ny, nw, nh;
7277
7278    nx = sd->pos.x;
7279    if ((x - sd->pos.x) < 0)
7280      nx = x;
7281    else if ((x + w - sd->pos.x) > (sd->w))
7282      nx = x + w - sd->w;
7283    ny = sd->pos.y;
7284    if ((y - sd->pos.y) < 0)
7285      ny = y;
7286    else if ((y + h - sd->pos.y) > (sd->h))
7287      ny = y + h - sd->h;
7288    e_fm2_pan_set(sd->obj, nx, ny);
7289    evas_object_smart_callback_call(sd->obj, "pan_changed", NULL);
7290  */
7291
7292    E_Fm2_Icon *ic;
7293    EINA_LIST_FOREACH(sd->icons, l, ic)
7294      {
7295         int ix, iy, iw, ih;
7296         int ix_t, iy_t, iw_t, ih_t;
7297
7298         if (!ic) continue;
7299         evas_object_geometry_get(ic->obj_icon, &ix, &iy, &iw, &ih);
7300         evas_object_geometry_get(edje_object_part_object_get(ic->obj,
7301                                                              "e.text.label"),
7302                                  &ix_t, &iy_t, &iw_t, &ih_t);
7303         if (E_INTERSECTS(x, y, w, h, ix, iy, iw, ih) ||
7304             E_INTERSECTS(x, y, w, h, ix_t, iy_t, iw_t, ih_t))
7305           {
7306              if (!ic->selected)
7307                {
7308                   _e_fm2_icon_select(ic);
7309                   sel_change = 1;
7310                }
7311           }
7312         else
7313           {
7314              if (ic->selected)
7315                {
7316                   _e_fm2_icon_deselect(ic);
7317                   sel_change = 1;
7318                }
7319           }
7320      }
7321    if (sel_change)
7322      evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
7323 }
7324
7325 static void
7326 _e_fm2_sel_rect_update(void *data)
7327 {
7328    E_Fm2_Smart_Data *sd;
7329
7330    sd = data;
7331    evas_object_move(sd->sel_rect, sd->selrect.x, sd->selrect.y);
7332    evas_object_resize(sd->sel_rect, sd->selrect.w, sd->selrect.h);
7333    evas_object_show(sd->sel_rect);
7334 }
7335
7336 static void
7337 _e_fm2_cb_scroll_job(void *data)
7338 {
7339    E_Fm2_Smart_Data *sd;
7340
7341    sd = evas_object_smart_data_get(data);
7342    if (!sd) return;
7343    sd->scroll_job = NULL;
7344    evas_event_freeze(evas_object_evas_get(sd->obj));
7345    edje_freeze();
7346    _e_fm2_regions_eval(sd->obj);
7347    _e_fm2_obj_icons_place(sd);
7348    edje_thaw();
7349    evas_event_thaw(evas_object_evas_get(sd->obj));
7350    _e_fm2_dir_save_props(sd);
7351 }
7352
7353 static void
7354 _e_fm2_cb_resize_job(void *data)
7355 {
7356    E_Fm2_Smart_Data *sd;
7357    Eina_List *l;
7358
7359    sd = evas_object_smart_data_get(data);
7360    if (!sd) return;
7361    sd->resize_job = NULL;
7362    evas_event_freeze(evas_object_evas_get(sd->obj));
7363    edje_freeze();
7364    switch (_e_fm2_view_mode_get(sd))
7365      {
7366       case E_FM2_VIEW_MODE_ICONS:
7367         _e_fm2_regions_free(sd->obj);
7368         _e_fm2_icons_place(sd->obj);
7369         _e_fm2_regions_populate(sd->obj);
7370         break;
7371
7372       case E_FM2_VIEW_MODE_GRID_ICONS:
7373         _e_fm2_regions_free(sd->obj);
7374         _e_fm2_icons_place(sd->obj);
7375         _e_fm2_regions_populate(sd->obj);
7376         break;
7377
7378       case E_FM2_VIEW_MODE_CUSTOM_ICONS:
7379         if (sd->config->view.fit_custom_pos)
7380           {
7381              E_Fm2_Icon *ic;
7382              EINA_LIST_FOREACH(sd->icons, l, ic)
7383                {
7384                   ic->region = NULL;
7385                   _e_fm2_icon_geom_adjust(ic, ic->x, ic->y, ic->w, ic->h, sd->pw, sd->ph);
7386                }
7387           }
7388         _e_fm2_regions_free(sd->obj);
7389 //      _e_fm2_regions_eval(sd->obj);
7390         _e_fm2_icons_place(sd->obj);
7391         _e_fm2_regions_populate(sd->obj);
7392         break;
7393
7394       case E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS:
7395         /* FIXME: not going to implement this at this stage */
7396         _e_fm2_regions_free(sd->obj);
7397 //      _e_fm2_regions_eval(sd->obj);
7398         _e_fm2_icons_place(sd->obj);
7399         _e_fm2_regions_populate(sd->obj);
7400         break;
7401
7402       case E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS:
7403         /* FIXME: not going to implement this at this stage */
7404         _e_fm2_regions_free(sd->obj);
7405 //      _e_fm2_regions_eval(sd->obj);
7406         _e_fm2_icons_place(sd->obj);
7407         _e_fm2_regions_populate(sd->obj);
7408         break;
7409
7410       case E_FM2_VIEW_MODE_LIST:
7411         if (sd->iconlist_changed)
7412           {
7413              E_Fm2_Icon *ic;
7414              EINA_LIST_FOREACH(sd->icons, l, ic)
7415                {
7416                   ic->region = NULL;
7417 //                _e_fm2_icon_unrealize(ic);
7418                }
7419           }
7420         _e_fm2_regions_free(sd->obj);
7421         _e_fm2_icons_place(sd->obj);
7422         _e_fm2_regions_populate(sd->obj);
7423         break;
7424
7425       default:
7426         break;
7427      }
7428    edje_thaw();
7429    evas_event_thaw(evas_object_evas_get(sd->obj));
7430    sd->iconlist_changed = EINA_FALSE;
7431    sd->pw = sd->w;
7432    sd->ph = sd->h;
7433
7434    if ((sd->max.w > 0) && (sd->max.h > 0) && (sd->w > 0) && (sd->h > 0))
7435      {
7436         E_Fm2_Custom_File *cf = e_fm2_custom_file_get(sd->realpath);
7437         if ((cf) && (cf->dir))
7438           {
7439              sd->pos.x = cf->dir->pos.x * (sd->max.w - sd->w);
7440              sd->pos.y = cf->dir->pos.y * (sd->max.h - sd->h);
7441              evas_object_smart_callback_call(sd->obj, "pan_changed", NULL);
7442           }
7443      }
7444 }
7445
7446 static int
7447 _e_fm2_cb_icon_sort(const void *data1, const void *data2)
7448 {
7449    const E_Fm2_Icon *ic1, *ic2;
7450    char *l1, *l2;
7451
7452    ic1 = data1;
7453    ic2 = data2;
7454    l1 = (char *)ic1->info.file;
7455    if (ic1->info.label) l1 = (char *)ic1->info.label;
7456    l2 = (char *)ic2->info.file;
7457    if (ic2->info.label) l2 = (char *)ic2->info.label;
7458    if (ic1->sd->config->list.sort.dirs.first)
7459      {
7460         if ((S_ISDIR(ic1->info.statinfo.st_mode)) !=
7461             (S_ISDIR(ic2->info.statinfo.st_mode)))
7462           {
7463              if (S_ISDIR(ic1->info.statinfo.st_mode)) return -1;
7464              else return 1;
7465           }
7466      }
7467    else if (ic1->sd->config->list.sort.dirs.last)
7468      {
7469         if ((S_ISDIR(ic1->info.statinfo.st_mode)) !=
7470             (S_ISDIR(ic2->info.statinfo.st_mode)))
7471           {
7472              if (S_ISDIR(ic1->info.statinfo.st_mode)) return 1;
7473              else return -1;
7474           }
7475      }
7476    if (ic1->sd->config->list.sort.no_case)
7477      {
7478         char buf1[4096], buf2[4096], *p;
7479
7480 /*      if (ic1->sd->config->list.sort.category)
7481           {
7482  * FIXME: implement category sorting
7483           }
7484         else
7485  */     {
7486            eina_strlcpy(buf1, l1, sizeof(buf1));
7487            eina_strlcpy(buf2, l2, sizeof(buf2));
7488         }
7489         p = buf1;
7490         while (*p)
7491           {
7492              *p = tolower(*p);
7493              p++;
7494           }
7495         p = buf2;
7496         while (*p)
7497           {
7498              *p = tolower(*p);
7499              p++;
7500           }
7501         return strcmp(buf1, buf2);
7502      }
7503    return strcmp(l1, l2);
7504 }
7505
7506 static Eina_Bool
7507 _e_fm2_cb_scan_timer(void *data)
7508 {
7509    E_Fm2_Smart_Data *sd;
7510
7511    sd = evas_object_smart_data_get(data);
7512    if (!sd) return ECORE_CALLBACK_CANCEL;
7513    _e_fm2_queue_process(data);
7514    sd->scan_timer = NULL;
7515    if (!sd->listing)
7516      {
7517         _e_fm2_client_monitor_list_end(data);
7518         return ECORE_CALLBACK_CANCEL;
7519      }
7520    if (sd->busy_count > 0)
7521      sd->scan_timer = ecore_timer_add(0.2, _e_fm2_cb_scan_timer, sd->obj);
7522    else
7523      {
7524         if (!sd->sort_idler)
7525           sd->sort_idler = ecore_idler_add(_e_fm2_cb_sort_idler, data);
7526      }
7527    return ECORE_CALLBACK_CANCEL;
7528 }
7529
7530 static Eina_Bool
7531 _e_fm2_cb_sort_idler(void *data)
7532 {
7533    E_Fm2_Smart_Data *sd;
7534
7535    sd = evas_object_smart_data_get(data);
7536    if (!sd) return ECORE_CALLBACK_CANCEL;
7537    _e_fm2_queue_process(data);
7538    if (!sd->listing)
7539      {
7540         sd->sort_idler = NULL;
7541         _e_fm2_client_monitor_list_end(data);
7542         return ECORE_CALLBACK_CANCEL;
7543      }
7544    return ECORE_CALLBACK_RENEW;
7545 }
7546
7547 static Eina_Bool
7548 _e_fm2_cb_theme(void *data, int type __UNUSED__, void *event __UNUSED__)
7549 {
7550    e_fm2_refresh(data);
7551    return ECORE_CALLBACK_RENEW;
7552 }
7553
7554 /**************************/
7555 static void
7556 _e_fm2_obj_icons_place(E_Fm2_Smart_Data *sd)
7557 {
7558    const Eina_List *l;
7559    E_Fm2_Region *rg;
7560
7561    evas_event_freeze(evas_object_evas_get(sd->obj));
7562    edje_freeze();
7563    EINA_LIST_FOREACH(sd->regions.list, l, rg)
7564      {
7565         if (rg->realized)
7566           {
7567              const Eina_List *ll;
7568              E_Fm2_Icon *ic;
7569
7570              EINA_LIST_FOREACH(rg->list, ll, ic)
7571                {
7572                   if (ic->realized)
7573                     {
7574                        if (!_e_fm2_icon_visible(ic))
7575                          {
7576                             e_thumb_icon_end(ic->obj_icon);
7577                          }
7578                        evas_object_move(ic->obj,
7579                                         sd->x + ic->x - sd->pos.x,
7580                                         sd->y + ic->y - sd->pos.y);
7581                        evas_object_resize(ic->obj, ic->w, ic->h);
7582                        _e_fm2_icon_thumb(ic, ic->obj_icon, 0);
7583                     }
7584                }
7585           }
7586      }
7587    edje_thaw();
7588    evas_event_thaw(evas_object_evas_get(sd->obj));
7589 }
7590
7591 /**************************/
7592
7593 static void
7594 _e_fm2_smart_add(Evas_Object *obj)
7595 {
7596    E_Fm2_Smart_Data *sd;
7597
7598    sd = E_NEW(E_Fm2_Smart_Data, 1);
7599    if (!sd) return;
7600
7601    sd->view_mode = -1; /* unset */
7602    sd->icon_size = -1; /* unset */
7603
7604    sd->obj = obj;
7605    sd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
7606    evas_object_smart_member_add(sd->clip, obj);
7607    evas_object_color_set(sd->clip, 255, 255, 255, 255);
7608
7609    sd->underlay = evas_object_rectangle_add(evas_object_evas_get(obj));
7610    evas_object_clip_set(sd->underlay, sd->clip);
7611    evas_object_smart_member_add(sd->underlay, obj);
7612    evas_object_color_set(sd->underlay, 0, 0, 0, 0);
7613    evas_object_show(sd->underlay);
7614
7615    evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN, _e_fm2_cb_key_down, sd);
7616    evas_object_event_callback_add(sd->underlay, EVAS_CALLBACK_MOUSE_DOWN, _e_fm2_cb_mouse_down, sd);
7617    evas_object_event_callback_add(sd->underlay, EVAS_CALLBACK_MOUSE_UP, _e_fm2_cb_mouse_up, sd);
7618    evas_object_event_callback_add(sd->underlay, EVAS_CALLBACK_MOUSE_MOVE, _e_fm2_cb_mouse_move, sd);
7619
7620    sd->drop = edje_object_add(evas_object_evas_get(obj));
7621    evas_object_clip_set(sd->drop, sd->clip);
7622    _e_fm2_theme_edje_object_set(sd, sd->drop,
7623                                 "base/theme/fileman",
7624                                 "list/drop_between");
7625    evas_object_smart_member_add(sd->drop, obj);
7626    evas_object_show(sd->drop);
7627
7628    sd->drop_in = edje_object_add(evas_object_evas_get(obj));
7629    evas_object_clip_set(sd->drop_in, sd->clip);
7630    _e_fm2_theme_edje_object_set(sd, sd->drop_in,
7631                                 "base/theme/fileman",
7632                                 "list/drop_in");
7633    evas_object_smart_member_add(sd->drop_in, obj);
7634    evas_object_show(sd->drop_in);
7635
7636    sd->overlay = edje_object_add(evas_object_evas_get(obj));
7637    evas_object_clip_set(sd->overlay, sd->clip);
7638    _e_fm2_theme_edje_object_set(sd, sd->overlay,
7639                                 "base/theme/fileman",
7640                                 "overlay");
7641    evas_object_smart_member_add(sd->overlay, obj);
7642    evas_object_show(sd->overlay);
7643
7644    sd->sel_rect = edje_object_add(evas_object_evas_get(obj));
7645    evas_object_clip_set(sd->sel_rect, sd->clip);
7646    _e_fm2_theme_edje_object_set(sd, sd->sel_rect, "base/theme/fileman",
7647                                 "rubberband");
7648    evas_object_smart_member_add(sd->sel_rect, obj);
7649
7650    evas_object_smart_data_set(obj, sd);
7651    evas_object_move(obj, 0, 0);
7652    evas_object_resize(obj, 0, 0);
7653
7654    sd->event_handlers = eina_list_append(sd->event_handlers,
7655                                          ecore_event_handler_add(E_EVENT_CONFIG_ICON_THEME,
7656                                                                  _e_fm2_cb_theme,
7657                                                                  sd->obj));
7658
7659
7660    _e_fm2_list = eina_list_append(_e_fm2_list, sd->obj);
7661 }
7662
7663 static void
7664 _e_fm2_smart_del(Evas_Object *obj)
7665 {
7666    E_Fm2_Smart_Data *sd;
7667    Ecore_Event_Handler *hdl;
7668
7669    sd = evas_object_smart_data_get(obj);
7670    if (!sd) return;
7671
7672    EINA_LIST_FREE(sd->event_handlers, hdl)
7673       ecore_event_handler_del(hdl);
7674
7675    _e_fm2_client_monitor_list_end(obj);
7676    if (sd->realpath) _e_fm2_client_monitor_del(sd->id, sd->realpath);
7677    _e_fm2_live_process_end(obj);
7678    _e_fm2_queue_free(obj);
7679    _e_fm2_regions_free(obj);
7680    _e_fm2_icons_free(obj);
7681    if (sd->menu)
7682      {
7683         e_menu_post_deactivate_callback_set(sd->menu, NULL, NULL);
7684         e_object_del(E_OBJECT(sd->menu));
7685         sd->menu = NULL;
7686      }
7687    if (sd->entry_dialog)
7688      {
7689         e_object_del(E_OBJECT(sd->entry_dialog));
7690         sd->entry_dialog = NULL;
7691      }
7692    if (sd->image_dialog)
7693      {
7694         e_object_del(E_OBJECT(sd->image_dialog));
7695         sd->image_dialog = NULL;
7696      }
7697    if (sd->scroll_job) ecore_job_del(sd->scroll_job);
7698    if (sd->resize_job) ecore_job_del(sd->resize_job);
7699    if (sd->refresh_job) ecore_job_del(sd->refresh_job);
7700    eina_stringshare_del(sd->custom_theme);
7701    eina_stringshare_del(sd->custom_theme_content);
7702    sd->custom_theme = sd->custom_theme_content = NULL;
7703    eina_stringshare_del(sd->dev);
7704    eina_stringshare_del(sd->path);
7705    eina_stringshare_del(sd->realpath);
7706    sd->dev = sd->path = sd->realpath = NULL;
7707    if (sd->mount)
7708      {
7709         e_fm2_device_unmount(sd->mount);
7710         sd->mount = NULL;
7711      }
7712    if (sd->config) _e_fm2_config_free(sd->config);
7713
7714    E_FREE(sd->typebuf.buf);
7715
7716    evas_object_del(sd->underlay);
7717    evas_object_del(sd->overlay);
7718    evas_object_del(sd->drop);
7719    evas_object_del(sd->drop_in);
7720    evas_object_del(sd->sel_rect);
7721    evas_object_del(sd->clip);
7722    if (sd->drop_handler) e_drop_handler_del(sd->drop_handler);
7723    if (_e_fm2_list_walking == 0)
7724      _e_fm2_list = eina_list_remove(_e_fm2_list, sd->obj);
7725    else
7726      _e_fm2_list_remove = eina_list_append(_e_fm2_list_remove, sd->obj);
7727    free(sd);
7728    e_fm2_custom_file_flush();
7729 }
7730
7731 static void
7732 _e_fm2_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
7733 {
7734    E_Fm2_Smart_Data *sd;
7735
7736    sd = evas_object_smart_data_get(obj);
7737    if (!sd) return;
7738    if ((sd->x == x) && (sd->y == y)) return;
7739    sd->x = x;
7740    sd->y = y;
7741    evas_object_move(sd->underlay, sd->x, sd->y);
7742    evas_object_move(sd->overlay, sd->x, sd->y);
7743    _e_fm2_dnd_drop_configure(sd->obj);
7744    evas_object_move(sd->clip, sd->x - OVERCLIP, sd->y - OVERCLIP);
7745    _e_fm2_obj_icons_place(sd);
7746    if (sd->drop_handler)
7747      e_drop_handler_geometry_set(sd->drop_handler, sd->x, sd->y, sd->w, sd->h);
7748 }
7749
7750 static void
7751 _e_fm2_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
7752 {
7753    E_Fm2_Smart_Data *sd;
7754    Eina_Bool wch = EINA_FALSE;
7755
7756    sd = evas_object_smart_data_get(obj);
7757    if (!sd) return;
7758    if ((sd->w == w) && (sd->h == h)) return;
7759    if (w != sd->w) wch = EINA_TRUE;
7760    sd->w = w;
7761    sd->h = h;
7762    evas_object_resize(sd->underlay, sd->w, sd->h);
7763    evas_object_resize(sd->overlay, sd->w, sd->h);
7764    _e_fm2_dnd_drop_configure(sd->obj);
7765    evas_object_resize(sd->clip, sd->w + (OVERCLIP * 2), sd->h + (OVERCLIP * 2));
7766
7767    /* for automatic layout - do this - NB; we could put this on a timer delay */
7768    if ((_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST) ||
7769        (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_GRID_ICONS))
7770      {
7771         if (wch)
7772           {
7773              if (sd->resize_job) ecore_job_del(sd->resize_job);
7774              sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, obj);
7775           }
7776         else
7777           {
7778              if (sd->scroll_job) ecore_job_del(sd->scroll_job);
7779              sd->scroll_job = ecore_job_add(_e_fm2_cb_scroll_job, obj);
7780           }
7781      }
7782    else if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_CUSTOM_ICONS)
7783      {
7784         if (sd->config->view.fit_custom_pos)
7785           {
7786              if (sd->resize_job) ecore_job_del(sd->resize_job);
7787              sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, obj);
7788           }
7789         else
7790           {
7791              if (sd->scroll_job) ecore_job_del(sd->scroll_job);
7792              sd->scroll_job = ecore_job_add(_e_fm2_cb_scroll_job, obj);
7793           }
7794      }
7795    if (sd->drop_handler)
7796      e_drop_handler_geometry_set(sd->drop_handler, sd->x, sd->y, sd->w, sd->h);
7797 }
7798
7799 static void
7800 _e_fm2_smart_show(Evas_Object *obj)
7801 {
7802    E_Fm2_Smart_Data *sd;
7803
7804    sd = evas_object_smart_data_get(obj);
7805    if (!sd) return;
7806    evas_object_show(sd->clip);
7807 }
7808
7809 static void
7810 _e_fm2_smart_hide(Evas_Object *obj)
7811 {
7812    E_Fm2_Smart_Data *sd;
7813
7814    sd = evas_object_smart_data_get(obj);
7815    if (!sd) return;
7816    evas_object_hide(sd->clip);
7817 }
7818
7819 static void
7820 _e_fm2_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
7821 {
7822    E_Fm2_Smart_Data *sd;
7823
7824    sd = evas_object_smart_data_get(obj);
7825    if (!sd) return;
7826    evas_object_color_set(sd->clip, r, g, b, a);
7827 }
7828
7829 static void
7830 _e_fm2_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
7831 {
7832    E_Fm2_Smart_Data *sd;
7833
7834    sd = evas_object_smart_data_get(obj);
7835    if (!sd) return;
7836    evas_object_clip_set(sd->clip, clip);
7837 }
7838
7839 static void
7840 _e_fm2_smart_clip_unset(Evas_Object *obj)
7841 {
7842    E_Fm2_Smart_Data *sd;
7843
7844    sd = evas_object_smart_data_get(obj);
7845    if (!sd) return;
7846    evas_object_clip_unset(sd->clip);
7847 }
7848
7849 static void
7850 _e_fm2_menu(Evas_Object *obj, unsigned int timestamp)
7851 {
7852    E_Fm2_Smart_Data *sd;
7853    E_Menu *mn;
7854    E_Menu_Item *mi;
7855    E_Manager *man;
7856    E_Container *con;
7857    E_Zone *zone;
7858    int x, y;
7859
7860    sd = evas_object_smart_data_get(obj);
7861    if (!sd) return;
7862
7863    mn = e_menu_new();
7864    e_object_data_set(E_OBJECT(mn), obj);
7865    e_menu_category_set(mn, "e/fileman/action");
7866
7867    if (sd->icon_menu.replace.func)
7868      sd->icon_menu.replace.func(sd->icon_menu.replace.data, sd->obj, mn, NULL);
7869    else
7870      {
7871         if (sd->icon_menu.start.func)
7872           {
7873              sd->icon_menu.start.func(sd->icon_menu.start.data, sd->obj, mn, NULL);
7874              mi = e_menu_item_new(mn);
7875              e_menu_item_separator_set(mi, 1);
7876           }
7877         if ((!(sd->icon_menu.flags & E_FM2_MENU_NO_INHERIT_PARENT)) &&
7878             (sd->view_flags & E_FM2_VIEW_INHERIT_DIR_CUSTOM))
7879           {
7880              mi = e_menu_item_new(mn);
7881              e_menu_item_label_set(mi, _("Inherit parent settings"));
7882              e_util_menu_item_theme_icon_set(mi, "view-inherit");
7883              e_menu_item_check_set(mi, 1);
7884              e_menu_item_toggle_set(mi, sd->inherited_dir_props);
7885              e_menu_item_callback_set(mi, _e_fm2_toggle_inherit_dir_props, sd);
7886           }
7887         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_VIEW_MENU))
7888           {
7889              mi = e_menu_item_new(mn);
7890              e_menu_item_label_set(mi, _("View Mode"));
7891              e_util_menu_item_theme_icon_set(mi, "preferences-look");
7892              e_menu_item_submenu_pre_callback_set(mi, _e_fm2_view_menu_pre, sd);
7893           }
7894         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_REFRESH))
7895           {
7896              mi = e_menu_item_new(mn);
7897              e_menu_item_label_set(mi, _("Refresh View"));
7898              e_util_menu_item_theme_icon_set(mi, "view-refresh");
7899              e_menu_item_callback_set(mi, _e_fm2_refresh, sd);
7900           }
7901
7902         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_SHOW_HIDDEN))
7903           {
7904              mi = e_menu_item_new(mn);
7905              e_menu_item_label_set(mi, _("Show Hidden Files"));
7906              e_util_menu_item_theme_icon_set(mi, "view-refresh");
7907              e_menu_item_check_set(mi, 1);
7908              e_menu_item_toggle_set(mi, sd->show_hidden_files);
7909              e_menu_item_callback_set(mi, _e_fm2_toggle_hidden_files, sd);
7910           }
7911
7912         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_REMEMBER_ORDERING))
7913           {
7914              if (!sd->config->view.always_order)
7915                {
7916                   mi = e_menu_item_new(mn);
7917                   e_menu_item_label_set(mi, _("Remember Ordering"));
7918                   e_util_menu_item_theme_icon_set(mi, "view-order");
7919                   e_menu_item_check_set(mi, 1);
7920                   e_menu_item_toggle_set(mi, sd->order_file);
7921                   e_menu_item_callback_set(mi, _e_fm2_toggle_ordering, sd);
7922                }
7923              if ((sd->order_file) || (sd->config->view.always_order))
7924                {
7925                   mi = e_menu_item_new(mn);
7926                   e_menu_item_label_set(mi, _("Sort Now"));
7927                   e_util_menu_item_theme_icon_set(mi, "view-sort");
7928                   e_menu_item_callback_set(mi, _e_fm2_sort, sd);
7929                }
7930           }
7931
7932         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_NEW_DIRECTORY))
7933           {
7934              mi = e_menu_item_new(mn);
7935              e_menu_item_separator_set(mi, 1);
7936
7937              mi = e_menu_item_new(mn);
7938              e_menu_item_label_set(mi, _("New Directory"));
7939              e_util_menu_item_theme_icon_set(mi, "folder-new");
7940              e_menu_item_callback_set(mi, _e_fm2_new_directory, sd);
7941           }
7942
7943         if (((!(sd->icon_menu.flags & E_FM2_MENU_NO_PASTE)) ||
7944              (!(sd->icon_menu.flags & E_FM2_MENU_NO_SYMLINK))) &&
7945             (eina_list_count(_e_fm_file_buffer) > 0) &&
7946             ecore_file_can_write(sd->realpath))
7947           {
7948              mi = e_menu_item_new(mn);
7949              e_menu_item_separator_set(mi, 1);
7950
7951              if (!(sd->icon_menu.flags & E_FM2_MENU_NO_PASTE))
7952                {
7953                   mi = e_menu_item_new(mn);
7954                   e_menu_item_label_set(mi, _("Paste"));
7955                   e_util_menu_item_theme_icon_set(mi, "edit-paste");
7956                   e_menu_item_callback_set(mi, _e_fm2_file_paste_menu, sd);
7957                }
7958
7959              if (!(sd->icon_menu.flags & E_FM2_MENU_NO_SYMLINK))
7960                {
7961                   mi = e_menu_item_new(mn);
7962                   e_menu_item_label_set(mi, _("Link"));
7963                   e_util_menu_item_theme_icon_set(mi, "emblem-symbolic-link");
7964                   e_menu_item_callback_set(mi, _e_fm2_file_symlink_menu, sd);
7965                }
7966           }
7967
7968         if (sd->icon_menu.end.func)
7969           sd->icon_menu.end.func(sd->icon_menu.end.data, sd->obj, mn, NULL);
7970      }
7971
7972    man = e_manager_current_get();
7973    if (!man)
7974      {
7975         e_object_del(E_OBJECT(mn));
7976         return;
7977      }
7978    con = e_container_current_get(man);
7979    if (!con)
7980      {
7981         e_object_del(E_OBJECT(mn));
7982         return;
7983      }
7984    ecore_x_pointer_xy_get(con->win, &x, &y);
7985    zone = e_util_zone_current_get(man);
7986    if (!zone)
7987      {
7988         e_object_del(E_OBJECT(mn));
7989         return;
7990      }
7991    sd->menu = mn;
7992    e_menu_post_deactivate_callback_set(mn, _e_fm2_menu_post_cb, sd);
7993    e_menu_activate_mouse(mn, zone,
7994                          x, y, 1, 1,
7995                          E_MENU_POP_DIRECTION_DOWN, timestamp);
7996 }
7997
7998 static void
7999 _e_fm2_menu_post_cb(void *data, E_Menu *m __UNUSED__)
8000 {
8001    E_Fm2_Smart_Data *sd;
8002
8003    sd = data;
8004    sd->menu = NULL;
8005 }
8006
8007 static void
8008 _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp)
8009 {
8010    E_Fm2_Smart_Data *sd;
8011    E_Menu *mn;
8012    E_Menu_Item *mi;
8013    E_Manager *man;
8014    E_Container *con;
8015    E_Zone *zone;
8016    Eina_List *sel, *l = NULL;
8017    int x, y, can_w, can_w2, protect;
8018    char buf[PATH_MAX], *ext;
8019
8020    sd = ic->sd;
8021
8022    mn = e_menu_new();
8023    e_object_data_set(E_OBJECT(mn), obj);
8024    e_menu_category_set(mn, "e/fileman/action");
8025
8026    if (sd->icon_menu.replace.func)
8027      sd->icon_menu.replace.func(sd->icon_menu.replace.data, sd->obj, mn, NULL);
8028    else
8029      {
8030         if (sd->icon_menu.start.func)
8031           {
8032              sd->icon_menu.start.func(sd->icon_menu.start.data, sd->obj, mn, NULL);
8033              mi = e_menu_item_new(mn);
8034              e_menu_item_separator_set(mi, 1);
8035           }
8036
8037         if ((!(sd->icon_menu.flags & E_FM2_MENU_NO_INHERIT_PARENT)) &&
8038             (sd->view_flags & E_FM2_VIEW_INHERIT_DIR_CUSTOM))
8039           {
8040              mi = e_menu_item_new(mn);
8041              e_menu_item_label_set(mi, _("Inherit parent settings"));
8042              e_util_menu_item_theme_icon_set(mi, "view-inherit");
8043              e_menu_item_check_set(mi, 1);
8044              e_menu_item_toggle_set(mi, sd->inherited_dir_props);
8045              e_menu_item_callback_set(mi, _e_fm2_toggle_inherit_dir_props, sd);
8046           }
8047         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_VIEW_MENU))
8048           {
8049              mi = e_menu_item_new(mn);
8050              e_menu_item_label_set(mi, _("View Mode"));
8051              e_util_menu_item_theme_icon_set(mi, "preferences-look");
8052              e_menu_item_submenu_pre_callback_set(mi, _e_fm2_icon_view_menu_pre, sd);
8053           }
8054         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_REFRESH))
8055           {
8056              mi = e_menu_item_new(mn);
8057              e_menu_item_label_set(mi, _("Refresh View"));
8058              e_util_menu_item_theme_icon_set(mi, "view-refresh");
8059              e_menu_item_callback_set(mi, _e_fm2_refresh, sd);
8060           }
8061
8062         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_SHOW_HIDDEN))
8063           {
8064              mi = e_menu_item_new(mn);
8065              e_menu_item_label_set(mi, _("Show Hidden Files"));
8066              e_util_menu_item_theme_icon_set(mi, "view-hidden-files");
8067              e_menu_item_check_set(mi, 1);
8068              e_menu_item_toggle_set(mi, sd->show_hidden_files);
8069              e_menu_item_callback_set(mi, _e_fm2_toggle_hidden_files, sd);
8070           }
8071
8072         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_REMEMBER_ORDERING))
8073           {
8074              if (!sd->config->view.always_order)
8075                {
8076                   mi = e_menu_item_new(mn);
8077                   e_menu_item_label_set(mi, _("Remember Ordering"));
8078                   e_util_menu_item_theme_icon_set(mi, "view-order");
8079                   e_menu_item_check_set(mi, 1);
8080                   e_menu_item_toggle_set(mi, sd->order_file);
8081                   e_menu_item_callback_set(mi, _e_fm2_toggle_ordering, sd);
8082                }
8083              if ((sd->order_file) || (sd->config->view.always_order))
8084                {
8085                   mi = e_menu_item_new(mn);
8086                   e_menu_item_label_set(mi, _("Sort Now"));
8087                   e_util_menu_item_theme_icon_set(mi, "view-sort");
8088                   e_menu_item_callback_set(mi, _e_fm2_sort, sd);
8089                }
8090           }
8091
8092         if (!(sd->icon_menu.flags & E_FM2_MENU_NO_NEW_DIRECTORY))
8093           {
8094              /* FIXME: stat the dir itself - move to e_fm_main */
8095               if (ecore_file_can_write(sd->realpath))
8096                 {
8097                    mi = e_menu_item_new(mn);
8098                    e_menu_item_separator_set(mi, 1);
8099
8100                    mi = e_menu_item_new(mn);
8101                    e_menu_item_label_set(mi, _("New Directory"));
8102                    e_util_menu_item_theme_icon_set(mi, "folder-new");
8103                    e_menu_item_callback_set(mi, _e_fm2_new_directory, sd);
8104                 }
8105           }
8106         if (!ic->info.removable)
8107           {
8108              if (!(sd->icon_menu.flags & E_FM2_MENU_NO_CUT))
8109                {
8110                   if (ecore_file_can_write(sd->realpath))
8111                     {
8112                        mi = e_menu_item_new(mn);
8113                        e_menu_item_separator_set(mi, 1);
8114
8115                        mi = e_menu_item_new(mn);
8116                        e_menu_item_label_set(mi, _("Cut"));
8117                        e_util_menu_item_theme_icon_set(mi, "edit-cut");
8118                        e_menu_item_callback_set(mi, _e_fm2_file_cut_menu, sd);
8119                     }
8120                }
8121              if (!(sd->icon_menu.flags & E_FM2_MENU_NO_COPY))
8122                {
8123                   if (!ecore_file_can_write(sd->realpath))
8124                     {
8125                        mi = e_menu_item_new(mn);
8126                        e_menu_item_separator_set(mi, 1);
8127                     }
8128
8129                   mi = e_menu_item_new(mn);
8130                   e_menu_item_label_set(mi, _("Copy"));
8131                   e_util_menu_item_theme_icon_set(mi, "edit-copy");
8132                   e_menu_item_callback_set(mi, _e_fm2_file_copy_menu, sd);
8133                }
8134
8135              if (((!(sd->icon_menu.flags & E_FM2_MENU_NO_PASTE)) ||
8136                   (!(sd->icon_menu.flags & E_FM2_MENU_NO_SYMLINK))) &&
8137                  (eina_list_count(_e_fm_file_buffer) > 0) &&
8138                  ecore_file_can_write(sd->realpath))
8139                {
8140                   if (!(sd->icon_menu.flags & E_FM2_MENU_NO_PASTE))
8141                     {
8142                        mi = e_menu_item_new(mn);
8143                        e_menu_item_label_set(mi, _("Paste"));
8144                        e_util_menu_item_theme_icon_set(mi, "edit-paste");
8145                        e_menu_item_callback_set(mi, _e_fm2_file_paste_menu, sd);
8146                     }
8147
8148                   if (!(sd->icon_menu.flags & E_FM2_MENU_NO_SYMLINK))
8149                     {
8150                        mi = e_menu_item_new(mn);
8151                        e_menu_item_label_set(mi, _("Link"));
8152                        e_util_menu_item_theme_icon_set(mi, "emblem-symbolic-link");
8153                        e_menu_item_callback_set(mi, _e_fm2_file_symlink_menu, sd);
8154                     }
8155                }
8156           }
8157
8158         can_w2 = 1;
8159         if (ic->sd->order_file)
8160           {
8161              snprintf(buf, sizeof(buf), "%s/.order", sd->realpath);
8162              /* FIXME: stat the .order itself - move to e_fm_main */
8163 //           can_w2 = ecore_file_can_write(buf);
8164           }
8165         if (ic->info.link)
8166           {
8167              can_w = 1;
8168 /*           struct stat st;
8169
8170              if (_e_fm2_icon_realpath(ic, buf, sizeof(buf)) &&
8171                  (lstat(buf, &st) == 0))
8172                {
8173                   if (st.st_uid == getuid())
8174                     {
8175                        if (st.st_mode & S_IWUSR) can_w = 1;
8176                     }
8177                   else if (st.st_gid == getgid())
8178                     {
8179                        if (st.st_mode & S_IWGRP) can_w = 1;
8180                     }
8181                   else
8182                     {
8183                        if (st.st_mode & S_IWOTH) can_w = 1;
8184                     }
8185                }
8186  */       }
8187         else
8188           can_w = 1;
8189
8190         sel = e_fm2_selected_list_get(ic->sd->obj);
8191         if ((!sel) || eina_list_count(sel) == 1)
8192           {
8193              _e_fm2_icon_realpath(ic, buf, sizeof(buf));
8194              protect = e_filereg_file_protected(buf);
8195           }
8196         else
8197           protect = 0;
8198         eina_list_free(sel);
8199
8200         if ((can_w) && (can_w2) && !(protect) && !ic->info.removable)
8201           {
8202              mi = e_menu_item_new(mn);
8203              e_menu_item_separator_set(mi, 1);
8204
8205              if (!(sd->icon_menu.flags & E_FM2_MENU_NO_DELETE))
8206                {
8207                   mi = e_menu_item_new(mn);
8208                   e_menu_item_label_set(mi, _("Delete"));
8209                   e_util_menu_item_theme_icon_set(mi, "edit-delete");
8210                   e_menu_item_callback_set(mi, _e_fm2_file_delete_menu, ic);
8211                }
8212
8213              if (!(sd->icon_menu.flags & E_FM2_MENU_NO_RENAME))
8214                {
8215                   mi = e_menu_item_new(mn);
8216                   e_menu_item_label_set(mi, _("Rename"));
8217                   e_util_menu_item_theme_icon_set(mi, "edit-rename");
8218                   e_menu_item_callback_set(mi, _e_fm2_file_rename, ic);
8219                }
8220           }
8221
8222         if (ic->info.removable)
8223           {
8224              E_Volume *v;
8225
8226              v = e_fm2_device_volume_find(ic->info.link);
8227              if (v)
8228                {
8229                   mi = e_menu_item_new(mn);
8230                   e_menu_item_separator_set(mi, 1);
8231
8232                   mi = e_menu_item_new(mn);
8233                   if (v->mounted)
8234                     {
8235                        e_menu_item_label_set(mi, _("Unmount"));
8236                        e_menu_item_callback_set(mi, _e_fm2_volume_unmount, v);
8237                     }
8238                   else
8239                     {
8240                        e_menu_item_label_set(mi, _("Mount"));
8241                        e_menu_item_callback_set(mi, _e_fm2_volume_mount, v);
8242                     }
8243
8244                   mi = e_menu_item_new(mn);
8245                   e_menu_item_label_set(mi, _("Eject"));
8246                   e_util_menu_item_theme_icon_set(mi, "media-eject");
8247                   e_menu_item_callback_set(mi, _e_fm2_volume_eject, v);
8248
8249                   mi = e_menu_item_new(mn);
8250                   e_menu_item_separator_set(mi, 1);
8251                }
8252           }
8253
8254         if (ic->info.mime && !strcmp(ic->info.mime, "application/x-desktop"))
8255           {
8256              mi = e_menu_item_new(mn);
8257              e_menu_item_label_set(mi, _("Application Properties"));
8258              e_util_menu_item_theme_icon_set(mi, "configure");
8259              e_menu_item_callback_set(mi, _e_fm2_file_application_properties, ic);
8260           }
8261
8262         mi = e_menu_item_new(mn);
8263         e_menu_item_label_set(mi, _("File Properties"));
8264         e_util_menu_item_theme_icon_set(mi, "document-properties");
8265         e_menu_item_callback_set(mi, _e_fm2_file_properties, ic);
8266
8267         if (ic->info.mime)
8268           {
8269              /* see if we have any mime handlers registered for this file */
8270               l = e_fm2_mime_handler_mime_handlers_get(ic->info.mime);
8271               if (l)
8272                 {
8273                    _e_fm2_icon_realpath(ic, buf, sizeof(buf));
8274                    _e_fm2_context_menu_append(obj, buf, l, mn, ic);
8275                 }
8276           }
8277
8278         /* see if we have any glob handlers registered for this file */
8279         ext = strrchr(ic->info.file, '.');
8280         if (ext)
8281           {
8282              snprintf(buf, sizeof(buf), "*%s", ext);
8283              l = e_fm2_mime_handler_glob_handlers_get(buf);
8284              if (l)
8285                {
8286                   _e_fm2_icon_realpath(ic, buf, sizeof(buf));
8287                   _e_fm2_context_menu_append(obj, buf, l, mn, ic);
8288                   eina_list_free(l);
8289                }
8290           }
8291
8292         if (sd->icon_menu.end.func)
8293           sd->icon_menu.end.func(sd->icon_menu.end.data, sd->obj, mn, &(ic->info));
8294      }
8295
8296    man = e_manager_current_get();
8297    if (!man)
8298      {
8299         e_object_del(E_OBJECT(mn));
8300         return;
8301      }
8302    con = e_container_current_get(man);
8303    if (!con)
8304      {
8305         e_object_del(E_OBJECT(mn));
8306         return;
8307      }
8308    ecore_x_pointer_xy_get(con->win, &x, &y);
8309    zone = e_util_zone_current_get(man);
8310    if (!zone)
8311      {
8312         e_object_del(E_OBJECT(mn));
8313         return;
8314      }
8315    ic->menu = mn;
8316    e_menu_post_deactivate_callback_set(mn, _e_fm2_icon_menu_post_cb, ic);
8317    e_menu_activate_mouse(mn, zone,
8318                          x, y, 1, 1,
8319                          E_MENU_POP_DIRECTION_DOWN, timestamp);
8320 }
8321
8322 static inline void
8323 _e_fm2_context_menu_append(Evas_Object *obj, const char *path, Eina_List *l, E_Menu *mn, E_Fm2_Icon *ic)
8324 {
8325    E_Fm2_Mime_Handler *handler;
8326    const Eina_List *ll;
8327
8328    if (!l) return;
8329
8330    l = eina_list_sort(l, -1, _e_fm2_context_list_sort);
8331
8332    EINA_LIST_FOREACH(l, ll, handler)
8333      {
8334         E_Fm2_Context_Menu_Data *md = NULL;
8335         E_Menu_Item *mi;
8336
8337         if ((!handler) || (!e_fm2_mime_handler_test(handler, obj, path)) ||
8338             (!handler->label)) continue;
8339         if (ll == l)
8340           {
8341              /* only append the separator if this is the first item */
8342              /* we do this in here because we dont want to add a separator
8343               * when we have no context entries */
8344                 mi = e_menu_item_new(mn);
8345                 e_menu_item_separator_set(mi, 1);
8346           }
8347
8348         md = E_NEW(E_Fm2_Context_Menu_Data, 1);
8349         if (!md) continue;
8350         md->icon = ic;
8351         md->handler = handler;
8352         _e_fm2_menu_contexts = eina_list_append(_e_fm2_menu_contexts, md);
8353
8354         mi = e_menu_item_new(mn);
8355         e_menu_item_label_set(mi, handler->label);
8356         if (handler->icon_group)
8357           e_util_menu_item_theme_icon_set(mi, handler->icon_group);
8358         e_menu_item_callback_set(mi, _e_fm2_icon_menu_item_cb, md);
8359      }
8360 }
8361
8362 static int
8363 _e_fm2_context_list_sort(const void *data1, const void *data2)
8364 {
8365    const E_Fm2_Mime_Handler *d1, *d2;
8366
8367    if (!data1) return 1;
8368    if (!data2) return -1;
8369    d1 = data1;
8370    if (!d1->label) return 1;
8371    d2 = data2;
8372    if (!d2->label) return -1;
8373    return strcmp(d1->label, d2->label);
8374 }
8375
8376 static void
8377 _e_fm2_icon_menu_post_cb(void *data, E_Menu *m __UNUSED__)
8378 {
8379    E_Fm2_Context_Menu_Data *md;
8380    E_Fm2_Icon *ic;
8381
8382    ic = data;
8383    ic->menu = NULL;
8384    EINA_LIST_FREE(_e_fm2_menu_contexts, md)
8385      E_FREE(md);
8386 }
8387
8388 static void
8389 _e_fm2_icon_menu_item_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
8390 {
8391    E_Fm2_Context_Menu_Data *md = NULL;
8392    Evas_Object *obj = NULL;
8393    char buf[PATH_MAX];
8394
8395    md = data;
8396    if (!md) return;
8397    obj = md->icon->info.fm;
8398    if (!obj) return;
8399    snprintf(buf, sizeof(buf), "%s/%s",
8400             e_fm2_real_path_get(obj), md->icon->info.file);
8401    e_fm2_mime_handler_call(md->handler, obj, buf);
8402 }
8403
8404 struct e_fm2_view_menu_icon_size_data
8405 {
8406    E_Fm2_Smart_Data *sd;
8407    short size;
8408 };
8409
8410 static void
8411 _e_fm2_view_menu_icon_size_data_free(void *obj)
8412 {
8413    struct e_fm2_view_menu_icon_size_data *d = e_object_data_get(obj);
8414    free(d);
8415 }
8416
8417 static void
8418 _e_fm2_view_menu_icon_size_change(void *data, E_Menu *m, E_Menu_Item *mi)
8419 {
8420    struct e_fm2_view_menu_icon_size_data *d = data;
8421    short current_size = _e_fm2_icon_w_get(d->sd);
8422    d->sd->icon_size = d->size;
8423    d->sd->inherited_dir_props = EINA_FALSE;
8424    if (current_size == d->size)
8425      return;
8426    _e_fm2_refresh(d->sd, m, mi);
8427 }
8428
8429 static void
8430 _e_fm2_view_menu_icon_size_use_default(void *data, E_Menu *m, E_Menu_Item *mi)
8431 {
8432    E_Fm2_Smart_Data *sd = data;
8433    short old, new;
8434
8435    old = _e_fm2_icon_w_get(sd);
8436
8437    if (sd->icon_size == -1)
8438      sd->icon_size = sd->config->icon.icon.w;
8439    else
8440      sd->icon_size = -1;
8441
8442    new = _e_fm2_icon_w_get(sd);
8443    sd->inherited_dir_props = EINA_FALSE;
8444
8445    if (new == old)
8446      return;
8447
8448    _e_fm2_refresh(sd, m, mi);
8449 }
8450
8451 static void
8452 _e_fm2_view_menu_icon_size_pre(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi)
8453 {
8454    E_Fm2_Smart_Data *sd = data;
8455    E_Menu *subm;
8456    const short *itr, sizes[] =
8457    {
8458       22, 32, 48, 64, 96, 128, 256, -1
8459    };
8460    short current_size = _e_fm2_icon_w_get(sd);
8461
8462    if (e_scale > 0.0)
8463      current_size /= e_scale;
8464
8465    subm = e_menu_new();
8466    e_menu_item_submenu_set(mi, subm);
8467
8468    for (itr = sizes; *itr > -1; itr++)
8469      {
8470         char buf[32];
8471         struct e_fm2_view_menu_icon_size_data *d;
8472
8473         d = malloc(sizeof(*d));
8474         if (!d)
8475           continue;
8476         d->sd = sd;
8477         d->size = *itr;
8478
8479         snprintf(buf, sizeof(buf), "%hd", *itr);
8480
8481         mi = e_menu_item_new(subm);
8482         e_object_data_set(E_OBJECT(mi), d);
8483         e_object_del_attach_func_set
8484           (E_OBJECT(mi), _e_fm2_view_menu_icon_size_data_free);
8485
8486         e_menu_item_label_set(mi, buf);
8487         e_menu_item_radio_group_set(mi, 1);
8488         e_menu_item_radio_set(mi, 1);
8489
8490         if (current_size == *itr)
8491           e_menu_item_toggle_set(mi, 1);
8492
8493         e_menu_item_callback_set(mi, _e_fm2_view_menu_icon_size_change, d);
8494      }
8495
8496    mi = e_menu_item_new(subm);
8497    e_menu_item_separator_set(mi, 1);
8498
8499    mi = e_menu_item_new(subm);
8500    e_menu_item_label_set(mi, _("Use default"));
8501    e_menu_item_check_set(mi, 1);
8502    e_menu_item_toggle_set(mi, sd->icon_size == -1);
8503    e_menu_item_callback_set(mi, _e_fm2_view_menu_icon_size_use_default, sd);
8504 }
8505
8506 static void
8507 _e_fm2_toggle_inherit_dir_props(void *data, E_Menu *m, E_Menu_Item *mi)
8508 {
8509    E_Fm2_Smart_Data *sd = data;
8510
8511    sd->inherited_dir_props = !sd->inherited_dir_props;
8512    _e_fm2_dir_save_props(sd);
8513    _e_fm2_dir_load_props(sd);
8514    _e_fm2_refresh(sd, m, mi);
8515 }
8516
8517 static void
8518 _e_fm2_view_menu_common(E_Menu *subm, E_Fm2_Smart_Data *sd)
8519 {
8520    E_Menu_Item *mi;
8521    char view_mode;
8522
8523    view_mode = _e_fm2_view_mode_get(sd);
8524
8525    mi = e_menu_item_new(subm);
8526    e_menu_item_label_set(mi, _("Grid Icons"));
8527    e_menu_item_radio_group_set(mi, 1);
8528    e_menu_item_radio_set(mi, 1);
8529    if (view_mode == E_FM2_VIEW_MODE_GRID_ICONS)
8530      e_menu_item_toggle_set(mi, 1);
8531    e_menu_item_callback_set(mi, _e_fm2_view_menu_grid_icons_cb, sd);
8532
8533    mi = e_menu_item_new(subm);
8534    e_menu_item_label_set(mi, _("Custom Icons"));
8535    e_menu_item_radio_group_set(mi, 1);
8536    e_menu_item_radio_set(mi, 1);
8537    if (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS)
8538      e_menu_item_toggle_set(mi, 1);
8539    e_menu_item_callback_set(mi, _e_fm2_view_menu_custom_icons_cb, sd);
8540
8541    mi = e_menu_item_new(subm);
8542    e_menu_item_label_set(mi, _("List"));
8543    e_menu_item_radio_group_set(mi, 1);
8544    e_menu_item_radio_set(mi, 1);
8545    if (view_mode == E_FM2_VIEW_MODE_LIST)
8546      e_menu_item_toggle_set(mi, 1);
8547    e_menu_item_callback_set(mi, _e_fm2_view_menu_list_cb, sd);
8548
8549    mi = e_menu_item_new(subm);
8550    e_menu_item_separator_set(mi, 1);
8551
8552    mi = e_menu_item_new(subm);
8553    e_menu_item_label_set(mi, _("Use default"));
8554    e_menu_item_check_set(mi, 1);
8555    e_menu_item_toggle_set(mi, sd->view_mode == -1);
8556    e_menu_item_callback_set(mi, _e_fm2_view_menu_use_default_cb, sd);
8557
8558    if (view_mode == E_FM2_VIEW_MODE_LIST)
8559      return;
8560
8561    char buf[64];
8562    int icon_size = _e_fm2_icon_w_get(sd);
8563
8564    // show the icon size as selected (even if it might be influnced by e_scale)
8565    /* if (e_scale > 0.0)
8566     *   icon_size /= e_scale; */
8567
8568    snprintf(buf, sizeof(buf), _("Icon Size (%d)"), icon_size);
8569
8570    mi = e_menu_item_new(subm);
8571    e_menu_item_label_set(mi, buf);
8572    e_menu_item_submenu_pre_callback_set(mi, _e_fm2_view_menu_icon_size_pre, sd);
8573 }
8574
8575 static void
8576 _e_fm2_icon_view_menu_pre(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi)
8577 {
8578    E_Menu *subm;
8579    E_Fm2_Smart_Data *sd;
8580
8581    sd = data;
8582
8583    subm = e_menu_new();
8584    e_object_data_set(E_OBJECT(subm), sd);
8585    e_menu_item_submenu_set(mi, subm);
8586
8587    _e_fm2_view_menu_common(subm, sd);
8588 }
8589
8590 static void
8591 _e_fm2_view_menu_pre(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi)
8592 {
8593    E_Menu *subm;
8594    E_Fm2_Smart_Data *sd;
8595    char buf[PATH_MAX];
8596    int access_ok;
8597    sd = data;
8598
8599    subm = e_menu_new();
8600    e_object_data_set(E_OBJECT(subm), sd);
8601    e_menu_item_submenu_set(mi, subm);
8602
8603    _e_fm2_view_menu_common(subm, sd);
8604
8605    snprintf(buf, sizeof(buf), "%s/.directory.desktop", sd->realpath);
8606    access_ok = ecore_file_exists(buf) ? ecore_file_can_write(buf)
8607      : ecore_file_can_write(sd->realpath);
8608    if (access_ok)
8609      {
8610         mi = e_menu_item_new(subm);
8611         e_menu_item_separator_set(mi, 1);
8612
8613         mi = e_menu_item_new(subm);
8614         e_menu_item_label_set(mi, _("Set background..."));
8615         e_util_menu_item_theme_icon_set(mi, "preferences-desktop-wallpaper");
8616         e_menu_item_callback_set(mi, _e_fm2_view_menu_set_background_cb, sd);
8617
8618         mi = e_menu_item_new(subm);
8619         e_menu_item_label_set(mi, _("Set overlay..."));
8620         e_menu_item_callback_set(mi, _e_fm2_view_menu_set_overlay_cb, sd);
8621      }
8622 }
8623
8624 static void
8625 _e_fm2_view_menu_grid_icons_cb(void *data, E_Menu *m, E_Menu_Item *mi)
8626 {
8627    E_Fm2_Smart_Data *sd = data;
8628    char old;
8629
8630    old = _e_fm2_view_mode_get(sd);
8631    sd->view_mode = E_FM2_VIEW_MODE_GRID_ICONS;
8632    sd->inherited_dir_props = EINA_FALSE;
8633    if (old == E_FM2_VIEW_MODE_GRID_ICONS)
8634      return;
8635
8636    _e_fm2_refresh(sd, m, mi);
8637 }
8638
8639 static void
8640 _e_fm2_view_menu_custom_icons_cb(void *data, E_Menu *m, E_Menu_Item *mi)
8641 {
8642    E_Fm2_Smart_Data *sd = data;
8643    char old;
8644
8645    old = _e_fm2_view_mode_get(sd);
8646    sd->view_mode = E_FM2_VIEW_MODE_CUSTOM_ICONS;
8647    sd->inherited_dir_props = EINA_FALSE;
8648    if (old == E_FM2_VIEW_MODE_CUSTOM_ICONS)
8649      return;
8650
8651    _e_fm2_refresh(sd, m, mi);
8652 }
8653
8654 static void
8655 _e_fm2_view_menu_list_cb(void *data, E_Menu *m, E_Menu_Item *mi)
8656 {
8657    E_Fm2_Smart_Data *sd = data;
8658    char old;
8659
8660    old = _e_fm2_view_mode_get(sd);
8661    sd->view_mode = E_FM2_VIEW_MODE_LIST;
8662    sd->inherited_dir_props = EINA_FALSE;
8663    if (old == E_FM2_VIEW_MODE_LIST)
8664      return;
8665
8666    _e_fm2_refresh(sd, m, mi);
8667 }
8668
8669 static void
8670 _e_fm2_view_menu_use_default_cb(void *data, E_Menu *m, E_Menu_Item *mi)
8671 {
8672    E_Fm2_Smart_Data *sd = data;
8673    char old, new;
8674
8675    old = _e_fm2_view_mode_get(sd);
8676
8677    if (sd->view_mode == -1)
8678      sd->view_mode = sd->config->view.mode;
8679    else
8680      sd->view_mode = -1;
8681
8682    new = _e_fm2_view_mode_get(sd);
8683    sd->inherited_dir_props = EINA_FALSE;
8684
8685    if (new == old)
8686      return;
8687
8688    _e_fm2_refresh(sd, m, mi);
8689 }
8690
8691 static void
8692 _e_fm2_view_image_sel(E_Fm2_Smart_Data *sd, const char *title,
8693                       void (*ok_cb)(void *data, E_Dialog *dia),
8694                       void (*clear_cb)(void *data, E_Dialog *dia))
8695 {
8696    E_Manager *man;
8697    E_Container *con;
8698    E_Dialog *dia;
8699    Evas_Object *o;
8700    Evas_Coord w, h;
8701
8702    man = e_manager_current_get();
8703    if (!man) return;
8704    con = e_container_current_get(man);
8705    if (!con) return;
8706
8707    dia = e_dialog_new(con, "E", "_fm2_view_image_select_dialog");
8708    if (!dia) return;
8709    e_dialog_title_set(dia, title);
8710
8711    o = e_widget_fsel_add(dia->win->evas, "/", sd->realpath, NULL, NULL, NULL, sd, NULL, sd, 1);
8712    evas_object_show(o);
8713    e_widget_size_min_get(o, &w, &h);
8714    e_dialog_content_set(dia, o, w, h);
8715    dia->data = o;
8716
8717    e_dialog_button_add(dia, _("OK"), NULL, ok_cb, sd);
8718    e_dialog_button_add(dia, _("Clear"), NULL, clear_cb, sd);
8719    e_dialog_button_add(dia, _("Cancel"), NULL, _e_fm2_view_image_sel_close, sd);
8720    e_dialog_resizable_set(dia, 1);
8721    e_win_centered_set(dia->win, 1);
8722    e_dialog_show(dia);
8723
8724    sd->image_dialog = dia;
8725 }
8726
8727 static void
8728 _e_fm2_view_image_sel_close(void *data, E_Dialog *dia)
8729 {
8730    E_Fm2_Smart_Data *sd;
8731
8732    sd = data;
8733    e_object_del(E_OBJECT(dia));
8734    sd->image_dialog = NULL;
8735 }
8736
8737 static void
8738 _custom_file_key_set(E_Fm2_Smart_Data *sd, const char *key, const char *value)
8739 {
8740    Efreet_Desktop *ef;
8741    char buf[PATH_MAX];
8742    int len;
8743
8744    snprintf(buf, sizeof(buf), "%s/.directory.desktop", sd->realpath);
8745    ef = efreet_desktop_new(buf);
8746    if (!ef)
8747      {
8748         ef = efreet_desktop_empty_new(buf);
8749         if (!ef) return;
8750         ef->type = EFREET_DESKTOP_TYPE_DIRECTORY;
8751         ef->name = strdup("Directory look and feel");
8752      }
8753
8754    len = strlen(sd->realpath);
8755    if (!strncmp(value, sd->realpath, len))
8756      efreet_desktop_x_field_set(ef, key, value + len + 1);
8757    else
8758      efreet_desktop_x_field_set(ef, key, value);
8759
8760    efreet_desktop_save(ef);
8761    efreet_desktop_free(ef);
8762 }
8763
8764 static void
8765 _custom_file_key_del(E_Fm2_Smart_Data *sd, const char *key)
8766 {
8767    Efreet_Desktop *ef;
8768    char buf[PATH_MAX];
8769
8770    snprintf(buf, sizeof(buf), "%s/.directory.desktop", sd->realpath);
8771    ef = efreet_desktop_new(buf);
8772    if (!ef) return;
8773
8774    if (efreet_desktop_x_field_del(ef, key))
8775      efreet_desktop_save(ef);
8776
8777    efreet_desktop_free(ef);
8778 }
8779
8780 static void
8781 _set_background_cb(void *data, E_Dialog *dia)
8782 {
8783    E_Fm2_Smart_Data *sd;
8784    const char *file;
8785
8786    sd = data;
8787    if (!sd) return;
8788
8789    file = e_widget_fsel_selection_path_get(dia->data);
8790
8791    if (file)
8792      _custom_file_key_set(sd, "X-Enlightenment-Directory-Wallpaper", file);
8793
8794    _e_fm2_view_image_sel_close(data, dia);
8795    evas_object_smart_callback_call(sd->obj, "dir_changed", NULL);
8796 }
8797
8798 static void
8799 _clear_background_cb(void *data, E_Dialog *dia)
8800 {
8801    E_Fm2_Smart_Data *sd;
8802
8803    sd = data;
8804    if (!sd) return;
8805
8806    _e_fm2_view_image_sel_close(data, dia);
8807
8808    _custom_file_key_del(sd, "X-Enlightenment-Directory-Wallpaper");
8809    evas_object_smart_callback_call(sd->obj, "dir_changed", NULL);
8810 }
8811
8812 static void
8813 _e_fm2_view_menu_set_background_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
8814 {
8815    E_Fm2_Smart_Data *sd;
8816
8817    sd = data;
8818    if (sd->image_dialog) return;
8819
8820    _e_fm2_view_image_sel(sd, _("Set background..."), _set_background_cb,
8821                          _clear_background_cb);
8822 }
8823
8824 static void
8825 _set_overlay_cb(void *data, E_Dialog *dia)
8826 {
8827    E_Fm2_Smart_Data *sd;
8828    const char *file;
8829
8830    sd = data;
8831    if (!sd) return;
8832
8833    file = e_widget_fsel_selection_path_get(dia->data);
8834
8835    if (file)
8836      _custom_file_key_set(sd, "X-Enlightenment-Directory-Overlay", file);
8837
8838    _e_fm2_view_image_sel_close(data, dia);
8839    evas_object_smart_callback_call(sd->obj, "dir_changed", NULL);
8840 }
8841
8842 static void
8843 _clear_overlay_cb(void *data, E_Dialog *dia)
8844 {
8845    E_Fm2_Smart_Data *sd;
8846
8847    sd = data;
8848    if (!sd) return;
8849
8850    _e_fm2_view_image_sel_close(data, dia);
8851
8852    _custom_file_key_del(sd, "X-Enlightenment-Directory-Overlay");
8853    evas_object_smart_callback_call(sd->obj, "dir_changed", NULL);
8854 }
8855
8856 static void
8857 _e_fm2_view_menu_set_overlay_cb(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
8858 {
8859    E_Fm2_Smart_Data *sd;
8860
8861    sd = data;
8862    if (sd->image_dialog) return;
8863
8864    _e_fm2_view_image_sel(sd, _("Set overlay..."), _set_overlay_cb,
8865                          _clear_overlay_cb);
8866 }
8867
8868 static void
8869 _e_fm2_refresh(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
8870 {
8871    E_Fm2_Smart_Data *sd;
8872
8873    sd = data;
8874    if (sd->refresh_job) ecore_job_del(sd->refresh_job);
8875    sd->refresh_job = ecore_job_add(_e_fm2_refresh_job_cb, sd->obj);
8876 }
8877
8878 static void
8879 _e_fm2_toggle_hidden_files(void *data, E_Menu *m, E_Menu_Item *mi)
8880 {
8881    E_Fm2_Smart_Data *sd;
8882
8883    sd = data;
8884    if (sd->show_hidden_files)
8885      sd->show_hidden_files = EINA_FALSE;
8886    else
8887      sd->show_hidden_files = EINA_TRUE;
8888
8889    sd->inherited_dir_props = EINA_FALSE;
8890    _e_fm2_refresh(data, m, mi);
8891 }
8892
8893 static void
8894 _e_fm2_toggle_ordering(void *data, E_Menu *m, E_Menu_Item *mi)
8895 {
8896    E_Fm2_Smart_Data *sd;
8897    char buf[4096];
8898
8899    sd = data;
8900    if (sd->order_file)
8901      {
8902         snprintf(buf, sizeof(buf), "%s/.order", sd->realpath);
8903         /* FIXME: move to e_fm_main */
8904         ecore_file_unlink(buf);
8905      }
8906    else
8907      {
8908         FILE *f;
8909
8910         snprintf(buf, sizeof(buf), "%s/.order", sd->realpath);
8911         f = fopen(buf, "w");
8912         if (f) fclose(f);
8913      }
8914    sd->inherited_dir_props = EINA_FALSE;
8915    _e_fm2_refresh(data, m, mi);
8916 }
8917
8918 static void
8919 _e_fm2_sort(void *data, E_Menu *m, E_Menu_Item *mi)
8920 {
8921    E_Fm2_Smart_Data *sd;
8922
8923    sd = data;
8924    sd->icons = eina_list_sort(sd->icons, eina_list_count(sd->icons),
8925                               _e_fm2_cb_icon_sort);
8926    _e_fm2_refresh(data, m, mi);
8927 }
8928
8929 static void
8930 _e_fm2_new_directory(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
8931 {
8932    E_Fm2_Smart_Data *sd;
8933    E_Manager *man;
8934    E_Container *con;
8935
8936    sd = data;
8937    if (sd->entry_dialog) return;
8938
8939    man = e_manager_current_get();
8940    if (!man) return;
8941    con = e_container_current_get(man);
8942    if (!con) return;
8943
8944    sd->entry_dialog = e_entry_dialog_show(_("Create a new Directory"), "folder",
8945                                           _("New Directory Name:"),
8946                                           "", NULL, NULL,
8947                                           _e_fm2_new_directory_yes_cb,
8948                                           _e_fm2_new_directory_no_cb, sd);
8949    E_OBJECT(sd->entry_dialog)->data = sd;
8950    e_object_del_attach_func_set(E_OBJECT(sd->entry_dialog), _e_fm2_new_directory_delete_cb);
8951 }
8952
8953 static void
8954 _e_fm2_new_directory_delete_cb(void *obj)
8955 {
8956    E_Fm2_Smart_Data *sd;
8957
8958    sd = E_OBJECT(obj)->data;
8959    sd->entry_dialog = NULL;
8960 }
8961
8962 static void
8963 _e_fm2_new_directory_yes_cb(char *text, void *data)
8964 {
8965    E_Fm2_Smart_Data *sd;
8966    char buf[PATH_MAX];
8967
8968    sd = data;
8969    sd->entry_dialog = NULL;
8970    if ((text) && (text[0]))
8971      {
8972         snprintf(buf, sizeof(buf), "%s/%s", sd->realpath, text);
8973
8974         _e_fm2_client_file_mkdir(buf, "", 0, 0, 0, sd->w, sd->h, sd->obj);
8975      }
8976 }
8977
8978 static void
8979 _e_fm2_new_directory_no_cb(void *data)
8980 {
8981    E_Fm2_Smart_Data *sd;
8982
8983    sd = data;
8984    sd->entry_dialog = NULL;
8985 }
8986
8987 static void
8988 _e_fm2_file_rename(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
8989 {
8990    E_Fm2_Icon *ic;
8991    char text[PATH_MAX + 256];
8992
8993    ic = data;
8994    if ((ic->entry_dialog) || (ic->entry_widget)) return;
8995
8996    if (!_e_fm2_icon_entry_widget_add(ic))
8997      {
8998         snprintf(text, PATH_MAX + 256,
8999                  _("Rename %s to:"),
9000                  ic->info.file);
9001         ic->entry_dialog = e_entry_dialog_show(_("Rename File"), "edit-rename",
9002                                                text, ic->info.file, NULL, NULL,
9003                                                _e_fm2_file_rename_yes_cb,
9004                                                _e_fm2_file_rename_no_cb, ic);
9005         E_OBJECT(ic->entry_dialog)->data = ic;
9006         e_object_del_attach_func_set(E_OBJECT(ic->entry_dialog),
9007                                      _e_fm2_file_rename_delete_cb);
9008      }
9009 }
9010
9011 static Evas_Object *
9012 _e_fm2_icon_entry_widget_add(E_Fm2_Icon *ic)
9013 {
9014    Evas_Object *eo;
9015
9016    if (ic->sd->iop_icon)
9017      _e_fm2_icon_entry_widget_accept(ic->sd->iop_icon);
9018
9019    if (!edje_object_part_exists(ic->obj, "e.swallow.entry"))
9020      return NULL;
9021
9022    ic->entry_widget = e_widget_entry_add(evas_object_evas_get(ic->obj),
9023                                          NULL, NULL, NULL, NULL);
9024    evas_object_event_callback_add(ic->entry_widget, EVAS_CALLBACK_KEY_DOWN,
9025                                   _e_fm2_icon_entry_widget_cb_key_down, ic);
9026    edje_object_part_swallow(ic->obj, "e.swallow.entry", ic->entry_widget);
9027    evas_object_show(ic->entry_widget);
9028    e_widget_entry_text_set(ic->entry_widget, ic->info.file);
9029    e_widget_focus_set(ic->entry_widget, 0);
9030    eo = e_widget_entry_editable_object_get(ic->entry_widget);
9031    e_editable_cursor_move_to_start(eo);
9032    e_editable_selection_move_to_end(eo);
9033    ic->sd->iop_icon = ic;
9034
9035    return ic->entry_widget;
9036 }
9037
9038 static void
9039 _e_fm2_icon_entry_widget_del(E_Fm2_Icon *ic)
9040 {
9041    ic->sd->iop_icon = NULL;
9042    evas_object_focus_set(ic->sd->obj, 1);
9043    evas_object_del(ic->entry_widget);
9044    ic->entry_widget = NULL;
9045 }
9046
9047 static void
9048 _e_fm2_icon_entry_widget_cb_key_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
9049 {
9050    Evas_Event_Key_Down *ev;
9051    E_Fm2_Icon *ic;
9052
9053    ev = event_info;
9054    ic = data;
9055
9056    if (!strcmp(ev->key, "Escape"))
9057      _e_fm2_icon_entry_widget_del(ic);
9058    else if (!strcmp(ev->key, "Return"))
9059      _e_fm2_icon_entry_widget_accept(ic);
9060 }
9061
9062 static void
9063 _e_fm2_icon_entry_widget_accept(E_Fm2_Icon *ic)
9064 {
9065    _e_fm2_file_do_rename(e_widget_entry_text_get(ic->entry_widget), ic);
9066    _e_fm2_icon_entry_widget_del(ic);
9067 }
9068
9069 static void
9070 _e_fm2_file_rename_delete_cb(void *obj)
9071 {
9072    E_Fm2_Icon *ic;
9073
9074    ic = E_OBJECT(obj)->data;
9075    ic->entry_dialog = NULL;
9076 }
9077
9078 static void
9079 _e_fm2_file_rename_yes_cb(char *text, void *data)
9080 {
9081    E_Fm2_Icon *ic;
9082
9083    ic = data;
9084    ic->entry_dialog = NULL;
9085
9086    _e_fm2_file_do_rename(text, ic);
9087 }
9088
9089 static void
9090 _e_fm2_file_rename_no_cb(void *data)
9091 {
9092    E_Fm2_Icon *ic;
9093
9094    ic = data;
9095    ic->entry_dialog = NULL;
9096 }
9097
9098 static void
9099 _e_fm2_file_do_rename(const char *text, E_Fm2_Icon *ic)
9100 {
9101    char oldpath[PATH_MAX];
9102    char newpath[PATH_MAX];
9103    char *args = NULL;
9104    size_t size = 0;
9105    size_t length = 0;
9106
9107    if ((text) && (strcmp(text, ic->info.file)))
9108      {
9109         _e_fm2_icon_realpath(ic, oldpath, sizeof(oldpath));
9110         snprintf(newpath, sizeof(newpath), "%s/%s", ic->sd->realpath, text);
9111         if (e_filereg_file_protected(oldpath)) return;
9112
9113         args = _e_fm_string_append_quoted(args, &size, &length, oldpath);
9114         args = _e_fm_string_append_char(args, &size, &length, ' ');
9115         args = _e_fm_string_append_quoted(args, &size, &length, newpath);
9116
9117         _e_fm_client_file_move(args, ic->sd->obj);
9118         free(args);
9119      }
9120 }
9121
9122 static E_Dialog *
9123 _e_fm_retry_abort_dialog(int pid, const char *str)
9124 {
9125    E_Manager *man;
9126    E_Container *con;
9127    E_Dialog *dialog;
9128    int *id;
9129    char text[4096 + PATH_MAX];
9130
9131    man = e_manager_current_get();
9132    if (!man) return NULL;
9133    con = e_container_current_get(man);
9134    if (!con) return NULL;
9135
9136    id = malloc(sizeof(int));
9137    *id = pid;
9138
9139    dialog = e_dialog_new(con, "E", "_fm_overwrite_dialog");
9140    E_OBJECT(dialog)->data = id;
9141    e_object_del_attach_func_set(E_OBJECT(dialog), _e_fm_retry_abort_delete_cb);
9142    e_dialog_button_add(dialog, _("Retry"), NULL, _e_fm_retry_abort_retry_cb, NULL);
9143    e_dialog_button_add(dialog, _("Abort"), NULL, _e_fm_retry_abort_abort_cb, NULL);
9144
9145    e_dialog_button_focus_num(dialog, 0);
9146    e_dialog_title_set(dialog, _("Error"));
9147    e_dialog_icon_set(dialog, "dialog-error", 64);
9148    snprintf(text, sizeof(text),
9149             _("%s"),
9150             str);
9151
9152    e_dialog_text_set(dialog, text);
9153    e_win_centered_set(dialog->win, 1);
9154    e_dialog_show(dialog);
9155    return dialog;
9156 }
9157
9158 static void
9159 _e_fm_retry_abort_delete_cb(void *obj)
9160 {
9161    int *id = E_OBJECT(obj)->data;
9162    free(id);
9163 }
9164
9165 static void
9166 _e_fm_retry_abort_retry_cb(void *data __UNUSED__, E_Dialog *dialog)
9167 {
9168    int *id = E_OBJECT(dialog)->data;
9169    _e_fm2_op_registry_go_on(*id);
9170    _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_RETRY, *id, NULL, 0);
9171    e_object_del(E_OBJECT(dialog));
9172 }
9173
9174 static void
9175 _e_fm_retry_abort_abort_cb(void *data __UNUSED__, E_Dialog *dialog)
9176 {
9177    int *id = E_OBJECT(dialog)->data;
9178    _e_fm2_op_registry_aborted(*id);
9179    _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_ABORT, *id, NULL, 0);
9180    e_object_del(E_OBJECT(dialog));
9181 }
9182
9183 static E_Dialog *
9184 _e_fm_overwrite_dialog(int pid, const char *str)
9185 {
9186    E_Manager *man;
9187    E_Container *con;
9188    E_Dialog *dialog;
9189    int *id;
9190    char text[4096 + PATH_MAX];
9191
9192    man = e_manager_current_get();
9193    if (!man) return NULL;
9194    con = e_container_current_get(man);
9195    if (!con) return NULL;
9196
9197    id = malloc(sizeof(int));
9198    *id = pid;
9199
9200    dialog = e_dialog_new(con, "E", "_fm_overwrite_dialog");
9201    E_OBJECT(dialog)->data = id;
9202    e_object_del_attach_func_set(E_OBJECT(dialog), _e_fm_overwrite_delete_cb);
9203    e_dialog_button_add(dialog, _("No"), NULL, _e_fm_overwrite_no_cb, NULL);
9204    e_dialog_button_add(dialog, _("No to all"), NULL, _e_fm_overwrite_no_all_cb, NULL);
9205    e_dialog_button_add(dialog, _("Yes"), NULL, _e_fm_overwrite_yes_cb, NULL);
9206    e_dialog_button_add(dialog, _("Yes to all"), NULL, _e_fm_overwrite_yes_all_cb, NULL);
9207
9208    e_dialog_button_focus_num(dialog, 0);
9209    e_dialog_title_set(dialog, _("Warning"));
9210    e_dialog_icon_set(dialog, "dialog-warning", 64);
9211    snprintf(text, sizeof(text),
9212             _("File already exists, overwrite?<br><hilight>%s</hilight>"), str);
9213
9214    e_dialog_text_set(dialog, text);
9215    e_win_centered_set(dialog->win, 1);
9216    e_dialog_show(dialog);
9217    return dialog;
9218 }
9219
9220 static void
9221 _e_fm_overwrite_delete_cb(void *obj)
9222 {
9223    int *id = E_OBJECT(obj)->data;
9224    free(id);
9225 }
9226
9227 static void
9228 _e_fm_overwrite_no_cb(void *data __UNUSED__, E_Dialog *dialog)
9229 {
9230    int *id = E_OBJECT(dialog)->data;
9231    _e_fm2_op_registry_go_on(*id);
9232    _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_NO, *id, NULL, 0);
9233    e_object_del(E_OBJECT(dialog));
9234 }
9235
9236 static void
9237 _e_fm_overwrite_no_all_cb(void *data __UNUSED__, E_Dialog *dialog)
9238 {
9239    int *id = E_OBJECT(dialog)->data;
9240    _e_fm2_op_registry_go_on(*id);
9241    _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_NO_ALL, *id, NULL, 0);
9242    e_object_del(E_OBJECT(dialog));
9243 }
9244
9245 static void
9246 _e_fm_overwrite_yes_cb(void *data __UNUSED__, E_Dialog *dialog)
9247 {
9248    int *id = E_OBJECT(dialog)->data;
9249    _e_fm2_op_registry_go_on(*id);
9250    _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_YES, *id, NULL, 0);
9251    e_object_del(E_OBJECT(dialog));
9252 }
9253
9254 static void
9255 _e_fm_overwrite_yes_all_cb(void *data __UNUSED__, E_Dialog *dialog)
9256 {
9257    int *id = E_OBJECT(dialog)->data;
9258    _e_fm2_op_registry_go_on(*id);
9259    _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_YES_ALL, *id, NULL, 0);
9260    e_object_del(E_OBJECT(dialog));
9261 }
9262
9263 static E_Dialog *
9264 _e_fm_error_dialog(int pid, const char *str)
9265 {
9266    E_Manager *man;
9267    E_Container *con;
9268    E_Dialog *dialog;
9269    int *id;
9270    char text[4096 + PATH_MAX];
9271
9272    man = e_manager_current_get();
9273    if (!man) return NULL;
9274    con = e_container_current_get(man);
9275    if (!con) return NULL;
9276
9277    id = malloc(sizeof(int));
9278    *id = pid;
9279
9280    dialog = e_dialog_new(con, "E", "_fm_error_dialog");
9281    E_OBJECT(dialog)->data = id;
9282    e_object_del_attach_func_set(E_OBJECT(dialog), _e_fm_error_delete_cb);
9283    e_dialog_button_add(dialog, _("Retry"), NULL, _e_fm_error_retry_cb, NULL);
9284    e_dialog_button_add(dialog, _("Abort"), NULL, _e_fm_error_abort_cb, NULL);
9285    e_dialog_button_add(dialog, _("Ignore this"), NULL, _e_fm_error_ignore_this_cb, NULL);
9286    e_dialog_button_add(dialog, _("Ignore all"), NULL, _e_fm_error_ignore_all_cb, NULL);
9287
9288    e_dialog_button_focus_num(dialog, 0);
9289    e_dialog_title_set(dialog, _("Error"));
9290    snprintf(text, sizeof(text),
9291             _("An error occurred while performing an operation.<br>"
9292               "%s"),
9293             str);
9294
9295    e_dialog_text_set(dialog, text);
9296    e_win_centered_set(dialog->win, 1);
9297    e_dialog_show(dialog);
9298    return dialog;
9299 }
9300
9301 static void
9302 _e_fm_error_delete_cb(void *obj)
9303 {
9304    int *id = E_OBJECT(obj)->data;
9305    free(id);
9306 }
9307
9308 static void
9309 _e_fm_error_retry_cb(void *data __UNUSED__, E_Dialog *dialog)
9310 {
9311    int *id = E_OBJECT(dialog)->data;
9312    _e_fm2_op_registry_go_on(*id);
9313    _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_RETRY, *id, NULL, 0);
9314    e_object_del(E_OBJECT(dialog));
9315 }
9316
9317 static void
9318 _e_fm_error_abort_cb(void *data __UNUSED__, E_Dialog *dialog)
9319 {
9320    int *id = E_OBJECT(dialog)->data;
9321    _e_fm2_op_registry_aborted(*id);
9322    _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_ABORT, *id, NULL, 0);
9323    e_object_del(E_OBJECT(dialog));
9324 }
9325
9326 static void
9327 _e_fm_error_ignore_this_cb(void *data __UNUSED__, E_Dialog *dialog)
9328 {
9329    int *id = E_OBJECT(dialog)->data;
9330    _e_fm2_op_registry_go_on(*id);
9331    _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_IGNORE_THIS, *id, NULL, 0);
9332    e_object_del(E_OBJECT(dialog));
9333 }
9334
9335 static void
9336 _e_fm_error_ignore_all_cb(void *data __UNUSED__, E_Dialog *dialog)
9337 {
9338    int *id = E_OBJECT(dialog)->data;
9339    _e_fm2_op_registry_go_on(*id);
9340    _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_IGNORE_ALL, *id, NULL, 0);
9341    e_object_del(E_OBJECT(dialog));
9342 }
9343
9344 static void
9345 _e_fm_device_error_dialog(const char *title, const char *msg, const char *pstr)
9346 {
9347    E_Manager *man;
9348    E_Container *con;
9349    E_Dialog *dialog;
9350    char text[PATH_MAX];
9351    const char *u, *d, *n, *m;
9352
9353    man = e_manager_current_get();
9354    if (!man) return;
9355    con = e_container_current_get(man);
9356    if (!con) return;
9357
9358    dialog = e_dialog_new(con, "E", "_fm_device_error_dialog");
9359    e_dialog_title_set(dialog, title);
9360    e_dialog_icon_set(dialog, "drive-harddisk", 64);
9361    e_dialog_button_add(dialog, _("OK"), NULL, NULL, NULL);
9362
9363    u = pstr;
9364    pstr += strlen(pstr) + 1;
9365    d = pstr;
9366    pstr += strlen(pstr) + 1;
9367    n = pstr;
9368    pstr += strlen(pstr) + 1;
9369    m = pstr;
9370    snprintf(text, sizeof(text), "%s<br>%s<br>%s<br>%s<br>%s", msg, u, d, n, m);
9371    e_dialog_text_set(dialog, text);
9372
9373    e_win_centered_set(dialog->win, 1);
9374    e_dialog_button_focus_num(dialog, 0);
9375    e_dialog_show(dialog);
9376 }
9377
9378 static void
9379 _e_fm2_file_application_properties(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
9380 {
9381    Efreet_Desktop *desktop;
9382    E_Fm2_Icon *ic;
9383    E_Manager *man;
9384    E_Container *con;
9385    char buf[PATH_MAX];
9386
9387    ic = data;
9388    if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
9389      return;
9390    desktop = efreet_desktop_get(buf);
9391
9392    man = e_manager_current_get();
9393    if (!man) return;
9394    con = e_container_current_get(man);
9395    if (!con) return;
9396
9397    e_desktop_edit(con, desktop);
9398 }
9399
9400 static void
9401 _e_fm2_file_properties(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
9402 {
9403    E_Fm2_Icon *ic;
9404    E_Manager *man;
9405    E_Container *con;
9406
9407    ic = data;
9408    if ((ic->entry_dialog) || (ic->entry_widget)) return;
9409
9410    man = e_manager_current_get();
9411    if (!man) return;
9412    con = e_container_current_get(man);
9413    if (!con) return;
9414
9415    if (ic->prop_dialog) e_object_del(E_OBJECT(ic->prop_dialog));
9416    ic->prop_dialog = e_fm_prop_file(con, ic);
9417    E_OBJECT(ic->prop_dialog)->data = ic;
9418    e_object_del_attach_func_set(E_OBJECT(ic->prop_dialog), _e_fm2_file_properties_delete_cb);
9419 }
9420
9421 static void
9422 _e_fm2_file_properties_delete_cb(void *obj)
9423 {
9424    E_Fm2_Icon *ic;
9425
9426    ic = E_OBJECT(obj)->data;
9427    ic->prop_dialog = NULL;
9428 }
9429
9430 static void
9431 _e_fm2_file_delete_menu(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
9432 {
9433    E_Fm2_Icon *ic = data;
9434    if ((!ic) || (!ic->sd)) return;
9435    _e_fm2_file_delete(ic->sd->obj);
9436 }
9437
9438 static void
9439 _e_fm2_file_delete(Evas_Object *obj)
9440 {
9441    E_Manager *man;
9442    E_Container *con;
9443    E_Dialog *dialog;
9444    E_Fm2_Icon *ic;
9445    char text[4096 + 256];
9446    Eina_List *sel;
9447
9448    man = e_manager_current_get();
9449    if (!man) return;
9450    con = e_container_current_get(man);
9451    if (!con) return;
9452    ic = _e_fm2_icon_first_selected_find(obj);
9453    if (!ic) return;
9454    if (ic->dialog) return;
9455    dialog = e_dialog_new(con, "E", "_fm_file_delete_dialog");
9456    ic->dialog = dialog;
9457    E_OBJECT(dialog)->data = ic;
9458    e_object_del_attach_func_set(E_OBJECT(dialog), _e_fm2_file_delete_delete_cb);
9459    e_dialog_button_add(dialog, _("Yes"), NULL, _e_fm2_file_delete_yes_cb, ic);
9460    e_dialog_button_add(dialog, _("No"), NULL, _e_fm2_file_delete_no_cb, ic);
9461    e_dialog_button_focus_num(dialog, 1);
9462    e_dialog_title_set(dialog, _("Confirm Delete"));
9463    e_dialog_icon_set(dialog, "dialog-warning", 64);
9464    sel = e_fm2_selected_list_get(obj);
9465    if ((!sel) || (eina_list_count(sel) == 1))
9466      snprintf(text, sizeof(text),
9467               _("Are you sure you want to delete<br>"
9468                 "<hilight>%s</hilight> ?"),
9469               ic->info.file);
9470    else
9471      {
9472         snprintf(text, sizeof(text),
9473                  _("Are you sure you want to delete<br>"
9474                    "the %d selected files in:<br>"
9475                    "<hilight>%s</hilight> ?"),
9476                  eina_list_count(sel),
9477                  ic->sd->realpath);
9478      }
9479    if (sel) eina_list_free(sel);
9480    e_dialog_text_set(dialog, text);
9481    e_win_centered_set(dialog->win, 1);
9482    e_dialog_show(dialog);
9483 }
9484
9485 static void
9486 _e_fm2_file_delete_delete_cb(void *obj)
9487 {
9488    E_Fm2_Icon *ic;
9489
9490    ic = E_OBJECT(obj)->data;
9491    ic->dialog = NULL;
9492 }
9493
9494 static char *
9495 _e_fm_string_append_char(char *str, size_t *size, size_t *len, char c)
9496 {
9497    if (!str)
9498      {
9499         str = malloc(4096);
9500         str[0] = '\x00';
9501         *size = 4096;
9502         *len = 0;
9503      }
9504
9505    if (*len >= *size - 1)
9506      {
9507         *size += 1024;
9508         str = realloc(str, *size);
9509      }
9510
9511    str[(*len)++] = c;
9512    str[*len] = '\x00';
9513
9514    return str;
9515 }
9516
9517 static char *
9518 _e_fm_string_append_quoted(char *str, size_t *size, size_t *len, const char *src)
9519 {
9520    str = _e_fm_string_append_char(str, size, len, '\'');
9521
9522    while (*src)
9523      {
9524         if (*src == '\'')
9525           {
9526              str = _e_fm_string_append_char(str, size, len, '\'');
9527              str = _e_fm_string_append_char(str, size, len, '\\');
9528              str = _e_fm_string_append_char(str, size, len, '\'');
9529              str = _e_fm_string_append_char(str, size, len, '\'');
9530           }
9531         else
9532           str = _e_fm_string_append_char(str, size, len, *src);
9533
9534         src++;
9535      }
9536
9537    str = _e_fm_string_append_char(str, size, len, '\'');
9538
9539    return str;
9540 }
9541
9542 static void
9543 _e_fm2_file_delete_yes_cb(void *data, E_Dialog *dialog)
9544 {
9545    E_Fm2_Icon *ic, *ic_next;
9546    char buf[PATH_MAX];
9547    char *files = NULL;
9548    size_t size = 0;
9549    size_t len = 0;
9550    Eina_List *sel, *l;
9551    E_Fm2_Icon_Info *ici;
9552
9553    ic = data;
9554    ic->dialog = NULL;
9555
9556    e_object_del(E_OBJECT(dialog));
9557    ic_next = _e_fm2_icon_next_find(ic->sd->obj, 1, NULL, NULL); 
9558    sel = e_fm2_selected_list_get(ic->sd->obj);
9559    if (sel && (eina_list_count(sel) != 1))
9560      {
9561         EINA_LIST_FOREACH(sel, l, ici)
9562           {
9563              if (ic_next && (&(ic_next->info) == ici))
9564                ic_next = NULL;
9565              
9566              snprintf(buf, sizeof(buf), "%s/%s", ic->sd->realpath, ici->file);
9567              if (e_filereg_file_protected(buf)) continue;
9568
9569              files = _e_fm_string_append_quoted(files, &size, &len, buf);
9570              if (eina_list_next(l))
9571                files = _e_fm_string_append_char(files, &size, &len, ' ');
9572           }
9573
9574         eina_list_free(sel);
9575      }
9576    else
9577      {
9578         _e_fm2_icon_realpath(ic, buf, sizeof(buf));
9579         if (e_filereg_file_protected(buf)) return;
9580         files = _e_fm_string_append_quoted(files, &size, &len, buf);
9581      }
9582
9583    _e_fm_client_file_del(files, ic->sd->obj);
9584
9585    free(files);
9586
9587    if (ic_next)
9588      {
9589         _e_fm2_icon_select(ic_next);
9590         evas_object_smart_callback_call(ic_next->sd->obj, "selection_change", NULL);
9591         _e_fm2_icon_make_visible(ic_next);
9592      }
9593    
9594    evas_object_smart_callback_call(ic->sd->obj, "files_deleted", NULL);
9595 }
9596
9597 static void
9598 _e_fm2_file_delete_no_cb(void *data, E_Dialog *dialog)
9599 {
9600    E_Fm2_Icon *ic;
9601
9602    ic = data;
9603    ic->dialog = NULL;
9604    e_object_del(E_OBJECT(dialog));
9605 }
9606
9607 static void
9608 _e_fm2_refresh_job_cb(void *data)
9609 {
9610    E_Fm2_Smart_Data *sd;
9611
9612    sd = evas_object_smart_data_get(data);
9613    if (!sd) return;
9614    e_fm2_refresh(data);
9615    sd->refresh_job = NULL;
9616 }
9617
9618 static void
9619 _e_fm2_live_file_add(Evas_Object *obj, const char *file, const char *file_rel, int after, E_Fm2_Finfo *finf)
9620 {
9621    E_Fm2_Smart_Data *sd;
9622    E_Fm2_Action *a;
9623
9624    sd = evas_object_smart_data_get(obj);
9625    if (!sd) return;
9626    a = E_NEW(E_Fm2_Action, 1);
9627    if (!a) return;
9628    sd->live.actions = eina_list_append(sd->live.actions, a);
9629    a->type = FILE_ADD;
9630    a->file = eina_stringshare_add(file);
9631    a->file2 = eina_stringshare_add(file_rel);
9632    a->flags = after;
9633    if (finf) memcpy(&(a->finf), finf, sizeof(E_Fm2_Finfo));
9634    a->finf.lnk = eina_stringshare_add(a->finf.lnk);
9635    a->finf.rlnk = eina_stringshare_add(a->finf.rlnk);
9636    _e_fm2_live_process_begin(obj);
9637 }
9638
9639 static void
9640 _e_fm2_live_file_del(Evas_Object *obj, const char *file)
9641 {
9642    E_Fm2_Smart_Data *sd;
9643    E_Fm2_Action *a;
9644
9645    sd = evas_object_smart_data_get(obj);
9646    if (!sd) return;
9647    a = E_NEW(E_Fm2_Action, 1);
9648    if (!a) return;
9649    sd->live.actions = eina_list_append(sd->live.actions, a);
9650    a->type = FILE_DEL;
9651    a->file = eina_stringshare_add(file);
9652    _e_fm2_live_process_begin(obj);
9653 }
9654
9655 static void
9656 _e_fm2_live_file_changed(Evas_Object *obj, const char *file, E_Fm2_Finfo *finf)
9657 {
9658    E_Fm2_Smart_Data *sd;
9659    E_Fm2_Action *a;
9660
9661    sd = evas_object_smart_data_get(obj);
9662    if (!sd) return;
9663    a = E_NEW(E_Fm2_Action, 1);
9664    if (!a) return;
9665    sd->live.actions = eina_list_append(sd->live.actions, a);
9666    a->type = FILE_CHANGE;
9667    a->file = eina_stringshare_add(file);
9668    if (finf) memcpy(&(a->finf), finf, sizeof(E_Fm2_Finfo));
9669    a->finf.lnk = eina_stringshare_add(a->finf.lnk);
9670    a->finf.rlnk = eina_stringshare_add(a->finf.rlnk);
9671    _e_fm2_live_process_begin(obj);
9672 }
9673
9674 static void
9675 _e_fm2_live_process_begin(Evas_Object *obj)
9676 {
9677    E_Fm2_Smart_Data *sd;
9678
9679    sd = evas_object_smart_data_get(obj);
9680    if (!sd->live.actions) return;
9681    if ((sd->live.idler) || (sd->live.timer) ||
9682        (sd->listing) || (sd->scan_timer)) return;
9683    sd->live.idler = ecore_idler_add(_e_fm2_cb_live_idler, obj);
9684    sd->live.timer = ecore_timer_add(0.2, _e_fm2_cb_live_timer, obj);
9685    sd->tmp.last_insert = NULL;
9686 }
9687
9688 static void
9689 _e_fm2_live_process_end(Evas_Object *obj)
9690 {
9691    E_Fm2_Smart_Data *sd;
9692    E_Fm2_Action *a;
9693
9694    sd = evas_object_smart_data_get(obj);
9695    EINA_LIST_FREE(sd->live.actions, a)
9696      {
9697         eina_stringshare_del(a->file);
9698         eina_stringshare_del(a->file2);
9699         eina_stringshare_del(a->finf.lnk);
9700         eina_stringshare_del(a->finf.rlnk);
9701         free(a);
9702      }
9703    if (sd->live.idler)
9704      {
9705         ecore_idler_del(sd->live.idler);
9706         sd->live.idler = NULL;
9707      }
9708    if (sd->live.timer)
9709      {
9710         ecore_timer_del(sd->live.timer);
9711         sd->live.timer = NULL;
9712      }
9713    sd->tmp.last_insert = NULL;
9714 }
9715
9716 static void
9717 _e_fm2_live_process(Evas_Object *obj)
9718 {
9719    E_Fm2_Smart_Data *sd;
9720    E_Fm2_Action *a;
9721    Eina_List *l;
9722    E_Fm2_Icon *ic;
9723
9724    sd = evas_object_smart_data_get(obj);
9725    if (!sd->live.actions) return;
9726    a = eina_list_data_get(sd->live.actions);
9727    sd->live.actions = eina_list_remove_list(sd->live.actions, sd->live.actions);
9728    switch (a->type)
9729      {
9730       case FILE_ADD:
9731         /* new file to sort in place */
9732         if (!strcmp(a->file, ".order"))
9733           {
9734              sd->order_file = EINA_TRUE;
9735              /* FIXME: reload fm view */
9736           }
9737         else
9738           {
9739              if (!((a->file[0] == '.') && (!sd->show_hidden_files)))
9740                _e_fm2_file_add(obj, a->file, 1, a->file2, a->flags, &(a->finf));
9741           }
9742         break;
9743
9744       case FILE_DEL:
9745         if (!strcmp(a->file, ".order"))
9746           {
9747              sd->order_file = EINA_FALSE;
9748              /* FIXME: reload fm view */
9749           }
9750         else
9751           {
9752              if (!((a->file[0] == '.') && (!sd->show_hidden_files)))
9753                _e_fm2_file_del(obj, a->file);
9754              sd->live.deletions = EINA_TRUE;
9755           }
9756         break;
9757
9758       case FILE_CHANGE:
9759         if (!strcmp(a->file, ".order"))
9760           {
9761              /* FIXME: reload fm view - ignore for now */
9762           }
9763         else
9764           {
9765              if (!((a->file[0] == '.') && (!sd->show_hidden_files)))
9766                {
9767                   EINA_LIST_FOREACH(sd->icons, l, ic)
9768                     {
9769                        if (!strcmp(ic->info.file, a->file))
9770                          {
9771                             if (ic->removable_state_change)
9772                               {
9773                                  _e_fm2_icon_unfill(ic);
9774                                  _e_fm2_icon_fill(ic, &(a->finf));
9775                                  ic->removable_state_change = EINA_FALSE;
9776                                  if ((ic->realized) && (ic->obj_icon))
9777                                    {
9778                                       _e_fm2_icon_removable_update(ic);
9779                                       _e_fm2_icon_label_set(ic, ic->obj);
9780                                    }
9781                               }
9782                             else
9783                               {
9784                                  int realized;
9785
9786                                  realized = ic->realized;
9787                                  if (realized) _e_fm2_icon_unrealize(ic);
9788                                  _e_fm2_icon_unfill(ic);
9789                                  _e_fm2_icon_fill(ic, &(a->finf));
9790                                  if (realized) _e_fm2_icon_realize(ic);
9791                               }
9792                             break;
9793                          }
9794                     }
9795                }
9796           }
9797         break;
9798
9799       default:
9800         break;
9801      }
9802    eina_stringshare_del(a->file);
9803    eina_stringshare_del(a->file2);
9804    eina_stringshare_del(a->finf.lnk);
9805    eina_stringshare_del(a->finf.rlnk);
9806    free(a);
9807 }
9808
9809 static Eina_Bool
9810 _e_fm2_cb_live_idler(void *data)
9811 {
9812    E_Fm2_Smart_Data *sd;
9813    double t;
9814
9815    sd = evas_object_smart_data_get(data);
9816    if (!sd) return ECORE_CALLBACK_CANCEL;
9817    t = ecore_time_get();
9818    do
9819      {
9820         if (!sd->live.actions) break;
9821         _e_fm2_live_process(data);
9822      }
9823    while ((ecore_time_get() - t) > 0.02);
9824    if (sd->live.actions) return ECORE_CALLBACK_RENEW;
9825    _e_fm2_live_process_end(data);
9826    _e_fm2_cb_live_timer(data);
9827    if ((sd->order_file) || (sd->config->view.always_order))
9828      {
9829         e_fm2_refresh(data);
9830      }
9831    sd->live.idler = NULL;
9832    return ECORE_CALLBACK_CANCEL;
9833 }
9834
9835 static Eina_Bool
9836 _e_fm2_cb_live_timer(void *data)
9837 {
9838    E_Fm2_Smart_Data *sd;
9839
9840    sd = evas_object_smart_data_get(data);
9841    if (!sd) return ECORE_CALLBACK_CANCEL;
9842    if (sd->queue) _e_fm2_queue_process(data);
9843    else if (sd->iconlist_changed)
9844      {
9845         if (sd->resize_job) ecore_job_del(sd->resize_job);
9846         sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, sd->obj);
9847      }
9848    else
9849      {
9850         if (sd->live.deletions)
9851           {
9852              sd->iconlist_changed = EINA_TRUE;
9853              if (sd->resize_job) ecore_job_del(sd->resize_job);
9854              sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, sd->obj);
9855           }
9856      }
9857    sd->live.deletions = EINA_FALSE;
9858    sd->live.timer = NULL;
9859    if ((!sd->queue) && (!sd->live.idler)) return ECORE_CALLBACK_CANCEL;
9860    sd->live.timer = ecore_timer_add(0.2, _e_fm2_cb_live_timer, data);
9861    return ECORE_CALLBACK_CANCEL;
9862 }
9863
9864 static int
9865 _e_fm2_theme_edje_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const char *category, const char *group)
9866 {
9867    char buf[1024];
9868    int ret;
9869
9870    if (sd->custom_theme_content)
9871      snprintf(buf, sizeof(buf), "e/fileman/%s/%s", sd->custom_theme_content, group);
9872    else
9873      snprintf(buf, sizeof(buf), "e/fileman/default/%s", group);
9874
9875    if (sd->custom_theme)
9876      {
9877         if (edje_object_file_set(o, sd->custom_theme, buf)) return 1;
9878      }
9879    if (sd->custom_theme)
9880      {
9881         if (!ecore_file_exists(sd->custom_theme))
9882           {
9883              eina_stringshare_del(sd->custom_theme);
9884              sd->custom_theme = NULL;
9885           }
9886      }
9887    ret = e_theme_edje_object_set(o, category, buf);
9888    return ret;
9889 }
9890
9891 static int
9892 _e_fm2_theme_edje_icon_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const char *category, const char *group)
9893 {
9894    char buf[1024];
9895    int ret;
9896
9897 //   if (sd->custom_theme_content)
9898 //     snprintf(buf, sizeof(buf), "e/icons/fileman/%s/%s", sd->custom_theme_content, group);
9899 //   else
9900    snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", group);
9901
9902    if (sd->custom_theme)
9903      {
9904         if (edje_object_file_set(o, sd->custom_theme, buf)) return 1;
9905      }
9906    if (sd->custom_theme)
9907      {
9908         if (!ecore_file_exists(sd->custom_theme))
9909           {
9910              eina_stringshare_del(sd->custom_theme);
9911              sd->custom_theme = NULL;
9912           }
9913      }
9914    ret = e_theme_edje_object_set(o, category, buf);
9915    return ret;
9916 }
9917
9918 static void
9919 _e_fm2_volume_mount(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
9920 {
9921    E_Volume *v;
9922    const char *mp;
9923
9924    v = data;
9925    if (!v) return;
9926
9927    mp = e_fm2_device_volume_mountpoint_get(v);
9928    _e_fm2_client_mount(v->udi, mp);
9929    eina_stringshare_del(mp);
9930 }
9931
9932 static void
9933 _e_fm2_volume_unmount(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
9934 {
9935    E_Volume *v;
9936
9937    v = data;
9938    if (!v) return;
9939
9940    v->auto_unmount = EINA_FALSE;
9941    _e_fm2_client_unmount(v->udi);
9942 }
9943
9944 static void
9945 _e_fm2_volume_eject(void *data, E_Menu *m __UNUSED__, E_Menu_Item *mi __UNUSED__)
9946 {
9947    E_Volume *v;
9948
9949    v = data;
9950    if (!v) return;
9951
9952    v->auto_unmount = EINA_FALSE;
9953    _e_fm2_client_eject(v->udi);
9954 }
9955
9956 static void
9957 _update_volume_icon(E_Volume *v, E_Fm2_Icon *ic)
9958 {
9959    if (ic->info.removable_full)
9960      edje_object_signal_emit(ic->obj_icon, "e,state,removable,full", "e");
9961    else
9962      edje_object_signal_emit(ic->obj_icon, "e,state,removable,empty", "e");
9963
9964    if (v)
9965      {
9966         if (v->mounted)
9967           edje_object_signal_emit(ic->obj, "e,state,volume,mounted", "e");
9968         else
9969           edje_object_signal_emit(ic->obj, "e,state,volume,unmounted", "e");
9970      }
9971    else
9972      edje_object_signal_emit(ic->obj, "e,state,volume,off", "e");
9973 }
9974
9975 static void
9976 _e_fm2_volume_icon_update(E_Volume *v)
9977 {
9978    Evas_Object *o;
9979    char file[PATH_MAX], fav[PATH_MAX], desk[PATH_MAX];
9980    Eina_List *l;
9981    E_Fm2_Icon *ic;
9982
9983    if (!v || !v->storage) return;
9984
9985    e_user_dir_snprintf(fav, sizeof(fav), "fileman/favorites");
9986    e_user_homedir_concat(desk, sizeof(desk), _("Desktop"));
9987    snprintf(file, sizeof(file), "|%s_%d.desktop",
9988             ecore_file_file_get(v->storage->udi), v->partition_number);
9989
9990    EINA_LIST_FOREACH(_e_fm2_list, l, o)
9991      {
9992         const char *rp;
9993
9994         if ((_e_fm2_list_walking > 0) &&
9995             (eina_list_data_find(_e_fm2_list_remove, o))) continue;
9996
9997         rp = e_fm2_real_path_get(o);
9998         if ((rp) && (strcmp(rp, fav)) && (strcmp(rp, desk))) continue;
9999
10000         ic = _e_fm2_icon_find(o, file);
10001         if (ic)
10002           _update_volume_icon(v, ic);
10003      }
10004 }
10005
10006 static void
10007 _e_fm2_icon_removable_update(E_Fm2_Icon *ic)
10008 {
10009    E_Volume *v;
10010
10011    if (!ic) return;
10012    v = e_fm2_device_volume_find(ic->info.link);
10013    _update_volume_icon(v, ic);
10014 }
10015
10016 static void
10017 _e_fm2_operation_abort_internal(E_Fm2_Op_Registry_Entry *ere)
10018 {
10019    ere->status = E_FM2_OP_STATUS_ABORTED;
10020    ere->finished = 1;
10021    ere->needs_attention = 0;
10022    ere->dialog = NULL;
10023    e_fm2_op_registry_entry_changed(ere);
10024    _e_fm_client_send(E_FM_OP_ABORT, ere->id, NULL, 0);
10025 }
10026
10027 EAPI void
10028 e_fm2_operation_abort(int id)
10029 {
10030    E_Fm2_Op_Registry_Entry *ere;
10031
10032    ere = e_fm2_op_registry_entry_get(id);
10033    if (!ere) return;
10034
10035    e_fm2_op_registry_entry_ref(ere);
10036    e_fm2_op_registry_entry_abort(ere);
10037    e_fm2_op_registry_entry_unref(ere);
10038 }
10039