27-Feb-2005 (Konstantinos Paliouras <squarious@gmail.com>)
authorAleksey Bragin <aleksey@reactos.org>
Tue, 8 Mar 2005 15:08:01 +0000 (15:08 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Tue, 8 Mar 2005 15:08:01 +0000 (15:08 +0000)
Implemented all the switches that were missing, and made the ros dir very similar to windows dir. Major part of the code is rewritten. /p is removed, to be rewriten in the main cmd code.

svn path=/trunk/; revision=13877

reactos/subsys/system/cmd/dir.c
reactos/subsys/system/cmd/precomp.h

index 31e8b4e..5a2d915 100644 (file)
  *
  *    30-Apr-2004 (Filip Navara <xnavara@volny.cz>)
  *        Fix /w to print long names.
+ *
+ *    27-Feb-2005 (Konstantinos Paliouras <squarious@gmail.com>)
+ *        Implemented all the switches that were missing, and made
+ *        the ros dir very similar to windows dir. Major part of
+ *        the code is rewritten. /p is removed, to be rewriten in
+ *        the main cmd code.
+ *        
  */
 
 #include "precomp.h"
 #ifdef INCLUDE_CMD_DIR
 
 
-/* flag definitions */
-enum
+
+/* Time Field enumeration */
+enum ETimeField
+{
+       TF_CREATIONDATE         = 0,
+       TF_MODIFIEDDATE         = 1,
+       TF_LASTACCESSEDDATE     = 2
+};
+
+/* Ordered by enumeration */
+enum EOrderBy
 {
-       DIR_RECURSE = 0x0001,
-       DIR_PAGE    = 0x0002,
-       DIR_WIDE    = 0x0004,        /* Rob Lake */
-       DIR_BARE    = 0x0008,        /* Rob Lake */
-       DIR_ALL     = 0x0010,        /* Rob Lake */
-       DIR_LWR     = 0x0020,        /* Rob Lake */
-       DIR_SORT    = 0x0040,        /* /O sort */
-       DIR_NEW     = 0x0080,        /* /N new style */
-       DIR_FOUR    = 0x0100         /* /4 four digit year */
+       ORDER_NAME              = 0,
+       ORDER_SIZE              = 1,
+       ORDER_DIRECTORY = 2,
+       ORDER_EXTENSION = 3,
+       ORDER_TIME              = 4
 };
 
+/* The struct for holding the switches */
+typedef struct TDirSwitchesFlags
+{
+       BOOL bBareFormat;       /* Bare Format */
+       BOOL bTSeperator;       /* Thousands seperator */
+       BOOL bWideList;         /* Wide list format     */
+       BOOL bWideListColSort;  /* Wide list format but sorted by column */
+       BOOL bLowerCase;        /* Uses lower case */
+       BOOL bNewLongList;      /* New long list */
+       BOOL bPause;            /* Pause per page */
+       BOOL bUser;                     /* Displays the owner of file */
+       BOOL bRecursive;        /* Displays files in specified directory and all sub */
+       BOOL bShortName;        /* Displays the sort name of files if exist     */
+       BOOL b4Digit;           /* Four digit year      */
+       struct
+       {
+               DWORD dwAttribVal;      /* The desired state of attribute */
+               DWORD dwAttribMask;     /* Which attributes to check */
+               BOOL bUnSet;            /* A helper flag if "-" was given with the switch */
+               BOOL bParSetted;        /* A helper flag if parameters of switch were given */
+       } stAttribs;            /* Displays files with this attributes only */
+       struct
+       {
+               enum EOrderBy eCriteria[3];     /* Criterias used to order by */
+               BOOL bCriteriaRev[3];           /* If the criteria is in reversed order */
+               short sCriteriaCount;           /* The quantity of criterias */
+               BOOL bUnSet;                            /* A helper flag if "-" was given with the switch */
+               BOOL bParSetted;                        /* A helper flag if parameters of switch were given */
+       } stOrderBy;            /* Ordered by criterias */
+       struct
+       {
+               enum ETimeField eTimeField;     /* The time field that will be used for */
+               BOOL bUnSet;                            /* A helper flag if "-" was given with the switch */
+               BOOL bParSetted;                        /* A helper flag if parameters of switch were given */
+       } stTimeField;          /* The time field to display or use for sorting */
+}DIRSWITCHFLAGS, * LPDIRSWITCHFLAGS;
 
 typedef BOOL STDCALL
 (*PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
@@ -158,177 +206,382 @@ static ULARGE_INTEGER recurse_bytes;
  * displays help screen for dir
  * Rob Lake
  */
-static VOID Help (VOID)
+static VOID
+       DirHelp (VOID)
 {
-  ConOutPuts(_T("Displays a list of files and subdirectories in a directory.\n"
-       "\n"
-       "DIR [drive:][path][filename] [/A] [/B] [/L] [/N] [/S] [/P] [/W] [/4]\n"
-       "\n"
-       "  [drive:][path][filename]\n"
-       "              Specifies drive, directory, and/or files to list.\n"
-       "\n"
-       "  /A          Displays files with HIDDEN SYSTEM attributes\n"
-       "              default is ARCHIVE and READ ONLY\n"
-       "  /B          Uses bare format (no heading information or summary).\n"
-       "  /L          Uses lowercase.\n"
-       "  /N          New long list format where filenames are on the far right.\n"
-       "  /S          Displays files in specified directory and all subdirectories\n"
-       "  /P          Pauses after each screen full\n"
-       "  /W          Prints in wide format\n"
-       "  /4          Display four digit years.\n"
-       "\n"
-       "Switches may be present in the DIRCMD environment variable.  Use\n"
-       "of the - (hyphen) can turn off defined swtiches.  Ex. /-W would\n"
-       "turn off printing in wide format.\n"
+       ConOutPuts(_T(
+               "DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]\n"
+               "  [/O[[:]sortorder]] [/P] [/Q] [/S] [/T[[:]timefield]] [/W] [/X] [/4]\n"
+               "\n"
+               "  [drive:][path][filename]\n"
+               "              Specifies drive, directory, and/or files to list.\n"
+               "\n"
+               "  /A          Displays files with specified attributes.\n"
+               "  attributes   D  Directories                R  Read-only files\n"
+               "               H  Hidden files               A  Files ready for archiving\n"
+               "               S  System files               -  Prefix meaning not\n"
+               "  /B          Uses bare format (no heading information or summary).\n"
+               "  /C          Display the thousand separator in file sizes.  This is the\n"
+               "              default.  Use /-C to disable display of separator.\n"
+               "  /D          Same as wide but files are list sorted by column.\n"
+               "  /L          Uses lowercase.\n"
+               "  /N          New long list format where filenames are on the far right.\n"
+               "  /O          List by files in sorted order.\n"
+               "  sortorder    N  By name (alphabetic)       S  By size (smallest first)\n"
+               "               E  By extension (alphabetic)  D  By date/time (oldest first)\n"
+               "               G  Group directories first    -  Prefix to reverse order\n"
+               "  /P          Pauses after each screenful of information.\n"
+               "  /Q          Display the owner of the file.\n"
+               "  /S          Displays files in specified directory and all subdirectories.\n"
+               "  /T          Controls which time field displayed or used for sorting\n"
+               "  timefield   C  Creation\n"
+               "              A  Last Access\n"
+               "              W  Last Written\n"
+               "  /W          Uses wide list format.\n"
+               "  /X          This displays the short names generated for non-8dot3 file\n"
+               "              names.  The format is that of /N with the short name inserted\n"
+               "              before the long name. If no short name is present, blanks are\n"
+               "              displayed in its place.\n"
+               "  /4          Displays four-digit years\n"
+               " \n"
+               "Switches may be preset in the DIRCMD environment variable.  Override\n"
+               "preset switches by prefixing any switch with - (hyphen)--for example, /-W.\n"
       ));
 }
 
 
+
 /*
- * DirReadParam
+ * DirReadParameters
  *
- * read the parameters from the command line
+ * Parse the parameters and switches of the command line and exports them
  */
-static BOOL
-DirReadParam (LPTSTR line, LPTSTR *param, LPDWORD lpFlags)
+static BOOL 
+DirReadParam (LPTSTR line,                             /* [IN] The line with the parameters & switches */
+                         LPTSTR *param,                        /* [OUT] The parameters after parsing */
+                         LPDIRSWITCHFLAGS lpFlags      /* [IN/OUT] The flags after calculating switches */
+                         )
 {
-       INT slash = 0;
-
-       if (!line)
-               return TRUE;
-
+TCHAR cCurSwitch;      /* The current switch */
+TCHAR cCurChar;                /* Current examing character */
+TCHAR cCurUChar;       /* Current upper examing character */
+BOOL bNegative;                /* Negative switch */
+BOOL bPNegative;       /* Negative switch parameter */
+BOOL bIntoQuotes;      /* A flag showing if we are in quotes (") */
+LPTSTR ptrLast;                /* A pointer to the last character of param */
+
+       /* Initialize variables; */
+       cCurSwitch = _T(' ');
+       bNegative = FALSE;
+       bPNegative = FALSE;
+       bIntoQuotes = FALSE;
+
+       /* No parameters yet  */
        *param = NULL;
-
-       /* scan the command line, processing switches */
+       ptrLast = NULL;
+       
+       /* We suppose that switch parameters
+          were given to avoid setting them to default
+          if the switch was not given */
+       lpFlags->stAttribs.bParSetted = TRUE;
+       lpFlags->stOrderBy.bParSetted = TRUE;
+       lpFlags->stTimeField.bParSetted = TRUE;
+
+       /* Main Loop (see README_DIR.txt) */
+       /* scan the command line char per char, and we process its char */
        while (*line)
        {
-               /* process switch */
-               if (*line == _T('/') || slash)
+               /* we save current character as it is and its upper case */
+               cCurChar = *line;
+               cCurUChar = _toupper(*line);
+               
+               /* 1st section (see README_DIR.txt) */
+               /* When a switch is expecting */
+               if (cCurSwitch == _T('/'))
                {
-                       if (!slash)
-                               line++;
-                       slash = 0;
-                       if (*line == _T('-'))
-                       {
-                               line++;
-                               if (_totupper (*line) == _T('S'))
-                                       *lpFlags &= ~DIR_RECURSE;
-                               else if (_totupper (*line) == _T('P'))
-                                       *lpFlags &= ~DIR_PAGE;
-                               else if (_totupper (*line) == _T('W'))
-                                       *lpFlags &= ~DIR_WIDE;
-                               else if (_totupper (*line) == _T('B'))
-                                       *lpFlags &= ~DIR_BARE;
-                               else if (_totupper (*line) == _T('A'))
-                                       *lpFlags &= ~DIR_ALL;
-                               else if (_totupper (*line) == _T('L'))
-                                       *lpFlags &= ~DIR_LWR;
-                               else if (_totupper (*line) == _T('N'))
-                                       *lpFlags &= ~DIR_NEW;
-                               else if (_totupper (*line) == _T('O'))
-                                       *lpFlags &= ~DIR_SORT;
-                               else if (_totupper (*line) == _T('4'))
-                                       *lpFlags &= ~DIR_FOUR;
-                               else
+                       if ((cCurUChar == _T('A')) ||(cCurUChar == _T('T')) || (cCurUChar == _T('O')))
+                       {                       
+                               cCurSwitch = cCurUChar;
+                               switch (cCurUChar)
                                {
-                                       error_invalid_switch ((TCHAR)_totupper (*line));
-                                       return FALSE;
+                               case _T('A'):
+                                       lpFlags->stAttribs.bUnSet = bNegative;
+                                       lpFlags->stAttribs.bParSetted = FALSE;
+                                       break;
+                               case _T('T'):
+                                       lpFlags->stTimeField.bUnSet = bNegative;
+                                       lpFlags->stTimeField.bParSetted = FALSE;
+                                       break;
+                               case _T('O'):
+                                       lpFlags->stOrderBy.bUnSet = bNegative;
+                                       lpFlags->stOrderBy.bParSetted = FALSE;
+                                       break;
                                }
-                               line++;
-                               continue;
                        }
-                       else
+                       else if (cCurUChar ==  _T('L'))
+                               lpFlags->bLowerCase = ! bNegative;
+                       else if (cCurUChar ==  _T('B'))                 
+                               lpFlags->bBareFormat = ! bNegative;
+                       else if (cCurUChar ==  _T('C'))
+                               lpFlags->bTSeperator = ! bNegative;
+                       else if (cCurUChar ==  _T('W'))
+                               lpFlags->bWideList = ! bNegative;                               
+                       else if (cCurUChar ==  _T('D'))
+                               lpFlags->bWideListColSort = ! bNegative;                                
+                       else if (cCurUChar ==  _T('N'))
+                               lpFlags->bNewLongList = ! bNegative;
+                       else if (cCurUChar ==  _T('P'))
+                               lpFlags->bPause = ! bNegative;
+                       else if (cCurUChar ==  _T('Q'))
+                               lpFlags->bUser = ! bNegative;
+                       else if (cCurUChar ==  _T('S'))
+                               lpFlags->bRecursive = ! bNegative;
+                       else if (cCurUChar ==  _T('X'))
+                               lpFlags->bShortName = ! bNegative;
+                       else if (cCurChar == _T('4'))
+                               lpFlags->b4Digit = ! bNegative;
+                       else if (cCurChar ==  _T('?'))
                        {
-                               if (_totupper (*line) == _T('S'))
-                                       *lpFlags |= DIR_RECURSE;
-                               else if (_totupper (*line) == _T('P'))
-                                       *lpFlags |= DIR_PAGE;
-                               else if (_totupper (*line) == _T('W'))
-                                       *lpFlags |= DIR_WIDE;
-                               else if (_totupper (*line) == _T('B'))
-                                       *lpFlags |= DIR_BARE;
-                               else if (_totupper (*line) == _T('A'))
-                                       *lpFlags |= DIR_ALL;
-                               else if (_totupper (*line) == _T('L'))
-                                       *lpFlags |= DIR_LWR;
-                               else if (_totupper (*line) == _T('N'))
-                                       *lpFlags |= DIR_NEW;
-                               else if (_totupper (*line) == _T('O'))
-                                       *lpFlags |= DIR_SORT;
-                               else if (_totupper (*line) == _T('4'))
-                                       *lpFlags |= DIR_FOUR;
-                               else if (*line == _T('?'))
-                               {
-                                       Help();
-                                       return FALSE;
-                               }
-                               else
-                               {
-                                       error_invalid_switch ((TCHAR)_totupper (*line));
-                                       return FALSE;
-                               }
-                               line++;
-                               continue;
+                               DirHelp();
+                               return FALSE;                
                        }
-               }
-
-               /* process parameter */
-               if (!_istspace (*line))
-               {
-                       if (*param)
+                       else if (cCurChar ==  _T('-'))
+                               bNegative = TRUE;
+                       else 
                        {
-                               error_too_many_parameters (line);
+                               error_invalid_switch ((TCHAR)_totupper (*line));
                                return FALSE;
                        }
 
-                       *param = line;
+                       /* We check if we calculated the negative value and realese the flag */
+                       if ((cCurChar != _T('-')) && bNegative)
+                               bNegative = FALSE;
 
-                       /* skip to end of line or next whitespace or next / */
-                       if (*line != _T('\"'))
-                       {
-                               while (*line && !_istspace (*line) && *line != _T('/'))
-                                       line++;
+                       /* if not a,o,t or - option then next parameter is not a switch */
+                       if ((cCurSwitch == _T('/')) && (!bNegative))
+                               cCurSwitch = _T(' ');
+
+               }
+               /* 2nd section (see README_DIR.txt) */
+               /* We are expecting parameter or the unknown */
+               else if ((cCurSwitch == _T(' ')) || (cCurSwitch == _T('P')))
+               {
+                       if (cCurChar == _T('/'))
+                               cCurSwitch = _T('/');
 
-                               /* if end of line, return */
-                               if (!*line)
-                                       return TRUE;
+                       /* Process a spacer */
+                       else if (cCurChar == _T(' '))
+                       {
+                               if (!bIntoQuotes)
+                               {
+                                       cCurSwitch = _T(' ');
+                                       if ((*param) && !(ptrLast))
+                                               ptrLast = line;
+                               }                               
+                                       
                        }
-                       else
+                       /* Process a quote */
+                       else if (cCurChar == _T('\"'))
+                       {
+                               bIntoQuotes = !bIntoQuotes;
+                               if (!bIntoQuotes) ptrLast = line;
+                       }
+                       /* Process a character for parameter */
+                       else                    
                        {
-                               /* skip over the initial quote */
-                               (*param)++;
-                               line++;
+                               if ((cCurSwitch == _T(' ')) && (*param))
+                               {
+                                       error_too_many_parameters(line);
+                                       return FALSE;
+                               }
+                               cCurSwitch = _T('P');
+                               if (!(*param))
+                                       *param = line;
+                       }
 
-                               while (*line && *line != _T('"'))
-                                       line++;
+               }
+               /* 3rd section (see README_DIR.txt) */
+               /* We are waiting for switch parameters */
+               else
+               {
+                       /* Check if there are no more switch parameters */
+                       if ((cCurChar == _T('/')) || ( cCurChar == _T(' ')))
+                       {
+                               /* Wrong desicion path, reprocess current character */
+                               cCurSwitch = cCurChar;
+                               continue;
+                       }
+                       /* Process parameter switch */
+                       switch(cCurSwitch)
+                       {
+                       case _T('A'):   /* Switch parameters for /A (attributes filter) */
+                               /* Ok a switch parameter was given */
+                               lpFlags->stAttribs.bParSetted = TRUE;
+
+                               if (cCurChar == _T(':'))
+                                       /* =V= dead command, used to make the "if" work */
+                                       cCurChar = cCurChar;
+                               else if(cCurChar == _T('-'))
+                                       bPNegative = TRUE;
+                               else if(cCurUChar == _T('D'))
+                               {
+                                       lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_DIRECTORY;
+                                       if (bPNegative)
+                                               lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_DIRECTORY;
+                                       else
+                                               lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_DIRECTORY;
+                               }
+                               else if(cCurUChar == _T('R'))
+                               {
+                                       lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_READONLY;
+                                       if (bPNegative)
+                                               lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_READONLY;
+                                       else
+                                               lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_READONLY;
+                               }
+                               else if(cCurUChar == _T('H'))
+                               {
+                                       lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_HIDDEN;
+                                       if (bPNegative)
+                                               lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_HIDDEN;
+                                       else
+                                               lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_HIDDEN;
+                               }
+                               else if(cCurUChar == _T('A'))
+                               {
+                                       lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_ARCHIVE;
+                                       if (bPNegative)
+                                               lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_ARCHIVE;
+                                       else
+                                               lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_ARCHIVE;
+                               }
+                               else if(cCurUChar == _T('S'))
+                               {
+                                       lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_SYSTEM;
+                                       if (bPNegative)
+                                               lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_SYSTEM;
+                                       else
+                                               lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_SYSTEM;
+                               }
+                               else
+                               {
+                                       error_parameter_format((TCHAR)_totupper (*line));
+                                       return FALSE;
+                               }
+                               break;
+                       case _T('T'):   /* Switch parameters for /T (time field) */
+
+                               /* Ok a switch parameter was given */
+                               lpFlags->stTimeField.bParSetted = TRUE;
+
+                               if (cCurChar == _T(':'))
+                                       /* =V= dead command, used to make the "if" work */
+                                       cCurChar = cCurChar;
+                               else if(cCurUChar == _T('C'))
+                                       lpFlags->stTimeField.eTimeField= TF_CREATIONDATE ;
+                               else if(cCurUChar == _T('A'))
+                                       lpFlags->stTimeField.eTimeField= TF_LASTACCESSEDDATE ;
+                               else if(cCurUChar == _T('W'))
+                                       lpFlags->stTimeField.eTimeField= TF_MODIFIEDDATE  ;
+                               else
+                               {
+                                       error_parameter_format((TCHAR)_totupper (*line));
+                                       return FALSE;
+                               }
+                               break;
+                       case _T('O'):   /* Switch parameters for /O (order) */
+                               /* Ok a switch parameter was given */
+                               lpFlags->stOrderBy.bParSetted = TRUE;
+
+                               if (cCurChar == _T(':'))
+                                       /* <== dead command, used to make the "if" work */
+                                       cCurChar = cCurChar;
+                               else if(cCurChar == _T('-'))
+                                       bPNegative = TRUE;
+                               else if(cCurUChar == _T('N'))
+                               {
+                                       if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+                                       lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+                                       lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_NAME;
+                               }
+                               else if(cCurUChar == _T('S'))
+                               {
+                                       if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+                                       lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+                                       lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_SIZE;
+                               }
+                               else if(cCurUChar == _T('G'))
+                               {
+                                       if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+                                       lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+                                       lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_DIRECTORY;
+                               }
+                               else if(cCurUChar == _T('E'))
+                               {
+                                       if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+                                       lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+                                       lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_EXTENSION;
+                               }
+                               else if(cCurUChar == _T('D'))
+                               {
+                                       if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+                                       lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+                                       lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_TIME;
+                               }
 
-                               if (*line == _T('"'))
-                                       *line = 0;
                                else
-                                       return TRUE;
-                       }
+                               {
+                                       error_parameter_format((TCHAR)_totupper (*line));
+                                       return FALSE;
+                               }
 
-                       /* if parameter, remember to process it later */
-                       if (*line == _T('/'))
-                               slash = 1;
 
-                       *line++ = 0;
-                       continue;
+                       }
+                       /* We check if we calculated the negative value and realese the flag */
+                       if ((cCurChar != _T('-')) && bPNegative)
+                               bPNegative = FALSE;
                }
-
+       
                line++;
        }
+       /* Terminate the parameters */
+       if (ptrLast) *ptrLast = 0;
 
-       if (slash)
+       /* Calculate the switches with no switch paramater  */
+       if (!(lpFlags->stAttribs.bParSetted))
        {
-               error_invalid_switch ((TCHAR)_totupper (*line));
-               return FALSE;
+               lpFlags->stAttribs.dwAttribVal = 0L;
+               lpFlags->stAttribs.dwAttribMask = lpFlags->stAttribs.dwAttribVal;
+       }
+       if (!(lpFlags->stOrderBy.bParSetted))
+       {
+               lpFlags->stOrderBy.sCriteriaCount = 1;
+               lpFlags->stOrderBy.eCriteria[0] = ORDER_NAME;
+               lpFlags->stOrderBy.bCriteriaRev[0] = FALSE;
        }
+       if (!(lpFlags->stOrderBy.bParSetted))
+               lpFlags->stTimeField.eTimeField = TF_MODIFIEDDATE ;
 
+       /* Calculate the unsetted switches (the "-" prefixed)*/
+       if (lpFlags->stAttribs.bUnSet)
+       {
+               lpFlags->stAttribs.bUnSet = FALSE;
+               lpFlags->stAttribs.dwAttribVal = 0L;
+               lpFlags->stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
+       }
+       if (lpFlags->stOrderBy.bUnSet)
+       {
+               lpFlags->stOrderBy.bUnSet = FALSE;
+               lpFlags->stOrderBy.sCriteriaCount = 0;
+       }
+       if (lpFlags->stTimeField.bUnSet )
+       {
+               lpFlags->stTimeField.bUnSet = FALSE;
+               lpFlags->stTimeField.eTimeField = TF_MODIFIEDDATE;
+       }
        return TRUE;
 }
 
-
 /*
  * ExtendFilespec
  *
@@ -507,9 +760,9 @@ DirParsePathspec (LPTSTR szPathspec, LPTSTR szPath, LPTSTR szFilespec)
  * incline
  *
  * increment our line if paginating, display message at end of screen
- */
+ *//*Maybe needed in future
 static BOOL
-IncLine (LPINT pLine, DWORD dwFlags)
+IncLine (LPINT pLine, LPDIRSWITCHFLAGS lpFlags)
 {
        BOOL error;
        CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo;
@@ -518,16 +771,21 @@ IncLine (LPINT pLine, DWORD dwFlags)
        
        WindowHeight= lpConsoleScreenBufferInfo.srWindow.Bottom - lpConsoleScreenBufferInfo.srWindow.Top;
 
-       if (!WindowHeight)  //That prevents bad behave if WindowHeight couln't calc
+       //That prevents bad behave if WindowHeight couln't calc 
+       if (!WindowHeight)  
        {
                 WindowHeight= 1000000;
        }
-       if (!(dwFlags & DIR_PAGE))
+       if (!(lpFlags->bPause))
                return FALSE;
 
        (*pLine)++;
 
-       if (*pLine >= (int)maxy - 2 || *pLine >= WindowHeight) //Because I don't know if WindowsHeight work under all cases, perhaps then maxy is the right value
+       // Because I don't know if WindowsHeight
+          work under all cases, perhaps then maxy
+          is the right value 
+   
+       if (*pLine >= (int)maxy - 2 || *pLine >= WindowHeight) 
        {
                *pLine = 0;
                return (PagePrompt () == PROMPT_BREAK);
@@ -535,7 +793,7 @@ IncLine (LPINT pLine, DWORD dwFlags)
 
        return FALSE;
 }
-
+*/
 
 /*
  * PrintDirectoryHeader
@@ -543,14 +801,14 @@ IncLine (LPINT pLine, DWORD dwFlags)
  * print the header for the dir command
  */
 static BOOL
-PrintDirectoryHeader (LPTSTR szPath, LPINT pLine, DWORD dwFlags)
+PrintDirectoryHeader (LPTSTR szPath, LPINT pLine, LPDIRSWITCHFLAGS lpFlags)
 {
   TCHAR szRootName[MAX_PATH];
   TCHAR szVolName[80];
   DWORD dwSerialNr;
   LPTSTR p;
 
-  if (dwFlags & DIR_BARE)
+  if (lpFlags->bBareFormat)
     return(TRUE);
 
   /* build usable root path */
@@ -607,15 +865,10 @@ PrintDirectoryHeader (LPTSTR szPath, LPINT pLine, DWORD dwFlags)
   else
     ConOutPrintf(_T(" has no label\n"));
 
-  if (IncLine(pLine, dwFlags))
-    return(FALSE);
-
   /* print the volume serial number if the return was successful */
   ConOutPrintf(_T(" Volume Serial Number is %04X-%04X\n"),
               HIWORD(dwSerialNr),
               LOWORD(dwSerialNr));
-  if (IncLine(pLine, dwFlags))
-    return(FALSE);
 
   return(TRUE);
 }
@@ -625,7 +878,7 @@ PrintDirectoryHeader (LPTSTR szPath, LPINT pLine, DWORD dwFlags)
  * convert
  *
  * insert commas into a number
- */
+ *//* Maybe needed in future
 static INT
 ConvertULong (ULONG num, LPTSTR des, INT len)
 {
@@ -656,10 +909,10 @@ ConvertULong (ULONG num, LPTSTR des, INT len)
 
        return n;
 }
-
+*/
 
 static INT
-ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len)
+ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len, BOOL bPutSeperator)
 {
        TCHAR temp[32];
        INT c = 0;
@@ -676,7 +929,7 @@ ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len)
                temp[31] = 0;
                while (num.QuadPart > 0)
                {
-                       if (((c + 1) % (nNumberGroups + 1)) == 0)
+                       if ((((c + 1) % (nNumberGroups + 1)) == 0) && (bPutSeperator))
                                temp[30 - c++] = cThousandSeparator;
                        temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0');
                        num.QuadPart /= 10;
@@ -691,44 +944,80 @@ ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len)
 
 
 static VOID
-PrintFileDateTime (LPSYSTEMTIME dt, DWORD dwFlags)
+DirPrintFileDateTime (TCHAR * lpDate,
+                                         TCHAR * lpTime,
+                                         LPWIN32_FIND_DATA lpFile,
+                                         LPDIRSWITCHFLAGS lpFlags)
 {
-       WORD wYear = (dwFlags & DIR_FOUR) ? dt->wYear : dt->wYear%100;
+FILETIME ft;
+SYSTEMTIME dt;
+TCHAR szDate[30];
+TCHAR szTime[30];
+WORD wYear;
+
+       /* Select the right time field */
+       switch (lpFlags->stTimeField.eTimeField)
+       {
+       case TF_CREATIONDATE:
+               if (!FileTimeToLocalFileTime(&lpFile->ftCreationTime, &ft))
+                       return;
+               FileTimeToSystemTime(&ft, &dt);         
+               break;
+       case TF_LASTACCESSEDDATE :
+               if (!FileTimeToLocalFileTime(&lpFile->ftLastAccessTime, &ft))
+                       return;
+               FileTimeToSystemTime(&ft, &dt);         
+               break;
+       case TF_MODIFIEDDATE:
+               if (!FileTimeToLocalFileTime(&lpFile->ftLastWriteTime, &ft))
+                       return;
+               FileTimeToSystemTime(&ft, &dt);         
+               break;
+       }
 
+       /* Format date */
+       wYear = (lpFlags->b4Digit) ? dt.wYear : dt.wYear%100;
        switch (nDateFormat)
        {
                case 0: /* mmddyy */
                default:
-                       ConOutPrintf (_T("%.2d%c%.2d%c%d"),
-                                       dt->wMonth, cDateSeparator, dt->wDay, cDateSeparator, wYear);
+                       _stprintf (szDate,_T("%02d%c%02d%c%0*d"),
+                                       dt.wMonth, cDateSeparator,
+                                       dt.wDay, cDateSeparator,
+                                       lpFlags->b4Digit?4:2, wYear);
                        break;
 
                case 1: /* ddmmyy */
-                       ConOutPrintf (_T("%.2d%c%.2d%c%d"),
-                                       dt->wDay, cDateSeparator, dt->wMonth, cDateSeparator, wYear);
+                       _stprintf (szDate, _T("%02d%c%02d%c%0*d"),
+                                       dt.wDay, cDateSeparator, dt.wMonth,
+                                       cDateSeparator,lpFlags->b4Digit?4:2, wYear);
                        break;
 
                case 2: /* yymmdd */
-                       ConOutPrintf (_T("%d%c%.2d%c%.2d"),
-                                       wYear, cDateSeparator, dt->wMonth, cDateSeparator, dt->wDay);
+                       _stprintf (szDate, _T("%0*d%c%02d%c%02d"),
+                                       lpFlags->b4Digit?4:2, wYear, cDateSeparator,
+                                       dt.wMonth, cDateSeparator, dt.wDay);
                        break;
        }
-
+       /* Format Time */
        switch (nTimeFormat)
        {
                case 0: /* 12 hour format */
                default:
-                       ConOutPrintf (_T("  %2d%c%.2u%c"),
-                                       (dt->wHour == 0 ? 12 : (dt->wHour <= 12 ? dt->wHour : dt->wHour - 12)),
+                       _stprintf (szTime,_T("  %02d%c%02u%c"),
+                                       (dt.wHour == 0 ? 12 : (dt.wHour <= 12 ? dt.wHour : dt.wHour - 12)),
                                        cTimeSeparator,
-                                        dt->wMinute, (dt->wHour <= 11 ? 'a' : 'p'));
+                                        dt.wMinute, (dt.wHour <= 11 ? 'a' : 'p'));
                        break;
 
                case 1: /* 24 hour format */
-                       ConOutPrintf (_T("  %2d%c%.2u"),
-                                       dt->wHour, cTimeSeparator, dt->wMinute);
+                       _stprintf (szTime, _T("  %02d%c%02u"),
+                                       dt.wHour, cTimeSeparator, dt.wMinute);
                        break;
        }
+       /* Copy results */
+       _tcscpy(lpDate, szDate);
+       _tcscpy(lpTime, szTime);
 }
 
 
@@ -783,457 +1072,734 @@ static INT
 PrintSummary(LPTSTR szPath,
             ULONG ulFiles,
             ULONG ulDirs,
-            ULARGE_INTEGER bytes,
+            ULARGE_INTEGER u64Bytes,
             LPINT pLine,
-            DWORD dwFlags)
+            LPDIRSWITCHFLAGS lpFlags)
 {
-  TCHAR buffer[64];
-  ULARGE_INTEGER uliFree;
-  TCHAR szRoot[] = _T("A:\\");
-
-  if (dwFlags & DIR_BARE)
-    return(0);
+TCHAR szBuffer[64];
+ULARGE_INTEGER uliFree;
+TCHAR szRoot[] = _T("A:\\");
 
-  /* Print number of files and bytes */
-  ConvertULong (ulFiles, buffer, sizeof(buffer));
-  ConOutPrintf (_T("          %6s File%c"),
-                buffer, ulFiles == 1 ? _T(' ') : _T('s'));
 
-  ConvertULargeInteger (bytes, buffer, sizeof(buffer));
-  ConOutPrintf (_T("  %15s byte%c\n"),
-                buffer, bytes.QuadPart == 1 ? _T(' ') : _T('s'));
-
-  if (IncLine (pLine, dwFlags))
-    return 1;
-
-  /* Print number of dirs and bytes free */
-  ConvertULong (ulDirs, buffer, sizeof(buffer));
-  ConOutPrintf (_T("          %6s Dir%c"),
-                buffer, ulDirs == 1 ? _T(' ') : _T('s'));
-
-  if (!(dwFlags & DIR_RECURSE))
-    {
-      szRoot[0] = szPath[0];
-      GetUserDiskFreeSpace(szRoot, &uliFree);
-      ConvertULargeInteger (uliFree, buffer, sizeof(buffer));
-      ConOutPrintf (_T("   %15s bytes free\n"), buffer);
-      if (IncLine (pLine, dwFlags))
-        return 1;
-    }
-  else
-    {
-      if ((dwFlags & DIR_BARE) == 0)
-        {
-         ConOutPrintf (_T("\n"));
-          if (IncLine (pLine, dwFlags))
-            return 1;
-          ConOutPrintf (_T("\n"));
+       /* Here we check if we didn't find anything */
+       if (!(ulFiles + ulDirs))
+       {
+               error_file_not_found();
+               return 1;
        }
-      if (IncLine (pLine, dwFlags))
-         return 1;
+       /* In bare format we don't print results */
+       if (lpFlags->bBareFormat)
+               return 0;
+
+       /* Print recursive specific results */
+       if (lpFlags->bRecursive)
+       {
+               ConvertULargeInteger (u64Bytes, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator);
+               ConOutPrintf (_T("\n     Total Files Listed:\n"));
+               ConOutPrintf(_T("%16i File(s)% 14s bytes\n"),ulFiles, szBuffer);
     }
 
+       /* Print total  directories and freespace */
+       szRoot[0] = szPath[0];
+       GetUserDiskFreeSpace(szRoot, &uliFree);
+       ConvertULargeInteger (uliFree, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator);
+    ConOutPrintf (_T("%16i Dir(s)% 15s bytes\n"),ulDirs, szBuffer);
+
   return 0;
 }
 
+/*
+ * getExt
+ *
+ * Get the extension of a filename 
+ */
+TCHAR* getExt(const TCHAR* file)
+{
+       
+       TCHAR* tmp = _tcsrchr(file,'.');
+       return tmp?tmp+1:"";
+}
 
 /*
- * dir_list
+ * getName
  *
- * list the files in the directory
+ * Get the name of the file without extension
  */
-static INT
-DirList (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
+TCHAR * getName(const TCHAR* file, TCHAR * dest)
 {
-       TCHAR szFullPath[MAX_PATH];
-       WIN32_FIND_DATA file;
-       ULARGE_INTEGER bytecount;
-       FILETIME   ft;
-       SYSTEMTIME dt;
-       HANDLE hFile;
-       TCHAR  buffer[32];
-       ULONG filecount = 0;
-       ULONG dircount = 0;
-       INT count = 0;
-       SHORT screenwidth;
-       INT longestfname = 0;
-
-       bytecount.QuadPart = 0;
+int iLen;
+TCHAR* end;
+       
+       /* Check for "." and ".." folders */
+       if ((_tcscmp(file, _T(".")) == 0)
+               || (_tcscmp(file, _T("..")) == 0))
+       {
+               _tcscpy(dest,file);
+               return dest;
+       }
 
-       _tcscpy (szFullPath, szPath);
-       if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
-               _tcscat (szFullPath, _T("\\"));
-       _tcscat (szFullPath, szFilespec);
+       end = _tcsrchr(file,'.');
+       if (!end)
+               iLen = _tcslen(file);   
+       else                    
+               iLen = (end - file);
+       
 
-       hFile = FindFirstFile (szFullPath, &file);
-       if (hFile == INVALID_HANDLE_VALUE)
+       _tcsncpy(dest, file, iLen);
+       *(dest + iLen) = _T('\0');
+       
+       return dest;
+}
+/*
+ *  DirPrintNewList
+ *
+ * The function that prints in new style
+ */
+static int
+DirPrintNewList(LPWIN32_FIND_DATA ptrFiles[],  /* [IN]Files' Info */
+                               DWORD dwCount,                                  /* [IN] The quantity of files */
+                               TCHAR * szCurPath,                              /* [IN] Full path of current directory */
+                               LPDIRSWITCHFLAGS lpFlags)               /* [IN] The flags used */
+{
+DWORD i;                                               /* An indexer for "for"s */
+TCHAR szSize[30];                              /* The size of file */
+TCHAR szShortName[15];                 /* The sort name */
+TCHAR szDate[20], szTime[20];  /* Date and time strings */
+int iSizeFormat;                               /* The format of size field */
+ULARGE_INTEGER u64FileSize;            /* The file size */
+
+       for(i = 0;i < dwCount;i++)
        {
-               /* Don't want to print anything if scanning recursively
-                * for a file. RL
-                */
-               if ((dwFlags & DIR_RECURSE) == 0)
+
+               /* Calculate size */            
+               if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+               /* Directory */
                {
-                       FindClose (hFile);
-                       error_file_not_found ();
-                       if (IncLine (pLine, dwFlags))
-                               return 0;
-                       return 1;
+                       iSizeFormat = -14;
+                       _tcscpy(szSize, _T("<DIR>"));
                }
-               FindClose (hFile);
-               return 0;
-       }
-
-       /* Get the size of longest filename for wide listing. FN */
-       if (dwFlags & DIR_WIDE && (dwFlags & DIR_BARE) == 0)
-       {
-               do
+               else
+               /* File */
                {
-                       if (_tcslen(file.cFileName) > longestfname)
-                       {
-                               longestfname = _tcslen(file.cFileName);
-                               /* Directories get extra brackets around them. */
-                               if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                                       longestfname += 2;
-                       }
+                       iSizeFormat = 14;
+                       u64FileSize.HighPart = ptrFiles[i]->nFileSizeHigh;
+                       u64FileSize.LowPart = ptrFiles[i]->nFileSizeLow;
+                       ConvertULargeInteger(u64FileSize, szSize, 20,lpFlags->bTSeperator);
                }
-               while (FindNextFile (hFile, &file));
-               FindClose (hFile);
-
-               hFile = FindFirstFile (szFullPath, &file);
-
-               /* Count the highest number of columns */
-               GetScreenSize(&screenwidth, 0);
-
-               /* For counting columns of output */
-               count = 0;
-
-               /* Increase by the number of spaces behind file name */
-               longestfname += 3;
-       }
-
-       /* moved down here because if we are recursively searching and
-        * don't find any files, we don't want just to print
-        * Directory of C:\SOMEDIR
-        * with nothing else
-        * Rob Lake 06/13/98
-        */
-       if ((dwFlags & DIR_BARE) == 0)
-       {
-               ConOutPrintf (_T(" Directory of %s\n"), szPath);
-               if (IncLine (pLine, dwFlags))
-                       return 1;
-               ConOutPrintf (_T("\n"));
-               if (IncLine (pLine, dwFlags))
-                       return 1;
+               /* Calculate short name */
+               szShortName[0] = _T('\0');
+               if (lpFlags->bShortName)                
+                       _stprintf(szShortName," %-12s", ptrFiles[i]->cAlternateFileName);
+               
+               /* Format date and time */
+               DirPrintFileDateTime(szDate,szTime,ptrFiles[i],lpFlags);
+
+               /* Print the line */
+               ConOutPrintf("%10s  %-8s    %*s%s %s\n",
+                       szDate,
+                       szTime,
+                       iSizeFormat,
+                       szSize,                 
+                       szShortName,
+                       ptrFiles[i]->cFileName );
+                       
        }
-
-       do
+       return 0;
+}
+/*
+ *  DirPrintWideList
+ *
+ * The function that prints in wide list
+ */
+static int
+DirPrintWideList(LPWIN32_FIND_DATA ptrFiles[], /* [IN] Files' Info */
+                               DWORD dwCount,                                  /* [IN] The quantity of files */
+                               TCHAR * szCurPath,                              /* [IN] Full path of current directory */
+                               LPDIRSWITCHFLAGS lpFlags)               /* [IN] The flags used */
+{
+DWORD i,j;                                             /* An indexer for "for"s */
+short iScreenWidth;                            /* The screen width */
+short iColumns;                                        /* The columns (used by wide list) */
+short iLines;                                  /* The lines (used by the wide list /d) */
+int iBiggestName;                              /* The biggest name, used for wide list */
+TCHAR szTempFname[MAX_PATH];   /* Temporary string */
+
+       /* Calculate biggest name */
+       iBiggestName = 1;
+       for(i = 0;i < dwCount;i++)
        {
-               /* next file, if user doesn't want all files */
-               if (!(dwFlags & DIR_ALL) &&
-                       ((file.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
-                        (file.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)))
-                       continue;
-
-               if (dwFlags & DIR_LWR)
+               if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
-                       _tcslwr (file.cAlternateFileName);
+                       /* Directories need 2 additinal characters for brackets */
+                       if ((_tcslen(ptrFiles[i]->cFileName) + 2) > iBiggestName)
+                               iBiggestName = _tcslen(ptrFiles[i]->cFileName) + 2;
                }
-
-               if (dwFlags & DIR_WIDE && (dwFlags & DIR_BARE) == 0)
+               else
                {
-                       ULARGE_INTEGER uliSize;
-
-                       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                       {
-                               _stprintf (buffer, _T("[%s]"), file.cFileName);
-                               dircount++;
-                       }
-                       else
-                       {
-                               _stprintf (buffer, _T("%s"), file.cFileName);
-                               filecount++;
-                       }
+                       if (_tcslen(ptrFiles[i]->cFileName)  > iBiggestName)
+                               iBiggestName = _tcslen(ptrFiles[i]->cFileName);
+               }
+       }
+               
+       /* Count the highest number of columns */
+       GetScreenSize(&iScreenWidth, 0);
+       iColumns = iScreenWidth / iBiggestName;
+
+       /* Check if there is enough space for spaces between names */
+       if (((iBiggestName * iColumns) + iColumns) >= iScreenWidth)
+               iColumns --;
+       /* A last check at iColumns to avoid division by zero */
+       if (!(iColumns)) iColumns = 1;
+
+       /* Print Column sorted */
+       if (lpFlags->bWideListColSort)
+       {
+               /* Calculate the lines that will be printed */                  
+               iLines = ceil((float)dwCount/(float)iColumns);
 
-                       ConOutPrintf (_T("%*s"), - longestfname, buffer);
-                       count++;
-                       /* output as much columns as fits on the screen */
-                       if (count >= (screenwidth / longestfname))
+               for (i = 0;i < iLines;i++)
+               {
+                       for (j = 0;j < iColumns;j++)
                        {
-                               /* print the new line only if we aren't on the
-                                * last column, in this case it wraps anyway */
-                               if (count * longestfname != screenwidth)
-                                       ConOutPrintf (_T("\n"));
-                               if (IncLine (pLine, dwFlags))
-                                       return 1;
-                               count = 0;
-                       }
+                               DWORD temp = (j*iLines)+i;
+                               if (temp >= dwCount) break;
+                               if (ptrFiles[temp]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                                       _stprintf(szTempFname, "[%s]", ptrFiles[temp]->cFileName);
+                               else
+                                       _stprintf(szTempFname, "%s", ptrFiles[temp]->cFileName);
 
-                       uliSize.LowPart = file.nFileSizeLow;
-                       uliSize.HighPart = file.nFileSizeHigh;
-                       bytecount.QuadPart += uliSize.QuadPart;
+                               ConOutPrintf("%-*s",iBiggestName + 1 , szTempFname );
+                       }                               
+                       ConOutPrintf("\n");
                }
-               else if (dwFlags & DIR_BARE)
+       }
+       /* Print Line sorted */
+       else
+       {
+               for (i = 0;i < dwCount;i++)
                {
-                       ULARGE_INTEGER uliSize;
-
-                       if (_tcscmp (file.cFileName, _T(".")) == 0 ||
-                               _tcscmp (file.cFileName, _T("..")) == 0)
-                               continue;
-
-                       if (dwFlags & DIR_RECURSE)
-                       {
-                               TCHAR dir[MAX_PATH];
-
-                               _tcscpy (dir, szPath);
-                               _tcscat (dir, _T("\\"));
-                               if (dwFlags & DIR_LWR)
-                                       _tcslwr (dir);
-                               ConOutPrintf (dir);
-                       }
-
-                       ConOutPrintf (_T("%-13s\n"), file.cFileName);
-                       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                               dircount++;
+                       if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                               _stprintf(szTempFname, "[%s]", ptrFiles[i]->cFileName);
                        else
-                               filecount++;
-                       if (IncLine (pLine, dwFlags))
-                               return 1;
+                               _stprintf(szTempFname, "%s", ptrFiles[i]->cFileName);
 
-                       uliSize.LowPart = file.nFileSizeLow;
-                       uliSize.HighPart = file.nFileSizeHigh;
-                       bytecount.QuadPart += uliSize.QuadPart;
+                               ConOutPrintf("%-*s", iBiggestName + 1, szTempFname );
+                       /* We print a new line at the end of each column
+                          except for the case that it is the last item.*/
+                       if (!((i+1)%iColumns) && (i < (dwCount-1)))
+                               ConOutPrintf("\n");
+               }
+               /* Add a new line after the last item */
+               ConOutPrintf("\n");
+       }
+       return 0;
+}
+/*
+ *  DirPrintOldList
+ *
+ * The function that prints in old style
+ */
+static int
+DirPrintOldList(LPWIN32_FIND_DATA ptrFiles[],  /* [IN] Files' Info */
+                               DWORD dwCount,                                  /* [IN] The quantity of files */
+                               TCHAR * szCurPath,                              /* [IN] Full path of current directory */
+                               LPDIRSWITCHFLAGS lpFlags)               /* [IN] The flags used */
+{
+DWORD i;                                               /* An indexer for "for"s */
+TCHAR szName[10];                              /* The name of file */
+TCHAR szExt[5];                                        /* The extension of file */
+TCHAR szDate[30],szTime[30];   /* Used to format time and date */
+TCHAR szSize[30];                              /* The size of file */
+int iSizeFormat;                               /* The format of size field */
+ULARGE_INTEGER u64FileSize;            /* The file size */
+
+       for(i = 0;i < dwCount;i++)
+       {
+               /* Broke 8.3 format */
+               if (*ptrFiles[i]->cAlternateFileName )
+               {
+                       /* If the file is long named then we read the alter name */
+                       getName( ptrFiles[i]->cAlternateFileName, szName);
+                       _tcscpy(szExt, getExt( ptrFiles[i]->cAlternateFileName));
                }
                else
                {
-                       if (dwFlags & DIR_NEW)
-                       {
-                               /* print file date and time */
-                               if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
-                               {
-                                       FileTimeToSystemTime (&ft, &dt);
-                                       PrintFileDateTime (&dt, dwFlags);
-                               }
+                       /* If the file is not long name we read its original name */
+                       getName( ptrFiles[i]->cFileName, szName);
+                       _tcscpy(szExt, getExt( ptrFiles[i]->cFileName));
+               }
 
-                               /* print file size */
-                               if (file.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
-                               {
-                                       ConOutPrintf (_T("         <JUNCTION>    "));
-                                       if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                                               dircount++;
-                               }
-                               else if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                               {
-                                       ConOutPrintf (_T("         <DIR>         "));
-                                       dircount++;
-                               }
-                               else
-                               {
-                                       ULARGE_INTEGER uliSize;
+               /* Calculate size */            
+               if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)           
+               {
+                       /* Directory, no size it's a directory*/
+                       iSizeFormat = -17;
+                       _tcscpy(szSize, _T("<DIR>"));
+               }
+               else            
+               {
+                       /* File */
+                       iSizeFormat = 17;
+                       u64FileSize.HighPart = ptrFiles[i]->nFileSizeHigh;
+                       u64FileSize.LowPart = ptrFiles[i]->nFileSizeLow;
+                       ConvertULargeInteger(u64FileSize, szSize, 20, lpFlags->bTSeperator);
+               }
+               
+               /* Format date and time */
+               DirPrintFileDateTime(szDate,szTime,ptrFiles[i],lpFlags);
+
+               /* Print the line */
+               ConOutPrintf("%-8s %-3s  %*s %s  %s\n",
+                       szName,                 /* The file's 8.3 name */
+                       szExt,                  /* The file's 8.3 extension */
+                       iSizeFormat,    /* print format for size column */
+                       szSize,                 /* The size of file or "<DIR>" for dirs */
+                       szDate,                 /* The date of file/dir */
+                       szTime);                /* The time of file/dir */
+       }
+       return 0;
+}
 
-                                       uliSize.LowPart = file.nFileSizeLow;
-                                       uliSize.HighPart = file.nFileSizeHigh;
+/*
+ *  DirPrintBareList
+ *
+ * The function that prints in bare format
+ */
+static int
+DirPrintBareList(LPWIN32_FIND_DATA ptrFiles[], /* [IN] Files' Info */
+                               DWORD dwCount,                                  /* [IN] The quantity of files */
+                               TCHAR * szCurPath,                              /* [IN] Full path of current directory */
+                               LPDIRSWITCHFLAGS lpFlags)               /* [IN] The flags used */
+{
+DWORD i;                                               /* An indexer for "for"s */
+TCHAR szFullName[MAX_PATH];            /* The fullpath name of file */
+               
+       for(i = 0;i < dwCount;i++)
+       {
+               if ((_tcscmp(ptrFiles[i]->cFileName, _T(".")) == 0) ||
+                       (_tcscmp(ptrFiles[i]->cFileName, _T("..")) == 0))
+               {
+               /* at bare format we don't print "." and ".." folder */
+                       continue;
+               }
+               /* at recursive mode we print full path of file */
+               if (lpFlags->bRecursive)
+               {
+                       _tcscpy(szFullName, szCurPath);
+                       _tcscat(szFullName, ptrFiles[i]->cFileName);
+                       ConOutPrintf("%s\n", szFullName);
+               }
+               /* if we are not in recursive mode we print the file names */
+               else
+                       ConOutPrintf("%s\n",ptrFiles[i]->cFileName);    
+       }
+       return 0;
+}
 
-                                       ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
-                                       ConOutPrintf (_T("   %20s"), buffer);
+/*
+ * DirPrintFiles
+ * 
+ * The functions that prints the files list
+ */
+static int
+DirPrintFiles(LPWIN32_FIND_DATA ptrFiles[],    /* [IN] Files' Info */
+                               DWORD dwCount,                          /* [IN] The quantity of files */
+                               TCHAR * szCurPath,                      /* [IN] Full path of current directory */
+                               LPDIRSWITCHFLAGS lpFlags)       /* [IN] The flags used */
+{
+TCHAR szTemp[MAX_PATH];                        /* A buffer to format the directory header */
+
+       /* Print directory header */
+       _tcscpy(szTemp, szCurPath);
+       /* We cut the trailing \ of the full path */
+       szTemp[_tcslen(szTemp)-1] = _T('\0');
+       /* Condition to print header:
+          We are not printing in bare format
+          and if we are in recursive mode... we must have results */
+       if (!(lpFlags->bBareFormat ) && !((lpFlags->bRecursive) && (dwCount <= 0)))
+               ConOutPrintf("\n Directory of %s\n\n", szTemp);
+
+       /* Bare format */
+       if (lpFlags->bBareFormat)
+       {
+               DirPrintBareList(ptrFiles, dwCount, szCurPath, lpFlags);
+       }
+       /* New list style / Short names */
+       else if(lpFlags->bShortName)
+       {
+               DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
+       }
+       /* Wide list */
+       else if(lpFlags->bWideListColSort || lpFlags->bWideList)
+       {
+               DirPrintWideList(ptrFiles, dwCount, szCurPath, lpFlags);
+       }
+       /* New list style*/
+       else if (lpFlags->bNewLongList )
+       {
+               DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
+       }
+       /* If nothing is selected old list is the default */
+       else
+       {
+               DirPrintOldList(ptrFiles, dwCount, szCurPath, lpFlags);
+       }
+       return 0;
+}
 
-                                       bytecount.QuadPart += uliSize.QuadPart;
-                                       filecount++;
-                               }
 
-                               /* print long filename */
-                               ConOutPrintf (_T(" %s\n"), file.cFileName);
-                       }
-                       else
-                       {
-                               if (file.cFileName[0] == _T('.'))
-                                       ConOutPrintf (_T("%-13s "), file.cFileName);
-                               else if (file.cAlternateFileName[0] == _T('\0'))
-                               {
-                                       TCHAR szShortName[13];
-                                       LPTSTR ext;
 
-                                       _tcsncpy (szShortName, file.cFileName, 13);
-                                       ext = _tcschr (szShortName, _T('.'));
-                                       if (!ext)
-                                               ext = _T("");
-                                       else
-                                               *ext++ = _T('\0');
-                                       ConOutPrintf (_T("%-8s %-3s  "), szShortName, ext);
-                               }
-                               else
-                               {
-                                       LPTSTR ext;
+/*
+ * CompareFiles
+ *
+ * Compares 2 files based on the order criteria
+ */
+static int
+       CompareFiles(
+               LPWIN32_FIND_DATA lpFile1,      /* [IN] A pointer to WIN32_FIND_DATA of file 1 */
+               LPWIN32_FIND_DATA lpFile2,      /* [IN] A pointer to WIN32_FIND_DATA of file 2 */
+               LPDIRSWITCHFLAGS lpFlags)       /* [IN] The flags that we use to list */
+{
+/* u64 variables used to translate some broken 32bit info */
+ULARGE_INTEGER u64File1, u64File2;
+int i;                                                         /* An indexer for "for"s */
+long iComp;                                                    /* The comparison result */
 
-                                       ext = _tcschr (file.cAlternateFileName, _T('.'));
-                                       if (!ext)
-                                               ext = _T("");
-                                       else
-                                               *ext++ = _T('\0');
-                                       ConOutPrintf (_T("%-8s %-3s  "), file.cAlternateFileName, ext);
-                               }
+       /* Calculate critiries by order given from user */
+       for (i = 0;i < lpFlags->stOrderBy.sCriteriaCount;i++)
+       {
 
-                               /* print file size */
-                               if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-                               {
-                                       ConOutPrintf (_T("%-14s"), _T("<DIR>"));
-                                       dircount++;
-                               }
-                               else
-                               {
-                                       ULARGE_INTEGER uliSize;
-
-                                       uliSize.LowPart = file.nFileSizeLow;
-                                       uliSize.HighPart = file.nFileSizeHigh;
-                                       ConvertULargeInteger (uliSize, buffer, sizeof(buffer));
-                                       ConOutPrintf (_T("   %10s "), buffer);
-                                       bytecount.QuadPart += uliSize.QuadPart;
-                                       filecount++;
-                               }
+               /* Calculate criteria */
+               switch(lpFlags->stOrderBy.eCriteria[i])
+               {
+               case ORDER_SIZE:                /* Order by size /o:s */
+                       /* concat the 32bit integers to a 64bit */
+                       u64File1.LowPart = lpFile1->nFileSizeLow;
+                       u64File1.HighPart = lpFile1->nFileSizeHigh;
+                       u64File2.LowPart = lpFile2->nFileSizeLow;
+                       u64File2.HighPart = lpFile2->nFileSizeHigh;
+
+                       /* In case that differnce is too big for a long */
+                       if (u64File1.QuadPart < u64File2.QuadPart)
+                               iComp = -1;
+                       else if (u64File1.QuadPart > u64File2.QuadPart)
+                               iComp = 1;
+                       else
+                               iComp = 0;
+                       break;
 
-                               /* print file date and time */
-                               if (FileTimeToLocalFileTime (&file.ftLastWriteTime, &ft))
-                               {
-                                       FileTimeToSystemTime (&ft, &dt);
-                                       PrintFileDateTime (&dt, dwFlags);
-                               }
+                       break;
+               case ORDER_DIRECTORY:   /* Order by directory attribute /o:g */
+                       iComp = ((lpFile2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)-
+                               (lpFile1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
+                       break;
+               case ORDER_EXTENSION:   /* Order by extension name /o:e */
+                       iComp = _stricmp(getExt(lpFile1->cFileName),getExt(lpFile2->cFileName));
+                       break;
+               case ORDER_NAME:                /* Order by filename /o:n */
+                       iComp = _stricmp(lpFile1->cFileName, lpFile2->cFileName);
+                       break;
+               case ORDER_TIME:                /* Order by file's time /o:t */
 
-                               /* print long filename */
-                               ConOutPrintf (_T(" %s\n"), file.cFileName);
+                       /* We compare files based on the time field selected by /t */
+                       switch(lpFlags->stTimeField.eTimeField)
+                       {
+                       case TF_CREATIONDATE:
+                               /* concat the 32bit integers to a 64bit */
+                               u64File1.LowPart = lpFile1->ftCreationTime.dwLowDateTime;
+                               u64File1.HighPart = lpFile1->ftCreationTime.dwHighDateTime ;
+                               u64File2.LowPart = lpFile2->ftCreationTime.dwLowDateTime;
+                               u64File2.HighPart = lpFile2->ftCreationTime.dwHighDateTime ;
+                               break;
+                       case TF_LASTACCESSEDDATE :
+                               /* concat the 32bit integers to a 64bit */
+                               u64File1.LowPart = lpFile1->ftLastAccessTime.dwLowDateTime;
+                               u64File1.HighPart = lpFile1->ftLastAccessTime.dwHighDateTime ;
+                               u64File2.LowPart = lpFile2->ftLastAccessTime.dwLowDateTime;
+                               u64File2.HighPart = lpFile2->ftLastAccessTime.dwHighDateTime ;
+                               break;
+                       case TF_MODIFIEDDATE:
+                               /* concat the 32bit integers to a 64bit */
+                               u64File1.LowPart = lpFile1->ftLastWriteTime.dwLowDateTime;
+                               u64File1.HighPart = lpFile1->ftLastWriteTime.dwHighDateTime ;
+                               u64File2.LowPart = lpFile2->ftLastWriteTime.dwLowDateTime;
+                               u64File2.HighPart = lpFile2->ftLastWriteTime.dwHighDateTime ;
+                               break;                  
                        }
-
-                       if (IncLine (pLine, dwFlags))
-                               return 1;
+                       
+                       /* In case that differnce is too big for a long */
+                       if (u64File1.QuadPart < u64File2.QuadPart)
+                               iComp = -1;
+                       else if (u64File1.QuadPart > u64File2.QuadPart)
+                               iComp = 1;
+                       else
+                               iComp = 0;
+                       break;
                }
-       }
-       while (FindNextFile (hFile, &file));
-       FindClose (hFile);
+               /* Reverse if desired */
+               if (lpFlags->stOrderBy.bCriteriaRev[i])
+                       iComp *= -1;
 
-       /* Rob Lake, need to make clean output */
-       /* JPP 07/08/1998 added check for count != 0 */
-       if ((dwFlags & DIR_WIDE) && (count != 0))
-       {
-               ConOutPrintf (_T("\n"));
-               if (IncLine (pLine, dwFlags))
-                       return 1;
+               /* If that criteria was enough for distinguishing
+                  the files/dirs,there is no need to calculate the others*/
+               if (iComp != 0) break;          
        }
+       
+       /* Translate the value of iComp to boolean */
+       if (iComp > 0)
+               return TRUE;
+       else
+               return FALSE;
+}
 
-       if (filecount || dircount)
-       {
-               recurse_dir_cnt += dircount;
-               recurse_file_cnt += filecount;
-               recurse_bytes.QuadPart += bytecount.QuadPart;
+/*
+ * QsortFiles
+ *
+ * Sort files by the order criterias using quicksort method
+ */
+static void
+QsortFiles(
+       LPWIN32_FIND_DATA ptrArray[],   /* [IN/OUT] The array with file info pointers */
+       int i,                                                  /* [IN]     The index of first item in array */
+       int j,                                                  /* [IN]     The index to last item in array */
+       LPDIRSWITCHFLAGS lpFlags)               /* [IN]     The flags that we will use to sort */
+{
+LPWIN32_FIND_DATA lpTemp;      /* A temporary pointer */
+                                                       /* used for exchangin pointers */
+int First, Last, Temp;
+BOOL Way;
 
-               /* print_summary */
-               if (PrintSummary (szPath, filecount, dircount, bytecount, pLine, dwFlags))
-                       return 1;
-       }
-       else
+       if (i < j)
        {
-               error_file_not_found ();
-               return 1;
-       }
+               First = i, Last = j, Way = TRUE;
+               while (i != j)
+               {
+                       if (Way == CompareFiles(ptrArray[i], ptrArray[j], lpFlags))
+                       {
+                               /* Swap the pointers of the array */
+                               lpTemp = ptrArray[i];
+                               ptrArray[i]= ptrArray[j];
+                               ptrArray[j] = lpTemp;
+                               /* Swap the indexers for inverting sorting */
+                               Temp = i, i=j,j =Temp;
+                               Way = !Way;
+                       }
+                       j += (!Way - Way);                      
 
-       return 0;
+               }
+               QsortFiles(ptrArray,First, i-1, lpFlags);
+               QsortFiles(ptrArray,i+1,Last, lpFlags);
+       }
 }
 
 
+
 /*
- * _Read_Dir: Actual function that does recursive listing
+ * DirList
+ *
+ * The functions that does everything except for printing results
  */
-static INT
-DirRead (LPTSTR szPath, LPTSTR szFilespec, LPINT pLine, DWORD dwFlags)
+static INT DirList (LPTSTR szPath,                             /* [IN] The path that dir starts */
+                                        LPTSTR szFilespec,                     /* [IN] The type of file that we are looking for */
+                                        LPINT pLine,                           /* FIXME: Maybe used for paginating */
+                                        LPDIRSWITCHFLAGS lpFlags)      /* [IN] The flags of the listing */
 {
-       TCHAR szFullPath[MAX_PATH];
-       WIN32_FIND_DATA file;
-       HANDLE hFile;
 
+/* Internal linked list */
+struct TDirFindListNode
+       {
+       WIN32_FIND_DATA stFindInfo;
+       struct TDirFindListNode * ptrNext;
+};
+
+HANDLE hSearch;                                                        /* The handle of the search */
+HANDLE hRecSearch;                                             /* The handle for searching recursivly */
+WIN32_FIND_DATA wfdFileInfo;                   /* The info of file that found */
+LPWIN32_FIND_DATA * ptrFileArray;              /* An array of pointers with all the files */
+struct TDirFindListNode * ptrStartNode;        /* The pointer to the first node */
+struct TDirFindListNode * ptrNextNode; /* A pointer used for relatives refernces */
+TCHAR szFullPath[MAX_PATH];                            /* The full path that we are listing with trailing \ */
+TCHAR szFullFileSpec[MAX_PATH];                        /* The full path with file specs that we ll request\ */
+TCHAR szBytes[20];                                             /* A string for converting ULARGE integer */
+DWORD dwCount;                                                 /* A counter of files found in directory */
+DWORD dwCountFiles;                                            /* Counter for files */
+DWORD dwCountDirs;                                             /* Counter for directories */
+ULARGE_INTEGER u64CountBytes;                  /* Counter for bytes */
+ULARGE_INTEGER u64Temp;                                        /* A temporary counter */
+
+       /* Initialize Variables */
+       ptrStartNode = NULL;
+       ptrNextNode = NULL;
+       dwCount = 0;
+       dwCountFiles = 0;
+       dwCountDirs = 0;
+       u64CountBytes.QuadPart = 0;     
+
+       /* Create szFullPath and szFullFileSpec */
        _tcscpy (szFullPath, szPath);
-       if (szFullPath[_tcslen (szFullPath) - 1] != _T('\\'))
+       if (szFullPath[_tcslen(szFullPath) - 1] != _T('\\'))
                _tcscat (szFullPath, _T("\\"));
-       _tcscat (szFullPath, _T("*"));
+       _tcscpy (szFullFileSpec, szFullPath);
+       _tcscat (szFullFileSpec, szFilespec);
 
-       hFile = FindFirstFile (szFullPath, &file);
-       if (hFile == INVALID_HANDLE_VALUE)
-               return 1;
+       /* Prepare the linked list, first node is allocated */
+       if ((ptrStartNode = malloc(sizeof(struct TDirFindListNode))) == NULL)
+       {
+#ifdef _DEBUG
+               ConErrPrintf("DEBUG: Cannot allocate memmory for ptrStartNode!\n");
+#endif
+               return 1;       /* Error cannot allocate memmory for 1st object */
+       }
+       ptrNextNode = ptrStartNode;
 
+       /* Collect the results for the current folder */
+       hSearch = FindFirstFile (szFullFileSpec, &wfdFileInfo);
        do
        {
-               /* don't list "." and ".." */
-               if (_tcscmp (file.cFileName, _T(".")) == 0 ||
-                       _tcscmp (file.cFileName, _T("..")) == 0)
-                       continue;
-
-               if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+               if (hSearch != INVALID_HANDLE_VALUE)
                {
-                       _tcscpy (szFullPath, szPath);
-                       if (szFullPath[_tcslen (szFullPath) - 1] != _T('\\'))
-                               _tcscat (szFullPath, _T("\\"));
-                       _tcscat (szFullPath, file.cFileName);
-                       
-                       if (DirList (szFullPath, szFilespec, pLine, dwFlags))
-                       {
-                               FindClose (hFile);
-                               return 1;
-                       }
-                       if (DirRead (szFullPath, szFilespec, pLine, dwFlags) == 1)
+                       /* Here we filter all the specified attributes */
+                       if ((wfdFileInfo.dwFileAttributes & lpFlags->stAttribs.dwAttribMask )
+                               == (lpFlags->stAttribs.dwAttribMask & lpFlags->stAttribs.dwAttribVal ))
                        {
-                               FindClose (hFile);
-                               return 1;
+                               ptrNextNode->ptrNext = malloc(sizeof(struct TDirFindListNode));
+                               /* If malloc fails we go to next file in hope it works,
+                                  without braking the linked list! */
+                               if (ptrNextNode->ptrNext)
+                               {
+                                       /* Copy the info of search at linked list */
+                                       memcpy((void *)&ptrNextNode->ptrNext->stFindInfo,
+                                               (void *)&wfdFileInfo,sizeof(WIN32_FIND_DATA));
+                                               
+                                       /* If lower case is selected do it here */
+                                       if (lpFlags->bLowerCase)
+                                       {
+                                               _tcslwr(ptrNextNode->ptrNext->stFindInfo.cAlternateFileName);
+                                               _tcslwr(ptrNextNode->ptrNext->stFindInfo.cFileName);
+                                       }
+
+                                       /* Continue at next node at linked list */
+                                       ptrNextNode = ptrNextNode->ptrNext;
+                                       dwCount ++;
+                               
+                                       /* Grab statistics */
+                                       if (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                                       {
+                                               /* Directory */
+                                               dwCountDirs++;
+                                       }
+                                       else
+                                       {
+                                               /* File */
+                                               dwCountFiles++;                                                 
+                                               u64Temp.HighPart = wfdFileInfo.nFileSizeHigh;
+                                               u64Temp.LowPart = wfdFileInfo.nFileSizeLow;
+                                               u64CountBytes.QuadPart += u64Temp.QuadPart;
+                                       }                                               
+                               }
                        }
-               }
-       }
-       while (FindNextFile (hFile, &file));
+                       
+               }               
+       }while(FindNextFile(hSearch,&wfdFileInfo));
 
-       if (!FindClose (hFile))
-               return 1;
+       /* Terminate list */
+       ptrNextNode->ptrNext = NULL;
 
-       return 0;
-}
+       /* Calculate and allocate space need for making an array of pointers */ 
+       ptrFileArray = malloc(sizeof(LPWIN32_FIND_DATA)*dwCount);
+       if (!(ptrFileArray))
+       {
+#ifdef _DEBUG
+               ConErrPrintf("DEBUG: Cannot allocate memmory for ptrFileArray!\n");
+#endif
+               goto _DirList_clear_n_exit;
+       }
 
+       /* Create an array of pointers from the linked list
+          this will be used to sort and print data, rather than the list */
+       ptrNextNode = ptrStartNode;
+       dwCount = 0;
+       while(ptrNextNode->ptrNext)
+       {       
+               *(ptrFileArray + dwCount) = &ptrNextNode->ptrNext->stFindInfo;
+               ptrNextNode = ptrNextNode->ptrNext;
+               dwCount++;
+       }
 
-/*
- * do_recurse: Sets up for recursive directory listing
- */
-static INT
-DirRecurse (LPTSTR szPath, LPTSTR szSpec, LPINT pLine, DWORD dwFlags)
-{
-       if (!PrintDirectoryHeader (szPath, pLine, dwFlags))
-               return 1;
+       /* Sort Data if requested*/
+       if (lpFlags->stOrderBy.sCriteriaCount > 0)
+               QsortFiles(ptrFileArray, 0, dwCount-1,lpFlags);
 
-       if (DirList (szPath, szSpec, pLine, dwFlags))
-               return 1;
+       /* Print Data */
+       DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);
 
-       if ((dwFlags & DIR_BARE) == 0)
+       /* Print Directory Summary */
+       /* Condition to print summary is:
+          If we are not in bare format and if we have results! */
+       if (!(lpFlags->bBareFormat) && (dwCount > 0))
        {
-               ConOutPrintf (_T("\n"));
-               if (IncLine (pLine, dwFlags))
-                       return 1;
+               ConvertULargeInteger(u64CountBytes, szBytes, 20, lpFlags->bTSeperator);
+               ConOutPrintf(_T("%16i File(s) %14s bytes\n"),
+                       dwCountFiles, szBytes);
        }
 
-       if (DirRead (szPath, szSpec, pLine, dwFlags))
-               return 1;
-
-       if ((dwFlags & DIR_BARE) == 0)
-               ConOutPrintf (_T("Total files listed:\n"));
-
-       dwFlags &= ~DIR_RECURSE;
+       /* Add statistics to recursive statistics*/
+       recurse_dir_cnt += dwCountDirs;
+       recurse_file_cnt += dwCountFiles;
+       recurse_bytes.QuadPart += u64CountBytes.QuadPart;
 
-       if (PrintSummary (szPath, recurse_file_cnt,
-                                         recurse_dir_cnt, recurse_bytes, pLine, dwFlags))
-               return 1;
+       /* Do the recursive job if requested
+          the recursive is be done on ALL(indepent of their attribs)
+          directoried of the current one.*/
+       if (lpFlags->bRecursive)
+       {
+               /* The new search is involving any *.* file */
+               _tcscpy(szFullFileSpec, szFullPath);
+               _tcscat(szFullFileSpec, _T("*.*"));
+               hRecSearch = FindFirstFile (szFullFileSpec, &wfdFileInfo);
+               do
+               {
+                       if (hRecSearch != INVALID_HANDLE_VALUE)
+                       {
+                               /* We search for directories other than "." and ".." */
+                               if ((_stricmp(wfdFileInfo.cFileName, _T(".")) != 0)
+                                       && (_stricmp(wfdFileInfo.cFileName, _T("..")) != 0 )
+                                       && (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+                               {
+                                       /* Concat the path and the directory to do recursive */
+                                       _tcscpy(szFullFileSpec, szFullPath);
+                                       _tcscat(szFullFileSpec, wfdFileInfo.cFileName);
+                                       /* We do the same for tha folder */
+                                       DirList(szFullFileSpec, szFilespec, pLine,lpFlags);
+                               }
+                       }
+               }while(FindNextFile(hRecSearch,&wfdFileInfo));
+       }
 
-       if ((dwFlags & DIR_BARE) == 0)
+_DirList_clear_n_exit: 
+/* Deallocate memmory */
+       /* Free linked list */
+       while (ptrStartNode)
        {
-               ConOutPrintf (_T("\n"));
-               if (IncLine (pLine, dwFlags))
-                       return 1;
+               ptrNextNode = ptrStartNode->ptrNext;
+               free(ptrStartNode);
+               ptrStartNode = ptrNextNode;
+               dwCount --;
        }
+       /* Free array */
+       free(ptrFileArray);
+
+       /* Close Handles */
+       if (hSearch != INVALID_HANDLE_VALUE)
+               FindClose(hSearch);
+       if (hRecSearch != INVALID_HANDLE_VALUE)
+               FindClose(hRecSearch);
 
        return 0;
 }
 
 
+
 /*
  * dir
  *
@@ -1241,27 +1807,45 @@ DirRecurse (LPTSTR szPath, LPTSTR szSpec, LPINT pLine, DWORD dwFlags)
  */
 INT CommandDir (LPTSTR first, LPTSTR rest)
 {
-       DWORD  dwFlags = DIR_NEW | DIR_FOUR;
-       TCHAR  dircmd[256];
+       TCHAR  dircmd[256];                                                     /* A variable to store the DIRCMD enviroment variable */
        TCHAR  szPath[MAX_PATH];
        TCHAR  szFilespec[MAX_PATH];
        LPTSTR param;
        INT    nLine = 0;
+       DIRSWITCHFLAGS stFlags;
 
-
+       /* Initialize variables */
        recurse_dir_cnt = 0L;
        recurse_file_cnt = 0L;
        recurse_bytes.QuadPart = 0;
 
+       /* Initialize Switch Flags < Default switches are setted here!> */
+       stFlags.b4Digit = TRUE;
+       stFlags.bBareFormat = FALSE;
+       stFlags.bLowerCase = FALSE;
+       stFlags.bNewLongList = TRUE;
+       stFlags.bPause = FALSE;
+       stFlags.bRecursive = FALSE;
+       stFlags.bShortName = FALSE;
+       stFlags.bTSeperator = TRUE;
+       stFlags.bUser = FALSE;
+       stFlags.bWideList = FALSE;
+       stFlags.bWideListColSort = FALSE;
+       stFlags.stTimeField.eTimeField = TF_MODIFIEDDATE;
+       stFlags.stTimeField.bUnSet = FALSE;
+       stFlags.stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
+       stFlags.stAttribs.dwAttribVal = 0L;
+       stFlags.stAttribs.bUnSet = FALSE;
+       stFlags.stOrderBy.sCriteriaCount = 0;
+       stFlags.stOrderBy.bUnSet = FALSE;
+
        /* read the parameters from the DIRCMD environment variable */
-       if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
-       {
-               if (!DirReadParam (dircmd, &param, &dwFlags))
-                       return 1;
-       }
+       if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256)) 
+               if (!DirReadParam(dircmd, &param, &stFlags))
+                       return 1;       
 
        /* read the parameters */
-       if (!DirReadParam (rest, &param, &dwFlags))
+       if (!DirReadParam(rest, &param, &stFlags))
                return 1;
 
        /* default to current directory */
@@ -1272,21 +1856,44 @@ INT CommandDir (LPTSTR first, LPTSTR rest)
        if (DirParsePathspec (param, szPath, szFilespec))
                return 1;
 
-       if (dwFlags & DIR_RECURSE)
-       {
-               if (IncLine (&nLine, dwFlags))
-                       return 0;
-               if (DirRecurse (szPath, szFilespec, &nLine, dwFlags))
+/* <Debug :>
+   Uncomment this to show the final state of switch flags*/
+/*
+       ConOutPrintf("Attributes mask/value %x/%x\n",stFlags.stAttribs.dwAttribMask,stFlags.stAttribs.dwAttribVal  );
+       ConOutPrintf("(B) Bare format : %i\n", stFlags.bBareFormat );
+       ConOutPrintf("(C) Thousand : %i\n", stFlags.bTSeperator );
+       ConOutPrintf("(W) Wide list : %i\n", stFlags.bWideList );
+       ConOutPrintf("(D) Wide list sort by column : %i\n", stFlags.bWideListColSort );
+       ConOutPrintf("(L) Lowercase : %i\n", stFlags.bLowerCase );
+       ConOutPrintf("(N) New : %i\n", stFlags.bNewLongList );
+       ConOutPrintf("(O) Order : %i\n", stFlags.stOrderBy.sCriteriaCount );
+       int i;
+       for (i =0;i<stFlags.stOrderBy.sCriteriaCount;i++)
+               ConOutPrintf(" Order Criteria [%i]: %i (Reversed: %i)\n",i, stFlags.stOrderBy.eCriteria[i], stFlags.stOrderBy.bCriteriaRev[i] );
+       ConOutPrintf("(P) Pause : %i\n", stFlags.bPause  );
+       ConOutPrintf("(Q) Owner : %i\n", stFlags.bUser );
+       ConOutPrintf("(S) Recursive : %i\n", stFlags.bRecursive );
+       ConOutPrintf("(T) Time field : %i\n", stFlags.stTimeField.eTimeField );
+       ConOutPrintf("(X) Short names : %i\n", stFlags.bShortName );
+       ConOutPrintf("Parameter : %s\n", param );
+*/
+
+       /* print the header  */
+       if (!stFlags.bBareFormat)
+               if (!PrintDirectoryHeader (szPath, &nLine, &stFlags))
                        return 1;
-               return 0;
-       }
 
-       /* print the header */
-       if (!PrintDirectoryHeader (szPath, &nLine, dwFlags))
+       /* do the actual dir */
+       if (DirList (szPath, szFilespec, &nLine, &stFlags))
                return 1;
 
-       if (DirList (szPath, szFilespec, &nLine, dwFlags))
-               return 1;
+       /* print the footer */  
+       PrintSummary(szPath,
+               recurse_file_cnt,
+               recurse_dir_cnt,
+               recurse_bytes,
+               &nLine,
+               &stFlags);
 
        return 0;
 }
index d2e970a..d8991b3 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <math.h>
 
 #include "cmd.h"
 #include "config.h"