2 * FILECOMP.C - handles filename completion.
7 * 30-Jul-1998 (John P Price <linux-guru@gcfl.net>)
8 * moved from command.c file
9 * made second TAB display list of filename matches
10 * made filename be lower case if last character typed is lower case
12 * 25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
13 * Cleanup. Unicode safe!
15 * 30-Apr-2004 (Filip Navara <xnavara@volny.cz>)
16 * Make the file listing readable when there is a lot of long names.
19 * 05-Jul-2004 (Jens Collin <jens.collin@lakhei.com>)
20 * Now expands lfn even when trailing " is omitted.
26 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
28 VOID
CompleteFilename (LPTSTR str
, INT charcount
)
37 BOOL found_dot
= FALSE
;
38 BOOL perfectmatch
= TRUE
;
40 TCHAR fname
[MAX_PATH
];
41 TCHAR maxmatch
[MAX_PATH
] = _T("");
42 TCHAR directory
[MAX_PATH
];
45 /* expand current file name */
46 count
= charcount
- 1;
50 /* find how many '"'s there is typed already.*/
54 if (str
[step
] == _T('"'))
58 /* if c is odd, then user typed " before name, else not.*/
60 /* find front of word */
61 if (str
[count
] == _T('"') || (c
% 2))
64 while (count
> 0 && str
[count
] != _T('"'))
69 while (count
> 0 && str
[count
] != _T(' '))
73 /* if not at beginning, go forward 1 */
74 if (str
[count
] == _T(' '))
79 if (str
[count
] == _T('"'))
80 count
++; /* don't increment start */
82 /* extract directory from word */
83 _tcscpy (directory
, &str
[count
]);
84 curplace
= _tcslen (directory
) - 1;
86 if (curplace
>= 0 && directory
[curplace
] == _T('"'))
87 directory
[curplace
--] = _T('\0');
89 _tcscpy (path
, directory
);
91 while (curplace
>= 0 && directory
[curplace
] != _T('\\') &&
92 directory
[curplace
] != _T(':'))
94 directory
[curplace
] = 0;
98 /* look for a '.' in the filename */
99 for (count
= _tcslen (directory
); path
[count
] != _T('\0'); count
++)
101 if (path
[count
] == _T('.'))
109 _tcscat (path
, _T("*"));
111 _tcscat (path
, _T("*.*"));
116 hFile
= FindFirstFile (path
, &file
);
117 if (hFile
!= INVALID_HANDLE_VALUE
)
122 /* ignore "." and ".." */
123 if (!_tcscmp (file
.cFileName
, _T(".")) ||
124 !_tcscmp (file
.cFileName
, _T("..")))
127 _tcscpy (fname
, file
.cFileName
);
129 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
130 _tcscat (fname
, _T("\\"));
132 if (!maxmatch
[0] && perfectmatch
)
134 _tcscpy(maxmatch
, fname
);
138 for (count
= 0; maxmatch
[count
] && fname
[count
]; count
++)
140 if (tolower(maxmatch
[count
]) != tolower(fname
[count
]))
142 perfectmatch
= FALSE
;
148 if (maxmatch
[count
] == _T('\0') &&
149 fname
[count
] != _T('\0'))
150 perfectmatch
= FALSE
;
153 while (FindNextFile (hFile
, &file
));
157 /* only quote if the filename contains spaces */
158 if (_tcschr(directory
, _T(' ')) ||
159 _tcschr(maxmatch
, _T(' ')))
161 str
[start
] = _T('\"');
162 _tcscpy (&str
[start
+1], directory
);
163 _tcscat (&str
[start
], maxmatch
);
164 _tcscat (&str
[start
], _T("\"") );
168 _tcscpy (&str
[start
], directory
);
169 _tcscat (&str
[start
], maxmatch
);
172 /* append a space if last word is not a directory */
175 curplace
= _tcslen(&str
[start
]);
176 if(str
[start
+curplace
-1] == _T('"'))
179 if(str
[start
+curplace
-1] != _T('\\'))
180 _tcscat(&str
[start
], _T(" "));
193 /* no match found - search for internal command */
194 for (cmds_ptr
= cmds
; cmds_ptr
->name
; cmds_ptr
++)
196 if (!_tcsnicmp (&str
[start
], cmds_ptr
->name
,
197 _tcslen (&str
[start
])))
199 /* return the mach only if it is unique */
200 if (_tcsnicmp (&str
[start
], (cmds_ptr
+1)->name
, _tcslen (&str
[start
])))
201 _tcscpy (&str
[start
], cmds_ptr
->name
);
216 * returns 1 if at least one match, else returns 0
219 BOOL
ShowCompletionMatches (LPTSTR str
, INT charcount
)
221 WIN32_FIND_DATA file
;
223 BOOL found_dot
= FALSE
;
227 TCHAR path
[MAX_PATH
];
228 TCHAR fname
[MAX_PATH
];
229 TCHAR directory
[MAX_PATH
];
230 INT longestfname
= 0;
233 /* expand current file name */
234 count
= charcount
- 1;
238 /* find front of word */
239 if (str
[count
] == _T('"'))
242 while (count
> 0 && str
[count
] != _T('"'))
247 while (count
> 0 && str
[count
] != _T(' '))
251 /* if not at beginning, go forward 1 */
252 if (str
[count
] == _T(' '))
257 if (str
[count
] == _T('"'))
258 count
++; /* don't increment start */
260 /* extract directory from word */
261 _tcscpy (directory
, &str
[count
]);
262 curplace
= _tcslen (directory
) - 1;
264 if (curplace
>= 0 && directory
[curplace
] == _T('"'))
265 directory
[curplace
--] = _T('\0');
267 _tcscpy (path
, directory
);
269 while (curplace
>= 0 &&
270 directory
[curplace
] != _T('\\') &&
271 directory
[curplace
] != _T(':'))
273 directory
[curplace
] = 0;
277 /* look for a . in the filename */
278 for (count
= _tcslen (directory
); path
[count
] != _T('\0'); count
++)
280 if (path
[count
] == _T('.'))
288 _tcscat (path
, _T("*"));
290 _tcscat (path
, _T("*.*"));
295 hFile
= FindFirstFile (path
, &file
);
296 if (hFile
!= INVALID_HANDLE_VALUE
)
298 /* Get the size of longest filename first. */
301 if (_tcslen(file
.cFileName
) > longestfname
)
303 longestfname
= _tcslen(file
.cFileName
);
304 /* Directories get extra brackets around them. */
305 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
309 while (FindNextFile (hFile
, &file
));
312 hFile
= FindFirstFile (path
, &file
);
314 /* Count the highest number of columns */
315 GetScreenSize(&screenwidth
, 0);
317 /* For counting columns of output */
320 /* Increase by the number of spaces behind file name */
324 ConOutChar (_T('\n'));
327 /* ignore . and .. */
328 if (!_tcscmp (file
.cFileName
, _T(".")) ||
329 !_tcscmp (file
.cFileName
, _T("..")))
332 if (file
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
333 _stprintf (fname
, _T("[%s]"), file
.cFileName
);
335 _tcscpy (fname
, file
.cFileName
);
337 ConOutPrintf (_T("%*s"), - longestfname
, fname
);
339 /* output as much columns as fits on the screen */
340 if (count
>= (screenwidth
/ longestfname
))
342 /* print the new line only if we aren't on the
343 * last column, in this case it wraps anyway */
344 if (count
* longestfname
!= screenwidth
)
345 ConOutPrintf (_T("\n"));
349 while (FindNextFile (hFile
, &file
));
354 ConOutChar (_T('\n'));
371 #ifdef FEATURE_4NT_FILENAME_COMPLETION
373 //static VOID BuildFilenameMatchList (...)
375 // VOID CompleteFilenameNext (LPTSTR, INT)
376 // VOID CompleteFilenamePrev (LPTSTR, INT)
378 // VOID RemoveFilenameMatchList (VOID)