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