2 * Copyright notice from original mutt:
3 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
5 * This file is part of mutt-ng, see http://www.muttng.org/.
6 * It's licensed under the GNU General Public License,
7 * please see the file GPL in the top level source directory.
27 #include <sys/types.h>
31 /* given a partial pathname, this routine fills in as much of the rest of the
34 * return 0 if ok, -1 if no matches
36 int mutt_complete (char *s, size_t slen)
43 char dirpart[_POSIX_PATH_MAX], exp_dirpart[_POSIX_PATH_MAX];
44 char filepart[_POSIX_PATH_MAX];
47 char imap_path[LONG_STRING];
50 dprint (2, (debugfile, "mutt_complete: completing %s\n", s));
53 if (option (OPTNEWS)) {
54 LIST *l = CurrentNewsSrv->list;
56 strfcpy (filepart, s, sizeof (filepart));
59 * special case to handle when there is no filepart yet.
60 * find the first subscribed newsgroup
62 if ((len = safe_strlen (filepart)) == 0) {
63 for (; l; l = l->next) {
64 NNTP_DATA *data = (NNTP_DATA *) l->data;
66 if (data && data->subscribed) {
67 strfcpy (filepart, data->group, sizeof (filepart));
75 for (; l; l = l->next) {
76 NNTP_DATA *data = (NNTP_DATA *) l->data;
78 if (data && data->subscribed &&
79 safe_strncmp (data->group, filepart, len) == 0) {
81 for (i = 0; filepart[i] && data->group[i]; i++) {
82 if (filepart[i] != data->group[i]) {
90 strfcpy (filepart, data->group, sizeof (filepart));
98 return (init ? 0 : -1);
103 /* we can use '/' as a delimiter, imap_complete rewrites it */
104 if (*s == '=' || *s == '+' || *s == '!') {
106 p = NONULL (Spoolfile);
108 p = NONULL (Maildir);
110 mutt_concat_path (imap_path, p, s + 1, sizeof (imap_path));
113 strfcpy (imap_path, s, sizeof (imap_path));
115 if (mx_get_magic (imap_path) == M_IMAP)
116 return imap_complete (s, slen, imap_path);
119 if (*s == '=' || *s == '+' || *s == '!') {
123 strfcpy (exp_dirpart, NONULL (Spoolfile), sizeof (exp_dirpart));
125 strfcpy (exp_dirpart, NONULL (Maildir), sizeof (exp_dirpart));
126 if ((p = strrchr (s, '/'))) {
127 char buf[_POSIX_PATH_MAX];
130 mutt_concat_path (buf, exp_dirpart, s + 1, sizeof (buf));
131 strfcpy (exp_dirpart, buf, sizeof (exp_dirpart));
132 snprintf (buf, sizeof (buf), "%s%s/", dirpart, s + 1);
133 strfcpy (dirpart, buf, sizeof (dirpart));
134 strfcpy (filepart, p, sizeof (filepart));
137 strfcpy (filepart, s + 1, sizeof (filepart));
138 dirp = opendir (exp_dirpart);
141 if ((p = strrchr (s, '/'))) {
142 if (p == s) { /* absolute path */
144 strfcpy (dirpart, "/", sizeof (dirpart));
146 strfcpy (filepart, p, sizeof (filepart));
147 dirp = opendir (dirpart);
151 len = (size_t) (p - s);
152 strncpy (dirpart, s, len);
155 strfcpy (filepart, p, sizeof (filepart));
156 strfcpy (exp_dirpart, dirpart, sizeof (exp_dirpart));
157 mutt_expand_path (exp_dirpart, sizeof (exp_dirpart));
158 dirp = opendir (exp_dirpart);
162 /* no directory name, so assume current directory. */
164 strfcpy (filepart, s, sizeof (filepart));
165 dirp = opendir (".");
171 (debugfile, "mutt_complete(): %s: %s (errno %d).\n", exp_dirpart,
172 strerror (errno), errno));
177 * special case to handle when there is no filepart yet. find the first
178 * file/directory which is not ``.'' or ``..''
180 if ((len = safe_strlen (filepart)) == 0) {
181 while ((de = readdir (dirp)) != NULL) {
182 if (safe_strcmp (".", de->d_name) != 0
183 && safe_strcmp ("..", de->d_name) != 0) {
184 strfcpy (filepart, de->d_name, sizeof (filepart));
191 while ((de = readdir (dirp)) != NULL) {
192 if (safe_strncmp (de->d_name, filepart, len) == 0) {
194 for (i = 0; filepart[i] && de->d_name[i]; i++) {
195 if (filepart[i] != de->d_name[i]) {
203 char buf[_POSIX_PATH_MAX];
206 strfcpy (filepart, de->d_name, sizeof (filepart));
208 /* check to see if it is a directory */
210 strfcpy (buf, exp_dirpart, sizeof (buf));
211 strfcpy (buf + safe_strlen (buf), "/", sizeof (buf) - safe_strlen (buf));
215 strfcpy (buf + safe_strlen (buf), filepart, sizeof (buf) - safe_strlen (buf));
216 if (stat (buf, &st) != -1 && (st.st_mode & S_IFDIR))
217 strfcpy (filepart + safe_strlen (filepart), "/",
218 sizeof (filepart) - safe_strlen (filepart));
226 strfcpy (s, dirpart, slen);
227 if (safe_strcmp ("/", dirpart) != 0 && dirpart[0] != '='
228 && dirpart[0] != '+')
229 strfcpy (s + safe_strlen (s), "/", slen - safe_strlen (s));
230 strfcpy (s + safe_strlen (s), filepart, slen - safe_strlen (s));
233 strfcpy (s, filepart, slen);
235 return (init ? 0 : -1);