delete .cvsignore
[reactos.git] / rosapps / winfile / utils.c
1 /*
2 * ReactOS winfile
3 *
4 * utils.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 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
24 #include <windows.h>
25 #include <commctrl.h>
26 #include <stdlib.h>
27 #include <malloc.h>
28 #include <memory.h>
29 #include <tchar.h>
30 #include <process.h>
31 #include <stdio.h>
32
33 #include <windowsx.h>
34 #include <ctype.h>
35
36 #include "main.h"
37 #include "listview.h"
38 #include "utils.h"
39 #include "sort.h"
40
41
42 #define FRM_CALC_CLIENT 0xBF83
43 #define Frame_CalcFrameClient(hWnd, prt) ((BOOL)SNDMSG(hWnd, FRM_CALC_CLIENT, 0, (LPARAM)(PRECT)prt))
44
45
46 void display_error(HWND hWnd, DWORD error)
47 {
48 PTSTR msg;
49
50 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
51 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL))
52 MessageBox(hWnd, msg, _T("Winefile"), MB_OK);
53 else
54 MessageBox(hWnd, _T("Error"), _T("Winefile"), MB_OK);
55 LocalFree(msg);
56 }
57
58
59 static void read_directory_win(Entry* parent, LPCTSTR path)
60 {
61 Entry* entry = (Entry*) malloc(sizeof(Entry));
62 int level = parent->level + 1;
63 Entry* last = 0;
64 HANDLE hFind;
65 //#ifndef _NO_EXTENSIONS
66 HANDLE hFile;
67 //#endif
68
69 TCHAR buffer[MAX_PATH], *p;
70 for(p=buffer; *path; )
71 *p++ = *path++;
72
73 lstrcpy(p, _T("\\*"));
74
75 memset(entry, 0, sizeof(Entry));
76 hFind = FindFirstFile(buffer, &entry->data);
77
78 if (hFind != INVALID_HANDLE_VALUE) {
79 parent->down = entry;
80
81 do {
82 entry->down = 0;
83 entry->up = parent;
84 entry->expanded = FALSE;
85 entry->scanned = FALSE;
86 entry->level = level;
87
88 //#ifdef _NO_EXTENSIONS
89 #if 0
90 // hide directory entry "."
91 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
92 LPCTSTR name = entry->data.cFileName;
93
94 if (name[0]=='.' && name[1]=='\0')
95 continue;
96 }
97 #else
98 entry->unix_dir = FALSE;
99 entry->bhfi_valid = FALSE;
100
101 lstrcpy(p+1, entry->data.cFileName);
102
103 hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
104 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
105
106 if (hFile != INVALID_HANDLE_VALUE) {
107 if (GetFileInformationByHandle(hFile, &entry->bhfi))
108 entry->bhfi_valid = TRUE;
109
110 CloseHandle(hFile);
111 }
112 #endif
113
114 last = entry;
115
116 entry = (Entry*) malloc(sizeof(Entry));
117 memset(entry, 0, sizeof(Entry));
118
119 if (last)
120 last->next = entry;
121 } while(FindNextFile(hFind, &entry->data));
122
123 last->next = 0;
124
125 FindClose(hFind);
126 } else
127 parent->down = 0;
128
129 free(entry);
130
131 parent->scanned = TRUE;
132 }
133
134
135 void read_directory(Entry* parent, LPCTSTR path, int sortOrder)
136 {
137 TCHAR buffer[MAX_PATH];
138 Entry* entry;
139 LPCTSTR s;
140 PTSTR d;
141
142 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
143 if (parent->unix_dir)
144 {
145 read_directory_unix(parent, path);
146
147 if (Globals.prescan_node) {
148 s = path;
149 d = buffer;
150
151 while(*s)
152 *d++ = *s++;
153
154 *d++ = _T('/');
155
156 for(entry=parent->down; entry; entry=entry->next)
157 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
158 lstrcpy(d, entry->data.cFileName);
159 read_directory_unix(entry, buffer);
160 SortDirectory(entry, sortOrder);
161 }
162 }
163 }
164 else
165 #endif
166 {
167 read_directory_win(parent, path);
168
169 if (Globals.prescan_node) {
170 s = path;
171 d = buffer;
172
173 while(*s)
174 *d++ = *s++;
175
176 *d++ = _T('\\');
177
178 for(entry=parent->down; entry; entry=entry->next)
179 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
180 lstrcpy(d, entry->data.cFileName);
181 read_directory_win(entry, buffer);
182 SortDirectory(entry, sortOrder);
183 }
184 }
185 }
186
187 SortDirectory(parent, sortOrder);
188 }
189
190 // get full path of specified directory entry
191 void get_path(Entry* dir, PTSTR path)
192 {
193 Entry* entry;
194 int len = 0;
195 int level = 0;
196
197 for(entry=dir; entry; level++) {
198 LPCTSTR name = entry->data.cFileName;
199 LPCTSTR s = name;
200 int l;
201
202 for(l=0; *s && *s!=_T('/') && *s!=_T('\\'); s++)
203 l++;
204
205 if (entry->up) {
206 memmove(path+l+1, path, len*sizeof(TCHAR));
207 memcpy(path+1, name, l*sizeof(TCHAR));
208 len += l+1;
209
210 #ifndef _NO_EXTENSIONS
211 if (entry->unix_dir)
212 path[0] = _T('/');
213 else
214 #endif
215 path[0] = _T('\\');
216
217 entry = entry->up;
218 } else {
219 memmove(path+l, path, len*sizeof(TCHAR));
220 memcpy(path, name, l*sizeof(TCHAR));
221 len += l;
222 break;
223 }
224 }
225
226 if (!level) {
227 #ifndef _NO_EXTENSIONS
228 if (entry->unix_dir)
229 path[len++] = _T('/');
230 else
231 #endif
232 path[len++] = _T('\\');
233 }
234
235 path[len] = _T('\0');
236 }
237
238
239 #ifndef _NO_EXTENSIONS
240
241 void frame_get_clientspace(HWND hWnd, PRECT prect)
242 {
243 RECT rt;
244
245 if (!IsIconic(hWnd))
246 GetClientRect(hWnd, prect);
247 else {
248 WINDOWPLACEMENT wp;
249 GetWindowPlacement(hWnd, &wp);
250 prect->left = prect->top = 0;
251 prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left-
252 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE));
253 prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top-
254 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))-
255 GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE);
256 }
257 if (IsWindowVisible(Globals.hToolBar)) {
258 GetClientRect(Globals.hToolBar, &rt);
259 prect->top += rt.bottom+2;
260 }
261 if (IsWindowVisible(Globals.hDriveBar)) {
262 GetClientRect(Globals.hDriveBar, &rt);
263 prect->top += rt.bottom+2;
264 }
265 if (IsWindowVisible(Globals.hStatusBar)) {
266 GetClientRect(Globals.hStatusBar, &rt);
267 prect->bottom -= rt.bottom;
268 }
269 }
270
271
272 #endif
273
274
275 int is_exe_file(LPCTSTR ext)
276 {
277 const static LPCTSTR executable_extensions[] = {
278 _T("COM"),
279 _T("EXE"),
280 _T("BAT"),
281 _T("CMD"),
282 #ifndef _NO_EXTENSIONS
283 _T("CMM"),
284 _T("BTM"),
285 _T("AWK"),
286 #endif
287 0
288 };
289 TCHAR ext_buffer[_MAX_EXT];
290 const LPCTSTR* p;
291 LPCTSTR s;
292 LPTSTR d;
293
294 for (s = ext + 1, d = ext_buffer; (*d = tolower(*s)); s++)
295 d++;
296 for (p = executable_extensions; *p; p++)
297 if (!_tcscmp(ext_buffer, *p))
298 return 1;
299 return 0;
300 }
301
302 int is_registered_type(LPCTSTR ext)
303 {
304 //TODO
305
306 return 1;
307 }
308
309 void set_curdir(ChildWnd* child, Entry* entry)
310 {
311 TCHAR path[MAX_PATH];
312
313 // child->left.cur = entry;
314 // child->right.root = entry;
315 // child->right.cur = entry;
316
317 if (!entry->scanned)
318 scan_entry(child, entry);
319 else {
320 // ListBox_ResetContent(child->hListWnd);
321 // insert_entries(&child->right, entry->down, -1);
322
323 // RefreshList(child->hListWnd, entry);
324
325 // calc_widths(&child->right, FALSE);
326 //#ifndef _NO_EXTENSIONS
327 // set_header(&child->right);
328 //#endif
329 }
330 RefreshList(child->hListWnd, entry->down);
331
332 get_path(entry, path);
333 lstrcpy(child->szPath, path);
334 SetWindowText(child->hWnd, path);
335 SetCurrentDirectory(path);
336 }
337
338
339 // calculate prefered width for all visible columns
340 BOOL calc_widths(Pane* pane, BOOL anyway)
341 {
342 int col, x, cx, spc=3*Globals.spaceSize.cx;
343 int entries = ListBox_GetCount(pane->hWnd);
344 int orgWidths[COLUMNS];
345 int orgPositions[COLUMNS+1];
346 HFONT hfontOld;
347 HDC hdc;
348 int cnt;
349
350 if (!anyway) {
351 memcpy(orgWidths, pane->widths, sizeof(orgWidths));
352 memcpy(orgPositions, pane->positions, sizeof(orgPositions));
353 }
354
355 for (col = 0; col < COLUMNS; col++)
356 pane->widths[col] = 0;
357
358 hdc = GetDC(pane->hWnd);
359 hfontOld = SelectFont(hdc, Globals.hFont);
360
361 for (cnt = 0; cnt < entries; cnt++) {
362 #if 0
363 Entry* entry = (Entry*) ListBox_GetItemData(pane->hWnd, cnt);
364 DRAWITEMSTRUCT dis = {0/*CtlType*/, 0/*CtlID*/,
365 0/*itemID*/, 0/*itemAction*/, 0/*itemState*/,
366 pane->hWnd/*hwndItem*/, hdc};
367 draw_item(pane, &dis, entry, COLUMNS);
368 #endif
369 }
370 SelectObject(hdc, hfontOld);
371 ReleaseDC(pane->hWnd, hdc);
372
373 x = 0;
374 for ( col = 0; col < COLUMNS; col++) {
375 pane->positions[col] = x;
376 cx = pane->widths[col];
377 if (cx) {
378 cx += spc;
379 if (cx < IMAGE_WIDTH)
380 cx = IMAGE_WIDTH;
381 pane->widths[col] = cx;
382 }
383 x += cx;
384 }
385 pane->positions[COLUMNS] = x;
386 ListBox_SetHorizontalExtent(pane->hWnd, x);
387
388 // no change?
389 if (!memcmp(orgWidths, pane->widths, sizeof(orgWidths)))
390 return FALSE;
391
392 // don't move, if only collapsing an entry
393 if (!anyway && pane->widths[0]<orgWidths[0] &&
394 !memcmp(orgWidths+1, pane->widths+1, sizeof(orgWidths)-sizeof(int))) {
395 pane->widths[0] = orgWidths[0];
396 memcpy(pane->positions, orgPositions, sizeof(orgPositions));
397
398 return FALSE;
399 }
400 InvalidateRect(pane->hWnd, 0, TRUE);
401 return TRUE;
402 }
403
404
405 // calculate one prefered column width
406
407 void calc_single_width(Pane* pane, int col)
408 {
409 HFONT hfontOld;
410 int x, cx;
411 int entries = ListBox_GetCount(pane->hWnd);
412 int cnt;
413 HDC hdc;
414
415 pane->widths[col] = 0;
416 hdc = GetDC(pane->hWnd);
417 hfontOld = SelectFont(hdc, Globals.hFont);
418 for (cnt = 0; cnt < entries; cnt++) {
419 #if 0
420 Entry* entry = (Entry*) ListBox_GetItemData(pane->hWnd, cnt);
421 DRAWITEMSTRUCT dis = {0, 0, 0, 0, 0, pane->hWnd, hdc};
422 draw_item(pane, &dis, entry, col);
423 #endif
424 }
425 SelectObject(hdc, hfontOld);
426 ReleaseDC(pane->hWnd, hdc);
427 cx = pane->widths[col];
428 if (cx) {
429 cx += 3*Globals.spaceSize.cx;
430 if (cx < IMAGE_WIDTH)
431 cx = IMAGE_WIDTH;
432 }
433 pane->widths[col] = cx;
434 x = pane->positions[col] + cx;
435 for(; col<COLUMNS; ) {
436 pane->positions[++col] = x;
437 x += pane->widths[col];
438 }
439 ListBox_SetHorizontalExtent(pane->hWnd, x);
440 }
441
442
443 #ifndef _NO_EXTENSIONS
444
445 static struct FullScreenParameters {
446 BOOL mode;
447 RECT orgPos;
448 BOOL wasZoomed;
449 } g_fullscreen = {
450 FALSE // mode
451 };
452
453 BOOL toggle_fullscreen(HWND hWnd)
454 {
455 RECT rt;
456
457 if ((g_fullscreen.mode=!g_fullscreen.mode)) {
458 GetWindowRect(hWnd, &g_fullscreen.orgPos);
459 g_fullscreen.wasZoomed = IsZoomed(hWnd);
460
461 Frame_CalcFrameClient(hWnd, &rt);
462 ClientToScreen(hWnd, (LPPOINT)&rt.left);
463 ClientToScreen(hWnd, (LPPOINT)&rt.right);
464
465 rt.left = g_fullscreen.orgPos.left-rt.left;
466 rt.top = g_fullscreen.orgPos.top-rt.top;
467 rt.right = GetSystemMetrics(SM_CXSCREEN)+g_fullscreen.orgPos.right-rt.right;
468 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+g_fullscreen.orgPos.bottom-rt.bottom;
469
470 MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
471 } else {
472 MoveWindow(hWnd, g_fullscreen.orgPos.left, g_fullscreen.orgPos.top,
473 g_fullscreen.orgPos.right-g_fullscreen.orgPos.left,
474 g_fullscreen.orgPos.bottom-g_fullscreen.orgPos.top, TRUE);
475
476 if (g_fullscreen.wasZoomed)
477 ShowWindow(hWnd, WS_MAXIMIZE);
478 }
479
480 return g_fullscreen.mode;
481 }
482
483 void fullscreen_move(HWND hWnd)
484 {
485 RECT rt, pos;
486 GetWindowRect(hWnd, &pos);
487
488 Frame_CalcFrameClient(hWnd, &rt);
489 ClientToScreen(hWnd, (LPPOINT)&rt.left);
490 ClientToScreen(hWnd, (LPPOINT)&rt.right);
491
492 rt.left = pos.left-rt.left;
493 rt.top = pos.top-rt.top;
494 rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right;
495 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom;
496
497 MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
498 }
499
500 #endif