276c0b6491d2c06e9e15f51dc79aa9f4c1b5f9d0
[reactos.git] / rosapps / winfile / entries.c
1 /*
2 * ReactOS winfile
3 *
4 * entries.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 <windowsx.h>
38
39 #include "winfile.h"
40 #include "entries.h"
41 #include "utils.h"
42
43
44
45 Entry* find_entry_win(Entry* parent, LPCTSTR name)
46 {
47 Entry* entry;
48
49 for(entry=parent->down; entry; entry=entry->next) {
50 LPCTSTR p = name;
51 LPCTSTR q = entry->data.cFileName;
52
53 do {
54 if (!*p || *p==_T('\\') || *p==_T('/'))
55 return entry;
56 } while(tolower(*p++) == tolower(*q++));
57
58 p = name;
59 q = entry->data.cAlternateFileName;
60
61 do {
62 if (!*p || *p==_T('\\') || *p==_T('/'))
63 return entry;
64 } while(tolower(*p++) == tolower(*q++));
65 }
66
67 return 0;
68 }
69
70
71 Entry* read_tree_win(Root* root, LPCTSTR path, int sortOrder)
72 {
73 TCHAR buffer[MAX_PATH];
74 Entry* entry = &root->entry;
75 LPCTSTR s = path;
76 PTSTR d = buffer;
77
78 #ifndef _NO_EXTENSIONS
79 entry->unix_dir = FALSE;
80 #endif
81
82 while(entry) {
83 while(*s && *s!=_T('\\') && *s!=_T('/'))
84 *d++ = *s++;
85
86 while(*s==_T('\\') || *s==_T('/'))
87 s++;
88
89 *d++ = _T('\\');
90 *d = _T('\0');
91
92 read_directory(entry, buffer, sortOrder);
93
94 if (entry->down)
95 entry->expanded = TRUE;
96
97 if (!*s)
98 break;
99
100 entry = find_entry_win(entry, s);
101 }
102
103 return entry;
104 }
105
106
107 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
108
109 static Entry* find_entry_unix(Entry* parent, LPCTSTR name)
110 {
111 Entry* entry;
112
113 for(entry=parent->down; entry; entry=entry->next) {
114 LPCTSTR p = name;
115 LPCTSTR q = entry->data.cFileName;
116
117 do {
118 if (!*p || *p==_T('/'))
119 return entry;
120 } while(*p++ == *q++);
121 }
122
123 return 0;
124 }
125
126 static Entry* read_tree_unix(Root* root, LPCTSTR path, int sortOrder)
127 {
128 TCHAR buffer[MAX_PATH];
129 Entry* entry = &root->entry;
130 LPCTSTR s = path;
131 PTSTR d = buffer;
132
133 entry->unix_dir = TRUE;
134
135 while(entry) {
136 while(*s && *s!=_T('/'))
137 *d++ = *s++;
138
139 while(*s == _T('/'))
140 s++;
141
142 *d++ = _T('/');
143 *d = _T('\0');
144
145 read_directory(entry, buffer, sortOrder);
146
147 if (entry->down)
148 entry->expanded = TRUE;
149
150 if (!*s)
151 break;
152
153 entry = find_entry_unix(entry, s);
154 }
155
156 return entry;
157 }
158
159 #endif
160
161
162 // recursively free all child entries
163 void free_entries(Entry* parent)
164 {
165 Entry *entry, *next=parent->down;
166
167 if (next) {
168 parent->down = 0;
169
170 do {
171 entry = next;
172 next = entry->next;
173
174 free_entries(entry);
175 free(entry);
176 } while(next);
177 }
178 }
179
180
181
182 // insert listbox entries after index idx
183 void insert_entries(Pane* pane, Entry* parent, int idx)
184 {
185 Entry* entry = parent;
186
187 if (!entry)
188 return;
189
190 ShowWindow(pane->hwnd, SW_HIDE);
191
192 for(; entry; entry=entry->next) {
193 #ifndef _LEFT_FILES
194 if (pane->treePane && !(entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
195 continue;
196 #endif
197
198 // don't display entries "." and ".." in the left pane
199 if (pane->treePane && (entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
200 && entry->data.cFileName[0]==_T('.'))
201 if (
202 #ifndef _NO_EXTENSIONS
203 entry->data.cFileName[1]==_T('\0') ||
204 #endif
205 (entry->data.cFileName[1]==_T('.') && entry->data.cFileName[2]==_T('\0')))
206 continue;
207
208 if (idx != -1)
209 idx++;
210
211 ListBox_InsertItemData(pane->hwnd, idx, entry);
212
213 if (pane->treePane && entry->expanded)
214 insert_entries(pane, entry->down, idx);
215 }
216
217 ShowWindow(pane->hwnd, SW_SHOW);
218 }
219
220
221 void scan_entry(ChildWnd* child, Entry* entry)
222 {
223 TCHAR path[MAX_PATH];
224 int idx = ListBox_GetCurSel(child->left.hwnd);
225 HCURSOR crsrOld = SetCursor(LoadCursor(0, IDC_WAIT));
226
227 // delete sub entries in left pane
228 for(;;) {
229 LRESULT res = ListBox_GetItemData(child->left.hwnd, idx+1);
230 Entry* sub = (Entry*) res;
231
232 if (res==LB_ERR || !sub || sub->level<=entry->level)
233 break;
234
235 ListBox_DeleteString(child->left.hwnd, idx+1);
236 }
237
238 // empty right pane
239 ListBox_ResetContent(child->right.hwnd);
240
241 // release memory
242 free_entries(entry);
243
244 // read contents from disk
245 get_path(entry, path);
246 read_directory(entry, path, child->sortOrder);
247
248 // insert found entries in right pane
249 insert_entries(&child->right, entry->down, -1);
250 calc_widths(&child->right, FALSE);
251 #ifndef _NO_EXTENSIONS
252 set_header(&child->right);
253 #endif
254
255 child->header_wdths_ok = FALSE;
256
257 SetCursor(crsrOld);
258 }
259
260
261 // expand a directory entry
262 BOOL expand_entry(ChildWnd* child, Entry* dir)
263 {
264 int idx;
265 Entry* p;
266
267 if (!dir || dir->expanded || !dir->down)
268 return FALSE;
269
270 p = dir->down;
271
272 if (p->data.cFileName[0]=='.' && p->data.cFileName[1]=='\0' && p->next) {
273 p = p->next;
274
275 if (p->data.cFileName[0]=='.' && p->data.cFileName[1]=='.' &&
276 p->data.cFileName[2]=='\0' && p->next)
277 p = p->next;
278 }
279
280 // no subdirectories ?
281 if (!(p->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
282 return FALSE;
283
284 idx = ListBox_FindItemData(child->left.hwnd, 0, dir);
285
286 dir->expanded = TRUE;
287
288 // insert entries in left pane
289 insert_entries(&child->left, p, idx);
290
291 if (!child->header_wdths_ok) {
292 if (calc_widths(&child->left, FALSE)) {
293 #ifndef _NO_EXTENSIONS
294 set_header(&child->left);
295 #endif
296
297 child->header_wdths_ok = TRUE;
298 }
299 }
300
301 return TRUE;
302 }
303
304
305 void collapse_entry(Pane* pane, Entry* dir)
306 {
307 int idx = ListBox_FindItemData(pane->hwnd, 0, dir);
308
309 ShowWindow(pane->hwnd, SW_HIDE);
310
311 // hide sub entries
312 for(;;) {
313 LRESULT res = ListBox_GetItemData(pane->hwnd, idx+1);
314 Entry* sub = (Entry*) res;
315
316 if (res==LB_ERR || !sub || sub->level<=dir->level)
317 break;
318
319 ListBox_DeleteString(pane->hwnd, idx+1);
320 }
321
322 dir->expanded = FALSE;
323
324 ShowWindow(pane->hwnd, SW_SHOW);
325 }
326
327
328 void activate_entry(ChildWnd* child, Pane* pane)
329 {
330 Entry* entry = pane->cur;
331
332 if (!entry)
333 return;
334
335 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
336 int scanned_old = entry->scanned;
337
338 if (!scanned_old)
339 scan_entry(child, entry);
340
341 #ifndef _NO_EXTENSIONS
342 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='\0')
343 return;
344 #endif
345
346 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='.' && entry->data.cFileName[2]=='\0') {
347 entry = child->left.cur->up;
348 collapse_entry(&child->left, entry);
349 goto focus_entry;
350 } else if (entry->expanded)
351 collapse_entry(pane, child->left.cur);
352 else {
353 expand_entry(child, child->left.cur);
354
355 if (!pane->treePane) focus_entry: {
356 int idx = ListBox_FindItemData(child->left.hwnd, ListBox_GetCurSel(child->left.hwnd), entry);
357 ListBox_SetCurSel(child->left.hwnd, idx);
358 set_curdir(child, entry);
359 }
360 }
361
362 if (!scanned_old) {
363 calc_widths(pane, FALSE);
364
365 #ifndef _NO_EXTENSIONS
366 set_header(pane);
367 #endif
368 }
369 } else {
370
371 //TODO: start program, open document...
372
373 }
374 }