eb69df50273ca17ddf416ca9f634e57178e1ac6a
[reactos.git] / rosapps / winfile / sort.c
1 /*
2 * ReactOS winfile
3 *
4 * sort.c
5 *
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #ifdef _MSC_VER
24 #include "stdafx.h"
25 #else
26 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <stdlib.h>
30 #include <malloc.h>
31 #include <memory.h>
32 #include <tchar.h>
33 #include <process.h>
34 #include <stdio.h>
35 #endif
36
37 #include <shellapi.h>
38 //#include <winspool.h>
39 #include <windowsx.h>
40 #include <shellapi.h>
41 #include <ctype.h>
42 #include <assert.h>
43 #define ASSERT assert
44
45 #include "main.h"
46 #include "sort.h"
47
48
49
50 // directories first...
51 static int compareType(const WIN32_FIND_DATA* fd1, const WIN32_FIND_DATA* fd2)
52 {
53 int dir1 = fd1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
54 int dir2 = fd2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
55
56 return dir2==dir1? 0: dir2<dir1? -1: 1;
57 }
58
59
60 static int compareName(const void* arg1, const void* arg2)
61 {
62 const WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
63 const WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
64
65 int cmp = compareType(fd1, fd2);
66 if (cmp)
67 return cmp;
68
69 return lstrcmpi(fd1->cFileName, fd2->cFileName);
70 }
71
72 static int compareExt(const void* arg1, const void* arg2)
73 {
74 const WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
75 const WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
76 const TCHAR *name1, *name2, *ext1, *ext2;
77
78 int cmp = compareType(fd1, fd2);
79 if (cmp)
80 return cmp;
81
82 name1 = fd1->cFileName;
83 name2 = fd2->cFileName;
84
85 ext1 = _tcsrchr(name1, _T('.'));
86 ext2 = _tcsrchr(name2, _T('.'));
87
88 if (ext1)
89 ext1++;
90 else
91 ext1 = _T("");
92
93 if (ext2)
94 ext2++;
95 else
96 ext2 = _T("");
97
98 cmp = lstrcmpi(ext1, ext2);
99 if (cmp)
100 return cmp;
101
102 return lstrcmpi(name1, name2);
103 }
104
105 static int compareSize(const void* arg1, const void* arg2)
106 {
107 WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
108 WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
109
110 int cmp = compareType(fd1, fd2);
111 if (cmp)
112 return cmp;
113
114 cmp = fd2->nFileSizeHigh - fd1->nFileSizeHigh;
115
116 if (cmp < 0)
117 return -1;
118 else if (cmp > 0)
119 return 1;
120
121 cmp = fd2->nFileSizeLow - fd1->nFileSizeLow;
122
123 return cmp<0? -1: cmp>0? 1: 0;
124 }
125
126 static int compareDate(const void* arg1, const void* arg2)
127 {
128 WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
129 WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
130
131 int cmp = compareType(fd1, fd2);
132 if (cmp)
133 return cmp;
134
135 return CompareFileTime(&fd2->ftLastWriteTime, &fd1->ftLastWriteTime);
136 }
137
138
139 static int (*sortFunctions[])(const void* arg1, const void* arg2) = {
140 compareName, // SORT_NAME
141 compareExt, // SORT_EXT
142 compareSize, // SORT_SIZE
143 compareDate // SORT_DATE
144 };
145
146
147 void SortDirectory(Entry* parent, SORT_ORDER sortOrder)
148 {
149 Entry* entry = parent->down;
150 Entry** array, **p;
151 int len;
152
153 len = 0;
154 for(entry=parent->down; entry; entry=entry->next)
155 len++;
156
157 if (len) {
158 #ifdef _MSC_VER
159 array = (Entry**) alloca(len*sizeof(Entry*));
160 #else
161 array = (Entry**) malloc(len*sizeof(Entry*));
162 #endif
163 memset(array, 0, len*sizeof(Entry*));
164 p = array;
165 for(entry=parent->down; entry; entry=entry->next)
166 *p++ = entry;
167
168 // call qsort with the appropriate compare function
169 qsort(array, len, sizeof(array[0]), sortFunctions[sortOrder]);
170
171 parent->down = array[0];
172
173 for(p=array; --len; p++)
174 p[0]->next = p[1];
175
176 (*p)->next = 0;
177 }
178 }
179
180