This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository efm2.

View the commit online.

commit 90609d695442a602066c67651eb023536ebebf00
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
AuthorDate: Wed Apr 9 15:57:08 2025 +0100

    implement ln as an op (need to use alt when dropping for ask menu)
---
 src/backends/default/cp.c        |  14 ++--
 src/backends/default/fs.c        |   3 +-
 src/backends/default/ln.c        | 177 +++++++++++++++++++++++++++++++++++++++
 src/backends/default/meson.build |  14 +++-
 src/backends/default/open.c      |   3 +-
 src/efm/efm_dnd.c                |  29 ++++---
 src/efm/efm_util.c               |   1 +
 7 files changed, 218 insertions(+), 23 deletions(-)

diff --git a/src/backends/default/cp.c b/src/backends/default/cp.c
index c8832c3..4c76ffe 100644
--- a/src/backends/default/cp.c
+++ b/src/backends/default/cp.c
@@ -45,7 +45,7 @@ file_set_add(Eina_List *files, const char *src, const char *dst)
 
 int
 main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
-{ // mv [src] [dstdir]
+{ // cp [src] [dstdir]
   const char  *fname, *home_dir;
   Eina_Strbuf *buf   = NULL;
   Eina_List   *files = NULL, *l;
@@ -108,7 +108,7 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
   status_begin();
   status_op("cp");
 
-  // build up a list of all files to mv and scan them to find how much
+  // build up a list of all files to cp and scan them to find how much
   EINA_LIST_FOREACH(files, l, fs)
   {
     struct stat stsrc, stdst;
@@ -175,7 +175,7 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
     if ((!src) || (!srctmpdir) || (!dst) || (!dsttmpdir) || (!dsttmpfile))
       mem_abort();
 
-    // can we modify the meta files in the src? (like mv/rm them?)
+    // can we modify the meta files in the src? (like cp/rm them?)
     src_can_write = meta_path_can_write(src);
     dst_can_write = meta_path_can_write(dst);
 
@@ -191,7 +191,7 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
       }
     umask(prev_umask);
 
-    // mv the file to a tmp file: mv /srcdir/filename /dstdir/.efm/filename.tmp
+    // cp the file to a tmp file: cp /srcdir/filename /dstdir/.efm/filename.tmp
     if (fs_cp(src, dsttmpfile, EINA_TRUE))
       { // it worked so deal with meta/thumbs
         char *src_meta, *dst_meta;
@@ -220,7 +220,7 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
             status_count(1, src_meta);
             fs_cp(src_meta, dst_meta, EINA_FALSE);
             // fix up the oprig stat info to match so thub is valid
-            // get stat info of new mv'd file
+            // get stat info of new cp'd file
             if (stat(dsttmpfile, &st) == 0)
               {
                 Eet_File     *ef;
@@ -243,7 +243,7 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
         free(src_meta);
         free(dst_meta);
 
-        // rename atomically the tmp mv'd file to its dest now thumb and meta
+        // rename atomically the tmp cp'd file to its dest now thumb and meta
         // are ok/valid. i.e.
         // mv /dstdir/.efm/filename.tmp /distdir/filename
         ret = rename(dsttmpfile, dst);
@@ -282,4 +282,4 @@ err:
   eet_shutdown();
   eina_shutdown();
   return 0;
-}
\ No newline at end of file
+}
diff --git a/src/backends/default/fs.c b/src/backends/default/fs.c
index 5028f92..0aa89ae 100644
--- a/src/backends/default/fs.c
+++ b/src/backends/default/fs.c
@@ -471,7 +471,8 @@ fs_cp(const char *src, const char *dst, Eina_Bool report_err)
   return res;
 }
 
-Eina_Bool fs_ln(const char *src, const char *dst, Eina_Bool report_err)
+Eina_Bool
+fs_ln(const char *src, const char *dst, Eina_Bool report_err)
 { // ln -s /path/to/src/filename /path/to/dst/filename
   Eina_Bool res = EINA_TRUE;
   const char *op  = "Symlink";
diff --git a/src/backends/default/ln.c b/src/backends/default/ln.c
new file mode 100644
index 0000000..8599876
--- /dev/null
+++ b/src/backends/default/ln.c
@@ -0,0 +1,177 @@
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_File.h>
+#include <Efreet.h>
+#include <Efreet_Mime.h>
+#include <Eet.h>
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "meta.h"
+#include "status.h"
+#include "fs.h"
+#include "esc.h"
+#include "sha.h"
+
+static const char *config_dir = NULL;
+
+typedef struct _File_Set
+{
+  const char *src, *dst;
+} File_Set;
+
+static void
+mem_abort(void)
+{
+  fprintf(stderr, "Out of memory!\n");
+  abort();
+}
+
+static Eina_List *
+file_set_add(Eina_List *files, const char *src, const char *dst)
+{
+  File_Set *fs = calloc(1, sizeof(File_Set));
+  if (!fs) mem_abort();
+  fs->src = ""
+  fs->dst = eina_stringshare_add(dst);
+  if ((!fs->src) || (!fs->dst)) mem_abort();
+  files = eina_list_append(files, fs);
+  return files;
+}
+
+int
+main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
+{ // ln [src] [dstdir]
+  const char  *fname, *home_dir;
+  Eina_Strbuf *buf   = NULL;
+  Eina_List   *files = NULL, *l;
+  File_Set    *fs;
+  size_t       sz;
+  char        *src = ""
+  char        *dst = NULL, *dstfile = NULL;
+  char         sbuf[PATH_MAX + 256];
+  int          ret;
+  struct stat  st;
+
+  eina_init();
+  eet_init();
+  ecore_init();
+  efreet_init();
+
+  for (;;)
+    { // read stdin of key=val\n ... or end\n
+      if (!fgets(sbuf, sizeof(sbuf), stdin)) break;
+      sz = strlen(sbuf);
+      if (sz < 1) break;                             // too small
+      if (sbuf[sz - 1] == '\n') sbuf[sz - 1] = '\0'; // remove \n if there
+      if (!strncmp(sbuf, "src="" 4))
+        {
+          if (src) free(src);
+          src = "" + 4);
+        }
+      else if (!strncmp(sbuf, "dst=", 4))
+        {
+          if (dst) free(dst);
+          dst = unescape(sbuf + 4);
+          if ((src) && (dst)) files = file_set_add(files, src, dst);
+          if (src) free(src);
+          if (dst) free(dst);
+          src = ""
+          dst = NULL;
+        }
+      else if (!strcmp(sbuf, "end")) break;
+    }
+  if (src) free(src);
+  if (dst) free(dst);
+  src = "" = NULL;
+
+  config_dir = getenv("E_HOME_DIR");
+  home_dir   = getenv("HOME");
+  if (!home_dir) return 77; // no $HOME? definitely an error!
+  if (!config_dir)
+    {
+      snprintf(sbuf, sizeof(sbuf), "%s/.e/e", home_dir);
+      config_dir = eina_stringshare_add(sbuf);
+    }
+  meta_init(config_dir);
+
+  buf = eina_strbuf_new();
+  if (!buf) goto err;
+
+  // set up status files for the op
+  status_begin();
+  status_op("ln");
+
+  // build up a list of all files to cp and scan them to find how much
+  EINA_LIST_FOREACH(files, l, fs)
+  {
+    struct stat stsrc, stdst;
+
+    if (strlen(fs->src) < 1) goto err2;
+    if (lstat(fs->src, &stsrc) != 0) break;
+    if (lstat(fs->dst, &stdst) != 0) break;
+    if (stsrc.st_dev == stdst.st_dev) status_count(1, fs->src);
+    else if (!fs_scan(fs->src)) goto err2;
+  }
+
+  EINA_LIST_FOREACH(files, l, fs)
+  {
+    fname = ecore_file_file_get(fs->src);
+    if (!fname) break;
+    // when monitoring/watching a status file dst dst=xxx allows you to place
+    // progress in the right dst dir
+    status_dst(fs->dst);
+    ret = stat(fs->dst, &st);
+    if (ret != 0)
+      { // if we can't stat the dstdir then we have issues
+        status_error(fs->src, fs->dst, "Cannot stat destination");
+        break;
+      }
+
+    // free up previous loop stuff
+    free(dstfile);
+    src = "" = NULL;
+
+    src = ""
+
+    eina_strbuf_reset(buf);
+    eina_strbuf_append(buf, fs->dst);
+    eina_strbuf_append(buf, "/");
+    eina_strbuf_append(buf, fname);
+    dstfile = strdup(eina_strbuf_string_get(buf));
+    if ((!dstfile)) mem_abort();
+
+    // ln the file with full path - that's just what we will do
+    if (fs_ln(src, dstfile, EINA_TRUE))
+      { // it worked
+        status_count(1, src);
+      }
+    else break;
+  }
+err2:
+  status_end();
+  // free up leftover strings from loop
+  free(src);
+  free(dstfile);
+
+err:
+  if (buf) eina_strbuf_free(buf);
+  EINA_LIST_FREE(files, fs)
+  {
+    eina_stringshare_del(fs->src);
+    eina_stringshare_del(fs->dst);
+    free(fs);
+  }
+
+  meta_shutdown();
+
+  efreet_shutdown();
+  ecore_shutdown();
+  eet_shutdown();
+  eina_shutdown();
+  return 0;
+}
diff --git a/src/backends/default/meson.build b/src/backends/default/meson.build
index 10bfec4..53972f9 100644
--- a/src/backends/default/meson.build
+++ b/src/backends/default/meson.build
@@ -63,4 +63,16 @@ executable('cp', [
   dependencies: deps,
   install: true,
   install_dir: dir)
-  
\ No newline at end of file
+executable('ln', [
+    '../../shared/sha.c',
+    '../../shared/esc.c',
+    '../../shared/util.c',
+    'fs.c',
+    'ln.c',
+    'meta.c',
+    'status.c'
+  ],
+  include_directories: inc,
+  dependencies: deps,
+  install: true,
+  install_dir: dir)
diff --git a/src/backends/default/open.c b/src/backends/default/open.c
index 6ff7a6b..492dcce 100644
--- a/src/backends/default/open.c
+++ b/src/backends/default/open.c
@@ -1346,7 +1346,8 @@ _handle_drop_paste(const char *over, const char *action, Eina_List *files)
           _op_run("mv", files, mondir);
         }
       else if (!strcmp(action, "link"))
-        { // XXX: implement
+        {
+          _op_run("ln", files, mondir);
         }
       else // "ask", "list", "description", or anything else
         { // actully we should never get this
diff --git a/src/efm/efm_dnd.c b/src/efm/efm_dnd.c
index a98d397..6bfb638 100644
--- a/src/efm/efm_dnd.c
+++ b/src/efm/efm_dnd.c
@@ -157,15 +157,18 @@ _dnd_drop_handle(Smart_Data *sd, char *urilist, Elm_Xdnd_Action act)
       fprintf(stderr, "XXX: LINK\n");
       cmd_strbuf_append(buf, "action", "link");
       break;
-    /* here for documentation but not used
-    case ELM_XDND_ACTION_ASK:
-      break;
-    case ELM_XDND_ACTION_LIST:
-      break;
-    case ELM_XDND_ACTION_DESCRIPTION:
-      break;
-    */
+    // should not see ask as it should have been handled already, but others
+    // are possivble, but not supported
+    case ELM_XDND_ACTION_ASK: // for documentation
+      // fallthrough
+    case ELM_XDND_ACTION_LIST: // for documentation
+      // fallthrough
+    case ELM_XDND_ACTION_DESCRIPTION: // for documentation
+      // fallthrough
     default:
+      if (act == ELM_XDND_ACTION_ASK) fprintf(stderr, "XXX: ASK\n");
+      else if (act == ELM_XDND_ACTION_LIST) fprintf(stderr, "XXX: LIST\n");
+      else if (act == ELM_XDND_ACTION_DESCRIPTION) fprintf(stderr, "XXX: DESCRIPTION\n");
       eina_strbuf_free(buf);
       sd->drop_over = NULL;
       return;
@@ -362,15 +365,15 @@ _cb_drop(void *data, Evas_Object *o EINA_UNUSED, Elm_Selection_Data *ev)
   memcpy(tmp, ev->data, ev->len);
   tmp[ev->len] = 0;
   if (act == ELM_XDND_ACTION_ASK)
-    {
-      // XXX: store tmp as urilist and pop up ask menu
+    { // store tmp as urilist and pop up ask menu
       Efm_Menu *m
         = _efm_menu_add("What to do?", NULL, _cb_menu_dnd_ask_done, sd, NULL);
-      _efm_menu_it_normal(m, "Copy", NULL, _cb_menu_dnd_drop_copy, sd, NULL);
-      _efm_menu_it_normal(m, "Move", NULL, _cb_menu_dnd_drop_move, sd, NULL);
-      _efm_menu_it_normal(m, "Link", NULL, _cb_menu_dnd_drop_link, sd, NULL);
+      _efm_menu_it_normal(m, "Copy", "std:folder-copy", _cb_menu_dnd_drop_copy, sd, NULL);
+      _efm_menu_it_normal(m, "Move", "std:folder-move", _cb_menu_dnd_drop_move, sd, NULL);
+      _efm_menu_it_normal(m, "Link", "std:insert-link", _cb_menu_dnd_drop_link, sd, NULL);
       _efm_menu_show(sd->o_smart, m, sd->dnd_x, sd->dnd_y);
       sd->dnd_drop_data = tmp;
+      printf("XXX: drop action modified to ask by modifier key\n");
     }
   else
     { // handle dnd here as we know the action
diff --git a/src/efm/efm_util.c b/src/efm/efm_util.c
index fb2b57b..6c0858b 100644
--- a/src/efm/efm_util.c
+++ b/src/efm/efm_util.c
@@ -1355,6 +1355,7 @@ _cb_icon_mouse_move(void *data, Evas *e EINA_UNUSED,
   // XXX: this "except to/from removable drive" is bad/inconsistent imho
   if (ev->buttons & (1 << 2)) // right mouse pressed
     action = ""
+  printf("XXX: ASK = %i\n", action == EFM_ACTION_ASK);
   _drag_start(icon, action);
 }
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to