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