2 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
34 #include <sys/types.h>
38 /* given a partial pathname, this routine fills in as much of the rest of the
41 * return 0 if ok, -1 if no matches
43 int mutt_complete (char *s, size_t slen)
50 char dirpart[_POSIX_PATH_MAX], exp_dirpart[_POSIX_PATH_MAX];
51 char filepart[_POSIX_PATH_MAX];
54 char imap_path[LONG_STRING];
57 dprint (2, (debugfile, "mutt_complete: completing %s\n", s));
60 if (option (OPTNEWS)) {
61 LIST *l = CurrentNewsSrv->list;
63 strfcpy (filepart, s, sizeof (filepart));
66 * special case to handle when there is no filepart yet.
67 * find the first subscribed newsgroup
69 if ((len = mutt_strlen (filepart)) == 0) {
70 for (; l; l = l->next) {
71 NNTP_DATA *data = (NNTP_DATA *) l->data;
73 if (data && data->subscribed) {
74 strfcpy (filepart, data->group, sizeof (filepart));
82 for (; l; l = l->next) {
83 NNTP_DATA *data = (NNTP_DATA *) l->data;
85 if (data && data->subscribed &&
86 mutt_strncmp (data->group, filepart, len) == 0) {
88 for (i = 0; filepart[i] && data->group[i]; i++) {
89 if (filepart[i] != data->group[i]) {
97 strfcpy (filepart, data->group, sizeof (filepart));
103 strcpy (s, filepart);
105 return (init ? 0 : -1);
110 /* we can use '/' as a delimiter, imap_complete rewrites it */
111 if (*s == '=' || *s == '+' || *s == '!') {
113 p = NONULL (Spoolfile);
115 p = NONULL (Maildir);
117 mutt_concat_path (imap_path, p, s + 1, sizeof (imap_path));
120 strfcpy (imap_path, s, sizeof (imap_path));
122 if (mx_is_imap (imap_path))
123 return imap_complete (s, slen, imap_path);
126 if (*s == '=' || *s == '+' || *s == '!') {
130 strfcpy (exp_dirpart, NONULL (Spoolfile), sizeof (exp_dirpart));
132 strfcpy (exp_dirpart, NONULL (Maildir), sizeof (exp_dirpart));
133 if ((p = strrchr (s, '/'))) {
134 char buf[_POSIX_PATH_MAX];
137 mutt_concat_path (buf, exp_dirpart, s + 1, sizeof (buf));
138 strfcpy (exp_dirpart, buf, sizeof (exp_dirpart));
139 snprintf (buf, sizeof (buf), "%s%s/", dirpart, s + 1);
140 strfcpy (dirpart, buf, sizeof (dirpart));
141 strfcpy (filepart, p, sizeof (filepart));
144 strfcpy (filepart, s + 1, sizeof (filepart));
145 dirp = opendir (exp_dirpart);
148 if ((p = strrchr (s, '/'))) {
149 if (p == s) { /* absolute path */
151 strfcpy (dirpart, "/", sizeof (dirpart));
153 strfcpy (filepart, p, sizeof (filepart));
154 dirp = opendir (dirpart);
158 len = (size_t) (p - s);
159 strncpy (dirpart, s, len);
162 strfcpy (filepart, p, sizeof (filepart));
163 strfcpy (exp_dirpart, dirpart, sizeof (exp_dirpart));
164 mutt_expand_path (exp_dirpart, sizeof (exp_dirpart));
165 dirp = opendir (exp_dirpart);
169 /* no directory name, so assume current directory. */
171 strfcpy (filepart, s, sizeof (filepart));
172 dirp = opendir (".");
178 (debugfile, "mutt_complete(): %s: %s (errno %d).\n", exp_dirpart,
179 strerror (errno), errno));
184 * special case to handle when there is no filepart yet. find the first
185 * file/directory which is not ``.'' or ``..''
187 if ((len = mutt_strlen (filepart)) == 0) {
188 while ((de = readdir (dirp)) != NULL) {
189 if (mutt_strcmp (".", de->d_name) != 0
190 && mutt_strcmp ("..", de->d_name) != 0) {
191 strfcpy (filepart, de->d_name, sizeof (filepart));
198 while ((de = readdir (dirp)) != NULL) {
199 if (mutt_strncmp (de->d_name, filepart, len) == 0) {
201 for (i = 0; filepart[i] && de->d_name[i]; i++) {
202 if (filepart[i] != de->d_name[i]) {
210 char buf[_POSIX_PATH_MAX];
213 strfcpy (filepart, de->d_name, sizeof (filepart));
215 /* check to see if it is a directory */
217 strfcpy (buf, exp_dirpart, sizeof (buf));
218 strfcpy (buf + strlen (buf), "/", sizeof (buf) - strlen (buf));
222 strfcpy (buf + strlen (buf), filepart, sizeof (buf) - strlen (buf));
223 if (stat (buf, &st) != -1 && (st.st_mode & S_IFDIR))
224 strfcpy (filepart + strlen (filepart), "/",
225 sizeof (filepart) - strlen (filepart));
233 strfcpy (s, dirpart, slen);
234 if (mutt_strcmp ("/", dirpart) != 0 && dirpart[0] != '='
235 && dirpart[0] != '+')
236 strfcpy (s + strlen (s), "/", slen - strlen (s));
237 strfcpy (s + strlen (s), filepart, slen - strlen (s));
240 strfcpy (s, filepart, slen);
242 return (init ? 0 : -1);