fixed tab completion with long file names
[reactos.git] / rosapps / cmd / filecomp.c
1 /*
2 * FILECOMP.C - handles filename completion.
3 *
4 *
5 * Comments:
6 *
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
11 *
12 * 25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
13 * Cleanup. Unicode safe!
14 */
15
16 #include "config.h"
17
18 #include <windows.h>
19 #include <tchar.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <stdio.h>
24
25 #include "cmd.h"
26
27
28 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
29
30 VOID CompleteFilename (LPTSTR str, INT charcount)
31 {
32 WIN32_FIND_DATA file;
33 HANDLE hFile;
34 INT curplace = 0;
35 INT start;
36 INT count;
37 BOOL found_dot = FALSE;
38 BOOL perfectmatch = TRUE;
39 TCHAR path[MAX_PATH];
40 TCHAR fname[MAX_PATH];
41 TCHAR maxmatch[MAX_PATH] = _T("");
42 TCHAR directory[MAX_PATH];
43 LPCOMMAND cmds_ptr;
44
45 /* expand current file name */
46 count = charcount - 1;
47 if (count < 0)
48 count = 0;
49
50 /* find front of word */
51 while (count > 0 && str[count] != _T(' '))
52 count--;
53
54 /* if not at beginning, go forward 1 */
55 if (str[count] == _T(' '))
56 count++;
57
58 start = count;
59
60 /* extract directory from word */
61 _tcscpy (directory, &str[start]);
62 curplace = _tcslen (directory) - 1;
63 while (curplace >= 0 && directory[curplace] != _T('\\') &&
64 directory[curplace] != _T(':'))
65 {
66 directory[curplace] = 0;
67 curplace--;
68 }
69
70 _tcscpy (path, &str[start]);
71
72 /* look for a '.' in the filename */
73 for (count = _tcslen (directory); path[count] != _T('\0'); count++)
74 {
75 if (path[count] == _T('.'))
76 {
77 found_dot = TRUE;
78 break;
79 }
80 }
81
82 if (found_dot)
83 _tcscat (path, _T("*"));
84 else
85 _tcscat (path, _T("*.*"));
86
87 /* current fname */
88 curplace = 0;
89
90 hFile = FindFirstFile (path, &file);
91 if (hFile != INVALID_HANDLE_VALUE)
92 {
93 /* find anything */
94 do
95 {
96 /* ignore "." and ".." */
97 if (!_tcscmp (file.cFileName, _T(".")) ||
98 !_tcscmp (file.cFileName, _T("..")))
99 continue;
100
101 _tcscpy (fname, file.cFileName);
102
103 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
104 _tcscat (fname, _T("\\"));
105 else
106 _tcscat (fname, _T(" "));
107
108 if (!maxmatch[0] && perfectmatch)
109 {
110 _tcscpy(maxmatch, fname);
111 }
112 else
113 {
114 for (count = 0; maxmatch[count] && fname[count]; count++)
115 {
116 if (tolower(maxmatch[count]) != tolower(fname[count]))
117 {
118 perfectmatch = FALSE;
119 maxmatch[count] = 0;
120 break;
121 }
122 }
123 }
124 }
125 while (FindNextFile (hFile, &file));
126
127 FindClose (hFile);
128 if( perfectmatch )
129 {
130 str[start] = '\"';
131 _tcscpy (&str[start+1], directory);
132 _tcscat (&str[start], maxmatch);
133 _tcscat (&str[start], "\"" );
134 }
135
136 else
137 #ifdef __REACTOS__
138 Beep (440, 50);
139 #else
140 MessageBeep (-1);
141 #endif
142 }
143 else
144 {
145 /* no match found - search for internal command */
146 for (cmds_ptr = cmds; cmds_ptr->name; cmds_ptr++)
147 {
148 if (!_tcsnicmp (&str[start], cmds_ptr->name,
149 _tcslen (&str[start])))
150 {
151 /* return the mach only if it is unique */
152 if (_tcsnicmp (&str[start], (cmds_ptr+1)->name, _tcslen (&str[start])))
153 _tcscpy (&str[start], cmds_ptr->name);
154 break;
155 }
156 }
157
158 #ifdef __REACTOS__
159 Beep (440, 50);
160 #else
161 MessageBeep (-1);
162 #endif
163 }
164 }
165
166
167 /*
168 * returns 1 if at least one match, else returns 0
169 */
170
171 BOOL ShowCompletionMatches (LPTSTR str, INT charcount)
172 {
173 WIN32_FIND_DATA file;
174 HANDLE hFile;
175 BOOL found_dot = FALSE;
176 INT curplace = 0;
177 INT start;
178 INT count;
179 TCHAR path[MAX_PATH];
180 TCHAR fname[MAX_PATH];
181 TCHAR directory[MAX_PATH];
182
183 /* expand current file name */
184 count = charcount - 1;
185 if (count < 0)
186 count = 0;
187
188 /* find front of word */
189 while (count > 0 && str[count] != _T(' '))
190 count--;
191
192 /* if not at beginning, go forward 1 */
193 if (str[count] == _T(' '))
194 count++;
195
196 start = count;
197
198 /* extract directory from word */
199 _tcscpy (directory, &str[start]);
200 curplace = _tcslen (directory) - 1;
201 while (curplace >= 0 &&
202 directory[curplace] != _T('\\') &&
203 directory[curplace] != _T(':'))
204 {
205 directory[curplace] = 0;
206 curplace--;
207 }
208
209 _tcscpy (path, &str[start]);
210
211 /* look for a . in the filename */
212 for (count = _tcslen (directory); path[count] != _T('\0'); count++)
213 {
214 if (path[count] == _T('.'))
215 {
216 found_dot = TRUE;
217 break;
218 }
219 }
220
221 if (found_dot)
222 _tcscat (path, _T("*"));
223 else
224 _tcscat (path, _T("*.*"));
225
226 /* current fname */
227 curplace = 0;
228
229 hFile = FindFirstFile (path, &file);
230 if (hFile != INVALID_HANDLE_VALUE)
231 {
232 /* find anything */
233 ConOutChar (_T('\n'));
234 count = 0;
235 do
236 {
237 /* ignore . and .. */
238 if (!_tcscmp (file.cFileName, _T(".")) ||
239 !_tcscmp (file.cFileName, _T("..")))
240 continue;
241
242 if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
243 _stprintf (fname, _T("[%s]"), file.cFileName);
244 else
245 _tcscpy (fname, file.cFileName);
246
247 ConOutPrintf (_T("%-14s"), fname);
248 if (++count == 5)
249 {
250 ConOutChar (_T('\n'));
251 count = 0;
252 }
253 }
254 while (FindNextFile (hFile, &file));
255
256 FindClose (hFile);
257
258 if (count)
259 ConOutChar (_T('\n'));
260 }
261 else
262 {
263 /* no match found */
264 #ifdef __REACTOS__
265 Beep (440, 50);
266 #else
267 MessageBeep (-1);
268 #endif
269 return FALSE;
270 }
271
272 return TRUE;
273 }
274 #endif
275
276 #ifdef FEATURE_4NT_FILENAME_COMPLETION
277
278 //static VOID BuildFilenameMatchList (...)
279
280 // VOID CompleteFilenameNext (LPTSTR, INT)
281 // VOID CompleteFilenamePrev (LPTSTR, INT)
282
283 // VOID RemoveFilenameMatchList (VOID)
284
285 #endif