- actually use PLUID
[wine/testsucceed.git] / programs / winefile / winefile.c
blob6bec3932b88c9cb52c52542dba338384fa71abda
1 /*
2 * Winefile
4 * Copyright 2000 Martin Fuchs
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #ifndef _WIN32
22 #include "config.h"
23 #include "wine/port.h"
24 #endif
26 #include "winefile.h"
27 #include "resource.h"
30 /* for read_directory_unix() */
31 #if !defined(_NO_EXTENSIONS) && !defined(_WIN32)
32 #include <dirent.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <time.h>
36 #endif
38 #ifdef _NO_EXTENSIONS
39 #undef _LEFT_FILES
40 #endif
42 #ifndef _MAX_PATH
43 #define _MAX_DRIVE 3
44 #define _MAX_FNAME 256
45 #define _MAX_DIR _MAX_FNAME
46 #define _MAX_EXT _MAX_FNAME
47 #define _MAX_PATH 260
48 #endif
50 WINEFILE_GLOBALS Globals;
52 extern void WineLicense(HWND hWnd);
53 extern void WineWarranty(HWND hWnd);
55 typedef struct _Entry {
56 struct _Entry* next;
57 struct _Entry* down;
58 struct _Entry* up;
60 BOOL expanded;
61 BOOL scanned;
62 int level;
64 WIN32_FIND_DATA data;
66 #ifndef _NO_EXTENSIONS
67 BY_HANDLE_FILE_INFORMATION bhfi;
68 BOOL bhfi_valid;
69 BOOL unix_dir;
70 #endif
71 } Entry;
73 typedef struct {
74 Entry entry;
75 TCHAR path[MAX_PATH];
76 TCHAR volname[_MAX_FNAME];
77 TCHAR fs[_MAX_DIR];
78 DWORD drive_type;
79 DWORD fs_flags;
80 } Root;
82 enum COLUMN_FLAGS {
83 COL_SIZE = 0x01,
84 COL_DATE = 0x02,
85 COL_TIME = 0x04,
86 COL_ATTRIBUTES = 0x08,
87 COL_DOSNAMES = 0x10,
88 #ifdef _NO_EXTENSIONS
89 COL_ALL = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_DOSNAMES
90 #else
91 COL_INDEX = 0x20,
92 COL_LINKS = 0x40,
93 COL_ALL = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_DOSNAMES|COL_INDEX|COL_LINKS
94 #endif
97 typedef enum {
98 SORT_NAME,
99 SORT_EXT,
100 SORT_SIZE,
101 SORT_DATE
102 } SORT_ORDER;
104 typedef struct {
105 HWND hwnd;
106 #ifndef _NO_EXTENSIONS
107 HWND hwndHeader;
108 #endif
110 #ifndef _NO_EXTENSIONS
111 #define COLUMNS 10
112 #else
113 #define COLUMNS 5
114 #endif
115 int widths[COLUMNS];
116 int positions[COLUMNS+1];
118 BOOL treePane;
119 int visible_cols;
120 Entry* root;
121 Entry* cur;
122 } Pane;
124 typedef struct {
125 HWND hwnd;
126 Pane left;
127 Pane right;
128 int focus_pane; /* 0: left 1: right */
129 WINDOWPLACEMENT pos;
130 int split_pos;
131 BOOL header_wdths_ok;
133 TCHAR path[MAX_PATH];
134 Root root;
136 SORT_ORDER sortOrder;
137 } ChildWnd;
140 static void read_directory(Entry* parent, LPCTSTR path, int sortOrder);
141 static void set_curdir(ChildWnd* child, Entry* entry);
143 LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
144 LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
145 LRESULT CALLBACK TreeWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
148 static void display_error(HWND hwnd, DWORD error)
150 PTSTR msg;
152 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
153 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL))
154 MessageBox(hwnd, msg, _T("Winefile"), MB_OK);
155 else
156 MessageBox(hwnd, _T("Error"), _T("Winefile"), MB_OK);
158 LocalFree(msg);
162 static void read_directory_win(Entry* parent, LPCTSTR path)
164 Entry* entry = (Entry*) malloc(sizeof(Entry));
165 int level = parent->level + 1;
166 Entry* last = 0;
167 HANDLE hFind;
168 #ifndef _NO_EXTENSIONS
169 HANDLE hFile;
170 #endif
172 TCHAR buffer[MAX_PATH], *p;
173 for(p=buffer; *path; )
174 *p++ = *path++;
176 lstrcpy(p, _T("\\*"));
178 hFind = FindFirstFile(buffer, &entry->data);
180 if (hFind != INVALID_HANDLE_VALUE) {
181 parent->down = entry;
183 do {
184 entry->down = 0;
185 entry->up = parent;
186 entry->expanded = FALSE;
187 entry->scanned = FALSE;
188 entry->level = level;
190 #ifdef _NO_EXTENSIONS
191 /* hide directory entry "." */
192 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
193 LPCTSTR name = entry->data.cFileName;
195 if (name[0]=='.' && name[1]=='\0')
196 continue;
198 #else
199 entry->unix_dir = FALSE;
200 entry->bhfi_valid = FALSE;
202 lstrcpy(p+1, entry->data.cFileName);
204 hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
205 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
207 if (hFile != INVALID_HANDLE_VALUE) {
208 if (GetFileInformationByHandle(hFile, &entry->bhfi))
209 entry->bhfi_valid = TRUE;
211 CloseHandle(hFile);
213 #endif
215 last = entry;
217 entry = (Entry*) malloc(sizeof(Entry));
219 if (last)
220 last->next = entry;
221 } while(FindNextFile(hFind, &entry->data));
223 last->next = 0;
225 FindClose(hFind);
226 } else
227 parent->down = 0;
229 free(entry);
231 parent->scanned = TRUE;
235 static Entry* find_entry_win(Entry* parent, LPCTSTR name)
237 Entry* entry;
239 for(entry=parent->down; entry; entry=entry->next) {
240 LPCTSTR p = name;
241 LPCTSTR q = entry->data.cFileName;
243 do {
244 if (!*p || *p==_T('\\') || *p==_T('/'))
245 return entry;
246 } while(tolower(*p++) == tolower(*q++));
248 p = name;
249 q = entry->data.cAlternateFileName;
251 do {
252 if (!*p || *p==_T('\\') || *p==_T('/'))
253 return entry;
254 } while(tolower(*p++) == tolower(*q++));
257 return 0;
261 static Entry* read_tree_win(Root* root, LPCTSTR path, int sortOrder)
263 TCHAR buffer[MAX_PATH];
264 Entry* entry = &root->entry;
265 LPCTSTR s = path;
266 PTSTR d = buffer;
268 #ifndef _NO_EXTENSIONS
269 entry->unix_dir = FALSE;
270 #endif
272 while(entry) {
273 while(*s && *s!=_T('\\') && *s!=_T('/'))
274 *d++ = *s++;
276 while(*s==_T('\\') || *s==_T('/'))
277 s++;
279 *d++ = _T('\\');
280 *d = _T('\0');
282 read_directory(entry, buffer, sortOrder);
284 if (entry->down)
285 entry->expanded = TRUE;
287 if (!*s)
288 break;
290 entry = find_entry_win(entry, s);
293 return entry;
297 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
299 BOOL to_filetime(const time_t* t, FILETIME* ftime)
301 struct tm* tm = gmtime(t);
302 SYSTEMTIME stime;
304 if (!tm)
305 return FALSE;
307 stime.wYear = tm->tm_year+1900;
308 stime.wMonth = tm->tm_mon+1;
309 /* stime.wDayOfWeek */
310 stime.wDay = tm->tm_mday;
311 stime.wHour = tm->tm_hour;
312 stime.wMinute = tm->tm_min;
313 stime.wSecond = tm->tm_sec;
315 return SystemTimeToFileTime(&stime, ftime);
318 static void read_directory_unix(Entry* parent, LPCTSTR path)
320 Entry* entry = (Entry*) malloc(sizeof(Entry));
321 int level = parent->level + 1;
322 Entry* last = 0;
324 DIR* dir = opendir(path);
326 if (dir) {
327 struct stat st;
328 struct dirent* ent;
329 TCHAR buffer[MAX_PATH], *p;
331 for(p=buffer; *path; )
332 *p++ = *path++;
334 if (p==buffer || p[-1]!='/')
335 *p++ = '/';
337 parent->down = entry;
339 while((ent=readdir(dir))) {
340 entry->unix_dir = TRUE;
341 lstrcpy(entry->data.cFileName, ent->d_name);
342 entry->data.dwFileAttributes = ent->d_name[0]=='.'? FILE_ATTRIBUTE_HIDDEN: 0;
344 strcpy(p, ent->d_name);
346 if (!stat(buffer, &st)) {
347 if (S_ISDIR(st.st_mode))
348 entry->data.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
350 entry->data.nFileSizeLow = st.st_size & 0xFFFFFFFF;
351 entry->data.nFileSizeHigh = st.st_size >> 32;
353 memset(&entry->data.ftCreationTime, 0, sizeof(FILETIME));
354 to_filetime(&st.st_atime, &entry->data.ftLastAccessTime);
355 to_filetime(&st.st_mtime, &entry->data.ftLastWriteTime);
357 entry->bhfi.nFileIndexLow = ent->d_ino;
358 entry->bhfi.nFileIndexHigh = 0;
360 entry->bhfi.nNumberOfLinks = st.st_nlink;
362 entry->bhfi_valid = TRUE;
363 } else {
364 entry->data.nFileSizeLow = 0;
365 entry->data.nFileSizeHigh = 0;
366 entry->bhfi_valid = FALSE;
369 entry->down = 0;
370 entry->up = parent;
371 entry->expanded = FALSE;
372 entry->scanned = FALSE;
373 entry->level = level;
375 last = entry;
377 entry = (Entry*) malloc(sizeof(Entry));
379 if (last)
380 last->next = entry;
383 last->next = 0;
385 closedir(dir);
386 } else
387 parent->down = 0;
389 free(entry);
391 parent->scanned = TRUE;
394 static Entry* find_entry_unix(Entry* parent, LPCTSTR name)
396 Entry* entry;
398 for(entry=parent->down; entry; entry=entry->next) {
399 LPCTSTR p = name;
400 LPCTSTR q = entry->data.cFileName;
402 do {
403 if (!*p || *p==_T('/'))
404 return entry;
405 } while(*p++ == *q++);
408 return 0;
411 static Entry* read_tree_unix(Root* root, LPCTSTR path, int sortOrder)
413 TCHAR buffer[MAX_PATH];
414 Entry* entry = &root->entry;
415 LPCTSTR s = path;
416 PTSTR d = buffer;
418 entry->unix_dir = TRUE;
420 while(entry) {
421 while(*s && *s!=_T('/'))
422 *d++ = *s++;
424 while(*s == _T('/'))
425 s++;
427 *d++ = _T('/');
428 *d = _T('\0');
430 read_directory(entry, buffer, sortOrder);
432 if (entry->down)
433 entry->expanded = TRUE;
435 if (!*s)
436 break;
438 entry = find_entry_unix(entry, s);
441 return entry;
444 #endif
447 /* directories first... */
448 static int compareType(const WIN32_FIND_DATA* fd1, const WIN32_FIND_DATA* fd2)
450 int dir1 = fd1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
451 int dir2 = fd2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
453 return dir2==dir1? 0: dir2<dir1? -1: 1;
457 static int compareName(const void* arg1, const void* arg2)
459 const WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
460 const WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
462 int cmp = compareType(fd1, fd2);
463 if (cmp)
464 return cmp;
466 return lstrcmpi(fd1->cFileName, fd2->cFileName);
469 static int compareExt(const void* arg1, const void* arg2)
471 const WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
472 const WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
473 const TCHAR *name1, *name2, *ext1, *ext2;
475 int cmp = compareType(fd1, fd2);
476 if (cmp)
477 return cmp;
479 name1 = fd1->cFileName;
480 name2 = fd2->cFileName;
482 ext1 = _tcsrchr(name1, _T('.'));
483 ext2 = _tcsrchr(name2, _T('.'));
485 if (ext1)
486 ext1++;
487 else
488 ext1 = _T("");
490 if (ext2)
491 ext2++;
492 else
493 ext2 = _T("");
495 cmp = lstrcmpi(ext1, ext2);
496 if (cmp)
497 return cmp;
499 return lstrcmpi(name1, name2);
502 static int compareSize(const void* arg1, const void* arg2)
504 WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
505 WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
507 int cmp = compareType(fd1, fd2);
508 if (cmp)
509 return cmp;
511 cmp = fd2->nFileSizeHigh - fd1->nFileSizeHigh;
513 if (cmp < 0)
514 return -1;
515 else if (cmp > 0)
516 return 1;
518 cmp = fd2->nFileSizeLow - fd1->nFileSizeLow;
520 return cmp<0? -1: cmp>0? 1: 0;
523 static int compareDate(const void* arg1, const void* arg2)
525 WIN32_FIND_DATA* fd1 = &(*(Entry**)arg1)->data;
526 WIN32_FIND_DATA* fd2 = &(*(Entry**)arg2)->data;
528 int cmp = compareType(fd1, fd2);
529 if (cmp)
530 return cmp;
532 return CompareFileTime(&fd2->ftLastWriteTime, &fd1->ftLastWriteTime);
536 static int (*sortFunctions[])(const void* arg1, const void* arg2) = {
537 compareName, /* SORT_NAME */
538 compareExt, /* SORT_EXT */
539 compareSize, /* SORT_SIZE */
540 compareDate /* SORT_DATE */
544 static void SortDirectory(Entry* parent, SORT_ORDER sortOrder)
546 Entry* entry = parent->down;
547 Entry** array, **p;
548 int len;
550 len = 0;
551 for(entry=parent->down; entry; entry=entry->next)
552 len++;
554 if (len) {
555 array = (Entry**) alloca(len*sizeof(Entry*));
557 p = array;
558 for(entry=parent->down; entry; entry=entry->next)
559 *p++ = entry;
561 /* call qsort with the appropriate compare function */
562 qsort(array, len, sizeof(array[0]), sortFunctions[sortOrder]);
564 parent->down = array[0];
566 for(p=array; --len; p++)
567 p[0]->next = p[1];
569 (*p)->next = 0;
574 static void read_directory(Entry* parent, LPCTSTR path, int sortOrder)
576 TCHAR buffer[MAX_PATH];
577 Entry* entry;
578 LPCTSTR s;
579 PTSTR d;
581 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
582 if (parent->unix_dir)
584 read_directory_unix(parent, path);
586 if (Globals.prescan_node) {
587 s = path;
588 d = buffer;
590 while(*s)
591 *d++ = *s++;
593 *d++ = _T('/');
595 for(entry=parent->down; entry; entry=entry->next)
596 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
597 lstrcpy(d, entry->data.cFileName);
598 read_directory_unix(entry, buffer);
599 SortDirectory(entry, sortOrder);
603 else
604 #endif
606 read_directory_win(parent, path);
608 if (Globals.prescan_node) {
609 s = path;
610 d = buffer;
612 while(*s)
613 *d++ = *s++;
615 *d++ = _T('\\');
617 for(entry=parent->down; entry; entry=entry->next)
618 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
619 lstrcpy(d, entry->data.cFileName);
620 read_directory_win(entry, buffer);
621 SortDirectory(entry, sortOrder);
626 SortDirectory(parent, sortOrder);
630 static ChildWnd* alloc_child_window(LPCTSTR path)
632 TCHAR drv[_MAX_DRIVE+1], dir[_MAX_DIR], name[_MAX_FNAME], ext[_MAX_EXT];
633 ChildWnd* child = (ChildWnd*) malloc(sizeof(ChildWnd));
634 Root* root = &child->root;
635 Entry* entry;
637 memset(child, 0, sizeof(ChildWnd));
639 child->left.treePane = TRUE;
640 child->left.visible_cols = 0;
642 child->right.treePane = FALSE;
643 #ifndef _NO_EXTENSIONS
644 child->right.visible_cols = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_INDEX|COL_LINKS;
645 #else
646 child->right.visible_cols = COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES;
647 #endif
649 child->pos.length = sizeof(WINDOWPLACEMENT);
650 child->pos.flags = 0;
651 child->pos.showCmd = SW_SHOWNORMAL;
652 child->pos.rcNormalPosition.left = CW_USEDEFAULT;
653 child->pos.rcNormalPosition.top = CW_USEDEFAULT;
654 child->pos.rcNormalPosition.right = CW_USEDEFAULT;
655 child->pos.rcNormalPosition.bottom = CW_USEDEFAULT;
657 child->focus_pane = 0;
658 child->split_pos = 200;
659 child->sortOrder = SORT_NAME;
660 child->header_wdths_ok = FALSE;
662 lstrcpy(child->path, path);
664 _tsplitpath(path, drv, dir, name, ext);
666 #if !defined(_NO_EXTENSIONS) && defined(__linux__)
667 if (*path == '/')
669 root->drive_type = GetDriveType(path);
671 lstrcat(drv, _T("/"));
672 lstrcpy(root->volname, _T("root fs"));
673 root->fs_flags = 0;
674 lstrcpy(root->fs, _T("unixfs"));
676 lstrcpy(root->path, _T("/"));
677 entry = read_tree_unix(root, path, child->sortOrder);
679 else
680 #endif
682 root->drive_type = GetDriveType(path);
684 lstrcat(drv, _T("\\"));
685 GetVolumeInformation(drv, root->volname, _MAX_FNAME, 0, 0, &root->fs_flags, root->fs, _MAX_DIR);
687 lstrcpy(root->path, drv);
688 entry = read_tree_win(root, path, child->sortOrder);
691 /*@@lstrcpy(root->entry.data.cFileName, drv); */
692 wsprintf(root->entry.data.cFileName, _T("%s - %s"), drv, root->fs);
694 root->entry.data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
696 child->left.root = &root->entry;
698 set_curdir(child, entry);
700 return child;
704 /* recursively free all child entries */
705 static void free_entries(Entry* parent)
707 Entry *entry, *next=parent->down;
709 if (next) {
710 parent->down = 0;
712 do {
713 entry = next;
714 next = entry->next;
716 free_entries(entry);
717 free(entry);
718 } while(next);
722 /* free all memory associated with a child window */
723 static void free_child_window(ChildWnd* child)
725 free_entries(&child->root.entry);
726 free(child);
730 /* get full path of specified directory entry */
731 static void get_path(Entry* dir, PTSTR path)
733 Entry* entry;
734 int len = 0;
735 int level = 0;
737 for(entry=dir; entry; level++) {
738 LPCTSTR name = entry->data.cFileName;
739 LPCTSTR s = name;
740 int l;
742 for(l=0; *s && *s!=_T('/') && *s!=_T('\\'); s++)
743 l++;
745 if (entry->up) {
746 memmove(path+l+1, path, len*sizeof(TCHAR));
747 memcpy(path+1, name, l*sizeof(TCHAR));
748 len += l+1;
750 #ifndef _NO_EXTENSIONS
751 if (entry->unix_dir)
752 path[0] = _T('/');
753 else
754 #endif
755 path[0] = _T('\\');
757 entry = entry->up;
758 } else {
759 memmove(path+l, path, len*sizeof(TCHAR));
760 memcpy(path, name, l*sizeof(TCHAR));
761 len += l;
762 break;
766 if (!level) {
767 #ifndef _NO_EXTENSIONS
768 if (entry->unix_dir)
769 path[len++] = _T('/');
770 else
771 #endif
772 path[len++] = _T('\\');
775 path[len] = _T('\0');
779 static void resize_frame_rect(HWND hwnd, PRECT prect)
781 int new_top;
782 RECT rt;
784 if (IsWindowVisible(Globals.htoolbar)) {
785 SendMessage(Globals.htoolbar, WM_SIZE, 0, 0);
786 GetClientRect(Globals.htoolbar, &rt);
787 prect->top = rt.bottom+3;
788 prect->bottom -= rt.bottom+3;
791 if (IsWindowVisible(Globals.hdrivebar)) {
792 SendMessage(Globals.hdrivebar, WM_SIZE, 0, 0);
793 GetClientRect(Globals.hdrivebar, &rt);
794 new_top = --prect->top + rt.bottom+3;
795 MoveWindow(Globals.hdrivebar, 0, prect->top, rt.right, new_top, TRUE);
796 prect->top = new_top;
797 prect->bottom -= rt.bottom+2;
800 if (IsWindowVisible(Globals.hstatusbar)) {
801 int parts[] = {300, 500};
803 SendMessage(Globals.hstatusbar, WM_SIZE, 0, 0);
804 SendMessage(Globals.hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
805 GetClientRect(Globals.hstatusbar, &rt);
806 prect->bottom -= rt.bottom;
809 MoveWindow(Globals.hmdiclient, prect->left-1,prect->top-1,prect->right+2,prect->bottom+1, TRUE);
812 static void resize_frame(HWND hwnd, int cx, int cy)
814 RECT rect;
816 rect.left = 0;
817 rect.top = 0;
818 rect.right = cx;
819 rect.bottom = cy;
821 resize_frame_rect(hwnd, &rect);
824 static void resize_frame_client(HWND hwnd)
826 RECT rect;
828 GetClientRect(hwnd, &rect);
830 resize_frame_rect(hwnd, &rect);
834 static HHOOK hcbthook;
835 static ChildWnd* newchild = NULL;
837 LRESULT CALLBACK CBTProc(int code, WPARAM wparam, LPARAM lparam)
839 if (code==HCBT_CREATEWND && newchild) {
840 ChildWnd* child = newchild;
841 newchild = NULL;
843 child->hwnd = (HWND) wparam;
844 SetWindowLong(child->hwnd, GWL_USERDATA, (LPARAM)child);
847 return CallNextHookEx(hcbthook, code, wparam, lparam);
850 static HWND create_child_window(ChildWnd* child)
852 MDICREATESTRUCT mcs;
853 int idx;
855 mcs.szClass = WINEFILETREE;
856 mcs.szTitle = (LPTSTR)child->path;
857 mcs.hOwner = Globals.hInstance;
858 mcs.x = child->pos.rcNormalPosition.left;
859 mcs.y = child->pos.rcNormalPosition.top;
860 mcs.cx = child->pos.rcNormalPosition.right-child->pos.rcNormalPosition.left;
861 mcs.cy = child->pos.rcNormalPosition.bottom-child->pos.rcNormalPosition.top;
862 mcs.style = 0;
863 mcs.lParam = 0;
865 hcbthook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId());
867 newchild = child;
868 child->hwnd = (HWND) SendMessage(Globals.hmdiclient, WM_MDICREATE, 0, (LPARAM)&mcs);
869 if (!child->hwnd)
870 return 0;
872 UnhookWindowsHookEx(hcbthook);
874 idx = ListBox_FindItemData(child->left.hwnd, ListBox_GetCurSel(child->left.hwnd), child->left.cur);
875 ListBox_SetCurSel(child->left.hwnd, idx);
877 return child->hwnd;
881 struct ExecuteDialog {
882 TCHAR cmd[MAX_PATH];
883 int cmdshow;
887 static BOOL CALLBACK ExecuteDialogWndProg(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
889 static struct ExecuteDialog* dlg;
891 switch(nmsg) {
892 case WM_INITDIALOG:
893 dlg = (struct ExecuteDialog*) lparam;
894 return 1;
896 case WM_COMMAND: {
897 int id = (int)wparam;
899 if (id == IDOK) {
900 GetWindowText(GetDlgItem(hwnd, 201), dlg->cmd, MAX_PATH);
901 dlg->cmdshow = Button_GetState(GetDlgItem(hwnd,214))&BST_CHECKED?
902 SW_SHOWMINIMIZED: SW_SHOWNORMAL;
903 EndDialog(hwnd, id);
904 } else if (id == IDCANCEL)
905 EndDialog(hwnd, id);
907 return 1;}
910 return 0;
914 #ifndef _NO_EXTENSIONS
916 static struct FullScreenParameters {
917 BOOL mode;
918 RECT orgPos;
919 BOOL wasZoomed;
920 } g_fullscreen = {
921 FALSE /* mode */
924 void frame_get_clientspace(HWND hwnd, PRECT prect)
926 RECT rt;
928 if (!IsIconic(hwnd))
929 GetClientRect(hwnd, prect);
930 else {
931 WINDOWPLACEMENT wp;
933 GetWindowPlacement(hwnd, &wp);
935 prect->left = prect->top = 0;
936 prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left-
937 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE));
938 prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top-
939 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))-
940 GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE);
943 if (IsWindowVisible(Globals.htoolbar)) {
944 GetClientRect(Globals.htoolbar, &rt);
945 prect->top += rt.bottom+2;
948 if (IsWindowVisible(Globals.hdrivebar)) {
949 GetClientRect(Globals.hdrivebar, &rt);
950 prect->top += rt.bottom+2;
953 if (IsWindowVisible(Globals.hstatusbar)) {
954 GetClientRect(Globals.hstatusbar, &rt);
955 prect->bottom -= rt.bottom;
959 static BOOL toggle_fullscreen(HWND hwnd)
961 RECT rt;
963 if ((g_fullscreen.mode=!g_fullscreen.mode)) {
964 GetWindowRect(hwnd, &g_fullscreen.orgPos);
965 g_fullscreen.wasZoomed = IsZoomed(hwnd);
967 Frame_CalcFrameClient(hwnd, &rt);
968 ClientToScreen(hwnd, (LPPOINT)&rt.left);
969 ClientToScreen(hwnd, (LPPOINT)&rt.right);
971 rt.left = g_fullscreen.orgPos.left-rt.left;
972 rt.top = g_fullscreen.orgPos.top-rt.top;
973 rt.right = GetSystemMetrics(SM_CXSCREEN)+g_fullscreen.orgPos.right-rt.right;
974 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+g_fullscreen.orgPos.bottom-rt.bottom;
976 MoveWindow(hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
977 } else {
978 MoveWindow(hwnd, g_fullscreen.orgPos.left, g_fullscreen.orgPos.top,
979 g_fullscreen.orgPos.right-g_fullscreen.orgPos.left,
980 g_fullscreen.orgPos.bottom-g_fullscreen.orgPos.top, TRUE);
982 if (g_fullscreen.wasZoomed)
983 ShowWindow(hwnd, WS_MAXIMIZE);
986 return g_fullscreen.mode;
989 static void fullscreen_move(HWND hwnd)
991 RECT rt, pos;
992 GetWindowRect(hwnd, &pos);
994 Frame_CalcFrameClient(hwnd, &rt);
995 ClientToScreen(hwnd, (LPPOINT)&rt.left);
996 ClientToScreen(hwnd, (LPPOINT)&rt.right);
998 rt.left = pos.left-rt.left;
999 rt.top = pos.top-rt.top;
1000 rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right;
1001 rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom;
1003 MoveWindow(hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
1006 #endif
1009 static void toggle_child(HWND hwnd, UINT cmd, HWND hchild)
1011 BOOL vis = IsWindowVisible(hchild);
1013 CheckMenuItem(Globals.hMenuOptions, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
1015 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
1017 #ifndef _NO_EXTENSIONS
1018 if (g_fullscreen.mode)
1019 fullscreen_move(hwnd);
1020 #endif
1022 resize_frame_client(hwnd);
1025 BOOL activate_drive_window(LPCTSTR path)
1027 TCHAR drv1[_MAX_DRIVE], drv2[_MAX_DRIVE];
1028 HWND child_wnd;
1030 _tsplitpath(path, drv1, 0, 0, 0);
1032 /* search for a already open window for the same drive */
1033 for(child_wnd=GetNextWindow(Globals.hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) {
1034 ChildWnd* child = (ChildWnd*) GetWindowLong(child_wnd, GWL_USERDATA);
1036 if (child) {
1037 _tsplitpath(child->root.path, drv2, 0, 0, 0);
1039 if (!lstrcmpi(drv2, drv1)) {
1040 SendMessage(Globals.hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1042 if (IsMinimized(child_wnd))
1043 ShowWindow(child_wnd, SW_SHOWNORMAL);
1045 return TRUE;
1050 return FALSE;
1053 LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
1055 switch(nmsg) {
1056 case WM_CLOSE:
1057 DestroyWindow(hwnd);
1058 break;
1060 case WM_DESTROY:
1061 PostQuitMessage(0);
1062 break;
1064 case WM_COMMAND: {
1065 UINT cmd = LOWORD(wparam);
1066 HWND hwndClient = (HWND) SendMessage(Globals.hmdiclient, WM_MDIGETACTIVE, 0, 0);
1068 if (SendMessage(hwndClient, WM_DISPATCH_COMMAND, wparam, lparam))
1069 break;
1071 if (cmd>=ID_DRIVE_FIRST && cmd<=ID_DRIVE_FIRST+0xFF) {
1072 TCHAR drv[_MAX_DRIVE], path[MAX_PATH];
1073 ChildWnd* child;
1074 LPCTSTR root = Globals.drives;
1075 int i;
1077 for(i=cmd-ID_DRIVE_FIRST; i--; root++)
1078 while(*root)
1079 root++;
1081 if (activate_drive_window(root))
1082 return 0;
1084 _tsplitpath(root, drv, 0, 0, 0);
1086 if (!SetCurrentDirectory(drv)) {
1087 display_error(hwnd, GetLastError());
1088 return 0;
1091 GetCurrentDirectory(MAX_PATH, path); /*@@ letztes Verzeichnis pro Laufwerk speichern */
1092 child = alloc_child_window(path);
1094 if (!create_child_window(child))
1095 free(child);
1096 } else switch(cmd) {
1097 case ID_FILE_EXIT:
1098 PostQuitMessage(0);
1099 break;
1101 case ID_WINDOW_NEW: {
1102 TCHAR path[MAX_PATH];
1103 ChildWnd* child;
1105 GetCurrentDirectory(MAX_PATH, path);
1106 child = alloc_child_window(path);
1108 if (!create_child_window(child))
1109 free(child);
1110 break;}
1112 case ID_WINDOW_CASCADE:
1113 SendMessage(Globals.hmdiclient, WM_MDICASCADE, 0, 0);
1114 break;
1116 case ID_WINDOW_TILE_HORZ:
1117 SendMessage(Globals.hmdiclient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
1118 break;
1120 case ID_WINDOW_TILE_VERT:
1121 SendMessage(Globals.hmdiclient, WM_MDITILE, MDITILE_VERTICAL, 0);
1122 break;
1124 case ID_WINDOW_ARRANGE:
1125 SendMessage(Globals.hmdiclient, WM_MDIICONARRANGE, 0, 0);
1126 break;
1128 case ID_VIEW_TOOL_BAR:
1129 toggle_child(hwnd, cmd, Globals.htoolbar);
1130 break;
1132 case ID_VIEW_DRIVE_BAR:
1133 toggle_child(hwnd, cmd, Globals.hdrivebar);
1134 break;
1136 case ID_VIEW_STATUSBAR:
1137 toggle_child(hwnd, cmd, Globals.hstatusbar);
1138 break;
1140 case ID_EXECUTE: {
1141 struct ExecuteDialog dlg = {{0}};
1142 if (DialogBoxParam(Globals.hInstance, MAKEINTRESOURCE(IDD_EXECUTE), hwnd, ExecuteDialogWndProg, (LPARAM)&dlg) == IDOK) {
1143 HINSTANCE hinst = ShellExecute(hwnd, NULL/*operation*/, dlg.cmd/*file*/, NULL/*parameters*/, NULL/*dir*/, dlg.cmdshow);
1145 if ((int)hinst <= 32)
1146 display_error(hwnd, GetLastError());
1148 break;}
1150 case ID_HELP:
1151 WinHelp(hwnd, _T("winfile"), HELP_INDEX, 0);
1152 break;
1154 #ifndef _NO_EXTENSIONS
1155 case ID_VIEW_FULLSCREEN:
1156 CheckMenuItem(Globals.hMenuOptions, cmd, toggle_fullscreen(hwnd)?MF_CHECKED:0);
1157 break;
1159 #ifdef __linux__
1160 case ID_DRIVE_UNIX_FS: {
1161 TCHAR path[MAX_PATH];
1162 ChildWnd* child;
1164 if (activate_drive_window(_T("/")))
1165 break;
1167 getcwd(path, MAX_PATH);
1168 child = alloc_child_window(path);
1170 if (!create_child_window(child))
1171 free(child);
1172 break;}
1173 #endif
1174 #endif
1176 /*TODO: There are even more menu items! */
1178 #ifndef _NO_EXTENSIONS
1179 case ID_LICENSE:
1180 WineLicense(Globals.hMainWnd);
1181 break;
1183 case ID_NO_WARRANTY:
1184 WineWarranty(Globals.hMainWnd);
1185 break;
1187 case ID_ABOUT_WINE:
1188 ShellAbout(hwnd, _T("WINE"), _T("Winefile"), 0);
1189 break;
1190 #endif
1192 default:
1193 /*@@if (wParam >= PM_FIRST_LANGUAGE && wParam <= PM_LAST_LANGUAGE)
1194 STRING_SelectLanguageByNumber(wParam - PM_FIRST_LANGUAGE);
1195 else */if ((cmd<IDW_FIRST_CHILD || cmd>=IDW_FIRST_CHILD+0x100) &&
1196 (cmd<SC_SIZE || cmd>SC_RESTORE))
1197 MessageBox(hwnd, _T("Not yet implemented"), _T("Winefile"), MB_OK);
1199 return DefFrameProc(hwnd, Globals.hmdiclient, nmsg, wparam, lparam);
1201 break;}
1203 case WM_SIZE:
1204 resize_frame(hwnd, LOWORD(lparam), HIWORD(lparam));
1205 break; /* do not pass message to DefFrameProc */
1207 #ifndef _NO_EXTENSIONS
1208 case WM_GETMINMAXINFO: {
1209 LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
1211 lpmmi->ptMaxTrackSize.x <<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
1212 lpmmi->ptMaxTrackSize.y <<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
1213 break;}
1215 case FRM_CALC_CLIENT:
1216 frame_get_clientspace(hwnd, (PRECT)lparam);
1217 return TRUE;
1218 #endif
1220 default:
1221 return DefFrameProc(hwnd, Globals.hmdiclient, nmsg, wparam, lparam);
1224 return 0;
1228 const static LPTSTR g_pos_names[COLUMNS] = {
1229 _T(""), /* symbol */
1230 _T("Name"),
1231 _T("Size"),
1232 _T("CDate"),
1233 #ifndef _NO_EXTENSIONS
1234 _T("ADate"),
1235 _T("MDate"),
1236 _T("Index/Inode"),
1237 _T("Links"),
1238 #endif
1239 _T("Attributes"),
1240 #ifndef _NO_EXTENSIONS
1241 _T("Security")
1242 #endif
1245 const static int g_pos_align[] = {
1247 HDF_LEFT, /* Name */
1248 HDF_RIGHT, /* Size */
1249 HDF_LEFT, /* CDate */
1250 #ifndef _NO_EXTENSIONS
1251 HDF_LEFT, /* ADate */
1252 HDF_LEFT, /* MDate */
1253 HDF_LEFT, /* Index */
1254 HDF_CENTER, /* Links */
1255 #endif
1256 HDF_CENTER, /* Attributes */
1257 #ifndef _NO_EXTENSIONS
1258 HDF_LEFT /* Security */
1259 #endif
1262 static void resize_tree(ChildWnd* child, int cx, int cy)
1264 HDWP hdwp = BeginDeferWindowPos(4);
1265 RECT rt;
1267 rt.left = 0;
1268 rt.top = 0;
1269 rt.right = cx;
1270 rt.bottom = cy;
1272 cx = child->split_pos + SPLIT_WIDTH/2;
1274 #ifndef _NO_EXTENSIONS
1276 WINDOWPOS wp;
1277 HD_LAYOUT hdl;
1279 hdl.prc = &rt;
1280 hdl.pwpos = &wp;
1282 Header_Layout(child->left.hwndHeader, &hdl);
1284 DeferWindowPos(hdwp, child->left.hwndHeader, wp.hwndInsertAfter,
1285 wp.x-1, wp.y, child->split_pos-SPLIT_WIDTH/2+1, wp.cy, wp.flags);
1286 DeferWindowPos(hdwp, child->right.hwndHeader, wp.hwndInsertAfter,
1287 rt.left+cx+1, wp.y, wp.cx-cx+2, wp.cy, wp.flags);
1289 #endif
1291 DeferWindowPos(hdwp, child->left.hwnd, 0, rt.left, rt.top, child->split_pos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
1292 DeferWindowPos(hdwp, child->right.hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
1294 EndDeferWindowPos(hdwp);
1298 #ifndef _NO_EXTENSIONS
1300 static HWND create_header(HWND parent, Pane* pane, int id)
1302 HD_ITEM hdi = {HDI_TEXT|HDI_WIDTH|HDI_FORMAT};
1303 int idx;
1305 HWND hwnd = CreateWindow(WC_HEADER, 0, WS_CHILD|WS_VISIBLE|HDS_HORZ/*TODO: |HDS_BUTTONS + sort orders*/,
1306 0, 0, 0, 0, parent, (HMENU)id, Globals.hInstance, 0);
1307 if (!hwnd)
1308 return 0;
1310 SendMessage(hwnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), FALSE);
1312 for(idx=0; idx<COLUMNS; idx++) {
1313 hdi.pszText = g_pos_names[idx];
1314 hdi.fmt = HDF_STRING | g_pos_align[idx];
1315 hdi.cxy = pane->widths[idx];
1316 Header_InsertItem(hwnd, idx, &hdi);
1319 return hwnd;
1322 #endif
1325 static void init_output(HWND hwnd)
1327 TCHAR b[16];
1328 HFONT old_font;
1329 HDC hdc = GetDC(hwnd);
1331 if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, _T("1000"), 0, b, 16) > 4)
1332 Globals.num_sep = b[1];
1333 else
1334 Globals.num_sep = _T('.');
1336 old_font = SelectFont(hdc, Globals.hfont);
1337 GetTextExtentPoint32(hdc, _T(" "), 1, &Globals.spaceSize);
1338 SelectFont(hdc, old_font);
1339 ReleaseDC(hwnd, hdc);
1342 static void draw_item(Pane* pane, LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol);
1345 /* calculate prefered width for all visible columns */
1347 static BOOL calc_widths(Pane* pane, BOOL anyway)
1349 int col, x, cx, spc=3*Globals.spaceSize.cx;
1350 int entries = ListBox_GetCount(pane->hwnd);
1351 int orgWidths[COLUMNS];
1352 int orgPositions[COLUMNS+1];
1353 HFONT hfontOld;
1354 HDC hdc;
1355 int cnt;
1357 if (!anyway) {
1358 memcpy(orgWidths, pane->widths, sizeof(orgWidths));
1359 memcpy(orgPositions, pane->positions, sizeof(orgPositions));
1362 for(col=0; col<COLUMNS; col++)
1363 pane->widths[col] = 0;
1365 hdc = GetDC(pane->hwnd);
1366 hfontOld = SelectFont(hdc, Globals.hfont);
1368 for(cnt=0; cnt<entries; cnt++) {
1369 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, cnt);
1371 DRAWITEMSTRUCT dis;
1373 dis.CtlType = 0;
1374 dis.CtlID = 0;
1375 dis.itemID = 0;
1376 dis.itemAction = 0;
1377 dis.itemState = 0;
1378 dis.hwndItem = pane->hwnd;
1379 dis.hDC = hdc;
1380 dis.rcItem.left = 0;
1381 dis.rcItem.top = 0;
1382 dis.rcItem.right = 0;
1383 dis.rcItem.bottom = 0;
1384 /*dis.itemData = 0; */
1386 draw_item(pane, &dis, entry, COLUMNS);
1389 SelectObject(hdc, hfontOld);
1390 ReleaseDC(pane->hwnd, hdc);
1392 x = 0;
1393 for(col=0; col<COLUMNS; col++) {
1394 pane->positions[col] = x;
1395 cx = pane->widths[col];
1397 if (cx) {
1398 cx += spc;
1400 if (cx < IMAGE_WIDTH)
1401 cx = IMAGE_WIDTH;
1403 pane->widths[col] = cx;
1406 x += cx;
1409 pane->positions[COLUMNS] = x;
1411 ListBox_SetHorizontalExtent(pane->hwnd, x);
1413 /* no change? */
1414 if (!memcmp(orgWidths, pane->widths, sizeof(orgWidths)))
1415 return FALSE;
1417 /* don't move, if only collapsing an entry */
1418 if (!anyway && pane->widths[0]<orgWidths[0] &&
1419 !memcmp(orgWidths+1, pane->widths+1, sizeof(orgWidths)-sizeof(int))) {
1420 pane->widths[0] = orgWidths[0];
1421 memcpy(pane->positions, orgPositions, sizeof(orgPositions));
1423 return FALSE;
1426 InvalidateRect(pane->hwnd, 0, TRUE);
1428 return TRUE;
1432 /* calculate one prefered column width */
1434 static void calc_single_width(Pane* pane, int col)
1436 HFONT hfontOld;
1437 int x, cx;
1438 int entries = ListBox_GetCount(pane->hwnd);
1439 int cnt;
1440 HDC hdc;
1442 pane->widths[col] = 0;
1444 hdc = GetDC(pane->hwnd);
1445 hfontOld = SelectFont(hdc, Globals.hfont);
1447 for(cnt=0; cnt<entries; cnt++) {
1448 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, cnt);
1449 DRAWITEMSTRUCT dis;
1451 dis.CtlType = 0;
1452 dis.CtlID = 0;
1453 dis.itemID = 0;
1454 dis.itemAction = 0;
1455 dis.itemState = 0;
1456 dis.hwndItem = pane->hwnd;
1457 dis.hDC = hdc;
1458 dis.rcItem.left = 0;
1459 dis.rcItem.top = 0;
1460 dis.rcItem.right = 0;
1461 dis.rcItem.bottom = 0;
1462 /*dis.itemData = 0; */
1464 draw_item(pane, &dis, entry, col);
1467 SelectObject(hdc, hfontOld);
1468 ReleaseDC(pane->hwnd, hdc);
1470 cx = pane->widths[col];
1472 if (cx) {
1473 cx += 3*Globals.spaceSize.cx;
1475 if (cx < IMAGE_WIDTH)
1476 cx = IMAGE_WIDTH;
1479 pane->widths[col] = cx;
1481 x = pane->positions[col] + cx;
1483 for(; col<COLUMNS; ) {
1484 pane->positions[++col] = x;
1485 x += pane->widths[col];
1488 ListBox_SetHorizontalExtent(pane->hwnd, x);
1492 /* insert listbox entries after index idx */
1494 static void insert_entries(Pane* pane, Entry* parent, int idx)
1496 Entry* entry = parent;
1498 if (!entry)
1499 return;
1501 ShowWindow(pane->hwnd, SW_HIDE);
1503 for(; entry; entry=entry->next) {
1504 #ifndef _LEFT_FILES
1505 if (pane->treePane && !(entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
1506 continue;
1507 #endif
1509 /* don't display entries "." and ".." in the left pane */
1510 if (pane->treePane && (entry->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
1511 && entry->data.cFileName[0]==_T('.'))
1512 if (
1513 #ifndef _NO_EXTENSIONS
1514 entry->data.cFileName[1]==_T('\0') ||
1515 #endif
1516 (entry->data.cFileName[1]==_T('.') && entry->data.cFileName[2]==_T('\0')))
1517 continue;
1519 if (idx != -1)
1520 idx++;
1522 ListBox_InsertItemData(pane->hwnd, idx, entry);
1524 if (pane->treePane && entry->expanded)
1525 insert_entries(pane, entry->down, idx);
1528 ShowWindow(pane->hwnd, SW_SHOW);
1532 static WNDPROC g_orgTreeWndProc;
1534 static void create_tree_window(HWND parent, Pane* pane, int id, int id_header)
1536 static int s_init = 0;
1537 Entry* entry = pane->root;
1539 pane->hwnd = CreateWindow(_T("ListBox"), _T(""), WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|
1540 LBS_DISABLENOSCROLL|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWFIXED|LBS_NOTIFY,
1541 0, 0, 0, 0, parent, (HMENU)id, Globals.hInstance, 0);
1543 SetWindowLong(pane->hwnd, GWL_USERDATA, (LPARAM)pane);
1544 g_orgTreeWndProc = SubclassWindow(pane->hwnd, TreeWndProc);
1546 SendMessage(pane->hwnd, WM_SETFONT, (WPARAM)Globals.hfont, FALSE);
1548 /* insert entries into listbox */
1549 if (entry)
1550 insert_entries(pane, entry, -1);
1552 /* calculate column widths */
1553 if (!s_init) {
1554 s_init = 1;
1555 init_output(pane->hwnd);
1558 calc_widths(pane, TRUE);
1560 #ifndef _NO_EXTENSIONS
1561 pane->hwndHeader = create_header(parent, pane, id_header);
1562 #endif
1566 static void InitChildWindow(ChildWnd* child)
1568 create_tree_window(child->hwnd, &child->left, IDW_TREE_LEFT, IDW_HEADER_LEFT);
1569 create_tree_window(child->hwnd, &child->right, IDW_TREE_RIGHT, IDW_HEADER_RIGHT);
1573 static void format_date(const FILETIME* ft, TCHAR* buffer, int visible_cols)
1575 SYSTEMTIME systime;
1576 FILETIME lft;
1577 int len = 0;
1579 *buffer = _T('\0');
1581 if (!ft->dwLowDateTime && !ft->dwHighDateTime)
1582 return;
1584 if (!FileTimeToLocalFileTime(ft, &lft))
1585 {err: _tcscpy(buffer,_T("???")); return;}
1587 if (!FileTimeToSystemTime(&lft, &systime))
1588 goto err;
1590 if (visible_cols & COL_DATE) {
1591 len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer, BUFFER_LEN);
1592 if (!len)
1593 goto err;
1596 if (visible_cols & COL_TIME) {
1597 if (len)
1598 buffer[len-1] = ' ';
1600 buffer[len++] = ' ';
1602 if (!GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer+len, BUFFER_LEN-len))
1603 buffer[len] = _T('\0');
1608 static void calc_width(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
1610 RECT rt = {0};
1612 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX);
1614 if (rt.right > pane->widths[col])
1615 pane->widths[col] = rt.right;
1618 static void calc_tabbed_width(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
1620 RECT rt = {0};
1622 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
1623 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
1625 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8));
1626 /*@@ rt (0,0) ??? */
1628 if (rt.right > pane->widths[col])
1629 pane->widths[col] = rt.right;
1633 static void output_text(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str, DWORD flags)
1635 int x = dis->rcItem.left;
1636 RECT rt;
1638 rt.left = x+pane->positions[col]+Globals.spaceSize.cx;
1639 rt.top = dis->rcItem.top;
1640 rt.right = x+pane->positions[col+1]-Globals.spaceSize.cx;
1641 rt.bottom = dis->rcItem.bottom;
1643 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|flags);
1646 static void output_tabbed_text(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
1648 int x = dis->rcItem.left;
1649 RECT rt;
1651 rt.left = x+pane->positions[col]+Globals.spaceSize.cx;
1652 rt.top = dis->rcItem.top;
1653 rt.right = x+pane->positions[col+1]-Globals.spaceSize.cx;
1654 rt.bottom = dis->rcItem.bottom;
1656 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
1657 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
1659 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8));
1662 static void output_number(Pane* pane, LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
1664 int x = dis->rcItem.left;
1665 RECT rt;
1666 LPCTSTR s = str;
1667 TCHAR b[128];
1668 LPTSTR d = b;
1669 int pos;
1671 rt.left = x+pane->positions[col]+Globals.spaceSize.cx;
1672 rt.top = dis->rcItem.top;
1673 rt.right = x+pane->positions[col+1]-Globals.spaceSize.cx;
1674 rt.bottom = dis->rcItem.bottom;
1676 if (*s)
1677 *d++ = *s++;
1679 /* insert number separator characters */
1680 pos = lstrlen(s) % 3;
1682 while(*s)
1683 if (pos--)
1684 *d++ = *s++;
1685 else {
1686 *d++ = Globals.num_sep;
1687 pos = 3;
1690 DrawText(dis->hDC, b, d-b, &rt, DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX|DT_END_ELLIPSIS);
1694 static int is_exe_file(LPCTSTR ext)
1696 const static LPCTSTR executable_extensions[] = {
1697 _T("COM"),
1698 _T("EXE"),
1699 _T("BAT"),
1700 _T("CMD"),
1701 #ifndef _NO_EXTENSIONS
1702 _T("CMM"),
1703 _T("BTM"),
1704 _T("AWK"),
1705 #endif
1709 TCHAR ext_buffer[_MAX_EXT];
1710 const LPCTSTR* p;
1711 LPCTSTR s;
1712 LPTSTR d;
1714 for(s=ext+1,d=ext_buffer; (*d=tolower(*s)); s++)
1715 d++;
1717 for(p=executable_extensions; *p; p++)
1718 if (!_tcscmp(ext_buffer, *p))
1719 return 1;
1721 return 0;
1724 static int is_registered_type(LPCTSTR ext)
1726 /* TODO */
1728 return 1;
1732 static void draw_item(Pane* pane, LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
1734 TCHAR buffer[BUFFER_LEN];
1735 DWORD attrs;
1736 int visible_cols = pane->visible_cols;
1737 COLORREF bkcolor, textcolor;
1738 RECT focusRect = dis->rcItem;
1739 HBRUSH hbrush;
1740 enum IMAGE img;
1741 int img_pos, cx;
1742 int col = 0;
1744 if (entry) {
1745 attrs = entry->data.dwFileAttributes;
1747 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
1748 if (entry->data.cFileName[0]==_T('.') && entry->data.cFileName[1]==_T('.')
1749 && entry->data.cFileName[2]==_T('\0'))
1750 img = IMG_FOLDER_UP;
1751 #ifndef _NO_EXTENSIONS
1752 else if (entry->data.cFileName[0]==_T('.') && entry->data.cFileName[1]==_T('\0'))
1753 img = IMG_FOLDER_CUR;
1754 #endif
1755 else if (
1756 #ifdef _NO_EXTENSIONS
1757 entry->expanded ||
1758 #endif
1759 (pane->treePane && (dis->itemState&ODS_FOCUS)))
1760 img = IMG_OPEN_FOLDER;
1761 else
1762 img = IMG_FOLDER;
1763 } else {
1764 LPCTSTR ext = _tcsrchr(entry->data.cFileName, '.');
1765 if (!ext)
1766 ext = _T("");
1768 if (is_exe_file(ext))
1769 img = IMG_EXECUTABLE;
1770 else if (is_registered_type(ext))
1771 img = IMG_DOCUMENT;
1772 else
1773 img = IMG_FILE;
1775 } else {
1776 attrs = 0;
1777 img = IMG_NONE;
1780 if (pane->treePane) {
1781 if (entry) {
1782 img_pos = dis->rcItem.left + entry->level*(IMAGE_WIDTH+Globals.spaceSize.cx);
1784 if (calcWidthCol == -1) {
1785 int x;
1786 int y = dis->rcItem.top + IMAGE_HEIGHT/2;
1787 Entry* up;
1788 RECT rt_clip;
1789 HRGN hrgn_org = CreateRectRgn(0, 0, 0, 0);
1790 HRGN hrgn;
1792 rt_clip.left = dis->rcItem.left;
1793 rt_clip.top = dis->rcItem.top;
1794 rt_clip.right = dis->rcItem.left+pane->widths[col];
1795 rt_clip.bottom = dis->rcItem.bottom;
1797 hrgn = CreateRectRgnIndirect(&rt_clip);
1799 if (!GetClipRgn(dis->hDC, hrgn_org)) {
1800 DeleteObject(hrgn_org);
1801 hrgn_org = 0;
1804 /* HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN)); */
1805 ExtSelectClipRgn(dis->hDC, hrgn, RGN_AND);
1806 DeleteObject(hrgn);
1808 if ((up=entry->up) != NULL) {
1809 MoveToEx(dis->hDC, img_pos-IMAGE_WIDTH/2, y, 0);
1810 LineTo(dis->hDC, img_pos-2, y);
1812 x = img_pos - IMAGE_WIDTH/2;
1814 do {
1815 x -= IMAGE_WIDTH+Globals.spaceSize.cx;
1817 if (up->next
1818 #ifndef _LEFT_FILES
1819 && (up->next->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
1820 #endif
1822 MoveToEx(dis->hDC, x, dis->rcItem.top, 0);
1823 LineTo(dis->hDC, x, dis->rcItem.bottom);
1825 } while((up=up->up) != NULL);
1828 x = img_pos - IMAGE_WIDTH/2;
1830 MoveToEx(dis->hDC, x, dis->rcItem.top, 0);
1831 LineTo(dis->hDC, x, y);
1833 if (entry->next
1834 #ifndef _LEFT_FILES
1835 && (entry->next->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
1836 #endif
1838 LineTo(dis->hDC, x, dis->rcItem.bottom);
1840 if (entry->down && entry->expanded) {
1841 x += IMAGE_WIDTH+Globals.spaceSize.cx;
1842 MoveToEx(dis->hDC, x, dis->rcItem.top+IMAGE_HEIGHT, 0);
1843 LineTo(dis->hDC, x, dis->rcItem.bottom);
1846 SelectClipRgn(dis->hDC, hrgn_org);
1847 if (hrgn_org) DeleteObject(hrgn_org);
1848 /* SelectObject(dis->hDC, holdPen); */
1849 } else if (calcWidthCol==col || calcWidthCol==COLUMNS) {
1850 int right = img_pos + IMAGE_WIDTH - Globals.spaceSize.cx;
1852 if (right > pane->widths[col])
1853 pane->widths[col] = right;
1855 } else {
1856 img_pos = dis->rcItem.left;
1858 } else {
1859 img_pos = dis->rcItem.left;
1861 if (calcWidthCol==col || calcWidthCol==COLUMNS)
1862 pane->widths[col] = IMAGE_WIDTH;
1865 if (calcWidthCol == -1) {
1866 focusRect.left = img_pos -2;
1868 #ifdef _NO_EXTENSIONS
1869 if (pane->treePane && entry) {
1870 RECT rt = {0};
1872 DrawText(dis->hDC, entry->data.cFileName, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX);
1874 focusRect.right = dis->rcItem.left+pane->positions[col+1]+Globals.spaceSize.cx + rt.right +2;
1876 #else
1878 if (attrs & FILE_ATTRIBUTE_COMPRESSED)
1879 textcolor = COLOR_COMPRESSED;
1880 else
1881 #endif
1882 textcolor = RGB(0,0,0);
1884 if (dis->itemState & ODS_FOCUS) {
1885 textcolor = RGB(255,255,255);
1886 bkcolor = COLOR_SELECTION;
1887 } else {
1888 bkcolor = RGB(255,255,255);
1891 hbrush = CreateSolidBrush(bkcolor);
1892 FillRect(dis->hDC, &focusRect, hbrush);
1893 DeleteObject(hbrush);
1895 SetBkMode(dis->hDC, TRANSPARENT);
1896 SetTextColor(dis->hDC, textcolor);
1898 cx = pane->widths[col];
1900 if (cx && img!=IMG_NONE) {
1901 if (cx > IMAGE_WIDTH)
1902 cx = IMAGE_WIDTH;
1904 ImageList_DrawEx(Globals.himl, img, dis->hDC,
1905 img_pos, dis->rcItem.top, cx,
1906 IMAGE_HEIGHT, bkcolor, CLR_DEFAULT, ILD_NORMAL);
1910 if (!entry)
1911 return;
1913 #ifdef _NO_EXTENSIONS
1914 if (img >= IMG_FOLDER_UP)
1915 return;
1916 #endif
1918 col++;
1920 /* ouput file name */
1921 if (calcWidthCol == -1)
1922 output_text(pane, dis, col, entry->data.cFileName, 0);
1923 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1924 calc_width(pane, dis, col, entry->data.cFileName);
1926 col++;
1928 #ifdef _NO_EXTENSIONS
1929 if (!pane->treePane) {
1930 #endif
1932 /* display file size */
1933 if (visible_cols & COL_SIZE) {
1934 #ifdef _NO_EXTENSIONS
1935 if (!(attrs&FILE_ATTRIBUTE_DIRECTORY))
1936 #endif
1938 ULONGLONG size;
1940 size = ((ULONGLONG)entry->data.nFileSizeHigh << 32) | entry->data.nFileSizeLow;
1942 _stprintf(buffer, _T("%") LONGLONGARG _T("d"), size);
1944 if (calcWidthCol == -1)
1945 output_number(pane, dis, col, buffer);
1946 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1947 calc_width(pane, dis, col, buffer);/*TODO: not ever time enough */
1950 col++;
1953 /* display file date */
1954 if (visible_cols & (COL_DATE|COL_TIME)) {
1955 #ifndef _NO_EXTENSIONS
1956 format_date(&entry->data.ftCreationTime, buffer, visible_cols);
1957 if (calcWidthCol == -1)
1958 output_text(pane, dis, col, buffer, 0);
1959 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1960 calc_width(pane, dis, col, buffer);
1961 col++;
1963 format_date(&entry->data.ftLastAccessTime, buffer, visible_cols);
1964 if (calcWidthCol == -1)
1965 output_text(pane, dis, col, buffer, 0);
1966 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1967 calc_width(pane, dis, col, buffer);
1968 col++;
1969 #endif
1971 format_date(&entry->data.ftLastWriteTime, buffer, visible_cols);
1972 if (calcWidthCol == -1)
1973 output_text(pane, dis, col, buffer, 0);
1974 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1975 calc_width(pane, dis, col, buffer);
1976 col++;
1979 #ifndef _NO_EXTENSIONS
1980 if (entry->bhfi_valid) {
1981 ULONGLONG index = ((ULONGLONG)entry->bhfi.nFileIndexHigh << 32) | entry->bhfi.nFileIndexLow;
1983 if (visible_cols & COL_INDEX) {
1984 _stprintf(buffer, _T("%") LONGLONGARG _T("X"), index);
1985 if (calcWidthCol == -1)
1986 output_text(pane, dis, col, buffer, DT_RIGHT);
1987 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1988 calc_width(pane, dis, col, buffer);
1989 col++;
1992 if (visible_cols & COL_LINKS) {
1993 wsprintf(buffer, _T("%d"), entry->bhfi.nNumberOfLinks);
1994 if (calcWidthCol == -1)
1995 output_text(pane, dis, col, buffer, DT_CENTER);
1996 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
1997 calc_width(pane, dis, col, buffer);
1998 col++;
2000 } else
2001 col += 2;
2002 #endif
2004 /* show file attributes */
2005 if (visible_cols & COL_ATTRIBUTES) {
2006 #ifdef _NO_EXTENSIONS
2007 _tcscpy(buffer, _T(" \t \t \t \t "));
2008 #else
2009 _tcscpy(buffer, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
2010 #endif
2012 if (attrs & FILE_ATTRIBUTE_NORMAL) buffer[ 0] = 'N';
2013 else {
2014 if (attrs & FILE_ATTRIBUTE_READONLY) buffer[ 2] = 'R';
2015 if (attrs & FILE_ATTRIBUTE_HIDDEN) buffer[ 4] = 'H';
2016 if (attrs & FILE_ATTRIBUTE_SYSTEM) buffer[ 6] = 'S';
2017 if (attrs & FILE_ATTRIBUTE_ARCHIVE) buffer[ 8] = 'A';
2018 if (attrs & FILE_ATTRIBUTE_COMPRESSED) buffer[10] = 'C';
2019 #ifndef _NO_EXTENSIONS
2020 if (attrs & FILE_ATTRIBUTE_DIRECTORY) buffer[12] = 'D';
2021 if (attrs & FILE_ATTRIBUTE_ENCRYPTED) buffer[14] = 'E';
2022 if (attrs & FILE_ATTRIBUTE_TEMPORARY) buffer[16] = 'T';
2023 if (attrs & FILE_ATTRIBUTE_SPARSE_FILE) buffer[18] = 'P';
2024 if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) buffer[20] = 'Q';
2025 if (attrs & FILE_ATTRIBUTE_OFFLINE) buffer[22] = 'O';
2026 if (attrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) buffer[24] = 'X';
2027 #endif
2030 if (calcWidthCol == -1)
2031 output_tabbed_text(pane, dis, col, buffer);
2032 else if (calcWidthCol==col || calcWidthCol==COLUMNS)
2033 calc_tabbed_width(pane, dis, col, buffer);
2035 col++;
2038 /*TODO
2039 if (flags.security) {
2040 DWORD rights = get_access_mask();
2042 tcscpy(buffer, _T(" \t \t \t \t \t \t \t \t \t \t \t "));
2044 if (rights & FILE_READ_DATA) buffer[ 0] = 'R';
2045 if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W';
2046 if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A';
2047 if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';}
2048 if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';}
2049 if (rights & FILE_EXECUTE) buffer[12] = 'X';
2050 if (rights & FILE_DELETE_CHILD) buffer[14] = 'D';
2051 if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';}
2052 if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';}
2053 if (rights & WRITE_DAC) buffer[22] = 'C';
2054 if (rights & WRITE_OWNER) buffer[24] = 'O';
2055 if (rights & SYNCHRONIZE) buffer[26] = 'S';
2057 output_text(dis, col++, buffer, DT_LEFT, 3, psize);
2060 if (flags.description) {
2061 get_description(buffer);
2062 output_text(dis, col++, buffer, 0, psize);
2066 #ifdef _NO_EXTENSIONS
2069 /* draw focus frame */
2070 if ((dis->itemState&ODS_FOCUS) && calcWidthCol==-1) {
2071 /* Currently [04/2000] Wine neither behaves exactly the same */
2072 /* way as WIN 95 nor like Windows NT... */
2073 HGDIOBJ lastBrush;
2074 HPEN lastPen;
2075 HPEN hpen;
2077 if (!(GetVersion() & 0x80000000)) { /* Windows NT? */
2078 LOGBRUSH lb = {PS_SOLID, RGB(255,255,255)};
2079 hpen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, 0);
2080 } else
2081 hpen = CreatePen(PS_DOT, 0, RGB(255,255,255));
2083 lastPen = SelectPen(dis->hDC, hpen);
2084 lastBrush = SelectObject(dis->hDC, GetStockObject(HOLLOW_BRUSH));
2085 SetROP2(dis->hDC, R2_XORPEN);
2086 Rectangle(dis->hDC, focusRect.left, focusRect.top, focusRect.right, focusRect.bottom);
2087 SelectObject(dis->hDC, lastBrush);
2088 SelectObject(dis->hDC, lastPen);
2089 DeleteObject(hpen);
2091 #endif
2095 #ifdef _NO_EXTENSIONS
2097 static void draw_splitbar(HWND hwnd, int x)
2099 RECT rt;
2100 HDC hdc = GetDC(hwnd);
2102 GetClientRect(hwnd, &rt);
2104 rt.left = x - SPLIT_WIDTH/2;
2105 rt.right = x + SPLIT_WIDTH/2+1;
2107 InvertRect(hdc, &rt);
2109 ReleaseDC(hwnd, hdc);
2112 #endif
2115 #ifndef _NO_EXTENSIONS
2117 static void set_header(Pane* pane)
2119 HD_ITEM item;
2120 int scroll_pos = GetScrollPos(pane->hwnd, SB_HORZ);
2121 int i=0, x=0;
2123 item.mask = HDI_WIDTH;
2124 item.cxy = 0;
2126 for(; x+pane->widths[i]<scroll_pos && i<COLUMNS; i++) {
2127 x += pane->widths[i];
2128 Header_SetItem(pane->hwndHeader, i, &item);
2131 if (i < COLUMNS) {
2132 x += pane->widths[i];
2133 item.cxy = x - scroll_pos;
2134 Header_SetItem(pane->hwndHeader, i++, &item);
2136 for(; i<COLUMNS; i++) {
2137 item.cxy = pane->widths[i];
2138 x += pane->widths[i];
2139 Header_SetItem(pane->hwndHeader, i, &item);
2144 static LRESULT pane_notify(Pane* pane, NMHDR* pnmh)
2146 switch(pnmh->code) {
2147 case HDN_TRACK:
2148 case HDN_ENDTRACK: {
2149 HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh;
2150 int idx = phdn->iItem;
2151 int dx = phdn->pitem->cxy - pane->widths[idx];
2152 int i;
2154 RECT clnt;
2155 GetClientRect(pane->hwnd, &clnt);
2157 /* move immediate to simulate HDS_FULLDRAG (for now [04/2000] not realy needed with WINELIB) */
2158 Header_SetItem(pane->hwndHeader, idx, phdn->pitem);
2160 pane->widths[idx] += dx;
2162 for(i=idx; ++i<=COLUMNS; )
2163 pane->positions[i] += dx;
2166 int scroll_pos = GetScrollPos(pane->hwnd, SB_HORZ);
2167 RECT rt_scr;
2168 RECT rt_clip;
2170 rt_scr.left = pane->positions[idx+1]-scroll_pos;
2171 rt_scr.top = 0;
2172 rt_scr.right = clnt.right;
2173 rt_scr.bottom = clnt.bottom;
2175 rt_clip.left = pane->positions[idx]-scroll_pos;
2176 rt_clip.top = 0;
2177 rt_clip.right = clnt.right;
2178 rt_clip.bottom = clnt.bottom;
2180 if (rt_scr.left < 0) rt_scr.left = 0;
2181 if (rt_clip.left < 0) rt_clip.left = 0;
2183 ScrollWindowEx(pane->hwnd, dx, 0, &rt_scr, &rt_clip, 0, 0, SW_INVALIDATE);
2185 rt_clip.right = pane->positions[idx+1];
2186 RedrawWindow(pane->hwnd, &rt_clip, 0, RDW_INVALIDATE|RDW_UPDATENOW);
2188 if (pnmh->code == HDN_ENDTRACK) {
2189 ListBox_SetHorizontalExtent(pane->hwnd, pane->positions[COLUMNS]);
2191 if (GetScrollPos(pane->hwnd, SB_HORZ) != scroll_pos)
2192 set_header(pane);
2196 return FALSE;
2199 case HDN_DIVIDERDBLCLICK: {
2200 HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh;
2201 HD_ITEM item;
2203 calc_single_width(pane, phdn->iItem);
2204 item.mask = HDI_WIDTH;
2205 item.cxy = pane->widths[phdn->iItem];
2207 Header_SetItem(pane->hwndHeader, phdn->iItem, &item);
2208 InvalidateRect(pane->hwnd, 0, TRUE);
2209 break;}
2212 return 0;
2215 #endif
2218 static void scan_entry(ChildWnd* child, Entry* entry)
2220 TCHAR path[MAX_PATH];
2221 int idx = ListBox_GetCurSel(child->left.hwnd);
2222 HCURSOR crsrOld = SetCursor(LoadCursor(0, IDC_WAIT));
2224 /* delete sub entries in left pane */
2225 for(;;) {
2226 LRESULT res = ListBox_GetItemData(child->left.hwnd, idx+1);
2227 Entry* sub = (Entry*) res;
2229 if (res==LB_ERR || !sub || sub->level<=entry->level)
2230 break;
2232 ListBox_DeleteString(child->left.hwnd, idx+1);
2235 /* empty right pane */
2236 ListBox_ResetContent(child->right.hwnd);
2238 /* release memory */
2239 free_entries(entry);
2241 /* read contents from disk */
2242 get_path(entry, path);
2243 read_directory(entry, path, child->sortOrder);
2245 /* insert found entries in right pane */
2246 insert_entries(&child->right, entry->down, -1);
2247 calc_widths(&child->right, FALSE);
2248 #ifndef _NO_EXTENSIONS
2249 set_header(&child->right);
2250 #endif
2252 child->header_wdths_ok = FALSE;
2254 SetCursor(crsrOld);
2258 /* expand a directory entry */
2260 static BOOL expand_entry(ChildWnd* child, Entry* dir)
2262 int idx;
2263 Entry* p;
2265 if (!dir || dir->expanded || !dir->down)
2266 return FALSE;
2268 p = dir->down;
2270 if (p->data.cFileName[0]=='.' && p->data.cFileName[1]=='\0' && p->next) {
2271 p = p->next;
2273 if (p->data.cFileName[0]=='.' && p->data.cFileName[1]=='.' &&
2274 p->data.cFileName[2]=='\0' && p->next)
2275 p = p->next;
2278 /* no subdirectories ? */
2279 if (!(p->data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
2280 return FALSE;
2282 idx = ListBox_FindItemData(child->left.hwnd, 0, dir);
2284 dir->expanded = TRUE;
2286 /* insert entries in left pane */
2287 insert_entries(&child->left, p, idx);
2289 if (!child->header_wdths_ok) {
2290 if (calc_widths(&child->left, FALSE)) {
2291 #ifndef _NO_EXTENSIONS
2292 set_header(&child->left);
2293 #endif
2295 child->header_wdths_ok = TRUE;
2299 return TRUE;
2303 static void collapse_entry(Pane* pane, Entry* dir)
2305 int idx = ListBox_FindItemData(pane->hwnd, 0, dir);
2307 ShowWindow(pane->hwnd, SW_HIDE);
2309 /* hide sub entries */
2310 for(;;) {
2311 LRESULT res = ListBox_GetItemData(pane->hwnd, idx+1);
2312 Entry* sub = (Entry*) res;
2314 if (res==LB_ERR || !sub || sub->level<=dir->level)
2315 break;
2317 ListBox_DeleteString(pane->hwnd, idx+1);
2320 dir->expanded = FALSE;
2322 ShowWindow(pane->hwnd, SW_SHOW);
2326 static void set_curdir(ChildWnd* child, Entry* entry)
2328 TCHAR path[MAX_PATH];
2330 child->left.cur = entry;
2331 child->right.root = entry->down;
2332 child->right.cur = entry;
2334 if (!entry->scanned)
2335 scan_entry(child, entry);
2336 else {
2337 ListBox_ResetContent(child->right.hwnd);
2338 insert_entries(&child->right, entry->down, -1);
2339 calc_widths(&child->right, FALSE);
2340 #ifndef _NO_EXTENSIONS
2341 set_header(&child->right);
2342 #endif
2345 get_path(entry, path);
2346 lstrcpy(child->path, path);
2348 if (child->hwnd) /* only change window title, if the window already exists */
2349 SetWindowText(child->hwnd, path);
2351 SetCurrentDirectory(path);
2355 static void activate_entry(ChildWnd* child, Pane* pane)
2357 Entry* entry = pane->cur;
2359 if (!entry)
2360 return;
2362 if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2363 int scanned_old = entry->scanned;
2365 if (!scanned_old)
2366 scan_entry(child, entry);
2368 #ifndef _NO_EXTENSIONS
2369 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='\0')
2370 return;
2371 #endif
2373 if (entry->data.cFileName[0]=='.' && entry->data.cFileName[1]=='.' && entry->data.cFileName[2]=='\0') {
2374 entry = child->left.cur->up;
2375 collapse_entry(&child->left, entry);
2376 goto focus_entry;
2377 } else if (entry->expanded)
2378 collapse_entry(pane, child->left.cur);
2379 else {
2380 expand_entry(child, child->left.cur);
2382 if (!pane->treePane) focus_entry: {
2383 int idx = ListBox_FindItemData(child->left.hwnd, ListBox_GetCurSel(child->left.hwnd), entry);
2384 ListBox_SetCurSel(child->left.hwnd, idx);
2385 set_curdir(child, entry);
2389 if (!scanned_old) {
2390 calc_widths(pane, FALSE);
2392 #ifndef _NO_EXTENSIONS
2393 set_header(pane);
2394 #endif
2396 } else {
2397 TCHAR cmd[MAX_PATH];
2398 HINSTANCE hinst;
2400 get_path(entry, cmd);
2402 /* start program, open document... */
2403 hinst = ShellExecute(child->hwnd, NULL/*operation*/, cmd, NULL/*parameters*/, NULL/*dir*/, SW_SHOWNORMAL);
2405 if ((int)hinst <= 32)
2406 display_error(child->hwnd, GetLastError());
2411 static BOOL pane_command(Pane* pane, UINT cmd)
2413 switch(cmd) {
2414 case ID_VIEW_NAME:
2415 if (pane->visible_cols) {
2416 pane->visible_cols = 0;
2417 calc_widths(pane, TRUE);
2418 #ifndef _NO_EXTENSIONS
2419 set_header(pane);
2420 #endif
2421 InvalidateRect(pane->hwnd, 0, TRUE);
2422 CheckMenuItem(Globals.hMenuView, ID_VIEW_NAME, MF_BYCOMMAND|MF_CHECKED);
2423 CheckMenuItem(Globals.hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND);
2424 CheckMenuItem(Globals.hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
2426 break;
2428 case ID_VIEW_ALL_ATTRIBUTES:
2429 if (pane->visible_cols != COL_ALL) {
2430 pane->visible_cols = COL_ALL;
2431 calc_widths(pane, TRUE);
2432 #ifndef _NO_EXTENSIONS
2433 set_header(pane);
2434 #endif
2435 InvalidateRect(pane->hwnd, 0, TRUE);
2436 CheckMenuItem(Globals.hMenuView, ID_VIEW_NAME, MF_BYCOMMAND);
2437 CheckMenuItem(Globals.hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND|MF_CHECKED);
2438 CheckMenuItem(Globals.hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
2440 break;
2442 #ifndef _NO_EXTENSIONS
2443 case ID_PREFERED_SIZES: {
2444 calc_widths(pane, TRUE);
2445 set_header(pane);
2446 InvalidateRect(pane->hwnd, 0, TRUE);
2447 break;}
2448 #endif
2450 /* TODO: more command ids... */
2452 default:
2453 return FALSE;
2456 return TRUE;
2460 LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
2462 static int last_split;
2464 ChildWnd* child = (ChildWnd*) GetWindowLong(hwnd, GWL_USERDATA);
2465 ASSERT(child);
2467 switch(nmsg) {
2468 case WM_DRAWITEM: {
2469 LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lparam;
2470 Entry* entry = (Entry*) dis->itemData;
2472 if (dis->CtlID == IDW_TREE_LEFT)
2473 draw_item(&child->left, dis, entry, -1);
2474 else
2475 draw_item(&child->right, dis, entry, -1);
2477 return TRUE;}
2479 case WM_CREATE:
2480 InitChildWindow(child);
2481 break;
2483 case WM_NCDESTROY:
2484 free_child_window(child);
2485 SetWindowLong(hwnd, GWL_USERDATA, 0);
2486 break;
2488 case WM_PAINT: {
2489 PAINTSTRUCT ps;
2490 HBRUSH lastBrush;
2491 RECT rt;
2492 GetClientRect(hwnd, &rt);
2493 BeginPaint(hwnd, &ps);
2494 rt.left = child->split_pos-SPLIT_WIDTH/2;
2495 rt.right = child->split_pos+SPLIT_WIDTH/2+1;
2496 lastBrush = SelectBrush(ps.hdc, (HBRUSH)GetStockObject(COLOR_SPLITBAR));
2497 Rectangle(ps.hdc, rt.left, rt.top-1, rt.right, rt.bottom+1);
2498 SelectObject(ps.hdc, lastBrush);
2499 #ifdef _NO_EXTENSIONS
2500 rt.top = rt.bottom - GetSystemMetrics(SM_CYHSCROLL);
2501 FillRect(ps.hdc, &rt, GetStockObject(BLACK_BRUSH));
2502 #endif
2503 EndPaint(hwnd, &ps);
2504 break;}
2506 case WM_SETCURSOR:
2507 if (LOWORD(lparam) == HTCLIENT) {
2508 POINT pt;
2509 GetCursorPos(&pt);
2510 ScreenToClient(hwnd, &pt);
2512 if (pt.x>=child->split_pos-SPLIT_WIDTH/2 && pt.x<child->split_pos+SPLIT_WIDTH/2+1) {
2513 SetCursor(LoadCursor(0, IDC_SIZEWE));
2514 return TRUE;
2517 goto def;
2519 case WM_LBUTTONDOWN: {
2520 RECT rt;
2521 int x = LOWORD(lparam);
2523 GetClientRect(hwnd, &rt);
2525 if (x>=child->split_pos-SPLIT_WIDTH/2 && x<child->split_pos+SPLIT_WIDTH/2+1) {
2526 last_split = child->split_pos;
2527 #ifdef _NO_EXTENSIONS
2528 draw_splitbar(hwnd, last_split);
2529 #endif
2530 SetCapture(hwnd);
2533 break;}
2535 case WM_LBUTTONUP:
2536 if (GetCapture() == hwnd) {
2537 #ifdef _NO_EXTENSIONS
2538 RECT rt;
2539 int x = LOWORD(lparam);
2540 draw_splitbar(hwnd, last_split);
2541 last_split = -1;
2542 GetClientRect(hwnd, &rt);
2543 child->split_pos = x;
2544 resize_tree(child, rt.right, rt.bottom);
2545 #endif
2546 ReleaseCapture();
2548 break;
2550 #ifdef _NO_EXTENSIONS
2551 case WM_CAPTURECHANGED:
2552 if (GetCapture()==hwnd && last_split>=0)
2553 draw_splitbar(hwnd, last_split);
2554 break;
2555 #endif
2557 case WM_KEYDOWN:
2558 if (wparam == VK_ESCAPE)
2559 if (GetCapture() == hwnd) {
2560 RECT rt;
2561 #ifdef _NO_EXTENSIONS
2562 draw_splitbar(hwnd, last_split);
2563 #else
2564 child->split_pos = last_split;
2565 #endif
2566 GetClientRect(hwnd, &rt);
2567 resize_tree(child, rt.right, rt.bottom);
2568 last_split = -1;
2569 ReleaseCapture();
2570 SetCursor(LoadCursor(0, IDC_ARROW));
2572 break;
2574 case WM_MOUSEMOVE:
2575 if (GetCapture() == hwnd) {
2576 RECT rt;
2577 int x = LOWORD(lparam);
2579 #ifdef _NO_EXTENSIONS
2580 HDC hdc = GetDC(hwnd);
2581 GetClientRect(hwnd, &rt);
2583 rt.left = last_split-SPLIT_WIDTH/2;
2584 rt.right = last_split+SPLIT_WIDTH/2+1;
2585 InvertRect(hdc, &rt);
2587 last_split = x;
2588 rt.left = x-SPLIT_WIDTH/2;
2589 rt.right = x+SPLIT_WIDTH/2+1;
2590 InvertRect(hdc, &rt);
2592 ReleaseDC(hwnd, hdc);
2593 #else
2594 GetClientRect(hwnd, &rt);
2596 if (x>=0 && x<rt.right) {
2597 child->split_pos = x;
2598 resize_tree(child, rt.right, rt.bottom);
2599 rt.left = x-SPLIT_WIDTH/2;
2600 rt.right = x+SPLIT_WIDTH/2+1;
2601 InvalidateRect(hwnd, &rt, FALSE);
2602 UpdateWindow(child->left.hwnd);
2603 UpdateWindow(hwnd);
2604 UpdateWindow(child->right.hwnd);
2606 #endif
2608 break;
2610 #ifndef _NO_EXTENSIONS
2611 case WM_GETMINMAXINFO:
2612 DefMDIChildProc(hwnd, nmsg, wparam, lparam);
2614 {LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
2616 lpmmi->ptMaxTrackSize.x <<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
2617 lpmmi->ptMaxTrackSize.y <<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
2618 break;}
2619 #endif
2621 case WM_SETFOCUS:
2622 SetCurrentDirectory(child->path);
2623 SetFocus(child->focus_pane? child->right.hwnd: child->left.hwnd);
2624 break;
2626 case WM_DISPATCH_COMMAND: {
2627 Pane* pane = GetFocus()==child->left.hwnd? &child->left: &child->right;
2629 switch(LOWORD(wparam)) {
2630 case ID_WINDOW_NEW: {
2631 ChildWnd* new_child = alloc_child_window(child->path);
2633 if (!create_child_window(new_child))
2634 free(new_child);
2636 break;}
2638 case ID_REFRESH:
2639 scan_entry(child, pane->cur);
2640 break;
2642 case ID_ACTIVATE:
2643 activate_entry(child, pane);
2644 break;
2646 default:
2647 return pane_command(pane, LOWORD(wparam));
2650 return TRUE;}
2652 case WM_COMMAND: {
2653 Pane* pane = GetFocus()==child->left.hwnd? &child->left: &child->right;
2655 switch(HIWORD(wparam)) {
2656 case LBN_SELCHANGE: {
2657 int idx = ListBox_GetCurSel(pane->hwnd);
2658 Entry* entry = (Entry*) ListBox_GetItemData(pane->hwnd, idx);
2660 if (pane == &child->left)
2661 set_curdir(child, entry);
2662 else
2663 pane->cur = entry;
2664 break;}
2666 case LBN_DBLCLK:
2667 activate_entry(child, pane);
2668 break;
2670 break;}
2672 #ifndef _NO_EXTENSIONS
2673 case WM_NOTIFY: {
2674 NMHDR* pnmh = (NMHDR*) lparam;
2675 return pane_notify(pnmh->idFrom==IDW_HEADER_LEFT? &child->left: &child->right, pnmh);}
2676 #endif
2678 case WM_SIZE:
2679 if (wparam != SIZE_MINIMIZED)
2680 resize_tree(child, LOWORD(lparam), HIWORD(lparam));
2681 /* fall through */
2683 default: def:
2684 return DefMDIChildProc(hwnd, nmsg, wparam, lparam);
2687 return 0;
2691 LRESULT CALLBACK TreeWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
2693 ChildWnd* child = (ChildWnd*) GetWindowLong(GetParent(hwnd), GWL_USERDATA);
2694 Pane* pane = (Pane*) GetWindowLong(hwnd, GWL_USERDATA);
2695 ASSERT(child);
2697 switch(nmsg) {
2698 #ifndef _NO_EXTENSIONS
2699 case WM_HSCROLL:
2700 set_header(pane);
2701 break;
2702 #endif
2704 case WM_SETFOCUS:
2705 child->focus_pane = pane==&child->right? 1: 0;
2706 ListBox_SetSel(hwnd, TRUE, 1);
2707 /*TODO: check menu items */
2708 break;
2710 case WM_KEYDOWN:
2711 if (wparam == VK_TAB) {
2712 /*TODO: SetFocus(Globals.hdrivebar) */
2713 SetFocus(child->focus_pane? child->left.hwnd: child->right.hwnd);
2717 return CallWindowProc(g_orgTreeWndProc, hwnd, nmsg, wparam, lparam);
2721 static void InitInstance(HINSTANCE hinstance)
2723 WNDCLASSEX wcFrame;
2724 ATOM hframeClass;
2725 WNDCLASS wcChild;
2726 WINE_UNUSED ATOM hChildClass;
2727 HMENU hMenuFrame = LoadMenu(hinstance, MAKEINTRESOURCE(IDM_WINEFILE));
2728 HMENU hMenuWindow = GetSubMenu(hMenuFrame, GetMenuItemCount(hMenuFrame)-2);
2730 CLIENTCREATESTRUCT ccs;
2732 INITCOMMONCONTROLSEX icc = {
2733 sizeof(INITCOMMONCONTROLSEX),
2734 ICC_BAR_CLASSES
2737 ChildWnd* child;
2738 TCHAR path[MAX_PATH];
2740 HDC hdc = GetDC(0);
2743 wcFrame.cbSize = sizeof(WNDCLASSEX);
2744 wcFrame.style = 0;
2745 wcFrame.lpfnWndProc = FrameWndProc;
2746 wcFrame.cbClsExtra = 0;
2747 wcFrame.cbWndExtra = 0;
2748 wcFrame.hInstance = hinstance;
2749 wcFrame.hIcon = LoadIcon(hinstance,
2750 MAKEINTRESOURCE(IDI_WINEFILE));
2751 wcFrame.hCursor = LoadCursor(0, IDC_ARROW);
2752 wcFrame.hbrBackground = 0;
2753 wcFrame.lpszMenuName = 0;
2754 wcFrame.lpszClassName = WINEFILEFRAME;
2755 wcFrame.hIconSm = (HICON)LoadImage(hinstance,
2756 MAKEINTRESOURCE(IDI_WINEFILE),
2757 IMAGE_ICON,
2758 GetSystemMetrics(SM_CXSMICON),
2759 GetSystemMetrics(SM_CYSMICON),
2760 LR_SHARED);
2762 /* register frame window class */
2763 hframeClass = RegisterClassEx(&wcFrame);
2765 wcChild.style = CS_CLASSDC|CS_DBLCLKS|CS_VREDRAW;
2766 wcChild.lpfnWndProc = ChildWndProc;
2767 wcChild.cbClsExtra = 0;
2768 wcChild.cbWndExtra = 0;
2769 wcChild.hInstance = hinstance;
2770 wcChild.hIcon = 0;
2771 wcChild.hCursor = LoadCursor(0, IDC_ARROW);
2772 wcChild.hbrBackground = 0;
2773 wcChild.lpszMenuName = 0;
2774 wcChild.lpszClassName = WINEFILETREE;
2776 /* register tree windows class */
2777 hChildClass = RegisterClass(&wcChild);
2779 ccs.hWindowMenu = hMenuWindow;
2780 ccs.idFirstChild = IDW_FIRST_CHILD;
2782 Globals.hMenuFrame = hMenuFrame;
2783 Globals.hMenuView = GetSubMenu(hMenuFrame, 3);
2784 Globals.hMenuOptions = GetSubMenu(hMenuFrame, 4);
2786 Globals.haccel = LoadAccelerators(hinstance, MAKEINTRESOURCE(IDA_WINEFILE));
2788 Globals.hfont = CreateFont(-MulDiv(8,GetDeviceCaps(hdc,LOGPIXELSY),72), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _T("MS Sans Serif"));
2790 ReleaseDC(0, hdc);
2792 Globals.hInstance = hinstance;
2794 /* create main window */
2795 Globals.hMainWnd = CreateWindowEx(0, (LPCTSTR)(int)hframeClass, _T("Wine File"), WS_OVERLAPPEDWINDOW,
2796 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2797 0/*hWndParent*/, Globals.hMenuFrame, hinstance, 0/*lpParam*/);
2800 Globals.hmdiclient = CreateWindowEx(0, _T("MDICLIENT"), NULL,
2801 WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER,
2802 0, 0, 0, 0,
2803 Globals.hMainWnd, 0, hinstance, &ccs);
2806 InitCommonControlsEx(&icc);
2809 TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP};
2810 int btn = 1;
2811 PTSTR p;
2813 Globals.hdrivebar = CreateToolbarEx(Globals.hMainWnd, WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,
2814 IDW_DRIVEBAR, 2, Globals.hInstance, IDB_DRIVEBAR, &drivebarBtn,
2815 1, 16, 13, 16, 13, sizeof(TBBUTTON));
2816 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_CHECKED);
2818 GetLogicalDriveStrings(BUFFER_LEN, Globals.drives);
2820 drivebarBtn.fsStyle = TBSTYLE_BUTTON;
2822 #ifndef _NO_EXTENSIONS
2823 #ifdef __linux__
2824 /* insert unix file system button */
2825 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)_T("/\0"));
2827 drivebarBtn.idCommand = ID_DRIVE_UNIX_FS;
2828 SendMessage(Globals.hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
2829 drivebarBtn.iString++;
2830 #endif
2832 /* register windows drive root strings */
2833 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)Globals.drives);
2834 #endif
2836 drivebarBtn.idCommand = ID_DRIVE_FIRST;
2838 for(p=Globals.drives; *p; ) {
2839 #ifdef _NO_EXTENSIONS
2840 /* insert drive letter */
2841 TCHAR b[3] = {tolower(*p)};
2842 SendMessage(Globals.hdrivebar, TB_ADDSTRING, 0, (LPARAM)b);
2843 #endif
2844 switch(GetDriveType(p)) {
2845 case DRIVE_REMOVABLE: drivebarBtn.iBitmap = 1; break;
2846 case DRIVE_CDROM: drivebarBtn.iBitmap = 3; break;
2847 case DRIVE_REMOTE: drivebarBtn.iBitmap = 4; break;
2848 case DRIVE_RAMDISK: drivebarBtn.iBitmap = 5; break;
2849 default:/*DRIVE_FIXED*/ drivebarBtn.iBitmap = 2;
2852 SendMessage(Globals.hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
2853 drivebarBtn.idCommand++;
2854 drivebarBtn.iString++;
2856 while(*p++);
2861 TBBUTTON toolbarBtns[] = {
2862 {0, 0, 0, TBSTYLE_SEP},
2863 {0, ID_WINDOW_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2864 {1, ID_WINDOW_CASCADE, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2865 {2, ID_WINDOW_TILE_HORZ, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2866 {3, ID_WINDOW_TILE_VERT, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2867 {4, 2/*TODO: ID_...*/, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2868 {5, 2/*TODO: ID_...*/, TBSTATE_ENABLED, TBSTYLE_BUTTON},
2871 Globals.htoolbar = CreateToolbarEx(Globals.hMainWnd, WS_CHILD|WS_VISIBLE,
2872 IDW_TOOLBAR, 2, Globals.hInstance, IDB_TOOLBAR, toolbarBtns,
2873 sizeof(toolbarBtns)/sizeof(TBBUTTON), 16, 15, 16, 15, sizeof(TBBUTTON));
2874 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_TOOL_BAR, MF_BYCOMMAND|MF_CHECKED);
2877 Globals.hstatusbar = CreateStatusWindow(WS_CHILD|WS_VISIBLE, 0, Globals.hMainWnd, IDW_STATUSBAR);
2878 CheckMenuItem(Globals.hMenuOptions, ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED);
2880 /* CreateStatusWindow does not accept WS_BORDER
2881 Globals.hstatusbar = CreateWindowEx(WS_EX_NOPARENTNOTIFY, STATUSCLASSNAME, 0,
2882 WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_BORDER|CCS_NODIVIDER, 0,0,0,0,
2883 Globals.hMainWnd, (HMENU)IDW_STATUSBAR, hinstance, 0);*/
2885 /*TODO: read paths and window placements from registry */
2886 GetCurrentDirectory(MAX_PATH, path);
2887 child = alloc_child_window(path);
2889 child->pos.showCmd = SW_SHOWMAXIMIZED;
2890 child->pos.rcNormalPosition.left = 0;
2891 child->pos.rcNormalPosition.top = 0;
2892 child->pos.rcNormalPosition.right = 320;
2893 child->pos.rcNormalPosition.bottom = 280;
2895 if (!create_child_window(child))
2896 free(child);
2898 SetWindowPlacement(child->hwnd, &child->pos);
2900 Globals.himl = ImageList_LoadBitmap(Globals.hInstance, MAKEINTRESOURCE(IDB_IMAGES), 16, 0, RGB(0,255,0));
2902 Globals.prescan_node = FALSE;
2905 void ExitInstance()
2907 ImageList_Destroy(Globals.himl);
2911 #ifdef _NO_EXTENSIONS
2913 /* search for already running win[e]files */
2915 static int g_foundPrevInstance = 0;
2917 static BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lparam)
2919 TCHAR cls[128];
2921 GetClassName(hwnd, cls, 128);
2923 if (!lstrcmp(cls, (LPCTSTR)lparam)) {
2924 g_foundPrevInstance++;
2925 return FALSE;
2928 return TRUE;
2931 #endif
2934 int APIENTRY WinMain(HINSTANCE hinstance,
2935 HINSTANCE previnstance,
2936 LPSTR cmdline,
2937 int cmdshow)
2939 MSG msg;
2941 #ifdef _NO_EXTENSIONS
2942 /* allow only one running instance */
2943 EnumWindows(EnumWndProc, (LPARAM)WINEFILEFRAME);
2945 if (g_foundPrevInstance)
2946 return 1;
2947 #endif
2949 InitInstance(hinstance);
2951 if (cmdshow == SW_SHOWNORMAL) {
2952 /*TODO: read window placement from registry */
2953 cmdshow = SW_MAXIMIZE;
2956 ShowWindow(Globals.hMainWnd, cmdshow);
2957 UpdateWindow(Globals.hMainWnd);
2959 while(GetMessage(&msg, 0, 0, 0)) {
2960 if (!TranslateMDISysAccel(Globals.hmdiclient, &msg) &&
2961 !TranslateAccelerator(Globals.hMainWnd, Globals.haccel, &msg))
2963 TranslateMessage(&msg);
2964 DispatchMessage(&msg);
2968 ExitInstance();
2970 return 0;