update for HEAD-2003050101
[reactos.git] / subsys / system / 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         if (str[count] == _T('"'))
52         {
53                 count--;
54                 while (count > 0 && str[count] != _T('"'))
55                         count--;
56         }
57         else
58         {
59                 while (count > 0 && str[count] != _T(' '))
60                         count--;
61         }
62
63         /* if not at beginning, go forward 1 */
64         if (str[count] == _T(' '))
65                 count++;
66
67         start = count;
68
69         if (str[count] == _T('"'))
70                 count++;        /* don't increment start */
71
72         /* extract directory from word */
73         _tcscpy (directory, &str[count]);
74         curplace = _tcslen (directory) - 1;
75
76         if (curplace >= 0 && directory[curplace] == _T('"'))
77                 directory[curplace--] = _T('\0');
78
79         _tcscpy (path, directory);
80
81         while (curplace >= 0 && directory[curplace] != _T('\\') &&
82                    directory[curplace] != _T(':'))
83         {
84                 directory[curplace] = 0;
85                 curplace--;
86         }
87
88         /* look for a '.' in the filename */
89         for (count = _tcslen (directory); path[count] != _T('\0'); count++)
90         {
91                 if (path[count] == _T('.'))
92                 {
93                         found_dot = TRUE;
94                         break;
95                 }
96         }
97
98         if (found_dot)
99                 _tcscat (path, _T("*"));
100         else
101                 _tcscat (path, _T("*.*"));
102
103         /* current fname */
104         curplace = 0;
105
106         hFile = FindFirstFile (path, &file);
107         if (hFile != INVALID_HANDLE_VALUE)
108         {
109                 /* find anything */
110                 do
111                 {
112                         /* ignore "." and ".." */
113                         if (!_tcscmp (file.cFileName, _T(".")) ||
114                                 !_tcscmp (file.cFileName, _T("..")))
115                                 continue;
116
117                         _tcscpy (fname, file.cFileName);
118
119                         if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
120                                 _tcscat (fname, _T("\\"));
121
122                         if (!maxmatch[0] && perfectmatch)
123                         {
124                                 _tcscpy(maxmatch, fname);
125                         }
126                         else
127                         {
128                                 for (count = 0; maxmatch[count] && fname[count]; count++)
129                                 {
130                                         if (tolower(maxmatch[count]) != tolower(fname[count]))
131                                         {
132                                                 perfectmatch = FALSE;
133                                                 maxmatch[count] = 0;
134                                                 break;
135                                         }
136                                 }
137
138                                 if (maxmatch[count] == _T('\0') &&
139                                     fname[count] != _T('\0'))
140                                         perfectmatch = FALSE;
141                         }
142                 }
143                 while (FindNextFile (hFile, &file));
144
145                 FindClose (hFile);
146
147                 /* only quote if the filename contains spaces */
148                 if (_tcschr(directory, _T(' ')) ||
149                     _tcschr(maxmatch, _T(' ')))
150                 {
151                         str[start] = _T('\"');
152                         _tcscpy (&str[start+1], directory);
153                         _tcscat (&str[start], maxmatch);
154                         _tcscat (&str[start], _T("\"") );
155                 }
156                 else
157                 {
158                         _tcscpy (&str[start], directory);
159                         _tcscat (&str[start], maxmatch);
160                 }
161
162                 /* append a space if last word is not a directory */
163                 if(perfectmatch)
164                 {
165                         curplace = _tcslen(&str[start]);
166                         if(str[start+curplace-1] == _T('"'))
167                                 curplace--;
168
169                         if(str[start+curplace-1] != _T('\\'))
170                                 _tcscat(&str[start], _T(" "));
171                 }
172                 else
173                 {
174 #ifdef __REACTOS__
175                         Beep (440, 50);
176 #else
177                         MessageBeep (-1);
178 #endif
179                 }
180         }
181         else
182         {
183                 /* no match found - search for internal command */
184                 for (cmds_ptr = cmds; cmds_ptr->name; cmds_ptr++)
185                 {
186                         if (!_tcsnicmp (&str[start], cmds_ptr->name,
187                                 _tcslen (&str[start])))
188                         {
189                                 /* return the mach only if it is unique */
190                                 if (_tcsnicmp (&str[start], (cmds_ptr+1)->name, _tcslen (&str[start])))
191                                         _tcscpy (&str[start], cmds_ptr->name);
192                                 break;
193                         }
194                 }
195
196 #ifdef __REACTOS__
197                 Beep (440, 50);
198 #else
199                 MessageBeep (-1);
200 #endif
201         }
202 }
203
204
205 /*
206  * returns 1 if at least one match, else returns 0
207  */
208
209 BOOL ShowCompletionMatches (LPTSTR str, INT charcount)
210 {
211         WIN32_FIND_DATA file;
212         HANDLE hFile;
213         BOOL  found_dot = FALSE;
214         INT   curplace = 0;
215         INT   start;
216         INT   count;
217         TCHAR path[MAX_PATH];
218         TCHAR fname[MAX_PATH];
219         TCHAR directory[MAX_PATH];
220
221         /* expand current file name */
222         count = charcount - 1;
223         if (count < 0)
224                 count = 0;
225
226         /* find front of word */
227         if (str[count] == _T('"'))
228         {
229                 count--;
230                 while (count > 0 && str[count] != _T('"'))
231                         count--;
232         }
233         else
234         {
235                 while (count > 0 && str[count] != _T(' '))
236                         count--;
237         }
238
239         /* if not at beginning, go forward 1 */
240         if (str[count] == _T(' '))
241                 count++;
242
243         start = count;
244
245         if (str[count] == _T('"'))
246                 count++;        /* don't increment start */
247
248         /* extract directory from word */
249         _tcscpy (directory, &str[count]);
250         curplace = _tcslen (directory) - 1;
251
252         if (curplace >= 0 && directory[curplace] == _T('"'))
253                 directory[curplace--] = _T('\0');
254         
255         _tcscpy (path, directory);
256         
257         while (curplace >= 0 &&
258                    directory[curplace] != _T('\\') &&
259                    directory[curplace] != _T(':'))
260         {
261                 directory[curplace] = 0;
262                 curplace--;
263         }
264
265         /* look for a . in the filename */
266         for (count = _tcslen (directory); path[count] != _T('\0'); count++)
267         {
268                 if (path[count] == _T('.'))
269                 {
270                         found_dot = TRUE;
271                         break;
272                 }
273         }
274
275         if (found_dot)
276                 _tcscat (path, _T("*"));
277         else
278                 _tcscat (path, _T("*.*"));
279
280         /* current fname */
281         curplace = 0;
282
283         hFile = FindFirstFile (path, &file);
284         if (hFile != INVALID_HANDLE_VALUE)
285         {
286                 /* find anything */
287                 ConOutChar (_T('\n'));
288                 count = 0;
289                 do
290                 {
291                         /* ignore . and .. */
292                         if (!_tcscmp (file.cFileName, _T(".")) || 
293                                 !_tcscmp (file.cFileName, _T("..")))
294                                 continue;
295
296                         if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
297                                 _stprintf (fname, _T("[%s]"), file.cFileName);
298                         else
299                                 _tcscpy (fname, file.cFileName);
300
301                         ConOutPrintf (_T("%-14s"), fname);
302                         if (++count == 5)
303                         {
304                                 ConOutChar (_T('\n'));
305                                 count = 0;
306                         }
307                 }
308                 while (FindNextFile (hFile, &file));
309
310                 FindClose (hFile);
311
312                 if (count)
313                         ConOutChar (_T('\n'));
314         }
315         else
316         {
317                 /* no match found */
318 #ifdef __REACTOS__
319                 Beep (440, 50);
320 #else
321                 MessageBeep (-1);
322 #endif
323                 return FALSE;
324         }
325
326         return TRUE;
327 }
328 #endif
329
330 #ifdef FEATURE_4NT_FILENAME_COMPLETION
331
332 //static VOID BuildFilenameMatchList (...)
333
334 // VOID CompleteFilenameNext (LPTSTR, INT)
335 // VOID CompleteFilenamePrev (LPTSTR, INT)
336
337 // VOID RemoveFilenameMatchList (VOID)
338
339 #endif