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