You would think that two commits are enough for fixing formulations in
the document, but I can easily prove you wrong...
Modified: branches/win32k rewrite attempt/win32k/docs/refs.txt
_____
Modified: branches/win32k rewrite attempt/win32k/docs/refs.txt
--- branches/win32k rewrite attempt/win32k/docs/refs.txt
2005-08-04 18:01:47 UTC (rev 17046)
+++ branches/win32k rewrite attempt/win32k/docs/refs.txt
2005-08-04 18:11:03 UTC (rev 17047)
@@ -18,7 +18,7 @@
So if you want the queue to hang around, you reference the
thread instead.
^ This is wrong, one can attach message queue to different thread using
-AttachThreadInput. The number of thread sharing a queue is stored in
the
+AttachThreadInput. The number of threads sharing a queue is stored in
the
message queue structure and can be considered a reference count. Also
on
Windows systems there is maintained a global list of thread
attachments.
@@ -36,12 +36,13 @@
NtUser/NtGdi/win32k syscalls
----------------------------
-A process and/or thread automatically gets converted to a GUI thread
when
-the first syscall from the shadow service table is called (ie. any
NtUser*
-or NtGdi* call). GUI threads have bigger kernel stack (FIXME: not the
case
-on ReactOS yet) and have associated storage for the Win32 structures.
The
-conversion itself happens in the syscall handler and the win32k
callbacks
-(registered with PsEstablishWin32Callouts) are called accordingly.
+A process and/or thread automatically gets converted to a GUI thread /
+process when the first syscall from the shadow service table is called
(ie.
+any NtUser* or NtGdi* call). GUI threads have bigger kernel stack
(FIXME:
+not the case on ReactOS yet) and have associated storage for the Win32
+structures. The conversion itself happens in the syscall handler and
the
+win32k callbacks (registered with PsEstablishWin32Callouts) are called
+accordingly.
A process automatically establishes a connection to a window station on
the
GUI thread conversion. The Win32 process initialization callback
routine
Fix grammar...
Modified: branches/win32k rewrite attempt/win32k/docs/refs.txt
_____
Modified: branches/win32k rewrite attempt/win32k/docs/refs.txt
--- branches/win32k rewrite attempt/win32k/docs/refs.txt
2005-08-04 17:49:53 UTC (rev 17045)
+++ branches/win32k rewrite attempt/win32k/docs/refs.txt
2005-08-04 18:01:47 UTC (rev 17046)
@@ -20,7 +20,7 @@
^ This is wrong, one can attach message queue to different thread using
AttachThreadInput. The number of thread sharing a queue is stored in
the
message queue structure and can be considered a reference count. Also
on
-Windows systems the a global list of thread attachments is maintained.
+Windows systems there is maintained a global list of thread
attachments.
Above references create following dependencies:
-----------------------------------------------
Update comments.
Modified: branches/win32k rewrite attempt/win32k/docs/refs.txt
_____
Modified: branches/win32k rewrite attempt/win32k/docs/refs.txt
--- branches/win32k rewrite attempt/win32k/docs/refs.txt
2005-08-04 16:32:18 UTC (rev 17044)
+++ branches/win32k rewrite attempt/win32k/docs/refs.txt
2005-08-04 17:49:53 UTC (rev 17045)
@@ -17,6 +17,11 @@
-If the (w32)thread exist, so does the message queue.
So if you want the queue to hang around, you reference the
thread instead.
+^ This is wrong, one can attach message queue to different thread using
+AttachThreadInput. The number of thread sharing a queue is stored in
the
+message queue structure and can be considered a reference count. Also
on
+Windows systems the a global list of thread attachments is maintained.
+
Above references create following dependencies:
-----------------------------------------------
@@ -28,33 +33,46 @@
process -> winsta -> session
-
-
NtUser/NtGdi/win32k syscalls
----------------------------
-A process automatically establishes a connection to a window station
and desktop
-when it first calls a USER32 or GDI32 function (other than the window
station or
-desktop functions). The process also get a Win32Proccess.
+A process and/or thread automatically gets converted to a GUI thread
when
+the first syscall from the shadow service table is called (ie. any
NtUser*
+or NtGdi* call). GUI threads have bigger kernel stack (FIXME: not the
case
+on ReactOS yet) and have associated storage for the Win32 structures.
The
+conversion itself happens in the syscall handler and the win32k
callbacks
+(registered with PsEstablishWin32Callouts) are called accordingly.
-A thread is automatically assigned a desktop when it first calls a
USER32 or GDI32
-function (other than the window station or desktop functions). The
thread also get
-a Win32Thread, a message queue and a thread input.
+A process automatically establishes a connection to a window station on
the
+GUI thread conversion. The Win32 process initialization callback
routine
+also creates and initializes the W32PROCESS structure and associates it
with
+the process.
-This means that when you are in a win32k syscall function (other than
the window station
-or desktop functions) you can be 100% sure that the following exists:
--the process WinSta
--the win32process
--the win32thread
--the thread message queue
--the thread input
--the thread desktop
--the process desktop (if there is such a thing)
+Similary for thread the callback routine automatically assigns a
desktop
+when the thread is converted to GUI thread. The thread also gets a
W32THREAD
+structure, a message queue and a thread input structures.
+Beware that there is an exception to these rules and that's WinLogon.
Since
+at the time the process starts no window stations or desktops exist,
none
+are assigned to the the initial thread / process. The first Win32k
calls
+the thread does are to create the window station and desktop and to
associate
+them with itself.
-There is no need to validate any of these values, because they MUST
EXIST!
+FIXME: At the time of this writing there's a second exception, a
"primitive
+message queue" thread in CSRSS that is created before any window
stations
+exist and is used to capture keyboard input in console mode. Eventually
we
+should get rid of it and replace is with hidden window w/ focus or
something
+similar.
- !!!!!NOTE!!!!
-Reactos is currently wrong on the thread desktop, process desktop and
process WinSta,
-since they can be NULL!!
+Generally this means that when you are in a Win32k syscall function
(other
+than the window station or desktop functions) you can be 100% sure that
the
+following exists:
+- Process window station
+- Win32 process structure
+- Win32 thread structure
+- Thread message queue
+- Thread input
+- Thread desktop
+
+There is no need to validate any of these values, because they MUST
EXIST!
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