Windows TAB complete style instead for unix style patch by Brandon
Turner. Thuse does people do not like windows tab complete, the can
always change in config.h to unix/linux tab complete code again.
Modified: trunk/reactos/subsys/system/cmd/cmd.h
Modified: trunk/reactos/subsys/system/cmd/cmdinput.c
Modified: trunk/reactos/subsys/system/cmd/config.h
Modified: trunk/reactos/subsys/system/cmd/filecomp.c
_____
Modified: trunk/reactos/subsys/system/cmd/cmd.h
--- trunk/reactos/subsys/system/cmd/cmd.h 2005-08-04 10:41:58 UTC
(rev 17042)
+++ trunk/reactos/subsys/system/cmd/cmd.h 2005-08-04 12:41:42 UTC
(rev 17043)
@@ -228,6 +228,7 @@
INT ShowCompletionMatches (LPTSTR, INT);
#endif
#ifdef FEATURE_4NT_FILENAME_COMPLETION
+VOID CompleteFilename (LPTSTR, BOOL, LPTSTR, INT);
#endif
_____
Modified: trunk/reactos/subsys/system/cmd/cmdinput.c
--- trunk/reactos/subsys/system/cmd/cmdinput.c 2005-08-04 10:41:58 UTC
(rev 17042)
+++ trunk/reactos/subsys/system/cmd/cmdinput.c 2005-08-04 12:41:42 UTC
(rev 17043)
@@ -98,6 +98,7 @@
*/
#include <precomp.h>
+#include "resource.h"
SHORT maxx;
@@ -314,10 +315,6 @@
charcount = _tcslen
(str);
current = charcount;
- if (current > 0 &&
- str[current-1] ==
_T('"'))
- current--;
-
SetCursorXY (orgx,
orgy);
ConOutPrintf (_T("%s"),
str);
@@ -366,17 +363,50 @@
}
#endif
#ifdef FEATURE_4NT_FILENAME_COMPLETION
- /* this is not implemented yet */
- if (ir.Event.KeyEvent.dwControlKeyState
& SHIFT_PRESSED)
+
+ /* used to later see if we went down to
the next line */
+ tempscreen = charcount;
+ TCHAR szPath[MAX_PATH];
+ szPath[0]=_T('\0');
+
+ /* str is the whole things that is on
the current line
+ that is and and out. arg 2 is
weather it goes back
+ one file or forward one file */
+ CompleteFilename(str,
!(ir.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED), szPath,
current);
+ /* Attempt to clear the line */
+ ClearCommandLine (str, maxlen, orgx,
orgy);
+ curx = orgx;
+ cury = orgy;
+ current = charcount = 0;
+ //str[0]=_T('\0');
+
+ /* Everything is deleted, lets add it
back in */
+ _tcscpy(str,szPath);
+
+ /* Figure out where cusor is going to be
after we print it */
+ charcount = _tcslen (str);
+ current = charcount;
+
+ SetCursorXY (orgx, orgy);
+ /* Print out what we have now */
+ ConOutPrintf (_T("%s"), str);
+
+ /* Move cursor accordingly */
+ if(tempscreen > charcount)
{
- /* get previous match */
-
+ GetCursorXY (&curx, &cury);
+ for(count = tempscreen -
charcount; count--; )
+ ConOutChar (_T(' '));
+ SetCursorXY (curx, cury);
}
else
{
- /* get next match */
+ if(((charcount + orgx) / maxx) +
orgy > maxy - 1)
+ orgy += maxy -
((charcount + orgx) / maxx + orgy + 1);
+ }
+ SetCursorXY((orgx + current) % maxx,
orgy + (orgx + current) / maxx);
+ GetCursorXY(&curx, &cury);
- }
#endif
break;
_____
Modified: trunk/reactos/subsys/system/cmd/config.h
--- trunk/reactos/subsys/system/cmd/config.h 2005-08-04 10:41:58 UTC
(rev 17042)
+++ trunk/reactos/subsys/system/cmd/config.h 2005-08-04 12:41:42 UTC
(rev 17043)
@@ -37,8 +37,8 @@
/* Define one of these to enable filename completion */
-#define FEATURE_UNIX_FILENAME_COMPLETION
-/* #define FEATURE_4NT_FILENAME_COMPLETION */
+//#define FEATURE_UNIX_FILENAME_COMPLETION
+#define FEATURE_4NT_FILENAME_COMPLETION
/* Define to enable the directory stack */
_____
Modified: trunk/reactos/subsys/system/cmd/filecomp.c
--- trunk/reactos/subsys/system/cmd/filecomp.c 2005-08-04 10:41:58 UTC
(rev 17042)
+++ trunk/reactos/subsys/system/cmd/filecomp.c 2005-08-04 12:41:42 UTC
(rev 17043)
@@ -21,8 +21,8 @@
*/
#include <precomp.h>
+#include "cmd.h"
-
#ifdef FEATURE_UNIX_FILENAME_COMPLETION
VOID CompleteFilename (LPTSTR str, INT charcount)
@@ -169,18 +169,8 @@
_tcscat (&str[start], maxmatch);
}
- /* append a space if last word is not a directory */
- if(perfectmatch)
+ if(!perfectmatch)
{
- curplace = _tcslen(&str[start]);
- if(str[start+curplace-1] == _T('"'))
- curplace--;
-
- if(str[start+curplace-1] != _T('\\'))
- _tcscat(&str[start], _T(" "));
- }
- else
- {
#ifdef __REACTOS__
Beep (440, 50);
#else
@@ -370,11 +360,377 @@
#ifdef FEATURE_4NT_FILENAME_COMPLETION
-//static VOID BuildFilenameMatchList (...)
+typedef struct _FileName
+{
+ TCHAR Name[MAX_PATH];
+} FileName;
-// VOID CompleteFilenameNext (LPTSTR, INT)
-// VOID CompleteFilenamePrev (LPTSTR, INT)
+VOID FindPrefixAndSuffix(LPTSTR strIN, LPTSTR szPrefix, LPTSTR
szSuffix)
+{
+ /* String that is to be examined */
+ TCHAR str[MAX_PATH];
+ /* temp pointers to used to find needed parts */
+ TCHAR * szSearch;
+ TCHAR * szSearch1;
+ TCHAR * szSearch2;
+ /* number of quotes in the string */
+ INT nQuotes = 0;
+ /* used in for loops */
+ INT i;
+ /* Char number to break the string at */
+ INT PBreak = 0;
+ INT SBreak = 0;
+ /* when phrasing a string, this tells weather
+ you are inside quotes ot not. */
+ BOOL bInside = FALSE;
+
+ szPrefix[0] = _T('\0');
+ szSuffix[0] = _T('\0');
-// VOID RemoveFilenameMatchList (VOID)
+ /* Copy over the string to later be edited */
+ _tcscpy(str,strIN);
+ /* Count number of " */
+ for(i = 0; i < _tcslen(str); i++)
+ if(str[i] == _T('\"'))
+ nQuotes++;
+
+ /* Find the prefix and suffix */
+ if(nQuotes % 2 && nQuotes)
+ {
+ /* Odd number of quotes. Just start from the last " */
+ /* THis is the way MS does it, and is an easy way out */
+ szSearch = _tcsrchr(str, _T('\"'));
+ /* Move to the next char past the " */
+ szSearch++;
+ _tcscpy(szSuffix,szSearch);
+ /* Find the one closest to end */
+ szSearch1 = _tcsrchr(str, _T('\"'));
+ szSearch2 = _tcsrchr(str, _T('\\'));
+ if(szSearch2 != NULL && _tcslen(szSearch1) >
_tcslen(szSearch2))
+ szSearch = szSearch2;
+ else
+ szSearch = szSearch1;
+ /* Move one char past */
+ szSearch++;
+ szSearch[0] = _T('\0');
+ _tcscpy(szPrefix,str);
+ return;
+
+ }
+
+ if(!_tcschr(str, _T(' ')))
+ {
+ /* No spaces, everything goes to Suffix */
+ _tcscpy(szSuffix,str);
+ /* look for a slash just in case */
+ szSearch = _tcsrchr(str, _T('\\'));
+ if(szSearch)
+ {
+ szSearch++;
+ szSearch[0] = _T('\0');
+ _tcscpy(szPrefix,str);
+ }
+ else
+ {
+ szPrefix[0] = _T('\0');
+ }
+ return;
+ }
+
+ if(!nQuotes)
+ {
+ /* No quotes, and there is a space*/
+ /* Take it after the last space */
+ szSearch = _tcsrchr(str, _T(' '));
+ szSearch++;
+ _tcscpy(szSuffix,szSearch);
+ /* Find the closest to the end space or \ */
+ _tcscpy(str,strIN);
+ szSearch1 = _tcsrchr(str, _T(' '));
+ szSearch2 = _tcsrchr(str, _T('\\'));
+ if(szSearch2 != NULL && _tcslen(szSearch1) >
_tcslen(szSearch2))
+ szSearch = szSearch2;
+ else
+ szSearch = szSearch1;
+ szSearch++;
+ szSearch[0] = _T('\0');
+ _tcscpy(szPrefix,str);
+ return;
+ }
+
+ /* All else fails and there is a lot of quotes, spaces and |
+ Then we search through and find the last space or \ that is
+ not inside a quotes */
+ for(i = 0; i < _tcslen(str); i++)
+ {
+ if(str[i] == _T('\"'))
+ bInside = !bInside;
+ if(str[i] == _T(' ') && !bInside)
+ SBreak = i;
+ if((!_tcsncmp(&str[i], _T(" "),1) || !_tcsncmp(&str[i],
_T("\\"),1)) && !bInside)
+ PBreak = i;
+
+ }
+ SBreak++;
+ PBreak++;
+ _tcscpy(szSuffix,&strIN[SBreak]);
+ strIN[PBreak] = _T('\0');
+ _tcscpy(szPrefix,strIN);
+ if(!_tcsncmp(&szPrefix[_tcslen(szPrefix) - 2],_T("\""),1))
+ {
+ /* need to remove the " right before a \ at the end to
+ allow the next stuff to stay inside one set of quotes
+ otherwise you would have multiple sets of
quotes*/
+ _tcscpy(&szPrefix[_tcslen(szPrefix) - 2],_T("\\"));
+
+ }
+
+}
+ int compare(const void *arg1,const void *arg2)
+ {
+ FileName * File1;
+ FileName * File2;
+ INT ret;
+
+ File1 = malloc(sizeof(FileName));
+ File2 = malloc(sizeof(FileName));
+ if(!File1 || !File2)
+ return 0;
+
+ memcpy(File1,arg1,sizeof(FileName));
+ memcpy(File2,arg2,sizeof(FileName));
+
+ ret = _tcsicmp(File1->Name, File2->Name);
+
+ free(File1);
+ free(File2);
+ return ret;
+ }
+
+VOID CompleteFilename (LPTSTR strIN, BOOL bNext, LPTSTR strOut, INT
cusor)
+{
+ /* Length of string before we complete it */
+ INT StartLength;
+ /* Length of string after completed */
+ INT EndLength;
+ /* The number of chars added too it */
+ static INT DiffLength = 0;
+ /* Used to find and assemble the string that is returned */
+ TCHAR szBaseWord[MAX_PATH];
+ TCHAR szPrefix[MAX_PATH];
+ TCHAR szOrginal[MAX_PATH];
+ TCHAR szSearchPath[MAX_PATH];
+ /* Save the strings used last time, so if they hit tab again */
+ static TCHAR LastReturned[MAX_PATH];
+ static TCHAR LastSearch[MAX_PATH];
+ static TCHAR LastPrefix[MAX_PATH];
+ /* Used to search for files */
+ HANDLE hFile;
+ WIN32_FIND_DATA file;
+ /* List of all the files */
+ FileName * FileList = NULL;
+ /* Number of files */
+ INT FileListSize = 0;
+ /* Used for loops */
+ INT i;
+ INT ii;
+ /* Editable string of what was passed in */
+ TCHAR str[MAX_PATH];
+ /* Keeps track of what element was last selected */
+ static INT Sel;
+ BOOL NeededQuote = FALSE;
+
+ strOut[0] = _T('\0');
+
+ /* Copy the string, str can be edited and orginal should not be
*/
+ _tcscpy(str,strIN);
+ _tcscpy(szOrginal,strIN);
+
+ /* Look to see if the cusor is not at the end of the string */
+ if((cusor + 1) < _tcslen(str))
+ str[cusor] = _T('\0');
+
+ /* Look to see if they hit tab again, if so cut off the diff
length */
+ if(_tcscmp(str,LastReturned))
+ {
+ /* We need to know how many chars we added from the start */
+ StartLength = _tcslen(str);
+
+ /* no string, we need all files in that directory */
+ if(!StartLength)
+ _tcscat(str,_T("*"));
+
+ /* Zero it out first */
+ szBaseWord[0] = _T('\0');
+ szPrefix[0] = _T('\0');
+
+ /*What comes out of this needs to be:
+ szBaseWord = path no quotes to the object
+ szPrefix = what leads up to the filename
+ no quote at the END of the full name */
+ FindPrefixAndSuffix(str,szPrefix,szBaseWord);
+ /* Strip quotes */
+ for(i = 0; i < _tcslen(szBaseWord); i++)
+ {
+ if(!_tcsncmp(&szBaseWord[i], _T("\""),1))
+ {
+ for(ii = i; ii < (_tcslen(szBaseWord)); ii++)
+ szBaseWord[ii] = szBaseWord[ii + 1];
+ }
+ }
+
+ /* clear it out */
+ memset(szSearchPath, 0, sizeof(szSearchPath));
+
+ /* Start the search for all the files */
+ GetFullPathName(szBaseWord, MAX_PATH, szSearchPath, NULL);
+ if(StartLength > 0)
+ _tcscat(szSearchPath,_T("*"));
+ _tcscpy(LastSearch,szSearchPath);
+ _tcscpy(LastPrefix,szPrefix);
+ }
+ else
+ {
+ _tcscpy(szSearchPath, LastSearch);
+ _tcscpy(szPrefix, LastPrefix);
+ }
+ /* search for the files it might be */
+ hFile = FindFirstFile (szSearchPath, &file);
+
+ /* aseemble a list of all files names */
+ do
+ {
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ /* Assemble the orginal string and return */
+ _tcscpy(strOut,szOrginal);
+ CloseHandle(hFile);
+ if(FileList != NULL)
+ free(FileList);
+ return;
+ }
+
+ if(!_tcscmp (file.cFileName, _T(".")) ||
+ !_tcscmp (file.cFileName, _T("..")))
+ continue;
+ /* Add the file to the list of files */
+ if(FileList == NULL)
+ {
+ FileListSize = 1;
+ FileList = malloc(FileListSize *
sizeof(FileName));
+ }
+ else
+ {
+ FileListSize++;
+ FileList = realloc(FileList, FileListSize *
sizeof(FileName));
+ }
+
+ if(FileList == NULL)
+ {
+ /* Assemble the orginal string and return */
+ _tcscpy(strOut,szOrginal);
+ CloseHandle(hFile);
+ ConOutFormatMessage (GetLastError());
+ return;
+ }
+ /* Copies the file name into the struct */
+ _tcscpy(FileList[FileListSize-1].Name,file.cFileName);
+
+ }while(FindNextFile(hFile,&file));
+
+
+ /* Sort the files */
+ qsort(FileList,FileListSize,sizeof(FileName), compare);
+
+ /* Find the next/previous */
+ if(!_tcscmp(szOrginal,LastReturned))
+ {
+ if(bNext)
+ {
+ if(FileListSize - 1 == Sel)
+ Sel = 0;
+ else
+ Sel++;
+ }
+ else
+ {
+ if(!Sel)
+ Sel = FileListSize - 1;
+ else
+ Sel--;
+ }
+ }
+ else
+ {
+ Sel = 0;
+ }
+
+ /* nothing found that matched last time
+ so return the first thing in the list */
+ strOut[0] = _T('\0');
+
+ /* space in the name */
+ if(_tcschr(FileList[Sel].Name, _T(' ')))
+ {
+ /* It needs a " at the end */
+ NeededQuote = TRUE;
+ INT LastSpace = -1;
+ BOOL bInside = FALSE;
+ /* Find the place to put the " at the start */
+ for(i = 0; i < _tcslen(szPrefix); i++)
+ {
+ if(szPrefix[i] == _T('\"'))
+ bInside = !bInside;
+ if(szPrefix[i] == _T(' ') && !bInside)
+ LastSpace = i;
+
+ }
+ /* insert the space and move things around */
+ if(_tcsncmp(&szPrefix[LastSpace + 1],_T("\""),1) &&
LastSpace != -1)
+ {
+ /* add another char or you will lose a null char
ending */
+ _tcsncat(szPrefix,&szPrefix[_tcslen(szPrefix) -
1],1);
+ for(i = _tcslen(szPrefix) - 1; i > LastSpace;
i--)
+ {
+ szPrefix[i] = szPrefix[i - 1];
+ }
+
+ if(LastSpace + 1 == _tcslen(szPrefix))
+ {
+ _tcscat(szPrefix,_T("\""));
+ }
+ szPrefix[LastSpace + 1] = _T('\"');
+ }
+ else if(LastSpace == -1)
+ {
+ _tcscpy(szBaseWord,_T("\""));
+ _tcscat(szBaseWord,szPrefix);
+ _tcscpy(szPrefix,szBaseWord);
+
+ }
+ }
+
+ _tcscpy(strOut,szPrefix);
+ _tcscat(strOut,FileList[Sel].Name);
+
+ /* check for odd number of quotes means we need to close them */
+ if(!NeededQuote)
+ {
+ for(i = 0; i < _tcslen(strOut); i++)
+ if(strOut[i] == _T('\"'))
+ NeededQuote = !NeededQuote;
+ }
+
+ if(szPrefix[_tcslen(szPrefix) - 1] == _T('\"') || NeededQuote)
+ _tcscat(strOut,_T("\""));
+
+ _tcscpy(LastReturned,strOut);
+ EndLength = _tcslen(strOut);
+ DiffLength = EndLength - StartLength;
+ CloseHandle(hFile);
+ if(FileList != NULL)
+ free(FileList);
+
+}
#endif