move more files.
[apps/madmutt.git] / lib-ui / complete.c
diff --git a/lib-ui/complete.c b/lib-ui/complete.c
new file mode 100644 (file)
index 0000000..2ad60ac
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright notice from original mutt:
+ * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <dirent.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <lib-lib/str.h>
+#include <lib-lib/file.h>
+
+#include "mutt.h"
+#include "mx.h"
+#include <imap/imap.h>
+#ifdef USE_NNTP
+#include <nntp/nntp.h>
+#endif
+
+/* given a partial pathname, this routine fills in as much of the rest of the
+ * path as is unique.
+ *
+ * return 0 if ok, -1 if no matches
+ */
+int mutt_complete (char *s, ssize_t slen)
+{
+  char *p;
+  DIR *dirp = NULL;
+  struct dirent *de;
+  int i, init = 0;
+  ssize_t len;
+  char dirpart[_POSIX_PATH_MAX], exp_dirpart[_POSIX_PATH_MAX];
+  char filepart[_POSIX_PATH_MAX];
+
+  char imap_path[LONG_STRING];
+
+#ifdef USE_NNTP
+  if (option (OPTNEWS)) {
+    string_list_t *l = CurrentNewsSrv->list;
+
+    m_strcpy(filepart, sizeof(filepart), s);
+
+    /*
+     * special case to handle when there is no filepart yet.
+     * find the first subscribed newsgroup
+     */
+    if ((len = m_strlen(filepart)) == 0) {
+      for (; l; l = l->next) {
+        NNTP_DATA *data = (NNTP_DATA *) l->data;
+
+        if (data && data->subscribed) {
+          m_strcpy(filepart, sizeof(filepart), data->group);
+          init++;
+          l = l->next;
+          break;
+        }
+      }
+    }
+
+    for (; l; l = l->next) {
+      NNTP_DATA *data = (NNTP_DATA *) l->data;
+
+      if (data && data->subscribed &&
+          m_strncmp(data->group, filepart, len) == 0) {
+        if (init) {
+          for (i = 0; filepart[i] && data->group[i]; i++) {
+            if (filepart[i] != data->group[i]) {
+              filepart[i] = 0;
+              break;
+            }
+          }
+          filepart[i] = 0;
+        }
+        else {
+          m_strcpy(filepart, sizeof(filepart), data->group);
+          init = 1;
+        }
+      }
+    }
+
+    strcpy (s, filepart);
+
+    return (init ? 0 : -1);
+  }
+#endif
+
+  /* we can use '/' as a delimiter, imap_complete rewrites it */
+  if (*s == '=' || *s == '+' || *s == '!') {
+      const char *q = NONULL(*s == '!' ? Spoolfile : Maildir);
+      mutt_concat_path(imap_path, sizeof(imap_path), q, s + 1);
+  }
+  else
+    m_strcpy(imap_path, sizeof(imap_path), s);
+
+  if (mx_get_magic (imap_path) == M_IMAP)
+    return imap_complete (s, slen, imap_path);
+
+  if (*s == '=' || *s == '+' || *s == '!') {
+    dirpart[0] = *s;
+    dirpart[1] = 0;
+    if (*s == '!')
+      m_strcpy(exp_dirpart, sizeof(exp_dirpart), NONULL(Spoolfile));
+    else
+      m_strcpy(exp_dirpart, sizeof(exp_dirpart), NONULL(Maildir));
+    if ((p = strrchr (s, '/'))) {
+      char buf[_POSIX_PATH_MAX];
+
+      *p++ = 0;
+      mutt_concat_path(buf, sizeof(buf), exp_dirpart, s + 1);
+      m_strcpy(exp_dirpart, sizeof(exp_dirpart), buf);
+      snprintf (buf, sizeof (buf), "%s%s/", dirpart, s + 1);
+      m_strcpy(dirpart, sizeof(dirpart), buf);
+      m_strcpy(filepart, sizeof(filepart), p);
+    }
+    else
+      m_strcpy(filepart, sizeof(filepart), s + 1);
+    dirp = opendir (exp_dirpart);
+  }
+  else {
+    if ((p = strrchr (s, '/'))) {
+      if (p == s) {             /* absolute path */
+        p = s + 1;
+        m_strcpy(dirpart, sizeof(dirpart), "/");
+        exp_dirpart[0] = 0;
+        m_strcpy(filepart, sizeof(filepart), p);
+        dirp = opendir (dirpart);
+      }
+      else {
+        *p = 0;
+        len = p - s;
+        memcpy(dirpart, s, len);
+        dirpart[len] = 0;
+        p++;
+        m_strcpy(filepart, sizeof(filepart), p);
+        m_strcpy(exp_dirpart, sizeof(exp_dirpart), dirpart);
+        mutt_expand_path (exp_dirpart, sizeof (exp_dirpart));
+        dirp = opendir (exp_dirpart);
+      }
+    }
+    else {
+      /* no directory name, so assume current directory. */
+      dirpart[0] = 0;
+      m_strcpy(filepart, sizeof(filepart), s);
+      dirp = opendir (".");
+    }
+  }
+
+  if (dirp == NULL) {
+    return (-1);
+  }
+
+  /*
+   * special case to handle when there is no filepart yet.  find the first
+   * file/directory which is not ``.'' or ``..''
+   */
+  if ((len = m_strlen(filepart)) == 0) {
+    while ((de = readdir (dirp)) != NULL) {
+      if (m_strcmp(".", de->d_name) != 0
+          && m_strcmp("..", de->d_name) != 0) {
+        m_strcpy(filepart, sizeof(filepart), de->d_name);
+        init++;
+        break;
+      }
+    }
+  }
+
+  while ((de = readdir (dirp)) != NULL) {
+    if (m_strncmp(de->d_name, filepart, len) == 0) {
+      if (init) {
+        for (i = 0; filepart[i] && de->d_name[i]; i++) {
+          if (filepart[i] != de->d_name[i]) {
+            filepart[i] = 0;
+            break;
+          }
+        }
+        filepart[i] = 0;
+      }
+      else {
+        char buf[_POSIX_PATH_MAX];
+        struct stat st;
+
+        m_strcpy(filepart, sizeof(filepart), de->d_name);
+
+        /* check to see if it is a directory */
+        if (dirpart[0]) {
+          m_strcpy(buf, sizeof(buf), exp_dirpart);
+          m_strcpy(buf + m_strlen(buf), sizeof(buf) - m_strlen(buf), "/");
+        }
+        else
+          buf[0] = 0;
+        m_strcpy(buf + m_strlen(buf), sizeof(buf) - m_strlen(buf), filepart);
+        if (stat (buf, &st) != -1 && (st.st_mode & S_IFDIR))
+          m_strcpy(filepart + m_strlen(filepart),
+                   sizeof(filepart) - m_strlen(filepart), "/");
+        init = 1;
+      }
+    }
+  }
+  closedir (dirp);
+
+  if (dirpart[0]) {
+    m_strcpy(s, slen, dirpart);
+    if (m_strcmp("/", dirpart) != 0 && dirpart[0] != '='
+        && dirpart[0] != '+')
+      m_strcpy(s + m_strlen(s), slen - m_strlen(s), "/");
+    m_strcpy(s + m_strlen(s), slen - m_strlen(s), filepart);
+  }
+  else
+    m_strcpy(s, slen, filepart);
+
+  return (init ? 0 : -1);
+}