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.
24 #include "lib/debug.h"
28 #include <sys/types.h>
32 /* given a partial pathname, this routine fills in as much of the rest of the
35 * return 0 if ok, -1 if no matches
37 int mutt_complete (char *s, size_t slen)
44 char dirpart[_POSIX_PATH_MAX], exp_dirpart[_POSIX_PATH_MAX];
45 char filepart[_POSIX_PATH_MAX];
48 char imap_path[LONG_STRING];
51 debug_print (2, ("completing %s\n", s));
54 if (option (OPTNEWS)) {
55 LIST *l = CurrentNewsSrv->list;
57 strfcpy (filepart, s, sizeof (filepart));
60 * special case to handle when there is no filepart yet.
61 * find the first subscribed newsgroup
63 if ((len = str_len (filepart)) == 0) {
64 for (; l; l = l->next) {
65 NNTP_DATA *data = (NNTP_DATA *) l->data;
67 if (data && data->subscribed) {
68 strfcpy (filepart, data->group, sizeof (filepart));
76 for (; l; l = l->next) {
77 NNTP_DATA *data = (NNTP_DATA *) l->data;
79 if (data && data->subscribed &&
80 str_ncmp (data->group, filepart, len) == 0) {
82 for (i = 0; filepart[i] && data->group[i]; i++) {
83 if (filepart[i] != data->group[i]) {
91 strfcpy (filepart, data->group, sizeof (filepart));
99 return (init ? 0 : -1);
104 /* we can use '/' as a delimiter, imap_complete rewrites it */
105 if (*s == '=' || *s == '+' || *s == '!') {
107 p = NONULL (Spoolfile);
109 p = NONULL (Maildir);
111 mutt_concat_path (imap_path, p, s + 1, sizeof (imap_path));
114 strfcpy (imap_path, s, sizeof (imap_path));
116 if (mx_get_magic (imap_path) == M_IMAP)
117 return imap_complete (s, slen, imap_path);
120 if (*s == '=' || *s == '+' || *s == '!') {
124 strfcpy (exp_dirpart, NONULL (Spoolfile), sizeof (exp_dirpart));
126 strfcpy (exp_dirpart, NONULL (Maildir), sizeof (exp_dirpart));
127 if ((p = strrchr (s, '/'))) {
128 char buf[_POSIX_PATH_MAX];
131 mutt_concat_path (buf, exp_dirpart, s + 1, sizeof (buf));
132 strfcpy (exp_dirpart, buf, sizeof (exp_dirpart));
133 snprintf (buf, sizeof (buf), "%s%s/", dirpart, s + 1);
134 strfcpy (dirpart, buf, sizeof (dirpart));
135 strfcpy (filepart, p, sizeof (filepart));
138 strfcpy (filepart, s + 1, sizeof (filepart));
139 dirp = opendir (exp_dirpart);
142 if ((p = strrchr (s, '/'))) {
143 if (p == s) { /* absolute path */
145 strfcpy (dirpart, "/", sizeof (dirpart));
147 strfcpy (filepart, p, sizeof (filepart));
148 dirp = opendir (dirpart);
152 len = (size_t) (p - s);
153 strncpy (dirpart, s, len);
156 strfcpy (filepart, p, sizeof (filepart));
157 strfcpy (exp_dirpart, dirpart, sizeof (exp_dirpart));
158 mutt_expand_path (exp_dirpart, sizeof (exp_dirpart));
159 dirp = opendir (exp_dirpart);
163 /* no directory name, so assume current directory. */
165 strfcpy (filepart, s, sizeof (filepart));
166 dirp = opendir (".");
171 debug_print (1, ("%s: %s (errno %d).\n", exp_dirpart, strerror (errno), errno));
176 * special case to handle when there is no filepart yet. find the first
177 * file/directory which is not ``.'' or ``..''
179 if ((len = str_len (filepart)) == 0) {
180 while ((de = readdir (dirp)) != NULL) {
181 if (str_cmp (".", de->d_name) != 0
182 && str_cmp ("..", de->d_name) != 0) {
183 strfcpy (filepart, de->d_name, sizeof (filepart));
190 while ((de = readdir (dirp)) != NULL) {
191 if (str_ncmp (de->d_name, filepart, len) == 0) {
193 for (i = 0; filepart[i] && de->d_name[i]; i++) {
194 if (filepart[i] != de->d_name[i]) {
202 char buf[_POSIX_PATH_MAX];
205 strfcpy (filepart, de->d_name, sizeof (filepart));
207 /* check to see if it is a directory */
209 strfcpy (buf, exp_dirpart, sizeof (buf));
210 strfcpy (buf + str_len (buf), "/", sizeof (buf) - str_len (buf));
214 strfcpy (buf + str_len (buf), filepart, sizeof (buf) - str_len (buf));
215 if (stat (buf, &st) != -1 && (st.st_mode & S_IFDIR))
216 strfcpy (filepart + str_len (filepart), "/",
217 sizeof (filepart) - str_len (filepart));
225 strfcpy (s, dirpart, slen);
226 if (str_cmp ("/", dirpart) != 0 && dirpart[0] != '='
227 && dirpart[0] != '+')
228 strfcpy (s + str_len (s), "/", slen - str_len (s));
229 strfcpy (s + str_len (s), filepart, slen - str_len (s));
232 strfcpy (s, filepart, slen);
234 return (init ? 0 : -1);